diff --git a/forge-game/src/main/java/forge/ImageKeys.java b/forge-game/src/main/java/forge/ImageKeys.java index 14e602c8af0..26c4ecea824 100644 --- a/forge-game/src/main/java/forge/ImageKeys.java +++ b/forge-game/src/main/java/forge/ImageKeys.java @@ -12,8 +12,9 @@ public class ImageKeys { public static final String BOOSTERBOX_PREFIX = "x:"; public static final String PRECON_PREFIX = "p:"; public static final String TOURNAMENTPACK_PREFIX = "o:"; - + public static final String MORPH_IMAGE = "morph"; + public static final String HIDDEN_CARD = TOKEN_PREFIX + MORPH_IMAGE; public static final String BACKFACE_POSTFIX = "$alt"; diff --git a/forge-game/src/main/java/forge/game/zone/MagicStack.java b/forge-game/src/main/java/forge/game/zone/MagicStack.java index 58517b70994..d9703fd5bd4 100644 --- a/forge-game/src/main/java/forge/game/zone/MagicStack.java +++ b/forge-game/src/main/java/forge/game/zone/MagicStack.java @@ -71,6 +71,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable stack = new LinkedBlockingDeque(); private final Stack frozenStack = new Stack(); private final Stack undoStack = new Stack(); + private Player undoStackOwner; private boolean frozen = false; private boolean bResolving = false; @@ -126,7 +127,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable */ public final void clearUndoStack() { + if (undoStackOwner == null) { return; } undoStack.clear(); + undoStackOwner = null; } /** @@ -289,13 +295,16 @@ public class MagicStack /* extends MyObservable */ implements Iterable newPanels = new ArrayList(); for (final CardView card : toAdd) { - if (card.isUiDisplayable()) { //only include cards that are meant for display - final CardPanel placeholder = new CardPanel(card); - placeholder.setDisplayEnabled(false); - this.getCardPanels().add(placeholder); - this.add(placeholder); - newPanels.add(placeholder); - } + final CardPanel placeholder = new CardPanel(card); + placeholder.setDisplayEnabled(false); + this.getCardPanels().add(placeholder); + this.add(placeholder); + newPanels.add(placeholder); } if (!newPanels.isEmpty()) { diff --git a/forge-gui-mobile/src/forge/Forge.java b/forge-gui-mobile/src/forge/Forge.java index 856888ff430..0065af3d9bd 100644 --- a/forge-gui-mobile/src/forge/Forge.java +++ b/forge-gui-mobile/src/forge/Forge.java @@ -235,7 +235,13 @@ public class Forge implements ApplicationListener { graphics.begin(screenWidth, screenHeight); screen.screenPos.setSize(screenWidth, screenHeight); + if (screen.getRotate180()) { + graphics.startRotateTransform(screenWidth / 2, screenHeight / 2, 180); + } screen.draw(graphics); + if (screen.getRotate180()) { + graphics.endTransform(); + } for (FOverlay overlay : FOverlay.getOverlays()) { overlay.screenPos.setSize(screenWidth, screenHeight); overlay.setSize(screenWidth, screenHeight); //update overlay sizes as they're rendered diff --git a/forge-gui-mobile/src/forge/card/CardRenderer.java b/forge-gui-mobile/src/forge/card/CardRenderer.java index 372950535d9..1b22e864ad8 100644 --- a/forge-gui-mobile/src/forge/card/CardRenderer.java +++ b/forge-gui-mobile/src/forge/card/CardRenderer.java @@ -27,7 +27,6 @@ import forge.item.IPaperCard; import forge.match.MatchUtil; import forge.model.FModel; import forge.properties.ForgePreferences.FPref; -import forge.screens.match.MatchController; import forge.toolbox.FCardPanel; import forge.toolbox.FDialog; import forge.toolbox.FList; @@ -268,7 +267,7 @@ public class CardRenderer { public static void drawCardListItem(Graphics g, FSkinFont font, FSkinColor foreColor, CardView card, int count, String suffix, float x, float y, float w, float h, boolean compactMode) { final CardStateView state = card.getOriginal(); - if (card.isUiDisplayable()) { + if (card.getId() > 0) { drawCardListItem(g, font, foreColor, getCardArt(card), card, card.getSetCode(), card.getRarity(), state.getPower(), state.getToughness(), state.getLoyalty(), count, suffix, x, y, w, h, compactMode); @@ -286,22 +285,10 @@ public class CardRenderer { } public static void drawCardListItem(Graphics g, FSkinFont font, FSkinColor foreColor, IPaperCard pc, int count, String suffix, float x, float y, float w, float h, boolean compactMode) { final CardView card = ViewUtil.getCardForUi(pc); - if (card.isUiDisplayable()) { - final CardStateView state = card.getOriginal(); - drawCardListItem(g, font, foreColor, getCardArt(pc), card, pc.getEdition(), - pc.getRarity(), state.getPower(), state.getToughness(), - state.getLoyalty(), count, suffix, x, y, w, h, compactMode); - } - else { //if fake card, just draw card name centered - String name = pc.getName(); - if (count > 0) { //preface name with count if applicable - name = count + " " + name; - } - if (suffix != null) { - name += suffix; - } - g.drawText(name, font, foreColor, x, y, w, h, false, HAlignment.CENTER, true); - } + final CardStateView state = card.getOriginal(); + drawCardListItem(g, font, foreColor, getCardArt(pc), card, pc.getEdition(), + pc.getRarity(), state.getPower(), state.getToughness(), + state.getLoyalty(), count, suffix, x, y, w, h, compactMode); } public static void drawCardListItem(Graphics g, FSkinFont font, FSkinColor foreColor, FImageComplex cardArt, CardView card, String set, CardRarity rarity, int power, int toughness, int loyalty, int count, String suffix, float x, float y, float w, float h, boolean compactMode) { float cardArtHeight = h + 2 * FList.PADDING; @@ -544,13 +531,13 @@ public class CardRenderer { w -= 2 * padding; h -= 2 * padding; - CardStateView details = MatchController.getCardDetails(card); + CardStateView details = card.getOriginal(); DetailColors borderColor = CardDetailUtil.getBorderColor(details); Color color = FSkinColor.fromRGB(borderColor.r, borderColor.g, borderColor.b); color = FSkinColor.tintColor(Color.WHITE, color, CardRenderer.PT_BOX_TINT); //draw name and mana cost overlays if card is small or default card image being used - if (h <= NAME_COST_THRESHOLD) { + if (h <= NAME_COST_THRESHOLD && card.mayBeShown()) { if (showCardNameOverlay(card)) { g.drawOutlinedText(details.getName(), FSkinFont.forHeight(h * 0.18f), Color.WHITE, Color.BLACK, x + padding, y + padding, w - 2 * padding, h * 0.4f, true, HAlignment.LEFT, false); } @@ -626,7 +613,7 @@ public class CardRenderer { CardFaceSymbols.drawSymbol("sacrifice", g, (x + (w / 2)) - sacSymbolSize / 2, (y + (h / 2)) - sacSymbolSize / 2, otherSymbolsSize, otherSymbolsSize); } - if (onTop && showCardPowerOverlay(card)) { //make sure card p/t box appears on top + if (onTop && showCardPowerOverlay(card) && (card.mayBeShown() || card.isFaceDown())) { //make sure card p/t box appears on top //only needed if on top since otherwise P/T will be hidden drawPtBox(g, card, details, color, x, y, w, h); } @@ -688,7 +675,7 @@ public class CardRenderer { } public static void drawFoilEffect(Graphics g, CardView card, float x, float y, float w, float h) { - if (isPreferenceEnabled(FPref.UI_OVERLAY_FOIL_EFFECT)) { + if (isPreferenceEnabled(FPref.UI_OVERLAY_FOIL_EFFECT) && card.mayBeShown()) { int foil = card.getOriginal().getFoilIndex(); if (foil > 0) { CardFaceSymbols.drawOther(g, String.format("foil%02d", foil), x, y, w, h); diff --git a/forge-gui-mobile/src/forge/deck/FDeckViewer.java b/forge-gui-mobile/src/forge/deck/FDeckViewer.java index bce5d0d331a..ba7c8e62314 100644 --- a/forge-gui-mobile/src/forge/deck/FDeckViewer.java +++ b/forge-gui-mobile/src/forge/deck/FDeckViewer.java @@ -8,6 +8,7 @@ import forge.item.PaperCard; import forge.itemmanager.CardManager; import forge.itemmanager.ItemManagerConfig; import forge.screens.FScreen; +import forge.screens.match.MatchController; import forge.toolbox.FButton; import forge.toolbox.FEvent; import forge.toolbox.FEvent.FEventHandler; @@ -33,7 +34,9 @@ public class FDeckViewer extends FScreen { public static void show(final Deck deck) { if (deck == null) { return; } - Forge.openScreen(new FDeckViewer(deck)); + FDeckViewer deckViewer = new FDeckViewer(deck); + deckViewer.setRotate180(MatchController.getView() != null && MatchController.getView().isTopHumanPlayerActive()); + Forge.openScreen(deckViewer); } private FDeckViewer(Deck deck0) { diff --git a/forge-gui-mobile/src/forge/screens/match/MatchController.java b/forge-gui-mobile/src/forge/screens/match/MatchController.java index 333e5831b09..6c63afa02e6 100644 --- a/forge-gui-mobile/src/forge/screens/match/MatchController.java +++ b/forge-gui-mobile/src/forge/screens/match/MatchController.java @@ -3,10 +3,8 @@ package forge.screens.match; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.Map.Entry; import org.apache.commons.lang3.tuple.Pair; @@ -47,14 +45,12 @@ import forge.view.GameEntityView; import forge.view.LocalGameView; import forge.view.PlayerView; import forge.view.SpellAbilityView; -import forge.view.CardView.CardStateView; public class MatchController implements IMatchController { private MatchController() { } public static final MatchController instance = new MatchController(); private static final Map avatarImages = new HashMap(); - private static final Map cardDetailsCache = new HashMap(); private static MatchScreen view; @@ -75,39 +71,10 @@ public class MatchController implements IMatchController { avatarImages.put(lp, avatarImage); } - public static CardStateView getCardDetails(CardView card) { - final CardStateView details = cardDetailsCache.get(card.getId()); - if (details == null) { - cardDetailsCache.put(card.getId(), card.getOriginal()); - return card.getOriginal(); - } - return details; - } - public void refreshCardDetails(Iterable cards) { - Set playersNeedingFieldUpdate = null; - - for (final CardView c : cards) { - //for each card in play, if it changed from creature to non-creature or vice versa, - //or if it changed from land to non-land or vice-versa, - //ensure field containing that card is updated to reflect that change - final CardStateView state = c.getOriginal(); - if (c.getZone() == ZoneType.Battlefield) { - CardStateView oldDetails = cardDetailsCache.get(c); - if (oldDetails == null || state.isCreature() != oldDetails.isCreature() || state.isLand() != oldDetails.isLand()) { - if (playersNeedingFieldUpdate == null) { - playersNeedingFieldUpdate = new HashSet(); - } - playersNeedingFieldUpdate.add(c.getController()); - } - } - cardDetailsCache.put(c.getId(), c.getOriginal()); - } - - if (playersNeedingFieldUpdate != null) { //update field for any players necessary - for (PlayerView p : playersNeedingFieldUpdate) { - view.getPlayerPanel(p).getField().update(); - } + //ensure cards appear in the correct row of the field + for (VPlayerPanel pnl : view.getPlayerPanels().values()) { + pnl.getField().update(); } } @@ -118,7 +85,6 @@ public class MatchController implements IMatchController { @Override public boolean resetForNewGame() { - cardDetailsCache.clear(); //ensure details cache cleared before starting a new game CardAreaPanel.resetForNewGame(); //ensure card panels reset between games return true; } @@ -359,7 +325,7 @@ public class MatchController implements IMatchController { @Override public void afterGameEnd() { Forge.back(); - cardDetailsCache.clear(); //ensure card details cache cleared ending game + view = null; } private static void actuateMatchPreferences() { diff --git a/forge-gui-mobile/src/forge/screens/match/views/VCardDisplayArea.java b/forge-gui-mobile/src/forge/screens/match/views/VCardDisplayArea.java index 538d9342eb6..b6a9d04e069 100644 --- a/forge-gui-mobile/src/forge/screens/match/views/VCardDisplayArea.java +++ b/forge-gui-mobile/src/forge/screens/match/views/VCardDisplayArea.java @@ -48,13 +48,11 @@ public abstract class VCardDisplayArea extends VDisplayArea { CardAreaPanel newCardPanel = null; for (CardView card : model) { - if (card.isUiDisplayable()) { //only include cards that are meant for display - CardAreaPanel cardPanel = CardAreaPanel.get(card); - addCardPanelToDisplayArea(cardPanel); - cardPanels.add(cardPanel); - if (newCardPanel == null && !orderedCards.contains(card)) { - newCardPanel = cardPanel; - } + CardAreaPanel cardPanel = CardAreaPanel.get(card); + addCardPanelToDisplayArea(cardPanel); + cardPanels.add(cardPanel); + if (newCardPanel == null && !orderedCards.contains(card)) { + newCardPanel = cardPanel; } } revalidate(); @@ -330,6 +328,14 @@ public abstract class VCardDisplayArea extends VDisplayArea { return origin; } + @Override + protected float getTappedAngle() { + if (displayArea != null && displayArea.rotateCards180) { + return -super.getTappedAngle(); //reverse tap angle if rotated 180 degrees + } + return super.getTappedAngle(); + } + @Override public void draw(Graphics g) { if (displayArea != null && displayArea.rotateCards180) { diff --git a/forge-gui-mobile/src/forge/screens/match/views/VField.java b/forge-gui-mobile/src/forge/screens/match/views/VField.java index 7e2eb26dcaf..c90556982b1 100644 --- a/forge-gui-mobile/src/forge/screens/match/views/VField.java +++ b/forge-gui-mobile/src/forge/screens/match/views/VField.java @@ -5,7 +5,6 @@ import java.util.List; import forge.FThreads; import forge.GuiBase; -import forge.screens.match.MatchController; import forge.screens.match.views.VCardDisplayArea.CardAreaPanel; import forge.toolbox.FContainer; import forge.view.CardView; @@ -62,7 +61,7 @@ public class VField extends FContainer { for (CardView card : model) { CardAreaPanel cardPanel = CardAreaPanel.get(card); - CardStateView details = MatchController.getCardDetails(card); //use details so creature/land check is accurate + CardStateView details = card.getOriginal(); if (cardPanel.getAttachedToPanel() == null) { //skip attached panels if (details.isCreature()) { if (!tryStackCard(card, creatures)) { @@ -124,14 +123,7 @@ public class VField extends FContainer { final CardAreaPanel toPanel = CardAreaPanel.get(card); if (toPanel == null) { return; } - if (card.isTapped()) { - toPanel.setTapped(true); - toPanel.setTappedAngle(CardAreaPanel.TAPPED_ANGLE); - } - else { - toPanel.setTapped(false); - toPanel.setTappedAngle(0); - } + toPanel.setTapped(card.isTapped()); toPanel.getAttachedPanels().clear(); if (card.isEnchanted()) { diff --git a/forge-gui-mobile/src/forge/screens/match/views/VGameMenu.java b/forge-gui-mobile/src/forge/screens/match/views/VGameMenu.java index 15a7fb36fbe..fcb85712779 100644 --- a/forge-gui-mobile/src/forge/screens/match/views/VGameMenu.java +++ b/forge-gui-mobile/src/forge/screens/match/views/VGameMenu.java @@ -1,6 +1,5 @@ package forge.screens.match.views; -import forge.LobbyPlayer; import forge.assets.FSkinImage; import forge.deck.Deck; import forge.deck.FDeckViewer; @@ -10,7 +9,6 @@ import forge.game.spellability.SpellAbility; import forge.match.MatchUtil; import forge.menu.FDropDownMenu; import forge.menu.FMenuItem; -import forge.player.GamePlayerUtil; import forge.screens.settings.SettingsScreen; import forge.toolbox.FEvent; import forge.toolbox.FEvent.FEventHandler; @@ -50,8 +48,7 @@ public class VGameMenu extends FDropDownMenu { addItem(new FMenuItem("Deck List", FSkinImage.DECKLIST, new FEventHandler() { @Override public void handleEvent(FEvent e) { - final LobbyPlayer guiPlayer = GamePlayerUtil.getGuiPlayer(); - final Deck deck = MatchUtil.getGameView().getDeck(guiPlayer); + final Deck deck = MatchUtil.getCurrentPlayer().getRegisteredPlayer().getDeck(); if (deck != null) { FDeckViewer.show(deck); } diff --git a/forge-gui-mobile/src/forge/screens/match/views/VPhaseIndicator.java b/forge-gui-mobile/src/forge/screens/match/views/VPhaseIndicator.java index 495b9dfce05..00dc485af98 100644 --- a/forge-gui-mobile/src/forge/screens/match/views/VPhaseIndicator.java +++ b/forge-gui-mobile/src/forge/screens/match/views/VPhaseIndicator.java @@ -53,14 +53,6 @@ public class VPhaseIndicator extends FContainer { } } - @Override - public void setRotate180(boolean b0) { - //only rotate phase labels themselves - for (PhaseLabel lbl : phaseLabels.values()) { - lbl.setRotate180(b0); - } - } - public float getPreferredHeight(float width) { //build string to use to determine ideal font float w = width / phaseLabels.size(); diff --git a/forge-gui-mobile/src/forge/toolbox/FCardPanel.java b/forge-gui-mobile/src/forge/toolbox/FCardPanel.java index b5cbc0fd733..c31d81ec4bc 100644 --- a/forge-gui-mobile/src/forge/toolbox/FCardPanel.java +++ b/forge-gui-mobile/src/forge/toolbox/FCardPanel.java @@ -7,7 +7,6 @@ import forge.util.Utils; import forge.view.CardView; public class FCardPanel extends FDisplayObject { - public static final float TAPPED_ANGLE = -90; public static final float ASPECT_RATIO = 3.5f / 2.5f; public static final float PADDING = Utils.scale(2); public static final float TARGET_ORIGIN_FACTOR_X = 0.15f; @@ -15,7 +14,6 @@ public class FCardPanel extends FDisplayObject { private CardView card; private boolean tapped; - private float tappedAngle = 0; private boolean highlighted; public FCardPanel() { @@ -46,11 +44,8 @@ public class FCardPanel extends FDisplayObject { tapped = tapped0; } - public float getTappedAngle() { - return tappedAngle; - } - public void setTappedAngle(float tappedAngle0) { - tappedAngle = tappedAngle0; + protected float getTappedAngle() { + return -90; } protected boolean renderedCardContains(float x, float y) { @@ -96,7 +91,7 @@ public class FCardPanel extends FDisplayObject { if (tapped) { float edgeOffset = w / 2f; - g.startRotateTransform(x + edgeOffset, y + h - edgeOffset, tappedAngle); + g.startRotateTransform(x + edgeOffset, y + h - edgeOffset, getTappedAngle()); } CardRenderer.drawCardWithOverlays(g, card, x, y, w, h, getStackPosition()); diff --git a/forge-gui/src/main/java/forge/card/CardDetailUtil.java b/forge-gui/src/main/java/forge/card/CardDetailUtil.java index a88b20348e0..07a986b376d 100644 --- a/forge-gui/src/main/java/forge/card/CardDetailUtil.java +++ b/forge-gui/src/main/java/forge/card/CardDetailUtil.java @@ -53,7 +53,7 @@ public class CardDetailUtil { if (card == null) { return getBorderColors(null, false, false, false).iterator().next(); } - return getBorderColors(card.getColors(), card.isLand(), card.getCard().isUiDisplayable(), false).iterator().next(); + return getBorderColors(card.getColors(), card.isLand(), card.getCard().mayBeShown(), false).iterator().next(); } public static DetailColors getBorderColor(final ColorSet cardColors, final boolean isLand, boolean canShow) { return getBorderColors(cardColors, isLand, canShow, false).get(0); @@ -62,7 +62,7 @@ public class CardDetailUtil { if (card == null) { return getBorderColors(null, false, false, true); } - return getBorderColors(card.getColors(), card.isLand(), card.getCard().isUiDisplayable(), true); + return getBorderColors(card.getColors(), card.isLand(), card.getCard().mayBeShown(), true); } private static List getBorderColors(final ColorSet cardColors, final boolean isLand, boolean canShow, boolean supportMultiple) { List borderColors = new ArrayList(); diff --git a/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java b/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java index 22122a393d5..4baa68a467e 100644 --- a/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java +++ b/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java @@ -32,6 +32,7 @@ import forge.game.event.GameEventCombatChanged; import forge.game.event.GameEventCombatEnded; import forge.game.event.GameEventGameFinished; import forge.game.event.GameEventGameOutcome; +import forge.game.event.GameEventGameStarted; import forge.game.event.GameEventManaPool; import forge.game.event.GameEventPlayerControl; import forge.game.event.GameEventPlayerLivesChanged; @@ -74,9 +75,16 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { @Subscribe public void receiveGameEvent(final GameEvent ev) { + gameView.updateViews(); ev.visit(this); } + @Override + public Void visit(GameEventGameStarted event) { + gameView.endUpdateDelay(); //allow views to update once game starts + return null; + } + private final AtomicBoolean phaseUpdPlanned = new AtomicBoolean(false); @Override public Void visit(final GameEventTurnPhase ev) { @@ -142,7 +150,7 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { final List options = Lists.newArrayList(); for (final Entry kv : ev.cards.entries()) { - final CardView fakeCard = new CardView(true); //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 --"); options.add(fakeCard); options.add(gameView.getCardView(kv.getValue())); @@ -294,8 +302,7 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { @Override public void run() { synchronized (cardsToUpdate) { - final Iterable newCardsToUpdate = gameView.getRefreshedCardViews(cardsToUpdate); - MatchUtil.updateCards(newCardsToUpdate); + MatchUtil.updateCards(cardsToUpdate); cardsToUpdate.clear(); } } diff --git a/forge-gui/src/main/java/forge/match/MatchUtil.java b/forge-gui/src/main/java/forge/match/MatchUtil.java index 14d21a33947..e7b219b596a 100644 --- a/forge-gui/src/main/java/forge/match/MatchUtil.java +++ b/forge-gui/src/main/java/forge/match/MatchUtil.java @@ -46,7 +46,6 @@ import forge.game.trigger.TriggerType; import forge.game.zone.ZoneType; import forge.match.input.InputPlaybackControl; import forge.match.input.InputQueue; -import forge.match.input.InputSynchronized; import forge.model.FModel; import forge.player.GamePlayerUtil; import forge.player.LobbyPlayerHuman; @@ -71,6 +70,7 @@ import forge.view.WatchLocalGame; public class MatchUtil { private static IMatchController controller; private static Game game; + private static Player currentPlayer; private static final List gameViews = new ArrayList(); /** Cache of players. */ @@ -180,6 +180,10 @@ public class MatchUtil { if (p.getController() instanceof PlayerControllerHuman) { final PlayerControllerHuman controller = (PlayerControllerHuman) p.getController(); LocalGameView gameView = controller.getGameView(); + if (humanCount == 0) { + currentPlayer = p; + gameView.startUpdateDelay(); //delay updating views until game finishes initializing + } game.subscribeToEvents(new FControlGameEventHandler(gameView, humanCount == 0)); gameViews.add(gameView); humanCount++; @@ -188,7 +192,9 @@ public class MatchUtil { if (humanCount == 0) { //watch game but do not participate LocalGameView gameView = new WatchLocalGame(GuiBase.getInterface(), game); - gameView.setLocalPlayer(sortedPlayers.get(0)); + currentPlayer = sortedPlayers.get(0); + gameView.setLocalPlayer(currentPlayer); + gameView.startUpdateDelay(); game.subscribeToEvents(new FControlGameEventHandler(gameView, true)); gameViews.add(gameView); } @@ -235,7 +241,7 @@ public class MatchUtil { } public static LocalGameView getGameView() { - return getGameView(getCurrentPlayer()); + return getGameView(currentPlayer); } public static LocalGameView getGameView(Player player) { switch (gameViews.size()) { @@ -244,10 +250,7 @@ public class MatchUtil { case 0: return null; default: - if (player != null && player.getController() instanceof PlayerControllerHuman) { - return ((PlayerControllerHuman)player.getController()).getGameView(); - } - return gameViews.get(0); + return gameViews.get(player.getId()); } } @@ -280,23 +283,14 @@ public class MatchUtil { } public static Player getCurrentPlayer() { - if (game == null) { return null; } - - LobbyPlayer lobbyPlayer = getGuiPlayer(); + return currentPlayer; + } + public static void setCurrentPlayer(Player currentPlayer0) { + if (currentPlayer == currentPlayer0) { return; } + currentPlayer = currentPlayer0; if (gameViews.size() > 1) { - //account for if second human player is currently being prompted - InputSynchronized activeInput = InputQueue.getActiveInput(); - if (activeInput != null) { - lobbyPlayer = activeInput.getOwner().getLobbyPlayer(); - } + gameViews.get(currentPlayer.getId()).updateViews(); //ensure views updated when current player changes to account for changes in card visibility } - - for (Player p : game.getPlayers()) { - if (p.getLobbyPlayer() == lobbyPlayer) { - return p; - } - } - return null; } public static void alphaStrike() { @@ -368,7 +362,7 @@ public class MatchUtil { } Player priorityPlayer = game.getPhaseHandler().getPriorityPlayer(); - boolean humanHasPriority = priorityPlayer == null || priorityPlayer.getLobbyPlayer() == getGuiPlayer(); + boolean humanHasPriority = priorityPlayer == null || priorityPlayer.getLobbyPlayer() instanceof LobbyPlayerHuman; if (humanCount > 0 && humanHasPriority) { game.getAction().checkGameOverCondition(); @@ -388,6 +382,7 @@ public class MatchUtil { if (game == null) { return; } game = null; + currentPlayer = null; gameViews.clear(); players.clear(); cards.clear(); diff --git a/forge-gui/src/main/java/forge/match/input/InputProxy.java b/forge-gui/src/main/java/forge/match/input/InputProxy.java index 74f719f7fe8..7de9493c75e 100644 --- a/forge-gui/src/main/java/forge/match/input/InputProxy.java +++ b/forge-gui/src/main/java/forge/match/input/InputProxy.java @@ -22,6 +22,9 @@ import java.util.Observer; import java.util.concurrent.atomic.AtomicReference; import forge.FThreads; +import forge.game.card.Card; +import forge.game.player.Player; +import forge.game.spellability.SpellAbility; import forge.interfaces.IGuiBase; import forge.util.ITriggerEvent; import forge.view.CardView; @@ -97,34 +100,23 @@ public class InputProxy implements Observer { } } - /** - *

- * selectPlayer. - *

- * - * @param player - * a {@link forge.game.player.Player} object. - */ - public final void selectPlayer(final PlayerView player, final ITriggerEvent triggerEvent) { + public final void selectPlayer(final PlayerView playerView, final ITriggerEvent triggerEvent) { final Input inp = getInput(); if (inp != null) { - inp.selectPlayer(gameView.getPlayer(player), triggerEvent); + final Player player = gameView.getPlayer(playerView); + if (player != null) { + inp.selectPlayer(player, triggerEvent); + } } } - /** - *

- * selectCard. - *

- * - * @param cardView - * a {@link forge.game.card.Card} object. - * @param triggerEvent - */ public final boolean selectCard(final CardView cardView, final ITriggerEvent triggerEvent) { final Input inp = getInput(); if (inp != null) { - return inp.selectCard(gameView.getCard(cardView), triggerEvent); + final Card card = gameView.getCard(cardView); + if (card != null) { + return inp.selectCard(card, triggerEvent); + } } return false; } @@ -132,7 +124,10 @@ public class InputProxy implements Observer { public final void selectAbility(final SpellAbilityView ab) { final Input inp = getInput(); if (inp != null) { - inp.selectAbility(gameView.getSpellAbility(ab)); + final SpellAbility sa = gameView.getSpellAbility(ab); + if (sa != null) { + inp.selectAbility(sa); + } } } 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 81d1570a1b7..3468b779dcc 100644 --- a/forge-gui/src/main/java/forge/match/input/InputQueue.java +++ b/forge-gui/src/main/java/forge/match/input/InputQueue.java @@ -22,6 +22,7 @@ import java.util.concurrent.BlockingDeque; import java.util.concurrent.LinkedBlockingDeque; import forge.game.Game; +import forge.match.MatchUtil; import forge.view.IGameView; /** @@ -33,12 +34,6 @@ import forge.view.IGameView; * @version $Id: InputQueue.java 24769 2014-02-09 13:56:04Z Hellfish $ */ public class InputQueue extends Observable { - private static InputSynchronized activeInput; - - public static InputSynchronized getActiveInput() { - return activeInput; - } - private final BlockingDeque inputStack = new LinkedBlockingDeque(); private final InputLockUI inputLock; @@ -62,9 +57,6 @@ public class InputQueue extends Observable { if (topMostInput != inp) { throw new RuntimeException("Cannot remove input " + inp.getClass().getSimpleName() + " because it's not on top of stack. Stack = " + inputStack ); } - if (inp == activeInput) { - activeInput = null; - } updateObservers(); } @@ -89,7 +81,9 @@ public class InputQueue extends Observable { } public void setInput(final InputSynchronized input) { - activeInput = input; + if (MatchUtil.getHumanCount() > 1) { //update current player if needed + MatchUtil.setCurrentPlayer(MatchUtil.players.getKey(input.getOwner().getId())); + } inputStack.push(input); inputLock.setGui(input.getGui()); InputBase.waitForOtherPlayer(); diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index 7e65eb95a0a..cf29d0b4c9e 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -11,11 +11,10 @@ import java.util.Collection; import java.util.Collections; import java.util.EnumMap; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Set; - import org.apache.commons.lang3.Range; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; @@ -29,8 +28,6 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; -import com.google.common.collect.Sets; - import forge.FThreads; import forge.LobbyPlayer; import forge.achievement.AchievementCollection; @@ -124,7 +121,6 @@ public class PlayerControllerHuman extends PlayerController { * Cards this player may look at right now, for example when searching a * library. */ - private final Set mayLookAt = Sets.newHashSet(); private boolean mayLookAtAllCards = false; public PlayerControllerHuman(Game game0, Player p, LobbyPlayer lp, IGuiBase gui) { @@ -163,6 +159,30 @@ public class PlayerControllerHuman extends PlayerController { return mayLookAtAllCards; } + private final HashSet tempShownCards = new HashSet(); + private void tempShowCard(Card c) { + CardView cv = MatchUtil.cards.get(c.getId()); + if (!cv.mayBeShown()) { + cv.setMayBeShown(true); + tempShownCards.add(c); + } + } + private void tempShowCards(Iterable cards) { + if (mayLookAtAllCards) { return; } //no needed if this is set + + for (Card c : cards) { + tempShowCard(c); + } + } + private void endTempShowCards() { + if (tempShownCards.isEmpty()) { return; } + + for (Card c : tempShownCards) { + MatchUtil.cards.get(c.getId()).setMayBeShown(false); + } + tempShownCards.clear(); + } + /** * Set this to {@code true} to enable this player to see all cards any other * player can see. @@ -355,9 +375,9 @@ public class PlayerControllerHuman extends PlayerController { return Lists.newArrayList(sc.getSelected()); } - this.mayLookAt.addAll(sourceList); + tempShowCards(sourceList); final List choices = SGuiChoose.many(getGui(), title, "Chosen Cards", min, max, gameView.getCardViews(sourceList), gameView.getCardView(sa.getHostCard())); - this.mayLookAt.removeAll(sourceList); + endTempShowCards(); return getCards(choices); } @@ -398,11 +418,11 @@ public class PlayerControllerHuman extends PlayerController { for (final T t : options) { if (t instanceof Card) { // assume you may see any card passed through here - mayLookAt.add((Card) t); + tempShowCard((Card) t); } } final GameEntityView result = isOptional ? SGuiChoose.oneOrNone(getGui(), title, gameView.getGameEntityViews((Iterable) options)) : SGuiChoose.one(getGui(), title, gameView.getGameEntityViews((Iterable) options)); - mayLookAt.clear(); + endTempShowCards(); return (T) gameView.getGameEntity(result); } @@ -540,9 +560,9 @@ public class PlayerControllerHuman extends PlayerController { } String fm = formatMessage(message, owner); if (!cards.isEmpty()) { - mayLookAt.addAll(cards); + tempShowCards(cards); SGuiChoose.reveal(getGui(), fm, gameView.getCardViews(cards)); - mayLookAt.clear(); + endTempShowCards(); } else { SGuiDialog.message(getGui(), formatMessage("There are no cards in {player's} " + @@ -555,7 +575,7 @@ public class PlayerControllerHuman extends PlayerController { List toBottom = null; List toTop = null; - mayLookAt.addAll(topN); + tempShowCards(topN); if (topN.size() == 1) { if (willPutCardOnTop(topN.get(0))) { toTop = topN; @@ -579,7 +599,7 @@ public class PlayerControllerHuman extends PlayerController { toTop = gameView.getCards(toTopViews); } } - mayLookAt.clear(); + endTempShowCards(); return ImmutablePair.of(toTop, toBottom); } @@ -594,7 +614,7 @@ public class PlayerControllerHuman extends PlayerController { @Override public List orderMoveToZoneList(List cards, ZoneType destinationZone) { List choices; - mayLookAt.addAll(cards); + tempShowCards(cards); switch (destinationZone) { case Library: choices = SGuiChoose.order(getGui(), "Choose order of cards to put into the library", "Closest to top", getCardViews(cards), null); @@ -616,20 +636,20 @@ public class PlayerControllerHuman extends PlayerController { break; default: System.out.println("ZoneType " + destinationZone + " - Not Ordered"); - mayLookAt.clear(); + endTempShowCards(); return cards; } - mayLookAt.clear(); + endTempShowCards(); return getCards(choices); } @Override public List chooseCardsToDiscardFrom(Player p, SpellAbility sa, List valid, int min, int max) { if (p != player) { - mayLookAt.addAll(valid); + tempShowCards(valid); final List choices = SGuiChoose.many(getGui(), "Choose " + min + " card" + (min != 1 ? "s" : "") + " to discard", "Discarded", min, min, gameView.getCardViews(valid), null); - mayLookAt.clear(); + endTempShowCards(); return getCards(choices); } @@ -1245,28 +1265,17 @@ public class PlayerControllerHuman extends PlayerController { return SGuiDialog.confirm(getGui(), gameView.getCardView(sa.getHostCard()), "Choose a Pile", possibleValues); } - mayLookAt.addAll(pile1); - mayLookAt.addAll(pile2); + tempShowCards(pile1); + tempShowCards(pile2); - final int idPile1 = Integer.MIN_VALUE, idPile2 = Integer.MIN_VALUE + 1; final List cards = Lists.newArrayListWithCapacity(pile1.size() + pile2.size() + 2); - final CardView pileView1 = new CardView(true) { - @Override - public String toString() { - return "--- Pile 1 ---"; - } - }; - pileView1.setId(idPile1); + final CardView pileView1 = new CardView(Integer.MIN_VALUE); + pileView1.getOriginal().setName("--- Pile 1 ---"); cards.add(pileView1); cards.addAll(getCardViews(pile1)); - final CardView pileView2 = new CardView(true) { - @Override - public String toString() { - return "--- Pile 2 ---"; - } - }; - pileView2.setId(idPile2); + final CardView pileView2 = new CardView(Integer.MIN_VALUE + 1); + pileView2.getOriginal().setName("--- Pile 2 ---"); cards.add(pileView2); cards.addAll(getCardViews(pile2)); @@ -1277,13 +1286,14 @@ public class PlayerControllerHuman extends PlayerController { if (chosen.equals(pileView1)) { result = true; break; - } else if (chosen.equals(pileView2)) { + } + if (chosen.equals(pileView2)) { result = false; break; } } - mayLookAt.clear(); + endTempShowCards(); return result; } @@ -1359,7 +1369,7 @@ public class PlayerControllerHuman extends PlayerController { @Override public boolean canUndoLastAction() { - if (!game.stack.canUndo()) { + if (!game.stack.canUndo(player)) { return false; } final Player priorityPlayer = game.getPhaseHandler().getPriorityPlayer(); @@ -1467,15 +1477,15 @@ public class PlayerControllerHuman extends PlayerController { */ @Override public boolean mayShowCard(final Card c) { - if (mayLookAtAllCards()) { + if (mayLookAtAllCards) { return true; } - return c == null || mayLookAt.contains(c) || c.canBeShownTo(player); + return c == null || tempShownCards.contains(c) || c.canBeShownTo(player); } @Override public boolean mayShowCardFace(final Card c) { - if (mayLookAtAllCards()) { + if (mayLookAtAllCards) { return true; } return c == null || !c.isFaceDown() || c.canCardFaceBeShownTo(player); diff --git a/forge-gui/src/main/java/forge/view/Cache.java b/forge-gui/src/main/java/forge/view/Cache.java index c0643ca8b80..081040f61ab 100644 --- a/forge-gui/src/main/java/forge/view/Cache.java +++ b/forge-gui/src/main/java/forge/view/Cache.java @@ -146,6 +146,14 @@ public class Cache { } } + public Iterable getKeys() { + return inverseCache.values(); + } + + public Iterable getValues() { + return cache.values(); + } + /** * Clear all the mappings in this Cache, except for any key that exists in * the argument. diff --git a/forge-gui/src/main/java/forge/view/CardView.java b/forge-gui/src/main/java/forge/view/CardView.java index 7e68202fcf0..ccdfe5675e3 100644 --- a/forge-gui/src/main/java/forge/view/CardView.java +++ b/forge-gui/src/main/java/forge/view/CardView.java @@ -30,18 +30,14 @@ import forge.game.zone.ZoneType; * @author elcnesh */ public class CardView extends GameEntityView { - - public static final CardView EMPTY = new CardView(true); - private final CardStateView original = new CardStateView(), alternate = new CardStateView(); private boolean hasAltState; - private int id; - /** Will be false for {@link forge.game.ability.effects.DetachedCardEffect}. */ - private final boolean isUiDisplayable; + private final int id; + private boolean mayBeShown; private PlayerView owner, controller; private ZoneType zone; private boolean isCloned, isFaceDown, isFlipCard, isFlipped, isSplitCard, isTransformed; @@ -68,14 +64,14 @@ public class CardView extends GameEntityView { private Iterable mustBlock; private CardView pairedWith; - public CardView(final boolean isUiDisplayable) { - this.isUiDisplayable = isUiDisplayable; + public CardView(int id0) { + this.id = id0; this.reset(); } public void reset() { final Iterable emptyIterable = ImmutableSet.of(); - this.id = 0; + this.mayBeShown = false; this.hasAltState = false; this.owner = null; this.controller = null; @@ -120,12 +116,11 @@ public class CardView extends GameEntityView { return id; } - public void setId(final int id) { - this.id = id; + public boolean mayBeShown() { + return this.mayBeShown; } - - public boolean isUiDisplayable() { - return isUiDisplayable; + public void setMayBeShown(boolean b0) { + this.mayBeShown = b0; } /** @@ -726,12 +721,19 @@ public class CardView extends GameEntityView { @Override public String toString() { + if (this.getId() <= 0) { //if fake card, just return name + return this.getOriginal().getName(); + } + + if (!mayBeShown) { + return "(Unknown card)"; + } + if (StringUtils.isEmpty(this.getOriginal().getName())) { - if (this.getId() <= 0) { - return "(Unknown card)"; - } else if (this.hasAltState()) { + if (this.hasAltState()) { return "Face-down card (" + this.getAlternate().getName() + ")"; } + return "(" + this.getId() + ")"; } return this.getOriginal().getName() + " (" + this.getId() + ")"; @@ -765,7 +767,7 @@ public class CardView extends GameEntityView { public void reset() { this.name = ""; this.colors = ColorSet.getNullColor(); - this.imageKey = ImageKeys.TOKEN_PREFIX + ImageKeys.MORPH_IMAGE; + this.imageKey = ImageKeys.HIDDEN_CARD; this.type = Collections.emptyList(); this.manaCost = ManaCost.NO_COST; this.power = 0; @@ -822,7 +824,7 @@ public class CardView extends GameEntityView { * @return the imageKey */ public String getImageKey() { - return imageKey; + return mayBeShown ? imageKey : ImageKeys.HIDDEN_CARD; } /** diff --git a/forge-gui/src/main/java/forge/view/LocalGameView.java b/forge-gui/src/main/java/forge/view/LocalGameView.java index 58ab8ce00a9..920d77286b3 100644 --- a/forge-gui/src/main/java/forge/view/LocalGameView.java +++ b/forge-gui/src/main/java/forge/view/LocalGameView.java @@ -38,6 +38,7 @@ public abstract class LocalGameView implements IGameView { protected final InputQueue inputQueue; protected final InputProxy inputProxy; private PlayerView localPlayerView; + private int updateDelays; public LocalGameView(IGuiBase gui0, Game game0) { game = game0; @@ -349,30 +350,6 @@ public abstract class LocalGameView implements IGameView { return ViewUtil.transformIfNotNull(players, FN_GET_PLAYER_VIEW); } - public PlayerView getPlayerView(final Player p) { - if (p == null) { - return null; - } - - PlayerView view = MatchUtil.players.get(p.getId()); - if (view != null) { - getPlayerView(p, view); - } - else { - view = new PlayerView(p.getLobbyPlayer(), p.getId()); - MatchUtil.players.put(p, view); - getPlayerView(p, view); - } - return view; - } - - private PlayerView getPlayerViewFast(final Player p) { - if (p == null) { - return null; - } - return MatchUtil.players.get(p.getId()); - } - public Player getPlayer(final PlayerView p) { if (p == null) { return null; @@ -380,7 +357,23 @@ public abstract class LocalGameView implements IGameView { return MatchUtil.players.getKey(p.getId()); } - private void getPlayerView(final Player p, final PlayerView view) { + public PlayerView getPlayerView(final Player p) { + if (p == null) { + return null; + } + + PlayerView view = MatchUtil.players.get(p.getId()); + if (view == null) { + view = new PlayerView(p.getLobbyPlayer(), p.getId()); + if (updateDelays == 0) { + writePlayerToView(p, view); + } + MatchUtil.players.put(p, view); + } + return view; + } + + private void writePlayerToView(final Player p, final PlayerView view) { view.setCommanderInfo(CardFactoryUtil.getCommanderInfo(p).trim().replace("\r\n", "; ")); view.setKeywords(p.getKeywords()); view.setLife(p.getLife()); @@ -408,46 +401,41 @@ public abstract class LocalGameView implements IGameView { } public CardView getCardView(final Card c) { - if (c == null) { + if (c == null || c != c.getCardForUi()) { return null; } - final Card cUi = c.getCardForUi(); - final boolean isDisplayable = cUi == c; - final boolean mayShow = mayShowCard(c); - CardView view = MatchUtil.cards.get(c.getId()); - final boolean isNewView; - if (view != null) { - // Update to ensure the Card reference in the cache - // is not an outdated Card. - if (view.getId() > 0) { - MatchUtil.cards.updateKey(view.getId(), c); + if (view == null) { + view = new CardView(c.getId()); + if (updateDelays == 0) { + writeCardToView(c, view, MatchUtil.getGameView()); } - isNewView = false; - } else if (isDisplayable && mayShow) { - view = new CardView(isDisplayable); - view.setId(c.getId()); MatchUtil.cards.put(c, view); - isNewView = true; - } else { - return CardView.EMPTY; } - - if (mayShow) { - writeCardToView(cUi, view); - } - else if (isDisplayable) { - if (!isNewView) { - view.reset(); - } - } - else { - return null; - } - return view; } + + public void startUpdateDelay() { + updateDelays++; + } + public void endUpdateDelay() { + if (updateDelays > 0 && --updateDelays == 0) { + updateViews(); + } + } + + public void updateViews() { + if (updateDelays > 0) { return; } + + for (Player p : MatchUtil.players.getKeys()) { + writePlayerToView(p, getPlayerView(p)); + } + LocalGameView gameView = MatchUtil.getGameView(); + for (Card c : MatchUtil.cards.getKeys()) { + writeCardToView(c, getCardView(c), gameView); + } + } private final Function FN_GET_CARD_VIEW = new Function() { @Override @@ -460,41 +448,6 @@ public abstract class LocalGameView implements IGameView { return ViewUtil.transformIfNotNull(cards, FN_GET_CARD_VIEW); } - public final List getRefreshedCardViews(final Iterable cardViews) { - return ViewUtil.transformIfNotNull(cardViews, new Function() { - @Override - public CardView apply(final CardView input) { - return MatchUtil.cards.getCurrentValue(input); - } - }); - } - - private CardView getCardViewFast(final Card c) { - if (c == null) { - return null; - } - - final CardView view = MatchUtil.cards.get(c.getId()); - if (mayShowCard(c)) { - return view; - } else if (view.isUiDisplayable()) { - return CardView.EMPTY; - } - - return null; - } - - private final Function FN_GET_CARDVIEW_FAST = new Function() { - @Override - public CardView apply(Card input) { - return getCardViewFast(input); - } - }; - - private List getCardViewsFast(final Iterable cards) { - return ViewUtil.transformIfNotNull(cards, FN_GET_CARDVIEW_FAST); - } - public Card getCard(final CardView c) { if (c == null) { return null; @@ -513,29 +466,29 @@ public abstract class LocalGameView implements IGameView { return ViewUtil.transformIfNotNull(cards, FN_GET_CARD); } - private void writeCardToView(final Card c, final CardView view) { + private void writeCardToView(final Card c, final CardView view, final LocalGameView gameView) { // First, write the values independent of other views. - ViewUtil.writeNonDependentCardViewProperties(c, view, mayShowCardFace(c)); + ViewUtil.writeNonDependentCardViewProperties(c, view, gameView.mayShowCard(c), gameView.mayShowCardFace(c)); // Next, write the values that depend on other views. final Combat combat = game.getCombat(); - view.setOwner(getPlayerViewFast(c.getOwner())); - view.setController(getPlayerViewFast(c.getController())); + view.setOwner(getPlayerView(c.getOwner())); + view.setController(getPlayerView(c.getController())); view.setAttacking(combat != null && combat.isAttacking(c)); view.setBlocking(combat != null && combat.isBlocking(c)); - view.setChosenPlayer(getPlayerViewFast(c.getChosenPlayer())); - view.setEquipping(getCardViewFast(Iterables.getFirst(c.getEquipping(), null))); - view.setEquippedBy(getCardViewsFast(c.getEquippedBy())); - view.setEnchantingCard(getCardViewFast(c.getEnchantingCard())); - view.setEnchantingPlayer(getPlayerViewFast(c.getEnchantingPlayer())); - view.setEnchantedBy(getCardViewsFast(c.getEnchantedBy())); - view.setFortifiedBy(getCardViewsFast(c.getFortifiedBy())); - view.setGainControlTargets(getCardViewsFast(c.getGainControlTargets())); - view.setCloneOrigin(getCardViewFast(c.getCloneOrigin())); - view.setImprinted(getCardViewsFast(c.getImprinted())); - view.setHauntedBy(getCardViewsFast(c.getHauntedBy())); - view.setHaunting(getCardViewFast(c.getHaunting())); - view.setMustBlock(c.getMustBlockCards() == null ? Collections.emptySet() : getCardViewsFast(c.getMustBlockCards())); - view.setPairedWith(getCardViewFast(c.getPairedWith())); + view.setChosenPlayer(getPlayerView(c.getChosenPlayer())); + view.setEquipping(getCardView(Iterables.getFirst(c.getEquipping(), null))); + view.setEquippedBy(getCardViews(c.getEquippedBy())); + view.setEnchantingCard(getCardView(c.getEnchantingCard())); + view.setEnchantingPlayer(getPlayerView(c.getEnchantingPlayer())); + view.setEnchantedBy(getCardViews(c.getEnchantedBy())); + view.setFortifiedBy(getCardViews(c.getFortifiedBy())); + view.setGainControlTargets(getCardViews(c.getGainControlTargets())); + view.setCloneOrigin(getCardView(c.getCloneOrigin())); + view.setImprinted(getCardViews(c.getImprinted())); + view.setHauntedBy(getCardViews(c.getHauntedBy())); + view.setHaunting(getCardView(c.getHaunting())); + view.setMustBlock(c.getMustBlockCards() == null ? Collections.emptySet() : getCardViews(c.getMustBlockCards())); + view.setPairedWith(getCardView(c.getPairedWith())); } public SpellAbilityView getSpellAbilityView(final SpellAbility sa) { diff --git a/forge-gui/src/main/java/forge/view/ViewUtil.java b/forge-gui/src/main/java/forge/view/ViewUtil.java index 9b2bf14ee5f..421e247445f 100644 --- a/forge-gui/src/main/java/forge/view/ViewUtil.java +++ b/forge-gui/src/main/java/forge/view/ViewUtil.java @@ -33,9 +33,9 @@ public final class ViewUtil { * @param view * the {@link CardView} to write to. */ - public static void writeNonDependentCardViewProperties(final Card c, final CardView view, final boolean mayShowCardFace) { + public static void writeNonDependentCardViewProperties(final Card c, final CardView view, final boolean mayShowCard, final boolean mayShowCardFace) { final boolean hasAltState = c.isDoubleFaced() || c.isFlipCard() || c.isSplitCard() || (c.isFaceDown() && mayShowCardFace); - view.setId(c.getUniqueNumber()); + view.setMayBeShown(mayShowCard); view.setZone(c.getZone() == null ? null : c.getZone().getZoneType()); view.setHasAltState(hasAltState); view.setFaceDown(c.isFaceDown()); @@ -130,8 +130,11 @@ public final class ViewUtil { public static CardView getCardForUi(final IPaperCard pc) { final Card c = Card.getCardForUi(pc); - final CardView view = new CardView(true); - writeNonDependentCardViewProperties(c, view, c.getCardForUi() == c); + if (c.getCardForUi() != c) { + return null; + } + final CardView view = new CardView(c.getId()); + writeNonDependentCardViewProperties(c, view, true, true); return view; }