Prevent stuff getting out of sync

This commit is contained in:
drdev
2014-10-02 22:17:54 +00:00
parent d2b6a0831d
commit 7c53f96328
11 changed files with 139 additions and 152 deletions

View File

@@ -616,7 +616,7 @@ public enum CMatchUI implements ICDoc, IMenuProvider, IMatchController {
public void openView(List<Player> sortedPlayers) { public void openView(List<Player> sortedPlayers) {
List<PlayerView> sortedPlayerViews = new ArrayList<PlayerView>(); List<PlayerView> sortedPlayerViews = new ArrayList<PlayerView>();
for (Player p : sortedPlayers) { for (Player p : sortedPlayers) {
sortedPlayerViews.add(MatchUtil.getGameView().getPlayerView(p)); sortedPlayerViews.add(MatchUtil.getGameView().getPlayerView(p, false));
} }
CMatchUI.SINGLETON_INSTANCE.initMatch(sortedPlayerViews, MatchUtil.getHumanCount() != 1); CMatchUI.SINGLETON_INSTANCE.initMatch(sortedPlayerViews, MatchUtil.getHumanCount() != 1);

View File

@@ -181,7 +181,7 @@ public enum VStack implements IVDoc<CStack> {
public StackInstanceTextArea(final LocalGameView gameView, final StackItemView item) { public StackInstanceTextArea(final LocalGameView gameView, final StackItemView item) {
sourceCard = item.getSource(); sourceCard = item.getSource();
final PlayerView localPlayer = gameView.getPlayerView(MatchUtil.getCurrentPlayer()); final PlayerView localPlayer = gameView.getPlayerView(MatchUtil.getCurrentPlayer(), false);
final String txt = (item.isOptionalTrigger() && item.getActivatingPlayer().equals(localPlayer) final String txt = (item.isOptionalTrigger() && item.getActivatingPlayer().equals(localPlayer)
? "(OPTIONAL) " : "") + item.getText(); ? "(OPTIONAL) " : "") + item.getText();

View File

@@ -102,7 +102,7 @@ public class MatchController implements IMatchController {
boolean noHumans = MatchUtil.getHumanCount() == 0; boolean noHumans = MatchUtil.getHumanCount() == 0;
List<VPlayerPanel> playerPanels = new ArrayList<VPlayerPanel>(); List<VPlayerPanel> playerPanels = new ArrayList<VPlayerPanel>();
for (Player p : sortedPlayers) { for (Player p : sortedPlayers) {
playerPanels.add(new VPlayerPanel(MatchUtil.getGameView(p).getPlayerView(p), noHumans || p.getController() instanceof PlayerControllerHuman)); playerPanels.add(new VPlayerPanel(MatchUtil.getGameView(p).getPlayerView(p, false), noHumans || p.getController() instanceof PlayerControllerHuman));
} }
view = new MatchScreen(playerPanels); view = new MatchScreen(playerPanels);

View File

@@ -256,7 +256,7 @@ public class VStack extends FDropDown {
@Override @Override
protected void buildMenu() { protected void buildMenu() {
final LocalGameView gameView = MatchUtil.getGameView(); final LocalGameView gameView = MatchUtil.getGameView();
final PlayerView playerView = gameView.getPlayerView(player); final PlayerView playerView = gameView.getPlayerView(player, false);
final String key = stackInstance.getKey(); final String key = stackInstance.getKey();
final boolean autoYield = gameView.shouldAutoYield(key); final boolean autoYield = gameView.shouldAutoYield(key);
addItem(new FCheckBoxMenuItem("Auto-Yield", autoYield, addItem(new FCheckBoxMenuItem("Auto-Yield", autoYield,

View File

@@ -79,6 +79,12 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
public FControlGameEventHandler(final LocalGameView gameView0) { public FControlGameEventHandler(final LocalGameView gameView0) {
gameView = gameView0; gameView = gameView0;
// aggressively cache a view for each player (also caches cards)
for (Player player : gameView.getGame().getRegisteredPlayers()) {
gameView.getPlayerView(player, true);
}
processEventsTimer = GuiBase.getInterface().createGuiTimer(processEvents, BASE_TIMER_INTERVAL); processEventsTimer = GuiBase.getInterface().createGuiTimer(processEvents, BASE_TIMER_INTERVAL);
processEventsTimer.start(); //start event processing loop processEventsTimer.start(); //start event processing loop
} }
@@ -90,26 +96,25 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
if (eventReceived) { if (eventReceived) {
eventReceived = false; eventReceived = false;
gameView.startUpdate();
IMatchController controller = MatchUtil.getController(); IMatchController controller = MatchUtil.getController();
if (!cardsUpdate.isEmpty()) { if (!cardsUpdate.isEmpty()) {
MatchUtil.updateCards(gameView.getCardViews(cardsUpdate)); MatchUtil.updateCards(gameView.getCardViews(cardsUpdate, true));
cardsUpdate.clear(); cardsUpdate.clear();
} }
if (!cardsRefreshDetails.isEmpty()) { if (!cardsRefreshDetails.isEmpty()) {
controller.refreshCardDetails(gameView.getCardViews(cardsRefreshDetails)); controller.refreshCardDetails(gameView.getCardViews(cardsRefreshDetails, true));
cardsRefreshDetails.clear(); cardsRefreshDetails.clear();
} }
if (!livesUpdate.isEmpty()) { if (!livesUpdate.isEmpty()) {
controller.updateLives(gameView.getPlayerViews(livesUpdate)); controller.updateLives(gameView.getPlayerViews(livesUpdate, true));
livesUpdate.clear(); livesUpdate.clear();
} }
if (!manaPoolUpdate.isEmpty()) { if (!manaPoolUpdate.isEmpty()) {
controller.updateManaPool(gameView.getPlayerViews(manaPoolUpdate)); controller.updateManaPool(gameView.getPlayerViews(manaPoolUpdate, true));
manaPoolUpdate.clear(); manaPoolUpdate.clear();
} }
if (!zonesUpdate.isEmpty()) { if (!zonesUpdate.isEmpty()) {
List<PlayerView> players = gameView.getPlayers(); List<PlayerView> players = gameView.getPlayers(true);
ArrayList<Pair<PlayerView, ZoneType>> zones = new ArrayList<Pair<PlayerView, ZoneType>>(); ArrayList<Pair<PlayerView, ZoneType>> zones = new ArrayList<Pair<PlayerView, ZoneType>>();
for (String z : zonesUpdate) { for (String z : zonesUpdate) {
int idx = z.indexOf(PLAYER_ZONE_DELIM); int idx = z.indexOf(PLAYER_ZONE_DELIM);
@@ -119,7 +124,7 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
zonesUpdate.clear(); zonesUpdate.clear();
} }
if (turnUpdate != null) { if (turnUpdate != null) {
controller.updateTurn(gameView.getPlayerView(turnUpdate)); controller.updateTurn(gameView.getPlayerView(turnUpdate, true));
turnUpdate = null; turnUpdate = null;
} }
if (needPhaseUpdate) { if (needPhaseUpdate) {
@@ -153,7 +158,6 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
gameView.updateAchievements(); gameView.updateAchievements();
processEventsTimer.stop(); processEventsTimer.stop();
} }
gameView.endUpdate();
} }
} }
} }
@@ -197,7 +201,7 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
final CardView fakeCard = new CardView(-1); //use fake card so real cards appear with proper formatting final CardView fakeCard = new CardView(-1); //use fake card so real cards appear with proper formatting
fakeCard.getOriginal().setName(" -- From " + Lang.getPossesive(kv.getKey().getName()) + " deck --"); fakeCard.getOriginal().setName(" -- From " + Lang.getPossesive(kv.getKey().getName()) + " deck --");
options.add(fakeCard); options.add(fakeCard);
options.add(gameView.getCardView(kv.getValue())); options.add(gameView.getCardView(kv.getValue(), true));
} }
SGuiChoose.reveal(gameView.getGui(), "These cards were chosen to ante", options); SGuiChoose.reveal(gameView.getGui(), "These cards were chosen to ante", options);
return null; return null;

View File

@@ -78,7 +78,7 @@ public class FControlGamePlayback extends IGameEventVisitor.Base<Void> {
@Override @Override
public Void visit(GameEventTurnPhase ev) { public Void visit(GameEventTurnPhase ev) {
boolean isUiToStop = MatchUtil.getController().stopAtPhase( boolean isUiToStop = MatchUtil.getController().stopAtPhase(
gameView.getPlayerView(ev.playerTurn), ev.phase); gameView.getPlayerView(ev.playerTurn, true), ev.phase);
switch(ev.phase) { switch(ev.phase) {
case COMBAT_END: case COMBAT_END:
@@ -124,9 +124,9 @@ public class FControlGamePlayback extends IGameEventVisitor.Base<Void> {
FThreads.invokeInEdtNowOrLater(gui, new Runnable() { FThreads.invokeInEdtNowOrLater(gui, new Runnable() {
@Override @Override
public void run() { public void run() {
gui.setCard(gameView.getCardView(event.spell.getHostCard())); gui.setCard(gameView.getCardView(event.spell.getHostCard(), true));
} }
}); });
pauseForEvent(resolveDelay); pauseForEvent(resolveDelay);
return null; return null;
} }
@@ -139,9 +139,9 @@ public class FControlGamePlayback extends IGameEventVisitor.Base<Void> {
FThreads.invokeInEdtNowOrLater(gui, new Runnable() { FThreads.invokeInEdtNowOrLater(gui, new Runnable() {
@Override @Override
public void run() { public void run() {
gui.setCard(gameView.getCardView(event.sa.getHostCard())); gui.setCard(gameView.getCardView(event.sa.getHostCard(), true));
} }
}); });
pauseForEvent(castDelay); pauseForEvent(castDelay);
return null; return null;
} }

View File

@@ -213,7 +213,7 @@ public class MatchUtil {
//ensure opponents set properly //ensure opponents set properly
for (PlayerView pv : gameViews.get(0).getPlayers()) { for (PlayerView pv : gameViews.get(0).getPlayers()) {
pv.setOpponents(gameViews.get(0).getPlayerViews(players.getKey(pv.getId()).getOpponents())); pv.setOpponents(gameViews.get(0).getPlayerViews(players.getKey(pv.getId()).getOpponents(), false));
} }
// It's important to run match in a different thread to allow GUI inputs to be invoked from inside game. // It's important to run match in a different thread to allow GUI inputs to be invoked from inside game.

View File

@@ -942,14 +942,15 @@ public class HumanCostDecision extends CostDecisionMakerBase {
inp.setMessage("Remove %d " + cost.counter.getName() + " counters from " + cost.getDescriptiveType()); inp.setMessage("Remove %d " + cost.counter.getName() + " counters from " + cost.getDescriptiveType());
inp.setCancelAllowed(true); inp.setCancelAllowed(true);
inp.showAndWait(); inp.showAndWait();
if(inp.hasCancelled()) if (inp.hasCancelled()) {
return null; return null;
}
// Have to hack here: remove all counters minus one, without firing any triggers, // Have to hack here: remove all counters minus one, without firing any triggers,
// triggers will fire when last is removed by executePayment. // triggers will fire when last is removed by executePayment.
// They don't care how many were removed anyway // They don't care how many were removed anyway
// int sum = 0; // int sum = 0;
for(Card crd : inp.getSelected()) { for (Card crd : inp.getSelected()) {
int removed = inp.getTimesSelected(crd); int removed = inp.getTimesSelected(crd);
// sum += removed; // sum += removed;
if(removed < 2) continue; if(removed < 2) continue;
@@ -961,9 +962,11 @@ public class HumanCostDecision extends CostDecisionMakerBase {
// Rift Elemental only - always removes 1 counter, so there will be no code for N counters. // Rift Elemental only - always removes 1 counter, so there will be no code for N counters.
List<CardView> suspended = Lists.newArrayList(); List<CardView> suspended = Lists.newArrayList();
for (final Card crd : validCards) for (final Card crd : validCards) {
if (crd.getCounters( cost.counter) > 0) if (crd.getCounters(cost.counter) > 0) {
suspended.add(controller.getCardView(crd)); suspended.add(controller.getCardView(crd));
}
}
final CardView view = SGuiChoose.oneOrNone(getGui(), "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); final Card card = controller.getCard(view);

View File

@@ -127,11 +127,6 @@ public class PlayerControllerHuman extends PlayerController {
super(game0, p, lp); super(game0, p, lp);
if (p.getController() == null || p.getLobbyPlayer() == lp) { if (p.getController() == null || p.getLobbyPlayer() == lp) {
gameView = new GameView(gui, game0); gameView = new GameView(gui, game0);
// aggressively cache a view for each player (also caches cards)
for (final Player player : game.getRegisteredPlayers()) {
gameView.getPlayerView(player);
}
} }
else { //handle the case of one player controlling another else { //handle the case of one player controlling another
for (Player p0 : game.getPlayers()) { for (Player p0 : game.getPlayers()) {
@@ -195,7 +190,7 @@ public class PlayerControllerHuman extends PlayerController {
} }
public boolean isUiSetToSkipPhase(final Player turn, final PhaseType phase) { public boolean isUiSetToSkipPhase(final Player turn, final PhaseType phase) {
return !MatchUtil.getController().stopAtPhase(gameView.getPlayerView(turn), phase); return !MatchUtil.getController().stopAtPhase(getPlayerView(turn), phase);
} }
/** /**
@@ -280,10 +275,10 @@ public class PlayerControllerHuman extends PlayerController {
if (defender != null && assignDamageAsIfNotBlocked(attacker)) { if (defender != null && assignDamageAsIfNotBlocked(attacker)) {
map.put(null, damageDealt); map.put(null, damageDealt);
} else { } else {
final List<CardView> vBlockers = gameView.getCardViews(blockers); final List<CardView> vBlockers = getCardViews(blockers);
if ((attacker.hasKeyword("Trample") && defender != null) || (blockers.size() > 1)) { if ((attacker.hasKeyword("Trample") && defender != null) || (blockers.size() > 1)) {
final CardView vAttacker = gameView.getCardView(attacker); final CardView vAttacker = getCardView(attacker);
final GameEntityView vDefender = gameView.getGameEntityView(defender); final GameEntityView vDefender = getGameEntityView(defender);
final Map<CardView, Integer> result = MatchUtil.getDamageToAssign(vAttacker, vBlockers, damageDealt, vDefender, overrideOrder); final Map<CardView, Integer> result = MatchUtil.getDamageToAssign(vAttacker, vBlockers, damageDealt, vDefender, overrideOrder);
for (final Entry<CardView, Integer> e : result.entrySet()) { for (final Entry<CardView, Integer> e : result.entrySet()) {
map.put(gameView.getCard(e.getKey()), e.getValue()); map.put(gameView.getCard(e.getKey()), e.getValue());
@@ -298,7 +293,7 @@ public class PlayerControllerHuman extends PlayerController {
private final boolean assignDamageAsIfNotBlocked(final Card attacker) { private final boolean assignDamageAsIfNotBlocked(final Card attacker) {
return attacker.hasKeyword("CARDNAME assigns its combat damage as though it weren't blocked.") 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.") || (attacker.hasKeyword("You may have CARDNAME assign its combat damage as though it weren't blocked.")
&& SGuiDialog.confirm(getGui(), gameView.getCardView(attacker), "Do you want to 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) /* (non-Javadoc)
@@ -354,7 +349,7 @@ public class PlayerControllerHuman extends PlayerController {
return singleChosen == null ? Lists.<Card>newArrayList() : Lists.newArrayList(singleChosen); return singleChosen == null ? Lists.<Card>newArrayList() : Lists.newArrayList(singleChosen);
} }
MatchUtil.getController().setPanelSelection(gameView.getCardView(sa.getHostCard())); MatchUtil.getController().setPanelSelection(getCardView(sa.getHostCard()));
// try to use InputSelectCardsFromList when possible // try to use InputSelectCardsFromList when possible
boolean cardsAreInMyHandOrBattlefield = true; boolean cardsAreInMyHandOrBattlefield = true;
@@ -376,7 +371,7 @@ public class PlayerControllerHuman extends PlayerController {
} }
tempShowCards(sourceList); tempShowCards(sourceList);
final List<CardView> choices = SGuiChoose.many(getGui(), title, "Chosen Cards", min, max, gameView.getCardViews(sourceList), gameView.getCardView(sa.getHostCard())); final List<CardView> choices = SGuiChoose.many(getGui(), title, "Chosen Cards", min, max, getCardViews(sourceList), getCardView(sa.getHostCard()));
endTempShowCards(); endTempShowCards();
return getCards(choices); return getCards(choices);
@@ -421,7 +416,7 @@ public class PlayerControllerHuman extends PlayerController {
tempShowCard((Card) t); tempShowCard((Card) t);
} }
} }
final GameEntityView result = isOptional ? SGuiChoose.oneOrNone(getGui(), title, gameView.getGameEntityViews((Iterable<GameEntity>) options)) : SGuiChoose.one(getGui(), title, gameView.getGameEntityViews((Iterable<GameEntity>) options)); final GameEntityView result = isOptional ? SGuiChoose.oneOrNone(getGui(), title, gameView.getGameEntityViews((Iterable<GameEntity>) options, false)) : SGuiChoose.one(getGui(), title, gameView.getGameEntityViews((Iterable<GameEntity>) options, false));
endTempShowCards(); endTempShowCards();
return (T) gameView.getGameEntity(result); return (T) gameView.getGameEntity(result);
} }
@@ -456,18 +451,18 @@ public class PlayerControllerHuman extends PlayerController {
*/ */
@Override @Override
public boolean confirmAction(SpellAbility sa, PlayerActionConfirmMode mode, String message) { public boolean confirmAction(SpellAbility sa, PlayerActionConfirmMode mode, String message) {
return SGuiDialog.confirm(getGui(), gameView.getCardView(sa.getHostCard()), message); return SGuiDialog.confirm(getGui(), getCardView(sa.getHostCard()), message);
} }
@Override @Override
public boolean confirmBidAction(SpellAbility sa, PlayerActionConfirmMode bidlife, public boolean confirmBidAction(SpellAbility sa, PlayerActionConfirmMode bidlife,
String string, int bid, Player winner) { String string, int bid, Player winner) {
return SGuiDialog.confirm(getGui(), gameView.getCardView(sa.getHostCard()), string + " Highest Bidder " + winner); return SGuiDialog.confirm(getGui(), getCardView(sa.getHostCard()), string + " Highest Bidder " + winner);
} }
@Override @Override
public boolean confirmStaticApplication(Card hostCard, GameEntity affected, String logic, String message) { public boolean confirmStaticApplication(Card hostCard, GameEntity affected, String logic, String message) {
return SGuiDialog.confirm(getGui(), gameView.getCardView(hostCard), message); return SGuiDialog.confirm(getGui(), getCardView(hostCard), message);
} }
@Override @Override
@@ -525,25 +520,25 @@ public class PlayerControllerHuman extends PlayerController {
@Override @Override
public List<Card> orderBlockers(final Card attacker, final List<Card> blockers) { public List<Card> orderBlockers(final Card attacker, final List<Card> blockers) {
final CardView vAttacker = gameView.getCardView(attacker); final CardView vAttacker = getCardView(attacker);
MatchUtil.getController().setPanelSelection(vAttacker); MatchUtil.getController().setPanelSelection(vAttacker);
final List<CardView> choices = SGuiChoose.order(getGui(), "Choose Damage Order for " + vAttacker, "Damaged First", gameView.getCardViews(blockers), vAttacker); final List<CardView> choices = SGuiChoose.order(getGui(), "Choose Damage Order for " + vAttacker, "Damaged First", getCardViews(blockers), vAttacker);
return gameView.getCards(choices); return gameView.getCards(choices);
} }
@Override @Override
public List<Card> orderBlocker(final Card attacker, final Card blocker, final List<Card> oldBlockers) { public List<Card> orderBlocker(final Card attacker, final Card blocker, final List<Card> oldBlockers) {
final CardView vAttacker = gameView.getCardView(attacker); final CardView vAttacker = getCardView(attacker);
MatchUtil.getController().setPanelSelection(vAttacker); MatchUtil.getController().setPanelSelection(vAttacker);
final List<CardView> choices = SGuiChoose.insertInList(getGui(), "Choose blocker after which to place " + vAttacker + " in damage order; cancel to place it first", gameView.getCardView(blocker), gameView.getCardViews(oldBlockers)); final List<CardView> choices = SGuiChoose.insertInList(getGui(), "Choose blocker after which to place " + vAttacker + " in damage order; cancel to place it first", getCardView(blocker), getCardViews(oldBlockers));
return gameView.getCards(choices); return gameView.getCards(choices);
} }
@Override @Override
public List<Card> orderAttackers(final Card blocker, final List<Card> attackers) { public List<Card> orderAttackers(final Card blocker, final List<Card> attackers) {
final CardView vBlocker = gameView.getCardView(blocker); final CardView vBlocker = getCardView(blocker);
MatchUtil.getController().setPanelSelection(vBlocker); MatchUtil.getController().setPanelSelection(vBlocker);
final List<CardView> choices = SGuiChoose.order(getGui(), "Choose Damage Order for " + vBlocker, "Damaged First", gameView.getCardViews(attackers), vBlocker); final List<CardView> choices = SGuiChoose.order(getGui(), "Choose Damage Order for " + vBlocker, "Damaged First", getCardViews(attackers), vBlocker);
return gameView.getCards(choices); return gameView.getCards(choices);
} }
@@ -561,7 +556,7 @@ public class PlayerControllerHuman extends PlayerController {
String fm = formatMessage(message, owner); String fm = formatMessage(message, owner);
if (!cards.isEmpty()) { if (!cards.isEmpty()) {
tempShowCards(cards); tempShowCards(cards);
SGuiChoose.reveal(getGui(), fm, gameView.getCardViews(cards)); SGuiChoose.reveal(getGui(), fm, getCardViews(cards));
endTempShowCards(); endTempShowCards();
} }
else { else {
@@ -585,7 +580,7 @@ public class PlayerControllerHuman extends PlayerController {
} }
} }
else { else {
final List<CardView> toBottomViews = SGuiChoose.many(getGui(), "Select cards to be put on the bottom of your library", "Cards to put on the bottom", -1, gameView.getCardViews(topN), null); final List<CardView> toBottomViews = SGuiChoose.many(getGui(), "Select cards to be put on the bottom of your library", "Cards to put on the bottom", -1, getCardViews(topN), null);
toBottom = gameView.getCards(toBottomViews); toBottom = gameView.getCards(toBottomViews);
topN.removeAll(toBottom); topN.removeAll(toBottom);
if (topN.isEmpty()) { if (topN.isEmpty()) {
@@ -595,7 +590,7 @@ public class PlayerControllerHuman extends PlayerController {
toTop = topN; toTop = topN;
} }
else { else {
final List<CardView> toTopViews = SGuiChoose.order(getGui(), "Arrange cards to be put on top of your library", "Cards arranged", gameView.getCardViews(topN), null); final List<CardView> toTopViews = SGuiChoose.order(getGui(), "Arrange cards to be put on top of your library", "Cards arranged", getCardViews(topN), null);
toTop = gameView.getCards(toTopViews); toTop = gameView.getCards(toTopViews);
} }
} }
@@ -607,7 +602,7 @@ public class PlayerControllerHuman extends PlayerController {
public boolean willPutCardOnTop(final Card c) { public boolean willPutCardOnTop(final Card c) {
final PaperCard pc = FModel.getMagicDb().getCommonCards().getCard(c.getName()); final PaperCard pc = FModel.getMagicDb().getCommonCards().getCard(c.getName());
final Card c1 = (pc != null ? Card.fromPaperCard(pc, null) : c); final Card c1 = (pc != null ? Card.fromPaperCard(pc, null) : c);
final CardView view = gameView.getCardView(c1); final CardView view = getCardView(c1);
return SGuiDialog.confirm(getGui(), view, "Put " + view + " on the top or bottom of your library?", new String[]{"Top", "Bottom"}); return SGuiDialog.confirm(getGui(), view, "Put " + view + " on the top or bottom of your library?", new String[]{"Top", "Bottom"});
} }
@@ -648,7 +643,7 @@ public class PlayerControllerHuman extends PlayerController {
if (p != player) { if (p != player) {
tempShowCards(valid); tempShowCards(valid);
final List<CardView> choices = SGuiChoose.many(getGui(), "Choose " + min + " card" + (min != 1 ? "s" : "") + " to discard", final List<CardView> choices = SGuiChoose.many(getGui(), "Choose " + min + " card" + (min != 1 ? "s" : "") + " to discard",
"Discarded", min, min, gameView.getCardViews(valid), null); "Discarded", min, min, getCardViews(valid), null);
endTempShowCards(); endTempShowCards();
return getCards(choices); return getCards(choices);
} }
@@ -661,7 +656,7 @@ public class PlayerControllerHuman extends PlayerController {
@Override @Override
public void playMiracle(final SpellAbility miracle, final Card card) { public void playMiracle(final SpellAbility miracle, final Card card) {
final CardView view = gameView.getCardView(card); final CardView view = getCardView(card);
if (SGuiDialog.confirm(getGui(), view, view + " - Drawn. Play for Miracle Cost?")) { if (SGuiDialog.confirm(getGui(), view, view + " - Drawn. Play for Miracle Cost?")) {
HumanPlay.playSpellAbility(this, player, miracle); HumanPlay.playSpellAbility(this, player, miracle);
} }
@@ -680,7 +675,7 @@ public class PlayerControllerHuman extends PlayerController {
System.out.println("Delve for " + chosenAmount); System.out.println("Delve for " + chosenAmount);
for (int i = 0; i < chosenAmount; i++) { for (int i = 0; i < chosenAmount; i++) {
final CardView nowChosen = SGuiChoose.oneOrNone(getGui(), "Exile which card?", gameView.getCardViews(grave)); final CardView nowChosen = SGuiChoose.oneOrNone(getGui(), "Exile which card?", getCardViews(grave));
if (nowChosen == null) { if (nowChosen == null) {
// User canceled,abort delving. // User canceled,abort delving.
@@ -778,7 +773,7 @@ public class PlayerControllerHuman extends PlayerController {
*/ */
@Override @Override
public boolean confirmReplacementEffect(ReplacementEffect replacementEffect, SpellAbility effectSA, String question) { public boolean confirmReplacementEffect(ReplacementEffect replacementEffect, SpellAbility effectSA, String question) {
return SGuiDialog.confirm(getGui(), gameView.getCardView(replacementEffect.getHostCard()), question); return SGuiDialog.confirm(getGui(), getCardView(replacementEffect.getHostCard()), question);
} }
@Override @Override
@@ -797,7 +792,7 @@ public class PlayerControllerHuman extends PlayerController {
//ensure they're declared and then delay slightly so user can see as much //ensure they're declared and then delay slightly so user can see as much
for (Pair<Card, GameEntity> attacker : mandatoryAttackers) { for (Pair<Card, GameEntity> attacker : mandatoryAttackers) {
combat.addAttacker(attacker.getLeft(), attacker.getRight()); combat.addAttacker(attacker.getLeft(), attacker.getRight());
MatchUtil.fireEvent(new UiEventAttackerDeclared(gameView.getCardView(attacker.getLeft()), gameView.getGameEntityView(attacker.getRight()))); MatchUtil.fireEvent(new UiEventAttackerDeclared(getCardView(attacker.getLeft()), getGameEntityView(attacker.getRight())));
} }
try { try {
Thread.sleep(FControlGamePlayback.combatDelay); Thread.sleep(FControlGamePlayback.combatDelay);
@@ -961,7 +956,7 @@ public class PlayerControllerHuman extends PlayerController {
if (srcCards.isEmpty()) { if (srcCards.isEmpty()) {
return result; return result;
} }
final List<CardView> chosen = SGuiChoose.many(getGui(), "Choose cards to activate from opening hand and their order", "Activate first", -1, gameView.getCardViews(srcCards), null); final List<CardView> chosen = SGuiChoose.many(getGui(), "Choose cards to activate from opening hand and their order", "Activate first", -1, getCardViews(srcCards), null);
for (final CardView view : chosen) { for (final CardView view : chosen) {
final Card c = getCard(view); final Card c = getCard(view);
for (SpellAbility sa : usableFromOpeningHand) { for (SpellAbility sa : usableFromOpeningHand) {
@@ -991,7 +986,7 @@ public class PlayerControllerHuman extends PlayerController {
case PlayOrDraw: labels = new String[]{"Play", "Draw"}; break; case PlayOrDraw: labels = new String[]{"Play", "Draw"}; break;
default: labels = kindOfChoice.toString().split("Or"); default: labels = kindOfChoice.toString().split("Or");
} }
return SGuiDialog.confirm(getGui(), gameView.getCardView(sa.getHostCard()), question, defaultVal == null || defaultVal.booleanValue(), labels); return SGuiDialog.confirm(getGui(), getCardView(sa.getHostCard()), question, defaultVal == null || defaultVal.booleanValue(), labels);
} }
@Override @Override
@@ -1163,7 +1158,7 @@ public class PlayerControllerHuman extends PlayerController {
if (colorNames.length > 2) { if (colorNames.length > 2) {
return MagicColor.fromName(SGuiChoose.one(getGui(), message, colorNames)); return MagicColor.fromName(SGuiChoose.one(getGui(), message, colorNames));
} }
int idxChosen = SGuiDialog.confirm(getGui(), gameView.getCardView(c), message, colorNames) ? 0 : 1; int idxChosen = SGuiDialog.confirm(getGui(), getCardView(c), message, colorNames) ? 0 : 1;
return MagicColor.fromName(colorNames[idxChosen]); return MagicColor.fromName(colorNames[idxChosen]);
} }
@@ -1262,7 +1257,7 @@ public class PlayerControllerHuman extends PlayerController {
final String p1Str = String.format("Pile 1 (%s cards)", pile1.size()); final String p1Str = String.format("Pile 1 (%s cards)", pile1.size());
final String p2Str = String.format("Pile 2 (%s cards)", pile2.size()); final String p2Str = String.format("Pile 2 (%s cards)", pile2.size());
final String[] possibleValues = { p1Str , p2Str }; final String[] possibleValues = { p1Str , p2Str };
return SGuiDialog.confirm(getGui(), gameView.getCardView(sa.getHostCard()), "Choose a Pile", possibleValues); return SGuiDialog.confirm(getGui(), getCardView(sa.getHostCard()), "Choose a Pile", possibleValues);
} }
tempShowCards(pile1); tempShowCards(pile1);
@@ -1598,7 +1593,7 @@ public class PlayerControllerHuman extends PlayerController {
* @see forge.view.LocalGameView#getGameEntityView(forge.game.GameEntity) * @see forge.view.LocalGameView#getGameEntityView(forge.game.GameEntity)
*/ */
public final GameEntityView getGameEntityView(GameEntity e) { public final GameEntityView getGameEntityView(GameEntity e) {
return gameView.getGameEntityView(e); return gameView.getGameEntityView(e, false);
} }
/** /**
@@ -1607,14 +1602,14 @@ public class PlayerControllerHuman extends PlayerController {
* @see forge.view.LocalGameView#getPlayerViews(java.lang.Iterable) * @see forge.view.LocalGameView#getPlayerViews(java.lang.Iterable)
*/ */
public final List<PlayerView> getPlayerViews(Iterable<Player> players) { public final List<PlayerView> getPlayerViews(Iterable<Player> players) {
return gameView.getPlayerViews(players); return gameView.getPlayerViews(players, false);
} }
public PlayerView getPlayerView() { public PlayerView getPlayerView() {
return gameView.getPlayerView(getPlayer()); return gameView.getPlayerView(getPlayer(), false);
} }
public PlayerView getPlayerView(Player p) { public PlayerView getPlayerView(Player p) {
return gameView.getPlayerView(p); return gameView.getPlayerView(p, false);
} }
/** /**
@@ -1632,7 +1627,7 @@ public class PlayerControllerHuman extends PlayerController {
* @see forge.view.LocalGameView#getCardView(forge.game.card.Card) * @see forge.view.LocalGameView#getCardView(forge.game.card.Card)
*/ */
public CardView getCardView(Card c) { public CardView getCardView(Card c) {
return gameView.getCardView(c); return gameView.getCardView(c, false);
} }
/** /**
@@ -1641,7 +1636,7 @@ public class PlayerControllerHuman extends PlayerController {
* @see forge.view.LocalGameView#getCardViews(java.util.List) * @see forge.view.LocalGameView#getCardViews(java.util.List)
*/ */
public final List<CardView> getCardViews(final Iterable<Card> cards) { public final List<CardView> getCardViews(final Iterable<Card> cards) {
return gameView.getCardViews(cards); return gameView.getCardViews(cards, false);
} }
/** /**
@@ -1740,7 +1735,7 @@ public class PlayerControllerHuman extends PlayerController {
public void setViewAllCards(final boolean canViewAll) { public void setViewAllCards(final boolean canViewAll) {
mayLookAtAllCards = canViewAll; mayLookAtAllCards = canViewAll;
for (final Player p : game.getPlayers()) { for (final Player p : game.getPlayers()) {
MatchUtil.updateCards(getCardViews(p.getAllCards())); MatchUtil.updateCards(gameView.getCardViews(p.getAllCards(), true));
} }
} }

View File

@@ -1,5 +1,6 @@
package forge.view; package forge.view;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Observer; import java.util.Observer;
@@ -67,7 +68,7 @@ public abstract class LocalGameView implements IGameView {
} }
public void setLocalPlayer(Player localPlayer) { public void setLocalPlayer(Player localPlayer) {
localPlayerView = getPlayerView(localPlayer); localPlayerView = getPlayerView(localPlayer, false);
} }
/* (non-Javadoc) /* (non-Javadoc)
@@ -203,10 +204,10 @@ public abstract class LocalGameView implements IGameView {
final List<Card> blockers = combat.getBlockers(b); final List<Card> blockers = combat.getBlockers(b);
final boolean isBlocked = b.isBlocked() == Boolean.TRUE; final boolean isBlocked = b.isBlocked() == Boolean.TRUE;
combatView.addAttackingBand( combatView.addAttackingBand(
getCardViews(b.getAttackers()), getCardViews(b.getAttackers(), false),
getGameEntityView(defender), getGameEntityView(defender, false),
blockers == null || !isBlocked ? null : getCardViews(blockers), blockers == null || !isBlocked ? null : getCardViews(blockers, false),
blockers == null ? null : getCardViews(blockers)); blockers == null ? null : getCardViews(blockers, false));
} }
} }
MatchUtil.cachedCombatView = combatView; MatchUtil.cachedCombatView = combatView;
@@ -241,12 +242,15 @@ public abstract class LocalGameView implements IGameView {
*/ */
@Override @Override
public List<PlayerView> getPlayers() { public List<PlayerView> getPlayers() {
return getPlayerViews(game.getRegisteredPlayers()); return getPlayerViews(game.getRegisteredPlayers(), false);
}
public List<PlayerView> getPlayers(boolean forceUpdate) {
return getPlayerViews(game.getRegisteredPlayers(), forceUpdate);
} }
@Override @Override
public PlayerView getPlayerTurn() { public PlayerView getPlayerTurn() {
return getPlayerView(game.getPhaseHandler().getPlayerTurn()); return getPlayerView(game.getPhaseHandler().getPlayerTurn(), false);
} }
@Override @Override
@@ -309,44 +313,40 @@ public abstract class LocalGameView implements IGameView {
return MatchUtil.stackItems.getKey(view.getId()); return MatchUtil.stackItems.getKey(view.getId());
} }
public final GameEntityView getGameEntityView(final GameEntity e) { public final GameEntityView getGameEntityView(final GameEntity e, final boolean forceUpdate) {
if (e instanceof Card) { if (e instanceof Card) {
return getCardView((Card)e); return getCardView((Card)e, forceUpdate);
} else if (e instanceof Player) { }
return getPlayerView((Player)e); if (e instanceof Player) {
return getPlayerView((Player)e, forceUpdate);
} }
return null; return null;
} }
private final Function<GameEntity, GameEntityView> FN_GET_GAME_ENTITY_VIEW = new Function<GameEntity, GameEntityView>() { public final List<GameEntityView> getGameEntityViews(final Iterable<GameEntity> entities, final boolean forceUpdate) {
@Override List<GameEntityView> views = new ArrayList<GameEntityView>();
public GameEntityView apply(GameEntity input) { for (GameEntity e : entities) {
return getGameEntityView(input); views.add(getGameEntityView(e, forceUpdate));
} }
}; return views;
public final List<GameEntityView> getGameEntityViews(final Iterable<GameEntity> entities) {
return ViewUtil.transformIfNotNull(entities, FN_GET_GAME_ENTITY_VIEW);
} }
public final GameEntity getGameEntity(final GameEntityView view) { public final GameEntity getGameEntity(final GameEntityView view) {
if (view instanceof CardView) { if (view instanceof CardView) {
return getCard((CardView) view); return getCard((CardView) view);
} else if (view instanceof PlayerView) { }
if (view instanceof PlayerView) {
return getPlayer((PlayerView) view); return getPlayer((PlayerView) view);
} }
return null; return null;
} }
private final Function<Player, PlayerView> FN_GET_PLAYER_VIEW = new Function<Player, PlayerView>() { public final List<PlayerView> getPlayerViews(final Iterable<Player> players, final boolean forceUpdate) {
@Override List<PlayerView> views = new ArrayList<PlayerView>();
public PlayerView apply(final Player input) { for (Player p : players) {
return getPlayerView(input); views.add(getPlayerView(p, forceUpdate));
} }
}; return views;
public final List<PlayerView> getPlayerViews(final Iterable<Player> players) {
return ViewUtil.transformIfNotNull(players, FN_GET_PLAYER_VIEW);
} }
public Player getPlayer(final PlayerView p) { public Player getPlayer(final PlayerView p) {
@@ -356,7 +356,7 @@ public abstract class LocalGameView implements IGameView {
return MatchUtil.players.getKey(p.getId()); return MatchUtil.players.getKey(p.getId());
} }
public PlayerView getPlayerView(final Player p) { public PlayerView getPlayerView(final Player p, final boolean forceUpdate) {
if (p == null) { if (p == null) {
return null; return null;
} }
@@ -364,18 +364,16 @@ public abstract class LocalGameView implements IGameView {
PlayerView view = MatchUtil.players.get(p.getId()); PlayerView view = MatchUtil.players.get(p.getId());
if (view == null) { if (view == null) {
view = new PlayerView(p.getLobbyPlayer(), p.getId()); view = new PlayerView(p.getLobbyPlayer(), p.getId());
writePlayerToView(p, view); writePlayerToView(p, view, forceUpdate);
MatchUtil.players.put(p, view); MatchUtil.players.put(p, view);
} }
else if (updateViewOnAccess) { else if (forceUpdate) {
updateViewOnAccess = false; //set to false temporarily to prevent stack overflow writePlayerToView(p, view, true);
writePlayerToView(p, view);
updateViewOnAccess = true;
} }
return view; return view;
} }
private void writePlayerToView(final Player p, final PlayerView view) { private void writePlayerToView(final Player p, final PlayerView view, final boolean forceUpdate) {
view.setCommanderInfo(CardFactoryUtil.getCommanderInfo(p).trim().replace("\r\n", "; ")); view.setCommanderInfo(CardFactoryUtil.getCommanderInfo(p).trim().replace("\r\n", "; "));
view.setKeywords(p.getKeywords()); view.setKeywords(p.getKeywords());
view.setLife(p.getLife()); view.setLife(p.getLife());
@@ -384,16 +382,16 @@ public abstract class LocalGameView implements IGameView {
view.setPoisonCounters(p.getPoisonCounters()); view.setPoisonCounters(p.getPoisonCounters());
view.setPreventNextDamage(p.getPreventNextDamageTotalShields()); view.setPreventNextDamage(p.getPreventNextDamageTotalShields());
view.setHasUnlimitedHandSize(p.isUnlimitedHandSize()); view.setHasUnlimitedHandSize(p.isUnlimitedHandSize());
view.setAnteCards(getCardViews(p.getCardsIn(ZoneType.Ante))); view.setAnteCards(getCardViews(p.getCardsIn(ZoneType.Ante), forceUpdate));
view.setBfCards(getCardViews(p.getCardsIn(ZoneType.Battlefield, false))); view.setBfCards(getCardViews(p.getCardsIn(ZoneType.Battlefield, false), forceUpdate));
view.setCommandCards(getCardViews(p.getCardsIn(ZoneType.Command))); view.setCommandCards(getCardViews(p.getCardsIn(ZoneType.Command), forceUpdate));
view.setExileCards(getCardViews(p.getCardsIn(ZoneType.Exile))); view.setExileCards(getCardViews(p.getCardsIn(ZoneType.Exile), forceUpdate));
view.setFlashbackCards(getCardViews(p.getCardsActivableInExternalZones(false))); view.setFlashbackCards(getCardViews(p.getCardsActivableInExternalZones(false), forceUpdate));
view.setGraveCards(getCardViews(p.getCardsIn(ZoneType.Graveyard))); view.setGraveCards(getCardViews(p.getCardsIn(ZoneType.Graveyard), forceUpdate));
final List<Card> handCards = p.getCardsIn(ZoneType.Hand), final List<Card> handCards = p.getCardsIn(ZoneType.Hand),
libraryCards = p.getCardsIn(ZoneType.Library); libraryCards = p.getCardsIn(ZoneType.Library);
view.setHandCards(getCardViews(handCards)); view.setHandCards(getCardViews(handCards, forceUpdate));
view.setLibraryCards(getCardViews(libraryCards)); view.setLibraryCards(getCardViews(libraryCards, forceUpdate));
view.setnHandCards(handCards.size()); view.setnHandCards(handCards.size());
view.setnLibraryCards(libraryCards.size()); view.setnLibraryCards(libraryCards.size());
@@ -402,15 +400,7 @@ public abstract class LocalGameView implements IGameView {
} }
} }
private boolean updateViewOnAccess; public CardView getCardView(final Card c, final boolean forceUpdate) {
public void startUpdate() {
updateViewOnAccess = true; //allow accessed card views and player views to be updated
}
public void endUpdate() {
updateViewOnAccess = false;
}
public CardView getCardView(final Card c) {
if (c == null || c != c.getCardForUi()) { if (c == null || c != c.getCardForUi()) {
return null; return null;
} }
@@ -421,10 +411,8 @@ public abstract class LocalGameView implements IGameView {
writeCardToView(c, view, MatchUtil.getGameView()); writeCardToView(c, view, MatchUtil.getGameView());
MatchUtil.cards.put(c, view); MatchUtil.cards.put(c, view);
} }
else if (updateViewOnAccess) { else if (forceUpdate) {
updateViewOnAccess = false; //set to false temporarily to prevent stack overflow
writeCardToView(c, view, MatchUtil.getGameView()); writeCardToView(c, view, MatchUtil.getGameView());
updateViewOnAccess = true;
} }
return view; return view;
} }
@@ -432,19 +420,16 @@ public abstract class LocalGameView implements IGameView {
public void updateAllCards() { public void updateAllCards() {
LocalGameView gameView = MatchUtil.getGameView(); LocalGameView gameView = MatchUtil.getGameView();
for (Card c : MatchUtil.cards.getKeys()) { for (Card c : MatchUtil.cards.getKeys()) {
writeCardToView(c, getCardView(c), gameView); writeCardToView(c, getCardView(c, false), gameView);
} }
} }
private final Function<Card, CardView> FN_GET_CARD_VIEW = new Function<Card, CardView>() { public final List<CardView> getCardViews(final Iterable<Card> cards, final boolean forceUpdate) {
@Override List<CardView> cardViews = new ArrayList<CardView>();
public CardView apply(final Card input) { for (Card c : cards) {
return getCardView(input); cardViews.add(getCardView(c, forceUpdate));
} }
}; return cardViews;
public final List<CardView> getCardViews(final Iterable<Card> cards) {
return ViewUtil.transformIfNotNull(cards, FN_GET_CARD_VIEW);
} }
public Card getCard(final CardView c) { public Card getCard(final CardView c) {
@@ -474,24 +459,24 @@ public abstract class LocalGameView implements IGameView {
if (!mayShowCard) { return; } if (!mayShowCard) { return; }
final Combat combat = game.getCombat(); final Combat combat = game.getCombat();
view.setOwner(getPlayerView(c.getOwner())); view.setOwner(getPlayerView(c.getOwner(), false));
view.setController(getPlayerView(c.getController())); view.setController(getPlayerView(c.getController(), false));
view.setAttacking(combat != null && combat.isAttacking(c)); view.setAttacking(combat != null && combat.isAttacking(c));
view.setBlocking(combat != null && combat.isBlocking(c)); view.setBlocking(combat != null && combat.isBlocking(c));
view.setChosenPlayer(getPlayerView(c.getChosenPlayer())); view.setChosenPlayer(getPlayerView(c.getChosenPlayer(), false));
view.setEquipping(getCardView(Iterables.getFirst(c.getEquipping(), null))); view.setEquipping(getCardView(Iterables.getFirst(c.getEquipping(), null), false));
view.setEquippedBy(getCardViews(c.getEquippedBy())); view.setEquippedBy(getCardViews(c.getEquippedBy(), false));
view.setEnchantingCard(getCardView(c.getEnchantingCard())); view.setEnchantingCard(getCardView(c.getEnchantingCard(), false));
view.setEnchantingPlayer(getPlayerView(c.getEnchantingPlayer())); view.setEnchantingPlayer(getPlayerView(c.getEnchantingPlayer(), false));
view.setEnchantedBy(getCardViews(c.getEnchantedBy())); view.setEnchantedBy(getCardViews(c.getEnchantedBy(), false));
view.setFortifiedBy(getCardViews(c.getFortifiedBy())); view.setFortifiedBy(getCardViews(c.getFortifiedBy(), false));
view.setGainControlTargets(getCardViews(c.getGainControlTargets())); view.setGainControlTargets(getCardViews(c.getGainControlTargets(), false));
view.setCloneOrigin(getCardView(c.getCloneOrigin())); view.setCloneOrigin(getCardView(c.getCloneOrigin(), false));
view.setImprinted(getCardViews(c.getImprinted())); view.setImprinted(getCardViews(c.getImprinted(), false));
view.setHauntedBy(getCardViews(c.getHauntedBy())); view.setHauntedBy(getCardViews(c.getHauntedBy(), false));
view.setHaunting(getCardView(c.getHaunting())); view.setHaunting(getCardView(c.getHaunting(), false));
view.setMustBlock(c.getMustBlockCards() == null ? Collections.<CardView>emptySet() : getCardViews(c.getMustBlockCards())); view.setMustBlock(c.getMustBlockCards() == null ? Collections.<CardView>emptySet() : getCardViews(c.getMustBlockCards(), false));
view.setPairedWith(getCardView(c.getPairedWith())); view.setPairedWith(getCardView(c.getPairedWith(), false));
} }
public SpellAbilityView getSpellAbilityView(final SpellAbility sa) { public SpellAbilityView getSpellAbilityView(final SpellAbility sa) {
@@ -544,7 +529,7 @@ public abstract class LocalGameView implements IGameView {
} }
private void writeSpellAbilityToView(final SpellAbility sa, final SpellAbilityView view) { private void writeSpellAbilityToView(final SpellAbility sa, final SpellAbilityView view) {
view.setHostCard(getCardView(sa.getHostCard())); view.setHostCard(getCardView(sa.getHostCard(), false));
view.setDescription(sa.toUnsuppressedString()); view.setDescription(sa.toUnsuppressedString());
view.setCanPlay(sa.canPlay()); view.setCanPlay(sa.canPlay());
view.setPromptIfOnlyPossibleAbility(sa.promptIfOnlyPossibleAbility()); view.setPromptIfOnlyPossibleAbility(sa.promptIfOnlyPossibleAbility());

View File

@@ -30,10 +30,10 @@ public class StackItemView implements IIdentifiable {
key = si.getSpellAbility().toUnsuppressedString(); key = si.getSpellAbility().toUnsuppressedString();
sourceTrigger = si.getSpellAbility().getSourceTrigger(); sourceTrigger = si.getSpellAbility().getSourceTrigger();
text = si.getStackDescription(); text = si.getStackDescription();
source = gameView.getCardView(si.getSourceCard()); source = gameView.getCardView(si.getSourceCard(), false);
activatingPlayer = gameView.getPlayerView(si.getActivator()); activatingPlayer = gameView.getPlayerView(si.getActivator(), false);
targetCards = gameView.getCardViews(si.getTargetChoices().getTargetCards()); targetCards = gameView.getCardViews(si.getTargetChoices().getTargetCards(), false);
targetPlayers = gameView.getPlayerViews(si.getTargetChoices().getTargetPlayers()); targetPlayers = gameView.getPlayerViews(si.getTargetChoices().getTargetPlayers(), false);
ability = si.isAbility(); ability = si.isAbility();
optionalTrigger = si.isOptionalTrigger(); optionalTrigger = si.isOptionalTrigger();
subInstance = si.getSubInstance() == null ? null : new StackItemView(si.getSubInstance(), gameView); subInstance = si.getSubInstance() == null ? null : new StackItemView(si.getSubInstance(), gameView);