From 45a59fe77ab9e33d394bcae5f4bf28701e637c65 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Fri, 1 Sep 2023 21:28:30 +0200 Subject: [PATCH 1/3] Treat rebranded versions extra --- .../src/main/java/forge/card/CardDb.java | 41 ++++++++++++++++++- .../src/main/java/forge/card/CardFace.java | 15 ++++++- .../src/main/java/forge/card/CardRules.java | 2 +- .../havengul_laboratory_havengul_mystery.txt | 25 ----------- ...ns_national_laboratory_the_upside_down.txt | 2 + 5 files changed, 56 insertions(+), 29 deletions(-) delete mode 100644 forge-gui/res/cardsfolder/h/havengul_laboratory_havengul_mystery.txt diff --git a/forge-core/src/main/java/forge/card/CardDb.java b/forge-core/src/main/java/forge/card/CardDb.java index e0a8bbc3639..37f2ac6504c 100644 --- a/forge-core/src/main/java/forge/card/CardDb.java +++ b/forge-core/src/main/java/forge/card/CardDb.java @@ -293,6 +293,9 @@ public final class CardDb implements ICardDatabase, IDeckGenPool { CardEdition upcomingSet = null; Date today = new Date(); + // do this first so they're not considered missing + buildRenamedCards(); + for (CardEdition e : editions.getOrderedEditions()) { boolean coreOrExpSet = e.getType() == CardEdition.Type.CORE || e.getType() == CardEdition.Type.EXPANSION; boolean isCoreExpSet = coreOrExpSet || e.getType() == CardEdition.Type.REPRINT; @@ -353,6 +356,38 @@ public final class CardDb implements ICardDatabase, IDeckGenPool { reIndex(); } + private void buildRenamedCards() { + // for now just check Universes Within + for (CardInSet cis : editions.get("SLX").getCards()) { + String orgName = alternateName.get(cis.name); + if (orgName != null) { + // found original (beyond) print + CardRules org = getRules(orgName); + + CardFace renamedMain = (CardFace) ((CardFace) org.getMainPart()).clone(); + renamedMain.setName(renamedMain.getAltName()); + renamedMain.setAltName(null); + // TODO this could mess up some "named ..." cardname literals but there's no printing like that currently + renamedMain.setOracleText(renamedMain.getOracleText().replace(orgName, renamedMain.getName())); + facesByName.put(renamedMain.getName(), renamedMain); + CardFace renamedOther = null; + if (org.getOtherPart() != null) { + renamedOther = (CardFace) ((CardFace) org.getOtherPart()).clone(); + orgName = renamedOther.getName(); + renamedOther.setName(renamedOther.getAltName()); + renamedOther.setAltName(null); + renamedOther.setOracleText(renamedOther.getOracleText().replace(orgName, renamedOther.getName())); + facesByName.put(renamedOther.getName(), renamedOther); + } + + CardRules within = new CardRules(new ICardFace[] { renamedMain, renamedOther, null, null, null, null, null }, org.getSplitType(), org.getAiHints()); + // so workshop can edit same script + within.setNormalizedName(org.getNormalizedName()); + rulesByName.put(cis.name, within); + } + } + } + public void addCard(PaperCard paperCard) { if (excludeCard(paperCard.getName(), paperCard.getEdition())) return; @@ -930,7 +965,11 @@ public final class CardDb implements ICardDatabase, IDeckGenPool { } public String getName(final String cardName) { - if (alternateName.containsKey(cardName)) { + return getName(cardName, false); + } + public String getName(final String cardName, boolean engine) { + if (alternateName.containsKey(cardName) && engine) { + // TODO might want to implement GUI option so it always fetches the Within version return alternateName.get(cardName); } return cardName; diff --git a/forge-core/src/main/java/forge/card/CardFace.java b/forge-core/src/main/java/forge/card/CardFace.java index 0d5c5bfc622..d35ceb0670e 100644 --- a/forge-core/src/main/java/forge/card/CardFace.java +++ b/forge-core/src/main/java/forge/card/CardFace.java @@ -20,7 +20,7 @@ import forge.card.mana.ManaCost; *

* Do not use reference to class except for card parsing.
Always use reference to interface type outside of package.
*/ -final class CardFace implements ICardFace { +final class CardFace implements ICardFace, Cloneable { public enum FaceSelectionMethod { // USE_ACTIVE_FACE, @@ -32,7 +32,7 @@ final class CardFace implements ICardFace { private final static List emptyList = Collections.unmodifiableList(new ArrayList<>()); private final static Map emptyMap = Collections.unmodifiableMap(new TreeMap<>()); - private final String name; + private String name; private String altName = null; private CardType type = null; private ManaCost manaCost = ManaCost.NO_COST; @@ -86,6 +86,7 @@ final class CardFace implements ICardFace { throw new RuntimeException("Card name is empty"); } // Here come setters to allow parser supply values + void setName(String name) { this.name = name; } void setAltName(String name) { this.altName = name; } void setType(CardType type0) { this.type = type0; } void setManaCost(ManaCost manaCost0) { this.manaCost = manaCost0; } @@ -153,4 +154,14 @@ final class CardFace implements ICardFace { public int compareTo(ICardFace o) { return getName().compareTo(o.getName()); } + + /** {@inheritDoc} */ + @Override + public final Object clone() { + try { + return super.clone(); + } catch (final Exception ex) { + throw new RuntimeException("CardFace : clone() error, " + ex); + } + } } diff --git a/forge-core/src/main/java/forge/card/CardRules.java b/forge-core/src/main/java/forge/card/CardRules.java index 29a31ad0b79..46e920b7a47 100644 --- a/forge-core/src/main/java/forge/card/CardRules.java +++ b/forge-core/src/main/java/forge/card/CardRules.java @@ -55,7 +55,7 @@ public final class CardRules implements ICardCharacteristics { private String partnerWith; private boolean custom; - private CardRules(ICardFace[] faces, CardSplitType altMode, CardAiHints cah) { + public CardRules(ICardFace[] faces, CardSplitType altMode, CardAiHints cah) { splitType = altMode; mainPart = faces[0]; otherPart = faces[1]; diff --git a/forge-gui/res/cardsfolder/h/havengul_laboratory_havengul_mystery.txt b/forge-gui/res/cardsfolder/h/havengul_laboratory_havengul_mystery.txt deleted file mode 100644 index ccbae2433a1..00000000000 --- a/forge-gui/res/cardsfolder/h/havengul_laboratory_havengul_mystery.txt +++ /dev/null @@ -1,25 +0,0 @@ -Name:Havengul Laboratory -ManaCost:no cost -Types:Legendary Land -A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}. -A:AB$ Investigate | Cost$ 4 T | SpellDescription$ Investigate. (Create a Clue token. It's an artifact with "{2}, Sacrifice this artifact: Draw a card.") -T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | CheckSVar$ ClueResearch | SVarCompare$ GE3 | Execute$ TrigTransform | TriggerDescription$ At the beginning of your end step, if you sacrificed three or more clues this turn, transform CARDNAME. -SVar:TrigTransform:DB$ SetState | Defined$ Self | Mode$ Transform -SVar:ClueResearch:PlayerCountPropertyYou$SacrificedThisTurn Clue -DeckHas:Ability$Investigate|Token|Sacrifice|Graveyard -DeckHints:Ability$Investigate -AlternateMode:DoubleFaced -Oracle:{T}: Add {C}.\n{4}, {T}: Investigate. (Create a Clue token. It's an artifact with "{2}, Sacrifice this artifact: Draw a card.")\nAt the beginning of your end step, if you sacrificed three or more clues this turn, transform Havengul Laboratory. - -ALTERNATE - -Name:Havengul Mystery -ManaCost:no cost -Types:Legendary Land -T:Mode$ Transformed | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerDescription$ When this land transforms into CARDNAME, return target creature card from your graveyard to the battlefield. -SVar:TrigReturn:DB$ ChangeZone | ValidTgts$ Creature.YouOwn | TgtPrompt$ Select target creature card from your graveyard | Origin$ Graveyard | Destination$ Battlefield | RememberTargets$ True -T:Mode$ ChangesZone | ValidCard$ Card.IsRemembered | Origin$ Battlefield | Destination$ Any | Execute$ TrigTransform2 | TriggerZones$ Battlefield | TriggerDescription$ When the creature card put onto the battlefield with CARDNAME leaves the battlefield, transform CARDNAME. -SVar:TrigTransform2:DB$ SetState | Defined$ Self | Mode$ Transform | SubAbility$ DBCleanup -SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True -A:AB$ Mana | Cost$ T PayLife<1> | Produced$ B | SpellDescription$ Add {B}. -Oracle:When this land transforms into Havengul Mystery, return target creature card from your graveyard to the battlefield.\nWhen the creature card put onto the battlefield with Havengul Mystery leaves the battlefield, transform Havengul Mystery.\n{T}, Pay 1 life: Add {B}. diff --git a/forge-gui/res/cardsfolder/h/hawkins_national_laboratory_the_upside_down.txt b/forge-gui/res/cardsfolder/h/hawkins_national_laboratory_the_upside_down.txt index 9c00c750aa4..f53fc7d0c35 100644 --- a/forge-gui/res/cardsfolder/h/hawkins_national_laboratory_the_upside_down.txt +++ b/forge-gui/res/cardsfolder/h/hawkins_national_laboratory_the_upside_down.txt @@ -1,4 +1,5 @@ Name:Hawkins National Laboratory +AltName:Havengul Laboratory ManaCost:no cost Types:Legendary Land A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}. @@ -14,6 +15,7 @@ Oracle:{T}: Add {C}.\n{4}, {T}: Investigate.\nAt the beginning of your end step, ALTERNATE Name:The Upside Down +AltName:Havengul Mystery ManaCost:no cost Types:Legendary Land T:Mode$ Transformed | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerDescription$ When this land transforms into CARDNAME, return target creature card from your graveyard to the battlefield. From 54302fc89b28d9452a0d6c3893485d48c9ea5e9f Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Fri, 1 Sep 2023 21:30:12 +0200 Subject: [PATCH 2/3] Account for rebranded cards --- .../main/java/forge/deck/generation/DeckGeneratorBase.java | 1 + .../forge/screens/deckeditor/controllers/ACEditorBase.java | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/forge-core/src/main/java/forge/deck/generation/DeckGeneratorBase.java b/forge-core/src/main/java/forge/deck/generation/DeckGeneratorBase.java index 87bb8b48e0a..3b23a851054 100644 --- a/forge-core/src/main/java/forge/deck/generation/DeckGeneratorBase.java +++ b/forge-core/src/main/java/forge/deck/generation/DeckGeneratorBase.java @@ -130,6 +130,7 @@ public abstract class DeckGeneratorBase { int res = 0; while (res < cnt) { PaperCard cp = source.get(MyRandom.getRandom().nextInt(srcLen)); + // TODO AltName conversion needed? int newCount = cardCounts.get(cp.getName()) + 1; //add card to deck if not already maxed out on card diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/ACEditorBase.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/ACEditorBase.java index 750d7c94112..08289e0b102 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/ACEditorBase.java +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/ACEditorBase.java @@ -215,7 +215,7 @@ public abstract class ACEditorBase> cardsByName = null; if (deck != null) { final CardPool allCards = deck.getAllCardsInASinglePool(deck.has(DeckSection.Commander)); - cardsByName = Aggregates.groupSumBy(allCards, PaperCard.FN_GET_NAME); + cardsByName = Aggregates.groupSumBy(allCards, pc -> pc.getRules().getNormalizedName()); } for (final Entry itemEntry : itemsToAdd) { @@ -237,7 +237,7 @@ public abstract class ACEditorBase cardAmountInfo = Iterables.find(cardsByName, new Predicate>() { @Override public boolean apply(Entry t) { - return t.getKey().equals(card.getName()); + return t.getKey().equals(card.getRules().getNormalizedName()); } }, null); if (cardAmountInfo != null) { From 770db2c56a5cbcbb674e7b5369ef0e219de2cdf4 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Fri, 1 Sep 2023 21:31:20 +0200 Subject: [PATCH 3/3] Rebranded is same name --- .../src/main/java/forge/game/card/Card.java | 16 +++++++++------- .../src/main/java/forge/game/card/CardView.java | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) 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 98c7ca8f3e3..a346348a822 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -859,21 +859,23 @@ public class Card extends GameEntity implements Comparable, IHasSVars { @Override public final String getName() { - return getName(currentState); + return getName(currentState, false); } + public final String getName(boolean alt) { + return getName(currentState, alt); + } public final String getName(CardStateName stateName) { - return getName(getState(stateName)); + return getName(getState(stateName), false); } - - public final String getName(CardState state) { + public final String getName(CardState state, boolean alt) { String name = state.getName(); for (CardChangedName change : this.changedCardNames.values()) { if (change.isOverwrite()) { name = change.getNewName(); } } - return name; + return alt ? StaticData.instance().getCommonCards().getName(name, true) : name; } public final boolean hasNonLegendaryCreatureNames() { @@ -5526,7 +5528,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { return true; } } - return sharesNameWith(c1.getName()); + return sharesNameWith(c1.getName(true)); } public final boolean sharesNameWith(final String name) { @@ -5535,7 +5537,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { return false; } - boolean shares = getName().equals(name); + boolean shares = getName(true).equals(name); // Split cards has extra logic to check if it does share a name with if (isSplitCard()) { 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 56cf2f352cb..18d247a71cd 100644 --- a/forge-game/src/main/java/forge/game/card/CardView.java +++ b/forge-game/src/main/java/forge/game/card/CardView.java @@ -1184,7 +1184,7 @@ public class CardView extends GameEntityView { } void updateName(CardState c) { Card card = c.getCard(); - setName(card.getName(c)); + setName(card.getName(c, false)); if (CardView.this.getCurrentState() == this) { if (card != null) {