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 26c487ab31c..de5f7abad38 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -124,6 +124,9 @@ public class Card extends GameEntity implements Comparable { private final CardChangedWords changedTextTypes = new CardChangedWords(); /** List of the keywords that have been added by text changes. */ private final List keywordsGrantedByTextChanges = Lists.newArrayList(); + + private final Map> cachedKeywords = Maps.newEnumMap(CardStateName.class); + /** Original values of SVars changed by text changes. */ private Map originalSVars = Maps.newHashMap(); @@ -3362,6 +3365,41 @@ public class Card extends GameEntity implements Comparable { return getUnhiddenKeywords(currentState); } public final Collection getUnhiddenKeywords(CardState state) { + CardStateName name = null; + for (Entry entry : states.entrySet()) { + if (entry.getValue().equals(state)) { + name = entry.getKey(); + break; + } + } + if (name == null) { + return Lists.newArrayList(); + } + + if (!cachedKeywords.containsKey(name)) { + updateKeywordsCache(state); + } + return cachedKeywords.get(name); + } + + public final void updateKeywordsCache(final CardState state) { + CardStateName name = null; + for (Entry entry : states.entrySet()) { + if (entry.getValue().equals(state)) { + name = entry.getKey(); + break; + } + } + if (name == null) { + return; + } + + if (cachedKeywords.containsKey(name)) { + cachedKeywords.get(name).clear(); + } else { + cachedKeywords.put(name, Lists.newArrayList()); + } + KeywordCollection keywords = new KeywordCollection(); //final List keywords = Lists.newArrayList(); @@ -3384,7 +3422,7 @@ public class Card extends GameEntity implements Comparable { keywords.insertAll(ck.getKeywords()); } } - return keywords.getValues(); + cachedKeywords.get(name).addAll(keywords.getValues()); } private void visitUnhiddenKeywords(CardState state, Visitor visitor) { if (changedCardKeywords.isEmpty()) { @@ -3396,7 +3434,7 @@ public class Card extends GameEntity implements Comparable { visitor.visit(kw); } } else { - for (KeywordInterface kw : getUnhiddenKeywords()) { + for (KeywordInterface kw : getUnhiddenKeywords(state)) { visitor.visit(kw); } } diff --git a/forge-game/src/main/java/forge/game/card/CardUtil.java b/forge-game/src/main/java/forge/game/card/CardUtil.java index a9e93a04327..7c2338f3dc4 100644 --- a/forge-game/src/main/java/forge/game/card/CardUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardUtil.java @@ -209,6 +209,8 @@ public final class CardUtil { // needed to ensure that the LKI object has correct CMC info no matter what state the original card was in // (e.g. Scrap Trawler + transformed Harvest Hand) newCopy.setLKICMC(in.getCMC()); + // used for the purpose of cards that care about the zone the card was known to be in last + newCopy.setLastKnownZone(in.getLastKnownZone()); if (in.isCloned()) { newCopy.addAlternateState(CardStateName.Cloner, false); @@ -260,8 +262,6 @@ public final class CardUtil { newCopy.setMeldedWith(in.getMeldedWith()); - newCopy.setLastKnownZone(in.getZone()); // used for the purpose of cards that care about the zone the card was known to be in last - return newCopy; } 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 1e924c9aecc..90d0cd59bad 100644 --- a/forge-game/src/main/java/forge/game/card/CardView.java +++ b/forge-game/src/main/java/forge/game/card/CardView.java @@ -977,6 +977,7 @@ public class CardView extends GameEntityView { set(TrackableProperty.AbilityText, c.getAbilityText(state)); } void updateKeywords(Card c, CardState state) { + c.updateKeywordsCache(state); set(TrackableProperty.HasDeathtouch, c.hasKeyword("Deathtouch", state)); set(TrackableProperty.HasHaste, c.hasKeyword("Haste", state)); set(TrackableProperty.HasInfect, c.hasKeyword("Infect", state));