diff --git a/src/main/java/forge/FThreads.java b/src/main/java/forge/FThreads.java index d15b3764e09..56b4fa3c965 100644 --- a/src/main/java/forge/FThreads.java +++ b/src/main/java/forge/FThreads.java @@ -107,5 +107,13 @@ public class FThreads { Singletons.getModel().getMatch().getInput().setInput(input); input.awaitLatchRelease(); } + + /** + * TODO: Write javadoc for this method. + * @return + */ + public static boolean isEDT() { + return SwingUtilities.isEventDispatchThread(); + } } diff --git a/src/main/java/forge/control/input/InputControl.java b/src/main/java/forge/control/input/InputControl.java index 5ef7ac4240c..98b87c34c3e 100644 --- a/src/main/java/forge/control/input/InputControl.java +++ b/src/main/java/forge/control/input/InputControl.java @@ -94,6 +94,10 @@ public class InputControl extends MyObservable implements java.io.Serializable { this.updateObservers(); } + public final boolean isEmpty() { + return inputStack.isEmpty(); + } + /** *
* updateInput. @@ -118,12 +122,6 @@ public class InputControl extends MyObservable implements java.io.Serializable { return this.inputStack.peek(); } - if (handler.hasPhaseEffects()) { - // Handle begin phase stuff, then start back from the top - handler.handleBeginPhase(); - return this.getActualInput(game); - } - // If the Phase we're in doesn't allow for Priority, return null to move // to next phase if (!handler.isPlayerPriorityAllowed()) { diff --git a/src/main/java/forge/control/input/InputPayment.java b/src/main/java/forge/control/input/InputPayment.java index 58f5dea23df..b166bf70fcf 100644 --- a/src/main/java/forge/control/input/InputPayment.java +++ b/src/main/java/forge/control/input/InputPayment.java @@ -1,5 +1,5 @@ package forge.control.input; -public interface InputPayment { +public interface InputPayment extends InputSynchronized { boolean isPaid(); } \ No newline at end of file diff --git a/src/main/java/forge/game/GameActionUtil.java b/src/main/java/forge/game/GameActionUtil.java index 096085342d2..f05ebc003ec 100644 --- a/src/main/java/forge/game/GameActionUtil.java +++ b/src/main/java/forge/game/GameActionUtil.java @@ -61,7 +61,6 @@ import forge.control.input.InputPayDiscardCostWithCommands; import forge.control.input.InputPayManaExecuteCommands; import forge.control.input.InputPayReturnCost; import forge.control.input.InputPayment; -import forge.control.input.InputSynchronized; import forge.game.event.CardDamagedEvent; import forge.game.event.LifeLossEvent; import forge.game.player.AIPlayer; @@ -575,7 +574,7 @@ public final class GameActionUtil { //the following costs need inputs and can't be combined at the moment - InputSynchronized toSet = null; + InputPayment toSet = null; if (costPart instanceof CostReturn) { toSet = new InputPayReturnCost((CostReturn) costPart, ability); } @@ -589,7 +588,7 @@ public final class GameActionUtil { if (toSet != null) { FThreads.setInputAndWait(toSet); - if (((InputPayment)toSet).isPaid() ) { + if (toSet.isPaid() ) { paid.execute(); } else { unpaid.execute(); diff --git a/src/main/java/forge/game/ai/AiInputBlock.java b/src/main/java/forge/game/ai/AiInputBlock.java index f21654dad34..341818aa4a8 100644 --- a/src/main/java/forge/game/ai/AiInputBlock.java +++ b/src/main/java/forge/game/ai/AiInputBlock.java @@ -3,6 +3,7 @@ package forge.game.ai; import java.util.List; import forge.Card; +import forge.Singletons; import forge.control.input.InputBase; import forge.game.GameState; import forge.game.phase.CombatUtil; @@ -38,6 +39,7 @@ public class AiInputBlock extends InputBase { CombatUtil.orderMultipleCombatants(game.getCombat()); game.getPhaseHandler().setPlayersPriorityPermission(false); - stop(); + // was not added to stack, so will be replaced by plain update + Singletons.getModel().getMatch().getInput().updateObservers(); } } diff --git a/src/main/java/forge/game/phase/PhaseHandler.java b/src/main/java/forge/game/phase/PhaseHandler.java index 9a847f8b644..e6561528d27 100644 --- a/src/main/java/forge/game/phase/PhaseHandler.java +++ b/src/main/java/forge/game/phase/PhaseHandler.java @@ -24,6 +24,7 @@ import java.util.Stack; import com.esotericsoftware.minlog.Log; import forge.Card; +import forge.FThreads; import forge.Singletons; import forge.card.trigger.TriggerType; import forge.game.GameState; @@ -399,7 +400,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { // This line fixes Combat Damage triggers not going off when they should game.getStack().unfreezeStack(); - + // UNTAP if (this.getPhase() != PhaseType.UNTAP) { // during untap @@ -734,7 +735,17 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { nextPhase(); return; } else if (!game.getStack().hasSimultaneousStackEntries()) { - game.getStack().resolveStack(); + Runnable proc = new Runnable(){ + @Override public void run() { + game.getStack().resolveStack(); + game.getStack().chooseOrderOfSimultaneousStackEntryAll(); + } + }; + + if ( FThreads.isEDT() ) + FThreads.invokeInNewThread(proc, true); + else + proc.run(); } } else { // pass the priority to other player @@ -742,7 +753,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { Singletons.getModel().getMatch().getInput().updateObservers(); } - game.getStack().chooseOrderOfSimultaneousStackEntryAll(); + } /** diff --git a/src/main/java/forge/gui/InputProxy.java b/src/main/java/forge/gui/InputProxy.java index 1327a4c49c7..df312f47f3a 100644 --- a/src/main/java/forge/gui/InputProxy.java +++ b/src/main/java/forge/gui/InputProxy.java @@ -50,12 +50,23 @@ public class InputProxy implements Observer { @Override public final synchronized void update(final Observable observable, final Object obj) { ButtonUtil.disableAll(); - GameState game = match.getCurrentGame(); - PhaseHandler ph = game.getPhaseHandler(); + final GameState game = match.getCurrentGame(); + final PhaseHandler ph = game.getPhaseHandler(); + + //System.out.print((FThreads.isEDT() ? "EDT > " : "TRD > ") + ph.debugPrintState()); + if ( match.getInput().isEmpty() && ph.hasPhaseEffects()) { + //System.out.println(" handle begin phase"); + FThreads.invokeInNewThread(new Runnable() { + @Override public void run() { + ph.handleBeginPhase(); + update(observable, obj); + } + }, true); + return; + } final Input nextInput = match.getInput().getActualInput(game); - System.out.print(ph.debugPrintState()); - System.out.printf(" input is %s \t stack = %s%n", nextInput == null ? "null" : nextInput.getClass().getSimpleName(), match.getInput().printInputStack()); + //System.out.printf(" input is %s \t stack = %s%n", nextInput == null ? "null" : nextInput.getClass().getSimpleName(), match.getInput().printInputStack()); if (nextInput != null) { this.input = nextInput;