mirror of
https://github.com/correl/mage.git
synced 2024-11-14 19:19:32 +00:00
Refactor cards and token images code (#10139):
- removed outdated token store format (example: BIRD.W.BIRD.CREATURE.1.1.full.jpg) - removed duplicated cache images code; - removed duplicated set code fields; - removed outdated auto-generated thumb files (also all *.thumb.zip files will be deleted on startup);
This commit is contained in:
parent
d93e533c75
commit
66d0ef4b35
25 changed files with 333 additions and 634 deletions
|
@ -293,7 +293,11 @@ public class CardIconsPanel extends JPanel {
|
|||
//BufferedImage iconImage = ImageManagerImpl.instance.getCardIcon(icon.getIconType().getResourceName(), this.halfSize * 2);
|
||||
|
||||
// cached call
|
||||
BufferedImage iconImageCached = ImageCache.getCardIconImage(icon.getIconType().getResourceName(), this.halfSize * 2, color.toString());
|
||||
BufferedImage iconImageCached = ImageCache.getCardIconImage(
|
||||
icon.getIconType().getResourceName(),
|
||||
this.halfSize * 2,
|
||||
color.toString()
|
||||
).getImage();
|
||||
|
||||
if (iconImageCached != null && this.font != null) {
|
||||
BufferedImage iconImageWithText = ImageManagerImpl.deepCopy(iconImageCached); // must copy cached value before modify
|
||||
|
|
|
@ -51,7 +51,6 @@ public final class Constants {
|
|||
|
||||
// cards render
|
||||
public static final Rectangle CARD_SIZE_FULL = new Rectangle(101, 149);
|
||||
public static final Rectangle THUMBNAIL_SIZE_FULL = new Rectangle(102, 146);
|
||||
|
||||
// resources - default images
|
||||
public static final String RESOURCE_PATH_DEFAULT_IMAGES = File.separator + "default";
|
||||
|
|
|
@ -677,7 +677,7 @@ public class MageActionCallback implements ActionCallback {
|
|||
switch (enlargeMode) {
|
||||
case COPY:
|
||||
if (cardView instanceof PermanentView) {
|
||||
image = ImageCache.getImageOriginal(((PermanentView) cardView).getOriginal());
|
||||
image = ImageCache.getImageOriginal(((PermanentView) cardView).getOriginal()).getImage();
|
||||
}
|
||||
break;
|
||||
case ALTERNATE:
|
||||
|
@ -686,9 +686,9 @@ public class MageActionCallback implements ActionCallback {
|
|||
&& !cardView.isFlipCard()
|
||||
&& !cardView.canTransform()
|
||||
&& ((PermanentView) cardView).isCopy()) {
|
||||
image = ImageCache.getImageOriginal(((PermanentView) cardView).getOriginal());
|
||||
image = ImageCache.getImageOriginal(((PermanentView) cardView).getOriginal()).getImage();
|
||||
} else {
|
||||
image = ImageCache.getImageOriginalAlternateName(cardView);
|
||||
image = ImageCache.getImageOriginalAlternateName(cardView).getImage();
|
||||
displayCard = displayCard.getSecondCardFace();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package org.mage.card.arcane;
|
|||
import mage.MageInt;
|
||||
import mage.cards.MageCardLocation;
|
||||
import mage.cards.action.ActionCallback;
|
||||
import mage.client.constants.Constants;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.client.util.ImageCaches;
|
||||
import mage.client.util.ImageHelper;
|
||||
|
@ -19,6 +18,7 @@ import mage.view.PermanentView;
|
|||
import mage.view.StackAbilityView;
|
||||
import org.jdesktop.swingx.graphics.GraphicsUtilities;
|
||||
import org.mage.plugins.card.images.ImageCache;
|
||||
import org.mage.plugins.card.images.ImageCacheData;
|
||||
import org.mage.plugins.card.utils.impl.ImageManagerImpl;
|
||||
|
||||
import javax.swing.*;
|
||||
|
@ -466,9 +466,9 @@ public class CardPanelRenderModeImage extends CardPanel {
|
|||
public Image getImage() {
|
||||
if (this.hasImage) {
|
||||
if (getGameCard().isFaceDown()) {
|
||||
return getFaceDownImage();
|
||||
return getFaceDownImage().getImage();
|
||||
} else {
|
||||
return ImageCache.getImageOriginal(getGameCard());
|
||||
return ImageCache.getImageOriginal(getGameCard()).getImage();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -629,27 +629,27 @@ public class CardPanelRenderModeImage extends CardPanel {
|
|||
setTappedAngle(isTapped() ? CardPanel.TAPPED_ANGLE : 0);
|
||||
setFlippedAngle(isFlipped() ? CardPanel.FLIPPED_ANGLE : 0);
|
||||
|
||||
//final CardView gameCard = this.gameCard;
|
||||
final int stamp = ++updateArtImageStamp;
|
||||
|
||||
Util.threadPool.submit(() -> {
|
||||
try {
|
||||
final BufferedImage srcImage;
|
||||
final ImageCacheData data;
|
||||
if (getGameCard().isFaceDown()) {
|
||||
srcImage = getFaceDownImage();
|
||||
} else if (getCardWidth() > Constants.THUMBNAIL_SIZE_FULL.width) {
|
||||
srcImage = ImageCache.getImage(getGameCard(), getCardWidth(), getCardHeight());
|
||||
data = getFaceDownImage();
|
||||
} else {
|
||||
srcImage = ImageCache.getThumbnail(getGameCard());
|
||||
data = ImageCache.getImage(getGameCard(), getCardWidth(), getCardHeight());
|
||||
}
|
||||
if (srcImage == null) {
|
||||
setFullPath(ImageCache.getFilePath(getGameCard(), getCardWidth()));
|
||||
|
||||
// show path on miss image
|
||||
if (data.getImage() == null) {
|
||||
setFullPath(data.getPath());
|
||||
}
|
||||
|
||||
UI.invokeLater(() -> {
|
||||
if (stamp == updateArtImageStamp) {
|
||||
hasImage = srcImage != null;
|
||||
hasImage = data.getImage() != null;
|
||||
setTitle(getGameCard());
|
||||
setImage(srcImage);
|
||||
setImage(data.getImage());
|
||||
}
|
||||
});
|
||||
} catch (Exception | Error e) {
|
||||
|
@ -658,7 +658,7 @@ public class CardPanelRenderModeImage extends CardPanel {
|
|||
});
|
||||
}
|
||||
|
||||
private BufferedImage getFaceDownImage() {
|
||||
private ImageCacheData getFaceDownImage() {
|
||||
// TODO: add download default images
|
||||
if (isPermanent() && getGameCard() instanceof PermanentView) {
|
||||
if (((PermanentView) getGameCard()).isMorphed()) {
|
||||
|
|
|
@ -3,7 +3,6 @@ package org.mage.card.arcane;
|
|||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import mage.cards.action.ActionCallback;
|
||||
import mage.client.constants.Constants;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
|
@ -13,6 +12,7 @@ import mage.view.PermanentView;
|
|||
import mage.view.StackAbilityView;
|
||||
import org.jdesktop.swingx.graphics.GraphicsUtilities;
|
||||
import org.mage.plugins.card.images.ImageCache;
|
||||
import org.mage.plugins.card.images.ImageCacheData;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
@ -194,9 +194,9 @@ public class CardPanelRenderModeMTGO extends CardPanel {
|
|||
return null;
|
||||
}
|
||||
if (getGameCard().isFaceDown()) {
|
||||
return getFaceDownImage();
|
||||
return getFaceDownImage().getImage();
|
||||
} else {
|
||||
return ImageCache.getImageOriginal(getGameCard());
|
||||
return ImageCache.getImageOriginal(getGameCard()).getImage();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -319,12 +319,9 @@ public class CardPanelRenderModeMTGO extends CardPanel {
|
|||
// Nothing to do
|
||||
srcImage = null;
|
||||
faceArtSrcImage = null;
|
||||
} else if (getCardWidth() > Constants.THUMBNAIL_SIZE_FULL.width) {
|
||||
srcImage = ImageCache.getImage(getGameCard(), getCardWidth(), getCardHeight());
|
||||
faceArtSrcImage = ImageCache.getFaceImage(getGameCard(), getCardWidth(), getCardHeight());
|
||||
} else {
|
||||
srcImage = ImageCache.getThumbnail(getGameCard());
|
||||
faceArtSrcImage = ImageCache.getFaceImage(getGameCard(), getCardWidth(), getCardHeight());
|
||||
srcImage = ImageCache.getImage(getGameCard(), getCardWidth(), getCardHeight()).getImage();
|
||||
faceArtSrcImage = ImageCache.getFaceImage(getGameCard(), getCardWidth(), getCardHeight()).getImage();
|
||||
}
|
||||
|
||||
UI.invokeLater(() -> {
|
||||
|
@ -352,7 +349,7 @@ public class CardPanelRenderModeMTGO extends CardPanel {
|
|||
return new CardPanelAttributes(getCardWidth(), getCardHeight(), isChoosable(), isSelected(), isTransformed());
|
||||
}
|
||||
|
||||
private BufferedImage getFaceDownImage() {
|
||||
private ImageCacheData getFaceDownImage() {
|
||||
// TODO: add download default images
|
||||
if (isPermanent() && getGameCard() instanceof PermanentView) {
|
||||
if (((PermanentView) getGameCard()).isMorphed()) {
|
||||
|
|
|
@ -710,6 +710,6 @@ public class CardPluginImpl implements CardPlugin {
|
|||
|
||||
@Override
|
||||
public BufferedImage getOriginalImage(CardView card) {
|
||||
return ImageCache.getImageOriginal(card);
|
||||
return ImageCache.getImageOriginal(card).getImage();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package org.mage.plugins.card.images;
|
|||
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
|
@ -14,8 +13,6 @@ public class CardDownloadData {
|
|||
private String downloadName;
|
||||
private String fileName = "";
|
||||
private String set;
|
||||
private String tokenSetCode;
|
||||
private String tokenDescriptor;
|
||||
private final String collectorId;
|
||||
private final Integer type;
|
||||
private boolean token;
|
||||
|
@ -28,55 +25,51 @@ public class CardDownloadData {
|
|||
private String tokenClassName;
|
||||
private boolean isType2;
|
||||
|
||||
public CardDownloadData(String name, String set, String collectorId, boolean usesVariousArt, Integer type, String tokenSetCode, String tokenDescriptor) {
|
||||
this(name, set, collectorId, usesVariousArt, type, tokenSetCode, tokenDescriptor, false, "");
|
||||
public CardDownloadData(String name, String setCode, String collectorId, boolean usesVariousArt, Integer type) {
|
||||
this(name, setCode, collectorId, usesVariousArt, type, false, "");
|
||||
}
|
||||
|
||||
public CardDownloadData(String name, String set, String collectorId, boolean usesVariousArt, Integer type, String tokenSetCode, String tokenDescriptor, boolean token) {
|
||||
this(name, set, collectorId, usesVariousArt, type, tokenSetCode, tokenDescriptor, token, false, false, "");
|
||||
public CardDownloadData(String name, String setCode, String collectorId, boolean usesVariousArt, Integer type, boolean token) {
|
||||
this(name, setCode, collectorId, usesVariousArt, type, token, false, false, "");
|
||||
}
|
||||
|
||||
public CardDownloadData(String name, String set, String collectorId, boolean usesVariousArt, Integer type, String tokenSetCode, String tokenDescriptor, boolean token, String fileName) {
|
||||
this(name, set, collectorId, usesVariousArt, type, tokenSetCode, tokenDescriptor, token, false, false, "");
|
||||
public CardDownloadData(String name, String setCode, String collectorId, boolean usesVariousArt, Integer type, boolean token, String fileName) {
|
||||
this(name, setCode, collectorId, usesVariousArt, type, token, false, false, "");
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public CardDownloadData(String name, String set, String collectorId, boolean usesVariousArt, Integer type, String tokenSetCode, String tokenDescriptor, boolean token, boolean twoFacedCard, boolean secondSide) {
|
||||
this(name, set, collectorId, usesVariousArt, type, tokenSetCode, tokenDescriptor, token, twoFacedCard, secondSide, "");
|
||||
public CardDownloadData(String name, String setCode, String collectorId, boolean usesVariousArt, Integer type, boolean token, boolean twoFacedCard, boolean secondSide) {
|
||||
this(name, setCode, collectorId, usesVariousArt, type, token, twoFacedCard, secondSide, "");
|
||||
}
|
||||
|
||||
public CardDownloadData(String name, String set, String collectorId, boolean usesVariousArt, Integer type, String tokenSetCode, String tokenDescriptor, boolean token, boolean twoFacedCard, boolean secondSide, String tokenClassName) {
|
||||
public CardDownloadData(String name, String setCode, String collectorId, boolean usesVariousArt, Integer type, boolean token, boolean twoFacedCard, boolean secondSide, String tokenClassName) {
|
||||
this.name = name;
|
||||
this.set = set;
|
||||
this.set = setCode;
|
||||
this.collectorId = collectorId;
|
||||
this.usesVariousArt = usesVariousArt;
|
||||
this.type = type;
|
||||
this.token = token;
|
||||
this.twoFacedCard = twoFacedCard;
|
||||
this.secondSide = secondSide;
|
||||
this.tokenSetCode = tokenSetCode;
|
||||
this.tokenDescriptor = tokenDescriptor;
|
||||
this.tokenClassName = tokenClassName;
|
||||
|
||||
if (this.tokenDescriptor == null || this.tokenDescriptor.equalsIgnoreCase("")) {
|
||||
this.tokenDescriptor = lastDitchTokenDescriptor();
|
||||
}
|
||||
}
|
||||
|
||||
public CardDownloadData(final CardDownloadData card) {
|
||||
this.name = card.name;
|
||||
this.downloadName = card.downloadName;
|
||||
this.fileName = card.fileName;
|
||||
this.set = card.set;
|
||||
this.collectorId = card.collectorId;
|
||||
this.type = card.type;
|
||||
this.token = card.token;
|
||||
this.twoFacedCard = card.twoFacedCard;
|
||||
this.secondSide = card.secondSide;
|
||||
this.type = card.type;
|
||||
this.flipCard = card.flipCard;
|
||||
this.flippedSide = card.flippedSide;
|
||||
this.splitCard = card.splitCard;
|
||||
this.usesVariousArt = card.usesVariousArt;
|
||||
this.tokenSetCode = card.tokenSetCode;
|
||||
this.tokenDescriptor = card.tokenDescriptor;
|
||||
this.tokenClassName = card.tokenClassName;
|
||||
this.fileName = card.fileName;
|
||||
|
||||
this.isType2 = card.isType2;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -94,7 +87,7 @@ public class CardDownloadData {
|
|||
if (!Objects.equals(this.set, other.set)) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.collectorId, other.collectorId) && (this.collectorId == null || !this.collectorId.equals(other.collectorId))) {
|
||||
if (!Objects.equals(this.collectorId, other.collectorId)) {
|
||||
return false;
|
||||
}
|
||||
if (this.token != other.token) {
|
||||
|
@ -123,6 +116,11 @@ public class CardDownloadData {
|
|||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s - %s", this.getSet(), this.getName());
|
||||
}
|
||||
|
||||
public String getCollectorId() {
|
||||
return collectorId;
|
||||
}
|
||||
|
@ -171,18 +169,6 @@ public class CardDownloadData {
|
|||
this.set = set;
|
||||
}
|
||||
|
||||
public String getTokenSetCode() {
|
||||
return tokenSetCode;
|
||||
}
|
||||
|
||||
public void setTokenSetCode(String tokenSetCode) {
|
||||
this.tokenSetCode = tokenSetCode;
|
||||
}
|
||||
|
||||
public String getTokenDescriptor() {
|
||||
return tokenDescriptor;
|
||||
}
|
||||
|
||||
public void setTokenClassName(String tokenClassName) {
|
||||
this.tokenClassName = tokenClassName;
|
||||
}
|
||||
|
@ -191,17 +177,6 @@ public class CardDownloadData {
|
|||
return tokenClassName;
|
||||
}
|
||||
|
||||
public void setTokenDescriptor(String tokenDescriptor) {
|
||||
this.tokenDescriptor = tokenDescriptor;
|
||||
}
|
||||
|
||||
private String lastDitchTokenDescriptor() {
|
||||
String tmpName = this.name.replaceAll("[^a-zA-Z0-9]", "");
|
||||
String descriptor = tmpName + "....";
|
||||
descriptor = descriptor.toUpperCase(Locale.ENGLISH);
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
public boolean isToken() {
|
||||
return token;
|
||||
}
|
||||
|
|
|
@ -444,7 +444,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
|
|||
if (!card.getCardNumber().isEmpty() && !"0".equals(card.getCardNumber()) && !card.getSetCode().isEmpty()) {
|
||||
String cardName = card.getName();
|
||||
boolean isType2 = type2SetsFilter.contains(card.getSetCode());
|
||||
CardDownloadData url = new CardDownloadData(cardName, card.getSetCode(), card.getCardNumber(), card.usesVariousArt(), 0, "", "", false, card.isDoubleFaced(), card.isNightCard());
|
||||
CardDownloadData url = new CardDownloadData(cardName, card.getSetCode(), card.getCardNumber(), card.usesVariousArt(), 0, false, card.isDoubleFaced(), card.isNightCard());
|
||||
|
||||
// variations must have diff file names with additional postfix
|
||||
if (url.getUsesVariousArt()) {
|
||||
|
@ -475,7 +475,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
|
|||
card.getSetCode(),
|
||||
secondSideCard.getCardNumber(),
|
||||
card.usesVariousArt(),
|
||||
0, "", "", false, card.isDoubleFaced(), true);
|
||||
0, false, card.isDoubleFaced(), true);
|
||||
url.setType2(isType2);
|
||||
allCardsUrls.add(url);
|
||||
}
|
||||
|
@ -488,7 +488,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
|
|||
card.getSetCode(),
|
||||
card.getCardNumber(),
|
||||
card.usesVariousArt(),
|
||||
0, "", "", false, card.isDoubleFaced(), card.isNightCard());
|
||||
0, false, card.isDoubleFaced(), card.isNightCard());
|
||||
cardDownloadData.setFlipCard(true);
|
||||
cardDownloadData.setFlippedSide(true);
|
||||
cardDownloadData.setType2(isType2);
|
||||
|
@ -510,7 +510,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
|
|||
card.getSetCode(),
|
||||
meldsToCard.getCardNumber(),
|
||||
card.usesVariousArt(),
|
||||
0, "", "", false, false, false);
|
||||
0, false, false, false);
|
||||
url.setType2(isType2);
|
||||
allCardsUrls.add(url);
|
||||
}
|
||||
|
@ -523,7 +523,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
|
|||
card.getSetCode(),
|
||||
card.getCardNumber(),
|
||||
card.usesVariousArt(),
|
||||
0, "", "", false, true, true);
|
||||
0, false, true, true);
|
||||
cardDownloadData.setType2(isType2);
|
||||
allCardsUrls.add(cardDownloadData);
|
||||
}
|
||||
|
@ -549,7 +549,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
|
|||
cardsToDownload.add(card);
|
||||
} else {
|
||||
// need missing cards
|
||||
File file = new TFile(CardImageUtils.buildImagePathToCard(card));
|
||||
File file = new TFile(CardImageUtils.buildImagePathToCardOrToken(card));
|
||||
if (!file.exists()) {
|
||||
cardsToDownload.add(card);
|
||||
}
|
||||
|
@ -592,32 +592,32 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
|
|||
|
||||
if (params[1].toLowerCase(Locale.ENGLISH).equals("generate") && params[2].startsWith("TOK:")) {
|
||||
String set = params[2].substring(4);
|
||||
CardDownloadData card = new CardDownloadData(params[3], set, "0", false, type, "", "", true);
|
||||
CardDownloadData card = new CardDownloadData(params[3], set, "0", false, type,true);
|
||||
card.setTokenClassName(tokenClassName);
|
||||
list.add(card);
|
||||
} else if (params[1].toLowerCase(Locale.ENGLISH).equals("generate") && params[2].startsWith("EMBLEM:")) {
|
||||
String set = params[2].substring(7);
|
||||
CardDownloadData card = new CardDownloadData("Emblem " + params[3], set, "0", false, type, "", "", true, fileName);
|
||||
CardDownloadData card = new CardDownloadData("Emblem " + params[3], set, "0", false, type, true, fileName);
|
||||
card.setTokenClassName(tokenClassName);
|
||||
list.add(card);
|
||||
} else if (params[1].toLowerCase(Locale.ENGLISH).equals("generate") && params[2].startsWith("EMBLEM-:")) {
|
||||
String set = params[2].substring(8);
|
||||
CardDownloadData card = new CardDownloadData(params[3] + " Emblem", set, "0", false, type, "", "", true, fileName);
|
||||
CardDownloadData card = new CardDownloadData(params[3] + " Emblem", set, "0", false, type,true, fileName);
|
||||
card.setTokenClassName(tokenClassName);
|
||||
list.add(card);
|
||||
} else if (params[1].toLowerCase(Locale.ENGLISH).equals("generate") && params[2].startsWith("EMBLEM!:")) {
|
||||
String set = params[2].substring(8);
|
||||
CardDownloadData card = new CardDownloadData(params[3], set, "0", false, type, "", "", true, fileName);
|
||||
CardDownloadData card = new CardDownloadData(params[3], set, "0", false, type, true, fileName);
|
||||
card.setTokenClassName(tokenClassName);
|
||||
list.add(card);
|
||||
} else if (params[1].toLowerCase(Locale.ENGLISH).equals("generate") && params[2].startsWith("PLANE:")) {
|
||||
String set = params[2].substring(6);
|
||||
CardDownloadData card = new CardDownloadData(params[3], set, "0", false, type, "", "", true, fileName);
|
||||
CardDownloadData card = new CardDownloadData(params[3], set, "0", false, type, true, fileName);
|
||||
card.setTokenClassName(tokenClassName);
|
||||
list.add(card);
|
||||
} else if (params[1].toLowerCase(Locale.ENGLISH).equals("generate") && params[2].startsWith("DUNGEON:")) {
|
||||
String set = params[2].substring(8);
|
||||
CardDownloadData card = new CardDownloadData(params[3], set, "0", false, type, "", "", true, fileName);
|
||||
CardDownloadData card = new CardDownloadData(params[3], set, "0", false, type, true, fileName);
|
||||
card.setTokenClassName(tokenClassName);
|
||||
list.add(card);
|
||||
} else {
|
||||
|
@ -833,7 +833,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
|
|||
destFile = new TFile(CardImageUtils.buildImagePathToTokens() + actualFilename + ".jpg");
|
||||
}
|
||||
} else {
|
||||
destFile = new TFile(CardImageUtils.buildImagePathToCard(card));
|
||||
destFile = new TFile(CardImageUtils.buildImagePathToCardOrToken(card));
|
||||
}
|
||||
|
||||
// FILE already exists (in zip or in dir)
|
||||
|
@ -1008,7 +1008,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
|
|||
// finished
|
||||
List<CardDownloadData> downloadedCards = Collections.synchronizedList(new ArrayList<>());
|
||||
DownloadPicturesService.this.cardsMissing.parallelStream().forEach(cardDownloadData -> {
|
||||
TFile file = new TFile(CardImageUtils.buildImagePathToCard(cardDownloadData));
|
||||
TFile file = new TFile(CardImageUtils.buildImagePathToCardOrToken(cardDownloadData));
|
||||
if (file.exists()) {
|
||||
downloadedCards.add(cardDownloadData);
|
||||
}
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
package org.mage.plugins.card.images;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.ComputationException;
|
||||
import mage.abilities.icon.CardIconColor;
|
||||
import mage.client.constants.Constants;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.client.util.SoftValuesLoadingCache;
|
||||
import mage.client.util.TransformedImageCache;
|
||||
import mage.view.CardView;
|
||||
import net.java.truevfs.access.TFile;
|
||||
import net.java.truevfs.access.TFileInputStream;
|
||||
import net.java.truevfs.access.TFileOutputStream;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.mage.plugins.card.dl.sources.DirectLinksForDownload;
|
||||
import org.mage.plugins.card.utils.CardImageUtils;
|
||||
|
@ -20,7 +17,6 @@ import javax.imageio.ImageIO;
|
|||
import java.awt.*;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
@ -29,165 +25,113 @@ import java.util.regex.Pattern;
|
|||
* that the images may be garbage collected when they are not needed any more,
|
||||
* but will be kept as long as possible.
|
||||
* <p>
|
||||
* Key format: "[cardname]#[setname]#[type]#[collectorID]#[param]"
|
||||
* <p>
|
||||
* where param is:
|
||||
* <ul>
|
||||
* <li>size of image</li>
|
||||
* Key format: "[cardname]#[setname]#[type]#[collectorID]#[image size]#[additional data]"
|
||||
*
|
||||
* <li>#Normal: request for unrotated image</li>
|
||||
* <li>#Tapped: request for rotated image</li>
|
||||
* <li>#Cropped: request for cropped image that is used for Shandalar like card
|
||||
* look</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author JayDi85
|
||||
*/
|
||||
public final class ImageCache {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(ImageCache.class);
|
||||
|
||||
private static final SoftValuesLoadingCache<String, BufferedImage> IMAGE_CACHE;
|
||||
private static final SoftValuesLoadingCache<String, BufferedImage> FACE_IMAGE_CACHE;
|
||||
private static final SoftValuesLoadingCache<String, BufferedImage> CARD_ICONS_CACHE;
|
||||
private static final SoftValuesLoadingCache<String, ImageCacheData> IMAGE_CACHE; // cards and tokens
|
||||
private static final SoftValuesLoadingCache<String, ImageCacheData> FACE_IMAGE_CACHE;
|
||||
private static final SoftValuesLoadingCache<String, ImageCacheData> CARD_ICONS_CACHE;
|
||||
|
||||
/**
|
||||
* Common pattern for keys. See ImageCache.getKey for structure info
|
||||
*/
|
||||
private static final Pattern KEY_PATTERN = Pattern.compile("(.*)#(.*)#(.*)#(.*)#(.*)#(.*)");
|
||||
private static final Pattern KEY_PATTERN = Pattern.compile("(.*)#(.*)#(.*)#(.*)#(.*)");
|
||||
private static final Pattern CARD_ICON_KEY_PATTERN = Pattern.compile("(.*)#(.*)#(.*)");
|
||||
|
||||
static {
|
||||
// softValues() = Specifies that each value (not key) stored in the map should be wrapped in a SoftReference
|
||||
// (by default, strong references are used). Softly-referenced objects will be garbage-collected in a
|
||||
// globally least-recently-used manner, in response to memory demand.
|
||||
IMAGE_CACHE = SoftValuesLoadingCache.from(new Function<String, BufferedImage>() {
|
||||
@Override
|
||||
public BufferedImage apply(String key) {
|
||||
try {
|
||||
boolean usesVariousArt = false;
|
||||
if (key.matches(".*#usesVariousArt.*")) {
|
||||
usesVariousArt = true;
|
||||
key = key.replace("#usesVariousArt", "");
|
||||
IMAGE_CACHE = SoftValuesLoadingCache.from(key -> {
|
||||
try {
|
||||
boolean usesVariousArt = false;
|
||||
if (key.matches(".*#usesVariousArt.*")) {
|
||||
usesVariousArt = true;
|
||||
key = key.replace("#usesVariousArt", "");
|
||||
}
|
||||
Matcher m = KEY_PATTERN.matcher(key);
|
||||
|
||||
if (m.matches()) {
|
||||
String name = m.group(1);
|
||||
String setCode = m.group(2);
|
||||
Integer type = Integer.parseInt(m.group(3));
|
||||
String collectorId = m.group(4);
|
||||
if (collectorId.equals("null")) {
|
||||
collectorId = "0";
|
||||
}
|
||||
boolean thumbnail = false;
|
||||
if (key.matches(".*#thumb.*")) {
|
||||
thumbnail = true;
|
||||
key = key.replace("#thumb", "");
|
||||
}
|
||||
Matcher m = KEY_PATTERN.matcher(key);
|
||||
|
||||
if (m.matches()) {
|
||||
String name = m.group(1);
|
||||
String set = m.group(2);
|
||||
Integer type = Integer.parseInt(m.group(3));
|
||||
String collectorId = m.group(4);
|
||||
if (collectorId.equals("null")) {
|
||||
collectorId = "0";
|
||||
}
|
||||
String tokenSetCode = m.group(5);
|
||||
String tokenDescriptor = m.group(6);
|
||||
CardDownloadData info = new CardDownloadData(name, setCode, collectorId, usesVariousArt, type);
|
||||
|
||||
CardDownloadData info = new CardDownloadData(name, set, collectorId, usesVariousArt, type, tokenSetCode, tokenDescriptor);
|
||||
boolean cardback = false;
|
||||
String path;
|
||||
if (collectorId.isEmpty() || "0".equals(collectorId)) {
|
||||
// TOKEN
|
||||
// can be a normal token or a token from card (see embalm ability)
|
||||
info.setToken(true);
|
||||
TFile tokenFile;
|
||||
|
||||
boolean cardback = false;
|
||||
String path;
|
||||
if (collectorId.isEmpty() || "0".equals(collectorId) || !tokenDescriptor.isEmpty()) { // tokenDescriptor for embalm ability
|
||||
info.setToken(true);
|
||||
path = CardImageUtils.generateTokenImagePath(info);
|
||||
if (path == null) {
|
||||
cardback = true;
|
||||
// try token image from card
|
||||
CardDownloadData newInfo = new CardDownloadData(info);
|
||||
newInfo.setToken(false);
|
||||
path = CardImageUtils.buildImagePathToCard(newInfo);
|
||||
TFile tokenFile = getTFile(path);
|
||||
if (tokenFile == null || !tokenFile.exists()) {
|
||||
// token empty token image
|
||||
// TODO: replace empty token by other default card, not cardback
|
||||
path = CardImageUtils.buildImagePathToDefault(DirectLinksForDownload.cardbackFilename);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
path = CardImageUtils.buildImagePathToCard(info);
|
||||
// try normal token
|
||||
path = CardImageUtils.buildImagePathToCardOrToken(info);
|
||||
tokenFile = getTFile(path);
|
||||
|
||||
// try token from card
|
||||
if (tokenFile == null || !tokenFile.exists()) {
|
||||
CardDownloadData tempInfo = new CardDownloadData(info);
|
||||
tempInfo.setToken(false);
|
||||
path = CardImageUtils.buildImagePathToCardOrToken(info);
|
||||
tokenFile = getTFile(path);
|
||||
}
|
||||
|
||||
if (path == null) {
|
||||
return null;
|
||||
}
|
||||
TFile file = getTFile(path);
|
||||
if (file == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (thumbnail && path.endsWith(".jpg")) {
|
||||
// need thumbnail image
|
||||
String thumbnailPath = buildThumbnailPath(path);
|
||||
TFile thumbnailFile = null;
|
||||
try {
|
||||
thumbnailFile = new TFile(thumbnailPath);
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
boolean exists = false;
|
||||
if (thumbnailFile != null) {
|
||||
try {
|
||||
exists = thumbnailFile.exists();
|
||||
} catch (Exception ex) {
|
||||
exists = false;
|
||||
}
|
||||
}
|
||||
if (exists) {
|
||||
LOGGER.debug("loading thumbnail for " + key + ", path=" + thumbnailPath);
|
||||
BufferedImage thumbnailImage = loadImage(thumbnailFile);
|
||||
if (thumbnailImage == null) { // thumbnail exists but broken for some reason
|
||||
LOGGER.warn("failed loading thumbnail for " + key + ", path=" + thumbnailPath
|
||||
+ ", thumbnail file is probably broken, attempting to recreate it...");
|
||||
thumbnailImage = makeThumbnailByFile(key, file, thumbnailPath);
|
||||
}
|
||||
|
||||
if (cardback) {
|
||||
// unknown tokens on opponent desk
|
||||
thumbnailImage = getRoundCorner(thumbnailImage);
|
||||
}
|
||||
|
||||
return thumbnailImage;
|
||||
} else {
|
||||
return makeThumbnailByFile(key, file, thumbnailPath);
|
||||
}
|
||||
} else {
|
||||
if (cardback) {
|
||||
// need cardback image
|
||||
BufferedImage image = loadImage(file);
|
||||
image = getRoundCorner(image);
|
||||
return image;
|
||||
} else {
|
||||
// need normal card image
|
||||
BufferedImage image = loadImage(file);
|
||||
image = getWizardsCard(image);
|
||||
image = getRoundCorner(image);
|
||||
return image;
|
||||
}
|
||||
// try unknown token image
|
||||
if (tokenFile == null || !tokenFile.exists()) {
|
||||
// TODO: replace empty token by other default card, not cardback
|
||||
cardback = true;
|
||||
path = CardImageUtils.buildImagePathToDefault(DirectLinksForDownload.cardbackFilename);
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
"Requested image doesn't fit the requirement for key (<cardname>#<setname>#<collectorID>): " + key);
|
||||
// CARD
|
||||
path = CardImageUtils.buildImagePathToCardOrToken(info);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
if (ex instanceof ComputationException) {
|
||||
throw (ComputationException) ex;
|
||||
} else {
|
||||
throw new ComputationException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BufferedImage makeThumbnailByFile(String key, TFile file, String thumbnailPath) {
|
||||
BufferedImage image = loadImage(file);
|
||||
image = getWizardsCard(image);
|
||||
image = getRoundCorner(image);
|
||||
if (image == null) {
|
||||
return null;
|
||||
TFile file = getTFile(path);
|
||||
if (file == null) {
|
||||
return new ImageCacheData(path, null);
|
||||
}
|
||||
|
||||
if (cardback) {
|
||||
// TODO: is there any different in images styles? Cardback must be from scryfall, not wizards
|
||||
// need cardback image
|
||||
BufferedImage image = loadImage(file);
|
||||
image = getRoundCorner(image);
|
||||
return new ImageCacheData(path, image);
|
||||
} else {
|
||||
// need normal card image
|
||||
BufferedImage image = loadImage(file);
|
||||
image = getWizardsCard(image);
|
||||
image = getRoundCorner(image);
|
||||
return new ImageCacheData(path, image);
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
"Requested image doesn't fit the requirement for key (<cardname>#<setname>#<collectorID>): " + key);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
if (ex instanceof ComputationException) {
|
||||
throw (ComputationException) ex;
|
||||
} else {
|
||||
throw new ComputationException(ex);
|
||||
}
|
||||
LOGGER.debug("creating thumbnail for " + key);
|
||||
return makeThumbnail(image, thumbnailPath);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -197,22 +141,18 @@ public final class ImageCache {
|
|||
|
||||
if (m.matches()) {
|
||||
String name = m.group(1);
|
||||
String set = m.group(2);
|
||||
//Integer artid = Integer.parseInt(m.group(2));
|
||||
String setCode = m.group(2);
|
||||
// skip type
|
||||
// skip collectorId
|
||||
|
||||
String path;
|
||||
path = CardImageUtils.generateFaceImagePath(name, set);
|
||||
|
||||
if (path == null) {
|
||||
return null;
|
||||
}
|
||||
String path = CardImageUtils.generateFaceImagePath(name, setCode);
|
||||
TFile file = getTFile(path);
|
||||
if (file == null) {
|
||||
return null;
|
||||
return new ImageCacheData(path, null);
|
||||
}
|
||||
|
||||
BufferedImage image = loadImage(file);
|
||||
return image;
|
||||
return new ImageCacheData(path, image);
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
"Requested face image doesn't fit the requirement for key (<cardname>#<artid>#: " + key);
|
||||
|
@ -235,7 +175,7 @@ public final class ImageCache {
|
|||
String resourceName = m.group(2);
|
||||
CardIconColor cardIconColor = CardIconColor.valueOf(m.group(3));
|
||||
BufferedImage image = ImageManagerImpl.instance.getCardIcon(resourceName, cardSize, cardIconColor);
|
||||
return image;
|
||||
return new ImageCacheData(resourceName, image);
|
||||
} else {
|
||||
throw new RuntimeException("Wrong card icons image key format: " + key);
|
||||
}
|
||||
|
@ -255,109 +195,38 @@ public final class ImageCache {
|
|||
CARD_ICONS_CACHE.invalidateAll();
|
||||
}
|
||||
|
||||
public static String getFilePath(CardView card, int width) {
|
||||
String key = getKey(card, card.getName(), Integer.toString(width));
|
||||
boolean usesVariousArt = false;
|
||||
if (key.matches(".*#usesVariousArt.*")) {
|
||||
usesVariousArt = true;
|
||||
key = key.replace("#usesVariousArt", "");
|
||||
}
|
||||
boolean thumbnail = false;
|
||||
if (key.matches(".*#thumb.*")) {
|
||||
thumbnail = true;
|
||||
key = key.replace("#thumb", "");
|
||||
}
|
||||
Matcher m = KEY_PATTERN.matcher(key);
|
||||
|
||||
if (m.matches()) {
|
||||
String name = m.group(1);
|
||||
String set = m.group(2);
|
||||
Integer type = Integer.parseInt(m.group(3));
|
||||
String collectorId = m.group(4);
|
||||
if (collectorId.equals("null")) {
|
||||
collectorId = "0";
|
||||
}
|
||||
String tokenSetCode = m.group(5);
|
||||
String tokenDescriptor = m.group(6);
|
||||
|
||||
CardDownloadData info = new CardDownloadData(name, set, collectorId, usesVariousArt, type, tokenSetCode, tokenDescriptor);
|
||||
|
||||
String path;
|
||||
if (collectorId.isEmpty() || "0".equals(collectorId) || !tokenDescriptor.isEmpty()) { // tokenDescriptor for embalm ability
|
||||
info.setToken(true);
|
||||
path = CardImageUtils.generateTokenImagePath(info);
|
||||
if (path == null) {
|
||||
// try token image from card
|
||||
CardDownloadData newInfo = new CardDownloadData(info);
|
||||
newInfo.setToken(false);
|
||||
path = CardImageUtils.buildImagePathToCard(newInfo);
|
||||
TFile tokenFile = getTFile(path);
|
||||
if (tokenFile == null || !tokenFile.exists()) {
|
||||
// token empty token image
|
||||
// TODO: replace empty token by other default card, not cardback
|
||||
path = CardImageUtils.buildImagePathToDefault(DirectLinksForDownload.cardbackFilename);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
path = CardImageUtils.buildImagePathToCard(info);
|
||||
}
|
||||
|
||||
if (thumbnail && path.endsWith(".jpg")) {
|
||||
return buildThumbnailPath(path);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
private ImageCache() {
|
||||
}
|
||||
|
||||
public static BufferedImage getCardbackImage() {
|
||||
BufferedImage image = ImageCache.loadImage(new TFile(CardImageUtils.buildImagePathToDefault(DirectLinksForDownload.cardbackFilename)));
|
||||
public static ImageCacheData getCardbackImage() {
|
||||
String path = CardImageUtils.buildImagePathToDefault(DirectLinksForDownload.cardbackFilename);
|
||||
BufferedImage image = ImageCache.loadImage(getTFile(path));
|
||||
image = getRoundCorner(image);
|
||||
return image;
|
||||
return new ImageCacheData(path, image);
|
||||
}
|
||||
|
||||
public static BufferedImage getMorphImage() {
|
||||
// TODO: replace by morth image
|
||||
CardDownloadData info = new CardDownloadData("Morph", "KTK", "0", false, 0, "KTK", "");
|
||||
public static ImageCacheData getMorphImage() {
|
||||
// TODO: replace by downloadable morth image
|
||||
CardDownloadData info = new CardDownloadData("Morph", "KTK", "0", false, 0);
|
||||
info.setToken(true);
|
||||
String path = CardImageUtils.generateTokenImagePath(info);
|
||||
if (path == null) {
|
||||
return null;
|
||||
}
|
||||
TFile file = getTFile(path);
|
||||
String path = CardImageUtils.buildImagePathToCardOrToken(info);
|
||||
|
||||
TFile file = getTFile(path);
|
||||
BufferedImage image = loadImage(file);
|
||||
image = getRoundCorner(image);
|
||||
return image;
|
||||
return new ImageCacheData(path, image);
|
||||
}
|
||||
|
||||
public static BufferedImage getManifestImage() {
|
||||
// TODO: replace by manifestest image
|
||||
CardDownloadData info = new CardDownloadData("Manifest", "FRF", "0", false, 0, "FRF", "");
|
||||
public static ImageCacheData getManifestImage() {
|
||||
// TODO: replace by downloadable manifestest image
|
||||
CardDownloadData info = new CardDownloadData("Manifest", "FRF", "0", false, 0);
|
||||
info.setToken(true);
|
||||
String path = CardImageUtils.generateTokenImagePath(info);
|
||||
if (path == null) {
|
||||
return null;
|
||||
}
|
||||
TFile file = getTFile(path);
|
||||
String path = CardImageUtils.buildImagePathToCardOrToken(info);
|
||||
|
||||
TFile file = getTFile(path);
|
||||
BufferedImage image = loadImage(file);
|
||||
image = getRoundCorner(image);
|
||||
return image;
|
||||
}
|
||||
|
||||
private static String buildThumbnailPath(String path) {
|
||||
String thumbnailPath;
|
||||
if (PreferencesDialog.isSaveImagesToZip()) {
|
||||
thumbnailPath = path.replace(".zip", ".thumb.zip");
|
||||
} else {
|
||||
thumbnailPath = path.replace(".jpg", ".thumb.jpg");
|
||||
}
|
||||
return thumbnailPath;
|
||||
return new ImageCacheData(path, image);
|
||||
}
|
||||
|
||||
public static BufferedImage getRoundCorner(BufferedImage image) {
|
||||
|
@ -387,6 +256,7 @@ public final class ImageCache {
|
|||
}
|
||||
|
||||
public static BufferedImage getWizardsCard(BufferedImage image) {
|
||||
// TODO: can be removed?
|
||||
if (image != null && image.getWidth() == 265 && image.getHeight() == 370) {
|
||||
BufferedImage crop = new BufferedImage(256, 360, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D graphics2D = crop.createGraphics();
|
||||
|
@ -398,80 +268,61 @@ public final class ImageCache {
|
|||
}
|
||||
}
|
||||
|
||||
public static boolean isFaceImagePresent(CardView card) {
|
||||
String path;
|
||||
path = CardImageUtils.generateFaceImagePath(card.getName(), card.getExpansionSetCode());
|
||||
|
||||
if (path == null) {
|
||||
return false;
|
||||
}
|
||||
TFile file = getTFile(path);
|
||||
if (file == null) {
|
||||
return false;
|
||||
}
|
||||
return file.exists();
|
||||
public static ImageCacheData getImageOriginal(CardView card) {
|
||||
return getImage(getKey(card, card.getName(), 0));
|
||||
}
|
||||
|
||||
public static BufferedImage getThumbnail(CardView card) {
|
||||
return getImage(getKey(card, card.getName(), "#thumb"));
|
||||
public static ImageCacheData getImageOriginalAlternateName(CardView card) {
|
||||
return getImage(getKey(card, card.getAlternateName(), 0));
|
||||
}
|
||||
|
||||
public static BufferedImage tryGetThumbnail(CardView card) {
|
||||
return tryGetImage(getKey(card, card.getName(), "#thumb"));
|
||||
}
|
||||
|
||||
public static BufferedImage getImageOriginal(CardView card) {
|
||||
return getImage(getKey(card, card.getName(), ""));
|
||||
}
|
||||
|
||||
public static BufferedImage getImageOriginalAlternateName(CardView card) {
|
||||
return getImage(getKey(card, card.getAlternateName(), ""));
|
||||
}
|
||||
|
||||
public static BufferedImage getCardIconImage(String resourceName, int iconSize, String cardColorName) {
|
||||
public static ImageCacheData getCardIconImage(String resourceName, int iconSize, String cardColorName) {
|
||||
return getCardIconImage(getCardIconKey(resourceName, iconSize, cardColorName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Image corresponding to the key
|
||||
*/
|
||||
private static BufferedImage getImage(String key) {
|
||||
private static ImageCacheData getImage(String key) {
|
||||
try {
|
||||
return IMAGE_CACHE.getOrNull(key);
|
||||
ImageCacheData data = IMAGE_CACHE.getOrNull(key);
|
||||
return data != null ? data : new ImageCacheData("ERROR: key - " + key, null);
|
||||
} catch (ComputationException ex) {
|
||||
// too low memory
|
||||
if (ex.getCause() instanceof NullPointerException) {
|
||||
return null;
|
||||
return new ImageCacheData("ERROR: low memory?", null);
|
||||
}
|
||||
LOGGER.error(ex, ex);
|
||||
return null;
|
||||
return new ImageCacheData("ERROR: see logs", null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Image corresponding to the key
|
||||
*/
|
||||
private static BufferedImage getFaceImage(String key) {
|
||||
private static ImageCacheData getFaceImage(String key) {
|
||||
try {
|
||||
return FACE_IMAGE_CACHE.getOrNull(key);
|
||||
ImageCacheData data = FACE_IMAGE_CACHE.getOrNull(key);
|
||||
return data != null ? data : new ImageCacheData("ERROR: key " + key, null);
|
||||
} catch (ComputationException ex) {
|
||||
if (ex.getCause() instanceof NullPointerException) {
|
||||
return null;
|
||||
return new ImageCacheData("ERROR: low memory?", null);
|
||||
}
|
||||
LOGGER.error(ex, ex);
|
||||
return null;
|
||||
return new ImageCacheData("ERROR: see logs", null);
|
||||
}
|
||||
}
|
||||
|
||||
private static BufferedImage getCardIconImage(String key) {
|
||||
private static ImageCacheData getCardIconImage(String key) {
|
||||
try {
|
||||
return CARD_ICONS_CACHE.getOrNull(key);
|
||||
ImageCacheData data = CARD_ICONS_CACHE.getOrNull(key);
|
||||
return data != null ? data : new ImageCacheData("ERROR: key - " + key, null);
|
||||
} catch (ComputationException ex) {
|
||||
if (ex.getCause() instanceof NullPointerException) {
|
||||
return null;
|
||||
return new ImageCacheData("ERROR: low memory?", null);
|
||||
}
|
||||
LOGGER.error(ex, ex);
|
||||
return null;
|
||||
return new ImageCacheData("ERROR: see logs", null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -479,22 +330,24 @@ public final class ImageCache {
|
|||
* Returns the Image corresponding to the key only if it already exists in
|
||||
* the cache.
|
||||
*/
|
||||
private static BufferedImage tryGetImage(String key) {
|
||||
private static ImageCacheData tryGetImage(String key) {
|
||||
return IMAGE_CACHE.peekIfPresent(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the map key for a card, without any suffixes for the image size.
|
||||
* Generate key for images cache (it must contain all info to search and load image from the disk)
|
||||
*
|
||||
* @param card
|
||||
* @param cardName - can be alternative name
|
||||
* @param imageSize - size info, 0 to use original image (with max size)
|
||||
*/
|
||||
private static String getKey(CardView card, String name, String suffix) {
|
||||
return (card.isToken() ? name.replace(" Token", "") : name)
|
||||
private static String getKey(CardView card, String cardName, int imageSize) {
|
||||
return (card.isToken() ? cardName.replace(" Token", "") : cardName)
|
||||
+ '#' + card.getExpansionSetCode()
|
||||
+ '#' + card.getType()
|
||||
+ '#' + card.getCardNumber()
|
||||
+ '#' + (card.getTokenSetCode() == null ? "" : card.getTokenSetCode())
|
||||
+ suffix
|
||||
+ (card.getUsesVariousArt() ? "#usesVariousArt" : "")
|
||||
+ '#' + (card.getTokenDescriptor() != null ? card.getTokenDescriptor() : "");
|
||||
+ '#' + imageSize
|
||||
+ (card.getUsesVariousArt() ? "#usesVariousArt" : "");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -534,24 +387,6 @@ public final class ImageCache {
|
|||
return image;
|
||||
}
|
||||
|
||||
public static BufferedImage makeThumbnail(BufferedImage original, String path) {
|
||||
BufferedImage image = TransformedImageCache.getResizedImage(original, Constants.THUMBNAIL_SIZE_FULL.width, Constants.THUMBNAIL_SIZE_FULL.height);
|
||||
TFile imageFile = getTFile(path);
|
||||
if (imageFile == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
try (TFileOutputStream outputStream = new TFileOutputStream(imageFile)) {
|
||||
String format = image.getColorModel().getNumComponents() > 3 ? "png" : "jpg";
|
||||
ImageIO.write(image, format, outputStream);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOGGER.error(e.getMessage(), e);
|
||||
imageFile.delete();
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an image scaled to the size given
|
||||
*
|
||||
|
@ -584,23 +419,22 @@ public final class ImageCache {
|
|||
* @param height
|
||||
* @return
|
||||
*/
|
||||
public static BufferedImage getImage(CardView card, int width, int height) {
|
||||
if (Constants.THUMBNAIL_SIZE_FULL.width + 10 > width) {
|
||||
return getThumbnail(card);
|
||||
}
|
||||
String key = getKey(card, card.getName(), Integer.toString(width));
|
||||
BufferedImage original = getImage(key);
|
||||
if (original == null) {
|
||||
LOGGER.debug(key + " not found");
|
||||
return null;
|
||||
public static ImageCacheData getImage(CardView card, int width, int height) {
|
||||
String key = getKey(card, card.getName(), width);
|
||||
ImageCacheData data = getImage(key);
|
||||
if (data.getImage() == null) {
|
||||
LOGGER.debug("Image doesn't exists in the cache: " + key);
|
||||
return data;
|
||||
}
|
||||
|
||||
double scale = Math.min((double) width / original.getWidth(), (double) height / original.getHeight());
|
||||
double scale = Math.min((double) width / data.getImage().getWidth(), (double) height / data.getImage().getHeight());
|
||||
if (scale >= 1) {
|
||||
return original;
|
||||
return data;
|
||||
}
|
||||
|
||||
return TransformedImageCache.getResizedImage(original, (int) (original.getWidth() * scale), (int) (original.getHeight() * scale));
|
||||
BufferedImage newImage = TransformedImageCache.getResizedImage(data.getImage(), (int) (data.getImage().getWidth() * scale), (int) (data.getImage().getHeight() * scale));
|
||||
data.setImage(newImage);
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -611,15 +445,13 @@ public final class ImageCache {
|
|||
* @param height
|
||||
* @return
|
||||
*/
|
||||
public static BufferedImage getFaceImage(CardView card, int width, int height) {
|
||||
public static ImageCacheData getFaceImage(CardView card, int width, int height) {
|
||||
String key = getFaceKey(card, card.getName(), card.getExpansionSetCode());
|
||||
BufferedImage original = getFaceImage(key);
|
||||
if (original == null) {
|
||||
ImageCacheData data = getFaceImage(key);
|
||||
if (data.getImage() == null) {
|
||||
LOGGER.debug(key + " (faceimage) not found");
|
||||
return null;
|
||||
}
|
||||
|
||||
return original;
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -632,29 +464,31 @@ public final class ImageCache {
|
|||
* @param height
|
||||
* @return
|
||||
*/
|
||||
public static BufferedImage tryGetImage(CardView card, int width, int height) {
|
||||
if (Constants.THUMBNAIL_SIZE_FULL.width + 10 > width) {
|
||||
return tryGetThumbnail(card);
|
||||
}
|
||||
String key = getKey(card, card.getName(), Integer.toString(width));
|
||||
BufferedImage original = tryGetImage(key);
|
||||
if (original == null) {
|
||||
public static ImageCacheData tryGetImage(CardView card, int width, int height) {
|
||||
String key = getKey(card, card.getName(), width);
|
||||
ImageCacheData data = tryGetImage(key);
|
||||
if (data.getImage() == null) {
|
||||
LOGGER.debug(key + " not found");
|
||||
return null;
|
||||
return data;
|
||||
}
|
||||
|
||||
double scale = Math.min((double) width / original.getWidth(), (double) height / original.getHeight());
|
||||
double scale = Math.min((double) width / data.getImage().getWidth(), (double) height / data.getImage().getHeight());
|
||||
if (scale >= 1) {
|
||||
return original;
|
||||
return data;
|
||||
}
|
||||
|
||||
return TransformedImageCache.getResizedImage(original, (int) (original.getWidth() * scale), (int) (original.getHeight() * scale));
|
||||
BufferedImage newImage = TransformedImageCache.getResizedImage(data.getImage(), (int) (data.getImage().getWidth() * scale), (int) (data.getImage().getHeight() * scale));
|
||||
data.setImage(newImage);
|
||||
return data;
|
||||
}
|
||||
|
||||
public static TFile getTFile(String path) {
|
||||
try {
|
||||
return new TFile(path);
|
||||
if (path != null) {
|
||||
return new TFile(path);
|
||||
}
|
||||
} catch (NullPointerException ex) {
|
||||
// TODO: raise error on path == null -- is it actual?!
|
||||
LOGGER.warn("Imagefile does not exist: " + path);
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
package org.mage.plugins.card.images;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class ImageCacheData {
|
||||
String path;
|
||||
BufferedImage image;
|
||||
|
||||
public ImageCacheData(String path, BufferedImage image) {
|
||||
this.path = path;
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public BufferedImage getImage() {
|
||||
return image;
|
||||
}
|
||||
|
||||
public void setImage(BufferedImage image) {
|
||||
this.image = image;
|
||||
}
|
||||
}
|
|
@ -5,7 +5,6 @@ import mage.client.constants.Constants;
|
|||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.remote.Connection;
|
||||
import mage.remote.Connection.ProxyType;
|
||||
import net.java.truevfs.access.TFile;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
|
@ -26,87 +25,13 @@ import java.nio.file.SimpleFileVisitor;
|
|||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.prefs.Preferences;
|
||||
|
||||
public final class CardImageUtils {
|
||||
|
||||
private static final HashMap<CardDownloadData, String> pathCache = new HashMap<>();
|
||||
private static final Logger LOGGER = Logger.getLogger(CardImageUtils.class);
|
||||
|
||||
/**
|
||||
* @param card
|
||||
* @return String if image exists, else null
|
||||
*/
|
||||
public static String generateTokenImagePath(CardDownloadData card) {
|
||||
if (card.isToken()) {
|
||||
String filePath = getTokenImagePath(card);
|
||||
if (pathCache.containsKey(card)) {
|
||||
if (filePath.equals(pathCache.get(card))) {
|
||||
return pathCache.get(card);
|
||||
}
|
||||
}
|
||||
TFile file = new TFile(filePath);
|
||||
|
||||
if (!file.exists() && card.getTokenSetCode() != null) {
|
||||
filePath = searchForCardImage(card);
|
||||
file = new TFile(filePath);
|
||||
}
|
||||
|
||||
if (file.exists()) {
|
||||
pathCache.put(card, filePath);
|
||||
return filePath;
|
||||
}
|
||||
|
||||
//log.warn("Token image file not found. Set: " + card.getSet() + " Token Set Code: " + card.getTokenSetCode() + " Name: " + card.getName() + " File path: " + getTokenImagePath(card));
|
||||
} else {
|
||||
LOGGER.warn("Trying to get token path for non token card. Set: " + card.getSet() + " Set Code: " + card.getTokenSetCode() + " Name: " + card.getName());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param card
|
||||
* @return String regardless of whether image exists
|
||||
*/
|
||||
public static String generateFullTokenImagePath(CardDownloadData card) {
|
||||
if (card.isToken()) {
|
||||
return getTokenImagePath(card);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private static String getTokenImagePath(CardDownloadData card) {
|
||||
String filename = buildImagePathToCard(card);
|
||||
|
||||
TFile file = new TFile(filename);
|
||||
if (!file.exists()) {
|
||||
String tokenDescriptorfilename = generateTokenDescriptorImagePath(card);
|
||||
if (!tokenDescriptorfilename.isEmpty()) {
|
||||
file = new TFile(filename);
|
||||
if (file.exists()) {
|
||||
return tokenDescriptorfilename;
|
||||
}
|
||||
}
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
|
||||
private static String searchForCardImage(CardDownloadData card) {
|
||||
TFile file;
|
||||
String path;
|
||||
CardDownloadData c = new CardDownloadData(card);
|
||||
c.setSet(card.getTokenSetCode());
|
||||
path = getTokenImagePath(c);
|
||||
file = new TFile(path);
|
||||
if (file.exists()) {
|
||||
pathCache.put(card, path);
|
||||
return path;
|
||||
}
|
||||
return generateTokenDescriptorImagePath(card);
|
||||
}
|
||||
|
||||
public static String prepareCardNameForFile(String cardName) {
|
||||
return cardName
|
||||
.replace(":", "")
|
||||
|
@ -141,12 +66,12 @@ public final class CardImageUtils {
|
|||
return getImagesDir() + Constants.RESOURCE_PATH_DEFAULT_IMAGES + File.separator + defaultFileName;
|
||||
}
|
||||
|
||||
public static String fixSetNameForWindows(String set) {
|
||||
public static String fixSetNameForWindows(String setCode) {
|
||||
// windows can't create con folders
|
||||
if (set.equals("CON") || set.equals("con")) {
|
||||
if (setCode.equals("CON") || setCode.equals("con")) {
|
||||
return "COX";
|
||||
} else {
|
||||
return set;
|
||||
return setCode;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,40 +85,34 @@ public final class CardImageUtils {
|
|||
}
|
||||
}
|
||||
|
||||
private static String buildImagePathToTokenDescriptor(CardDownloadData card) {
|
||||
return buildImagePathToTokens() + card.getTokenDescriptor() + ".full.jpg";
|
||||
}
|
||||
|
||||
public static String buildImagePathToSet(CardDownloadData card) {
|
||||
|
||||
if (card.getSet() == null) {
|
||||
throw new IllegalArgumentException("Card " + card.getName() + " have empty set.");
|
||||
}
|
||||
|
||||
String set = card.getSet().toUpperCase(Locale.ENGLISH);
|
||||
String setCode = card.getSet().toUpperCase(Locale.ENGLISH);
|
||||
|
||||
if (card.isToken()) {
|
||||
return buildImagePathToSetAsToken(set);
|
||||
return buildImagePathToSetAsToken(setCode);
|
||||
} else {
|
||||
return buildImagePathToSetAsCard(set);
|
||||
return buildImagePathToSetAsCard(setCode);
|
||||
}
|
||||
}
|
||||
|
||||
private static String buildImagePathToSetAsCard(String set) {
|
||||
private static String buildImagePathToSetAsCard(String setCode) {
|
||||
String imagesPath = getImagesDir() + File.separator;
|
||||
|
||||
if (PreferencesDialog.isSaveImagesToZip()) {
|
||||
return imagesPath + fixSetNameForWindows(set) + ".zip" + File.separator + fixSetNameForWindows(set) + File.separator;
|
||||
return imagesPath + fixSetNameForWindows(setCode) + ".zip" + File.separator + fixSetNameForWindows(setCode) + File.separator;
|
||||
} else {
|
||||
return imagesPath + fixSetNameForWindows(set) + File.separator;
|
||||
return imagesPath + fixSetNameForWindows(setCode) + File.separator;
|
||||
}
|
||||
}
|
||||
|
||||
private static String buildImagePathToSetAsToken(String set) {
|
||||
return buildImagePathToTokens() + fixSetNameForWindows(set) + File.separator;
|
||||
private static String buildImagePathToSetAsToken(String setCode) {
|
||||
return buildImagePathToTokens() + fixSetNameForWindows(setCode) + File.separator;
|
||||
}
|
||||
|
||||
public static String buildImagePathToCard(CardDownloadData card) {
|
||||
public static String buildImagePathToCardOrToken(CardDownloadData card) {
|
||||
|
||||
String setPath = buildImagePathToSet(card);
|
||||
|
||||
|
@ -207,7 +126,7 @@ public final class CardImageUtils {
|
|||
cardName = prepareCardNameForFile(card.getName());
|
||||
}
|
||||
|
||||
String finalFileName = "";
|
||||
String finalFileName;
|
||||
if (card.getUsesVariousArt()) {
|
||||
// different arts uses name + collector id
|
||||
finalFileName = cardName + prefixType + '.' + card.getCollectorIdAsFileName() + ".full.jpg";
|
||||
|
@ -216,54 +135,11 @@ public final class CardImageUtils {
|
|||
finalFileName = cardName + prefixType + ".full.jpg";
|
||||
}
|
||||
|
||||
/* 2019-01-12: no needs in name corrections, all files must be same and auto-downloaded
|
||||
// if image file exists, correct name (for case sensitive systems)
|
||||
// use TFile for zips
|
||||
TFile dirFile = new TFile(setPath);
|
||||
TFile imageFile = new TFile(setPath + finalFileName);
|
||||
// warning, zip files can be broken
|
||||
try {
|
||||
if (dirFile.exists() && !imageFile.exists()) {
|
||||
// search like names
|
||||
for (String fileName : dirFile.list()) {
|
||||
if (fileName.toLowerCase(Locale.ENGLISH).equals(finalFileName.toLowerCase(Locale.ENGLISH))) {
|
||||
finalFileName = fileName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
log.error("Can't read card name from file, may be it broken: " + setPath);
|
||||
}
|
||||
*/
|
||||
|
||||
return setPath + finalFileName;
|
||||
}
|
||||
|
||||
public static String generateFaceImagePath(String cardname, String set) {
|
||||
return getImagesDir() + File.separator + "FACE" + File.separator + fixSetNameForWindows(set) + File.separator + prepareCardNameForFile(cardname) + ".jpg";
|
||||
}
|
||||
|
||||
public static String generateTokenDescriptorImagePath(CardDownloadData card) {
|
||||
|
||||
String straightImageFile = buildImagePathToTokenDescriptor(card);
|
||||
TFile file = new TFile(straightImageFile);
|
||||
if (file.exists()) {
|
||||
return straightImageFile;
|
||||
}
|
||||
|
||||
straightImageFile = straightImageFile.replaceFirst("\\.[0-9]+\\.[0-9]+", ".X.X");
|
||||
file = new TFile(straightImageFile);
|
||||
if (file.exists()) {
|
||||
return straightImageFile;
|
||||
}
|
||||
|
||||
straightImageFile = straightImageFile.replaceFirst("\\.X\\.X", ".S.S");
|
||||
file = new TFile(straightImageFile);
|
||||
if (file.exists()) {
|
||||
return straightImageFile;
|
||||
}
|
||||
return "";
|
||||
public static String generateFaceImagePath(String cardName, String setCode) {
|
||||
return getImagesDir() + File.separator + "FACE" + File.separator + fixSetNameForWindows(setCode) + File.separator + prepareCardNameForFile(cardName) + ".jpg";
|
||||
}
|
||||
|
||||
public static Proxy getProxyFromPreferences() {
|
||||
|
@ -305,8 +181,7 @@ public final class CardImageUtils {
|
|||
}
|
||||
|
||||
public static void checkAndFixImageFiles() {
|
||||
// search broken files and delete it (zero size files)
|
||||
// search temp files and delete it (.tmp files from zip library)
|
||||
// search broken, temp or outdated files and delete it
|
||||
Path rootPath = new File(CardImageUtils.getImagesDir()).toPath();
|
||||
if (!Files.exists(rootPath)) {
|
||||
return;
|
||||
|
@ -314,6 +189,7 @@ public final class CardImageUtils {
|
|||
|
||||
Collection<Path> brokenFilesList = new ArrayList<>();
|
||||
Collection<Path> tempFilesList = new ArrayList<>();
|
||||
Collection<Path> outdatedFilesList = new ArrayList<>();
|
||||
try {
|
||||
Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() {
|
||||
@Override
|
||||
|
@ -329,6 +205,11 @@ public final class CardImageUtils {
|
|||
tempFilesList.add(file);
|
||||
}
|
||||
|
||||
// 3. outdated files delete without warning
|
||||
if (file.toString().endsWith(".thumb.zip")) {
|
||||
outdatedFilesList.add(file);
|
||||
}
|
||||
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
|
@ -336,10 +217,13 @@ public final class CardImageUtils {
|
|||
LOGGER.error("Can't load files list from images folder: " + rootPath.toAbsolutePath().toString(), e);
|
||||
}
|
||||
|
||||
// temp files must be deleted without errors
|
||||
for (Path tempFile : tempFilesList) {
|
||||
// temp and outdated files must be deleted without errors
|
||||
Collection<Path> list = new ArrayList<>();
|
||||
list.addAll(tempFilesList);
|
||||
list.addAll(outdatedFilesList);
|
||||
for (Path path : list) {
|
||||
try {
|
||||
Files.delete(tempFile);
|
||||
Files.delete(path);
|
||||
} catch (Throwable e) {
|
||||
// ignore any error (e.g. it opened by xmage app)
|
||||
}
|
||||
|
@ -353,7 +237,7 @@ public final class CardImageUtils {
|
|||
Files.delete(brokenFile);
|
||||
} catch (Throwable e) {
|
||||
// stop clean on any error
|
||||
LOGGER.error("Images check: ERROR, can't delete broken file: " + brokenFile.toAbsolutePath().toString(), e);
|
||||
LOGGER.error("Images check: ERROR, can't delete broken file: " + brokenFile.toAbsolutePath(), e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,16 +18,16 @@ public class TokensMtgImageSourceTest {
|
|||
public void generateTokenUrlTest() throws Exception {
|
||||
CardImageSource imageSource = TokensMtgImageSource.instance;
|
||||
|
||||
CardImageUrls url = imageSource.generateTokenUrl(new CardDownloadData("Thopter", "ORI", "0", false, 1, "ORI", ""));
|
||||
CardImageUrls url = imageSource.generateTokenUrl(new CardDownloadData("Thopter", "ORI", "0", false, 1));
|
||||
Assert.assertEquals("https://tokens.mtg.onl/tokens/ORI_010-Thopter.jpg", url.baseUrl);
|
||||
|
||||
url = imageSource.generateTokenUrl(new CardDownloadData("Thopter", "ORI", "0", false, 2, "ORI", ""));
|
||||
url = imageSource.generateTokenUrl(new CardDownloadData("Thopter", "ORI", "0", false, 2));
|
||||
Assert.assertEquals("https://tokens.mtg.onl/tokens/ORI_011-Thopter.jpg", url.baseUrl);
|
||||
|
||||
url = imageSource.generateTokenUrl(new CardDownloadData("Ashaya, the Awoken World", "ORI", "0", false, 0, "ORI", ""));
|
||||
url = imageSource.generateTokenUrl(new CardDownloadData("Ashaya, the Awoken World", "ORI", "0", false, 0));
|
||||
Assert.assertEquals("https://tokens.mtg.onl/tokens/ORI_007-Ashaya,-the-Awoken-World.jpg", url.baseUrl);
|
||||
|
||||
url = imageSource.generateTokenUrl(new CardDownloadData("Emblem Gideon, Ally of Zendikar", "BFZ", "0", false, 0, null, ""));
|
||||
url = imageSource.generateTokenUrl(new CardDownloadData("Emblem Gideon, Ally of Zendikar", "BFZ", "0", false, 0));
|
||||
Assert.assertEquals("https://tokens.mtg.onl/tokens/BFZ_012-Gideon-Emblem.jpg", url.baseUrl);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -273,7 +273,7 @@ public class CardView extends SimpleCardView {
|
|||
* @param storeZone if true the card zone will be set in the zone attribute.
|
||||
*/
|
||||
public CardView(Card card, Game game, boolean controlled, boolean showFaceDownCard, boolean storeZone) {
|
||||
super(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt(), card.getTokenSetCode(), game != null, card.getTokenDescriptor());
|
||||
super(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt(), game != null);
|
||||
this.originalCard = card;
|
||||
|
||||
// no information available for face down cards as long it's not a controlled face down morph card
|
||||
|
@ -487,7 +487,6 @@ public class CardView extends SimpleCardView {
|
|||
} else {
|
||||
// a created token
|
||||
this.expansionSetCode = card.getExpansionSetCode();
|
||||
this.tokenDescriptor = card.getTokenDescriptor();
|
||||
}
|
||||
//
|
||||
// set code and card number for token copies to get the image
|
||||
|
@ -600,7 +599,7 @@ public class CardView extends SimpleCardView {
|
|||
}
|
||||
|
||||
public CardView(MageObject object, Game game) {
|
||||
super(object.getId(), "", "0", false, "", true, "");
|
||||
super(object.getId(), "", "0", false, true);
|
||||
this.originalCard = null;
|
||||
|
||||
this.name = object.getName();
|
||||
|
@ -674,7 +673,7 @@ public class CardView extends SimpleCardView {
|
|||
}
|
||||
|
||||
protected CardView() {
|
||||
super(null, "", "0", false, "", true, "");
|
||||
super(null, "", "0", false, true);
|
||||
}
|
||||
|
||||
public CardView(EmblemView emblem) {
|
||||
|
@ -739,7 +738,7 @@ public class CardView extends SimpleCardView {
|
|||
}
|
||||
|
||||
public CardView(boolean empty) {
|
||||
super(null, "", "0", false, "", "");
|
||||
super(null, "", "0", false);
|
||||
if (!empty) {
|
||||
throw new IllegalArgumentException("Not supported.");
|
||||
}
|
||||
|
@ -793,9 +792,10 @@ public class CardView extends SimpleCardView {
|
|||
}
|
||||
|
||||
CardView(Token token, Game game) {
|
||||
super(token.getId(), "", "0", false, "", "");
|
||||
super(token.getId(), "", "0", false);
|
||||
this.isToken = true;
|
||||
this.id = token.getId();
|
||||
this.expansionSetCode = token.getOriginalExpansionSetCode();
|
||||
this.name = token.getName();
|
||||
this.displayName = token.getName();
|
||||
this.displayFullName = token.getName();
|
||||
|
@ -814,8 +814,6 @@ public class CardView extends SimpleCardView {
|
|||
this.manaCostRightStr = "";
|
||||
this.rarity = Rarity.SPECIAL;
|
||||
this.type = token.getTokenType();
|
||||
this.tokenDescriptor = token.getTokenDescriptor();
|
||||
this.tokenSetCode = token.getOriginalExpansionSetCode();
|
||||
}
|
||||
|
||||
protected final void addTargets(Targets targets, Effects effects, Ability source, Game game) {
|
||||
|
|
|
@ -20,7 +20,7 @@ public class LookedAtView implements Serializable {
|
|||
public LookedAtView(String name, Cards cards, Game game) {
|
||||
this.name = name;
|
||||
for (Card card: cards.getCards(game)) {
|
||||
this.cards.put(card.getId(), new SimpleCardView(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt(), card.getTokenSetCode(), card.getTokenDescriptor()));
|
||||
this.cards.put(card.getId(), new SimpleCardView(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,8 +54,7 @@ public class PermanentView extends CardView {
|
|||
if (isToken()) {
|
||||
original = new CardView(((PermanentToken) permanent).getToken().copy(), (Game) null);
|
||||
original.expansionSetCode = permanent.getExpansionSetCode();
|
||||
tokenSetCode = original.getTokenSetCode();
|
||||
tokenDescriptor = original.getTokenDescriptor();
|
||||
expansionSetCode = permanent.getExpansionSetCode();
|
||||
} else {
|
||||
if (card != null) {
|
||||
// original may not be face down
|
||||
|
|
|
@ -13,8 +13,6 @@ public class SimpleCardView implements Serializable, SelectableObjectView {
|
|||
@Expose
|
||||
protected UUID id;
|
||||
protected String expansionSetCode;
|
||||
protected String tokenSetCode;
|
||||
protected String tokenDescriptor;
|
||||
protected String cardNumber;
|
||||
protected boolean usesVariousArt;
|
||||
protected boolean gameObject;
|
||||
|
@ -26,28 +24,23 @@ public class SimpleCardView implements Serializable, SelectableObjectView {
|
|||
public SimpleCardView(final SimpleCardView view) {
|
||||
this.id = view.id;
|
||||
this.expansionSetCode = view.expansionSetCode;
|
||||
this.tokenSetCode = view.tokenSetCode;
|
||||
this.tokenDescriptor = view.tokenDescriptor;
|
||||
this.cardNumber = view.cardNumber;
|
||||
this.usesVariousArt = view.usesVariousArt;
|
||||
this.gameObject = view.gameObject;
|
||||
|
||||
this.isChoosable = view.isChoosable;
|
||||
this.isSelected = view.isSelected;
|
||||
this.playableStats = view.playableStats.copy();
|
||||
}
|
||||
|
||||
public SimpleCardView(UUID id, String expansionSetCode, String cardNumber, boolean usesVariousArt, String tokenSetCode, String tokenDescriptor) {
|
||||
this(id, expansionSetCode, cardNumber, usesVariousArt, tokenSetCode, false, tokenDescriptor);
|
||||
public SimpleCardView(UUID id, String expansionSetCode, String cardNumber, boolean usesVariousArt) {
|
||||
this(id, expansionSetCode, cardNumber, usesVariousArt, false);
|
||||
}
|
||||
|
||||
public SimpleCardView(UUID id, String expansionSetCode, String cardNumber, boolean usesVariousArt, String tokenSetCode, boolean isGameObject, String tokenDescriptor) {
|
||||
public SimpleCardView(UUID id, String expansionSetCode, String cardNumber, boolean usesVariousArt, boolean isGameObject) {
|
||||
this.id = id;
|
||||
this.expansionSetCode = expansionSetCode;
|
||||
this.tokenDescriptor = tokenDescriptor;
|
||||
this.cardNumber = cardNumber;
|
||||
this.usesVariousArt = usesVariousArt;
|
||||
this.tokenSetCode = tokenSetCode;
|
||||
this.gameObject = isGameObject;
|
||||
}
|
||||
|
||||
|
@ -67,14 +60,6 @@ public class SimpleCardView implements Serializable, SelectableObjectView {
|
|||
return usesVariousArt;
|
||||
}
|
||||
|
||||
public String getTokenSetCode() {
|
||||
return tokenSetCode;
|
||||
}
|
||||
|
||||
public String getTokenDescriptor() {
|
||||
return tokenDescriptor;
|
||||
}
|
||||
|
||||
public boolean isGameObject() {
|
||||
return gameObject;
|
||||
}
|
||||
|
|
|
@ -18,8 +18,7 @@ public class SimpleCardsView extends LinkedHashMap<UUID, SimpleCardView> {
|
|||
|
||||
public SimpleCardsView(Collection<Card> cards, boolean isGameObject) {
|
||||
for (Card card: cards) {
|
||||
this.put(card.getId(), new SimpleCardView(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt(), card.getTokenSetCode(), isGameObject,
|
||||
card.getTokenDescriptor()));
|
||||
this.put(card.getId(), new SimpleCardView(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt(), isGameObject));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
package org.mage.test.serverside;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.permanent.PermanentToken;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class TokenImagesTest extends CardTestPlayerBase {
|
||||
|
||||
@Test
|
||||
public void test_TokenMustGetSameSetCodeAsSourceCard() {
|
||||
//{3}{W}, {T}, Sacrifice Memorial to Glory: Create two 1/1 white Soldier creature tokens.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "40K:Memorial to Glory");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{3}{W}, {T}, Sacrifice");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Soldier Token", 2);
|
||||
currentGame.getBattlefield().getAllPermanents().stream()
|
||||
.filter(card -> card.getName().equals("Soldier Token"))
|
||||
.forEach(card -> {
|
||||
Assert.assertEquals("40K", card.getExpansionSetCode());
|
||||
Assert.assertEquals("40K", ((PermanentToken) card).getToken().getOriginalExpansionSetCode());
|
||||
});
|
||||
}
|
||||
}
|
|
@ -622,7 +622,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
|
|||
Assert.fail("Can't add card " + cardName + " - alias " + aliasName + " already exists for " + player.getName());
|
||||
}
|
||||
|
||||
// set code for
|
||||
// set code for card
|
||||
String setCode = "";
|
||||
String setLookup = CardUtil.substring(cardName, CardUtil.TESTS_SET_CODE_LOOKUP_LENGTH);
|
||||
if (setLookup.contains(":")) {
|
||||
|
|
|
@ -49,11 +49,6 @@ public interface Card extends MageObject {
|
|||
List<String> getRules(Game game); // gets card rules + in game modifications
|
||||
|
||||
String getExpansionSetCode();
|
||||
|
||||
String getTokenSetCode();
|
||||
|
||||
String getTokenDescriptor();
|
||||
|
||||
void checkForCountersToAdd(Permanent permanent, Ability source, Game game);
|
||||
|
||||
void setFaceDown(boolean value, Game game);
|
||||
|
|
|
@ -42,8 +42,6 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
protected UUID ownerId;
|
||||
protected String cardNumber;
|
||||
protected String expansionSetCode;
|
||||
protected String tokenSetCode;
|
||||
protected String tokenDescriptor;
|
||||
protected Rarity rarity;
|
||||
protected Class<? extends Card> secondSideCardClazz;
|
||||
protected Class<? extends Card> meldsWithClazz;
|
||||
|
@ -121,8 +119,6 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
ownerId = card.ownerId;
|
||||
cardNumber = card.cardNumber;
|
||||
expansionSetCode = card.expansionSetCode;
|
||||
tokenSetCode = card.tokenSetCode;
|
||||
tokenDescriptor = card.tokenDescriptor;
|
||||
rarity = card.rarity;
|
||||
|
||||
secondSideCardClazz = card.secondSideCardClazz;
|
||||
|
@ -378,16 +374,6 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
return expansionSetCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTokenSetCode() {
|
||||
return tokenSetCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTokenDescriptor() {
|
||||
return tokenDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Mana> getMana() {
|
||||
List<Mana> mana = new ArrayList<>();
|
||||
|
|
|
@ -87,7 +87,6 @@ public class PermanentToken extends PermanentImpl {
|
|||
this.supertype.clear();
|
||||
this.supertype.addAll(token.getSuperType());
|
||||
this.subtype.copyFrom(token.getSubtype(game));
|
||||
this.tokenDescriptor = token.getTokenDescriptor();
|
||||
this.startingLoyalty = token.getStartingLoyalty();
|
||||
// workaround for entersTheBattlefield replacement effects
|
||||
if (this.abilities.containsClass(ChangelingAbility.class)) {
|
||||
|
|
|
@ -17,8 +17,6 @@ public interface Token extends MageObject {
|
|||
@Override
|
||||
Token copy();
|
||||
|
||||
String getTokenDescriptor();
|
||||
|
||||
String getDescription();
|
||||
|
||||
List<UUID> getLastAddedTokenIds();
|
||||
|
|
|
@ -85,12 +85,6 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
|
|||
this.tokenDescriptor = tokenDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTokenDescriptor() {
|
||||
this.tokenDescriptor = tokenDescriptor();
|
||||
return tokenDescriptor;
|
||||
}
|
||||
|
||||
private String tokenDescriptor() {
|
||||
String strName = this.name.replaceAll("[^a-zA-Z0-9]", "");
|
||||
String strColor = this.color.toString().replaceAll("[^a-zA-Z0-9]", "");
|
||||
|
|
|
@ -697,16 +697,6 @@ public class Spell extends StackObjectImpl implements Card {
|
|||
return card.getExpansionSetCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTokenSetCode() {
|
||||
return card.getTokenSetCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTokenDescriptor() {
|
||||
return card.getTokenDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFaceDown(boolean value, Game game) {
|
||||
faceDown = value;
|
||||
|
|
Loading…
Reference in a new issue