From 07f932ba2520f30edea16935c3a573f283b8f8eb Mon Sep 17 00:00:00 2001 From: shoeless Date: Sun, 9 Aug 2026 17:51:38 -0700 Subject: [PATCH] CardDb: skip redundant loadCard calls that duplicated PaperCards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit loadCard is not idempotent: addSetCard unconditionally increments the art index and appends a fresh PaperCard, so a redundant call for a (name, set) printing already loaded duplicates it in allCardsByName (and, since initialize() resets artIds per edition, the duplicates repeat artIndex 1..n — inflating the art counts CardPool's random-art selection uses). Skip when that exact card's (name, set) printing already exists. The guard matches the card's rules name, not just the lookup name: names can be shared across cards (CopyFaceFrom alt faces, flavor names), and it only applies to resolvable set codes — the null/UNKNOWN-set path is unchanged. Co-Authored-By: Claude Opus 4.8 --- .../src/main/java/forge/card/CardDb.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/forge-core/src/main/java/forge/card/CardDb.java b/forge-core/src/main/java/forge/card/CardDb.java index 2a615dcecffc..403c1569441e 100644 --- a/forge-core/src/main/java/forge/card/CardDb.java +++ b/forge-core/src/main/java/forge/card/CardDb.java @@ -445,6 +445,12 @@ public void loadCard(String cardName, String setCode, CardRules cr) { return; } } + // addSetCard appends unconditionally, so skip if this card's printing from this set + // is already loaded (presence in other sets isn't enough — loadCard also adds new-set printings) + CardEdition guardEd = editions.get(setCode); + if (guardEd != null && !guardEd.equals(CardEdition.UNKNOWN) && hasPrintingInSet(cr, guardEd)) { + return; + } boolean reIndexNecessary = false; CardEdition ed = editions.get(setCode); if (ed == null || ed.equals(CardEdition.UNKNOWN)) { @@ -462,6 +468,18 @@ public void loadCard(String cardName, String setCode, CardRules cr) { } } + /** True if a printing of this card from edition is already loaded (no side effects, unlike getCardFromSet). */ + private boolean hasPrintingInSet(CardRules cr, CardEdition edition) { + String code1 = edition.getCode(), code2 = edition.getCode2(); + for (PaperCard pc : getAllCards(cr)) { + String ed = pc.getEdition(); + if (ed.equalsIgnoreCase(code1) || ed.equalsIgnoreCase(code2)) { + return true; + } + } + return false; + } + public void initialize(boolean logMissingPerEdition, boolean logMissingSummary, boolean enableUnknownCards) { Set allMissingCards = new LinkedHashSet<>(); List missingCards = new ArrayList<>();