diff --git a/.gitattributes b/.gitattributes index a0f7aa7c6c0..a8db68f31fe 100644 --- a/.gitattributes +++ b/.gitattributes @@ -716,6 +716,7 @@ forge-gui-desktop/src/main/html/js/jquery/jquery-1.9.1.js -text forge-gui-desktop/src/main/html/js/jquery/jquery-1.9.1.min.js -text forge-gui-desktop/src/main/html/js/observable.js -text forge-gui-desktop/src/main/html/js/socket.js -text +forge-gui-desktop/src/main/java/forge/GuiBase.java -text forge-gui-desktop/src/main/java/forge/GuiDesktop.java -text forge-gui-desktop/src/main/java/forge/ImageCache.java -text forge-gui-desktop/src/main/java/forge/ImageLoader.java -text @@ -16643,7 +16644,6 @@ forge-gui/src/main/html/js/jquery/jquery-1.9.1.min.js -text forge-gui/src/main/html/js/observable.js -text forge-gui/src/main/html/js/socket.js -text forge-gui/src/main/java/forge/FThreads.java -text -forge-gui/src/main/java/forge/GuiBase.java -text forge-gui/src/main/java/forge/UiCommand.java svneol=native#text/plain forge-gui/src/main/java/forge/assets/FSkinProp.java -text forge-gui/src/main/java/forge/assets/ISkinImage.java -text @@ -16719,7 +16719,6 @@ forge-gui/src/main/java/forge/limited/WinstonDraft.java -text forge-gui/src/main/java/forge/limited/WinstonDraftAI.java -text forge-gui/src/main/java/forge/limited/package-info.java svneol=native#text/plain forge-gui/src/main/java/forge/match/MatchConstants.java -text -forge-gui/src/main/java/forge/match/MatchUtil.java -text forge-gui/src/main/java/forge/match/input/ButtonUtil.java -text forge-gui/src/main/java/forge/match/input/Input.java -text forge-gui/src/main/java/forge/match/input/InputAttack.java -text @@ -16758,6 +16757,7 @@ forge-gui/src/main/java/forge/player/HumanPlay.java -text forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java -text forge-gui/src/main/java/forge/player/LobbyPlayerHuman.java -text forge-gui/src/main/java/forge/player/PlayerControllerHuman.java -text +forge-gui/src/main/java/forge/player/PlayerControllerLocal.java -text forge-gui/src/main/java/forge/player/TargetSelection.java -text forge-gui/src/main/java/forge/player/package-info.java -text forge-gui/src/main/java/forge/properties/ForgeConstants.java -text @@ -16837,7 +16837,6 @@ forge-gui/src/main/java/forge/util/IgnoringXStream.java -text forge-gui/src/main/java/forge/util/LineReader.java -text forge-gui/src/main/java/forge/util/MultiplexOutputStream.java svneol=native#text/plain forge-gui/src/main/java/forge/util/OperatingSystem.java -text -forge-gui/src/main/java/forge/util/WaitCallback.java -text forge-gui/src/main/java/forge/util/XmlUtil.java -text forge-gui/src/main/java/forge/util/gui/SGuiChoose.java -text forge-gui/src/main/java/forge/util/gui/SGuiDialog.java -text diff --git a/forge-core/src/main/java/forge/card/CardEdition.java b/forge-core/src/main/java/forge/card/CardEdition.java index 26a1bb33f6a..5704c7413b6 100644 --- a/forge-core/src/main/java/forge/card/CardEdition.java +++ b/forge-core/src/main/java/forge/card/CardEdition.java @@ -21,6 +21,7 @@ import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; + import forge.StaticData; import forge.card.CardDb.SetPreference; import forge.deck.CardPool; @@ -30,9 +31,11 @@ import forge.util.Aggregates; import forge.util.FileSection; import forge.util.FileUtil; import forge.util.IItemReader; +import forge.util.MyRandom; import forge.util.storage.StorageBase; import forge.util.storage.StorageReaderBase; import forge.util.storage.StorageReaderFolder; + import org.apache.commons.lang3.StringUtils; import java.io.File; @@ -483,5 +486,20 @@ public final class CardEdition implements Comparable { // immutable return true; }; }; - } + } + + public static int getRandomFoil(final String setCode) { + FoilType foilType = FoilType.NOT_SUPPORTED; + if (setCode != null + && StaticData.instance().getEditions().get(setCode) != null) { + foilType = StaticData.instance().getEditions().get(setCode) + .getFoilType(); + } + if (foilType != FoilType.NOT_SUPPORTED) { + return foilType == FoilType.MODERN + ? MyRandom.getRandom().nextInt(9) + 1 + : MyRandom.getRandom().nextInt(9) + 11; + } + return 0; + } } diff --git a/forge-game/src/main/java/forge/game/GameLog.java b/forge-game/src/main/java/forge/game/GameLog.java index 192b96509f5..c1dc97c01fb 100644 --- a/forge-game/src/main/java/forge/game/GameLog.java +++ b/forge-game/src/main/java/forge/game/GameLog.java @@ -23,13 +23,10 @@ import forge.game.io.GameStateDeserializer; import forge.game.io.GameStateSerializer; import forge.game.io.IGameStateObject; -import org.apache.commons.lang3.StringUtils; - import java.util.ArrayList; import java.util.List; import java.util.Observable; - /** *

* GameLog class. @@ -64,7 +61,6 @@ public class GameLog extends Observable implements IGameStateObject { * Instantiates a new game log. */ public GameLog() { - } /** @@ -82,11 +78,6 @@ public class GameLog extends Observable implements IGameStateObject { log.add(entry); this.setChanged(); this.notifyObservers(); - } - - public String getLogText(final GameLogEntryType logLevel) { - List filteredAndReversed = getLogEntries(logLevel); - return StringUtils.join(filteredAndReversed, "\r\n"); } /** diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChangeTargetsEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChangeTargetsEffect.java index a433aa93d81..9742c6dac59 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChangeTargetsEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChangeTargetsEffect.java @@ -1,6 +1,8 @@ package forge.game.ability.effects; import com.google.common.collect.Iterables; + +import forge.game.GameEntity; import forge.game.GameObject; import forge.game.ability.SpellAbilityEffect; import forge.game.player.Player; @@ -9,6 +11,7 @@ import forge.game.spellability.SpellAbilityStackInstance; import forge.game.spellability.TargetChoices; import forge.game.zone.MagicStack; import forge.util.Aggregates; + import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; @@ -87,8 +90,8 @@ public class ChangeTargetsEffect extends SpellAbilityEffect { SpellAbility changingTgtSA = changingTgtSI.getSpellAbility(); if (sa.hasParam("RandomTarget")){ changingTgtSA.resetTargets(); - List candidates = changingTgtSA.getTargetRestrictions().getAllCandidates(changingTgtSA, true); - GameObject choice = Aggregates.random(candidates); + List candidates = changingTgtSA.getTargetRestrictions().getAllCandidates(changingTgtSA, true); + GameEntity choice = Aggregates.random(candidates); changingTgtSA.getTargets().add(choice); changingTgtSI.updateTarget(changingTgtSA.getTargets()); } else if (sa.hasParam("DefinedMagnet")){ diff --git a/forge-game/src/main/java/forge/game/ability/effects/CopySpellAbilityEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CopySpellAbilityEffect.java index 80b58340147..613ac42186d 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CopySpellAbilityEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CopySpellAbilityEffect.java @@ -1,7 +1,8 @@ package forge.game.ability.effects; import com.google.common.collect.Iterables; -import forge.game.GameObject; + +import forge.game.GameEntity; import forge.game.ability.AbilityUtils; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; @@ -94,7 +95,7 @@ public class CopySpellAbilityEffect extends SpellAbilityEffect { if (targetedSA == null) { return; } - List candidates = targetedSA.getTargetRestrictions().getAllCandidates(targetedSA, true); + final List candidates = targetedSA.getTargetRestrictions().getAllCandidates(targetedSA, true); if (sa.hasParam("CanTargetPlayer")) { // Radiate // Remove targeted players because getAllCandidates include all the valid players @@ -102,7 +103,7 @@ public class CopySpellAbilityEffect extends SpellAbilityEffect { candidates.remove(p); mayChoseNewTargets = false; - for (GameObject o : candidates) { + for (GameEntity o : candidates) { SpellAbility copy = CardFactory.copySpellAbilityAndSrcCard(card, chosenSA.getHostCard(), chosenSA, true); copy.resetFirstTarget(o, targetedSA); copies.add(copy); @@ -110,7 +111,7 @@ public class CopySpellAbilityEffect extends SpellAbilityEffect { } else {// Precursor Golem, Ink-Treader Nephilim final String type = sa.getParam("CopyForEachCanTarget"); List valid = new ArrayList(); - for (final Object o : candidates) { + for (final GameEntity o : candidates) { if (o instanceof Card) { valid.add((Card) o); } diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index bf4bda8c1f0..99864575026 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -58,7 +58,6 @@ import forge.item.PaperCard; import forge.util.CollectionSuppliers; import forge.util.Expressions; import forge.util.Lang; -import forge.util.MyRandom; import forge.util.TextUtil; import forge.util.maps.HashMapOfLists; import forge.util.maps.MapOfLists; @@ -1632,29 +1631,15 @@ public class Card extends GameEntity implements Comparable { } /** - * - * TODO Write javadoc for this method. - * - * @param globalChanges - * an ArrayList - * @return a CardColor + * @return a {@link ColorSet}. + * @see CardCharacteristics#determineColor() */ public final ColorSet determineColor() { if (this.isImmutable()) { return ColorSet.getNullColor(); } - List colorList = this.getCharacteristics().getCardColor(); - - byte colors = 0; - for (int i = colorList.size() - 1;i >= 0;i--) { - final CardColor cc = colorList.get(i); - colors |= cc.getColorMask(); - if (!cc.isAdditional()) { - return ColorSet.fromMask(colors); - } - } - return ColorSet.fromMask(colors); + return this.getCharacteristics().determineColor(); } /** @@ -8244,13 +8229,7 @@ public class Card extends GameEntity implements Comparable { * removed. */ public final void setRandomFoil() { - CardEdition.FoilType foilType = CardEdition.FoilType.NOT_SUPPORTED; - if (this.getCurSetCode() != null && StaticData.instance().getEditions().get(this.getCurSetCode()) != null) { - foilType = StaticData.instance().getEditions().get(this.getCurSetCode()).getFoilType(); - } - if (foilType != CardEdition.FoilType.NOT_SUPPORTED) { - this.setFoil(foilType == CardEdition.FoilType.MODERN ? MyRandom.getRandom().nextInt(9) + 1 : MyRandom.getRandom().nextInt(9) + 11); - } + this.setFoil(CardEdition.getRandomFoil(this.getCurSetCode())); } /** diff --git a/forge-game/src/main/java/forge/game/card/CardCharacteristics.java b/forge-game/src/main/java/forge/game/card/CardCharacteristics.java index d0567a22773..12013113511 100644 --- a/forge-game/src/main/java/forge/game/card/CardCharacteristics.java +++ b/forge-game/src/main/java/forge/game/card/CardCharacteristics.java @@ -18,8 +18,10 @@ package forge.game.card; import com.google.common.collect.Lists; + import forge.card.CardEdition; import forge.card.CardRarity; +import forge.card.ColorSet; import forge.card.mana.ManaCost; import forge.game.replacement.ReplacementEffect; import forge.game.spellability.SpellAbility; @@ -432,7 +434,6 @@ public class CardCharacteristics { } } - public CardRarity getRarity() { return rarity; } @@ -452,4 +453,22 @@ public class CardCharacteristics { this.curSetCode = curSetCode; } + + /** + * Determine the colors. + * + * @return a {@link ColorSet}. + */ + public final ColorSet determineColor() { + final List colorList = this.getCardColor(); + byte colors = 0; + for (int i = colorList.size() - 1;i >= 0;i--) { + final CardColor cc = colorList.get(i); + colors |= cc.getColorMask(); + if (!cc.isAdditional()) { + return ColorSet.fromMask(colors); + } + } + return ColorSet.fromMask(colors); + } } diff --git a/forge-game/src/main/java/forge/game/player/PlayerController.java b/forge-game/src/main/java/forge/game/player/PlayerController.java index 90b7bcc9c74..fc587d18721 100644 --- a/forge-game/src/main/java/forge/game/player/PlayerController.java +++ b/forge-game/src/main/java/forge/game/player/PlayerController.java @@ -3,6 +3,7 @@ package forge.game.player; import com.google.common.base.Predicate; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; +import com.google.common.collect.Sets; import forge.LobbyPlayer; import forge.card.ColorSet; @@ -38,12 +39,10 @@ import org.apache.commons.lang3.tuple.Pair; import java.util.Collection; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; - /** * A prototype for player controller class * @@ -83,11 +82,11 @@ public abstract class PlayerController { } /** - * Automatically pass priority until reaching the given phase of the current turn - * @param phase + * Automatically pass priority until reaching the Cleanup phase of the + * current turn. */ - public void autoPassUntil(PhaseType phase) { - autoPassUntilPhase = phase; + public void autoPassUntilEndOfTurn() { + autoPassUntilPhase = PhaseType.CLEANUP; } protected PhaseType getAutoPassUntilPhase() { @@ -118,14 +117,14 @@ public abstract class PlayerController { } // Abilities to auto-yield to - private Set autoYields = new HashSet(); + private final Set autoYields = Sets.newHashSet(); public Iterable getAutoYields() { return autoYields; } - public boolean shouldAutoYield(String key) { + public boolean shouldAutoYield(final String key) { return autoYields.contains(key); } - public void setShouldAutoYield(String key, boolean autoYield) { + public void setShouldAutoYield(final String key, final boolean autoYield) { if (autoYield) { autoYields.add(key); } diff --git a/forge-game/src/main/java/forge/game/spellability/TargetRestrictions.java b/forge-game/src/main/java/forge/game/spellability/TargetRestrictions.java index 4ac0c78b435..c2d94b48dff 100644 --- a/forge-game/src/main/java/forge/game/spellability/TargetRestrictions.java +++ b/forge-game/src/main/java/forge/game/spellability/TargetRestrictions.java @@ -17,21 +17,22 @@ */ package forge.game.spellability; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; + +import com.google.common.collect.Lists; + import forge.card.CardType; import forge.game.Game; -import forge.game.GameObject; +import forge.game.GameEntity; import forge.game.ability.AbilityUtils; import forge.game.card.Card; import forge.game.player.Player; import forge.game.zone.ZoneType; -import org.apache.commons.lang3.StringUtils; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; - /** *

* Target class. @@ -473,9 +474,9 @@ public class TargetRestrictions { * Check Valid Candidates and Targeting * @return a List. */ - public final List getAllCandidates(final SpellAbility sa, final boolean isTargeted) { + public final List getAllCandidates(final SpellAbility sa, final boolean isTargeted) { final Game game = sa.getActivatingPlayer().getGame(); - List candidates = new ArrayList(); + final List candidates = Lists.newArrayList(); for (Player player : game.getPlayers()) { if (sa.canTarget(player)) { candidates.add(player); diff --git a/forge-gui/src/main/java/forge/GuiBase.java b/forge-gui-desktop/src/main/java/forge/GuiBase.java similarity index 100% rename from forge-gui/src/main/java/forge/GuiBase.java rename to forge-gui-desktop/src/main/java/forge/GuiBase.java diff --git a/forge-gui-desktop/src/main/java/forge/GuiDesktop.java b/forge-gui-desktop/src/main/java/forge/GuiDesktop.java index b4b89dfd744..33b8f8a68ac 100644 --- a/forge-gui-desktop/src/main/java/forge/GuiDesktop.java +++ b/forge-gui-desktop/src/main/java/forge/GuiDesktop.java @@ -36,7 +36,7 @@ import forge.game.Match; import forge.game.phase.PhaseType; import forge.game.player.IHasIcon; import forge.game.player.RegisteredPlayer; -import forge.game.spellability.SpellAbility; +//import forge.game.spellability.SpellAbility; import forge.game.zone.ZoneType; import forge.gui.BoxedProductCardListViewer; import forge.gui.CardListViewer; @@ -79,6 +79,7 @@ import forge.view.CombatView; import forge.view.GameEntityView; import forge.view.IGameView; import forge.view.PlayerView; +import forge.view.SpellAbilityView; public class GuiDesktop implements IGuiBase { @@ -153,7 +154,7 @@ public class GuiDesktop implements IGuiBase { @Override public int showCardOptionDialog(final CardView card, String message, String title, FSkinProp skinIcon, String[] options, int defaultOption) { if (card != null) { - FThreads.invokeInEdtAndWait(new Runnable() { + FThreads.invokeInEdtAndWait(GuiBase.getInterface(), new Runnable() { @Override public void run() { GuiBase.getInterface().setCard(card); @@ -213,7 +214,7 @@ public class GuiDesktop implements IGuiBase { public void focusButton(final IButton button) { // ensure we don't steal focus from an overlay if (!SOverlayUtils.overlayHasFocus()) { - FThreads.invokeInEdtLater(new Runnable() { + FThreads.invokeInEdtLater(GuiBase.getInterface(), new Runnable() { @Override public void run() { ((FButton)button).requestFocusInWindow(); @@ -294,7 +295,7 @@ public class GuiDesktop implements IGuiBase { } @Override - public SpellAbility getAbilityToPlay(List abilities, ITriggerEvent triggerEvent) { + public SpellAbilityView getAbilityToPlay(List abilities, ITriggerEvent triggerEvent) { if (triggerEvent == null) { if (abilities.isEmpty()) { return null; @@ -308,7 +309,7 @@ public class GuiDesktop implements IGuiBase { if (abilities.isEmpty()) { return null; } - if (abilities.size() == 1 && !abilities.get(0).promptIfOnlyPossibleAbility()) { + if (abilities.size() == 1 && !abilities.get(0).isPromptIfOnlyPossibleAbility()) { if (abilities.get(0).canPlay()) { return abilities.get(0); //only return ability if it's playable, otherwise return null } @@ -321,7 +322,7 @@ public class GuiDesktop implements IGuiBase { boolean enabled; boolean hasEnabled = false; int shortcut = KeyEvent.VK_1; //use number keys as shortcuts for abilities 1-9 - for (final SpellAbility ab : abilities) { + for (final SpellAbilityView ab : abilities) { enabled = ab.canPlay(); if (enabled) { hasEnabled = true; @@ -451,7 +452,7 @@ public class GuiDesktop implements IGuiBase { } @Override - public void refreshCardDetails(final Collection cards) { + public void refreshCardDetails(final Iterable cards) { CMatchUI.SINGLETON_INSTANCE.refreshCardDetails(cards); } diff --git a/forge-gui-desktop/src/main/java/forge/ImageCache.java b/forge-gui-desktop/src/main/java/forge/ImageCache.java index 558fb848c38..dc34f08cd7f 100644 --- a/forge-gui-desktop/src/main/java/forge/ImageCache.java +++ b/forge-gui-desktop/src/main/java/forge/ImageCache.java @@ -199,7 +199,7 @@ public class ImageCache { * Returns the Image corresponding to the key. */ private static BufferedImage getImage(final String key) { - FThreads.assertExecutedByEdt(true); + FThreads.assertExecutedByEdt(GuiBase.getInterface(), true); try { return ImageCache._CACHE.get(key); } catch (final ExecutionException ex) { diff --git a/forge-gui-desktop/src/main/java/forge/Singletons.java b/forge-gui-desktop/src/main/java/forge/Singletons.java index aad80dab48f..9ca5f379333 100644 --- a/forge-gui-desktop/src/main/java/forge/Singletons.java +++ b/forge-gui-desktop/src/main/java/forge/Singletons.java @@ -19,6 +19,8 @@ package forge; import forge.control.FControl; import forge.model.FModel; +import forge.properties.ForgeConstants; +import forge.properties.ForgeProfileProperties; import forge.view.FView; /** @@ -37,7 +39,7 @@ public final class Singletons { public static FControl getControl() { return control; } public static void initializeOnce(boolean withUi) { - FThreads.assertExecutedByEdt(false); + FThreads.assertExecutedByEdt(GuiBase.getInterface(), false); synchronized (Singletons.class) { if (initialized) { @@ -46,11 +48,14 @@ public final class Singletons { initialized = true; } + ForgeConstants.init(GuiBase.getInterface()); + ForgeProfileProperties.init(GuiBase.getInterface()); + if (withUi) { view = FView.SINGLETON_INSTANCE; } - FModel.initialize(view == null ? null : view.getSplash().getProgressBar()); + FModel.initialize(GuiBase.getInterface(), view == null ? null : view.getSplash().getProgressBar()); if (withUi) { control = FControl.instance; diff --git a/forge-gui-desktop/src/main/java/forge/control/FControl.java b/forge-gui-desktop/src/main/java/forge/control/FControl.java index 5363a6a97c1..9e5e0854b85 100644 --- a/forge-gui-desktop/src/main/java/forge/control/FControl.java +++ b/forge-gui-desktop/src/main/java/forge/control/FControl.java @@ -51,6 +51,7 @@ import forge.game.GameRules; import forge.game.GameType; import forge.game.Match; import forge.game.player.Player; +//import forge.game.player.Player; import forge.game.player.RegisteredPlayer; import forge.gui.GuiDialog; import forge.gui.SOverlayUtils; @@ -66,6 +67,8 @@ import forge.menus.ForgeMenu; import forge.model.FModel; import forge.player.GamePlayerUtil; import forge.player.LobbyPlayerHuman; +import forge.player.PlayerControllerHuman; +import forge.player.PlayerControllerLocal; import forge.properties.ForgeConstants; import forge.properties.ForgePreferences; import forge.properties.ForgePreferences.FPref; @@ -122,7 +125,7 @@ public enum FControl implements KeyEventDispatcher { EXIT_FORGE } - private final SoundSystem soundSystem = new SoundSystem(); + private final SoundSystem soundSystem = new SoundSystem(GuiBase.getInterface()); /** *

@@ -190,10 +193,10 @@ public enum FControl implements KeyEventDispatcher { public boolean canExitForge(boolean forRestart) { String action = (forRestart ? "Restart" : "Exit"); String userPrompt = "Are you sure you wish to " + (forRestart ? "restart" : "exit") + " Forge?"; - if (this.game != null) { + if (this.gameView != null) { userPrompt = "A game is currently active. " + userPrompt; } - if (!FOptionPane.showConfirmDialog(userPrompt, action + " Forge", action, "Cancel", this.game == null)) { //default Yes if no game active + if (!FOptionPane.showConfirmDialog(userPrompt, action + " Forge", action, "Cancel", this.gameView == null)) { //default Yes if no game active return false; } if (!CDeckEditorUI.SINGLETON_INSTANCE.canSwitchAway(true)) { @@ -385,11 +388,6 @@ public enum FControl implements KeyEventDispatcher { private IGameView gameView; private boolean gameHasHumanPlayer; - @Deprecated - public Game getObservedGame() { - return game; - } - public IGameView getGameView() { return this.gameView; } @@ -443,22 +441,24 @@ public enum FControl implements KeyEventDispatcher { } public final void startGameWithUi(final Match match) { - if (this.game != null) { + if (this.gameView != null) { this.setCurrentScreen(FScreen.MATCH_SCREEN); SOverlayUtils.hideOverlay(); FOptionPane.showMessageDialog("Cannot start a new game while another game is already in progress."); return; //TODO: See if it's possible to run multiple games at once without crashing } setPlayerName(match.getPlayers()); - this.game = match.createGame(); + final Game game = match.createGame(); final LobbyPlayer me = getGuiPlayer(); - for (final Player p : this.game.getPlayers()) { + for (final Player p : game.getPlayers()) { if (p.getLobbyPlayer().equals(me)) { this.gameView = (IGameView) p.getController(); + fcVisitor = new FControlGameEventHandler((PlayerControllerHuman) p.getController()); break; } } + inputQueue = new InputQueue(GuiBase.getInterface(), game); attachToGame(this.gameView); // It's important to run match in a different thread to allow GUI inputs to be invoked from inside game. @@ -473,14 +473,15 @@ public enum FControl implements KeyEventDispatcher { } public final void endCurrentGame() { - if (this.game == null) { return; } + if (this.gameView == null) { return; } Singletons.getView().getNavigationBar().closeTab(FScreen.MATCH_SCREEN); this.game = null; + this.gameView = null; } - private final FControlGameEventHandler fcVisitor = new FControlGameEventHandler(); - private final FControlGamePlayback playbackControl = new FControlGamePlayback(); + private FControlGameEventHandler fcVisitor; + private FControlGamePlayback playbackControl;// = new FControlGamePlayback(); private void attachToGame(final IGameView game0) { if (game0.getGameType().equals(GameType.Quest)) { QuestController qc = FModel.getQuest(); @@ -491,8 +492,6 @@ public enum FControl implements KeyEventDispatcher { game0.subscribeToEvents(qc); // this one listens to player's mulligans ATM } - inputQueue = new InputQueue(); - game0.subscribeToEvents(Singletons.getControl().getSoundSystem()); //switch back to match screen music @@ -531,6 +530,11 @@ public enum FControl implements KeyEventDispatcher { // Add playback controls to match if needed if (localPlayer != null) { + // Create dummy controller + final PlayerControllerHuman controller = + new PlayerControllerLocal(game, null, humanLobbyPlayer, GuiBase.getInterface()); + playbackControl = new FControlGamePlayback(controller); + playbackControl.setGame(game); game0.subscribeToEvents(playbackControl); } @@ -590,7 +594,7 @@ public enum FControl implements KeyEventDispatcher { boolean isPlayerOneHuman = players.get(0).getPlayer() instanceof LobbyPlayerHuman; boolean isPlayerTwoComputer = players.get(1).getPlayer() instanceof LobbyPlayerAi; if (isPlayerOneHuman && isPlayerTwoComputer) { - GamePlayerUtil.setPlayerName(); + GamePlayerUtil.setPlayerName(GuiBase.getInterface()); } } } @@ -616,7 +620,7 @@ public enum FControl implements KeyEventDispatcher { final Match mc = new Match(rules, players); SOverlayUtils.startGameOverlay(); SOverlayUtils.showOverlay(); - FThreads.invokeInEdtLater(new Runnable(){ + FThreads.invokeInEdtLater(GuiBase.getInterface(), new Runnable(){ @Override public void run() { startGameWithUi(mc); @@ -740,7 +744,7 @@ public enum FControl implements KeyEventDispatcher { return player; } - private final LobbyPlayer guiPlayer = new LobbyPlayerHuman("Human"); + private final LobbyPlayer guiPlayer = new LobbyPlayerHuman("Human", GuiBase.getInterface()); public final LobbyPlayer getGuiPlayer() { return guiPlayer; } diff --git a/forge-gui-desktop/src/main/java/forge/deckchooser/FDeckChooser.java b/forge-gui-desktop/src/main/java/forge/deckchooser/FDeckChooser.java index 5a4d22e8304..9160825eca9 100644 --- a/forge-gui-desktop/src/main/java/forge/deckchooser/FDeckChooser.java +++ b/forge-gui-desktop/src/main/java/forge/deckchooser/FDeckChooser.java @@ -1,6 +1,7 @@ package forge.deckchooser; import forge.FThreads; +import forge.GuiBase; import forge.UiCommand; import forge.deck.ColorDeckGenerator; import forge.deck.Deck; @@ -50,7 +51,7 @@ public class FDeckChooser extends JPanel implements IDecksComboBoxListener { //Show dialog to select a deck public static Deck promptForDeck(String title, DeckType defaultDeckType, boolean forAi) { - FThreads.assertExecutedByEdt(true); + FThreads.assertExecutedByEdt(GuiBase.getInterface(), true); final FDeckChooser chooser = new FDeckChooser(forAi); chooser.initialize(defaultDeckType); chooser.populate(); @@ -130,7 +131,7 @@ public class FDeckChooser extends JPanel implements IDecksComboBoxListener { "White", "Blue", "Black", "Red", "Green" }; ArrayList decks = new ArrayList(); for (int i = 0; i < colors.length; i++) { - decks.add(new ColorDeckGenerator(colors[i], i, lstDecks, isAi)); + decks.add(new ColorDeckGenerator(GuiBase.getInterface(), colors[i], i, lstDecks, isAi)); } lstDecks.setPool(decks); diff --git a/forge-gui-desktop/src/main/java/forge/download/GuiDownloader.java b/forge-gui-desktop/src/main/java/forge/download/GuiDownloader.java index 7b5559e9dd0..f85e95416fa 100644 --- a/forge-gui-desktop/src/main/java/forge/download/GuiDownloader.java +++ b/forge-gui-desktop/src/main/java/forge/download/GuiDownloader.java @@ -19,6 +19,7 @@ package forge.download; import java.net.Proxy; +import forge.GuiBase; import forge.UiCommand; import forge.assets.FSkinProp; import forge.gui.SOverlayUtils; @@ -95,7 +96,7 @@ public class GuiDownloader extends DefaultBoundedRangeModel { pnl.add(pnlDialog, "w 400px!, h 350px!, ax center, ay center"); SOverlayUtils.showOverlay(); - service.initialize(txtAddress, txtPort, progressBar, btnStart, cmdClose, null, new Runnable() { + service.initialize(GuiBase.getInterface(), txtAddress, txtPort, progressBar, btnStart, cmdClose, null, new Runnable() { @Override public void run() { fireStateChanged(); diff --git a/forge-gui-desktop/src/main/java/forge/error/BugReportDialog.java b/forge-gui-desktop/src/main/java/forge/error/BugReportDialog.java index e71c5eb4f70..8a0a7129a5c 100644 --- a/forge-gui-desktop/src/main/java/forge/error/BugReportDialog.java +++ b/forge-gui-desktop/src/main/java/forge/error/BugReportDialog.java @@ -17,6 +17,7 @@ */ package forge.error; +import forge.GuiBase; import forge.gui.WrapLayout; import forge.toolbox.FHyperlink; import forge.toolbox.FLabel; @@ -92,7 +93,7 @@ public class BugReportDialog { @Override public void actionPerformed(final ActionEvent e) { - BugReporter.copyAndGoToForums(text.getText()); + BugReporter.copyAndGoToForums(GuiBase.getInterface(), text.getText()); } } @@ -108,7 +109,7 @@ public class BugReportDialog { @Override public void actionPerformed(final ActionEvent e) { - BugReporter.saveToFile(area.getText()); + BugReporter.saveToFile(GuiBase.getInterface(), area.getText()); } } diff --git a/forge-gui-desktop/src/main/java/forge/gui/GuiChoose.java b/forge-gui-desktop/src/main/java/forge/gui/GuiChoose.java index 052f73f9883..b2186fdca05 100644 --- a/forge-gui-desktop/src/main/java/forge/gui/GuiChoose.java +++ b/forge-gui-desktop/src/main/java/forge/gui/GuiChoose.java @@ -20,6 +20,7 @@ import com.google.common.base.Function; import com.google.common.collect.Iterables; import forge.FThreads; +import forge.GuiBase; import forge.Singletons; import forge.item.InventoryItem; import forge.screens.match.CMatchUI; @@ -237,7 +238,7 @@ public class GuiChoose { }; FutureTask> future = new FutureTask>(showChoice); - FThreads.invokeInEdtAndWait(future); + FThreads.invokeInEdtAndWait(GuiBase.getInterface(), future); try { return future.get(); } catch (Exception e) { // should be no exception here @@ -296,7 +297,7 @@ public class GuiChoose { }; FutureTask> ft = new FutureTask>(callable); - FThreads.invokeInEdtAndWait(ft); + FThreads.invokeInEdtAndWait(GuiBase.getInterface(), ft); try { return ft.get(); } catch (Exception e) { // we have waited enough diff --git a/forge-gui-desktop/src/main/java/forge/gui/GuiDialog.java b/forge-gui-desktop/src/main/java/forge/gui/GuiDialog.java index 749587f9ba9..c219e0506a3 100644 --- a/forge-gui-desktop/src/main/java/forge/gui/GuiDialog.java +++ b/forge-gui-desktop/src/main/java/forge/gui/GuiDialog.java @@ -8,6 +8,7 @@ import javax.swing.UIManager; import org.apache.commons.lang3.StringUtils; import forge.FThreads; +import forge.GuiBase; import forge.screens.match.CMatchUI; import forge.toolbox.FOptionPane; import forge.view.CardView; @@ -45,7 +46,7 @@ public class GuiDialog { }}; FutureTask future = new FutureTask(confirmTask); - FThreads.invokeInEdtAndWait(future); + FThreads.invokeInEdtAndWait(GuiBase.getInterface(), future); try { return future.get().booleanValue(); } @@ -68,7 +69,7 @@ public class GuiDialog { } public static void message(final String message, final String title) { - FThreads.invokeInEdtAndWait(new Runnable() { + FThreads.invokeInEdtAndWait(GuiBase.getInterface(), new Runnable() { @Override public void run() { FOptionPane.showMessageDialog(message, title, null); diff --git a/forge-gui-desktop/src/main/java/forge/gui/ListChooser.java b/forge-gui-desktop/src/main/java/forge/gui/ListChooser.java index ab0e24ba507..34884bdd71b 100644 --- a/forge-gui-desktop/src/main/java/forge/gui/ListChooser.java +++ b/forge-gui-desktop/src/main/java/forge/gui/ListChooser.java @@ -22,6 +22,7 @@ import com.google.common.base.Function; import com.google.common.collect.Lists; import forge.FThreads; +import forge.GuiBase; import forge.toolbox.FList; import forge.toolbox.FMouseAdapter; import forge.toolbox.FOptionPane; @@ -75,7 +76,7 @@ public class ListChooser { private FOptionPane optionPane; public ListChooser(final String title, final int minChoices, final int maxChoices, final Collection list, final Function display) { - FThreads.assertExecutedByEdt(true); + FThreads.assertExecutedByEdt(GuiBase.getInterface(), true); this.minChoices = minChoices; this.maxChoices = maxChoices; this.list = list.getClass().isInstance(List.class) ? (List)list : Lists.newArrayList(list); diff --git a/forge-gui-desktop/src/main/java/forge/gui/framework/SDisplayUtil.java b/forge-gui-desktop/src/main/java/forge/gui/framework/SDisplayUtil.java index d09d245c1ac..eaac40a670e 100644 --- a/forge-gui-desktop/src/main/java/forge/gui/framework/SDisplayUtil.java +++ b/forge-gui-desktop/src/main/java/forge/gui/framework/SDisplayUtil.java @@ -1,9 +1,11 @@ package forge.gui.framework; import forge.FThreads; +import forge.GuiBase; import forge.view.FFrame; import javax.swing.*; + import java.awt.*; import java.util.Timer; import java.util.TimerTask; @@ -100,7 +102,7 @@ public class SDisplayUtil { } } }; - FThreads.invokeInEdtLater(showTabRoutine); + FThreads.invokeInEdtLater(GuiBase.getInterface(), showTabRoutine); } public static GraphicsDevice getGraphicsDevice(Point point) { diff --git a/forge-gui-desktop/src/main/java/forge/screens/bazaar/VBazaarUI.java b/forge-gui-desktop/src/main/java/forge/screens/bazaar/VBazaarUI.java index 45b23c277e8..27f6f68acdf 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/bazaar/VBazaarUI.java +++ b/forge-gui-desktop/src/main/java/forge/screens/bazaar/VBazaarUI.java @@ -1,5 +1,6 @@ package forge.screens.bazaar; +import forge.GuiBase; import forge.UiCommand; import forge.assets.FSkinProp; import forge.gui.framework.FScreen; @@ -42,7 +43,7 @@ public enum VBazaarUI implements IVTopLevelUI { final FLabel lbl = new FLabel.ButtonBuilder().text(s + " ") .fontAlign(SwingConstants.RIGHT).iconInBackground(true).selectable() - .fontSize(16).icon((SkinImage)bazaar.getStall(s).getIcon()).build(); + .fontSize(16).icon((SkinImage)GuiBase.getInterface().getSkinIcon(bazaar.getStall(s).getIcon())).build(); pnlAllStalls.add(lbl, "h 80px!, w 90%!, gap 0 0 10px 10px"); diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuestCardShop.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuestCardShop.java index 92f792e882c..9407581ba8b 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuestCardShop.java +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuestCardShop.java @@ -17,6 +17,7 @@ */ package forge.screens.deckeditor.controllers; +import forge.GuiBase; import forge.UiCommand; import forge.assets.FSkinProp; import forge.deck.DeckBase; @@ -148,7 +149,7 @@ public final class CEditorQuestCardShop extends ACEditorBase> items, boolean toAlternate) { if (showingFullCatalog || toAlternate) { return; } - QuestSpellShop.sell(items, this.getCatalogManager(), this.getDeckManager(), true); + QuestSpellShop.sell(GuiBase.getInterface(), items, this.getCatalogManager(), this.getDeckManager(), true); updateCreditsLabel(); } diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuChallenges.java b/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuChallenges.java index 2a12e6bf0a3..ad792637acc 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuChallenges.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuChallenges.java @@ -1,5 +1,6 @@ package forge.screens.home.quest; +import forge.GuiBase; import forge.UiCommand; import forge.Singletons; import forge.gui.framework.EDocID; @@ -42,29 +43,29 @@ public enum CSubmenuChallenges implements ICDoc { view.getBtnSpellShop().setCommand( new UiCommand() { @Override - public void run() { QuestUtil.showSpellShop(); } }); + public void run() { QuestUtil.showSpellShop(GuiBase.getInterface()); } }); view.getBtnBazaar().setCommand( new UiCommand() { @Override - public void run() { QuestUtil.showBazaar(); } }); + public void run() { QuestUtil.showBazaar(GuiBase.getInterface()); } }); view.getBtnUnlock().setCommand( new UiCommand() { @Override - public void run() { QuestUtil.chooseAndUnlockEdition(); CSubmenuChallenges.this.update(); } }); + public void run() { QuestUtil.chooseAndUnlockEdition(GuiBase.getInterface()); CSubmenuChallenges.this.update(); } }); view.getBtnTravel().setCommand( new UiCommand() { @Override - public void run() { QuestUtil.travelWorld(); CSubmenuChallenges.this.update(); } }); + public void run() { QuestUtil.travelWorld(GuiBase.getInterface()); CSubmenuChallenges.this.update(); } }); view.getBtnStart().addActionListener( new ActionListener() { @Override - public void actionPerformed(final ActionEvent e) { QuestUtil.startGame(); } }); + public void actionPerformed(final ActionEvent e) { QuestUtil.startGame(GuiBase.getInterface()); } }); ((FLabel) view.getLblZep()).setCommand( new UiCommand() { @Override public void run() { - if (!QuestUtil.checkActiveQuest("Launch a Zeppelin.")) { + if (!QuestUtil.checkActiveQuest(GuiBase.getInterface(), "Launch a Zeppelin.")) { return; } FModel.getQuest().getAchievements().setCurrentChallenges(null); diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuDuels.java b/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuDuels.java index d62ba3cb3d1..0bd320bdbf1 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuDuels.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuDuels.java @@ -1,5 +1,6 @@ package forge.screens.home.quest; +import forge.GuiBase; import forge.UiCommand; import forge.gui.framework.EDocID; import forge.gui.framework.ICDoc; @@ -36,23 +37,23 @@ public enum CSubmenuDuels implements ICDoc { view.getBtnSpellShop().setCommand( new UiCommand() { @Override - public void run() { QuestUtil.showSpellShop(); } }); + public void run() { QuestUtil.showSpellShop(GuiBase.getInterface()); } }); view.getBtnBazaar().setCommand( new UiCommand() { @Override - public void run() { QuestUtil.showBazaar(); } }); + public void run() { QuestUtil.showBazaar(GuiBase.getInterface()); } }); view.getBtnTravel().setCommand( new UiCommand() { @Override - public void run() { QuestUtil.travelWorld(); CSubmenuDuels.this.update(); } }); + public void run() { QuestUtil.travelWorld(GuiBase.getInterface()); CSubmenuDuels.this.update(); } }); view.getBtnUnlock().setCommand( new UiCommand() { @Override - public void run() { QuestUtil.chooseAndUnlockEdition(); CSubmenuDuels.this.update(); } }); + public void run() { QuestUtil.chooseAndUnlockEdition(GuiBase.getInterface()); CSubmenuDuels.this.update(); } }); view.getBtnStart().addActionListener( new ActionListener() { @Override - public void actionPerformed(final ActionEvent e) { QuestUtil.startGame(); } }); + public void actionPerformed(final ActionEvent e) { QuestUtil.startGame(GuiBase.getInterface()); } }); final QuestController quest = FModel.getQuest(); view.getCbPlant().addActionListener(new ActionListener() { @@ -86,11 +87,11 @@ public enum CSubmenuDuels implements ICDoc { view.getBtnRandomOpponent().setCommand(new UiCommand() { @Override public void run() { - if (QuestUtil.canStartGame()) { + if (QuestUtil.canStartGame(GuiBase.getInterface())) { FModel.getQuest().getDuelsManager().randomizeOpponents(); final List duels = FModel.getQuest().getDuelsManager().generateDuels(); QuestUtil.setEvent(duels.get((int) (Math.random() * duels.size()))); - QuestUtil.startGame(); + QuestUtil.startGame(GuiBase.getInterface()); } } }); diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestDecks.java b/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestDecks.java index 0716077c3f1..f899f376674 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestDecks.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestDecks.java @@ -1,5 +1,6 @@ package forge.screens.home.quest; +import forge.GuiBase; import forge.UiCommand; import forge.Singletons; import forge.deck.DeckProxy; @@ -56,7 +57,7 @@ public enum CSubmenuQuestDecks implements ICDoc { VSubmenuQuestDecks.SINGLETON_INSTANCE.getBtnNewDeck().setCommand(new UiCommand() { @Override public void run() { - if (!QuestUtil.checkActiveQuest("Create a Deck.")) { + if (!QuestUtil.checkActiveQuest(GuiBase.getInterface(), "Create a Deck.")) { return; } Singletons.getControl().setCurrentScreen(FScreen.DECK_EDITOR_QUEST); diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestDraft.java b/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestDraft.java index 3904c3ac1f0..2b0acd618cb 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestDraft.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestDraft.java @@ -297,7 +297,7 @@ public enum CSubmenuQuestDraft implements ICDoc { view.setMode(Mode.TOURNAMENT_ACTIVE); } - QuestDraftUtils.update(); + QuestDraftUtils.update(GuiBase.getInterface()); switch (view.getMode()) { @@ -477,7 +477,7 @@ public enum CSubmenuQuestDraft implements ICDoc { drafting = true; - BoosterDraft draft = draftEvent.enter(); + BoosterDraft draft = draftEvent.enter(GuiBase.getInterface()); final CEditorQuestDraftingProcess draftController = new CEditorQuestDraftingProcess(); draftController.showGui(draft); @@ -517,7 +517,7 @@ public enum CSubmenuQuestDraft implements ICDoc { return; } - QuestDraftUtils.startNextMatch(); + QuestDraftUtils.startNextMatch(GuiBase.getInterface()); } diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/quest/ViewItem.java b/forge-gui-desktop/src/main/java/forge/screens/home/quest/ViewItem.java index 734de95c0e5..0dd8e7c70ff 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/quest/ViewItem.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/quest/ViewItem.java @@ -1,6 +1,8 @@ package forge.screens.home.quest; +import forge.GuiBase; import forge.UiCommand; +import forge.assets.FSkinProp; import forge.model.FModel; import forge.quest.QuestUtil; import forge.quest.bazaar.IQuestBazaarItem; @@ -75,7 +77,23 @@ public class ViewItem extends FPanel { final QuestAssets qA = FModel.getQuest().getAssets(); IQuestBazaarItem bazaarItem = ViewItem.this.getItem(); - ViewItem.this.lblIcon.setIcon((SkinImage)bazaarItem.getIcon(qA)); + SkinImage i; + try { + final FSkinProp f = FSkinProp.valueOf(FSkinProp.class, bazaarItem.getIcon(qA)); + i = (SkinImage) GuiBase.getInterface().getSkinIcon(f); + } catch (final IllegalArgumentException e) { + // Failed to parse FSkinProp + try { + i = (SkinImage) GuiBase.getInterface().getUnskinnedIcon(bazaarItem.getIcon(qA)); + } catch (final Exception e1) { + // give up, icon unknown + e1.printStackTrace(); + i = (SkinImage) GuiBase.getInterface().getSkinIcon(FSkinProp.ICO_UNKNOWN); + } + } + + ViewItem.this.lblIcon.setIcon(i); + ViewItem.this.lblName.setText(bazaarItem.getPurchaseName()); ViewItem.this.lblPrice.setText("Cost: " + String.valueOf(bazaarItem.getBuyingPrice(qA)) + " credits"); String desc = bazaarItem.getPurchaseDescription(qA); diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuDraft.java b/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuDraft.java index 10fb0fbfb65..448f1eeee55 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuDraft.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuDraft.java @@ -114,11 +114,11 @@ public enum CSubmenuDraft implements ICDoc { } } - FModel.getGauntletMini().resetGauntletDraft(); + FModel.getGauntletMini(GuiBase.getInterface()).resetGauntletDraft(); if (gauntlet) { int rounds = FModel.getDecks().getDraft().get(humanDeck.getName()).getAiDecks().size(); - FModel.getGauntletMini().launch(rounds, humanDeck.getDeck(), gameType); + FModel.getGauntletMini(GuiBase.getInterface()).launch(rounds, humanDeck.getDeck(), gameType); return; } @@ -152,7 +152,7 @@ public enum CSubmenuDraft implements ICDoc { final LimitedPoolType poolType = GuiChoose.oneOrNone("Choose Draft Format", LimitedPoolType.values()); if (poolType == null) { return; } - BoosterDraft draft = BoosterDraft.createDraft(poolType); + BoosterDraft draft = BoosterDraft.createDraft(GuiBase.getInterface(), poolType); if (draft == null) { return; } final CEditorDraftingProcess draftController = new CEditorDraftingProcess(); diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuSealed.java b/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuSealed.java index b4e864e8177..cc6654f8d0e 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuSealed.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuSealed.java @@ -1,5 +1,6 @@ package forge.screens.home.sanctioned; +import forge.GuiBase; import forge.UiCommand; import forge.Singletons; import forge.deck.*; @@ -16,6 +17,7 @@ import forge.screens.deckeditor.CDeckEditorUI; import forge.screens.deckeditor.controllers.ACEditorBase; import forge.screens.deckeditor.controllers.CEditorLimited; import forge.toolbox.FOptionPane; + import javax.swing.*; import java.awt.event.ActionEvent; @@ -108,12 +110,12 @@ public enum CSubmenuSealed implements ICDoc { } int matches = FModel.getDecks().getSealed().get(human.getName()).getAiDecks().size(); - FModel.getGauntletMini().launch(matches, human.getDeck(), gameType); + FModel.getGauntletMini(GuiBase.getInterface()).launch(matches, human.getDeck(), gameType); } @SuppressWarnings("unchecked") private void setupSealed() { - final DeckGroup sealed = SealedCardPoolGenerator.generateSealedDeck(true); + final DeckGroup sealed = SealedCardPoolGenerator.generateSealedDeck(GuiBase.getInterface(), true); if (sealed == null) { return; } final ACEditorBase editor = (ACEditorBase) new CEditorLimited( diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuWinston.java b/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuWinston.java index c0025c6267e..157c77ea59a 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuWinston.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuWinston.java @@ -142,7 +142,7 @@ public enum CSubmenuWinston implements ICDoc { final LimitedPoolType poolType = GuiChoose.oneOrNone("Choose Draft Format", LimitedPoolType.values()); if (poolType == null) { return; } - WinstonDraft draft = WinstonDraft.createDraft(poolType); + WinstonDraft draft = WinstonDraft.createDraft(GuiBase.getInterface(), poolType); if (draft == null) { return; } final CEditorWinstonProcess draftController = new CEditorWinstonProcess(); diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuDownloaders.java b/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuDownloaders.java index 371ecce6bd5..55b04d2e2fc 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuDownloaders.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuDownloaders.java @@ -1,5 +1,6 @@ package forge.screens.home.settings; +import forge.GuiBase; import forge.UiCommand; import forge.download.GuiDownloadPicturesLQ; import forge.download.GuiDownloadPrices; @@ -37,7 +38,7 @@ public enum CSubmenuDownloaders implements ICDoc { private final UiCommand cmdImportPictures = new UiCommand() { @Override public void run() { new ImportDialog(null, null); } }; private final UiCommand cmdReportBug = new UiCommand() { @Override - public void run() { BugReporter.reportBug(null); } + public void run() { BugReporter.reportBug(GuiBase.getInterface(), null); } }; /* (non-Javadoc) diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java b/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java index 5f1f746a71e..122c1d359c5 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java @@ -1,5 +1,6 @@ package forge.screens.home.settings; +import forge.GuiBase; import forge.UiCommand; import forge.Singletons; import forge.ai.AiProfileUtil; @@ -339,7 +340,7 @@ public enum CSubmenuPreferences implements ICDoc { return new UiCommand() { @Override public void run() { - GamePlayerUtil.setPlayerName(); + GamePlayerUtil.setPlayerName(GuiBase.getInterface()); setPlayerNameButtonText(); } }; diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java b/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java index 5e52d045269..b8d59384b78 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java @@ -34,6 +34,7 @@ import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; import forge.FThreads; +import forge.GuiBase; import forge.ImageCache; import forge.LobbyPlayer; import forge.Singletons; @@ -257,7 +258,7 @@ public enum CMatchUI implements ICDoc, IMenuProvider { } final Object[] result = { null }; // how else can I extract a value from EDT thread? - FThreads.invokeInEdtAndWait(new Runnable() { + FThreads.invokeInEdtAndWait(GuiBase.getInterface(), new Runnable() { @Override public void run() { VAssignDamage v = new VAssignDamage(attacker, blockers, damage, defender, overrideOrder); @@ -285,7 +286,7 @@ public enum CMatchUI implements ICDoc, IMenuProvider { } public void setCard(final CardView c, final boolean isInAltState) { - FThreads.assertExecutedByEdt(true); + FThreads.assertExecutedByEdt(GuiBase.getInterface(), true); CDetail.SINGLETON_INSTANCE.showCard(c, isInAltState); CPicture.SINGLETON_INSTANCE.showCard(c, isInAltState); } @@ -335,7 +336,7 @@ public enum CMatchUI implements ICDoc, IMenuProvider { Set highlightedCards = Sets.newHashSet(); // used to highlight cards in UI public void setUsedToPay(CardView card, boolean value) { - FThreads.assertExecutedByEdt(true); + FThreads.assertExecutedByEdt(GuiBase.getInterface(), true); boolean hasChanged = value ? highlightedCards.add(card) : highlightedCards.remove(card); if (hasChanged) { // since we are in UI thread, may redraw the card right now @@ -417,7 +418,7 @@ public enum CMatchUI implements ICDoc, IMenuProvider { // UI-related events should arrive here public void fireEvent(UiEvent uiEvent) { if (LOG_UIEVENTS) { - System.out.println("UI: " + uiEvent.toString() + " \t\t " + FThreads.debugGetStackTraceItem(4, true)); + System.out.println("UI: " + uiEvent.toString() + " \t\t " + FThreads.debugGetStackTraceItem(GuiBase.getInterface(), 4, true)); } uiEvents.post(uiEvent); } diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/GauntletWinLose.java b/forge-gui-desktop/src/main/java/forge/screens/match/GauntletWinLose.java index 07772d8fefc..f7712af1702 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/GauntletWinLose.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/GauntletWinLose.java @@ -27,6 +27,7 @@ import javax.swing.SwingConstants; import net.miginfocom.swing.MigLayout; import forge.assets.FSkinProp; import forge.gauntlet.GauntletWinLoseController; +import forge.interfaces.IGuiBase; import forge.toolbox.FLabel; import forge.toolbox.FSkin; import forge.toolbox.FSkin.SkinnedPanel; @@ -45,9 +46,9 @@ public class GauntletWinLose extends ControlWinLose { * @param view0 ViewWinLose object * @param match */ - public GauntletWinLose(final ViewWinLose view0, final IGameView game0) { + public GauntletWinLose(final ViewWinLose view0, final IGameView game0, final IGuiBase gui) { super(view0, game0); - controller = new GauntletWinLoseController(view0, game0) { + controller = new GauntletWinLoseController(view0, game0, gui) { @Override protected void showOutcome(String message1, String message2, FSkinProp icon, List lstEventNames, List lstEventRecords, int len, int num) { final JLabel lblTitle = new FLabel.Builder().text("Gauntlet Progress") diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/LimitedWinLose.java b/forge-gui-desktop/src/main/java/forge/screens/match/LimitedWinLose.java index 352e0a6318d..42bbefd1f7a 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/LimitedWinLose.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/LimitedWinLose.java @@ -21,6 +21,7 @@ import java.awt.Dimension; import javax.swing.SwingConstants; +import forge.GuiBase; import forge.limited.LimitedWinLoseController; import forge.toolbox.FSkin; import forge.toolbox.FSkin.Colors; @@ -48,7 +49,7 @@ public class LimitedWinLose extends ControlWinLose { */ public LimitedWinLose(final ViewWinLose view0, final IGameView game0) { super(view0, game0); - controller = new LimitedWinLoseController(view0, game0) { + controller = new LimitedWinLoseController(view0, game0, GuiBase.getInterface()) { @Override protected void showOutcome(Runnable runnable) { runnable.run(); //just run on GUI thread diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/QuestDraftWinLose.java b/forge-gui-desktop/src/main/java/forge/screens/match/QuestDraftWinLose.java index 04a48b14ee5..03f198ed5d2 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/QuestDraftWinLose.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/QuestDraftWinLose.java @@ -102,10 +102,10 @@ public class QuestDraftWinLose extends ControlWinLose { if (lastGame.isMatchOver()) { this.actionOnQuitMatch(); QuestDraftUtils.matchInProgress = false; - QuestDraftUtils.update(); + QuestDraftUtils.update(GuiBase.getInterface()); } else { this.actionOnContinue(); - QuestDraftUtils.update(); + QuestDraftUtils.update(GuiBase.getInterface()); } return false; @@ -126,7 +126,7 @@ public class QuestDraftWinLose extends ControlWinLose { public void actionPerformed(final ActionEvent e) { GuiBase.getInterface().endCurrentGame(); QuestDraftUtils.matchInProgress = false; - QuestDraftUtils.continueMatches(); + QuestDraftUtils.continueMatches(GuiBase.getInterface()); } }); } else { @@ -141,7 +141,7 @@ public class QuestDraftWinLose extends ControlWinLose { if (FOptionPane.showOptionDialog("Quitting the match now will forfeit the tournament!\n\nReally quit?", "Really Quit Tournament?", FSkin.getImage(FSkinProp.ICO_WARNING).scale(2), new String[] { "Yes", "No" }, 1) == 0) { GuiBase.getInterface().endCurrentGame(); QuestDraftUtils.matchInProgress = false; - QuestDraftUtils.continueMatches(); + QuestDraftUtils.continueMatches(GuiBase.getInterface()); } } }); diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/QuestWinLose.java b/forge-gui-desktop/src/main/java/forge/screens/match/QuestWinLose.java index 3a48b50521f..f9c8ca444e7 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/QuestWinLose.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/QuestWinLose.java @@ -21,6 +21,7 @@ import java.util.List; import javax.swing.SwingConstants; +import forge.GuiBase; import forge.assets.FSkinProp; import forge.item.PaperCard; import forge.model.FModel; @@ -64,7 +65,7 @@ public class QuestWinLose extends ControlWinLose { public QuestWinLose(final ViewWinLose view0, final IGameView game0) { super(view0, game0); view = view0; - controller = new QuestWinLoseController(game0) { + controller = new QuestWinLoseController(game0, GuiBase.getInterface()) { @Override protected void showRewards(Runnable runnable) { runnable.run(); //just run on GUI thread diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/ViewWinLose.java b/forge-gui-desktop/src/main/java/forge/screens/match/ViewWinLose.java index 822faa224b8..af707f6ef3f 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/ViewWinLose.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/ViewWinLose.java @@ -14,6 +14,7 @@ import net.miginfocom.swing.MigLayout; import org.apache.commons.lang3.StringUtils; +import forge.GuiBase; import forge.LobbyPlayer; import forge.UiCommand; import forge.game.GameLogEntry; @@ -68,14 +69,14 @@ public class ViewWinLose implements IWinLoseView { control = new QuestDraftWinLose(this, game0); break; case Draft: - if (!FModel.getGauntletMini().isGauntletDraft()) { + if (!FModel.getGauntletMini(GuiBase.getInterface()).isGauntletDraft()) { break; } case Sealed: control = new LimitedWinLose(this, game0); break; case Gauntlet: - control = new GauntletWinLose(this, game0); + control = new GauntletWinLose(this, game0, GuiBase.getInterface()); break; default: // will catch it after switch break; diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CDock.java b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CDock.java index 808e6b0c0e6..ebe8c0e6fed 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CDock.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CDock.java @@ -71,7 +71,7 @@ public enum CDock implements ICDoc { SOverlayUtils.genericOverlay(); FView.SINGLETON_INSTANCE.getPnlContent().removeAll(); - FThreads.invokeInEdtLater(new Runnable(){ + FThreads.invokeInEdtLater(GuiBase.getInterface(), new Runnable(){ @Override public void run() { SLayoutIO.loadLayout(null); SOverlayUtils.hideOverlay(); @@ -101,7 +101,7 @@ public enum CDock implements ICDoc { FView.SINGLETON_INSTANCE.getPnlContent().removeAll(); // let it redraw everything first - FThreads.invokeInEdtLater(new Runnable() { + FThreads.invokeInEdtLater(GuiBase.getInterface(), new Runnable() { @Override public void run() { if (loadFile != null) { diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CHand.java b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CHand.java index 77f23dcaa0f..13e38b01c2a 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CHand.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CHand.java @@ -28,6 +28,7 @@ import javax.swing.JLayeredPane; import javax.swing.SwingUtilities; import forge.FThreads; +import forge.GuiBase; import forge.Singletons; import forge.UiCommand; import forge.gui.framework.ICDoc; @@ -79,7 +80,7 @@ public class CHand implements ICDoc { } public void update(final Observable a, final Object b) { - FThreads.invokeInEdtNowOrLater(updateRoutine); + FThreads.invokeInEdtNowOrLater(GuiBase.getInterface(), updateRoutine); } private final Runnable updateRoutine = new Runnable() { @@ -87,7 +88,7 @@ public class CHand implements ICDoc { }; public void updateHand() { - FThreads.assertExecutedByEdt(true); + FThreads.assertExecutedByEdt(GuiBase.getInterface(), true); final HandArea p = view.getHandArea(); diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CLog.java b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CLog.java index 31bac22cd81..2dfe34c1a07 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CLog.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CLog.java @@ -1,5 +1,6 @@ package forge.screens.match.controllers; +import forge.GuiBase; import forge.UiCommand; import forge.FThreads; import forge.gui.framework.ICDoc; @@ -66,7 +67,7 @@ public enum CLog implements ICDoc, Observer { */ @Override public void update() { - FThreads.invokeInEdtNowOrLater(r); + FThreads.invokeInEdtNowOrLater(GuiBase.getInterface(), r); } } diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CPrompt.java b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CPrompt.java index 05ea935f80d..8d5dcade4ec 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CPrompt.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CPrompt.java @@ -27,6 +27,7 @@ import java.awt.event.FocusListener; import javax.swing.JButton; import forge.FThreads; +import forge.GuiBase; import forge.Singletons; import forge.UiCommand; import forge.gui.framework.ICDoc; @@ -118,7 +119,7 @@ public enum CPrompt implements ICDoc { */ public void updateText() { - FThreads.assertExecutedByEdt(true); + FThreads.assertExecutedByEdt(GuiBase.getInterface(), true); final IGameView game = Singletons.getControl().getGameView(); final String text = String.format("T:%d G:%d/%d [%s]", game.getTurnNumber(), game.getNumPlayedGamesInMatch() + 1, game.getNumGamesInMatch(), game.getGameType()); view.getLblGames().setText(text); diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/menus/GameMenu.java b/forge-gui-desktop/src/main/java/forge/screens/match/menus/GameMenu.java index 4667934a5e6..73d4aeeb133 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/menus/GameMenu.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/menus/GameMenu.java @@ -1,9 +1,16 @@ package forge.screens.match.menus; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; + +import javax.swing.ButtonGroup; +import javax.swing.JMenu; +import javax.swing.JPopupMenu; + import forge.Singletons; import forge.assets.FSkinProp; import forge.control.FControl; -import forge.match.MatchUtil; import forge.menus.MenuUtil; import forge.model.FModel; import forge.properties.ForgePreferences; @@ -11,13 +18,11 @@ import forge.properties.ForgePreferences.FPref; import forge.screens.match.CMatchUI; import forge.screens.match.VAutoYields; import forge.screens.match.controllers.CDock; -import forge.toolbox.FSkin.*; - -import javax.swing.*; - -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.KeyEvent; +import forge.toolbox.FSkin.SkinIcon; +import forge.toolbox.FSkin.SkinnedCheckBoxMenuItem; +import forge.toolbox.FSkin.SkinnedMenu; +import forge.toolbox.FSkin.SkinnedMenuItem; +import forge.toolbox.FSkin.SkinnedRadioButtonMenuItem; /** * Returns a JMenu containing options associated with current game. @@ -80,7 +85,7 @@ public final class GameMenu { return new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - MatchUtil.undoLastAction(); + Singletons.getControl().getGameView().tryUndoLastAction(); } }; } diff --git a/forge-gui-desktop/src/main/java/forge/toolbox/FProgressBar.java b/forge-gui-desktop/src/main/java/forge/toolbox/FProgressBar.java index 0a4931b886c..cab64ee741f 100644 --- a/forge-gui-desktop/src/main/java/forge/toolbox/FProgressBar.java +++ b/forge-gui-desktop/src/main/java/forge/toolbox/FProgressBar.java @@ -1,6 +1,7 @@ package forge.toolbox; import forge.FThreads; +import forge.GuiBase; import forge.interfaces.IProgressBar; import javax.swing.*; @@ -36,7 +37,7 @@ public class FProgressBar extends JProgressBar implements IProgressBar { * @param s0   A description to prepend before statistics. */ public void setDescription(final String s0) { - FThreads.assertExecutedByEdt(true); + FThreads.assertExecutedByEdt(GuiBase.getInterface(), true); desc = s0; setString(s0); } @@ -81,7 +82,7 @@ public class FProgressBar extends JProgressBar implements IProgressBar { /** Resets the various values required for this class. Must be called from EDT. */ public void reset() { - FThreads.assertExecutedByEdt(true); + FThreads.assertExecutedByEdt(GuiBase.getInterface(), true); setIndeterminate(true); setValue(0); tempVal = 0; diff --git a/forge-gui-desktop/src/main/java/forge/toolbox/FSkin.java b/forge-gui-desktop/src/main/java/forge/toolbox/FSkin.java index 6c4266905cf..37001e0da1e 100644 --- a/forge-gui-desktop/src/main/java/forge/toolbox/FSkin.java +++ b/forge-gui-desktop/src/main/java/forge/toolbox/FSkin.java @@ -18,6 +18,7 @@ package forge.toolbox; import forge.FThreads; +import forge.GuiBase; import forge.Singletons; import forge.assets.FSkinProp; import forge.assets.ISkinImage; @@ -981,7 +982,7 @@ public class FSkin { public static void loadLight(final String skinName, final boolean onInit) { if (onInit) { // No need for this method to be loaded while on the EDT. - FThreads.assertExecutedByEdt(false); + FThreads.assertExecutedByEdt(GuiBase.getInterface(), false); if (allSkins == null) { //initialize allSkins = new ArrayList(); @@ -1053,7 +1054,7 @@ public class FSkin { public static void loadFull(final boolean onInit) { if (onInit) { // No need for this method to be loaded while on the EDT. - FThreads.assertExecutedByEdt(false); + FThreads.assertExecutedByEdt(GuiBase.getInterface(), false); // Preferred skin name must be called via loadLight() method, // which does some cleanup and init work. diff --git a/forge-gui-desktop/src/main/java/forge/toolbox/imaging/FImageUtil.java b/forge-gui-desktop/src/main/java/forge/toolbox/imaging/FImageUtil.java index 66ab05691b3..efd8a7caff4 100644 --- a/forge-gui-desktop/src/main/java/forge/toolbox/imaging/FImageUtil.java +++ b/forge-gui-desktop/src/main/java/forge/toolbox/imaging/FImageUtil.java @@ -23,8 +23,6 @@ import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import forge.ImageCache; -import forge.card.CardCharacteristicName; -import forge.game.card.Card; import forge.model.FModel; import forge.properties.ForgePreferences; import forge.toolbox.CardFaceSymbols; @@ -37,36 +35,9 @@ import forge.view.CardView.CardStateView; * @version $Id: FImageUtil.java 25265 2014-03-27 02:18:47Z drdev $ * */ -public final class FImageUtil { - private FImageUtil() {} +public final class FImageUtil { - @Deprecated - public static BufferedImage getImage(Card card, CardCharacteristicName state) { - BufferedImage image = ImageCache.getOriginalImage(card.getImageKey(state), true); - int foilIndex = card.getFoil(); - if (image != null && foilIndex > 0) { - image = getImageWithFoilEffect(image, foilIndex); - } - return image; - } - - /** - * Gets the image associated with a card. - *

- * Adds a random foil effect if enabled. - *

- * For double-sided cards, returns the front-side image.
- * For flip cards, returns the un-flipped image. - */ - @Deprecated - public static BufferedImage getImage(Card card) { - BufferedImage image = ImageCache.getOriginalImage(card.getImageKey(), true); - int foilIndex = card.getFoil(); - if (image != null && foilIndex > 0) { - image = getImageWithFoilEffect(image, foilIndex); - } - return image; - } + private FImageUtil() {} /** * Gets the image associated with a card. diff --git a/forge-gui-desktop/src/main/java/forge/view/ButtonUtil.java b/forge-gui-desktop/src/main/java/forge/view/ButtonUtil.java index 52f4f00181d..2ec42532427 100644 --- a/forge-gui-desktop/src/main/java/forge/view/ButtonUtil.java +++ b/forge-gui-desktop/src/main/java/forge/view/ButtonUtil.java @@ -18,6 +18,7 @@ package forge.view; import forge.FThreads; +import forge.GuiBase; import forge.gui.SOverlayUtils; import forge.screens.match.VMatchUI; @@ -68,7 +69,7 @@ public class ButtonUtil { // ensure we don't steal focus from an overlay if (!SOverlayUtils.overlayHasFocus()) { - FThreads.invokeInEdtLater(new Runnable() { @Override public void run() { button.requestFocusInWindow(); } }); + FThreads.invokeInEdtLater(GuiBase.getInterface(), new Runnable() { @Override public void run() { button.requestFocusInWindow(); } }); } } diff --git a/forge-gui-desktop/src/main/java/forge/view/SimulateMatch.java b/forge-gui-desktop/src/main/java/forge/view/SimulateMatch.java index df75eb573f4..395aabd76f1 100644 --- a/forge-gui-desktop/src/main/java/forge/view/SimulateMatch.java +++ b/forge-gui-desktop/src/main/java/forge/view/SimulateMatch.java @@ -21,7 +21,7 @@ import forge.util.Lang; public class SimulateMatch { public static void simulate(String[] args) { - FModel.initialize(null); + FModel.initialize(GuiBase.getInterface(), null); System.out.println("Simulation mode"); if(args.length < 3 ) { diff --git a/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanelContainer.java b/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanelContainer.java index 599cbd42419..fb5f6110c7d 100644 --- a/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanelContainer.java +++ b/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanelContainer.java @@ -30,6 +30,7 @@ import java.util.List; import javax.swing.SwingUtilities; import forge.FThreads; +import forge.GuiBase; import forge.screens.match.CMatchUI; import forge.toolbox.FScrollPane; import forge.toolbox.FSkin.SkinnedPanel; @@ -332,7 +333,7 @@ public abstract class CardPanelContainer extends SkinnedPanel { * a {@link forge.view.arcane.CardPanel} object. */ public final void removeCardPanel(final CardPanel fromPanel) { - FThreads.assertExecutedByEdt(true); + FThreads.assertExecutedByEdt(GuiBase.getInterface(), true); if (CardPanelContainer.this.getMouseDragPanel() != null) { CardPanel.getDragAnimationPanel().setVisible(false); CardPanel.getDragAnimationPanel().repaint(); @@ -384,7 +385,7 @@ public abstract class CardPanelContainer extends SkinnedPanel { *

*/ public final void clear() { - FThreads.assertExecutedByEdt(true); + FThreads.assertExecutedByEdt(GuiBase.getInterface(), true); for (CardPanel p : CardPanelContainer.this.getCardPanels()) { p.dispose(); } diff --git a/forge-gui-desktop/src/main/java/forge/view/arcane/PlayArea.java b/forge-gui-desktop/src/main/java/forge/view/arcane/PlayArea.java index 0ee0321df71..c67a4a30ed5 100644 --- a/forge-gui-desktop/src/main/java/forge/view/arcane/PlayArea.java +++ b/forge-gui-desktop/src/main/java/forge/view/arcane/PlayArea.java @@ -28,6 +28,7 @@ import java.util.List; import com.google.common.collect.Lists; import forge.FThreads; +import forge.GuiBase; import forge.screens.match.CMatchUI; import forge.screens.match.controllers.CPrompt; import forge.toolbox.FScrollPane; @@ -590,7 +591,7 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen *

*/ public void setupPlayZone() { - FThreads.assertExecutedByEdt(true); + FThreads.assertExecutedByEdt(GuiBase.getInterface(), true); recalculateCardPanels(model); } diff --git a/forge-gui-desktop/src/test/java/forge/BoosterDraft1Test.java b/forge-gui-desktop/src/test/java/forge/BoosterDraft1Test.java index 833140e0c6f..9c7bde42cbd 100644 --- a/forge-gui-desktop/src/test/java/forge/BoosterDraft1Test.java +++ b/forge-gui-desktop/src/test/java/forge/BoosterDraft1Test.java @@ -3,6 +3,7 @@ package forge; import forge.deck.CardPool; import forge.limited.BoosterDraft; import forge.limited.LimitedPoolType; + import org.testng.annotations.Test; /** @@ -19,7 +20,7 @@ public class BoosterDraft1Test { */ @Test(groups = { "UnitTest", "fast" }, timeOut = 1000, enabled = false) public void boosterDraft1Test1() throws Exception { - final BoosterDraft draft = BoosterDraft.createDraft(LimitedPoolType.Full); + final BoosterDraft draft = BoosterDraft.createDraft(GuiBase.getInterface(), LimitedPoolType.Full); if (draft == null) { return; } while (draft.hasNextChoice()) { diff --git a/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java b/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java index 05474fce7c7..d34bb1f56a2 100644 --- a/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java +++ b/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java @@ -97,7 +97,7 @@ public class PlayerControllerForTests extends PlayerController { public void playSpellAbilityNoStack(SpellAbility effectSA, boolean mayChoseNewTargets) { //TODO: eventually (when the real code is refactored) this should be handled normally... if (effectSA.getDescription().equals("At the beginning of your upkeep, if you have exactly 1 life, you win the game.")) {//test_104_2b_effect_may_state_that_player_wins_the_game - HumanPlay.playSpellAbilityNoStack(player, effectSA, !mayChoseNewTargets); + HumanPlay.playSpellAbilityNoStack(null, player, effectSA, !mayChoseNewTargets); return; } SpellAbilityAi sai = SpellApiToAi.Converter.get(effectSA.getApi()); @@ -106,7 +106,7 @@ public class PlayerControllerForTests extends PlayerController { (effectSA.getHostCard().getName().equals("Laboratory Maniac") && sai instanceof GameWinAi) || (effectSA.getHostCard().getName().equals("Nefarious Lich") && sai instanceof ChangeZoneAi) ) {//test_104_3f_if_a_player_would_win_and_lose_simultaneously_he_loses - HumanPlay.playSpellAbilityNoStack(player, effectSA, !mayChoseNewTargets); + HumanPlay.playSpellAbilityNoStack(null, player, effectSA, !mayChoseNewTargets); return; } throw new IllegalStateException("Callers of this method currently assume that it performs extra functionality!"); diff --git a/forge-gui/src/main/java/forge/FThreads.java b/forge-gui/src/main/java/forge/FThreads.java index 686d4787d38..45368fdd994 100644 --- a/forge-gui/src/main/java/forge/FThreads.java +++ b/forge-gui/src/main/java/forge/FThreads.java @@ -1,9 +1,9 @@ package forge; -import forge.util.ThreadUtil; - import java.io.PrintStream; +import forge.interfaces.IGuiBase; +import forge.util.ThreadUtil; public class FThreads { private FThreads() { } // no instances supposed @@ -15,8 +15,8 @@ public class FThreads { * @param methodName   String, part of the custom exception message. * @param mustBeEDT   boolean: true = exception if not EDT, false = exception if EDT */ - public static void assertExecutedByEdt(final boolean mustBeEDT) { - if (isGuiThread() != mustBeEDT) { + public static void assertExecutedByEdt(final IGuiBase gui, final boolean mustBeEDT) { + if (isGuiThread(gui) != mustBeEDT) { StackTraceElement[] trace = Thread.currentThread().getStackTrace(); final String methodName = trace[2].getClassName() + "." + trace[2].getMethodName(); String modalOperator = mustBeEDT ? " must be" : " may not be"; @@ -24,16 +24,16 @@ public class FThreads { } } - public static void invokeInEdtLater(Runnable runnable) { - GuiBase.getInterface().invokeInEdtLater(runnable); + public static void invokeInEdtLater(final IGuiBase gui, final Runnable runnable) { + gui.invokeInEdtLater(runnable); } - public static void invokeInEdtNowOrLater(Runnable proc) { - if (isGuiThread()) { + public static void invokeInEdtNowOrLater(final IGuiBase gui, final Runnable proc) { + if (isGuiThread(gui)) { proc.run(); } else { - invokeInEdtLater(proc); + invokeInEdtLater(gui, proc); } } @@ -49,8 +49,8 @@ public class FThreads { * the Runnable to run * @see fgd.SwingUtilities#invokeLater(Runnable) */ - public static void invokeInEdtAndWait(final Runnable proc) { - GuiBase.getInterface().invokeInEdtAndWait(proc); + public static void invokeInEdtAndWait(final IGuiBase gui, final Runnable proc) { + gui.invokeInEdtAndWait(proc); } private static int backgroundThreadCount; @@ -60,31 +60,31 @@ public class FThreads { backgroundThreadCount++; } - public static boolean isGuiThread() { - return GuiBase.getInterface().isGuiThread(); + public static boolean isGuiThread(IGuiBase gui) { + return gui.isGuiThread(); } - public static void delayInEDT(int milliseconds, final Runnable inputUpdater) { + public static void delayInEDT(final IGuiBase gui, final int milliseconds, final Runnable inputUpdater) { Runnable runInEdt = new Runnable() { @Override public void run() { - FThreads.invokeInEdtNowOrLater(inputUpdater); + FThreads.invokeInEdtNowOrLater(gui, inputUpdater); } }; ThreadUtil.delay(milliseconds, runInEdt); } - public static String debugGetCurrThreadId() { - return isGuiThread() ? "EDT" : Thread.currentThread().getName(); + public static String debugGetCurrThreadId(final IGuiBase gui) { + return isGuiThread(gui) ? "EDT" : Thread.currentThread().getName(); } - public static String prependThreadId(String message) { - return debugGetCurrThreadId() + " > " + message; + public static String prependThreadId(final IGuiBase gui, String message) { + return debugGetCurrThreadId(gui) + " > " + message; } - public static void dumpStackTrace(PrintStream stream) { + public static void dumpStackTrace(final IGuiBase gui, final PrintStream stream) { StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - stream.printf("%s > %s called from %s%n", debugGetCurrThreadId(), + stream.printf("%s > %s called from %s%n", debugGetCurrThreadId(gui), trace[2].getClassName() + "." + trace[2].getMethodName(), trace[3].toString()); int i = 0; for (StackTraceElement se : trace) { @@ -93,7 +93,7 @@ public class FThreads { } } - public static String debugGetStackTraceItem(int depth, boolean shorter) { + public static String debugGetStackTraceItem(final IGuiBase gui, final int depth, final boolean shorter) { StackTraceElement[] trace = Thread.currentThread().getStackTrace(); String lastItem = trace[depth].toString(); if (shorter) { @@ -101,13 +101,13 @@ public class FThreads { lastPeriod = lastItem.lastIndexOf('.', lastPeriod-1); lastPeriod = lastItem.lastIndexOf('.', lastPeriod-1); lastItem = lastItem.substring(lastPeriod+1); - return String.format("%s > from %s", debugGetCurrThreadId(), lastItem); + return String.format("%s > from %s", debugGetCurrThreadId(gui), lastItem); } - return String.format("%s > %s called from %s", debugGetCurrThreadId(), + return String.format("%s > %s called from %s", debugGetCurrThreadId(gui), trace[2].getClassName() + "." + trace[2].getMethodName(), lastItem); } - public static String debugGetStackTraceItem(int depth) { - return debugGetStackTraceItem(depth, false); + public static String debugGetStackTraceItem(final IGuiBase gui, final int depth) { + return debugGetStackTraceItem(gui, depth, false); } } diff --git a/forge-gui/src/main/java/forge/card/CardScriptInfo.java b/forge-gui/src/main/java/forge/card/CardScriptInfo.java index f99059ea417..e39405a150d 100644 --- a/forge-gui/src/main/java/forge/card/CardScriptInfo.java +++ b/forge-gui/src/main/java/forge/card/CardScriptInfo.java @@ -17,20 +17,18 @@ */ package forge.card; -import forge.CardStorageReader; -import forge.card.CardRules; -import forge.properties.ForgeConstants; -import forge.util.FileUtil; -import forge.util.gui.SOptionPane; - -import org.apache.commons.lang3.StringUtils; - import java.io.File; import java.io.PrintWriter; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import org.apache.commons.lang3.StringUtils; + +import forge.CardStorageReader; +import forge.properties.ForgeConstants; +import forge.util.FileUtil; + public final class CardScriptInfo { private String text; private File file; @@ -53,20 +51,21 @@ public final class CardScriptInfo { } public boolean trySetText(String text0) { - if (file == null) { return false; } + if (file == null) { return false; } - try { - PrintWriter p = new PrintWriter(file); - p.print(text0); - p.close(); + try { + PrintWriter p = new PrintWriter(file); + p.print(text0); + p.close(); - text = text0; - return true; - } - catch (final Exception ex) { - SOptionPane.showErrorDialog("Problem writing file - " + file + " : " + ex); - return false; - } + text = text0; + return true; + } + catch (final Exception ex) { + System.err.println("Problem writing file - " + file); + ex.printStackTrace(); + return false; + } } private static Map allScripts = new ConcurrentHashMap<>(); diff --git a/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java b/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java index 243e3e98b46..f8c3cbb4889 100644 --- a/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java +++ b/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java @@ -1,34 +1,69 @@ package forge.control; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; +import java.util.Vector; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.commons.lang3.tuple.Pair; + +import com.google.common.collect.Iterables; import com.google.common.collect.Sets; import com.google.common.eventbus.Subscribe; import forge.FThreads; -import forge.GuiBase; import forge.game.Game; import forge.game.card.Card; -import forge.game.event.*; +import forge.game.event.GameEvent; +import forge.game.event.GameEventAnteCardsSelected; +import forge.game.event.GameEventAttackersDeclared; +import forge.game.event.GameEventBlockersDeclared; +import forge.game.event.GameEventCardAttachment; +import forge.game.event.GameEventCardCounters; +import forge.game.event.GameEventCardDamaged; +import forge.game.event.GameEventCardPhased; +import forge.game.event.GameEventCardStatsChanged; +import forge.game.event.GameEventCardTapped; +import forge.game.event.GameEventCombatEnded; +import forge.game.event.GameEventGameFinished; +import forge.game.event.GameEventGameOutcome; +import forge.game.event.GameEventManaPool; +import forge.game.event.GameEventPlayerControl; +import forge.game.event.GameEventPlayerLivesChanged; +import forge.game.event.GameEventPlayerPoisoned; +import forge.game.event.GameEventPlayerPriority; +import forge.game.event.GameEventSpellAbilityCast; +import forge.game.event.GameEventSpellRemovedFromStack; +import forge.game.event.GameEventSpellResolved; +import forge.game.event.GameEventTurnBegan; +import forge.game.event.GameEventTurnPhase; +import forge.game.event.GameEventZone; +import forge.game.event.IGameEventVisitor; import forge.game.player.Player; import forge.game.zone.PlayerZone; import forge.game.zone.Zone; import forge.game.zone.ZoneType; +import forge.interfaces.IGuiBase; import forge.match.input.ButtonUtil; import forge.match.input.InputBase; import forge.model.FModel; +import forge.player.PlayerControllerHuman; import forge.properties.ForgePreferences.FPref; import forge.util.Lang; import forge.util.gui.SGuiChoose; import forge.util.maps.MapOfLists; import forge.view.CardView; - -import org.apache.commons.lang3.tuple.Pair; - -import java.util.*; -import java.util.Map.Entry; -import java.util.concurrent.atomic.AtomicBoolean; +import forge.view.PlayerView; public class FControlGameEventHandler extends IGameEventVisitor.Base { - public FControlGameEventHandler() { + private final PlayerControllerHuman controller; + private final IGuiBase gui; + public FControlGameEventHandler(final PlayerControllerHuman controller) { + this.controller = controller; + this.gui = controller.getGui(); } @Subscribe @@ -41,11 +76,11 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { public Void visit(final GameEventTurnPhase ev) { if (phaseUpdPlanned.getAndSet(true)) return null; - FThreads.invokeInEdtNowOrLater(new Runnable() { + FThreads.invokeInEdtNowOrLater(gui, new Runnable() { @Override public void run() { phaseUpdPlanned.set(false); - GuiBase.getInterface().updatePhase(); + gui.updatePhase(); } }); return null; @@ -58,11 +93,11 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { @Override public Void visit(GameEventPlayerPriority event) { if (combatUpdPlanned.getAndSet(true)) { return null; } - FThreads.invokeInEdtNowOrLater(new Runnable() { + FThreads.invokeInEdtNowOrLater(gui, new Runnable() { @Override public void run() { combatUpdPlanned.set(false); - GuiBase.getInterface().showCombat(GuiBase.getInterface().getGame().getCombat()); + gui.showCombat(controller.getCombat()); } }); return null; @@ -73,16 +108,16 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { public Void visit(final GameEventTurnBegan event) { if (FModel.getPreferences().getPrefBoolean(FPref.UI_STACK_CREATURES) && event.turnOwner != null) { // anything except stack will get here - updateZone(Pair.of(event.turnOwner, ZoneType.Battlefield)); + updateZone(Pair.of(controller.getPlayerView(event.turnOwner), ZoneType.Battlefield)); } if (turnUpdPlanned.getAndSet(true)) { return null; } - FThreads.invokeInEdtNowOrLater(new Runnable() { + FThreads.invokeInEdtNowOrLater(gui, new Runnable() { @Override public void run() { turnUpdPlanned.set(false); - GuiBase.getInterface().updateTurn(event); + gui.updateTurn(controller.getPlayerView(event.turnOwner)); } }); return null; @@ -97,20 +132,20 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { options.add(fakeCard); options.add(kv.getValue()); } - SGuiChoose.reveal("These cards were chosen to ante", options); + SGuiChoose.reveal(gui, "These cards were chosen to ante", options); return null; } @Override public Void visit(GameEventPlayerControl ev) { - if (GuiBase.getInterface().getGame().isGameOver()) { + if (gui.getGame().isGameOver()) { return null; } - FThreads.invokeInEdtNowOrLater(new Runnable() { + FThreads.invokeInEdtNowOrLater(gui, new Runnable() { @Override public void run() { - GuiBase.getInterface().updatePlayerControl(); + gui.updatePlayerControl(); } }); return null; @@ -119,25 +154,25 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { private final Runnable unlockGameThreadOnGameOver = new Runnable() { @Override public void run() { - GuiBase.getInterface().getInputQueue().onGameOver(true); // this will unlock any game threads waiting for inputs to complete + gui.getInputQueue().onGameOver(true); // this will unlock any game threads waiting for inputs to complete } }; @Override public Void visit(GameEventGameOutcome ev) { - FThreads.invokeInEdtNowOrLater(unlockGameThreadOnGameOver); + FThreads.invokeInEdtNowOrLater(gui, unlockGameThreadOnGameOver); return null; } @Override public Void visit(GameEventGameFinished ev) { - FThreads.invokeInEdtNowOrLater(new Runnable() { + FThreads.invokeInEdtNowOrLater(gui, new Runnable() { @Override public void run() { InputBase.cancelAwaitNextInput(); //ensure "Waiting for opponent..." doesn't appear behind WinLo - GuiBase.getInterface().showPromptMessage(""); //clear prompt behind WinLose overlay - ButtonUtil.update("", "", false, false, false); - GuiBase.getInterface().finishGame(); + gui.showPromptMessage(""); //clear prompt behind WinLose overlay + ButtonUtil.update(gui, "", "", false, false, false); + gui.finishGame(); } }); return null; @@ -148,38 +183,38 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { @Override public void run() { stackUpdPlanned.set(false); - GuiBase.getInterface().updateStack(); + gui.updateStack(); } }; @Override public Void visit(GameEventSpellAbilityCast event) { if (!stackUpdPlanned.getAndSet(true)) { - FThreads.invokeInEdtNowOrLater(updStack); + FThreads.invokeInEdtNowOrLater(gui, updStack); } return null; } @Override public Void visit(GameEventSpellResolved event) { if (!stackUpdPlanned.getAndSet(true)) { - FThreads.invokeInEdtNowOrLater(updStack); + FThreads.invokeInEdtNowOrLater(gui, updStack); } return null; } @Override public Void visit(GameEventSpellRemovedFromStack event) { if (!stackUpdPlanned.getAndSet(true)) { - FThreads.invokeInEdtNowOrLater(updStack); + FThreads.invokeInEdtNowOrLater(gui, updStack); } return null; } - private final List> zonesToUpdate = new Vector>(); + private final List> zonesToUpdate = new Vector>(); private final Runnable updZones = new Runnable() { @Override public void run() { synchronized (zonesToUpdate) { - GuiBase.getInterface().updateZones(zonesToUpdate); + gui.updateZones(zonesToUpdate); zonesToUpdate.clear(); } } @@ -189,7 +224,7 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { public Void visit(GameEventZone event) { if (event.player != null) { // anything except stack will get here - updateZone(Pair.of(event.player, event.zoneType)); + updateZone(Pair.of(controller.getPlayerView(event.player), event.zoneType)); } return null; } @@ -208,11 +243,11 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { return updateZone(zEq); } - private Void updateZone(Zone z) { - return updateZone(Pair.of(z.getPlayer(), z.getZoneType())); + private Void updateZone(final Zone z) { + return updateZone(Pair.of(controller.getPlayerView(z.getPlayer()), z.getZoneType())); } - private Void updateZone(Pair kv) { + private Void updateZone(final Pair kv) { boolean needUpdate = false; synchronized (zonesToUpdate) { needUpdate = zonesToUpdate.isEmpty(); @@ -221,7 +256,7 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { } } if (needUpdate) { - FThreads.invokeInEdtNowOrLater(updZones); + FThreads.invokeInEdtNowOrLater(gui, updZones); } return null; } @@ -231,37 +266,37 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { @Override public void run() { synchronized (cardsToUpdate) { - GuiBase.getInterface().updateCards(cardsToUpdate); + gui.updateCards(cardsToUpdate); cardsToUpdate.clear(); } } }; @Override - public Void visit(GameEventCardTapped event) { - return updateSingleCard(event.card); + public Void visit(final GameEventCardTapped event) { + return updateSingleCard(controller.getCardView(event.card)); } @Override - public Void visit(GameEventCardPhased event) { - return updateSingleCard(event.card); + public Void visit(final GameEventCardPhased event) { + return updateSingleCard(controller.getCardView(event.card)); } @Override - public Void visit(GameEventCardDamaged event) { - return updateSingleCard(event.card); + public Void visit(final GameEventCardDamaged event) { + return updateSingleCard(controller.getCardView(event.card)); } @Override - public Void visit(GameEventCardCounters event) { - return updateSingleCard(event.card); + public Void visit(final GameEventCardCounters event) { + return updateSingleCard(controller.getCardView(event.card)); } @Override - public Void visit(GameEventBlockersDeclared event) { // This is to draw icons on blockers declared by AI + public Void visit(final GameEventBlockersDeclared event) { // This is to draw icons on blockers declared by AI for (MapOfLists kv : event.blockers.values()) { for (Collection blockers : kv.values()) { - updateManyCards(blockers); + updateManyCards(controller.getCardViews(blockers)); } } return super.visit(event); @@ -270,13 +305,13 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { @Override public Void visit(GameEventAttackersDeclared event) { // Skip redraw for GUI player? - if (event.player.getLobbyPlayer() == GuiBase.getInterface().getGuiPlayer()) { + if (event.player.getLobbyPlayer() == gui.getGuiPlayer()) { return null; } // Update all attackers. // Although they might have been updated when they were apped, there could be someone with vigilance, not redrawn yet. - updateManyCards(event.attackersMap.values()); + updateManyCards(controller.getCardViews(event.attackersMap.values())); return super.visit(event); } @@ -284,8 +319,8 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { @Override public Void visit(GameEventCombatEnded event) { // This should remove sword/shield icons from combatants by the time game moves to M2 - updateManyCards(event.attackers); - updateManyCards(event.blockers); + updateManyCards(controller.getCardViews(event.attackers)); + updateManyCards(controller.getCardViews(event.blockers)); return null; } @@ -298,19 +333,19 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { } } if (needUpdate) { - FThreads.invokeInEdtNowOrLater(updCards); + FThreads.invokeInEdtNowOrLater(gui, updCards); } return null; } - private Void updateManyCards(Collection cc) { + private Void updateManyCards(final Iterable cc) { boolean needUpdate = false; synchronized (cardsToUpdate) { needUpdate = cardsToUpdate.isEmpty(); - cardsToUpdate.addAll(cc); + Iterables.addAll(cardsToUpdate, cc); } if (needUpdate) { - FThreads.invokeInEdtNowOrLater(updCards); + FThreads.invokeInEdtNowOrLater(gui, updCards); } return null; } @@ -320,8 +355,9 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { */ @Override public Void visit(GameEventCardStatsChanged event) { - GuiBase.getInterface().refreshCardDetails(event.cards); - return updateManyCards(event.cards); + final Iterable cardViews = controller.getCardViews(event.cards); + gui.refreshCardDetails(cardViews); + return updateManyCards(cardViews); } // Update manapool @@ -329,7 +365,7 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { private final Runnable updManaPool = new Runnable() { @Override public void run() { synchronized (manaPoolUpdate) { - GuiBase.getInterface().updateManaPool(manaPoolUpdate); + gui.updateManaPool(controller.getPlayerViews(manaPoolUpdate)); manaPoolUpdate.clear(); } } @@ -345,7 +381,7 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { } } if (invokeUpdate) { - FThreads.invokeInEdtNowOrLater(updManaPool); + FThreads.invokeInEdtNowOrLater(gui, updManaPool); } return null; } @@ -355,7 +391,7 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { private final Runnable updLives = new Runnable() { @Override public void run() { synchronized (livesUpdate) { - GuiBase.getInterface().updateLives(livesUpdate); + gui.updateLives(controller.getPlayerViews(livesUpdate)); livesUpdate.clear(); } } @@ -370,7 +406,7 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { } } if (invokeUpdate) { - FThreads.invokeInEdtNowOrLater(updLives); + FThreads.invokeInEdtNowOrLater(gui, updLives); } return null; } @@ -385,7 +421,7 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { } } if (invokeUpdate) { - FThreads.invokeInEdtNowOrLater(updLives); + FThreads.invokeInEdtNowOrLater(gui, updLives); } return null; } diff --git a/forge-gui/src/main/java/forge/control/FControlGamePlayback.java b/forge-gui/src/main/java/forge/control/FControlGamePlayback.java index 0f47c7d7e8d..988ea1f612b 100644 --- a/forge-gui/src/main/java/forge/control/FControlGamePlayback.java +++ b/forge-gui/src/main/java/forge/control/FControlGamePlayback.java @@ -1,23 +1,46 @@ package forge.control; -import com.google.common.eventbus.Subscribe; - -import forge.FThreads; -import forge.GuiBase; -import forge.game.event.*; -import forge.match.input.InputPlaybackControl; - import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.atomic.AtomicBoolean; +import com.google.common.eventbus.Subscribe; + +import forge.FThreads; +import forge.game.Game; +import forge.game.event.GameEvent; +import forge.game.event.GameEventBlockersDeclared; +import forge.game.event.GameEventGameFinished; +import forge.game.event.GameEventGameStarted; +import forge.game.event.GameEventLandPlayed; +import forge.game.event.GameEventPlayerPriority; +import forge.game.event.GameEventSpellAbilityCast; +import forge.game.event.GameEventSpellResolved; +import forge.game.event.GameEventTurnPhase; +import forge.game.event.IGameEventVisitor; +import forge.match.input.InputPlaybackControl; +import forge.player.PlayerControllerHuman; + public class FControlGamePlayback extends IGameEventVisitor.Base { - private final InputPlaybackControl inputPlayback = new InputPlaybackControl(this); + private InputPlaybackControl inputPlayback; private final AtomicBoolean paused = new AtomicBoolean(false); private final CyclicBarrier gameThreadPauser = new CyclicBarrier(2); - public FControlGamePlayback() { + private final PlayerControllerHuman controller; + public FControlGamePlayback(final PlayerControllerHuman controller) { + this.controller = controller; + } + + private Game game; + + public Game getGame() { + return game; + } + + public void setGame(Game game) { + this.game = game; + this.inputPlayback = new InputPlaybackControl(controller.getGui(), game, this); } @Subscribe @@ -50,13 +73,14 @@ public class FControlGamePlayback extends IGameEventVisitor.Base { */ @Override public Void visit(GameEventTurnPhase ev) { - boolean isUiToStop = GuiBase.getInterface().stopAtPhase(ev.playerTurn, ev.phase); + boolean isUiToStop = controller.getGui().stopAtPhase( + controller.getPlayerView(ev.playerTurn), ev.phase); switch(ev.phase) { case COMBAT_END: case COMBAT_DECLARE_ATTACKERS: case COMBAT_DECLARE_BLOCKERS: - if (GuiBase.getInterface().getGame().getPhaseHandler().inCombat()) { + if (getGame().getPhaseHandler().inCombat()) { pauseForEvent(combatDelay); } break; @@ -75,13 +99,13 @@ public class FControlGamePlayback extends IGameEventVisitor.Base { */ @Override public Void visit(GameEventGameFinished event) { - GuiBase.getInterface().getInputQueue().removeInput(inputPlayback); + controller.getGui().getInputQueue().removeInput(inputPlayback); return null; } @Override public Void visit(GameEventGameStarted event) { - GuiBase.getInterface().getInputQueue().setInput(inputPlayback); + controller.getGui().getInputQueue().setInput(inputPlayback); return null; } @@ -93,7 +117,13 @@ public class FControlGamePlayback extends IGameEventVisitor.Base { @Override public Void visit(final GameEventSpellResolved event) { - FThreads.invokeInEdtNowOrLater(new Runnable() { @Override public void run() { GuiBase.getInterface().setCard(event.spell.getHostCard()); } }); + FThreads.invokeInEdtNowOrLater(controller.getGui(), new Runnable() { + @Override + public void run() { + controller.getGui().setCard( + controller.getCardView(event.spell.getHostCard())); + } + }); pauseForEvent(resolveDelay); return null; } @@ -103,7 +133,13 @@ public class FControlGamePlayback extends IGameEventVisitor.Base { */ @Override public Void visit(final GameEventSpellAbilityCast event) { - FThreads.invokeInEdtNowOrLater(new Runnable() { @Override public void run() { GuiBase.getInterface().setCard(event.sa.getHostCard()); } }); + FThreads.invokeInEdtNowOrLater(controller.getGui(), new Runnable() { + @Override + public void run() { + controller.getGui().setCard( + controller.getCardView(event.sa.getHostCard())); + } + }); pauseForEvent(castDelay); return null; } @@ -139,7 +175,7 @@ public class FControlGamePlayback extends IGameEventVisitor.Base { private void releaseGameThread() { // just need to run another thread through the barrier... not edt preferrably :) - GuiBase.getInterface().getGame().getAction().invoke(new Runnable() { + getGame().getAction().invoke(new Runnable() { @Override public void run() { try { diff --git a/forge-gui/src/main/java/forge/deck/ColorDeckGenerator.java b/forge-gui/src/main/java/forge/deck/ColorDeckGenerator.java index 23a27a30a2f..6e4c5dca740 100644 --- a/forge-gui/src/main/java/forge/deck/ColorDeckGenerator.java +++ b/forge-gui/src/main/java/forge/deck/ColorDeckGenerator.java @@ -3,17 +3,20 @@ package forge.deck; import java.util.ArrayList; import java.util.List; +import forge.interfaces.IGuiBase; import forge.itemmanager.IItemManager; public class ColorDeckGenerator extends DeckProxy implements Comparable { + private final IGuiBase gui; private String name; private int index; private final IItemManager lstDecks; private final boolean isAi; - public ColorDeckGenerator(String name0, int index0, IItemManager lstDecks0, boolean isAi0) { + public ColorDeckGenerator(final IGuiBase gui, String name0, int index0, IItemManager lstDecks0, boolean isAi0) { super(); + this.gui = gui; name = name0; index = index0; lstDecks = lstDecks0; @@ -42,7 +45,7 @@ public class ColorDeckGenerator extends DeckProxy implements Comparable 0) { - BugReporter.reportBug(errorBuilder.toString()); + throw new RuntimeException(errorBuilder.toString()); } return deck; } diff --git a/forge-gui/src/main/java/forge/deck/DeckgenUtil.java b/forge-gui/src/main/java/forge/deck/DeckgenUtil.java index 1dc48aef318..0cdb6eae47b 100644 --- a/forge-gui/src/main/java/forge/deck/DeckgenUtil.java +++ b/forge-gui/src/main/java/forge/deck/DeckgenUtil.java @@ -12,6 +12,7 @@ import forge.deck.CardPool; import forge.deck.Deck; import forge.deck.DeckSection; import forge.deck.generation.*; +import forge.interfaces.IGuiBase; import forge.item.PaperCard; import forge.itemmanager.IItemManager; import forge.model.FModel; @@ -186,18 +187,18 @@ public class DeckgenUtil { * @param colors0 String[] * @return boolean */ - public static boolean colorCheck(final List colors0) { + public static boolean colorCheck(final IGuiBase gui, final List colors0) { boolean result = true; if (colors0.size() == 4) { - SOptionPane.showMessageDialog( + SOptionPane.showMessageDialog(gui, "Sorry, four color generated decks aren't supported yet." + "\n\rPlease use 2, 3, or 5 colors for this deck.", "Generate deck: 4 colors", SOptionPane.ERROR_ICON); result = false; } else if (colors0.size() > 5) { - SOptionPane.showMessageDialog( + SOptionPane.showMessageDialog(gui, "Generate deck: maximum five colors!", "Generate deck: too many colors", SOptionPane.ERROR_ICON); result = false; diff --git a/forge-gui/src/main/java/forge/deck/io/OldDeckParser.java b/forge-gui/src/main/java/forge/deck/io/OldDeckParser.java index d73305d0482..9a09566332d 100644 --- a/forge-gui/src/main/java/forge/deck/io/OldDeckParser.java +++ b/forge-gui/src/main/java/forge/deck/io/OldDeckParser.java @@ -19,6 +19,7 @@ package forge.deck.io; import forge.deck.Deck; import forge.deck.DeckGroup; +import forge.interfaces.IGuiBase; import forge.properties.ForgeConstants; import forge.util.FileSection; import forge.util.FileUtil; @@ -47,6 +48,8 @@ public class OldDeckParser { } }; + private final IGuiBase gui; + /** * TODO: Write javadoc for Constructor. * @@ -56,8 +59,9 @@ public class OldDeckParser { * @param sealed2 the sealed2 * @param cube2 the cube2 */ - public OldDeckParser(final IStorage constructed2, final IStorage draft2, + public OldDeckParser(final IGuiBase gui, final IStorage constructed2, final IStorage draft2, final IStorage sealed2, final IStorage cube2) { + this.gui = gui; this.deckDir = new File(ForgeConstants.DECK_BASE_DIR); this.sealed = sealed2; this.constructed = constructed2; @@ -145,7 +149,7 @@ public class OldDeckParser { this.draft.add(d); } else { final String msg = String.format("Draft '%s' lacked some decks.%n%nShould it be deleted?"); - mayDelete = SOptionPane.showConfirmDialog(msg, "Draft loading error"); + mayDelete = SOptionPane.showConfirmDialog(gui, msg, "Draft loading error"); } if (mayDelete) { @@ -181,7 +185,7 @@ public class OldDeckParser { final String msg = String .format("Can not convert deck '%s' for some unsupported cards it contains. %n%s%n%nMay Forge delete all such decks?", name, ex.getMessage()); - allowDeleteUnsupportedConstructed = SOptionPane.showConfirmDialog(msg, "Problem converting decks"); + allowDeleteUnsupportedConstructed = SOptionPane.showConfirmDialog(gui, msg, "Problem converting decks"); } } if (importedOk || allowDeleteUnsupportedConstructed) { @@ -200,7 +204,7 @@ public class OldDeckParser { final String msg = String .format("Can not convert deck '%s' for some unsupported cards it contains. %n%s%n%nMay Forge delete all such decks?", name, ex.getMessage()); - allowDeleteUnsupportedConstructed = SOptionPane.showConfirmDialog(msg, "Problem converting decks"); + allowDeleteUnsupportedConstructed = SOptionPane.showConfirmDialog(gui, msg, "Problem converting decks"); } } if (importedOk || allowDeleteUnsupportedConstructed) { @@ -252,7 +256,7 @@ public class OldDeckParser { } sb.append(System.getProperty("line.separator")); sb.append("May Forge delete these decks?"); - if (SOptionPane.showConfirmDialog(sb.toString(), "Some of your sealed decks are orphaned")) { + if (SOptionPane.showConfirmDialog(gui, sb.toString(), "Some of your sealed decks are orphaned")) { for (final Pair> s : sealedDecks.values()) { if (s.getRight().getLeft() != null) { s.getRight().getLeft().delete(); diff --git a/forge-gui/src/main/java/forge/download/GuiDownloadService.java b/forge-gui/src/main/java/forge/download/GuiDownloadService.java index 8133a9d5ecf..63cc0e23a11 100644 --- a/forge-gui/src/main/java/forge/download/GuiDownloadService.java +++ b/forge-gui/src/main/java/forge/download/GuiDownloadService.java @@ -17,31 +17,36 @@ */ package forge.download; -import com.esotericsoftware.minlog.Log; - -import forge.FThreads; -import forge.GuiBase; -import forge.UiCommand; -import forge.error.BugReporter; -import forge.interfaces.IButton; -import forge.interfaces.IProgressBar; -import forge.interfaces.ITextField; -import forge.util.FileUtil; -import forge.util.MyRandom; - -import org.apache.commons.lang3.tuple.Pair; - import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; -import java.net.*; +import java.net.ConnectException; +import java.net.HttpURLConnection; +import java.net.InetSocketAddress; +import java.net.MalformedURLException; +import java.net.Proxy; +import java.net.URL; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.util.Map; import java.util.Map.Entry; import java.util.Random; +import org.apache.commons.lang3.tuple.Pair; + +import com.esotericsoftware.minlog.Log; + +import forge.FThreads; +import forge.UiCommand; +import forge.error.BugReporter; +import forge.interfaces.IButton; +import forge.interfaces.IGuiBase; +import forge.interfaces.IProgressBar; +import forge.interfaces.ITextField; +import forge.util.FileUtil; +import forge.util.MyRandom; + @SuppressWarnings("serial") public abstract class GuiDownloadService implements Runnable { public static final Proxy.Type[] TYPES = Proxy.Type.values(); @@ -53,12 +58,13 @@ public abstract class GuiDownloadService implements Runnable { private IButton btnStart; private UiCommand cmdClose; private Runnable onUpdate; + private IGuiBase gui; private final UiCommand cmdStartDownload = new UiCommand() { @Override public void run() { //invalidate image cache so newly downloaded images will be loaded - GuiBase.getInterface().clearImageCache(); + gui.clearImageCache(); FThreads.invokeInBackgroundThread(GuiDownloadService.this); btnStart.setEnabled(false); } @@ -78,13 +84,14 @@ public abstract class GuiDownloadService implements Runnable { protected GuiDownloadService() { } - public void initialize(ITextField txtAddress0, ITextField txtPort0, IProgressBar progressBar0, IButton btnStart0, UiCommand cmdClose0, final Runnable onReadyToStart, Runnable onUpdate0) { + public void initialize(final IGuiBase gui, ITextField txtAddress0, ITextField txtPort0, IProgressBar progressBar0, IButton btnStart0, UiCommand cmdClose0, final Runnable onReadyToStart, Runnable onUpdate0) { txtAddress = txtAddress0; txtPort = txtPort0; progressBar = progressBar0; btnStart = btnStart0; cmdClose = cmdClose0; onUpdate = onUpdate0; + this.gui = gui; // Free up the EDT by assembling card list on a background thread FThreads.invokeInBackgroundThread(new Runnable() { @@ -96,7 +103,7 @@ public abstract class GuiDownloadService implements Runnable { catch (Exception e) { e.printStackTrace(); } - FThreads.invokeInEdtLater(new Runnable() { + FThreads.invokeInEdtLater(gui, new Runnable() { @Override public void run() { if (onReadyToStart != null) { @@ -123,7 +130,7 @@ public abstract class GuiDownloadService implements Runnable { } btnStart.setEnabled(true); - FThreads.invokeInEdtLater(new Runnable() { + FThreads.invokeInEdtLater(gui, new Runnable() { @Override public void run() { btnStart.requestFocusInWindow(); @@ -162,7 +169,7 @@ public abstract class GuiDownloadService implements Runnable { } private void update(final int count, final File dest) { - FThreads.invokeInEdtLater(new Runnable() { + FThreads.invokeInEdtLater(gui, new Runnable() { @Override public void run() { if (onUpdate != null) { diff --git a/forge-gui/src/main/java/forge/error/BugReporter.java b/forge-gui/src/main/java/forge/error/BugReporter.java index cf97f4df58b..370fc299be1 100644 --- a/forge-gui/src/main/java/forge/error/BugReporter.java +++ b/forge-gui/src/main/java/forge/error/BugReporter.java @@ -17,16 +17,21 @@ */ package forge.error; -import forge.FThreads; -import forge.GuiBase; -import forge.util.BuildInfo; -import forge.util.gui.SOptionPane; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.Map; +import java.util.Map.Entry; import org.apache.commons.lang3.StringUtils; -import java.io.*; -import java.util.Map; -import java.util.Map.Entry; +import forge.FThreads; +import forge.interfaces.IGuiBase; +import forge.util.BuildInfo; +import forge.util.gui.SOptionPane; /** * The class ErrorViewer. Enables showing and saving error messages that @@ -68,22 +73,22 @@ public class BugReporter { * Shows exception information in a format ready to post to the forum as a crash report. Uses the exception's message * as the reason if message is null. */ - public static void reportException(final Throwable ex, final String message) { + public static void reportException(final Throwable ex, final IGuiBase gui, final String message) { if (ex == null) { return; } if (message != null) { - System.err.printf("%s > %s%n", FThreads.debugGetCurrThreadId(), message); + System.err.printf("%s > %s%n", FThreads.debugGetCurrThreadId(gui), message); } - System.err.print(FThreads.debugGetCurrThreadId() + " > "); + System.err.print(FThreads.debugGetCurrThreadId(gui) + " > "); ex.printStackTrace(); StringBuilder sb = new StringBuilder(); sb.append("Description: [describe what you were doing when the crash occurred]\n\n"); - buildSpoilerHeader(sb, ex.getClass().getSimpleName()); + buildSpoilerHeader(gui, sb, ex.getClass().getSimpleName()); sb.append("\n\n"); if (null != message && !message.isEmpty()) { - sb.append(FThreads.debugGetCurrThreadId()).append(" > ").append(message).append("\n"); + sb.append(FThreads.debugGetCurrThreadId(gui)).append(" > ").append(message).append("\n"); } StringWriter sw = new StringWriter(); @@ -100,10 +105,10 @@ public class BugReporter { else { sb.append(swStr); } - + buildSpoilerFooter(sb); - GuiBase.getInterface().showBugReportDialog("Report a crash", sb.toString(), true); + gui.showBugReportDialog("Report a crash", sb.toString(), true); } /** @@ -123,26 +128,26 @@ public class BugReporter { /** * Shows a forum post template for reporting a bug. */ - public static void reportBug(String details) { + public static void reportBug(final IGuiBase gui, final String details) { StringBuilder sb = new StringBuilder(); sb.append("Description: [describe the problem]\n\n"); - buildSpoilerHeader(sb, "General bug report"); + buildSpoilerHeader(gui, sb, "General bug report"); if (null != details && !details.isEmpty()) { sb.append("\n\n"); sb.append(details); } buildSpoilerFooter(sb); - GuiBase.getInterface().showBugReportDialog("Report a bug", sb.toString(), false); + gui.showBugReportDialog("Report a bug", sb.toString(), false); } /** * Shows thread stack information in a format ready to post to the forum. */ - public static void reportThreadStacks(final String message) { + public static void reportThreadStacks(final IGuiBase gui,final String message) { StringBuilder sb = new StringBuilder(); sb.append("Description: [describe what you were doing at the time]\n\n"); - buildSpoilerHeader(sb, "Thread stack dump"); + buildSpoilerHeader(gui, sb, "Thread stack dump"); sb.append("\n\n"); if (null != message && !message.isEmpty()) { sb.append(message); @@ -162,7 +167,7 @@ public class BugReporter { sb.append(sw.toString()); buildSpoilerFooter(sb); - GuiBase.getInterface().showBugReportDialog("Thread stack dump", sb.toString(), false); + gui.showBugReportDialog("Thread stack dump", sb.toString(), false); } /** @@ -172,9 +177,9 @@ public class BugReporter { reportThreadStacks(String.format(format, args)); } - private static StringBuilder buildSpoilerHeader(StringBuilder sb, String reportTitle) { + private static StringBuilder buildSpoilerHeader(final IGuiBase gui, final StringBuilder sb, final String reportTitle) { sb.append("[spoiler=").append(reportTitle).append("][code]"); - sb.append("\nForge Version: ").append(GuiBase.getInterface().getCurrentVersion()); + sb.append("\nForge Version: ").append(gui.getCurrentVersion()); sb.append("\nOperating System: ").append(System.getProperty("os.name")) .append(" ").append(System.getProperty("os.version")) .append(" ").append(System.getProperty("os.arch")); @@ -188,19 +193,19 @@ public class BugReporter { return sb; } - public static void copyAndGoToForums(String text) { + public static void copyAndGoToForums(final IGuiBase gui, final String text) { try { // copy text to clipboard - GuiBase.getInterface().copyToClipboard(text); - GuiBase.getInterface().browseToUrl(FORUM_URL); + gui.copyToClipboard(text); + gui.browseToUrl(FORUM_URL); } catch (Exception ex) { - SOptionPane.showMessageDialog("Sorry, a problem occurred while opening the forum in your default browser.", + SOptionPane.showMessageDialog(gui, "Sorry, a problem occurred while opening the forum in your default browser.", "A problem occurred", SOptionPane.ERROR_ICON); } } - public static void saveToFile(String text) { + public static void saveToFile(final IGuiBase gui, final String text) { File f; long curTime = System.currentTimeMillis(); for (int i = 0;; i++) { @@ -211,7 +216,7 @@ public class BugReporter { } } - f = GuiBase.getInterface().getSaveFile(f); + f = gui.getSaveFile(f); try { final BufferedWriter bw = new BufferedWriter(new FileWriter(f)); @@ -219,7 +224,7 @@ public class BugReporter { bw.close(); } catch (final IOException ex) { - SOptionPane.showMessageDialog("There was an error during saving. Sorry!\n" + ex, + SOptionPane.showMessageDialog(gui, "There was an error during saving. Sorry!\n" + ex, "Error saving file", SOptionPane.ERROR_ICON); } } diff --git a/forge-gui/src/main/java/forge/gauntlet/GauntletWinLoseController.java b/forge-gui/src/main/java/forge/gauntlet/GauntletWinLoseController.java index 837f6d60fae..3d8405b8237 100644 --- a/forge-gui/src/main/java/forge/gauntlet/GauntletWinLoseController.java +++ b/forge-gui/src/main/java/forge/gauntlet/GauntletWinLoseController.java @@ -4,7 +4,6 @@ import java.util.List; import com.google.common.collect.Lists; -import forge.GuiBase; import forge.LobbyPlayer; import forge.assets.FSkinProp; import forge.deck.Deck; @@ -19,10 +18,12 @@ import forge.view.IGameView; public abstract class GauntletWinLoseController { private final IGameView lastGame; private final IWinLoseView view; + private final IGuiBase gui; - public GauntletWinLoseController(IWinLoseView view0, final IGameView game0) { + public GauntletWinLoseController(IWinLoseView view0, final IGameView game0, final IGuiBase gui) { view = view0; lastGame = game0; + this.gui = gui; } public void showOutcome() { @@ -47,7 +48,7 @@ public abstract class GauntletWinLoseController { // the player can restart Forge to replay a match. // Pretty sure this can't be fixed until in-game states can be // saved. Doublestrike 07-10-12 - LobbyPlayer questPlayer = GuiBase.getInterface().getQuestPlayer(); + LobbyPlayer questPlayer = gui.getQuestPlayer(); // In all cases, update stats. lstEventRecords.set(gd.getCompleted(), lastGame.getGamesWonBy(questPlayer) + " - " @@ -114,15 +115,14 @@ public abstract class GauntletWinLoseController { GauntletData gd = FModel.getGauntletData(); Deck aiDeck = gd.getDecks().get(gd.getCompleted()); List players = Lists.newArrayList(); - IGuiBase fc = GuiBase.getInterface(); - players.add(new RegisteredPlayer(gd.getUserDeck()).setPlayer(fc.getGuiPlayer())); - players.add(new RegisteredPlayer(aiDeck).setPlayer(fc.createAiPlayer())); + players.add(new RegisteredPlayer(gd.getUserDeck()).setPlayer(gui.getGuiPlayer())); + players.add(new RegisteredPlayer(aiDeck).setPlayer(gui.createAiPlayer())); view.hide(); saveOptions(); - GuiBase.getInterface().endCurrentGame(); + gui.endCurrentGame(); - GuiBase.getInterface().startMatch(GameType.Gauntlet, players); + gui.startMatch(GameType.Gauntlet, players); return true; } return false; diff --git a/forge-gui/src/main/java/forge/interfaces/IGuiBase.java b/forge-gui/src/main/java/forge/interfaces/IGuiBase.java index 8f97298170f..8d93e222830 100644 --- a/forge-gui/src/main/java/forge/interfaces/IGuiBase.java +++ b/forge-gui/src/main/java/forge/interfaces/IGuiBase.java @@ -20,7 +20,6 @@ import forge.game.Match; import forge.game.phase.PhaseType; import forge.game.player.IHasIcon; import forge.game.player.RegisteredPlayer; -import forge.game.spellability.SpellAbility; import forge.game.zone.ZoneType; import forge.item.PaperCard; import forge.match.input.InputQueue; @@ -32,6 +31,7 @@ import forge.view.CombatView; import forge.view.GameEntityView; import forge.view.IGameView; import forge.view.PlayerView; +import forge.view.SpellAbilityView; public interface IGuiBase { boolean isRunningOnDesktop(); @@ -81,7 +81,7 @@ public interface IGuiBase { void updateStack(); void updateZones(List> zonesToUpdate); void updateCards(Set cardsToUpdate); - void refreshCardDetails(Collection cards); + void refreshCardDetails(Iterable cards); void updateManaPool(List manaPoolUpdate); void updateLives(List livesUpdate); void endCurrentGame(); @@ -89,7 +89,7 @@ public interface IGuiBase { void setPanelSelection(CardView hostCard); Map getDamageToAssign(CardView attacker, List blockers, int damageDealt, GameEntityView defender, boolean overrideOrder); - SpellAbility getAbilityToPlay(List abilities, ITriggerEvent triggerEvent); + SpellAbilityView getAbilityToPlay(List abilities, ITriggerEvent triggerEvent); void hear(LobbyPlayer player, String message); int getAvatarCount(); void copyToClipboard(String text); diff --git a/forge-gui/src/main/java/forge/limited/BoosterDraft.java b/forge-gui/src/main/java/forge/limited/BoosterDraft.java index fc725744d7e..10df160a5e6 100644 --- a/forge-gui/src/main/java/forge/limited/BoosterDraft.java +++ b/forge-gui/src/main/java/forge/limited/BoosterDraft.java @@ -25,6 +25,7 @@ import forge.card.UnOpenedProduct; import forge.deck.CardPool; import forge.deck.Deck; import forge.game.card.Card; +import forge.interfaces.IGuiBase; import forge.item.IPaperCard; import forge.item.PaperCard; import forge.item.SealedProduct; @@ -66,13 +67,13 @@ public class BoosterDraft implements IBoosterDraft { protected final List>> product = new ArrayList>>(); - public static BoosterDraft createDraft(final LimitedPoolType draftType) { + public static BoosterDraft createDraft(final IGuiBase gui, final LimitedPoolType draftType) { BoosterDraft draft = new BoosterDraft(draftType); - if (!draft.generateProduct()) { return null; } + if (!draft.generateProduct(gui)) { return null; } return draft; } - protected boolean generateProduct() { + protected boolean generateProduct(final IGuiBase gui) { switch (this.draftFormat) { case Full: // Draft from all cards in Forge Supplier> s = new UnOpenedProduct(SealedProduct.Template.genericBooster); @@ -95,12 +96,12 @@ public class BoosterDraft implements IBoosterDraft { } } - final CardBlock block = SGuiChoose.oneOrNone("Choose Block", blocks); + final CardBlock block = SGuiChoose.oneOrNone(gui, "Choose Block", blocks); if (block == null) { return false; } final CardEdition[] cardSets = block.getSets(); if (cardSets.length == 0) { - SOptionPane.showErrorDialog(block.toString() + " does not contain any set combinations."); + SOptionPane.showErrorDialog(gui, block.toString() + " does not contain any set combinations."); return false; } @@ -118,16 +119,16 @@ public class BoosterDraft implements IBoosterDraft { final int nPacks = block.getCntBoostersDraft(); if (sets.size() > 1) { - final Object p = SGuiChoose.oneOrNone("Choose Set Combination", getSetCombos(sets)); + final Object p = SGuiChoose.oneOrNone(gui, "Choose Set Combination", getSetCombos(sets)); if (p == null) { return false; } final String[] pp = p.toString().split("/"); for (int i = 0; i < nPacks; i++) { - this.product.add(block.getBooster(pp[i])); + this.product.add(block.getBooster(pp[i], gui)); } } else { - IUnOpenedProduct product1 = block.getBooster(sets.get(0)); + IUnOpenedProduct product1 = block.getBooster(sets.get(0), gui); for (int i = 0; i < nPacks; i++) { this.product.add(product1); @@ -141,10 +142,10 @@ public class BoosterDraft implements IBoosterDraft { final List myDrafts = this.loadCustomDrafts(); if (myDrafts.isEmpty()) { - SOptionPane.showMessageDialog("No custom draft files found."); + SOptionPane.showMessageDialog(gui, "No custom draft files found."); } else { - final CustomLimited customDraft = SGuiChoose.oneOrNone("Choose Custom Draft", myDrafts); + final CustomLimited customDraft = SGuiChoose.oneOrNone(gui, "Choose Custom Draft", myDrafts); if (customDraft == null) { return false; } this.setupCustomDraft(customDraft); @@ -159,13 +160,13 @@ public class BoosterDraft implements IBoosterDraft { return true; } - public static BoosterDraft createDraft(final LimitedPoolType draftType, final CardBlock block, final String[] boosters) { + public static BoosterDraft createDraft(final IGuiBase gui, final LimitedPoolType draftType, final CardBlock block, final String[] boosters) { BoosterDraft draft = new BoosterDraft(draftType); final int nPacks = boosters.length; for (int i = 0; i < nPacks; i++) { - draft.product.add(block.getBooster(boosters[i])); + draft.product.add(block.getBooster(boosters[i], gui)); } IBoosterDraft.LAND_SET_CODE[0] = block.getLandSet(); diff --git a/forge-gui/src/main/java/forge/limited/GauntletMini.java b/forge-gui/src/main/java/forge/limited/GauntletMini.java index c5906d8b5da..a52ecc7e7ca 100644 --- a/forge-gui/src/main/java/forge/limited/GauntletMini.java +++ b/forge-gui/src/main/java/forge/limited/GauntletMini.java @@ -17,7 +17,9 @@ */ package forge.limited; -import forge.GuiBase; +import java.util.ArrayList; +import java.util.List; + import forge.deck.Deck; import forge.game.GameType; import forge.game.player.RegisteredPlayer; @@ -25,9 +27,6 @@ import forge.interfaces.IGuiBase; import forge.model.FModel; import forge.util.Aggregates; -import java.util.ArrayList; -import java.util.List; - /** *

* GauntletMini class. @@ -39,6 +38,7 @@ import java.util.List; */ public class GauntletMini { + private final IGuiBase gui; private int rounds; private Deck humanDeck; private int currentRound; @@ -48,6 +48,10 @@ public class GauntletMini { private GameType gauntletType; private List aiOpponents = new ArrayList(); + public GauntletMini(IGuiBase gui) { + this.gui = gui; + } + // private final String humanName; /** * TODO: Write javadoc for Constructor. @@ -81,7 +85,7 @@ public class GauntletMini { } currentRound++; - GuiBase.getInterface().endCurrentGame(); + gui.endCurrentGame(); startRound(); } @@ -135,11 +139,10 @@ public class GauntletMini { */ private void startRound() { List starter = new ArrayList(); - IGuiBase fc = GuiBase.getInterface(); - starter.add(new RegisteredPlayer(humanDeck).setPlayer(fc.getGuiPlayer())); - starter.add(aiOpponents.get(currentRound - 1).setPlayer(fc.createAiPlayer())); + starter.add(new RegisteredPlayer(humanDeck).setPlayer(gui.getGuiPlayer())); + starter.add(aiOpponents.get(currentRound - 1).setPlayer(gui.createAiPlayer())); - fc.startMatch(gauntletType, starter); + gui.startMatch(gauntletType, starter); } /** diff --git a/forge-gui/src/main/java/forge/limited/LimitedWinLoseController.java b/forge-gui/src/main/java/forge/limited/LimitedWinLoseController.java index 80cd7b184fc..4d5aa18b142 100644 --- a/forge-gui/src/main/java/forge/limited/LimitedWinLoseController.java +++ b/forge-gui/src/main/java/forge/limited/LimitedWinLoseController.java @@ -1,23 +1,25 @@ package forge.limited; -import forge.GuiBase; import forge.interfaces.IButton; +import forge.interfaces.IGuiBase; import forge.interfaces.IWinLoseView; import forge.model.FModel; import forge.view.IGameView; public abstract class LimitedWinLoseController { - private final IGameView lastGame; - private final boolean wonMatch; private final IWinLoseView view; + private final IGameView lastGame; + private final IGuiBase gui; + private final boolean wonMatch; private GauntletMini gauntlet; private boolean nextRound = false; - public LimitedWinLoseController(IWinLoseView view0, final IGameView game0) { + public LimitedWinLoseController(IWinLoseView view0, final IGameView game0, final IGuiBase gui) { view = view0; lastGame = game0; - gauntlet = FModel.getGauntletMini(); - wonMatch = lastGame.isMatchWonBy(GuiBase.getInterface().getGuiPlayer()); + this.gui = gui; + gauntlet = FModel.getGauntletMini(gui); + wonMatch = lastGame.isMatchWonBy(gui.getGuiPlayer()); } public void showOutcome() { @@ -29,7 +31,7 @@ public abstract class LimitedWinLoseController { resetView(); nextRound = false; - if (lastGame.isWinner(GuiBase.getInterface().getGuiPlayer())) { + if (lastGame.isWinner(gui.getGuiPlayer())) { gauntlet.addWin(); } else { gauntlet.addLoss(); diff --git a/forge-gui/src/main/java/forge/limited/SealedCardPoolGenerator.java b/forge-gui/src/main/java/forge/limited/SealedCardPoolGenerator.java index 83196ec5aed..94f3e7295e9 100644 --- a/forge-gui/src/main/java/forge/limited/SealedCardPoolGenerator.java +++ b/forge-gui/src/main/java/forge/limited/SealedCardPoolGenerator.java @@ -26,6 +26,7 @@ import forge.deck.CardPool; import forge.deck.Deck; import forge.deck.DeckGroup; import forge.deck.DeckSection; +import forge.interfaces.IGuiBase; import forge.item.PaperCard; import forge.item.SealedProduct; import forge.model.CardBlock; @@ -66,12 +67,12 @@ public class SealedCardPoolGenerator { /** The Land set code. */ private String landSetCode = null; - public static DeckGroup generateSealedDeck(boolean addBasicLands) { + public static DeckGroup generateSealedDeck(final IGuiBase gui, final boolean addBasicLands) { final String prompt = "Choose Sealed Deck Format"; - final LimitedPoolType poolType = SGuiChoose.oneOrNone(prompt, LimitedPoolType.values()); + final LimitedPoolType poolType = SGuiChoose.oneOrNone(gui, prompt, LimitedPoolType.values()); if (poolType == null) { return null; } - SealedCardPoolGenerator sd = new SealedCardPoolGenerator(poolType); + SealedCardPoolGenerator sd = new SealedCardPoolGenerator(gui, poolType); if (sd.isEmpty()) { return null; } final CardPool humanPool = sd.getCardPool(true); @@ -82,10 +83,10 @@ public class SealedCardPoolGenerator { // This seems to be limited by the MAX_DRAFT_PLAYERS constant // in DeckGroupSerializer.java. You could create more AI decks // but only the first seven would load. --BBU - Integer rounds = SGuiChoose.getInteger("How many opponents are you willing to face?", 1, 7); + Integer rounds = SGuiChoose.getInteger(gui, "How many opponents are you willing to face?", 1, 7); if (rounds == null) { return null; } - final String sDeckName = SOptionPane.showInputDialog( + final String sDeckName = SOptionPane.showInputDialog(gui, "Save this card pool as:", "Save Card Pool", FSkinProp.ICO_QUESTION); @@ -96,7 +97,7 @@ public class SealedCardPoolGenerator { final IStorage sealedDecks = FModel.getDecks().getSealed(); if (sealedDecks.contains(sDeckName)) { - if (!SOptionPane.showConfirmDialog( + if (!SOptionPane.showConfirmDialog(gui, "'" + sDeckName + "' already exists. Do you want to replace it?", "Sealed Deck Game Exists")) { return null; @@ -154,11 +155,11 @@ public class SealedCardPoolGenerator { * @param poolType * a {@link java.lang.String} object. */ - private SealedCardPoolGenerator(final LimitedPoolType poolType) { + private SealedCardPoolGenerator(final IGuiBase gui, final LimitedPoolType poolType) { switch(poolType) { case Full: // Choose number of boosters - if (!chooseNumberOfBoosters(new UnOpenedProduct(SealedProduct.Template.genericBooster))) { + if (!chooseNumberOfBoosters(gui, new UnOpenedProduct(SealedProduct.Template.genericBooster))) { return; } landSetCode = CardEdition.Predicates.getRandomSetWithAllBasicLands(FModel.getMagicDb().getEditions()).getCode(); @@ -172,7 +173,7 @@ public class SealedCardPoolGenerator { blocks.add(b); } - final CardBlock block = SGuiChoose.oneOrNone("Choose Block", blocks); + final CardBlock block = SGuiChoose.oneOrNone(gui, "Choose Block", blocks); if (block == null) { return; } final int nPacks = block.getCntBoostersSealed(); @@ -192,7 +193,7 @@ public class SealedCardPoolGenerator { throw new RuntimeException("Unsupported amount of packs (" + nPacks + ") in a Sealed Deck block!"); } - final String p = setCombos.size() > 1 ? SGuiChoose.oneOrNone("Choose packs to play with", setCombos) : setCombos.get(0); + final String p = setCombos.size() > 1 ? SGuiChoose.oneOrNone(gui, "Choose packs to play with", setCombos) : setCombos.get(0); if (p == null) { return; } for (String pz : TextUtil.split(p, ',')) { @@ -200,12 +201,12 @@ public class SealedCardPoolGenerator { String setCode = pps[pps.length - 1]; int nBoosters = pps.length > 1 ? Integer.parseInt(pps[0]) : 1; while (nBoosters-- > 0) { - this.product.add(block.getBooster(setCode)); + this.product.add(block.getBooster(setCode, gui)); } } } else { - IUnOpenedProduct prod = block.getBooster(sets.get(0)); + IUnOpenedProduct prod = block.getBooster(sets.get(0), gui); for (int i = 0; i < nPacks; i++) { this.product.add(prod); } @@ -243,16 +244,16 @@ public class SealedCardPoolGenerator { // present list to user if (customs.isEmpty()) { - SOptionPane.showMessageDialog("No custom sealed files found."); + SOptionPane.showMessageDialog(gui, "No custom sealed files found."); return; } - final CustomLimited draft = SGuiChoose.oneOrNone("Choose Custom Sealed Pool", customs); + final CustomLimited draft = SGuiChoose.oneOrNone(gui, "Choose Custom Sealed Pool", customs); if (draft == null) { return; } UnOpenedProduct toAdd = new UnOpenedProduct(draft.getSealedProductTemplate(), draft.getCardPool()); toAdd.setLimitedPool(draft.isSingleton()); - if (!chooseNumberOfBoosters(toAdd)) { + if (!chooseNumberOfBoosters(gui, toAdd)) { return; } @@ -261,8 +262,8 @@ public class SealedCardPoolGenerator { } } - private boolean chooseNumberOfBoosters(final IUnOpenedProduct product1) { - Integer boosterCount = SGuiChoose.getInteger("How many booster packs?", 3, 12); + private boolean chooseNumberOfBoosters(final IGuiBase gui, final IUnOpenedProduct product1) { + Integer boosterCount = SGuiChoose.getInteger(gui, "How many booster packs?", 3, 12); if (boosterCount == null) { return false; } for (int i = 0; i < boosterCount; i++) { diff --git a/forge-gui/src/main/java/forge/limited/WinstonDraft.java b/forge-gui/src/main/java/forge/limited/WinstonDraft.java index 3b94ec36a56..ff8f02bf51c 100644 --- a/forge-gui/src/main/java/forge/limited/WinstonDraft.java +++ b/forge-gui/src/main/java/forge/limited/WinstonDraft.java @@ -3,8 +3,10 @@ package forge.limited; import com.google.common.base.Predicates; import com.google.common.base.Supplier; import com.google.common.collect.Iterables; + import forge.deck.CardPool; import forge.deck.Deck; +import forge.interfaces.IGuiBase; import forge.item.PaperCard; import forge.util.MyRandom; @@ -18,9 +20,9 @@ public class WinstonDraft extends BoosterDraft { private Stack deck; // main deck where all cards private List> piles; // 3 piles to draft from - public static WinstonDraft createDraft(final LimitedPoolType draftType) { + public static WinstonDraft createDraft(final IGuiBase gui, final LimitedPoolType draftType) { WinstonDraft draft = new WinstonDraft(draftType); - if (!draft.generateProduct()) { + if (!draft.generateProduct(gui)) { return null; } draft.initializeWinstonDraft(); diff --git a/forge-gui/src/main/java/forge/match/MatchUtil.java b/forge-gui/src/main/java/forge/match/MatchUtil.java deleted file mode 100644 index c305ddcf191..00000000000 --- a/forge-gui/src/main/java/forge/match/MatchUtil.java +++ /dev/null @@ -1,31 +0,0 @@ -package forge.match; - -import forge.GuiBase; -import forge.game.Game; -import forge.game.player.Player; -import forge.match.input.Input; -import forge.match.input.InputPassPriority; - -public class MatchUtil { - public static boolean undoLastAction() { - if (canUndoLastAction() && GuiBase.getInterface().getGame().stack.undo()) { - Input currentInput = GuiBase.getInterface().getInputQueue().getInput(); - if (currentInput instanceof InputPassPriority) { - currentInput.showMessageInitial(); //ensure prompt updated if needed - } - return true; - } - return false; - } - - public static boolean canUndoLastAction() { - Game game = GuiBase.getInterface().getGame(); - if (game.stack.canUndo()) { - Player player = game.getPhaseHandler().getPriorityPlayer(); - if (player != null && player.getLobbyPlayer() == GuiBase.getInterface().getGuiPlayer()) { - return true; - } - } - return false; - } -} diff --git a/forge-gui/src/main/java/forge/match/input/ButtonUtil.java b/forge-gui/src/main/java/forge/match/input/ButtonUtil.java index e120ac88282..1efe0092125 100644 --- a/forge-gui/src/main/java/forge/match/input/ButtonUtil.java +++ b/forge-gui/src/main/java/forge/match/input/ButtonUtil.java @@ -17,29 +17,29 @@ */ package forge.match.input; -import forge.GuiBase; import forge.interfaces.IButton; +import forge.interfaces.IGuiBase; /** * Manages match UI OK/Cancel button enabling and focus */ public class ButtonUtil { - public static void update(boolean okEnabled, boolean cancelEnabled, boolean focusOk) { - update("OK", "Cancel", okEnabled, cancelEnabled, focusOk); + public static void update(final IGuiBase gui, boolean okEnabled, boolean cancelEnabled, boolean focusOk) { + update(gui, "OK", "Cancel", okEnabled, cancelEnabled, focusOk); } - public static void update(String okLabel, String cancelLabel, boolean okEnabled, boolean cancelEnabled, boolean focusOk) { - IButton btnOk = GuiBase.getInterface().getBtnOK(); - IButton btnCancel = GuiBase.getInterface().getBtnCancel(); + public static void update(final IGuiBase gui, String okLabel, String cancelLabel, boolean okEnabled, boolean cancelEnabled, boolean focusOk) { + IButton btnOk = gui.getBtnOK(); + IButton btnCancel = gui.getBtnCancel(); btnOk.setText(okLabel); btnCancel.setText(cancelLabel); btnOk.setEnabled(okEnabled); btnCancel.setEnabled(cancelEnabled); if (okEnabled && focusOk) { - GuiBase.getInterface().focusButton(btnOk); + gui.focusButton(btnOk); } else if (cancelEnabled) { - GuiBase.getInterface().focusButton(btnCancel); + gui.focusButton(btnCancel); } } } diff --git a/forge-gui/src/main/java/forge/match/input/InputAttack.java b/forge-gui/src/main/java/forge/match/input/InputAttack.java index 1c4e5032695..2f17adb5ebb 100644 --- a/forge-gui/src/main/java/forge/match/input/InputAttack.java +++ b/forge-gui/src/main/java/forge/match/input/InputAttack.java @@ -17,9 +17,13 @@ */ package forge.match.input; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.tuple.Pair; + import com.google.common.collect.Iterables; -import forge.GuiBase; import forge.events.UiEventAttackerDeclared; import forge.game.GameEntity; import forge.game.card.Card; @@ -31,13 +35,9 @@ import forge.game.combat.Combat; import forge.game.combat.CombatUtil; import forge.game.player.Player; import forge.game.zone.ZoneType; +import forge.player.PlayerControllerHuman; import forge.util.ITriggerEvent; -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.lang3.tuple.Pair; - /** *

* InputAttack class. @@ -56,7 +56,8 @@ public class InputAttack extends InputSyncronizedBase { private final Player playerAttacks; private AttackingBand activeBand = null; - public InputAttack(Player attacks0, Combat combat0) { + public InputAttack(PlayerControllerHuman controller, Player attacks0, Combat combat0) { + super(controller); playerAttacks = attacks0; combat = combat0; defenders = combat.getDefenders(); @@ -77,7 +78,9 @@ public class InputAttack extends InputSyncronizedBase { List> mandatoryAttackers = CombatUtil.getMandatoryAttackers(playerAttacks, combat, defenders); for (Pair attacker : mandatoryAttackers) { combat.addAttacker(attacker.getLeft(), attacker.getRight()); - GuiBase.getInterface().fireEvent(new UiEventAttackerDeclared(attacker.getLeft(), attacker.getRight())); + getGui().fireEvent(new UiEventAttackerDeclared( + getController().getCardView(attacker.getLeft()), + getController().getGameEntityView(attacker.getRight()))); } updateMessage(); } @@ -94,10 +97,10 @@ public class InputAttack extends InputSyncronizedBase { private void updatePrompt() { if (canCallBackAttackers()) { - ButtonUtil.update("OK", "Call Back", true, true, true); + ButtonUtil.update(getGui(), "OK", "Call Back", true, true, true); } else { - ButtonUtil.update("OK", "Alpha Strike", true, true, true); + ButtonUtil.update(getGui(), "OK", "Alpha Strike", true, true, true); } } @@ -225,7 +228,9 @@ public class InputAttack extends InputSyncronizedBase { combat.addAttacker(card, currentDefender, activeBand); activateBand(activeBand); - GuiBase.getInterface().fireEvent(new UiEventAttackerDeclared(card, currentDefender)); + getGui().fireEvent(new UiEventAttackerDeclared( + getController().getCardView(card), + getController().getGameEntityView(currentDefender))); } private boolean canUndeclareAttacker(Card card) { @@ -238,11 +243,12 @@ public class InputAttack extends InputSyncronizedBase { if (canUndeclareAttacker(card)) { // TODO Is there no way to attacks each turn cards to attack Planeswalkers? combat.removeFromCombat(card); - GuiBase.getInterface().setUsedToPay(card, false); + getGui().setUsedToPay(getController().getCardView(card), false); // When removing an attacker clear the attacking band activateBand(null); - GuiBase.getInterface().fireEvent(new UiEventAttackerDeclared(card, null)); + getGui().fireEvent(new UiEventAttackerDeclared( + getController().getCardView(card), null)); return true; } return false; @@ -252,10 +258,10 @@ public class InputAttack extends InputSyncronizedBase { currentDefender = def; for (final GameEntity ge : defenders) { if (ge instanceof Card) { - GuiBase.getInterface().setUsedToPay((Card)ge, ge == def); + getGui().setUsedToPay(getController().getCardView((Card) ge), ge == def); } else if (ge instanceof Player) { - GuiBase.getInterface().setHighlighted((Player) ge, ge == def); + getGui().setHighlighted(getController().getPlayerView((Player) ge), ge == def); } } @@ -265,14 +271,14 @@ public class InputAttack extends InputSyncronizedBase { private final void activateBand(final AttackingBand band) { if (activeBand != null) { for (final Card card : activeBand.getAttackers()) { - GuiBase.getInterface().setUsedToPay(card, false); + getGui().setUsedToPay(getController().getCardView(card), false); } } activeBand = band; if (activeBand != null) { for (final Card card : activeBand.getAttackers()) { - GuiBase.getInterface().setUsedToPay(card, true); + getGui().setUsedToPay(getController().getCardView(card), true); } } } @@ -296,6 +302,6 @@ public class InputAttack extends InputSyncronizedBase { showMessage(message); updatePrompt(); - GuiBase.getInterface().showCombat(combat); // redraw sword icons + getGui().showCombat(getController().getCombat(combat)); // redraw sword icons } } diff --git a/forge-gui/src/main/java/forge/match/input/InputBase.java b/forge-gui/src/main/java/forge/match/input/InputBase.java index ca2203e8b35..fa294141a69 100644 --- a/forge-gui/src/main/java/forge/match/input/InputBase.java +++ b/forge-gui/src/main/java/forge/match/input/InputBase.java @@ -21,12 +21,13 @@ import java.util.Timer; import java.util.TimerTask; import forge.FThreads; -import forge.GuiBase; import forge.game.Game; import forge.game.card.Card; import forge.game.phase.PhaseHandler; import forge.game.player.Player; import forge.game.spellability.SpellAbility; +import forge.interfaces.IGuiBase; +import forge.player.PlayerControllerHuman; import forge.util.ITriggerEvent; /** @@ -40,13 +41,25 @@ import forge.util.ITriggerEvent; public abstract class InputBase implements java.io.Serializable, Input { /** Constant serialVersionUID=-6539552513871194081L. */ private static final long serialVersionUID = -6539552513871194081L; + + private final PlayerControllerHuman controller; + public InputBase(final PlayerControllerHuman controller) { + this.controller = controller; + } + protected final PlayerControllerHuman getController() { + return this.controller; + } + protected IGuiBase getGui() { + return getController().getGui(); + } + private boolean finished = false; protected final boolean isFinished() { return finished; } protected final void setFinished() { finished = true; if (allowAwaitNextInput()) { - awaitNextInput(); + awaitNextInput(getGui()); } } @@ -57,18 +70,18 @@ public abstract class InputBase implements java.io.Serializable, Input { private static final Timer awaitNextInputTimer = new Timer(); private static TimerTask awaitNextInputTask; - public static void awaitNextInput() { + public static void awaitNextInput(final IGuiBase gui) { //delay updating prompt to await next input briefly so buttons don't flicker disabled then enabled awaitNextInputTask = new TimerTask() { @Override public void run() { - FThreads.invokeInEdtLater(new Runnable() { + FThreads.invokeInEdtLater(gui, new Runnable() { @Override public void run() { synchronized (awaitNextInputTimer) { if (awaitNextInputTask != null) { - GuiBase.getInterface().showPromptMessage("Waiting for opponent..."); - ButtonUtil.update(false, false, false); + gui.showPromptMessage("Waiting for opponent..."); + ButtonUtil.update(gui, false, false, false); awaitNextInputTask = null; } } @@ -137,11 +150,11 @@ public abstract class InputBase implements java.io.Serializable, Input { // to remove need for CMatchUI dependence protected final void showMessage(final String message) { - GuiBase.getInterface().showPromptMessage(message); + getGui().showPromptMessage(message); } protected final void flashIncorrectAction() { - GuiBase.getInterface().flashIncorrectAction(); + getGui().flashIncorrectAction(); } protected String getTurnPhasePriorityMessage(final Game game) { diff --git a/forge-gui/src/main/java/forge/match/input/InputBlock.java b/forge-gui/src/main/java/forge/match/input/InputBlock.java index 9eff32b7743..91556fb5cbd 100644 --- a/forge-gui/src/main/java/forge/match/input/InputBlock.java +++ b/forge-gui/src/main/java/forge/match/input/InputBlock.java @@ -18,7 +18,6 @@ package forge.match.input; import forge.FThreads; -import forge.GuiBase; import forge.events.UiEventBlockerAssigned; import forge.game.card.Card; import forge.game.card.CardLists; @@ -27,8 +26,10 @@ import forge.game.combat.Combat; import forge.game.combat.CombatUtil; import forge.game.player.Player; import forge.game.zone.ZoneType; +import forge.player.PlayerControllerHuman; import forge.util.ITriggerEvent; import forge.util.gui.SGuiDialog; +import forge.view.CardView; /** *

@@ -47,7 +48,8 @@ public class InputBlock extends InputSyncronizedBase { private final Combat combat; private final Player defender; - public InputBlock(Player defender0, Combat combat0) { + public InputBlock(final PlayerControllerHuman controller, final Player defender0, final Combat combat0) { + super(controller); defender = defender0; combat = combat0; @@ -55,7 +57,7 @@ public class InputBlock extends InputSyncronizedBase { for (final Card attacker : combat.getAttackers()) { for (final Card c : CardLists.filter(defender.getCardsIn(ZoneType.Battlefield), Presets.CREATURES)) { if (CombatUtil.canBlock(attacker, c, combat)) { - FThreads.invokeInEdtNowOrLater(new Runnable() { //must set current attacker on EDT + FThreads.invokeInEdtNowOrLater(getGui(), new Runnable() { //must set current attacker on EDT @Override public void run() { setCurrentAttacker(attacker); @@ -71,7 +73,7 @@ public class InputBlock extends InputSyncronizedBase { @Override protected final void showMessage() { // could add "Reset Blockers" button - ButtonUtil.update(true, false, true); + ButtonUtil.update(getGui(), true, false, true); if (currentAttacker == null) { showMessage("Select another attacker to declare blockers for."); @@ -82,7 +84,7 @@ public class InputBlock extends InputSyncronizedBase { showMessage(message); } - GuiBase.getInterface().showCombat(combat); + getGui().showCombat(getController().getCombat(combat)); } /** {@inheritDoc} */ @@ -95,7 +97,7 @@ public class InputBlock extends InputSyncronizedBase { stop(); } else { - SGuiDialog.message(blockErrors); + SGuiDialog.message(getGui(), blockErrors); } } @@ -105,7 +107,8 @@ public class InputBlock extends InputSyncronizedBase { boolean isCorrectAction = false; if (triggerEvent != null && triggerEvent.getButton() == 3 && card.getController() == defender) { combat.removeFromCombat(card); - GuiBase.getInterface().fireEvent(new UiEventBlockerAssigned(card, (Card)null)); + getGui().fireEvent(new UiEventBlockerAssigned( + getController().getCardView(card), (CardView) null)); isCorrectAction = true; } else { @@ -120,14 +123,17 @@ public class InputBlock extends InputSyncronizedBase { if (combat.isBlocking(card, currentAttacker)) { //if creature already blocking current attacker, remove blocker from combat combat.removeBlockAssignment(currentAttacker, card); - GuiBase.getInterface().fireEvent(new UiEventBlockerAssigned(card, (Card)null)); + getGui().fireEvent(new UiEventBlockerAssigned( + getController().getCardView(card), (CardView) null)); isCorrectAction = true; } else { isCorrectAction = CombatUtil.canBlock(currentAttacker, card, combat); if (isCorrectAction) { combat.addBlocker(currentAttacker, card); - GuiBase.getInterface().fireEvent(new UiEventBlockerAssigned(card, currentAttacker)); + getGui().fireEvent(new UiEventBlockerAssigned( + getController().getCardView(card), + getController().getCardView(currentAttacker))); } } } @@ -141,10 +147,10 @@ public class InputBlock extends InputSyncronizedBase { return isCorrectAction; } - private void setCurrentAttacker(Card card) { + private void setCurrentAttacker(final Card card) { currentAttacker = card; - for (Card c : combat.getAttackers()) { - GuiBase.getInterface().setUsedToPay(c, card == c); + for (final Card c : combat.getAttackers()) { + getGui().setUsedToPay(getController().getCardView(c), card == c); } } } diff --git a/forge-gui/src/main/java/forge/match/input/InputConfirm.java b/forge-gui/src/main/java/forge/match/input/InputConfirm.java index 0f1472bae2a..e7441ab8603 100644 --- a/forge-gui/src/main/java/forge/match/input/InputConfirm.java +++ b/forge-gui/src/main/java/forge/match/input/InputConfirm.java @@ -17,6 +17,8 @@ */ package forge.match.input; +import forge.player.PlayerControllerHuman; + /** *

* InputConfirm class. @@ -34,15 +36,16 @@ public class InputConfirm extends InputSyncronizedBase { private final boolean defaultYes; private boolean result; - public InputConfirm(String message0) { - this(message0, "Yes", "No", true); + public InputConfirm(final PlayerControllerHuman controller, String message0) { + this(controller, message0, "Yes", "No", true); } - public InputConfirm(String message0, String yesButtonText0, String noButtonText0) { - this(message0, yesButtonText0, noButtonText0, true); + public InputConfirm(final PlayerControllerHuman controller, String message0, String yesButtonText0, String noButtonText0) { + this(controller, message0, yesButtonText0, noButtonText0, true); } - public InputConfirm(String message0, String yesButtonText0, String noButtonText0, boolean defaultYes0) { + public InputConfirm(final PlayerControllerHuman controller, String message0, String yesButtonText0, String noButtonText0, boolean defaultYes0) { + super(controller); message = message0; yesButtonText = yesButtonText0; noButtonText = noButtonText0; @@ -53,7 +56,7 @@ public class InputConfirm extends InputSyncronizedBase { /** {@inheritDoc} */ @Override protected final void showMessage() { - ButtonUtil.update(yesButtonText, noButtonText, true, true, defaultYes); + ButtonUtil.update(getGui(), yesButtonText, noButtonText, true, true, defaultYes); showMessage(message); } diff --git a/forge-gui/src/main/java/forge/match/input/InputConfirmMulligan.java b/forge-gui/src/main/java/forge/match/input/InputConfirmMulligan.java index c98a1579287..d697aae5e2e 100644 --- a/forge-gui/src/main/java/forge/match/input/InputConfirmMulligan.java +++ b/forge-gui/src/main/java/forge/match/input/InputConfirmMulligan.java @@ -17,18 +17,19 @@ */ package forge.match.input; -import forge.GuiBase; +import java.util.ArrayList; +import java.util.List; + import forge.game.Game; import forge.game.card.Card; import forge.game.player.Player; import forge.game.zone.ZoneType; +import forge.player.PlayerControllerHuman; import forge.util.ITriggerEvent; import forge.util.Lang; import forge.util.ThreadUtil; import forge.util.gui.SGuiDialog; - -import java.util.ArrayList; -import java.util.List; +import forge.view.CardView; /** *

@@ -49,7 +50,8 @@ public class InputConfirmMulligan extends InputSyncronizedBase { private final Player player; private final Player startingPlayer; - public InputConfirmMulligan(Player humanPlayer, Player startsGame, boolean commander) { + public InputConfirmMulligan(final PlayerControllerHuman controller, final Player humanPlayer, final Player startsGame, final boolean commander) { + super(controller); player = humanPlayer; isCommander = commander; startingPlayer = startsGame; @@ -70,11 +72,11 @@ public class InputConfirmMulligan extends InputSyncronizedBase { } if (isCommander) { - ButtonUtil.update("Keep", "Exile", true, false, true); + ButtonUtil.update(getGui(), "Keep", "Exile", true, false, true); sb.append("Will you keep your hand or choose some cards to exile those and draw one less card?"); } else { - ButtonUtil.update("Keep", "Mulligan", true, true, true); + ButtonUtil.update(getGui(), "Keep", "Mulligan", true, true, true); sb.append("Do you want to keep your hand?"); } @@ -98,8 +100,8 @@ public class InputConfirmMulligan extends InputSyncronizedBase { private void done() { if (isCommander) { // Clear the "selected" icon after clicking the done button - for (Card c : this.selected) { - GuiBase.getInterface().setUsedToPay(c, false); + for (final Card c : this.selected) { + getGui().setUsedToPay(getController().getCardView(c), false); } } stop(); @@ -117,7 +119,8 @@ public class InputConfirmMulligan extends InputSyncronizedBase { return false; } - if (isSerumPowder && SGuiDialog.confirm(c0, "Use " + c0.getName() + "'s ability?")) { + final CardView cView = getController().getCardView(c0); + if (isSerumPowder && SGuiDialog.confirm(getGui(), cView, "Use " + cView + "'s ability?")) { cardSelectLocked = true; ThreadUtil.invokeInGameThread(new Runnable() { public void run() { @@ -134,14 +137,14 @@ public class InputConfirmMulligan extends InputSyncronizedBase { if (isCommander) { // allow to choose cards for partial paris if (selected.contains(c0)) { - GuiBase.getInterface().setUsedToPay(c0, false); + getGui().setUsedToPay(getController().getCardView(c0), false); selected.remove(c0); } else { - GuiBase.getInterface().setUsedToPay(c0, true); + getGui().setUsedToPay(getController().getCardView(c0), true); selected.add(c0); } - ButtonUtil.update("Keep", "Exile", true, !selected.isEmpty(), true); + ButtonUtil.update(getGui(), "Keep", "Exile", true, !selected.isEmpty(), true); } return true; } diff --git a/forge-gui/src/main/java/forge/match/input/InputLockUI.java b/forge-gui/src/main/java/forge/match/input/InputLockUI.java index d763a2cff53..b0b884c66a8 100644 --- a/forge-gui/src/main/java/forge/match/input/InputLockUI.java +++ b/forge-gui/src/main/java/forge/match/input/InputLockUI.java @@ -1,21 +1,28 @@ package forge.match.input; +import java.util.concurrent.atomic.AtomicInteger; + import forge.FThreads; -import forge.GuiBase; import forge.game.Game; import forge.game.card.Card; import forge.game.player.Player; import forge.game.spellability.SpellAbility; +import forge.interfaces.IGuiBase; import forge.util.ITriggerEvent; import forge.util.ThreadUtil; -import java.util.concurrent.atomic.AtomicInteger; - - public class InputLockUI implements Input { private final AtomicInteger iCall = new AtomicInteger(); - public InputLockUI(InputQueue inputQueue) { + private final IGuiBase gui; + private final Game game; + public InputLockUI(final IGuiBase gui, final Game game, final InputQueue inputQueue) { + this.gui = gui; + this.game = game; + } + + private IGuiBase getGui() { + return gui; } public void showMessageInitial() { @@ -39,24 +46,24 @@ public class InputLockUI implements Input { public void run() { if ( ixCall != iCall.get() || !isActive()) // cancel the message if it's not from latest call or input is gone already return; - FThreads.invokeInEdtLater(showMessageFromEdt); + FThreads.invokeInEdtLater(getGui(), showMessageFromEdt); } }; private final Runnable showMessageFromEdt = new Runnable() { @Override public void run() { - ButtonUtil.update("", "", false, false, false); + ButtonUtil.update(getGui(), "", "", false, false, false); showMessage("Waiting for actions..."); } }; protected final boolean isActive() { - return GuiBase.getInterface().getInputQueue().getInput() == this; + return getGui().getInputQueue().getInput() == this; } protected void showMessage(String message) { - GuiBase.getInterface().showPromptMessage(message); + getGui().showPromptMessage(message); } @Override @@ -75,7 +82,6 @@ public class InputLockUI implements Input { @Override public void selectButtonCancel() { //cancel auto pass for all players - Game game = GuiBase.getInterface().getGame(); for (Player player : game.getPlayers()) { player.getController().autoPassCancel(); } diff --git a/forge-gui/src/main/java/forge/match/input/InputPassPriority.java b/forge-gui/src/main/java/forge/match/input/InputPassPriority.java index 15deb4b65b2..c7bdc785e3f 100644 --- a/forge-gui/src/main/java/forge/match/input/InputPassPriority.java +++ b/forge-gui/src/main/java/forge/match/input/InputPassPriority.java @@ -17,20 +17,19 @@ */ package forge.match.input; -import forge.GuiBase; +import java.util.List; + import forge.game.Game; import forge.game.card.Card; import forge.game.player.Player; import forge.game.spellability.SpellAbility; -import forge.match.MatchUtil; import forge.model.FModel; +import forge.player.PlayerControllerHuman; import forge.properties.ForgePreferences.FPref; import forge.util.ITriggerEvent; import forge.util.ThreadUtil; import forge.util.gui.SOptionPane; -import java.util.List; - /** *

* Input_PassPriority class. @@ -46,7 +45,8 @@ public class InputPassPriority extends InputSyncronizedBase { private SpellAbility chosenSa; - public InputPassPriority(Player human) { + public InputPassPriority(final PlayerControllerHuman controller, final Player human) { + super(controller); player = human; } @@ -55,11 +55,11 @@ public class InputPassPriority extends InputSyncronizedBase { public final void showMessage() { showMessage(getTurnPhasePriorityMessage(player.getGame())); chosenSa = null; - if (MatchUtil.canUndoLastAction()) { //allow undoing with cancel button if can undo last action - ButtonUtil.update("OK", "Undo", true, true, true); + if (getController().canUndoLastAction()) { //allow undoing with cancel button if can undo last action + ButtonUtil.update(getGui(), "OK", "Undo", true, true, true); } else { //otherwise allow ending turn with cancel button - ButtonUtil.update("OK", "End Turn", true, true, true); + ButtonUtil.update(getGui(), "OK", "End Turn", true, true, true); } } @@ -77,7 +77,7 @@ public class InputPassPriority extends InputSyncronizedBase { /** {@inheritDoc} */ @Override protected final void onCancel() { - if (!MatchUtil.undoLastAction()) { //undo if possible + if (!getController().tryUndoLastAction()) { //undo if possible //otherwise end turn passPriority(new Runnable() { @Override @@ -97,10 +97,10 @@ public class InputPassPriority extends InputSyncronizedBase { private void passPriority(final Runnable runnable) { if (FModel.getPreferences().getPrefBoolean(FPref.UI_MANA_LOST_PROMPT)) { //if gui player has mana floating that will be lost if phase ended right now, prompt before passing priority - Game game = GuiBase.getInterface().getGame(); + final Game game = player.getGame(); if (game.getStack().isEmpty()) { //phase can't end right now if stack isn't empty Player player = game.getPhaseHandler().getPriorityPlayer(); - if (player != null && player.getManaPool().willManaBeLostAtEndOfPhase() && player.getLobbyPlayer() == GuiBase.getInterface().getGuiPlayer()) { + if (player != null && player.getManaPool().willManaBeLostAtEndOfPhase() && player.getLobbyPlayer() == getGui().getGuiPlayer()) { ThreadUtil.invokeInGameThread(new Runnable() { //must invoke in game thread so dialog can be shown on mobile game @Override public void run() { @@ -108,7 +108,7 @@ public class InputPassPriority extends InputSyncronizedBase { if (FModel.getPreferences().getPrefBoolean(FPref.UI_MANABURN)) { message += " You will take mana burn damage equal to the amount of floating mana lost this way."; } - if (SOptionPane.showOptionDialog(message, "Mana Floating", SOptionPane.WARNING_ICON, new String[]{"OK", "Cancel"}) == 0) { + if (SOptionPane.showOptionDialog(getGui(), message, "Mana Floating", SOptionPane.WARNING_ICON, new String[]{"OK", "Cancel"}) == 0) { runnable.run(); } } diff --git a/forge-gui/src/main/java/forge/match/input/InputPayMana.java b/forge-gui/src/main/java/forge/match/input/InputPayMana.java index b974fca3fce..df07aa70d0c 100644 --- a/forge-gui/src/main/java/forge/match/input/InputPayMana.java +++ b/forge-gui/src/main/java/forge/match/input/InputPayMana.java @@ -1,7 +1,12 @@ package forge.match.input; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; + import forge.FThreads; -import forge.GuiBase; import forge.ai.ComputerUtilMana; import forge.ai.PlayerControllerAi; import forge.card.ColorSet; @@ -17,16 +22,11 @@ import forge.game.replacement.ReplacementEffect; import forge.game.spellability.AbilityManaPart; import forge.game.spellability.SpellAbility; import forge.player.HumanPlay; +import forge.player.PlayerControllerHuman; import forge.util.Evaluator; import forge.util.ITriggerEvent; import forge.util.gui.SGuiChoose; -import org.apache.commons.lang3.StringUtils; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - public abstract class InputPayMana extends InputSyncronizedBase { private static final long serialVersionUID = -9133423708688480255L; @@ -45,20 +45,21 @@ public abstract class InputPayMana extends InputSyncronizedBase { private boolean locked = false; - protected InputPayMana(SpellAbility saPaidFor0, Player player0) { + protected InputPayMana(final PlayerControllerHuman controller, final SpellAbility saPaidFor0, final Player player0) { + super(controller); player = player0; game = player.getGame(); saPaidFor = saPaidFor0; //if player is floating mana, show mana pool to make it easier to use that mana wasFloatingMana = !player.getManaPool().isEmpty(); - zoneToRestore = wasFloatingMana ? GuiBase.getInterface().showManaPool(player) : null; + zoneToRestore = wasFloatingMana ? getGui().showManaPool(getController().getPlayerView(player)) : null; } @Override protected void onStop() { if (wasFloatingMana) { //hide mana pool if it was shown due to floating mana - GuiBase.getInterface().hideManaPool(player, zoneToRestore); + getGui().hideManaPool(getController().getPlayerView(player), zoneToRestore); } } @@ -244,7 +245,7 @@ public abstract class InputPayMana extends InputSyncronizedBase { final SpellAbility chosen; if (chosenAbility == null) { - chosen = abilities.size() > 1 && choice ? SGuiChoose.one("Choose mana ability", abilities) : abilities.get(0); + chosen = abilities.size() > 1 && choice ? SGuiChoose.one(getGui(), "Choose mana ability", abilities) : abilities.get(0); } else { chosen = chosenAbility; @@ -256,7 +257,7 @@ public abstract class InputPayMana extends InputSyncronizedBase { Runnable proc = new Runnable() { @Override public void run() { - HumanPlay.playSpellAbility(chosen.getActivatingPlayer(), chosen); + HumanPlay.playSpellAbility(getController(), chosen.getActivatingPlayer(), chosen); player.getManaPool().payManaFromAbility(saPaidFor, InputPayMana.this.manaCost, chosen); onManaAbilityPaid(); @@ -370,10 +371,10 @@ public abstract class InputPayMana extends InputSyncronizedBase { protected void updateButtons() { if (supportAutoPay()) { - ButtonUtil.update("Auto", "Cancel", false, true, false); + ButtonUtil.update(getGui(), "Auto", "Cancel", false, true, false); } else { - ButtonUtil.update("", "Cancel", false, true, false); + ButtonUtil.update(getGui(), "", "Cancel", false, true, false); } } @@ -392,7 +393,7 @@ public abstract class InputPayMana extends InputSyncronizedBase { canPayManaCost = proc.getResult(); } if (canPayManaCost) { //enabled Auto button if mana cost can be paid - ButtonUtil.update("Auto", "Cancel", true, true, true); + ButtonUtil.update(getGui(), "Auto", "Cancel", true, true, true); } } showMessage(getMessage()); @@ -412,7 +413,7 @@ public abstract class InputPayMana extends InputSyncronizedBase { stop(); } else { - FThreads.invokeInEdtNowOrLater(new Runnable() { + FThreads.invokeInEdtNowOrLater(getGui(), new Runnable() { @Override public void run() { updateMessage(); diff --git a/forge-gui/src/main/java/forge/match/input/InputPayManaOfCostPayment.java b/forge-gui/src/main/java/forge/match/input/InputPayManaOfCostPayment.java index 37d65bc530b..9d1605c2e19 100644 --- a/forge-gui/src/main/java/forge/match/input/InputPayManaOfCostPayment.java +++ b/forge-gui/src/main/java/forge/match/input/InputPayManaOfCostPayment.java @@ -4,11 +4,12 @@ import forge.game.card.Card; import forge.game.mana.ManaCostBeingPaid; import forge.game.player.Player; import forge.game.spellability.SpellAbility; +import forge.player.PlayerControllerHuman; import forge.util.ITriggerEvent; public class InputPayManaOfCostPayment extends InputPayMana { - public InputPayManaOfCostPayment(ManaCostBeingPaid cost, SpellAbility spellAbility, Player payer) { - super(spellAbility, payer); + public InputPayManaOfCostPayment(final PlayerControllerHuman controller, ManaCostBeingPaid cost, SpellAbility spellAbility, Player payer) { + super(controller, spellAbility, payer); manaCost = cost; } diff --git a/forge-gui/src/main/java/forge/match/input/InputPayManaSimple.java b/forge-gui/src/main/java/forge/match/input/InputPayManaSimple.java index fcde4ade39a..06f12728a37 100644 --- a/forge-gui/src/main/java/forge/match/input/InputPayManaSimple.java +++ b/forge-gui/src/main/java/forge/match/input/InputPayManaSimple.java @@ -23,6 +23,7 @@ import forge.game.card.Card; import forge.game.mana.ManaCostBeingPaid; import forge.game.player.Player; import forge.game.spellability.SpellAbility; +import forge.player.PlayerControllerHuman; import forge.util.ITriggerEvent; //pays the cost of a card played from the player's hand @@ -36,8 +37,8 @@ public class InputPayManaSimple extends InputPayMana { private final Card originalCard; private final ManaCost originalManaCost; - public InputPayManaSimple(final Game game, final SpellAbility sa, final ManaCostBeingPaid manaCostToPay) { - super(sa, sa.getActivatingPlayer()); + public InputPayManaSimple(final PlayerControllerHuman controller, final Game game, final SpellAbility sa, final ManaCostBeingPaid manaCostToPay) { + super(controller, sa, sa.getActivatingPlayer()); this.originalManaCost = manaCostToPay.toManaCost(); this.originalCard = sa.getHostCard(); diff --git a/forge-gui/src/main/java/forge/match/input/InputPayManaX.java b/forge-gui/src/main/java/forge/match/input/InputPayManaX.java index 7a75f431739..92bcef4d4bd 100644 --- a/forge-gui/src/main/java/forge/match/input/InputPayManaX.java +++ b/forge-gui/src/main/java/forge/match/input/InputPayManaX.java @@ -1,5 +1,10 @@ package forge.match.input; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; + import forge.card.ColorSet; import forge.card.mana.ManaCost; import forge.card.mana.ManaCostParser; @@ -7,13 +12,9 @@ import forge.game.card.Card; import forge.game.mana.Mana; import forge.game.mana.ManaCostBeingPaid; import forge.game.spellability.SpellAbility; +import forge.player.PlayerControllerHuman; import forge.util.ITriggerEvent; -import org.apache.commons.lang3.StringUtils; - -import java.util.ArrayList; -import java.util.List; - public class InputPayManaX extends InputPayMana { private static final long serialVersionUID = -6900234444347364050L; private int xPaid = 0; @@ -23,8 +24,8 @@ public class InputPayManaX extends InputPayMana { private final boolean xCanBe0; private boolean canceled = false; - public InputPayManaX(final SpellAbility sa0, final int amountX, final boolean xCanBe0) { - super(sa0, sa0.getActivatingPlayer()); + public InputPayManaX(final PlayerControllerHuman controller, final SpellAbility sa0, final int amountX, final boolean xCanBe0) { + super(controller, sa0, sa0.getActivatingPlayer()); xPaid = 0; if (saPaidFor.hasParam("XColor")) { @@ -82,7 +83,7 @@ public class InputPayManaX extends InputPayMana { // Enable just cancel is full X value hasn't been paid for multiple X values // or X is 0, and x can't be 0 - ButtonUtil.update(isPaid(), true, true); + ButtonUtil.update(getGui(), isPaid(), true, true); return msg.toString(); } diff --git a/forge-gui/src/main/java/forge/match/input/InputPlaybackControl.java b/forge-gui/src/main/java/forge/match/input/InputPlaybackControl.java index 9a5d8594096..6102c3e60c8 100644 --- a/forge-gui/src/main/java/forge/match/input/InputPlaybackControl.java +++ b/forge-gui/src/main/java/forge/match/input/InputPlaybackControl.java @@ -1,22 +1,30 @@ package forge.match.input; -import forge.GuiBase; import forge.control.FControlGamePlayback; import forge.game.Game; import forge.game.phase.PhaseHandler; - +import forge.interfaces.IGuiBase; public class InputPlaybackControl extends InputSyncronizedBase implements InputSynchronized { private static final long serialVersionUID = 7979208993306642072L; - FControlGamePlayback control; + final FControlGamePlayback control; private boolean isPaused = false; private boolean isFast = false; - public InputPlaybackControl(FControlGamePlayback fControlGamePlayback) { + private final IGuiBase gui; + private final Game game; + public InputPlaybackControl(final IGuiBase gui, final Game game, final FControlGamePlayback fControlGamePlayback) { + super(null); + this.gui = gui; + this.game = game; control = fControlGamePlayback; } + @Override + protected IGuiBase getGui() { + return gui; + } /* (non-Javadoc) * @see forge.gui.input.InputBase#showMessage() @@ -29,7 +37,6 @@ public class InputPlaybackControl extends InputSyncronizedBase implements InputS //update message based on current turn and paused state private int currentTurn; public void updateTurnMessage() { - Game game = GuiBase.getInterface().getGame(); if (isPaused) { showMessage(getTurnPhasePriorityMessage(game)); currentTurn = 0; @@ -46,10 +53,10 @@ public class InputPlaybackControl extends InputSyncronizedBase implements InputS private void setPause(boolean pause) { isPaused = pause; if (isPaused) { - ButtonUtil.update("Resume", "Step", true, true, true); + ButtonUtil.update(getGui(), "Resume", "Step", true, true, true); } else { - ButtonUtil.update("Pause", isFast ? "1x Speed" : "10x Faster", true, true, true); + ButtonUtil.update(getGui(), "Pause", isFast ? "1x Speed" : "10x Faster", true, true, true); } } diff --git a/forge-gui/src/main/java/forge/match/input/InputProliferate.java b/forge-gui/src/main/java/forge/match/input/InputProliferate.java index 60a331d1723..acdf0603b75 100644 --- a/forge-gui/src/main/java/forge/match/input/InputProliferate.java +++ b/forge-gui/src/main/java/forge/match/input/InputProliferate.java @@ -1,22 +1,26 @@ package forge.match.input; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + import forge.game.GameEntity; import forge.game.card.Card; import forge.game.card.CounterType; import forge.game.player.Player; +import forge.player.PlayerControllerHuman; import forge.util.ITriggerEvent; import forge.util.gui.SGuiChoose; -import java.util.*; -import java.util.Map.Entry; - - public final class InputProliferate extends InputSelectManyBase { private static final long serialVersionUID = -1779224307654698954L; private Map chosenCounters = new HashMap(); - public InputProliferate() { - super(1, Integer.MAX_VALUE); + public InputProliferate(final PlayerControllerHuman controller) { + super(controller, 1, Integer.MAX_VALUE); allowUnselect = true; } @@ -59,7 +63,7 @@ public final class InputProliferate extends InputSelectManyBase { } } - CounterType toAdd = choices.size() == 1 ? choices.get(0) : SGuiChoose.one("Select counter type", choices); + CounterType toAdd = choices.size() == 1 ? choices.get(0) : SGuiChoose.one(getGui(), "Select counter type", choices); chosenCounters.put(card, toAdd); } diff --git a/forge-gui/src/main/java/forge/match/input/InputProxy.java b/forge-gui/src/main/java/forge/match/input/InputProxy.java index 3828afc3bbc..d0cce6352d5 100644 --- a/forge-gui/src/main/java/forge/match/input/InputProxy.java +++ b/forge-gui/src/main/java/forge/match/input/InputProxy.java @@ -22,13 +22,14 @@ import java.util.Observer; import java.util.concurrent.atomic.AtomicReference; import forge.FThreads; -import forge.GuiBase; -import forge.game.spellability.SpellAbility; +import forge.interfaces.IGuiBase; +import forge.player.PlayerControllerHuman; import forge.util.ITriggerEvent; import forge.util.gui.SOptionPane; import forge.view.CardView; import forge.view.IGameView; import forge.view.PlayerView; +import forge.view.SpellAbilityView; /** *

@@ -45,23 +46,32 @@ public class InputProxy implements Observer { private IGameView game = null; // private static final boolean DEBUG_INPUT = true; // false; - + + private final PlayerControllerHuman controller; + public InputProxy(final PlayerControllerHuman controller) { + this.controller = controller; + } + + private IGuiBase getGui() { + return controller.getGui(); + } + public void setGame(IGameView game0) { game = game0; - GuiBase.getInterface().getInputQueue().addObserver(this); + getGui().getInputQueue().addObserver(this); } public boolean passPriority() { - Input inp = getInput(); - if (inp != null && inp instanceof InputPassPriority) { + final Input inp = getInput(); + if (inp instanceof InputPassPriority) { inp.selectButtonOK(); return true; } - FThreads.invokeInEdtNowOrLater(new Runnable() { + FThreads.invokeInEdtNowOrLater(getGui(), new Runnable() { @Override public void run() { - SOptionPane.showMessageDialog("Cannot pass priority at this time."); + SOptionPane.showMessageDialog(getGui(), "Cannot pass priority at this time."); } }); return false; @@ -69,7 +79,7 @@ public class InputProxy implements Observer { @Override public final void update(final Observable observable, final Object obj) { - final Input nextInput = GuiBase.getInterface().getInputQueue().getActualInput(game); + final Input nextInput = getGui().getInputQueue().getActualInput(game); /* if(DEBUG_INPUT) System.out.printf("%s ... \t%s on %s, \tstack = %s%n", @@ -80,13 +90,13 @@ public class InputProxy implements Observer { Runnable showMessage = new Runnable() { @Override public void run() { Input current = getInput(); - GuiBase.getInterface().getInputQueue().syncPoint(); + getGui().getInputQueue().syncPoint(); //System.out.printf("\t%s > showMessage @ %s/%s during %s%n", FThreads.debugGetCurrThreadId(), nextInput.getClass().getSimpleName(), current.getClass().getSimpleName(), game.getPhaseHandler().debugPrintState()); current.showMessageInitial(); } }; - FThreads.invokeInEdtLater(showMessage); + FThreads.invokeInEdtLater(getGui(), showMessage); } /** *

@@ -123,7 +133,7 @@ public class InputProxy implements Observer { public final void selectPlayer(final PlayerView player, final ITriggerEvent triggerEvent) { final Input inp = getInput(); if (inp != null) { - inp.selectPlayer(player, triggerEvent); + inp.selectPlayer(controller.getPlayer(player), triggerEvent); } } @@ -139,15 +149,15 @@ public class InputProxy implements Observer { public final boolean selectCard(final CardView cardView, final ITriggerEvent triggerEvent) { final Input inp = getInput(); if (inp != null) { - return inp.selectCard(cardView, triggerEvent); + return inp.selectCard(controller.getCard(cardView), triggerEvent); } return false; } - public final void selectAbility(final SpellAbility ab) { + public final void selectAbility(final SpellAbilityView ab) { final Input inp = getInput(); if (inp != null) { - inp.selectAbility(ab); + inp.selectAbility(controller.getSpellAbility(ab)); } } diff --git a/forge-gui/src/main/java/forge/match/input/InputQueue.java b/forge-gui/src/main/java/forge/match/input/InputQueue.java index aa85dde6583..6c65d67fdf7 100644 --- a/forge-gui/src/main/java/forge/match/input/InputQueue.java +++ b/forge-gui/src/main/java/forge/match/input/InputQueue.java @@ -17,12 +17,14 @@ */ package forge.match.input; -import forge.view.IGameView; - import java.util.Observable; import java.util.concurrent.BlockingDeque; import java.util.concurrent.LinkedBlockingDeque; +import forge.game.Game; +import forge.interfaces.IGuiBase; +import forge.view.IGameView; + /** *

* InputControl class. @@ -35,8 +37,8 @@ public class InputQueue extends Observable { private final BlockingDeque inputStack = new LinkedBlockingDeque(); private final InputLockUI inputLock; - public InputQueue() { - inputLock = new InputLockUI(this); + public InputQueue(final IGuiBase gui, final Game game) { + inputLock = new InputLockUI(gui, game, this); } public final void updateObservers() { diff --git a/forge-gui/src/main/java/forge/match/input/InputSelectCardsForConvoke.java b/forge-gui/src/main/java/forge/match/input/InputSelectCardsForConvoke.java index 913ff20b88e..1b85e78da26 100644 --- a/forge-gui/src/main/java/forge/match/input/InputSelectCardsForConvoke.java +++ b/forge-gui/src/main/java/forge/match/input/InputSelectCardsForConvoke.java @@ -1,21 +1,22 @@ package forge.match.input; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.lang3.tuple.ImmutablePair; + import forge.card.mana.ManaCost; import forge.card.mana.ManaCostShard; import forge.game.card.Card; import forge.game.card.CardUtil; import forge.game.mana.ManaCostBeingPaid; import forge.game.player.Player; +import forge.player.PlayerControllerHuman; import forge.util.ITriggerEvent; -import org.apache.commons.lang3.tuple.ImmutablePair; - -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - public final class InputSelectCardsForConvoke extends InputSelectManyBase { private static final long serialVersionUID = -1779224307654698954L; @@ -24,8 +25,8 @@ public final class InputSelectCardsForConvoke extends InputSelectManyBase private final Player player; private final List availableCreatures; - public InputSelectCardsForConvoke(Player p, ManaCost cost, List untapped) { - super(0, Math.min(cost.getCMC(), untapped.size())); + public InputSelectCardsForConvoke(final PlayerControllerHuman controller, final Player p, final ManaCost cost, final List untapped) { + super(controller, 0, Math.min(cost.getCMC(), untapped.size())); remainingCost = new ManaCostBeingPaid(cost); player = p; allowUnselect = true; diff --git a/forge-gui/src/main/java/forge/match/input/InputSelectCardsFromList.java b/forge-gui/src/main/java/forge/match/input/InputSelectCardsFromList.java index e1485ba5a20..c580c4a8222 100644 --- a/forge-gui/src/main/java/forge/match/input/InputSelectCardsFromList.java +++ b/forge-gui/src/main/java/forge/match/input/InputSelectCardsFromList.java @@ -1,21 +1,22 @@ package forge.match.input; -import forge.game.card.Card; - import java.util.Collection; +import forge.game.card.Card; +import forge.player.PlayerControllerHuman; + public class InputSelectCardsFromList extends InputSelectEntitiesFromList { private static final long serialVersionUID = 6230360322294805986L; - public InputSelectCardsFromList(int cnt, Collection validCards) { - super(cnt, cnt, validCards); // to avoid hangs + public InputSelectCardsFromList(final PlayerControllerHuman controller, final int cnt, final Collection validCards) { + super(controller, cnt, cnt, validCards); // to avoid hangs } - public InputSelectCardsFromList(int min, int max, Collection validCards) { - super(min, max, validCards); // to avoid hangs + public InputSelectCardsFromList(final PlayerControllerHuman controller, final int min, final int max, final Collection validCards) { + super(controller, min, max, validCards); // to avoid hangs } - public InputSelectCardsFromList(Collection validCards) { - super(1, 1, validCards); // to avoid hangs + public InputSelectCardsFromList(final PlayerControllerHuman controller, final Collection validCards) { + super(controller, 1, 1, validCards); // to avoid hangs } } \ No newline at end of file diff --git a/forge-gui/src/main/java/forge/match/input/InputSelectEntitiesFromList.java b/forge-gui/src/main/java/forge/match/input/InputSelectEntitiesFromList.java index 39b36c68025..ab7612c53dc 100644 --- a/forge-gui/src/main/java/forge/match/input/InputSelectEntitiesFromList.java +++ b/forge-gui/src/main/java/forge/match/input/InputSelectEntitiesFromList.java @@ -1,27 +1,28 @@ package forge.match.input; -import forge.game.GameEntity; -import forge.game.card.Card; -import forge.game.player.Player; -import forge.util.ITriggerEvent; - import java.util.ArrayList; import java.util.Collection; import java.util.List; +import forge.game.GameEntity; +import forge.game.card.Card; +import forge.game.player.Player; +import forge.player.PlayerControllerHuman; +import forge.util.ITriggerEvent; + public class InputSelectEntitiesFromList extends InputSelectManyBase { private static final long serialVersionUID = -6609493252672573139L; private final Collection validChoices; protected final List selected = new ArrayList(); - public InputSelectEntitiesFromList(int min, int max, Collection validChoices) { - super(Math.min(min, validChoices.size()), Math.min(max, validChoices.size())); + public InputSelectEntitiesFromList(final PlayerControllerHuman controller, final int min, final int max, final Collection validChoices) { + super(controller, Math.min(min, validChoices.size()), Math.min(max, validChoices.size())); this.validChoices = validChoices; - if ( min > validChoices.size() ) + if (min > validChoices.size()) { System.out.println(String.format("Trying to choose at least %d cards from a list with only %d cards!", min, validChoices.size())); - + } } @Override diff --git a/forge-gui/src/main/java/forge/match/input/InputSelectManyBase.java b/forge-gui/src/main/java/forge/match/input/InputSelectManyBase.java index 85905ac09d0..920ce6afc13 100644 --- a/forge-gui/src/main/java/forge/match/input/InputSelectManyBase.java +++ b/forge-gui/src/main/java/forge/match/input/InputSelectManyBase.java @@ -1,12 +1,12 @@ package forge.match.input; +import java.util.Collection; + import com.google.common.collect.Iterables; -import forge.GuiBase; import forge.game.GameEntity; import forge.game.card.Card; - -import java.util.Collection; +import forge.player.PlayerControllerHuman; public abstract class InputSelectManyBase extends InputSyncronizedBase { private static final long serialVersionUID = -2305549394512889450L; @@ -19,7 +19,8 @@ public abstract class InputSelectManyBase extends InputSyn protected String message = "Source-Card-Name - Select %d more card(s)"; - protected InputSelectManyBase(int min, int max) { + protected InputSelectManyBase(final PlayerControllerHuman controller, final int min, final int max) { + super(controller); if (min > max) { throw new IllegalArgumentException("Min must not be greater than Max"); } @@ -44,7 +45,7 @@ public abstract class InputSelectManyBase extends InputSyn @Override public final void showMessage() { showMessage(getMessage()); - ButtonUtil.update(hasEnoughTargets(), allowCancel, true); + ButtonUtil.update(getGui(), hasEnoughTargets(), allowCancel, true); } @Override @@ -72,16 +73,16 @@ public abstract class InputSelectManyBase extends InputSyn this.message = message0; } - protected void onSelectStateChanged(GameEntity c, boolean newState) { + protected void onSelectStateChanged(final GameEntity c, final boolean newState) { if (c instanceof Card) { - GuiBase.getInterface().setUsedToPay((Card)c, newState); // UI supports card highlighting though this abstraction-breaking mechanism + getGui().setUsedToPay(getController().getCardView((Card) c), newState); // UI supports card highlighting though this abstraction-breaking mechanism } } protected void afterStop() { - for (GameEntity c : getSelected()) { + for (final GameEntity c : getSelected()) { if (c instanceof Card) { - GuiBase.getInterface().setUsedToPay((Card)c, false); + getGui().setUsedToPay(getController().getCardView((Card) c), false); } } } diff --git a/forge-gui/src/main/java/forge/match/input/InputSelectTargets.java b/forge-gui/src/main/java/forge/match/input/InputSelectTargets.java index 708315eb56a..1c4464af0f5 100644 --- a/forge-gui/src/main/java/forge/match/input/InputSelectTargets.java +++ b/forge-gui/src/main/java/forge/match/input/InputSelectTargets.java @@ -1,6 +1,11 @@ package forge.match.input; -import forge.GuiBase; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + import forge.game.GameEntity; import forge.game.GameObject; import forge.game.ability.ApiType; @@ -8,15 +13,10 @@ import forge.game.card.Card; import forge.game.player.Player; import forge.game.spellability.SpellAbility; import forge.game.spellability.TargetRestrictions; +import forge.player.PlayerControllerHuman; import forge.util.ITriggerEvent; import forge.util.gui.SGuiChoose; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - public final class InputSelectTargets extends InputSyncronizedBase { private final List choices; @@ -43,7 +43,8 @@ public final class InputSelectTargets extends InputSyncronizedBase { * @param sa * @param mandatory */ - public InputSelectTargets(List choices, SpellAbility sa, boolean mandatory) { + public InputSelectTargets(final PlayerControllerHuman controller, final List choices, final SpellAbility sa, final boolean mandatory) { + super(controller); this.choices = choices; this.tgt = sa.getTargetRestrictions(); this.sa = sa; @@ -77,19 +78,19 @@ public final class InputSelectTargets extends InputSyncronizedBase { if (!tgt.isMinTargetsChosen(sa.getHostCard(), sa) || tgt.isDividedAsYouChoose()) { if (mandatory && tgt.hasCandidates(sa, true)) { // Player has to click on a target - ButtonUtil.update(false, false, false); + ButtonUtil.update(getGui(), false, false, false); } else { - ButtonUtil.update(false, true, false); + ButtonUtil.update(getGui(), false, true, false); } } else { if (mandatory && tgt.hasCandidates(sa, true)) { // Player has to click on a target or ok - ButtonUtil.update(true, false, true); + ButtonUtil.update(getGui(), true, false, true); } else { - ButtonUtil.update(true, true, true); + ButtonUtil.update(getGui(), true, true, true); } } } @@ -176,7 +177,7 @@ public final class InputSelectTargets extends InputSyncronizedBase { final StringBuilder sb = new StringBuilder(); sb.append(apiBasedMessage); sb.append(card.toString()); - Integer chosen = SGuiChoose.oneOrNone(sb.toString(), choices); + Integer chosen = SGuiChoose.oneOrNone(getGui(), sb.toString(), choices); if (chosen == null) { return true; //still return true since there was a valid choice } @@ -220,7 +221,7 @@ public final class InputSelectTargets extends InputSyncronizedBase { final StringBuilder sb = new StringBuilder(); sb.append(apiBasedMessage); sb.append(player.getName()); - Integer chosen = SGuiChoose.oneOrNone(sb.toString(), choices); + Integer chosen = SGuiChoose.oneOrNone(getGui(), sb.toString(), choices); if (null == chosen) { return; } @@ -234,13 +235,13 @@ public final class InputSelectTargets extends InputSyncronizedBase { addTarget(player); } - private void addTarget(GameEntity ge) { + private void addTarget(final GameEntity ge) { sa.getTargets().add(ge); if (ge instanceof Card) { - GuiBase.getInterface().setUsedToPay((Card) ge, true); + getGui().setUsedToPay(getController().getCardView((Card) ge), true); lastTarget = (Card) ge; } - Integer val = targetDepth.get(ge); + final Integer val = targetDepth.get(ge); targetDepth.put(ge, val == null ? Integer.valueOf(1) : Integer.valueOf(val.intValue() + 1) ); if(hasAllTargets()) { @@ -252,9 +253,9 @@ public final class InputSelectTargets extends InputSyncronizedBase { } private void done() { - for (GameEntity c : targetDepth.keySet()) { + for (final GameEntity c : targetDepth.keySet()) { if (c instanceof Card) { - GuiBase.getInterface().setUsedToPay((Card)c, false); + getGui().setUsedToPay(getController().getCardView((Card) c), false); } } diff --git a/forge-gui/src/main/java/forge/match/input/InputSyncronizedBase.java b/forge-gui/src/main/java/forge/match/input/InputSyncronizedBase.java index ad4b6a785ea..54d89175bed 100644 --- a/forge-gui/src/main/java/forge/match/input/InputSyncronizedBase.java +++ b/forge-gui/src/main/java/forge/match/input/InputSyncronizedBase.java @@ -1,21 +1,22 @@ package forge.match.input; -import forge.FThreads; -import forge.GuiBase; -import forge.error.BugReporter; - import java.util.concurrent.CountDownLatch; +import forge.FThreads; +import forge.error.BugReporter; +import forge.player.PlayerControllerHuman; + public abstract class InputSyncronizedBase extends InputBase implements InputSynchronized { private static final long serialVersionUID = 8756177361251703052L; private final CountDownLatch cdlDone; - public InputSyncronizedBase() { + public InputSyncronizedBase(final PlayerControllerHuman controller) { + super(controller); cdlDone = new CountDownLatch(1); } public void awaitLatchRelease() { - FThreads.assertExecutedByEdt(false); + FThreads.assertExecutedByEdt(getGui(), false); try{ cdlDone.await(); } @@ -30,7 +31,7 @@ public abstract class InputSyncronizedBase extends InputBase implements InputSyn public void showAndWait() { - GuiBase.getInterface().getInputQueue().setInput(this); + getGui().getInputQueue().setInput(this); awaitLatchRelease(); } @@ -38,7 +39,7 @@ public abstract class InputSyncronizedBase extends InputBase implements InputSyn onStop(); // ensure input won't accept any user actions. - FThreads.invokeInEdtNowOrLater(new Runnable() { + FThreads.invokeInEdtNowOrLater(getGui(), new Runnable() { @Override public void run() { setFinished(); @@ -46,7 +47,7 @@ public abstract class InputSyncronizedBase extends InputBase implements InputSyn }); // thread irrelevant - GuiBase.getInterface().getInputQueue().removeInput(InputSyncronizedBase.this); + getGui().getInputQueue().removeInput(InputSyncronizedBase.this); cdlDone.countDown(); } diff --git a/forge-gui/src/main/java/forge/model/CardBlock.java b/forge-gui/src/main/java/forge/model/CardBlock.java index 7c3951a1517..12f7f89a6ce 100644 --- a/forge-gui/src/main/java/forge/model/CardBlock.java +++ b/forge-gui/src/main/java/forge/model/CardBlock.java @@ -19,13 +19,16 @@ package forge.model; import com.google.common.base.Function; import com.google.common.base.Predicate; + import forge.card.CardEdition; import forge.card.IUnOpenedProduct; import forge.card.UnOpenedProduct; +import forge.interfaces.IGuiBase; import forge.item.IPaperCard; import forge.item.PaperCard; import forge.util.TextUtil; import forge.util.storage.StorageReaderFile; + import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; @@ -292,11 +295,13 @@ public final class CardBlock implements Comparable { * Tries to create a booster for the selected meta-set code. * * @param code - * String, the MetaSet code + * String, the MetaSet code + * @param gui + * the {@link IGuiBase} resolving any choices to be made. * @return UnOpenedProduct, the created booster. */ - public IUnOpenedProduct getBooster(final String code) { + public IUnOpenedProduct getBooster(final String code, final IGuiBase gui) { MetaSet ms = metaSets.get(code); - return ms == null ? new UnOpenedProduct(FModel.getMagicDb().getBoosters().get(code)) : ms.getBooster(); + return ms == null ? new UnOpenedProduct(FModel.getMagicDb().getBoosters().get(code)) : ms.getBooster(gui); } } diff --git a/forge-gui/src/main/java/forge/model/CardCollections.java b/forge-gui/src/main/java/forge/model/CardCollections.java index 2ec1b02aace..22598bc28fa 100644 --- a/forge-gui/src/main/java/forge/model/CardCollections.java +++ b/forge-gui/src/main/java/forge/model/CardCollections.java @@ -22,9 +22,11 @@ import forge.deck.DeckGroup; import forge.deck.io.DeckGroupSerializer; import forge.deck.io.DeckStorage; import forge.deck.io.OldDeckParser; +import forge.interfaces.IGuiBase; import forge.properties.ForgeConstants; import forge.util.storage.IStorage; import forge.util.storage.StorageImmediatelySerialized; + import org.apache.commons.lang3.time.StopWatch; import java.io.File; @@ -48,7 +50,7 @@ public class CardCollections { * * @param file the file */ - public CardCollections() { + public CardCollections(final IGuiBase gui) { StopWatch sw = new StopWatch(); sw.start(); this.constructed = new StorageImmediatelySerialized("Constructed decks", new DeckStorage(new File(ForgeConstants.DECK_CONSTRUCTED_DIR), true), true); @@ -64,7 +66,7 @@ public class CardCollections { // int sum = constructed.size() + sealed.size() + draft.size() + cube.size() + scheme.size() + plane.size(); // FSkin.setProgessBarMessage(String.format("Loaded %d decks in %f sec", sum, sw.getTime() / 1000f )); // remove this after most people have been switched to new layout - final OldDeckParser oldParser = new OldDeckParser(this.constructed, this.draft, this.sealed, this.cube); + final OldDeckParser oldParser = new OldDeckParser(gui, this.constructed, this.draft, this.sealed, this.cube); oldParser.tryParse(); } diff --git a/forge-gui/src/main/java/forge/model/FModel.java b/forge-gui/src/main/java/forge/model/FModel.java index 7ccd460bc46..c4ab1c0488e 100644 --- a/forge-gui/src/main/java/forge/model/FModel.java +++ b/forge-gui/src/main/java/forge/model/FModel.java @@ -28,6 +28,7 @@ import forge.deck.io.DeckPreferences; import forge.game.GameFormat; import forge.game.card.CardUtil; import forge.gauntlet.GauntletData; +import forge.interfaces.IGuiBase; import forge.interfaces.IProgressBar; import forge.itemmanager.ItemManagerConfig; import forge.limited.GauntletMini; @@ -74,7 +75,7 @@ public class FModel { private static IStorage worlds; private static GameFormat.Collection formats; - public static void initialize(final IProgressBar progressBar) { + public static void initialize(final IGuiBase gui, final IProgressBar progressBar) { // Instantiate preferences: quest and regular //Preferences are initialized first so that the splash screen can be translated. @@ -92,7 +93,7 @@ public class FModel { ProgressObserver.emptyObserver : new ProgressObserver() { @Override public void setOperationName(final String name, final boolean usePercents) { - FThreads.invokeInEdtLater(new Runnable() { + FThreads.invokeInEdtLater(gui, new Runnable() { @Override public void run() { progressBar.setDescription(name); @@ -103,7 +104,7 @@ public class FModel { @Override public void report(final int current, final int total) { - FThreads.invokeInEdtLater(new Runnable() { + FThreads.invokeInEdtLater(gui, new Runnable() { @Override public void run() { progressBar.setMaximum(total); @@ -140,7 +141,7 @@ public class FModel { loadDynamicGamedata(); if (progressBar != null) { - FThreads.invokeInEdtLater(new Runnable() { + FThreads.invokeInEdtLater(gui, new Runnable() { @Override public void run() { progressBar.setDescription(Localizer.getInstance().getMessage("splash.loading.decks")); @@ -148,8 +149,8 @@ public class FModel { }); } - decks = new CardCollections(); - quest = new QuestController(); + decks = new CardCollections(gui); + quest = new QuestController(gui); CardPreferences.load(); DeckPreferences.load(); @@ -264,9 +265,9 @@ public class FModel { gauntletData = data0; } - public static GauntletMini getGauntletMini() { + public static GauntletMini getGauntletMini(final IGuiBase gui) { if (gauntlet == null) { - gauntlet = new GauntletMini(); + gauntlet = new GauntletMini(gui); } return gauntlet; } diff --git a/forge-gui/src/main/java/forge/model/MetaSet.java b/forge-gui/src/main/java/forge/model/MetaSet.java index 5f3b8b54ac1..f5858413cf6 100644 --- a/forge-gui/src/main/java/forge/model/MetaSet.java +++ b/forge-gui/src/main/java/forge/model/MetaSet.java @@ -22,6 +22,7 @@ import com.google.common.base.Predicate; import forge.card.IUnOpenedProduct; import forge.card.UnOpenedProduct; +import forge.interfaces.IGuiBase; import forge.item.IPaperCard; import forge.item.PaperCard; import forge.item.SealedProduct; @@ -162,7 +163,7 @@ public class MetaSet { * * @return UnOpenedProduct, the generated booster. */ - public IUnOpenedProduct getBooster() { + public IUnOpenedProduct getBooster(final IGuiBase gui) { switch(type) { case Full: @@ -181,7 +182,7 @@ public class MetaSet { Predicate predicate = IPaperCard.Predicates.printedInSets(data.split(" ")); return new UnOpenedProduct(SealedProduct.Template.genericBooster, predicate); - case Choose: return UnOpenedMeta.choose(data); + case Choose: return UnOpenedMeta.choose(data, gui); case Random: return UnOpenedMeta.random(data); case Combo: return UnOpenedMeta.selectAll(data); diff --git a/forge-gui/src/main/java/forge/model/UnOpenedMeta.java b/forge-gui/src/main/java/forge/model/UnOpenedMeta.java index bd750d01eb2..e8f145866fd 100644 --- a/forge-gui/src/main/java/forge/model/UnOpenedMeta.java +++ b/forge-gui/src/main/java/forge/model/UnOpenedMeta.java @@ -19,6 +19,7 @@ package forge.model; import forge.card.IUnOpenedProduct; +import forge.interfaces.IGuiBase; import forge.item.PaperCard; import forge.util.MyRandom; import forge.util.TextUtil; @@ -44,17 +45,22 @@ public class UnOpenedMeta implements IUnOpenedProduct { private final ArrayList metaSets; private final JoinOperation operation; private final Random generator = MyRandom.getRandom(); + private final IGuiBase gui; /** * Constructor for UnOpenedMeta. + * * @param creationString - * String, is parsed for MetaSet info. + * String, is parsed for MetaSet info. * @param choose - * sets the random/choice status. + * sets the random/choice status. + * @param gui + * the gui. */ - private UnOpenedMeta(final String creationString, final JoinOperation op) { + private UnOpenedMeta(final String creationString, final JoinOperation op, final IGuiBase gui) { metaSets = new ArrayList(); operation = op; + this.gui = gui; for (String m : TextUtil.splitWithParenthesis(creationString, ';')) { metaSets.add(new MetaSet(m, true)); @@ -88,39 +94,39 @@ public class UnOpenedMeta implements IUnOpenedProduct { if (isHuman) { final MetaSet ms; if (allowCancel) { - ms = SGuiChoose.oneOrNone("Choose Booster", metaSets); + ms = SGuiChoose.oneOrNone(gui, "Choose Booster", metaSets); if (ms == null) { return null; } } else { - ms = SGuiChoose.one("Choose Booster", metaSets); + ms = SGuiChoose.one(gui, "Choose Booster", metaSets); } - return ms.getBooster().get(); + return ms.getBooster(gui).get(); } case RandomOne: // AI should fall though here from the case above int selected = generator.nextInt(metaSets.size()); - final IUnOpenedProduct newBooster = metaSets.get(selected).getBooster(); + final IUnOpenedProduct newBooster = metaSets.get(selected).getBooster(gui); return newBooster.get(); case SelectAll: List allCards = new ArrayList(); for (MetaSet ms : metaSets) { - allCards.addAll(ms.getBooster().get()); + allCards.addAll(ms.getBooster(gui).get()); } return allCards; } throw new IllegalStateException("Got wrong operation type in unopenedMeta - execution should never reach this point"); } - public static UnOpenedMeta choose(String desc) { - return new UnOpenedMeta(desc, JoinOperation.ChooseOne); + public static UnOpenedMeta choose(final String desc, final IGuiBase gui) { + return new UnOpenedMeta(desc, JoinOperation.ChooseOne, gui); } - public static UnOpenedMeta random(String desc) { - return new UnOpenedMeta(desc, JoinOperation.RandomOne); + public static UnOpenedMeta random(final String desc) { + return new UnOpenedMeta(desc, JoinOperation.RandomOne, null); } - public static UnOpenedMeta selectAll(String desc) { - return new UnOpenedMeta(desc, JoinOperation.SelectAll); + public static UnOpenedMeta selectAll(final String desc) { + return new UnOpenedMeta(desc, JoinOperation.SelectAll, null); } } diff --git a/forge-gui/src/main/java/forge/player/GamePlayerUtil.java b/forge-gui/src/main/java/forge/player/GamePlayerUtil.java index 3b8b243223d..af5fad20a50 100644 --- a/forge-gui/src/main/java/forge/player/GamePlayerUtil.java +++ b/forge-gui/src/main/java/forge/player/GamePlayerUtil.java @@ -1,5 +1,6 @@ package forge.player; +import forge.interfaces.IGuiBase; import forge.model.FModel; import forge.properties.ForgePreferences; import forge.properties.ForgePreferences.FPref; @@ -12,42 +13,42 @@ public final class GamePlayerUtil { private final static ForgePreferences prefs = FModel.getPreferences(); - public static void setPlayerName() { + public static void setPlayerName(final IGuiBase gui) { String oldPlayerName = prefs.getPref(FPref.PLAYER_NAME); String newPlayerName = null; if (StringUtils.isBlank(oldPlayerName)) { - newPlayerName = getVerifiedPlayerName(getPlayerNameUsingFirstTimePrompt(), oldPlayerName); + newPlayerName = getVerifiedPlayerName(getPlayerNameUsingFirstTimePrompt(gui), oldPlayerName); } else { - newPlayerName = getVerifiedPlayerName(getPlayerNameUsingStandardPrompt(oldPlayerName), oldPlayerName); + newPlayerName = getVerifiedPlayerName(getPlayerNameUsingStandardPrompt(gui, oldPlayerName), oldPlayerName); } prefs.setPref(FPref.PLAYER_NAME, newPlayerName); prefs.save(); if (StringUtils.isBlank(oldPlayerName) && newPlayerName != "Human") { - showThankYouPrompt(newPlayerName); + showThankYouPrompt(gui, newPlayerName); } } - private static void showThankYouPrompt(String playerName) { - SOptionPane.showMessageDialog("Thank you, " + playerName + ". " + private static void showThankYouPrompt(final IGuiBase gui, final String playerName) { + SOptionPane.showMessageDialog(gui, "Thank you, " + playerName + ". " + "You will not be prompted again but you can change\n" + "your name at any time using the \"Player Name\" setting in Preferences\n" + "or via the constructed match setup screen\n"); } - private static String getPlayerNameUsingFirstTimePrompt() { - return SOptionPane.showInputDialog( + private static String getPlayerNameUsingFirstTimePrompt(final IGuiBase gui) { + return SOptionPane.showInputDialog(gui, "By default, Forge will refer to you as the \"Human\" during gameplay.\n" + "If you would prefer a different name please enter it now.", "Personalize Forge Gameplay", SOptionPane.QUESTION_ICON); } - private static String getPlayerNameUsingStandardPrompt(String playerName) { - return SOptionPane.showInputDialog( + private static String getPlayerNameUsingStandardPrompt(final IGuiBase gui, final String playerName) { + return SOptionPane.showInputDialog(gui, "Please enter a new name. (alpha-numeric only)", "Personalize Forge Gameplay", null, diff --git a/forge-gui/src/main/java/forge/player/HumanCostDecision.java b/forge-gui/src/main/java/forge/player/HumanCostDecision.java index 919993ad4eb..dbfe8233efa 100644 --- a/forge-gui/src/main/java/forge/player/HumanCostDecision.java +++ b/forge-gui/src/main/java/forge/player/HumanCostDecision.java @@ -18,6 +18,7 @@ import forge.game.player.Player; import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbilityStackInstance; import forge.game.zone.ZoneType; +import forge.interfaces.IGuiBase; import forge.match.input.InputSelectCardsFromList; import forge.match.input.InputSelectManyBase; import forge.util.Aggregates; @@ -25,21 +26,29 @@ import forge.util.ITriggerEvent; import forge.util.Lang; import forge.util.gui.SGuiChoose; import forge.util.gui.SGuiDialog; +import forge.view.CardView; +import forge.view.PlayerView; import java.util.*; import java.util.Map.Entry; public class HumanCostDecision extends CostDecisionMakerBase { + private final PlayerControllerHuman controller; private final SpellAbility ability; private final Card source; - - public HumanCostDecision(Player p, SpellAbility sa, Card source) { + + public HumanCostDecision(final PlayerControllerHuman controller, final Player p, final SpellAbility sa, final Card source) { super(p); + this.controller = controller; ability = sa; this.source = source; } - + + private IGuiBase getGui() { + return this.controller.getGui(); + } + protected int chooseXValue(final int maxValue) { /*final String chosen = sa.getSVar("ChosenX"); if (chosen.length() > 0) { @@ -51,7 +60,7 @@ public class HumanCostDecision extends CostDecisionMakerBase { source.setSVar("ChosenX", Integer.toString(chosenX)); return chosenX; } - + @Override public PaymentDecision visit(CostAddMana cost) { Integer c = cost.convertAmount(); @@ -63,7 +72,7 @@ public class HumanCostDecision extends CostDecisionMakerBase { @Override public PaymentDecision visit(CostChooseCreatureType cost) { - String choice = player.getController().chooseSomeType("Creature", ability, new ArrayList(CardType.getCreatureTypes()), new ArrayList(), true); + String choice = controller.chooseSomeType("Creature", ability, new ArrayList(CardType.getCreatureTypes()), new ArrayList(), true); if( null == choice ) return null; return PaymentDecision.type(choice); @@ -122,7 +131,7 @@ public class HumanCostDecision extends CostDecisionMakerBase { if (c == 0) { return PaymentDecision.card(Lists.newArrayList()); } List discarded = new ArrayList(); while (c > 0) { - InputSelectCardsFromList inp = new InputSelectCardsFromList(1, 1, handList); + InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, 1, 1, handList); inp.setMessage("Select one of the cards with the same name to discard. Already chosen: " + discarded); inp.setCancelAllowed(true); inp.showAndWait(); @@ -153,7 +162,7 @@ public class HumanCostDecision extends CostDecisionMakerBase { } } - InputSelectCardsFromList inp = new InputSelectCardsFromList(c, c, handList); + InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, c, c, handList); inp.setMessage("Select %d more " + cost.getDescriptiveType() + " to discard."); inp.setCancelAllowed(true); inp.showAndWait(); @@ -251,7 +260,7 @@ public class HumanCostDecision extends CostDecisionMakerBase { } if (cost.from == ZoneType.Battlefield || cost.from == ZoneType.Hand) { - InputSelectCardsFromList inp = new InputSelectCardsFromList(c, c, list); + InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, c, c, list); inp.setMessage("Exile %d card(s) from your" + cost.from); inp.setCancelAllowed(true); inp.showAndWait(); @@ -290,8 +299,9 @@ public class HumanCostDecision extends CostDecisionMakerBase { if (nNeeded == 0) { return PaymentDecision.number(0); } - - final Player p = SGuiChoose.oneOrNone(String.format("Exile from whose %s?", cost.getFrom()), payableZone); + final PlayerView view = SGuiChoose.oneOrNone(getGui(), String.format("Exile from whose %s?", cost.getFrom()), + controller.getPlayerViews(payableZone)); + final Player p = controller.getPlayer(view); if (p == null) { return null; } @@ -301,7 +311,7 @@ public class HumanCostDecision extends CostDecisionMakerBase { if(count < nNeeded) return null; - List toExile = SGuiChoose.many("Exile from " + cost.getFrom(), "To be exiled", count - nNeeded, typeList, null); + List toExile = SGuiChoose.many(getGui(), "Exile from " + cost.getFrom(), "To be exiled", count - nNeeded, typeList, null); return PaymentDecision.card(toExile); } @@ -348,7 +358,7 @@ public class HumanCostDecision extends CostDecisionMakerBase { List exiled = new ArrayList(); for (int i = 0; i < c; i++) { //Have to use the stack descriptions here because some copied spells have no description otherwise - final String o = SGuiChoose.oneOrNone("Exile from Stack", descList); + final String o = SGuiChoose.oneOrNone(getGui(), "Exile from Stack", descList); if (o != null) { final SpellAbility toExile = saList.get(descList.indexOf(o)); @@ -382,7 +392,8 @@ public class HumanCostDecision extends CostDecisionMakerBase { List exiled = new ArrayList(); for (int i = 0; i < nNeeded; i++) { - final Card c = SGuiChoose.oneOrNone("Exile from " + cost.getFrom(), typeList); + final CardView view = SGuiChoose.oneOrNone(getGui(), "Exile from " + cost.getFrom(), controller.getCardViews(typeList)); + final Card c = controller.getCard(view); if (c != null) { typeList.remove(c); @@ -416,7 +427,9 @@ public class HumanCostDecision extends CostDecisionMakerBase { if (list.size() < c) return null; - return PaymentDecision.card(SGuiChoose.many("Choose an exiled card to put into graveyard", "To graveyard", c, list, source)); + final List choice = SGuiChoose.many(getGui(), "Choose an exiled card to put into graveyard", "To graveyard", c, + controller.getCardViews(list), controller.getCardView(source)); + return PaymentDecision.card(controller.getCards(choice)); } @Override @@ -447,7 +460,7 @@ public class HumanCostDecision extends CostDecisionMakerBase { final List list = player.getCardsIn(ZoneType.Battlefield); List validCards = CardLists.getValidCards(list, cost.getType().split(";"), player, source); - InputSelectCardsFromList inp = new InputSelectCardsFromList(c, validCards); + InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, c, validCards); final String desc = cost.getTypeDescription() == null ? cost.getType() : cost.getTypeDescription(); inp.setMessage("Gain control of %d " + desc); inp.showAndWait(); @@ -487,7 +500,8 @@ public class HumanCostDecision extends CostDecisionMakerBase { final StringBuilder sb = new StringBuilder(); sb.append(source.getName()).append(" - Choose an opponent to gain ").append(c).append(" life:"); - final Player chosenToGain = SGuiChoose.oneOrNone(sb.toString(), oppsThatCanGainLife); + final PlayerView chosenToGainView = SGuiChoose.oneOrNone(getGui(), sb.toString(), controller.getPlayerViews(oppsThatCanGainLife)); + final Player chosenToGain = controller.getPlayer(chosenToGainView); if (null == chosenToGain) return null; else @@ -568,7 +582,7 @@ public class HumanCostDecision extends CostDecisionMakerBase { list = CardLists.getValidCards(list, cost.getType().split(";"), player, source); if (cost.from == ZoneType.Hand) { - InputSelectCardsFromList inp = new InputSelectCardsFromList(c, c, list); + InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, c, c, list); inp.setMessage("Put %d card(s) from your " + cost.from ); inp.setCancelAllowed(true); inp.showAndWait(); @@ -597,14 +611,16 @@ public class HumanCostDecision extends CostDecisionMakerBase { if(typeList.size() < nNeeded) return null; + final List viewList = controller.getCardViews(typeList); List chosen = new ArrayList<>(); for (int i = 0; i < nNeeded; i++) { - final Card c = SGuiChoose.oneOrNone("Put from " + fromZone + " to library", typeList); + final CardView view = SGuiChoose.oneOrNone(getGui(), "Put from " + fromZone + " to library", viewList); + final Card c = controller.getCard(view); if (c == null) return null; - - typeList.remove(c); + + viewList.remove(view); chosen.add(c); } return PaymentDecision.card(chosen); @@ -615,21 +631,27 @@ public class HumanCostDecision extends CostDecisionMakerBase { return PaymentDecision.number(0); } - final Player p = SGuiChoose.oneOrNone(String.format("Put cards from whose %s?", fromZone), payableZone); + final List players = controller.getPlayerViews(payableZone); + final PlayerView pView = SGuiChoose.oneOrNone(getGui(), String.format("Put cards from whose %s?", fromZone), players); + final Player p = controller.getPlayer(pView); if (p == null) { return null; } List typeList = CardLists.filter(list, CardPredicates.isOwner(p)); - if(typeList.size() < nNeeded) + if (typeList.size() < nNeeded) return null; - + + final List viewList = controller.getCardViews(typeList); List chosen = new ArrayList<>(); for (int i = 0; i < nNeeded; i++) { - final Card c = SGuiChoose.oneOrNone("Put cards from " + fromZone + " to Library", typeList); + final CardView view = SGuiChoose.oneOrNone(getGui(), "Put cards from " + fromZone + " to Library", viewList); + final Card c = controller.getCard(view); + if (c == null) return null; - typeList.remove(c); + + viewList.remove(view); chosen.add(c); } return PaymentDecision.card(chosen); @@ -647,8 +669,8 @@ public class HumanCostDecision extends CostDecisionMakerBase { // Cards to use this branch: Scarscale Ritual, Wandering Mage - each adds only one counter List typeList = CardLists.getValidCards(player.getCardsIn(ZoneType.Battlefield), cost.getType().split(";"), player, ability.getHostCard()); - InputSelectCardsFromList inp = new InputSelectCardsFromList(1, 1, typeList); - inp.setMessage("Put " + Lang.nounWithAmount(c, cost.getCounter().getName() + " counter") + " on " +cost.getDescriptiveType()); + InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, 1, 1, typeList); + inp.setMessage("Put " + Lang.nounWithAmount(c, cost.getCounter().getName() + " counter") + " on " + cost.getDescriptiveType()); inp.setCancelAllowed(true); inp.showAndWait(); @@ -676,13 +698,14 @@ public class HumanCostDecision extends CostDecisionMakerBase { if (cost.payCostFromSource()) { final Card card = ability.getHostCard(); if (card.getController() == player && card.isInPlay()) { - return player.getController().confirmPayment(cost, "Return " + card.getName() + " to hand?") ? PaymentDecision.card(card) : null; + final CardView view = controller.getCardView(card); + return player.getController().confirmPayment(cost, "Return " + view + " to hand?") ? PaymentDecision.card(card) : null; } } else { List validCards = CardLists.getValidCards(ability.getActivatingPlayer().getCardsIn(ZoneType.Battlefield), cost.getType().split(";"), ability.getActivatingPlayer(), ability.getHostCard()); - InputSelectCardsFromList inp = new InputSelectCardsFromList(c, c, validCards); + InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, c, c, validCards); inp.setMessage("Return %d " + cost.getType() + " " + cost.getType() + " card(s) to hand"); inp.showAndWait(); if (inp.hasCancelled()) @@ -723,7 +746,7 @@ public class HumanCostDecision extends CostDecisionMakerBase { if (num == 0) return PaymentDecision.number(0); - inp = new InputSelectCardsFromList(num, handList) { + inp = new InputSelectCardsFromList(controller, num, handList) { private static final long serialVersionUID = 8338626212893374798L; @Override @@ -754,7 +777,7 @@ public class HumanCostDecision extends CostDecisionMakerBase { if ( num == 0 ) return PaymentDecision.number(0);; - inp = new InputSelectCardsFromList(num, num, handList); + inp = new InputSelectCardsFromList(controller, num, num, handList); inp.setMessage("Select %d more " + cost.getDescriptiveType() + " card(s) to reveal."); } inp.setCancelAllowed(true); @@ -784,7 +807,7 @@ public class HumanCostDecision extends CostDecisionMakerBase { return card.hasCounters(); } }); - InputSelectCardsFromList inp = new InputSelectCardsFromList(1, 1, list); + InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, 1, 1, list); inp.setMessage("Select " + cost.getDescriptiveType() + " to remove a counter"); inp.setCancelAllowed(false); inp.showAndWait(); @@ -798,7 +821,7 @@ public class HumanCostDecision extends CostDecisionMakerBase { } String prompt = "Select type counters to remove"; - cost.setCounterType(SGuiChoose.one(prompt, typeChoices)); + cost.setCounterType(SGuiChoose.one(getGui(), prompt, typeChoices)); return PaymentDecision.card(selected, cost.getCounter()); } @@ -810,8 +833,8 @@ public class HumanCostDecision extends CostDecisionMakerBase { private final CounterType counterType; private final List validChoices; - public InputSelectCardToRemoveCounter(int cntCounters, CounterType cType, List validCards) { - super(cntCounters, cntCounters); + public InputSelectCardToRemoveCounter(final PlayerControllerHuman controller, int cntCounters, CounterType cType, List validCards) { + super(controller, cntCounters, cntCounters); this.validChoices = validCards; counterType = cType; cardsChosen = cntCounters > 0 ? new HashMap() : null; @@ -888,7 +911,8 @@ public class HumanCostDecision extends CostDecisionMakerBase { if (cost.payCostFromSource()) { int maxCounters = source.getCounters(cost.counter); if (amount.equals("All")) { - if (!SGuiDialog.confirm(ability.getHostCard(), "Remove all counters?")) { + final CardView view = controller.getCardView(ability.getHostCard()); + if (!SGuiDialog.confirm(getGui(), view, "Remove all counters?")) { return null; } cntRemoved = maxCounters; @@ -914,7 +938,7 @@ public class HumanCostDecision extends CostDecisionMakerBase { List validCards = CardLists.getValidCards(player.getCardsIn(cost.zone), type.split(";"), player, source); if (cost.zone.equals(ZoneType.Battlefield)) { - final InputSelectCardToRemoveCounter inp = new InputSelectCardToRemoveCounter(cntRemoved, cost.counter, validCards); + final InputSelectCardToRemoveCounter inp = new InputSelectCardToRemoveCounter(controller, cntRemoved, cost.counter, validCards); inp.setMessage("Remove %d " + cost.counter.getName() + " counters from " + cost.getDescriptiveType()); inp.setCancelAllowed(true); inp.showAndWait(); @@ -936,12 +960,13 @@ public class HumanCostDecision extends CostDecisionMakerBase { } // Rift Elemental only - always removes 1 counter, so there will be no code for N counters. - List suspended = new ArrayList(); - for(Card crd : validCards) - if(crd.getCounters( cost.counter) > 0 ) - suspended.add(crd); + List suspended = Lists.newArrayList(); + for (final Card crd : validCards) + if (crd.getCounters( cost.counter) > 0) + suspended.add(controller.getCardView(crd)); - final Card card = SGuiChoose.oneOrNone("Remove counter(s) from a card in " + cost.zone, suspended); + final CardView view = SGuiChoose.oneOrNone(getGui(), "Remove counter(s) from a card in " + cost.zone, suspended); + final Card card = controller.getCard(view); return null == card ? null : PaymentDecision.card(card, c); } @@ -982,7 +1007,7 @@ public class HumanCostDecision extends CostDecisionMakerBase { if (list.size() < c) { return null; } - InputSelectCardsFromList inp = new InputSelectCardsFromList(c, c, list); + InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, c, c, list); inp.setMessage("Select a " + cost.getDescriptiveType() + " to sacrifice (%d left)"); inp.setCancelAllowed(true); inp.showAndWait(); @@ -1050,7 +1075,7 @@ public class HumanCostDecision extends CostDecisionMakerBase { if (c == 0) return PaymentDecision.number(0); List tapped = new ArrayList(); while (c > 0) { - InputSelectCardsFromList inp = new InputSelectCardsFromList(1, 1, typeList); + InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, 1, 1, typeList); inp.setMessage("Select one of the cards to tap. Already chosen: " + tapped); inp.setCancelAllowed(true); inp.showAndWait(); @@ -1072,7 +1097,7 @@ public class HumanCostDecision extends CostDecisionMakerBase { if (totalPower) { int i = Integer.parseInt(totalP); - InputSelectCardsFromList inp = new InputSelectCardsFromList(0, typeList.size(), typeList); + InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, 0, typeList.size(), typeList); inp.setMessage("Select a card to tap."); inp.setUnselectAllowed(true); inp.setCancelAllowed(true); @@ -1085,7 +1110,7 @@ public class HumanCostDecision extends CostDecisionMakerBase { } } - InputSelectCardsFromList inp = new InputSelectCardsFromList(c, c, typeList); + InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, c, c, typeList); inp.setMessage("Select a " + cost.getDescriptiveType() + " to tap (%d left)"); inp.showAndWait(); if ( inp.hasCancelled() ) @@ -1113,7 +1138,7 @@ public class HumanCostDecision extends CostDecisionMakerBase { c = AbilityUtils.calculateAmount(source, amount, ability); } } - InputSelectCardsFromList inp = new InputSelectCardsFromList(c, c, typeList); + InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, c, c, typeList); inp.setMessage("Select a " + cost.getDescriptiveType() + " to untap (%d left)"); inp.showAndWait(); if( inp.hasCancelled() || inp.getSelected().size() != c ) diff --git a/forge-gui/src/main/java/forge/player/HumanPlay.java b/forge-gui/src/main/java/forge/player/HumanPlay.java index 9d202ecd81b..f67acda35e2 100644 --- a/forge-gui/src/main/java/forge/player/HumanPlay.java +++ b/forge-gui/src/main/java/forge/player/HumanPlay.java @@ -41,8 +41,7 @@ import java.util.Map; public class HumanPlay { - public HumanPlay() { - // TODO Auto-generated constructor stub + private HumanPlay() { } /** @@ -53,8 +52,8 @@ public class HumanPlay { * @param sa * a {@link forge.game.spellability.SpellAbility} object. */ - public final static void playSpellAbility(Player p, SpellAbility sa) { - FThreads.assertExecutedByEdt(false); + public final static void playSpellAbility(final PlayerControllerHuman controller, final Player p, SpellAbility sa) { + FThreads.assertExecutedByEdt(controller.getGui(), false); if (sa == Ability.PLAY_LAND_SURROGATE) { p.playLand(sa.getHostCard(), false); @@ -93,10 +92,10 @@ public class HumanPlay { Cost abCost = sa.getPayCosts() == null ? new Cost("0", sa.isAbility()) : sa.getPayCosts(); CostPayment payment = new CostPayment(abCost, sa); - final HumanPlaySpellAbility req = new HumanPlaySpellAbility(sa, payment); + final HumanPlaySpellAbility req = new HumanPlaySpellAbility(controller, sa, payment); req.playAbility(true, false, false); } - else if (payManaCostIfNeeded(p, sa)) { + else if (payManaCostIfNeeded(controller, p, sa)) { if (sa.isSpell() && !source.isCopiedSpell()) { sa.setHostCard(p.getGame().getAction().moveToStack(source)); } @@ -120,7 +119,7 @@ public class HumanPlay { return p.getController().getAbilityToPlay(abilities); } - private static boolean payManaCostIfNeeded(final Player p, final SpellAbility sa) { + private static boolean payManaCostIfNeeded(final PlayerControllerHuman controller, final Player p, final SpellAbility sa) { final ManaCostBeingPaid manaCost; if (sa.getHostCard().isCopiedSpell() && sa.isSpell()) { manaCost = new ManaCostBeingPaid(ManaCost.ZERO); @@ -133,7 +132,7 @@ public class HumanPlay { boolean isPaid = manaCost.isPaid(); if (!isPaid) { - InputPayManaSimple inputPay = new InputPayManaSimple(p.getGame(), sa, manaCost); + InputPayManaSimple inputPay = new InputPayManaSimple(controller, p.getGame(), sa, manaCost); inputPay.showAndWait(); isPaid = inputPay.isPaid(); } @@ -148,8 +147,8 @@ public class HumanPlay { * @param sa * a {@link forge.game.spellability.SpellAbility} object. */ - public static final void playSaWithoutPayingManaCost(final Game game, final SpellAbility sa, boolean mayChooseNewTargets) { - FThreads.assertExecutedByEdt(false); + public static final void playSaWithoutPayingManaCost(final PlayerControllerHuman controller, final Game game, final SpellAbility sa, boolean mayChooseNewTargets) { + FThreads.assertExecutedByEdt(controller.getGui(), false); final Card source = sa.getHostCard(); source.setSplitStateToPlayAbility(sa); @@ -160,7 +159,7 @@ public class HumanPlay { } final CostPayment payment = new CostPayment(sa.getPayCosts(), sa); - final HumanPlaySpellAbility req = new HumanPlaySpellAbility(sa, payment); + final HumanPlaySpellAbility req = new HumanPlaySpellAbility(controller, sa, payment); req.playAbility(mayChooseNewTargets, true, false); } else { @@ -184,19 +183,19 @@ public class HumanPlay { * @param skipTargeting * a boolean. */ - public final static void playSpellAbilityNoStack(final Player player, final SpellAbility sa) { - playSpellAbilityNoStack(player, sa, false); + public final static void playSpellAbilityNoStack(final PlayerControllerHuman controller, final Player player, final SpellAbility sa) { + playSpellAbilityNoStack(controller, player, sa, false); } - public final static void playSpellAbilityNoStack(final Player player, final SpellAbility sa, boolean useOldTargets) { + public final static void playSpellAbilityNoStack(final PlayerControllerHuman controller, final Player player, final SpellAbility sa, boolean useOldTargets) { sa.setActivatingPlayer(player); if (sa.getPayCosts() != null) { - final HumanPlaySpellAbility req = new HumanPlaySpellAbility(sa, new CostPayment(sa.getPayCosts(), sa)); + final HumanPlaySpellAbility req = new HumanPlaySpellAbility(controller, sa, new CostPayment(sa.getPayCosts(), sa)); req.playAbility(!useOldTargets, false, true); } - else if (payManaCostIfNeeded(player, sa)) { + else if (payManaCostIfNeeded(controller, player, sa)) { AbilityUtils.resolve(sa); } } @@ -235,7 +234,7 @@ public class HumanPlay { * a {@link forge.UiCommand} object. * @param sourceAbility TODO */ - public static boolean payCostDuringAbilityResolve(final Player p, final Card source, final Cost cost, SpellAbility sourceAbility, String prompt) { + public static boolean payCostDuringAbilityResolve(final PlayerControllerHuman controller, final Player p, final Card source, final Cost cost, SpellAbility sourceAbility, String prompt) { // Only human player pays this way Card current = null; // Used in spells with RepeatEach effect to distinguish cards, Cut the Tethers if (sourceAbility.hasParam("ShowCurrentCard")) { @@ -263,7 +262,7 @@ public class HumanPlay { } } - HumanCostDecision hcd = new HumanCostDecision(p, sourceAbility, source); + final HumanCostDecision hcd = new HumanCostDecision(controller, p, sourceAbility, source); //the following costs do not need inputs for (CostPart part : parts) { @@ -382,7 +381,7 @@ public class HumanPlay { return false; } while (amount > 0) { - InputSelectCardsFromList inp = new InputSelectCardsFromList(1, 1, list); + InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, 1, 1, list); inp.setMessage("Select a card to add a counter to"); inp.setCancelAllowed(true); inp.showAndWait(); @@ -434,7 +433,7 @@ public class HumanPlay { } }); if (list.isEmpty()) { return false; } - InputSelectCardsFromList inp = new InputSelectCardsFromList(1, 1, list); + InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, 1, 1, list); inp.setMessage("Select a card to remove a counter"); inp.setCancelAllowed(true); inp.showAndWait(); @@ -451,7 +450,7 @@ public class HumanPlay { } if (typeChoices.size() > 1) { String cprompt = "Select type counters to remove"; - counterType = SGuiChoose.one(cprompt, typeChoices); + counterType = SGuiChoose.one(controller.getGui(), cprompt, typeChoices); } else { counterType = typeChoices.get(0); @@ -492,7 +491,7 @@ public class HumanPlay { } // replace this with input for (int i = 0; i < nNeeded; i++) { - final Card c = SGuiChoose.oneOrNone("Exile from " + from, list); + final Card c = SGuiChoose.oneOrNone(controller.getGui(), "Exile from " + from, list); if (c == null) { return false; } @@ -526,7 +525,7 @@ public class HumanPlay { payableZone.add(player); } } - Player chosen = SGuiChoose.oneOrNone(String.format("Put cards from whose %s?", from), payableZone); + Player chosen = SGuiChoose.oneOrNone(controller.getGui(), String.format("Put cards from whose %s?", from), payableZone); if (chosen == null) { return false; } @@ -538,7 +537,7 @@ public class HumanPlay { return false; } - final Card c = SGuiChoose.oneOrNone("Put cards to Library", typeList); + final Card c = SGuiChoose.oneOrNone(controller.getGui(), "Put cards to Library", typeList); if (c != null) { typeList.remove(c); @@ -550,7 +549,7 @@ public class HumanPlay { } } else if (from == ZoneType.Hand) { // Tainted Specter - boolean hasPaid = payCostPart(sourceAbility, (CostPartWithList)part, amount, list, "put into library." + orString); + boolean hasPaid = payCostPart(controller, sourceAbility, (CostPartWithList)part, amount, list, "put into library." + orString); if (!hasPaid) { return false; } @@ -560,19 +559,19 @@ public class HumanPlay { else if (part instanceof CostSacrifice) { int amount = Integer.parseInt(((CostSacrifice)part).getAmount()); List list = CardLists.getValidCards(p.getCardsIn(ZoneType.Battlefield), part.getType(), p, source); - boolean hasPaid = payCostPart(sourceAbility, (CostPartWithList)part, amount, list, "sacrifice." + orString); + boolean hasPaid = payCostPart(controller, sourceAbility, (CostPartWithList)part, amount, list, "sacrifice." + orString); if (!hasPaid) { return false; } } else if (part instanceof CostGainControl) { int amount = Integer.parseInt(((CostGainControl)part).getAmount()); List list = CardLists.getValidCards(p.getGame().getCardsIn(ZoneType.Battlefield), part.getType(), p, source); - boolean hasPaid = payCostPart(sourceAbility, (CostPartWithList)part, amount, list, "gain control." + orString); + boolean hasPaid = payCostPart(controller, sourceAbility, (CostPartWithList)part, amount, list, "gain control." + orString); if (!hasPaid) { return false; } } else if (part instanceof CostReturn) { List list = CardLists.getValidCards(p.getCardsIn(ZoneType.Battlefield), part.getType(), p, source); int amount = getAmountFromPartX(part, source, sourceAbility); - boolean hasPaid = payCostPart(sourceAbility, (CostPartWithList)part, amount, list, "return to hand." + orString); + boolean hasPaid = payCostPart(controller, sourceAbility, (CostPartWithList)part, amount, list, "return to hand." + orString); if (!hasPaid) { return false; } } else if (part instanceof CostDiscard) { @@ -588,21 +587,21 @@ public class HumanPlay { } else { List list = CardLists.getValidCards(p.getCardsIn(ZoneType.Hand), part.getType(), p, source); int amount = getAmountFromPartX(part, source, sourceAbility); - boolean hasPaid = payCostPart(sourceAbility, (CostPartWithList)part, amount, list, "discard." + orString); + boolean hasPaid = payCostPart(controller, sourceAbility, (CostPartWithList)part, amount, list, "discard." + orString); if (!hasPaid) { return false; } } } else if (part instanceof CostReveal) { List list = CardLists.getValidCards(p.getCardsIn(ZoneType.Hand), part.getType(), p, source); int amount = getAmountFromPartX(part, source, sourceAbility); - boolean hasPaid = payCostPart(sourceAbility, (CostPartWithList)part, amount, list, "reveal." + orString); + boolean hasPaid = payCostPart(controller, sourceAbility, (CostPartWithList)part, amount, list, "reveal." + orString); if (!hasPaid) { return false; } } else if (part instanceof CostTapType) { List list = CardLists.getValidCards(p.getCardsIn(ZoneType.Battlefield), part.getType(), p, source); list = CardLists.filter(list, Presets.UNTAPPED); int amount = getAmountFromPartX(part, source, sourceAbility); - boolean hasPaid = payCostPart(sourceAbility, (CostPartWithList)part, amount, list, "tap." + orString); + boolean hasPaid = payCostPart(controller, sourceAbility, (CostPartWithList)part, amount, list, "tap." + orString); if (!hasPaid) { return false; } } else if (part instanceof CostPartMana) { @@ -645,10 +644,10 @@ public class HumanPlay { return paid; } - private static boolean payCostPart(SpellAbility sourceAbility, CostPartWithList cpl, int amount, List list, String actionName) { + private static boolean payCostPart(final PlayerControllerHuman controller, SpellAbility sourceAbility, CostPartWithList cpl, int amount, List list, String actionName) { if (list.size() < amount) { return false; } // unable to pay (not enough cards) - InputSelectCardsFromList inp = new InputSelectCardsFromList(amount, amount, list); + InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, amount, amount, list); inp.setMessage("Select %d " + cpl.getDescriptiveType() + " card(s) to " + actionName); inp.setCancelAllowed(true); @@ -689,7 +688,7 @@ public class HumanPlay { return done; } - public static boolean payManaCost(final ManaCost realCost, final CostPartMana mc, final SpellAbility ability, final Player activator, String prompt, boolean isActivatedSa) { + public static boolean payManaCost(final PlayerControllerHuman controller, final ManaCost realCost, final CostPartMana mc, final SpellAbility ability, final Player activator, String prompt, boolean isActivatedSa) { final Card source = ability.getHostCard(); ManaCostBeingPaid toPay = new ManaCostBeingPaid(realCost, mc.getRestiction()); @@ -718,7 +717,7 @@ public class HumanPlay { return false; } if (!toPay.isPaid()) { - inpPayment = new InputPayManaOfCostPayment(toPay, ability, activator); + inpPayment = new InputPayManaOfCostPayment(controller, toPay, ability, activator); inpPayment.setMessagePrefix(prompt); inpPayment.showAndWait(); if (!inpPayment.isPaid()) { @@ -731,7 +730,7 @@ public class HumanPlay { if (mc.getAmountOfX() > 0) { if (!ability.isAnnouncing("X") && !xWasBilled) { source.setXManaCostPaid(0); - inpPayment = new InputPayManaX(ability, mc.getAmountOfX(), mc.canXbe0()); + inpPayment = new InputPayManaX(controller, ability, mc.getAmountOfX(), mc.canXbe0()); inpPayment.showAndWait(); if (!inpPayment.isPaid()) { return false; diff --git a/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java b/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java index 68889d69619..a4c3c4a27c2 100644 --- a/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java +++ b/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java @@ -50,10 +50,12 @@ import java.util.List; * @version $Id: HumanPlaySpellAbility.java 24317 2014-01-17 08:32:39Z Max mtg $ */ public class HumanPlaySpellAbility { + private final PlayerControllerHuman controller; private final SpellAbility ability; private final CostPayment payment; - public HumanPlaySpellAbility(final SpellAbility sa, final CostPayment cp) { + public HumanPlaySpellAbility(final PlayerControllerHuman controller, final SpellAbility sa, final CostPayment cp) { + this.controller = controller; this.ability = sa; this.payment = cp; } @@ -94,7 +96,7 @@ public class HumanPlaySpellAbility { boolean prerequisitesMet = this.announceValuesLikeX() && this.announceType() && (!mayChooseTargets || setupTargets()) // if you can choose targets, then do choose them. - && (isFree || this.payment.payCost(new HumanCostDecision(human, ability, ability.getHostCard()))); + && (isFree || this.payment.payCost(new HumanCostDecision(controller, human, ability, ability.getHostCard()))); if (!prerequisitesMet) { if (!ability.isTrigger()) { diff --git a/forge-gui/src/main/java/forge/player/LobbyPlayerHuman.java b/forge-gui/src/main/java/forge/player/LobbyPlayerHuman.java index ebd8de25b53..5a1d36cde26 100644 --- a/forge-gui/src/main/java/forge/player/LobbyPlayerHuman.java +++ b/forge-gui/src/main/java/forge/player/LobbyPlayerHuman.java @@ -1,30 +1,33 @@ package forge.player; -import forge.GuiBase; import forge.LobbyPlayer; import forge.game.Game; import forge.game.player.IGameEntitiesFactory; import forge.game.player.Player; import forge.game.player.PlayerController; +import forge.interfaces.IGuiBase; import forge.model.FModel; import forge.properties.ForgePreferences; import forge.properties.ForgePreferences.FPref; import forge.util.GuiDisplayUtil; public class LobbyPlayerHuman extends LobbyPlayer implements IGameEntitiesFactory { - public LobbyPlayerHuman(String name) { + final IGuiBase gui; + + public LobbyPlayerHuman(final String name, final IGuiBase gui) { super(name); + this.gui = gui; } @Override public PlayerController createControllerFor(Player human) { - return new PlayerControllerHuman(human.getGame(), human, this); + return new PlayerControllerLocal(human.getGame(), human, this, gui); } @Override public Player createIngamePlayer(Game game) { Player player = new Player(GuiDisplayUtil.personalizeHuman(getName()), game); - player.setFirstController(new PlayerControllerHuman(game, player, this)); + player.setFirstController(new PlayerControllerLocal(game, player, this, gui)); if (ForgePreferences.DEV_MODE && FModel.getPreferences().getPrefBoolean(FPref.DEV_UNLIMITED_LAND)) { player.canCheatPlayUnlimitedLands = true; @@ -33,6 +36,6 @@ public class LobbyPlayerHuman extends LobbyPlayer implements IGameEntitiesFactor } public void hear(LobbyPlayer player, String message) { - GuiBase.getInterface().hear(player, message); + gui.hear(player, message); } } \ No newline at end of file diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index 37b0f756f12..c178972f561 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -1,1652 +1,127 @@ -package forge.player; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Observer; - -import org.apache.commons.lang3.Range; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; - -import com.google.common.base.Function; -import com.google.common.base.Predicate; -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.BiMap; -import com.google.common.collect.HashBiMap; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Multimap; - -import forge.GuiBase; -import forge.LobbyPlayer; -import forge.card.ColorSet; -import forge.card.MagicColor; -import forge.card.mana.ManaCost; -import forge.card.mana.ManaCostShard; -import forge.control.FControlGamePlayback; -import forge.deck.CardPool; -import forge.deck.Deck; -import forge.deck.DeckSection; -import forge.events.UiEventAttackerDeclared; -import forge.game.Game; -import forge.game.GameEntity; -import forge.game.GameLogEntry; -import forge.game.GameLogEntryType; -import forge.game.GameObject; -import forge.game.GameOutcome; -import forge.game.GameType; -import forge.game.ability.effects.CharmEffect; -import forge.game.card.Card; -import forge.game.card.CardFactoryUtil; -import forge.game.card.CardShields; -import forge.game.card.CounterType; -import forge.game.combat.AttackingBand; -import forge.game.combat.Combat; -import forge.game.combat.CombatUtil; -import forge.game.cost.Cost; -import forge.game.cost.CostPart; -import forge.game.cost.CostPartMana; -import forge.game.mana.Mana; -import forge.game.phase.PhaseType; -import forge.game.player.Player; -import forge.game.player.PlayerActionConfirmMode; -import forge.game.player.PlayerController; -import forge.game.player.RegisteredPlayer; -import forge.game.replacement.ReplacementEffect; -import forge.game.spellability.AbilitySub; -import forge.game.spellability.SpellAbility; -import forge.game.spellability.SpellAbilityStackInstance; -import forge.game.spellability.TargetChoices; -import forge.game.trigger.Trigger; -import forge.game.trigger.WrappedAbility; -import forge.game.zone.MagicStack; -import forge.game.zone.Zone; -import forge.game.zone.ZoneType; -import forge.item.PaperCard; -import forge.match.input.ButtonUtil; -import forge.match.input.InputAttack; -import forge.match.input.InputBase; -import forge.match.input.InputBlock; -import forge.match.input.InputConfirm; -import forge.match.input.InputConfirmMulligan; -import forge.match.input.InputPassPriority; -import forge.match.input.InputProliferate; -import forge.match.input.InputSelectCardsForConvoke; -import forge.match.input.InputSelectCardsFromList; -import forge.match.input.InputSelectEntitiesFromList; -import forge.model.FModel; -import forge.properties.ForgePreferences.FPref; -import forge.util.DevModeUtil; -import forge.util.ITriggerEvent; -import forge.util.Lang; -import forge.util.TextUtil; -import forge.util.gui.SGuiChoose; -import forge.util.gui.SGuiDialog; -import forge.util.gui.SOptionPane; -import forge.view.CardView; -import forge.view.CombatView; -import forge.view.GameEntityView; -import forge.view.IGameView; -import forge.view.PlayerView; -import forge.view.StackItemView; -import forge.view.ViewUtil; - -/** - * A prototype for player controller class - * - * Handles phase skips for now. - */ -public class PlayerControllerHuman extends PlayerController implements IGameView { - public PlayerControllerHuman(Game game0, Player p, LobbyPlayer lp) { - super(game0, p, lp); - // aggressively cache a view for each player - for (final Player player : game.getRegisteredPlayers()) { - getPlayerView(player); - } - // aggressively cache a view for each card - for (final Card c : game.getCardsInGame()) { - getCardView(c); - } - } - - public boolean isUiSetToSkipPhase(final Player turn, final PhaseType phase) { - return !GuiBase.getInterface().stopAtPhase(getPlayerView(turn), phase); - } - - /** - * Uses GUI to learn which spell the player (human in our case) would like to play - */ - public SpellAbility getAbilityToPlay(List abilities, ITriggerEvent triggerEvent) { - return GuiBase.getInterface().getAbilityToPlay(abilities, triggerEvent); - } - - /** - * TODO: Write javadoc for this method. - * @param c - */ - /**public void playFromSuspend(Card c) { - c.setSuspendCast(true); - HumanPlay.playCardWithoutPayingManaCost(player, c); - }**/ - - - /* (non-Javadoc) - * @see forge.game.player.PlayerController#mayPlaySpellAbilityForFree(forge.card.spellability.SpellAbility) - */ - @Override - public void playSpellAbilityForFree(SpellAbility copySA, boolean mayChoseNewTargets) { - HumanPlay.playSaWithoutPayingManaCost(player.getGame(), copySA, mayChoseNewTargets); - } - - @Override - public void playSpellAbilityNoStack(SpellAbility effectSA, boolean canSetupTargets) { - HumanPlay.playSpellAbilityNoStack(player, effectSA, !canSetupTargets); - } - - /* (non-Javadoc) - * @see forge.game.player.PlayerController#sideboard(forge.deck.Deck) - */ - @Override - public List sideboard(Deck deck, GameType gameType) { - CardPool sideboard = deck.get(DeckSection.Sideboard); - if (sideboard == null) { - // Use an empty cardpool instead of null for 75/0 sideboarding scenario. - sideboard = new CardPool(); - } - - CardPool main = deck.get(DeckSection.Main); - - int mainSize = main.countAll(); - int sbSize = sideboard.countAll(); - int combinedDeckSize = mainSize + sbSize; - - int deckMinSize = Math.min(mainSize, gameType.getDeckFormat().getMainRange().getMinimum()); - Range sbRange = gameType.getDeckFormat().getSideRange(); - // Limited doesn't have a sideboard max, so let the Main min take care of things. - int sbMax = sbRange == null ? combinedDeckSize : sbRange.getMaximum(); - - List newMain = null; - - //Skip sideboard loop if there are no sideboarding opportunities - if (sbSize == 0 && mainSize == deckMinSize) { return null; } - - // conformance should not be checked here - boolean conform = FModel.getPreferences().getPrefBoolean(FPref.ENFORCE_DECK_LEGALITY); - do { - if (newMain != null) { - String errMsg; - if (newMain.size() < deckMinSize) { - errMsg = String.format("Too few cards in your main deck (minimum %d), please make modifications to your deck again.", deckMinSize); - } - else { - errMsg = String.format("Too many cards in your sideboard (maximum %d), please make modifications to your deck again.", sbMax); - } - SOptionPane.showErrorDialog(errMsg, "Invalid Deck"); - } - // Sideboard rules have changed for M14, just need to consider min maindeck and max sideboard sizes - // No longer need 1:1 sideboarding in non-limited formats - newMain = GuiBase.getInterface().sideboard(sideboard, main); - } while (conform && (newMain.size() < deckMinSize || combinedDeckSize - newMain.size() > sbMax)); - - return newMain; - } - - /* (non-Javadoc) - * @see forge.game.player.PlayerController#assignCombatDamage() - */ - @Override - public Map assignCombatDamage(final Card attacker, - final List blockers, final int damageDealt, - final GameEntity defender, final boolean overrideOrder) { - // Attacker is a poor name here, since the creature assigning damage - // could just as easily be the blocker. - final Map map = Maps.newHashMap(); - if (defender != null && assignDamageAsIfNotBlocked(attacker)) { - map.put(null, damageDealt); - } else { - final List vBlockers = Lists.transform(blockers, FN_GET_CARD_VIEW); - if ((attacker.hasKeyword("Trample") && defender != null) || (blockers.size() > 1)) { - final CardView vAttacker = getCardView(attacker); - final GameEntityView vDefender = getGameEntityView(defender); - final Map result = GuiBase.getInterface().getDamageToAssign(vAttacker, vBlockers, damageDealt, vDefender, overrideOrder); - for (final Entry e : result.entrySet()) { - map.put(getCard(e.getKey()), e.getValue()); - } - } else { - map.put(blockers.get(0), damageDealt); - } - } - return map; - } - - private final boolean assignDamageAsIfNotBlocked(final Card attacker) { - return attacker.hasKeyword("CARDNAME assigns its combat damage as though it weren't blocked.") - || (attacker.hasKeyword("You may have CARDNAME assign its combat damage as though it weren't blocked.") - && SGuiDialog.confirm(getCardView(attacker), "Do you want to assign its combat damage as though it weren't blocked?")); - } - - /* (non-Javadoc) - * @see forge.game.player.PlayerController#announceRequirements(java.lang.String) - */ - @Override - public Integer announceRequirements(SpellAbility ability, String announce, boolean canChooseZero) { - int min = canChooseZero ? 0 : 1; - return SGuiChoose.getInteger("Choose " + announce + " for " + ability.getHostCard().getName(), - min, Integer.MAX_VALUE, min + 9); - } - - @Override - public List choosePermanentsToSacrifice(SpellAbility sa, int min, int max, List valid, String message) { - String outerMessage = "Select %d " + message + "(s) to sacrifice"; - return choosePermanentsTo(min, max, valid, outerMessage); - } - - @Override - public List choosePermanentsToDestroy(SpellAbility sa, int min, int max, List valid, String message) { - String outerMessage = "Select %d " + message + "(s) to be destroyed"; - return choosePermanentsTo(min, max, valid, outerMessage); - } - - private List choosePermanentsTo(int min, int max, List valid, String outerMessage) { - max = Math.min(max, valid.size()); - if (max <= 0) { - return new ArrayList(); - } - - InputSelectCardsFromList inp = new InputSelectCardsFromList(min == 0 ? 1 : min, max, valid); - inp.setMessage(outerMessage); - inp.setCancelAllowed(min == 0); - inp.showAndWait(); - return Lists.newArrayList(inp.getSelected()); - } - - - /* (non-Javadoc) - * @see forge.game.player.PlayerController#chooseCardsForEffect(java.util.Collection, forge.card.spellability.SpellAbility, java.lang.String, int, boolean) - */ - @Override - public List chooseCardsForEffect(List sourceList, SpellAbility sa, String title, int min, int max, boolean isOptional) { - // If only one card to choose, use a dialog box. - // Otherwise, use the order dialog to be able to grab multiple cards in one shot - if (max == 1) { - Card singleChosen = chooseSingleEntityForEffect(sourceList, sa, title, isOptional); - return singleChosen == null ? Lists.newArrayList() : Lists.newArrayList(singleChosen); - } - - GuiBase.getInterface().setPanelSelection(getCardView(sa.getHostCard())); - - // try to use InputSelectCardsFromList when possible - boolean cardsAreInMyHandOrBattlefield = true; - for(Card c : sourceList) { - Zone z = c.getZone(); - if (z != null && (z.is(ZoneType.Battlefield) || z.is(ZoneType.Hand, player))) - continue; - cardsAreInMyHandOrBattlefield = false; - break; - } - - if(cardsAreInMyHandOrBattlefield) { - InputSelectCardsFromList sc = new InputSelectCardsFromList(min, max, sourceList); - sc.setMessage(title); - sc.setCancelAllowed(isOptional); - sc.showAndWait(); - return Lists.newArrayList(sc.getSelected()); - } - - return SGuiChoose.many(title, "Chosen Cards", min, max, sourceList, getCardView(sa.getHostCard())); - } - - @Override - public T chooseSingleEntityForEffect(Collection options, SpellAbility sa, String title, boolean isOptional, Player targetedPlayer) { - // Human is supposed to read the message and understand from it what to choose - if (options.isEmpty()) { - return null; - } - if (!isOptional && options.size() == 1) { - return Iterables.getFirst(options, null); - } - - boolean canUseSelectCardsInput = true; - for (GameEntity c : options) { - if (c instanceof Player) - continue; - Zone cz = ((Card)c).getZone(); - // can point at cards in own hand and anyone's battlefield - boolean canUiPointAtCards = cz != null && (cz.is(ZoneType.Hand) && cz.getPlayer() == player || cz.is(ZoneType.Battlefield)); - if (!canUiPointAtCards) { - canUseSelectCardsInput = false; - break; - } - } - - if (canUseSelectCardsInput) { - InputSelectEntitiesFromList input = new InputSelectEntitiesFromList(isOptional ? 0 : 1, 1, options); - input.setCancelAllowed(isOptional); - input.setMessage(formatMessage(title, targetedPlayer)); - input.showAndWait(); - return Iterables.getFirst(input.getSelected(), null); - } - - return isOptional ? SGuiChoose.oneOrNone(title, options) : SGuiChoose.one(title, options); - } - - @Override - public int chooseNumber(SpellAbility sa, String title, int min, int max) { - final Integer[] choices = new Integer[max + 1 - min]; - for (int i = 0; i <= max - min; i++) { - choices[i] = Integer.valueOf(i + min); - } - return SGuiChoose.one(title, choices).intValue(); - } - - @Override - public int chooseNumber(SpellAbility sa, String title, List choices, Player relatedPlayer) { - return SGuiChoose.one(title, choices).intValue(); - } - - @Override - public SpellAbility chooseSingleSpellForEffect(java.util.List spells, SpellAbility sa, String title) { - // Human is supposed to read the message and understand from it what to choose - return spells.size() < 2 ? spells.get(0) : SGuiChoose.one(title, spells); - } - - /* (non-Javadoc) - * @see forge.game.player.PlayerController#confirmAction(forge.card.spellability.SpellAbility, java.lang.String, java.lang.String) - */ - @Override - public boolean confirmAction(SpellAbility sa, PlayerActionConfirmMode mode, String message) { - return SGuiDialog.confirm(getCardView(sa.getHostCard()), message); - } - - @Override - public boolean confirmBidAction(SpellAbility sa, PlayerActionConfirmMode bidlife, - String string, int bid, Player winner) { - return SGuiDialog.confirm(getCardView(sa.getHostCard()), string + " Highest Bidder " + winner); - } - - @Override - public boolean confirmStaticApplication(Card hostCard, GameEntity affected, String logic, String message) { - return SGuiDialog.confirm(getCardView(hostCard), message); - } - - @Override - public boolean confirmTrigger(SpellAbility sa, Trigger regtrig, Map triggerParams, boolean isMandatory) { - if (this.shouldAlwaysAcceptTrigger(regtrig.getId())) { - return true; - } - if (this.shouldAlwaysDeclineTrigger(regtrig.getId())) { - return false; - } - - final StringBuilder buildQuestion = new StringBuilder("Use triggered ability of "); - buildQuestion.append(regtrig.getHostCard().toString()).append("?"); - if (!FModel.getPreferences().getPrefBoolean(FPref.UI_COMPACT_PROMPT)) { - //append trigger description unless prompt is compact - buildQuestion.append("\n("); - buildQuestion.append(triggerParams.get("TriggerDescription").replace("CARDNAME", regtrig.getHostCard().getName())); - buildQuestion.append(")"); - } - HashMap tos = sa.getTriggeringObjects(); - if (tos.containsKey("Attacker")) { - buildQuestion.append("\nAttacker: " + tos.get("Attacker")); - } - if (tos.containsKey("Card")) { - Card card = (Card) tos.get("Card"); - if (card != null && (card.getController() == player || game.getZoneOf(card) == null - || game.getZoneOf(card).getZoneType().isKnown())) { - buildQuestion.append("\nTriggered by: " + tos.get("Card")); - } - } - - InputConfirm inp = new InputConfirm(buildQuestion.toString()); - inp.showAndWait(); - return inp.getResult(); - } - - @Override - public Player chooseStartingPlayer(boolean isFirstGame) { - if (game.getPlayers().size() == 2) { - final String prompt = String.format("%s, you %s\n\nWould you like to play or draw?", - player.getName(), isFirstGame ? " have won the coin toss." : " lost the last game."); - final InputConfirm inp = new InputConfirm(prompt, "Play", "Draw"); - inp.showAndWait(); - return inp.getResult() ? this.player : this.player.getOpponents().get(0); - } else { - final String prompt = String.format("%s, you %s\n\nWho would you like to start this game?", - player.getName(), isFirstGame ? " have won the coin toss." : " lost the last game."); - final InputSelectEntitiesFromList input = new InputSelectEntitiesFromList<>(1, 1, game.getPlayersInTurnOrder()); - input.setMessage(prompt); - input.showAndWait(); - return input.getFirstSelected(); - } - } - - @Override - public List orderBlockers(final Card attacker, final List blockers) { - final CardView vAttacker = getCardView(attacker); - GuiBase.getInterface().setPanelSelection(vAttacker); - final List choices = SGuiChoose.order("Choose Damage Order for " + vAttacker, "Damaged First", getCardViews(blockers), vAttacker); - return getCards(choices); - } - - @Override - public List orderBlocker(final Card attacker, final Card blocker, final List oldBlockers) { - final CardView vAttacker = getCardView(attacker); - GuiBase.getInterface().setPanelSelection(vAttacker); - final List choices = SGuiChoose.insertInList("Choose blocker after which to place " + vAttacker + " in damage order; cancel to place it first", getCardView(blocker), getCardViews(oldBlockers)); - return getCards(choices); - } - - @Override - public List orderAttackers(final Card blocker, final List attackers) { - final CardView vBlocker = getCardView(blocker); - GuiBase.getInterface().setPanelSelection(vBlocker); - final List choices = SGuiChoose.order("Choose Damage Order for " + vBlocker, "Damaged First", getCardViews(attackers), vBlocker); - return getCards(choices); - } - - /* (non-Javadoc) - * @see forge.game.player.PlayerController#reveal(java.lang.String, java.util.List, forge.game.zone.ZoneType, forge.game.player.Player) - */ - @Override - public void reveal(Collection cards, ZoneType zone, Player owner, String message) { - if (StringUtils.isBlank(message)) { - message = "Looking at cards in {player's} " + zone.name().toLowerCase(); - } - else { - message += "{player's} " + zone.name().toLowerCase(); - } - String fm = formatMessage(message, owner); - if (!cards.isEmpty()) { - SGuiChoose.reveal(fm, cards); - } - else { - SGuiDialog.message(formatMessage("There are no cards in {player's} " + - zone.name().toLowerCase(), owner), fm); - } - } - - @Override - public ImmutablePair, List> arrangeForScry(List topN) { - List toBottom = null; - List toTop = null; - - if (topN.size() == 1) { - if (willPutCardOnTop(topN.get(0))) { - toTop = topN; - } - else { - toBottom = topN; - } - } - else { - toBottom = SGuiChoose.many("Select cards to be put on the bottom of your library", "Cards to put on the bottom", -1, topN, null); - topN.removeAll(toBottom); - if (topN.isEmpty()) { - toTop = null; - } - else if (topN.size() == 1) { - toTop = topN; - } - else { - toTop = SGuiChoose.order("Arrange cards to be put on top of your library", "Cards arranged", topN, null); - } - } - return ImmutablePair.of(toTop, toBottom); - } - - @Override - public boolean willPutCardOnTop(final Card c) { - final PaperCard pc = FModel.getMagicDb().getCommonCards().getCard(c.getName()); - final Card c1 = (pc != null ? Card.fromPaperCard(pc, null) : c); - final CardView view = getCardView(c1); - return SGuiDialog.confirm(view, "Put " + view + " on the top or bottom of your library?", new String[]{"Top", "Bottom"}); - } - - @Override - public List orderMoveToZoneList(List cards, ZoneType destinationZone) { - switch (destinationZone) { - case Library: - return SGuiChoose.order("Choose order of cards to put into the library", "Closest to top", cards, null); - case Battlefield: - return SGuiChoose.order("Choose order of cards to put onto the battlefield", "Put first", cards, null); - case Graveyard: - return SGuiChoose.order("Choose order of cards to put into the graveyard", "Closest to bottom", cards, null); - case PlanarDeck: - return SGuiChoose.order("Choose order of cards to put into the planar deck", "Closest to top", cards, null); - case SchemeDeck: - return SGuiChoose.order("Choose order of cards to put into the scheme deck", "Closest to top", cards, null); - case Stack: - return SGuiChoose.order("Choose order of copies to cast", "Put first", cards, null); - default: - System.out.println("ZoneType " + destinationZone + " - Not Ordered"); - break; - } - return cards; - } - - @Override - public List chooseCardsToDiscardFrom(Player p, SpellAbility sa, List valid, int min, int max) { - if (p != player) { - return SGuiChoose.many("Choose " + min + " card" + (min != 1 ? "s" : "") + " to discard", - "Discarded", min, min, valid, null); - } - - InputSelectCardsFromList inp = new InputSelectCardsFromList(min, max, valid); - inp.setMessage(sa.hasParam("AnyNumber") ? "Discard up to %d card(s)" : "Discard %d card(s)"); - inp.showAndWait(); - return Lists.newArrayList(inp.getSelected()); - } - - @Override - public void playMiracle(final SpellAbility miracle, final Card card) { - final CardView view = getCardView(card); - if (SGuiDialog.confirm(view, view + " - Drawn. Play for Miracle Cost?")) { - HumanPlay.playSpellAbility(player, miracle); - } - } - - @Override - public List chooseCardsToDelve(int colorLessAmount, List grave) { - List toExile = new ArrayList(); - int cardsInGrave = grave.size(); - final Integer[] cntChoice = new Integer[cardsInGrave + 1]; - for (int i = 0; i <= cardsInGrave; i++) { - cntChoice[i] = Integer.valueOf(i); - } - - final Integer chosenAmount = SGuiChoose.one("Exile how many cards?", cntChoice); - System.out.println("Delve for " + chosenAmount); - - for (int i = 0; i < chosenAmount; i++) { - final Card nowChosen = SGuiChoose.oneOrNone("Exile which card?", grave); - - if (nowChosen == null) { - // User canceled,abort delving. - toExile.clear(); - break; - } - - grave.remove(nowChosen); - toExile.add(nowChosen); - } - return toExile; - } - - /* (non-Javadoc) - * @see forge.game.player.PlayerController#chooseTargets(forge.card.spellability.SpellAbility, forge.card.spellability.SpellAbilityStackInstance) - */ - @Override - public TargetChoices chooseNewTargetsFor(SpellAbility ability) { - SpellAbility sa = ability.isWrapper() ? ((WrappedAbility) ability).getWrappedAbility() : ability; - if (sa.getTargetRestrictions() == null) { - return null; - } - TargetChoices oldTarget = sa.getTargets(); - TargetSelection select = new TargetSelection(sa); - sa.resetTargets(); - if (select.chooseTargets(oldTarget.getNumTargeted())) { - return sa.getTargets(); - } - else { - // Return old target, since we had to reset them above - return oldTarget; - } - } - - /* (non-Javadoc) - * @see forge.game.player.PlayerController#chooseCardsToDiscardUnlessType(int, java.lang.String, forge.card.spellability.SpellAbility) - */ - @Override - public List chooseCardsToDiscardUnlessType(int num, List hand, final String uType, SpellAbility sa) { - final InputSelectEntitiesFromList target = new InputSelectEntitiesFromList(num, num, hand) { - private static final long serialVersionUID = -5774108410928795591L; - - @Override - protected boolean hasAllTargets() { - for (Card c : selected) { - if (c.isType(uType)) { - return true; - } - } - return super.hasAllTargets(); - } - }; - target.setMessage("Select %d card(s) to discard, unless you discard a " + uType + "."); - target.showAndWait(); - return Lists.newArrayList(target.getSelected()); - } - - /* (non-Javadoc) - * @see forge.game.player.PlayerController#chooseManaFromPool(java.util.List) - */ - @Override - public Mana chooseManaFromPool(List manaChoices) { - List options = new ArrayList(); - for (int i = 0; i < manaChoices.size(); i++) { - Mana m = manaChoices.get(i); - options.add(String.format("%d. %s mana from %s", 1+i, MagicColor.toLongString(m.getColor()), m.getSourceCard())); - } - String chosen = SGuiChoose.one("Pay Mana from Mana Pool", options); - String idx = TextUtil.split(chosen, '.')[0]; - return manaChoices.get(Integer.parseInt(idx)-1); - } - - /* (non-Javadoc) - * @see forge.game.player.PlayerController#chooseSomeType(java.lang.String, java.lang.String, java.util.List, java.util.List, java.lang.String) - */ - @Override - public String chooseSomeType(final String kindOfType, final SpellAbility sa, final List validTypes, List invalidTypes, final boolean isOptional) { - final List types = Lists.newArrayList(validTypes); - if (invalidTypes != null && !invalidTypes.isEmpty()) { - Iterables.removeAll(types, invalidTypes); - } - if(isOptional) - return SGuiChoose.oneOrNone("Choose a " + kindOfType.toLowerCase() + " type", types); - else - return SGuiChoose.one("Choose a " + kindOfType.toLowerCase() + " type", types); - } - - @Override - public Object vote(SpellAbility sa, String prompt, List options, ArrayListMultimap votes) { - return SGuiChoose.one(prompt, options); - } - - /* (non-Javadoc) - * @see forge.game.player.PlayerController#confirmReplacementEffect(forge.card.replacement.ReplacementEffect, forge.card.spellability.SpellAbility, java.lang.String) - */ - @Override - public boolean confirmReplacementEffect(ReplacementEffect replacementEffect, SpellAbility effectSA, String question) { - return SGuiDialog.confirm(getCardView(replacementEffect.getHostCard()), question); - } - - @Override - public List getCardsToMulligan(boolean isCommander, Player firstPlayer) { - final InputConfirmMulligan inp = new InputConfirmMulligan(player, firstPlayer, isCommander); - inp.showAndWait(); - return inp.isKeepHand() ? null : isCommander ? inp.getSelectedCards() : player.getCardsIn(ZoneType.Hand); - } - - @Override - public void declareAttackers(Player attackingPlayer, Combat combat) { - if (mayAutoPass()) { - List> mandatoryAttackers = CombatUtil.getMandatoryAttackers(attackingPlayer, combat, combat.getDefenders()); - if (!mandatoryAttackers.isEmpty()) { - //even if auto-passing attack phase, if there are any mandatory attackers, - //ensure they're declared and then delay slightly so user can see as much - for (Pair attacker : mandatoryAttackers) { - combat.addAttacker(attacker.getLeft(), attacker.getRight()); - GuiBase.getInterface().fireEvent(new UiEventAttackerDeclared(getCardView(attacker.getLeft()), getGameEntityView(attacker.getRight()))); - } - try { - Thread.sleep(FControlGamePlayback.combatDelay); - } - catch (InterruptedException e) { - e.printStackTrace(); - } - } - return; //don't prompt to declare attackers if user chose to end the turn - } - - // This input should not modify combat object itself, but should return user choice - InputAttack inpAttack = new InputAttack(attackingPlayer, combat); - inpAttack.showAndWait(); - } - - @Override - public void declareBlockers(Player defender, Combat combat) { - // This input should not modify combat object itself, but should return user choice - InputBlock inpBlock = new InputBlock(defender, combat); - inpBlock.showAndWait(); - updateAutoPassPrompt(); - } - - public void updateAutoPassPrompt() { - if (mayAutoPass()) { - //allow user to cancel auto-pass - InputBase.cancelAwaitNextInput(); //don't overwrite prompt with awaiting opponent - PhaseType phase = getAutoPassUntilPhase(); - GuiBase.getInterface().showPromptMessage("Yielding until " + (phase == PhaseType.CLEANUP ? "end of turn" : phase.nameForUi.toString()) + - ".\nYou may cancel this yield to take an action."); - ButtonUtil.update(false, true, false); - } - } - - @Override - public void autoPassUntilEndOfTurn() { - super.autoPassUntilEndOfTurn(); - updateAutoPassPrompt(); - } - - @Override - public void autoPassCancel() { - if (getAutoPassUntilPhase() == null) { return; } - super.autoPassCancel(); - - //prevent prompt getting stuck on yielding message while actually waiting for next input opportunity - GuiBase.getInterface().showPromptMessage(""); - ButtonUtil.update(false, false, false); - InputBase.awaitNextInput(); - } - - @Override - public SpellAbility chooseSpellAbilityToPlay() { - MagicStack stack = game.getStack(); - - if (mayAutoPass()) { - //avoid prompting for input if current phase is set to be auto-passed - //instead posing a short delay if needed to prevent the game jumping ahead too quick - int delay = 0; - if (stack.isEmpty()) { - //make sure to briefly pause at phases you're not set up to skip - if (!isUiSetToSkipPhase(game.getPhaseHandler().getPlayerTurn(), game.getPhaseHandler().getPhase())) { - delay = FControlGamePlayback.phasesDelay; - } - } - else { - //pause slightly longer for spells and abilities on the stack resolving - delay = FControlGamePlayback.resolveDelay; - } - if (delay > 0) { - try { - Thread.sleep(delay); - } - catch (InterruptedException e) { - e.printStackTrace(); - } - } - return null; - } - - if (stack.isEmpty()) { - if (isUiSetToSkipPhase(game.getPhaseHandler().getPlayerTurn(), game.getPhaseHandler().getPhase())) { - return null; //avoid prompt for input if stack is empty and player is set to skip the current phase - } - } - else if (!game.getDisableAutoYields()) { - SpellAbility ability = stack.peekAbility(); - if (ability != null && ability.isAbility() && shouldAutoYield(ability.toUnsuppressedString())) { - //avoid prompt for input if top ability of stack is set to auto-yield - try { - Thread.sleep(FControlGamePlayback.resolveDelay); - } - catch (InterruptedException e) { - e.printStackTrace(); - } - return null; - } - } - - InputPassPriority defaultInput = new InputPassPriority(player); - defaultInput.showAndWait(); - return defaultInput.getChosenSa(); - } - - @Override - public void playChosenSpellAbility(SpellAbility chosenSa) { - HumanPlay.playSpellAbility(player, chosenSa); - } - - @Override - public List chooseCardsToDiscardToMaximumHandSize(int nDiscard) { - final int max = player.getMaxHandSize(); - - InputSelectCardsFromList inp = new InputSelectCardsFromList(nDiscard, nDiscard, player.getZone(ZoneType.Hand).getCards()); - String message = "Cleanup Phase\nSelect " + nDiscard + " card" + (nDiscard > 1 ? "s" : "") + - " to discard to bring your hand down to the maximum of " + max + " cards."; - inp.setMessage(message); - inp.setCancelAllowed(false); - inp.showAndWait(); - return Lists.newArrayList(inp.getSelected()); - } - - /* (non-Javadoc) - * @see forge.game.player.PlayerController#chooseCardsToRevealFromHand(int, int, java.util.List) - */ - @Override - public List chooseCardsToRevealFromHand(int min, int max, List valid) { - max = Math.min(max, valid.size()); - min = Math.min(min, max); - InputSelectCardsFromList inp = new InputSelectCardsFromList(min, max, valid); - inp.setMessage("Choose Which Cards to Reveal"); - inp.showAndWait(); - return Lists.newArrayList(inp.getSelected()); - } - - /* (non-Javadoc) - * @see forge.game.player.PlayerController#payManaOptional(forge.Card, forge.card.cost.Cost) - */ - @Override - public boolean payManaOptional(Card c, Cost cost, SpellAbility sa, String prompt, ManaPaymentPurpose purpose) { - if (sa == null && cost.isOnlyManaCost() && cost.getTotalMana().isZero() - && !FModel.getPreferences().getPrefBoolean(FPref.MATCHPREF_PROMPT_FREE_BLOCKS)) - return true; - - return HumanPlay.payCostDuringAbilityResolve(player, c, cost, sa, prompt); - } - - /* (non-Javadoc) - * @see forge.game.player.PlayerController#chooseSaToActivateFromOpeningHand(java.util.List) - */ - @Override - public List chooseSaToActivateFromOpeningHand(List usableFromOpeningHand) { - List srcCards = new ArrayList(); - for (SpellAbility sa : usableFromOpeningHand) { - srcCards.add(sa.getHostCard()); - } - List result = new ArrayList(); - if (srcCards.isEmpty()) { - return result; - } - List chosen = SGuiChoose.many("Choose cards to activate from opening hand and their order", "Activate first", -1, srcCards, null); - for (Card c : chosen) { - for (SpellAbility sa : usableFromOpeningHand) { - if (sa.getHostCard() == c) { - result.add(sa); - break; - } - } - } - return result; - } - - // end of not related candidates for move. - - /* (non-Javadoc) - * @see forge.game.player.PlayerController#chooseBinary(java.lang.String, boolean) - */ - @Override - public boolean chooseBinary(SpellAbility sa, String question, BinaryChoiceType kindOfChoice, Boolean defaultVal) { - String[] labels = new String[]{"Option1", "Option2"}; - switch(kindOfChoice) { - case HeadsOrTails: labels = new String[]{"Heads", "Tails"}; break; - case TapOrUntap: labels = new String[]{"Tap", "Untap"}; break; - case OddsOrEvens: labels = new String[]{"Odds", "Evens"}; break; - case UntapOrLeaveTapped: labels = new String[]{"Untap", "Leave tapped"}; break; - case UntapTimeVault: labels = new String[]{"Untap (and skip this turn)", "Leave tapped"}; break; - case PlayOrDraw: labels = new String[]{"Play", "Draw"}; break; - default: labels = kindOfChoice.toString().split("Or"); - - } - return SGuiDialog.confirm(getCardView(sa.getHostCard()), question, defaultVal == null || defaultVal.booleanValue(), labels); - } - - @Override - public boolean chooseFlipResult(SpellAbility sa, Player flipper, boolean[] results, boolean call) { - String[] labelsSrc = call ? new String[]{"heads", "tails"} : new String[]{"win the flip", "lose the flip"}; - String[] strResults = new String[results.length]; - for (int i = 0; i < results.length; i++) { - strResults[i] = labelsSrc[results[i] ? 0 : 1]; - } - return SGuiChoose.one(sa.getHostCard().getName() + " - Choose a result", strResults) == labelsSrc[0]; - } - - @Override - public Card chooseProtectionShield(GameEntity entityBeingDamaged, List options, Map choiceMap) { - String title = entityBeingDamaged + " - select which prevention shield to use"; - return choiceMap.get(SGuiChoose.one(title, options)); - } - - @Override - public Pair chooseAndRemoveOrPutCounter(Card cardWithCounter) { - if (!cardWithCounter.hasCounters()) { - System.out.println("chooseCounterType was reached with a card with no counters on it. Consider filtering this card out earlier"); - return null; - } - - String counterChoiceTitle = "Choose a counter type on " + cardWithCounter; - final CounterType chosen = SGuiChoose.one(counterChoiceTitle, cardWithCounter.getCounters().keySet()); - - String putOrRemoveTitle = "What to do with that '" + chosen.getName() + "' counter "; - final String putString = "Put another " + chosen.getName() + " counter on " + cardWithCounter; - final String removeString = "Remove a " + chosen.getName() + " counter from " + cardWithCounter; - final String addOrRemove = SGuiChoose.one(putOrRemoveTitle, new String[]{putString,removeString}); - - return new ImmutablePair(chosen,addOrRemove); - } - - @Override - public Pair chooseTarget(SpellAbility saSpellskite, List> allTargets) { - if (allTargets.size() < 2) { - return Iterables.getFirst(allTargets, null); - } - - final Function, String> fnToString = new Function, String>() { - @Override - public String apply(Pair targ) { - return targ.getRight().toString() + " - " + targ.getLeft().getStackDescription(); - } - }; - - List> chosen = SGuiChoose.getChoices(saSpellskite.getHostCard().getName(), 1, 1, allTargets, null, fnToString); - return Iterables.getFirst(chosen, null); - } - - @Override - public void notifyOfValue(SpellAbility sa, GameObject realtedTarget, String value) { - String message = formatNotificationMessage(sa, realtedTarget, value); - if (sa.isManaAbility()) { - game.getGameLog().add(GameLogEntryType.LAND, message); - } else { - SGuiDialog.message(message, sa.getHostCard() == null ? "" : sa.getHostCard().getName()); - } - } - - private String formatMessage(String message, Object related) { - if(related instanceof Player && message.indexOf("{player") >= 0) - message = message.replace("{player}", mayBeYou(related)).replace("{player's}", Lang.getPossesive(mayBeYou(related))); - - return message; - } - - // These are not much related to PlayerController - private String formatNotificationMessage(SpellAbility sa, GameObject target, String value) { - if (sa.getApi() == null || sa.getHostCard() == null) { - return ("Result: " + value); - } - switch(sa.getApi()) { - case ChooseDirection: - return value; - case ChooseNumber: - if (sa.hasParam("SecretlyChoose")) { - return value; - } - final boolean random = sa.hasParam("Random"); - return String.format(random ? "Randomly chosen number for %s is %s" : "%s choses number: %s", mayBeYou(target), value); - case FlipACoin: - String flipper = StringUtils.capitalize(mayBeYou(target)); - return sa.hasParam("NoCall") - ? String.format("%s flip comes up %s", Lang.getPossesive(flipper), value) - : String.format("%s %s the flip", flipper, Lang.joinVerb(flipper, value)); - case Protection: - String choser = StringUtils.capitalize(mayBeYou(target)); - return String.format("%s %s protection from %s", choser, Lang.joinVerb(choser, "choose"), value); - case Vote: - String chooser = StringUtils.capitalize(mayBeYou(target)); - return String.format("%s %s %s", chooser, Lang.joinVerb(chooser, "vote"), value); - default: - return String.format("%s effect's value for %s is %s", sa.getHostCard().getName(), mayBeYou(target), value); - } - } - - private String mayBeYou(Object what) { - return what == null ? "(null)" : what == player ? "you" : what.toString(); - } - - // end of not related candidates for move. - - /* (non-Javadoc) - * @see forge.game.player.PlayerController#chooseModeForAbility(forge.card.spellability.SpellAbility, java.util.List, int, int) - */ - @Override - public List chooseModeForAbility(SpellAbility sa, int min, int num) { - List choices = CharmEffect.makePossibleOptions(sa); - String modeTitle = String.format("%s activated %s - Choose a mode", sa.getActivatingPlayer(), sa.getHostCard()); - List chosen = new ArrayList(); - for (int i = 0; i < num; i++) { - AbilitySub a; - if (i < min) { - a = SGuiChoose.one(modeTitle, choices); - } - else { - a = SGuiChoose.oneOrNone(modeTitle, choices); - } - if (null == a) { - break; - } - - choices.remove(a); - chosen.add(a); - } - return chosen; - } - - @Override - public List chooseColors(String message, SpellAbility sa, int min, int max, List options) { - return SGuiChoose.getChoices(message, min, max, options); - } - - @Override - public byte chooseColor(String message, SpellAbility sa, ColorSet colors) { - int cntColors = colors.countColors(); - switch (cntColors) { - case 0: return 0; - case 1: return colors.getColor(); - default: return chooseColorCommon(message, sa == null ? null : sa.getHostCard(), colors, false); - } - } - - @Override - public byte chooseColorAllowColorless(String message, Card c, ColorSet colors) { - int cntColors = 1 + colors.countColors(); - switch (cntColors) { - case 1: return 0; - default: return chooseColorCommon(message, c, colors, true); - } - } - - private byte chooseColorCommon(String message, Card c, ColorSet colors, boolean withColorless) { - int cntColors = colors.countColors(); - if(withColorless) cntColors++; - String[] colorNames = new String[cntColors]; - int i = 0; - if(withColorless) - colorNames[i++] = MagicColor.toLongString((byte)0); - for (byte b : colors) { - colorNames[i++] = MagicColor.toLongString(b); - } - if (colorNames.length > 2) { - return MagicColor.fromName(SGuiChoose.one(message, colorNames)); - } - int idxChosen = SGuiDialog.confirm(getCardView(c), message, colorNames) ? 0 : 1; - return MagicColor.fromName(colorNames[idxChosen]); - } - - @Override - public PaperCard chooseSinglePaperCard(SpellAbility sa, String message, Predicate cpp, String name) { - Iterable cardsFromDb = FModel.getMagicDb().getCommonCards().getUniqueCards(); - List cards = Lists.newArrayList(Iterables.filter(cardsFromDb, cpp)); - Collections.sort(cards); - return SGuiChoose.one(message, cards); - } - - @Override - public CounterType chooseCounterType(Collection options, SpellAbility sa, String prompt) { - if (options.size() <= 1) { - return Iterables.getFirst(options, null); - } - return SGuiChoose.one(prompt, options); - } - - @Override - public boolean confirmPayment(CostPart costPart, String question) { - InputConfirm inp = new InputConfirm(question); - inp.showAndWait(); - return inp.getResult(); - } - - @Override - public ReplacementEffect chooseSingleReplacementEffect(String prompt, List possibleReplacers, HashMap runParams) { - if(possibleReplacers.size() == 1) - return possibleReplacers.get(0); - return SGuiChoose.one(prompt, possibleReplacers); - } - - @Override - public String chooseProtectionType(String string, SpellAbility sa, List choices) { - return SGuiChoose.one(string, choices); - } - - @Override - public boolean payCostToPreventEffect(Cost cost, SpellAbility sa, boolean alreadyPaid, List allPayers) { - // if it's paid by the AI already the human can pay, but it won't change anything - return HumanPlay.payCostDuringAbilityResolve(player, sa.getHostCard(), cost, sa, null); - } - - @Override - public void orderAndPlaySimultaneousSa(List activePlayerSAs) { - List orderedSAs = activePlayerSAs; - if (activePlayerSAs.size() > 1) { // give a dual list form to create instead of needing to do it one at a time - orderedSAs = SGuiChoose.order("Select order for Simultaneous Spell Abilities", "Resolve first", activePlayerSAs, null); - } - int size = orderedSAs.size(); - for (int i = size - 1; i >= 0; i--) { - SpellAbility next = orderedSAs.get(i); - if (next.isTrigger()) { - HumanPlay.playSpellAbility(player, next); - } else { - player.getGame().getStack().add(next); - } - } - } - - @Override - public void playTrigger(Card host, WrappedAbility wrapperAbility, boolean isMandatory) { - HumanPlay.playSpellAbilityNoStack(player, wrapperAbility); - } - - @Override - public boolean playSaFromPlayEffect(SpellAbility tgtSA) { - HumanPlay.playSpellAbility(player, tgtSA); - return true; - } - - @Override - public Map chooseProliferation() { - InputProliferate inp = new InputProliferate(); - inp.setCancelAllowed(true); - inp.showAndWait(); - if (inp.hasCancelled()) { - return null; - } - return inp.getProliferationMap(); - } - - @Override - public boolean chooseTargetsFor(SpellAbility currentAbility) { - final TargetSelection select = new TargetSelection(currentAbility); - return select.chooseTargets(null); - } - - @Override - public boolean chooseCardsPile(SpellAbility sa, List pile1, List pile2, boolean faceUp) { - if (!faceUp) { - final String p1Str = String.format("Pile 1 (%s cards)", pile1.size()); - final String p2Str = String.format("Pile 2 (%s cards)", pile2.size()); - final String[] possibleValues = { p1Str , p2Str }; - return SGuiDialog.confirm(getCardView(sa.getHostCard()), "Choose a Pile", possibleValues); - } else { - final Card[] disp = new Card[pile1.size() + pile2.size() + 2]; - disp[0] = new Card(-1); - disp[0].setName("Pile 1"); - for (int i = 0; i < pile1.size(); i++) { - disp[1 + i] = pile1.get(i); - } - disp[pile1.size() + 1] = new Card(-2); - disp[pile1.size() + 1].setName("Pile 2"); - for (int i = 0; i < pile2.size(); i++) { - disp[pile1.size() + i + 2] = pile2.get(i); - } - - // make sure Pile 1 or Pile 2 is clicked on - while (true) { - final Object o = SGuiChoose.one("Choose a pile", disp); - final Card c = (Card) o; - String name = c.getName(); - - if (!(name.equals("Pile 1") || name.equals("Pile 2"))) { - continue; - } - - return name.equals("Pile 1"); - } - } - } - - @Override - public void revealAnte(String message, Multimap removedAnteCards) { - for (Player p : removedAnteCards.keySet()) { - SGuiChoose.reveal(message + " from " + Lang.getPossessedObject(mayBeYou(p), "deck"), removedAnteCards.get(p)); - } - } - - @Override - public CardShields chooseRegenerationShield(Card c) { - if (c.getShield().size() < 2) { - return Iterables.getFirst(c.getShield(), null); - } - return SGuiChoose.one("Choose a regeneration shield:", c.getShield()); - } - - @Override - public List chooseCardsYouWonToAddToDeck(List losses) { - return SGuiChoose.many("Select cards to add to your deck", "Add these to my deck", 0, losses.size(), losses, null); - } - - @Override - public boolean payManaCost(ManaCost toPay, CostPartMana costPartMana, SpellAbility sa, String prompt, boolean isActivatedSa) { - return HumanPlay.payManaCost(toPay, costPartMana, sa, player, prompt, isActivatedSa); - } - - @Override - public Map chooseCardsForConvoke(SpellAbility sa, ManaCost manaCost, List untappedCreats) { - InputSelectCardsForConvoke inp = new InputSelectCardsForConvoke(player, manaCost, untappedCreats); - inp.showAndWait(); - return inp.getConvokeMap(); - } - - @Override - public String chooseCardName(SpellAbility sa, Predicate cpp, String valid, String message) { - PaperCard cp = null; - while(true) { - cp = chooseSinglePaperCard(sa, message, cpp, sa.getHostCard().getName()); - Card instanceForPlayer = Card.fromPaperCard(cp, player); // the Card instance for test needs a game to be tested - if (instanceForPlayer.isValid(valid, sa.getHostCard().getController(), sa.getHostCard())) - return cp.getName(); - } - } - - @Override - public Card chooseSingleCardForZoneChange(ZoneType destination, List origin, SpellAbility sa, List fetchList, String selectPrompt, boolean b, Player decider) { - return chooseSingleEntityForEffect(fetchList, sa, selectPrompt, b, decider); - } - - public boolean isGuiPlayer() { - return lobbyPlayer == GuiBase.getInterface().getGuiPlayer(); - } +package forge.player; - /* - * What follows are the View methods. - */ - - /** Cache of players. */ - private final BiMap players - = HashBiMap.create(); - /** Cache of cards. */ - private final BiMap cards - = HashBiMap.create(); - /** Cache of stack items. */ - private final BiMap stackItems - = HashBiMap.create(); - /** Combat view. */ - private final CombatView combatView = new CombatView(); - - /* (non-Javadoc) - * @see forge.view.IGameView#isCommander() - */ - @Override - public boolean isCommander() { - return game.getRules().hasAppliedVariant(GameType.Commander); - } - /* (non-Javadoc) - * @see forge.view.IGameView#getGameType() - */ - @Override - public GameType getGameType() { - return this.game.getMatch().getRules().getGameType(); - } - - @Override - public int getTurnNumber() { - return this.game.getPhaseHandler().getTurn(); - } - - @Override - public boolean isCommandZoneNeeded() { - return this.game.getMatch().getRules().getGameType().isCommandZoneNeeded(); - } - - @Override - public boolean isWinner(final LobbyPlayer p) { - return game.getOutcome() == null ? null : game.getOutcome().isWinner(p); - } - - @Override - public LobbyPlayer getWinningPlayer() { - return game.getOutcome() == null ? null : game.getOutcome().getWinningLobbyPlayer(); - } - - @Override - public int getWinningTeam() { - return game.getOutcome() == null ? -1 : game.getOutcome().getWinningTeam(); - } - - /* (non-Javadoc) - * @see forge.view.IGameView#isFirstGameInMatch() - */ - @Override - public boolean isFirstGameInMatch() { - return this.game.getMatch().getPlayedGames().isEmpty(); - } - - @Override - public boolean isMatchOver() { - return this.game.getMatch().isMatchOver(); - } - - @Override - public int getNumGamesInMatch() { - return this.game.getMatch().getRules().getGamesPerMatch(); - } - - @Override - public int getNumPlayedGamesInMatch() { - return this.game.getMatch().getPlayedGames().size(); - } - - @Override - public boolean isMatchWonBy(final LobbyPlayer p) { - return this.game.getMatch().isWonBy(p); - } - - @Override - public int getGamesWonBy(LobbyPlayer p) { - return this.game.getMatch().getGamesWonBy(p); - } - - @Override - public GameOutcome.AnteResult getAnteResult() { - return this.game.getOutcome().anteResult.get(player); - } - - /* (non-Javadoc) - * @see forge.view.IGameView#isCombatDeclareAttackers() - */ - @Override - public boolean isCombatDeclareAttackers() { - return game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_ATTACKERS) - && game.getCombat() != null; - } - - /* (non-Javadoc) - * @see forge.view.IGameView#isGameOver() - */ - @Override - public boolean isGameOver() { - return game.isGameOver(); - } - - @Override - public int getPoisonCountersToLose() { - return game.getRules().getPoisonCountersToLose(); - } - - /* (non-Javadoc) - * @see forge.view.IGameView#subscribeToEvents(java.lang.Object) - */ - @Override - public void subscribeToEvents(final Object subscriber) { - game.subscribeToEvents(subscriber); - } - - /* (non-Javadoc) - * @see forge.view.IGameView#getCombat() - */ - @Override - public CombatView getCombat() { - updateCombatView(game.getCombat()); - return combatView; - } - - private final void updateCombatView(final Combat combat) { - combatView.reset(); - for (final AttackingBand b : combat.getAttackingBands()) { - final GameEntity defender = combat.getDefenderByAttacker(b); - final List blockers = b.isBlocked() ? combat.getBlockers(b) : null; - combatView.addAttackingBand(getCardViews(b.getAttackers()), getGameEntityView(defender), getCardViews(blockers)); - } - } - - @Override - public void addLogObserver(final Observer o) { - game.getGameLog().addObserver(o); - } - - @Override - public List getLogEntries(final GameLogEntryType maxLogLevel) { - return game.getGameLog().getLogEntries(maxLogLevel); - } - - @Override - public List getLogEntriesExact(final GameLogEntryType logLevel) { - return game.getGameLog().getLogEntriesExact(logLevel); - } - - /* (non-Javadoc) - * @see forge.view.IGameView#getGuiRegisteredPlayer(forge.LobbyPlayer) - */ - @Override - public RegisteredPlayer getGuiRegisteredPlayer(final LobbyPlayer p) { - for (final RegisteredPlayer player : game.getMatch().getPlayers()) { - if (player.getPlayer() == p) { - return player; - } - } - return null; - } - - /* (non-Javadoc) - * @see forge.view.IGameView#getRegisteredPlayers() - */ - @Override - public List getPlayers() { - return Lists.transform(game.getRegisteredPlayers(), FN_GET_PLAYER_VIEW); - } - - @Override - public PlayerView getPlayerTurn() { - return getPlayerView(game.getPhaseHandler().getPlayerTurn()); - } - - @Override - public PhaseType getPhase() { - return game.getPhaseHandler().getPhase(); - } - - /* (non-Javadoc) - * @see forge.view.IGameView#getStack() - */ - @Override - public List getStack() { - final List items = Collections.unmodifiableList(getStack(game.getStack())); - // clear the cache - stackItems.keySet().retainAll(items); - return items; - } - - /* (non-Javadoc) - * @see forge.view.IGameView#peekStack() - */ - @Override - public StackItemView peekStack() { - final SpellAbilityStackInstance top = - Iterables.getFirst(game.getStack(), null); - if (top == null) { - return null; - } - return getStack(Lists.newArrayList(top)).iterator().next(); - } - - private List getStack(final Iterable stack) { - final List items = Lists.newLinkedList(); - for (final SpellAbilityStackInstance si : stack) { - if (stackItems.containsKey(si)) { - items.add(stackItems.get(si)); - } else { - final StackItemView newItem = new StackItemView( - si.getSpellAbility().toUnsuppressedString(), - si.getSpellAbility().getSourceTrigger(), - si.getStackDescription(), getCardView(si.getSourceCard()), - getPlayerView(si.getActivator()), si.isAbility(), - si.isOptionalTrigger()); - items.add(newItem); - stackItems.put(si, newItem); - } - } - return items; - } - - private GameEntityView getGameEntityView(final GameEntity e) { - if (e instanceof Card) { - return getCardView((Card)e); - } else if (e instanceof Player) { - return getPlayerView((Player)e); - } - return null; - } - - private PlayerView getPlayerView(final Player p) { - if (p == null) { - return null; - } - - final PlayerView view; - if (players.containsKey(p)) { - view = players.get(p); - getPlayerView(p, view); - } else { - view = new PlayerView(p.getLobbyPlayer(), p.getController()); - getPlayerView(p, view); - players.put(p, view); - } - return view; - } - - private final Function FN_GET_PLAYER_VIEW = new Function() { - @Override - public PlayerView apply(final Player input) { - return getPlayerView(input); - } - }; - - private Player getPlayer(final PlayerView p) { - return players.inverse().get(p); - } - - private void getPlayerView(final Player p, final PlayerView view) { - view.setCommanderInfo(CardFactoryUtil.getCommanderInfo(p).trim().replace("\r\n", "; ")); - view.setKeywords(p.getKeywords()); - view.setLife(p.getLife()); - view.setMaxHandSize(p.getMaxHandSize()); - view.setNumDrawnThisTurn(p.getNumDrawnThisTurn()); - view.setPoisonCounters(p.getPoisonCounters()); - view.setPreventNextDamage(p.getPreventNextDamageTotalShields()); - view.setHasUnlimitedHandSize(p.isUnlimitedHandSize()); - view.setAnteCards(getCardViews(p.getCardsIn(ZoneType.Ante))); - view.setBfCards(getCardViews(p.getCardsIn(ZoneType.Battlefield))); - view.setExileCards(getCardViews(p.getCardsIn(ZoneType.Exile))); - view.setFlashbackCards(getCardViews(p.getCardsActivableInExternalZones(false))); - view.setGraveCards(getCardViews(p.getCardsIn(ZoneType.Graveyard))); - view.setHandCards(getCardViews(p.getCardsIn(ZoneType.Hand))); - view.setLibraryCards(getCardViews(p.getCardsIn(ZoneType.Library))); - } - - private CardView getCardView(final Card c) { - if (c == null) { - return null; - } - - final Card cUi = c.getCardForUi(); - final CardView view; - if (cards.containsKey(cUi)) { - view = cards.get(cUi); - writeCardToView(cUi, view); - } else { - view = new CardView(cUi, cUi.getUniqueNumber(), cUi == c); - writeCardToView(cUi, view); - cards.put(cUi, view); - } - return view; - } - - private final Function FN_GET_CARD_VIEW = new Function() { - @Override - public CardView apply(final Card input) { - return getCardView(input); - } - }; - - private List getCardViews(final List cards) { - return Lists.transform(cards, FN_GET_CARD_VIEW); - } - - private Card getCard(final CardView c) { - return cards.inverse().get(c); - } - - private final Function FN_GET_CARD = new Function() { - @Override - public Card apply(final CardView input) { - return getCard(input); - } - }; - - private List getCards(final List cards) { - return Lists.transform(cards, FN_GET_CARD); - } - - private void writeCardToView(final Card c, final CardView view) { - if (!c.canBeShownTo(player)) { - view.getOriginal().reset(); - view.getAlternate().reset(); - return; - } - - // First, write the values independent of other views. - ViewUtil.writeNonDependentCardViewProperties(c, view); - // Next, write the values that depend on other views. - view.setOwner(getPlayerView(c.getOwner())); - view.setController(getPlayerView(c.getController())); - view.setAttacking(game.getCombat() != null && game.getCombat().isAttacking(c)); - view.setBlocking(game.getCombat() != null && game.getCombat().isBlocking(c)); - view.setChosenPlayer(getPlayerView(c.getChosenPlayer())); - view.setEquipping(getCardView(Iterables.getFirst(c.getEquipping(), null))); - view.setEquippedBy(getCardViews(c.getEquippedBy())); - view.setEnchantingCard(getCardView(c.getEnchantingCard())); - view.setEnchantingPlayer(getPlayerView(c.getEnchantingPlayer())); - view.setEnchantedBy(getCardViews(c.getEnchantedBy())); - view.setFortifiedBy(getCardViews(c.getFortifiedBy())); - view.setGainControlTargets(getCardViews(c.getGainControlTargets())); - view.setCloneOrigin(getCardView(c.getCloneOrigin())); - view.setImprinted(getCardViews(c.getImprinted())); - view.setHauntedBy(getCardViews(c.getHauntedBy())); - view.setHaunting(getCardView(c.getHaunting())); - view.setMustBlock(c.getMustBlockCards() == null ? Collections.emptySet() : Iterables.transform(c.getMustBlockCards(), FN_GET_CARD_VIEW)); - view.setPairedWith(getCardView(c.getPairedWith())); - } - - @Override - public boolean mayShowCard(final CardView c) { - return cards.inverse().get(c).canBeShownTo(player); - } - - @Override - public boolean getDisableAutoYields() { - return this.game.getDisableAutoYields(); - } - @Override - public void setDisableAutoYields(final boolean b) { - this.game.setDisableAutoYields(b); - } - - // Dev mode functions - @Override - public void devTogglePlayManyLands(final boolean b) { - player.canCheatPlayUnlimitedLands = b; - } - @Override - public void devGenerateMana() { - DevModeUtil.devModeGenerateMana(game); - } - @Override - public void devSetupGameState() { - DevModeUtil.devSetupGameState(game); - } - @Override - public void devTutorForCard() { - DevModeUtil.devModeTutor(game); - } - @Override - public void devAddCardToHand() { - DevModeUtil.devModeCardToHand(game); - } - @Override - public void devAddCounterToPermanent() { - DevModeUtil.devModeAddCounter(game); - } - @Override - public void devTapPermanent() { - DevModeUtil.devModeTapPerm(game); - } - @Override - public void devUntapPermanent() { - DevModeUtil.devModeUntapPerm(game); - } - @Override - public void devSetPlayerLife() { - DevModeUtil.devModeSetLife(game); - } - @Override - public void devWinGame() { - DevModeUtil.devModeWinGame(game, player.getLobbyPlayer()); - } - @Override - public void devAddCardToBattlefield() { - DevModeUtil.devModeCardToBattlefield(game); - } - @Override - public void devRiggedPlanerRoll() { - DevModeUtil.devModeRiggedPlanarRoll(game); - } - @Override - public void devPlaneswalkTo() { - DevModeUtil.devModeRiggedPlanarRoll(game); +import java.util.List; + +import com.google.common.base.Function; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; + +import forge.LobbyPlayer; +import forge.game.Game; +import forge.game.GameEntity; +import forge.game.card.Card; +import forge.game.combat.Combat; +import forge.game.player.Player; +import forge.game.player.PlayerController; +import forge.game.spellability.SpellAbility; +import forge.game.spellability.SpellAbilityStackInstance; +import forge.interfaces.IGuiBase; +import forge.view.CardView; +import forge.view.CombatView; +import forge.view.GameEntityView; +import forge.view.PlayerView; +import forge.view.SpellAbilityView; +import forge.view.StackItemView; + +public abstract class PlayerControllerHuman extends PlayerController { + + private final IGuiBase gui; + + public PlayerControllerHuman(final Game game0, final Player p, final LobbyPlayer lp, final IGuiBase gui) { + super(game0, p, lp); + this.gui = gui; } -} + + public final IGuiBase getGui() { + return this.gui; + } + + public abstract boolean canUndoLastAction(); + public abstract boolean tryUndoLastAction(); + + public abstract CardView getCardView(Card c); + + private final Function FN_GET_CARD_VIEW = new Function() { + @Override + public CardView apply(final Card input) { + return getCardView(input); + } + }; + + public final List getCardViews(final List cards) { + return Lists.transform(cards, FN_GET_CARD_VIEW); + } + public final Iterable getCardViews(final Iterable cards) { + return Iterables.transform(cards, FN_GET_CARD_VIEW); + } + public abstract Card getCard(CardView c); + + private final Function FN_GET_CARD = new Function() { + @Override + public Card apply(final CardView input) { + return getCard(input); + } + }; + + protected final List getCards(final List cards) { + return Lists.transform(cards, FN_GET_CARD); + } + + public final GameEntityView getGameEntityView(final GameEntity e) { + if (e instanceof Card) { + return getCardView((Card)e); + } else if (e instanceof Player) { + return getPlayerView((Player)e); + } + return null; + } + + public abstract PlayerView getPlayerView(Player p); + + private final Function FN_GET_PLAYER_VIEW = new Function() { + @Override + public PlayerView apply(final Player input) { + return getPlayerView(input); + } + }; + + public final List getPlayerViews(final List players) { + return Lists.transform(players, FN_GET_PLAYER_VIEW); + } + + public abstract Player getPlayer(PlayerView p); + + public abstract SpellAbilityView getSpellAbilityView(SpellAbility sa); + + private final Function FN_GET_SPAB_VIEW = new Function() { + @Override + public SpellAbilityView apply(final SpellAbility input) { + return getSpellAbilityView(input); + } + }; + + public final List getSpellAbilityViews(final List cards) { + return Lists.transform(cards, FN_GET_SPAB_VIEW); + } + + public abstract SpellAbility getSpellAbility(SpellAbilityView c); + + private final Function FN_GET_SPAB = new Function() { + @Override + public SpellAbility apply(final SpellAbilityView input) { + return getSpellAbility(input); + } + }; + + public final List getSpellAbilities(final List cards) { + return Lists.transform(cards, FN_GET_SPAB); + } + + public final CombatView getCombat() { + return getCombat(game.getCombat()); + } + public abstract CombatView getCombat(Combat c); + + public abstract StackItemView getStackItemView(SpellAbilityStackInstance si); + public abstract SpellAbilityStackInstance getStackItem(StackItemView view); +} diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerLocal.java b/forge-gui/src/main/java/forge/player/PlayerControllerLocal.java new file mode 100644 index 00000000000..efeb0c19e41 --- /dev/null +++ b/forge-gui/src/main/java/forge/player/PlayerControllerLocal.java @@ -0,0 +1,1685 @@ +package forge.player; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Observer; + +import org.apache.commons.lang3.Range; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; + +import forge.LobbyPlayer; +import forge.card.ColorSet; +import forge.card.MagicColor; +import forge.card.mana.ManaCost; +import forge.card.mana.ManaCostShard; +import forge.control.FControlGamePlayback; +import forge.deck.CardPool; +import forge.deck.Deck; +import forge.deck.DeckSection; +import forge.events.UiEventAttackerDeclared; +import forge.game.Game; +import forge.game.GameEntity; +import forge.game.GameLogEntry; +import forge.game.GameLogEntryType; +import forge.game.GameObject; +import forge.game.GameOutcome; +import forge.game.GameType; +import forge.game.ability.effects.CharmEffect; +import forge.game.card.Card; +import forge.game.card.CardFactoryUtil; +import forge.game.card.CardShields; +import forge.game.card.CounterType; +import forge.game.combat.AttackingBand; +import forge.game.combat.Combat; +import forge.game.combat.CombatUtil; +import forge.game.cost.Cost; +import forge.game.cost.CostPart; +import forge.game.cost.CostPartMana; +import forge.game.mana.Mana; +import forge.game.phase.PhaseType; +import forge.game.player.Player; +import forge.game.player.PlayerActionConfirmMode; +import forge.game.player.RegisteredPlayer; +import forge.game.replacement.ReplacementEffect; +import forge.game.spellability.AbilitySub; +import forge.game.spellability.SpellAbility; +import forge.game.spellability.SpellAbilityStackInstance; +import forge.game.spellability.TargetChoices; +import forge.game.trigger.Trigger; +import forge.game.trigger.WrappedAbility; +import forge.game.zone.MagicStack; +import forge.game.zone.Zone; +import forge.game.zone.ZoneType; +import forge.interfaces.IGuiBase; +import forge.item.PaperCard; +import forge.match.input.ButtonUtil; +import forge.match.input.Input; +import forge.match.input.InputAttack; +import forge.match.input.InputBase; +import forge.match.input.InputBlock; +import forge.match.input.InputConfirm; +import forge.match.input.InputConfirmMulligan; +import forge.match.input.InputPassPriority; +import forge.match.input.InputProliferate; +import forge.match.input.InputSelectCardsForConvoke; +import forge.match.input.InputSelectCardsFromList; +import forge.match.input.InputSelectEntitiesFromList; +import forge.model.FModel; +import forge.properties.ForgePreferences.FPref; +import forge.util.DevModeUtil; +import forge.util.ITriggerEvent; +import forge.util.Lang; +import forge.util.TextUtil; +import forge.util.gui.SGuiChoose; +import forge.util.gui.SGuiDialog; +import forge.util.gui.SOptionPane; +import forge.view.CardView; +import forge.view.CombatView; +import forge.view.GameEntityView; +import forge.view.IGameView; +import forge.view.PlayerView; +import forge.view.SpellAbilityView; +import forge.view.StackItemView; +import forge.view.ViewUtil; + +/** + * A prototype for player controller class + * + * Handles phase skips for now. + */ +public class PlayerControllerLocal extends PlayerControllerHuman implements IGameView { + public PlayerControllerLocal(final Game game0, final Player p, final LobbyPlayer lp, final IGuiBase gui) { + super(game0, p, lp, gui); + // aggressively cache a view for each player + for (final Player player : game.getRegisteredPlayers()) { + getPlayerView(player); + } + // aggressively cache a view for each card + for (final Card c : game.getCardsInGame()) { + getCardView(c); + } + } + + public boolean isUiSetToSkipPhase(final Player turn, final PhaseType phase) { + return !getGui().stopAtPhase(getPlayerView(turn), phase); + } + + /** + * Uses GUI to learn which spell the player (human in our case) would like to play + */ + public SpellAbility getAbilityToPlay(final List abilities, final ITriggerEvent triggerEvent) { + final SpellAbilityView choice = getGui().getAbilityToPlay(getSpellAbilityViews(abilities), triggerEvent); + return getSpellAbility(choice); + } + + /* (non-Javadoc) + * @see forge.game.player.PlayerController#mayPlaySpellAbilityForFree(forge.card.spellability.SpellAbility) + */ + @Override + public void playSpellAbilityForFree(SpellAbility copySA, boolean mayChoseNewTargets) { + HumanPlay.playSaWithoutPayingManaCost(this, player.getGame(), copySA, mayChoseNewTargets); + } + + @Override + public void playSpellAbilityNoStack(SpellAbility effectSA, boolean canSetupTargets) { + HumanPlay.playSpellAbilityNoStack(this, player, effectSA, !canSetupTargets); + } + + /* (non-Javadoc) + * @see forge.game.player.PlayerController#sideboard(forge.deck.Deck) + */ + @Override + public List sideboard(Deck deck, GameType gameType) { + CardPool sideboard = deck.get(DeckSection.Sideboard); + if (sideboard == null) { + // Use an empty cardpool instead of null for 75/0 sideboarding scenario. + sideboard = new CardPool(); + } + + CardPool main = deck.get(DeckSection.Main); + + int mainSize = main.countAll(); + int sbSize = sideboard.countAll(); + int combinedDeckSize = mainSize + sbSize; + + int deckMinSize = Math.min(mainSize, gameType.getDeckFormat().getMainRange().getMinimum()); + Range sbRange = gameType.getDeckFormat().getSideRange(); + // Limited doesn't have a sideboard max, so let the Main min take care of things. + int sbMax = sbRange == null ? combinedDeckSize : sbRange.getMaximum(); + + List newMain = null; + + //Skip sideboard loop if there are no sideboarding opportunities + if (sbSize == 0 && mainSize == deckMinSize) { return null; } + + // conformance should not be checked here + boolean conform = FModel.getPreferences().getPrefBoolean(FPref.ENFORCE_DECK_LEGALITY); + do { + if (newMain != null) { + String errMsg; + if (newMain.size() < deckMinSize) { + errMsg = String.format("Too few cards in your main deck (minimum %d), please make modifications to your deck again.", deckMinSize); + } + else { + errMsg = String.format("Too many cards in your sideboard (maximum %d), please make modifications to your deck again.", sbMax); + } + SOptionPane.showErrorDialog(getGui(), errMsg, "Invalid Deck"); + } + // Sideboard rules have changed for M14, just need to consider min maindeck and max sideboard sizes + // No longer need 1:1 sideboarding in non-limited formats + newMain = getGui().sideboard(sideboard, main); + } while (conform && (newMain.size() < deckMinSize || combinedDeckSize - newMain.size() > sbMax)); + + return newMain; + } + + /* (non-Javadoc) + * @see forge.game.player.PlayerController#assignCombatDamage() + */ + @Override + public Map assignCombatDamage(final Card attacker, + final List blockers, final int damageDealt, + final GameEntity defender, final boolean overrideOrder) { + // Attacker is a poor name here, since the creature assigning damage + // could just as easily be the blocker. + final Map map = Maps.newHashMap(); + if (defender != null && assignDamageAsIfNotBlocked(attacker)) { + map.put(null, damageDealt); + } else { + final List vBlockers = getCardViews(blockers); + if ((attacker.hasKeyword("Trample") && defender != null) || (blockers.size() > 1)) { + final CardView vAttacker = getCardView(attacker); + final GameEntityView vDefender = getGameEntityView(defender); + final Map result = getGui().getDamageToAssign(vAttacker, vBlockers, damageDealt, vDefender, overrideOrder); + for (final Entry e : result.entrySet()) { + map.put(getCard(e.getKey()), e.getValue()); + } + } else { + map.put(blockers.get(0), damageDealt); + } + } + return map; + } + + private final boolean assignDamageAsIfNotBlocked(final Card attacker) { + return attacker.hasKeyword("CARDNAME assigns its combat damage as though it weren't blocked.") + || (attacker.hasKeyword("You may have CARDNAME assign its combat damage as though it weren't blocked.") + && SGuiDialog.confirm(getGui(), getCardView(attacker), "Do you want to assign its combat damage as though it weren't blocked?")); + } + + /* (non-Javadoc) + * @see forge.game.player.PlayerController#announceRequirements(java.lang.String) + */ + @Override + public Integer announceRequirements(SpellAbility ability, String announce, boolean canChooseZero) { + int min = canChooseZero ? 0 : 1; + return SGuiChoose.getInteger(getGui(), "Choose " + announce + " for " + ability.getHostCard().getName(), + min, Integer.MAX_VALUE, min + 9); + } + + @Override + public List choosePermanentsToSacrifice(SpellAbility sa, int min, int max, List valid, String message) { + String outerMessage = "Select %d " + message + "(s) to sacrifice"; + return choosePermanentsTo(min, max, valid, outerMessage); + } + + @Override + public List choosePermanentsToDestroy(SpellAbility sa, int min, int max, List valid, String message) { + String outerMessage = "Select %d " + message + "(s) to be destroyed"; + return choosePermanentsTo(min, max, valid, outerMessage); + } + + private List choosePermanentsTo(int min, int max, List valid, String outerMessage) { + max = Math.min(max, valid.size()); + if (max <= 0) { + return new ArrayList(); + } + + InputSelectCardsFromList inp = new InputSelectCardsFromList(this, min == 0 ? 1 : min, max, valid); + inp.setMessage(outerMessage); + inp.setCancelAllowed(min == 0); + inp.showAndWait(); + return Lists.newArrayList(inp.getSelected()); + } + + + /* (non-Javadoc) + * @see forge.game.player.PlayerController#chooseCardsForEffect(java.util.Collection, forge.card.spellability.SpellAbility, java.lang.String, int, boolean) + */ + @Override + public List chooseCardsForEffect(List sourceList, SpellAbility sa, String title, int min, int max, boolean isOptional) { + // If only one card to choose, use a dialog box. + // Otherwise, use the order dialog to be able to grab multiple cards in one shot + if (max == 1) { + Card singleChosen = chooseSingleEntityForEffect(sourceList, sa, title, isOptional); + return singleChosen == null ? Lists.newArrayList() : Lists.newArrayList(singleChosen); + } + + getGui().setPanelSelection(getCardView(sa.getHostCard())); + + // try to use InputSelectCardsFromList when possible + boolean cardsAreInMyHandOrBattlefield = true; + for(Card c : sourceList) { + Zone z = c.getZone(); + if (z != null && (z.is(ZoneType.Battlefield) || z.is(ZoneType.Hand, player))) + continue; + cardsAreInMyHandOrBattlefield = false; + break; + } + + if(cardsAreInMyHandOrBattlefield) { + InputSelectCardsFromList sc = new InputSelectCardsFromList(this, min, max, sourceList); + sc.setMessage(title); + sc.setCancelAllowed(isOptional); + sc.showAndWait(); + return Lists.newArrayList(sc.getSelected()); + } + + return SGuiChoose.many(getGui(), title, "Chosen Cards", min, max, sourceList, getCardView(sa.getHostCard())); + } + + @Override + public T chooseSingleEntityForEffect(Collection options, SpellAbility sa, String title, boolean isOptional, Player targetedPlayer) { + // Human is supposed to read the message and understand from it what to choose + if (options.isEmpty()) { + return null; + } + if (!isOptional && options.size() == 1) { + return Iterables.getFirst(options, null); + } + + boolean canUseSelectCardsInput = true; + for (GameEntity c : options) { + if (c instanceof Player) + continue; + Zone cz = ((Card)c).getZone(); + // can point at cards in own hand and anyone's battlefield + boolean canUiPointAtCards = cz != null && (cz.is(ZoneType.Hand) && cz.getPlayer() == player || cz.is(ZoneType.Battlefield)); + if (!canUiPointAtCards) { + canUseSelectCardsInput = false; + break; + } + } + + if (canUseSelectCardsInput) { + InputSelectEntitiesFromList input = new InputSelectEntitiesFromList(this, isOptional ? 0 : 1, 1, options); + input.setCancelAllowed(isOptional); + input.setMessage(formatMessage(title, targetedPlayer)); + input.showAndWait(); + return Iterables.getFirst(input.getSelected(), null); + } + + return isOptional ? SGuiChoose.oneOrNone(getGui(), title, options) : SGuiChoose.one(getGui(), title, options); + } + + @Override + public int chooseNumber(SpellAbility sa, String title, int min, int max) { + final Integer[] choices = new Integer[max + 1 - min]; + for (int i = 0; i <= max - min; i++) { + choices[i] = Integer.valueOf(i + min); + } + return SGuiChoose.one(getGui(), title, choices).intValue(); + } + + @Override + public int chooseNumber(SpellAbility sa, String title, List choices, Player relatedPlayer) { + return SGuiChoose.one(getGui(), title, choices).intValue(); + } + + @Override + public SpellAbility chooseSingleSpellForEffect(java.util.List spells, SpellAbility sa, String title) { + // Human is supposed to read the message and understand from it what to choose + return spells.size() < 2 ? spells.get(0) : SGuiChoose.one(getGui(), title, spells); + } + + /* (non-Javadoc) + * @see forge.game.player.PlayerController#confirmAction(forge.card.spellability.SpellAbility, java.lang.String, java.lang.String) + */ + @Override + public boolean confirmAction(SpellAbility sa, PlayerActionConfirmMode mode, String message) { + return SGuiDialog.confirm(getGui(), getCardView(sa.getHostCard()), message); + } + + @Override + public boolean confirmBidAction(SpellAbility sa, PlayerActionConfirmMode bidlife, + String string, int bid, Player winner) { + return SGuiDialog.confirm(getGui(), getCardView(sa.getHostCard()), string + " Highest Bidder " + winner); + } + + @Override + public boolean confirmStaticApplication(Card hostCard, GameEntity affected, String logic, String message) { + return SGuiDialog.confirm(getGui(), getCardView(hostCard), message); + } + + @Override + public boolean confirmTrigger(SpellAbility sa, Trigger regtrig, Map triggerParams, boolean isMandatory) { + if (this.shouldAlwaysAcceptTrigger(regtrig.getId())) { + return true; + } + if (this.shouldAlwaysDeclineTrigger(regtrig.getId())) { + return false; + } + + final StringBuilder buildQuestion = new StringBuilder("Use triggered ability of "); + buildQuestion.append(regtrig.getHostCard().toString()).append("?"); + if (!FModel.getPreferences().getPrefBoolean(FPref.UI_COMPACT_PROMPT)) { + //append trigger description unless prompt is compact + buildQuestion.append("\n("); + buildQuestion.append(triggerParams.get("TriggerDescription").replace("CARDNAME", regtrig.getHostCard().getName())); + buildQuestion.append(")"); + } + HashMap tos = sa.getTriggeringObjects(); + if (tos.containsKey("Attacker")) { + buildQuestion.append("\nAttacker: " + tos.get("Attacker")); + } + if (tos.containsKey("Card")) { + Card card = (Card) tos.get("Card"); + if (card != null && (card.getController() == player || game.getZoneOf(card) == null + || game.getZoneOf(card).getZoneType().isKnown())) { + buildQuestion.append("\nTriggered by: " + tos.get("Card")); + } + } + + InputConfirm inp = new InputConfirm(this, buildQuestion.toString()); + inp.showAndWait(); + return inp.getResult(); + } + + @Override + public Player chooseStartingPlayer(boolean isFirstGame) { + if (game.getPlayers().size() == 2) { + final String prompt = String.format("%s, you %s\n\nWould you like to play or draw?", + player.getName(), isFirstGame ? " have won the coin toss." : " lost the last game."); + final InputConfirm inp = new InputConfirm(this, prompt, "Play", "Draw"); + inp.showAndWait(); + return inp.getResult() ? this.player : this.player.getOpponents().get(0); + } else { + final String prompt = String.format("%s, you %s\n\nWho would you like to start this game?", + player.getName(), isFirstGame ? " have won the coin toss." : " lost the last game."); + final InputSelectEntitiesFromList input = new InputSelectEntitiesFromList<>(this, 1, 1, game.getPlayersInTurnOrder()); + input.setMessage(prompt); + input.showAndWait(); + return input.getFirstSelected(); + } + } + + @Override + public List orderBlockers(final Card attacker, final List blockers) { + final CardView vAttacker = getCardView(attacker); + getGui().setPanelSelection(vAttacker); + final List choices = SGuiChoose.order(getGui(), "Choose Damage Order for " + vAttacker, "Damaged First", getCardViews(blockers), vAttacker); + return getCards(choices); + } + + @Override + public List orderBlocker(final Card attacker, final Card blocker, final List oldBlockers) { + final CardView vAttacker = getCardView(attacker); + getGui().setPanelSelection(vAttacker); + final List choices = SGuiChoose.insertInList(getGui(), "Choose blocker after which to place " + vAttacker + " in damage order; cancel to place it first", getCardView(blocker), getCardViews(oldBlockers)); + return getCards(choices); + } + + @Override + public List orderAttackers(final Card blocker, final List attackers) { + final CardView vBlocker = getCardView(blocker); + getGui().setPanelSelection(vBlocker); + final List choices = SGuiChoose.order(getGui(), "Choose Damage Order for " + vBlocker, "Damaged First", getCardViews(attackers), vBlocker); + return getCards(choices); + } + + /* (non-Javadoc) + * @see forge.game.player.PlayerController#reveal(java.lang.String, java.util.List, forge.game.zone.ZoneType, forge.game.player.Player) + */ + @Override + public void reveal(Collection cards, ZoneType zone, Player owner, String message) { + if (StringUtils.isBlank(message)) { + message = "Looking at cards in {player's} " + zone.name().toLowerCase(); + } + else { + message += "{player's} " + zone.name().toLowerCase(); + } + String fm = formatMessage(message, owner); + if (!cards.isEmpty()) { + SGuiChoose.reveal(getGui(), fm, cards); + } + else { + SGuiDialog.message(getGui(), formatMessage("There are no cards in {player's} " + + zone.name().toLowerCase(), owner), fm); + } + } + + @Override + public ImmutablePair, List> arrangeForScry(List topN) { + List toBottom = null; + List toTop = null; + + if (topN.size() == 1) { + if (willPutCardOnTop(topN.get(0))) { + toTop = topN; + } + else { + toBottom = topN; + } + } + else { + toBottom = SGuiChoose.many(getGui(), "Select cards to be put on the bottom of your library", "Cards to put on the bottom", -1, topN, null); + topN.removeAll(toBottom); + if (topN.isEmpty()) { + toTop = null; + } + else if (topN.size() == 1) { + toTop = topN; + } + else { + toTop = SGuiChoose.order(getGui(), "Arrange cards to be put on top of your library", "Cards arranged", topN, null); + } + } + return ImmutablePair.of(toTop, toBottom); + } + + @Override + public boolean willPutCardOnTop(final Card c) { + final PaperCard pc = FModel.getMagicDb().getCommonCards().getCard(c.getName()); + final Card c1 = (pc != null ? Card.fromPaperCard(pc, null) : c); + final CardView view = getCardView(c1); + return SGuiDialog.confirm(getGui(), view, "Put " + view + " on the top or bottom of your library?", new String[]{"Top", "Bottom"}); + } + + @Override + public List orderMoveToZoneList(List cards, ZoneType destinationZone) { + switch (destinationZone) { + case Library: + return SGuiChoose.order(getGui(), "Choose order of cards to put into the library", "Closest to top", cards, null); + case Battlefield: + return SGuiChoose.order(getGui(), "Choose order of cards to put onto the battlefield", "Put first", cards, null); + case Graveyard: + return SGuiChoose.order(getGui(), "Choose order of cards to put into the graveyard", "Closest to bottom", cards, null); + case PlanarDeck: + return SGuiChoose.order(getGui(), "Choose order of cards to put into the planar deck", "Closest to top", cards, null); + case SchemeDeck: + return SGuiChoose.order(getGui(), "Choose order of cards to put into the scheme deck", "Closest to top", cards, null); + case Stack: + return SGuiChoose.order(getGui(), "Choose order of copies to cast", "Put first", cards, null); + default: + System.out.println("ZoneType " + destinationZone + " - Not Ordered"); + break; + } + return cards; + } + + @Override + public List chooseCardsToDiscardFrom(Player p, SpellAbility sa, List valid, int min, int max) { + if (p != player) { + return SGuiChoose.many(getGui(), "Choose " + min + " card" + (min != 1 ? "s" : "") + " to discard", + "Discarded", min, min, valid, null); + } + + InputSelectCardsFromList inp = new InputSelectCardsFromList(this, min, max, valid); + inp.setMessage(sa.hasParam("AnyNumber") ? "Discard up to %d card(s)" : "Discard %d card(s)"); + inp.showAndWait(); + return Lists.newArrayList(inp.getSelected()); + } + + @Override + public void playMiracle(final SpellAbility miracle, final Card card) { + final CardView view = getCardView(card); + if (SGuiDialog.confirm(getGui(), view, view + " - Drawn. Play for Miracle Cost?")) { + HumanPlay.playSpellAbility(this, player, miracle); + } + } + + @Override + public List chooseCardsToDelve(int colorLessAmount, List grave) { + List toExile = new ArrayList(); + int cardsInGrave = grave.size(); + final Integer[] cntChoice = new Integer[cardsInGrave + 1]; + for (int i = 0; i <= cardsInGrave; i++) { + cntChoice[i] = Integer.valueOf(i); + } + + final Integer chosenAmount = SGuiChoose.one(getGui(), "Exile how many cards?", cntChoice); + System.out.println("Delve for " + chosenAmount); + + for (int i = 0; i < chosenAmount; i++) { + final Card nowChosen = SGuiChoose.oneOrNone(getGui(), "Exile which card?", grave); + + if (nowChosen == null) { + // User canceled,abort delving. + toExile.clear(); + break; + } + + grave.remove(nowChosen); + toExile.add(nowChosen); + } + return toExile; + } + + /* (non-Javadoc) + * @see forge.game.player.PlayerController#chooseTargets(forge.card.spellability.SpellAbility, forge.card.spellability.SpellAbilityStackInstance) + */ + @Override + public TargetChoices chooseNewTargetsFor(SpellAbility ability) { + SpellAbility sa = ability.isWrapper() ? ((WrappedAbility) ability).getWrappedAbility() : ability; + if (sa.getTargetRestrictions() == null) { + return null; + } + TargetChoices oldTarget = sa.getTargets(); + TargetSelection select = new TargetSelection(this, sa); + sa.resetTargets(); + if (select.chooseTargets(oldTarget.getNumTargeted())) { + return sa.getTargets(); + } + else { + // Return old target, since we had to reset them above + return oldTarget; + } + } + + /* (non-Javadoc) + * @see forge.game.player.PlayerController#chooseCardsToDiscardUnlessType(int, java.lang.String, forge.card.spellability.SpellAbility) + */ + @Override + public List chooseCardsToDiscardUnlessType(int num, List hand, final String uType, SpellAbility sa) { + final InputSelectEntitiesFromList target = new InputSelectEntitiesFromList(this, num, num, hand) { + private static final long serialVersionUID = -5774108410928795591L; + + @Override + protected boolean hasAllTargets() { + for (Card c : selected) { + if (c.isType(uType)) { + return true; + } + } + return super.hasAllTargets(); + } + }; + target.setMessage("Select %d card(s) to discard, unless you discard a " + uType + "."); + target.showAndWait(); + return Lists.newArrayList(target.getSelected()); + } + + /* (non-Javadoc) + * @see forge.game.player.PlayerController#chooseManaFromPool(java.util.List) + */ + @Override + public Mana chooseManaFromPool(List manaChoices) { + List options = new ArrayList(); + for (int i = 0; i < manaChoices.size(); i++) { + Mana m = manaChoices.get(i); + options.add(String.format("%d. %s mana from %s", 1+i, MagicColor.toLongString(m.getColor()), m.getSourceCard())); + } + String chosen = SGuiChoose.one(getGui(), "Pay Mana from Mana Pool", options); + String idx = TextUtil.split(chosen, '.')[0]; + return manaChoices.get(Integer.parseInt(idx)-1); + } + + /* (non-Javadoc) + * @see forge.game.player.PlayerController#chooseSomeType(java.lang.String, java.lang.String, java.util.List, java.util.List, java.lang.String) + */ + @Override + public String chooseSomeType(final String kindOfType, final SpellAbility sa, final List validTypes, List invalidTypes, final boolean isOptional) { + final List types = Lists.newArrayList(validTypes); + if (invalidTypes != null && !invalidTypes.isEmpty()) { + Iterables.removeAll(types, invalidTypes); + } + if(isOptional) + return SGuiChoose.oneOrNone(getGui(), "Choose a " + kindOfType.toLowerCase() + " type", types); + else + return SGuiChoose.one(getGui(), "Choose a " + kindOfType.toLowerCase() + " type", types); + } + + @Override + public Object vote(SpellAbility sa, String prompt, List options, ArrayListMultimap votes) { + return SGuiChoose.one(getGui(), prompt, options); + } + + /* (non-Javadoc) + * @see forge.game.player.PlayerController#confirmReplacementEffect(forge.card.replacement.ReplacementEffect, forge.card.spellability.SpellAbility, java.lang.String) + */ + @Override + public boolean confirmReplacementEffect(ReplacementEffect replacementEffect, SpellAbility effectSA, String question) { + return SGuiDialog.confirm(getGui(), getCardView(replacementEffect.getHostCard()), question); + } + + @Override + public List getCardsToMulligan(boolean isCommander, Player firstPlayer) { + final InputConfirmMulligan inp = new InputConfirmMulligan(this, player, firstPlayer, isCommander); + inp.showAndWait(); + return inp.isKeepHand() ? null : isCommander ? inp.getSelectedCards() : player.getCardsIn(ZoneType.Hand); + } + + @Override + public void declareAttackers(Player attackingPlayer, Combat combat) { + if (mayAutoPass()) { + List> mandatoryAttackers = CombatUtil.getMandatoryAttackers(attackingPlayer, combat, combat.getDefenders()); + if (!mandatoryAttackers.isEmpty()) { + //even if auto-passing attack phase, if there are any mandatory attackers, + //ensure they're declared and then delay slightly so user can see as much + for (Pair attacker : mandatoryAttackers) { + combat.addAttacker(attacker.getLeft(), attacker.getRight()); + getGui().fireEvent(new UiEventAttackerDeclared(getCardView(attacker.getLeft()), getGameEntityView(attacker.getRight()))); + } + try { + Thread.sleep(FControlGamePlayback.combatDelay); + } + catch (InterruptedException e) { + e.printStackTrace(); + } + } + return; //don't prompt to declare attackers if user chose to end the turn + } + + // This input should not modify combat object itself, but should return user choice + final InputAttack inpAttack = new InputAttack(this, attackingPlayer, combat); + inpAttack.showAndWait(); + } + + @Override + public void declareBlockers(Player defender, Combat combat) { + // This input should not modify combat object itself, but should return user choice + final InputBlock inpBlock = new InputBlock(this, defender, combat); + inpBlock.showAndWait(); + updateAutoPassPrompt(); + } + + public void updateAutoPassPrompt() { + if (mayAutoPass()) { + //allow user to cancel auto-pass + InputBase.cancelAwaitNextInput(); //don't overwrite prompt with awaiting opponent + PhaseType phase = getAutoPassUntilPhase(); + getGui().showPromptMessage("Yielding until " + (phase == PhaseType.CLEANUP ? "end of turn" : phase.nameForUi.toString()) + + ".\nYou may cancel this yield to take an action."); + ButtonUtil.update(getGui(), false, true, false); + } + } + + @Override + public void autoPassUntilEndOfTurn() { + super.autoPassUntilEndOfTurn(); + updateAutoPassPrompt(); + } + + @Override + public void autoPassCancel() { + if (getAutoPassUntilPhase() == null) { return; } + super.autoPassCancel(); + + //prevent prompt getting stuck on yielding message while actually waiting for next input opportunity + getGui().showPromptMessage(""); + ButtonUtil.update(getGui(), false, false, false); + InputBase.awaitNextInput(getGui()); + } + + @Override + public SpellAbility chooseSpellAbilityToPlay() { + MagicStack stack = game.getStack(); + + if (mayAutoPass()) { + //avoid prompting for input if current phase is set to be auto-passed + //instead posing a short delay if needed to prevent the game jumping ahead too quick + int delay = 0; + if (stack.isEmpty()) { + //make sure to briefly pause at phases you're not set up to skip + if (!isUiSetToSkipPhase(game.getPhaseHandler().getPlayerTurn(), game.getPhaseHandler().getPhase())) { + delay = FControlGamePlayback.phasesDelay; + } + } + else { + //pause slightly longer for spells and abilities on the stack resolving + delay = FControlGamePlayback.resolveDelay; + } + if (delay > 0) { + try { + Thread.sleep(delay); + } + catch (InterruptedException e) { + e.printStackTrace(); + } + } + return null; + } + + if (stack.isEmpty()) { + if (isUiSetToSkipPhase(game.getPhaseHandler().getPlayerTurn(), game.getPhaseHandler().getPhase())) { + return null; //avoid prompt for input if stack is empty and player is set to skip the current phase + } + } + else if (!game.getDisableAutoYields()) { + SpellAbility ability = stack.peekAbility(); + if (ability != null && ability.isAbility() && shouldAutoYield(ability.toUnsuppressedString())) { + //avoid prompt for input if top ability of stack is set to auto-yield + try { + Thread.sleep(FControlGamePlayback.resolveDelay); + } + catch (InterruptedException e) { + e.printStackTrace(); + } + return null; + } + } + + InputPassPriority defaultInput = new InputPassPriority(this, player); + defaultInput.showAndWait(); + return defaultInput.getChosenSa(); + } + + @Override + public void playChosenSpellAbility(SpellAbility chosenSa) { + HumanPlay.playSpellAbility(this, player, chosenSa); + } + + @Override + public List chooseCardsToDiscardToMaximumHandSize(int nDiscard) { + final int max = player.getMaxHandSize(); + + InputSelectCardsFromList inp = new InputSelectCardsFromList(this, nDiscard, nDiscard, player.getZone(ZoneType.Hand).getCards()); + String message = "Cleanup Phase\nSelect " + nDiscard + " card" + (nDiscard > 1 ? "s" : "") + + " to discard to bring your hand down to the maximum of " + max + " cards."; + inp.setMessage(message); + inp.setCancelAllowed(false); + inp.showAndWait(); + return Lists.newArrayList(inp.getSelected()); + } + + /* (non-Javadoc) + * @see forge.game.player.PlayerController#chooseCardsToRevealFromHand(int, int, java.util.List) + */ + @Override + public List chooseCardsToRevealFromHand(int min, int max, List valid) { + max = Math.min(max, valid.size()); + min = Math.min(min, max); + InputSelectCardsFromList inp = new InputSelectCardsFromList(this, min, max, valid); + inp.setMessage("Choose Which Cards to Reveal"); + inp.showAndWait(); + return Lists.newArrayList(inp.getSelected()); + } + + /* (non-Javadoc) + * @see forge.game.player.PlayerController#payManaOptional(forge.Card, forge.card.cost.Cost) + */ + @Override + public boolean payManaOptional(Card c, Cost cost, SpellAbility sa, String prompt, ManaPaymentPurpose purpose) { + if (sa == null && cost.isOnlyManaCost() && cost.getTotalMana().isZero() + && !FModel.getPreferences().getPrefBoolean(FPref.MATCHPREF_PROMPT_FREE_BLOCKS)) + return true; + + return HumanPlay.payCostDuringAbilityResolve(this, player, c, cost, sa, prompt); + } + + /* (non-Javadoc) + * @see forge.game.player.PlayerController#chooseSaToActivateFromOpeningHand(java.util.List) + */ + @Override + public List chooseSaToActivateFromOpeningHand(List usableFromOpeningHand) { + List srcCards = new ArrayList(); + for (SpellAbility sa : usableFromOpeningHand) { + srcCards.add(sa.getHostCard()); + } + List result = new ArrayList(); + if (srcCards.isEmpty()) { + return result; + } + List chosen = SGuiChoose.many(getGui(), "Choose cards to activate from opening hand and their order", "Activate first", -1, srcCards, null); + for (Card c : chosen) { + for (SpellAbility sa : usableFromOpeningHand) { + if (sa.getHostCard() == c) { + result.add(sa); + break; + } + } + } + return result; + } + + // end of not related candidates for move. + + /* (non-Javadoc) + * @see forge.game.player.PlayerController#chooseBinary(java.lang.String, boolean) + */ + @Override + public boolean chooseBinary(SpellAbility sa, String question, BinaryChoiceType kindOfChoice, Boolean defaultVal) { + String[] labels = new String[]{"Option1", "Option2"}; + switch(kindOfChoice) { + case HeadsOrTails: labels = new String[]{"Heads", "Tails"}; break; + case TapOrUntap: labels = new String[]{"Tap", "Untap"}; break; + case OddsOrEvens: labels = new String[]{"Odds", "Evens"}; break; + case UntapOrLeaveTapped: labels = new String[]{"Untap", "Leave tapped"}; break; + case UntapTimeVault: labels = new String[]{"Untap (and skip this turn)", "Leave tapped"}; break; + case PlayOrDraw: labels = new String[]{"Play", "Draw"}; break; + default: labels = kindOfChoice.toString().split("Or"); + + } + return SGuiDialog.confirm(getGui(), getCardView(sa.getHostCard()), question, defaultVal == null || defaultVal.booleanValue(), labels); + } + + @Override + public boolean chooseFlipResult(SpellAbility sa, Player flipper, boolean[] results, boolean call) { + String[] labelsSrc = call ? new String[]{"heads", "tails"} : new String[]{"win the flip", "lose the flip"}; + String[] strResults = new String[results.length]; + for (int i = 0; i < results.length; i++) { + strResults[i] = labelsSrc[results[i] ? 0 : 1]; + } + return SGuiChoose.one(getGui(), sa.getHostCard().getName() + " - Choose a result", strResults) == labelsSrc[0]; + } + + @Override + public Card chooseProtectionShield(GameEntity entityBeingDamaged, List options, Map choiceMap) { + String title = entityBeingDamaged + " - select which prevention shield to use"; + return choiceMap.get(SGuiChoose.one(getGui(), title, options)); + } + + @Override + public Pair chooseAndRemoveOrPutCounter(Card cardWithCounter) { + if (!cardWithCounter.hasCounters()) { + System.out.println("chooseCounterType was reached with a card with no counters on it. Consider filtering this card out earlier"); + return null; + } + + String counterChoiceTitle = "Choose a counter type on " + cardWithCounter; + final CounterType chosen = SGuiChoose.one(getGui(), counterChoiceTitle, cardWithCounter.getCounters().keySet()); + + String putOrRemoveTitle = "What to do with that '" + chosen.getName() + "' counter "; + final String putString = "Put another " + chosen.getName() + " counter on " + cardWithCounter; + final String removeString = "Remove a " + chosen.getName() + " counter from " + cardWithCounter; + final String addOrRemove = SGuiChoose.one(getGui(), putOrRemoveTitle, new String[]{putString,removeString}); + + return new ImmutablePair(chosen,addOrRemove); + } + + @Override + public Pair chooseTarget(SpellAbility saSpellskite, List> allTargets) { + if (allTargets.size() < 2) { + return Iterables.getFirst(allTargets, null); + } + + final Function, String> fnToString = new Function, String>() { + @Override + public String apply(Pair targ) { + return targ.getRight().toString() + " - " + targ.getLeft().getStackDescription(); + } + }; + + List> chosen = SGuiChoose.getChoices(getGui(), saSpellskite.getHostCard().getName(), 1, 1, allTargets, null, fnToString); + return Iterables.getFirst(chosen, null); + } + + @Override + public void notifyOfValue(SpellAbility sa, GameObject realtedTarget, String value) { + String message = formatNotificationMessage(sa, realtedTarget, value); + if (sa.isManaAbility()) { + game.getGameLog().add(GameLogEntryType.LAND, message); + } else { + SGuiDialog.message(getGui(), message, sa.getHostCard() == null ? "" : sa.getHostCard().getName()); + } + } + + private String formatMessage(String message, Object related) { + if(related instanceof Player && message.indexOf("{player") >= 0) + message = message.replace("{player}", mayBeYou(related)).replace("{player's}", Lang.getPossesive(mayBeYou(related))); + + return message; + } + + // These are not much related to PlayerController + private String formatNotificationMessage(SpellAbility sa, GameObject target, String value) { + if (sa.getApi() == null || sa.getHostCard() == null) { + return ("Result: " + value); + } + switch(sa.getApi()) { + case ChooseDirection: + return value; + case ChooseNumber: + if (sa.hasParam("SecretlyChoose")) { + return value; + } + final boolean random = sa.hasParam("Random"); + return String.format(random ? "Randomly chosen number for %s is %s" : "%s choses number: %s", mayBeYou(target), value); + case FlipACoin: + String flipper = StringUtils.capitalize(mayBeYou(target)); + return sa.hasParam("NoCall") + ? String.format("%s flip comes up %s", Lang.getPossesive(flipper), value) + : String.format("%s %s the flip", flipper, Lang.joinVerb(flipper, value)); + case Protection: + String choser = StringUtils.capitalize(mayBeYou(target)); + return String.format("%s %s protection from %s", choser, Lang.joinVerb(choser, "choose"), value); + case Vote: + String chooser = StringUtils.capitalize(mayBeYou(target)); + return String.format("%s %s %s", chooser, Lang.joinVerb(chooser, "vote"), value); + default: + return String.format("%s effect's value for %s is %s", sa.getHostCard().getName(), mayBeYou(target), value); + } + } + + private String mayBeYou(Object what) { + return what == null ? "(null)" : what == player ? "you" : what.toString(); + } + + // end of not related candidates for move. + + /* (non-Javadoc) + * @see forge.game.player.PlayerController#chooseModeForAbility(forge.card.spellability.SpellAbility, java.util.List, int, int) + */ + @Override + public List chooseModeForAbility(SpellAbility sa, int min, int num) { + List choices = CharmEffect.makePossibleOptions(sa); + String modeTitle = String.format("%s activated %s - Choose a mode", sa.getActivatingPlayer(), sa.getHostCard()); + List chosen = new ArrayList(); + for (int i = 0; i < num; i++) { + AbilitySub a; + if (i < min) { + a = SGuiChoose.one(getGui(), modeTitle, choices); + } + else { + a = SGuiChoose.oneOrNone(getGui(), modeTitle, choices); + } + if (null == a) { + break; + } + + choices.remove(a); + chosen.add(a); + } + return chosen; + } + + @Override + public List chooseColors(String message, SpellAbility sa, int min, int max, List options) { + return SGuiChoose.getChoices(getGui(), message, min, max, options); + } + + @Override + public byte chooseColor(String message, SpellAbility sa, ColorSet colors) { + int cntColors = colors.countColors(); + switch (cntColors) { + case 0: return 0; + case 1: return colors.getColor(); + default: return chooseColorCommon(message, sa == null ? null : sa.getHostCard(), colors, false); + } + } + + @Override + public byte chooseColorAllowColorless(String message, Card c, ColorSet colors) { + int cntColors = 1 + colors.countColors(); + switch (cntColors) { + case 1: return 0; + default: return chooseColorCommon(message, c, colors, true); + } + } + + private byte chooseColorCommon(String message, Card c, ColorSet colors, boolean withColorless) { + int cntColors = colors.countColors(); + if(withColorless) cntColors++; + String[] colorNames = new String[cntColors]; + int i = 0; + if(withColorless) + colorNames[i++] = MagicColor.toLongString((byte)0); + for (byte b : colors) { + colorNames[i++] = MagicColor.toLongString(b); + } + if (colorNames.length > 2) { + return MagicColor.fromName(SGuiChoose.one(getGui(), message, colorNames)); + } + int idxChosen = SGuiDialog.confirm(getGui(), getCardView(c), message, colorNames) ? 0 : 1; + return MagicColor.fromName(colorNames[idxChosen]); + } + + @Override + public PaperCard chooseSinglePaperCard(SpellAbility sa, String message, Predicate cpp, String name) { + Iterable cardsFromDb = FModel.getMagicDb().getCommonCards().getUniqueCards(); + List cards = Lists.newArrayList(Iterables.filter(cardsFromDb, cpp)); + Collections.sort(cards); + return SGuiChoose.one(getGui(), message, cards); + } + + @Override + public CounterType chooseCounterType(Collection options, SpellAbility sa, String prompt) { + if (options.size() <= 1) { + return Iterables.getFirst(options, null); + } + return SGuiChoose.one(getGui(), prompt, options); + } + + @Override + public boolean confirmPayment(CostPart costPart, String question) { + InputConfirm inp = new InputConfirm(this, question); + inp.showAndWait(); + return inp.getResult(); + } + + @Override + public ReplacementEffect chooseSingleReplacementEffect(String prompt, List possibleReplacers, HashMap runParams) { + if(possibleReplacers.size() == 1) + return possibleReplacers.get(0); + return SGuiChoose.one(getGui(), prompt, possibleReplacers); + } + + @Override + public String chooseProtectionType(String string, SpellAbility sa, List choices) { + return SGuiChoose.one(getGui(), string, choices); + } + + @Override + public boolean payCostToPreventEffect(Cost cost, SpellAbility sa, boolean alreadyPaid, List allPayers) { + // if it's paid by the AI already the human can pay, but it won't change anything + return HumanPlay.payCostDuringAbilityResolve(this, player, sa.getHostCard(), cost, sa, null); + } + + @Override + public void orderAndPlaySimultaneousSa(List activePlayerSAs) { + List orderedSAs = activePlayerSAs; + if (activePlayerSAs.size() > 1) { // give a dual list form to create instead of needing to do it one at a time + orderedSAs = SGuiChoose.order(getGui(), "Select order for Simultaneous Spell Abilities", "Resolve first", activePlayerSAs, null); + } + int size = orderedSAs.size(); + for (int i = size - 1; i >= 0; i--) { + SpellAbility next = orderedSAs.get(i); + if (next.isTrigger()) { + HumanPlay.playSpellAbility(this, player, next); + } else { + player.getGame().getStack().add(next); + } + } + } + + @Override + public void playTrigger(Card host, WrappedAbility wrapperAbility, boolean isMandatory) { + HumanPlay.playSpellAbilityNoStack(this, player, wrapperAbility); + } + + @Override + public boolean playSaFromPlayEffect(SpellAbility tgtSA) { + HumanPlay.playSpellAbility(this, player, tgtSA); + return true; + } + + @Override + public Map chooseProliferation() { + InputProliferate inp = new InputProliferate(this); + inp.setCancelAllowed(true); + inp.showAndWait(); + if (inp.hasCancelled()) { + return null; + } + return inp.getProliferationMap(); + } + + @Override + public boolean chooseTargetsFor(SpellAbility currentAbility) { + final TargetSelection select = new TargetSelection(this, currentAbility); + return select.chooseTargets(null); + } + + @Override + public boolean chooseCardsPile(SpellAbility sa, List pile1, List pile2, boolean faceUp) { + if (!faceUp) { + final String p1Str = String.format("Pile 1 (%s cards)", pile1.size()); + final String p2Str = String.format("Pile 2 (%s cards)", pile2.size()); + final String[] possibleValues = { p1Str , p2Str }; + return SGuiDialog.confirm(getGui(), getCardView(sa.getHostCard()), "Choose a Pile", possibleValues); + } else { + final Card[] disp = new Card[pile1.size() + pile2.size() + 2]; + disp[0] = new Card(-1); + disp[0].setName("Pile 1"); + for (int i = 0; i < pile1.size(); i++) { + disp[1 + i] = pile1.get(i); + } + disp[pile1.size() + 1] = new Card(-2); + disp[pile1.size() + 1].setName("Pile 2"); + for (int i = 0; i < pile2.size(); i++) { + disp[pile1.size() + i + 2] = pile2.get(i); + } + + // make sure Pile 1 or Pile 2 is clicked on + while (true) { + final Object o = SGuiChoose.one(getGui(), "Choose a pile", disp); + final Card c = (Card) o; + String name = c.getName(); + + if (!(name.equals("Pile 1") || name.equals("Pile 2"))) { + continue; + } + + return name.equals("Pile 1"); + } + } + } + + @Override + public void revealAnte(String message, Multimap removedAnteCards) { + for (Player p : removedAnteCards.keySet()) { + SGuiChoose.reveal(getGui(), message + " from " + Lang.getPossessedObject(mayBeYou(p), "deck"), removedAnteCards.get(p)); + } + } + + @Override + public CardShields chooseRegenerationShield(Card c) { + if (c.getShield().size() < 2) { + return Iterables.getFirst(c.getShield(), null); + } + return SGuiChoose.one(getGui(), "Choose a regeneration shield:", c.getShield()); + } + + @Override + public List chooseCardsYouWonToAddToDeck(List losses) { + return SGuiChoose.many(getGui(), "Select cards to add to your deck", "Add these to my deck", 0, losses.size(), losses, null); + } + + @Override + public boolean payManaCost(ManaCost toPay, CostPartMana costPartMana, SpellAbility sa, String prompt, boolean isActivatedSa) { + return HumanPlay.payManaCost(this, toPay, costPartMana, sa, player, prompt, isActivatedSa); + } + + @Override + public Map chooseCardsForConvoke(SpellAbility sa, ManaCost manaCost, List untappedCreats) { + InputSelectCardsForConvoke inp = new InputSelectCardsForConvoke(this, player, manaCost, untappedCreats); + inp.showAndWait(); + return inp.getConvokeMap(); + } + + @Override + public String chooseCardName(SpellAbility sa, Predicate cpp, String valid, String message) { + PaperCard cp = null; + while(true) { + cp = chooseSinglePaperCard(sa, message, cpp, sa.getHostCard().getName()); + Card instanceForPlayer = Card.fromPaperCard(cp, player); // the Card instance for test needs a game to be tested + if (instanceForPlayer.isValid(valid, sa.getHostCard().getController(), sa.getHostCard())) + return cp.getName(); + } + } + + @Override + public Card chooseSingleCardForZoneChange(ZoneType destination, List origin, SpellAbility sa, List fetchList, String selectPrompt, boolean b, Player decider) { + return chooseSingleEntityForEffect(fetchList, sa, selectPrompt, b, decider); + } + + public boolean isGuiPlayer() { + return lobbyPlayer == getGui().getGuiPlayer(); + } + + /* + * What follows are the View methods. + */ + + /** Cache of players. */ + private final BiMap players + = HashBiMap.create(); + /** Cache of cards. */ + private final BiMap cards + = HashBiMap.create(); + /** Cache of spellabilities. */ + private final BiMap spabs + = HashBiMap.create(); + /** Cache of stack items. */ + private final BiMap stackItems + = HashBiMap.create(); + /** Combat view. */ + private final CombatView combatView = new CombatView(); + + /* (non-Javadoc) + * @see forge.view.IGameView#isCommander() + */ + @Override + public boolean isCommander() { + return game.getRules().hasAppliedVariant(GameType.Commander); + } + /* (non-Javadoc) + * @see forge.view.IGameView#getGameType() + */ + @Override + public GameType getGameType() { + return this.game.getMatch().getRules().getGameType(); + } + + @Override + public int getTurnNumber() { + return this.game.getPhaseHandler().getTurn(); + } + + @Override + public boolean isCommandZoneNeeded() { + return this.game.getMatch().getRules().getGameType().isCommandZoneNeeded(); + } + + @Override + public boolean isWinner(final LobbyPlayer p) { + return game.getOutcome() == null ? null : game.getOutcome().isWinner(p); + } + + @Override + public LobbyPlayer getWinningPlayer() { + return game.getOutcome() == null ? null : game.getOutcome().getWinningLobbyPlayer(); + } + + @Override + public int getWinningTeam() { + return game.getOutcome() == null ? -1 : game.getOutcome().getWinningTeam(); + } + + /* (non-Javadoc) + * @see forge.view.IGameView#isFirstGameInMatch() + */ + @Override + public boolean isFirstGameInMatch() { + return this.game.getMatch().getPlayedGames().isEmpty(); + } + + @Override + public boolean isMatchOver() { + return this.game.getMatch().isMatchOver(); + } + + @Override + public int getNumGamesInMatch() { + return this.game.getMatch().getRules().getGamesPerMatch(); + } + + @Override + public int getNumPlayedGamesInMatch() { + return this.game.getMatch().getPlayedGames().size(); + } + + @Override + public Iterable getOutcomesOfMatch() { + return Iterables.unmodifiableIterable(this.game.getMatch().getPlayedGames()); + } + + @Override + public boolean isMatchWonBy(final LobbyPlayer p) { + return this.game.getMatch().isWonBy(p); + } + + @Override + public int getGamesWonBy(LobbyPlayer p) { + return this.game.getMatch().getGamesWonBy(p); + } + + @Override + public GameOutcome.AnteResult getAnteResult() { + return this.game.getOutcome().anteResult.get(player); + } + + /* (non-Javadoc) + * @see forge.view.IGameView#isCombatDeclareAttackers() + */ + @Override + public boolean isCombatDeclareAttackers() { + return game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_ATTACKERS) + && game.getCombat() != null; + } + + /* (non-Javadoc) + * @see forge.view.IGameView#isGameOver() + */ + @Override + public boolean isGameOver() { + return game.isGameOver(); + } + + @Override + public int getPoisonCountersToLose() { + return game.getRules().getPoisonCountersToLose(); + } + + /* (non-Javadoc) + * @see forge.view.IGameView#subscribeToEvents(java.lang.Object) + */ + @Override + public void subscribeToEvents(final Object subscriber) { + game.subscribeToEvents(subscriber); + } + + /* (non-Javadoc) + * @see forge.view.IGameView#getCombat() + */ + @Override + public CombatView getCombat(final Combat c) { + updateCombatView(c); + return combatView; + } + + private final void updateCombatView(final Combat combat) { + combatView.reset(); + for (final AttackingBand b : combat.getAttackingBands()) { + final GameEntity defender = combat.getDefenderByAttacker(b); + final List blockers = b.isBlocked() ? combat.getBlockers(b) : null; + combatView.addAttackingBand(getCardViews(b.getAttackers()), getGameEntityView(defender), getCardViews(blockers)); + } + } + + @Override + public void addLogObserver(final Observer o) { + game.getGameLog().addObserver(o); + } + + @Override + public List getLogEntries(final GameLogEntryType maxLogLevel) { + return game.getGameLog().getLogEntries(maxLogLevel); + } + + @Override + public List getLogEntriesExact(final GameLogEntryType logLevel) { + return game.getGameLog().getLogEntriesExact(logLevel); + } + + public boolean canUndoLastAction() { + if (!game.stack.canUndo()) { + return false; + } + final Player priorityPlayer = game.getPhaseHandler().getPriorityPlayer(); + if (priorityPlayer == null || priorityPlayer != this.player) { + return false; + } + return true; + } + + @Override + public boolean tryUndoLastAction() { + if (!canUndoLastAction()) { + return false; + } + + if (game.getStack().undo()) {//canUndoLastAction(gui) && GuiBase.getInterface().getGame().stack.undo()) { + final Input currentInput = getGui().getInputQueue().getInput(); + if (currentInput instanceof InputPassPriority) { + currentInput.showMessageInitial(); //ensure prompt updated if needed + } + return true; + } + return false; + } + + /* (non-Javadoc) + * @see forge.view.IGameView#getGuiRegisteredPlayer(forge.LobbyPlayer) + */ + @Override + public RegisteredPlayer getGuiRegisteredPlayer(final LobbyPlayer p) { + for (final RegisteredPlayer player : game.getMatch().getPlayers()) { + if (player.getPlayer() == p) { + return player; + } + } + return null; + } + + /* (non-Javadoc) + * @see forge.view.IGameView#getRegisteredPlayers() + */ + @Override + public List getPlayers() { + return getPlayerViews(game.getRegisteredPlayers()); + } + + @Override + public PlayerView getPlayerTurn() { + return getPlayerView(game.getPhaseHandler().getPlayerTurn()); + } + + @Override + public PhaseType getPhase() { + return game.getPhaseHandler().getPhase(); + } + + /* (non-Javadoc) + * @see forge.view.IGameView#getStack() + */ + @Override + public List getStack() { + final List items = Collections.unmodifiableList(getStack(game.getStack())); + // clear the cache + stackItems.keySet().retainAll(items); + return items; + } + + /* (non-Javadoc) + * @see forge.view.IGameView#peekStack() + */ + @Override + public StackItemView peekStack() { + final SpellAbilityStackInstance top = + Iterables.getFirst(game.getStack(), null); + if (top == null) { + return null; + } + return getStack(Lists.newArrayList(top)).iterator().next(); + } + + private List getStack(final Iterable stack) { + synchronized (this) { + stackItems.keySet().retainAll(Lists.newArrayList(stack)); + final List items = Lists.newLinkedList(); + for (final SpellAbilityStackInstance si : stack) { + if (stackItems.containsKey(si)) { + items.add(stackItems.get(si)); + } else { + items.add(getStackItemView(si)); + } + } + return items; + } + } + + @Override + public StackItemView getStackItemView(final SpellAbilityStackInstance si) { + final StackItemView newItem = new StackItemView( + si.getSpellAbility().toUnsuppressedString(), + si.getSpellAbility().getSourceTrigger(), + si.getStackDescription(), getCardView(si.getSourceCard()), + getPlayerView(si.getActivator()), si.isAbility(), + si.isOptionalTrigger()); + stackItems.put(si, newItem); + return newItem; + } + + @Override + public SpellAbilityStackInstance getStackItem(final StackItemView view) { + return stackItems.inverse().get(view); + } + + @Override + public PlayerView getPlayerView(final Player p) { + if (p == null) { + return null; + } + + final PlayerView view; + if (players.containsKey(p)) { + view = players.get(p); + getPlayerView(p, view); + } else { + view = new PlayerView(p.getLobbyPlayer(), p.getController()); + getPlayerView(p, view); + players.put(p, view); + } + return view; + } + + @Override + public Player getPlayer(final PlayerView p) { + return players.inverse().get(p); + } + + private void getPlayerView(final Player p, final PlayerView view) { + view.setCommanderInfo(CardFactoryUtil.getCommanderInfo(p).trim().replace("\r\n", "; ")); + view.setKeywords(p.getKeywords()); + view.setLife(p.getLife()); + view.setMaxHandSize(p.getMaxHandSize()); + view.setNumDrawnThisTurn(p.getNumDrawnThisTurn()); + view.setPoisonCounters(p.getPoisonCounters()); + view.setPreventNextDamage(p.getPreventNextDamageTotalShields()); + view.setHasUnlimitedHandSize(p.isUnlimitedHandSize()); + view.setAnteCards(getCardViews(p.getCardsIn(ZoneType.Ante))); + view.setBfCards(getCardViews(p.getCardsIn(ZoneType.Battlefield))); + view.setExileCards(getCardViews(p.getCardsIn(ZoneType.Exile))); + view.setFlashbackCards(getCardViews(p.getCardsActivableInExternalZones(false))); + view.setGraveCards(getCardViews(p.getCardsIn(ZoneType.Graveyard))); + view.setHandCards(getCardViews(p.getCardsIn(ZoneType.Hand))); + view.setLibraryCards(getCardViews(p.getCardsIn(ZoneType.Library))); + } + + public CardView getCardView(final Card c) { + if (c == null) { + return null; + } + + final Card cUi = c.getCardForUi(); + final CardView view; + if (cards.containsKey(cUi)) { + view = cards.get(cUi); + writeCardToView(cUi, view); + } else { + view = new CardView(cUi, cUi.getUniqueNumber(), cUi == c); + writeCardToView(cUi, view); + cards.put(cUi, view); + } + return view; + } + + public Card getCard(final CardView c) { + return cards.inverse().get(c); + } + + private void writeCardToView(final Card c, final CardView view) { + if (!c.canBeShownTo(player)) { + view.getOriginal().reset(); + view.getAlternate().reset(); + return; + } + + // First, write the values independent of other views. + ViewUtil.writeNonDependentCardViewProperties(c, view); + // Next, write the values that depend on other views. + view.setOwner(getPlayerView(c.getOwner())); + view.setController(getPlayerView(c.getController())); + view.setAttacking(game.getCombat() != null && game.getCombat().isAttacking(c)); + view.setBlocking(game.getCombat() != null && game.getCombat().isBlocking(c)); + view.setChosenPlayer(getPlayerView(c.getChosenPlayer())); + view.setEquipping(getCardView(Iterables.getFirst(c.getEquipping(), null))); + view.setEquippedBy(getCardViews(c.getEquippedBy())); + view.setEnchantingCard(getCardView(c.getEnchantingCard())); + view.setEnchantingPlayer(getPlayerView(c.getEnchantingPlayer())); + view.setEnchantedBy(getCardViews(c.getEnchantedBy())); + view.setFortifiedBy(getCardViews(c.getFortifiedBy())); + view.setGainControlTargets(getCardViews(c.getGainControlTargets())); + view.setCloneOrigin(getCardView(c.getCloneOrigin())); + view.setImprinted(getCardViews(c.getImprinted())); + view.setHauntedBy(getCardViews(c.getHauntedBy())); + view.setHaunting(getCardView(c.getHaunting())); + view.setMustBlock(c.getMustBlockCards() == null ? Collections.emptySet() : getCardViews(c.getMustBlockCards())); + view.setPairedWith(getCardView(c.getPairedWith())); + } + + @Override + public boolean mayShowCard(final CardView c) { + return cards.inverse().get(c).canBeShownTo(player); + } + + @Override + public SpellAbilityView getSpellAbilityView(final SpellAbility sa) { + if (sa == null) { + return null; + } + + final SpellAbilityView view; + if (spabs.containsKey(sa)) { + view = spabs.get(sa); + writeSpellAbilityToView(sa, view); + } else { + view = new SpellAbilityView(); + writeSpellAbilityToView(sa, view); + spabs.put(sa, view); + } + return view; + } + + @Override + public SpellAbility getSpellAbility(final SpellAbilityView c) { + return spabs.inverse().get(c); + } + + private void writeSpellAbilityToView(final SpellAbility sa, final SpellAbilityView view) { + view.setHostCard(getCardView(sa.getHostCard())); + view.setCanPlay(sa.canPlay()); + view.setPromptIfOnlyPossibleAbility(sa.promptIfOnlyPossibleAbility()); + } + + @Override + public boolean getDisableAutoYields() { + return this.game.getDisableAutoYields(); + } + @Override + public void setDisableAutoYields(final boolean b) { + this.game.setDisableAutoYields(b); + } + + // Dev mode functions + @Override + public void devTogglePlayManyLands(final boolean b) { + player.canCheatPlayUnlimitedLands = b; + } + @Override + public void devGenerateMana() { + DevModeUtil.devModeGenerateMana(game, this); + } + @Override + public void devSetupGameState() { + DevModeUtil.devSetupGameState(game, this); + } + @Override + public void devTutorForCard() { + DevModeUtil.devModeTutor(game, this); + } + @Override + public void devAddCardToHand() { + DevModeUtil.devModeCardToHand(game, this); + } + @Override + public void devAddCounterToPermanent() { + DevModeUtil.devModeAddCounter(game, this); + } + @Override + public void devTapPermanent() { + DevModeUtil.devModeTapPerm(game, this); + } + @Override + public void devUntapPermanent() { + DevModeUtil.devModeUntapPerm(game, this); + } + @Override + public void devSetPlayerLife() { + DevModeUtil.devModeSetLife(game, this); + } + @Override + public void devWinGame() { + DevModeUtil.devModeWinGame(game, this); + } + @Override + public void devAddCardToBattlefield() { + DevModeUtil.devModeCardToBattlefield(game, this); + } + @Override + public void devRiggedPlanerRoll() { + DevModeUtil.devModeRiggedPlanarRoll(game, this); + } + @Override + public void devPlaneswalkTo() { + DevModeUtil.devModeRiggedPlanarRoll(game, this); + } +} diff --git a/forge-gui/src/main/java/forge/player/TargetSelection.java b/forge-gui/src/main/java/forge/player/TargetSelection.java index 8a9f015ba9d..7db8c956732 100644 --- a/forge-gui/src/main/java/forge/player/TargetSelection.java +++ b/forge-gui/src/main/java/forge/player/TargetSelection.java @@ -17,15 +17,19 @@ */ package forge.player; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + import com.google.common.base.Predicate; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; -import forge.GuiBase; import forge.game.Game; +import forge.game.GameEntity; import forge.game.GameObject; import forge.game.card.Card; import forge.game.card.CardLists; -import forge.game.player.Player; import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbilityStackInstance; import forge.game.spellability.TargetRestrictions; @@ -35,12 +39,8 @@ import forge.match.input.InputSelectTargets; import forge.util.Aggregates; import forge.util.gui.SGuiChoose; import forge.view.CardView; -import forge.view.SpellAbilityView; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import forge.view.PlayerView; +import forge.view.StackItemView; /** *

@@ -51,9 +51,11 @@ import java.util.Map; * @version $Id: TargetSelection.java 25148 2014-03-12 08:28:52Z swordshine $ */ public class TargetSelection { + private final PlayerControllerHuman controller; private final SpellAbility ability; - public TargetSelection(final SpellAbility currentAbility) { + public TargetSelection(final PlayerControllerHuman controller, final SpellAbility currentAbility) { + this.controller = controller; this.ability = currentAbility; } @@ -106,7 +108,7 @@ public class TargetSelection { final boolean choiceResult; final boolean random = tgt.isRandomTarget(); if (random) { - final List candidates = tgt.getAllCandidates(this.ability, true); + final List candidates = tgt.getAllCandidates(this.ability, true); final GameObject choice = Aggregates.random(candidates); return ability.getTargets().add(choice); } @@ -116,12 +118,12 @@ public class TargetSelection { return this.chooseCardFromStack(mandatory); } else { - final List validTargets = this.getValidCardsToTarget(); + final List validTargets = this.getValidCardsToTarget(); if (validTargets.isEmpty()) { //if no valid cards to target and only one valid non-card, auto-target the non-card //this handles "target opponent" cards, along with any other cards that can only target a single non-card game entity //note that we don't handle auto-targeting cards this way since it's possible that the result will be undesirable - List nonCardTargets = tgt.getAllCandidates(this.ability, true); + List nonCardTargets = tgt.getAllCandidates(this.ability, true); if (nonCardTargets.size() == 1) { return ability.getTargets().add(nonCardTargets.get(0)); } @@ -132,16 +134,16 @@ public class TargetSelection { //to play a spell or activat an ability return ability.getTargets().add(validTargets.get(0)); } - final Map playersWithValidTargets = new HashMap(); + final Map playersWithValidTargets = Maps.newHashMap(); for (Card card : validTargets) { - playersWithValidTargets.put(card.getController(), null); + playersWithValidTargets.put(controller.getPlayerView(card.getController()), null); } - if (GuiBase.getInterface().openZones(zone, playersWithValidTargets)) { - InputSelectTargets inp = new InputSelectTargets(validTargets, ability, mandatory); + if (controller.getGui().openZones(zone, playersWithValidTargets)) { + InputSelectTargets inp = new InputSelectTargets(controller, validTargets, ability, mandatory); inp.showAndWait(); choiceResult = !inp.hasCancelled(); bTargetingDone = inp.hasPressedOk(); - GuiBase.getInterface().restoreOldZones(playersWithValidTargets); + controller.getGui().restoreOldZones(playersWithValidTargets); } else { // for every other case an all-purpose GuiChoose @@ -163,7 +165,7 @@ public class TargetSelection { *

* @return */ - private final List getValidCardsToTarget() { + private final List getValidCardsToTarget() { final TargetRestrictions tgt = this.getTgt(); final Game game = ability.getActivatingPlayer().getGame(); final List zone = tgt.getZone(); @@ -227,20 +229,21 @@ public class TargetSelection { // Send in a list of valid cards, and popup a choice box to target final Game game = ability.getActivatingPlayer().getGame(); - final List crdsBattle = new ArrayList(); - final List crdsExile = new ArrayList(); - final List crdsGrave = new ArrayList(); - final List crdsLibrary = new ArrayList(); - final List crdsStack = new ArrayList(); - final List crdsAnte = new ArrayList(); + final List crdsBattle = Lists.newArrayList(); + final List crdsExile = Lists.newArrayList(); + final List crdsGrave = Lists.newArrayList(); + final List crdsLibrary = Lists.newArrayList(); + final List crdsStack = Lists.newArrayList(); + final List crdsAnte = Lists.newArrayList(); for (final Card inZone : choices) { + final CardView view = controller.getCardView(inZone); Zone zz = game.getZoneOf(inZone); - if (zz.is(ZoneType.Battlefield)) crdsBattle.add(inZone); - else if (zz.is(ZoneType.Exile)) crdsExile.add(inZone); - else if (zz.is(ZoneType.Graveyard)) crdsGrave.add(inZone); - else if (zz.is(ZoneType.Library)) crdsLibrary.add(inZone); - else if (zz.is(ZoneType.Stack)) crdsStack.add(inZone); - else if (zz.is(ZoneType.Ante)) crdsAnte.add(inZone); + if (zz.is(ZoneType.Battlefield)) crdsBattle.add(view); + else if (zz.is(ZoneType.Exile)) crdsExile.add(view); + else if (zz.is(ZoneType.Graveyard)) crdsGrave.add(view); + else if (zz.is(ZoneType.Library)) crdsLibrary.add(view); + else if (zz.is(ZoneType.Stack)) crdsStack.add(view); + else if (zz.is(ZoneType.Ante)) crdsAnte.add(view); } List choicesFiltered = new ArrayList(); if (!crdsBattle.isEmpty()) { @@ -276,9 +279,9 @@ public class TargetSelection { Object chosen = null; if (!choices.isEmpty() && mandatory) { - chosen = SGuiChoose.one(getTgt().getVTSelection(), choicesFiltered); + chosen = SGuiChoose.one(controller.getGui(), getTgt().getVTSelection(), choicesFiltered); } else { - chosen = SGuiChoose.oneOrNone(getTgt().getVTSelection(), choicesFiltered); + chosen = SGuiChoose.oneOrNone(controller.getGui(), getTgt().getVTSelection(), choicesFiltered); } if (chosen == null) { return false; @@ -287,9 +290,11 @@ public class TargetSelection { bTargetingDone = true; return true; } - - if (chosen instanceof Card ) - ability.getTargets().add((Card)chosen); + + if (chosen instanceof CardView) { + final Card chosenCard = controller.getCard((CardView) chosen); + ability.getTargets().add(chosenCard); + } return true; } @@ -308,14 +313,13 @@ public class TargetSelection { final List selectOptions = new ArrayList(); final Game game = ability.getActivatingPlayer().getGame(); - for (SpellAbilityStackInstance si : game.getStack()) { + for (final SpellAbilityStackInstance si : game.getStack()) { SpellAbility abilityOnStack = si.getSpellAbility(); if (ability.equals(abilityOnStack)) { // By peeking at stack item, target is set to its SI state. So set it back before adding targets ability.resetTargets(); - } - else if (ability.canTargetSpellAbility(abilityOnStack)) { - selectOptions.add(abilityOnStack); + } else if (ability.canTargetSpellAbility(abilityOnStack)) { + selectOptions.add(controller.getStackItemView(si)); } } @@ -333,12 +337,12 @@ public class TargetSelection { // Not enough targets, cancel targeting return false; } else { - final Object madeChoice = SGuiChoose.oneOrNone(message, selectOptions); + final Object madeChoice = SGuiChoose.oneOrNone(controller.getGui(), message, selectOptions); if (madeChoice == null) { return false; } - if (madeChoice instanceof SpellAbility) { - ability.getTargets().add((SpellAbility)madeChoice); + if (madeChoice instanceof StackItemView) { + ability.getTargets().add(controller.getStackItem((StackItemView)madeChoice).getSpellAbility()); } else // 'FINISH TARGETING' chosen bTargetingDone = true; } diff --git a/forge-gui/src/main/java/forge/properties/ForgeConstants.java b/forge-gui/src/main/java/forge/properties/ForgeConstants.java index 6c28213f8c3..6cfd72f6198 100644 --- a/forge-gui/src/main/java/forge/properties/ForgeConstants.java +++ b/forge-gui/src/main/java/forge/properties/ForgeConstants.java @@ -17,17 +17,22 @@ */ package forge.properties; -import forge.GuiBase; - import java.util.Collections; import java.util.Map; +import forge.interfaces.IGuiBase; + public final class ForgeConstants { - public static final String ASSETS_DIR = GuiBase.getInterface().getAssetsDir(); - public static final String PROFILE_FILE = ASSETS_DIR + "forge.profile.properties"; + public static void init(final IGuiBase gui) { + ASSETS_DIR = gui.getAssetsDir(); + } + + private static String ASSETS_DIR; + public static String ASSETS_DIR() { return ASSETS_DIR; } + public static final String PROFILE_FILE = ASSETS_DIR() + "forge.profile.properties"; public static final String PROFILE_TEMPLATE_FILE = PROFILE_FILE + ".example"; - public static final String RES_DIR = ASSETS_DIR + "res/"; + public static final String RES_DIR = ASSETS_DIR() + "res/"; public static final String LISTS_DIR = RES_DIR + "lists/"; public static final String KEYWORD_LIST_FILE = LISTS_DIR + "NonStackingKWList.txt"; public static final String TYPE_LIST_FILE = LISTS_DIR + "TypeLists.txt"; @@ -41,9 +46,9 @@ public final class ForgeConstants { public static final String IMAGE_LIST_QUEST_PRECONS_FILE = LISTS_DIR + "precon-images.txt"; public static final String IMAGE_LIST_QUEST_TOURNAMENTPACKS_FILE = LISTS_DIR + "tournamentpack-images.txt"; - public static final String CHANGES_FILE = ASSETS_DIR + "CHANGES.txt"; - public static final String LICENSE_FILE = ASSETS_DIR + "LICENSE.txt"; - public static final String README_FILE = ASSETS_DIR + "README.txt"; + public static final String CHANGES_FILE = ASSETS_DIR() + "CHANGES.txt"; + public static final String LICENSE_FILE = ASSETS_DIR() + "LICENSE.txt"; + public static final String README_FILE = ASSETS_DIR() + "README.txt"; public static final String HOWTO_FILE = RES_DIR + "howto.txt"; public static final String DRAFT_DIR = RES_DIR + "draft/"; diff --git a/forge-gui/src/main/java/forge/properties/ForgeProfileProperties.java b/forge-gui/src/main/java/forge/properties/ForgeProfileProperties.java index d30fa8afcf7..cdcd1fa93ce 100644 --- a/forge-gui/src/main/java/forge/properties/ForgeProfileProperties.java +++ b/forge-gui/src/main/java/forge/properties/ForgeProfileProperties.java @@ -17,25 +17,26 @@ */ package forge.properties; -import forge.GuiBase; -import forge.util.FileSection; -import forge.util.FileUtil; - -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.tuple.Pair; - import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.Map; import java.util.Properties; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; + +import forge.interfaces.IGuiBase; +import forge.util.FileSection; +import forge.util.FileUtil; + /** * Determines the user data and cache dirs, first looking at the specified file for overrides * then falling back to platform-specific defaults. Resulting dir strings are guaranteed to end in a slash * so they can be easily appended with further path elements. */ public class ForgeProfileProperties { + private static boolean isRunningOnDesktop; private static String userDir; private static String cacheDir; private static String cardPicsDir; @@ -52,6 +53,10 @@ public class ForgeProfileProperties { //prevent initializing static class } + public static void init(final IGuiBase gui) { + isRunningOnDesktop = gui.isRunningOnDesktop(); + } + public static void load() { Properties props = new Properties(); File propFile = new File(ForgeConstants.PROFILE_FILE); @@ -144,8 +149,8 @@ public class ForgeProfileProperties { // returns a pair private static Pair getDefaultDirs() { - if (!GuiBase.getInterface().isRunningOnDesktop()) { //special case for mobile devices - String assetsDir = ForgeConstants.ASSETS_DIR; + if (isRunningOnDesktop) { //special case for mobile devices + String assetsDir = ForgeConstants.ASSETS_DIR(); return Pair.of(assetsDir + "data" + File.separator, assetsDir + "cache" + File.separator); } diff --git a/forge-gui/src/main/java/forge/quest/QuestController.java b/forge-gui/src/main/java/forge/quest/QuestController.java index 1d119cea177..5d0f60318f8 100644 --- a/forge-gui/src/main/java/forge/quest/QuestController.java +++ b/forge-gui/src/main/java/forge/quest/QuestController.java @@ -24,16 +24,17 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; + import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.eventbus.Subscribe; -import forge.GuiBase; import forge.deck.Deck; import forge.deck.DeckGroup; import forge.game.GameFormat; import forge.game.event.GameEvent; import forge.game.event.GameEventMulligan; +import forge.interfaces.IGuiBase; import forge.item.PaperCard; import forge.item.PreconDeck; import forge.model.FModel; @@ -57,6 +58,7 @@ import forge.util.storage.StorageBase; */ public class QuestController { + private final IGuiBase gui; private QuestData model; // gadgets @@ -99,7 +101,15 @@ public class QuestController { /** */ public static final int MAX_PET_SLOTS = 2; - + + public QuestController(final IGuiBase gui) { + this.gui = gui; + } + + public final IGuiBase getGui() { + return this.gui; + } + /** * * TODO: Write javadoc for this method. @@ -471,7 +481,7 @@ public class QuestController { if (ev instanceof GameEventMulligan) { GameEventMulligan mev = (GameEventMulligan) ev; // First mulligan is free - if (mev.player.getLobbyPlayer() == GuiBase.getInterface().getQuestPlayer() + if (mev.player.getLobbyPlayer() == gui.getGuiPlayer() && getAssets().hasItem(QuestItemType.SLEIGHT) && mev.player.getStats().getMulliganCount() < 7) { mev.player.drawCard(); } diff --git a/forge-gui/src/main/java/forge/quest/QuestDraftUtils.java b/forge-gui/src/main/java/forge/quest/QuestDraftUtils.java index be1863aca75..c62fca7fd32 100644 --- a/forge-gui/src/main/java/forge/quest/QuestDraftUtils.java +++ b/forge-gui/src/main/java/forge/quest/QuestDraftUtils.java @@ -1,7 +1,9 @@ package forge.quest; +import java.util.ArrayList; +import java.util.List; + import forge.FThreads; -import forge.GuiBase; import forge.deck.Deck; import forge.deck.DeckGroup; import forge.deck.DeckSection; @@ -10,13 +12,11 @@ import forge.game.GameRules; import forge.game.GameType; import forge.game.Match; import forge.game.player.RegisteredPlayer; +import forge.interfaces.IGuiBase; import forge.model.FModel; import forge.properties.ForgePreferences.FPref; import forge.util.storage.IStorage; -import java.util.ArrayList; -import java.util.List; - public class QuestDraftUtils { private static List matchups = new ArrayList(); @@ -24,11 +24,11 @@ public class QuestDraftUtils { public static boolean aiMatchInProgress = false; private static boolean waitForUserInput = false; - public static void continueMatch(Game lastGame) { + public static void continueMatch(final Game lastGame, final IGuiBase gui) { if (lastGame.getMatch().isMatchOver()) { matchInProgress = false; } - GuiBase.getInterface().continueMatch(matchInProgress ? lastGame.getMatch() : null); + gui.continueMatch(matchInProgress ? lastGame.getMatch() : null); } public static void completeDraft(DeckGroup finishedDraft) { @@ -59,7 +59,7 @@ public class QuestDraftUtils { return null; } - public static void startNextMatch() { + public static void startNextMatch(final IGuiBase gui) { if (matchups.size() > 0) { return; @@ -82,38 +82,38 @@ public class QuestDraftUtils { switch (currentSet) { case 7: - addMatchup(0, 1, draft); - addMatchup(2, 3, draft); - addMatchup(4, 5, draft); - addMatchup(6, 7, draft); + addMatchup(0, 1, draft, gui); + addMatchup(2, 3, draft, gui); + addMatchup(4, 5, draft, gui); + addMatchup(6, 7, draft, gui); break; case 8: - addMatchup(2, 3, draft); - addMatchup(4, 5, draft); - addMatchup(6, 7, draft); + addMatchup(2, 3, draft, gui); + addMatchup(4, 5, draft, gui); + addMatchup(6, 7, draft, gui); break; case 9: - addMatchup(4, 5, draft); - addMatchup(6, 7, draft); + addMatchup(4, 5, draft, gui); + addMatchup(6, 7, draft, gui); break; case 10: - addMatchup(6, 7, draft); + addMatchup(6, 7, draft, gui); break; case 11: - addMatchup(8, 9, draft); - addMatchup(10, 11, draft); + addMatchup(8, 9, draft, gui); + addMatchup(10, 11, draft, gui); break; case 12: - addMatchup(10, 11, draft); + addMatchup(10, 11, draft, gui); break; case 13: - addMatchup(12, 13, draft); + addMatchup(12, 13, draft, gui); break; case 14: @@ -122,11 +122,11 @@ public class QuestDraftUtils { } - update(); + update(gui); } - private static void addMatchup(final int player1, final int player2, final QuestEventDraft draft) { + private static void addMatchup(final int player1, final int player2, final QuestEventDraft draft, final IGuiBase gui) { DraftMatchup matchup = new DraftMatchup(); DeckGroup decks = FModel.getQuest().getAssets().getDraftDeckStorage().get(QuestEventDraft.DECK_NAME); @@ -145,12 +145,12 @@ public class QuestDraftUtils { if (humanIndex > -1) { matchup.hasHumanPlayer = true; - matchup.matchStarter.add(new RegisteredPlayer(decks.getHumanDeck()).setPlayer(GuiBase.getInterface().getGuiPlayer())); + matchup.matchStarter.add(new RegisteredPlayer(decks.getHumanDeck()).setPlayer(gui.getGuiPlayer())); int aiName = Integer.parseInt(draft.getStandings()[aiIndex]) - 1; int aiDeckIndex = Integer.parseInt(draft.getStandings()[aiIndex]) - 1; - matchup.matchStarter.add(new RegisteredPlayer(decks.getAiDecks().get(aiDeckIndex)).setPlayer(GuiBase.getInterface().createAiPlayer(draft.getAINames()[aiName], draft.getAIIcons()[aiName]))); + matchup.matchStarter.add(new RegisteredPlayer(decks.getAiDecks().get(aiDeckIndex)).setPlayer(gui.createAiPlayer(draft.getAINames()[aiName], draft.getAIIcons()[aiName]))); } else { @@ -158,17 +158,17 @@ public class QuestDraftUtils { int aiName2 = Integer.parseInt(draft.getStandings()[player2]) - 1; int aiDeckIndex = Integer.parseInt(draft.getStandings()[player1]) - 1; - matchup.matchStarter.add(new RegisteredPlayer(decks.getAiDecks().get(aiDeckIndex)).setPlayer(GuiBase.getInterface().createAiPlayer(draft.getAINames()[aiName1], draft.getAIIcons()[aiName1]))); + matchup.matchStarter.add(new RegisteredPlayer(decks.getAiDecks().get(aiDeckIndex)).setPlayer(gui.createAiPlayer(draft.getAINames()[aiName1], draft.getAIIcons()[aiName1]))); aiDeckIndex = Integer.parseInt(draft.getStandings()[player2]) - 1; - matchup.matchStarter.add(new RegisteredPlayer(decks.getAiDecks().get(aiDeckIndex)).setPlayer(GuiBase.getInterface().createAiPlayer(draft.getAINames()[aiName2], draft.getAIIcons()[aiName2]))); + matchup.matchStarter.add(new RegisteredPlayer(decks.getAiDecks().get(aiDeckIndex)).setPlayer(gui.createAiPlayer(draft.getAINames()[aiName2], draft.getAIIcons()[aiName2]))); } matchups.add(matchup); } - public static void update() { + public static void update(final IGuiBase gui) { if (matchups.isEmpty()) { if (!matchInProgress) { aiMatchInProgress = false; @@ -184,14 +184,14 @@ public class QuestDraftUtils { return; } - GuiBase.getInterface().enableOverlay(); + gui.enableOverlay(); DraftMatchup nextMatch = matchups.remove(0); matchInProgress = true; if (!nextMatch.hasHumanPlayer) { - GuiBase.getInterface().disableOverlay(); + gui.disableOverlay(); waitForUserInput = false; aiMatchInProgress = true; } @@ -208,17 +208,17 @@ public class QuestDraftUtils { rules.canCloneUseTargetsImage = FModel.getPreferences().getPrefBoolean(FPref.UI_CLONE_MODE_SOURCE); final Match match = new Match(rules, nextMatch.matchStarter); - FThreads.invokeInEdtLater(new Runnable(){ + FThreads.invokeInEdtLater(gui, new Runnable(){ @Override public void run() { - GuiBase.getInterface().startGame(match); + gui.startGame(match); } }); } - public static void continueMatches() { + public static void continueMatches(final IGuiBase gui) { waitForUserInput = false; - update(); + update(gui); } private static class DraftMatchup { diff --git a/forge-gui/src/main/java/forge/quest/QuestEventDraft.java b/forge-gui/src/main/java/forge/quest/QuestEventDraft.java index b5c5f44cb72..c9819f0937e 100644 --- a/forge-gui/src/main/java/forge/quest/QuestEventDraft.java +++ b/forge-gui/src/main/java/forge/quest/QuestEventDraft.java @@ -17,8 +17,17 @@ */ package forge.quest; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.List; +import java.util.Map; + import com.google.common.base.Function; -import forge.GuiBase; + import forge.card.CardEdition; import forge.card.CardEdition.CardInSet; import forge.card.CardRarity; @@ -26,6 +35,7 @@ import forge.deck.CardPool; import forge.deck.Deck; import forge.deck.DeckGroup; import forge.deck.DeckSection; +import forge.interfaces.IGuiBase; import forge.item.BoosterPack; import forge.item.PaperCard; import forge.limited.BoosterDraft; @@ -37,9 +47,6 @@ import forge.quest.io.ReadPriceList; import forge.util.NameGenerator; import forge.util.storage.IStorage; -import java.text.SimpleDateFormat; -import java.util.*; - /** *

* QuestEvent. @@ -657,18 +664,18 @@ public class QuestEventDraft { return output; } - - public boolean canEnter() { - long creditsAvailable = FModel.getQuest().getAssets().getCredits(); - return creditsAvailable < getEntryFee(); - } - - public BoosterDraft enter() { - FModel.getQuest().getAchievements().setCurrentDraft(this); - FModel.getQuest().getAssets().subtractCredits(getEntryFee()); - return BoosterDraft.createDraft(LimitedPoolType.Block, FModel.getBlocks().get(getBlock()), getBoosterConfiguration()); - } - + + public boolean canEnter() { + long creditsAvailable = FModel.getQuest().getAssets().getCredits(); + return creditsAvailable < getEntryFee(); + } + + public BoosterDraft enter(final IGuiBase gui) { + FModel.getQuest().getAchievements().setCurrentDraft(this); + FModel.getQuest().getAssets().subtractCredits(getEntryFee()); + return BoosterDraft.createDraft(gui, LimitedPoolType.Block, FModel.getBlocks().get(getBlock()), getBoosterConfiguration()); + } + public boolean isStarted() { return started; } @@ -790,14 +797,14 @@ public class QuestEventDraft { } List usedNames = new ArrayList(); - usedNames.add(GuiBase.getInterface().getGuiPlayer().getName()); + usedNames.add(quest.getGui().getGuiPlayer().getName()); for (int i = 0; i < 7; i++) { event.aiNames[i] = NameGenerator.getRandomName("Any", "Any", usedNames); usedNames.add(event.aiNames[i]); } - int numberOfIcons = GuiBase.getInterface().getAvatarCount(); + int numberOfIcons = quest.getGui().getAvatarCount(); List usedIcons = new ArrayList(); for (int i = 0; i < 7; i++) { diff --git a/forge-gui/src/main/java/forge/quest/QuestSpellShop.java b/forge-gui/src/main/java/forge/quest/QuestSpellShop.java index 84fcbc437a8..1ee015be829 100644 --- a/forge-gui/src/main/java/forge/quest/QuestSpellShop.java +++ b/forge-gui/src/main/java/forge/quest/QuestSpellShop.java @@ -10,10 +10,10 @@ import org.apache.commons.lang3.tuple.Pair; import com.google.common.base.Function; -import forge.GuiBase; import forge.deck.CardPool; import forge.deck.Deck; import forge.deck.DeckSection; +import forge.interfaces.IGuiBase; import forge.item.BoosterBox; import forge.item.BoosterPack; import forge.item.BoxedProduct; @@ -151,7 +151,7 @@ public class QuestSpellShop { } }; - public static void buy(Iterable> items, IItemManager shopManager, IItemManager inventoryManager, boolean confirmPurchase) { + public static void buy(IGuiBase gui, Iterable> items, IItemManager shopManager, IItemManager inventoryManager, boolean confirmPurchase) { long totalCost = 0; ItemPool itemsToBuy = new ItemPool(InventoryItem.class); for (Entry itemEntry : items) { @@ -171,11 +171,11 @@ public class QuestSpellShop { long creditsShort = totalCost - FModel.getQuest().getAssets().getCredits(); if (creditsShort > 0) { - SOptionPane.showMessageDialog("You need " + creditsShort + " more credits to purchase the following " + suffix.toLowerCase() + ".\n" + displayList, title); + SOptionPane.showMessageDialog(gui, "You need " + creditsShort + " more credits to purchase the following " + suffix.toLowerCase() + ".\n" + displayList, title); return; } - if (confirmPurchase && !SOptionPane.showConfirmDialog("Pay " + totalCost + " credits to purchase the following " + + if (confirmPurchase && !SOptionPane.showConfirmDialog(gui, "Pay " + totalCost + " credits to purchase the following " + suffix.toLowerCase() + "?\n" + displayList, title, "Buy", "Cancel")) { return; } @@ -219,7 +219,7 @@ public class QuestSpellShop { final List remainingCards = new ArrayList<>(); while (((BoxedProduct) booster).boosterPacksRemaining() > 0 && !skipTheRest) { - skipTheRest = GuiBase.getInterface().showBoxedProduct(booster.getName(), "You have found the following cards inside (Booster Pack " + (totalPacks - ((BoxedProduct) booster).boosterPacksRemaining() + 1) + " of " + totalPacks + "):", ((BoxedProduct) booster).getNextBoosterPack()); + skipTheRest = gui.showBoxedProduct(booster.getName(), "You have found the following cards inside (Booster Pack " + (totalPacks - ((BoxedProduct) booster).boosterPacksRemaining() + 1) + " of " + totalPacks + "):", ((BoxedProduct) booster).getNextBoosterPack()); } if (skipTheRest) { @@ -231,12 +231,12 @@ public class QuestSpellShop { remainingCards.addAll(((BoxedProduct) booster).getExtraCards()); if (remainingCards.size() > 0) { - GuiBase.getInterface().showCardList(booster.getName(), "You have found the following cards inside:", remainingCards); + gui.showCardList(booster.getName(), "You have found the following cards inside:", remainingCards); } } else { - GuiBase.getInterface().showCardList(booster.getName(), "You have found the following cards inside:", newCards); + gui.showCardList(booster.getName(), "You have found the following cards inside:", newCards); } } } @@ -249,7 +249,7 @@ public class QuestSpellShop { } boolean one = (qty == 1); - SOptionPane.showMessageDialog(String.format( + SOptionPane.showMessageDialog(gui, String.format( "%s '%s' %s added to your decklist.%n%n%s cards were also added to your pool.", one ? "Deck" : String.format("%d copies of deck", qty), deck.getName(), one ? "was" : "were", one ? "Its" : "Their"), @@ -261,7 +261,7 @@ public class QuestSpellShop { inventoryManager.addItems(itemsToAdd); } - public static void sell(Iterable> items, IItemManager shopManager, IItemManager inventoryManager, boolean confirmSale) { + public static void sell(final IGuiBase gui, Iterable> items, IItemManager shopManager, IItemManager inventoryManager, boolean confirmSale) { long totalReceived = 0; ItemPool itemsToSell = new ItemPool(InventoryItem.class); for (Entry itemEntry : items) { @@ -280,7 +280,7 @@ public class QuestSpellShop { String displayList = SItemManagerUtil.buildDisplayList(itemsToSell); String title = "Sell " + suffix; - if (!SOptionPane.showConfirmDialog("Sell the following " + suffix.toLowerCase() + " for " + totalReceived + + if (!SOptionPane.showConfirmDialog(gui, "Sell the following " + suffix.toLowerCase() + " for " + totalReceived + " credit" + (totalReceived != 1 ? "s" : "") + "?\n" + displayList, title, "Sell", "Cancel")) { return; } diff --git a/forge-gui/src/main/java/forge/quest/QuestUtil.java b/forge-gui/src/main/java/forge/quest/QuestUtil.java index ccbd1076c54..f0e3d0105e0 100644 --- a/forge-gui/src/main/java/forge/quest/QuestUtil.java +++ b/forge-gui/src/main/java/forge/quest/QuestUtil.java @@ -17,8 +17,12 @@ */ package forge.quest; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.tuple.ImmutablePair; + import forge.FThreads; -import forge.GuiBase; import forge.LobbyPlayer; import forge.assets.FSkinProp; import forge.card.CardDb.SetPreference; @@ -31,6 +35,7 @@ import forge.game.Match; import forge.game.card.Card; import forge.game.player.RegisteredPlayer; import forge.interfaces.IButton; +import forge.interfaces.IGuiBase; import forge.item.IPaperCard; import forge.item.PaperToken; import forge.model.FModel; @@ -44,11 +49,6 @@ import forge.quest.data.QuestPreferences.QPref; import forge.util.gui.SGuiChoose; import forge.util.gui.SOptionPane; -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.lang3.tuple.ImmutablePair; - /** *

* QuestUtil class. @@ -191,8 +191,8 @@ public class QuestUtil { return FModel.getMagicDb().getCommonCards().getCardFromEdition(name, SetPreference.Latest); } - public static void travelWorld() { - if (!checkActiveQuest("Travel between worlds.")) { + public static void travelWorld(final IGuiBase gui) { + if (!checkActiveQuest(gui, "Travel between worlds.")) { return; } List worlds = new ArrayList(); @@ -205,12 +205,12 @@ public class QuestUtil { } if (worlds.size() < 1) { - SOptionPane.showErrorDialog("There are currently no worlds you can travel to\nin this version of Forge.", "No Worlds"); + SOptionPane.showErrorDialog(gui, "There are currently no worlds you can travel to\nin this version of Forge.", "No Worlds"); return; } final String setPrompt = "Where do you wish to travel?"; - final QuestWorld newWorld = SGuiChoose.oneOrNone(setPrompt, worlds); + final QuestWorld newWorld = SGuiChoose.oneOrNone(gui, setPrompt, worlds); if (worlds.indexOf(newWorld) < 0) { return; @@ -221,7 +221,7 @@ public class QuestUtil { if (nextChallengeInWins() < 1 && qCtrl.getAchievements().getCurrentChallenges().size() > 0) { needRemove = true; - if (!SOptionPane.showConfirmDialog( + if (!SOptionPane.showConfirmDialog(gui, "You have uncompleted challenges in your current world. If you travel now, they will be LOST!" + "\nAre you sure you wish to travel anyway?\n" + "(Click \"No\" to go back and complete your current challenges first.)", @@ -466,11 +466,11 @@ public class QuestUtil { return draftEvent; } - public static boolean checkActiveQuest(String location) { + public static boolean checkActiveQuest(final IGuiBase gui, final String location) { QuestController qc = FModel.getQuest(); if (qc == null || qc.getAssets() == null) { String msg = "Please create a Quest before attempting to " + location; - SOptionPane.showErrorDialog(msg, "No Quest"); + SOptionPane.showErrorDialog(gui, msg, "No Quest"); System.out.println(msg); return false; } @@ -478,24 +478,24 @@ public class QuestUtil { } /** */ - public static void showSpellShop() { - if (!checkActiveQuest("Visit the Spell Shop.")) { + public static void showSpellShop(final IGuiBase gui) { + if (!checkActiveQuest(gui, "Visit the Spell Shop.")) { return; } - GuiBase.getInterface().showSpellShop(); + gui.showSpellShop(); } /** */ - public static void showBazaar() { - if (!checkActiveQuest("Visit the Bazaar.")) { + public static void showBazaar(final IGuiBase gui) { + if (!checkActiveQuest(gui, "Visit the Bazaar.")) { return; } - GuiBase.getInterface().showBazaar(); + gui.showBazaar(); } /** */ - public static void chooseAndUnlockEdition() { - if (!checkActiveQuest("Unlock Editions.")) { + public static void chooseAndUnlockEdition(final IGuiBase gui) { + if (!checkActiveQuest(gui, "Unlock Editions.")) { return; } final QuestController qData = FModel.getQuest(); @@ -506,19 +506,19 @@ public class QuestUtil { CardEdition unlocked = toUnlock.left; qData.getAssets().subtractCredits(toUnlock.right); - SOptionPane.showMessageDialog("You have successfully unlocked " + unlocked.getName() + "!", + SOptionPane.showMessageDialog(gui, "You have successfully unlocked " + unlocked.getName() + "!", unlocked.getName() + " unlocked!", null); - QuestUtilUnlockSets.doUnlock(qData, unlocked); + QuestUtilUnlockSets.doUnlock(gui, qData, unlocked); } - public static void startGame() { - if (canStartGame()) { - finishStartingGame(); + public static void startGame(final IGuiBase gui) { + if (canStartGame(gui)) { + finishStartingGame(gui); } } - public static void finishStartingGame() { + public static void finishStartingGame(final IGuiBase gui) { final QuestController qData = FModel.getQuest(); FThreads.invokeInBackgroundThread(new Runnable() { @@ -564,10 +564,10 @@ public class QuestUtil { } List starter = new ArrayList(); - starter.add(humanStart.setPlayer(GuiBase.getInterface().getQuestPlayer())); + starter.add(humanStart.setPlayer(gui.getQuestPlayer())); - LobbyPlayer aiPlayer = GuiBase.getInterface().getAiPlayer(event.getOpponent() == null ? event.getTitle() : event.getOpponent()); - GuiBase.getInterface().setPlayerAvatar(aiPlayer, event); + LobbyPlayer aiPlayer = gui.getAiPlayer(event.getOpponent() == null ? event.getTitle() : event.getOpponent()); + gui.setPlayerAvatar(aiPlayer, event); starter.add(aiStart.setPlayer(aiPlayer)); boolean useRandomFoil = FModel.getPreferences().getPrefBoolean(FPref.UI_RANDOM_FOIL); @@ -585,10 +585,10 @@ public class QuestUtil { rules.setManaBurn(FModel.getPreferences().getPrefBoolean(FPref.UI_MANABURN)); rules.canCloneUseTargetsImage = FModel.getPreferences().getPrefBoolean(FPref.UI_CLONE_MODE_SOURCE); final Match mc = new Match(rules, starter); - FThreads.invokeInEdtNowOrLater(new Runnable(){ + FThreads.invokeInEdtNowOrLater(gui, new Runnable(){ @Override public void run() { - GuiBase.getInterface().startGame(mc); + gui.startGame(mc); } }); } @@ -610,15 +610,15 @@ public class QuestUtil { * Checks to see if a game can be started and displays relevant dialogues. * @return */ - public static boolean canStartGame() { - if (!checkActiveQuest("Start a duel.") || null == event) { + public static boolean canStartGame(final IGuiBase gui) { + if (!checkActiveQuest(gui, "Start a duel.") || null == event) { return false; } Deck deck = getDeckForNewGame(); if (deck == null) { String msg = "Please select a Quest Deck."; - SOptionPane.showErrorDialog(msg, "No Deck"); + SOptionPane.showErrorDialog(gui, msg, "No Deck"); System.out.println(msg); return false; } @@ -626,7 +626,7 @@ public class QuestUtil { if (FModel.getPreferences().getPrefBoolean(FPref.ENFORCE_DECK_LEGALITY)) { String errorMessage = GameType.Quest.getDeckFormat().getDeckConformanceProblem(deck); if (null != errorMessage) { - SOptionPane.showErrorDialog("Your deck " + errorMessage + " Please edit or choose a different deck.", "Invalid Deck"); + SOptionPane.showErrorDialog(gui, "Your deck " + errorMessage + " Please edit or choose a different deck.", "Invalid Deck"); return false; } } diff --git a/forge-gui/src/main/java/forge/quest/QuestUtilUnlockSets.java b/forge-gui/src/main/java/forge/quest/QuestUtilUnlockSets.java index 057ce5fe391..42adb4f7a39 100644 --- a/forge-gui/src/main/java/forge/quest/QuestUtilUnlockSets.java +++ b/forge-gui/src/main/java/forge/quest/QuestUtilUnlockSets.java @@ -17,13 +17,22 @@ */ package forge.quest; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.EnumSet; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang3.tuple.ImmutablePair; + import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; -import forge.GuiBase; import forge.card.CardEdition; import forge.card.UnOpenedProduct; +import forge.interfaces.IGuiBase; import forge.item.PaperCard; import forge.item.SealedProduct; import forge.model.FModel; @@ -32,10 +41,6 @@ import forge.util.gui.SGuiChoose; import forge.util.gui.SOptionPane; import forge.util.storage.IStorage; -import org.apache.commons.lang3.tuple.ImmutablePair; - -import java.util.*; - /** * This is a helper class for unlocking new sets during a format-limited * quest. @@ -77,7 +82,7 @@ public class QuestUtilUnlockSets { options.add(String.format("%s [PRICE: %d credits]", ee.left.getName(), ee.right)); } - int index = options.indexOf(SGuiChoose.oneOrNone(setPrompt, options)); + int index = options.indexOf(SGuiChoose.oneOrNone(qData.getGui(), setPrompt, options)); if (index < 0 || index >= options.size()) { return null; } @@ -88,7 +93,8 @@ public class QuestUtilUnlockSets { CardEdition choosenEdition = toBuy.left; if (qData.getAssets().getCredits() < price) { - SOptionPane.showMessageDialog("Unfortunately, you cannot afford that set yet.\n" + SOptionPane.showMessageDialog(qData.getGui(), + "Unfortunately, you cannot afford that set yet.\n" + "To unlock " + choosenEdition.getName() + ", you need " + price + " credits.\n" + "You have only " + qData.getAssets().getCredits() + " credits.", "Failed to unlock " + choosenEdition.getName(), @@ -96,7 +102,7 @@ public class QuestUtilUnlockSets { return null; } - if (!SOptionPane.showConfirmDialog( + if (!SOptionPane.showConfirmDialog(qData.getGui(), "Unlocking " + choosenEdition.getName() + " will cost you " + price + " credits.\n" + "You have " + qData.getAssets().getCredits() + " credits.\n\n" + "Are you sure you want to unlock " + choosenEdition.getName() + "?", @@ -173,7 +179,7 @@ public class QuestUtilUnlockSets { * @param qData the quest controller * @param unlockedSet the edition to unlock */ - public static void doUnlock(QuestController qData, final CardEdition unlockedSet) { + public static void doUnlock(final IGuiBase gui, final QuestController qData, final CardEdition unlockedSet) { IStorage starters = FModel.getMagicDb().getTournamentPacks(); IStorage boosters = FModel.getMagicDb().getBoosters(); qData.getFormat().unlockSet(unlockedSet.getCode()); @@ -192,7 +198,7 @@ public class QuestUtilUnlockSets { } qData.getCards().addAllCards(cardsWon); - GuiBase.getInterface().showCardList(unlockedSet.getName(), "You get the following bonus cards:", cardsWon); + gui.showCardList(unlockedSet.getName(), "You get the following bonus cards:", cardsWon); qData.save(); } } diff --git a/forge-gui/src/main/java/forge/quest/QuestWinLoseController.java b/forge-gui/src/main/java/forge/quest/QuestWinLoseController.java index 15f0804c790..ca03f237931 100644 --- a/forge-gui/src/main/java/forge/quest/QuestWinLoseController.java +++ b/forge-gui/src/main/java/forge/quest/QuestWinLoseController.java @@ -8,21 +8,19 @@ import java.util.Map.Entry; import org.apache.commons.lang3.StringUtils; -import forge.GuiBase; import forge.LobbyPlayer; import forge.assets.FSkinProp; import forge.card.CardEdition; import forge.card.IUnOpenedProduct; import forge.card.UnOpenedProduct; -import forge.game.Game; import forge.game.GameEndReason; import forge.game.GameFormat; import forge.game.GameOutcome; import forge.game.player.GameLossReason; -import forge.game.player.Player; import forge.game.player.PlayerOutcome; import forge.game.player.PlayerStatistics; import forge.interfaces.IButton; +import forge.interfaces.IGuiBase; import forge.interfaces.IWinLoseView; import forge.item.BoosterPack; import forge.item.InventoryItem; @@ -42,16 +40,18 @@ import forge.view.PlayerView; public abstract class QuestWinLoseController { private final IGameView lastGame; + private final IGuiBase gui; private final transient boolean wonMatch; private final transient boolean isAnte; private final transient QuestController qData; private final transient QuestEvent qEvent; - public QuestWinLoseController(final IGameView game0) { + public QuestWinLoseController(final IGameView game0, final IGuiBase gui) { lastGame = game0; + this.gui = gui; qData = FModel.getQuest(); qEvent = qData.getCurrentEvent(); - wonMatch = lastGame.isMatchWonBy(GuiBase.getInterface().getQuestPlayer()); + wonMatch = lastGame.isMatchWonBy(gui.getQuestPlayer()); isAnte = FModel.getPreferences().getPrefBoolean(FPref.UI_ANTE); } @@ -65,7 +65,7 @@ public abstract class QuestWinLoseController { qc.getCards().getShopList(); } - final LobbyPlayer questLobbyPlayer = GuiBase.getInterface().getQuestPlayer(); + final LobbyPlayer questLobbyPlayer = gui.getQuestPlayer(); PlayerView player = null; for (final PlayerView p : lastGame.getPlayers()) { if (p.getLobbyPlayer().equals(questLobbyPlayer)) { @@ -240,8 +240,8 @@ public abstract class QuestWinLoseController { boolean hasNeverLost = true; int lifeDifferenceCredits = 0; - final LobbyPlayer localHuman = GuiBase.getInterface().getQuestPlayer(); - for (final GameOutcome game : lastGame.getMatch().getPlayedGames()) { + final LobbyPlayer localHuman = gui.getQuestPlayer(); + for (final GameOutcome game : lastGame.getOutcomesOfMatch()) { if (!game.isWinner(localHuman)) { hasNeverLost = false; continue; // no rewards for losing a game @@ -510,7 +510,7 @@ public abstract class QuestWinLoseController { Collections.sort(formats); - final GameFormat selected = SGuiChoose.getChoices("Choose bonus booster format", 1, 1, formats, pref, null).get(0); + final GameFormat selected = SGuiChoose.getChoices(gui, "Choose bonus booster format", 1, 1, formats, pref, null).get(0); FModel.getQuestPreferences().setPref(QPref.BOOSTER_FORMAT, selected.toString()); cardsWon = qData.getCards().generateQuestBooster(selected.getFilterPrinted()); @@ -547,7 +547,7 @@ public abstract class QuestWinLoseController { maxChoices--; } - final CardEdition chooseEd = SGuiChoose.one("Choose bonus booster set", options); + final CardEdition chooseEd = SGuiChoose.one(gui, "Choose bonus booster set", options); IUnOpenedProduct product = new UnOpenedProduct(FModel.getMagicDb().getBoosters().get(chooseEd.getCode())); cardsWon = product.get(); @@ -638,7 +638,7 @@ public abstract class QuestWinLoseController { } else if (ii instanceof IQuestRewardCard) { final List cardChoices = ((IQuestRewardCard) ii).getChoices(); - final PaperCard chosenCard = (null == cardChoices ? null : SGuiChoose.one("Choose " + ((IQuestRewardCard) ii).getName(), cardChoices)); + final PaperCard chosenCard = (null == cardChoices ? null : SGuiChoose.one(gui, "Choose " + ((IQuestRewardCard) ii).getName(), cardChoices)); if (null != chosenCard) { cardsWon.add(chosenCard); } diff --git a/forge-gui/src/main/java/forge/quest/bazaar/IQuestBazaarItem.java b/forge-gui/src/main/java/forge/quest/bazaar/IQuestBazaarItem.java index aeaba814430..4b7993f73db 100644 --- a/forge-gui/src/main/java/forge/quest/bazaar/IQuestBazaarItem.java +++ b/forge-gui/src/main/java/forge/quest/bazaar/IQuestBazaarItem.java @@ -17,7 +17,6 @@ */ package forge.quest.bazaar; -import forge.assets.ISkinImage; import forge.quest.data.QuestAssets; /** @@ -50,9 +49,9 @@ public interface IQuestBazaarItem extends Comparable { * getIcon. *

* - * @return the image that is displayed in the bazaar + * @return the image that is dispslayed in the bazaar */ - ISkinImage getIcon(QuestAssets qA); + String getIcon(QuestAssets qA); /** *

diff --git a/forge-gui/src/main/java/forge/quest/bazaar/QuestItemBasic.java b/forge-gui/src/main/java/forge/quest/bazaar/QuestItemBasic.java index 2f27cebcb2b..b0b4a4feb8f 100644 --- a/forge-gui/src/main/java/forge/quest/bazaar/QuestItemBasic.java +++ b/forge-gui/src/main/java/forge/quest/bazaar/QuestItemBasic.java @@ -17,15 +17,13 @@ */ package forge.quest.bazaar; +import org.apache.commons.lang3.StringUtils; + import com.thoughtworks.xstream.annotations.XStreamAsAttribute; -import forge.GuiBase; import forge.assets.FSkinProp; -import forge.assets.ISkinImage; import forge.quest.data.QuestAssets; -import org.apache.commons.lang3.StringUtils; - /** *

* Abstract QuestItemAbstract class. @@ -170,8 +168,8 @@ public class QuestItemBasic implements IQuestBazaarItem { * */ @Override - public ISkinImage getIcon(QuestAssets qA) { - return GuiBase.getInterface().getSkinIcon(icon); + public String getIcon(final QuestAssets qA) { + return icon.name(); } /** diff --git a/forge-gui/src/main/java/forge/quest/bazaar/QuestPetController.java b/forge-gui/src/main/java/forge/quest/bazaar/QuestPetController.java index 339ca40b1d2..1efb0cbca5b 100644 --- a/forge-gui/src/main/java/forge/quest/bazaar/QuestPetController.java +++ b/forge-gui/src/main/java/forge/quest/bazaar/QuestPetController.java @@ -17,19 +17,16 @@ */ package forge.quest.bazaar; +import java.util.ArrayList; +import java.util.List; + import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAsAttribute; -import forge.GuiBase; -import forge.assets.FSkinProp; -import forge.assets.ISkinImage; import forge.item.PaperToken; import forge.properties.ForgeConstants; import forge.quest.data.QuestAssets; -import java.util.ArrayList; -import java.util.List; - /** *

* Abstract QuestPetAbstract class. @@ -120,22 +117,10 @@ public class QuestPetController implements IQuestBazaarItem { * @return a {@link java.lang.String} object. */ @Override - public final ISkinImage getIcon(final QuestAssets qA) { + public final String getIcon(final QuestAssets qA) { final String path = ForgeConstants.CACHE_TOKEN_PICS_DIR; final int level = this.getPetLevel(qA); - try { - return GuiBase.getInterface().getUnskinnedIcon(path + this.levels.get(level < this.maxLevel ? level + 1 : level).getPicture() + ".jpg"); - } - catch (Exception e) { - e.printStackTrace(); - } - try { - return GuiBase.getInterface().getUnskinnedIcon(ForgeConstants.NO_CARD_FILE); - } - catch (Exception e) { - e.printStackTrace(); - } - return GuiBase.getInterface().getSkinIcon(FSkinProp.ICO_UNKNOWN); + return path + this.levels.get(level < this.maxLevel ? level + 1 : level).getPicture() + ".jpg"; } /** diff --git a/forge-gui/src/main/java/forge/quest/bazaar/QuestStallDefinition.java b/forge-gui/src/main/java/forge/quest/bazaar/QuestStallDefinition.java index 2b9ad6ae48d..64420a85b9f 100644 --- a/forge-gui/src/main/java/forge/quest/bazaar/QuestStallDefinition.java +++ b/forge-gui/src/main/java/forge/quest/bazaar/QuestStallDefinition.java @@ -17,15 +17,13 @@ */ package forge.quest.bazaar; +import java.util.ArrayList; +import java.util.List; + import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAsAttribute; -import forge.GuiBase; import forge.assets.FSkinProp; -import forge.assets.ISkinImage; - -import java.util.ArrayList; -import java.util.List; /** *

@@ -89,8 +87,8 @@ public class QuestStallDefinition { * * @return the icon */ - public ISkinImage getIcon() { - return GuiBase.getInterface().getSkinIcon(icon); + public FSkinProp getIcon() { + return icon; } /** diff --git a/forge-gui/src/main/java/forge/sound/EventVisualizer.java b/forge-gui/src/main/java/forge/sound/EventVisualizer.java index 5733b8bc4b1..06fc794b450 100644 --- a/forge-gui/src/main/java/forge/sound/EventVisualizer.java +++ b/forge-gui/src/main/java/forge/sound/EventVisualizer.java @@ -1,23 +1,49 @@ package forge.sound; -import forge.GuiBase; +import java.util.Collection; + +import forge.LobbyPlayer; import forge.events.IUiEventVisitor; import forge.events.UiEventAttackerDeclared; import forge.events.UiEventBlockerAssigned; import forge.game.card.Card; -import forge.game.event.*; +import forge.game.event.GameEvent; +import forge.game.event.GameEventBlockersDeclared; +import forge.game.event.GameEventCardAttachment; +import forge.game.event.GameEventCardChangeZone; +import forge.game.event.GameEventCardCounters; +import forge.game.event.GameEventCardDamaged; +import forge.game.event.GameEventCardDestroyed; +import forge.game.event.GameEventCardPhased; +import forge.game.event.GameEventCardRegenerated; +import forge.game.event.GameEventCardSacrificed; +import forge.game.event.GameEventCardTapped; +import forge.game.event.GameEventFlipCoin; +import forge.game.event.GameEventGameOutcome; +import forge.game.event.GameEventLandPlayed; +import forge.game.event.GameEventPlayerLivesChanged; +import forge.game.event.GameEventPlayerPoisoned; +import forge.game.event.GameEventShuffle; +import forge.game.event.GameEventSpellResolved; +import forge.game.event.GameEventTokenCreated; +import forge.game.event.GameEventTurnEnded; +import forge.game.event.IGameEventVisitor; import forge.game.spellability.SpellAbility; import forge.game.zone.ZoneType; +import forge.interfaces.IGuiBase; import forge.util.maps.MapOfLists; -import java.util.Collection; - /** * This class is in charge of converting any forge.game.event.Event to a SoundEffectType. * */ public class EventVisualizer extends IGameEventVisitor.Base implements IUiEventVisitor { + final LobbyPlayer player; + public EventVisualizer(final IGuiBase gui) { + this.player = gui.getGuiPlayer(); + } + public SoundEffectType visit(GameEventCardDamaged event) { return SoundEffectType.Damage; } public SoundEffectType visit(GameEventCardDestroyed event) { return SoundEffectType.Destroy; } public SoundEffectType visit(GameEventCardAttachment event) { return SoundEffectType.Equip; } @@ -41,7 +67,7 @@ public class EventVisualizer extends IGameEventVisitor.Base imp public SoundEffectType visit(GameEventShuffle event) { return SoundEffectType.Shuffle; } public SoundEffectType visit(GameEventTokenCreated event) { return SoundEffectType.Token; } public SoundEffectType visit(GameEventBlockersDeclared event) { - boolean isLocalHuman = event.defendingPlayer.getLobbyPlayer() == GuiBase.getInterface().getGuiPlayer(); + final boolean isLocalHuman = event.defendingPlayer.getLobbyPlayer() == player; if (isLocalHuman) return null; // already played sounds in interactive mode @@ -60,7 +86,7 @@ public class EventVisualizer extends IGameEventVisitor.Base imp * Plays the sound corresponding to the outcome of the duel. */ public SoundEffectType visit(GameEventGameOutcome event) { - boolean humanWonTheDuel = event.result.getWinningLobbyPlayer() == GuiBase.getInterface().getGuiPlayer(); + boolean humanWonTheDuel = event.result.getWinningLobbyPlayer() == player; return humanWonTheDuel ? SoundEffectType.WinDuel : SoundEffectType.LoseDuel; } diff --git a/forge-gui/src/main/java/forge/sound/SoundSystem.java b/forge-gui/src/main/java/forge/sound/SoundSystem.java index 2891b3d9722..e36ae011731 100644 --- a/forge-gui/src/main/java/forge/sound/SoundSystem.java +++ b/forge-gui/src/main/java/forge/sound/SoundSystem.java @@ -1,18 +1,18 @@ package forge.sound; -import com.google.common.eventbus.Subscribe; - -import forge.GuiBase; -import forge.events.UiEvent; -import forge.game.event.GameEvent; -import forge.model.FModel; -import forge.properties.ForgeConstants; -import forge.properties.ForgePreferences.FPref; - import java.util.EnumMap; import java.util.HashMap; import java.util.Map; +import com.google.common.eventbus.Subscribe; + +import forge.events.UiEvent; +import forge.game.event.GameEvent; +import forge.interfaces.IGuiBase; +import forge.model.FModel; +import forge.properties.ForgeConstants; +import forge.properties.ForgePreferences.FPref; + /** * Manages playback of all sounds for the client. * @@ -24,8 +24,13 @@ public class SoundSystem { private static final Map loadedClips = new EnumMap(SoundEffectType.class); private static final Map loadedScriptClips = new HashMap(); - private final EventVisualizer visualizer = new EventVisualizer(); + private final IGuiBase gui; + private final EventVisualizer visualizer; + public SoundSystem(final IGuiBase gui) { + this.gui = gui; + this.visualizer = new EventVisualizer(gui); + } private boolean isUsingAltSystem() { return FModel.getPreferences().getPrefBoolean(FPref.UI_ALT_SOUND_SYSTEM); } @@ -45,7 +50,7 @@ public class SoundSystem { IAudioClip clip = loadedClips.get(type); if (clip == null) { // cache miss String resource = type.getResourceFileName(); - clip = GuiBase.getInterface().createAudioClip(resource); + clip = gui.createAudioClip(resource); if (clip == null) { clip = emptySound; } @@ -67,7 +72,7 @@ public class SoundSystem { IAudioClip clip = loadedScriptClips.get(fileName); if (null == clip) { // cache miss - clip = GuiBase.getInterface().createAudioClip(fileName); + clip = gui.createAudioClip(fileName); if (clip == null) { clip = emptySound; } @@ -82,7 +87,7 @@ public class SoundSystem { */ public void play(String resourceFileName, boolean isSynchronized) { if (isUsingAltSystem()) { - GuiBase.getInterface().startAltSoundSystem(ForgeConstants.SOUND_DIR + resourceFileName, isSynchronized); + gui.startAltSoundSystem(ForgeConstants.SOUND_DIR + resourceFileName, isSynchronized); } else { IAudioClip snd = fetchResource(resourceFileName); @@ -97,7 +102,7 @@ public class SoundSystem { */ public void play(SoundEffectType type, boolean isSynchronized) { if (isUsingAltSystem()) { - GuiBase.getInterface().startAltSoundSystem(ForgeConstants.SOUND_DIR + type.getResourceFileName(), isSynchronized); + gui.startAltSoundSystem(ForgeConstants.SOUND_DIR + type.getResourceFileName(), isSynchronized); } else { IAudioClip snd = fetchResource(type); @@ -183,7 +188,7 @@ public class SoundSystem { if (filename == null) { return; } try { - currentTrack = GuiBase.getInterface().createAudioMusic(filename); + currentTrack = gui.createAudioMusic(filename); currentTrack.play(new Runnable() { @Override public void run() { diff --git a/forge-gui/src/main/java/forge/util/DevModeUtil.java b/forge-gui/src/main/java/forge/util/DevModeUtil.java index 96c9a520662..604feaf8cf7 100644 --- a/forge-gui/src/main/java/forge/util/DevModeUtil.java +++ b/forge-gui/src/main/java/forge/util/DevModeUtil.java @@ -17,7 +17,6 @@ import java.util.Map.Entry; import com.google.common.base.Predicates; import com.google.common.collect.Lists; -import forge.GuiBase; import forge.LobbyPlayer; import forge.card.CardCharacteristicName; import forge.game.Game; @@ -40,6 +39,7 @@ import forge.match.input.InputPassPriority; import forge.match.input.InputSelectCardsFromList; import forge.model.FModel; import forge.player.HumanPlay; +import forge.player.PlayerControllerHuman; import forge.properties.ForgeConstants; import forge.util.gui.SGuiChoose; import forge.util.gui.SGuiDialog; @@ -50,10 +50,10 @@ public final class DevModeUtil { private DevModeUtil() { } - public static void devModeGenerateMana(final Game game) { + public static void devModeGenerateMana(final Game game, final PlayerControllerHuman controller) { Player pPriority = game.getPhaseHandler().getPriorityPlayer(); if (pPriority == null) { - SGuiDialog.message("No player has priority at the moment, so mana cannot be added to their pool."); + SGuiDialog.message(controller.getGui(), "No player has priority at the moment, so mana cannot be added to their pool."); return; } @@ -67,7 +67,7 @@ public final class DevModeUtil { }); } - public static void devSetupGameState(final Game game) { + public static void devSetupGameState(final Game game, final PlayerControllerHuman controller) { int humanLife = -1; int computerLife = -1; @@ -82,7 +82,7 @@ public final class DevModeUtil { gamesDir.mkdir(); } - String filename = GuiBase.getInterface().showFileDialog("Select Game State File", ForgeConstants.USER_GAMES_DIR); + String filename = controller.getGui().showFileDialog("Select Game State File", ForgeConstants.USER_GAMES_DIR); if (filename == null) { return; } @@ -125,22 +125,22 @@ public final class DevModeUtil { in.close(); } catch (final FileNotFoundException fnfe) { - SOptionPane.showErrorDialog("File not found: " + filename); + SOptionPane.showErrorDialog(controller.getGui(), "File not found: " + filename); } catch (final Exception e) { - SOptionPane.showErrorDialog("Error loading battle setup file!"); + SOptionPane.showErrorDialog(controller.getGui(), "Error loading battle setup file!"); return; } - setupGameState(game, humanLife, computerLife, humanCardTexts, aiCardTexts, tChangePlayer, tChangePhase); + setupGameState(game, humanLife, computerLife, humanCardTexts, aiCardTexts, tChangePlayer, tChangePhase, controller); } private static void setupGameState(final Game game, final int humanLife, final int computerLife, final Map humanCardTexts, - final Map aiCardTexts, final String tChangePlayer, final String tChangePhase) { + final Map aiCardTexts, final String tChangePlayer, final String tChangePhase, final PlayerControllerHuman controller) { Player pPriority = game.getPhaseHandler().getPriorityPlayer(); if (pPriority == null) { - SGuiDialog.message("No player has priority at the moment, so game state cannot be setup."); + SGuiDialog.message(controller.getGui(), "No player has priority at the moment, so game state cannot be setup."); return; } game.getAction().invoke(new Runnable() { @@ -239,15 +239,15 @@ public final class DevModeUtil { * * @since 1.0.15 */ - public static void devModeTutor(final Game game) { + public static void devModeTutor(final Game game, final PlayerControllerHuman controller) { Player pPriority = game.getPhaseHandler().getPriorityPlayer(); if (pPriority == null) { - SGuiDialog.message("No player has priority at the moment, so their deck can't be tutored from."); + SGuiDialog.message(controller.getGui(), "No player has priority at the moment, so their deck can't be tutored from."); return; } final List lib = pPriority.getCardsIn(ZoneType.Library); - final Card card = SGuiChoose.oneOrNone("Choose a card", lib); + final Card card = SGuiChoose.oneOrNone(controller.getGui(), "Choose a card", lib); if (card == null) { return; } game.getAction().invoke(new Runnable() { @@ -265,14 +265,14 @@ public final class DevModeUtil { * * @since 1.0.15 */ - public static void devModeAddCounter(final Game game) { - final Card card = SGuiChoose.oneOrNone("Add counters to which card?", game.getCardsIn(ZoneType.Battlefield)); + public static void devModeAddCounter(final Game game, final PlayerControllerHuman controller) { + final Card card = SGuiChoose.oneOrNone(controller.getGui(), "Add counters to which card?", game.getCardsIn(ZoneType.Battlefield)); if (card == null) { return; } - final CounterType counter = SGuiChoose.oneOrNone("Which type of counter?", CounterType.values()); + final CounterType counter = SGuiChoose.oneOrNone(controller.getGui(), "Which type of counter?", CounterType.values()); if (counter == null) { return; } - final Integer count = SGuiChoose.getInteger("How many counters?", 1, Integer.MAX_VALUE, 10); + final Integer count = SGuiChoose.getInteger(controller.getGui(), "How many counters?", 1, Integer.MAX_VALUE, 10); if (count == null) { return; } card.addCounter(counter, count, false); @@ -285,12 +285,12 @@ public final class DevModeUtil { * * @since 1.0.15 */ - public static void devModeTapPerm(final Game game) { + public static void devModeTapPerm(final Game game, final PlayerControllerHuman controller) { game.getAction().invoke(new Runnable() { @Override public void run() { final List untapped = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), Predicates.not(CardPredicates.Presets.TAPPED)); - InputSelectCardsFromList inp = new InputSelectCardsFromList(0, Integer.MAX_VALUE, untapped); + InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, 0, Integer.MAX_VALUE, untapped); inp.setCancelAllowed(true); inp.setMessage("Choose permanents to tap"); inp.showAndWait(); @@ -310,12 +310,12 @@ public final class DevModeUtil { * * @since 1.0.15 */ - public static void devModeUntapPerm(final Game game) { + public static void devModeUntapPerm(final Game game, final PlayerControllerHuman controller) { game.getAction().invoke(new Runnable() { @Override public void run() { final List tapped = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.TAPPED); - InputSelectCardsFromList inp = new InputSelectCardsFromList(0, Integer.MAX_VALUE, tapped); + InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, 0, Integer.MAX_VALUE, tapped); inp.setCancelAllowed(true); inp.setMessage("Choose permanents to untap"); inp.showAndWait(); @@ -333,12 +333,12 @@ public final class DevModeUtil { * * @since 1.1.3 */ - public static void devModeSetLife(final Game game) { + public static void devModeSetLife(final Game game, final PlayerControllerHuman controller) { final List players = game.getPlayers(); - final Player player = SGuiChoose.oneOrNone("Set life for which player?", players); + final Player player = SGuiChoose.oneOrNone(controller.getGui(), "Set life for which player?", players); if (player == null) { return; } - final Integer life = SGuiChoose.getInteger("Set life to what?", 0); + final Integer life = SGuiChoose.getInteger(controller.getGui(), "Set life to what?", 0); if (life == null) { return; } player.setLife(life, null); @@ -351,14 +351,15 @@ public final class DevModeUtil { * * @since 1.5.23 */ - public static void devModeWinGame(final Game game, final LobbyPlayer guiPlayer) { - Input input = GuiBase.getInterface().getInputQueue().getInput(); + public static void devModeWinGame(final Game game, final PlayerControllerHuman controller) { + Input input = controller.getGui().getInputQueue().getInput(); if (!(input instanceof InputPassPriority)) { - SOptionPane.showMessageDialog("You must have priority to use this feature.", "Win Game", SOptionPane.INFORMATION_ICON); + SOptionPane.showMessageDialog(controller.getGui(), "You must have priority to use this feature.", "Win Game", SOptionPane.INFORMATION_ICON); return; } //set life of all other players to 0 + final LobbyPlayer guiPlayer = controller.getLobbyPlayer(); final List players = game.getPlayers(); for (Player player : players) { if (player.getLobbyPlayer() != guiPlayer) { @@ -377,9 +378,9 @@ public final class DevModeUtil { * * @since 1.2.7 */ - public static void devModeCardToHand(final Game game) { + public static void devModeCardToHand(final Game game, final PlayerControllerHuman controller) { final List players = game.getPlayers(); - final Player p = SGuiChoose.oneOrNone("Put card in hand for which player?", players); + final Player p = SGuiChoose.oneOrNone(controller.getGui(), "Put card in hand for which player?", players); if (null == p) { return; } @@ -388,7 +389,7 @@ public final class DevModeUtil { Collections.sort(cards); // use standard forge's list selection dialog - final IPaperCard c = SGuiChoose.oneOrNone("Name the card", cards); + final IPaperCard c = SGuiChoose.oneOrNone(controller.getGui(), "Name the card", cards); if (c == null) { return; } @@ -398,9 +399,9 @@ public final class DevModeUtil { }}); } - public static void devModeCardToBattlefield(final Game game) { + public static void devModeCardToBattlefield(final Game game, final PlayerControllerHuman controller) { final List players = game.getPlayers(); - final Player p = SGuiChoose.oneOrNone("Put card in play for which player?", players); + final Player p = SGuiChoose.oneOrNone(controller.getGui(), "Put card in play for which player?", players); if (null == p) { return; } @@ -409,7 +410,7 @@ public final class DevModeUtil { Collections.sort(cards); // use standard forge's list selection dialog - final IPaperCard c = SGuiChoose.oneOrNone("Name the card", cards); + final IPaperCard c = SGuiChoose.oneOrNone(controller.getGui(), "Name the card", cards); if (c == null) { return; } @@ -426,7 +427,7 @@ public final class DevModeUtil { return; // when would it happen? } - final SpellAbility sa = choices.size() == 1 ? choices.get(0) : SGuiChoose.oneOrNone("Choose", choices); + final SpellAbility sa = choices.size() == 1 ? choices.get(0) : SGuiChoose.oneOrNone(controller.getGui(), "Choose", choices); if (sa == null) { return; // happens if cancelled } @@ -434,19 +435,19 @@ public final class DevModeUtil { game.getAction().moveToHand(forgeCard); // this is really needed (for rollbacks at least) // Human player is choosing targets for an ability controlled by chosen player. sa.setActivatingPlayer(p); - HumanPlay.playSaWithoutPayingManaCost(game, sa, true); + HumanPlay.playSaWithoutPayingManaCost(controller, game, sa, true); } game.getStack().addAllTriggeredAbilitiesToStack(); // playSa could fire some triggers } }); } - public static void devModeRiggedPlanarRoll(final Game game) { + public static void devModeRiggedPlanarRoll(final Game game, final PlayerControllerHuman controller) { final List players = game.getPlayers(); - final Player player = SGuiChoose.oneOrNone("Which player should roll?", players); + final Player player = SGuiChoose.oneOrNone(controller.getGui(), "Which player should roll?", players); if (player == null) { return; } - final PlanarDice res = SGuiChoose.oneOrNone("Choose result", PlanarDice.values()); + final PlanarDice res = SGuiChoose.oneOrNone(controller.getGui(), "Choose result", PlanarDice.values()); if (res == null) { return; } System.out.println("Rigging planar dice roll: " + res.toString()); @@ -465,7 +466,7 @@ public final class DevModeUtil { }); } - public static void devModePlaneswalkTo(final Game game) { + public static void devModePlaneswalkTo(final Game game, final PlayerControllerHuman controller) { if (!game.getRules().hasAppliedVariant(GameType.Planechase)) { return; } final Player p = game.getPhaseHandler().getPlayerTurn(); @@ -478,7 +479,7 @@ public final class DevModeUtil { Collections.sort(allPlanars); // use standard forge's list selection dialog - final IPaperCard c = SGuiChoose.oneOrNone("Name the card", allPlanars); + final IPaperCard c = SGuiChoose.oneOrNone(controller.getGui(), "Name the card", allPlanars); if (c == null) { return; } final Card forgeCard = Card.fromPaperCard(c, p); diff --git a/forge-gui/src/main/java/forge/util/WaitCallback.java b/forge-gui/src/main/java/forge/util/WaitCallback.java deleted file mode 100644 index c8c488b0d64..00000000000 --- a/forge-gui/src/main/java/forge/util/WaitCallback.java +++ /dev/null @@ -1,34 +0,0 @@ -package forge.util; - -import forge.FThreads; - -public abstract class WaitCallback extends Callback implements Runnable { - public class Lock { - } - - private final Lock lock = new Lock(); - - private T result; - - @Override - public final void run(T result0) { - result = result0; - synchronized(lock) { - lock.notify(); - } - } - - public final T invokeAndWait() { - FThreads.assertExecutedByEdt(false); //not supported if on UI thread - FThreads.invokeInEdtLater(this); - try { - synchronized(lock) { - lock.wait(); - } - } - catch (InterruptedException e) { - e.printStackTrace(); - } - return result; - } -} diff --git a/forge-gui/src/main/java/forge/util/gui/SGuiChoose.java b/forge-gui/src/main/java/forge/util/gui/SGuiChoose.java index 4b37b65e2d5..c1874e66171 100644 --- a/forge-gui/src/main/java/forge/util/gui/SGuiChoose.java +++ b/forge-gui/src/main/java/forge/util/gui/SGuiChoose.java @@ -13,7 +13,7 @@ import com.google.common.base.Function; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; -import forge.GuiBase; +import forge.interfaces.IGuiBase; import forge.view.CardView; public class SGuiChoose { @@ -31,19 +31,19 @@ public class SGuiChoose { * getChoices. * @see #getChoices(String, int, int, Object...) */ - public static T oneOrNone(final String message, final T[] choices) { + public static T oneOrNone(final IGuiBase gui, final String message, final T[] choices) { if ((choices == null) || (choices.length == 0)) { return null; } - final List choice = SGuiChoose.getChoices(message, 0, 1, choices); + final List choice = SGuiChoose.getChoices(gui, message, 0, 1, choices); return choice.isEmpty() ? null : choice.get(0); } - public static T oneOrNone(final String message, final Collection choices) { + public static T oneOrNone(final IGuiBase gui, final String message, final Collection choices) { if ((choices == null) || choices.isEmpty()) { return null; } - final List choice = SGuiChoose.getChoices(message, 0, 1, choices); + final List choice = SGuiChoose.getChoices(gui, message, 0, 1, choices); return choice.isEmpty() ? null : choice.get(0); } @@ -61,13 +61,13 @@ public class SGuiChoose { * a T object. * @return a T object. */ - public static T one(final String message, final T[] choices) { - final List choice = SGuiChoose.getChoices(message, 1, 1, choices); + public static T one(final IGuiBase gui, final String message, final T[] choices) { + final List choice = SGuiChoose.getChoices(gui, message, 1, 1, choices); assert choice.size() == 1; return choice.get(0); } - public static T one(final String message, final Collection choices) { + public static T one(final IGuiBase gui, final String message, final Collection choices) { if (choices == null || choices.isEmpty()) { return null; } @@ -75,58 +75,58 @@ public class SGuiChoose { return Iterables.getFirst(choices, null); } - final List choice = SGuiChoose.getChoices(message, 1, 1, choices); + final List choice = SGuiChoose.getChoices(gui, message, 1, 1, choices); assert choice.size() == 1; return choice.get(0); } - public static List noneOrMany(final String message, final Collection choices) { - return SGuiChoose.getChoices(message, 0, choices.size(), choices, null, null); + public static List noneOrMany(final IGuiBase gui, final String message, final Collection choices) { + return SGuiChoose.getChoices(gui, message, 0, choices.size(), choices, null, null); } // Nothing to choose here. Code uses this to just reveal one or more items - public static void reveal(final String message, final T item) { + public static void reveal(final IGuiBase gui, final String message, final T item) { List items = new ArrayList(); items.add(item); - reveal(message, items); + reveal(gui, message, items); } - public static void reveal(final String message, final T[] items) { - SGuiChoose.getChoices(message, -1, -1, items); + public static void reveal(final IGuiBase gui, final String message, final T[] items) { + SGuiChoose.getChoices(gui, message, -1, -1, items); } - public static void reveal(final String message, final Collection items) { - SGuiChoose.getChoices(message, -1, -1, items); + public static void reveal(final IGuiBase gui, final String message, final Collection items) { + SGuiChoose.getChoices(gui, message, -1, -1, items); } // Get Integer in range - public static Integer getInteger(final String message) { - return getInteger(message, 0, Integer.MAX_VALUE); + public static Integer getInteger(final IGuiBase gui, final String message) { + return getInteger(gui, message, 0, Integer.MAX_VALUE); } - public static Integer getInteger(final String message, int min) { - return getInteger(message, min, Integer.MAX_VALUE); + public static Integer getInteger(final IGuiBase gui, final String message, int min) { + return getInteger(gui, message, min, Integer.MAX_VALUE); } - public static Integer getInteger(final String message, int min, int max) { + public static Integer getInteger(final IGuiBase gui, final String message, int min, int max) { if (max <= min) { return min; } //just return min if max <= min //force cutting off after 100 numbers at most if (max == Integer.MAX_VALUE) { - return getInteger(message, min, max, min + 99); + return getInteger(gui, message, min, max, min + 99); } int count = max - min + 1; if (count > 100) { - return getInteger(message, min, max, min + 99); + return getInteger(gui, message, min, max, min + 99); } final Integer[] choices = new Integer[count]; for (int i = 0; i < count; i++) { choices[i] = Integer.valueOf(i + min); } - return SGuiChoose.oneOrNone(message, choices); + return SGuiChoose.oneOrNone(gui, message, choices); } - public static Integer getInteger(final String message, int min, int max, int cutoff) { + public static Integer getInteger(final IGuiBase gui, final String message, int min, int max, int cutoff) { if (max <= min || cutoff < min) { return min; } //just return min if max <= min or cutoff < min if (cutoff >= max) { //fallback to regular integer prompt if cutoff at or after max - return getInteger(message, min, max); + return getInteger(gui, message, min, max); } List choices = new ArrayList(); @@ -135,7 +135,7 @@ public class SGuiChoose { } choices.add("Other..."); - Object choice = SGuiChoose.oneOrNone(message, choices); + Object choice = SGuiChoose.oneOrNone(gui, message, choices); if (choice instanceof Integer || choice == null) { return (Integer)choice; } @@ -156,7 +156,7 @@ public class SGuiChoose { prompt += ":"; while (true) { - String str = SOptionPane.showInputDialog(prompt, message); + String str = SOptionPane.showInputDialog(gui, prompt, message); if (str == null) { return null; } // that is 'cancel' if (StringUtils.isNumeric(str)) { @@ -169,30 +169,30 @@ public class SGuiChoose { } // returned Object will never be null - public static List getChoices(final String message, final int min, final int max, final T[] choices) { - return getChoices(message, min, max, Arrays.asList(choices), null, null); + public static List getChoices(final IGuiBase gui, final String message, final int min, final int max, final T[] choices) { + return getChoices(gui, message, min, max, Arrays.asList(choices), null, null); } - public static List getChoices(final String message, final int min, final int max, final Collection choices) { - return getChoices(message, min, max, choices, null, null); + public static List getChoices(final IGuiBase gui, final String message, final int min, final int max, final Collection choices) { + return getChoices(gui, message, min, max, choices, null, null); } - public static List getChoices(final String message, final int min, final int max, final Collection choices, final T selected, final Function display) { - return GuiBase.getInterface().getChoices(message, min, max, choices, selected, display); + public static List getChoices(final IGuiBase gui, final String message, final int min, final int max, final Collection choices, final T selected, final Function display) { + return gui.getChoices(message, min, max, choices, selected, display); } - public static List many(final String title, final String topCaption, int cnt, final List sourceChoices, final CardView referenceCard) { - return order(title, topCaption, cnt, cnt, sourceChoices, null, referenceCard, false); + public static List many(final IGuiBase gui, final String title, final String topCaption, int cnt, final List sourceChoices, final CardView referenceCard) { + return order(gui, title, topCaption, cnt, cnt, sourceChoices, null, referenceCard, false); } - public static List many(final String title, final String topCaption, int min, int max, final List sourceChoices, final CardView referenceCard) { + public static List many(final IGuiBase gui, final String title, final String topCaption, int min, int max, final List sourceChoices, final CardView referenceCard) { int m2 = min >= 0 ? sourceChoices.size() - min : -1; int m1 = max >= 0 ? sourceChoices.size() - max : -1; - return order(title, topCaption, m1, m2, sourceChoices, null, referenceCard, false); + return order(gui, title, topCaption, m1, m2, sourceChoices, null, referenceCard, false); } - public static List order(final String title, final String top, final List sourceChoices, final CardView referenceCard) { - return order(title, top, 0, 0, sourceChoices, null, referenceCard, false); + public static List order(final IGuiBase gui, final String title, final String top, final List sourceChoices, final CardView referenceCard) { + return order(gui, title, top, 0, 0, sourceChoices, null, referenceCard, false); } /** @@ -205,8 +205,8 @@ public class SGuiChoose { * @param oldItems the list of objects. * @return A shallow copy of the list of objects, with newItem inserted. */ - public static List insertInList(final String title, final T newItem, final List oldItems) { - final T placeAfter = oneOrNone(title, oldItems); + public static List insertInList(final IGuiBase gui, final String title, final T newItem, final List oldItems) { + final T placeAfter = oneOrNone(gui, title, oldItems); final int indexAfter = (placeAfter == null ? 0 : oldItems.indexOf(placeAfter) + 1); final List result = Lists.newArrayListWithCapacity(oldItems.size() + 1); result.addAll(oldItems); @@ -214,62 +214,62 @@ public class SGuiChoose { return result; } - private static List order(final String title, final String top, final int remainingObjectsMin, final int remainingObjectsMax, + private static List order(final IGuiBase gui, final String title, final String top, final int remainingObjectsMin, final int remainingObjectsMax, final List sourceChoices, final List destChoices, final CardView referenceCard, final boolean sideboardingMode) { - return GuiBase.getInterface().order(title, top, remainingObjectsMin, remainingObjectsMax, sourceChoices, destChoices, referenceCard, sideboardingMode); + return gui.order(title, top, remainingObjectsMin, remainingObjectsMax, sourceChoices, destChoices, referenceCard, sideboardingMode); } // If comparer is NULL, T has to be comparable. Otherwise you'll get an exception from inside the Arrays.sort() routine - public static T sortedOneOrNone(final String message, final T[] choices, Comparator comparer) { + public static T sortedOneOrNone(final IGuiBase gui, final String message, final T[] choices, Comparator comparer) { if ((choices == null) || (choices.length == 0)) { return null; } - final List choice = SGuiChoose.sortedGetChoices(message, 0, 1, choices, comparer); + final List choice = SGuiChoose.sortedGetChoices(gui, message, 0, 1, choices, comparer); return choice.isEmpty() ? null : choice.get(0); } // If comparer is NULL, T has to be comparable. Otherwise you'll get an exception from inside the Arrays.sort() routine - public static T sortedOneOrNone(final String message, final List choices, Comparator comparer) { + public static T sortedOneOrNone(final IGuiBase gui, final String message, final List choices, Comparator comparer) { if ((choices == null) || choices.isEmpty()) { return null; } - final List choice = SGuiChoose.sortedGetChoices(message, 0, 1, choices, comparer); + final List choice = SGuiChoose.sortedGetChoices(gui, message, 0, 1, choices, comparer); return choice.isEmpty() ? null : choice.get(0); } // If comparer is NULL, T has to be comparable. Otherwise you'll get an exception from inside the Arrays.sort() routine - public static T sortedOne(final String message, final T[] choices, Comparator comparer) { - final List choice = SGuiChoose.sortedGetChoices(message, 1, 1, choices, comparer); + public static T sortedOne(final IGuiBase gui, final String message, final T[] choices, Comparator comparer) { + final List choice = SGuiChoose.sortedGetChoices(gui, message, 1, 1, choices, comparer); assert choice.size() == 1; return choice.get(0); } // If comparer is NULL, T has to be comparable. Otherwise you'll get an exception from inside the Arrays.sort() routine - public static T sortedOne(final String message, final List choices, Comparator comparer) { + public static T sortedOne(final IGuiBase gui, final String message, final List choices, Comparator comparer) { if ((choices == null) || (choices.size() == 0)) { return null; } - final List choice = SGuiChoose.sortedGetChoices(message, 1, 1, choices, comparer); + final List choice = SGuiChoose.sortedGetChoices(gui, message, 1, 1, choices, comparer); assert choice.size() == 1; return choice.get(0); } // If comparer is NULL, T has to be comparable. Otherwise you'll get an exception from inside the Arrays.sort() routine - public static List sortedNoneOrMany(final String message, final List choices, Comparator comparer) { - return SGuiChoose.sortedGetChoices(message, 0, choices.size(), choices, comparer); + public static List sortedNoneOrMany(final IGuiBase gui, final String message, final List choices, Comparator comparer) { + return SGuiChoose.sortedGetChoices(gui, message, 0, choices.size(), choices, comparer); } // If comparer is NULL, T has to be comparable. Otherwise you'll get an exception from inside the Arrays.sort() routine - public static List sortedGetChoices(final String message, final int min, final int max, final T[] choices, Comparator comparer) { + public static List sortedGetChoices(final IGuiBase gui, final String message, final int min, final int max, final T[] choices, Comparator comparer) { // You may create a copy of source array if callers expect the collection to be unchanged Arrays.sort(choices, comparer); - return getChoices(message, min, max, choices); + return getChoices(gui, message, min, max, choices); } // If comparer is NULL, T has to be comparable. Otherwise you'll get an exception from inside the Arrays.sort() routine - public static List sortedGetChoices(final String message, final int min, final int max, final List choices, Comparator comparer) { + public static List sortedGetChoices(final IGuiBase gui, final String message, final int min, final int max, final List choices, Comparator comparer) { // You may create a copy of source list if callers expect the collection to be unchanged Collections.sort(choices, comparer); - return getChoices(message, min, max, choices); + return getChoices(gui, message, min, max, choices); } } diff --git a/forge-gui/src/main/java/forge/util/gui/SGuiDialog.java b/forge-gui/src/main/java/forge/util/gui/SGuiDialog.java index d18a1238605..1235e3d4435 100644 --- a/forge-gui/src/main/java/forge/util/gui/SGuiDialog.java +++ b/forge-gui/src/main/java/forge/util/gui/SGuiDialog.java @@ -2,6 +2,7 @@ package forge.util.gui; import org.apache.commons.lang3.StringUtils; +import forge.interfaces.IGuiBase; import forge.view.CardView; /** @@ -11,21 +12,21 @@ import forge.view.CardView; public class SGuiDialog { private static final String[] defaultConfirmOptions = { "Yes", "No" }; - public static boolean confirm(final CardView c, final String question) { - return SGuiDialog.confirm(c, question, true, null); + public static boolean confirm(final IGuiBase gui, final CardView c, final String question) { + return SGuiDialog.confirm(gui, c, question, true, null); } - public static boolean confirm(final CardView c, final String question, final boolean defaultChoice) { - return SGuiDialog.confirm(c, question, defaultChoice, null); + public static boolean confirm(final IGuiBase gui, final CardView c, final String question, final boolean defaultChoice) { + return SGuiDialog.confirm(gui, c, question, defaultChoice, null); } - public static boolean confirm(final CardView c, final String question, String[] options) { - return SGuiDialog.confirm(c, question, true, options); + public static boolean confirm(final IGuiBase gui, final CardView c, final String question, String[] options) { + return SGuiDialog.confirm(gui, c, question, true, options); } - public static boolean confirm(final CardView c, final String question, final boolean defaultIsYes, final String[] options) { + public static boolean confirm(final IGuiBase gui, final CardView c, final String question, final boolean defaultIsYes, final String[] options) { final String title = c == null ? "Question" : c + " - Ability"; String questionToUse = StringUtils.isBlank(question) ? "Activate card's ability?" : question; String[] opts = options == null ? defaultConfirmOptions : options; - int answer = SOptionPane.showCardOptionDialog(c, questionToUse, title, SOptionPane.QUESTION_ICON, opts, defaultIsYes ? 0 : 1); + int answer = SOptionPane.showCardOptionDialog(gui, c, questionToUse, title, SOptionPane.QUESTION_ICON, opts, defaultIsYes ? 0 : 1); return answer == 0; } @@ -37,11 +38,11 @@ public class SGuiDialog { * @param message * a {@link java.lang.String} object. */ - public static void message(final String message) { - message(message, "Forge"); + public static void message(final IGuiBase gui, final String message) { + message(gui, message, "Forge"); } - public static void message(final String message, final String title) { - SOptionPane.showMessageDialog(message, title, null); + public static void message(final IGuiBase gui, final String message, final String title) { + SOptionPane.showMessageDialog(gui, message, title, null); } } diff --git a/forge-gui/src/main/java/forge/util/gui/SOptionPane.java b/forge-gui/src/main/java/forge/util/gui/SOptionPane.java index d0feb812d16..442c984f289 100644 --- a/forge-gui/src/main/java/forge/util/gui/SOptionPane.java +++ b/forge-gui/src/main/java/forge/util/gui/SOptionPane.java @@ -1,7 +1,7 @@ package forge.util.gui; -import forge.GuiBase; import forge.assets.FSkinProp; +import forge.interfaces.IGuiBase; import forge.view.CardView; public class SOptionPane { @@ -10,74 +10,74 @@ public class SOptionPane { public static final FSkinProp WARNING_ICON = FSkinProp.ICO_WARNING; public static final FSkinProp ERROR_ICON = FSkinProp.ICO_ERROR; - public static void showMessageDialog(String message) { - showMessageDialog(message, "Forge", INFORMATION_ICON); + public static void showMessageDialog(IGuiBase gui, String message) { + showMessageDialog(gui, message, "Forge", INFORMATION_ICON); } - public static void showMessageDialog(String message, String title) { - showMessageDialog(message, title, INFORMATION_ICON); + public static void showMessageDialog(IGuiBase gui, String message, String title) { + showMessageDialog(gui, message, title, INFORMATION_ICON); } - public static void showErrorDialog(String message) { - showMessageDialog(message, "Forge", ERROR_ICON); + public static void showErrorDialog(IGuiBase gui, String message) { + showMessageDialog(gui, message, "Forge", ERROR_ICON); } - public static void showErrorDialog(String message, String title) { - showMessageDialog(message, title, ERROR_ICON); + public static void showErrorDialog(IGuiBase gui, String message, String title) { + showMessageDialog(gui, message, title, ERROR_ICON); } - public static void showMessageDialog(String message, String title, FSkinProp icon) { - showOptionDialog(message, title, icon, new String[] {"OK"}, 0); + public static void showMessageDialog(IGuiBase gui, String message, String title, FSkinProp icon) { + showOptionDialog(gui, message, title, icon, new String[] {"OK"}, 0); } - public static boolean showConfirmDialog(String message) { - return showConfirmDialog(message, "Forge"); + public static boolean showConfirmDialog(IGuiBase gui, String message) { + return showConfirmDialog(gui, message, "Forge"); } - public static boolean showConfirmDialog(String message, String title) { - return showConfirmDialog(message, title, "Yes", "No", true); + public static boolean showConfirmDialog(IGuiBase gui, String message, String title) { + return showConfirmDialog(gui, message, title, "Yes", "No", true); } - public static boolean showConfirmDialog(String message, String title, boolean defaultYes) { - return showConfirmDialog(message, title, "Yes", "No", defaultYes); + public static boolean showConfirmDialog(IGuiBase gui, String message, String title, boolean defaultYes) { + return showConfirmDialog(gui, message, title, "Yes", "No", defaultYes); } - public static boolean showConfirmDialog(String message, String title, String yesButtonText, String noButtonText) { - return showConfirmDialog(message, title, yesButtonText, noButtonText, true); + public static boolean showConfirmDialog(IGuiBase gui, String message, String title, String yesButtonText, String noButtonText) { + return showConfirmDialog(gui, message, title, yesButtonText, noButtonText, true); } - public static boolean showConfirmDialog(String message, String title, String yesButtonText, String noButtonText, boolean defaultYes) { + public static boolean showConfirmDialog(IGuiBase gui, String message, String title, String yesButtonText, String noButtonText, boolean defaultYes) { String[] options = {yesButtonText, noButtonText}; - int reply = SOptionPane.showOptionDialog(message, title, QUESTION_ICON, options, defaultYes ? 0 : 1); + int reply = SOptionPane.showOptionDialog(gui, message, title, QUESTION_ICON, options, defaultYes ? 0 : 1); return (reply == 0); } - public static int showOptionDialog(String message, String title, FSkinProp icon, String[] options) { - return showOptionDialog(message, title, icon, options, 0); + public static int showOptionDialog(IGuiBase gui, String message, String title, FSkinProp icon, String[] options) { + return showOptionDialog(gui, message, title, icon, options, 0); } - public static int showOptionDialog(String message, String title, FSkinProp icon, String[] options, int defaultOption) { - return GuiBase.getInterface().showOptionDialog(message, title, icon, options, defaultOption); + public static int showOptionDialog(IGuiBase gui, String message, String title, FSkinProp icon, String[] options, int defaultOption) { + return gui.showOptionDialog(message, title, icon, options, defaultOption); } - public static int showCardOptionDialog(CardView card, String message, String title, FSkinProp icon, String[] options, int defaultOption) { - return GuiBase.getInterface().showCardOptionDialog(card, message, title, icon, options, defaultOption); + public static int showCardOptionDialog(IGuiBase gui, CardView card, String message, String title, FSkinProp icon, String[] options, int defaultOption) { + return gui.showCardOptionDialog(card, message, title, icon, options, defaultOption); } - public static String showInputDialog(String message, String title) { - return showInputDialog(message, title, null, "", null); + public static String showInputDialog(IGuiBase gui, String message, String title) { + return showInputDialog(gui, message, title, null, "", null); } - public static String showInputDialog(String message, String title, FSkinProp icon) { - return showInputDialog(message, title, icon, "", null); + public static String showInputDialog(IGuiBase gui, String message, String title, FSkinProp icon) { + return showInputDialog(gui, message, title, icon, "", null); } - public static String showInputDialog(String message, String title, FSkinProp icon, String initialInput) { - return showInputDialog(message, title, icon, initialInput, null); + public static String showInputDialog(IGuiBase gui, String message, String title, FSkinProp icon, String initialInput) { + return showInputDialog(gui, message, title, icon, initialInput, null); } - public static T showInputDialog(String message, String title, FSkinProp icon, T initialInput, T[] inputOptions) { - return GuiBase.getInterface().showInputDialog(message, title, icon, initialInput, inputOptions); + public static T showInputDialog(IGuiBase gui, String message, String title, FSkinProp icon, T initialInput, T[] inputOptions) { + return gui.showInputDialog(message, title, icon, initialInput, inputOptions); } private SOptionPane() { diff --git a/forge-gui/src/main/java/forge/view/IGameView.java b/forge-gui/src/main/java/forge/view/IGameView.java index 2867d9f1bc1..d878fd3613f 100644 --- a/forge-gui/src/main/java/forge/view/IGameView.java +++ b/forge-gui/src/main/java/forge/view/IGameView.java @@ -29,6 +29,7 @@ public interface IGameView { public abstract boolean isMatchOver(); public abstract int getNumGamesInMatch(); public abstract int getNumPlayedGamesInMatch(); + public abstract Iterable getOutcomesOfMatch(); public abstract boolean isMatchWonBy(LobbyPlayer p); public abstract int getGamesWonBy(LobbyPlayer p); public abstract GameOutcome.AnteResult getAnteResult(); @@ -47,6 +48,8 @@ public interface IGameView { public abstract List getLogEntries(final GameLogEntryType maxLogLevel); public abstract List getLogEntriesExact(final GameLogEntryType logLevel); + public abstract boolean tryUndoLastAction(); + // the following method should eventually be replaced by methods returning // View classes @Deprecated @@ -94,4 +97,5 @@ public interface IGameView { public abstract void devAddCardToBattlefield(); public abstract void devRiggedPlanerRoll(); public abstract void devPlaneswalkTo(); + } \ No newline at end of file diff --git a/forge-gui/src/main/java/forge/view/SpellAbilityView.java b/forge-gui/src/main/java/forge/view/SpellAbilityView.java index ee3ad329ef0..346989aa5e3 100644 --- a/forge-gui/src/main/java/forge/view/SpellAbilityView.java +++ b/forge-gui/src/main/java/forge/view/SpellAbilityView.java @@ -3,6 +3,7 @@ package forge.view; public class SpellAbilityView { private CardView hostCard; + private boolean canPlay, promptIfOnlyPossibleAbility; /** * @return the hostCard @@ -18,4 +19,32 @@ public class SpellAbilityView { this.hostCard = hostCard; } + /** + * @return the canPlay + */ + public boolean canPlay() { + return canPlay; + } + + /** + * @param canPlay the canPlay to set + */ + public void setCanPlay(boolean canPlay) { + this.canPlay = canPlay; + } + + /** + * @return the promptIfOnlyPossibleAbility + */ + public boolean isPromptIfOnlyPossibleAbility() { + return promptIfOnlyPossibleAbility; + } + + /** + * @param promptIfOnlyPossibleAbility the promptIfOnlyPossibleAbility to set + */ + public void setPromptIfOnlyPossibleAbility(boolean promptIfOnlyPossibleAbility) { + this.promptIfOnlyPossibleAbility = promptIfOnlyPossibleAbility; + } + }