Skip to content

Commit 42e35cb

Browse files
shoelessclaude
andcommitted
CardDb: make loadCard idempotent (fix latent duplicate-PaperCard bug)
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. Skip when that exact (name, set) printing already exists. Guarding on card-name presence alone would break the "add a printing from a not-yet-loaded set" path (StaticData.getOrLoadCommonCard), where the card can exist under other sets while the requested set's printing is still missing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TGBC7aB5gagjvXk9qCgC2d
1 parent 926eebe commit 42e35cb

1 file changed

Lines changed: 18 additions & 0 deletions

File tree

forge-core/src/main/java/forge/card/CardDb.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,12 @@ public void loadCard(String cardName, String setCode, CardRules cr) {
445445
return;
446446
}
447447
}
448+
// idempotency: addSetCard appends unconditionally, so skip if this exact (name,set)
449+
// printing is already loaded (guarding on name alone would break the load-new-set path)
450+
CardEdition guardEd = editions.get(setCode);
451+
if (guardEd != null && !guardEd.equals(CardEdition.UNKNOWN) && hasPrintingInSet(cardName, guardEd)) {
452+
return;
453+
}
448454
boolean reIndexNecessary = false;
449455
CardEdition ed = editions.get(setCode);
450456
if (ed == null || ed.equals(CardEdition.UNKNOWN)) {
@@ -462,6 +468,18 @@ public void loadCard(String cardName, String setCode, CardRules cr) {
462468
}
463469
}
464470

471+
/** True if a printing of cardName from edition is already loaded (no side effects, unlike getCardFromSet). */
472+
private boolean hasPrintingInSet(String cardName, CardEdition edition) {
473+
String code1 = edition.getCode(), code2 = edition.getCode2();
474+
for (PaperCard pc : getAllCards(cardName)) {
475+
String ed = pc.getEdition();
476+
if (ed.equalsIgnoreCase(code1) || ed.equalsIgnoreCase(code2)) {
477+
return true;
478+
}
479+
}
480+
return false;
481+
}
482+
465483
public void initialize(boolean logMissingPerEdition, boolean logMissingSummary, boolean enableUnknownCards) {
466484
Set<String> allMissingCards = new LinkedHashSet<>();
467485
List<String> missingCards = new ArrayList<>();

0 commit comments

Comments
 (0)