diff --git a/src/main/java/forge/control/input/InputQueue.java b/src/main/java/forge/control/input/InputQueue.java index 96a21036da9..ebb7929798b 100644 --- a/src/main/java/forge/control/input/InputQueue.java +++ b/src/main/java/forge/control/input/InputQueue.java @@ -43,14 +43,10 @@ public class InputQueue extends MyObservable implements java.io.Serializable { private static final long serialVersionUID = 3955194449319994301L; private final BlockingDeque inputStack = new LinkedBlockingDeque(); - private final GameState game; - - private final InputLockUI inputLock; - public InputQueue(GameState game0) { - game = game0; + public InputQueue() { inputLock = new InputLockUI(this); } @@ -80,17 +76,6 @@ public class InputQueue extends MyObservable implements java.io.Serializable { return inputStack.isEmpty() ? null : this.inputStack.peek(); } - /** - *

- * clearInput. - *

- */ - public final void clearInput() { - this.inputStack.clear(); - this.updateObservers(); - } - - /** *

* resetInput. @@ -101,19 +86,11 @@ public class InputQueue extends MyObservable implements java.io.Serializable { */ final void removeInput(Input inp) { FThreads.assertExecutedByEdt(false); - Input topMostInput = inputStack.isEmpty() ? null : inputStack.pop(); - -// StackTraceElement[] trace = Thread.currentThread().getStackTrace(); -// System.out.printf("%s > Remove input %s -- called from %s%n", FThreads.isEDT() ? "EDT" : "TRD", topMostInput, trace[2].toString()); -// if( trace[2].toString().contains("InputBase.stop")) -// for(StackTraceElement se : trace) { -// System.out.println(se.toString()); -// } - + if( topMostInput != inp ) throw new RuntimeException("Inputs adding/removal into stack is imbalanced! Check your code again!"); - + this.updateObservers(); } @@ -128,7 +105,7 @@ public class InputQueue extends MyObservable implements java.io.Serializable { * * @return a {@link forge.control.input.InputBase} object. */ - public final Input getActualInput() { + public final Input getActualInput(GameState game) { GameAge age = game.getAge(); if ( game.isGameOver() ) @@ -142,7 +119,7 @@ public class InputQueue extends MyObservable implements java.io.Serializable { return inputLock; final PhaseHandler handler = game.getPhaseHandler(); - final PhaseType phase = handler.getPhase(); + final Player playerTurn = handler.getPlayerTurn(); final Player priority = handler.getPriorityPlayer(); if (priority == null) @@ -155,6 +132,7 @@ public class InputQueue extends MyObservable implements java.io.Serializable { } // Special Inputs needed for the following phases: + final PhaseType phase = handler.getPhase(); final MagicStack stack = game.getStack(); switch (phase) { case COMBAT_DECLARE_ATTACKERS: @@ -168,12 +146,8 @@ public class InputQueue extends MyObservable implements java.io.Serializable { case COMBAT_DECLARE_BLOCKERS: stack.freezeStack(); - if (game.getCombat().isPlayerAttacked(priority)) { - return pc.getBlockInput(); - } - - // noone attacks you - return pc.getAutoPassPriorityInput(); + boolean isAttacked = game.getCombat().isPlayerAttacked(priority); + return isAttacked ? pc.getBlockInput() : pc.getAutoPassPriorityInput(); case CLEANUP: // discard diff --git a/src/main/java/forge/game/GameAction.java b/src/main/java/forge/game/GameAction.java index 03c7ef7fb02..e7a9883ac40 100644 --- a/src/main/java/forge/game/GameAction.java +++ b/src/main/java/forge/game/GameAction.java @@ -1476,12 +1476,16 @@ public class GameAction { public void mulligan(final Player firstPlayer) { performMulligans(firstPlayer, game.getType() == GameType.Commander); - handleLeylinesAndChancellors(); - // Run Trigger beginning of the game - final HashMap runParams = new HashMap(); - game.getTriggerHandler().runTrigger(TriggerType.NewGame, runParams, false); game.setAge(GameAge.Play); - game.getInputQueue().clearInput(); + + // THIS CODE WILL WORK WITH PHASE = NULL { + handleLeylinesAndChancellors(); + // Run Trigger beginning of the game + final HashMap runParams = new HashMap(); + game.getTriggerHandler().runTrigger(TriggerType.NewGame, runParams, false); + // } + + game.getPhaseHandler().startFirstTurn(firstPlayer); } private void performMulligans(final Player firstPlayer, final boolean isCommander) { diff --git a/src/main/java/forge/game/GameState.java b/src/main/java/forge/game/GameState.java index 38964f39ca9..228dc7dbc66 100644 --- a/src/main/java/forge/game/GameState.java +++ b/src/main/java/forge/game/GameState.java @@ -89,7 +89,7 @@ public class GameState { private final MatchController match; private GameAge age = GameAge.BeforeMulligan; - private final InputQueue inputQueue; + private final InputQueue inputQueue = new InputQueue(); /** * Constructor. @@ -128,8 +128,6 @@ public class GameState { endOfTurn = new EndOfTurn(this); endOfCombat = new EndOfCombat(this); - inputQueue = new InputQueue(this); - if ( match0.getGameType() == GameType.Quest) events.register(Singletons.getModel().getQuest()); // this one listens to player's mulligans ATM diff --git a/src/main/java/forge/game/MatchController.java b/src/main/java/forge/game/MatchController.java index 770ce189bb6..50bd5e7e5f1 100644 --- a/src/main/java/forge/game/MatchController.java +++ b/src/main/java/forge/game/MatchController.java @@ -132,7 +132,6 @@ public class MatchController { currentGame.getInputQueue().invokeGameAction(new Runnable() { @Override public void run() { - currentGame.getInputQueue().clearInput(); if(currentGame.getType() == GameType.Planechase) firstPlayer.initPlane(); @@ -266,7 +265,6 @@ public class MatchController { boolean willPlay = goesFirst.getController().getWillPlayOnFirstTurn(message); goesFirst = willPlay ? goesFirst : goesFirst.getOpponent(); - game.getPhaseHandler().setPlayerTurn(goesFirst); return goesFirst; } diff --git a/src/main/java/forge/game/phase/PhaseHandler.java b/src/main/java/forge/game/phase/PhaseHandler.java index e2d5090c1ba..d64b1a68ee8 100644 --- a/src/main/java/forge/game/phase/PhaseHandler.java +++ b/src/main/java/forge/game/phase/PhaseHandler.java @@ -56,9 +56,10 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { /** Constant serialVersionUID=5207222278370963197L. */ private static final long serialVersionUID = 5207222278370963197L; - private PhaseType phase = PhaseType.UNTAP; - private int turn = 1; - // Start turn at 1, since first untap is where we start + // Start turn at 0, since we start even before first untap + private PhaseType phase = null; + private int turn = 0; + private final transient Stack extraTurns = new Stack(); private final transient Map> extraPhases = new HashMap>(); @@ -232,38 +233,39 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { p.updateObservers(); } - switch (this.phase) { - case UNTAP: - this.nCombatsThisTurn = 0; - break; - - case COMBAT_DECLARE_ATTACKERS: - game.getStack().unfreezeStack(); - this.nCombatsThisTurn++; - break; - - case COMBAT_DECLARE_BLOCKERS: - game.getStack().unfreezeStack(); - break; - - case COMBAT_END: - //SDisplayUtil.showTab(EDocID.REPORT_STACK.getDoc()); - game.getCombat().reset(playerTurn); - this.getPlayerTurn().resetAttackedThisCombat(); - this.bCombat.set(false); - - break; - - case CLEANUP: - this.bPreventCombatDamageThisTurn = false; - if (!this.bRepeatCleanup) { - this.setPlayerTurn(this.handleNextTurn()); - } - this.planarDiceRolledthisTurn = 0; - // Play the End Turn sound - game.getEvents().post(new EndOfTurnEvent()); - break; - default: // no action + if( phase != null ) { + switch (this.phase) { + case UNTAP: + this.nCombatsThisTurn = 0; + break; + + case COMBAT_DECLARE_ATTACKERS: + game.getStack().unfreezeStack(); + this.nCombatsThisTurn++; + break; + + case COMBAT_DECLARE_BLOCKERS: + game.getStack().unfreezeStack(); + break; + + case COMBAT_END: + game.getCombat().reset(playerTurn); + this.getPlayerTurn().resetAttackedThisCombat(); + this.bCombat.set(false); + + break; + + case CLEANUP: + this.bPreventCombatDamageThisTurn = false; + if (!this.bRepeatCleanup) { + this.setPlayerTurn(this.handleNextTurn()); + } + this.planarDiceRolledthisTurn = 0; + // Play the End Turn sound + game.getEvents().post(new EndOfTurnEvent()); + break; + default: // no action + } } String phaseType = ""; @@ -283,7 +285,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { this.phase = nextPhase; phaseType = "Additional "; } else { - this.phase = phase.getNextPhase(); + this.phase = PhaseType.getNext(phase); } } @@ -712,15 +714,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { // System.out.println(String.format("%s %s: %s passes priority to %s", playerTurn, phase, actingPlayer, nextPlayer)); if (firstAction.equals(nextPlayer)) { if (game.getStack().isEmpty()) { - this.setPriority(this.getPlayerTurn()); // this needs to be set early as we exit the phase - // end phase - setPlayersPriorityPermission(true); - nextPhase(); - // When consecutively skipping phases (like in combat) this section - // pushes through that block - handleBeginPhase(); - // it no longer does. - updateObservers(); + advancePhase(); } else if (!game.getStack().hasSimultaneousStackEntries()) { game.getStack().resolveStack(); game.getStack().chooseOrderOfSimultaneousStackEntryAll(); @@ -733,6 +727,26 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { } } + + public void startFirstTurn(Player goesFirst) { + if(phase != null) + throw new IllegalStateException("Turns already started, call this only once per game"); + setPlayerTurn(goesFirst); + advancePhase(); + } + + private void advancePhase() { // may be called externally only from gameAction after mulligans + + this.setPriority(this.getPlayerTurn()); // this needs to be set early as we exit the phase + // end phase + setPlayersPriorityPermission(true); + nextPhase(); + // When consecutively skipping phases (like in combat) this section + // pushes through that block + handleBeginPhase(); + // it no longer does. + updateObservers(); + } /** *

diff --git a/src/main/java/forge/game/phase/PhaseType.java b/src/main/java/forge/game/phase/PhaseType.java index a75cc138b06..d3f3693faea 100644 --- a/src/main/java/forge/game/phase/PhaseType.java +++ b/src/main/java/forge/game/phase/PhaseType.java @@ -106,9 +106,9 @@ public enum PhaseType { * Get the next PhaseType in turn order. * @return */ - public PhaseType getNextPhase() { - int iNext = ALL_PHASES.indexOf(this) + 1; - while (iNext >= ALL_PHASES.size()) { + public static PhaseType getNext(PhaseType current) { + int iNext = ALL_PHASES.indexOf(current) + 1; + if (iNext >= ALL_PHASES.size()) { iNext = 0; } return ALL_PHASES.get(iNext); diff --git a/src/main/java/forge/gui/InputProxy.java b/src/main/java/forge/gui/InputProxy.java index 702db29bcf7..bd07228e212 100644 --- a/src/main/java/forge/gui/InputProxy.java +++ b/src/main/java/forge/gui/InputProxy.java @@ -43,11 +43,10 @@ public class InputProxy implements Observer { private AtomicReference input = new AtomicReference(); private GameState game = null; - private static final boolean INPUT_DEBUG = false; + private static final boolean DEBUG_INPUT = false; public void setGame(GameState game0) { game = game0; - // game.getStack().addObserver(this); game.getPhaseHandler().addObserver(this); game.getInputQueue().addObserver(this); } @@ -58,19 +57,15 @@ public class InputProxy implements Observer { FThreads.assertExecutedByEdt(false); final PhaseHandler ph = game.getPhaseHandler(); - final Input nextInput = game.getInputQueue().getActualInput(); + final Input nextInput = game.getInputQueue().getActualInput(game); - - if(INPUT_DEBUG) { - System.out.print(FThreads.debugGetStackTraceItem(6, true) + " ... "); - System.out.printf("\t%s on %s, \tstack = %s%n", nextInput == null ? "null" : nextInput.getClass().getSimpleName(), ph.debugPrintState(), game.getInputQueue().printInputStack()); - } + if(DEBUG_INPUT) + System.out.printf("%s ... \t%s on %s, \tstack = %s%n", FThreads.debugGetStackTraceItem(6, true), nextInput == null ? "null" : nextInput.getClass().getSimpleName(), ph.debugPrintState(), game.getInputQueue().printInputStack()); this.input.set(nextInput); Runnable showMessage = new Runnable() { @Override public void run() { - //if(INPUT_DEBUG) - // System.out.printf("%s > showMessage @ %s/%s during %s%n%n", FThreads.debugGetCurrThreadId(), nextInput.getClass().getSimpleName(), getInput().getClass().getSimpleName(), ph.debugPrintState()); + // System.out.printf("%s > showMessage @ %s/%s during %s%n%n", FThreads.debugGetCurrThreadId(), nextInput.getClass().getSimpleName(), getInput().getClass().getSimpleName(), ph.debugPrintState()); getInput().showMessage(game.getInputQueue()); } };