diff --git a/.gitattributes b/.gitattributes index f3b066b05cb..fd1b78a05d8 100644 --- a/.gitattributes +++ b/.gitattributes @@ -14159,8 +14159,8 @@ src/main/java/forge/control/input/InputBlock.java svneol=native#text/plain src/main/java/forge/control/input/InputCleanup.java svneol=native#text/plain src/main/java/forge/control/input/InputConfirmMulligan.java svneol=native#text/plain src/main/java/forge/control/input/InputLockUI.java -text -src/main/java/forge/control/input/InputNonSyncBase.java -text src/main/java/forge/control/input/InputPassPriority.java svneol=native#text/plain +src/main/java/forge/control/input/InputPassPriorityBase.java -text src/main/java/forge/control/input/InputPayManaBase.java -text src/main/java/forge/control/input/InputPayManaExecuteCommands.java svneol=native#text/plain src/main/java/forge/control/input/InputPayManaOfCostPayment.java -text diff --git a/src/main/java/forge/control/input/InputAttack.java b/src/main/java/forge/control/input/InputAttack.java index ea35bc497c0..2b8d7dded28 100644 --- a/src/main/java/forge/control/input/InputAttack.java +++ b/src/main/java/forge/control/input/InputAttack.java @@ -42,7 +42,7 @@ import forge.view.ButtonUtil; * @author Forge * @version $Id$ */ -public class InputAttack extends InputNonSyncBase { +public class InputAttack extends InputPassPriorityBase { /** Constant serialVersionUID=7849903731842214245L. */ private static final long serialVersionUID = 7849903731842214245L; @@ -96,10 +96,10 @@ public class InputAttack extends InputNonSyncBase { public final void selectButtonOK() { // Propaganda costs could have been paid here. setCurrentDefender(null); // remove highlights - game.getPhaseHandler().setCombat(!game.getCombat().getAttackers().isEmpty()); game.getPhaseHandler().setPlayersPriorityPermission(false); - game.getInputQueue().updateObservers(); + + pass(); } @Override diff --git a/src/main/java/forge/control/input/InputAutoPassPriority.java b/src/main/java/forge/control/input/InputAutoPassPriority.java index 477917750e9..bed8f37cfdf 100644 --- a/src/main/java/forge/control/input/InputAutoPassPriority.java +++ b/src/main/java/forge/control/input/InputAutoPassPriority.java @@ -6,7 +6,7 @@ import forge.game.player.Player; * TODO: Write javadoc for this type. * */ -public class InputAutoPassPriority extends InputNonSyncBase { +public class InputAutoPassPriority extends InputPassPriorityBase { private static final long serialVersionUID = -7520803307255234647L; public InputAutoPassPriority(Player player) { @@ -15,7 +15,7 @@ public class InputAutoPassPriority extends InputNonSyncBase { @Override public void showMessage() { - passPriority(); + pass(); } } diff --git a/src/main/java/forge/control/input/InputBase.java b/src/main/java/forge/control/input/InputBase.java index 185b22cae59..009a898fd92 100644 --- a/src/main/java/forge/control/input/InputBase.java +++ b/src/main/java/forge/control/input/InputBase.java @@ -35,11 +35,15 @@ public abstract class InputBase implements java.io.Serializable, Input { /** Constant serialVersionUID=-6539552513871194081L. */ private static final long serialVersionUID = -6539552513871194081L; private InputQueue queue; + private boolean finished = false; + protected final boolean isFinished() { return finished; } + protected final void setFinished() { finished = true; } // showMessage() is always the first method called @Override public final void showMessage(InputQueue iq) { queue = iq; + finished = false; showMessage(); } @@ -55,23 +59,18 @@ public abstract class InputBase implements java.io.Serializable, Input { public void selectButtonCancel() { } // to remove need for CMatchUI dependence - protected void showMessage(String message) { + protected final void showMessage(String message) { CMatchUI.SINGLETON_INSTANCE.showMessage(message); } - // Removes this input from the stack and releases any latches (in synchronous imports) - protected final void stop() { - // clears a "temp" Input like Input_PayManaCost if there is one - queue.removeInput(this); - afterStop(); // sync inputs will release their latch there - } protected void afterStop() { } - - - protected final void flashIncorrectAction() { SDisplayUtil.remind(VMessage.SINGLETON_INSTANCE); } -} \ No newline at end of file + + protected InputQueue getQueue() { + return queue; + } +} diff --git a/src/main/java/forge/control/input/InputBlock.java b/src/main/java/forge/control/input/InputBlock.java index 57fd22d7baa..23f1b4306b5 100644 --- a/src/main/java/forge/control/input/InputBlock.java +++ b/src/main/java/forge/control/input/InputBlock.java @@ -37,7 +37,7 @@ import forge.view.ButtonUtil; * @author Forge * @version $Id$ */ -public class InputBlock extends InputNonSyncBase { +public class InputBlock extends InputPassPriorityBase { /** Constant serialVersionUID=6120743598368928128L. */ private static final long serialVersionUID = 6120743598368928128L; @@ -92,7 +92,7 @@ public class InputBlock extends InputNonSyncBase { currentAttacker = null; allBlocking.clear(); - passPriority(); + pass(); } } diff --git a/src/main/java/forge/control/input/InputCleanup.java b/src/main/java/forge/control/input/InputCleanup.java index 081b56d1733..a317c3e51e5 100644 --- a/src/main/java/forge/control/input/InputCleanup.java +++ b/src/main/java/forge/control/input/InputCleanup.java @@ -31,7 +31,7 @@ import forge.view.ButtonUtil; * @author Forge * @version $Id$ */ -public class InputCleanup extends InputNonSyncBase { +public class InputCleanup extends InputPassPriorityBase { /** Constant serialVersionUID=-4164275418971547948L. */ private static final long serialVersionUID = -4164275418971547948L; private final GameState game; @@ -55,7 +55,7 @@ public class InputCleanup extends InputNonSyncBase { final int max = active.getMaxHandSize(); // goes to the next phase if (active.isUnlimitedHandSize() || n <= max || n <= 0 || active != turnOwner) { - passPriority(); + pass(); return; } ButtonUtil.disableAll(); diff --git a/src/main/java/forge/control/input/InputNonSyncBase.java b/src/main/java/forge/control/input/InputNonSyncBase.java deleted file mode 100644 index 98bcf6bd7cb..00000000000 --- a/src/main/java/forge/control/input/InputNonSyncBase.java +++ /dev/null @@ -1,26 +0,0 @@ -package forge.control.input; - -import forge.FThreads; -import forge.game.player.Player; - -public abstract class InputNonSyncBase extends InputBase { - private static final long serialVersionUID = -4038934296796872326L; - protected final Player player; - - public InputNonSyncBase(Player p) { - this.player = p; - } - - protected void passPriority() { - final Runnable pass = new Runnable() { - @Override public void run() { - player.getController().passPriority(); - } - }; - if( FThreads.isEDT() ) - FThreads.invokeInNewThread(pass); -// player.getGame().getInputQueue().LockAndInvokeGameAction(pass); - else - pass.run(); - } -} \ No newline at end of file diff --git a/src/main/java/forge/control/input/InputPassPriority.java b/src/main/java/forge/control/input/InputPassPriority.java index 67ace04c706..669060626de 100644 --- a/src/main/java/forge/control/input/InputPassPriority.java +++ b/src/main/java/forge/control/input/InputPassPriority.java @@ -33,10 +33,9 @@ import forge.view.ButtonUtil; * @author Forge * @version $Id$ */ -public class InputPassPriority extends InputNonSyncBase { +public class InputPassPriority extends InputPassPriorityBase { /** Constant serialVersionUID=-581477682214137181L. */ private static final long serialVersionUID = -581477682214137181L; - private boolean canUse = false; /** * TODO: Write javadoc for Constructor. @@ -53,7 +52,6 @@ public class InputPassPriority extends InputNonSyncBase { p.getZone(ZoneType.Battlefield).updateObservers(); } ButtonUtil.enableOnlyOk(); - canUse = true; final PhaseHandler ph = player.getGame().getPhaseHandler(); final StringBuilder sb = new StringBuilder(); @@ -77,11 +75,8 @@ public class InputPassPriority extends InputNonSyncBase { /** {@inheritDoc} */ @Override public final void selectButtonOK() { - if( canUse ) { - canUse = false; - passPriority(); - } - + if( isFinished() ) return; + pass(); } /** {@inheritDoc} */ diff --git a/src/main/java/forge/control/input/InputPassPriorityBase.java b/src/main/java/forge/control/input/InputPassPriorityBase.java new file mode 100644 index 00000000000..09ab310447d --- /dev/null +++ b/src/main/java/forge/control/input/InputPassPriorityBase.java @@ -0,0 +1,29 @@ +package forge.control.input; + +import forge.FThreads; +import forge.game.player.Player; + +public abstract class InputPassPriorityBase extends InputBase { + private static final long serialVersionUID = -4038934296796872326L; + protected final Player player; + + public InputPassPriorityBase(Player p) { + this.player = p; + } + + final Runnable passPriority = new Runnable() { + @Override public void run() { + player.getController().passPriority(); + } + }; + + protected final void pass() { // no futher overloads possible + setFinished(); + + + if( FThreads.isEDT() ) + FThreads.invokeInNewThread(passPriority); + else + passPriority.run(); + } +} \ No newline at end of file diff --git a/src/main/java/forge/control/input/InputQueue.java b/src/main/java/forge/control/input/InputQueue.java index 9829e096223..56e4d90217f 100644 --- a/src/main/java/forge/control/input/InputQueue.java +++ b/src/main/java/forge/control/input/InputQueue.java @@ -100,6 +100,8 @@ public class InputQueue extends MyObservable implements java.io.Serializable { * a boolean. */ public final void removeInput(Input inp) { + FThreads.assertExecutedByEdt(false); + Input topMostInput = inputStack.isEmpty() ? null : inputStack.pop(); // StackTraceElement[] trace = Thread.currentThread().getStackTrace(); @@ -153,9 +155,9 @@ public class InputQueue extends MyObservable implements java.io.Serializable { switch (phase) { case COMBAT_DECLARE_ATTACKERS: stack.freezeStack(); - if (playerTurn.isHuman() && !playerTurn.getController().mayAutoPass(phase)) { + if (!playerTurn.getController().mayAutoPass(phase)) { game.getCombat().initiatePossibleDefenders(playerTurn.getOpponents()); - return new InputAttack(playerTurn); + return playerTurn.getController().getAttackInput(); } break; @@ -215,10 +217,10 @@ public class InputQueue extends MyObservable implements java.io.Serializable { } public void LockAndInvokeGameAction(final Runnable proc) { - this.lock(); Runnable toRun = new Runnable() { @Override public void run() { + InputQueue.this.lock(); proc.run(); InputQueue.this.unlock(); } diff --git a/src/main/java/forge/control/input/InputSyncronizedBase.java b/src/main/java/forge/control/input/InputSyncronizedBase.java index 4fd384c5bfa..f4fc63a8534 100644 --- a/src/main/java/forge/control/input/InputSyncronizedBase.java +++ b/src/main/java/forge/control/input/InputSyncronizedBase.java @@ -9,7 +9,7 @@ import forge.error.BugReporter; public abstract class InputSyncronizedBase extends InputBase implements InputSynchronized { private static final long serialVersionUID = 8756177361251703052L; - private boolean finished = false; + private final CountDownLatch cdlDone; @@ -26,33 +26,36 @@ public abstract class InputSyncronizedBase extends InputBase implements InputSyn } } - - @Override - protected void afterStop() { - finished = true; - cdlDone.countDown(); - } + protected final void stop() { + setFinished(); + FThreads.invokeInNewThread(new Runnable() { + @Override + public void run() { + getQueue().removeInput(InputSyncronizedBase.this); + cdlDone.countDown(); + } + }); + } @Override public final void selectButtonCancel() { - if( finished ) return; + if( isFinished() ) return; onCancel(); } @Override public final void selectButtonOK() { - if( finished ) return; + if( isFinished() ) return; onOk(); } @Override public final void selectCard(Card c, boolean isMetaDown) { - if( finished ) return; + if( isFinished() ) return; onCardSelected(c); } - protected final boolean isFinished() { return finished; } protected void onCardSelected(Card c) {} protected void onCancel() {} protected void onOk() {} diff --git a/src/main/java/forge/game/MatchController.java b/src/main/java/forge/game/MatchController.java index b72819d174b..9715e96b845 100644 --- a/src/main/java/forge/game/MatchController.java +++ b/src/main/java/forge/game/MatchController.java @@ -124,15 +124,15 @@ public class MatchController { } final Player firstPlayer = determineFirstTurnPlayer(getLastGameOutcome(), currentGame); - - currentGame.getInputQueue().clearInput(); - if(currentGame.getType() == GameType.Planechase) - firstPlayer.initPlane(); // This code was run from EDT. FThreads.invokeInNewThread( new Runnable() { @Override public void run() { + currentGame.getInputQueue().clearInput(); + if(currentGame.getType() == GameType.Planechase) + firstPlayer.initPlane(); + currentGame.getAction().mulligan(firstPlayer); } }); diff --git a/src/main/java/forge/game/ai/AiController.java b/src/main/java/forge/game/ai/AiController.java index 6672814f609..2a006e1a0af 100644 --- a/src/main/java/forge/game/ai/AiController.java +++ b/src/main/java/forge/game/ai/AiController.java @@ -848,7 +848,6 @@ public class AiController { break; } } - player.getController().passPriority(); } diff --git a/src/main/java/forge/game/ai/AiInputBlock.java b/src/main/java/forge/game/ai/AiInputBlock.java index 9f83f703efa..d0ad3643100 100644 --- a/src/main/java/forge/game/ai/AiInputBlock.java +++ b/src/main/java/forge/game/ai/AiInputBlock.java @@ -3,7 +3,7 @@ package forge.game.ai; import java.util.List; import forge.Card; -import forge.control.input.InputNonSyncBase; +import forge.control.input.InputPassPriorityBase; import forge.game.GameState; import forge.game.phase.CombatUtil; import forge.game.player.Player; @@ -12,7 +12,7 @@ import forge.game.player.Player; * TODO: Write javadoc for this type. * */ -public class AiInputBlock extends InputNonSyncBase { +public class AiInputBlock extends InputPassPriorityBase { private final GameState game; /** * TODO: Write javadoc for Constructor. @@ -32,9 +32,6 @@ public class AiInputBlock extends InputNonSyncBase { final List blockers = player.getCreaturesInPlay(); game.setCombat(ComputerUtilBlock.getBlockers(player, game.getCombat(), blockers)); CombatUtil.orderMultipleCombatants(game); - game.getPhaseHandler().setPlayersPriorityPermission(false); - - // was not added to stack, so will be replaced by plain update - game.getInputQueue().updateObservers(); + pass(); } } diff --git a/src/main/java/forge/game/ai/AiInputCommon.java b/src/main/java/forge/game/ai/AiInputCommon.java index 631a06fb7fc..08b8054b402 100644 --- a/src/main/java/forge/game/ai/AiInputCommon.java +++ b/src/main/java/forge/game/ai/AiInputCommon.java @@ -17,7 +17,7 @@ */ package forge.game.ai; -import forge.control.input.InputNonSyncBase; +import forge.control.input.InputPassPriorityBase; /** *

@@ -27,7 +27,7 @@ import forge.control.input.InputNonSyncBase; * @author Forge * @version $Id$ */ -public class AiInputCommon extends InputNonSyncBase implements AiInput { +public class AiInputCommon extends InputPassPriorityBase implements AiInput { /** Constant serialVersionUID=-3091338639571662216L. */ private static final long serialVersionUID = -3091338639571662216L; @@ -71,6 +71,7 @@ public class AiInputCommon extends InputNonSyncBase implements AiInput { @Override public void run() { computer.onPriorityRecieved(); + pass(); } }; } diff --git a/src/main/java/forge/game/phase/PhaseHandler.java b/src/main/java/forge/game/phase/PhaseHandler.java index fed39b0b5c4..753ea7c5991 100644 --- a/src/main/java/forge/game/phase/PhaseHandler.java +++ b/src/main/java/forge/game/phase/PhaseHandler.java @@ -232,29 +232,11 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { } public final void handleBeginPhase() { - this.setPhaseEffects(false); - if ( FThreads.isEDT() ) { - System.out.printf("Handle begin %s phase of %s turn from EDT%n", phase, playerTurn); - FThreads.invokeInNewThread(beginPhase); - } else { - beginPhase.run(); - } - } - - private final Runnable beginPhase = new Runnable() { @Override public void run() { - doBeginPhase(); - updateObservers(); - } }; - - /** - *

- * handleBeginPhase. - *

- */ - private final void doBeginPhase() { if (null == playerTurn) { return; } + this.setPhaseEffects(false); + // Handle effects that happen at the beginning of phases game.getAction().checkStateEffects(); @@ -263,7 +245,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { case UNTAP: //SDisplayUtil.showTab(EDocID.REPORT_STACK.getDoc()); game.getPhaseHandler().setPlayersPriorityPermission(false); - updateObservers(); + //updateObservers(); PhaseUtil.handleUntap(game); break; @@ -307,7 +289,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { if (playerTurn.isSkippingCombat()) { this.setPlayersPriorityPermission(false); playerTurn.removeKeyword("Skip your next combat phase."); - } + } /* else game.getInputQueue().setInput(playerTurn.getController().getAttackInput());*/ break; case COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY: @@ -836,8 +818,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { */ public final void setPhaseState(final PhaseType phase0) { this.phase = phase0; - this.setPhaseEffects(false); - this.doBeginPhase(); + this.handleBeginPhase(); } /** diff --git a/src/main/java/forge/game/player/PlayerController.java b/src/main/java/forge/game/player/PlayerController.java index 4edfc2b294c..59e627e78b4 100644 --- a/src/main/java/forge/game/player/PlayerController.java +++ b/src/main/java/forge/game/player/PlayerController.java @@ -45,6 +45,8 @@ public abstract class PlayerController { public abstract Input getDefaultInput(); public abstract Input getBlockInput(); public abstract Input getCleanupInput(); + public abstract Input getAttackInput(); + public final Input getAutoPassPriorityInput() { return autoPassPriorityInput; } /** diff --git a/src/main/java/forge/game/player/PlayerControllerAi.java b/src/main/java/forge/game/player/PlayerControllerAi.java index 82d7d1b05b9..e47cec4a10a 100644 --- a/src/main/java/forge/game/player/PlayerControllerAi.java +++ b/src/main/java/forge/game/player/PlayerControllerAi.java @@ -65,6 +65,11 @@ public class PlayerControllerAi extends PlayerController { return blockInput; } + @Override + public Input getAttackInput() { + return defaultInput; + } + /** * @return the cleanupInput */ diff --git a/src/main/java/forge/game/player/PlayerControllerHuman.java b/src/main/java/forge/game/player/PlayerControllerHuman.java index 84bfc0c99be..2a243adbc3e 100644 --- a/src/main/java/forge/game/player/PlayerControllerHuman.java +++ b/src/main/java/forge/game/player/PlayerControllerHuman.java @@ -19,6 +19,7 @@ import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; import forge.card.spellability.TargetSelection; import forge.control.input.Input; +import forge.control.input.InputAttack; import forge.control.input.InputBlock; import forge.control.input.InputCleanup; import forge.control.input.InputConfirmMulligan; @@ -67,6 +68,9 @@ public class PlayerControllerHuman extends PlayerController { return blockInput; } + @Override + public Input getAttackInput() { return new InputAttack(player); } + /** * @return the cleanupInput */ diff --git a/src/main/java/forge/game/zone/MagicStack.java b/src/main/java/forge/game/zone/MagicStack.java index afff4de221a..29aa1f118d5 100644 --- a/src/main/java/forge/game/zone/MagicStack.java +++ b/src/main/java/forge/game/zone/MagicStack.java @@ -522,7 +522,7 @@ public class MagicStack extends MyObservable implements Iterable 0) { + if (!this.getSimultaneousStackEntryList().isEmpty()) { game.getPhaseHandler().passPriority(); } } diff --git a/src/main/java/forge/gui/InputProxy.java b/src/main/java/forge/gui/InputProxy.java index 48c5ed4e1d6..45af0e9e25d 100644 --- a/src/main/java/forge/gui/InputProxy.java +++ b/src/main/java/forge/gui/InputProxy.java @@ -54,7 +54,8 @@ public class InputProxy implements Observer { @Override public final synchronized void update(final Observable observable, final Object obj) { //synchronized(this) {} // want to update all changes to memory - + FThreads.assertExecutedByEdt(false); + final PhaseHandler ph = game.getPhaseHandler(); if(INPUT_DEBUG) @@ -62,9 +63,8 @@ public class InputProxy implements Observer { if ( game.getInputQueue().isEmpty() && ph.hasPhaseEffects()) { if(INPUT_DEBUG) - System.out.printf("\t%s > handle begin phase during %s%n", FThreads.debugGetCurrThreadId(), ph.debugPrintState()); + System.out.printf("\t%s > handle begin phase for %s%n", FThreads.debugGetCurrThreadId(), ph.debugPrintState()); ph.handleBeginPhase(); - return; } final Input nextInput = game.getInputQueue().getActualInput();