From 88c017f9624045940c79ababc32636af82ea10e7 Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Sat, 28 Nov 2020 19:02:33 +0100 Subject: [PATCH] GameView: do not store Game anymore, get it from Match --- .../java/forge/ai/PlayerControllerAi.java | 38 ++--- forge-game/src/main/java/forge/game/Game.java | 27 ++- .../java/forge/game/GameLogFormatter.java | 5 +- .../src/main/java/forge/game/GameOutcome.java | 52 +++--- .../src/main/java/forge/game/GameView.java | 47 ++++-- .../src/main/java/forge/game/Match.java | 94 +++++------ .../game/event/GameEventGameOutcome.java | 6 +- .../forge/game/player/PlayerController.java | 9 +- .../controllers/CEditorConstructed.java | 5 +- .../home/quest/CSubmenuQuestPrefs.java | 2 +- .../java/forge/screens/match/CMatchUI.java | 2 +- .../src/main/java/forge/view/Main.java | 3 +- .../util/PlayerControllerForTests.java | 38 ++--- .../forge/limited/CardThemedDeckBuilder.java | 4 +- .../main/java/forge/match/HostedMatch.java | 2 +- .../java/forge/match/input/InputLockUI.java | 7 +- .../java/forge/match/input/InputQueue.java | 12 +- .../forge/player/PlayerControllerHuman.java | 159 +++++++++--------- 18 files changed, 274 insertions(+), 238 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java index af537f70e2d..2105a24592f 100644 --- a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java +++ b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java @@ -267,7 +267,7 @@ public class PlayerControllerAi extends PlayerController { } @Override - public Player chooseStartingPlayer(boolean isFirstGame) { + public Player chooseStartingPlayer(boolean isFirstgame) { return this.player; // AI is brave :) } @@ -364,7 +364,7 @@ public class PlayerControllerAi extends PlayerController { if (destinationZone == ZoneType.Graveyard) { // In presence of Volrath's Shapeshifter in deck, try to place the best creature on top of the graveyard - if (!CardLists.filter(game.getCardsInGame(), new Predicate() { + if (!CardLists.filter(getGame().getCardsInGame(), new Predicate() { @Override public boolean apply(Card card) { // need a custom predicate here since Volrath's Shapeshifter may have a different name OTB @@ -485,7 +485,7 @@ public class PlayerControllerAi extends PlayerController { public void playSpellAbilityNoStack(SpellAbility effectSA, boolean canSetupTargets) { if (canSetupTargets) brains.doTrigger(effectSA, true); // first parameter does not matter, since return value won't be used - ComputerUtil.playNoStack(player, effectSA, game); + ComputerUtil.playNoStack(player, effectSA, getGame()); } @Override @@ -522,7 +522,7 @@ public class PlayerControllerAi extends PlayerController { chosen = validTypes.iterator().next(); System.err.println("AI has no idea how to choose " + kindOfType +", defaulting to arbitrary element: chosen"); } - game.getAction().nofityOfValue(sa, player, chosen, player); + getGame().getAction().nofityOfValue(sa, player, chosen, player); return chosen; } @@ -617,10 +617,10 @@ public class PlayerControllerAi extends PlayerController { if (sa instanceof LandAbility) { if (sa.canPlay()) { sa.resolve(); - game.updateLastStateForCard(sa.getHostCard()); + getGame().updateLastStateForCard(sa.getHostCard()); } } else { - ComputerUtil.handlePlayingSpellAbility(player, sa, game); + ComputerUtil.handlePlayingSpellAbility(player, sa, getGame()); } } @@ -659,7 +659,7 @@ public class PlayerControllerAi extends PlayerController { // - End of hack for Exile a card from library Cumulative Upkeep - if (ComputerUtilCost.canPayCost(ability, c.getController())) { - ComputerUtil.playNoStack(c.getController(), ability, game); + ComputerUtil.playNoStack(c.getController(), ability, getGame()); return true; } return false; @@ -889,8 +889,8 @@ public class PlayerControllerAi extends PlayerController { public String chooseProtectionType(String string, SpellAbility sa, List choices) { String choice = choices.get(0); SpellAbility hostsa = null; //for Protect sub-ability - if (game.stack.size() > 1) { - for (SpellAbilityStackInstance si : game.getStack()) { + if (getGame().stack.size() > 1) { + for (SpellAbilityStackInstance si : getGame().getStack()) { SpellAbility spell = si.getSpellAbility(true); if (sa != spell && sa.getHostCard() != spell.getHostCard()) { String s = ProtectAi.toProtectFrom(spell.getHostCard(), sa); @@ -901,10 +901,10 @@ public class PlayerControllerAi extends PlayerController { } } } - final Combat combat = game.getCombat(); + final Combat combat = getGame().getCombat(); if (combat != null) { - if (game.stack.size() == 1) { - SpellAbility topstack = game.stack.peekAbility(); + if (getGame().stack.size() == 1) { + SpellAbility topstack = getGame().stack.peekAbility(); if (topstack.getSubAbility() == sa) { hostsa = topstack; } @@ -927,7 +927,7 @@ public class PlayerControllerAi extends PlayerController { } } } - final PhaseHandler ph = game.getPhaseHandler(); + final PhaseHandler ph = getGame().getPhaseHandler(); if (ph.getPlayerTurn() == sa.getActivatingPlayer() && ph.getPhase() == PhaseType.MAIN1 && sa.getTargetCard() != null) { AiAttackController aiAtk = new AiAttackController(sa.getActivatingPlayer(), sa.getTargetCard()); String s = aiAtk.toProtectAttacker(sa); @@ -942,7 +942,7 @@ public class PlayerControllerAi extends PlayerController { list.addAll(opp.getCreaturesInPlay()); } if (list.isEmpty()) { - list = CardLists.filterControlledBy(game.getCardsInGame(), player.getOpponents()); + list = CardLists.filterControlledBy(getGame().getCardsInGame(), player.getOpponents()); } if (!list.isEmpty()) { choice = ComputerUtilCard.getMostProminentColor(list); @@ -961,7 +961,7 @@ public class PlayerControllerAi extends PlayerController { emptyAbility.setSVar(sVar, sa.getSVar(sVar)); } if (ComputerUtilCost.willPayUnlessCost(sa, player, cost, alreadyPaid, allPayers) && ComputerUtilCost.canPayCost(emptyAbility, player)) { - ComputerUtil.playNoStack(player, emptyAbility, game); // AI needs something to resolve to pay that cost + ComputerUtil.playNoStack(player, emptyAbility, getGame()); // AI needs something to resolve to pay that cost return true; } return false; @@ -1007,7 +1007,7 @@ public class PlayerControllerAi extends PlayerController { @Override public void playTrigger(Card host, WrappedAbility wrapperAbility, boolean isMandatory) { if (prepareSingleSa(host, wrapperAbility, isMandatory)) { - ComputerUtil.playNoStack(wrapperAbility.getActivatingPlayer(), wrapperAbility, game); + ComputerUtil.playNoStack(wrapperAbility.getActivatingPlayer(), wrapperAbility, getGame()); } } @@ -1019,9 +1019,9 @@ public class PlayerControllerAi extends PlayerController { Spell spell = (Spell) tgtSA; if (brains.canPlayFromEffectAI(spell, !optional, noManaCost) == AiPlayDecision.WillPlay || !optional) { if (noManaCost) { - return ComputerUtil.playSpellAbilityWithoutPayingManaCost(player, tgtSA, game); + return ComputerUtil.playSpellAbilityWithoutPayingManaCost(player, tgtSA, getGame()); } else { - return ComputerUtil.playStack(tgtSA, player, game); + return ComputerUtil.playStack(tgtSA, player, getGame()); } } else return false; // didn't play spell @@ -1167,7 +1167,7 @@ public class PlayerControllerAi extends PlayerController { return SpecialCardAi.CursedScroll.chooseCard(player, sa); } } else { - CardCollectionView list = CardLists.filterControlledBy(game.getCardsInGame(), player.getOpponents()); + CardCollectionView list = CardLists.filterControlledBy(getGame().getCardsInGame(), player.getOpponents()); list = CardLists.filter(list, Predicates.not(Presets.LANDS)); if (!list.isEmpty()) { return list.get(0).getName(); diff --git a/forge-game/src/main/java/forge/game/Game.java b/forge-game/src/main/java/forge/game/Game.java index 96c5c5d8d69..d15dc214c2e 100644 --- a/forge-game/src/main/java/forge/game/Game.java +++ b/forge-game/src/main/java/forge/game/Game.java @@ -62,6 +62,12 @@ import org.apache.commons.lang3.tuple.Pair; * Represents the state of a single game, a new instance is created for each game. */ public class Game { + + private static int maxId = 0; + private static int nextId() { return ++maxId; } + + /** The ID. */ + private int id; private final GameRules rules; private final PlayerCollection allPlayers = new PlayerCollection(); private final PlayerCollection ingamePlayers = new PlayerCollection(); @@ -107,6 +113,15 @@ public class Game { private final GameView view; private final Tracker tracker = new Tracker(); + /** + * Gets the id. + * + * @return the id + */ + public int getId() { + return this.id; + } + public Player getMonarch() { return monarch; } @@ -204,9 +219,11 @@ public class Game { changeZoneLKIInfo.clear(); } - public Game(List players0, GameRules rules0, Match match0) { /* no more zones to map here */ + public Game(Iterable players0, GameRules rules0, Match match0) { /* no more zones to map here */ rules = rules0; match = match0; + this.id = nextId(); + match.addGame(this); int highestTeam = -1; for (RegisteredPlayer psc : players0) { @@ -217,6 +234,9 @@ public class Game { } } + // View needs to be done before PlayerController + view = new GameView(this); + int plId = 0; for (RegisteredPlayer psc : players0) { IGameEntitiesFactory factory = (IGameEntitiesFactory)psc.getPlayer(); @@ -248,7 +268,8 @@ public class Game { endOfCombat = new Phase(PhaseType.COMBAT_END); endOfTurn = new Phase(PhaseType.END_OF_TURN); - view = new GameView(this); + // update players + view.updatePlayers(this); subscribeToEvents(gameLog.getEventVisitor()); } @@ -437,7 +458,7 @@ public class Game { view.updateGameOver(this); // The log shall listen to events and generate text internally - fireEvent(new GameEventGameOutcome(result, match.getPlayedGames())); + fireEvent(new GameEventGameOutcome(result, match.getOutcomes())); } public Zone getZoneOf(final Card card) { diff --git a/forge-game/src/main/java/forge/game/GameLogFormatter.java b/forge-game/src/main/java/forge/game/GameLogFormatter.java index 74e3910d35a..15d611d1414 100644 --- a/forge-game/src/main/java/forge/game/GameLogFormatter.java +++ b/forge-game/src/main/java/forge/game/GameLogFormatter.java @@ -5,6 +5,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map.Entry; +import com.google.common.collect.Iterables; import com.google.common.eventbus.Subscribe; import forge.LobbyPlayer; @@ -131,8 +132,8 @@ public class GameLogFormatter extends IGameEventVisitor.Base { return new GameLogEntry(GameLogEntryType.STACK_RESOLVE, modeChoiceOutcome); } - private static GameLogEntry generateSummary(final List gamesPlayed) { - final GameOutcome outcome1 = gamesPlayed.get(0); + private static GameLogEntry generateSummary(final Collection gamesPlayed) { + final GameOutcome outcome1 = Iterables.getFirst(gamesPlayed, null); final HashMap players = outcome1.getPlayerNames(); final HashMap winCount = new HashMap<>(); diff --git a/forge-game/src/main/java/forge/game/GameOutcome.java b/forge-game/src/main/java/forge/game/GameOutcome.java index 2cb077ef14a..494f46e2b29 100644 --- a/forge-game/src/main/java/forge/game/GameOutcome.java +++ b/forge-game/src/main/java/forge/game/GameOutcome.java @@ -22,6 +22,7 @@ import forge.LobbyPlayer; import forge.game.player.Player; import forge.game.player.PlayerOutcome; import forge.game.player.PlayerStatistics; +import forge.game.player.PlayerView; import forge.game.player.RegisteredPlayer; import forge.item.PaperCard; @@ -45,18 +46,10 @@ public final class GameOutcome implements Iterable lostCards; - public final List wonCards; + public final List lostCards = Lists.newArrayList(); + public final List wonCards = Lists.newArrayList(); - private AnteResult(List cards, boolean won) { - // Need empty lists for other results for addition of change ownership cards - if (won) { - this.wonCards = cards; - this.lostCards = new ArrayList<>(); - } else { - this.lostCards = cards; - this.wonCards = new ArrayList<>(); - } + public AnteResult() { } public void addWon(List cards) { @@ -66,14 +59,6 @@ public final class GameOutcome implements Iterable cards) { this.lostCards.addAll(cards); } - - public static AnteResult won(List cards) { - return new AnteResult(cards, true); - } - - public static AnteResult lost(List cards) { - return new AnteResult(cards, false); - } } private int lastTurnNumber = 0; @@ -83,7 +68,7 @@ public final class GameOutcome implements Iterable playerRating = new HashMap<>(); private final HashMap playerNames = new HashMap<>(); - public final Map anteResult = new HashMap<>(); + private final Map anteResult = new HashMap<>(); private GameEndReason winCondition; public GameOutcome(GameEndReason reason, final Iterable players) { @@ -242,4 +227,31 @@ public final class GameOutcome implements Iterable cards) { + if (!anteResult.containsKey(pl)) { + anteResult.put(pl, new AnteResult()); + } + anteResult.get(pl).addWon(cards); + } + + public void addAnteLost(RegisteredPlayer pl, List cards) { + if (!anteResult.containsKey(pl)) { + anteResult.put(pl, new AnteResult()); + } + anteResult.get(pl).addWon(cards); + } + + public AnteResult getAnteResult(RegisteredPlayer pl) { + return anteResult.get(pl); + } + + public AnteResult getAnteResult(PlayerView pv) { + for (Map.Entry e : this.anteResult.entrySet()) { + if (pv.isLobbyPlayer(e.getKey().getPlayer())) { + return e.getValue(); + } + } + return null; + } } diff --git a/forge-game/src/main/java/forge/game/GameView.java b/forge-game/src/main/java/forge/game/GameView.java index 39c50ea2171..3523e933bd0 100644 --- a/forge-game/src/main/java/forge/game/GameView.java +++ b/forge-game/src/main/java/forge/game/GameView.java @@ -11,8 +11,8 @@ import forge.game.combat.Combat; import forge.game.combat.CombatView; import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseType; -import forge.game.player.Player; import forge.game.player.PlayerView; +import forge.game.player.RegisteredPlayer; import forge.game.spellability.StackItemView; import forge.game.zone.MagicStack; import forge.trackable.TrackableObject; @@ -24,11 +24,11 @@ import java.util.List; public class GameView extends TrackableObject { private static final long serialVersionUID = 8522884512960961528L; - private final transient Game game; //TODO: Remove this when possible before network support added + private final transient Match match; //TODO: Remove this when possible before network support added - public GameView(final Game game0) { - super(-1, game0.getTracker()); //ID not needed - game = game0; + public GameView(final Game game) { + super(game.getId(), game.getTracker()); + match = game.getMatch(); set(TrackableProperty.Title, game.getMatch().getTitle()); set(TrackableProperty.WinningTeam, -1); @@ -39,15 +39,26 @@ public class GameView extends TrackableObject { set(TrackableProperty.NumGamesInMatch, rules.getGamesPerMatch()); set(TrackableProperty.GameLog, game.getGameLog()); - set(TrackableProperty.NumPlayedGamesInMatch, game.getMatch().getPlayedGames().size()); + set(TrackableProperty.NumPlayedGamesInMatch, game.getMatch().getOutcomes().size()); - set(TrackableProperty.Players, PlayerView.getCollection(game.getPlayers())); + } + + public Match getMatch() { + return match; + } + + public Game getGame() { + return getMatch().getGameById(getId()); // Match currently has only One running Game } public FCollectionView getPlayers() { return get(TrackableProperty.Players); } + public void updatePlayers(final Game game) { + set(TrackableProperty.Players, PlayerView.getCollection(game.getPlayers())); + } + public String getTitle() { return get(TrackableProperty.Title); } @@ -193,31 +204,35 @@ public class GameView extends TrackableObject { //TODO: Find better ways to make this information available to all GUIs without using the Game class public boolean isMatchWonBy(LobbyPlayer questPlayer) { - return game.getMatch().isWonBy(questPlayer); + return getMatch().isWonBy(questPlayer); } public Iterable getOutcomesOfMatch() { - return game.getMatch().getOutcomes(); + return getMatch().getOutcomes(); } public boolean isWinner(LobbyPlayer guiPlayer) { - return game.getOutcome().isWinner(guiPlayer); + return getOutcome().isWinner(guiPlayer); } public int getGamesWonBy(LobbyPlayer questPlayer) { - return game.getMatch().getGamesWonBy(questPlayer); + return getMatch().getGamesWonBy(questPlayer); } - public Deck getDeck(final String lobbyPlayerName) { - for (final Player p : game.getRegisteredPlayers()) { - if (p.getLobbyPlayer().getName().equals(lobbyPlayerName)) { - return p.getRegisteredPlayer().getDeck(); + public Deck getDeck(final PlayerView pv) { + for (final RegisteredPlayer rp : getMatch().getPlayers()) { + if (pv.isLobbyPlayer(rp.getPlayer())) { + return rp.getDeck(); } } return null; } + public GameOutcome getOutcome() { + return getMatch().getOutcomeById(getId()); + } + public AnteResult getAnteResult(PlayerView player) { - return game.getOutcome().anteResult.get(game.getPlayer(player).getRegisteredPlayer()); + return getOutcome().getAnteResult(player); } } diff --git a/forge-game/src/main/java/forge/game/Match.java b/forge-game/src/main/java/forge/game/Match.java index 59b99b724ee..9ab296b45c4 100644 --- a/forge-game/src/main/java/forge/game/Match.java +++ b/forge-game/src/main/java/forge/game/Match.java @@ -29,11 +29,13 @@ public class Match { private final GameRules rules; private final String title; - private final List gamesPlayed = new ArrayList<>(); - private final List gamesPlayedRo; + private Game lastGame = null; + private final Map runningGames = Maps.newHashMap(); + private final Map gameOutcomes = Maps.newHashMap(); + + private GameOutcome lastOutcome = null; public Match(final GameRules rules0, final List players0, final String title) { - gamesPlayedRo = Collections.unmodifiableList(gamesPlayed); players = Collections.unmodifiableList(Lists.newArrayList(players0)); rules = rules0; this.title = title; @@ -54,15 +56,12 @@ public class Match { return titleAppend.toString(); } - public final List getPlayedGames() { - return gamesPlayedRo; - } - public void addGamePlayed(Game finished) { if (!finished.isGameOver()) { throw new IllegalStateException("Game is not over yet."); } - gamesPlayed.add(finished.getOutcome()); + lastOutcome = finished.getOutcome(); + gameOutcomes.put(finished.getId(), finished.getOutcome()); } public Game createGame() { @@ -85,9 +84,7 @@ public class Match { game.fireEvent(new GameEventAnteCardsSelected(list)); } - GameOutcome lastOutcome = gamesPlayed.isEmpty() ? null : gamesPlayed.get(gamesPlayed.size() - 1); - - game.getAction().startGame(lastOutcome, startGameHook); + game.getAction().startGame(this.lastOutcome, startGameHook); if (rules.useAnte()) { executeAnte(game); @@ -97,26 +94,44 @@ public class Match { // will pull UI dialog, when the UI is listening game.fireEvent(new GameEventGameFinished()); + // FIXME needed to close the Match Dialog because that this moment there isn't any game + lastGame = game; + runningGames.remove(game.getId()); + + //run GC after game is finished + System.gc(); + } + + public Game getGameById(int id) { + if (runningGames.containsKey(id)) { + return runningGames.get(id); + } + // FIXME fallback for last game in case the UI is outdated + return lastGame; + } + + public GameOutcome getOutcomeById(int id) { + return gameOutcomes.get(id); + } + + public void addGame(Game game) { + runningGames.put(game.getId(), game); } public void clearGamesPlayed() { - gamesPlayed.clear(); + gameOutcomes.clear(); for (RegisteredPlayer p : players) { p.restoreDeck(); } } - public void clearLastGame() { - gamesPlayed.remove(gamesPlayed.size() - 1); - } - - public Iterable getOutcomes() { - return gamesPlayedRo; + public Collection getOutcomes() { + return gameOutcomes.values(); } public boolean isMatchOver() { int[] victories = new int[players.size()]; - for (GameOutcome go : gamesPlayed) { + for (GameOutcome go : getOutcomes()) { LobbyPlayer winner = go.getWinningLobbyPlayer(); int i = 0; for (RegisteredPlayer p : players) { @@ -136,7 +151,7 @@ public class Match { public int getGamesWonBy(LobbyPlayer questPlayer) { int sum = 0; - for (GameOutcome go : gamesPlayed) { + for (GameOutcome go : getOutcomes()) { if (questPlayer.equals(go.getWinningLobbyPlayer())) { sum++; } @@ -145,7 +160,7 @@ public class Match { } public Multiset getGamesWon() { final Multiset won = HashMultiset.create(players.size()); - for (final GameOutcome go : gamesPlayedRo) { + for (final GameOutcome go : getOutcomes()) { if (go.getWinningPlayer() == null) { // Game hasn't finished yet. Exit early. return won; @@ -161,7 +176,7 @@ public class Match { public RegisteredPlayer getWinner() { if (this.isMatchOver()) { - return gamesPlayedRo.get(gamesPlayedRo.size()-1).getWinningPlayer(); + return lastOutcome.getWinningPlayer(); } return null; } @@ -189,7 +204,7 @@ public class Match { for (final Entry stackOfCards : section) { final PaperCard cp = stackOfCards.getKey(); for (int i = 0; i < stackOfCards.getValue(); i++) { - final Card card = Card.fromPaperCard(cp, player); + final Card card = Card.fromPaperCard(cp, player); // Assign card-specific foiling or random foiling on approximately 1:20 cards if enabled if (cp.isFoil() || (canRandomFoil && MyRandom.percentTrue(5))) { @@ -214,16 +229,16 @@ public class Match { final FCollectionView players = game.getPlayers(); final List playersConditions = game.getMatch().getPlayers(); - boolean isFirstGame = game.getMatch().getPlayedGames().isEmpty(); + boolean isFirstGame = gameOutcomes.isEmpty(); boolean canSideBoard = !isFirstGame && rules.getGameType().isSideboardingAllowed(); // Only allow this if feature flag is on AND for certain match types boolean sideboardForAIs = rules.getSideboardForAI() && rules.getGameType().getDeckFormat().equals(DeckFormat.Constructed); PlayerController sideboardProxy = null; if (canSideBoard && sideboardForAIs) { - for (int i = 0; i < playersConditions.size(); i++) { + for (int i = 0; i < players.size(); i++) { final Player player = players.get(i); - final RegisteredPlayer psc = playersConditions.get(i); + //final RegisteredPlayer psc = playersConditions.get(i); if (!player.getController().isAI()) { sideboardProxy = player.getController(); break; @@ -337,11 +352,7 @@ public class Match { for(Card c : lostOwnership) { lostPaperOwnership.add((PaperCard)c.getPaperCard()); } - if (outcome.anteResult.containsKey(registered)) { - outcome.anteResult.get(registered).addLost(lostPaperOwnership); - } else { - outcome.anteResult.put(registered, GameOutcome.AnteResult.lost(lostPaperOwnership)); - } + outcome.addAnteLost(registered, lostPaperOwnership); } if (!gainedOwnership.isEmpty()) { @@ -349,12 +360,7 @@ public class Match { for(Card c : gainedOwnership) { gainedPaperOwnership.add((PaperCard)c.getPaperCard()); } - if (outcome.anteResult.containsKey(registered)) { - outcome.anteResult.get(registered).addWon(gainedPaperOwnership); - } - else { - outcome.anteResult.put(registered, GameOutcome.AnteResult.won(gainedPaperOwnership)); - } + outcome.addAnteWon(registered, gainedPaperOwnership); } if (outcome.isDraw()) { @@ -377,24 +383,14 @@ public class Match { losses.add(toRemove); } - if (outcome.anteResult.containsKey(registered)) { - outcome.anteResult.get(registered).addLost(personalLosses); - } - else { - outcome.anteResult.put(registered, GameOutcome.AnteResult.lost(personalLosses)); - } + outcome.addAnteLost(registered, personalLosses); } if (iWinner >= 0) { // Winner gains these cards always Player fromGame = lastGame.getRegisteredPlayers().get(iWinner); RegisteredPlayer registered = fromGame.getRegisteredPlayer(); - if (outcome.anteResult.containsKey(registered)) { - outcome.anteResult.get(registered).addWon(losses); - } - else { - outcome.anteResult.put(registered, GameOutcome.AnteResult.won(losses)); - } + outcome.addAnteWon(registered, losses); if (rules.getGameType().canAddWonCardsMidGame()) { // But only certain game types lets you swap midgame diff --git a/forge-game/src/main/java/forge/game/event/GameEventGameOutcome.java b/forge-game/src/main/java/forge/game/event/GameEventGameOutcome.java index 7ec0475415a..978f768873f 100644 --- a/forge-game/src/main/java/forge/game/event/GameEventGameOutcome.java +++ b/forge-game/src/main/java/forge/game/event/GameEventGameOutcome.java @@ -2,13 +2,13 @@ package forge.game.event; import forge.game.GameOutcome; -import java.util.List; +import java.util.Collection; public class GameEventGameOutcome extends GameEvent { public final GameOutcome result; - public final List history; + public final Collection history; - public GameEventGameOutcome(GameOutcome lastOne, List history) { + public GameEventGameOutcome(GameOutcome lastOne, Collection history) { this.result = lastOne; this.history = history; } 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 1b7c860296d..db47b63dc7e 100644 --- a/forge-game/src/main/java/forge/game/player/PlayerController.java +++ b/forge-game/src/main/java/forge/game/player/PlayerController.java @@ -22,6 +22,7 @@ import forge.game.GameEntity; import forge.game.GameObject; import forge.game.GameOutcome.AnteResult; import forge.game.GameType; +import forge.game.GameView; import forge.game.card.Card; import forge.game.card.CardCollection; import forge.game.card.CardCollectionView; @@ -73,13 +74,13 @@ public abstract class PlayerController { AddOrRemove, } - protected final Game game; + protected final GameView gameView; protected final Player player; protected final LobbyPlayer lobbyPlayer; public PlayerController(Game game0, Player p, LobbyPlayer lp) { - game = game0; + gameView = game0.getView(); player = p; lobbyPlayer = lp; } @@ -88,7 +89,7 @@ public abstract class PlayerController { return false; } - public Game getGame() { return game; } + public Game getGame() { return gameView.getGame(); } public Player getPlayer() { return player; } public LobbyPlayer getLobbyPlayer() { return lobbyPlayer; } @@ -280,7 +281,7 @@ public abstract class PlayerController { } public AnteResult getAnteResult() { - return game.getOutcome().anteResult.get(player.getRegisteredPlayer()); + return gameView.getAnteResult(player.getView()); } public abstract List chooseOptionalCosts(SpellAbility choosen, List optionalCostValues); diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorConstructed.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorConstructed.java index 0d72be9a4e5..f44771d9395 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorConstructed.java +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorConstructed.java @@ -128,6 +128,7 @@ public final class CEditorConstructed extends CDeckEditor { wantUnique = true; break; + default: } catalogManager = new CardManager(getCDetailPicture(), wantUnique, false); @@ -163,6 +164,7 @@ public final class CEditorConstructed extends CDeckEditor { case TinyLeaders: this.controller = new DeckController<>(FModel.getDecks().getTinyLeaders(), this, newCreator); break; + default: } getBtnAddBasicLands().setCommand(new UiCommand() { @@ -189,6 +191,7 @@ public final class CEditorConstructed extends CDeckEditor { case TinyLeaders: case Brawl: return CardLimit.Singleton; + default: } } return CardLimit.None; //if not enforcing deck legality, don't enforce default limit @@ -488,6 +491,7 @@ public final class CEditorConstructed extends CDeckEditor { default: break; } + default: } this.sectionMode = sectionMode; @@ -508,7 +512,6 @@ public final class CEditorConstructed extends CDeckEditor { /* (non-Javadoc) * @see forge.gui.deckeditor.ACEditorBase#show(forge.Command) */ - @SuppressWarnings("serial") @Override public void update() { this.getCatalogManager().setup(ItemManagerConfig.CARD_CATALOG); diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestPrefs.java b/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestPrefs.java index 42a363b4eac..6134fec353b 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestPrefs.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestPrefs.java @@ -60,7 +60,7 @@ public enum CSubmenuQuestPrefs implements ICDoc { || QPref.WILD_OPPONENTS_MULTIPLIER.equals(i0.getQPref())) { Double val = null; try { - val = new Double(i0.getText()); + val = Double.valueOf(i0.getText()); } catch (Exception e) { } validationError = val == null ? localizer.getMessage("lblEnteraDecimal") : null; 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 ca686b3bc43..b13b76535f3 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 @@ -271,7 +271,7 @@ public final class CMatchUI if (!isInGame()) { return; } - final Deck deck = getGameView().getDeck(getCurrentPlayer().getLobbyPlayerName()); + final Deck deck = getGameView().getDeck(getCurrentPlayer()); if (deck != null) { FDeckViewer.show(deck); } diff --git a/forge-gui-desktop/src/main/java/forge/view/Main.java b/forge-gui-desktop/src/main/java/forge/view/Main.java index 9a7424bc7e7..b4fa85c8968 100644 --- a/forge-gui-desktop/src/main/java/forge/view/Main.java +++ b/forge-gui-desktop/src/main/java/forge/view/Main.java @@ -85,7 +85,8 @@ public final class Main { System.exit(0); } - @Override + @SuppressWarnings("deprecation") + @Override protected void finalize() throws Throwable { try { ExceptionHandler.unregisterErrorHandling(); 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 fa806fab900..242e681cb4a 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 @@ -84,10 +84,6 @@ public class PlayerControllerForTests extends PlayerController { return player; } - public Game getGame() { - return game; - } - @Override public void playSpellAbilityForFree(SpellAbility copySA, boolean mayChoseNewTargets) { throw new IllegalStateException("Callers of this method currently assume that it performs extra functionality!"); @@ -202,7 +198,7 @@ public class PlayerControllerForTests extends PlayerController { } @Override - public Player chooseStartingPlayer(boolean isFirstGame) { + public Player chooseStartingPlayer(boolean isFirstgame) { return this.player; } @@ -320,7 +316,7 @@ public class PlayerControllerForTests extends PlayerController { if (playerActions == null) { return; } - DeclareAttackersAction declareAttackers = playerActions.getNextActionIfApplicable(player, game, DeclareAttackersAction.class); + DeclareAttackersAction declareAttackers = playerActions.getNextActionIfApplicable(player, getGame(), DeclareAttackersAction.class); if (declareAttackers == null) { return; } @@ -330,11 +326,11 @@ public class PlayerControllerForTests extends PlayerController { //TODO: banding (don't really care at the moment...) for (Map.Entry playerAttackAssignment : declareAttackers.getPlayerAttackAssignments().entrySet()) { - Player defender = getPlayerBeingAttacked(game, player, playerAttackAssignment.getValue()); + Player defender = getPlayerBeingAttacked(getGame(), player, playerAttackAssignment.getValue()); attack(combat, playerAttackAssignment.getKey(), defender); } for (Map.Entry planeswalkerAttackAssignment: declareAttackers.getPlaneswalkerAttackAssignments().entrySet()) { - Card defender = CardSpecificationHandler.INSTANCE.find(game.getCardsInGame(), planeswalkerAttackAssignment.getKey()); + Card defender = CardSpecificationHandler.INSTANCE.find(getGame().getCardsInGame(), planeswalkerAttackAssignment.getKey()); attack(combat, planeswalkerAttackAssignment.getKey(), defender); } @@ -345,12 +341,12 @@ public class PlayerControllerForTests extends PlayerController { private Player getPlayerBeingAttacked(Game game, Player attacker, PlayerSpecification defenderSpecification) { if (defenderSpecification != null) { - return PlayerSpecificationHandler.INSTANCE.find(game.getPlayers(), defenderSpecification); + return PlayerSpecificationHandler.INSTANCE.find(getGame().getPlayers(), defenderSpecification); } - if (game.getPlayers().size() != 2) { + if (getGame().getPlayers().size() != 2) { throw new IllegalStateException("Can't use implicit defender specification in this situation!"); } - for (Player player : game.getPlayers()) { + for (Player player : getGame().getPlayers()) { if (!attacker.equals(player)) { return player; } @@ -372,7 +368,7 @@ public class PlayerControllerForTests extends PlayerController { if (playerActions == null) { return; } - DeclareBlockersAction declareBlockers = playerActions.getNextActionIfApplicable(player, game, DeclareBlockersAction.class); + DeclareBlockersAction declareBlockers = playerActions.getNextActionIfApplicable(player, getGame(), DeclareBlockersAction.class); if (declareBlockers == null) { return; } @@ -384,7 +380,7 @@ public class PlayerControllerForTests extends PlayerController { for (Map.Entry> blockingAssignment : declareBlockers.getBlockingAssignments().asMap().entrySet()) { Card attacker = CardSpecificationHandler.INSTANCE.find(combat.getAttackers(), blockingAssignment.getKey()); for (CardSpecification blockerSpecification : blockingAssignment.getValue()) { - Card blocker = CardSpecificationHandler.INSTANCE.find(game, blockerSpecification); + Card blocker = CardSpecificationHandler.INSTANCE.find(getGame(), blockerSpecification); if (!CombatUtil.canBlock(attacker, blocker)) { throw new IllegalStateException(blocker + " can't block " + blocker); } @@ -402,14 +398,14 @@ public class PlayerControllerForTests extends PlayerController { //TODO: This method has to return the spellability chosen by player // It should not play the sa right from here. The code has been left as it is to quickly adapt to changed playercontroller interface if (playerActions != null) { - CastSpellFromHandAction castSpellFromHand = playerActions.getNextActionIfApplicable(player, game, CastSpellFromHandAction.class); + CastSpellFromHandAction castSpellFromHand = playerActions.getNextActionIfApplicable(player, getGame(), CastSpellFromHandAction.class); if (castSpellFromHand != null) { - castSpellFromHand.castSpellFromHand(player, game); + castSpellFromHand.castSpellFromHand(player, getGame()); } - ActivateAbilityAction activateAbilityAction = playerActions.getNextActionIfApplicable(player, game, ActivateAbilityAction.class); + ActivateAbilityAction activateAbilityAction = playerActions.getNextActionIfApplicable(player, getGame(), ActivateAbilityAction.class); if (activateAbilityAction != null) { - activateAbilityAction.activateAbility(player, game); + activateAbilityAction.activateAbility(player, getGame()); } } return null; @@ -526,7 +522,7 @@ public class PlayerControllerForTests extends PlayerController { public void orderAndPlaySimultaneousSa(List activePlayerSAs) { for (final SpellAbility sa : activePlayerSAs) { prepareSingleSa(sa.getHostCard(),sa,true); - ComputerUtil.playStack(sa, player, game); + ComputerUtil.playStack(sa, player, getGame()); } } @@ -544,7 +540,7 @@ public class PlayerControllerForTests extends PlayerController { @Override public void playTrigger(Card host, WrappedAbility wrapperAbility, boolean isMandatory) { prepareSingleSa(host, wrapperAbility, isMandatory); - ComputerUtil.playNoStack(wrapperAbility.getActivatingPlayer(), wrapperAbility, game); + ComputerUtil.playNoStack(wrapperAbility.getActivatingPlayer(), wrapperAbility, getGame()); } @Override @@ -557,9 +553,9 @@ public class PlayerControllerForTests extends PlayerController { // if (spell.canPlayFromEffectAI(player, !optional, noManaCost) || !optional) { -- could not save this part if (spell.canPlay() || !optional) { if (noManaCost) { - ComputerUtil.playSpellAbilityWithoutPayingManaCost(player, tgtSA, game); + ComputerUtil.playSpellAbilityWithoutPayingManaCost(player, tgtSA, getGame()); } else { - ComputerUtil.playStack(tgtSA, player, game); + ComputerUtil.playStack(tgtSA, player, getGame()); } } else return false; // didn't play spell diff --git a/forge-gui/src/main/java/forge/limited/CardThemedDeckBuilder.java b/forge-gui/src/main/java/forge/limited/CardThemedDeckBuilder.java index a1521f88113..fe572df8845 100644 --- a/forge-gui/src/main/java/forge/limited/CardThemedDeckBuilder.java +++ b/forge-gui/src/main/java/forge/limited/CardThemedDeckBuilder.java @@ -213,7 +213,7 @@ public class CardThemedDeckBuilder extends DeckGeneratorBase { if(FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.FILTERED_HANDS)){ baseLandParameter--; } - landsNeeded = new Double((baseLandParameter + 3.14f * avCMC) * targetSize/60f).intValue(); + landsNeeded = Double.valueOf((baseLandParameter + 3.14f * avCMC) * targetSize/60f).intValue(); if (logToConsole) { System.out.println("Required lands from linear regression : " + avCMC + " cmc, needed: " + landsNeeded); } @@ -425,8 +425,6 @@ public class CardThemedDeckBuilder extends DeckGeneratorBase { @Override public boolean apply(CardRules subject) { - ManaCost mc = subject.getManaCost(); - boolean generic = mc.isPureGeneric(); return ((allowedColor.containsAllColorsFrom(subject.getColorIdentity().getColor()))); } } diff --git a/forge-gui/src/main/java/forge/match/HostedMatch.java b/forge-gui/src/main/java/forge/match/HostedMatch.java index d68678494b1..6478c2b78db 100644 --- a/forge-gui/src/main/java/forge/match/HostedMatch.java +++ b/forge-gui/src/main/java/forge/match/HostedMatch.java @@ -149,7 +149,7 @@ public class HostedMatch { if (game.getRules().getGameType() == GameType.Quest) { final QuestController qc = FModel.getQuest(); // Reset new list when the Match round starts, not when each game starts - if (game.getMatch().getPlayedGames().isEmpty()) { + if (game.getMatch().getOutcomes().isEmpty()) { qc.getCards().resetNewList(); } game.subscribeToEvents(qc); // this one listens to player's mulligans ATM 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 657f77ec96f..76a13d6eb93 100644 --- a/forge-gui/src/main/java/forge/match/input/InputLockUI.java +++ b/forge-gui/src/main/java/forge/match/input/InputLockUI.java @@ -4,7 +4,6 @@ import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import forge.FThreads; -import forge.game.Game; import forge.game.card.Card; import forge.game.player.Player; import forge.game.player.PlayerView; @@ -17,10 +16,8 @@ public class InputLockUI implements Input { private final AtomicInteger iCall = new AtomicInteger(); private final InputQueue inputQueue; - private final Game game; private final PlayerControllerHuman controller; - public InputLockUI(final Game game0, final InputQueue inputQueue0, final PlayerControllerHuman controller) { - game = game0; + public InputLockUI(final InputQueue inputQueue0, final PlayerControllerHuman controller) { inputQueue = inputQueue0; this.controller = controller; } @@ -90,7 +87,7 @@ public class InputLockUI implements Input { @Override public void selectButtonCancel() { //cancel auto pass for all players - for (final Player player : game.getPlayers()) { + for (final Player player : controller.getGame().getPlayers()) { player.getController().autoPassCancel(); } } 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 2b745dcd1b1..1e5a5e90f74 100644 --- a/forge-gui/src/main/java/forge/match/input/InputQueue.java +++ b/forge-gui/src/main/java/forge/match/input/InputQueue.java @@ -21,7 +21,7 @@ import java.util.Observable; import java.util.concurrent.BlockingDeque; import java.util.concurrent.LinkedBlockingDeque; -import forge.game.Game; +import forge.game.GameView; import forge.player.PlayerControllerHuman; /** @@ -34,10 +34,10 @@ import forge.player.PlayerControllerHuman; */ public class InputQueue extends Observable { private final BlockingDeque inputStack = new LinkedBlockingDeque<>(); - private final Game game; + private final GameView gameView; - public InputQueue(final Game game, final InputProxy inputProxy) { - this.game = game; + public InputQueue(final GameView gameView, final InputProxy inputProxy) { + this.gameView = gameView; addObserver(inputProxy); } @@ -64,10 +64,10 @@ public class InputQueue extends Observable { public final Input getActualInput(final PlayerControllerHuman controller) { final Input topMost = inputStack.peek(); // incoming input to Control - if (topMost != null && !game.isGameOver()) { + if (topMost != null && !gameView.isGameOver()) { return topMost; } - return new InputLockUI(game, this, controller); + return new InputLockUI(this, controller); } // getInput() // only for debug purposes diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index 474390ac626..a08cac623d0 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -5,6 +5,8 @@ import java.util.*; import java.util.Map.Entry; import forge.game.ability.AbilityUtils; + +import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.Range; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; @@ -108,7 +110,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont public PlayerControllerHuman(final Game game0, final Player p, final LobbyPlayer lp) { super(game0, p, lp); inputProxy = new InputProxy(this); - inputQueue = new InputQueue(game, inputProxy); + inputQueue = new InputQueue(game0.getView(), inputProxy); } public PlayerControllerHuman(final Player p, final LobbyPlayer lp, final PlayerControllerHuman owner) { @@ -268,19 +270,8 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont // 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 - Object resp = getGui().sideboard(sideboard, main, message); - if (resp instanceof List && - !((List) resp).isEmpty() && - ((List) resp).get(0) instanceof PaperCard) { - newMain = (List) resp; - } else if (resp == null) { - // if we got here, the user took too long to reply - newMain = main.toFlatList(); - } else { - System.err.println("PlayerControllerHuman.sideboard -- FAILED!"); - System.err.println("resp instanceof " + resp.getClass().toString()); - System.err.println("resp = " + resp.toString()); - } + List resp = getGui().sideboard(sideboard, main, message); + newMain = ObjectUtils.defaultIfNull(resp, main.toFlatList()); } while (conform && (newMain.size() < deckMinSize || combinedDeckSize - newMain.size() > sbMax)); return newMain; @@ -667,8 +658,8 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont } if (tos.containsKey(AbilityKey.Card)) { final Card card = (Card) tos.get(AbilityKey.Card); - if (card != null && (card.getController() == player || game.getZoneOf(card) == null - || game.getZoneOf(card).getZoneType().isKnown())) { + if (card != null && (card.getController() == player || getGame().getZoneOf(card) == null + || getGame().getZoneOf(card).getZoneType().isKnown())) { buildQuestion.append("\n").append(localizer.getMessage("lblTriggeredby")).append(": ").append(tos.get(AbilityKey.Card)); } } @@ -680,7 +671,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont @Override public Player chooseStartingPlayer(final boolean isFirstGame) { - if (game.getPlayers().size() == 2) { + if (getGame().getPlayers().size() == 2) { String prompt = null; if (isFirstGame) { prompt = localizer.getMessage("lblYouHaveWonTheCoinToss", player.getName()); @@ -702,7 +693,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont } prompt += "\n\n" + localizer.getMessage("lblWhoWouldYouLiketoStartthisGame"); final InputSelectEntitiesFromList input = new InputSelectEntitiesFromList<>(this, 1, 1, - new FCollection<>(game.getPlayersInTurnOrder())); + new FCollection<>(getGame().getPlayersInTurnOrder())); input.setMessage(prompt); input.showAndWait(); return input.getFirstSelected(); @@ -922,7 +913,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont return cards; case ForgeConstants.GRAVEYARD_ORDERING_OWN_CARDS: // Order only if the relevant cards controlled by the player determine the potential necessity for it - if (!game.isGraveyardOrdered(player)) { + if (!getGame().isGraveyardOrdered(player)) { return cards; } break; @@ -1286,7 +1277,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont @Override public List chooseSpellAbilityToPlay() { - final MagicStack stack = game.getStack(); + final MagicStack stack = getGame().getStack(); if (mayAutoPass()) { // avoid prompting for input if current phase is set to be @@ -1297,8 +1288,8 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont if (stack.isEmpty()) { // make sure to briefly pause at phases you're not set up to // skip - if (!getGui().isUiSetToSkipPhase(game.getPhaseHandler().getPlayerTurn().getView(), - game.getPhaseHandler().getPhase())) { + if (!getGui().isUiSetToSkipPhase(getGame().getPhaseHandler().getPlayerTurn().getView(), + getGame().getPhaseHandler().getPhase())) { delay = FControlGamePlayback.phasesDelay; } } else { @@ -1317,8 +1308,8 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont } if (stack.isEmpty()) { - if (getGui().isUiSetToSkipPhase(game.getPhaseHandler().getPlayerTurn().getView(), - game.getPhaseHandler().getPhase())) { + if (getGui().isUiSetToSkipPhase(getGame().getPhaseHandler().getPlayerTurn().getView(), + getGame().getPhaseHandler().getPhase())) { return null; // avoid prompt for input if stack is empty and // player is set to skip the current phase } @@ -1504,7 +1495,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont public void notifyOfValue(final SpellAbility sa, final GameObject realtedTarget, final String value) { final String message = MessageUtil.formatNotificationMessage(sa, player, realtedTarget, value); if (sa != null && sa.isManaAbility()) { - game.getGameLog().add(GameLogEntryType.LAND, message); + getGame().getGameLog().add(GameLogEntryType.LAND, message); } else { getGui().message(message, sa == null || sa.getHostCard() == null ? "" : CardView.get(sa.getHostCard()).toString()); @@ -1522,14 +1513,14 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont @Override public List chooseModeForAbility(final SpellAbility sa, List possible, final int min, final int num, boolean allowRepeat) { - boolean trackerFrozen = game.getTracker().isFrozen(); + boolean trackerFrozen = getGame().getTracker().isFrozen(); if (trackerFrozen) { // The view tracker needs to be unfrozen to update the SpellAbilityViews at this point, or it may crash - game.getTracker().unfreeze(); + getGame().getTracker().unfreeze(); } Map spellViewCache = SpellAbilityView.getMap(possible); if (trackerFrozen) { - game.getTracker().freeze(); // refreeze if the tracker was frozen prior to this update + getGame().getTracker().freeze(); // refreeze if the tracker was frozen prior to this update } final List choices = Lists.newArrayList(spellViewCache.keySet()); final String modeTitle = localizer.getMessage("lblPlayerActivatedCardChooseMode", sa.getActivatingPlayer().toString(), CardTranslation.getTranslatedName(sa.getHostCard().getName())); @@ -1894,10 +1885,10 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont } public boolean canUndoLastAction() { - if (!game.stack.canUndo(player)) { + if (!getGame().stack.canUndo(player)) { return false; } - final Player priorityPlayer = game.getPhaseHandler().getPriorityPlayer(); + final Player priorityPlayer = getGame().getPhaseHandler().getPriorityPlayer(); return priorityPlayer != null && priorityPlayer == player; } @@ -1911,7 +1902,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont return false; } - if (game.getStack().undo()) { + if (getGame().getStack().undo()) { final Input currentInput = inputQueue.getInput(); if (currentInput instanceof InputPassPriority) { // ensure prompt updated if needed @@ -2057,7 +2048,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont @Override public void setViewAllCards(final boolean canViewAll) { mayLookAtAllCards = canViewAll; - for (final Player p : game.getPlayers()) { + for (final Player p : getGame().getPlayers()) { getGui().updateCards(CardView.getCollection(p.getAllCards())); } } @@ -2069,18 +2060,18 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont */ @Override public void generateMana() { - final Player pPriority = game.getPhaseHandler().getPriorityPlayer(); + final Player pPriority = getGame().getPhaseHandler().getPriorityPlayer(); if (pPriority == null) { getGui().message(localizer.getMessage("lblNoPlayerHasPriorityCannotAddedManaToPool")); return; } - final Card dummy = new Card(-777777, game); + final Card dummy = new Card(-777777, getGame()); dummy.setOwner(pPriority); final Map produced = Maps.newHashMap(); produced.put("Produced", "W W W W W W W U U U U U U U B B B B B B B G G G G G G G R R R R R R R 7"); final AbilityManaPart abMana = new AbilityManaPart(dummy, produced); - game.getAction().invoke(new Runnable() { + getGame().getAction().invoke(new Runnable() { @Override public void run() { abMana.produceMana(null); @@ -2106,7 +2097,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont public void dumpGameState() { final GameState state = createGameStateObject(); try { - state.initFromGame(game); + state.initFromGame(getGame()); final File f = GuiBase.getInterface().getSaveFile(new File(ForgeConstants.USER_GAMES_DIR, "state.txt")); if (f != null && (!f.exists() || getGui().showConfirmDialog(localizer.getMessage("lblOverwriteExistFileConfirm"), localizer.getMessage("lblFileExists")))) { @@ -2156,12 +2147,12 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont return; } - final Player pPriority = game.getPhaseHandler().getPriorityPlayer(); + final Player pPriority = getGame().getPhaseHandler().getPriorityPlayer(); if (pPriority == null) { getGui().message(localizer.getMessage("lblNoPlayerPriorityGameStateCannotBeSetup")); return; } - state.applyToGame(game); + state.applyToGame(getGame()); } /* @@ -2171,7 +2162,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont */ @Override public void tutorForCard() { - final Player pPriority = game.getPhaseHandler().getPriorityPlayer(); + final Player pPriority = getGame().getPhaseHandler().getPriorityPlayer(); if (pPriority == null) { getGui().message(localizer.getMessage("lblNoPlayerPriorityDeckCantBeTutoredFrom")); return; @@ -2180,17 +2171,17 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont final CardCollection lib = (CardCollection) pPriority.getCardsIn(ZoneType.Library); final List origin = Lists.newArrayList(); origin.add(ZoneType.Library); - final SpellAbility sa = new SpellAbility.EmptySa(new Card(-1, game)); + final SpellAbility sa = new SpellAbility.EmptySa(new Card(-1, getGame())); final Card card = chooseSingleCardForZoneChange(ZoneType.Hand, origin, sa, lib, null, localizer.getMessage("lblChooseaCard"), true, pPriority); if (card == null) { return; } - game.getAction().invoke(new Runnable() { + getGame().getAction().invoke(new Runnable() { @Override public void run() { - game.getAction().moveToHand(card, null); + getGame().getAction().moveToHand(card, null); } }); } @@ -2218,7 +2209,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont public void modifyCountersOnPermanent(boolean subtract) { final String titleMsg = subtract ? localizer.getMessage("lblRemoveCountersFromWhichCard") : localizer.getMessage("lblAddCountersToWhichCard"); - GameEntityViewMap gameCacheCounters = GameEntityView.getMap(game.getCardsIn(ZoneType.Battlefield)); + GameEntityViewMap gameCacheCounters = GameEntityView.getMap(getGame().getCardsIn(ZoneType.Battlefield)); final CardView cv = getGui().oneOrNone(titleMsg, gameCacheCounters.getTrackableKeys()); if (cv == null || !gameCacheCounters.containsKey(cv)) { @@ -2259,10 +2250,10 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont */ @Override public void tapPermanents() { - game.getAction().invoke(new Runnable() { + getGame().getAction().invoke(new Runnable() { @Override public void run() { - final CardCollectionView untapped = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), + final CardCollectionView untapped = CardLists.filter(getGame().getCardsIn(ZoneType.Battlefield), Predicates.not(CardPredicates.Presets.TAPPED)); final InputSelectCardsFromList inp = new InputSelectCardsFromList(PlayerControllerHuman.this, 0, Integer.MAX_VALUE, untapped); @@ -2285,10 +2276,10 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont */ @Override public void untapPermanents() { - game.getAction().invoke(new Runnable() { + getGame().getAction().invoke(new Runnable() { @Override public void run() { - final CardCollectionView tapped = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), + final CardCollectionView tapped = CardLists.filter(getGame().getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.TAPPED); final InputSelectCardsFromList inp = new InputSelectCardsFromList(PlayerControllerHuman.this, 0, Integer.MAX_VALUE, tapped); @@ -2312,7 +2303,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont @Override public void setPlayerLife() { - GameEntityViewMap gameCachePlayer = GameEntityView.getMap(game.getPlayers()); + GameEntityViewMap gameCachePlayer = GameEntityView.getMap(getGame().getPlayers()); final PlayerView pv = getGui().oneOrNone(localizer.getMessage("lblSetLifeforWhichPlayer"), gameCachePlayer.getTrackableKeys()); if (pv == null || !gameCachePlayer.containsKey(pv)) { @@ -2343,7 +2334,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont // set life of all other players to 0 final LobbyPlayer guiPlayer = getLobbyPlayer(); - final FCollectionView players = game.getPlayers(); + final FCollectionView players = getGame().getPlayers(); for (final Player player : players) { if (player.getLobbyPlayer() != guiPlayer) { player.setLife(0, null); @@ -2448,7 +2439,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont return; } } else { - GameEntityViewMap gameCachePlayer = GameEntityView.getMap(game.getPlayers()); + GameEntityViewMap gameCachePlayer = GameEntityView.getMap(getGame().getPlayers()); PlayerView pv = getGui().oneOrNone(message, gameCachePlayer.getTrackableKeys()); if (pv == null || !gameCachePlayer.containsKey(pv)) { return; @@ -2470,9 +2461,9 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont final PaperCard c = carddb.getUniqueByName(f.getName()); final Card forgeCard = Card.fromPaperCard(c, p); - forgeCard.setTimestamp(game.getNextTimestamp()); + forgeCard.setTimestamp(getGame().getNextTimestamp()); - game.getAction().invoke(new Runnable() { + getGame().getAction().invoke(new Runnable() { @Override public void run() { if (targetZone == ZoneType.Battlefield) { @@ -2488,7 +2479,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont } } } - game.getAction().moveTo(targetZone, forgeCard, null); + getGame().getAction().moveTo(targetZone, forgeCard, null); if (forgeCard.isCreature()) { forgeCard.setSickness(lastSummoningSickness); } @@ -2499,10 +2490,10 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont } else { if (c.getRules().getType().isLand()) { // this is needed to ensure land abilities fire - game.getAction().moveToHand(forgeCard, null); - game.getAction().moveToPlay(forgeCard, null); + getGame().getAction().moveToHand(forgeCard, null); + getGame().getAction().moveToPlay(forgeCard, null); // ensure triggered abilities fire - game.getTriggerHandler().runWaitingTriggers(); + getGame().getTriggerHandler().runWaitingTriggers(); } else { final FCollectionView choices = forgeCard.getBasicSpells(); if (choices.isEmpty()) { @@ -2522,14 +2513,14 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont lastAddedSA = sa; // this is really needed (for rollbacks at least) - game.getAction().moveToHand(forgeCard, null); + getGame().getAction().moveToHand(forgeCard, null); // Human player is choosing targets for an ability // controlled by chosen player. sa.setActivatingPlayer(p); - HumanPlay.playSaWithoutPayingManaCost(PlayerControllerHuman.this, game, sa, true); + HumanPlay.playSaWithoutPayingManaCost(PlayerControllerHuman.this, getGame(), sa, true); } // playSa could fire some triggers - game.getStack().addAllTriggeredAbilitiesToStack(); + getGame().getStack().addAllTriggeredAbilitiesToStack(); } } else if (targetZone == ZoneType.Library) { if (!repeatLast) { @@ -2537,12 +2528,12 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont true, Arrays.asList(localizer.getMessage("lblTop"), localizer.getMessage("lblBottom"))); } if (lastTopOfTheLibrary) { - game.getAction().moveToLibrary(forgeCard, null); + getGame().getAction().moveToLibrary(forgeCard, null); } else { - game.getAction().moveToBottomOfLibrary(forgeCard, null); + getGame().getAction().moveToBottomOfLibrary(forgeCard, null); } } else { - game.getAction().moveTo(targetZone, forgeCard, null); + getGame().getAction().moveTo(targetZone, forgeCard, null); } lastAdded = f; @@ -2560,7 +2551,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont */ @Override public void exileCardsFromHand() { - GameEntityViewMap gameCachePlayer = GameEntityView.getMap(game.getPlayers()); + GameEntityViewMap gameCachePlayer = GameEntityView.getMap(getGame().getPlayers()); final PlayerView pv = getGui().oneOrNone(localizer.getMessage("lblExileCardsFromPlayerHandConfirm"), gameCachePlayer.getTrackableKeys()); @@ -2581,12 +2572,12 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont if (c == null) { continue; } - if (game.getAction().moveTo(ZoneType.Exile, c, null) != null) { + if (getGame().getAction().moveTo(ZoneType.Exile, c, null) != null) { StringBuilder sb = new StringBuilder(); sb.append(p).append(" exiles ").append(c).append(" due to Dev Cheats."); - game.getGameLog().add(GameLogEntryType.DISCARD, sb.toString()); + getGame().getGameLog().add(GameLogEntryType.DISCARD, sb.toString()); } else { - game.getGameLog().add(GameLogEntryType.INFORMATION, "DISCARD CHEAT ERROR"); + getGame().getGameLog().add(GameLogEntryType.INFORMATION, "DISCARD CHEAT ERROR"); } } } @@ -2598,7 +2589,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont */ @Override public void exileCardsFromBattlefield() { - GameEntityViewMap gameCachePlayer = GameEntityView.getMap(game.getPlayers()); + GameEntityViewMap gameCachePlayer = GameEntityView.getMap(getGame().getPlayers()); final PlayerView pv = getGui().oneOrNone(localizer.getMessage("lblExileCardsFromPlayerBattlefieldConfirm"), gameCachePlayer.getTrackableKeys()); @@ -2619,12 +2610,12 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont if (c == null) { continue; } - if (game.getAction().moveTo(ZoneType.Exile, c, null) != null) { + if (getGame().getAction().moveTo(ZoneType.Exile, c, null) != null) { StringBuilder sb = new StringBuilder(); sb.append(p).append(" exiles ").append(c).append(" due to Dev Cheats."); - game.getGameLog().add(GameLogEntryType.ZONE_CHANGE, sb.toString()); + getGame().getGameLog().add(GameLogEntryType.ZONE_CHANGE, sb.toString()); } else { - game.getGameLog().add(GameLogEntryType.INFORMATION, "EXILE FROM PLAY CHEAT ERROR"); + getGame().getGameLog().add(GameLogEntryType.INFORMATION, "EXILE FROM PLAY CHEAT ERROR"); } } } @@ -2636,7 +2627,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont */ @Override public void removeCardsFromGame() { - GameEntityViewMap gameCachePlayer = GameEntityView.getMap(game.getPlayers()); + GameEntityViewMap gameCachePlayer = GameEntityView.getMap(getGame().getPlayers()); final PlayerView pv = getGui().oneOrNone(localizer.getMessage("lblRemoveCardBelongingWitchPlayer"), gameCachePlayer.getTrackableKeys()); @@ -2665,7 +2656,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont StringBuilder sb = new StringBuilder(); sb.append(p).append(" removes ").append(c).append(" from game due to Dev Cheats."); - game.getGameLog().add(GameLogEntryType.ZONE_CHANGE, sb.toString()); + getGame().getGameLog().add(GameLogEntryType.ZONE_CHANGE, sb.toString()); } } @@ -2676,7 +2667,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont */ @Override public void riggedPlanarRoll() { - GameEntityViewMap gameCachePlayer = GameEntityView.getMap(game.getPlayers()); + GameEntityViewMap gameCachePlayer = GameEntityView.getMap(getGame().getPlayers()); final PlayerView pv = getGui().oneOrNone(localizer.getMessage("lblWhichPlayerShouldRoll"), gameCachePlayer.getTrackableKeys()); if (pv == null || !gameCachePlayer.containsKey(pv)) { @@ -2691,7 +2682,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont System.out.println("Rigging planar dice roll: " + res.toString()); - game.getAction().invoke(new Runnable() { + getGame().getAction().invoke(new Runnable() { @Override public void run() { PlanarDice.roll(player, res); @@ -2706,10 +2697,10 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont */ @Override public void planeswalkTo() { - if (!game.getRules().hasAppliedVariant(GameType.Planechase)) { + if (!getGame().getRules().hasAppliedVariant(GameType.Planechase)) { return; } - final Player p = game.getPhaseHandler().getPlayerTurn(); + final Player p = getGame().getPhaseHandler().getPlayerTurn(); final List allPlanars = Lists.newArrayList(); for (final PaperCard c : FModel.getMagicDb().getVariantCards().getAllCards()) { @@ -2727,10 +2718,10 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont final Card forgeCard = Card.fromPaperCard(c, p); forgeCard.setOwner(p); - game.getAction().invoke(new Runnable() { + getGame().getAction().invoke(new Runnable() { @Override public void run() { - game.getAction().changeZone(null, p.getZone(ZoneType.PlanarDeck), forgeCard, 0, null); + getGame().getAction().changeZone(null, p.getZone(ZoneType.PlanarDeck), forgeCard, 0, null); PlanarDice.roll(p, PlanarDice.Planeswalk); } }); @@ -2781,7 +2772,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont // the parsing // process, and this implementation is still a "proof of concept". int opponentID = 0; - for (final Player player : game.getPlayers()) { + for (final Player player : getGame().getPlayers()) { if (player.getId() != playerID) { opponentID = player.getId(); break; @@ -2842,14 +2833,14 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont // Fetch cards and players specified by the user input final ZoneType[] zones = { ZoneType.Battlefield, ZoneType.Hand, ZoneType.Graveyard, ZoneType.Exile, ZoneType.Command }; - final CardCollectionView cards = game.getCardsIn(Arrays.asList(zones)); + final CardCollectionView cards = getGame().getCardsIn(Arrays.asList(zones)); for (final Pair entity : entityInfo) { boolean found = false; // Nested loops are no fun; however, seems there's no better way // to get stuff by ID boolean isPlayer = entity.getValue(); if (isPlayer) { - for (final Player player : game.getPlayers()) { + for (final Player player : getGame().getPlayers()) { if (player.getId() == entity.getKey()) { found = true; rememberedActions.add(Pair.of(player.getView(), true)); @@ -2945,7 +2936,11 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont @Override public void nextGameDecision(final NextGameDecision decision) { - game.fireEvent(new UiEventNextGameDecision(this, decision)); + Game game = getGame(); + // in case the game ended before the button is pressed, then match doesn't remember the game anymore + if (game != null) { + game.fireEvent(new UiEventNextGameDecision(this, decision)); + } } @Override