From b95d03640162ea79c2f57e19404aeef31549eb79 Mon Sep 17 00:00:00 2001 From: Dragynrain Date: Tue, 6 Jan 2026 12:33:46 -0800 Subject: [PATCH] ImageKeys: Fix image loading for sets with modern folder names When images are downloaded via Scryfall, they are stored in folders using modern set codes (e.g., DST for Darksteel). However, the image lookup system only checked legacy Code2 folders (e.g., DS), causing images to not load on first access in Adventure mode shops. This fix extends hasImage() to check multiple folder locations: 1. Legacy Code2 folder (e.g., DS/) - checked first, wins for duplicates 2. Modern code folder (e.g., DST/) 3. Alias folder (if defined) The fix also handles mixed setups where images may be split across multiple folders, merging contents into the cache while preserving priority for existing legacy folder images. Fixes #9408 --- forge-core/src/main/java/forge/ImageKeys.java | 60 +++++++++++++++---- 1 file changed, 49 insertions(+), 11 deletions(-) diff --git a/forge-core/src/main/java/forge/ImageKeys.java b/forge-core/src/main/java/forge/ImageKeys.java index e6b2c166685..4d02ef13495 100644 --- a/forge-core/src/main/java/forge/ImageKeys.java +++ b/forge-core/src/main/java/forge/ImageKeys.java @@ -431,20 +431,58 @@ public static boolean hasImage(PaperCard pc, boolean update) { if (!aliasSet.isEmpty()) editionAlias.put(setFolder, aliasSet); } - editionHasImage = FileUtil.isDirectoryWithFiles(CACHE_CARD_PICS_DIR + setFolder); + // Build list of all folders that contain images for this set + // This handles mixed setups where images may be split across legacy (Code2), + // modern code, and alias folders (e.g., some in DS/, some in DST/) + List foldersWithImages = new ArrayList<>(); + + // Check Code2 folder first (legacy - highest priority for duplicates) + if (FileUtil.isDirectoryWithFiles(CACHE_CARD_PICS_DIR + setFolder)) { + foldersWithImages.add(setFolder); + } + + // Check modern code and alias folders + if (ed != null) { + String code = ed.getCode(); + if (code != null && !code.equalsIgnoreCase(setFolder)) { + if (FileUtil.isDirectoryWithFiles(CACHE_CARD_PICS_DIR + code)) { + foldersWithImages.add(code); + } + } + String alias = ed.getAlias(); + if (alias != null && !alias.equalsIgnoreCase(setFolder) + && (code == null || !alias.equalsIgnoreCase(code))) { + if (FileUtil.isDirectoryWithFiles(CACHE_CARD_PICS_DIR + alias)) { + foldersWithImages.add(alias); + } + } + } + + editionHasImage = !foldersWithImages.isEmpty(); editionImageLookup.put(pc.getEdition(), editionHasImage); if (editionHasImage) { - File f = new File(CACHE_CARD_PICS_DIR + setFolder); // no need to check this, otherwise editionHasImage would be false! HashSet setFolderContent = new HashSet<>(); - for (String filename : Arrays.asList(f.list())) { - // TODO: should this use FILE_EXTENSIONS ? - if (!filename.endsWith(".jpg") && !filename.endsWith(".png")) - continue; // not image - not interested - setFolderContent.add(filename.split("\\.")[0]); // get rid of any full or fullborder - //preload cachedCards at startUp - String key = setFolder + "/" + filename.replace(".fullborder", ".full").replace(".jpg", "").replace(".png", ""); - File value = new File(CACHE_CARD_PICS_DIR + setFolder + "/" + filename); - cachedCards.put(key, value); + // Process all folders, merging their contents + // First folder in list wins for duplicates (legacy Code2 has priority) + for (String folder : foldersWithImages) { + File f = new File(CACHE_CARD_PICS_DIR + folder); + String[] files = f.list(); + if (files == null) continue; + for (String filename : files) { + // TODO: should this use FILE_EXTENSIONS ? + if (!filename.endsWith(".jpg") && !filename.endsWith(".png")) + continue; // not image - not interested + String cardName = filename.split("\\.")[0]; // get rid of any full or fullborder + setFolderContent.add(cardName); + //preload cachedCards at startUp + // Use setFolder in key (for lookup) but actual folder in path + String key = setFolder + "/" + filename.replace(".fullborder", ".full").replace(".jpg", "").replace(".png", ""); + // Only cache if not already present (first folder wins) + if (!cachedCards.containsKey(key)) { + File value = new File(CACHE_CARD_PICS_DIR + folder + "/" + filename); + cachedCards.put(key, value); + } + } } cachedContent.put(setFolder, setFolderContent); }