From 6551ebcce505f3981b1cb8860954519016beb8ac Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Fri, 27 Sep 2019 12:16:07 +0000 Subject: [PATCH] Add feature request Can duplicate tokens with summoning sickness not be in same pile as tokens without it OR the ones without it be on the top? It's really annoying on Android to equip/enchant a token that can attack this turn (need to zoom in, then out). (https://www.slightlymagic.net/forum/viewtopic.php?f=26&t=1516&start=2190#p230560) --- .../src/main/java/forge/game/card/Card.java | 12 ++++++++++ .../main/java/forge/game/card/CardView.java | 3 +++ .../game/event/GameEventTokenStateUpdate.java | 24 +++++++++++++++++++ .../forge/game/event/IGameEventVisitor.java | 2 ++ .../java/forge/game/phase/PhaseHandler.java | 2 ++ .../main/java/forge/game/player/Player.java | 7 ++++++ .../forge/trackable/TrackableProperty.java | 1 + .../src/forge/screens/match/views/VField.java | 3 +++ .../control/FControlGameEventHandler.java | 6 +++++ 9 files changed, 60 insertions(+) create mode 100644 forge-game/src/main/java/forge/game/event/GameEventTokenStateUpdate.java diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index 1803e42b3bf..a47eadf2eec 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -3659,6 +3659,8 @@ public class Card extends GameEntity implements Comparable { if (updateView) { updateKeywords(); + if (isToken()) + game.fireEvent(new GameEventTokenStateUpdate(this)); } } @@ -3713,6 +3715,8 @@ public class Card extends GameEntity implements Comparable { KeywordsChange change = changedCardKeywords.remove(timestamp); if (change != null && updateView) { updateKeywords(); + if (isToken()) + game.fireEvent(new GameEventTokenStateUpdate(this)); } return change; } @@ -5460,6 +5464,14 @@ public class Card extends GameEntity implements Comparable { } return hexproofKey; } + public String getKeywordKey() { + List ability = new ArrayList<>(); + for (final KeywordInterface inst : getKeywords()) { + ability.add(inst.getOriginal()); + } + Collections.sort(ability); + return String.join(",", ability); + } public Zone getZone() { return currentZone; } diff --git a/forge-game/src/main/java/forge/game/card/CardView.java b/forge-game/src/main/java/forge/game/card/CardView.java index cf83a240f5a..845b729ebe0 100644 --- a/forge-game/src/main/java/forge/game/card/CardView.java +++ b/forge-game/src/main/java/forge/game/card/CardView.java @@ -1017,6 +1017,7 @@ public class CardView extends GameEntityView { foilIndexOverride = index0; } + public String getKeywordKey() { return get(TrackableProperty.KeywordKey); } public String getProtectionKey() { return get(TrackableProperty.ProtectionKey); } public String getHexproofKey() { return get(TrackableProperty.HexproofKey); } public boolean hasDeathtouch() { return get(TrackableProperty.HasDeathtouch); } @@ -1076,6 +1077,8 @@ public class CardView extends GameEntityView { set(TrackableProperty.ProtectionKey, c.getProtectionKey()); //set hexproofKeys for Icons set(TrackableProperty.HexproofKey, c.getHexproofKey()); + //keywordkey + set(TrackableProperty.KeywordKey, c.getKeywordKey()); } public boolean isBasicLand() { diff --git a/forge-game/src/main/java/forge/game/event/GameEventTokenStateUpdate.java b/forge-game/src/main/java/forge/game/event/GameEventTokenStateUpdate.java new file mode 100644 index 00000000000..a0e10e652c8 --- /dev/null +++ b/forge-game/src/main/java/forge/game/event/GameEventTokenStateUpdate.java @@ -0,0 +1,24 @@ +package forge.game.event; + +import forge.game.card.Card; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +public class GameEventTokenStateUpdate extends GameEvent { + + public final Collection cards; + public GameEventTokenStateUpdate(Card affected) { + cards = Arrays.asList(affected); + } + + public GameEventTokenStateUpdate(List affected) { + cards = affected; + } + + @Override + public T visit(IGameEventVisitor visitor) { + return visitor.visit(this); + } +} diff --git a/forge-game/src/main/java/forge/game/event/IGameEventVisitor.java b/forge-game/src/main/java/forge/game/event/IGameEventVisitor.java index 8dd56af94d4..d78e2c4fc66 100644 --- a/forge-game/src/main/java/forge/game/event/IGameEventVisitor.java +++ b/forge-game/src/main/java/forge/game/event/IGameEventVisitor.java @@ -37,6 +37,7 @@ public interface IGameEventVisitor { T visit(GameEventPlayerPoisoned event); T visit(GameEventPlayerPriority event); T visit(GameEventPlayerStatsChanged event); + T visit(GameEventTokenStateUpdate event); T visit(GameEventScry event); T visit(GameEventShuffle event); T visit(GameEventSpellAbilityCast gameEventSpellAbilityCast); @@ -83,6 +84,7 @@ public interface IGameEventVisitor { public T visit(GameEventPlayerPoisoned event) { return null; } public T visit(GameEventPlayerPriority event) { return null; } public T visit(GameEventPlayerStatsChanged event) { return null; } + public T visit(GameEventTokenStateUpdate event) { return null; } public T visit(GameEventScry event) { return null; } public T visit(GameEventShuffle event) { return null; } public T visit(GameEventSpellResolved event) { return null; } diff --git a/forge-game/src/main/java/forge/game/phase/PhaseHandler.java b/forge-game/src/main/java/forge/game/phase/PhaseHandler.java index bc7ef03f4a2..48e86dbfa72 100644 --- a/forge-game/src/main/java/forge/game/phase/PhaseHandler.java +++ b/forge-game/src/main/java/forge/game/phase/PhaseHandler.java @@ -189,6 +189,8 @@ public class PhaseHandler implements java.io.Serializable { final List lands = CardLists.filter(playerTurn.getLandsInPlay(), Presets.UNTAPPED); playerTurn.setNumPowerSurgeLands(lands.size()); } + //update tokens + game.fireEvent(new GameEventTokenStateUpdate(playerTurn.getTokensInPlay())); game.fireEvent(new GameEventTurnPhase(playerTurn, phase, phaseType)); } diff --git a/forge-game/src/main/java/forge/game/player/Player.java b/forge-game/src/main/java/forge/game/player/Player.java index 02b148414e7..d707f8c174d 100644 --- a/forge-game/src/main/java/forge/game/player/Player.java +++ b/forge-game/src/main/java/forge/game/player/Player.java @@ -2362,6 +2362,13 @@ public class Player extends GameEntity implements Comparable { return CardLists.filter(getCardsIn(ZoneType.Battlefield), Presets.CREATURES); } + /** + * use to get a list of tokens in play for a given player. + */ + public CardCollection getTokensInPlay() { + return CardLists.filter(getCardsIn(ZoneType.Battlefield), Presets.TOKEN); + } + /** * use to get a list of all lands a given player has on the battlefield. */ diff --git a/forge-game/src/main/java/forge/trackable/TrackableProperty.java b/forge-game/src/main/java/forge/trackable/TrackableProperty.java index 4a7186362c9..bae1cc49933 100644 --- a/forge-game/src/main/java/forge/trackable/TrackableProperty.java +++ b/forge-game/src/main/java/forge/trackable/TrackableProperty.java @@ -82,6 +82,7 @@ public enum TrackableProperty { ChangedColorWords(TrackableTypes.StringMapType), ChangedTypes(TrackableTypes.StringMapType), + KeywordKey(TrackableTypes.StringType), HasDeathtouch(TrackableTypes.BooleanType), HasDefender(TrackableTypes.BooleanType), HasDoubleStrike(TrackableTypes.BooleanType), diff --git a/forge-gui-mobile/src/forge/screens/match/views/VField.java b/forge-gui-mobile/src/forge/screens/match/views/VField.java index 583fecb2710..20ce926a90b 100644 --- a/forge-gui-mobile/src/forge/screens/match/views/VField.java +++ b/forge-gui-mobile/src/forge/screens/match/views/VField.java @@ -110,6 +110,9 @@ public class VField extends FContainer { if (!c.hasCardAttachments() && cardName.equals(c.getCurrentState().getName()) && card.hasSameCounters(c) && + card.getCurrentState().getKeywordKey().equals(c.getCurrentState().getKeywordKey()) && + card.isTapped() == c.isTapped() && // don't stack tapped tokens on untapped tokens + card.isSick() == c.isSick() && //don't stack sick tokens on non sick card.isToken() == c.isToken()) { //don't stack tokens on top of non-tokens CardAreaPanel cPanel = CardAreaPanel.get(c); while (cPanel.getNextPanelInStack() != null) { diff --git a/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java b/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java index 799364cff24..d3bdc446df1 100644 --- a/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java +++ b/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java @@ -357,6 +357,12 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { return processCards(cards, cardsRefreshDetails); } + @Override + public Void visit(final GameEventTokenStateUpdate event) { + processCards(event.cards, cardsRefreshDetails); + return processCards(event.cards, cardsUpdate); + } + @Override public Void visit(final GameEventShuffle event) { //pfps the change to the library has already been performed by a setCards call