From e4799a4f73dbef3a21b62d53e3ac5302371d0694 Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Sun, 1 Jun 2025 23:09:27 +0200 Subject: [PATCH] ImageKeys: unify PaperCard imageKeys --- forge-core/src/main/java/forge/ImageKeys.java | 48 ++++- .../src/main/java/forge/card/CardEdition.java | 11 ++ .../src/main/java/forge/card/CardRules.java | 46 +++-- .../src/main/java/forge/item/PaperCard.java | 39 ++-- .../src/main/java/forge/util/ImageUtil.java | 141 +++++++++------ .../src/main/java/forge/game/card/Card.java | 24 --- .../java/forge/game/card/CardFactory.java | 16 +- .../main/java/forge/game/card/CardView.java | 12 ++ .../forge/trackable/TrackableProperty.java | 1 + .../src/main/java/forge/ImageCache.java | 91 ++++------ .../src/main/java/forge/ImageLoader.java | 3 +- .../forge/toolbox/imaging/FImageUtil.java | 33 ---- .../java/forge/util/SwingImageFetcher.java | 12 +- .../src/forge/adventure/util/RewardActor.java | 11 +- .../src/forge/assets/ImageCache.java | 3 - .../src/forge/card/CardImageRenderer.java | 12 +- forge-gui-mobile/src/forge/card/CardZoom.java | 7 +- .../java/forge/player/HumanCostDecision.java | 6 +- .../forge/player/PlayerControllerHuman.java | 2 +- .../main/java/forge/util/ImageFetcher.java | 169 +++++++----------- 20 files changed, 323 insertions(+), 364 deletions(-) diff --git a/forge-core/src/main/java/forge/ImageKeys.java b/forge-core/src/main/java/forge/ImageKeys.java index 9e88336b61d..ae901c90d1d 100644 --- a/forge-core/src/main/java/forge/ImageKeys.java +++ b/forge-core/src/main/java/forge/ImageKeys.java @@ -33,11 +33,6 @@ public final class ImageKeys { public static final String RADIATION_IMAGE = "radiation"; public static final String BACKFACE_POSTFIX = "$alt"; - public static final String SPECFACE_W = "$wspec"; - public static final String SPECFACE_U = "$uspec"; - public static final String SPECFACE_B = "$bspec"; - public static final String SPECFACE_R = "$rspec"; - public static final String SPECFACE_G = "$gspec"; private static String CACHE_CARD_PICS_DIR, CACHE_TOKEN_PICS_DIR, CACHE_ICON_PICS_DIR, CACHE_BOOSTER_PICS_DIR, CACHE_FATPACK_PICS_DIR, CACHE_BOOSTERBOX_PICS_DIR, CACHE_PRECON_PICS_DIR, CACHE_TOURNAMENTPACK_PICS_DIR; @@ -97,13 +92,28 @@ public final class ImageKeys { return cachedCards.get(key); } public static File getImageFile(String key) { + return getImageFile(key, false); + } + public static File getImageFile(String key, boolean artCrop) { if (StringUtils.isEmpty(key)) return null; final String dir; final String filename; String[] tempdata = null; - if (key.startsWith(ImageKeys.TOKEN_PREFIX)) { + if (key.startsWith(ImageKeys.CARD_PREFIX)) { + tempdata = key.substring(ImageKeys.CARD_PREFIX.length()).split("\\|"); + String tokenname = tempdata[0]; + if (tempdata.length > 1) { + tokenname += "_" + tempdata[1]; + } + if (tempdata.length > 2) { + tokenname += "_" + tempdata[2]; + } + filename = tokenname ; + + dir = CACHE_CARD_PICS_DIR; + } else if (key.startsWith(ImageKeys.TOKEN_PREFIX)) { tempdata = key.substring(ImageKeys.TOKEN_PREFIX.length()).split("\\|"); String tokenname = tempdata[0]; if (tempdata.length > 1) { @@ -154,7 +164,31 @@ public final class ImageKeys { cachedCards.put(filename, file); return file; } - if (dir.equals(CACHE_TOKEN_PICS_DIR)) { + if (tempdata != null && dir.equals(CACHE_CARD_PICS_DIR)) { + String setlessFilename = tempdata[0] + (artCrop ? ".artcrop" : ".fullborder"); + String setCode = tempdata.length > 1 ? tempdata[1] : ""; + String collectorNumber = tempdata.length > 2 ? tempdata[2] : ""; + if (!setCode.isEmpty()) { + if (!collectorNumber.isEmpty()) { + file = findFile(dir, setCode + "/" + collectorNumber + "_" + setlessFilename); + if (file != null) { + cachedCards.put(filename, file); + return file; + } + } + file = findFile(dir, setCode + "/" + setlessFilename); + if (file != null) { + cachedCards.put(filename, file); + return file; + } + } + file = findFile(dir, setlessFilename); + if (file != null) { + cachedCards.put(filename, file); + return file; + } + } + if (tempdata != null && dir.equals(CACHE_TOKEN_PICS_DIR)) { String setlessFilename = tempdata[0]; String setCode = tempdata.length > 1 ? tempdata[1] : ""; String collectorNumber = tempdata.length > 2 ? tempdata[2] : ""; diff --git a/forge-core/src/main/java/forge/card/CardEdition.java b/forge-core/src/main/java/forge/card/CardEdition.java index 316b7f9951f..810b77b7626 100644 --- a/forge-core/src/main/java/forge/card/CardEdition.java +++ b/forge-core/src/main/java/forge/card/CardEdition.java @@ -433,6 +433,17 @@ public final class CardEdition implements Comparable { public Multimap getTokens() { return tokenMap; } + public EditionEntry getTokenFromCollectorNumber(String collectorNumber) { + if(collectorNumber == null || collectorNumber.isEmpty()) + return null; + for(EditionEntry c : this.tokenMap.values()) { + //Could build a map for this one too if it's used for more than one-offs. + if (c.collectorNumber.equalsIgnoreCase(collectorNumber)) + return c; + } + return null; + } + public String getTokenSet(String token) { if (tokenMap.containsKey(token)) { return this.getCode(); diff --git a/forge-core/src/main/java/forge/card/CardRules.java b/forge-core/src/main/java/forge/card/CardRules.java index fe6f4aba3bf..851d99be341 100644 --- a/forge-core/src/main/java/forge/card/CardRules.java +++ b/forge-core/src/main/java/forge/card/CardRules.java @@ -20,6 +20,8 @@ package forge.card; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; + +import forge.StaticData; import forge.card.mana.IParserManaCost; import forge.card.mana.ManaCost; import forge.card.mana.ManaCostShard; @@ -149,6 +151,10 @@ public final class CardRules implements ICardCharacteristics { return splitType; } + public boolean hasBackSide() { + return CardSplitType.DUAL_FACED_CARDS.contains(splitType) || splitType == CardSplitType.Flip; + } + public ICardFace getMainPart() { return mainPart; } @@ -165,20 +171,32 @@ public final class CardRules implements ICardCharacteristics { return Iterables.concat(Arrays.asList(mainPart, otherPart), specializedParts.values()); } - public ICardFace getWSpecialize() { - return specializedParts.get(CardStateName.SpecializeW); - } - public ICardFace getUSpecialize() { - return specializedParts.get(CardStateName.SpecializeU); - } - public ICardFace getBSpecialize() { - return specializedParts.get(CardStateName.SpecializeB); - } - public ICardFace getRSpecialize() { - return specializedParts.get(CardStateName.SpecializeR); - } - public ICardFace getGSpecialize() { - return specializedParts.get(CardStateName.SpecializeG); + public String getImageName(CardStateName state) { + if (splitType == CardSplitType.Split) { + return mainPart.getName() + otherPart.getName(); + } else if (state.equals(splitType.getChangedStateName())) { + if (otherPart != null) { + return otherPart.getName(); + } else if (this.hasBackSide()) { + if (!getMeldWith().isEmpty()) { + final CardDb db = StaticData.instance().getCommonCards(); + return db.getRules(getMeldWith()).getOtherPart().getName(); + } + return null; + } + } + + switch (state) { + case SpecializeW: + case SpecializeU: + case SpecializeB: + case SpecializeR: + case SpecializeG: + ICardFace face = specializedParts.get(state); + return face != null ? face.getName() : null; + default: + return getName(); + } } public String getName() { diff --git a/forge-core/src/main/java/forge/item/PaperCard.java b/forge-core/src/main/java/forge/item/PaperCard.java index 942f88b5536..aa1e09212aa 100644 --- a/forge-core/src/main/java/forge/item/PaperCard.java +++ b/forge-core/src/main/java/forge/item/PaperCard.java @@ -24,7 +24,6 @@ import forge.util.CardTranslation; import forge.util.ImageUtil; import forge.util.Localizer; import forge.util.TextUtil; -import org.apache.commons.lang3.StringUtils; import java.io.*; import java.util.*; @@ -364,20 +363,14 @@ public class PaperCard implements Comparable, InventoryItemFromSet, @Override public String getImageKey(boolean altState) { - String normalizedName = StringUtils.stripAccents(name); - String imageKey = ImageKeys.CARD_PREFIX + normalizedName + CardDb.NameSetSeparator - + edition + CardDb.NameSetSeparator + artIndex; - if (altState) { - imageKey += ImageKeys.BACKFACE_POSTFIX; - } - return imageKey; + return altState ? this.getCardAltImageKey() : this.getCardImageKey(); } private String cardImageKey = null; @Override public String getCardImageKey() { if (this.cardImageKey == null) - this.cardImageKey = ImageUtil.getImageKey(this, "", true); + this.cardImageKey = ImageUtil.getImageKey(this, CardStateName.Original); return cardImageKey; } @@ -386,9 +379,9 @@ public class PaperCard implements Comparable, InventoryItemFromSet, public String getCardAltImageKey() { if (this.cardAltImageKey == null){ if (this.hasBackFace()) - this.cardAltImageKey = ImageUtil.getImageKey(this, "back", true); + this.cardAltImageKey = ImageUtil.getImageKey(this, this.getRules().getSplitType().getChangedStateName()); else // altImageKey will be the same as cardImageKey - this.cardAltImageKey = ImageUtil.getImageKey(this, "", true); + this.cardAltImageKey = getCardImageKey(); } return cardAltImageKey; } @@ -398,9 +391,9 @@ public class PaperCard implements Comparable, InventoryItemFromSet, public String getCardWSpecImageKey() { if (this.cardWSpecImageKey == null) { if (this.rules.getSplitType() == CardSplitType.Specialize) - this.cardWSpecImageKey = ImageUtil.getImageKey(this, "white", true); + this.cardWSpecImageKey = ImageUtil.getImageKey(this, CardStateName.SpecializeW); else // just use cardImageKey - this.cardWSpecImageKey = ImageUtil.getImageKey(this, "", true); + this.cardWSpecImageKey = getCardImageKey(); } return cardWSpecImageKey; } @@ -410,9 +403,9 @@ public class PaperCard implements Comparable, InventoryItemFromSet, public String getCardUSpecImageKey() { if (this.cardUSpecImageKey == null) { if (this.rules.getSplitType() == CardSplitType.Specialize) - this.cardUSpecImageKey = ImageUtil.getImageKey(this, "blue", true); + this.cardUSpecImageKey = ImageUtil.getImageKey(this, CardStateName.SpecializeU); else // just use cardImageKey - this.cardUSpecImageKey = ImageUtil.getImageKey(this, "", true); + this.cardUSpecImageKey = getCardImageKey(); } return cardUSpecImageKey; } @@ -422,9 +415,9 @@ public class PaperCard implements Comparable, InventoryItemFromSet, public String getCardBSpecImageKey() { if (this.cardBSpecImageKey == null) { if (this.rules.getSplitType() == CardSplitType.Specialize) - this.cardBSpecImageKey = ImageUtil.getImageKey(this, "black", true); + this.cardBSpecImageKey = ImageUtil.getImageKey(this, CardStateName.SpecializeB); else // just use cardImageKey - this.cardBSpecImageKey = ImageUtil.getImageKey(this, "", true); + this.cardBSpecImageKey = getCardImageKey(); } return cardBSpecImageKey; } @@ -434,9 +427,9 @@ public class PaperCard implements Comparable, InventoryItemFromSet, public String getCardRSpecImageKey() { if (this.cardRSpecImageKey == null) { if (this.rules.getSplitType() == CardSplitType.Specialize) - this.cardRSpecImageKey = ImageUtil.getImageKey(this, "red", true); + this.cardRSpecImageKey = ImageUtil.getImageKey(this, CardStateName.SpecializeR); else // just use cardImageKey - this.cardRSpecImageKey = ImageUtil.getImageKey(this, "", true); + this.cardRSpecImageKey = getCardImageKey(); } return cardRSpecImageKey; } @@ -446,18 +439,16 @@ public class PaperCard implements Comparable, InventoryItemFromSet, public String getCardGSpecImageKey() { if (this.cardGSpecImageKey == null) { if (this.rules.getSplitType() == CardSplitType.Specialize) - this.cardGSpecImageKey = ImageUtil.getImageKey(this, "green", true); + this.cardGSpecImageKey = ImageUtil.getImageKey(this, CardStateName.SpecializeG); else // just use cardImageKey - this.cardGSpecImageKey = ImageUtil.getImageKey(this, "", true); + this.cardGSpecImageKey = getCardImageKey(); } return cardGSpecImageKey; } @Override public boolean hasBackFace(){ - CardSplitType cst = this.rules.getSplitType(); - return cst == CardSplitType.Transform || cst == CardSplitType.Flip || cst == CardSplitType.Meld - || cst == CardSplitType.Modal; + return this.rules.hasBackSide(); } @Override diff --git a/forge-core/src/main/java/forge/util/ImageUtil.java b/forge-core/src/main/java/forge/util/ImageUtil.java index fe57fec1d1a..8cecb06df5a 100644 --- a/forge-core/src/main/java/forge/util/ImageUtil.java +++ b/forge-core/src/main/java/forge/util/ImageUtil.java @@ -5,6 +5,7 @@ import forge.StaticData; import forge.card.CardDb; import forge.card.CardRules; import forge.card.CardSplitType; +import forge.card.CardStateName; import forge.item.IPaperCard; import forge.item.PaperCard; import org.apache.commons.lang3.StringUtils; @@ -24,20 +25,17 @@ public class ImageUtil { key = imageKey.substring(ImageKeys.CARD_PREFIX.length()); else return null; + + if (key.endsWith(ImageKeys.BACKFACE_POSTFIX)) { + key = key.substring(0, key.length() - ImageKeys.BACKFACE_POSTFIX.length()); + } + if (key.isEmpty()) return null; - CardDb db = StaticData.instance().getCommonCards(); - PaperCard cp = null; - //db shouldn't be null - if (db != null) { - cp = db.getCard(key); - if (cp == null) { - db = StaticData.instance().getVariantCards(); - if (db != null) - cp = db.getCard(key); - } - } + String[] tempdata = key.split("\\|"); + PaperCard cp = StaticData.instance().fetchCard(tempdata[0], tempdata[1], tempdata[2]); + if (cp == null) System.err.println("Can't find PaperCard from key: " + key); // return cp regardless if it's null @@ -54,6 +52,21 @@ public class ImageUtil { return key; } + public static String getImageRelativePath(String name, String set, String collectorNumber, boolean artChop) { + StringBuilder sb = new StringBuilder(); + + sb.append(set).append("/"); + if (!collectorNumber.isEmpty() && !collectorNumber.equals(IPaperCard.NO_COLLECTOR_NUMBER)) { + sb.append(collectorNumber).append("_"); + } + sb.append(StringUtils.stripAccents(name)); + + sb.append(artChop ? ".artcrop" : ".fullborder"); + sb.append(".jpg"); + return sb.toString(); + } + + public static String getImageRelativePath(PaperCard cp, String face, boolean includeSet, boolean isDownloadUrl) { final String nameToUse = cp == null ? null : getNameToUse(cp, face); if (nameToUse == null) { @@ -123,25 +136,15 @@ public class ImageUtil { else return null; } else if (face.equals("white")) { - if (card.getWSpecialize() != null) { - return card.getWSpecialize().getName(); - } + return card.getImageName(CardStateName.SpecializeW); } else if (face.equals("blue")) { - if (card.getUSpecialize() != null) { - return card.getUSpecialize().getName(); - } + return card.getImageName(CardStateName.SpecializeU); } else if (face.equals("black")) { - if (card.getBSpecialize() != null) { - return card.getBSpecialize().getName(); - } + return card.getImageName(CardStateName.SpecializeB); } else if (face.equals("red")) { - if (card.getRSpecialize() != null) { - return card.getRSpecialize().getName(); - } + return card.getImageName(CardStateName.SpecializeR); } else if (face.equals("green")) { - if (card.getGSpecialize() != null) { - return card.getGSpecialize().getName(); - } + return card.getImageName(CardStateName.SpecializeG); } else if (CardSplitType.Split == cp.getRules().getSplitType()) { return card.getMainPart().getName() + card.getOtherPart().getName(); } else if (!IPaperCard.NO_FUNCTIONAL_VARIANT.equals(cp.getFunctionalVariant())) { @@ -150,50 +153,86 @@ public class ImageUtil { return cp.getName(); } + public static String getNameToUse(PaperCard cp, CardStateName face) { + if (!IPaperCard.NO_FUNCTIONAL_VARIANT.equals(cp.getFunctionalVariant())) { + return cp.getFunctionalVariant(); + } + final CardRules card = cp.getRules(); + return card.getImageName(face); + } + public static String getImageKey(PaperCard cp, String face, boolean includeSet) { return getImageRelativePath(cp, face, includeSet, false); } + public static String getImageKey(PaperCard cp, CardStateName face) { + String name = getNameToUse(cp, face); + String number = cp.getCollectorNumber(); + String suffix = ""; + switch (face) { + case SpecializeB: + number += "b"; + break; + case SpecializeG: + number += "g"; + break; + case SpecializeR: + number += "r"; + break; + case SpecializeU: + number += "u"; + break; + case SpecializeW: + number += "w"; + break; + case Meld: + case Modal: + case Secondary: + case Transformed: + suffix = ImageKeys.BACKFACE_POSTFIX; + break; + case Flipped: + break; // add info to rotate the image? + default: + break; + }; + return ImageKeys.CARD_PREFIX + name + CardDb.NameSetSeparator + cp.getEdition() + + CardDb.NameSetSeparator + number + CardDb.NameSetSeparator + cp.getArtIndex() + suffix; + } + public static String getDownloadUrl(PaperCard cp, String face) { return getImageRelativePath(cp, face, true, true); } - public static String getScryfallDownloadUrl(PaperCard cp, String face, String setCode, String langCode, boolean useArtCrop){ - return getScryfallDownloadUrl(cp, face, setCode, langCode, useArtCrop, false); + public static String getScryfallDownloadUrl(String collectorNumber, String setCode, String langCode, String faceParam, boolean useArtCrop){ + return getScryfallDownloadUrl(collectorNumber, setCode, langCode, faceParam, useArtCrop, false); } - public static String getScryfallDownloadUrl(PaperCard cp, String face, String setCode, String langCode, boolean useArtCrop, boolean hyphenateAlchemy){ - String editionCode; - if ((setCode != null) && (setCode.length() > 0)) - editionCode = setCode; - else - editionCode = cp.getEdition().toLowerCase(); - String cardCollectorNumber = cp.getCollectorNumber(); + public static String getScryfallDownloadUrl(String collectorNumber, String setCode, String langCode, String faceParam, boolean useArtCrop, boolean hyphenateAlchemy){ // Hack to account for variations in Arabian Nights - cardCollectorNumber = cardCollectorNumber.replace("+", "†"); + collectorNumber = collectorNumber.replace("+", "†"); // override old planechase sets from their modified id since scryfall move the planechase cards outside their original setcode - if (cardCollectorNumber.startsWith("OHOP")) { - editionCode = "ohop"; - cardCollectorNumber = cardCollectorNumber.substring("OHOP".length()); - } else if (cardCollectorNumber.startsWith("OPCA")) { - editionCode = "opca"; - cardCollectorNumber = cardCollectorNumber.substring("OPCA".length()); - } else if (cardCollectorNumber.startsWith("OPC2")) { - editionCode = "opc2"; - cardCollectorNumber = cardCollectorNumber.substring("OPC2".length()); + if (collectorNumber.startsWith("OHOP")) { + setCode = "ohop"; + collectorNumber = collectorNumber.substring("OHOP".length()); + } else if (collectorNumber.startsWith("OPCA")) { + setCode = "opca"; + collectorNumber = collectorNumber.substring("OPCA".length()); + } else if (collectorNumber.startsWith("OPC2")) { + setCode = "opc2"; + collectorNumber = collectorNumber.substring("OPC2".length()); } else if (hyphenateAlchemy) { - if (!cardCollectorNumber.startsWith("A")) { + if (!collectorNumber.startsWith("A")) { return null; } - cardCollectorNumber = cardCollectorNumber.replace("A", "A-"); + collectorNumber = collectorNumber.replace("A", "A-"); } String versionParam = useArtCrop ? "art_crop" : "normal"; - String faceParam = ""; - if (cp.getRules().getOtherPart() != null) { - faceParam = (face.equals("back") ? "&face=back" : "&face=front"); + if (!faceParam.isEmpty()) { + faceParam = (faceParam.equals("back") ? "&face=back" : "&face=front"); } - return String.format("%s/%s/%s?format=image&version=%s%s", editionCode, cardCollectorNumber, + return String.format("%s/%s/%s?format=image&version=%s%s", setCode, collectorNumber, langCode, versionParam, faceParam); } 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 dab02191267..664ae532a32 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -6515,29 +6515,6 @@ public class Card extends GameEntity implements Comparable, IHasSVars, ITr if(uiCard != null) uiCard.currentState.setImageKey(iFN); } - public final void setImageKey(final IPaperCard ipc, final CardStateName stateName) { - if (ipc == null) - return; - switch (stateName) { - case SpecializeB: - setImageKey(ipc.getCardBSpecImageKey()); - break; - case SpecializeR: - setImageKey(ipc.getCardRSpecImageKey()); - break; - case SpecializeG: - setImageKey(ipc.getCardGSpecImageKey()); - break; - case SpecializeU: - setImageKey(ipc.getCardUSpecImageKey()); - break; - case SpecializeW: - setImageKey(ipc.getCardWSpecImageKey()); - break; - default: - break; - } - } public String getImageKey(CardStateName state) { if (!getRenderForUI()) { @@ -6837,7 +6814,6 @@ public class Card extends GameEntity implements Comparable, IHasSVars, ITr } public final void setSpecialized(final boolean bool) { specialized = bool; - setImageKey(getPaperCard(), getCurrentStateName()); } public final boolean canSpecialize() { return getRules() != null && getRules().getSplitType() == CardSplitType.Specialize; diff --git a/forge-game/src/main/java/forge/game/card/CardFactory.java b/forge-game/src/main/java/forge/game/card/CardFactory.java index 17ec3d297a4..4d638e36eb5 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactory.java +++ b/forge-game/src/main/java/forge/game/card/CardFactory.java @@ -187,7 +187,7 @@ public class CardFactory { c.setRarity(cp.getRarity()); // Would like to move this away from in-game entities - String originalPicture = cp.getImageKey(false); + String originalPicture = cp.getCardImageKey(); c.setImageKey(originalPicture); if(cp.isToken()) @@ -198,11 +198,11 @@ public class CardFactory { if (c.hasAlternateState()) { if (c.isFlipCard()) { c.setState(CardStateName.Flipped, false); - c.setImageKey(cp.getImageKey(true)); + c.setImageKey(cp.getCardAltImageKey()); } else if (c.isDoubleFaced() && cardRules != null) { c.setState(cardRules.getSplitType().getChangedStateName(), false); - c.setImageKey(cp.getImageKey(true)); + c.setImageKey(cp.getCardAltImageKey()); } else if (c.isSplitCard()) { c.setState(CardStateName.LeftSplit, false); @@ -216,23 +216,23 @@ public class CardFactory { c.setImageKey(originalPicture); } else if (c.canSpecialize()) { c.setState(CardStateName.SpecializeW, false); - c.setImageKey(cp.getImageKey(false) + ImageKeys.SPECFACE_W); + c.setImageKey(cp.getCardWSpecImageKey()); c.setSetCode(cp.getEdition()); c.setRarity(cp.getRarity()); c.setState(CardStateName.SpecializeU, false); - c.setImageKey(cp.getImageKey(false) + ImageKeys.SPECFACE_U); + c.setImageKey(cp.getCardUSpecImageKey()); c.setSetCode(cp.getEdition()); c.setRarity(cp.getRarity()); c.setState(CardStateName.SpecializeB, false); - c.setImageKey(cp.getImageKey(false) + ImageKeys.SPECFACE_B); + c.setImageKey(cp.getCardBSpecImageKey()); c.setSetCode(cp.getEdition()); c.setRarity(cp.getRarity()); c.setState(CardStateName.SpecializeR, false); - c.setImageKey(cp.getImageKey(false) + ImageKeys.SPECFACE_R); + c.setImageKey(cp.getCardRSpecImageKey()); c.setSetCode(cp.getEdition()); c.setRarity(cp.getRarity()); c.setState(CardStateName.SpecializeG, false); - c.setImageKey(cp.getImageKey(false) + ImageKeys.SPECFACE_G); + c.setImageKey(cp.getCardGSpecImageKey()); c.setSetCode(cp.getEdition()); c.setRarity(cp.getRarity()); } 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 96547dac712..3111f0c2e32 100644 --- a/forge-game/src/main/java/forge/game/card/CardView.java +++ b/forge-game/src/main/java/forge/game/card/CardView.java @@ -1335,9 +1335,21 @@ public class CardView extends GameEntityView { } void updateImageKey(Card c) { set(TrackableProperty.ImageKey, c.getImageKey()); + IPaperCard pc = c.getPaperCard(); + if (pc != null) { + set(TrackableProperty.Artist, pc.getArtist()); + } } void updateImageKey(CardState c) { set(TrackableProperty.ImageKey, c.getImageKey()); + IPaperCard pc = c.getCard().getPaperCard(); + if (pc != null) { // currently Artist is per Card + set(TrackableProperty.Artist, pc.getArtist()); + } + } + + public String getArtist() { + return get(TrackableProperty.Artist); } public CardTypeView getType() { diff --git a/forge-game/src/main/java/forge/trackable/TrackableProperty.java b/forge-game/src/main/java/forge/trackable/TrackableProperty.java index a303fb14d2d..c9e8d15e01a 100644 --- a/forge-game/src/main/java/forge/trackable/TrackableProperty.java +++ b/forge-game/src/main/java/forge/trackable/TrackableProperty.java @@ -118,6 +118,7 @@ public enum TrackableProperty { //Card State Name(TrackableTypes.StringType), + Artist(TrackableTypes.StringType), Colors(TrackableTypes.ColorSetType), OriginalColors(TrackableTypes.ColorSetType), LeftSplitColors(TrackableTypes.ColorSetType), diff --git a/forge-gui-desktop/src/main/java/forge/ImageCache.java b/forge-gui-desktop/src/main/java/forge/ImageCache.java index 8c46d438d22..a5ed142457e 100644 --- a/forge-gui-desktop/src/main/java/forge/ImageCache.java +++ b/forge-gui-desktop/src/main/java/forge/ImageCache.java @@ -40,7 +40,7 @@ import com.google.common.cache.CacheLoader.InvalidCacheLoadException; import com.google.common.cache.LoadingCache; import com.mortennobel.imagescaling.ResampleOp; -import forge.card.CardSplitType; +import forge.card.CardEdition; import forge.game.card.Card; import forge.game.card.CardView; import forge.game.player.PlayerView; @@ -56,8 +56,8 @@ import forge.model.FModel; import forge.toolbox.FSkin; import forge.toolbox.FSkin.SkinIcon; import forge.toolbox.imaging.FCardImageRenderer; +import forge.util.Aggregates; import forge.util.ImageUtil; -import forge.util.TextUtil; /** * This class stores ALL card images in a cache with soft values. this means @@ -171,65 +171,41 @@ public class ImageCache { IPaperCard ipc = null; boolean altState = imageKey.endsWith(ImageKeys.BACKFACE_POSTFIX); - String specColor = ""; - if (imageKey.endsWith(ImageKeys.SPECFACE_W)) { - specColor = "white"; - } else if (imageKey.endsWith(ImageKeys.SPECFACE_U)) { - specColor = "blue"; - } else if (imageKey.endsWith(ImageKeys.SPECFACE_B)) { - specColor = "black"; - } else if (imageKey.endsWith(ImageKeys.SPECFACE_R)) { - specColor = "red"; - } else if (imageKey.endsWith(ImageKeys.SPECFACE_G)) { - specColor = "green"; - } + boolean useArtCrop = "Crop".equals(FModel.getPreferences().getPref(ForgePreferences.FPref.UI_CARD_ART_FORMAT)); + String fileName = imageKey; if (altState) imageKey = imageKey.substring(0, imageKey.length() - ImageKeys.BACKFACE_POSTFIX.length()); - if (!specColor.isEmpty()) - imageKey = imageKey.substring(0, imageKey.length() - ImageKeys.SPECFACE_W.length()); if (imageKey.startsWith(ImageKeys.CARD_PREFIX)) { - ipc = ImageUtil.getPaperCardFromImageKey(imageKey); - if (ipc != null) { - if (altState) { - imageKey = ipc.getCardAltImageKey(); - } else if (!specColor.isEmpty()) { - switch (specColor) { - case "white": - imageKey = ipc.getCardWSpecImageKey(); - break; - case "blue": - imageKey = ipc.getCardUSpecImageKey(); - break; - case "black": - imageKey = ipc.getCardBSpecImageKey(); - break; - case "red": - imageKey = ipc.getCardRSpecImageKey(); - break; - case "green": - imageKey = ipc.getCardGSpecImageKey(); - break; + String[] tempdata = imageKey.substring(2).split("\\|"); //We want to check the edition first. + + String name = tempdata[0]; + String setCode = tempdata.length > 1 ? tempdata[1] : CardEdition.UNKNOWN_CODE; + String collectorNumber = tempdata.length > 3 ? tempdata[2] : IPaperCard.NO_COLLECTOR_NUMBER; + + CardEdition edition = StaticData.instance().getEditions().get(setCode); + + if (useArtCrop) { + CardEdition.EditionEntry ee; + if (!collectorNumber.isEmpty() && !collectorNumber.equals(IPaperCard.NO_COLLECTOR_NUMBER)) { + ee = edition.getCardFromCollectorNumber(collectorNumber); + if (ee != null) { // TODO handle Specialize Collector number + ee = edition.getCardFromCollectorNumber(collectorNumber.substring(0, collectorNumber.length() - 1)); } } else { - imageKey = ipc.getCardImageKey(); + ee = Aggregates.random(edition.getCardInSet(name)); } - if (StringUtils.isBlank(imageKey)) - return Pair.of(_defaultImage, true); - } - } - // Replace .full to .artcrop if art crop is preferred - // Only allow use art if the artist info is available - boolean useArtCrop = "Crop".equals(FModel.getPreferences().getPref(ForgePreferences.FPref.UI_CARD_ART_FORMAT)) - && ipc != null && !ipc.getArtist().isEmpty(); - String originalKey = imageKey; - if (useArtCrop) { - if (ipc != null && ipc.getRules().getSplitType() == CardSplitType.Flip) { - // Art crop will always use front face as image key for flip cards - imageKey = ipc.getCardImageKey(); + // Skip fetching if artist info is not available for art crop + if (ee != null && ee.artistName().isEmpty()) { + useArtCrop = false; + } } - imageKey = TextUtil.fastReplace(imageKey, ".full", ".artcrop"); - } + ipc = StaticData.instance().fetchCard(name, setCode, collectorNumber); + + fileName = ImageUtil.getImageRelativePath(name, setCode, collectorNumber, useArtCrop); + } // TODO add artCrop for Token + + String originalKey = imageKey; // Load from file and add to cache if not found in cache initially. BufferedImage original = getImage(imageKey); @@ -239,16 +215,11 @@ public class ImageCache { } // if art crop is exist, check also if the full card image is also cached. - if (useArtCrop && original != null) { - BufferedImage cached = _CACHE.getIfPresent(originalKey); - if (cached != null) - return Pair.of(cached, false); - } boolean noBorder = !useArtCrop && !isPreferenceEnabled(ForgePreferences.FPref.UI_RENDER_BLACK_BORDERS); boolean fetcherEnabled = isPreferenceEnabled(ForgePreferences.FPref.UI_ENABLE_ONLINE_IMAGE_FETCHER); boolean isPlaceholder = (original == null) && fetcherEnabled; - String setCode = imageKey.split("/")[0].trim().toUpperCase(); + String setCode = fileName.split("/")[0].trim().toUpperCase(); // If the user has indicated that they prefer Forge NOT render a black border, round the image corners // to account for JPEG images that don't have a transparency. @@ -301,7 +272,7 @@ public class ImageCache { CardView card = ipc != null ? Card.getCardForUi(ipc).getView() : cardView; String legalString = null; original = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); - if (art != null) { + if (art != null && ipc != null) { Calendar cal = Calendar.getInstance(); cal.setTime(StaticData.instance().getCardEdition(ipc.getEdition()).getDate()); int year = cal.get(Calendar.YEAR); diff --git a/forge-gui-desktop/src/main/java/forge/ImageLoader.java b/forge-gui-desktop/src/main/java/forge/ImageLoader.java index 29f6d0b2839..f0a588abe4b 100644 --- a/forge-gui-desktop/src/main/java/forge/ImageLoader.java +++ b/forge-gui-desktop/src/main/java/forge/ImageLoader.java @@ -18,7 +18,8 @@ final class ImageLoader extends CacheLoader { if (FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_DISABLE_CARD_IMAGES)) return null; - File file = ImageKeys.getImageFile(key); + boolean useArtCrop = "Crop".equals(FModel.getPreferences().getPref(ForgePreferences.FPref.UI_CARD_ART_FORMAT)); + File file = ImageKeys.getImageFile(key, useArtCrop); if (file != null) { if (!file.exists()) { return null; diff --git a/forge-gui-desktop/src/main/java/forge/toolbox/imaging/FImageUtil.java b/forge-gui-desktop/src/main/java/forge/toolbox/imaging/FImageUtil.java index 6587f3223ee..e4c56a227db 100644 --- a/forge-gui-desktop/src/main/java/forge/toolbox/imaging/FImageUtil.java +++ b/forge-gui-desktop/src/main/java/forge/toolbox/imaging/FImageUtil.java @@ -77,41 +77,11 @@ public final class FImageUtil { } boolean altState = key.endsWith(ImageKeys.BACKFACE_POSTFIX); - String specColor = ""; - if (key.endsWith(ImageKeys.SPECFACE_W)) { - specColor = "white"; - } else if (key.endsWith(ImageKeys.SPECFACE_U)) { - specColor = "blue"; - } else if (key.endsWith(ImageKeys.SPECFACE_B)) { - specColor = "black"; - } else if (key.endsWith(ImageKeys.SPECFACE_R)) { - specColor = "red"; - } else if (key.endsWith(ImageKeys.SPECFACE_G)) { - specColor = "green"; - } String imageKey = key; if (prefix.equals(ImageKeys.CARD_PREFIX)) { PaperCard card = ImageUtil.getPaperCardFromImageKey(key); if (altState) { imageKey = card.getCardAltImageKey(); - } else if (!specColor.isEmpty()) { - switch (specColor) { - case "white": - imageKey = card.getCardWSpecImageKey(); - break; - case "blue": - imageKey = card.getCardUSpecImageKey(); - break; - case "black": - imageKey = card.getCardBSpecImageKey(); - break; - case "red": - imageKey = card.getCardRSpecImageKey(); - break; - case "green": - imageKey = card.getCardGSpecImageKey(); - break; - } } else { imageKey = card.getCardImageKey(); } @@ -119,9 +89,6 @@ public final class FImageUtil { if(altState) { imageKey = imageKey.substring(0, imageKey.length() - ImageKeys.BACKFACE_POSTFIX.length()); imageKey += "full.jpg"; - } else if (!specColor.isEmpty()) { - imageKey = imageKey.substring(0, imageKey.length() - ImageKeys.SPECFACE_W.length()); - imageKey += "full.jpg"; } File file = ImageKeys.getImageFile(imageKey); diff --git a/forge-gui-desktop/src/main/java/forge/util/SwingImageFetcher.java b/forge-gui-desktop/src/main/java/forge/util/SwingImageFetcher.java index d8fb622e71e..77afbfa2174 100644 --- a/forge-gui-desktop/src/main/java/forge/util/SwingImageFetcher.java +++ b/forge-gui-desktop/src/main/java/forge/util/SwingImageFetcher.java @@ -34,10 +34,14 @@ public class SwingImageFetcher extends ImageFetcher { return false; } - String newdespath = urlToDownload.contains(".fullborder.jpg") || urlToDownload.startsWith(ForgeConstants.URL_PIC_SCRYFALL_DOWNLOAD) ? - TextUtil.fastReplace(destPath, ".full.jpg", ".fullborder.jpg") : destPath; - if (!newdespath.contains(".full") && urlToDownload.startsWith(ForgeConstants.URL_PIC_SCRYFALL_DOWNLOAD) && !destPath.startsWith(ForgeConstants.CACHE_TOKEN_PICS_DIR)) - newdespath = newdespath.replace(".jpg", ".fullborder.jpg"); //fix planes/phenomenon for round border options + String newdespath = destPath; + if (!destPath.contains(".artcrop")) { + newdespath = urlToDownload.contains(".fullborder.jpg") || urlToDownload.startsWith(ForgeConstants.URL_PIC_SCRYFALL_DOWNLOAD) ? + TextUtil.fastReplace(destPath, ".full.jpg", ".fullborder.jpg") : destPath; + if (!newdespath.contains(".full") && urlToDownload.startsWith(ForgeConstants.URL_PIC_SCRYFALL_DOWNLOAD) && !destPath.startsWith(ForgeConstants.CACHE_TOKEN_PICS_DIR)) + newdespath = newdespath.replace(".jpg", ".fullborder.jpg"); //fix planes/phenomenon for round border options + } + URL url = new URL(urlToDownload); System.out.println("Attempting to fetch: " + url); BufferedImage image = ImageIO.read(url); diff --git a/forge-gui-mobile/src/forge/adventure/util/RewardActor.java b/forge-gui-mobile/src/forge/adventure/util/RewardActor.java index b6551e8923c..f2c6cc720ee 100644 --- a/forge-gui-mobile/src/forge/adventure/util/RewardActor.java +++ b/forge-gui-mobile/src/forge/adventure/util/RewardActor.java @@ -124,8 +124,6 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb if(reward.type.equals(Reward.Type.Card)) { imageKey = reward.getCard().getImageKey(false); - PaperCard card = ImageUtil.getPaperCardFromImageKey(imageKey); - imageKey = card.getCardImageKey(); int count = 0; @@ -248,8 +246,7 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb hasbackface = reward.getCard().hasBackFace(); if (ImageCache.getInstance().imageKeyFileExists(reward.getCard().getImageKey(false)) && !Forge.enableUIMask.equals("Art")) { int count = 0; - PaperCard card = ImageUtil.getPaperCardFromImageKey(reward.getCard().getImageKey(false)); - File frontFace = ImageKeys.getImageFile(card.getCardImageKey()); + File frontFace = ImageKeys.getImageFile(reward.getCard().getImageKey(false)); if (frontFace != null) { try { Texture front = Forge.getAssets().manager().get(frontFace.getPath(), Texture.class, false); @@ -275,8 +272,7 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb //preload card back for performance if (hasbackface) { if (ImageCache.getInstance().imageKeyFileExists(reward.getCard().getImageKey(true))) { - PaperCard cardBack = ImageUtil.getPaperCardFromImageKey(reward.getCard().getImageKey(true)); - File backFace = ImageKeys.getImageFile(cardBack.getCardAltImageKey()); + File backFace = ImageKeys.getImageFile(reward.getCard().getImageKey(true)); if (backFace != null) { try { Texture back = Forge.getAssets().manager().get(backFace.getPath(), Texture.class, false); @@ -400,8 +396,7 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb if (imageKey != "") { isBooster = true; File file = new File(IMAGE_LIST_QUEST_BOOSTERS_FILE); - try { - Scanner scanner = new Scanner(file); + try (Scanner scanner = new Scanner(file)) { String boosterPath = ""; while(scanner.hasNextLine()) { diff --git a/forge-gui-mobile/src/forge/assets/ImageCache.java b/forge-gui-mobile/src/forge/assets/ImageCache.java index 9ea9214595c..3ed8d56a844 100644 --- a/forge-gui-mobile/src/forge/assets/ImageCache.java +++ b/forge-gui-mobile/src/forge/assets/ImageCache.java @@ -247,9 +247,6 @@ public class ImageCache { imageKey = imageKey.substring(0, imageKey.length() - ImageKeys.BACKFACE_POSTFIX.length()); } if (imageKey.startsWith(ImageKeys.CARD_PREFIX)) { - PaperCard card = ImageUtil.getPaperCardFromImageKey(imageKey); - if (card != null) - imageKey = altState ? card.getCardAltImageKey() : card.getCardImageKey(); if (StringUtils.isBlank(imageKey)) { if (useDefaultIfNotFound) return getDefaultImage(); diff --git a/forge-gui-mobile/src/forge/card/CardImageRenderer.java b/forge-gui-mobile/src/forge/card/CardImageRenderer.java index 9c8cda736cb..7d4ff63bca1 100644 --- a/forge-gui-mobile/src/forge/card/CardImageRenderer.java +++ b/forge-gui-mobile/src/forge/card/CardImageRenderer.java @@ -9,9 +9,9 @@ import java.util.List; import forge.ImageKeys; import forge.assets.*; -import forge.item.PaperCard; -import forge.util.ImageUtil; import forge.util.TextBounds; + +import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import com.badlogic.gdx.graphics.Color; @@ -156,13 +156,7 @@ public class CardImageRenderer { } //space for artist textBoxHeight -= 2 * PT_FONT.getCapHeight(); - PaperCard paperCard = null; - try { - paperCard = ImageUtil.getPaperCardFromImageKey(state.getImageKey()); - } catch (Exception e) {} - String artist = "WOTC"; - if (paperCard != null && !paperCard.getArtist().isEmpty()) - artist = paperCard.getArtist(); + String artist = ObjectUtils.firstNonNull(state.getArtist(), "WOTC"); float minTextBoxHeight = 2 * headerHeight; if (textBoxHeight < minTextBoxHeight) { artHeight -= (minTextBoxHeight - textBoxHeight); //subtract from art height if text box not big enough otherwise diff --git a/forge-gui-mobile/src/forge/card/CardZoom.java b/forge-gui-mobile/src/forge/card/CardZoom.java index ce1b07dd26b..adc228be81b 100644 --- a/forge-gui-mobile/src/forge/card/CardZoom.java +++ b/forge-gui-mobile/src/forge/card/CardZoom.java @@ -103,27 +103,22 @@ public class CardZoom extends FOverlay { if (pc != null) { Card cardW = Card.fromPaperCard(pc, null); cardW.setState(CardStateName.SpecializeW, true); - cardW.setImageKey(pc, CardStateName.SpecializeW); list.add(cardW.getView()); Card cardU = Card.fromPaperCard(pc, null); - cardU.setState(CardStateName.SpecializeU, true); - cardU.setImageKey(pc, CardStateName.SpecializeU); + cardU.setState(CardStateName.SpecializeU, true);; list.add(cardU.getView()); Card cardB = Card.fromPaperCard(pc, null); cardB.setState(CardStateName.SpecializeB, true); - cardB.setImageKey(pc, CardStateName.SpecializeB); list.add(cardB.getView()); Card cardR = Card.fromPaperCard(pc, null); cardR.setState(CardStateName.SpecializeR, true); - cardR.setImageKey(pc, CardStateName.SpecializeR); list.add(cardR.getView()); Card cardG = Card.fromPaperCard(pc, null); cardG.setState(CardStateName.SpecializeG, true); - cardG.setImageKey(pc, CardStateName.SpecializeG); list.add(cardG.getView()); } if (!list.isEmpty()) diff --git a/forge-gui/src/main/java/forge/player/HumanCostDecision.java b/forge-gui/src/main/java/forge/player/HumanCostDecision.java index c5c1d199c34..ab6286659b7 100644 --- a/forge-gui/src/main/java/forge/player/HumanCostDecision.java +++ b/forge-gui/src/main/java/forge/player/HumanCostDecision.java @@ -1384,13 +1384,9 @@ public class HumanCostDecision extends CostDecisionMakerBase { try { //for cards like Sword-Point Diplomacy and others that uses imprinted as container for their ability if (cardView != null && cardView.getImprintedCards() != null && cardView.getImprintedCards().size() == 1) - cardView = CardView.getCardForUi(ImageUtil.getPaperCardFromImageKey(cardView.getImprintedCards().get(0).getCurrentState().getTrackableImageKey())); + cardView = cardView.getImprintedCards().get(0); else if (ability.getTargets() != null && ability.getTargets().isTargetingAnyCard() && ability.getTargets().size() == 1) cardView = CardView.get(ability.getTargetCard()); - else if (cardView.getZone() == null || cardView.getZone().isHidden()) { - if (!cardView.hasAlternateState()) //don't override if it has alternatestate since it maybe showing alternate view - cardView = CardView.getCardForUi(ImageUtil.getPaperCardFromImageKey(cardView.getCurrentState().getTrackableImageKey())); - } } catch (Exception e) { //prevent NPE when overriding the cardView, the getPaperCardFromImageKey can return null making the GUI freeze, reset the view if error happens cardView = ability.getCardView(); diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index 46ea67c7522..14c7c78d37a 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -1931,7 +1931,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont if (GuiBase.getInterface().isLibgdxPort()) { CardView cardView; try { - cardView = CardView.getCardForUi(ImageUtil.getPaperCardFromImageKey(sa.getView().getHostCard().getCurrentState().getTrackableImageKey())); + cardView = sa.getView().getHostCard(); } catch (Exception e) { SpellAbilityView spellAbilityView = sa.getView(); if (spellAbilityView != null) //updated view diff --git a/forge-gui/src/main/java/forge/util/ImageFetcher.java b/forge-gui/src/main/java/forge/util/ImageFetcher.java index 0f91c192dc7..0dc3b3f3e70 100644 --- a/forge-gui/src/main/java/forge/util/ImageFetcher.java +++ b/forge-gui/src/main/java/forge/util/ImageFetcher.java @@ -35,49 +35,25 @@ public abstract class ImageFetcher { langCodeMap.put("zh-HK", "zht"); }; private HashMap> currentFetches = new HashMap<>(); - private HashMap tokenImages; - private String getScryfallDownloadURL(PaperCard c, String face, boolean useArtCrop, boolean hasSetLookup, String imagePath, ArrayList downloadUrls) { - StaticData data = StaticData.instance(); - CardEdition edition = data.getEditions().get(c.getEdition()); + private String getScryfallDownloadURL(String collectorNumber, CardEdition edition, String face, boolean useArtCrop, ArrayList downloadUrls) { if (edition == null) // edition does not exist - some error occurred with card data return null; - if (hasSetLookup) { - List clones = StaticData.instance().getCommonCards().getAllCards(c.getName()); - for (PaperCard pc : clones) { - if (clones.size() > 1) {//clones only - if (!c.getEdition().equalsIgnoreCase(pc.getEdition())) { - CardEdition ed = data.getEditions().get(pc.getEdition()); - if (ed != null) { - String setCode =ed.getScryfallCode(); - String langCode = ed.getCardsLangCode(); - downloadUrls.add(ForgeConstants.URL_PIC_SCRYFALL_DOWNLOAD + ImageUtil.getScryfallDownloadUrl(pc, face, setCode, langCode, useArtCrop)); - } - } - } else {// original from set - CardEdition ed = data.getEditions().get(pc.getEdition()); - if (ed != null) { - String setCode =ed.getScryfallCode(); - String langCode = ed.getCardsLangCode(); - downloadUrls.add(ForgeConstants.URL_PIC_SCRYFALL_DOWNLOAD + ImageUtil.getScryfallDownloadUrl(pc, face, setCode, langCode, useArtCrop)); - } - } - } - } else { - String setCode = edition.getScryfallCode(); - String langCode = edition.getCardsLangCode(); - String primaryUrl = ImageUtil.getScryfallDownloadUrl(c, face, setCode, langCode, useArtCrop); - downloadUrls.add(ForgeConstants.URL_PIC_SCRYFALL_DOWNLOAD + primaryUrl); - // It seems like the scryfall lookup might be better if we didn't include the language code at all? - downloadUrls.add(ForgeConstants.URL_PIC_SCRYFALL_DOWNLOAD + ImageUtil.getScryfallDownloadUrl(c, face, setCode, "", useArtCrop)); + String setCode = edition.getScryfallCode(); + String langCode = edition.getCardsLangCode(); + String primaryUrl = ImageUtil.getScryfallDownloadUrl(collectorNumber, setCode, langCode, face, useArtCrop); + downloadUrls.add(ForgeConstants.URL_PIC_SCRYFALL_DOWNLOAD + primaryUrl); - String alternateUrl = ImageUtil.getScryfallDownloadUrl(c, face, setCode, langCode, useArtCrop, true); - if (alternateUrl != null && !alternateUrl.equals(primaryUrl)) { - downloadUrls.add(ForgeConstants.URL_PIC_SCRYFALL_DOWNLOAD + alternateUrl); - downloadUrls.add(ForgeConstants.URL_PIC_SCRYFALL_DOWNLOAD + ImageUtil.getScryfallDownloadUrl(c, face, setCode, "", useArtCrop, true)); - } + // It seems like the scryfall lookup might be better if we didn't include the language code at all? + downloadUrls.add(ForgeConstants.URL_PIC_SCRYFALL_DOWNLOAD + ImageUtil.getScryfallDownloadUrl(collectorNumber, setCode, "", face, useArtCrop)); + + String alternateUrl = ImageUtil.getScryfallDownloadUrl(collectorNumber, setCode, langCode, face, useArtCrop, true); + if (alternateUrl != null && !alternateUrl.equals(primaryUrl)) { + downloadUrls.add(ForgeConstants.URL_PIC_SCRYFALL_DOWNLOAD + alternateUrl); + downloadUrls.add(ForgeConstants.URL_PIC_SCRYFALL_DOWNLOAD + ImageUtil.getScryfallDownloadUrl(collectorNumber, setCode, "", face, useArtCrop, true)); } + return null; } @@ -131,7 +107,45 @@ public abstract class ImageFetcher { File destFile = null; String face = ""; if (prefix.equals(ImageKeys.CARD_PREFIX)) { - PaperCard paperCard = ImageUtil.getPaperCardFromImageKey(imageKey); + String tmp = imageKey; + if (tmp.endsWith(ImageKeys.BACKFACE_POSTFIX)) { + face = "back"; + tmp = tmp.substring(0, tmp.length() - ImageKeys.BACKFACE_POSTFIX.length()); + } + String[] tempdata = tmp.substring(2).split("\\|"); //We want to check the edition first. + + String name = tempdata[0]; + String setCode = tempdata.length > 1 ? tempdata[1] : CardEdition.UNKNOWN_CODE; + String collectorNumber = tempdata.length > 3 ? tempdata[2] : IPaperCard.NO_COLLECTOR_NUMBER; + + CardEdition edition = StaticData.instance().getEditions().get(setCode); + if (edition == null || edition.getType() == CardEdition.Type.CUSTOM_SET) return; //Custom set token, skip fetching. + + if (useArtCrop) { + CardEdition.EditionEntry ee; + if (!collectorNumber.isEmpty() && !collectorNumber.equals(IPaperCard.NO_COLLECTOR_NUMBER)) { + ee = edition.getCardFromCollectorNumber(collectorNumber); + if (ee == null) { // TODO handle Specialize Collector number + ee = edition.getCardFromCollectorNumber(collectorNumber.substring(0, collectorNumber.length() - 1)); + } + } else { + ee = Aggregates.random(edition.getCardInSet(name)); + } + + // Skip fetching if artist info is not available for art crop + if (ee != null && ee.artistName().isEmpty()) { + return; + } + } + + //TODO i don't want from imageKey to PaperCard, just to check for isCustom + PaperCard paperCard = StaticData.instance().fetchCard(name, setCode, collectorNumber); + // TODO handle Specialize Collector number + if (paperCard == null && !collectorNumber.isEmpty() && !collectorNumber.equals(IPaperCard.NO_COLLECTOR_NUMBER)) { + paperCard = StaticData.instance().fetchCard(name, setCode, collectorNumber.substring(0, collectorNumber.length() - 1)); + } + + //PaperCard paperCard = ImageUtil.getPaperCardFromImageKey(tmp); if (paperCard == null) { System.err.println("Paper card not found for: " + imageKey); return; @@ -143,71 +157,21 @@ public abstract class ImageFetcher { // Skip fetching if artist info is not available for art crop if (useArtCrop && paperCard.getArtist().isEmpty()) return; - String imagePath = ImageUtil.getImageRelativePath(paperCard, "", true, false); - final boolean hasSetLookup = ImageKeys.hasSetLookup(imagePath); - if (imageKey.endsWith(ImageKeys.BACKFACE_POSTFIX)) { - face = "back"; - } else if (imageKey.endsWith(ImageKeys.SPECFACE_W)) { - face = "white"; - } else if (imageKey.endsWith(ImageKeys.SPECFACE_U)) { - face = "blue"; - } else if (imageKey.endsWith(ImageKeys.SPECFACE_B)) { - face = "black"; - } else if (imageKey.endsWith(ImageKeys.SPECFACE_R)) { - face = "red"; - } else if (imageKey.endsWith(ImageKeys.SPECFACE_G)) { - face = "green"; + + String imagePath = ImageUtil.getImageRelativePath(name, setCode, collectorNumber, useArtCrop); + + destFile = new File(ForgeConstants.CACHE_CARD_PICS_DIR, imagePath); + if (destFile.exists()) { + paperCard.hasImage(true); } - String filename = ""; - switch (face) { - case "back": - filename = paperCard.getCardAltImageKey(); - break; - case "white": - filename = paperCard.getCardWSpecImageKey(); - break; - case "blue": - filename = paperCard.getCardUSpecImageKey(); - break; - case "black": - filename = paperCard.getCardBSpecImageKey(); - break; - case "red": - filename = paperCard.getCardRSpecImageKey(); - break; - case "green": - filename = paperCard.getCardGSpecImageKey(); - break; - default: - filename = paperCard.getCardImageKey(); - break; - } - if (useArtCrop) { - filename = TextUtil.fastReplace(filename, ".full", ".artcrop"); - } - boolean updateLink = false; - if ("back".equals(face)) {// seems getimage relative path don't process variants for back faces. - try { - filename = TextUtil.fastReplace(filename, "1.full", imageKey.substring(imageKey.lastIndexOf('|') + 1, imageKey.indexOf('$')) + ".full"); - updateLink = true; - } catch (Exception e) { - filename = paperCard.getCardAltImageKey(); - updateLink = false; - } - } - destFile = new File(ForgeConstants.CACHE_CARD_PICS_DIR, filename + ".jpg"); //skip ftp if using art crop + /* if (!useArtCrop) { //move priority of ftp image here StringBuilder setDownload = new StringBuilder(ForgeConstants.URL_PIC_DOWNLOAD); if (!hasSetLookup) { - if (!updateLink) { - setDownload.append(ImageUtil.getDownloadUrl(paperCard, face)); - } else { - String url = ImageUtil.getDownloadUrl(paperCard, face); - setDownload.append(TextUtil.fastReplace(url, "1.full", imageKey.substring(imageKey.lastIndexOf('|') + 1, imageKey.indexOf('$')) + ".full")); - } + setDownload.append(ImageUtil.getDownloadUrl(paperCard, face)); downloadUrls.add(setDownload.toString()); } else { List clones = StaticData.instance().getCommonCards().getAllCards(paperCard.getName()); @@ -222,10 +186,10 @@ public abstract class ImageFetcher { } } } - final String cardCollectorNumber = paperCard.getCollectorNumber(); - if (!cardCollectorNumber.equals(IPaperCard.NO_COLLECTOR_NUMBER)) { + //*/ + if (!collectorNumber.equals(IPaperCard.NO_COLLECTOR_NUMBER)) { // This function adds to downloadUrls for us - this.getScryfallDownloadURL(paperCard, face, useArtCrop, hasSetLookup, filename, downloadUrls); + this.getScryfallDownloadURL(collectorNumber, edition, face, useArtCrop, downloadUrls); } } else if (ImageKeys.getTokenKey(ImageKeys.HIDDEN_CARD).equals(imageKey)) { // extra logic for hidden card to not clog the other logic @@ -315,13 +279,6 @@ public abstract class ImageFetcher { } if (destFile.exists()) { - // TODO: Figure out why this codepath gets reached. - // Ideally, fetchImage() wouldn't be called if we already have the image. - if (prefix.equals(ImageKeys.CARD_PREFIX)) { - PaperCard paperCard = ImageUtil.getPaperCardFromImageKey(imageKey); - if (paperCard != null) - paperCard.hasImage(true); - } return; }