diff --git a/.gitattributes b/.gitattributes index abca738a842..dc26207456b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -13820,6 +13820,7 @@ src/main/java/forge/control/bazaar/ControlStall.java -text src/main/java/forge/control/bazaar/package-info.java svneol=native#text/plain src/main/java/forge/control/input/Input.java -text src/main/java/forge/control/input/InputAttack.java svneol=native#text/plain +src/main/java/forge/control/input/InputAutoPassPriority.java -text src/main/java/forge/control/input/InputBase.java svneol=native#text/plain src/main/java/forge/control/input/InputBlock.java svneol=native#text/plain src/main/java/forge/control/input/InputCleanup.java svneol=native#text/plain diff --git a/src/main/java/forge/FThreads.java b/src/main/java/forge/FThreads.java index 1c0a0aaa86a..8ca661eb834 100644 --- a/src/main/java/forge/FThreads.java +++ b/src/main/java/forge/FThreads.java @@ -123,5 +123,9 @@ public class FThreads { public static void delay(int milliseconds, Runnable inputUpdater) { getScheduledPool().schedule(inputUpdater, milliseconds, TimeUnit.MILLISECONDS); } + + public static String debugGetCurrThreadId() { + return isEDT() ? "EDT" : Long.toString(Thread.currentThread().getId()); + } } diff --git a/src/main/java/forge/card/cost/CostPartMana.java b/src/main/java/forge/card/cost/CostPartMana.java index 7385fbe8c57..bf9c65aecb4 100644 --- a/src/main/java/forge/card/cost/CostPartMana.java +++ b/src/main/java/forge/card/cost/CostPartMana.java @@ -223,7 +223,7 @@ public class CostPartMana extends CostPart { } if (this.getAmountOfX() > 0) { source.setXManaCostPaid(0); - InputPayment inpPayment = new InputPayManaX(game, ability, this.getAmountOfX(), this.canXbe0()); + InputPayment inpPayment = new InputPayManaX(ability, this.getAmountOfX(), this.canXbe0()); FThreads.setInputAndWait(inpPayment); if(!inpPayment.isPaid()) return false; diff --git a/src/main/java/forge/card/cost/CostTapType.java b/src/main/java/forge/card/cost/CostTapType.java index 26969477c28..29024f70249 100644 --- a/src/main/java/forge/card/cost/CostTapType.java +++ b/src/main/java/forge/card/cost/CostTapType.java @@ -23,83 +23,21 @@ import forge.Card; import forge.CardLists; import forge.CardPredicates.Presets; import forge.FThreads; -import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.spellability.SpellAbility; -import forge.control.input.InputPayment; +import forge.control.input.InputSelectCards; +import forge.control.input.InputSelectCardsFromList; import forge.game.GameState; import forge.game.ai.ComputerUtil; import forge.game.player.AIPlayer; import forge.game.player.Player; -import forge.game.zone.Zone; import forge.game.zone.ZoneType; -import forge.view.ButtonUtil; /** * The Class CostTapType. */ public class CostTapType extends CostPartWithList { - /** - * TODO: Write javadoc for this type. - * - */ - public static final class InputPayCostTapType extends InputPayCostBase { - private final CostTapType tapType; - private final int nCards; - private final List cardList; - private static final long serialVersionUID = 6438988130447851042L; - private int nTapped = 0; - - /** - * TODO: Write javadoc for Constructor. - * @param sa - * @param tapType - * @param nCards - * @param cardList - * @param payment - */ - public InputPayCostTapType(CostTapType tapType, int nCards, List cardList) { - this.tapType = tapType; - this.nCards = nCards; - this.cardList = cardList; - } - - @Override - public void showMessage() { - - final int left = nCards - this.nTapped; - showMessage("Select a " + tapType.getDescription() + " to tap (" + left + " left)"); - ButtonUtil.enableOnlyCancel(); - if (nCards == 0) { - this.done(); - } - } - - - - @Override - public void selectCard(final Card card) { - Zone zone = Singletons.getModel().getGame().getZoneOf(card); - if (zone.is(ZoneType.Battlefield) && cardList.contains(card) && card.isUntapped()) { - // send in List for Typing - tapType.executePayment(null, card); - cardList.remove(card); - - this.nTapped++; - - if (this.nTapped == nCards) { - this.done(); - } else if (cardList.size() == 0) { - // happen - this.cancel(); - } else { - this.showMessage(); - } - } - } - } - private final boolean canTapSource; /** @@ -214,9 +152,15 @@ public class CostTapType extends CostPartWithList { c = AbilityUtils.calculateAmount(source, amount, ability); } } - InputPayment inp = new InputPayCostTapType(this, c, typeList); + + + InputSelectCards inp = new InputSelectCardsFromList(c, c, typeList); + inp.setMessage("Select a " + getDescription() + " to tap (%d left)"); FThreads.setInputAndWait(inp); - return inp.isPaid(); + if ( inp.hasCancelled() ) + return false; + + return executePayment(ability, inp.getSelected()); } /* (non-Javadoc) diff --git a/src/main/java/forge/card/cost/InputPayCostBase.java b/src/main/java/forge/card/cost/InputPayCostBase.java index 00847b3c488..33c65bff7b3 100644 --- a/src/main/java/forge/card/cost/InputPayCostBase.java +++ b/src/main/java/forge/card/cost/InputPayCostBase.java @@ -1,5 +1,6 @@ package forge.card.cost; +import forge.Singletons; import forge.control.input.InputPayment; import forge.control.input.InputSyncronizedBase; @@ -8,6 +9,14 @@ import forge.control.input.InputSyncronizedBase; * */ abstract class InputPayCostBase extends InputSyncronizedBase implements InputPayment { + /** + * TODO: Write javadoc for Constructor. + * @param player + */ + public InputPayCostBase() { + super(Singletons.getControl().getPlayer()); + } + private static final long serialVersionUID = -2967434867139585579L; boolean bPaid = false; diff --git a/src/main/java/forge/card/spellability/TargetSelection.java b/src/main/java/forge/card/spellability/TargetSelection.java index 4f8185c312e..b1952e2b120 100644 --- a/src/main/java/forge/card/spellability/TargetSelection.java +++ b/src/main/java/forge/card/spellability/TargetSelection.java @@ -71,6 +71,7 @@ public class TargetSelection { * @param mandatory */ public InputSelectTargets(TargetSelection select, List choices, ArrayList alreadyTargeted, boolean targeted, Target tgt, SpellAbility sa, boolean mandatory) { + super(sa.getActivatingPlayer()); this.select = select; this.choices = choices; this.alreadyTargeted = alreadyTargeted; diff --git a/src/main/java/forge/control/input/InputAttack.java b/src/main/java/forge/control/input/InputAttack.java index 5a6d05d1631..ae75e889a74 100644 --- a/src/main/java/forge/control/input/InputAttack.java +++ b/src/main/java/forge/control/input/InputAttack.java @@ -47,8 +47,9 @@ public class InputAttack extends InputBase { private static final long serialVersionUID = 7849903731842214245L; private final GameState game; - public InputAttack(GameState game0) { - game = game0; + public InputAttack(Player human) { + super(human); + game = human.getGame(); } diff --git a/src/main/java/forge/control/input/InputAutoPassPriority.java b/src/main/java/forge/control/input/InputAutoPassPriority.java new file mode 100644 index 00000000000..d3244abc907 --- /dev/null +++ b/src/main/java/forge/control/input/InputAutoPassPriority.java @@ -0,0 +1,21 @@ +package forge.control.input; + +import forge.game.player.Player; + +/** + * TODO: Write javadoc for this type. + * + */ +public class InputAutoPassPriority extends InputBase { + private static final long serialVersionUID = -7520803307255234647L; + + public InputAutoPassPriority(Player player) { + super(player); + } + + @Override + public void showMessage() { + passPriority(); + } + +} diff --git a/src/main/java/forge/control/input/InputBase.java b/src/main/java/forge/control/input/InputBase.java index f835e028ab3..d3da28bee70 100644 --- a/src/main/java/forge/control/input/InputBase.java +++ b/src/main/java/forge/control/input/InputBase.java @@ -18,6 +18,7 @@ package forge.control.input; import forge.Card; +import forge.FThreads; import forge.Singletons; import forge.game.player.Player; import forge.gui.match.CMatchUI; @@ -33,7 +34,11 @@ import forge.gui.match.CMatchUI; public abstract class InputBase implements java.io.Serializable, Input { /** Constant serialVersionUID=-6539552513871194081L. */ private static final long serialVersionUID = -6539552513871194081L; - + protected final Player player; + public InputBase(Player player) { + this.player = player; + } + // showMessage() is always the first method called @Override public abstract void showMessage(); @@ -64,4 +69,18 @@ public abstract class InputBase implements java.io.Serializable, Input { } protected void afterStop() { } + + + + protected void passPriority() { + final Runnable pass = new Runnable() { + @Override public void run() { + player.getController().passPriority(); + } + }; + if( FThreads.isEDT() ) + FThreads.invokeInNewThread(pass, true); + else + pass.run(); + } } \ No newline at end of file diff --git a/src/main/java/forge/control/input/InputBlock.java b/src/main/java/forge/control/input/InputBlock.java index e2f172403bf..29ad874a3c0 100644 --- a/src/main/java/forge/control/input/InputBlock.java +++ b/src/main/java/forge/control/input/InputBlock.java @@ -23,7 +23,6 @@ import java.util.List; import forge.Card; import forge.Singletons; -import forge.control.FControl; import forge.game.GameState; import forge.game.phase.CombatUtil; import forge.game.player.Player; @@ -48,14 +47,13 @@ public class InputBlock extends InputBase { private Card currentAttacker = null; private final HashMap> allBlocking = new HashMap>(); - private final Player defender; /** * TODO: Write javadoc for Constructor. * @param priority */ - public InputBlock(Player priority) { - defender = priority; + public InputBlock(Player human) { + super(human); } /** @@ -98,14 +96,14 @@ public class InputBlock extends InputBase { @Override public final void selectButtonOK() { final GameState game = Singletons.getModel().getGame(); - if (CombatUtil.finishedMandatoryBlocks(game.getCombat(), defender)) { + if (CombatUtil.finishedMandatoryBlocks(game.getCombat(), player)) { // Done blocking ButtonUtil.reset(); CombatUtil.orderMultipleCombatants(game.getCombat()); currentAttacker = null; allBlocking.clear(); - FControl.SINGLETON_INSTANCE.getPlayer().getController().passPriority(); + passPriority(); } } @@ -121,8 +119,8 @@ public class InputBlock extends InputBase { } else { Zone zone = Singletons.getModel().getGame().getZoneOf(card); // Make sure this card is valid to even be a blocker - if (this.currentAttacker != null && card.isCreature() && card.getController().equals(defender) - && zone.is(ZoneType.Battlefield, defender)) { + if (this.currentAttacker != null && card.isCreature() && card.getController().equals(player) + && zone.is(ZoneType.Battlefield, player)) { // Create a new blockedBy list if it doesn't exist if (!this.allBlocking.containsKey(card)) { this.allBlocking.put(card, new ArrayList()); diff --git a/src/main/java/forge/control/input/InputCleanup.java b/src/main/java/forge/control/input/InputCleanup.java index 5e8f98fddbb..0f0f21c4ef5 100644 --- a/src/main/java/forge/control/input/InputCleanup.java +++ b/src/main/java/forge/control/input/InputCleanup.java @@ -24,7 +24,6 @@ import forge.game.GameState; import forge.game.player.Player; import forge.game.zone.Zone; import forge.game.zone.ZoneType; -import forge.gui.match.CMatchUI; import forge.view.ButtonUtil; /** @@ -44,9 +43,9 @@ public class InputCleanup extends InputBase { * TODO: Write javadoc for Constructor. * @param game */ - public InputCleanup(GameState game) { - super(); - this.game = game; + public InputCleanup(Player player) { + super(player); + this.game = player.getGame(); } /** {@inheritDoc} */ @@ -59,7 +58,7 @@ public class InputCleanup extends InputBase { final int max = active.getMaxHandSize(); // goes to the next phase if (active.isUnlimitedHandSize() || n <= max || n <= 0 || active != turnOwner) { - active.getController().passPriority(); + passPriority(); return; } ButtonUtil.disableAll(); @@ -69,7 +68,7 @@ public class InputCleanup extends InputBase { final StringBuffer sb = new StringBuffer(); sb.append("Cleanup Phase: You can only have a maximum of ").append(max); sb.append(" cards, you currently have ").append(n).append(" cards in your hand - select a card to discard"); - CMatchUI.SINGLETON_INSTANCE.showMessage(sb.toString()); + showMessage(sb.toString()); } /** {@inheritDoc} */ diff --git a/src/main/java/forge/control/input/InputControl.java b/src/main/java/forge/control/input/InputControl.java index a2be674d7e9..cba5c1c743e 100644 --- a/src/main/java/forge/control/input/InputControl.java +++ b/src/main/java/forge/control/input/InputControl.java @@ -19,6 +19,7 @@ package forge.control.input; import java.util.Stack; +import forge.Singletons; import forge.game.GameState; import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseType; @@ -115,38 +116,37 @@ public class InputControl extends MyObservable implements java.io.Serializable { */ public final Input getActualInput(GameState game) { if ( !game.hasMulliganned() ) - return new InputMulligan(); + return new InputMulligan(Singletons.getModel().getMatch(), Singletons.getControl().getPlayer()); final PhaseHandler handler = game.getPhaseHandler(); final PhaseType phase = handler.getPhase(); final Player playerTurn = handler.getPlayerTurn(); final Player priority = handler.getPriorityPlayer(); - final MagicStack stack = game.getStack(); + if (priority == null) + throw new RuntimeException("No player has priority!"); + PlayerController pc = priority.getController(); + + - - // TODO this resolving portion needs more work, but fixes Death Cloud - // issues if (!this.inputStack.isEmpty()) { // incoming input to Control return this.inputStack.peek(); } - // If the Phase we're in doesn't allow for Priority, return null to move - // to next phase + + + // If the Phase we're in doesn't allow for Priority, move to next phase if (!handler.isPlayerPriorityAllowed()) { - return null; + return pc.getAutoPassPriorityInput(); } - if (priority == null) - return null; - PlayerController pc = priority.getController(); - // Special Inputs needed for the following phases: + final MagicStack stack = game.getStack(); switch (phase) { case COMBAT_DECLARE_ATTACKERS: stack.freezeStack(); if (playerTurn.isHuman() && !playerTurn.getController().mayAutoPass(phase)) { game.getCombat().initiatePossibleDefenders(playerTurn.getOpponents()); - return new InputAttack(game); + return new InputAttack(playerTurn); } break; @@ -158,8 +158,7 @@ public class InputControl extends MyObservable implements java.io.Serializable { } // noone attacks you - pc.passPriority(); - return null; + return pc.getAutoPassPriorityInput(); case CLEANUP: // discard @@ -176,10 +175,9 @@ public class InputControl extends MyObservable implements java.io.Serializable { // Special phases handled above, everything else is handled simply by // priority - boolean prioritySkip = pc.mayAutoPass(phase) || pc.isUiSetToSkipPhase(playerTurn, phase); - if (game.getStack().isEmpty() && prioritySkip) { - pc.passPriority(); - return null; + boolean maySkipPriority = pc.mayAutoPass(phase) || pc.isUiSetToSkipPhase(playerTurn, phase); + if (game.getStack().isEmpty() && maySkipPriority) { + return pc.getAutoPassPriorityInput(); } else pc.autoPassCancel(); // probably cancel, since something has happened diff --git a/src/main/java/forge/control/input/InputLockUI.java b/src/main/java/forge/control/input/InputLockUI.java index 2fb4c2eba7e..5beace5ed26 100644 --- a/src/main/java/forge/control/input/InputLockUI.java +++ b/src/main/java/forge/control/input/InputLockUI.java @@ -2,16 +2,18 @@ package forge.control.input; import java.util.concurrent.atomic.AtomicInteger; +import forge.Card; import forge.FThreads; +import forge.Singletons; +import forge.game.player.Player; +import forge.gui.match.CMatchUI; import forge.view.ButtonUtil; /** * TODO: Write javadoc for this type. * */ -public class InputLockUI extends InputBase { - private static final long serialVersionUID = 5777143577098597374L; - +public class InputLockUI implements Input { private final AtomicInteger iCall = new AtomicInteger(); public void showMessage() { @@ -47,5 +49,18 @@ public class InputLockUI extends InputBase { showMessage("Waiting for actions..."); } }; + + protected final boolean isActive() { + return Singletons.getModel().getMatch().getInput().getInput() == this; + } + + protected void showMessage(String message) { + CMatchUI.SINGLETON_INSTANCE.showMessage(message); + } + + @Override public void selectCard(Card c) {} + @Override public void selectPlayer(Player player) {} + @Override public void selectButtonOK() {} + @Override public void selectButtonCancel() {} } diff --git a/src/main/java/forge/control/input/InputMulligan.java b/src/main/java/forge/control/input/InputMulligan.java index ed7b64ffab9..be6961b84b8 100644 --- a/src/main/java/forge/control/input/InputMulligan.java +++ b/src/main/java/forge/control/input/InputMulligan.java @@ -24,12 +24,13 @@ import com.google.common.collect.Iterables; import forge.Card; import forge.CardPredicates; -import forge.Singletons; +import forge.FThreads; import forge.card.ability.AbilityFactory; import forge.card.spellability.SpellAbility; import forge.game.GameAction; import forge.game.GameState; import forge.game.GameType; +import forge.game.MatchController; import forge.game.ai.ComputerUtil; import forge.game.player.AIPlayer; import forge.game.player.Player; @@ -52,22 +53,28 @@ import forge.view.ButtonUtil; public class InputMulligan extends InputBase { /** Constant serialVersionUID=-8112954303001155622L. */ private static final long serialVersionUID = -8112954303001155622L; - + + private final MatchController match; + + public InputMulligan(MatchController match0, Player humanPlayer) { + super(humanPlayer); + match = match0; + } + /** {@inheritDoc} */ @Override public final void showMessage() { ButtonUtil.setButtonText("No", "Yes"); ButtonUtil.enableAllFocusOk(); - GameState game = Singletons.getModel().getGame(); + GameState game = match.getCurrentGame(); Player startingPlayer = game.getPhaseHandler().getPlayerTurn(); - Player localPlayer = Singletons.getControl().getPlayer(); StringBuilder sb = new StringBuilder(); sb.append(startingPlayer.getName()).append(" is going first. "); - if (!startingPlayer.equals(localPlayer)) { - sb.append("You are going ").append(game.getOrdinalPosition(localPlayer, startingPlayer)).append(". "); + if (!startingPlayer.equals(player)) { + sb.append("You are going ").append(game.getOrdinalPosition(player, startingPlayer)).append(". "); } sb.append("Do you want to Mulligan?"); @@ -83,10 +90,9 @@ public class InputMulligan extends InputBase { /** {@inheritDoc} */ @Override public final void selectButtonCancel() { - final Player humanPlayer = Singletons.getControl().getPlayer(); - humanPlayer.doMulligan(); + player.doMulligan(); - if (humanPlayer.getCardsIn(ZoneType.Hand).isEmpty()) { + if (player.getCardsIn(ZoneType.Hand).isEmpty()) { this.end(); } else { ButtonUtil.enableAllFocusOk(); @@ -94,9 +100,9 @@ public class InputMulligan extends InputBase { } final void end() { - GameState game = Singletons.getModel().getGame(); // Computer mulligan + final GameState game = match.getCurrentGame(); for (Player p : game.getPlayers()) { if (!(p instanceof AIPlayer)) { continue; @@ -173,17 +179,22 @@ public class InputMulligan extends InputBase { SDisplayUtil.showTab(nextField); game.setMulliganned(true); - Singletons.getModel().getMatch().getInput().clearInput(); + FThreads.invokeInNewThread( new Runnable() { + @Override + public void run() { + match.getInput().clearInput(); + } + }); } @Override public void selectCard(Card c0) { - Zone z0 = Singletons.getModel().getGame().getZoneOf(c0); + Zone z0 = match.getCurrentGame().getZoneOf(c0); if (c0.getName().equals("Serum Powder") && z0.is(ZoneType.Hand)) { if (GuiDialog.confirm(c0, "Use " + c0.getName() + "'s ability?")) { List hand = new ArrayList(c0.getController().getCardsIn(ZoneType.Hand)); for (Card c : hand) { - Singletons.getModel().getGame().getAction().exile(c); + match.getCurrentGame().getAction().exile(c); } c0.getController().drawCards(hand.size()); } diff --git a/src/main/java/forge/control/input/InputPassPriority.java b/src/main/java/forge/control/input/InputPassPriority.java index 4fe8b4bcf64..114893439b0 100644 --- a/src/main/java/forge/control/input/InputPassPriority.java +++ b/src/main/java/forge/control/input/InputPassPriority.java @@ -19,11 +19,9 @@ package forge.control.input; import forge.Card; import forge.FThreads; -import forge.Singletons; import forge.card.spellability.SpellAbility; -import forge.control.FControl; -import forge.game.phase.PhaseType; -import forge.game.player.Player; +import forge.game.phase.PhaseHandler; +import forge.game.player.HumanPlayer; import forge.gui.GuiDisplayUtil; import forge.gui.framework.SDisplayUtil; import forge.gui.match.CMatchUI; @@ -42,26 +40,28 @@ public class InputPassPriority extends InputBase { /** Constant serialVersionUID=-581477682214137181L. */ private static final long serialVersionUID = -581477682214137181L; + /** + * TODO: Write javadoc for Constructor. + * @param player + */ + public InputPassPriority(HumanPlayer human) { + super(human); + } + /** {@inheritDoc} */ @Override public final void showMessage() { GuiDisplayUtil.updateGUI(); ButtonUtil.enableOnlyOk(); - final PhaseType phase = Singletons.getModel().getGame().getPhaseHandler().getPhase(); - final Player player = Singletons.getModel().getGame().getPhaseHandler().getPriorityPlayer(); - - if (player.isComputer()) { - System.err.println(phase + ": Computer in passpriority"); - } - + final PhaseHandler ph = player.getGame().getPhaseHandler(); final StringBuilder sb = new StringBuilder(); - sb.append("Turn : ").append(Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn()).append("\n"); - sb.append("Phase: ").append(phase.Name).append("\n"); + sb.append("Turn : ").append(ph.getPlayerTurn()).append("\n"); + sb.append("Phase: ").append(ph.getPhase().Name).append("\n"); sb.append("Stack: "); - if (Singletons.getModel().getGame().getStack().size() != 0) { - sb.append(Singletons.getModel().getGame().getStack().size()).append(" to Resolve."); + if (player.getGame().getStack().size() != 0) { + sb.append(player.getGame().getStack().size()).append(" to Resolve."); } else { sb.append("Empty"); } @@ -71,16 +71,17 @@ public class InputPassPriority extends InputBase { CMatchUI.SINGLETON_INSTANCE.showMessage(sb.toString()); } + /** {@inheritDoc} */ @Override public final void selectButtonOK() { - FControl.SINGLETON_INSTANCE.getPlayer().getController().passPriority(); + ButtonUtil.disableAll(); + passPriority(); } /** {@inheritDoc} */ @Override public final void selectCard(final Card card) { - final Player player = Singletons.getControl().getPlayer(); final SpellAbility ab = player.getController().getAbilityToPlay(player.getGame().getAbilitesOfCard(card, player)); if ( null != ab) { Runnable execAbility = new Runnable() { diff --git a/src/main/java/forge/control/input/InputPayManaBase.java b/src/main/java/forge/control/input/InputPayManaBase.java index 424667b1318..4438fb45ecd 100644 --- a/src/main/java/forge/control/input/InputPayManaBase.java +++ b/src/main/java/forge/control/input/InputPayManaBase.java @@ -30,16 +30,15 @@ public abstract class InputPayManaBase extends InputSyncronizedBase implements I protected int phyLifeToLose = 0; - protected final Player whoPays; protected final GameState game; protected ManaCostBeingPaid manaCost; protected final SpellAbility saPaidFor; boolean bPaid = false; - protected InputPayManaBase(final GameState game, SpellAbility saToPayFor) { - this.game = game; - this.whoPays = saToPayFor.getActivatingPlayer(); + protected InputPayManaBase(SpellAbility saToPayFor) { + super(saToPayFor.getActivatingPlayer()); + this.game = player.getGame(); this.saPaidFor = saToPayFor; } @@ -115,7 +114,7 @@ public abstract class InputPayManaBase extends InputSyncronizedBase implements I * @return ManaCost the amount of mana remaining to be paid after the mana is activated */ protected void useManaFromPool(String color, ManaCostBeingPaid manaCost) { - ManaPool mp = whoPays.getManaPool(); + ManaPool mp = player.getManaPool(); // Convert Color to short String String manaStr = "1"; @@ -144,7 +143,7 @@ public abstract class InputPayManaBase extends InputSyncronizedBase implements I */ protected void activateManaAbility(final Card card, ManaCostBeingPaid manaCost) { // make sure computer's lands aren't selected - if (card.getController() != whoPays) { + if (card.getController() != player) { return; } @@ -168,7 +167,7 @@ public abstract class InputPayManaBase extends InputSyncronizedBase implements I // you can't remove unneeded abilities inside a for(am:abilities) loop :( for (SpellAbility ma : card.getManaAbility()) { - ma.setActivatingPlayer(whoPays); + ma.setActivatingPlayer(player); AbilityManaPart m = null; SpellAbility tail = ma; while(m == null && tail != null) @@ -303,11 +302,11 @@ public abstract class InputPayManaBase extends InputSyncronizedBase implements I public void onManaAbilityPlayed(final SpellAbility saPaymentSrc) { if ( saPaymentSrc != null) // null comes when they've paid from pool - this.manaCost = whoPays.getManaPool().payManaFromAbility(saPaidFor, manaCost, saPaymentSrc); + this.manaCost = player.getManaPool().payManaFromAbility(saPaidFor, manaCost, saPaymentSrc); onManaAbilityPaid(); if ( saPaymentSrc != null ) - whoPays.getZone(ZoneType.Battlefield).updateObservers(); + player.getZone(ZoneType.Battlefield).updateObservers(); } protected final void checkIfAlredyPaid() { diff --git a/src/main/java/forge/control/input/InputPayManaExecuteCommands.java b/src/main/java/forge/control/input/InputPayManaExecuteCommands.java index 0214bc8177a..5d0ee10ac24 100644 --- a/src/main/java/forge/control/input/InputPayManaExecuteCommands.java +++ b/src/main/java/forge/control/input/InputPayManaExecuteCommands.java @@ -62,7 +62,7 @@ public class InputPayManaExecuteCommands extends InputPayManaBase implements Inp * a {@link forge.Command} object. */ public InputPayManaExecuteCommands(final Player p, final String prompt, final ManaCost manaCost2) { - super(p.getGame(), new SpellAbility(null) { + super(new SpellAbility(null) { @Override public void resolve() {} @@ -90,8 +90,8 @@ public class InputPayManaExecuteCommands extends InputPayManaBase implements Inp } @Override - public void selectPlayer(final Player player) { - if (player == whoPays) { + public void selectPlayer(final Player selectedPlayer) { + if (player == selectedPlayer) { if (player.canPayLife(this.phyLifeToLose + 2) && manaCost.payPhyrexian()) { this.phyLifeToLose += 2; } diff --git a/src/main/java/forge/control/input/InputPayManaOfCostPayment.java b/src/main/java/forge/control/input/InputPayManaOfCostPayment.java index b241ebf074a..8812c1f3cf6 100644 --- a/src/main/java/forge/control/input/InputPayManaOfCostPayment.java +++ b/src/main/java/forge/control/input/InputPayManaOfCostPayment.java @@ -12,7 +12,7 @@ import forge.view.ButtonUtil; public class InputPayManaOfCostPayment extends InputPayManaBase { public InputPayManaOfCostPayment(final GameState game, CostPartMana costMana, SpellAbility spellAbility, int toAdd) { - super(game, spellAbility); + super(spellAbility); manaCost = new ManaCostBeingPaid(costMana.getManaToPay()); manaCost.increaseColorlessMana(toAdd); } @@ -21,8 +21,8 @@ public class InputPayManaOfCostPayment extends InputPayManaBase { private int phyLifeToLose = 0; @Override - public void selectPlayer(final Player player) { - if (player == whoPays) { + public void selectPlayer(final Player selectedPlayer) { + if (player == selectedPlayer) { if (player.canPayLife(this.phyLifeToLose + 2) && manaCost.payPhyrexian()) { this.phyLifeToLose += 2; } diff --git a/src/main/java/forge/control/input/InputPayManaSimple.java b/src/main/java/forge/control/input/InputPayManaSimple.java index 712f0ebfe4d..3f502812d7f 100644 --- a/src/main/java/forge/control/input/InputPayManaSimple.java +++ b/src/main/java/forge/control/input/InputPayManaSimple.java @@ -37,7 +37,7 @@ public class InputPayManaSimple extends InputPayManaBase { private final String originalManaCost; public InputPayManaSimple(final GameState game, final SpellAbility sa, final ManaCostBeingPaid manaCostToPay) { - super(game, sa); + super(sa); this.originalManaCost = manaCostToPay.toString(); // Change this.originalCard = sa.getSourceCard(); @@ -68,9 +68,9 @@ public class InputPayManaSimple extends InputPayManaBase { /** {@inheritDoc} */ @Override - public final void selectPlayer(final Player player) { + public final void selectPlayer(final Player selectedPlayer) { - if (player == whoPays) { + if (player == selectedPlayer) { if (player.canPayLife(this.phyLifeToLose + 2) && manaCost.payPhyrexian()) { this.phyLifeToLose += 2; } @@ -88,10 +88,10 @@ public class InputPayManaSimple extends InputPayManaBase { @Override protected void done() { if (this.phyLifeToLose > 0) { - whoPays.payLife(this.phyLifeToLose, this.originalCard); + player.payLife(this.phyLifeToLose, this.originalCard); } if (!this.saPaidFor.getSourceCard().isCopiedSpell()) { - whoPays.getManaPool().clearManaPaid(this.saPaidFor, false); + player.getManaPool().clearManaPaid(this.saPaidFor, false); this.resetManaCost(); if (this.saPaidFor.isSpell()) { @@ -110,8 +110,8 @@ public class InputPayManaSimple extends InputPayManaBase { handleConvokedCards(true); this.resetManaCost(); - whoPays.getManaPool().refundManaPaid(this.saPaidFor, true); - whoPays.getZone(ZoneType.Battlefield).updateObservers(); // DO + player.getManaPool().refundManaPaid(this.saPaidFor, true); + player.getZone(ZoneType.Battlefield).updateObservers(); // DO this.stop(); } diff --git a/src/main/java/forge/control/input/InputPayManaX.java b/src/main/java/forge/control/input/InputPayManaX.java index 75d1a3bc544..fc77d6fd52b 100644 --- a/src/main/java/forge/control/input/InputPayManaX.java +++ b/src/main/java/forge/control/input/InputPayManaX.java @@ -3,7 +3,6 @@ package forge.control.input; import forge.Card; import forge.card.mana.ManaCostBeingPaid; import forge.card.spellability.SpellAbility; -import forge.game.GameState; import forge.view.ButtonUtil; public class InputPayManaX extends InputPayManaBase { @@ -15,9 +14,9 @@ public class InputPayManaX extends InputPayManaBase { private final boolean xCanBe0; - public InputPayManaX(final GameState game, final SpellAbility sa0, final int amountX, final boolean xCanBe0) + public InputPayManaX(final SpellAbility sa0, final int amountX, final boolean xCanBe0) { - super(game, sa0); + super(sa0); xPaid = 0; colorX = saPaidFor.hasParam("XColor") ? saPaidFor.getParam("XColor") : ""; diff --git a/src/main/java/forge/control/input/InputSelectManyBase.java b/src/main/java/forge/control/input/InputSelectManyBase.java index 84c58f000c7..06e04d39727 100644 --- a/src/main/java/forge/control/input/InputSelectManyBase.java +++ b/src/main/java/forge/control/input/InputSelectManyBase.java @@ -5,6 +5,7 @@ import java.util.List; import forge.Card; import forge.GameEntity; +import forge.Singletons; import forge.view.ButtonUtil; public abstract class InputSelectManyBase extends InputSyncronizedBase implements InputSelectMany { @@ -23,6 +24,7 @@ public abstract class InputSelectManyBase extends InputSyn protected InputSelectManyBase(int min, int max) { + super(Singletons.getControl().getPlayer()); selected = new ArrayList(); if (min > max) { throw new IllegalArgumentException("Min must not be greater than Max"); diff --git a/src/main/java/forge/control/input/InputSyncronizedBase.java b/src/main/java/forge/control/input/InputSyncronizedBase.java index 6b975f19ec7..7d3f1928c51 100644 --- a/src/main/java/forge/control/input/InputSyncronizedBase.java +++ b/src/main/java/forge/control/input/InputSyncronizedBase.java @@ -4,13 +4,15 @@ import java.util.concurrent.CountDownLatch; import forge.FThreads; import forge.error.BugReporter; +import forge.game.player.Player; public abstract class InputSyncronizedBase extends InputBase implements InputSynchronized { private static final long serialVersionUID = 8756177361251703052L; private final CountDownLatch cdlDone; - public InputSyncronizedBase() { + public InputSyncronizedBase(Player player) { + super(player); cdlDone = new CountDownLatch(1); } diff --git a/src/main/java/forge/game/ai/AiInputBlock.java b/src/main/java/forge/game/ai/AiInputBlock.java index 341818aa4a8..55873b3bfe7 100644 --- a/src/main/java/forge/game/ai/AiInputBlock.java +++ b/src/main/java/forge/game/ai/AiInputBlock.java @@ -14,21 +14,17 @@ import forge.game.player.Player; * */ public class AiInputBlock extends InputBase { - private final GameState game; /** * TODO: Write javadoc for Constructor. * @param game * @param player */ - public AiInputBlock(GameState game, Player player) { - super(); - this.game = game; - this.player = player; + public AiInputBlock(Player human) { + super(human); + this.game = human.getGame(); } - private final Player player; - private static final long serialVersionUID = -2253562658069995572L; @Override diff --git a/src/main/java/forge/game/ai/AiInputCommon.java b/src/main/java/forge/game/ai/AiInputCommon.java index 277e1f77e90..ca32bbbbf65 100644 --- a/src/main/java/forge/game/ai/AiInputCommon.java +++ b/src/main/java/forge/game/ai/AiInputCommon.java @@ -43,6 +43,7 @@ public class AiInputCommon extends InputBase implements AiInput { * a {@link forge.game.player.Computer} object. */ public AiInputCommon(final AiController iComputer) { + super(iComputer.getPlayer()); this.computer = iComputer; } diff --git a/src/main/java/forge/game/phase/PhaseHandler.java b/src/main/java/forge/game/phase/PhaseHandler.java index e6561528d27..4b2ca17178f 100644 --- a/src/main/java/forge/game/phase/PhaseHandler.java +++ b/src/main/java/forge/game/phase/PhaseHandler.java @@ -709,6 +709,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { *

*/ public final void passPriority() { + FThreads.checkEDT("PhaseHandler.passPriority", false); // stop game if it's outcome is clear if (game.isGameOver()) { return; diff --git a/src/main/java/forge/game/player/PlayerController.java b/src/main/java/forge/game/player/PlayerController.java index 728d000af4a..5c34f535821 100644 --- a/src/main/java/forge/game/player/PlayerController.java +++ b/src/main/java/forge/game/player/PlayerController.java @@ -29,13 +29,15 @@ public abstract class PlayerController { private PhaseType autoPassUntil = null; - public PlayerController(GameState game0) { game = game0; + } + public abstract Input getDefaultInput(); public abstract Input getBlockInput(); public abstract Input getCleanupInput(); + public abstract Input getAutoPassPriorityInput(); /** diff --git a/src/main/java/forge/game/player/PlayerControllerAi.java b/src/main/java/forge/game/player/PlayerControllerAi.java index 242ffed7898..f405302cec1 100644 --- a/src/main/java/forge/game/player/PlayerControllerAi.java +++ b/src/main/java/forge/game/player/PlayerControllerAi.java @@ -13,6 +13,7 @@ import forge.GameEntity; import forge.card.spellability.Spell; import forge.card.spellability.SpellAbility; import forge.control.input.Input; +import forge.control.input.InputAutoPassPriority; import forge.deck.Deck; import forge.game.GameState; import forge.game.GameType; @@ -36,6 +37,7 @@ public class PlayerControllerAi extends PlayerController { private Input defaultInput; private Input blockInput; private Input cleanupInput; + private Input autoPassPriorityInput; private final AiController brains; private final AIPlayer player; @@ -52,9 +54,9 @@ public class PlayerControllerAi extends PlayerController { brains = new AiController(p, game); defaultInput = new AiInputCommon(brains); - blockInput = new AiInputBlock(game, getPlayer()); + blockInput = new AiInputBlock(getPlayer()); cleanupInput = getDefaultInput(); - + autoPassPriorityInput = new InputAutoPassPriority(getPlayer()); } /** @@ -75,6 +77,11 @@ public class PlayerControllerAi extends PlayerController { return blockInput; } + @Override + public Input getAutoPassPriorityInput() { + return autoPassPriorityInput; + } + /** * @return the cleanupInput */ diff --git a/src/main/java/forge/game/player/PlayerControllerHuman.java b/src/main/java/forge/game/player/PlayerControllerHuman.java index ba777e5b0db..d6a5825d9bb 100644 --- a/src/main/java/forge/game/player/PlayerControllerHuman.java +++ b/src/main/java/forge/game/player/PlayerControllerHuman.java @@ -16,6 +16,7 @@ import forge.FThreads; import forge.GameEntity; import forge.card.spellability.SpellAbility; import forge.control.input.Input; +import forge.control.input.InputAutoPassPriority; import forge.control.input.InputBlock; import forge.control.input.InputCleanup; import forge.control.input.InputPassPriority; @@ -45,8 +46,9 @@ public class PlayerControllerHuman extends PlayerController { private final Input defaultInput; private final Input blockInput; private final Input cleanupInput; + private final Input autoPassPriorityInput; private final HumanPlayer player; - + public final Input getDefaultInput() { return defaultInput; } @@ -55,9 +57,10 @@ public class PlayerControllerHuman extends PlayerController { super(game0); player = p; - defaultInput = new InputPassPriority(); + defaultInput = new InputPassPriority(player); blockInput = new InputBlock(getPlayer()); - cleanupInput = new InputCleanup(game); + cleanupInput = new InputCleanup(getPlayer()); + autoPassPriorityInput = new InputAutoPassPriority(getPlayer()); } @Override @@ -83,6 +86,11 @@ public class PlayerControllerHuman extends PlayerController { return blockInput; } + @Override + public Input getAutoPassPriorityInput() { + return autoPassPriorityInput; + } + /** * @return the cleanupInput */ diff --git a/src/main/java/forge/game/zone/MagicStack.java b/src/main/java/forge/game/zone/MagicStack.java index 037c94a5d4c..c22e38500dc 100644 --- a/src/main/java/forge/game/zone/MagicStack.java +++ b/src/main/java/forge/game/zone/MagicStack.java @@ -391,7 +391,7 @@ public class MagicStack extends MyObservable { final int xCost = sa.getXManaCost(); Player player = sp.getSourceCard().getController(); if (player.isHuman()) { - InputSynchronized inp = new InputPayManaX(game, sa, xCost, true); + InputSynchronized inp = new InputPayManaX(sa, xCost, true); FThreads.setInputAndWait(inp); MagicStack.this.push(sa); } else { diff --git a/src/main/java/forge/gui/InputProxy.java b/src/main/java/forge/gui/InputProxy.java index 17b2e107906..590e31f3c1c 100644 --- a/src/main/java/forge/gui/InputProxy.java +++ b/src/main/java/forge/gui/InputProxy.java @@ -26,7 +26,6 @@ import forge.FThreads; import forge.control.input.Input; import forge.game.GameState; import forge.game.MatchController; -import forge.game.ai.AiInput; import forge.game.phase.PhaseHandler; import forge.game.player.Player; @@ -50,35 +49,37 @@ public class InputProxy implements Observer { @Override public final synchronized void update(final Observable observable, final Object obj) { - this.input.set(null); final GameState game = match.getCurrentGame(); final PhaseHandler ph = game.getPhaseHandler(); + //System.out.printf("%s > InputProxy.update() =>%n", FThreads.debugGetCurrThreadId()); - //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() { + Runnable rPhase = new Runnable() { + @Override + public void run() { + //System.out.printf("\t%s > handle begin phase during %s%n", FThreads.debugGetCurrThreadId(), ph.debugPrintState()); ph.handleBeginPhase(); - update(observable, obj); - } - }, true); + update(null, null); + } + }; + FThreads.invokeInNewThread(rPhase); return; } final Input nextInput = match.getInput().getActualInput(game); - //System.out.printf(" input is %s \t stack = %s%n", nextInput == null ? "null" : nextInput.getClass().getSimpleName(), match.getInput().printInputStack()); - - if (nextInput != null) { - this.input.set(nextInput); - Runnable showMessage = new Runnable() { @Override public void run() { nextInput.showMessage(); } }; + //System.out.printf("\tinput is %s during %s, \tstack = %s%n", nextInput == null ? "null" : nextInput.getClass().getSimpleName(), ph.debugPrintState(), match.getInput().printInputStack()); + + this.input.set(nextInput); + Runnable showMessage = new Runnable() { + @Override public void run() { + //System.out.printf("%s > showMessage @ %s during %s%n", FThreads.debugGetCurrThreadId(), nextInput.getClass().getSimpleName(), ph.debugPrintState()); + nextInput.showMessage(); + } + }; // if( nextInput instanceof AiInput ) // FThreads.invokeInNewThread(showMessage, true); // else - FThreads.invokeInEDT(showMessage); - } else if (!ph.isPlayerPriorityAllowed()) { - ph.getPriorityPlayer().getController().passPriority(); - } + FThreads.invokeInEDT(showMessage); } /** *