From 1a9b54cdd4813aba4298ec553b8a8fac2a50d540 Mon Sep 17 00:00:00 2001 From: elcnesh Date: Wed, 3 Sep 2014 12:21:24 +0000 Subject: [PATCH] Update combat display code in GUI refactoring branch --- .../src/main/java/forge/GuiDesktop.java | 4 +- .../src/main/java/forge/control/FControl.java | 2 +- .../main/java/forge/gui/CardContainer.java | 6 +- .../main/java/forge/gui/CardPicturePanel.java | 7 - .../java/forge/screens/match/CMatchUI.java | 43 ++--- .../screens/match/controllers/CCombat.java | 170 +++++++++--------- .../main/java/forge/interfaces/IGuiBase.java | 4 +- .../forge/player/PlayerControllerHuman.java | 10 +- .../src/main/java/forge/view/CombatView.java | 44 ++++- 9 files changed, 166 insertions(+), 124 deletions(-) diff --git a/forge-gui-desktop/src/main/java/forge/GuiDesktop.java b/forge-gui-desktop/src/main/java/forge/GuiDesktop.java index a1886a018fe..b4b89dfd744 100644 --- a/forge-gui-desktop/src/main/java/forge/GuiDesktop.java +++ b/forge-gui-desktop/src/main/java/forge/GuiDesktop.java @@ -33,7 +33,6 @@ import forge.error.BugReportDialog; import forge.events.UiEvent; import forge.game.GameType; import forge.game.Match; -import forge.game.combat.Combat; import forge.game.phase.PhaseType; import forge.game.player.IHasIcon; import forge.game.player.RegisteredPlayer; @@ -76,6 +75,7 @@ import forge.toolbox.special.PhaseLabel; import forge.util.BuildInfo; import forge.util.ITriggerEvent; import forge.view.CardView; +import forge.view.CombatView; import forge.view.GameEntityView; import forge.view.IGameView; import forge.view.PlayerView; @@ -378,7 +378,7 @@ public class GuiDesktop implements IGuiBase { } @Override - public void showCombat(Combat combat) { + public void showCombat(final CombatView combat) { CMatchUI.SINGLETON_INSTANCE.showCombat(combat); } 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 8fbc46e4eff..5363a6a97c1 100644 --- a/forge-gui-desktop/src/main/java/forge/control/FControl.java +++ b/forge-gui-desktop/src/main/java/forge/control/FControl.java @@ -501,7 +501,7 @@ public enum FControl implements KeyEventDispatcher { final LobbyPlayer humanLobbyPlayer = getGuiPlayer(); // The UI controls should use these game data as models final List players = game0.getPlayers(); - CMatchUI.SINGLETON_INSTANCE.initMatch(players, humanLobbyPlayer); + CMatchUI.SINGLETON_INSTANCE.initMatch(game0, players, humanLobbyPlayer); localPlayer = null; gameHasHumanPlayer = 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 0c0c608a078..778d8629634 100644 --- a/forge-gui-desktop/src/main/java/forge/gui/CardContainer.java +++ b/forge-gui-desktop/src/main/java/forge/gui/CardContainer.java @@ -22,7 +22,7 @@ import forge.view.CardView; /** * The class CardContainer. A card container is an object that references a - * card. + * {@link CardView}. * * @author Clemens Koza * @version V0.0 17.02.2010 @@ -34,7 +34,7 @@ public interface CardContainer { *

* * @param card - * a {@link forge.game.card.Card} object. + * a {@link CardView} object. */ void setCard(CardView card); @@ -43,7 +43,7 @@ public interface CardContainer { * getCard. *

* - * @return a {@link forge.game.card.Card} object. + * @return a {@link CardView} object. */ CardView getCard(); 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 3f89f658b41..76c74aeed9f 100644 --- a/forge-gui-desktop/src/main/java/forge/gui/CardPicturePanel.java +++ b/forge-gui-desktop/src/main/java/forge/gui/CardPicturePanel.java @@ -25,7 +25,6 @@ import javax.swing.JPanel; import forge.ImageCache; import forge.ImageKeys; -import forge.game.card.Card; import forge.item.InventoryItem; import forge.model.FModel; import forge.properties.ForgePreferences.FPref; @@ -61,12 +60,6 @@ public final class CardPicturePanel extends JPanel { this.setImage(); } - @Deprecated - public void setCard(final Card c) { - this.displayed = c; - this.setImage(); - } - public void setCard(final CardStateView c) { this.displayed = c; this.setImage(); 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 e2dcb6a43b1..5e52d045269 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 @@ -42,7 +42,6 @@ import forge.events.IUiEventVisitor; import forge.events.UiEvent; import forge.events.UiEventAttackerDeclared; import forge.events.UiEventBlockerAssigned; -import forge.game.combat.Combat; import forge.game.phase.PhaseType; import forge.game.zone.ZoneType; import forge.gui.framework.EDocID; @@ -71,7 +70,9 @@ import forge.toolbox.FSkin; import forge.toolbox.FSkin.SkinImage; import forge.toolbox.special.PhaseLabel; import forge.view.CardView; +import forge.view.CombatView; import forge.view.GameEntityView; +import forge.view.IGameView; import forge.view.PlayerView; import forge.view.arcane.CardPanel; import forge.view.arcane.PlayArea; @@ -87,6 +88,7 @@ import forge.view.arcane.PlayArea; public enum CMatchUI implements ICDoc, IMenuProvider { SINGLETON_INSTANCE; + private IGameView game; private List sortedPlayers; private VMatchUI view; @@ -122,7 +124,8 @@ public enum CMatchUI implements ICDoc, IMenuProvider { * @param numFieldPanels int * @param numHandPanels int */ - public void initMatch(final List players, LobbyPlayer localPlayer) { + public void initMatch(final IGameView game, final List players, LobbyPlayer localPlayer) { + this.game = game; view = VMatchUI.SINGLETON_INSTANCE; // TODO fix for use with multiplayer @@ -291,33 +294,33 @@ public enum CMatchUI implements ICDoc, IMenuProvider { CDetail.SINGLETON_INSTANCE.showCard(c); CPicture.SINGLETON_INSTANCE.showImage(c); } - + private int getPlayerIndex(PlayerView player) { return sortedPlayers.indexOf(player); } - public void showCombat(Combat combat) { - if (combat != null && combat.getAttackers().size() > 0 && combat.getAttackingPlayer().getGame().getStack().isEmpty()) { - if (selectedDocBeforeCombat == null) { - IVDoc combatDoc = EDocID.REPORT_COMBAT.getDoc(); - if (combatDoc.getParentCell() != null) { - selectedDocBeforeCombat = combatDoc.getParentCell().getSelected(); - if (selectedDocBeforeCombat != combatDoc) { - SDisplayUtil.showTab(combatDoc); - } - else { - selectedDocBeforeCombat = null; //don't need to cache combat doc this way - } - } - } + public void showCombat(final CombatView combat) { + if (combat != null && combat.getNumAttackers() > 0 && game.peekStack() == null) { + if (selectedDocBeforeCombat == null) { + IVDoc combatDoc = EDocID.REPORT_COMBAT.getDoc(); + if (combatDoc.getParentCell() != null) { + selectedDocBeforeCombat = combatDoc.getParentCell().getSelected(); + if (selectedDocBeforeCombat != combatDoc) { + SDisplayUtil.showTab(combatDoc); + } + else { + selectedDocBeforeCombat = null; //don't need to cache combat doc this way + } + } + } } else if (selectedDocBeforeCombat != null) { //re-select doc that was selected before once combat finished - SDisplayUtil.showTab(selectedDocBeforeCombat); - selectedDocBeforeCombat = null; + SDisplayUtil.showTab(selectedDocBeforeCombat); + selectedDocBeforeCombat = null; } CCombat.SINGLETON_INSTANCE.setModel(combat); CCombat.SINGLETON_INSTANCE.update(); - } // showBlockers() + } // showCombat(CombatView) final Set highlightedPlayers = Sets.newHashSet(); public void setHighlighted(PlayerView ge, boolean b) { diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CCombat.java b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CCombat.java index 95015182f97..f7773888c98 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CCombat.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CCombat.java @@ -1,16 +1,18 @@ package forge.screens.match.controllers; +import org.apache.commons.lang3.StringUtils; + +import com.google.common.collect.Iterables; + import forge.UiCommand; -import forge.game.GameEntity; -import forge.game.card.Card; -import forge.game.combat.AttackingBand; -import forge.game.combat.Combat; -import forge.game.player.Player; import forge.gui.framework.ICDoc; import forge.screens.match.views.VCombat; import forge.util.Lang; - -import java.util.List; +import forge.view.CardView; +import forge.view.CardView.CardStateView; +import forge.view.CombatView; +import forge.view.GameEntityView; +import forge.view.PlayerView; /** * Controls the combat panel in the match UI. @@ -22,7 +24,7 @@ public enum CCombat implements ICDoc { /** */ SINGLETON_INSTANCE; - private Combat combat; + private CombatView combat; /* (non-Javadoc) * @see forge.gui.framework.ICDoc#getCommandOnSelect() @@ -44,84 +46,90 @@ public enum CCombat implements ICDoc { */ @Override public void update() { - Combat localCombat = this.combat; // noone will re-assign this from other thread. + final CombatView localCombat = this.combat; // noone will re-assign this from other thread. if (localCombat != null) { - VCombat.SINGLETON_INSTANCE.updateCombat(localCombat.getAttackers().size(), getCombatDescription(localCombat)); - } - else { + VCombat.SINGLETON_INSTANCE.updateCombat(localCombat.getNumAttackers(), getCombatDescription(localCombat)); + } else { VCombat.SINGLETON_INSTANCE.updateCombat(0, ""); } } - - public void setModel(Combat combat) { + + public void setModel(final CombatView combat) { this.combat = combat; } - - private static String getCombatDescription(Combat combat) { + + private static String getCombatDescription(final CombatView localCombat) { final StringBuilder display = new StringBuilder(); - // Not a big fan of the triple nested loop here - for (GameEntity defender : combat.getDefenders()) { - List bands = combat.getAttackingBandsOf(defender); - if (bands == null || bands.isEmpty()) { - continue; - } - - if (display.length() > 0) { - display.append("\n"); - } - - if (defender instanceof Card) { - Player controller = ((Card) defender).getController(); - display.append(Lang.getPossesive(controller.getName())).append(" "); - } - - display.append(defender.getName()).append(" is attacked by:\n"); - - // Associate Bands, Attackers Blockers - boolean previousBand = false; - for(AttackingBand band : bands) { - if (band.isEmpty()) - continue; - - // Space out band blocks from non-band blocks - if (previousBand) { - display.append("\n"); - } - - Boolean blocked = band.isBlocked(); - boolean isBand = band.getAttackers().size() > 1; - if (isBand) { - // Only print Band data if it's actually a band - display.append(" > BAND"); - - if( blocked != null ) - display.append(blocked.booleanValue() ? " (blocked)" : " >>>"); - - display.append("\n"); - } - - for (final Card c : band.getAttackers()) { - display.append(" > "); - display.append(combatantToString(c)).append("\n"); - } - - List blockers = combat.getBlockers(band); - if (!isBand && blockers.isEmpty()) { - // if single creature is blocked, but no longer has blockers, tell the user! - if (blocked != null) - display.append(blocked.booleanValue() ? " (blocked)\n" : " >>>\n"); - } - - for (final Card element : blockers) { - display.append(" < ").append(combatantToString(element)).append("\n"); - } - previousBand = isBand; - } + for (final GameEntityView defender : localCombat.getDefenders()) { + display.append(getCombatDescription(localCombat, defender)); } return display.toString().trim(); } - + + private static String getCombatDescription(final CombatView localCombat, final GameEntityView defender) { + final StringBuilder display = new StringBuilder(); + + Iterable> bands = localCombat.getAttackingBandsOf(defender); + if (bands == null || Iterables.isEmpty(bands)) { + return StringUtils.EMPTY; + } + + display.append("\n"); + + if (defender instanceof CardView) { + final PlayerView controller = ((CardView) defender).getController(); + display.append(Lang.getPossesive(controller.getName())).append(" "); + } + + display.append(defender).append(" is attacked by:\n"); + + // Associate Bands, Attackers Blockers + boolean previousBand = false; + for (final Iterable band : bands) { + final int bandSize = Iterables.size(band); + if (bandSize == 0) { + continue; + } + + // Space out band blocks from non-band blocks + if (previousBand) { + display.append("\n"); + } + + final Iterable blockers = localCombat.getBlockers(band); + boolean blocked = (blockers == null); + boolean isBand = bandSize > 1; + if (isBand) { + // Only print Band data if it's actually a band + display.append(" > BAND"); + display.append(blocked ? " (blocked)" : " >>>"); + display.append("\n"); + } + + for (final CardView attacker : band) { + display.append(" > "); + display.append(combatantToString(attacker)).append("\n"); + } + + if (!isBand) { + if (blockers != null && Iterables.isEmpty(blockers)) { + // if single creature is blocked, but no longer has blockers, tell the user! + display.append(" (blocked)\n"); + } else { + display.append(" >>>\n"); + } + } + + for (final CardView blocker : blockers) { + display.append(" < ").append(combatantToString(blocker)).append("\n"); + } + previousBand = isBand; + } + + return display.toString(); + } + /** *

* combatantToString. @@ -131,15 +139,15 @@ public enum CCombat implements ICDoc { * a {@link forge.game.card.Card} object. * @return a {@link java.lang.String} object. */ - private static String combatantToString(final Card c) { + private static String combatantToString(final CardView c) { final StringBuilder sb = new StringBuilder(); + final CardStateView state = c.getState(); - final String name = (c.isFaceDown()) ? "Morph" : c.getName(); - - sb.append("( ").append(c.getNetAttack()).append(" / ").append(c.getNetDefense()).append(" ) ... "); + final String name = state.getName(); + + sb.append("( ").append(state.getPower()).append(" / ").append(state.getToughness()).append(" ) ... "); sb.append(name); - sb.append(" [").append(c.getUniqueNumber()).append("] "); - + sb.append(" [").append(c.getId()).append("] "); return sb.toString(); } diff --git a/forge-gui/src/main/java/forge/interfaces/IGuiBase.java b/forge-gui/src/main/java/forge/interfaces/IGuiBase.java index 40552274f50..8f97298170f 100644 --- a/forge-gui/src/main/java/forge/interfaces/IGuiBase.java +++ b/forge-gui/src/main/java/forge/interfaces/IGuiBase.java @@ -17,7 +17,6 @@ import forge.deck.CardPool; import forge.events.UiEvent; import forge.game.GameType; import forge.game.Match; -import forge.game.combat.Combat; import forge.game.phase.PhaseType; import forge.game.player.IHasIcon; import forge.game.player.RegisteredPlayer; @@ -29,6 +28,7 @@ import forge.sound.IAudioClip; import forge.sound.IAudioMusic; import forge.util.ITriggerEvent; import forge.view.CardView; +import forge.view.CombatView; import forge.view.GameEntityView; import forge.view.IGameView; import forge.view.PlayerView; @@ -57,7 +57,7 @@ public interface IGuiBase { boolean showBoxedProduct(final String title, final String message, final List list); void fireEvent(UiEvent e); void setCard(CardView card); - void showCombat(Combat combat); + void showCombat(CombatView combat); void setUsedToPay(CardView card, boolean b); void setHighlighted(PlayerView player, boolean b); void showPromptMessage(String message); diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index abbfb00044e..37b0f756f12 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -47,6 +47,7 @@ import forge.game.card.Card; import forge.game.card.CardFactoryUtil; import forge.game.card.CardShields; import forge.game.card.CounterType; +import forge.game.combat.AttackingBand; import forge.game.combat.Combat; import forge.game.combat.CombatUtil; import forge.game.cost.Cost; @@ -1355,10 +1356,11 @@ public class PlayerControllerHuman extends PlayerController implements IGameView } private final void updateCombatView(final Combat combat) { - for (final Card c : combat.getAttackers()) { - final GameEntity defender = combat.getDefenderByAttacker(c); - final List blockers = combat.getBlockers(c); - combatView.addAttacker(getCardView(c), getGameEntityView(defender), getCardViews(blockers)); + combatView.reset(); + for (final AttackingBand b : combat.getAttackingBands()) { + final GameEntity defender = combat.getDefenderByAttacker(b); + final List blockers = b.isBlocked() ? combat.getBlockers(b) : null; + combatView.addAttackingBand(getCardViews(b.getAttackers()), getGameEntityView(defender), getCardViews(blockers)); } } diff --git a/forge-gui/src/main/java/forge/view/CombatView.java b/forge-gui/src/main/java/forge/view/CombatView.java index 15c545bd9c9..717d25eeeb9 100644 --- a/forge-gui/src/main/java/forge/view/CombatView.java +++ b/forge-gui/src/main/java/forge/view/CombatView.java @@ -4,19 +4,30 @@ import java.util.Map; import com.google.common.base.Predicates; import com.google.common.collect.Maps; +import com.google.common.collect.Sets; public class CombatView { private Map attackersWithDefenders; private Map> attackersWithBlockers; + private Map, GameEntityView> bandsWithDefenders; + private Map, Iterable> bandsWithBlockers; public CombatView() { } + public int getNumAttackers() { + return attackersWithDefenders.size(); + } + public Iterable getAttackers() { return attackersWithDefenders.keySet(); } + public Iterable getDefenders() { + return Sets.newHashSet(attackersWithDefenders.values()); + } + public GameEntityView getDefender(final CardView attacker) { return attackersWithDefenders.get(attacker); } @@ -25,13 +36,38 @@ public class CombatView { return attackersWithBlockers.get(attacker); } + /** + * Get an {@link Iterable} of the blockers of the specified band, or + * {@code null} if that band is unblocked. + * + * @param attackingBand + * an {@link Iterable} representing an attacking band. + * @return an {@link Iterable} of {@link CardView} objects, or {@code null}. + */ + public Iterable getBlockers(final Iterable attackingBand) { + return bandsWithBlockers.get(attackingBand); + } + public Iterable getAttackersOf(final GameEntityView defender) { return Maps.filterValues(attackersWithDefenders, Predicates.equalTo(defender)).keySet(); } - - public void addAttacker(final CardView attacker, final GameEntityView defender, final Iterable blockers) { - this.attackersWithDefenders.put(attacker, defender); - this.attackersWithBlockers.put(attacker, blockers); + public Iterable> getAttackingBandsOf(final GameEntityView defender) { + return Maps.filterValues(bandsWithDefenders, Predicates.equalTo(defender)).keySet(); } + public void addAttackingBand(final Iterable attackingBand, final GameEntityView defender, final Iterable blockers) { + for (final CardView attacker : attackingBand) { + this.attackersWithDefenders.put(attacker, defender); + this.attackersWithBlockers.put(attacker, blockers); + } + this.bandsWithDefenders.put(attackingBand, defender); + this.bandsWithBlockers.put(attackingBand, blockers); + } + + public void reset() { + this.attackersWithDefenders = Maps.newHashMap(); + this.attackersWithBlockers = Maps.newHashMap(); + this.bandsWithDefenders = Maps.newHashMap(); + this.bandsWithBlockers = Maps.newHashMap(); + } }