diff --git a/.project b/.project index bd5285d6a7e..107b0a19ca3 100644 --- a/.project +++ b/.project @@ -1,9 +1,11 @@ - ForgeLocal + forge + + org.eclipse.m2e.core.maven2Nature diff --git a/forge-gui-desktop/src/main/java/forge/GuiDesktop.java b/forge-gui-desktop/src/main/java/forge/GuiDesktop.java index 5f038e872c4..a1886a018fe 100644 --- a/forge-gui-desktop/src/main/java/forge/GuiDesktop.java +++ b/forge-gui-desktop/src/main/java/forge/GuiDesktop.java @@ -31,17 +31,11 @@ import forge.control.FControl; import forge.deck.CardPool; import forge.error.BugReportDialog; import forge.events.UiEvent; -import forge.game.Game; -import forge.game.GameEntity; import forge.game.GameType; import forge.game.Match; -import forge.game.card.Card; import forge.game.combat.Combat; -import forge.game.event.GameEventTurnBegan; -import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseType; import forge.game.player.IHasIcon; -import forge.game.player.Player; import forge.game.player.RegisteredPlayer; import forge.game.spellability.SpellAbility; import forge.game.zone.ZoneType; @@ -81,6 +75,10 @@ import forge.toolbox.MouseTriggerEvent; import forge.toolbox.special.PhaseLabel; import forge.util.BuildInfo; import forge.util.ITriggerEvent; +import forge.view.CardView; +import forge.view.GameEntityView; +import forge.view.IGameView; +import forge.view.PlayerView; public class GuiDesktop implements IGuiBase { @@ -132,7 +130,7 @@ public class GuiDesktop implements IGuiBase { } @Override - public boolean mayShowCard(Card card) { + public boolean mayShowCard(CardView card) { return Singletons.getControl().mayShowCard(card); } @@ -153,7 +151,7 @@ public class GuiDesktop implements IGuiBase { } @Override - public int showCardOptionDialog(final Card card, String message, String title, FSkinProp skinIcon, String[] options, int defaultOption) { + public int showCardOptionDialog(final CardView card, String message, String title, FSkinProp skinIcon, String[] options, int defaultOption) { if (card != null) { FThreads.invokeInEdtAndWait(new Runnable() { @Override @@ -177,7 +175,7 @@ public class GuiDesktop implements IGuiBase { @Override public List order(final String title, final String top, final int remainingObjectsMin, final int remainingObjectsMax, - final List sourceChoices, final List destChoices, final Card referenceCard, final boolean sideboardingMode) { + final List sourceChoices, final List destChoices, final CardView referenceCard, final boolean sideboardingMode) { return GuiChoose.order(title, top, remainingObjectsMin, remainingObjectsMax, sourceChoices, destChoices, referenceCard, sideboardingMode); } @@ -231,10 +229,11 @@ public class GuiDesktop implements IGuiBase { @Override public void updatePhase() { - PhaseHandler pH = Singletons.getControl().getObservedGame().getPhaseHandler(); - Player p = pH.getPlayerTurn(); - PhaseType ph = pH.getPhase(); + //PhaseHandler pH = Singletons.getControl().getObservedGame().getPhaseHandler(); + //PhaseType ph = pH.getPhase(); + final PlayerView p = Singletons.getControl().getGameView().getPlayerTurn(); + final PhaseType ph = Singletons.getControl().getGameView().getPhase(); final CMatchUI matchUi = CMatchUI.SINGLETON_INSTANCE; PhaseLabel lbl = matchUi.getFieldViewFor(p).getPhaseIndicator().getLabelFor(ph); @@ -245,10 +244,10 @@ public class GuiDesktop implements IGuiBase { } @Override - public void updateTurn(final GameEventTurnBegan event, final Game game) { - VField nextField = CMatchUI.SINGLETON_INSTANCE.getFieldViewFor(event.turnOwner); + public void updateTurn(final PlayerView player) { + VField nextField = CMatchUI.SINGLETON_INSTANCE.getFieldViewFor(player); SDisplayUtil.showTab(nextField); - CPrompt.SINGLETON_INSTANCE.updateText(game); + CPrompt.SINGLETON_INSTANCE.updateText(); } @Override @@ -273,7 +272,7 @@ public class GuiDesktop implements IGuiBase { @Override public void finishGame() { - new ViewWinLose(Singletons.getControl().getObservedGame()); + new ViewWinLose(Singletons.getControl().getGameView()); if (showOverlay) { SOverlayUtils.showOverlay(); } @@ -290,7 +289,7 @@ public class GuiDesktop implements IGuiBase { } @Override - public void setPanelSelection(Card c) { + public void setPanelSelection(final CardView c) { GuiUtils.setPanelSelection(c); } @@ -374,7 +373,7 @@ public class GuiDesktop implements IGuiBase { } @Override - public void setCard(Card card) { + public void setCard(final CardView card) { CMatchUI.SINGLETON_INSTANCE.setCard(card); } @@ -384,22 +383,22 @@ public class GuiDesktop implements IGuiBase { } @Override - public void setUsedToPay(Card card, boolean b) { + public void setUsedToPay(final CardView card, final boolean b) { CMatchUI.SINGLETON_INSTANCE.setUsedToPay(card, b); } @Override - public void setHighlighted(Player player, boolean b) { + public void setHighlighted(final PlayerView player, final boolean b) { CMatchUI.SINGLETON_INSTANCE.setHighlighted(player, b); } @Override - public void showPromptMessage(String message) { + public void showPromptMessage(final String message) { CMatchUI.SINGLETON_INSTANCE.showMessage(message); } @Override - public boolean stopAtPhase(Player playerTurn, PhaseType phase) { + public boolean stopAtPhase(final PlayerView playerTurn, PhaseType phase) { return CMatchUI.SINGLETON_INSTANCE.stopAtPhase(playerTurn, phase); } @@ -409,21 +408,22 @@ public class GuiDesktop implements IGuiBase { } @Override - public Game getGame() { - return FControl.instance.getObservedGame(); + @Deprecated + public IGameView getGame() { + return FControl.instance.getGameView(); } - public Object showManaPool(Player player) { + public Object showManaPool(final PlayerView player) { return null; //not needed since mana pool icons are always visible } @Override - public void hideManaPool(Player player, Object zoneToRestore) { + public void hideManaPool(final PlayerView player, final Object zoneToRestore) { //not needed since mana pool icons are always visible } @Override - public boolean openZones(List zones, Map players) { + public boolean openZones(final List zones, final Map players) { if (zones.size() == 1) { switch (zones.get(0)) { case Battlefield: @@ -437,31 +437,31 @@ public class GuiDesktop implements IGuiBase { } @Override - public void restoreOldZones(Map playersToRestoreZonesFor) { + public void restoreOldZones(final Map playersToRestoreZonesFor) { } @Override - public void updateZones(List> zonesToUpdate) { + public void updateZones(final List> zonesToUpdate) { CMatchUI.SINGLETON_INSTANCE.updateZones(zonesToUpdate); } @Override - public void updateCards(Set cardsToUpdate) { + public void updateCards(final Set cardsToUpdate) { CMatchUI.SINGLETON_INSTANCE.updateCards(cardsToUpdate); } @Override - public void refreshCardDetails(Collection cards) { + public void refreshCardDetails(final Collection cards) { CMatchUI.SINGLETON_INSTANCE.refreshCardDetails(cards); } @Override - public void updateManaPool(List manaPoolUpdate) { + public void updateManaPool(final List manaPoolUpdate) { CMatchUI.SINGLETON_INSTANCE.updateManaPool(manaPoolUpdate); } @Override - public void updateLives(List livesUpdate) { + public void updateLives(final List livesUpdate) { CMatchUI.SINGLETON_INSTANCE.updateLives(livesUpdate); } @@ -471,10 +471,11 @@ public class GuiDesktop implements IGuiBase { } @Override - public Map getDamageToAssign(Card attacker, List blockers, - int damageDealt, GameEntity defender, boolean overrideOrder) { - return CMatchUI.SINGLETON_INSTANCE.getDamageToAssign(attacker, blockers, - damageDealt, defender, overrideOrder); + public Map getDamageToAssign(final CardView attacker, + final List blockers, final int damageDealt, + final GameEntityView defender, final boolean overrideOrder) { + return CMatchUI.SINGLETON_INSTANCE.getDamageToAssign(attacker, + blockers, damageDealt, defender, overrideOrder); } @Override diff --git a/forge-gui-desktop/src/main/java/forge/ImageCache.java b/forge-gui-desktop/src/main/java/forge/ImageCache.java index db9e4421fc8..53f8f4a9a82 100644 --- a/forge-gui-desktop/src/main/java/forge/ImageCache.java +++ b/forge-gui-desktop/src/main/java/forge/ImageCache.java @@ -29,6 +29,7 @@ import forge.item.InventoryItem; import forge.properties.ForgeConstants; import forge.toolbox.FSkin; import forge.toolbox.FSkin.SkinIcon; +import forge.view.CardView; import org.apache.commons.lang3.StringUtils; @@ -80,6 +81,7 @@ public class ImageCache { * retrieve an image from the cache. returns null if the image is not found in the cache * and cannot be loaded from disk. pass -1 for width and/or height to avoid resizing in that dimension. */ + @Deprecated public static BufferedImage getImage(Card card, int width, int height) { final String key; if (!Singletons.getControl().mayShowCard(card) || card.isFaceDown()) { @@ -89,7 +91,21 @@ public class ImageCache { } return scaleImage(key, width, height, true); } - + + /** + * retrieve an image from the cache. returns null if the image is not found in the cache + * and cannot be loaded from disk. pass -1 for width and/or height to avoid resizing in that dimension. + */ + public static BufferedImage getImage(final CardView card, final int width, final int height) { + final String key; + if (!Singletons.getControl().mayShowCard(card)) { + key = ImageKeys.TOKEN_PREFIX + ImageKeys.MORPH_IMAGE; + } else { + key = card.getOriginal().getImageKey(); + } + return scaleImage(key, width, height, true); + } + /** * retrieve an image from the cache. returns null if the image is not found in the cache * and cannot be loaded from disk. pass -1 for width and/or height to avoid resizing in that dimension. diff --git a/forge-gui-desktop/src/main/java/forge/control/FControl.java b/forge-gui-desktop/src/main/java/forge/control/FControl.java index 62a0f135d05..34f230b365f 100644 --- a/forge-gui-desktop/src/main/java/forge/control/FControl.java +++ b/forge-gui-desktop/src/main/java/forge/control/FControl.java @@ -17,6 +17,26 @@ */ package forge.control; +import java.awt.Component; +import java.awt.KeyEventDispatcher; +import java.awt.KeyboardFocusManager; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.KeyEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import javax.swing.ImageIcon; +import javax.swing.JLayeredPane; +import javax.swing.SwingUtilities; +import javax.swing.WindowConstants; + +import org.apache.commons.lang3.StringUtils; + import forge.FThreads; import forge.GuiBase; import forge.ImageCache; @@ -35,15 +55,21 @@ import forge.game.player.Player; import forge.game.player.RegisteredPlayer; import forge.gui.GuiDialog; import forge.gui.SOverlayUtils; -import forge.gui.framework.*; -import forge.player.GamePlayerUtil; -import forge.player.LobbyPlayerHuman; +import forge.gui.framework.EDocID; +import forge.gui.framework.FScreen; +import forge.gui.framework.InvalidLayoutFileException; +import forge.gui.framework.SDisplayUtil; +import forge.gui.framework.SLayoutIO; +import forge.gui.framework.SOverflowUtil; +import forge.gui.framework.SResizingUtil; import forge.match.input.InputQueue; import forge.menus.ForgeMenu; import forge.model.FModel; +import forge.player.GamePlayerUtil; +import forge.player.LobbyPlayerHuman; +import forge.properties.ForgeConstants; import forge.properties.ForgePreferences; import forge.properties.ForgePreferences.FPref; -import forge.properties.ForgeConstants; import forge.quest.QuestController; import forge.quest.data.QuestPreferences.QPref; import forge.quest.io.QuestDataIO; @@ -66,19 +92,11 @@ import forge.toolbox.special.PhaseIndicator; import forge.util.GuiDisplayUtil; import forge.util.MyRandom; import forge.util.NameGenerator; +import forge.view.CardView; import forge.view.FFrame; import forge.view.FView; - -import org.apache.commons.lang3.StringUtils; - -import javax.swing.*; - -import java.awt.*; -import java.awt.event.*; -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; +import forge.view.IGameView; +import forge.view.PlayerView; /** *

@@ -97,7 +115,7 @@ public enum FControl implements KeyEventDispatcher { private FScreen currentScreen; private boolean altKeyLastDown; private CloseAction closeAction; - private Player localPlayer; + private PlayerView localPlayer; public static enum CloseAction { NONE, @@ -352,6 +370,7 @@ public enum FControl implements KeyEventDispatcher { if (children.length != 0) { children[0].setSize(display.getSize()); } } + @Deprecated public Player getCurrentPlayer() { // try current priority Player currentPriority = game.getPhaseHandler().getPriorityPlayer(); @@ -369,9 +388,13 @@ public enum FControl implements KeyEventDispatcher { return null; } + @Deprecated public boolean mayShowCard(Card c) { return game == null || !gameHasHumanPlayer || c.canBeShownTo(getCurrentPlayer()); } + public boolean mayShowCard(final CardView c) { + return gameView == null || !gameHasHumanPlayer || gameView.mayShowCard(c, getCurrentPlayer()); + } /** * TODO: Write javadoc for this method. @@ -382,13 +405,19 @@ public enum FControl implements KeyEventDispatcher { } private Game game; + private IGameView gameView; private boolean gameHasHumanPlayer; + @Deprecated public Game getObservedGame() { return game; } - public Player getLocalPlayer() { + public IGameView getGameView() { + return this.gameView; + } + + public PlayerView getLocalPlayer() { return localPlayer; } @@ -428,6 +457,14 @@ public enum FControl implements KeyEventDispatcher { return inputQueue; } + public final void startGameInSameMatch() { + this.startGameWithUi(game.getMatch()); + } + public final void startGameAndClearMatch() { + game.getMatch().clearGamesPlayed(); + startGameInSameMatch(); + } + public final void startGameWithUi(final Match match) { if (this.game != null) { this.setCurrentScreen(FScreen.MATCH_SCREEN); @@ -436,15 +473,23 @@ public enum FControl implements KeyEventDispatcher { return; //TODO: See if it's possible to run multiple games at once without crashing } setPlayerName(match.getPlayers()); - final Game newGame = match.createGame(); - attachToGame(newGame); - + this.game = match.createGame(); + final LobbyPlayer me = getGuiPlayer(); + for (final Player p : this.game.getPlayers()) { + if (p.getLobbyPlayer().equals(me)) { + this.gameView = (IGameView) p.getController(); + break; + } + } + + attachToGame(this.gameView); + // It's important to run match in a different thread to allow GUI inputs to be invoked from inside game. // Game is set on pause while gui player takes decisions game.getAction().invoke(new Runnable() { @Override public void run() { - match.startGame(newGame); + match.startGame(game); } }); SOverlayUtils.hideOverlay(); @@ -459,11 +504,11 @@ public enum FControl implements KeyEventDispatcher { private final FControlGameEventHandler fcVisitor = new FControlGameEventHandler(); private final FControlGamePlayback playbackControl = new FControlGamePlayback(); - private void attachToGame(Game game0) { - if (game0.getRules().getGameType() == GameType.Quest) { + private void attachToGame(final IGameView game0) { + if (game0.getGameType().equals(GameType.Quest)) { QuestController qc = FModel.getQuest(); // Reset new list when the Match round starts, not when each game starts - if (game0.getMatch().getPlayedGames().isEmpty()) { + if (game0.isFirstGameInMatch()) { qc.getCards().resetNewList(); } game0.subscribeToEvents(qc); // this one listens to player's mulligans ATM @@ -471,49 +516,45 @@ public enum FControl implements KeyEventDispatcher { inputQueue = new InputQueue(); - this.game = game0; - game.subscribeToEvents(Singletons.getControl().getSoundSystem()); + game0.subscribeToEvents(Singletons.getControl().getSoundSystem()); //switch back to match screen music Singletons.getControl().getSoundSystem().setBackgroundMusic(MusicPlaylist.MATCH); - LobbyPlayer humanLobbyPlayer = getGuiPlayer(); + final LobbyPlayer humanLobbyPlayer = getGuiPlayer(); // The UI controls should use these game data as models - CMatchUI.SINGLETON_INSTANCE.initMatch(game.getRegisteredPlayers(), humanLobbyPlayer); + final List players = game0.getPlayers(); + CMatchUI.SINGLETON_INSTANCE.initMatch(players, humanLobbyPlayer); localPlayer = null; - for (Player p : game.getPlayers()) { + gameHasHumanPlayer = false; + for (final PlayerView p : players) { if (p.getLobbyPlayer() == humanLobbyPlayer) { localPlayer = p; + gameHasHumanPlayer = true; break; } } - CDock.SINGLETON_INSTANCE.setModel(game, humanLobbyPlayer); - CStack.SINGLETON_INSTANCE.setModel(game.getStack(), localPlayer); - CPlayers.SINGLETON_INSTANCE.setModel(game); - CLog.SINGLETON_INSTANCE.setModel(game.getGameLog()); + CDock.SINGLETON_INSTANCE.setModel(game0, humanLobbyPlayer); + CStack.SINGLETON_INSTANCE.setModel(game0, localPlayer); + CPlayers.SINGLETON_INSTANCE.setModel(game0); + CLog.SINGLETON_INSTANCE.setModel(game0.getGameLog()); actuateMatchPreferences(); - VAntes.SINGLETON_INSTANCE.setModel(game.getRegisteredPlayers()); + VAntes.SINGLETON_INSTANCE.setModel(players); setCurrentScreen(FScreen.MATCH_SCREEN); SDisplayUtil.showTab(EDocID.REPORT_LOG.getDoc()); - CPrompt.SINGLETON_INSTANCE.getInputControl().setGame(game); + CPrompt.SINGLETON_INSTANCE.getInputControl().setGame(game0); // Listen to DuelOutcome event to show ViewWinLose - game.subscribeToEvents(fcVisitor); + game0.subscribeToEvents(fcVisitor); // Add playback controls to match if needed - gameHasHumanPlayer = false; - for (Player p : game.getPlayers()) { - if (p.getController().getLobbyPlayer() == getGuiPlayer()) - gameHasHumanPlayer = true; - } - - if (!gameHasHumanPlayer) { - game.subscribeToEvents(playbackControl); + if (localPlayer != null) { + game0.subscribeToEvents(playbackControl); } for (final VField field : VMatchUI.SINGLETON_INSTANCE.getFieldViews()) { @@ -522,7 +563,7 @@ public enum FControl implements KeyEventDispatcher { // per player observers were set in CMatchUI.SINGLETON_INSTANCE.initMatch //Set Field shown to current player. - VField nextField = CMatchUI.SINGLETON_INSTANCE.getFieldViewFor(game.getPlayers().get(0)); + final VField nextField = CMatchUI.SINGLETON_INSTANCE.getFieldViewFor(localPlayer); SDisplayUtil.showTab(nextField); } diff --git a/forge-gui-desktop/src/main/java/forge/deckchooser/FDeckViewer.java b/forge-gui-desktop/src/main/java/forge/deckchooser/FDeckViewer.java index efd2fc21b90..7c93417cfb1 100644 --- a/forge-gui-desktop/src/main/java/forge/deckchooser/FDeckViewer.java +++ b/forge-gui-desktop/src/main/java/forge/deckchooser/FDeckViewer.java @@ -36,7 +36,7 @@ public class FDeckViewer extends FDialog { private final CardManager cardManager; private DeckSection currentSection; - private final CardDetailPanel cardDetail = new CardDetailPanel(null); + private final CardDetailPanel cardDetail = new CardDetailPanel(); private final CardPicturePanel cardPicture = new CardPicturePanel(); private final FButton btnCopyToClipboard = new FButton("Copy to Clipboard"); private final FButton btnChangeSection = new FButton("Change Section"); diff --git a/forge-gui-desktop/src/main/java/forge/gui/BoxedProductCardListViewer.java b/forge-gui-desktop/src/main/java/forge/gui/BoxedProductCardListViewer.java index 41a60064180..05a840ea733 100644 --- a/forge-gui-desktop/src/main/java/forge/gui/BoxedProductCardListViewer.java +++ b/forge-gui-desktop/src/main/java/forge/gui/BoxedProductCardListViewer.java @@ -99,7 +99,7 @@ public class BoxedProductCardListViewer extends FDialog { public BoxedProductCardListViewer(final String title, final String message, final List list, final Icon dialogIcon) { this.list = Collections.unmodifiableList(list); this.jList = new JList(new ChooserListModel()); - this.detail = new CardDetailPanel(null); + this.detail = new CardDetailPanel(); this.picture = new CardPicturePanel(); this.picture.setOpaque(false); diff --git a/forge-gui-desktop/src/main/java/forge/gui/CardContainer.java b/forge-gui-desktop/src/main/java/forge/gui/CardContainer.java index bf7380b7fa9..0c0c608a078 100644 --- a/forge-gui-desktop/src/main/java/forge/gui/CardContainer.java +++ b/forge-gui-desktop/src/main/java/forge/gui/CardContainer.java @@ -18,7 +18,7 @@ package forge.gui; -import forge.game.card.Card; +import forge.view.CardView; /** * The class CardContainer. A card container is an object that references a @@ -36,7 +36,7 @@ public interface CardContainer { * @param card * a {@link forge.game.card.Card} object. */ - void setCard(Card card); + void setCard(CardView card); /** *

@@ -45,6 +45,6 @@ public interface CardContainer { * * @return a {@link forge.game.card.Card} object. */ - Card getCard(); + CardView getCard(); } diff --git a/forge-gui-desktop/src/main/java/forge/gui/CardDetailPanel.java b/forge-gui-desktop/src/main/java/forge/gui/CardDetailPanel.java index 8f673783cbd..5bbcb6f3fb1 100644 --- a/forge-gui-desktop/src/main/java/forge/gui/CardDetailPanel.java +++ b/forge-gui-desktop/src/main/java/forge/gui/CardDetailPanel.java @@ -30,6 +30,8 @@ import forge.item.InventoryItemFromSet; import forge.model.FModel; import forge.toolbox.*; import forge.toolbox.FSkin.SkinnedPanel; +import forge.view.CardView; +import forge.view.CardView.CardStateView; import forge.view.FDialog; import org.apache.commons.lang3.StringUtils; @@ -62,7 +64,7 @@ public class CardDetailPanel extends SkinnedPanel { private final FHtmlViewer cdArea; private final FScrollPane scrArea; - public CardDetailPanel(final Card card) { + public CardDetailPanel() { super(); this.setLayout(null); this.setOpaque(false); @@ -74,7 +76,7 @@ public class CardDetailPanel extends SkinnedPanel { this.setInfoLabel = new JLabel(); this.setInfoLabel.setHorizontalAlignment(SwingConstants.CENTER); - Font font = new Font("Dialog", 0, 14); + final Font font = new Font("Dialog", 0, 14); this.nameCostLabel.setFont(font); this.typeLabel.setFont(font); this.idLabel.setFont(font); @@ -91,8 +93,6 @@ public class CardDetailPanel extends SkinnedPanel { this.add(this.powerToughnessLabel); this.add(this.setInfoLabel); this.add(this.scrArea); - - this.setCard(card); } @Override @@ -121,7 +121,7 @@ public class CardDetailPanel extends SkinnedPanel { this.scrArea.setBounds(0, y, getWidth(), getHeight() - y); } - public final void setItem(InventoryItemFromSet item) { + public final void setItem(final InventoryItemFromSet item) { nameCostLabel.setText(item.getName()); typeLabel.setVisible(false); powerToughnessLabel.setVisible(false); @@ -155,7 +155,7 @@ public class CardDetailPanel extends SkinnedPanel { }); } - /** {@inheritDoc} */ + @Deprecated public final void setCard(Card card) { this.nameCostLabel.setText(""); this.typeLabel.setVisible(true); @@ -169,7 +169,7 @@ public class CardDetailPanel extends SkinnedPanel { this.setInfoLabel.setBorder(null); this.cdArea.setText(""); if (card == null) { - this.updateBorder(null, false); + this.updateBorder((Card)null, false); return; } @@ -258,6 +258,102 @@ public class CardDetailPanel extends SkinnedPanel { }); } + public final void setCard(final CardView card, final boolean isInAltState) { + this.nameCostLabel.setText(""); + this.typeLabel.setVisible(true); + this.typeLabel.setText(""); + this.powerToughnessLabel.setVisible(true); + this.powerToughnessLabel.setText(""); + this.idLabel.setText(""); + this.setInfoLabel.setText(""); + this.setInfoLabel.setToolTipText(""); + this.setInfoLabel.setOpaque(false); + this.setInfoLabel.setBorder(null); + this.cdArea.setText(""); + if (card == null) { + this.updateBorder((CardStateView)null, false); + return; + } + + final CardStateView state = card.getState(isInAltState); + //this.setCard(card.card); + + boolean canShowThis = false; + + if (Singletons.getControl().mayShowCard(card) || FDialog.isModalOpen()) { //allow showing cards while modal open to account for revealing, picking, and ordering cards + canShowThis = true; + + if (state.getManaCost().isNoCost()) { + this.nameCostLabel.setText(state.getName()); + } else { + String manaCost = state.getManaCost().toString(); + //if (state.isSplitCard() && card.getCurState() == CardCharacteristicName.Original) { + // manaCost = card.getRules().getMainPart().getManaCost().toString() + " // " + card.getRules().getOtherPart().getManaCost().toString(); + //} + this.nameCostLabel.setText(FSkin.encodeSymbols(state.getName() + " - " + manaCost, true)); + } + this.typeLabel.setText(CardDetailUtil.formatCardType(state)); + + String set = card.getSetCode(); + this.setInfoLabel.setText(set); + if (null != set && !set.isEmpty()) { + CardEdition edition = FModel.getMagicDb().getEditions().get(set); + if (null == edition) { + setInfoLabel.setToolTipText(card.getRarity().name()); + } + else { + setInfoLabel.setToolTipText(String.format("%s (%s)", edition.getName(), card.getRarity().name())); + } + + this.setInfoLabel.setOpaque(true); + + Color backColor; + switch(card.getRarity()) { + case Uncommon: + backColor = fromDetailColor(DetailColors.UNCOMMON); + break; + + case Rare: + backColor = fromDetailColor(DetailColors.RARE); + break; + + case MythicRare: + backColor = fromDetailColor(DetailColors.MYTHIC); + break; + + case Special: //"Timeshifted" or other Special Rarity Cards + backColor = fromDetailColor(DetailColors.SPECIAL); + break; + + default: //case BasicLand: + case Common: + backColor = fromDetailColor(DetailColors.COMMON); + break; + } + + Color foreColor = FSkin.getHighContrastColor(backColor); + this.setInfoLabel.setBackground(backColor); + this.setInfoLabel.setForeground(foreColor); + this.setInfoLabel.setBorder(BorderFactory.createLineBorder(foreColor)); + } + } + + this.updateBorder(state, canShowThis); + + this.powerToughnessLabel.setText(CardDetailUtil.formatPowerToughness(state)); + + this.idLabel.setText(CardDetailUtil.formatCardId(state)); + + // fill the card text + this.cdArea.setText(FSkin.encodeSymbols(CardDetailUtil.composeCardText(state, canShowThis), true)); + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + scrArea.getVerticalScrollBar().setValue(scrArea.getVerticalScrollBar().getMinimum()); + } + }); + } + /** @return FLabel */ public FLabel getNameCostLabel() { return this.nameCostLabel; @@ -283,6 +379,7 @@ public class CardDetailPanel extends SkinnedPanel { return this.cdArea; } + @Deprecated private void updateBorder(final Card card, final boolean canShow) { // color info if (card == null) { @@ -296,6 +393,19 @@ public class CardDetailPanel extends SkinnedPanel { scrArea.setBorder(BorderFactory.createMatteBorder(2, 0, 0, 0, color)); } + private void updateBorder(final CardStateView card, final boolean canShow) { + // color info + if (card == null) { + this.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); + scrArea.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0)); + return; + } + + Color color = fromDetailColor(CardDetailUtil.getBorderColor(card, canShow)); + this.setBorder(BorderFactory.createLineBorder(color, 2)); + scrArea.setBorder(BorderFactory.createMatteBorder(2, 0, 0, 0, color)); + } + //ensure mouse listener hooked up to all certain opaque child components so it can get raised properly @Override public void addMouseListener(MouseListener l) { diff --git a/forge-gui-desktop/src/main/java/forge/gui/CardListViewer.java b/forge-gui-desktop/src/main/java/forge/gui/CardListViewer.java index 339d8b00f6c..093ef6dc939 100644 --- a/forge-gui-desktop/src/main/java/forge/gui/CardListViewer.java +++ b/forge-gui-desktop/src/main/java/forge/gui/CardListViewer.java @@ -97,7 +97,7 @@ public class CardListViewer extends FDialog { public CardListViewer(final String title, final String message, final List list, final Icon dialogIcon) { this.list = Collections.unmodifiableList(list); this.jList = new JList(new ChooserListModel()); - this.detail = new CardDetailPanel(null); + this.detail = new CardDetailPanel(); this.picture = new CardPicturePanel(); this.picture.setOpaque(false); diff --git a/forge-gui-desktop/src/main/java/forge/gui/CardPicturePanel.java b/forge-gui-desktop/src/main/java/forge/gui/CardPicturePanel.java index 8febb3583ef..bc171540a6c 100644 --- a/forge-gui-desktop/src/main/java/forge/gui/CardPicturePanel.java +++ b/forge-gui-desktop/src/main/java/forge/gui/CardPicturePanel.java @@ -18,21 +18,21 @@ package forge.gui; +import java.awt.BorderLayout; +import java.awt.image.BufferedImage; + +import javax.swing.JPanel; + import forge.ImageCache; import forge.ImageKeys; -import forge.card.CardCharacteristicName; import forge.game.card.Card; import forge.item.InventoryItem; import forge.model.FModel; import forge.properties.ForgePreferences.FPref; import forge.toolbox.imaging.FImagePanel; -import forge.toolbox.imaging.FImageUtil; import forge.toolbox.imaging.FImagePanel.AutoSizeImageMode; - -import javax.swing.*; - -import java.awt.*; -import java.awt.image.BufferedImage; +import forge.toolbox.imaging.FImageUtil; +import forge.view.CardView.CardStateView; /** * Displays image associated with a card or inventory item. @@ -48,7 +48,7 @@ public final class CardPicturePanel extends JPanel { private final FImagePanel panel; private BufferedImage currentImage; - private boolean mayShowCard; + private boolean mayShowObject; public CardPicturePanel() { super(new BorderLayout()); @@ -59,23 +59,21 @@ public final class CardPicturePanel extends JPanel { public void setCard(final InventoryItem cp) { this.displayed = cp; - this.mayShowCard = true; + this.mayShowObject = true; this.setImage(); } - //@Override + @Deprecated public void setCard(final Card c, boolean mayShowCard) { this.displayed = c; - this.mayShowCard = mayShowCard; + this.mayShowObject = mayShowCard; this.setImage(); } - public void setCardImage(CardCharacteristicName flipState) { - BufferedImage image = FImageUtil.getImage((Card)displayed, flipState); - if (image != null && image != this.currentImage) { - this.currentImage = image; - this.panel.setImage(image, getAutoSizeImageMode()); - } + public void setCard(final CardStateView c, final boolean mayShowCard) { + this.displayed = c; + this.mayShowObject = mayShowCard; + this.setImage(); } public void setImage() { @@ -88,14 +86,19 @@ public final class CardPicturePanel extends JPanel { public BufferedImage getImage() { if (displayed instanceof InventoryItem) { - InventoryItem item = (InventoryItem) displayed; + final InventoryItem item = (InventoryItem) displayed; return ImageCache.getOriginalImage(ImageKeys.getImageKey(item, false), true); } else if (displayed instanceof Card) { - if (mayShowCard) { + if (mayShowObject) { return FImageUtil.getImage((Card)displayed); } return ImageCache.getOriginalImage(ImageKeys.TOKEN_PREFIX + ImageKeys.MORPH_IMAGE, true); + } else if (displayed instanceof CardStateView) { + if (mayShowObject) { + return FImageUtil.getImage((CardStateView)displayed); + } + return ImageCache.getOriginalImage(ImageKeys.TOKEN_PREFIX + ImageKeys.MORPH_IMAGE, true); } return null; } diff --git a/forge-gui-desktop/src/main/java/forge/gui/DualListBox.java b/forge-gui-desktop/src/main/java/forge/gui/DualListBox.java index e3201fd2d39..97b46b7482d 100644 --- a/forge-gui-desktop/src/main/java/forge/gui/DualListBox.java +++ b/forge-gui-desktop/src/main/java/forge/gui/DualListBox.java @@ -1,23 +1,37 @@ package forge.gui; -import forge.game.card.Card; -import forge.game.spellability.SpellAbility; -import forge.item.IPaperCard; -import forge.item.PaperCard; -import forge.screens.match.CMatchUI; -import forge.toolbox.*; -import forge.view.FDialog; +import java.awt.BorderLayout; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; -import javax.swing.*; +import javax.swing.JPanel; +import javax.swing.ListModel; +import javax.swing.SwingUtilities; import javax.swing.event.ListDataEvent; import javax.swing.event.ListDataListener; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; -import java.awt.*; -import java.awt.event.*; -import java.util.ArrayList; -import java.util.List; +import forge.item.IPaperCard; +import forge.item.PaperCard; +import forge.screens.match.CMatchUI; +import forge.toolbox.FButton; +import forge.toolbox.FLabel; +import forge.toolbox.FList; +import forge.toolbox.FPanel; +import forge.toolbox.FScrollPane; +import forge.view.CardView; +import forge.view.FDialog; +import forge.view.SpellAbilityView; // An input box for handling the order of choices. // Left box has the original choices @@ -310,13 +324,13 @@ public class DualListBox extends FDialog { if (!showCard || null == obj) { return; } - Card card = null; - if (obj instanceof Card) { - card = (Card) obj; - } else if (obj instanceof SpellAbility) { - card = ((SpellAbility) obj).getHostCard(); + CardView card = null; + if (obj instanceof CardView) { + card = (CardView) obj; + } else if (obj instanceof SpellAbilityView) { + card = ((SpellAbilityView) obj).getHostCard(); } else if (obj instanceof PaperCard) { - card = Card.getCardForUi((IPaperCard) obj); + card = CardView.getCardForUi((IPaperCard) obj); } GuiUtils.clearPanelSelections(); diff --git a/forge-gui-desktop/src/main/java/forge/gui/GuiChoose.java b/forge-gui-desktop/src/main/java/forge/gui/GuiChoose.java index adc73d70132..052f73f9883 100644 --- a/forge-gui-desktop/src/main/java/forge/gui/GuiChoose.java +++ b/forge-gui-desktop/src/main/java/forge/gui/GuiChoose.java @@ -1,24 +1,30 @@ package forge.gui; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.FutureTask; + +import javax.swing.JList; +import javax.swing.WindowConstants; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +import org.apache.commons.lang3.StringUtils; + import com.google.common.base.Function; import com.google.common.collect.Iterables; import forge.FThreads; import forge.Singletons; -import forge.game.card.Card; import forge.item.InventoryItem; import forge.screens.match.CMatchUI; import forge.toolbox.FOptionPane; - -import org.apache.commons.lang3.StringUtils; - -import javax.swing.*; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; - -import java.util.*; -import java.util.concurrent.Callable; -import java.util.concurrent.FutureTask; +import forge.view.CardView; /** * TODO: Write javadoc for this type. @@ -200,8 +206,8 @@ public class GuiChoose { list.addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(final ListSelectionEvent ev) { - if (list.getSelectedValue() instanceof Card) { - Card card = (Card) list.getSelectedValue(); + if (list.getSelectedValue() instanceof CardView) { + final CardView card = (CardView) list.getSelectedValue(); if (card.isFaceDown() && Singletons.getControl().mayShowCard(card)) { CMatchUI.SINGLETON_INSTANCE.setCard(card, true); } @@ -240,17 +246,17 @@ public class GuiChoose { return null; } - public static List many(final String title, final String topCaption, int cnt, final List sourceChoices, Card referenceCard) { + public static List many(final String title, final String topCaption, int cnt, final List sourceChoices, final CardView referenceCard) { return order(title, topCaption, cnt, cnt, sourceChoices, null, referenceCard, false); } - public static List many(final String title, final String topCaption, int min, int max, final List sourceChoices, Card referenceCard) { + public static List many(final String title, final String topCaption, int min, int max, final List sourceChoices, final CardView referenceCard) { int m2 = min >= 0 ? sourceChoices.size() - min : -1; int m1 = max >= 0 ? sourceChoices.size() - max : -1; return order(title, topCaption, m1, m2, sourceChoices, null, referenceCard, false); } - public static List order(final String title, final String top, final List sourceChoices, Card referenceCard) { + public static List order(final String title, final String top, final List sourceChoices, final CardView referenceCard) { return order(title, top, 0, 0, sourceChoices, null, referenceCard, false); } @@ -261,7 +267,7 @@ public class GuiChoose { } public static List order(final String title, final String top, final int remainingObjectsMin, final int remainingObjectsMax, - final List sourceChoices, final List destChoices, final Card referenceCard, final boolean sideboardingMode) { + final List sourceChoices, final List destChoices, final CardView referenceCard, final boolean sideboardingMode) { // An input box for handling the order of choices. Callable> callable = new Callable>() { diff --git a/forge-gui-desktop/src/main/java/forge/gui/GuiDialog.java b/forge-gui-desktop/src/main/java/forge/gui/GuiDialog.java index c5f9fddd099..749587f9ba9 100644 --- a/forge-gui-desktop/src/main/java/forge/gui/GuiDialog.java +++ b/forge-gui-desktop/src/main/java/forge/gui/GuiDialog.java @@ -1,17 +1,17 @@ package forge.gui; -import forge.FThreads; -import forge.game.card.Card; -import forge.screens.match.CMatchUI; -import forge.toolbox.FOptionPane; - -import org.apache.commons.lang3.StringUtils; - -import javax.swing.*; - import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; +import javax.swing.UIManager; + +import org.apache.commons.lang3.StringUtils; + +import forge.FThreads; +import forge.screens.match.CMatchUI; +import forge.toolbox.FOptionPane; +import forge.view.CardView; + /** * Holds player interactions using standard windows * @@ -19,17 +19,17 @@ import java.util.concurrent.FutureTask; public class GuiDialog { private static final String[] defaultConfirmOptions = { "Yes", "No" }; - public static boolean confirm(final Card c, final String question) { + public static boolean confirm(final CardView c, final String question) { return GuiDialog.confirm(c, question, true, null); } - public static boolean confirm(final Card c, final String question, final boolean defaultChoice) { + public static boolean confirm(final CardView c, final String question, final boolean defaultChoice) { return GuiDialog.confirm(c, question, defaultChoice, null); } - public static boolean confirm(final Card c, final String question, String[] options) { + public static boolean confirm(final CardView c, final String question, String[] options) { return GuiDialog.confirm(c, question, true, options); } - public static boolean confirm(final Card c, final String question, final boolean defaultIsYes, final String[] options) { + public static boolean confirm(final CardView c, final String question, final boolean defaultIsYes, final String[] options) { Callable confirmTask = new Callable() { @Override public Boolean call() throws Exception { @@ -37,7 +37,7 @@ public class GuiDialog { CMatchUI.SINGLETON_INSTANCE.setCard(c); } - final String title = c == null ? "Question" : c.getCardForUi().getName() + " - Ability"; + final String title = c == null ? "Question" : c + " - Ability"; String questionToUse = StringUtils.isBlank(question) ? "Activate card's ability?" : question; String[] opts = options == null ? defaultConfirmOptions : options; int answer = FOptionPane.showOptionDialog(questionToUse, title, FOptionPane.QUESTION_ICON, opts, defaultIsYes ? 0 : 1); diff --git a/forge-gui-desktop/src/main/java/forge/gui/GuiUtils.java b/forge-gui-desktop/src/main/java/forge/gui/GuiUtils.java index 70628bb636a..d1ba41f8a4b 100644 --- a/forge-gui-desktop/src/main/java/forge/gui/GuiUtils.java +++ b/forge-gui-desktop/src/main/java/forge/gui/GuiUtils.java @@ -17,20 +17,26 @@ */ package forge.gui; -import forge.game.card.Card; -import forge.screens.match.VMatchUI; -import forge.screens.match.views.VField; -import forge.view.arcane.CardPanel; - -import javax.swing.*; - -import java.awt.*; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontFormatException; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.IOException; import java.util.List; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.JSeparator; +import javax.swing.KeyStroke; + +import forge.screens.match.VMatchUI; +import forge.screens.match.views.VField; +import forge.view.CardView; +import forge.view.arcane.CardPanel; + /** *

* GuiUtils class. @@ -81,15 +87,15 @@ public final class GuiUtils { /** * Highlight a card on the playfield. * - * @param c + * @param card * a card to be highlighted */ - public static void setPanelSelection(final Card c) { + public static void setPanelSelection(final CardView card) { mainLoop: - for (VField v : VMatchUI.SINGLETON_INSTANCE.getFieldViews()) { - List panels = v.getTabletop().getCardPanels(); - for (CardPanel p : panels) { - if (p.getCard().equals(c)) { + for (final VField v : VMatchUI.SINGLETON_INSTANCE.getFieldViews()) { + final List panels = v.getTabletop().getCardPanels(); + for (final CardPanel p : panels) { + if (p.getCard().equals(card)) { p.setSelected(true); break mainLoop; } diff --git a/forge-gui-desktop/src/main/java/forge/itemmanager/views/ImageView.java b/forge-gui-desktop/src/main/java/forge/itemmanager/views/ImageView.java index db29dfe15a7..fa5d28e7497 100644 --- a/forge-gui-desktop/src/main/java/forge/itemmanager/views/ImageView.java +++ b/forge-gui-desktop/src/main/java/forge/itemmanager/views/ImageView.java @@ -1,7 +1,6 @@ package forge.itemmanager.views; import forge.ImageCache; -import forge.game.card.Card; import forge.assets.FSkinProp; import forge.deck.DeckProxy; import forge.gui.framework.ILocalRepaint; @@ -20,6 +19,7 @@ import forge.toolbox.FSkin.SkinColor; import forge.toolbox.FSkin.SkinFont; import forge.toolbox.FSkin.SkinImage; import forge.toolbox.special.CardZoomer; +import forge.view.CardView; import forge.view.arcane.CardPanel; import javax.swing.*; @@ -232,7 +232,7 @@ public class ImageView extends ItemView { ItemInfo item = getItemAtPoint(e.getPoint()); if (item != null && item.item instanceof IPaperCard) { setLockHoveredItem(true); //lock hoveredItem while zoomer open - Card card = Card.getCardForUi((IPaperCard) item.item); + final CardView card = CardView.getCardForUi((IPaperCard) item.item); CardZoomer.SINGLETON_INSTANCE.doMouseButtonZoom(card); } } @@ -1099,8 +1099,8 @@ public class ImageView extends ItemView { if (item instanceof IPaperCard) { IPaperCard paperCard = (IPaperCard)item; if (paperCard.isFoil()) { - Card card = Card.getCardForUi(paperCard); - if (card.getFoil() == 0) { //if foil finish not yet established, assign a random one + final CardView card = CardView.getCardForUi(paperCard); + if (card.getFoilIndex() == 0) { //if foil finish not yet established, assign a random one card.setRandomFoil(); } CardPanel.drawFoilEffect(g, card, bounds.x, bounds.y, bounds.width, bounds.height, borderSize); diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/VSubmenuConstructed.java b/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/VSubmenuConstructed.java index 6469802d6cc..bf2d0ab3e70 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/VSubmenuConstructed.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/VSubmenuConstructed.java @@ -321,7 +321,7 @@ public enum VSubmenuConstructed implements IVSubmenu { FScrollPane scrAvatars = new FScrollPane(vgdAvatarList, true, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - CardDetailPanel vgdDetail = new CardDetailPanel(null); + CardDetailPanel vgdDetail = new CardDetailPanel(); vgdAvatarDetails.add(vgdDetail); vgdDeckPanel.setLayout(new MigLayout(sectionConstraints)); diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java b/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java index d1eeb8611e2..e2dcb6a43b1 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java @@ -17,49 +17,65 @@ */ package forge.screens.match; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.swing.JMenu; + +import org.apache.commons.lang3.tuple.Pair; +import org.testng.collections.Maps; + import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; -import forge.LobbyPlayer; -import forge.UiCommand; import forge.FThreads; import forge.ImageCache; +import forge.LobbyPlayer; import forge.Singletons; +import forge.UiCommand; import forge.events.IUiEventVisitor; import forge.events.UiEvent; import forge.events.UiEventAttackerDeclared; import forge.events.UiEventBlockerAssigned; -import forge.game.GameEntity; -import forge.game.card.Card; import forge.game.combat.Combat; import forge.game.phase.PhaseType; -import forge.game.player.Player; -import forge.game.zone.Zone; import forge.game.zone.ZoneType; -import forge.gui.framework.*; +import forge.gui.framework.EDocID; +import forge.gui.framework.FScreen; +import forge.gui.framework.ICDoc; +import forge.gui.framework.IVDoc; +import forge.gui.framework.SDisplayUtil; import forge.item.InventoryItem; import forge.menus.IMenuProvider; import forge.model.FModel; import forge.properties.ForgePreferences.FPref; import forge.quest.QuestDraftUtils; -import forge.screens.match.controllers.*; +import forge.screens.match.controllers.CAntes; +import forge.screens.match.controllers.CCombat; +import forge.screens.match.controllers.CDetail; +import forge.screens.match.controllers.CPicture; +import forge.screens.match.controllers.CPrompt; import forge.screens.match.menus.CMatchUIMenus; -import forge.screens.match.views.*; +import forge.screens.match.views.VCommand; +import forge.screens.match.views.VField; +import forge.screens.match.views.VHand; +import forge.screens.match.views.VPlayers; import forge.toolbox.FOptionPane; import forge.toolbox.FOverlay; import forge.toolbox.FSkin; import forge.toolbox.FSkin.SkinImage; import forge.toolbox.special.PhaseLabel; +import forge.view.CardView; +import forge.view.GameEntityView; +import forge.view.PlayerView; import forge.view.arcane.CardPanel; import forge.view.arcane.PlayArea; -import org.apache.commons.lang3.tuple.Pair; - -import javax.swing.*; - -import java.util.*; - /** * Constructs instance of match UI controller, used as a single point of * top-level control for child UIs. Tasks targeting the view of individual @@ -71,7 +87,7 @@ import java.util.*; public enum CMatchUI implements ICDoc, IMenuProvider { SINGLETON_INSTANCE; - private List sortedPlayers; + private List sortedPlayers; private VMatchUI view; private EventBus uiEvents; @@ -85,14 +101,12 @@ public enum CMatchUI implements ICDoc, IMenuProvider { uiEvents.register(visitor); } - private SkinImage getPlayerAvatar(final Player p, final int defaultIndex) { - LobbyPlayer lp = p.getLobbyPlayer(); - - if (avatarImages.containsKey(lp)) { - return ImageCache.getIcon(avatarImages.get(lp)); + private SkinImage getPlayerAvatar(final LobbyPlayer p, final int defaultIndex) { + if (avatarImages.containsKey(p)) { + return ImageCache.getIcon(avatarImages.get(p)); } - int avatarIdx = lp.getAvatarIndex(); + int avatarIdx = p.getAvatarIndex(); return FSkin.getAvatars().get(avatarIdx >= 0 ? avatarIdx : defaultIndex); } @@ -108,7 +122,7 @@ public enum CMatchUI implements ICDoc, IMenuProvider { * @param numFieldPanels int * @param numHandPanels int */ - public void initMatch(final List players, LobbyPlayer localPlayer) { + public void initMatch(final List players, LobbyPlayer localPlayer) { view = VMatchUI.SINGLETON_INSTANCE; // TODO fix for use with multiplayer @@ -121,7 +135,7 @@ public enum CMatchUI implements ICDoc, IMenuProvider { final List commands = new ArrayList(); int i = 0; - for (Player p : sortedPlayers) { + for (final PlayerView p : sortedPlayers) { // A field must be initialized after it's instantiated, to update player info. // No player, no init. VField f = new VField(EDocID.Fields[i], p, localPlayer); @@ -130,7 +144,7 @@ public enum CMatchUI implements ICDoc, IMenuProvider { commands.add(c); //setAvatar(f, new ImageIcon(FSkin.getAvatars().get())); - setAvatar(f, getPlayerAvatar(p, Integer.parseInt(indices[i > 2 ? 1 : 0]))); + setAvatar(f, getPlayerAvatar(p.getLobbyPlayer(), Integer.parseInt(indices[i > 2 ? 1 : 0]))); f.getLayoutControl().initialize(); c.getLayoutControl().initialize(); i++; @@ -149,7 +163,7 @@ public enum CMatchUI implements ICDoc, IMenuProvider { final List hands = new ArrayList(); int i = 0; - for (Player p : sortedPlayers) { + for (final PlayerView p : sortedPlayers) { if (p.getLobbyPlayer() == localPlayer) { VHand newHand = new VHand(EDocID.Hands[i], p); newHand.getLayoutControl().initialize(); @@ -166,9 +180,9 @@ public enum CMatchUI implements ICDoc, IMenuProvider { view.setHandViews(hands); } - private List shiftPlayersPlaceLocalFirst(final List players, LobbyPlayer localPlayer) { + private List shiftPlayersPlaceLocalFirst(final List players, final LobbyPlayer localPlayer) { // get an arranged list so that the first local player is at index 0 - List sortedPlayers = Lists.newArrayList(players); + final List sortedPlayers = Lists.newArrayList(players); int ixFirstHuman = -1; for (int i = 0; i < players.size(); i++) { if (sortedPlayers.get(i).getLobbyPlayer() == localPlayer) { @@ -199,17 +213,17 @@ public enum CMatchUI implements ICDoc, IMenuProvider { CPrompt.SINGLETON_INSTANCE.setMessage(s0); } - public VField getFieldViewFor(Player p) { + public VField getFieldViewFor(PlayerView p) { int idx = getPlayerIndex(p); return idx < 0 ? null :view.getFieldViews().get(idx); } - public VCommand getCommandFor(Player p) { + public VCommand getCommandFor(PlayerView p) { int idx = getPlayerIndex(p); return idx < 0 ? null :view.getCommandViews().get(idx); } - public VHand getHandFor(Player p) { + public VHand getHandFor(PlayerView p) { int idx = getPlayerIndex(p); List allHands = view.getHands(); return idx < 0 || idx >= allHands.size() ? null : allHands.get(idx); @@ -226,15 +240,15 @@ public enum CMatchUI implements ICDoc, IMenuProvider { * @param overrideOrder overriding combatant order */ @SuppressWarnings("unchecked") - public Map getDamageToAssign(final Card attacker, final List blockers, final int damage, final GameEntity defender, final boolean overrideOrder) { + public Map getDamageToAssign(final CardView attacker, final List blockers, final int damage, final GameEntityView defender, final boolean overrideOrder) { if (damage <= 0) { - return new HashMap(); + return Maps.newHashMap(); } // If the first blocker can absorb all of the damage, don't show the Assign Damage Frame - Card firstBlocker = blockers.get(0); - if (!overrideOrder && !attacker.hasKeyword("Deathtouch") && firstBlocker.getLethalDamage() >= damage) { - Map res = new HashMap(); + final CardView firstBlocker = blockers.get(0); + if (!overrideOrder && !attacker.getState().hasDeathtouch() && firstBlocker.getLethalDamage() >= damage) { + final Map res = Maps.newHashMap(); res.put(firstBlocker, damage); return res; } @@ -246,7 +260,7 @@ public enum CMatchUI implements ICDoc, IMenuProvider { VAssignDamage v = new VAssignDamage(attacker, blockers, damage, defender, overrideOrder); result[0] = v.getDamageMap(); }}); - return (Map)result[0]; + return (Map)result[0]; } /** @@ -257,20 +271,20 @@ public enum CMatchUI implements ICDoc, IMenuProvider { * @param phase   {@link java.lang.String} * @return boolean */ - public final boolean stopAtPhase(final Player turn, final PhaseType phase) { + public final boolean stopAtPhase(final PlayerView turn, final PhaseType phase) { VField vf = getFieldViewFor(turn); PhaseLabel label = vf.getPhaseIndicator().getLabelFor(phase); return label == null || label.getEnabled(); } - public void setCard(final Card c) { - FThreads.assertExecutedByEdt(true); - setCard(c, false); + public void setCard(final CardView c) { + this.setCard(c, c.isInAltState()); } - public void setCard(final Card c, final boolean showFlipped) { - CDetail.SINGLETON_INSTANCE.showCard(c); - CPicture.SINGLETON_INSTANCE.showCard(c, showFlipped); + public void setCard(final CardView c, final boolean isInAltState) { + FThreads.assertExecutedByEdt(true); + CDetail.SINGLETON_INSTANCE.showCard(c, isInAltState); + CPicture.SINGLETON_INSTANCE.showCard(c, isInAltState); } public void setCard(final InventoryItem c) { @@ -278,7 +292,7 @@ public enum CMatchUI implements ICDoc, IMenuProvider { CPicture.SINGLETON_INSTANCE.showImage(c); } - private int getPlayerIndex(Player player) { + private int getPlayerIndex(PlayerView player) { return sortedPlayers.indexOf(player); } @@ -305,19 +319,19 @@ public enum CMatchUI implements ICDoc, IMenuProvider { CCombat.SINGLETON_INSTANCE.update(); } // showBlockers() - Set highlightedPlayers = new HashSet(); - public void setHighlighted(Player ge, boolean b) { + final Set highlightedPlayers = Sets.newHashSet(); + public void setHighlighted(PlayerView ge, boolean b) { if (b) highlightedPlayers.add(ge); else highlightedPlayers.remove(ge); } - public boolean isHighlighted(Player player) { + public boolean isHighlighted(final PlayerView player) { return highlightedPlayers.contains(player); } - Set highlightedCards = new HashSet(); + Set highlightedCards = Sets.newHashSet(); // used to highlight cards in UI - public void setUsedToPay(Card card, boolean value) { + public void setUsedToPay(CardView card, boolean value) { FThreads.assertExecutedByEdt(true); boolean hasChanged = value ? highlightedCards.add(card) : highlightedCards.remove(card); @@ -326,14 +340,14 @@ public enum CMatchUI implements ICDoc, IMenuProvider { } } - public boolean isUsedToPay(Card card) { + public boolean isUsedToPay(CardView card) { return highlightedCards.contains(card); } - public void updateZones(List> zonesToUpdate) { + public void updateZones(List> zonesToUpdate) { //System.out.println("updateZones " + zonesToUpdate); - for (Pair kv : zonesToUpdate) { - Player owner = kv.getKey(); + for (Pair kv : zonesToUpdate) { + PlayerView owner = kv.getKey(); ZoneType zt = kv.getValue(); if (zt == ZoneType.Command) { @@ -355,41 +369,39 @@ public enum CMatchUI implements ICDoc, IMenuProvider { } // Player's mana pool changes - public void updateManaPool(List manaPoolUpdate) { - for (Player p : manaPoolUpdate) { + public void updateManaPool(final List manaPoolUpdate) { + for (final PlayerView p : manaPoolUpdate) { getFieldViewFor(p).getDetailsPanel().updateManaPool(); } } // Player's lives and poison counters - public void updateLives(List livesUpdate) { - for (Player p : livesUpdate) { + public void updateLives(final List livesUpdate) { + for (final PlayerView p : livesUpdate) { getFieldViewFor(p).updateDetails(); } } - public void updateCards(Set cardsToUpdate) { - for (Card c : cardsToUpdate) { + public void updateCards(final Set cardsToUpdate) { + for (final CardView c : cardsToUpdate) { updateSingleCard(c); } } - public void updateSingleCard(Card c) { - Zone zone = c.getZone(); - if (zone != null && zone.getZoneType() == ZoneType.Battlefield) { - PlayArea pa = getFieldViewFor(zone.getPlayer()).getTabletop(); + public void updateSingleCard(final CardView c) { + if (ZoneType.Battlefield.equals(c.getZone())) { + final PlayArea pa = getFieldViewFor(c.getController()).getTabletop(); pa.updateCard(c, false); } } - public void refreshCardDetails(Collection cards) { - for (Card c : cards) { - Zone zone = c.getZone(); - if (zone != null && zone.getZoneType() == ZoneType.Battlefield) { - PlayArea pa = getFieldViewFor(zone.getPlayer()).getTabletop(); - CardPanel pnl = pa.getCardPanel(c.getUniqueNumber()); + public void refreshCardDetails(final Iterable cards) { + for (final CardView c : cards) { + if (ZoneType.Battlefield.equals(c.getZone())) { + PlayArea pa = getFieldViewFor(c.getController()).getTabletop(); + CardPanel pnl = pa.getCardPanel(c.getId()); if (pnl != null) { pnl.updatePTOverlay(); } diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/ControlWinLose.java b/forge-gui-desktop/src/main/java/forge/screens/match/ControlWinLose.java index 8d902dbfe55..5695a7b80b9 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/ControlWinLose.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/ControlWinLose.java @@ -1,15 +1,15 @@ package forge.screens.match; -import forge.Singletons; -import forge.game.Game; -import forge.game.Match; -import forge.gui.SOverlayUtils; -import forge.gui.framework.FScreen; -import javax.swing.*; - import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import javax.swing.JButton; + +import forge.Singletons; +import forge.gui.SOverlayUtils; +import forge.gui.framework.FScreen; +import forge.view.IGameView; + /** * Default controller for a ViewWinLose object. This class can * be extended for various game modes to populate the custom @@ -18,13 +18,13 @@ import java.awt.event.ActionListener; */ public class ControlWinLose { private final ViewWinLose view; - protected final Game lastGame; + protected final IGameView lastGame; /** @param v   ViewWinLose * @param match */ - public ControlWinLose(final ViewWinLose v, Game game) { + public ControlWinLose(final ViewWinLose v, final IGameView game0) { this.view = v; - this.lastGame = game; + this.lastGame = game0; addListeners(); } @@ -59,17 +59,15 @@ public class ControlWinLose { saveOptions(); Singletons.getControl().endCurrentGame(); - Singletons.getControl().startGameWithUi(lastGame.getMatch()); + Singletons.getControl().startGameInSameMatch(); } /** Action performed when "restart" button is pressed in default win/lose UI. */ public void actionOnRestart() { SOverlayUtils.hideOverlay(); saveOptions(); - final Match match = lastGame.getMatch(); - match.clearGamesPlayed(); Singletons.getControl().endCurrentGame(); - Singletons.getControl().startGameWithUi(match); + Singletons.getControl().startGameAndClearMatch(); } /** Action performed when "quit" button is pressed in default win/lose UI. */ diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/GauntletWinLose.java b/forge-gui-desktop/src/main/java/forge/screens/match/GauntletWinLose.java index 052da685a6c..07772d8fefc 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/GauntletWinLose.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/GauntletWinLose.java @@ -17,18 +17,20 @@ package forge.screens.match; * along with this program. If not, see . */ +import java.awt.Color; +import java.util.List; + +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SwingConstants; + +import net.miginfocom.swing.MigLayout; import forge.assets.FSkinProp; -import forge.game.Game; import forge.gauntlet.GauntletWinLoseController; import forge.toolbox.FLabel; import forge.toolbox.FSkin; import forge.toolbox.FSkin.SkinnedPanel; -import net.miginfocom.swing.MigLayout; - -import javax.swing.*; - -import java.awt.*; -import java.util.List; +import forge.view.IGameView; /** * The Win/Lose handler for 'gauntlet' type tournament @@ -43,9 +45,9 @@ public class GauntletWinLose extends ControlWinLose { * @param view0 ViewWinLose object * @param match */ - public GauntletWinLose(final ViewWinLose view0, Game lastGame) { - super(view0, lastGame); - controller = new GauntletWinLoseController(view0, lastGame) { + public GauntletWinLose(final ViewWinLose view0, final IGameView game0) { + super(view0, game0); + controller = new GauntletWinLoseController(view0, game0) { @Override protected void showOutcome(String message1, String message2, FSkinProp icon, List lstEventNames, List lstEventRecords, int len, int num) { final JLabel lblTitle = new FLabel.Builder().text("Gauntlet Progress") diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/LimitedWinLose.java b/forge-gui-desktop/src/main/java/forge/screens/match/LimitedWinLose.java index d283b8be1a5..352e0a6318d 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/LimitedWinLose.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/LimitedWinLose.java @@ -21,12 +21,12 @@ import java.awt.Dimension; import javax.swing.SwingConstants; -import forge.game.Game; import forge.limited.LimitedWinLoseController; import forge.toolbox.FSkin; import forge.toolbox.FSkin.Colors; import forge.toolbox.FSkin.SkinColor; import forge.toolbox.FSkin.SkinnedLabel; +import forge.view.IGameView; /** * The Win/Lose handler for 'gauntlet' type tournament @@ -46,9 +46,9 @@ public class LimitedWinLose extends ControlWinLose { * @param view0 {@link forge.screens.match.ViewWinLose} * @param match {@link forge.game.Match} */ - public LimitedWinLose(final ViewWinLose view0, Game lastGame) { - super(view0, lastGame); - controller = new LimitedWinLoseController(view0, lastGame) { + public LimitedWinLose(final ViewWinLose view0, final IGameView game0) { + super(view0, game0); + controller = new LimitedWinLoseController(view0, game0) { @Override protected void showOutcome(Runnable runnable) { runnable.run(); //just run on GUI thread diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/QuestDraftWinLose.java b/forge-gui-desktop/src/main/java/forge/screens/match/QuestDraftWinLose.java index f67d21b8fdd..04a48b14ee5 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/QuestDraftWinLose.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/QuestDraftWinLose.java @@ -24,8 +24,6 @@ import forge.GuiBase; import forge.LobbyPlayer; import forge.Singletons; import forge.assets.FSkinProp; -import forge.game.Game; -import forge.game.player.Player; import forge.gui.SOverlayUtils; import forge.gui.framework.FScreen; import forge.model.FModel; @@ -37,6 +35,8 @@ import forge.screens.home.quest.CSubmenuQuestDraft; import forge.screens.home.quest.VSubmenuQuestDraft; import forge.toolbox.FOptionPane; import forge.toolbox.FSkin; +import forge.view.IGameView; +import forge.view.PlayerView; /** *

@@ -58,8 +58,8 @@ public class QuestDraftWinLose extends ControlWinLose { * @param view0 ViewWinLose object * @param match2 */ - public QuestDraftWinLose(final ViewWinLose view0, Game lastGame) { - super(view0, lastGame); + public QuestDraftWinLose(final ViewWinLose view0, final IGameView game0) { + super(view0, game0); this.view = view0; qData = FModel.getQuest(); } @@ -79,18 +79,18 @@ public class QuestDraftWinLose extends ControlWinLose { QuestController quest = FModel.getQuest(); final LobbyPlayer questLobbyPlayer = GuiBase.getInterface().getQuestPlayer(); - List players = lastGame.getRegisteredPlayers(); + final List players = lastGame.getPlayers(); boolean gameHadHumanPlayer = false; - for (Player p : players) { + for (final PlayerView p : players) { if (p.getLobbyPlayer().equals(questLobbyPlayer)) { gameHadHumanPlayer = true; break; } } - if (lastGame.getMatch().isMatchOver()) { + if (lastGame.isMatchOver()) { - String winner = lastGame.getOutcome().getWinningPlayer().getName(); + String winner = lastGame.getWinningPlayer().getName(); quest.getAchievements().getCurrentDraft().setWinner(winner); quest.save(); @@ -99,7 +99,7 @@ public class QuestDraftWinLose extends ControlWinLose { if (!gameHadHumanPlayer) { - if (lastGame.getMatch().isMatchOver()) { + if (lastGame.isMatchOver()) { this.actionOnQuitMatch(); QuestDraftUtils.matchInProgress = false; QuestDraftUtils.update(); @@ -114,7 +114,7 @@ public class QuestDraftWinLose extends ControlWinLose { view.getBtnRestart().setEnabled(false); view.getBtnRestart().setVisible(false); - if (lastGame.getMatch().isMatchOver()) { + if (lastGame.isMatchOver()) { view.getBtnQuit().setEnabled(true); view.getBtnContinue().setEnabled(false); view.getBtnQuit().setText("Continue Tournament"); diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/QuestWinLose.java b/forge-gui-desktop/src/main/java/forge/screens/match/QuestWinLose.java index abb7e9b71cb..3a48b50521f 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/QuestWinLose.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/QuestWinLose.java @@ -16,12 +16,16 @@ */ package forge.screens.match; +import java.awt.Dimension; +import java.util.List; + +import javax.swing.SwingConstants; + import forge.assets.FSkinProp; -import forge.game.Game; -import forge.item.*; +import forge.item.PaperCard; import forge.model.FModel; import forge.properties.ForgePreferences.FPref; -import forge.quest.*; +import forge.quest.QuestWinLoseController; import forge.screens.home.quest.CSubmenuChallenges; import forge.screens.home.quest.CSubmenuDuels; import forge.toolbox.FSkin; @@ -29,11 +33,7 @@ import forge.toolbox.FSkin.Colors; import forge.toolbox.FSkin.SkinColor; import forge.toolbox.FSkin.SkinIcon; import forge.toolbox.FSkin.SkinnedLabel; - -import java.awt.Dimension; -import java.util.List; - -import javax.swing.SwingConstants; +import forge.view.IGameView; /** *

@@ -61,10 +61,10 @@ public class QuestWinLose extends ControlWinLose { * @param view0 ViewWinLose object * @param match2 */ - public QuestWinLose(final ViewWinLose view0, Game lastGame) { - super(view0, lastGame); + public QuestWinLose(final ViewWinLose view0, final IGameView game0) { + super(view0, game0); view = view0; - controller = new QuestWinLoseController(lastGame) { + controller = new QuestWinLoseController(game0) { @Override protected void showRewards(Runnable runnable) { runnable.run(); //just run on GUI thread diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/QuestWinLoseCardViewer.java b/forge-gui-desktop/src/main/java/forge/screens/match/QuestWinLoseCardViewer.java index 36f8ec984ca..e0993944417 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/QuestWinLoseCardViewer.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/QuestWinLoseCardViewer.java @@ -63,7 +63,7 @@ public class QuestWinLoseCardViewer extends FPanel { public QuestWinLoseCardViewer(final List list) { this.list = Collections.unmodifiableList(list); this.jList = new FList(new ChooserListModel()); - this.detail = new CardDetailPanel(null); + this.detail = new CardDetailPanel(); this.picture = new CardPicturePanel(); this.scroller = new FScrollPane(this.jList, false); diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/VAssignDamage.java b/forge-gui-desktop/src/main/java/forge/screens/match/VAssignDamage.java index 425e03768b7..555db808de3 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/VAssignDamage.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/VAssignDamage.java @@ -17,6 +17,7 @@ */ package forge.screens.match; +import forge.control.FControl; import forge.game.GameEntity; import forge.game.card.Card; import forge.game.card.CounterType; @@ -27,13 +28,20 @@ import forge.toolbox.FLabel; import forge.toolbox.FScrollPane; import forge.toolbox.FSkin; import forge.toolbox.FSkin.SkinnedPanel; +import forge.view.CardView; import forge.view.FDialog; +import forge.view.GameEntityView; +import forge.view.PlayerView; import forge.view.arcane.CardPanel; import net.miginfocom.swing.MigLayout; import javax.swing.*; import javax.swing.border.Border; +import org.testng.collections.Lists; + +import com.google.common.collect.Maps; + import java.awt.Dialog.ModalityType; import java.awt.*; import java.awt.event.ActionEvent; @@ -68,7 +76,7 @@ public class VAssignDamage { private boolean attackerHasInfect = false; private boolean overrideCombatantOrder = false; - private final GameEntity defender; + private final GameEntityView defender; private final JLabel lblTotalDamage = new FLabel.Builder().text("Available damage points: Unknown").build(); private final JLabel lblAssignRemaining = new FLabel.Builder().text("Distribute the remaining damage points among lethally wounded entities").build(); @@ -79,24 +87,24 @@ public class VAssignDamage { private static class DamageTarget { - public final Card card; + public final CardView card; public final JLabel label; public int damage; - public DamageTarget(Card entity0, JLabel lbl) { - card = entity0; + public DamageTarget(final CardView c, final JLabel lbl) { + card = c; label = lbl; } } // Indexes of defenders correspond to their indexes in the damage list and labels. - private final List defenders = new ArrayList(); // NULL in this map means defender - private final Map damage = new HashMap(); // NULL in this map means defender + private final List defenders = Lists.newArrayList(); // NULL in this map means defender + private final Map damage = Maps.newHashMap(); // NULL in this map means defender - private boolean canAssignTo(Card card) { - for(DamageTarget dt : defenders) { - if ( dt.card == card ) return true; - if ( getDamageToKill(dt.card) > dt.damage ) + private boolean canAssignTo(final CardView card) { + for (DamageTarget dt : defenders) { + if (dt.card == card ) return true; + if (getDamageToKill(dt.card) > dt.damage ) return false; } throw new RuntimeException("Asking to assign damage to object which is not present in defenders list"); @@ -106,10 +114,10 @@ public class VAssignDamage { private final MouseAdapter mad = new MouseAdapter() { @Override public void mouseEntered(final MouseEvent evt) { - Card source = ((CardPanel) evt.getSource()).getCard(); + CardView source = ((CardPanel) evt.getSource()).getCard(); if (!damage.containsKey(source)) source = null; // to get player instead of fake card - - FSkin.Colors brdrColor = VAssignDamage.this.canAssignTo(source) ? FSkin.Colors.CLR_ACTIVE : FSkin.Colors.CLR_INACTIVE; + + final FSkin.Colors brdrColor = VAssignDamage.this.canAssignTo(source) ? FSkin.Colors.CLR_ACTIVE : FSkin.Colors.CLR_INACTIVE; ((CardPanel) evt.getSource()).setBorder(new FSkin.LineSkinBorder(FSkin.getColor(brdrColor), 2)); } @@ -120,7 +128,7 @@ public class VAssignDamage { @Override public void mousePressed(final MouseEvent evt) { - Card source = ((CardPanel) evt.getSource()).getCard(); // will be NULL for player + CardView source = ((CardPanel) evt.getSource()).getCard(); // will be NULL for player boolean meta = evt.isControlDown(); boolean isLMB = SwingUtilities.isLeftMouseButton(evt); @@ -133,22 +141,22 @@ public class VAssignDamage { /** Constructor. * - * @param attacker0 {@link forge.game.card.Card} - * @param defenderCards List<{@link forge.game.card.Card}> + * @param attacker {@link forge.game.card.Card} + * @param blockers List<{@link forge.game.card.Card}> * @param damage0 int * @param defender GameEntity that's bein attacked * @param overrideOrder override combatant order */ - public VAssignDamage(final Card attacker0, final List defenderCards, final int damage0, final GameEntity defender, boolean overrideOrder) { - dlg.setTitle("Assign damage dealt by " + attacker0.getName()); + public VAssignDamage(final CardView attacker, final List blockers, final int damage0, final GameEntityView defender, boolean overrideOrder) { + dlg.setTitle("Assign damage dealt by " + attacker); // Set damage storage vars this.totalDamageToAssign = damage0; this.defender = defender; - this.attackerHasDeathtouch = attacker0.hasKeyword("Deathtouch"); - this.attackerHasInfect = attacker0.hasKeyword("Infect"); - this.attackerHasTrample = defender != null && attacker0.hasKeyword("Trample"); + this.attackerHasDeathtouch = attacker.getState().hasDeathtouch(); + this.attackerHasInfect = attacker.getState().hasInfect(); + this.attackerHasTrample = defender != null && attacker.getState().hasTrample(); this.overrideCombatantOrder = overrideOrder; // Top-level UI stuff @@ -157,7 +165,7 @@ public class VAssignDamage { pnlMain.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2)); // Attacker area - final CardPanel pnlAttacker = new CardPanel(attacker0); + final CardPanel pnlAttacker = new CardPanel(attacker); pnlAttacker.setOpaque(false); pnlAttacker.setCardBounds(0, 0, 105, 150); @@ -170,14 +178,14 @@ public class VAssignDamage { // Defenders area final JPanel pnlDefenders = new JPanel(); pnlDefenders.setOpaque(false); - int cols = attackerHasTrample ? defenderCards.size() + 1 : defenderCards.size(); + int cols = attackerHasTrample ? blockers.size() + 1 : blockers.size(); final String wrap = "wrap " + Integer.toString(cols); pnlDefenders.setLayout(new MigLayout("insets 0, gap 0, ax center, " + wrap)); final FScrollPane scrDefenders = new FScrollPane(pnlDefenders, false); // Top row of cards... - for (final Card c : defenderCards) { + for (final CardView c : blockers) { DamageTarget dt = new DamageTarget(c, new FLabel.Builder().text("0").fontSize(18).fontAlign(SwingConstants.CENTER).build()); this.damage.put(c, dt); this.defenders.add(dt); @@ -188,18 +196,18 @@ public class VAssignDamage { DamageTarget dt = new DamageTarget(null, new FLabel.Builder().text("0").fontSize(18).fontAlign(SwingConstants.CENTER).build()); this.damage.put(null, dt); this.defenders.add(dt); - Card fakeCard; - if (defender instanceof Card) - fakeCard = (Card)defender; - else if (defender instanceof Player) { - fakeCard = new Card(-1); - fakeCard.setName(this.defender.getName()); - fakeCard.setOwner((Player)defender); - Player p = (Player)defender; - fakeCard.setImageKey(CMatchUI.SINGLETON_INSTANCE.avatarImages.get(p.getOriginalLobbyPlayer())); + final CardView fakeCard; + if (defender instanceof CardView) + fakeCard = (CardView)defender; + else if (defender instanceof PlayerView) { + fakeCard = new CardView(null, -1); + fakeCard.getState().setName(this.defender.toString()); + final PlayerView p = (PlayerView)defender; + fakeCard.getState().setOwner(p); + fakeCard.getState().setImageKey(CMatchUI.SINGLETON_INSTANCE.avatarImages.get(p.getLobbyPlayer())); } else { - fakeCard = new Card(-2); - fakeCard.setName(this.defender.getName()); + fakeCard = new CardView(null, -2); + fakeCard.getState().setName(this.defender.toString()); } addPanelForDefender(pnlDefenders, fakeCard); } @@ -259,7 +267,7 @@ public class VAssignDamage { * @param pnlDefenders * @param defender */ - private void addPanelForDefender(final JPanel pnlDefenders, final Card defender) { + private void addPanelForDefender(final JPanel pnlDefenders, final CardView defender) { final CardPanel cp = new CardPanel(defender); cp.setCardBounds(0, 0, 105, 150); cp.setOpaque(true); @@ -273,7 +281,7 @@ public class VAssignDamage { * @param meta * @param isLMB */ - private void assignDamageTo(Card source, boolean meta, boolean isAdding) { + private void assignDamageTo(CardView source, final boolean meta, final boolean isAdding) { if ( !damage.containsKey(source) ) source = null; @@ -366,14 +374,14 @@ public class VAssignDamage { dt.damage = 0; } - private void addDamage(final Card card, int addedDamage) { + private void addDamage(final CardView card, int addedDamage) { // If we don't have enough left or we're trying to unassign too much return - int canAssign = getRemainingDamage(); + final int canAssign = getRemainingDamage(); if (canAssign < addedDamage) { addedDamage = canAssign; } - DamageTarget dt = damage.get(card); + final DamageTarget dt = damage.get(card); dt.damage = Math.max(0, addedDamage + dt.damage); } @@ -433,28 +441,28 @@ public class VAssignDamage { /** * TODO: Write javadoc for this method. - * @param source + * @param card * @return */ - private int getDamageToKill(Card source) { + private int getDamageToKill(final CardView card) { int lethalDamage = 0; - if ( source == null ) { - if ( defender instanceof Player ) { - Player p = (Player)defender; - lethalDamage = attackerHasInfect ? p.getGame().getRules().getPoisonCountersToLose() - p.getPoisonCounters() : p.getLife(); - } else if ( defender instanceof Card ) { // planeswalker - Card pw = (Card)defender; - lethalDamage = pw.getCounters(CounterType.LOYALTY); + if (card == null) { + if (defender instanceof PlayerView) { + final PlayerView p = (PlayerView)defender; + lethalDamage = attackerHasInfect ? FControl.instance.getGameView().getPoisonCountersToLose() - p.getPoisonCounters() : p.getLife(); + } else if (defender instanceof CardView) { // planeswalker + final CardView pw = (CardView)defender; + lethalDamage = pw.getState().getLoyalty(); } } else { - lethalDamage = VAssignDamage.this.attackerHasDeathtouch ? 1 : Math.max(0, source.getLethalDamage()); + lethalDamage = VAssignDamage.this.attackerHasDeathtouch ? 1 : Math.max(0, card.getLethalDamage()); } return lethalDamage; } - public Map getDamageMap() { - Map result = new HashMap(); - for(DamageTarget dt : defenders) + public Map getDamageMap() { + Map result = Maps.newHashMapWithExpectedSize(defenders.size()); + for (DamageTarget dt : defenders) result.put(dt.card, dt.damage); return result; } diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/VAutoYields.java b/forge-gui-desktop/src/main/java/forge/screens/match/VAutoYields.java index 238d8d9262c..db32ba8e81a 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/VAutoYields.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/VAutoYields.java @@ -10,14 +10,14 @@ import javax.swing.event.ChangeListener; import forge.Singletons; import forge.UiCommand; -import forge.game.Game; -import forge.game.player.Player; import forge.toolbox.FButton; import forge.toolbox.FCheckBox; import forge.toolbox.FList; import forge.toolbox.FOptionPane; import forge.toolbox.FScrollPane; import forge.view.FDialog; +import forge.view.IGameView; +import forge.view.PlayerView; @SuppressWarnings("serial") public class VAutoYields extends FDialog { @@ -32,12 +32,12 @@ public class VAutoYields extends FDialog { private final FCheckBox chkDisableAll; private final List autoYields; - public VAutoYields(final Game game, final Player player) { + public VAutoYields(final IGameView game, final PlayerView playerView) { super(true); setTitle("Auto-Yields"); autoYields = new ArrayList(); - for (String autoYield : player.getController().getAutoYields()) { + for (final String autoYield : playerView.getController().getAutoYields()) { autoYields.add(autoYield); } lstAutoYields = new FList(new AutoYieldsListModel()); @@ -72,7 +72,7 @@ public class VAutoYields extends FDialog { if (selected != null) { autoYields.remove(selected); btnRemove.setEnabled(autoYields.size() > 0); - player.getController().setShouldAutoYield(selected, false); + playerView.getController().setShouldAutoYield(selected, false); VAutoYields.this.revalidate(); lstAutoYields.repaint(); } diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/ViewWinLose.java b/forge-gui-desktop/src/main/java/forge/screens/match/ViewWinLose.java index 2348f95ab73..90ef30a024a 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/ViewWinLose.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/ViewWinLose.java @@ -11,13 +11,11 @@ import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import net.miginfocom.swing.MigLayout; +import forge.LobbyPlayer; import forge.UiCommand; -import forge.game.Game; import forge.game.GameLog; import forge.game.GameLogEntry; import forge.game.GameLogEntryType; -import forge.game.GameOutcome; -import forge.game.player.Player; import forge.gui.SOverlayUtils; import forge.interfaces.IWinLoseView; import forge.model.FModel; @@ -29,7 +27,7 @@ import forge.toolbox.FSkin; import forge.toolbox.FSkin.SkinnedLabel; import forge.toolbox.FSkin.SkinnedPanel; import forge.toolbox.FTextArea; - +import forge.view.IGameView; public class ViewWinLose implements IWinLoseView { private final FButton btnContinue, btnRestart, btnQuit; @@ -39,12 +37,12 @@ public class ViewWinLose implements IWinLoseView { private final SkinnedLabel lblStats = new SkinnedLabel("WinLoseFrame > lblStats needs updating."); private final JPanel pnlOutcomes = new JPanel(new MigLayout("wrap, align center")); - private final Game game; + private final IGameView game; @SuppressWarnings("serial") - public ViewWinLose(final Game game0) { + public ViewWinLose(final IGameView game0) { - game = game0; + this.game = game0; final JPanel overlay = FOverlay.SINGLETON_INSTANCE.getPanel(); @@ -60,7 +58,7 @@ public class ViewWinLose implements IWinLoseView { // Control of the win/lose is handled differently for various game // modes. ControlWinLose control = null; - switch (game0.getRules().getGameType()) { + switch (game0.getGameType()) { case Quest: control = new QuestWinLose(this, game0); break; @@ -103,7 +101,7 @@ public class ViewWinLose implements IWinLoseView { btnRestart.setFont(FSkin.getFont(22)); btnQuit.setText("Quit Match"); btnQuit.setFont(FSkin.getFont(22)); - btnContinue.setEnabled(!game0.getMatch().isMatchOver()); + btnContinue.setEnabled(!game0.isMatchOver()); // Assemble game log scroller. final FTextArea txtLog = new FTextArea(); @@ -180,20 +178,20 @@ public class ViewWinLose implements IWinLoseView { } }); - lblTitle.setText(composeTitle(game0.getOutcome())); + lblTitle.setText(composeTitle(game0)); showGameOutcomeSummary(); showPlayerScores(); } - private String composeTitle(GameOutcome outcome) { - Player winner = outcome.getWinningPlayer(); - int winningTeam = outcome.getWinningTeam(); + private String composeTitle(final IGameView game) { + final LobbyPlayer winner = game.getWinningPlayer(); + final int winningTeam = game.getWinningTeam(); if (winner == null) { return "It's a draw!"; } else if (winningTeam != -1) { - return "Team " + winner.getTeam() + " Won!"; + return "Team " + winningTeam + " Won!"; } else { return winner.getName() + " Won!"; } diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/ZoneAction.java b/forge-gui-desktop/src/main/java/forge/screens/match/ZoneAction.java index cdcec07dd48..ca483f0cc2b 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/ZoneAction.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/ZoneAction.java @@ -1,17 +1,16 @@ package forge.screens.match; -import forge.Singletons; -import forge.card.CardCharacteristicName; -import forge.game.card.Card; -import forge.game.card.CardFactory; -import forge.game.zone.PlayerZone; +import java.awt.event.ActionEvent; +import java.util.List; + +import com.beust.jcommander.internal.Lists; +import com.google.common.collect.Iterables; + import forge.gui.ForgeAction; import forge.gui.GuiChoose; import forge.match.MatchConstants; - -import java.awt.event.ActionEvent; -import java.util.ArrayList; -import java.util.List; +import forge.view.CardView; +import forge.view.CardView.CardStateView; /** * Receives click and programmatic requests for viewing data stacks in the @@ -20,7 +19,7 @@ import java.util.List; */ public class ZoneAction extends ForgeAction { private static final long serialVersionUID = -5822976087772388839L; - private final PlayerZone zone; + private final Iterable cards; private final String title; /** @@ -33,10 +32,10 @@ public class ZoneAction extends ForgeAction { * @param property *   String obj */ - public ZoneAction(final PlayerZone zone, MatchConstants property) { + public ZoneAction(final Iterable cards, final MatchConstants property) { super(property); this.title = property.title; - this.zone = zone; + this.cards = Iterables.unmodifiableIterable(cards); } /** @@ -45,37 +44,33 @@ public class ZoneAction extends ForgeAction { */ @Override public void actionPerformed(final ActionEvent e) { - final List choices = this.getCardsAsIterable(); - if (choices.isEmpty()) { + final Iterable choices = this.getCardsAsIterable(); + if (!choices.iterator().hasNext()) { GuiChoose.reveal(this.title, "no cards"); return; } - final ArrayList choices2 = new ArrayList(); - for (Card crd : choices) { - Card toAdd = crd; - if (crd.isFaceDown()) { - if (Singletons.getControl().mayShowCard(crd)) { - toAdd = CardFactory.copyCard(crd, false); - toAdd.setState(CardCharacteristicName.Original); - } else { - toAdd = new Card(0); - toAdd.setName("Face Down"); - } - } + final List choices2 = Lists.newLinkedList(); + for (final CardView crd : choices) { + final CardStateView toAdd; + if (crd.isFaceDown() && crd.hasAltState()) { + toAdd = crd.getAlternate(); + } else { + toAdd = crd.getState(); + } choices2.add(toAdd); } - final Card choice = GuiChoose.oneOrNone(this.title, choices2); + final CardStateView choice = GuiChoose.oneOrNone(this.title, choices2); if (choice != null) { - this.doAction(choice); + this.doAction(choice.getCard()); } } - protected List getCardsAsIterable() { - return this.zone.getCards(); + protected Iterable getCardsAsIterable() { + return cards; } - protected void doAction(final Card c) { + protected void doAction(final CardView c) { } } // End ZoneAction \ No newline at end of file diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CCommand.java b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CCommand.java index c20236a9565..e03ce86c1a7 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CCommand.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CCommand.java @@ -18,24 +18,25 @@ package forge.screens.match.controllers; import forge.UiCommand; -import forge.game.player.Player; import forge.gui.framework.ICDoc; import forge.screens.match.views.VCommand; +import forge.view.PlayerView; + /** * Controls Swing components of a player's command instance. */ public class CCommand implements ICDoc { - private final Player player; + private final PlayerView player; private final VCommand view; /** * Controls Swing components of a player's command instance. * - * @param p0   {@link forge.game.player.Player} + * @param player2   {@link forge.game.player.Player} * @param v0   {@link forge.screens.match.views.VCommand} */ - public CCommand(final Player p0, final VCommand v0) { - this.player = p0; + public CCommand(final PlayerView player2, final VCommand v0) { + this.player = player2; this.view = v0; } @@ -48,7 +49,7 @@ public class CCommand implements ICDoc { } /** @return {@link forge.game.player.Player} */ - public Player getPlayer() { + public PlayerView getPlayer() { return this.player; } diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CDetail.java b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CDetail.java index 638116e987c..7ab511e32b7 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CDetail.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CDetail.java @@ -27,6 +27,7 @@ import forge.item.InventoryItem; import forge.item.InventoryItemFromSet; import forge.screens.match.views.VDetail; import forge.toolbox.FMouseAdapter; +import forge.view.CardView; import java.awt.event.MouseEvent; @@ -45,6 +46,7 @@ public enum CDetail implements ICDoc { * * @param c   Card object */ + @Deprecated public void showCard(Card c) { if (c != null) { c = c.getCardForUi(); @@ -56,7 +58,15 @@ public enum CDetail implements ICDoc { } } - public void showCard(InventoryItem item) { + public void showCard(final CardView c, final boolean isInAltState) { + view.getLblFlipcard().setVisible(c != null && c.hasAltState() && Singletons.getControl().mayShowCard(c)); + view.getPnlDetail().setCard(c, isInAltState); + if (view.getParentCell() != null) { + view.getParentCell().repaintSelf(); + } + } + + public void showCard(final InventoryItem item) { if (item instanceof IPaperCard) { showCard(Card.getCardForUi((IPaperCard)item)); } diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CDock.java b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CDock.java index 150cee8782d..5fc548d7774 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CDock.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CDock.java @@ -17,19 +17,18 @@ */ package forge.screens.match.controllers; +import forge.GuiBase; import forge.LobbyPlayer; import forge.UiCommand; import forge.FThreads; import forge.Singletons; import forge.assets.FSkinProp; import forge.deckchooser.FDeckViewer; -import forge.game.Game; import forge.game.card.Card; import forge.game.card.CardLists; import forge.game.card.CardPredicates.Presets; import forge.game.combat.Combat; import forge.game.combat.CombatUtil; -import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseType; import forge.game.player.Player; import forge.game.player.RegisteredPlayer; @@ -38,7 +37,6 @@ import forge.gui.SOverlayUtils; import forge.gui.framework.ICDoc; import forge.gui.framework.SLayoutIO; import forge.model.FModel; -import forge.player.GamePlayerUtil; import forge.properties.FileLocation; import forge.properties.ForgePreferences.FPref; import forge.screens.match.CMatchUI; @@ -47,6 +45,7 @@ import forge.toolbox.FSkin; import forge.toolbox.SaveOpenDialog; import forge.toolbox.SaveOpenDialog.Filetypes; import forge.view.FView; +import forge.view.IGameView; import java.io.File; import java.util.List; @@ -61,9 +60,9 @@ public enum CDock implements ICDoc { SINGLETON_INSTANCE; private int arcState; - private Game game; + private IGameView game; - public void setModel(Game game0, LobbyPlayer player0) { + public void setModel(IGameView game0, LobbyPlayer player0) { game = game0; } @@ -136,7 +135,8 @@ public enum CDock implements ICDoc { * View deck list. */ public void viewDeckList() { - RegisteredPlayer player = GamePlayerUtil.getGuiRegisteredPlayer(game); + final LobbyPlayer guiPlayer = GuiBase.getInterface().getGuiPlayer(); + final RegisteredPlayer player = game.getGuiRegisteredPlayer(guiPlayer); if (player != null) { FDeckViewer.show(player.getDeck()); } @@ -178,12 +178,9 @@ public enum CDock implements ICDoc { /** Attack with everyone. */ public void alphaStrike() { - final PhaseHandler ph = game.getPhaseHandler(); - - final Player p = findAffectedPlayer(); - final Game game = p.getGame(); - Combat combat = game.getCombat(); - if (ph.is(PhaseType.COMBAT_DECLARE_ATTACKERS, p) && combat!= null) { // ph.is(...) includes null check + final Player p = this.findAffectedPlayer(); + final Combat combat = game.getCombat(); + if (this.game.isCombatDeclareAttackers()) { List defenders = p.getOpponents(); for (Card c : CardLists.filter(p.getCardsIn(ZoneType.Battlefield), Presets.CREATURES)) { diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CField.java b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CField.java index 04b85e68083..89f8de18c4d 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CField.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CField.java @@ -17,14 +17,17 @@ */ package forge.screens.match.controllers; +import java.awt.event.ActionEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.List; + import com.google.common.base.Function; import forge.LobbyPlayer; -import forge.UiCommand; import forge.Singletons; -import forge.game.card.Card; -import forge.game.player.Player; -import forge.game.zone.ZoneType; +import forge.UiCommand; import forge.gui.framework.ICDoc; import forge.match.MatchConstants; import forge.match.input.Input; @@ -33,19 +36,15 @@ import forge.properties.ForgePreferences; import forge.screens.match.ZoneAction; import forge.screens.match.views.VField; import forge.toolbox.MouseTriggerEvent; - -import java.awt.event.ActionEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.util.List; +import forge.view.CardView; +import forge.view.PlayerView; /** * Controls Swing components of a player's field instance. */ public class CField implements ICDoc { // The one who owns cards on this side of table - private final Player player; + private final PlayerView player; // Tho one who looks at screen and 'performs actions' private final LobbyPlayer viewer; private final VField view; @@ -61,42 +60,44 @@ public class CField implements ICDoc { /** * Controls Swing components of a player's field instance. * - * @param p0   {@link forge.game.player.Player} + * @param player2   {@link forge.game.player.Player} * @param v0   {@link forge.screens.match.views.VField} * @param playerViewer */ @SuppressWarnings("serial") - public CField(final Player p0, final VField v0, LobbyPlayer playerViewer) { - this.player = p0; + public CField(final PlayerView player2, final VField v0, LobbyPlayer playerViewer) { + this.player = player2; this.viewer = playerViewer; this.view = v0; - ZoneAction handAction = new ZoneAction(player.getZone(ZoneType.Hand), MatchConstants.HUMANHAND) { + final ZoneAction handAction = new ZoneAction(player.getHandCards(), MatchConstants.HUMANHAND) { @Override public void actionPerformed(ActionEvent e) { - if ( player.getLobbyPlayer() == viewer || ForgePreferences.DEV_MODE || player.hasKeyword("Play with your hand revealed.")) + if (player.getLobbyPlayer() == viewer || ForgePreferences.DEV_MODE) {// || player.hasKeyword("Play with your hand revealed.")) super.actionPerformed(e); + } } }; - - ZoneAction libraryAction = new ZoneAction(player.getZone(ZoneType.Library), MatchConstants.HUMANLIBRARY) { + + final ZoneAction libraryAction = new ZoneAction(player.getLibraryCards(), MatchConstants.HUMANLIBRARY) { @Override public void actionPerformed(ActionEvent e) { - if (ForgePreferences.DEV_MODE) + if (ForgePreferences.DEV_MODE) { super.actionPerformed(e); + } } }; - - ZoneAction exileAction = new ZoneAction(player.getZone(ZoneType.Exile), MatchConstants.HUMANEXILED); - ZoneAction graveAction = new ZoneAction(player.getZone(ZoneType.Graveyard), MatchConstants.HUMANGRAVEYARD); - ZoneAction flashBackAction = new ZoneAction(player.getZone(ZoneType.Graveyard), MatchConstants.HUMANFLASHBACK) { + + final ZoneAction exileAction = new ZoneAction(player.getExileCards(), MatchConstants.HUMANEXILED); + final ZoneAction graveAction = new ZoneAction(player.getGraveCards(), MatchConstants.HUMANGRAVEYARD); + final ZoneAction flashBackAction = new ZoneAction(player.getFlashbackCards(), MatchConstants.HUMANFLASHBACK) { @Override - protected List getCardsAsIterable() { - return player.getCardsActivableInExternalZones(true); + protected List getCardsAsIterable() { + return player.getFlashbackCards(); } @Override - protected void doAction(final Card c) { + protected void doAction(final CardView c) { // activate cards only via your own flashback button if (player.getLobbyPlayer() != CField.this.viewer) { return; @@ -157,16 +158,6 @@ public class CField implements ICDoc { public void update() { } - /** @return {@link forge.game.player.Player} */ - public Player getPlayer() { - return this.player; - } - - /** @return {@link forge.screens.match.views.VField} */ - public VField getView() { - return this.view; - } - /* (non-Javadoc) * @see forge.gui.framework.ICDoc#getCommandOnSelect() */ diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CHand.java b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CHand.java index a640d2909b3..77f23dcaa0f 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CHand.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CHand.java @@ -17,35 +17,36 @@ */ package forge.screens.match.controllers; -import forge.UiCommand; -import forge.FThreads; -import forge.Singletons; -import forge.game.card.Card; -import forge.game.player.Player; -import forge.game.zone.ZoneType; -import forge.gui.framework.ICDoc; -import forge.screens.match.CMatchUI; -import forge.screens.match.views.VField; -import forge.screens.match.views.VHand; -import forge.view.arcane.CardPanel; -import forge.view.arcane.HandArea; -import forge.view.arcane.util.Animation; -import forge.view.arcane.util.CardPanelMouseAdapter; - -import javax.swing.*; - -import java.awt.*; +import java.awt.Point; +import java.awt.Rectangle; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.List; import java.util.Observable; +import javax.swing.JLayeredPane; +import javax.swing.SwingUtilities; + +import forge.FThreads; +import forge.Singletons; +import forge.UiCommand; +import forge.gui.framework.ICDoc; +import forge.screens.match.CMatchUI; +import forge.screens.match.views.VField; +import forge.screens.match.views.VHand; +import forge.view.CardView; +import forge.view.PlayerView; +import forge.view.arcane.CardPanel; +import forge.view.arcane.HandArea; +import forge.view.arcane.util.Animation; +import forge.view.arcane.util.CardPanelMouseAdapter; + /** * Controls Swing components of a player's hand instance. * */ public class CHand implements ICDoc { - private final Player player; + private final PlayerView player; private final VHand view; private boolean initializedAlready = false; @@ -55,15 +56,15 @@ public class CHand implements ICDoc { * @param p0   {@link forge.game.player.Player} * @param v0   {@link forge.screens.match.views.VHand} */ - public CHand(final Player p0, final VHand v0) { + public CHand(final PlayerView p0, final VHand v0) { this.player = p0; this.view = v0; v0.getHandArea().addCardPanelMouseListener(new CardPanelMouseAdapter() { @Override public void mouseDragEnd(CardPanel dragPanel, MouseEvent evt) { //update index of dragged card in hand zone to match new index within hand area - int index = CHand.this.view.getHandArea().getCardPanels().indexOf(dragPanel); - CHand.this.player.getZone(ZoneType.Hand).reposition(dragPanel.getCard(), index); + //int index = CHand.this.view.getHandArea().getCardPanels().indexOf(dragPanel); + //CHand.this.player.getZone(ZoneType.Hand).reposition(dragPanel.getCard(), index); } }); } @@ -103,12 +104,12 @@ public class CHand implements ICDoc { } //update card panels in hand area - final List cards = player.getZone(ZoneType.Hand).getCards(); + final List cards = player.getHandCards(); final List placeholders = new ArrayList(); final List cardPanels = new ArrayList(); - - for (Card card : cards) { - CardPanel cardPanel = p.getCardPanel(card.getUniqueNumber()); + + for (final CardView card : cards) { + CardPanel cardPanel = p.getCardPanel(card.getId()); if (cardPanel == null) { //create placeholders for new cards cardPanel = new CardPanel(card); cardPanel.setDisplayEnabled(false); diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CPicture.java b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CPicture.java index 3cb2a0adaa4..cbb8c0cf4c8 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CPicture.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CPicture.java @@ -29,6 +29,7 @@ import forge.item.InventoryItem; import forge.screens.match.views.VPicture; import forge.toolbox.FMouseAdapter; import forge.toolbox.special.CardZoomer; +import forge.view.CardView; import forge.view.FDialog; import javax.swing.*; @@ -57,9 +58,14 @@ public enum CPicture implements ICDoc { private final JLabel flipIndicator = this.view.getLblFlipcard(); private final CardZoomer zoomer = CardZoomer.SINGLETON_INSTANCE; + @Deprecated private Card currentCard = null; + @Deprecated private CardCharacteristicName displayedState = CardCharacteristicName.Original; + private CardView currentView = null; + private boolean isDisplayAlt = false; + private boolean mayShowCurrentCard() { if (currentCard == null) { return false; } if (FDialog.isModalOpen()) { return true; } //allow showing cards while modal open to account for revealing, picking, and ordering cards @@ -70,8 +76,9 @@ public enum CPicture implements ICDoc { * Shows card details and/or picture in sidebar cardview tabber. * */ + @Deprecated public void showCard(Card c, boolean showFlipped) { - if (c == null) { + if (null == c) { return; } @@ -86,6 +93,24 @@ public enum CPicture implements ICDoc { } } + /** + * Shows card details and/or picture in sidebar cardview tabber. + * + */ + public void showCard(final CardView c, boolean showAlt) { + if (null == c) { + return; + } + + currentView = c; + isDisplayAlt = false; + flipIndicator.setVisible(c.hasAltState()); + picturePanel.setCard(c.getState(showAlt), mayShowCurrentCard()); + if (showAlt && c.hasAltState()) { + flipCard(); + } + } + /** * Displays image associated with either a {@code Card} * or {@code InventoryItem} instance. @@ -137,7 +162,7 @@ public enum CPicture implements ICDoc { @Override public void onMiddleMouseDown(MouseEvent e) { if (isCardDisplayed()) { - CardZoomer.SINGLETON_INSTANCE.doMouseButtonZoom(currentCard, displayedState); + CardZoomer.SINGLETON_INSTANCE.doMouseButtonZoom(currentView); } } @@ -162,7 +187,7 @@ public enum CPicture implements ICDoc { public void mouseWheelMoved(MouseWheelEvent arg0) { if (isCardDisplayed()) { if (arg0.getWheelRotation() < 0) { - zoomer.doMouseWheelZoom(currentCard, displayedState); + zoomer.doMouseWheelZoom(currentView); } } } @@ -178,10 +203,9 @@ public enum CPicture implements ICDoc { } public void flipCard() { - if (isCurrentCardFlippable()) { - displayedState = CardDetailUtil.getAlternateState(currentCard, displayedState); - picturePanel.setCardImage(displayedState); - setCardDetailPanel(); + if (currentView.hasAltState()) { + isDisplayAlt = !isDisplayAlt; + picturePanel.setCard(currentView.getState(isDisplayAlt), mayShowCurrentCard()); } } @@ -205,6 +229,7 @@ public enum CPicture implements ICDoc { currentCard.setState(temp); } + @Deprecated private boolean isCurrentCardFlippable() { if (!mayShowCurrentCard()) { return false; } diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CPlayers.java b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CPlayers.java index 219fa300875..28a964f1134 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CPlayers.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CPlayers.java @@ -1,9 +1,9 @@ package forge.screens.match.controllers; import forge.UiCommand; -import forge.game.Game; import forge.gui.framework.ICDoc; import forge.screens.match.views.VPlayers; +import forge.view.IGameView; /** * Controls the combat panel in the match UI. @@ -14,7 +14,7 @@ import forge.screens.match.views.VPlayers; public enum CPlayers implements ICDoc { /** */ SINGLETON_INSTANCE; - private Game game; + private IGameView game; /* (non-Javadoc) * @see forge.gui.framework.ICDoc#getCommandOnSelect() @@ -39,7 +39,7 @@ public enum CPlayers implements ICDoc { VPlayers.SINGLETON_INSTANCE.update(game); } - public void setModel(Game game) { + public void setModel(IGameView game) { this.game = game; } diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CPrompt.java b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CPrompt.java index 8f6546b0c62..285b4fbcd46 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CPrompt.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CPrompt.java @@ -17,8 +17,18 @@ */ package forge.screens.match.controllers; -import forge.UiCommand; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; + +import javax.swing.JButton; + import forge.FThreads; +import forge.Singletons; +import forge.UiCommand; import forge.game.Game; import forge.game.GameRules; import forge.game.Match; @@ -28,11 +38,6 @@ import forge.match.input.InputProxy; import forge.screens.match.views.VPrompt; import forge.toolbox.FSkin; -import javax.swing.*; - -import java.awt.*; -import java.awt.event.*; - /** * Controls the prompt panel in the match UI. * @@ -114,8 +119,9 @@ public enum CPrompt implements ICDoc { * @see java.util.Observer#update(java.util.Observable, java.lang.Object) */ - public void updateText(Game game) { + public void updateText() { FThreads.assertExecutedByEdt(true); + final Game game = Singletons.getControl().getObservedGame(); final Match match = game.getMatch(); final GameRules rules = game.getRules(); final String text = String.format("T:%d G:%d/%d [%s]", game.getPhaseHandler().getTurn(), match.getPlayedGames().size() + 1, rules.getGamesPerMatch(), rules.getGameType()); diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CStack.java b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CStack.java index 5301c40e5c8..2d2c50f0100 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CStack.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CStack.java @@ -1,12 +1,12 @@ package forge.screens.match.controllers; import forge.UiCommand; -import forge.game.player.Player; -import forge.game.zone.MagicStack; import forge.gui.framework.EDocID; import forge.gui.framework.ICDoc; import forge.gui.framework.SDisplayUtil; import forge.screens.match.views.VStack; +import forge.view.IGameView; +import forge.view.PlayerView; /** * Controls the combat panel in the match UI. @@ -18,8 +18,8 @@ public enum CStack implements ICDoc { /** */ SINGLETON_INSTANCE; - private MagicStack model; - private Player localPlayer; + private IGameView model; + private PlayerView localPlayer; /* (non-Javadoc) * @see forge.gui.framework.ICDoc#getCommandOnSelect() @@ -42,8 +42,9 @@ public enum CStack implements ICDoc { VStack.SINGLETON_INSTANCE.updateStack(model, localPlayer); } - public void setModel(MagicStack model0, Player localPlayer0) { - model = model0; - localPlayer = localPlayer0; + public void setModel(final IGameView game0, final PlayerView localPlayer) { + model = game0; + this.localPlayer = localPlayer; } + } diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/menus/GameMenu.java b/forge-gui-desktop/src/main/java/forge/screens/match/menus/GameMenu.java index 709c2ae48b8..859915955ea 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/menus/GameMenu.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/menus/GameMenu.java @@ -198,8 +198,8 @@ public final class GameMenu { return new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - FControl control = Singletons.getControl(); - VAutoYields autoYields = new VAutoYields(control.getObservedGame(), control.getLocalPlayer()); + final FControl control = Singletons.getControl(); + final VAutoYields autoYields = new VAutoYields(control.getGameView(), control.getLocalPlayer()); autoYields.showAutoYields(); } }; diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/views/VAntes.java b/forge-gui-desktop/src/main/java/forge/screens/match/views/VAntes.java index ab810ddccc3..ec18e49738d 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/views/VAntes.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/views/VAntes.java @@ -17,9 +17,15 @@ */ package forge.screens.match.views; -import forge.game.card.Card; -import forge.game.player.Player; -import forge.game.zone.ZoneType; +import java.awt.Dimension; +import java.util.List; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.swing.JPanel; +import javax.swing.SwingConstants; + +import net.miginfocom.swing.MigLayout; import forge.gui.CardPicturePanel; import forge.gui.WrapLayout; import forge.gui.framework.DragCell; @@ -29,13 +35,8 @@ import forge.gui.framework.IVDoc; import forge.screens.match.controllers.CAntes; import forge.toolbox.FLabel; import forge.toolbox.FScrollPane; -import net.miginfocom.swing.MigLayout; - -import javax.swing.*; - -import java.awt.*; -import java.util.SortedSet; -import java.util.TreeSet; +import forge.view.CardView; +import forge.view.PlayerView; /** * Assembles Swing components of card ante area. @@ -54,7 +55,7 @@ public enum VAntes implements IVDoc { private final FScrollPane scroller = new FScrollPane(pnl, false); private final SortedSet allAntes = new TreeSet(); - private Iterable players; + private Iterable players; //========== Constructor private VAntes() { pnl.setLayout(new WrapLayout()); @@ -72,8 +73,8 @@ public enum VAntes implements IVDoc { parentCell.getBody().add(scroller, "w 100%!, h 100%!"); } - public final void setModel(Iterable playerz) { - players = playerz; + public final void setModel(final List players) { + this.players = players; update(); } @@ -121,8 +122,8 @@ public enum VAntes implements IVDoc { allAntes.clear(); pnl.removeAll(); - for(Player p : players) { - for(Card c : p.getZone(ZoneType.Ante)) { + for (final PlayerView p : players) { + for (final CardView c : p.getAnteCards()) { final AntePanel pnlTemp = new AntePanel(c); allAntes.add(pnlTemp); } @@ -136,15 +137,15 @@ public enum VAntes implements IVDoc { //========= Private class handling @SuppressWarnings("serial") private class AntePanel extends JPanel implements Comparable { - private final Card card; + private final CardView card; /** * * @param p0   {@link forge.game.player.Player} - * @param c0   {@link forge.game.card.Card} + * @param c   {@link forge.game.card.Card} */ - public AntePanel(final Card c0) { + public AntePanel(final CardView c) { super(); - card = c0; + card = c; final Dimension d = new Dimension(160, 250); setPreferredSize(d); @@ -157,12 +158,12 @@ public enum VAntes implements IVDoc { .fontAlign(SwingConstants.CENTER).build(), "w 160px, h 20px"); CardPicturePanel picPanel = new CardPicturePanel(); add(picPanel, "w 160px, h 230px"); - picPanel.setCard(c0, true); + picPanel.setCard(c.getState(), true); } @Override - public int compareTo(AntePanel o) { - return o.card.getUniqueNumber() - card.getUniqueNumber(); + public int compareTo(final AntePanel o) { + return o.card.getId() - card.getId(); } } } diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/views/VCommand.java b/forge-gui-desktop/src/main/java/forge/screens/match/views/VCommand.java index c9c19ec9280..85d20e80b02 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/views/VCommand.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/views/VCommand.java @@ -17,8 +17,9 @@ */ package forge.screens.match.views; -import forge.game.player.Player; -import forge.game.zone.ZoneType; +import javax.swing.JPanel; + +import net.miginfocom.swing.MigLayout; import forge.gui.framework.DragCell; import forge.gui.framework.DragTab; import forge.gui.framework.EDocID; @@ -26,10 +27,8 @@ import forge.gui.framework.IVDoc; import forge.screens.match.controllers.CCommand; import forge.toolbox.FScrollPane; import forge.toolbox.FSkin; +import forge.view.PlayerView; import forge.view.arcane.PlayArea; -import net.miginfocom.swing.MigLayout; - -import javax.swing.*; /** * Assembles Swing components of a player command instance. @@ -44,7 +43,7 @@ public class VCommand implements IVDoc { private final DragTab tab = new DragTab("Command"); // Other fields - private Player player = null; + private PlayerView player = null; // Top-level containers private final FScrollPane scroller = new FScrollPane(false); @@ -54,20 +53,20 @@ public class VCommand implements IVDoc { /** * Assembles Swing components of a player command instance. * - * @param player0   {@link forge.game.player.Player} + * @param p   {@link forge.game.player.Player} * @param id0   {@link forge.gui.framework.EDocID} */ - public VCommand(final EDocID id0, final Player player0) { + public VCommand(final EDocID id0, final PlayerView p) { this.docID = id0; id0.setDoc(this); - this.player = player0; - if (player0 != null) { tab.setText(player0.getName() + " Command"); } + this.player = p; + if (p != null) { tab.setText(p.getName() + " Command"); } else { tab.setText("NO PLAYER FOR " + docID.toString()); } // TODO player is hard-coded into tabletop...should be dynamic // (haven't looked into it too deeply). Doublestrike 12-04-12 - tabletop = new PlayArea(scroller, id0 == EDocID.COMMAND_0, player.getZone(ZoneType.Command).getCards(false)); + tabletop = new PlayArea(scroller, id0 == EDocID.COMMAND_0, player.getCommandCards()); control = new CCommand(player, this); @@ -135,7 +134,7 @@ public class VCommand implements IVDoc { * Gets the player currently associated with this command. * @return {@link forge.game.player.Player} */ - public Player getPlayer() { + public PlayerView getPlayer() { return this.player; } diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/views/VDetail.java b/forge-gui-desktop/src/main/java/forge/screens/match/views/VDetail.java index 251b92077ee..e3c31cb2887 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/views/VDetail.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/views/VDetail.java @@ -44,7 +44,7 @@ public enum VDetail implements IVDoc { private final DragTab tab = new DragTab("Card Detail"); // Top-level containers - private final CardDetailPanel pnlDetail = new CardDetailPanel(null); + private final CardDetailPanel pnlDetail = new CardDetailPanel(); private final SkinnedLabel lblFlipcard = new SkinnedLabel(); //========= Constructor diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/views/VField.java b/forge-gui-desktop/src/main/java/forge/screens/match/views/VField.java index b3f969fffd6..47b345f3d5c 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/views/VField.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/views/VField.java @@ -17,9 +17,18 @@ */ package forge.screens.match.views; +import java.awt.Color; +import java.awt.Font; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import javax.swing.border.Border; +import javax.swing.border.LineBorder; + +import net.miginfocom.swing.MigLayout; import forge.LobbyPlayer; -import forge.game.player.Player; -import forge.game.zone.ZoneType; import forge.gui.framework.DragCell; import forge.gui.framework.DragTab; import forge.gui.framework.EDocID; @@ -32,16 +41,8 @@ import forge.toolbox.FSkin; import forge.toolbox.FSkin.SkinnedPanel; import forge.toolbox.special.PhaseIndicator; import forge.toolbox.special.PlayerDetailsPanel; +import forge.view.PlayerView; import forge.view.arcane.PlayArea; -import net.miginfocom.swing.MigLayout; - -import javax.swing.*; -import javax.swing.border.Border; -import javax.swing.border.LineBorder; - -import java.awt.*; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; /** * Assembles Swing components of a player field instance. @@ -56,7 +57,7 @@ public class VField implements IVDoc { private final DragTab tab = new DragTab("Field"); // Other fields - private Player player = null; + private PlayerView player = null; // Top-level containers private final FScrollPane scroller = new FScrollPane(false); @@ -79,22 +80,22 @@ public class VField implements IVDoc { /** * Assembles Swing components of a player field instance. * - * @param playerOnwer   {@link forge.game.player.Player} + * @param p   {@link forge.game.player.Player} * @param id0   {@link forge.gui.framework.EDocID} */ - public VField(final EDocID id0, final Player playerOnwer, LobbyPlayer playerViewer) { + public VField(final EDocID id0, final PlayerView p, final LobbyPlayer playerViewer) { this.docID = id0; id0.setDoc(this); - this.player = playerOnwer; - if (playerOnwer != null) { tab.setText(playerOnwer.getName() + " Field"); } + this.player = p; + if (p != null) { tab.setText(p.getName() + " Field"); } else { tab.setText("NO PLAYER FOR " + docID.toString()); } detailsPanel = new PlayerDetailsPanel(player); // TODO player is hard-coded into tabletop...should be dynamic // (haven't looked into it too deeply). Doublestrike 12-04-12 - tabletop = new PlayArea(scroller, id0 == EDocID.FIELD_1, player.getZone(ZoneType.Battlefield).getCards(false)); + tabletop = new PlayArea(scroller, id0 == EDocID.FIELD_1, player.getBfCards()); control = new CField(player, this, playerViewer); @@ -195,7 +196,7 @@ public class VField implements IVDoc { * Gets the player currently associated with this field. * @return {@link forge.game.player.Player} */ - public Player getPlayer() { + public PlayerView getPlayer() { return this.player; } diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/views/VHand.java b/forge-gui-desktop/src/main/java/forge/screens/match/views/VHand.java index a0a03ca74b2..2ae80cab48d 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/views/VHand.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/views/VHand.java @@ -17,17 +17,17 @@ */ package forge.screens.match.views; -import forge.game.player.Player; +import javax.swing.JPanel; + +import net.miginfocom.swing.MigLayout; import forge.gui.framework.DragCell; import forge.gui.framework.DragTab; import forge.gui.framework.EDocID; import forge.gui.framework.IVDoc; import forge.screens.match.controllers.CHand; import forge.toolbox.FScrollPane; +import forge.view.PlayerView; import forge.view.arcane.HandArea; -import net.miginfocom.swing.MigLayout; - -import javax.swing.*; /** * Assembles Swing components of hand area. @@ -41,7 +41,6 @@ public class VHand implements IVDoc { private final EDocID docID; private final DragTab tab = new DragTab("Your Hand"); - // Top-level containers private final FScrollPane scroller = new FScrollPane(false); private final HandArea hand = new HandArea(scroller); @@ -51,23 +50,23 @@ public class VHand implements IVDoc { * Assembles Swing components of a player hand instance. * * @param id0   {@link forge.gui.framework.EDocID} - * @param owner   {@link forge.game.player.Player} + * @param p   {@link forge.game.player.Player} */ - public VHand(final EDocID id0, final Player owner) { + public VHand(final EDocID id0, final PlayerView p) { docID = id0; id0.setDoc(this); - if (owner == null) { + if (p == null) { tab.setText("NO PLAYER Hand"); } else { - tab.setText(owner.getName() + " Hand"); + tab.setText(p.getName() + " Hand"); } scroller.setViewportView(VHand.this.hand); hand.setOpaque(false); - control = new CHand(owner, this); + control = new CHand(p, this); } //========= Overridden methods diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/views/VPlayers.java b/forge-gui-desktop/src/main/java/forge/screens/match/views/VPlayers.java index 07995c95f1b..e0793518f53 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/views/VPlayers.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/views/VPlayers.java @@ -17,12 +17,17 @@ */ package forge.screens.match.views; -import forge.game.Game; -import forge.game.GameType; -import forge.game.card.Card; -import forge.game.card.CardFactoryUtil; -import forge.game.player.Player; -import forge.game.zone.ZoneType; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import javax.swing.JLabel; +import javax.swing.ScrollPaneConstants; + +import net.miginfocom.swing.MigLayout; + +import org.testng.collections.Maps; + import forge.gui.framework.DragCell; import forge.gui.framework.DragTab; import forge.gui.framework.EDocID; @@ -33,14 +38,9 @@ import forge.screens.match.controllers.CPlayers; import forge.toolbox.FScrollPanel; import forge.toolbox.FSkin; import forge.toolbox.FSkin.SkinnedLabel; -import net.miginfocom.swing.MigLayout; - -import javax.swing.*; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; +import forge.view.CardView; +import forge.view.IGameView; +import forge.view.PlayerView; /** * Assembles Swing components of players report. @@ -59,7 +59,7 @@ public enum VPlayers implements IVDoc { ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); // Other fields - private Map infoLBLs; + private Map infoLBLs; //========= Overridden methods @@ -70,7 +70,7 @@ public enum VPlayers implements IVDoc { public void populate() { scroller.removeAll(); final String constraints = "w 97%!, gapleft 2%, gapbottom 1%"; - for (final Entry p : infoLBLs.entrySet()) { + for (final Entry p : infoLBLs.entrySet()) { for (JLabel label : p.getValue()) { scroller.add(label, constraints); } @@ -79,9 +79,9 @@ public enum VPlayers implements IVDoc { parentCell.getBody().add(scroller, "w 100%, h 100%!"); } - public void init(final Iterable players) { - this.infoLBLs = new HashMap(); - for (final Player p : players) { + public void init(final List players) { + this.infoLBLs = Maps.newHashMap(); + for (final PlayerView p : players) { // Create and store labels detailing various non-critical player info. final InfoLabel name = new InfoLabel(); final InfoLabel life = new InfoLabel(); @@ -142,27 +142,27 @@ public enum VPlayers implements IVDoc { //========== Observer update methods /** @param p0 {@link forge.game.player.Player} */ - public void update(Game game) { + public void update(final IGameView game) { // No need to update if this panel isn't showing if (parentCell == null || !this.equals(parentCell.getSelected())) { return; } - boolean isCommander = game.getRules().hasAppliedVariant(GameType.Commander); + boolean isCommander = game.isCommander(); - for(Entry rr : infoLBLs.entrySet()) { - Player p0 = rr.getKey(); + for(final Entry rr : infoLBLs.entrySet()) { + PlayerView p0 = rr.getKey(); final JLabel[] temp = rr.getValue(); temp[1].setText("Life: " + String.valueOf(p0.getLife()) + " | Poison counters: " + String.valueOf(p0.getPoisonCounters())); temp[2].setText("Maximum hand size: " + String.valueOf(p0.getMaxHandSize())); temp[3].setText("Cards drawn this turn: " + String.valueOf(p0.getNumDrawnThisTurn())); - temp[4].setText("Damage Prevention: " + String.valueOf(p0.getPreventNextDamageTotalShields())); + temp[4].setText("Damage Prevention: " + String.valueOf(p0.getPreventNextDamage())); if (!p0.getKeywords().isEmpty()) { temp[5].setText(p0.getKeywords().toString()); } else { temp[5].setText(""); } if (FModel.getPreferences().getPrefBoolean(FPref.UI_ANTE)) { - List list = p0.getCardsIn(ZoneType.Ante); - StringBuilder sb = new StringBuilder(); + final List list = p0.getAnteCards(); + final StringBuilder sb = new StringBuilder(); sb.append("Ante'd: "); for (int i = 0; i < list.size(); i++) { sb.append(list.get(i)); @@ -173,7 +173,7 @@ public enum VPlayers implements IVDoc { temp[6].setText(sb.toString()); } if (isCommander) { - temp[7].setText(CardFactoryUtil.getCommanderInfo(p0).trim().replace("\r\n", "; ")); + temp[7].setText(p0.getCommanderInfo()); } } } diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/views/VStack.java b/forge-gui-desktop/src/main/java/forge/screens/match/views/VStack.java index e5dc7fb7175..58e16567820 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/views/VStack.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/views/VStack.java @@ -17,16 +17,28 @@ */ package forge.screens.match.views; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; + +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.ScrollPaneConstants; +import javax.swing.SwingUtilities; +import javax.swing.border.EmptyBorder; + +import net.miginfocom.swing.MigLayout; import forge.ImageCache; import forge.Singletons; import forge.card.CardDetailUtil; import forge.card.CardDetailUtil.DetailColors; -import forge.game.card.Card; -import forge.game.player.Player; import forge.game.player.PlayerController; -import forge.game.spellability.SpellAbility; -import forge.game.spellability.SpellAbilityStackInstance; -import forge.game.zone.MagicStack; import forge.gui.framework.DragCell; import forge.gui.framework.DragTab; import forge.gui.framework.EDocID; @@ -39,18 +51,11 @@ import forge.toolbox.FMouseAdapter; import forge.toolbox.FScrollPanel; import forge.toolbox.FSkin; import forge.toolbox.FSkin.SkinnedTextArea; +import forge.view.CardView; +import forge.view.IGameView; +import forge.view.PlayerView; +import forge.view.StackItemView; import forge.view.arcane.CardPanel; -import net.miginfocom.swing.MigLayout; - -import javax.swing.*; -import javax.swing.border.EmptyBorder; - -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.image.BufferedImage; /** * Assembles Swing components of stack report. @@ -129,10 +134,11 @@ public enum VStack implements IVDoc { //========== Observer update methods /** - * @param stack + * @param model * @param viewer */ - public void updateStack(final MagicStack stack, final Player localPlayer) { - tab.setText("Stack : " + stack.size()); + public void updateStack(final IGameView model, final PlayerView localPlayer) { + final java.util.List items = model.getStack(); + tab.setText("Stack : " + items.size()); // No need to update the rest unless it's showing if (!parentCell.getSelected().equals(this)) { return; } @@ -140,15 +146,15 @@ public enum VStack implements IVDoc { scroller.removeAll(); boolean isFirst = true; - for (final SpellAbilityStackInstance spell : stack) { - StackInstanceTextArea tar = new StackInstanceTextArea(stack, spell, localPlayer); + for (final StackItemView item : items) { + final StackInstanceTextArea tar = new StackInstanceTextArea(model, item, localPlayer); scroller.add(tar, "pushx, growx" + (isFirst ? "" : ", gaptop 2px")); //update the Card Picture/Detail when the spell is added to the stack if (isFirst) { isFirst = false; - CMatchUI.SINGLETON_INSTANCE.setCard(spell.getSourceCard()); + CMatchUI.SINGLETON_INSTANCE.setCard(item.getSource()); } } @@ -169,16 +175,14 @@ public enum VStack implements IVDoc { private static final int CARD_WIDTH = 50; private static final int CARD_HEIGHT = Math.round((float)CARD_WIDTH * CardPanel.ASPECT_RATIO); - private final Card sourceCard; + private final CardView sourceCard; - public StackInstanceTextArea(final MagicStack stack, final SpellAbilityStackInstance spell, final Player localPlayer) { - sourceCard = spell.getSourceCard().getCardForUi(); + public StackInstanceTextArea(final IGameView game, final StackItemView item, final PlayerView localPlayer) { + sourceCard = item.getSource(); + + final String txt = (item.isOptionalTrigger() && item.getActivatingPlayer().equals(localPlayer) + ? "(OPTIONAL) " : "") + item.getText(); - String txt = spell.getStackDescription(); - if (spell.getSpellAbility().isOptionalTrigger() - && spell.getSourceCard().getController().equals(localPlayer)) { - txt = "(OPTIONAL) " + txt; - } setText(txt); setToolTipText(txt); setOpaque(true); @@ -193,13 +197,13 @@ public enum VStack implements IVDoc { addMouseListener(new MouseAdapter() { @Override public void mouseEntered(final MouseEvent e) { - if (!spell.getStackDescription().startsWith("Morph ")) { - CMatchUI.SINGLETON_INSTANCE.setCard(spell.getSpellAbility().getHostCard()); + if (!txt.startsWith("Morph ")) { + CMatchUI.SINGLETON_INSTANCE.setCard(item.getSource()); } } }); - if (spell.getSpellAbility().isAbility() && localPlayer != null) { + if (item.isAbility() && localPlayer != null) { addMouseListener(new FMouseAdapter() { @Override public void onLeftClick(MouseEvent e) { @@ -210,13 +214,13 @@ public enum VStack implements IVDoc { onClick(e); } private void onClick(MouseEvent e) { - abilityMenu.setStackInstance(stack, spell.getSpellAbility(), localPlayer); + abilityMenu.setStackInstance(game, item, localPlayer); abilityMenu.show(e.getComponent(), e.getX(), e.getY()); } }); } - DetailColors color = CardDetailUtil.getBorderColor(sourceCard, !spell.getStackDescription().startsWith("Morph ")); + DetailColors color = CardDetailUtil.getBorderColor(item.getSource().getOriginal(), !txt.startsWith("Morph ")); setBackground(new Color(color.r, color.g, color.b)); setForeground(FSkin.getHighContrastColor(getBackground())); } @@ -228,7 +232,7 @@ public enum VStack implements IVDoc { final Graphics2D g2d = (Graphics2D) g; //draw image for source card - BufferedImage img = ImageCache.getImage(sourceCard, CARD_WIDTH, CARD_HEIGHT); + final BufferedImage img = ImageCache.getImage(sourceCard, CARD_WIDTH, CARD_HEIGHT); if (img != null) { g2d.drawImage(img, null, PADDING, PADDING); } @@ -242,8 +246,8 @@ public enum VStack implements IVDoc { private final JCheckBoxMenuItem jmiAutoYield; private final JCheckBoxMenuItem jmiAlwaysYes; private final JCheckBoxMenuItem jmiAlwaysNo; - private MagicStack stack; - private SpellAbility ability; + private IGameView game; + private StackItemView item; private PlayerController controller; private Integer triggerID = 0; @@ -253,10 +257,10 @@ public enum VStack implements IVDoc { jmiAutoYield.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { - final String key = ability.toUnsuppressedString(); + final String key = item.getKey(); final boolean autoYield = controller.shouldAutoYield(key); controller.setShouldAutoYield(key, !autoYield); - if (!autoYield && stack.peekAbility() == ability) { + if (!autoYield && game.peekStack() == item) { //auto-pass priority if ability is on top of stack CPrompt.SINGLETON_INSTANCE.getInputControl().passPriority(); } @@ -273,7 +277,7 @@ public enum VStack implements IVDoc { } else { controller.setShouldAlwaysAcceptTrigger(triggerID); - if (stack.peekAbility() == ability && + if (game.peekStack() == item && Singletons.getControl().getInputQueue().getInput() instanceof InputConfirm) { //auto-yes if ability is on top of stack CPrompt.SINGLETON_INSTANCE.getInputControl().selectButtonOK(); @@ -292,7 +296,7 @@ public enum VStack implements IVDoc { } else { controller.setShouldAlwaysDeclineTrigger(triggerID); - if (stack.peekAbility() == ability && + if (game.peekStack() == item && Singletons.getControl().getInputQueue().getInput() instanceof InputConfirm) { //auto-no if ability is on top of stack CPrompt.SINGLETON_INSTANCE.getInputControl().selectButtonOK(); @@ -303,15 +307,15 @@ public enum VStack implements IVDoc { add(jmiAlwaysNo); } - public void setStackInstance(final MagicStack stack0, final SpellAbility ability0, final Player localPlayer) { - stack = stack0; - ability = ability0; + public void setStackInstance(final IGameView game, final StackItemView item, final PlayerView localPlayer) { + this.game = game; + this.item = item; controller = localPlayer.getController(); - triggerID = ability.getSourceTrigger(); + triggerID = Integer.valueOf(item.getSourceTrigger()); - jmiAutoYield.setSelected(controller.shouldAutoYield(ability.toUnsuppressedString())); + jmiAutoYield.setSelected(controller.shouldAutoYield(item.getKey())); - if (ability.isOptionalTrigger() && ability.getActivatingPlayer() == localPlayer) { + if (item.isOptionalTrigger() && item.getActivatingPlayer().equals(localPlayer)) { jmiAlwaysYes.setSelected(controller.shouldAlwaysAcceptTrigger(triggerID)); jmiAlwaysNo.setSelected(controller.shouldAlwaysDeclineTrigger(triggerID)); jmiAlwaysYes.setVisible(true); diff --git a/forge-gui-desktop/src/main/java/forge/toolbox/imaging/FImageUtil.java b/forge-gui-desktop/src/main/java/forge/toolbox/imaging/FImageUtil.java index 173a9ffbe67..66ab05691b3 100644 --- a/forge-gui-desktop/src/main/java/forge/toolbox/imaging/FImageUtil.java +++ b/forge-gui-desktop/src/main/java/forge/toolbox/imaging/FImageUtil.java @@ -18,6 +18,10 @@ package forge.toolbox.imaging; +import java.awt.Dimension; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; + import forge.ImageCache; import forge.card.CardCharacteristicName; import forge.game.card.Card; @@ -25,10 +29,7 @@ import forge.model.FModel; import forge.properties.ForgePreferences; import forge.toolbox.CardFaceSymbols; import forge.toolbox.FSkin.SkinIcon; - -import java.awt.Dimension; -import java.awt.image.BufferedImage; -import java.awt.image.ColorModel; +import forge.view.CardView.CardStateView; /** * Common image-related routines specific to Forge images. @@ -38,7 +39,8 @@ import java.awt.image.ColorModel; */ public final class FImageUtil { private FImageUtil() {} - + + @Deprecated public static BufferedImage getImage(Card card, CardCharacteristicName state) { BufferedImage image = ImageCache.getOriginalImage(card.getImageKey(state), true); int foilIndex = card.getFoil(); @@ -56,6 +58,7 @@ public final class FImageUtil { * For double-sided cards, returns the front-side image.
* For flip cards, returns the un-flipped image. */ + @Deprecated public static BufferedImage getImage(Card card) { BufferedImage image = ImageCache.getOriginalImage(card.getImageKey(), true); int foilIndex = card.getFoil(); @@ -64,7 +67,24 @@ public final class FImageUtil { } return image; } - + + /** + * Gets the image associated with a card. + *

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

+ * For double-sided cards, returns the front-side image.
+ * For flip cards, returns the un-flipped image. + */ + public static BufferedImage getImage(final CardStateView card) { + BufferedImage image = ImageCache.getOriginalImage(card.getImageKey(), true); + final int foilIndex = card.getCard().getFoilIndex(); + if (image != null && foilIndex > 0) { + image = getImageWithFoilEffect(image, foilIndex); + } + return image; + } + /** * Applies a foil effect to a card image. */ diff --git a/forge-gui-desktop/src/main/java/forge/toolbox/special/CardViewer.java b/forge-gui-desktop/src/main/java/forge/toolbox/special/CardViewer.java index 7c28c99bdd5..80f03156d2e 100644 --- a/forge-gui-desktop/src/main/java/forge/toolbox/special/CardViewer.java +++ b/forge-gui-desktop/src/main/java/forge/toolbox/special/CardViewer.java @@ -56,7 +56,7 @@ public class CardViewer extends JPanel { public CardViewer(final List list) { this.list = Collections.unmodifiableList(list); this.jList = new JList(new ChooserListModel()); - this.detail = new CardDetailPanel(null); + this.detail = new CardDetailPanel(); this.picture = new CardPicturePanel(); this.add(new FScrollPane(this.jList, true)); diff --git a/forge-gui-desktop/src/main/java/forge/toolbox/special/CardZoomer.java b/forge-gui-desktop/src/main/java/forge/toolbox/special/CardZoomer.java index 5349bb86b05..3c3b76bef55 100644 --- a/forge-gui-desktop/src/main/java/forge/toolbox/special/CardZoomer.java +++ b/forge-gui-desktop/src/main/java/forge/toolbox/special/CardZoomer.java @@ -18,23 +18,29 @@ package forge.toolbox.special; -import forge.Singletons; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; + +import javax.swing.JPanel; +import javax.swing.Timer; + +import net.miginfocom.swing.MigLayout; import forge.assets.FSkinProp; -import forge.card.CardCharacteristicName; -import forge.card.CardDetailUtil; -import forge.game.card.Card; import forge.gui.SOverlayUtils; import forge.toolbox.FOverlay; import forge.toolbox.FSkin; import forge.toolbox.FSkin.SkinnedLabel; import forge.toolbox.imaging.FImagePanel; -import forge.toolbox.imaging.FImageUtil; import forge.toolbox.imaging.FImagePanel.AutoSizeImageMode; -import net.miginfocom.swing.MigLayout; - -import javax.swing.*; - -import java.awt.event.*; +import forge.toolbox.imaging.FImageUtil; +import forge.view.CardView; +import forge.view.CardView.CardStateView; /** * Displays card image at its original size and correct orientation. @@ -46,30 +52,28 @@ import java.awt.event.*; * */ public enum CardZoomer { - SINGLETON_INSTANCE; + SINGLETON_INSTANCE; // Gui controls private final JPanel overlay = FOverlay.SINGLETON_INSTANCE.getPanel(); private JPanel pnlMain; private FImagePanel imagePanel; private SkinnedLabel lblFlipcard = new SkinnedLabel(); - + // Details about the current card being displayed. - private Card thisCard; - private CardCharacteristicName cardState = CardCharacteristicName.Original; - private boolean isImageFlipped = false; - private boolean isFaceDownCard = false; - + private CardView thisCard; + private boolean isInAltState; + // The zoomer is in button mode when it is activated by holding down the // middle mouse button or left and right mouse buttons simultaneously. private boolean isButtonMode = false; private boolean isOpen = false; private long lastClosedTime; - + // Used to ignore mouse wheel rotation for a short period of time. private Timer mouseWheelCoolDownTimer; private boolean isMouseWheelEnabled = false; - + // ctr private CardZoomer() { lblFlipcard.setIcon(FSkin.getIcon(FSkinProp.ICO_FLIPCARD)); @@ -77,7 +81,7 @@ public enum CardZoomer { setMouseWheelListener(); setKeyListeners(); } - + /** * Creates listener for keys that are recognised by zoomer. *

    @@ -103,30 +107,33 @@ public enum CardZoomer { /** * Creates listener for mouse button events. *

    - * NOTE: Needed even if ButtonMode to prevent Zoom getting stuck open on certain systems. + * NOTE: Needed even if ButtonMode to prevent Zoom getting stuck open on + * certain systems. */ private void setMouseButtonListener() { - overlay.addMouseListener(new MouseAdapter() { + overlay.addMouseListener(new MouseAdapter() { @Override public void mouseReleased(MouseEvent e) { closeZoomer(); } }); } - + /** * Creates listener for mouse wheel events. *

    - * If the zoomer is opened using the mouse wheel then additional - * actions can be performed dependent on the card type - - *

      + * If the zoomer is opened using the mouse wheel then additional actions can + * be performed dependent on the card type - + *

      + *

        *
      • If mouse wheel is rotated back then close zoomer. - *
      • If mouse wheel is rotated forward and...
          - *
        • if image is a flip card then rotate 180 degrees. - *
        • if image is a double-sided card then show other side. + *
        • If mouse wheel is rotated forward and... + *
            + *
          • if image is a flip card then rotate 180 degrees. + *
          • if image is a double-sided card then show other side. */ private void setMouseWheelListener() { - overlay.addMouseWheelListener(new MouseWheelListener() { + overlay.addMouseWheelListener(new MouseWheelListener() { @Override public void mouseWheelMoved(MouseWheelEvent e) { if (!isButtonMode) { @@ -136,111 +143,86 @@ public enum CardZoomer { closeZoomer(); } else { toggleCardImage(); - startMouseWheelCoolDownTimer(250); - } - } + startMouseWheelCoolDownTimer(250); + } + } } - } + } }); } - + /** * Opens zoomer in mouse wheel mode and displays the image associated with - * the given card based on its current {@code CardCharacteristicName} state. + * the given card based. *

            - * This method should be called if the zoomer is activated by rotating the mouse wheel. + * This method should be called if the zoomer is activated by rotating the + * mouse wheel. */ - public void doMouseWheelZoom(Card newCard) { - doMouseWheelZoom(newCard, newCard.getCurState()); - } - - /** - * Opens zoomer in mouse wheel mode and displays the image associated with - * the given card based on the specified {@code CardCharacteristicName} state. - *

            - * This method should be called if the zoomer is activated by rotating the mouse wheel. - */ - public void doMouseWheelZoom(Card newCard, CardCharacteristicName state) { + public void doMouseWheelZoom(final CardView card) { isButtonMode = false; - isFaceDownCard = (state == CardCharacteristicName.FaceDown); - cardState = state; - displayCard(newCard); - startMouseWheelCoolDownTimer(200); + displayCard(card); + startMouseWheelCoolDownTimer(200); } /** * Opens zoomer in mouse button mode and displays the image associated with - * the given card based on its current {@code CardCharacteristicName} state. - *

            - * This method should be called if the zoomer is activated by holding down - * the middle mouse button or left and right mouse buttons simultaneously. - */ - public void doMouseButtonZoom(Card newCard) { - doMouseButtonZoom(newCard, newCard.getCurState()); - } - - /** - * Opens zoomer in mouse button mode and displays the image associated with - * the given card based on the specified {@code CardCharacteristicName} state. + * the given card. *

            * This method should be called if the zoomer is activated by holding down * the middle mouse button or left and right mouse buttons simultaneously. */ - public void doMouseButtonZoom(Card newCard, CardCharacteristicName state) { - + public void doMouseButtonZoom(final CardView newCard) { + // don't display zoom if already zoomed or just closed zoom // (handles mouse wheeling while middle clicking) if (isOpen || System.currentTimeMillis() - lastClosedTime < 250) { return; - } - + } + isButtonMode = true; - isFaceDownCard = (state == CardCharacteristicName.FaceDown); - cardState = state; displayCard(newCard); } - + public boolean isZoomerOpen() { return isOpen; } - - private void displayCard(Card card) { + + private void displayCard(final CardView newCard) { isMouseWheelEnabled = false; - isImageFlipped = false; - thisCard = card.getCardForUi(); + thisCard = newCard; + isInAltState = false; setLayout(); setImage(); SOverlayUtils.showOverlay(); isOpen = true; } - + /** * Displays a graphical indicator that shows whether the current card can be flipped or transformed. */ private void setFlipIndicator() { - boolean isFaceDownFlippable = (isFaceDownCard && Singletons.getControl().mayShowCard(thisCard)); - if (thisCard.isFlipCard() || thisCard.isDoubleFaced() || isFaceDownFlippable ) { + if (thisCard.hasAltState()) { imagePanel.setLayout(new MigLayout("insets 0, w 100%!, h 100%!")); imagePanel.add(lblFlipcard, "pos (100% - 100px) 0"); - } + } } - + /** * Needs to be called whenever the source image changes. */ private void setImage() { imagePanel = new FImagePanel(); - imagePanel.setImage(FImageUtil.getImage(thisCard, cardState), getInitialRotation(), AutoSizeImageMode.SOURCE); + imagePanel.setImage(FImageUtil.getImage(getState()), getInitialRotation(), AutoSizeImageMode.SOURCE); pnlMain.removeAll(); pnlMain.add(imagePanel, "w 80%!, h 80%!"); pnlMain.validate(); setFlipIndicator(); } - + private int getInitialRotation() { - return (thisCard.isSplitCard() || thisCard.isPlane() || thisCard.isPhenomenon() ? 90 : 0); + return (thisCard.isSplitCard() || getState().isPlane() || getState().isPhenomenon() ? 90 : 0); } - + private void setLayout() { overlay.removeAll(); pnlMain = new JPanel(); @@ -283,53 +265,35 @@ public enum CardZoomer { }); } } - + private void stopMouseWheelCoolDownTimer() { if (mouseWheelCoolDownTimer != null && mouseWheelCoolDownTimer.isRunning()) { mouseWheelCoolDownTimer.stop(); } } - + /** * Toggles between primary and alternate image associated with card if applicable. */ private void toggleCardImage() { - if (thisCard.isFlipCard()) { + if (thisCard.hasAltState()) { toggleFlipCard(); - } else if (thisCard.isDoubleFaced()) { - toggleDoubleFacedCard(); - } else if (isFaceDownCard) { - toggleFaceDownCard(); } } - + /** * Flips image by rotating 180 degrees each time. *

            * No need to get the alternate card image from cache. * Can simply rotate current card image in situ to get same effect. */ - private void toggleFlipCard() { - isImageFlipped = !isImageFlipped; - imagePanel.setRotation(isImageFlipped ? 180 : 0); - } - - /** - * Toggles between the front and back image of a card that can be - * played face-down (eg. morph). - *

            - * Uses constraint that prevents a player from identifying opponent's face-down cards. - */ - private void toggleFaceDownCard() { - cardState = CardDetailUtil.getAlternateState(thisCard, cardState); + private void toggleFlipCard() { + isInAltState = !isInAltState; + imagePanel.setRotation(thisCard.isFlipCard() && isInAltState ? 180 : 0); setImage(); } - - /** - * Toggles between the front and back image of a double-sided card. - */ - private void toggleDoubleFacedCard() { - cardState = CardDetailUtil.getAlternateState(thisCard, cardState); - setImage(); + + private CardStateView getState() { + return thisCard.getState(isButtonMode); } } diff --git a/forge-gui-desktop/src/main/java/forge/toolbox/special/PlayerDetailsPanel.java b/forge-gui-desktop/src/main/java/forge/toolbox/special/PlayerDetailsPanel.java index ea227ed5b8b..c71df8d12bc 100644 --- a/forge-gui-desktop/src/main/java/forge/toolbox/special/PlayerDetailsPanel.java +++ b/forge-gui-desktop/src/main/java/forge/toolbox/special/PlayerDetailsPanel.java @@ -1,35 +1,36 @@ package forge.toolbox.special; +import java.awt.Color; +import java.awt.Font; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.JPanel; +import javax.swing.SwingConstants; + +import net.miginfocom.swing.MigLayout; + +import org.apache.commons.lang3.tuple.Pair; + import com.google.common.base.Function; import forge.assets.FSkinProp; import forge.card.MagicColor; -import forge.game.mana.ManaPool; -import forge.game.player.Player; -import forge.game.zone.ZoneType; import forge.gui.ForgeAction; import forge.properties.ForgePreferences; import forge.screens.match.controllers.CPlayers; import forge.toolbox.FLabel; import forge.toolbox.FSkin; import forge.toolbox.FSkin.SkinnedPanel; -import net.miginfocom.swing.MigLayout; - -import org.apache.commons.lang3.tuple.Pair; - -import javax.swing.*; - -import java.awt.*; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.ArrayList; -import java.util.List; +import forge.view.PlayerView; public class PlayerDetailsPanel extends JPanel { private static final long serialVersionUID = 8444559244193214459L; - private Player player; + private PlayerView player; // Info labels private FLabel lblHand = getBuiltFLabel(FSkinProp.IMG_ZONE_HAND, "99", "Cards in hand"); @@ -47,8 +48,7 @@ public class PlayerDetailsPanel extends JPanel { .text(s0).tooltip(s1).fontAlign(SwingConstants.RIGHT).build(); } - public PlayerDetailsPanel(Player player) { - + public PlayerDetailsPanel(final PlayerView player) { this.player = player; manaLabels.add(Pair.of(getBuiltFLabel(FSkinProp.IMG_MANA_B, "99", "Black mana"), MagicColor.BLACK)); @@ -121,14 +121,14 @@ public class PlayerDetailsPanel extends JPanel { * @param p0   {@link forge.game.player.Player} */ public void updateZones() { - this.getLblHand().setText("" + player.getZone(ZoneType.Hand).size()); - final String handMaxToolTip = player.isUnlimitedHandSize() + this.getLblHand().setText("" + player.getHandCards().size()); + final String handMaxToolTip = player.hasUnlimitedHandSize() ? "no maximum hand size" : String.valueOf(player.getMaxHandSize()); - this.getLblHand().setToolTipText("Cards in hand (max: " + handMaxToolTip + ")"); - this.getLblGraveyard().setText("" + player.getZone(ZoneType.Graveyard).size()); - this.getLblLibrary().setText("" + player.getZone(ZoneType.Library).size()); - this.getLblFlashback().setText("" + player.getCardsActivableInExternalZones(true).size()); - this.getLblExile().setText("" + player.getZone(ZoneType.Exile).size()); + this.getLblHand().setToolTipText("Cards in hand (max: " + handMaxToolTip + ")"); + this.getLblGraveyard().setText("" + player.getGraveCards().size()); + this.getLblLibrary().setText("" + player.getLibraryCards().size()); + this.getLblFlashback().setText("" + player.getFlashbackCards().size()); + this.getLblExile().setText("" + player.getExileCards().size()); } @@ -158,9 +158,8 @@ public class PlayerDetailsPanel extends JPanel { * @param p0   {@link forge.game.player.Player} */ public void updateManaPool() { - ManaPool m = player.getManaPool(); - for(Pair label : manaLabels) - label.getKey().setText(Integer.toString(m.getAmountOfColor(label.getRight()))); + for (final Pair label : manaLabels) + label.getKey().setText(Integer.toString(player.getMana(label.getRight()))); } public FLabel getLblHand() { diff --git a/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanel.java b/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanel.java index dc3286eface..6c58853acc0 100644 --- a/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanel.java +++ b/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanel.java @@ -17,31 +17,38 @@ */ package forge.view.arcane; -import forge.ImageCache; -import forge.Singletons; -import forge.card.CardCharacteristicName; -import forge.card.CardEdition; -import forge.card.mana.ManaCost; -import forge.game.card.Card; -import forge.game.combat.Combat; -import forge.gui.CardContainer; -import forge.model.FModel; -import forge.properties.ForgePreferences.FPref; -import forge.screens.match.CMatchUI; -import forge.toolbox.CardFaceSymbols; -import forge.toolbox.IDisposable; -import forge.toolbox.FSkin.SkinnedPanel; -import forge.view.arcane.util.OutlinedLabel; - -import javax.swing.*; - -import java.awt.*; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.RenderingHints; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.List; +import javax.swing.JRootPane; +import javax.swing.SwingUtilities; + +import forge.ImageCache; +import forge.Singletons; +import forge.card.CardEdition; +import forge.card.mana.ManaCost; +import forge.gui.CardContainer; +import forge.model.FModel; +import forge.properties.ForgePreferences.FPref; +import forge.screens.match.CMatchUI; +import forge.toolbox.CardFaceSymbols; +import forge.toolbox.FSkin.SkinnedPanel; +import forge.toolbox.IDisposable; +import forge.view.CardView; +import forge.view.CardView.CardStateView; +import forge.view.arcane.util.OutlinedLabel; + /** *

            * CardPanel class. @@ -85,7 +92,7 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl */ private static final float ROT_CENTER_TO_BOTTOM_CORNER = 0.7071067811865475244008443621048f; - private Card card; + private CardView card; private CardPanel attachedToPanel; private List attachedPanels = new ArrayList(); private boolean tapped; @@ -110,7 +117,7 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl * @param newCard * a {@link forge.game.card.Card} object. */ - public CardPanel(final Card card0) { + public CardPanel(final CardView card0) { this.card = card0; this.setBackground(Color.black); @@ -321,8 +328,8 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl // White border if card is known to have it. if (this.getCard() != null && Singletons.getControl().mayShowCard(this.getCard()) && !this.getCard().isFaceDown()) { - CardEdition ed = FModel.getMagicDb().getEditions().get(this.getCard().getCurSetCode()); - if (ed != null && ed.isWhiteBorder() && this.getCard().getFoil() == 0) { + CardEdition ed = FModel.getMagicDb().getEditions().get(this.getCard().getSetCode()); + if (ed != null && ed.isWhiteBorder() && this.getCard().getFoilIndex() == 0) { g2d.setColor(Color.white); int ins = 1; g2d.fillRoundRect(this.cardXOffset + ins, this.cardYOffset + ins, this.cardWidth - ins*2, this.cardHeight - ins*2, cornerSize-ins, cornerSize-ins); @@ -351,12 +358,12 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl } if (showCardManaCostOverlay() && this.cardWidth < 200) { - boolean showSplitMana = card.isSplitCard() && card.getCurState() == CardCharacteristicName.Original; + final boolean showSplitMana = card.isSplitCard(); if (!showSplitMana) { - drawManaCost(g, card.getManaCost(), 0); + drawManaCost(g, card.getState().getManaCost(), 0); } else { - drawManaCost(g, card.getRules().getMainPart().getManaCost(), +12); - drawManaCost(g, card.getRules().getOtherPart().getManaCost(), -12); + drawManaCost(g, card.getOriginal().getManaCost(), +12); + drawManaCost(g, card.getAlternate().getManaCost(), -12); } } @@ -382,17 +389,14 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl final int stateXSymbols = (this.cardXOffset + (this.cardWidth / 2)) - 16; final int ySymbols = (this.cardYOffset + this.cardHeight) - (this.cardHeight / 8) - 16; - Combat combat = card.getGame().getCombat(); - if (combat != null) { - if (combat.isAttacking(card)) { - CardFaceSymbols.drawSymbol("attack", g, combatXSymbols, ySymbols); - } - if (combat.isBlocking(card)) { - CardFaceSymbols.drawSymbol("defend", g, combatXSymbols, ySymbols); - } + if (card.isAttacking()) { + CardFaceSymbols.drawSymbol("attack", g, combatXSymbols, ySymbols); + } + if (card.isBlocking()) { + CardFaceSymbols.drawSymbol("defend", g, combatXSymbols, ySymbols); } - if (card.isSick() && card.isInPlay()) { + if (card.isSick()) { CardFaceSymbols.drawSymbol("summonsick", g, stateXSymbols, ySymbols); } @@ -409,9 +413,9 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl this.cardWidth, this.cardHeight, Math.round(this.cardWidth * BLACK_BORDER_SIZE)); } - public static void drawFoilEffect(Graphics g, Card card, int x, int y, int width, int height, int borderSize) { + public static void drawFoilEffect(final Graphics g, final CardView card2, final int x, final int y, final int width, final int height, final int borderSize) { if (isPreferenceEnabled(FPref.UI_OVERLAY_FOIL_EFFECT)) { - int foil = card.getFoil(); + int foil = card2.getFoilIndex(); if (foil > 0) { CardFaceSymbols.drawOther(g, String.format("foil%02d", foil), x + borderSize, y + borderSize, width - 2 * borderSize, height - 2 * borderSize); @@ -479,7 +483,7 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl @Override public final String toString() { - return this.getCard().getName(); + return this.getCard().toString(); } /** @@ -610,27 +614,28 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl this.titleText.setText(""); } else { - this.titleText.setText(card.getName()); + this.titleText.setText(card.getState().getName()); } int damage = card.getDamage(); this.damageText.setText(damage > 0 ? "\u00BB " + String.valueOf(damage) + " \u00AB" : ""); // Card Id overlay - this.cardIdText.setText(Integer.toString(card.getUniqueNumber())); + this.cardIdText.setText(Integer.toString(card.getId())); } public final void updatePTOverlay() { // P/T overlay + final CardStateView state = card.getState(); String sPt = ""; - if (card.isCreature() && card.isPlaneswalker()) { - sPt = String.format("%d/%d (%d)", card.getNetAttack(), card.getNetDefense(), card.getCurrentLoyalty()); + if (state.isCreature() && state.isPlaneswalker()) { + sPt = String.format("%d/%d (%d)", state.getPower(), state.getToughness(), state.getLoyalty()); } - else if (card.isCreature()) { - sPt = String.format("%d/%d", card.getNetAttack(), card.getNetDefense()); + else if (state.isCreature()) { + sPt = String.format("%d/%d", state.getPower(), state.getToughness()); } - else if (card.isPlaneswalker()) { - sPt = String.valueOf(card.getCurrentLoyalty()); + else if (state.isPlaneswalker()) { + sPt = String.valueOf(state.getLoyalty()); } this.ptText.setText(sPt); } @@ -641,28 +646,28 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl * @return the card */ @Override - public final Card getCard() { + public final CardView getCard() { return this.card; } /** {@inheritDoc} */ @Override - public final void setCard(final Card card) { - if ((this.getCard() != null) && this.getCard().equals(card) && this.isAnimationPanel + public final void setCard(final CardView cardView) { + if ((this.getCard() != null) && this.getCard().equals(cardView) && this.isAnimationPanel && this.imagePanel.hasImage()) { return; } - if (this.card != card) { + if (this.card != cardView) { this.updatePTOverlay(); //update PT Overlay if card changes } - this.card = card; + this.card = cardView; if (!this.isShowing()) { return; } - final BufferedImage image = card == null ? null : ImageCache.getImage(card, imagePanel.getWidth(), imagePanel.getHeight()); + final BufferedImage image = cardView == null ? null : ImageCache.getImage(cardView, imagePanel.getWidth(), imagePanel.getHeight()); this.updateText(); this.setImage(image); diff --git a/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanelContainer.java b/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanelContainer.java index fbe9c44eaae..599cbd42419 100644 --- a/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanelContainer.java +++ b/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanelContainer.java @@ -17,21 +17,26 @@ */ package forge.view.arcane; +import java.awt.Dimension; +import java.awt.Rectangle; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionListener; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.SwingUtilities; + import forge.FThreads; -import forge.game.card.Card; import forge.screens.match.CMatchUI; import forge.toolbox.FScrollPane; import forge.toolbox.FSkin.SkinnedPanel; import forge.toolbox.special.CardZoomer; +import forge.view.CardView; import forge.view.arcane.util.CardPanelMouseListener; -import javax.swing.*; - -import java.awt.*; -import java.awt.event.*; -import java.util.ArrayList; -import java.util.List; - /** * Manages mouse events and common functionality for CardPanel containing * components. @@ -278,6 +283,29 @@ public abstract class CardPanelContainer extends SkinnedPanel { protected abstract CardPanel getCardPanel(int x, int y); /** +<<<<<<< .mine + * Must call from the Swing event thread. + * + * @param card + * a {@link forge.game.card.Card} object. + * @return a {@link forge.view.arcane.CardPanel} object. + */ + public CardPanel addCard(final CardView card) { + final CardPanel placeholder = new CardPanel(card); + placeholder.setDisplayEnabled(false); + this.getCardPanels().add(placeholder); + this.add(placeholder); + this.doLayout(); + // int y = Math.min(placeholder.getHeight(), + // scrollPane.getVisibleRect().height); + this.scrollRectToVisible(new Rectangle(placeholder.getCardX(), placeholder.getCardY(), placeholder + .getCardWidth(), placeholder.getCardHeight())); + return placeholder; + } + + /** +======= +>>>>>>> .r27195 *

            * getCardPanel. *

            @@ -288,7 +316,7 @@ public abstract class CardPanelContainer extends SkinnedPanel { */ public final CardPanel getCardPanel(final int gameCardID) { for (final CardPanel panel : this.getCardPanels()) { - if (panel.getCard().getUniqueNumber() == gameCardID) { + if (panel.getCard().getId() == gameCardID) { return panel; } } @@ -584,7 +612,7 @@ public abstract class CardPanelContainer extends SkinnedPanel { * * @return a {@link forge.game.card.Card} object. */ - public final Card getHoveredCard(MouseEvent e) { + public final CardView getHoveredCard(final MouseEvent e) { // re-evaluate cursor position so if we hovered over a card, alt-tabbed out of the application, then // clicked back on the application somewhere else, the last hovered card won't register the click // this cannot protect against alt tabbing off then re-focusing on the application by clicking on diff --git a/forge-gui-desktop/src/main/java/forge/view/arcane/PlayArea.java b/forge-gui-desktop/src/main/java/forge/view/arcane/PlayArea.java index b07d117f698..775d1708769 100644 --- a/forge-gui-desktop/src/main/java/forge/view/arcane/PlayArea.java +++ b/forge-gui-desktop/src/main/java/forge/view/arcane/PlayArea.java @@ -17,20 +17,26 @@ */ package forge.view.arcane; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Rectangle; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import com.google.common.collect.Lists; + import forge.FThreads; -import forge.game.card.Card; import forge.screens.match.CMatchUI; import forge.screens.match.controllers.CPrompt; import forge.toolbox.FScrollPane; import forge.toolbox.MouseTriggerEvent; +import forge.view.CardView; +import forge.view.CardView.CardStateView; import forge.view.arcane.util.Animation; import forge.view.arcane.util.CardPanelMouseListener; -import java.awt.*; -import java.awt.event.MouseEvent; -import java.util.*; -import java.util.List; - /** *

            * PlayArea class. @@ -69,8 +75,8 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen private int extraCardSpacingX, cardSpacingX, cardSpacingY; private int stackSpacingX, stackSpacingY; - private List model; - + private final List model; + /** *

            * Constructor for PlayArea. @@ -78,13 +84,13 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen * * @param scrollPane * @param mirror - * @param modelRef + * @param list */ - public PlayArea(final FScrollPane scrollPane, final boolean mirror, List modelRef) { + public PlayArea(final FScrollPane scrollPane, final boolean mirror, final List list) { super(scrollPane); this.setBackground(Color.white); this.mirror = mirror; - this.model = modelRef; + this.model = list; } private final CardStackRow collectAllLands() { @@ -93,7 +99,10 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen outerLoop: // for (final CardPanel panel : this.getCardPanels()) { - if (!panel.getCard().isLand() || panel.getCard().isCreature()) { + final CardView card = panel.getCard(); + final CardStateView state = card.getState(); + + if (!state.isLand() || state.isCreature()) { continue; } @@ -103,7 +112,7 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen for (int i = 0, n = allLands.size(); i < n; i++) { final CardStack stack = allLands.get(i); final CardPanel firstPanel = stack.get(0); - if (firstPanel.getCard().getName().equals(panel.getCard().getName())) { + if (firstPanel.getCard().getState().getName().equals(state.getName())) { if (!firstPanel.getAttachedPanels().isEmpty() || firstPanel.getCard().isEnchanted()) { // Put this land to the left of lands with the same name // and attachments. @@ -139,7 +148,10 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen outerLoop: // for (final CardPanel panel : this.getCardPanels()) { - if (!panel.getCard().isToken()) { + final CardView card = panel.getCard(); + final CardStateView state = card.getState(); + + if (!card.isToken()) { continue; } @@ -149,7 +161,10 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen for (int i = 0, n = allTokens.size(); i < n; i++) { final CardStack stack = allTokens.get(i); final CardPanel firstPanel = stack.get(0); - if (firstPanel.getCard().getName().equals(panel.getCard().getName())) { + final CardView firstCard = firstPanel.getCard(); + final CardStateView firstState = firstCard.getState(); + + if (firstPanel.getCard().getState().getName().equals(state.getName())) { if (!firstPanel.getAttachedPanels().isEmpty()) { // Put this token to the left of tokens with the same // name and attachments. @@ -157,15 +172,15 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen break; } - Set keywords = new HashSet<>(panel.getCard().getIntrinsicKeyword()); - Set firstKeywords = new HashSet<>(firstPanel.getCard().getIntrinsicKeyword()); - + final String text = state.getText(); + final String firstText = firstState.getText(); + if (!panel.getAttachedPanels().isEmpty() - || !panel.getCard().getCounters().equals(firstPanel.getCard().getCounters()) - || (panel.getCard().isSick() != firstPanel.getCard().isSick()) - || (panel.getCard().getNetAttack() != firstPanel.getCard().getNetAttack()) - || (panel.getCard().getNetDefense() != firstPanel.getCard().getNetDefense()) - || !(keywords.equals(firstKeywords)) + || !card.getCounters().equals(firstPanel.getCard().getCounters()) + || (card.isSick() != firstCard.isSick()) + || (state.getPower() != firstState.getPower()) + || (state.getToughness() != firstState.getToughness()) + || !(text.equals(firstText)) || (stack.size() == tokenStackMax)) { // If this token has attachments or the stack is full, // put it to the right. @@ -241,6 +256,15 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen }*/ @Override + public final CardPanel addCard(final CardView card) { + final CardPanel placeholder = new CardPanel(card); + placeholder.setDisplayEnabled(false); + this.getCardPanels().add(placeholder); + this.add(placeholder); + return placeholder; + } + + @Override public final void doLayout() { final Rectangle rect = this.getScrollPane().getVisibleRect(); @@ -323,7 +347,7 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen for (int stackIndex = 0, stackCount = row.size(); stackIndex < stackCount; stackIndex++) { final CardStack stack = row.get(stackIndex); // Align others to the right. - if (RowType.Other.isGoodFor(stack.get(0).getCard())) { + if (RowType.Other.isGoodFor(stack.get(0).getCard().getState())) { x = (this.playAreaWidth - PlayArea.GUTTER_X) + this.extraCardSpacingX; for (int i = stackIndex, n = row.size(); i < n; i++) { CardStack r = row.get(i); @@ -570,20 +594,19 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen recalculateCardPanels(model); } - private void recalculateCardPanels(final List model) { - List oldCards, toDelete; - oldCards = new ArrayList(); + private void recalculateCardPanels(final List model) { + final List oldCards = Lists.newArrayList(); for (final CardPanel cpa : getCardPanels()) { oldCards.add(cpa.getCard()); } - toDelete = new ArrayList(oldCards); - List toReplace = new ArrayList(); - + final List toDelete = Lists.newArrayList(oldCards); + final List toReplace = Lists.newArrayList(); + // delete all cards that differ in timestamp (they have been blinked) - for (final Card c : model) { + for (final CardView c : model) { for (int i = 0; i < toDelete.size(); i++) { - final Card c2 = toDelete.get(i); - if (c.equals(c2)) { + final CardView c2 = toDelete.get(i); + if (c.getId() == c2.getId()) { if (c.getTimestamp() == c2.getTimestamp()) { toDelete.remove(i); } else { @@ -595,17 +618,17 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen if (toDelete.size() == getCardPanels().size()) { clear(); } else { - for (final Card card : toDelete) { - removeCardPanel(getCardPanel(card.getUniqueNumber())); + for (final CardView card : toDelete) { + removeCardPanel(getCardPanel(card.getId())); } } - List toAdd = new ArrayList(model); + List toAdd = new ArrayList(model); toAdd.removeAll(oldCards); toAdd.addAll(toReplace); List newPanels = new ArrayList(); - for (final Card card : toAdd) { + for (final CardView card : toAdd) { if (card.getCardForUi() == card) { //only include cards that are meant for display final CardPanel placeholder = new CardPanel(card); placeholder.setDisplayEnabled(false); @@ -624,15 +647,15 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen } } - for (final Card card : model) { + for (final CardView card : model) { updateCard(card, true); } invalidate(); repaint(); } - public void updateCard(final Card card, boolean fromRefresh) { - final CardPanel toPanel = getCardPanel(card.getUniqueNumber()); + public void updateCard(final CardView card, boolean fromRefresh) { + final CardPanel toPanel = getCardPanel(card.getId()); if (null == toPanel) { return; } if (card.isTapped()) { @@ -643,42 +666,37 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen toPanel.setTappedAngle(0); } toPanel.getAttachedPanels().clear(); - if (card.isEnchanted()) { - final ArrayList enchants = card.getEnchantedBy(); - for (final Card e : enchants) { - final forge.view.arcane.CardPanel cardE = getCardPanel(e.getUniqueNumber()); - if (cardE != null) { - toPanel.getAttachedPanels().add(cardE); - } - } - } - - if (card.isEquipped()) { - final ArrayList enchants = card.getEquippedBy(); - for (final Card e : enchants) { - final forge.view.arcane.CardPanel cardE = getCardPanel(e.getUniqueNumber()); - if (cardE != null) { - toPanel.getAttachedPanels().add(cardE); - } + + final Iterable enchants = card.getEnchantedBy(); + for (final CardView e : enchants) { + final CardPanel cardE = getCardPanel(e.getId()); + if (cardE != null) { + toPanel.getAttachedPanels().add(cardE); } } - if (card.isFortified()) { - final ArrayList fortifications = card.getFortifiedBy(); - for (final Card e : fortifications) { - final forge.view.arcane.CardPanel cardE = getCardPanel(e.getUniqueNumber()); - if (cardE != null) { - toPanel.getAttachedPanels().add(cardE); - } + final Iterable equips = card.getEquippedBy(); + for (final CardView e : equips) { + final CardPanel cardE = getCardPanel(e.getId()); + if (cardE != null) { + toPanel.getAttachedPanels().add(cardE); } } - if (card.isEnchantingCard()) { - toPanel.setAttachedToPanel(getCardPanel(card.getEnchantingCard().getUniqueNumber())); - } else if (card.isEquipping()) { - toPanel.setAttachedToPanel(getCardPanel(card.getEquipping().get(0).getUniqueNumber())); - } else if (card.isFortifying()) { - toPanel.setAttachedToPanel(getCardPanel(card.getFortifying().get(0).getUniqueNumber())); + final Iterable fortifications = card.getFortifiedBy(); + for (final CardView f : fortifications) { + final CardPanel cardE = getCardPanel(f.getId()); + if (cardE != null) { + toPanel.getAttachedPanels().add(cardE); + } + } + + if (card.getEnchantingCard() != null) { + toPanel.setAttachedToPanel(getCardPanel(card.getEnchantingCard().getId())); + } else if (card.getEquipping() != null) { + toPanel.setAttachedToPanel(getCardPanel(card.getEquipping().getId())); + } else if (card.getFortifying() != null) { + toPanel.setAttachedToPanel(getCardPanel(card.getFortifying().getId())); } else { toPanel.setAttachedToPanel(null); } @@ -695,12 +713,12 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen CreatureNonToken, Other; - public boolean isGoodFor(final Card card) { + public boolean isGoodFor(final CardStateView stateView) { switch (this) { - case Land: return card.isLand(); - case Creature: return card.isCreature(); - case CreatureNonToken: return card.isCreature() && !card.isToken(); - case Other: return !card.isLand() && !card.isCreature(); + case Land: return stateView.isLand(); + case Creature: return stateView.isCreature(); + case CreatureNonToken: return stateView.isCreature() && !stateView.getCard().isToken(); + case Other: return !stateView.isLand() && !stateView.isCreature(); default: throw new RuntimeException("Unhandled type: " + this); } } @@ -724,7 +742,7 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen private void addAll(final List cardPanels, final RowType type) { for (final CardPanel panel : cardPanels) { - if (!type.isGoodFor(panel.getCard()) || (panel.getAttachedToPanel() != null)) { + if (!type.isGoodFor(panel.getCard().getState()) || (panel.getAttachedToPanel() != null)) { continue; } final CardStack stack = new CardStack(); @@ -741,14 +759,16 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen */ private void addAllOthers(final List cardPanels, final RowType type) { for (final CardPanel panel : cardPanels) { - if (!type.isGoodFor(panel.getCard()) || (panel.getAttachedToPanel() != null)) { + if (!type.isGoodFor(panel.getCard().getState()) || (panel.getAttachedToPanel() != null)) { continue; } boolean stackable = false; - for (CardStack s : this) { - Card otherCard = s.get(0).getCard(); - Card thisCard = panel.getCard(); - if (otherCard.getName().equals(thisCard.getName()) && s.size() < othersStackMax) { + for (final CardStack s : this) { + final CardView otherCard = s.get(0).getCard(); + final CardStateView otherState = otherCard.getState(); + final CardView thisCard = panel.getCard(); + final CardStateView thisState = thisCard.getState(); + if (otherState.getName().equals(thisState.getName()) && s.size() < othersStackMax) { if (panel.getAttachedPanels().isEmpty() && thisCard.getCounters().equals(otherCard.getCounters()) && (thisCard.isSick() == otherCard.isSick()) diff --git a/forge-gui-desktop/src/test/java/forge/gui/game/CardDetailPanelTest.java b/forge-gui-desktop/src/test/java/forge/gui/game/CardDetailPanelTest.java index 96b73fb57f1..be4895e71a2 100644 --- a/forge-gui-desktop/src/test/java/forge/gui/game/CardDetailPanelTest.java +++ b/forge-gui-desktop/src/test/java/forge/gui/game/CardDetailPanelTest.java @@ -16,7 +16,7 @@ public class CardDetailPanelTest { @Test(groups = { "UnitTest", "fast" }, enabled = false) public void cardDetailPanelTest1() { try { - CardDetailPanel dialog = new CardDetailPanel(null); + CardDetailPanel dialog = new CardDetailPanel(); // dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); dialog.setVisible(true); Assert.assertNotNull(dialog); diff --git a/forge-gui/src/main/java/forge/card/CardDetailUtil.java b/forge-gui/src/main/java/forge/card/CardDetailUtil.java index 37feb31e450..59058e18e51 100644 --- a/forge-gui/src/main/java/forge/card/CardDetailUtil.java +++ b/forge-gui/src/main/java/forge/card/CardDetailUtil.java @@ -8,8 +8,6 @@ import java.util.Map.Entry; import com.google.common.collect.Sets; -import forge.GuiBase; -import forge.game.Game; import forge.game.GameEntity; import forge.game.card.Card; import forge.game.card.CardUtil; @@ -20,6 +18,8 @@ import forge.item.InventoryItemFromSet; import forge.item.PreconDeck; import forge.item.SealedProduct; import forge.util.Lang; +import forge.view.CardView; +import forge.view.CardView.CardStateView; public class CardDetailUtil { private CardDetailUtil() { @@ -51,12 +51,17 @@ public class CardDetailUtil { } } + public static DetailColors getBorderColor(final CardStateView card, final boolean canShow) { + return getBorderColors(card.getColors(), card.isLand(), canShow, false).iterator().next(); + } + @Deprecated public static DetailColors getBorderColor(final Card card, boolean canShow) { return getBorderColors(card.determineColor(), card.isLand(), canShow, false).get(0); } public static DetailColors getBorderColor(final ColorSet cardColors, final boolean isLand, boolean canShow) { return getBorderColors(cardColors, isLand, canShow, false).get(0); } + @Deprecated public static List getBorderColors(final Card card, boolean canShow, boolean supportMultiple) { return getBorderColors(card.determineColor(), card.isLand(), canShow, supportMultiple); } @@ -157,6 +162,7 @@ public class CardDetailUtil { return item.getName(); } + @Deprecated public static String formatCardType(final Card card) { final ArrayList list = card.getType(); final StringBuilder sb = new StringBuilder(); @@ -200,6 +206,50 @@ public class CardDetailUtil { return sb.toString(); } + public static String formatCardType(final CardStateView card) { + final List list = card.getType(); + final StringBuilder sb = new StringBuilder(); + + final List superTypes = new ArrayList(); + final List cardTypes = new ArrayList(); + final List subTypes = new ArrayList(); + final boolean allCreatureTypes = list.contains("AllCreatureTypes"); + + for (final String t : list) { + if (allCreatureTypes && t.equals("AllCreatureTypes")) { + continue; + } + if (CardType.isASuperType(t) && !superTypes.contains(t)) { + superTypes.add(t); + } + if (CardType.isACardType(t) && !cardTypes.contains(t)) { + cardTypes.add(t); + } + if (CardType.isASubType(t) && !subTypes.contains(t) && (!allCreatureTypes || !CardType.isACreatureType(t))) { + subTypes.add(t); + } + } + + for (final String type : superTypes) { + sb.append(type).append(" "); + } + for (final String type : cardTypes) { + sb.append(type).append(" "); + } + if (!subTypes.isEmpty() || allCreatureTypes) { + sb.append("- "); + } + if (allCreatureTypes) { + sb.append("All creature types "); + } + for (final String type : subTypes) { + sb.append(type).append(" "); + } + + return sb.toString(); + } + + @Deprecated public static String formatPowerToughness(final Card card) { StringBuilder ptText = new StringBuilder(); if (card.isCreature()) { @@ -219,11 +269,37 @@ public class CardDetailUtil { } return ptText.toString(); } - + + public static String formatPowerToughness(final CardStateView card) { + StringBuilder ptText = new StringBuilder(); + if (card.isCreature()) { + ptText.append(card.getPower()).append(" / ").append(card.getToughness()); + } + + if (card.isPlaneswalker()) { + if (ptText.length() > 0) { + ptText.insert(0, "P/T: "); + ptText.append(" - ").append("Loy: "); + } + else { + ptText.append("Loyalty: "); + } + + ptText.append(card.getLoyalty()); + } + return ptText.toString(); + } + + @Deprecated public static String formatCardId(final Card card) { return card.getUniqueNumber() > 0 ? "[" + card.getUniqueNumber() + "]" : ""; } + public static String formatCardId(final CardStateView card) { + final int id = card.getCard().getId(); + return id > 0 ? "[" + id + "]" : ""; + } + @Deprecated public static String composeCardText(final Card card, final boolean canShow) { final StringBuilder area = new StringBuilder(); @@ -438,21 +514,7 @@ public class CardDetailUtil { if (area.length() != 0) { area.append("\n"); } - area.append("*Enchanting "); - - if (entity instanceof Card) { - final Card c = (Card) entity; - if (!GuiBase.getInterface().mayShowCard(c)) { - area.append("Morph ("); - area.append(card.getUniqueNumber()); - area.append(")"); - } else { - area.append(entity); - } - } else { - area.append(entity); - } - area.append("*"); + area.append("*Enchanting ").append(entity).append("*"); } // enchanted by @@ -538,8 +600,8 @@ public class CardDetailUtil { area.append("Must block " + mustBlockThese); } - //show current storm count for storm cards - if (card.getKeyword().contains("Storm")) { + /*show current storm count for storm cards + if (card.getKeyword().contains("Storm")) Game game = GuiBase.getInterface().getGame(); if (game != null) { if (area.length() != 0) { @@ -547,51 +609,325 @@ public class CardDetailUtil { } area.append("Current Storm Count: " + game.getStack().getCardsCastThisTurn().size()); } - } + }*/ return area.toString(); } + public static String composeCardText(final CardStateView state, final boolean canShow) { + final CardView card = state.getCard(); + final StringBuilder area = new StringBuilder(); + + // Token + if (card.isToken()) { + area.append("Token"); + } + + if (canShow) { + // card text + if (area.length() != 0) { + area.append("\n"); + } + String text = state.getText(); + // LEVEL [0-9]+-[0-9]+ + // LEVEL [0-9]+\+ + + String regex = "LEVEL [0-9]+-[0-9]+ "; + text = text.replaceAll(regex, "$0\r\n"); + + regex = "LEVEL [0-9]+\\+ "; + text = text.replaceAll(regex, "\r\n$0\r\n"); + + // displays keywords that have dots in them a little better: + regex = "\\., "; + text = text.replaceAll(regex, ".\r\n"); + + area.append(text); + } + + if (card.isPhasedOut()) { + if (area.length() != 0) { + area.append("\n"); + } + area.append("Phased Out"); + } + + // text changes + final Map changedColorWords = state.getChangedColorWords(), + changedTypes = state.getChangedTypes(); + if (!(changedColorWords.isEmpty() && changedTypes.isEmpty())) { + if (area.length() != 0) { + area.append("\n"); + } + } + for (final Entry e : Sets.union(changedColorWords.entrySet(), changedTypes.entrySet())) { + // ignore lower case and plural form keys, to avoid duplicity + if (Character.isUpperCase(e.getKey().charAt(0)) && + !CardUtil.singularTypes.containsKey(e.getKey())) { + area.append("Text changed: all instances of "); + if (e.getKey().equals("Any")) { + if (changedColorWords.containsKey(e.getKey())) { + area.append("color words"); + } else if (forge.card.CardType.getBasicTypes().contains(e.getValue())) { + area.append("basic land types"); + } else { + area.append("creature types"); + } + } else { + area.append(e.getKey()); + } + area.append(" are replaced by "); + area.append(e.getValue()); + area.append(".\n"); + } + } + + // counter text + for (final Entry c : card.getCounters().entrySet()) { + if (c.getValue().intValue() != 0) { + if (area.length() != 0) { + area.append("\n"); + } + area.append(c.getKey().getName() + " counters: "); + area.append(c.getValue()); + } + } + + if (state.isCreature()) { + final int damage = card.getDamage(); + if (damage > 0) { + if (area.length() != 0) { + area.append("\n"); + } + area.append("Damage: " + damage); + } + } + if (state.isCreature() || state.isPlaneswalker()) { + final int assigned = card.getAssignedDamage(); + if (assigned > 0) { + if (area.length() != 0) { + area.append("\n"); + } + area.append("Assigned Damage: " + assigned); + } + } + + // Regeneration Shields + final int regenShields = card.getRegenerationShields(); + if (regenShields > 0) { + if (area.length() != 0) { + area.append("\n"); + } + area.append("Regeneration Shields: ").append(regenShields); + } + + // Damage Prevention + final int preventNextDamage = card.getPreventNextDamage(); + if (preventNextDamage > 0) { + area.append("\n"); + area.append("Prevent the next ").append(preventNextDamage).append(" damage that would be dealt to "); + area.append(state.getName()).append(" this turn."); + } + + // top revealed + /* + if ((card.hasKeyword("Play with the top card of your library revealed.") || card + .hasKeyword("Players play with the top card of their libraries revealed.")) + && card.getController() != null + && (card.isInZone(ZoneType.Battlefield) || (card.isInZone(ZoneType.Command) && !card.isCommander())) + && !card.getController().getZone(ZoneType.Library).isEmpty()) { + area.append("\r\nTop card of your library: "); + area.append(card.getController().getCardsIn(ZoneType.Library, 1)); + if (card.hasKeyword("Players play with the top card of their libraries revealed.")) { + for (final Player p : card.getController().getAllOtherPlayers()) { + if (p.getZone(ZoneType.Library).isEmpty()) { + area.append(p.getName()); + area.append("'s library is empty."); + } else { + area.append("\r\nTop card of "); + area.append(p.getName()); + area.append("'s library: "); + area.append(p.getCardsIn(ZoneType.Library, 1)); + } + } + } + }*/ + + // chosen type + if (!card.getChosenType().equals("")) { + if (area.length() != 0) { + area.append("\n"); + } + area.append("(chosen type: "); + area.append(card.getChosenType()); + area.append(")"); + } + + // chosen color + if (!card.getChosenColors().isEmpty()) { + if (area.length() != 0) { + area.append("\n"); + } + area.append("(chosen colors: "); + area.append(Lang.joinHomogenous(card.getChosenColors())); + area.append(")"); + } + + // chosen player + if (card.getChosenPlayer() != null) { + if (area.length() != 0) { + area.append("\n"); + } + area.append("(chosen player: " + card.getChosenPlayer() + ")"); + } + + // named card + if (!card.getNamedCard().equals("")) { + if (area.length() != 0) { + area.append("\n"); + } + area.append("(named card: "); + area.append(card.getNamedCard()); + area.append(")"); + } + + // equipping + if (card.getEquipping() != null) { + if (area.length() != 0) { + area.append("\n"); + } + area.append("=Equipping "); + area.append(card.getEquipping()); + area.append("="); + } + + // equipped by + if (card.getEquippedBy().iterator().hasNext()) { + if (area.length() != 0) { + area.append("\n"); + } + area.append("=Equipped by "); + for (final Iterator it = card.getEquippedBy().iterator(); it.hasNext();) { + area.append(it.next()); + if (it.hasNext()) { + area.append(", "); + } + } + area.append("="); + } + + // enchanting + if (card.getEnchantingCard() != null) { + if (area.length() != 0) { + area.append("\n"); + } + area.append("*Enchanting ").append(card.getEnchantingCard()).append("*"); + } + if (card.getEnchantingPlayer() != null) { + if (area.length() != 0) { + area.append("\n"); + } + area.append("*Enchanting ").append(card.getEnchantingPlayer()).append("*"); + } + + // enchanted by + if (card.getEnchantedBy().iterator().hasNext()) { + if (area.length() != 0) { + area.append("\n"); + } + area.append("*Enchanted by "); + for (final Iterator it = card.getEnchantedBy().iterator(); it.hasNext();) { + area.append(it.next()); + if (it.hasNext()) { + area.append(", "); + } + } + area.append("*"); + } + + // controlling + if (card.getGainControlTargets().iterator().hasNext()) { + if (area.length() != 0) { + area.append("\n"); + } + area.append("+Controlling: "); + for (final Iterator it = card.getGainControlTargets().iterator(); it.hasNext();) { + area.append(it.next()); + if (it.hasNext()) { + area.append(", "); + } + } + area.append("+"); + } + + // cloned via + if (card.getCloneOrigin() != null) { + if (area.length() != 0) { + area.append("\n"); + } + area.append("^Cloned via: "); + area.append(card.getCloneOrigin().getState().getName()); + area.append("^"); + } + + // Imprint + if (card.getImprinted().iterator().hasNext()) { + if (area.length() != 0) { + area.append("\n"); + } + area.append("Imprinting: "); + for (final Iterator it = card.getImprinted().iterator(); it.hasNext();) { + area.append(it.next()); + if (it.hasNext()) { + area.append(", "); + } + } + } + + // Haunt + if (card.getHauntedBy().iterator().hasNext()) { + if (area.length() != 0) { + area.append("\n"); + } + area.append("Haunted by: "); + for (final Iterator it = card.getHauntedBy().iterator(); it.hasNext();) { + area.append(it.next()); + if (it.hasNext()) { + area.append(", "); + } + } + } + if (card.getHaunting() != null) { + if (area.length() != 0) { + area.append("\n"); + } + area.append("Haunting " + card.getHaunting()); + } + + // must block + if (card.getMustBlock().iterator().hasNext()) { + if (area.length() != 0) { + area.append("\n"); + } + final String mustBlockThese = Lang.joinHomogenous(card.getMustBlock()); + area.append("Must block " + mustBlockThese); + } + + /*show current storm count for storm cards + if (state.hasStorm()) { + Game game = GuiBase.getInterface().getGame(); + if (game != null) { + if (area.length() != 0) { + area.append("\n\n"); + } + area.append("Current Storm Count: " + game.getStack().getCardsCastThisTurn().size()); + } + }*/ + return area.toString(); + } + + @Deprecated public static boolean isCardFlippable(Card card) { return card.isDoubleFaced() || card.isFlipCard() || card.isFaceDown(); } - /** - * Card characteristic state machine. - *

            - * Given a card and a state in terms of {@code CardCharacteristicName} this - * will determine whether there is a valid alternate {@code CardCharacteristicName} - * state for that card. - * - * @param card the {@code Card} - * @param currentState not necessarily {@code card.getCurState()} - * @return the alternate {@code CardCharacteristicName} state or default if not applicable - */ - public static CardCharacteristicName getAlternateState(final Card card, CardCharacteristicName currentState) { - // Default. Most cards will only ever have an "Original" state represented by a single image. - CardCharacteristicName alternateState = CardCharacteristicName.Original; - - if (card.isDoubleFaced()) { - if (currentState == CardCharacteristicName.Original) { - alternateState = CardCharacteristicName.Transformed; - } - } - else if (card.isFlipCard()) { - if (currentState == CardCharacteristicName.Original) { - alternateState = CardCharacteristicName.Flipped; - } - } - else if (card.isFaceDown()) { - if (currentState == CardCharacteristicName.Original) { - alternateState = CardCharacteristicName.FaceDown; - } - else if (GuiBase.getInterface().mayShowCard(card)) { - alternateState = CardCharacteristicName.Original; - } - else { - alternateState = currentState; - } - } - - return alternateState; - } } diff --git a/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java b/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java index 9288f55a306..243e3e98b46 100644 --- a/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java +++ b/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java @@ -1,5 +1,6 @@ package forge.control; +import com.google.common.collect.Sets; import com.google.common.eventbus.Subscribe; import forge.FThreads; @@ -18,6 +19,7 @@ import forge.properties.ForgePreferences.FPref; import forge.util.Lang; import forge.util.gui.SGuiChoose; import forge.util.maps.MapOfLists; +import forge.view.CardView; import org.apache.commons.lang3.tuple.Pair; @@ -76,12 +78,11 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { if (turnUpdPlanned.getAndSet(true)) { return null; } - final Game game = GuiBase.getInterface().getGame(); // to make sure control gets a correct game instance FThreads.invokeInEdtNowOrLater(new Runnable() { @Override public void run() { turnUpdPlanned.set(false); - GuiBase.getInterface().updateTurn(event, game); + GuiBase.getInterface().updateTurn(event); } }); return null; @@ -225,7 +226,7 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { return null; } - private final Set cardsToUpdate = new HashSet(); + private final Set cardsToUpdate = Sets.newHashSet(); private final Runnable updCards = new Runnable() { @Override public void run() { @@ -288,7 +289,7 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { return null; } - private Void updateSingleCard(Card c) { + private Void updateSingleCard(final CardView c) { boolean needUpdate = false; synchronized (cardsToUpdate) { needUpdate = cardsToUpdate.isEmpty(); diff --git a/forge-gui/src/main/java/forge/events/UiEventAttackerDeclared.java b/forge-gui/src/main/java/forge/events/UiEventAttackerDeclared.java index 245bbf26677..2e61784bd86 100644 --- a/forge-gui/src/main/java/forge/events/UiEventAttackerDeclared.java +++ b/forge-gui/src/main/java/forge/events/UiEventAttackerDeclared.java @@ -1,7 +1,7 @@ package forge.events; -import forge.game.GameEntity; -import forge.game.card.Card; +import forge.view.CardView; +import forge.view.GameEntityView; /** * TODO: Write javadoc for this type. @@ -9,16 +9,16 @@ import forge.game.card.Card; */ public class UiEventAttackerDeclared extends UiEvent { - public final Card attacker; - public final GameEntity defender; + public final CardView attacker; + public final GameEntityView defender; - public UiEventAttackerDeclared(Card card, GameEntity currentDefender) { + public UiEventAttackerDeclared(final CardView card, final GameEntityView currentDefender) { attacker = card; defender = currentDefender; } @Override - public T visit(IUiEventVisitor visitor) { + public T visit(final IUiEventVisitor visitor) { return visitor.visit(this); } @@ -27,6 +27,6 @@ public class UiEventAttackerDeclared extends UiEvent { */ @Override public String toString() { - return attacker.toString() + ( defender == null ? " removed from combat" : " declared to attack " + defender.getName() ); + return attacker.toString() + ( defender == null ? " removed from combat" : " declared to attack " + defender ); } } diff --git a/forge-gui/src/main/java/forge/events/UiEventBlockerAssigned.java b/forge-gui/src/main/java/forge/events/UiEventBlockerAssigned.java index 8b64d8a1cdb..467a2f4742b 100644 --- a/forge-gui/src/main/java/forge/events/UiEventBlockerAssigned.java +++ b/forge-gui/src/main/java/forge/events/UiEventBlockerAssigned.java @@ -1,19 +1,19 @@ package forge.events; -import forge.game.card.Card; +import forge.view.CardView; public class UiEventBlockerAssigned extends UiEvent { - public final Card blocker; - public final Card attackerBeingBlocked; + public final CardView blocker; + public final CardView attackerBeingBlocked; - public UiEventBlockerAssigned(Card card, Card currentAttacker) { + public UiEventBlockerAssigned(final CardView card, final CardView currentAttacker) { blocker = card; attackerBeingBlocked = currentAttacker; } @Override - public T visit(IUiEventVisitor visitor) { + public T visit(final IUiEventVisitor visitor) { return visitor.visit(this); } diff --git a/forge-gui/src/main/java/forge/gauntlet/GauntletWinLoseController.java b/forge-gui/src/main/java/forge/gauntlet/GauntletWinLoseController.java index 4c8bf3d65f0..837f6d60fae 100644 --- a/forge-gui/src/main/java/forge/gauntlet/GauntletWinLoseController.java +++ b/forge-gui/src/main/java/forge/gauntlet/GauntletWinLoseController.java @@ -8,22 +8,21 @@ import forge.GuiBase; import forge.LobbyPlayer; import forge.assets.FSkinProp; import forge.deck.Deck; -import forge.game.Game; import forge.game.GameType; -import forge.game.Match; import forge.game.player.RegisteredPlayer; import forge.interfaces.IButton; import forge.interfaces.IGuiBase; import forge.interfaces.IWinLoseView; import forge.model.FModel; +import forge.view.IGameView; public abstract class GauntletWinLoseController { - private final Game lastGame; + private final IGameView lastGame; private final IWinLoseView view; - public GauntletWinLoseController(IWinLoseView view0, Game lastGame0) { + public GauntletWinLoseController(IWinLoseView view0, final IGameView game0) { view = view0; - lastGame = lastGame0; + lastGame = game0; } public void showOutcome() { @@ -43,8 +42,6 @@ public abstract class GauntletWinLoseController { // Generic event record. lstEventRecords.set(gd.getCompleted(), "Ongoing"); - final Match match = lastGame.getMatch(); - // Match won't be saved until it is over. This opens up a cheat // or failsafe mechanism (depending on your perspective) in which // the player can restart Forge to replay a match. @@ -53,14 +50,14 @@ public abstract class GauntletWinLoseController { LobbyPlayer questPlayer = GuiBase.getInterface().getQuestPlayer(); // In all cases, update stats. - lstEventRecords.set(gd.getCompleted(), match.getGamesWonBy(questPlayer) + " - " - + (match.getPlayedGames().size() - match.getGamesWonBy(questPlayer))); + lstEventRecords.set(gd.getCompleted(), lastGame.getGamesWonBy(questPlayer) + " - " + + (lastGame.getNumPlayedGamesInMatch() - lastGame.getGamesWonBy(questPlayer))); - if (match.isMatchOver()) { + if (lastGame.isMatchOver()) { gd.setCompleted(gd.getCompleted() + 1); // Win match case - if (match.isWonBy(questPlayer)) { + if (lastGame.isMatchWonBy(questPlayer)) { // Gauntlet complete: Remove save file if (gd.getCompleted() == lstDecks.size()) { icon = FSkinProp.ICO_QUEST_COIN; @@ -112,7 +109,7 @@ public abstract class GauntletWinLoseController { } public final boolean actionOnContinue() { - if (lastGame.getMatch().isMatchOver()) { + if (lastGame.isMatchOver()) { // To change the AI deck, we have to create a new match. GauntletData gd = FModel.getGauntletData(); Deck aiDeck = gd.getDecks().get(gd.getCompleted()); diff --git a/forge-gui/src/main/java/forge/interfaces/IGuiBase.java b/forge-gui/src/main/java/forge/interfaces/IGuiBase.java index 37c1093c543..40552274f50 100644 --- a/forge-gui/src/main/java/forge/interfaces/IGuiBase.java +++ b/forge-gui/src/main/java/forge/interfaces/IGuiBase.java @@ -15,16 +15,11 @@ import forge.assets.FSkinProp; import forge.assets.ISkinImage; import forge.deck.CardPool; import forge.events.UiEvent; -import forge.game.Game; -import forge.game.GameEntity; import forge.game.GameType; import forge.game.Match; -import forge.game.card.Card; import forge.game.combat.Combat; -import forge.game.event.GameEventTurnBegan; import forge.game.phase.PhaseType; import forge.game.player.IHasIcon; -import forge.game.player.Player; import forge.game.player.RegisteredPlayer; import forge.game.spellability.SpellAbility; import forge.game.zone.ZoneType; @@ -33,7 +28,10 @@ import forge.match.input.InputQueue; import forge.sound.IAudioClip; import forge.sound.IAudioMusic; import forge.util.ITriggerEvent; - +import forge.view.CardView; +import forge.view.GameEntityView; +import forge.view.IGameView; +import forge.view.PlayerView; public interface IGuiBase { boolean isRunningOnDesktop(); @@ -42,55 +40,55 @@ public interface IGuiBase { void invokeInEdtAndWait(final Runnable proc); boolean isGuiThread(); String getAssetsDir(); - boolean mayShowCard(Card card); + boolean mayShowCard(CardView card); ISkinImage getSkinIcon(FSkinProp skinProp); ISkinImage getUnskinnedIcon(String path); void showBugReportDialog(String title, String text, boolean showExitAppBtn); int showOptionDialog(String message, String title, FSkinProp icon, String[] options, int defaultOption); - int showCardOptionDialog(Card card, String message, String title, FSkinProp icon, String[] options, int defaultOption); + int showCardOptionDialog(CardView card, String message, String title, FSkinProp icon, String[] options, int defaultOption); T showInputDialog(String message, String title, FSkinProp icon, T initialInput, T[] inputOptions); List getChoices(final String message, final int min, final int max, final Collection choices, final T selected, final Function display); List order(final String title, final String top, final int remainingObjectsMin, final int remainingObjectsMax, - final List sourceChoices, final List destChoices, final Card referenceCard, final boolean sideboardingMode); + final List sourceChoices, final List destChoices, final CardView referenceCard, final boolean sideboardingMode); List sideboard(CardPool sideboard, CardPool main); String showFileDialog(String title, String defaultDir); File getSaveFile(File defaultFile); void showCardList(final String title, final String message, final List list); boolean showBoxedProduct(final String title, final String message, final List list); void fireEvent(UiEvent e); - void setCard(Card card); + void setCard(CardView card); void showCombat(Combat combat); - void setUsedToPay(Card card, boolean b); - void setHighlighted(Player player, boolean b); + void setUsedToPay(CardView card, boolean b); + void setHighlighted(PlayerView player, boolean b); void showPromptMessage(String message); - boolean stopAtPhase(Player playerTurn, PhaseType phase); + boolean stopAtPhase(PlayerView playerTurn, PhaseType phase); InputQueue getInputQueue(); - Game getGame(); + IGameView getGame(); IButton getBtnOK(); IButton getBtnCancel(); void focusButton(IButton button); void flashIncorrectAction(); void updatePhase(); - void updateTurn(GameEventTurnBegan event, Game game); + void updateTurn(PlayerView player); void updatePlayerControl(); void enableOverlay(); void disableOverlay(); void finishGame(); - Object showManaPool(Player player); - void hideManaPool(Player player, Object zoneToRestore); - boolean openZones(List zones, Map players); - void restoreOldZones(Map playersToRestoreZonesFor); + Object showManaPool(PlayerView player); + void hideManaPool(PlayerView player, Object zoneToRestore); + boolean openZones(List zones, Map players); + void restoreOldZones(Map playersToRestoreZonesFor); void updateStack(); - void updateZones(List> zonesToUpdate); - void updateCards(Set cardsToUpdate); - void refreshCardDetails(Collection cards); - void updateManaPool(List manaPoolUpdate); - void updateLives(List livesUpdate); + void updateZones(List> zonesToUpdate); + void updateCards(Set cardsToUpdate); + void refreshCardDetails(Collection cards); + void updateManaPool(List manaPoolUpdate); + void updateLives(List livesUpdate); void endCurrentGame(); void startMatch(GameType gauntletType, List starter); - void setPanelSelection(Card hostCard); - Map getDamageToAssign(Card attacker, List blockers, - int damageDealt, GameEntity defender, boolean overrideOrder); + void setPanelSelection(CardView hostCard); + Map getDamageToAssign(CardView attacker, List blockers, + int damageDealt, GameEntityView defender, boolean overrideOrder); SpellAbility getAbilityToPlay(List abilities, ITriggerEvent triggerEvent); void hear(LobbyPlayer player, String message); int getAvatarCount(); diff --git a/forge-gui/src/main/java/forge/limited/LimitedWinLoseController.java b/forge-gui/src/main/java/forge/limited/LimitedWinLoseController.java index 86b67a5a2eb..80cd7b184fc 100644 --- a/forge-gui/src/main/java/forge/limited/LimitedWinLoseController.java +++ b/forge-gui/src/main/java/forge/limited/LimitedWinLoseController.java @@ -1,23 +1,23 @@ package forge.limited; import forge.GuiBase; -import forge.game.Game; import forge.interfaces.IButton; import forge.interfaces.IWinLoseView; import forge.model.FModel; +import forge.view.IGameView; public abstract class LimitedWinLoseController { - private final Game lastGame; + private final IGameView lastGame; private final boolean wonMatch; private final IWinLoseView view; private GauntletMini gauntlet; private boolean nextRound = false; - public LimitedWinLoseController(IWinLoseView view0, Game lastGame0) { + public LimitedWinLoseController(IWinLoseView view0, final IGameView game0) { view = view0; - lastGame = lastGame0; + lastGame = game0; gauntlet = FModel.getGauntletMini(); - wonMatch = lastGame.getMatch().isWonBy(GuiBase.getInterface().getGuiPlayer()); + wonMatch = lastGame.isMatchWonBy(GuiBase.getInterface().getGuiPlayer()); } public void showOutcome() { @@ -29,10 +29,9 @@ public abstract class LimitedWinLoseController { resetView(); nextRound = false; - if (lastGame.getOutcome().isWinner(GuiBase.getInterface().getGuiPlayer())) { + if (lastGame.isWinner(GuiBase.getInterface().getGuiPlayer())) { gauntlet.addWin(); - } - else { + } else { gauntlet.addLoss(); } @@ -41,7 +40,7 @@ public abstract class LimitedWinLoseController { showOutcome(new Runnable() { @Override public void run() { - if (!lastGame.getMatch().isMatchOver()) { + if (!lastGame.isMatchOver()) { showTournamentInfo("Tournament Info"); return; } diff --git a/forge-gui/src/main/java/forge/match/input/Input.java b/forge-gui/src/main/java/forge/match/input/Input.java index 524fb58d950..94339ad7b67 100644 --- a/forge-gui/src/main/java/forge/match/input/Input.java +++ b/forge-gui/src/main/java/forge/match/input/Input.java @@ -5,12 +5,11 @@ import forge.game.player.Player; import forge.game.spellability.SpellAbility; import forge.util.ITriggerEvent; - public interface Input { void showMessageInitial(); - boolean selectCard(Card c, ITriggerEvent triggerEvent); - + boolean selectCard(Card card, ITriggerEvent triggerEvent); + void selectAbility(SpellAbility ab); void selectPlayer(Player player, ITriggerEvent triggerEvent); diff --git a/forge-gui/src/main/java/forge/match/input/InputAttack.java b/forge-gui/src/main/java/forge/match/input/InputAttack.java index 893022ab8e5..1c4e5032695 100644 --- a/forge-gui/src/main/java/forge/match/input/InputAttack.java +++ b/forge-gui/src/main/java/forge/match/input/InputAttack.java @@ -248,9 +248,9 @@ public class InputAttack extends InputSyncronizedBase { return false; } - private final void setCurrentDefender(GameEntity def) { + private final void setCurrentDefender(final GameEntity def) { currentDefender = def; - for (GameEntity ge : defenders) { + for (final GameEntity ge : defenders) { if (ge instanceof Card) { GuiBase.getInterface().setUsedToPay((Card)ge, ge == def); } @@ -262,16 +262,16 @@ public class InputAttack extends InputSyncronizedBase { updateMessage(); } - private final void activateBand(AttackingBand band) { + private final void activateBand(final AttackingBand band) { if (activeBand != null) { - for (Card card : activeBand.getAttackers()) { + for (final Card card : activeBand.getAttackers()) { GuiBase.getInterface().setUsedToPay(card, false); } } activeBand = band; if (activeBand != null) { - for(Card card : activeBand.getAttackers()) { + for (final Card card : activeBand.getAttackers()) { GuiBase.getInterface().setUsedToPay(card, true); } } @@ -279,8 +279,8 @@ public class InputAttack extends InputSyncronizedBase { //only enable banding message and actions if a creature that can attack has banding private boolean isBandingPossible() { - List possibleAttackers = playerAttacks.getCardsIn(ZoneType.Battlefield); - for (Card c : Iterables.filter(possibleAttackers, CardPredicates.hasKeyword("Banding"))) { + final List possibleAttackers = playerAttacks.getCardsIn(ZoneType.Battlefield); + for (final Card c : Iterables.filter(possibleAttackers, CardPredicates.hasKeyword("Banding"))) { if (c.isCreature() && CombatUtil.canAttack(c, currentDefender, combat)) { return true; } diff --git a/forge-gui/src/main/java/forge/match/input/InputBase.java b/forge-gui/src/main/java/forge/match/input/InputBase.java index 34444e3a3c2..ca2203e8b35 100644 --- a/forge-gui/src/main/java/forge/match/input/InputBase.java +++ b/forge-gui/src/main/java/forge/match/input/InputBase.java @@ -108,7 +108,7 @@ public abstract class InputBase implements java.io.Serializable, Input { } @Override - public void selectAbility(SpellAbility ab) { } + public void selectAbility(final SpellAbility ab) { } @Override public final void selectButtonCancel() { @@ -131,12 +131,12 @@ public abstract class InputBase implements java.io.Serializable, Input { protected boolean onCardSelected(final Card c, final ITriggerEvent triggerEvent) { return false; } - protected void onPlayerSelected(final Player p, final ITriggerEvent triggerEvent) {} + protected void onPlayerSelected(final Player player, final ITriggerEvent triggerEvent) {} protected void onCancel() {} protected void onOk() {} // to remove need for CMatchUI dependence - protected final void showMessage(String message) { + protected final void showMessage(final String message) { GuiBase.getInterface().showPromptMessage(message); } @@ -144,7 +144,7 @@ public abstract class InputBase implements java.io.Serializable, Input { GuiBase.getInterface().flashIncorrectAction(); } - protected String getTurnPhasePriorityMessage(Game game) { + protected String getTurnPhasePriorityMessage(final Game game) { final PhaseHandler ph = game.getPhaseHandler(); final StringBuilder sb = new StringBuilder(); 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 24de86350a7..3828afc3bbc 100644 --- a/forge-gui/src/main/java/forge/match/input/InputProxy.java +++ b/forge-gui/src/main/java/forge/match/input/InputProxy.java @@ -17,19 +17,19 @@ */ package forge.match.input; -import forge.FThreads; -import forge.GuiBase; -import forge.game.Game; -import forge.game.card.Card; -import forge.game.player.Player; -import forge.game.spellability.SpellAbility; -import forge.util.ITriggerEvent; -import forge.util.gui.SOptionPane; - import java.util.Observable; import java.util.Observer; import java.util.concurrent.atomic.AtomicReference; +import forge.FThreads; +import forge.GuiBase; +import forge.game.spellability.SpellAbility; +import forge.util.ITriggerEvent; +import forge.util.gui.SOptionPane; +import forge.view.CardView; +import forge.view.IGameView; +import forge.view.PlayerView; + /** *

            * GuiInput class. @@ -42,11 +42,11 @@ public class InputProxy implements Observer { /** The input. */ private AtomicReference input = new AtomicReference(); - private Game game = null; + private IGameView game = null; // private static final boolean DEBUG_INPUT = true; // false; - public void setGame(Game game0) { + public void setGame(IGameView game0) { game = game0; GuiBase.getInterface().getInputQueue().addObserver(this); } @@ -120,8 +120,8 @@ public class InputProxy implements Observer { * @param player * a {@link forge.game.player.Player} object. */ - public final void selectPlayer(final Player player, final ITriggerEvent triggerEvent) { - Input inp = getInput(); + public final void selectPlayer(final PlayerView player, final ITriggerEvent triggerEvent) { + final Input inp = getInput(); if (inp != null) { inp.selectPlayer(player, triggerEvent); } @@ -132,20 +132,20 @@ public class InputProxy implements Observer { * selectCard. *

            * - * @param card + * @param cardView * a {@link forge.game.card.Card} object. * @param triggerEvent */ - public final boolean selectCard(final Card card, final ITriggerEvent triggerEvent) { - Input inp = getInput(); + public final boolean selectCard(final CardView cardView, final ITriggerEvent triggerEvent) { + final Input inp = getInput(); if (inp != null) { - return inp.selectCard(card, triggerEvent); + return inp.selectCard(cardView, triggerEvent); } return false; } - public final void selectAbility(SpellAbility ab) { - Input inp = getInput(); + public final void selectAbility(final SpellAbility ab) { + final Input inp = getInput(); if (inp != null) { inp.selectAbility(ab); } diff --git a/forge-gui/src/main/java/forge/match/input/InputQueue.java b/forge-gui/src/main/java/forge/match/input/InputQueue.java index 413e0ca67d1..aa85dde6583 100644 --- a/forge-gui/src/main/java/forge/match/input/InputQueue.java +++ b/forge-gui/src/main/java/forge/match/input/InputQueue.java @@ -17,7 +17,8 @@ */ package forge.match.input; -import forge.game.Game; +import forge.view.IGameView; + import java.util.Observable; import java.util.concurrent.BlockingDeque; import java.util.concurrent.LinkedBlockingDeque; @@ -63,7 +64,7 @@ public class InputQueue extends Observable { * * @return a {@link forge.gui.input.InputBase} object. */ - public final Input getActualInput(Game game) { + public final Input getActualInput(IGameView game) { Input topMost = inputStack.peek(); // incoming input to Control if (topMost != null && !game.isGameOver()) { return topMost; diff --git a/forge-gui/src/main/java/forge/player/GamePlayerUtil.java b/forge-gui/src/main/java/forge/player/GamePlayerUtil.java index 431a4472286..3b8b243223d 100644 --- a/forge-gui/src/main/java/forge/player/GamePlayerUtil.java +++ b/forge-gui/src/main/java/forge/player/GamePlayerUtil.java @@ -1,9 +1,5 @@ package forge.player; -import forge.GuiBase; -import forge.LobbyPlayer; -import forge.game.Game; -import forge.game.player.RegisteredPlayer; import forge.model.FModel; import forge.properties.ForgePreferences; import forge.properties.ForgePreferences.FPref; @@ -69,13 +65,4 @@ public final class GamePlayerUtil { return newName; } - public static RegisteredPlayer getGuiRegisteredPlayer(Game game) { - LobbyPlayer guiPlayer = GuiBase.getInterface().getGuiPlayer(); - for (RegisteredPlayer player : game.getMatch().getPlayers()) { - if (player.getPlayer() == guiPlayer) { - return player; - } - } - return null; - } } diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index 15ff759ca8d..55127481dd6 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -1,14 +1,30 @@ package forge.player; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.lang3.Range; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; + import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import com.google.common.collect.Multimap; -import forge.LobbyPlayer; import forge.GuiBase; +import forge.LobbyPlayer; import forge.card.ColorSet; import forge.card.MagicColor; import forge.card.mana.ManaCost; @@ -20,11 +36,14 @@ import forge.deck.DeckSection; import forge.events.UiEventAttackerDeclared; import forge.game.Game; import forge.game.GameEntity; +import forge.game.GameLog; import forge.game.GameLogEntryType; import forge.game.GameObject; +import forge.game.GameOutcome; import forge.game.GameType; import forge.game.ability.effects.CharmEffect; import forge.game.card.Card; +import forge.game.card.CardFactoryUtil; import forge.game.card.CardShields; import forge.game.card.CounterType; import forge.game.combat.Combat; @@ -37,6 +56,7 @@ import forge.game.phase.PhaseType; import forge.game.player.Player; import forge.game.player.PlayerActionConfirmMode; import forge.game.player.PlayerController; +import forge.game.player.RegisteredPlayer; import forge.game.replacement.ReplacementEffect; import forge.game.spellability.AbilitySub; import forge.game.spellability.SpellAbility; @@ -48,7 +68,17 @@ import forge.game.zone.MagicStack; import forge.game.zone.Zone; import forge.game.zone.ZoneType; import forge.item.PaperCard; -import forge.match.input.*; +import forge.match.input.ButtonUtil; +import forge.match.input.InputAttack; +import forge.match.input.InputBase; +import forge.match.input.InputBlock; +import forge.match.input.InputConfirm; +import forge.match.input.InputConfirmMulligan; +import forge.match.input.InputPassPriority; +import forge.match.input.InputProliferate; +import forge.match.input.InputSelectCardsForConvoke; +import forge.match.input.InputSelectCardsFromList; +import forge.match.input.InputSelectEntitiesFromList; import forge.model.FModel; import forge.properties.ForgePreferences.FPref; import forge.util.ITriggerEvent; @@ -57,13 +87,12 @@ import forge.util.TextUtil; import forge.util.gui.SGuiChoose; import forge.util.gui.SGuiDialog; import forge.util.gui.SOptionPane; - -import org.apache.commons.lang3.Range; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; - -import java.util.*; +import forge.view.CardView; +import forge.view.GameEntityView; +import forge.view.IGameView; +import forge.view.PlayerView; +import forge.view.StackItemView; +import forge.view.ViewUtil; /** @@ -71,13 +100,21 @@ import java.util.*; * * Handles phase skips for now. */ -public class PlayerControllerHuman extends PlayerController { +public class PlayerControllerHuman extends PlayerController implements IGameView { public PlayerControllerHuman(Game game0, Player p, LobbyPlayer lp) { super(game0, p, lp); + // aggressively cache a view for each player + for (final Player player : game.getRegisteredPlayers()) { + getPlayerView(player); + } + // aggressively cache a view for each card + for (final Card c : game.getCardsInGame()) { + getCardView(c); + } } public boolean isUiSetToSkipPhase(final Player turn, final PhaseType phase) { - return !GuiBase.getInterface().stopAtPhase(turn, phase); + return !GuiBase.getInterface().stopAtPhase(getPlayerView(turn), phase); } /** @@ -162,27 +199,31 @@ public class PlayerControllerHuman extends PlayerController { * @see forge.game.player.PlayerController#assignCombatDamage() */ @Override - public Map assignCombatDamage(Card attacker, List blockers, int damageDealt, GameEntity defender, boolean overrideOrder) { + public Map assignCombatDamage(final Card attacker, + final List blockers, final int damageDealt, + final GameEntity defender, final boolean overrideOrder) { // Attacker is a poor name here, since the creature assigning damage // could just as easily be the blocker. - Map map; + final Map map = Maps.newHashMap(); if (defender != null && assignDamageAsIfNotBlocked(attacker)) { - map = new HashMap(); map.put(null, damageDealt); - } - else { + } else { + final List vBlockers = Lists.transform(blockers, FN_GET_CARD_VIEW); if ((attacker.hasKeyword("Trample") && defender != null) || (blockers.size() > 1)) { - map = GuiBase.getInterface().getDamageToAssign(attacker, blockers, damageDealt, defender, overrideOrder); - } - else { - map = new HashMap(); + final CardView vAttacker = getCardView(attacker); + final GameEntityView vDefender = getGameEntityView(defender); + final Map result = GuiBase.getInterface().getDamageToAssign(vAttacker, vBlockers, damageDealt, vDefender, overrideOrder); + for (final Entry e : result.entrySet()) { + map.put(getCard(e.getKey()), e.getValue()); + } + } else { map.put(blockers.get(0), damageDealt); } } return map; } - private final boolean assignDamageAsIfNotBlocked(Card attacker) { + private final boolean assignDamageAsIfNotBlocked(final Card attacker) { return attacker.hasKeyword("CARDNAME assigns its combat damage as though it weren't blocked.") || (attacker.hasKeyword("You may have CARDNAME assign its combat damage as though it weren't blocked.") && SGuiDialog.confirm(attacker, "Do you want to assign its combat damage as though it weren't blocked?")); @@ -235,8 +276,9 @@ public class PlayerControllerHuman extends PlayerController { Card singleChosen = chooseSingleEntityForEffect(sourceList, sa, title, isOptional); return singleChosen == null ? Lists.newArrayList() : Lists.newArrayList(singleChosen); } - GuiBase.getInterface().setPanelSelection(sa.getHostCard()); - + + GuiBase.getInterface().setPanelSelection(getCardView(sa.getHostCard())); + // try to use InputSelectCardsFromList when possible boolean cardsAreInMyHandOrBattlefield = true; for(Card c : sourceList) { @@ -255,7 +297,7 @@ public class PlayerControllerHuman extends PlayerController { return Lists.newArrayList(sc.getSelected()); } - return SGuiChoose.many(title, "Chosen Cards", min, max, sourceList, sa.getHostCard()); + return SGuiChoose.many(title, "Chosen Cards", min, max, sourceList, getCardView(sa.getHostCard())); } @Override @@ -384,21 +426,27 @@ public class PlayerControllerHuman extends PlayerController { } @Override - public List orderBlockers(Card attacker, List blockers) { - GuiBase.getInterface().setPanelSelection(attacker); - return SGuiChoose.order("Choose Damage Order for " + attacker, "Damaged First", blockers, attacker); - } - - @Override - public List orderBlocker(final Card attacker, final Card blocker, final List oldBlockers) { - GuiBase.getInterface().setPanelSelection(attacker); - return SGuiChoose.insertInList("Choose blocker after which to place " + attacker + " in damage order; cancel to place it first", blocker, oldBlockers); + public List orderBlockers(final Card attacker, final List blockers) { + final CardView vAttacker = getCardView(attacker); + GuiBase.getInterface().setPanelSelection(vAttacker); + final List choices = SGuiChoose.order("Choose Damage Order for " + vAttacker, "Damaged First", getCardViews(blockers), vAttacker); + return getCards(choices); } @Override - public List orderAttackers(Card blocker, List attackers) { - GuiBase.getInterface().setPanelSelection(blocker); - return SGuiChoose.order("Choose Damage Order for " + blocker, "Damaged First", attackers, blocker); + public List orderBlocker(final Card attacker, final Card blocker, final List oldBlockers) { + final CardView vAttacker = getCardView(attacker); + GuiBase.getInterface().setPanelSelection(vAttacker); + final List choices = SGuiChoose.insertInList("Choose blocker after which to place " + vAttacker + " in damage order; cancel to place it first", getCardView(blocker), getCardViews(oldBlockers)); + return getCards(choices); + } + + @Override + public List orderAttackers(final Card blocker, final List attackers) { + final CardView vBlocker = getCardView(blocker); + GuiBase.getInterface().setPanelSelection(vBlocker); + final List choices = SGuiChoose.order("Choose Damage Order for " + vBlocker, "Damaged First", getCardViews(attackers), vBlocker); + return getCards(choices); } /* (non-Javadoc) @@ -630,7 +678,7 @@ public class PlayerControllerHuman extends PlayerController { //ensure they're declared and then delay slightly so user can see as much for (Pair attacker : mandatoryAttackers) { combat.addAttacker(attacker.getLeft(), attacker.getRight()); - GuiBase.getInterface().fireEvent(new UiEventAttackerDeclared(attacker.getLeft(), attacker.getRight())); + GuiBase.getInterface().fireEvent(new UiEventAttackerDeclared(getCardView(attacker.getLeft()), getGameEntityView(attacker.getRight()))); } try { Thread.sleep(FControlGamePlayback.combatDelay); @@ -1168,4 +1216,342 @@ public class PlayerControllerHuman extends PlayerController { public boolean isGuiPlayer() { return lobbyPlayer == GuiBase.getInterface().getGuiPlayer(); } + + /* + * What follows are the View methods. + */ + + /** Cache of players. */ + private final BiMap players + = HashBiMap.create(); + /** Cache of cards. */ + private final BiMap cards + = HashBiMap.create(); + /** Cache of stack items. */ + private final BiMap stackItems + = HashBiMap.create(); + + /* (non-Javadoc) + * @see forge.view.IGameView#isCommander() + */ + @Override + public boolean isCommander() { + return game.getRules().hasAppliedVariant(GameType.Commander); + } + /* (non-Javadoc) + * @see forge.view.IGameView#getGameType() + */ + @Override + public GameType getGameType() { + return this.game.getMatch().getRules().getGameType(); + } + + @Override + public boolean isWinner(final LobbyPlayer p) { + return game.getOutcome() == null ? null : game.getOutcome().isWinner(p); + } + + @Override + public LobbyPlayer getWinningPlayer() { + return game.getOutcome() == null ? null : game.getOutcome().getWinningLobbyPlayer(); + } + + @Override + public int getWinningTeam() { + return game.getOutcome() == null ? -1 : game.getOutcome().getWinningTeam(); + } + + /* (non-Javadoc) + * @see forge.view.IGameView#isFirstGameInMatch() + */ + @Override + public boolean isFirstGameInMatch() { + return this.game.getMatch().getPlayedGames().isEmpty(); + } + + @Override + public boolean isMatchOver() { + return this.game.getMatch().isMatchOver(); + } + + @Override + public int getNumPlayedGamesInMatch() { + return this.game.getMatch().getPlayedGames().size(); + } + + @Override + public boolean isMatchWonBy(final LobbyPlayer p) { + return this.game.getMatch().isWonBy(p); + } + + @Override + public int getGamesWonBy(LobbyPlayer p) { + return this.game.getMatch().getGamesWonBy(p); + } + + @Override + public GameOutcome.AnteResult getAnteResult() { + return this.game.getOutcome().anteResult.get(player); + } + + /* (non-Javadoc) + * @see forge.view.IGameView#isCombatDeclareAttackers() + */ + @Override + public boolean isCombatDeclareAttackers() { + return game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_ATTACKERS) + && game.getCombat() != null; + } + + /* (non-Javadoc) + * @see forge.view.IGameView#isGameOver() + */ + @Override + public boolean isGameOver() { + return game.isGameOver(); + } + + @Override + public int getPoisonCountersToLose() { + return game.getRules().getPoisonCountersToLose(); + } + + /* (non-Javadoc) + * @see forge.view.IGameView#subscribeToEvents(java.lang.Object) + */ + @Override + public void subscribeToEvents(final Object subscriber) { + game.subscribeToEvents(subscriber); + } + + // the following methods should eventually be replaced by methods returning + // View classes + /* (non-Javadoc) + * @see forge.view.IGameView#getCombat() + */ + @Override + public Combat getCombat() { + return game.getCombat(); + } + /* (non-Javadoc) + * @see forge.view.IGameView#getGameLog() + */ + @Override + public GameLog getGameLog() { + return game.getGameLog(); + } + /* (non-Javadoc) + * @see forge.view.IGameView#getGuiRegisteredPlayer(forge.LobbyPlayer) + */ + @Override + public RegisteredPlayer getGuiRegisteredPlayer(final LobbyPlayer p) { + for (final RegisteredPlayer player : game.getMatch().getPlayers()) { + if (player.getPlayer() == p) { + return player; + } + } + return null; + } + + /* (non-Javadoc) + * @see forge.view.IGameView#getRegisteredPlayers() + */ + @Override + public List getPlayers() { + return Lists.transform(game.getRegisteredPlayers(), FN_GET_PLAYER_VIEW); + } + + @Override + public PlayerView getPlayerTurn() { + return getPlayerView(game.getPhaseHandler().getPlayerTurn()); + } + + @Override + public PhaseType getPhase() { + return game.getPhaseHandler().getPhase(); + } + + /* (non-Javadoc) + * @see forge.view.IGameView#getStack() + */ + @Override + public List getStack() { + final List items = Collections.unmodifiableList(getStack(game.getStack())); + // clear the cache + stackItems.keySet().retainAll(items); + return items; + } + + /* (non-Javadoc) + * @see forge.view.IGameView#peekStack() + */ + @Override + public StackItemView peekStack() { + final SpellAbilityStackInstance top = + Iterables.getFirst(game.getStack(), null); + if (top == null) { + return null; + } + return getStack(Lists.newArrayList(top)).iterator().next(); + } + + private List getStack(final Iterable stack) { + final List items = Lists.newLinkedList(); + for (final SpellAbilityStackInstance si : stack) { + if (stackItems.containsKey(si)) { + items.add(stackItems.get(si)); + } else { + final StackItemView newItem = new StackItemView( + si.getSpellAbility().toUnsuppressedString(), + si.getSpellAbility().getSourceTrigger(), + si.getStackDescription(), getCardView(si.getSourceCard()), + getPlayerView(si.getActivator()), si.isAbility(), + si.isOptionalTrigger()); + items.add(newItem); + stackItems.put(si, newItem); + } + } + return items; + } + + private GameEntityView getGameEntityView(final GameEntity e) { + if (e instanceof Card) { + return getCardView((Card)e); + } else if (e instanceof Player) { + return getPlayerView((Player)e); + } + return null; + } + + private PlayerView getPlayerView(final Player p) { + if (p == null) { + return null; + } + + final PlayerView view; + if (players.containsKey(p)) { + view = players.get(p); + getPlayerView(p, view); + } else { + view = new PlayerView(p.getLobbyPlayer(), p.getController()); + getPlayerView(p, view); + players.put(p, view); + } + return view; + } + + private final Function FN_GET_PLAYER_VIEW = new Function() { + @Override + public PlayerView apply(final Player input) { + return getPlayerView(input); + } + }; + + private Player getPlayer(final PlayerView p) { + return players.inverse().get(p); + } + + private void getPlayerView(final Player p, final PlayerView view) { + view.setCommanderInfo(CardFactoryUtil.getCommanderInfo(p).trim().replace("\r\n", "; ")); + view.setKeywords(p.getKeywords()); + view.setLife(p.getLife()); + view.setMaxHandSize(p.getMaxHandSize()); + view.setNumDrawnThisTurn(p.getNumDrawnThisTurn()); + view.setPoisonCounters(p.getPoisonCounters()); + view.setPreventNextDamage(p.getPreventNextDamageTotalShields()); + view.setHasUnlimitedHandSize(p.isUnlimitedHandSize()); + view.setAnteCards(getCardViews(p.getCardsIn(ZoneType.Ante))); + view.setBfCards(getCardViews(p.getCardsIn(ZoneType.Battlefield))); + view.setExileCards(getCardViews(p.getCardsIn(ZoneType.Exile))); + view.setFlashbackCards(getCardViews(p.getCardsActivableInExternalZones(false))); + view.setGraveCards(getCardViews(p.getCardsIn(ZoneType.Graveyard))); + view.setHandCards(getCardViews(p.getCardsIn(ZoneType.Hand))); + view.setLibraryCards(getCardViews(p.getCardsIn(ZoneType.Library))); + } + + private CardView getCardView(final Card c) { + if (c == null) { + return null; + } + + final CardView view; + if (cards.containsKey(c)) { + view = cards.get(c); + writeCardToView(c, view); + } else { + view = new CardView(c, c.getUniqueNumber()); + writeCardToView(c, view); + cards.put(c, view); + } + return view; + } + + private final Function FN_GET_CARD_VIEW = new Function() { + @Override + public CardView apply(final Card input) { + return getCardView(input); + } + }; + + private List getCardViews(final List cards) { + return Lists.transform(cards, FN_GET_CARD_VIEW); + } + + private Card getCard(final CardView c) { + return cards.inverse().get(c); + } + + private final Function FN_GET_CARD = new Function() { + @Override + public Card apply(final CardView input) { + return getCard(input); + } + }; + + private List getCards(final List cards) { + return Lists.transform(cards, FN_GET_CARD); + } + + private void writeCardToView(final Card c, final CardView view) { + if (!c.canBeShownTo(player)) { + view.getOriginal().reset(); + view.getAlternate().reset(); + return; + } + + // First, write the values independent of other views. + ViewUtil.writeNonDependentCardViewProperties(c, view); + // Next, write the values that depend on other views. + view.setOwner(getPlayerView(c.getOwner())); + view.setController(getPlayerView(c.getController())); + view.setAttacking(game.getCombat() != null && game.getCombat().isAttacking(c)); + view.setBlocking(game.getCombat() != null && game.getCombat().isBlocking(c)); + view.setChosenPlayer(getPlayerView(c.getChosenPlayer())); + view.setEquipping(getCardView(Iterables.getFirst(c.getEquipping(), null))); + view.setEquippedBy(getCardViews(c.getEquippedBy())); + view.setEnchantingCard(getCardView(c.getEnchantingCard())); + view.setEnchantingPlayer(getPlayerView(c.getEnchantingPlayer())); + view.setEnchantedBy(getCardViews(c.getEnchantedBy())); + view.setFortifiedBy(getCardViews(c.getFortifiedBy())); + view.setGainControlTargets(getCardViews(c.getGainControlTargets())); + view.setCloneOrigin(getCardView(c.getCloneOrigin())); + view.setImprinted(getCardViews(c.getImprinted())); + view.setHauntedBy(getCardViews(c.getHauntedBy())); + view.setHaunting(getCardView(c.getHaunting())); + view.setMustBlock(c.getMustBlockCards() == null ? Collections.emptySet() : Iterables.transform(c.getMustBlockCards(), FN_GET_CARD_VIEW)); + } + + @Override + public boolean mayShowCard(final CardView c, final Player viewer) { + return cards.inverse().get(c).canBeShownTo(viewer); + } + + @Override + public boolean getDisableAutoYields() { + return this.game.getDisableAutoYields(); + } + @Override + public void setDisableAutoYields(final boolean b) { + this.game.setDisableAutoYields(b); + } } diff --git a/forge-gui/src/main/java/forge/player/TargetSelection.java b/forge-gui/src/main/java/forge/player/TargetSelection.java index 80986d48b25..8a9f015ba9d 100644 --- a/forge-gui/src/main/java/forge/player/TargetSelection.java +++ b/forge-gui/src/main/java/forge/player/TargetSelection.java @@ -34,6 +34,8 @@ import forge.game.zone.ZoneType; import forge.match.input.InputSelectTargets; import forge.util.Aggregates; import forge.util.gui.SGuiChoose; +import forge.view.CardView; +import forge.view.SpellAbilityView; import java.util.ArrayList; import java.util.HashMap; @@ -51,9 +53,8 @@ import java.util.Map; public class TargetSelection { private final SpellAbility ability; - - public TargetSelection(final SpellAbility sa) { - this.ability = sa; + public TargetSelection(final SpellAbility currentAbility) { + this.ability = currentAbility; } private final TargetRestrictions getTgt() { @@ -70,7 +71,7 @@ public class TargetSelection { */ public final boolean chooseTargets(Integer numTargets) { - TargetRestrictions tgt = getTgt(); + final TargetRestrictions tgt = getTgt(); final boolean canTarget = tgt != null && tgt.doesTarget(); if (!canTarget) { throw new RuntimeException("TargetSelection.chooseTargets called for ability that does not target - " + ability); @@ -81,8 +82,8 @@ public class TargetSelection { final int maxTargets = numTargets != null ? numTargets.intValue() : tgt.getMaxTargets(ability.getHostCard(), ability); final int numTargeted = ability.getTargets().getNumTargeted(); - boolean hasEnoughTargets = minTargets == 0 || numTargeted >= minTargets; - boolean hasAllTargets = numTargeted == maxTargets && maxTargets > 0; + final boolean hasEnoughTargets = minTargets == 0 || numTargeted >= minTargets; + final boolean hasAllTargets = numTargeted == maxTargets && maxTargets > 0; if (maxTargets == 0) { return true; } // if not enough targets chosen, cancel Ability @@ -105,8 +106,8 @@ public class TargetSelection { final boolean choiceResult; final boolean random = tgt.isRandomTarget(); if (random) { - List candidates = tgt.getAllCandidates(this.ability, true); - GameObject choice = Aggregates.random(candidates); + final List candidates = tgt.getAllCandidates(this.ability, true); + final GameObject choice = Aggregates.random(candidates); return ability.getTargets().add(choice); } else if (zone.size() == 1 && zone.get(0) == ZoneType.Stack) { @@ -115,7 +116,7 @@ public class TargetSelection { return this.chooseCardFromStack(mandatory); } else { - final List validTargets = this.getValidCardsToTarget(); + final List validTargets = this.getValidCardsToTarget(); if (validTargets.isEmpty()) { //if no valid cards to target and only one valid non-card, auto-target the non-card //this handles "target opponent" cards, along with any other cards that can only target a single non-card game entity @@ -162,7 +163,7 @@ public class TargetSelection { *

            * @return */ - private final List getValidCardsToTarget() { + private final List getValidCardsToTarget() { final TargetRestrictions tgt = this.getTgt(); final Game game = ability.getActivatingPlayer().getGame(); final List zone = tgt.getZone(); diff --git a/forge-gui/src/main/java/forge/quest/QuestEventDifficulty.java b/forge-gui/src/main/java/forge/quest/QuestEventDifficulty.java index 804502fcf83..0ad8d40362c 100644 --- a/forge-gui/src/main/java/forge/quest/QuestEventDifficulty.java +++ b/forge-gui/src/main/java/forge/quest/QuestEventDifficulty.java @@ -7,22 +7,28 @@ import org.apache.commons.lang3.StringUtils; * */ public enum QuestEventDifficulty { - EASY("easy"), - MEDIUM("medium"), - HARD("hard"), - EXPERT("very hard"); - - String inFile; - - private QuestEventDifficulty(String storedInFile) { + EASY ("easy", 1. ), + MEDIUM("medium", 1.5), + HARD ("hard", 2. ), + EXPERT("very hard", 3. ); + + private final String inFile; + private final double multiplier; + + private QuestEventDifficulty(final String storedInFile, final double multiplier) { inFile = storedInFile; + this.multiplier = multiplier; } - + public final String getTitle() { return inFile; } - - public static QuestEventDifficulty fromString(String src) { + + public final double getMultiplier() { + return this.multiplier; + } + + public static QuestEventDifficulty fromString(final String src) { if ( StringUtils.isBlank(src) ) return MEDIUM; // player have custom files, that didn't specify a valid difficulty diff --git a/forge-gui/src/main/java/forge/quest/QuestWinLoseController.java b/forge-gui/src/main/java/forge/quest/QuestWinLoseController.java index e3ba75856c0..15f0804c790 100644 --- a/forge-gui/src/main/java/forge/quest/QuestWinLoseController.java +++ b/forge-gui/src/main/java/forge/quest/QuestWinLoseController.java @@ -37,19 +37,21 @@ import forge.quest.data.QuestPreferences.DifficultyPrefs; import forge.quest.data.QuestPreferences.QPref; import forge.util.MyRandom; import forge.util.gui.SGuiChoose; +import forge.view.IGameView; +import forge.view.PlayerView; public abstract class QuestWinLoseController { - private final Game lastGame; + private final IGameView lastGame; private final transient boolean wonMatch; private final transient boolean isAnte; private final transient QuestController qData; private final transient QuestEvent qEvent; - public QuestWinLoseController(Game lastGame0) { - lastGame = lastGame0; + public QuestWinLoseController(final IGameView game0) { + lastGame = game0; qData = FModel.getQuest(); qEvent = qData.getCurrentEvent(); - wonMatch = lastGame.getMatch().isWonBy(GuiBase.getInterface().getQuestPlayer()); + wonMatch = lastGame.isMatchWonBy(GuiBase.getInterface().getQuestPlayer()); isAnte = FModel.getPreferences().getPrefBoolean(FPref.UI_ANTE); } @@ -58,21 +60,21 @@ public abstract class QuestWinLoseController { final QuestController qc = FModel.getQuest(); // After the first game, reset the card shop pool to be able to buy back anted cards - if (lastGame.getMatch().getPlayedGames().size() == 1) { + if (lastGame.getNumPlayedGamesInMatch() == 1) { qc.getCards().clearShopList(); qc.getCards().getShopList(); } final LobbyPlayer questLobbyPlayer = GuiBase.getInterface().getQuestPlayer(); - Player player = null; - for (Player p : lastGame.getRegisteredPlayers()) { + PlayerView player = null; + for (final PlayerView p : lastGame.getPlayers()) { if (p.getLobbyPlayer().equals(questLobbyPlayer)) { player = p; } } - final Player questPlayer = player; + final PlayerView questPlayer = player; - final boolean matchIsNotOver = !lastGame.getMatch().isMatchOver(); + final boolean matchIsNotOver = !lastGame.isMatchOver(); if (matchIsNotOver) { view.getBtnQuit().setText("Quit (-15 Credits)"); } @@ -91,11 +93,8 @@ public abstract class QuestWinLoseController { @Override public void run() { if (isAnte) { - //do per-game actions - GameOutcome outcome = lastGame.getOutcome(); - // Won/lost cards should already be calculated (even in a draw) - GameOutcome.AnteResult anteResult = outcome.anteResult.get(questPlayer); + GameOutcome.AnteResult anteResult = lastGame.getAnteResult(); if (anteResult != null) { if (anteResult.wonCards != null) { qc.getCards().addAllCards(anteResult.wonCards); @@ -103,7 +102,7 @@ public abstract class QuestWinLoseController { if (anteResult.lostCards != null) { qc.getCards().loseCards(anteResult.lostCards); } - anteReport(anteResult.wonCards, anteResult.lostCards, questPlayer.equals(outcome.getWinningPlayer())); + anteReport(anteResult.wonCards, anteResult.lostCards, questPlayer.getLobbyPlayer().equals(lastGame.getWinningPlayer())); } } @@ -223,21 +222,14 @@ public abstract class QuestWinLoseController { // Basic win bonus final int base = FModel.getQuestPreferences().getPrefInt(QPref.REWARDS_BASE); - double multiplier = 1; - - switch (qEvent.getDifficulty()) { - case EASY: multiplier = 1; break; - case MEDIUM: multiplier = 1.5; break; - case HARD: multiplier = 2; break; - case EXPERT: multiplier = 3; break; - } + final double multiplier = qEvent.getDifficulty().getMultiplier(); credBase = (int) (base * multiplier); sb.append(StringUtils.capitalize(qEvent.getDifficulty().getTitle())); sb.append(" opponent: ").append(credBase).append(" credits.\n"); - int creditsForPreviousWins = (int) ((Double.parseDouble(FModel.getQuestPreferences() + final int creditsForPreviousWins = (int) ((Double.parseDouble(FModel.getQuestPreferences() .getPref(QPref.REWARDS_WINS_MULTIPLIER)) * qData.getAchievements().getWin())); credBase += creditsForPreviousWins; @@ -247,8 +239,8 @@ public abstract class QuestWinLoseController { // Gameplay bonuses (for each game win) boolean hasNeverLost = true; int lifeDifferenceCredits = 0; - - LobbyPlayer localHuman = GuiBase.getInterface().getQuestPlayer(); + + final LobbyPlayer localHuman = GuiBase.getInterface().getQuestPlayer(); for (final GameOutcome game : lastGame.getMatch().getPlayedGames()) { if (!game.isWinner(localHuman)) { hasNeverLost = false; diff --git a/forge-gui/src/main/java/forge/util/gui/SGuiChoose.java b/forge-gui/src/main/java/forge/util/gui/SGuiChoose.java index eb9abbed521..4b37b65e2d5 100644 --- a/forge-gui/src/main/java/forge/util/gui/SGuiChoose.java +++ b/forge-gui/src/main/java/forge/util/gui/SGuiChoose.java @@ -14,7 +14,7 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import forge.GuiBase; -import forge.game.card.Card; +import forge.view.CardView; public class SGuiChoose { /** @@ -181,17 +181,17 @@ public class SGuiChoose { return GuiBase.getInterface().getChoices(message, min, max, choices, selected, display); } - public static List many(final String title, final String topCaption, int cnt, final List sourceChoices, Card referenceCard) { + public static List many(final String title, final String topCaption, int cnt, final List sourceChoices, final CardView referenceCard) { return order(title, topCaption, cnt, cnt, sourceChoices, null, referenceCard, false); } - public static List many(final String title, final String topCaption, int min, int max, final List sourceChoices, Card referenceCard) { + public static List many(final String title, final String topCaption, int min, int max, final List sourceChoices, final CardView referenceCard) { int m2 = min >= 0 ? sourceChoices.size() - min : -1; int m1 = max >= 0 ? sourceChoices.size() - max : -1; return order(title, topCaption, m1, m2, sourceChoices, null, referenceCard, false); } - public static List order(final String title, final String top, final List sourceChoices, Card referenceCard) { + public static List order(final String title, final String top, final List sourceChoices, final CardView referenceCard) { return order(title, top, 0, 0, sourceChoices, null, referenceCard, false); } @@ -215,11 +215,10 @@ public class SGuiChoose { } private static List order(final String title, final String top, final int remainingObjectsMin, final int remainingObjectsMax, - final List sourceChoices, final List destChoices, final Card referenceCard, final boolean sideboardingMode) { + final List sourceChoices, final List destChoices, final CardView referenceCard, final boolean sideboardingMode) { return GuiBase.getInterface().order(title, top, remainingObjectsMin, remainingObjectsMax, sourceChoices, destChoices, referenceCard, sideboardingMode); } - // If comparer is NULL, T has to be comparable. Otherwise you'll get an exception from inside the Arrays.sort() routine public static T sortedOneOrNone(final String message, final T[] choices, Comparator comparer) { if ((choices == null) || (choices.length == 0)) { diff --git a/forge-gui/src/main/java/forge/util/gui/SOptionPane.java b/forge-gui/src/main/java/forge/util/gui/SOptionPane.java index 81374d9aeda..d0feb812d16 100644 --- a/forge-gui/src/main/java/forge/util/gui/SOptionPane.java +++ b/forge-gui/src/main/java/forge/util/gui/SOptionPane.java @@ -2,8 +2,7 @@ package forge.util.gui; import forge.GuiBase; import forge.assets.FSkinProp; -import forge.game.card.Card; - +import forge.view.CardView; public class SOptionPane { public static final FSkinProp QUESTION_ICON = FSkinProp.ICO_QUESTION; @@ -61,7 +60,7 @@ public class SOptionPane { return GuiBase.getInterface().showOptionDialog(message, title, icon, options, defaultOption); } - public static int showCardOptionDialog(Card card, String message, String title, FSkinProp icon, String[] options, int defaultOption) { + public static int showCardOptionDialog(CardView card, String message, String title, FSkinProp icon, String[] options, int defaultOption) { return GuiBase.getInterface().showCardOptionDialog(card, message, title, icon, options, defaultOption); }