mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 10:40:06 -08: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);
|
//BufferedImage iconImage = ImageManagerImpl.instance.getCardIcon(icon.getIconType().getResourceName(), this.halfSize * 2);
|
||||||
|
|
||||||
// cached call
|
// 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) {
|
if (iconImageCached != null && this.font != null) {
|
||||||
BufferedImage iconImageWithText = ImageManagerImpl.deepCopy(iconImageCached); // must copy cached value before modify
|
BufferedImage iconImageWithText = ImageManagerImpl.deepCopy(iconImageCached); // must copy cached value before modify
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,6 @@ public final class Constants {
|
||||||
|
|
||||||
// cards render
|
// cards render
|
||||||
public static final Rectangle CARD_SIZE_FULL = new Rectangle(101, 149);
|
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
|
// resources - default images
|
||||||
public static final String RESOURCE_PATH_DEFAULT_IMAGES = File.separator + "default";
|
public static final String RESOURCE_PATH_DEFAULT_IMAGES = File.separator + "default";
|
||||||
|
|
|
||||||
|
|
@ -677,7 +677,7 @@ public class MageActionCallback implements ActionCallback {
|
||||||
switch (enlargeMode) {
|
switch (enlargeMode) {
|
||||||
case COPY:
|
case COPY:
|
||||||
if (cardView instanceof PermanentView) {
|
if (cardView instanceof PermanentView) {
|
||||||
image = ImageCache.getImageOriginal(((PermanentView) cardView).getOriginal());
|
image = ImageCache.getImageOriginal(((PermanentView) cardView).getOriginal()).getImage();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ALTERNATE:
|
case ALTERNATE:
|
||||||
|
|
@ -686,9 +686,9 @@ public class MageActionCallback implements ActionCallback {
|
||||||
&& !cardView.isFlipCard()
|
&& !cardView.isFlipCard()
|
||||||
&& !cardView.canTransform()
|
&& !cardView.canTransform()
|
||||||
&& ((PermanentView) cardView).isCopy()) {
|
&& ((PermanentView) cardView).isCopy()) {
|
||||||
image = ImageCache.getImageOriginal(((PermanentView) cardView).getOriginal());
|
image = ImageCache.getImageOriginal(((PermanentView) cardView).getOriginal()).getImage();
|
||||||
} else {
|
} else {
|
||||||
image = ImageCache.getImageOriginalAlternateName(cardView);
|
image = ImageCache.getImageOriginalAlternateName(cardView).getImage();
|
||||||
displayCard = displayCard.getSecondCardFace();
|
displayCard = displayCard.getSecondCardFace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ package org.mage.card.arcane;
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.cards.MageCardLocation;
|
import mage.cards.MageCardLocation;
|
||||||
import mage.cards.action.ActionCallback;
|
import mage.cards.action.ActionCallback;
|
||||||
import mage.client.constants.Constants;
|
|
||||||
import mage.client.dialog.PreferencesDialog;
|
import mage.client.dialog.PreferencesDialog;
|
||||||
import mage.client.util.ImageCaches;
|
import mage.client.util.ImageCaches;
|
||||||
import mage.client.util.ImageHelper;
|
import mage.client.util.ImageHelper;
|
||||||
|
|
@ -19,6 +18,7 @@ import mage.view.PermanentView;
|
||||||
import mage.view.StackAbilityView;
|
import mage.view.StackAbilityView;
|
||||||
import org.jdesktop.swingx.graphics.GraphicsUtilities;
|
import org.jdesktop.swingx.graphics.GraphicsUtilities;
|
||||||
import org.mage.plugins.card.images.ImageCache;
|
import org.mage.plugins.card.images.ImageCache;
|
||||||
|
import org.mage.plugins.card.images.ImageCacheData;
|
||||||
import org.mage.plugins.card.utils.impl.ImageManagerImpl;
|
import org.mage.plugins.card.utils.impl.ImageManagerImpl;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
@ -466,9 +466,9 @@ public class CardPanelRenderModeImage extends CardPanel {
|
||||||
public Image getImage() {
|
public Image getImage() {
|
||||||
if (this.hasImage) {
|
if (this.hasImage) {
|
||||||
if (getGameCard().isFaceDown()) {
|
if (getGameCard().isFaceDown()) {
|
||||||
return getFaceDownImage();
|
return getFaceDownImage().getImage();
|
||||||
} else {
|
} else {
|
||||||
return ImageCache.getImageOriginal(getGameCard());
|
return ImageCache.getImageOriginal(getGameCard()).getImage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -629,27 +629,27 @@ public class CardPanelRenderModeImage extends CardPanel {
|
||||||
setTappedAngle(isTapped() ? CardPanel.TAPPED_ANGLE : 0);
|
setTappedAngle(isTapped() ? CardPanel.TAPPED_ANGLE : 0);
|
||||||
setFlippedAngle(isFlipped() ? CardPanel.FLIPPED_ANGLE : 0);
|
setFlippedAngle(isFlipped() ? CardPanel.FLIPPED_ANGLE : 0);
|
||||||
|
|
||||||
//final CardView gameCard = this.gameCard;
|
|
||||||
final int stamp = ++updateArtImageStamp;
|
final int stamp = ++updateArtImageStamp;
|
||||||
|
|
||||||
Util.threadPool.submit(() -> {
|
Util.threadPool.submit(() -> {
|
||||||
try {
|
try {
|
||||||
final BufferedImage srcImage;
|
final ImageCacheData data;
|
||||||
if (getGameCard().isFaceDown()) {
|
if (getGameCard().isFaceDown()) {
|
||||||
srcImage = getFaceDownImage();
|
data = getFaceDownImage();
|
||||||
} else if (getCardWidth() > Constants.THUMBNAIL_SIZE_FULL.width) {
|
|
||||||
srcImage = ImageCache.getImage(getGameCard(), getCardWidth(), getCardHeight());
|
|
||||||
} else {
|
} 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(() -> {
|
UI.invokeLater(() -> {
|
||||||
if (stamp == updateArtImageStamp) {
|
if (stamp == updateArtImageStamp) {
|
||||||
hasImage = srcImage != null;
|
hasImage = data.getImage() != null;
|
||||||
setTitle(getGameCard());
|
setTitle(getGameCard());
|
||||||
setImage(srcImage);
|
setImage(data.getImage());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (Exception | Error e) {
|
} catch (Exception | Error e) {
|
||||||
|
|
@ -658,7 +658,7 @@ public class CardPanelRenderModeImage extends CardPanel {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private BufferedImage getFaceDownImage() {
|
private ImageCacheData getFaceDownImage() {
|
||||||
// TODO: add download default images
|
// TODO: add download default images
|
||||||
if (isPermanent() && getGameCard() instanceof PermanentView) {
|
if (isPermanent() && getGameCard() instanceof PermanentView) {
|
||||||
if (((PermanentView) getGameCard()).isMorphed()) {
|
if (((PermanentView) getGameCard()).isMorphed()) {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ package org.mage.card.arcane;
|
||||||
import com.google.common.cache.Cache;
|
import com.google.common.cache.Cache;
|
||||||
import com.google.common.cache.CacheBuilder;
|
import com.google.common.cache.CacheBuilder;
|
||||||
import mage.cards.action.ActionCallback;
|
import mage.cards.action.ActionCallback;
|
||||||
import mage.client.constants.Constants;
|
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
import mage.constants.SuperType;
|
import mage.constants.SuperType;
|
||||||
|
|
@ -13,6 +12,7 @@ import mage.view.PermanentView;
|
||||||
import mage.view.StackAbilityView;
|
import mage.view.StackAbilityView;
|
||||||
import org.jdesktop.swingx.graphics.GraphicsUtilities;
|
import org.jdesktop.swingx.graphics.GraphicsUtilities;
|
||||||
import org.mage.plugins.card.images.ImageCache;
|
import org.mage.plugins.card.images.ImageCache;
|
||||||
|
import org.mage.plugins.card.images.ImageCacheData;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
|
@ -194,9 +194,9 @@ public class CardPanelRenderModeMTGO extends CardPanel {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (getGameCard().isFaceDown()) {
|
if (getGameCard().isFaceDown()) {
|
||||||
return getFaceDownImage();
|
return getFaceDownImage().getImage();
|
||||||
} else {
|
} else {
|
||||||
return ImageCache.getImageOriginal(getGameCard());
|
return ImageCache.getImageOriginal(getGameCard()).getImage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -319,12 +319,9 @@ public class CardPanelRenderModeMTGO extends CardPanel {
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
srcImage = null;
|
srcImage = null;
|
||||||
faceArtSrcImage = null;
|
faceArtSrcImage = null;
|
||||||
} else if (getCardWidth() > Constants.THUMBNAIL_SIZE_FULL.width) {
|
|
||||||
srcImage = ImageCache.getImage(getGameCard(), getCardWidth(), getCardHeight());
|
|
||||||
faceArtSrcImage = ImageCache.getFaceImage(getGameCard(), getCardWidth(), getCardHeight());
|
|
||||||
} else {
|
} else {
|
||||||
srcImage = ImageCache.getThumbnail(getGameCard());
|
srcImage = ImageCache.getImage(getGameCard(), getCardWidth(), getCardHeight()).getImage();
|
||||||
faceArtSrcImage = ImageCache.getFaceImage(getGameCard(), getCardWidth(), getCardHeight());
|
faceArtSrcImage = ImageCache.getFaceImage(getGameCard(), getCardWidth(), getCardHeight()).getImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
UI.invokeLater(() -> {
|
UI.invokeLater(() -> {
|
||||||
|
|
@ -352,7 +349,7 @@ public class CardPanelRenderModeMTGO extends CardPanel {
|
||||||
return new CardPanelAttributes(getCardWidth(), getCardHeight(), isChoosable(), isSelected(), isTransformed());
|
return new CardPanelAttributes(getCardWidth(), getCardHeight(), isChoosable(), isSelected(), isTransformed());
|
||||||
}
|
}
|
||||||
|
|
||||||
private BufferedImage getFaceDownImage() {
|
private ImageCacheData getFaceDownImage() {
|
||||||
// TODO: add download default images
|
// TODO: add download default images
|
||||||
if (isPermanent() && getGameCard() instanceof PermanentView) {
|
if (isPermanent() && getGameCard() instanceof PermanentView) {
|
||||||
if (((PermanentView) getGameCard()).isMorphed()) {
|
if (((PermanentView) getGameCard()).isMorphed()) {
|
||||||
|
|
|
||||||
|
|
@ -710,6 +710,6 @@ public class CardPluginImpl implements CardPlugin {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BufferedImage getOriginalImage(CardView card) {
|
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 mage.util.CardUtil;
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -14,8 +13,6 @@ public class CardDownloadData {
|
||||||
private String downloadName;
|
private String downloadName;
|
||||||
private String fileName = "";
|
private String fileName = "";
|
||||||
private String set;
|
private String set;
|
||||||
private String tokenSetCode;
|
|
||||||
private String tokenDescriptor;
|
|
||||||
private final String collectorId;
|
private final String collectorId;
|
||||||
private final Integer type;
|
private final Integer type;
|
||||||
private boolean token;
|
private boolean token;
|
||||||
|
|
@ -28,55 +25,51 @@ public class CardDownloadData {
|
||||||
private String tokenClassName;
|
private String tokenClassName;
|
||||||
private boolean isType2;
|
private boolean isType2;
|
||||||
|
|
||||||
public CardDownloadData(String name, String set, String collectorId, boolean usesVariousArt, Integer type, String tokenSetCode, String tokenDescriptor) {
|
public CardDownloadData(String name, String setCode, String collectorId, boolean usesVariousArt, Integer type) {
|
||||||
this(name, set, collectorId, usesVariousArt, type, tokenSetCode, tokenDescriptor, false, "");
|
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) {
|
public CardDownloadData(String name, String setCode, String collectorId, boolean usesVariousArt, Integer type, boolean token) {
|
||||||
this(name, set, collectorId, usesVariousArt, type, tokenSetCode, tokenDescriptor, token, false, false, "");
|
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) {
|
public CardDownloadData(String name, String setCode, String collectorId, boolean usesVariousArt, Integer type, boolean token, String fileName) {
|
||||||
this(name, set, collectorId, usesVariousArt, type, tokenSetCode, tokenDescriptor, token, false, false, "");
|
this(name, setCode, collectorId, usesVariousArt, type, token, false, false, "");
|
||||||
this.fileName = fileName;
|
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) {
|
public CardDownloadData(String name, String setCode, String collectorId, boolean usesVariousArt, Integer type, boolean token, boolean twoFacedCard, boolean secondSide) {
|
||||||
this(name, set, collectorId, usesVariousArt, type, tokenSetCode, tokenDescriptor, token, twoFacedCard, 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.name = name;
|
||||||
this.set = set;
|
this.set = setCode;
|
||||||
this.collectorId = collectorId;
|
this.collectorId = collectorId;
|
||||||
this.usesVariousArt = usesVariousArt;
|
this.usesVariousArt = usesVariousArt;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.token = token;
|
this.token = token;
|
||||||
this.twoFacedCard = twoFacedCard;
|
this.twoFacedCard = twoFacedCard;
|
||||||
this.secondSide = secondSide;
|
this.secondSide = secondSide;
|
||||||
this.tokenSetCode = tokenSetCode;
|
|
||||||
this.tokenDescriptor = tokenDescriptor;
|
|
||||||
this.tokenClassName = tokenClassName;
|
this.tokenClassName = tokenClassName;
|
||||||
|
|
||||||
if (this.tokenDescriptor == null || this.tokenDescriptor.equalsIgnoreCase("")) {
|
|
||||||
this.tokenDescriptor = lastDitchTokenDescriptor();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CardDownloadData(final CardDownloadData card) {
|
public CardDownloadData(final CardDownloadData card) {
|
||||||
this.name = card.name;
|
this.name = card.name;
|
||||||
|
this.downloadName = card.downloadName;
|
||||||
|
this.fileName = card.fileName;
|
||||||
this.set = card.set;
|
this.set = card.set;
|
||||||
this.collectorId = card.collectorId;
|
this.collectorId = card.collectorId;
|
||||||
|
this.type = card.type;
|
||||||
this.token = card.token;
|
this.token = card.token;
|
||||||
this.twoFacedCard = card.twoFacedCard;
|
this.twoFacedCard = card.twoFacedCard;
|
||||||
this.secondSide = card.secondSide;
|
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.usesVariousArt = card.usesVariousArt;
|
||||||
this.tokenSetCode = card.tokenSetCode;
|
|
||||||
this.tokenDescriptor = card.tokenDescriptor;
|
|
||||||
this.tokenClassName = card.tokenClassName;
|
this.tokenClassName = card.tokenClassName;
|
||||||
this.fileName = card.fileName;
|
this.isType2 = card.isType2;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -94,7 +87,7 @@ public class CardDownloadData {
|
||||||
if (!Objects.equals(this.set, other.set)) {
|
if (!Objects.equals(this.set, other.set)) {
|
||||||
return false;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
if (this.token != other.token) {
|
if (this.token != other.token) {
|
||||||
|
|
@ -123,6 +116,11 @@ public class CardDownloadData {
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("%s - %s", this.getSet(), this.getName());
|
||||||
|
}
|
||||||
|
|
||||||
public String getCollectorId() {
|
public String getCollectorId() {
|
||||||
return collectorId;
|
return collectorId;
|
||||||
}
|
}
|
||||||
|
|
@ -171,18 +169,6 @@ public class CardDownloadData {
|
||||||
this.set = set;
|
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) {
|
public void setTokenClassName(String tokenClassName) {
|
||||||
this.tokenClassName = tokenClassName;
|
this.tokenClassName = tokenClassName;
|
||||||
}
|
}
|
||||||
|
|
@ -191,17 +177,6 @@ public class CardDownloadData {
|
||||||
return tokenClassName;
|
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() {
|
public boolean isToken() {
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -444,7 +444,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
|
||||||
if (!card.getCardNumber().isEmpty() && !"0".equals(card.getCardNumber()) && !card.getSetCode().isEmpty()) {
|
if (!card.getCardNumber().isEmpty() && !"0".equals(card.getCardNumber()) && !card.getSetCode().isEmpty()) {
|
||||||
String cardName = card.getName();
|
String cardName = card.getName();
|
||||||
boolean isType2 = type2SetsFilter.contains(card.getSetCode());
|
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
|
// variations must have diff file names with additional postfix
|
||||||
if (url.getUsesVariousArt()) {
|
if (url.getUsesVariousArt()) {
|
||||||
|
|
@ -475,7 +475,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
|
||||||
card.getSetCode(),
|
card.getSetCode(),
|
||||||
secondSideCard.getCardNumber(),
|
secondSideCard.getCardNumber(),
|
||||||
card.usesVariousArt(),
|
card.usesVariousArt(),
|
||||||
0, "", "", false, card.isDoubleFaced(), true);
|
0, false, card.isDoubleFaced(), true);
|
||||||
url.setType2(isType2);
|
url.setType2(isType2);
|
||||||
allCardsUrls.add(url);
|
allCardsUrls.add(url);
|
||||||
}
|
}
|
||||||
|
|
@ -488,7 +488,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
|
||||||
card.getSetCode(),
|
card.getSetCode(),
|
||||||
card.getCardNumber(),
|
card.getCardNumber(),
|
||||||
card.usesVariousArt(),
|
card.usesVariousArt(),
|
||||||
0, "", "", false, card.isDoubleFaced(), card.isNightCard());
|
0, false, card.isDoubleFaced(), card.isNightCard());
|
||||||
cardDownloadData.setFlipCard(true);
|
cardDownloadData.setFlipCard(true);
|
||||||
cardDownloadData.setFlippedSide(true);
|
cardDownloadData.setFlippedSide(true);
|
||||||
cardDownloadData.setType2(isType2);
|
cardDownloadData.setType2(isType2);
|
||||||
|
|
@ -510,7 +510,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
|
||||||
card.getSetCode(),
|
card.getSetCode(),
|
||||||
meldsToCard.getCardNumber(),
|
meldsToCard.getCardNumber(),
|
||||||
card.usesVariousArt(),
|
card.usesVariousArt(),
|
||||||
0, "", "", false, false, false);
|
0, false, false, false);
|
||||||
url.setType2(isType2);
|
url.setType2(isType2);
|
||||||
allCardsUrls.add(url);
|
allCardsUrls.add(url);
|
||||||
}
|
}
|
||||||
|
|
@ -523,7 +523,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
|
||||||
card.getSetCode(),
|
card.getSetCode(),
|
||||||
card.getCardNumber(),
|
card.getCardNumber(),
|
||||||
card.usesVariousArt(),
|
card.usesVariousArt(),
|
||||||
0, "", "", false, true, true);
|
0, false, true, true);
|
||||||
cardDownloadData.setType2(isType2);
|
cardDownloadData.setType2(isType2);
|
||||||
allCardsUrls.add(cardDownloadData);
|
allCardsUrls.add(cardDownloadData);
|
||||||
}
|
}
|
||||||
|
|
@ -549,7 +549,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
|
||||||
cardsToDownload.add(card);
|
cardsToDownload.add(card);
|
||||||
} else {
|
} else {
|
||||||
// need missing cards
|
// need missing cards
|
||||||
File file = new TFile(CardImageUtils.buildImagePathToCard(card));
|
File file = new TFile(CardImageUtils.buildImagePathToCardOrToken(card));
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
cardsToDownload.add(card);
|
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:")) {
|
if (params[1].toLowerCase(Locale.ENGLISH).equals("generate") && params[2].startsWith("TOK:")) {
|
||||||
String set = params[2].substring(4);
|
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);
|
card.setTokenClassName(tokenClassName);
|
||||||
list.add(card);
|
list.add(card);
|
||||||
} else if (params[1].toLowerCase(Locale.ENGLISH).equals("generate") && params[2].startsWith("EMBLEM:")) {
|
} else if (params[1].toLowerCase(Locale.ENGLISH).equals("generate") && params[2].startsWith("EMBLEM:")) {
|
||||||
String set = params[2].substring(7);
|
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);
|
card.setTokenClassName(tokenClassName);
|
||||||
list.add(card);
|
list.add(card);
|
||||||
} else if (params[1].toLowerCase(Locale.ENGLISH).equals("generate") && params[2].startsWith("EMBLEM-:")) {
|
} else if (params[1].toLowerCase(Locale.ENGLISH).equals("generate") && params[2].startsWith("EMBLEM-:")) {
|
||||||
String set = params[2].substring(8);
|
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);
|
card.setTokenClassName(tokenClassName);
|
||||||
list.add(card);
|
list.add(card);
|
||||||
} else if (params[1].toLowerCase(Locale.ENGLISH).equals("generate") && params[2].startsWith("EMBLEM!:")) {
|
} else if (params[1].toLowerCase(Locale.ENGLISH).equals("generate") && params[2].startsWith("EMBLEM!:")) {
|
||||||
String set = params[2].substring(8);
|
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);
|
card.setTokenClassName(tokenClassName);
|
||||||
list.add(card);
|
list.add(card);
|
||||||
} else if (params[1].toLowerCase(Locale.ENGLISH).equals("generate") && params[2].startsWith("PLANE:")) {
|
} else if (params[1].toLowerCase(Locale.ENGLISH).equals("generate") && params[2].startsWith("PLANE:")) {
|
||||||
String set = params[2].substring(6);
|
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);
|
card.setTokenClassName(tokenClassName);
|
||||||
list.add(card);
|
list.add(card);
|
||||||
} else if (params[1].toLowerCase(Locale.ENGLISH).equals("generate") && params[2].startsWith("DUNGEON:")) {
|
} else if (params[1].toLowerCase(Locale.ENGLISH).equals("generate") && params[2].startsWith("DUNGEON:")) {
|
||||||
String set = params[2].substring(8);
|
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);
|
card.setTokenClassName(tokenClassName);
|
||||||
list.add(card);
|
list.add(card);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -833,7 +833,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
|
||||||
destFile = new TFile(CardImageUtils.buildImagePathToTokens() + actualFilename + ".jpg");
|
destFile = new TFile(CardImageUtils.buildImagePathToTokens() + actualFilename + ".jpg");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
destFile = new TFile(CardImageUtils.buildImagePathToCard(card));
|
destFile = new TFile(CardImageUtils.buildImagePathToCardOrToken(card));
|
||||||
}
|
}
|
||||||
|
|
||||||
// FILE already exists (in zip or in dir)
|
// FILE already exists (in zip or in dir)
|
||||||
|
|
@ -1008,7 +1008,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
|
||||||
// finished
|
// finished
|
||||||
List<CardDownloadData> downloadedCards = Collections.synchronizedList(new ArrayList<>());
|
List<CardDownloadData> downloadedCards = Collections.synchronizedList(new ArrayList<>());
|
||||||
DownloadPicturesService.this.cardsMissing.parallelStream().forEach(cardDownloadData -> {
|
DownloadPicturesService.this.cardsMissing.parallelStream().forEach(cardDownloadData -> {
|
||||||
TFile file = new TFile(CardImageUtils.buildImagePathToCard(cardDownloadData));
|
TFile file = new TFile(CardImageUtils.buildImagePathToCardOrToken(cardDownloadData));
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
downloadedCards.add(cardDownloadData);
|
downloadedCards.add(cardDownloadData);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,13 @@
|
||||||
package org.mage.plugins.card.images;
|
package org.mage.plugins.card.images;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
|
||||||
import com.google.common.collect.ComputationException;
|
import com.google.common.collect.ComputationException;
|
||||||
import mage.abilities.icon.CardIconColor;
|
import mage.abilities.icon.CardIconColor;
|
||||||
import mage.client.constants.Constants;
|
import mage.client.constants.Constants;
|
||||||
import mage.client.dialog.PreferencesDialog;
|
|
||||||
import mage.client.util.SoftValuesLoadingCache;
|
import mage.client.util.SoftValuesLoadingCache;
|
||||||
import mage.client.util.TransformedImageCache;
|
import mage.client.util.TransformedImageCache;
|
||||||
import mage.view.CardView;
|
import mage.view.CardView;
|
||||||
import net.java.truevfs.access.TFile;
|
import net.java.truevfs.access.TFile;
|
||||||
import net.java.truevfs.access.TFileInputStream;
|
import net.java.truevfs.access.TFileInputStream;
|
||||||
import net.java.truevfs.access.TFileOutputStream;
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
import org.mage.plugins.card.dl.sources.DirectLinksForDownload;
|
import org.mage.plugins.card.dl.sources.DirectLinksForDownload;
|
||||||
import org.mage.plugins.card.utils.CardImageUtils;
|
import org.mage.plugins.card.utils.CardImageUtils;
|
||||||
|
|
@ -20,7 +17,6 @@ import javax.imageio.ImageIO;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.geom.RoundRectangle2D;
|
import java.awt.geom.RoundRectangle2D;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
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,
|
* that the images may be garbage collected when they are not needed any more,
|
||||||
* but will be kept as long as possible.
|
* but will be kept as long as possible.
|
||||||
* <p>
|
* <p>
|
||||||
* Key format: "[cardname]#[setname]#[type]#[collectorID]#[param]"
|
* Key format: "[cardname]#[setname]#[type]#[collectorID]#[image size]#[additional data]"
|
||||||
* <p>
|
|
||||||
* where param is:
|
|
||||||
* <ul>
|
|
||||||
* <li>size of image</li>
|
|
||||||
*
|
*
|
||||||
* <li>#Normal: request for unrotated image</li>
|
* <li>#Normal: request for unrotated image</li>
|
||||||
* <li>#Tapped: request for rotated image</li>
|
* <li>#Tapped: request for rotated image</li>
|
||||||
* <li>#Cropped: request for cropped image that is used for Shandalar like card
|
* <li>#Cropped: request for cropped image that is used for Shandalar like card
|
||||||
* look</li>
|
* look</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
|
*
|
||||||
|
* @author JayDi85
|
||||||
*/
|
*/
|
||||||
public final class ImageCache {
|
public final class ImageCache {
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(ImageCache.class);
|
private static final Logger LOGGER = Logger.getLogger(ImageCache.class);
|
||||||
|
|
||||||
private static final SoftValuesLoadingCache<String, BufferedImage> IMAGE_CACHE;
|
private static final SoftValuesLoadingCache<String, ImageCacheData> IMAGE_CACHE; // cards and tokens
|
||||||
private static final SoftValuesLoadingCache<String, BufferedImage> FACE_IMAGE_CACHE;
|
private static final SoftValuesLoadingCache<String, ImageCacheData> FACE_IMAGE_CACHE;
|
||||||
private static final SoftValuesLoadingCache<String, BufferedImage> CARD_ICONS_CACHE;
|
private static final SoftValuesLoadingCache<String, ImageCacheData> CARD_ICONS_CACHE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common pattern for keys. See ImageCache.getKey for structure info
|
* 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("(.*)#(.*)#(.*)");
|
private static final Pattern CARD_ICON_KEY_PATTERN = Pattern.compile("(.*)#(.*)#(.*)");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// softValues() = Specifies that each value (not key) stored in the map should be wrapped in a SoftReference
|
// 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
|
// (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.
|
// globally least-recently-used manner, in response to memory demand.
|
||||||
IMAGE_CACHE = SoftValuesLoadingCache.from(new Function<String, BufferedImage>() {
|
IMAGE_CACHE = SoftValuesLoadingCache.from(key -> {
|
||||||
@Override
|
try {
|
||||||
public BufferedImage apply(String key) {
|
boolean usesVariousArt = false;
|
||||||
try {
|
if (key.matches(".*#usesVariousArt.*")) {
|
||||||
boolean usesVariousArt = false;
|
usesVariousArt = true;
|
||||||
if (key.matches(".*#usesVariousArt.*")) {
|
key = key.replace("#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()) {
|
CardDownloadData info = new CardDownloadData(name, setCode, collectorId, usesVariousArt, type);
|
||||||
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);
|
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;
|
// try normal token
|
||||||
String path;
|
path = CardImageUtils.buildImagePathToCardOrToken(info);
|
||||||
if (collectorId.isEmpty() || "0".equals(collectorId) || !tokenDescriptor.isEmpty()) { // tokenDescriptor for embalm ability
|
tokenFile = getTFile(path);
|
||||||
info.setToken(true);
|
|
||||||
path = CardImageUtils.generateTokenImagePath(info);
|
// try token from card
|
||||||
if (path == null) {
|
if (tokenFile == null || !tokenFile.exists()) {
|
||||||
cardback = true;
|
CardDownloadData tempInfo = new CardDownloadData(info);
|
||||||
// try token image from card
|
tempInfo.setToken(false);
|
||||||
CardDownloadData newInfo = new CardDownloadData(info);
|
path = CardImageUtils.buildImagePathToCardOrToken(info);
|
||||||
newInfo.setToken(false);
|
tokenFile = getTFile(path);
|
||||||
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 (path == null) {
|
// try unknown token image
|
||||||
return null;
|
if (tokenFile == null || !tokenFile.exists()) {
|
||||||
}
|
// TODO: replace empty token by other default card, not cardback
|
||||||
TFile file = getTFile(path);
|
cardback = true;
|
||||||
if (file == null) {
|
path = CardImageUtils.buildImagePathToDefault(DirectLinksForDownload.cardbackFilename);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException(
|
// CARD
|
||||||
"Requested image doesn't fit the requirement for key (<cardname>#<setname>#<collectorID>): " + key);
|
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) {
|
TFile file = getTFile(path);
|
||||||
BufferedImage image = loadImage(file);
|
if (file == null) {
|
||||||
image = getWizardsCard(image);
|
return new ImageCacheData(path, null);
|
||||||
image = getRoundCorner(image);
|
}
|
||||||
if (image == null) {
|
|
||||||
return 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()) {
|
if (m.matches()) {
|
||||||
String name = m.group(1);
|
String name = m.group(1);
|
||||||
String set = m.group(2);
|
String setCode = m.group(2);
|
||||||
//Integer artid = Integer.parseInt(m.group(2));
|
// skip type
|
||||||
|
// skip collectorId
|
||||||
|
|
||||||
String path;
|
String path = CardImageUtils.generateFaceImagePath(name, setCode);
|
||||||
path = CardImageUtils.generateFaceImagePath(name, set);
|
|
||||||
|
|
||||||
if (path == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
TFile file = getTFile(path);
|
TFile file = getTFile(path);
|
||||||
if (file == null) {
|
if (file == null) {
|
||||||
return null;
|
return new ImageCacheData(path, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferedImage image = loadImage(file);
|
BufferedImage image = loadImage(file);
|
||||||
return image;
|
return new ImageCacheData(path, image);
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException(
|
throw new RuntimeException(
|
||||||
"Requested face image doesn't fit the requirement for key (<cardname>#<artid>#: " + key);
|
"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);
|
String resourceName = m.group(2);
|
||||||
CardIconColor cardIconColor = CardIconColor.valueOf(m.group(3));
|
CardIconColor cardIconColor = CardIconColor.valueOf(m.group(3));
|
||||||
BufferedImage image = ImageManagerImpl.instance.getCardIcon(resourceName, cardSize, cardIconColor);
|
BufferedImage image = ImageManagerImpl.instance.getCardIcon(resourceName, cardSize, cardIconColor);
|
||||||
return image;
|
return new ImageCacheData(resourceName, image);
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("Wrong card icons image key format: " + key);
|
throw new RuntimeException("Wrong card icons image key format: " + key);
|
||||||
}
|
}
|
||||||
|
|
@ -255,109 +195,38 @@ public final class ImageCache {
|
||||||
CARD_ICONS_CACHE.invalidateAll();
|
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() {
|
private ImageCache() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BufferedImage getCardbackImage() {
|
public static ImageCacheData getCardbackImage() {
|
||||||
BufferedImage image = ImageCache.loadImage(new TFile(CardImageUtils.buildImagePathToDefault(DirectLinksForDownload.cardbackFilename)));
|
String path = CardImageUtils.buildImagePathToDefault(DirectLinksForDownload.cardbackFilename);
|
||||||
|
BufferedImage image = ImageCache.loadImage(getTFile(path));
|
||||||
image = getRoundCorner(image);
|
image = getRoundCorner(image);
|
||||||
return image;
|
return new ImageCacheData(path, image);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BufferedImage getMorphImage() {
|
public static ImageCacheData getMorphImage() {
|
||||||
// TODO: replace by morth image
|
// TODO: replace by downloadable morth image
|
||||||
CardDownloadData info = new CardDownloadData("Morph", "KTK", "0", false, 0, "KTK", "");
|
CardDownloadData info = new CardDownloadData("Morph", "KTK", "0", false, 0);
|
||||||
info.setToken(true);
|
info.setToken(true);
|
||||||
String path = CardImageUtils.generateTokenImagePath(info);
|
String path = CardImageUtils.buildImagePathToCardOrToken(info);
|
||||||
if (path == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
TFile file = getTFile(path);
|
|
||||||
|
|
||||||
|
TFile file = getTFile(path);
|
||||||
BufferedImage image = loadImage(file);
|
BufferedImage image = loadImage(file);
|
||||||
image = getRoundCorner(image);
|
image = getRoundCorner(image);
|
||||||
return image;
|
return new ImageCacheData(path, image);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BufferedImage getManifestImage() {
|
public static ImageCacheData getManifestImage() {
|
||||||
// TODO: replace by manifestest image
|
// TODO: replace by downloadable manifestest image
|
||||||
CardDownloadData info = new CardDownloadData("Manifest", "FRF", "0", false, 0, "FRF", "");
|
CardDownloadData info = new CardDownloadData("Manifest", "FRF", "0", false, 0);
|
||||||
info.setToken(true);
|
info.setToken(true);
|
||||||
String path = CardImageUtils.generateTokenImagePath(info);
|
String path = CardImageUtils.buildImagePathToCardOrToken(info);
|
||||||
if (path == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
TFile file = getTFile(path);
|
|
||||||
|
|
||||||
|
TFile file = getTFile(path);
|
||||||
BufferedImage image = loadImage(file);
|
BufferedImage image = loadImage(file);
|
||||||
image = getRoundCorner(image);
|
image = getRoundCorner(image);
|
||||||
return image;
|
return new ImageCacheData(path, 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BufferedImage getRoundCorner(BufferedImage image) {
|
public static BufferedImage getRoundCorner(BufferedImage image) {
|
||||||
|
|
@ -387,6 +256,7 @@ public final class ImageCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BufferedImage getWizardsCard(BufferedImage image) {
|
public static BufferedImage getWizardsCard(BufferedImage image) {
|
||||||
|
// TODO: can be removed?
|
||||||
if (image != null && image.getWidth() == 265 && image.getHeight() == 370) {
|
if (image != null && image.getWidth() == 265 && image.getHeight() == 370) {
|
||||||
BufferedImage crop = new BufferedImage(256, 360, BufferedImage.TYPE_INT_RGB);
|
BufferedImage crop = new BufferedImage(256, 360, BufferedImage.TYPE_INT_RGB);
|
||||||
Graphics2D graphics2D = crop.createGraphics();
|
Graphics2D graphics2D = crop.createGraphics();
|
||||||
|
|
@ -398,80 +268,61 @@ public final class ImageCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isFaceImagePresent(CardView card) {
|
public static ImageCacheData getImageOriginal(CardView card) {
|
||||||
String path;
|
return getImage(getKey(card, card.getName(), 0));
|
||||||
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 BufferedImage getThumbnail(CardView card) {
|
public static ImageCacheData getImageOriginalAlternateName(CardView card) {
|
||||||
return getImage(getKey(card, card.getName(), "#thumb"));
|
return getImage(getKey(card, card.getAlternateName(), 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BufferedImage tryGetThumbnail(CardView card) {
|
public static ImageCacheData getCardIconImage(String resourceName, int iconSize, String cardColorName) {
|
||||||
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) {
|
|
||||||
return getCardIconImage(getCardIconKey(resourceName, iconSize, cardColorName));
|
return getCardIconImage(getCardIconKey(resourceName, iconSize, cardColorName));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Image corresponding to the key
|
* Returns the Image corresponding to the key
|
||||||
*/
|
*/
|
||||||
private static BufferedImage getImage(String key) {
|
private static ImageCacheData getImage(String key) {
|
||||||
try {
|
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) {
|
} catch (ComputationException ex) {
|
||||||
// too low memory
|
// too low memory
|
||||||
if (ex.getCause() instanceof NullPointerException) {
|
if (ex.getCause() instanceof NullPointerException) {
|
||||||
return null;
|
return new ImageCacheData("ERROR: low memory?", null);
|
||||||
}
|
}
|
||||||
LOGGER.error(ex, ex);
|
LOGGER.error(ex, ex);
|
||||||
return null;
|
return new ImageCacheData("ERROR: see logs", null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Image corresponding to the key
|
* Returns the Image corresponding to the key
|
||||||
*/
|
*/
|
||||||
private static BufferedImage getFaceImage(String key) {
|
private static ImageCacheData getFaceImage(String key) {
|
||||||
try {
|
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) {
|
} catch (ComputationException ex) {
|
||||||
if (ex.getCause() instanceof NullPointerException) {
|
if (ex.getCause() instanceof NullPointerException) {
|
||||||
return null;
|
return new ImageCacheData("ERROR: low memory?", null);
|
||||||
}
|
}
|
||||||
LOGGER.error(ex, ex);
|
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 {
|
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) {
|
} catch (ComputationException ex) {
|
||||||
if (ex.getCause() instanceof NullPointerException) {
|
if (ex.getCause() instanceof NullPointerException) {
|
||||||
return null;
|
return new ImageCacheData("ERROR: low memory?", null);
|
||||||
}
|
}
|
||||||
LOGGER.error(ex, ex);
|
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
|
* Returns the Image corresponding to the key only if it already exists in
|
||||||
* the cache.
|
* the cache.
|
||||||
*/
|
*/
|
||||||
private static BufferedImage tryGetImage(String key) {
|
private static ImageCacheData tryGetImage(String key) {
|
||||||
return IMAGE_CACHE.peekIfPresent(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) {
|
private static String getKey(CardView card, String cardName, int imageSize) {
|
||||||
return (card.isToken() ? name.replace(" Token", "") : name)
|
return (card.isToken() ? cardName.replace(" Token", "") : cardName)
|
||||||
+ '#' + card.getExpansionSetCode()
|
+ '#' + card.getExpansionSetCode()
|
||||||
+ '#' + card.getType()
|
+ '#' + card.getType()
|
||||||
+ '#' + card.getCardNumber()
|
+ '#' + card.getCardNumber()
|
||||||
+ '#' + (card.getTokenSetCode() == null ? "" : card.getTokenSetCode())
|
+ '#' + imageSize
|
||||||
+ suffix
|
+ (card.getUsesVariousArt() ? "#usesVariousArt" : "");
|
||||||
+ (card.getUsesVariousArt() ? "#usesVariousArt" : "")
|
|
||||||
+ '#' + (card.getTokenDescriptor() != null ? card.getTokenDescriptor() : "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -534,24 +387,6 @@ public final class ImageCache {
|
||||||
return image;
|
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
|
* Returns an image scaled to the size given
|
||||||
*
|
*
|
||||||
|
|
@ -584,23 +419,22 @@ public final class ImageCache {
|
||||||
* @param height
|
* @param height
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static BufferedImage getImage(CardView card, int width, int height) {
|
public static ImageCacheData getImage(CardView card, int width, int height) {
|
||||||
if (Constants.THUMBNAIL_SIZE_FULL.width + 10 > width) {
|
String key = getKey(card, card.getName(), width);
|
||||||
return getThumbnail(card);
|
ImageCacheData data = getImage(key);
|
||||||
}
|
if (data.getImage() == null) {
|
||||||
String key = getKey(card, card.getName(), Integer.toString(width));
|
LOGGER.debug("Image doesn't exists in the cache: " + key);
|
||||||
BufferedImage original = getImage(key);
|
return data;
|
||||||
if (original == null) {
|
|
||||||
LOGGER.debug(key + " not found");
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
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
|
* @param height
|
||||||
* @return
|
* @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());
|
String key = getFaceKey(card, card.getName(), card.getExpansionSetCode());
|
||||||
BufferedImage original = getFaceImage(key);
|
ImageCacheData data = getFaceImage(key);
|
||||||
if (original == null) {
|
if (data.getImage() == null) {
|
||||||
LOGGER.debug(key + " (faceimage) not found");
|
LOGGER.debug(key + " (faceimage) not found");
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
return data;
|
||||||
return original;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -632,29 +464,31 @@ public final class ImageCache {
|
||||||
* @param height
|
* @param height
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static BufferedImage tryGetImage(CardView card, int width, int height) {
|
public static ImageCacheData tryGetImage(CardView card, int width, int height) {
|
||||||
if (Constants.THUMBNAIL_SIZE_FULL.width + 10 > width) {
|
String key = getKey(card, card.getName(), width);
|
||||||
return tryGetThumbnail(card);
|
ImageCacheData data = tryGetImage(key);
|
||||||
}
|
if (data.getImage() == null) {
|
||||||
String key = getKey(card, card.getName(), Integer.toString(width));
|
|
||||||
BufferedImage original = tryGetImage(key);
|
|
||||||
if (original == null) {
|
|
||||||
LOGGER.debug(key + " not found");
|
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) {
|
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) {
|
public static TFile getTFile(String path) {
|
||||||
try {
|
try {
|
||||||
return new TFile(path);
|
if (path != null) {
|
||||||
|
return new TFile(path);
|
||||||
|
}
|
||||||
} catch (NullPointerException ex) {
|
} catch (NullPointerException ex) {
|
||||||
|
// TODO: raise error on path == null -- is it actual?!
|
||||||
LOGGER.warn("Imagefile does not exist: " + path);
|
LOGGER.warn("Imagefile does not exist: " + path);
|
||||||
}
|
}
|
||||||
return null;
|
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.client.dialog.PreferencesDialog;
|
||||||
import mage.remote.Connection;
|
import mage.remote.Connection;
|
||||||
import mage.remote.Connection.ProxyType;
|
import mage.remote.Connection.ProxyType;
|
||||||
import net.java.truevfs.access.TFile;
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
import org.jsoup.Jsoup;
|
import org.jsoup.Jsoup;
|
||||||
import org.jsoup.nodes.Document;
|
import org.jsoup.nodes.Document;
|
||||||
|
|
@ -26,87 +25,13 @@ import java.nio.file.SimpleFileVisitor;
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.prefs.Preferences;
|
import java.util.prefs.Preferences;
|
||||||
|
|
||||||
public final class CardImageUtils {
|
public final class CardImageUtils {
|
||||||
|
|
||||||
private static final HashMap<CardDownloadData, String> pathCache = new HashMap<>();
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(CardImageUtils.class);
|
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) {
|
public static String prepareCardNameForFile(String cardName) {
|
||||||
return cardName
|
return cardName
|
||||||
.replace(":", "")
|
.replace(":", "")
|
||||||
|
|
@ -141,12 +66,12 @@ public final class CardImageUtils {
|
||||||
return getImagesDir() + Constants.RESOURCE_PATH_DEFAULT_IMAGES + File.separator + defaultFileName;
|
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
|
// windows can't create con folders
|
||||||
if (set.equals("CON") || set.equals("con")) {
|
if (setCode.equals("CON") || setCode.equals("con")) {
|
||||||
return "COX";
|
return "COX";
|
||||||
} else {
|
} 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) {
|
public static String buildImagePathToSet(CardDownloadData card) {
|
||||||
|
|
||||||
if (card.getSet() == null) {
|
if (card.getSet() == null) {
|
||||||
throw new IllegalArgumentException("Card " + card.getName() + " have empty set.");
|
throw new IllegalArgumentException("Card " + card.getName() + " have empty set.");
|
||||||
}
|
}
|
||||||
|
String setCode = card.getSet().toUpperCase(Locale.ENGLISH);
|
||||||
String set = card.getSet().toUpperCase(Locale.ENGLISH);
|
|
||||||
|
|
||||||
if (card.isToken()) {
|
if (card.isToken()) {
|
||||||
return buildImagePathToSetAsToken(set);
|
return buildImagePathToSetAsToken(setCode);
|
||||||
} else {
|
} else {
|
||||||
return buildImagePathToSetAsCard(set);
|
return buildImagePathToSetAsCard(setCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String buildImagePathToSetAsCard(String set) {
|
private static String buildImagePathToSetAsCard(String setCode) {
|
||||||
String imagesPath = getImagesDir() + File.separator;
|
String imagesPath = getImagesDir() + File.separator;
|
||||||
|
|
||||||
if (PreferencesDialog.isSaveImagesToZip()) {
|
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 {
|
} else {
|
||||||
return imagesPath + fixSetNameForWindows(set) + File.separator;
|
return imagesPath + fixSetNameForWindows(setCode) + File.separator;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String buildImagePathToSetAsToken(String set) {
|
private static String buildImagePathToSetAsToken(String setCode) {
|
||||||
return buildImagePathToTokens() + fixSetNameForWindows(set) + File.separator;
|
return buildImagePathToTokens() + fixSetNameForWindows(setCode) + File.separator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String buildImagePathToCard(CardDownloadData card) {
|
public static String buildImagePathToCardOrToken(CardDownloadData card) {
|
||||||
|
|
||||||
String setPath = buildImagePathToSet(card);
|
String setPath = buildImagePathToSet(card);
|
||||||
|
|
||||||
|
|
@ -207,7 +126,7 @@ public final class CardImageUtils {
|
||||||
cardName = prepareCardNameForFile(card.getName());
|
cardName = prepareCardNameForFile(card.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
String finalFileName = "";
|
String finalFileName;
|
||||||
if (card.getUsesVariousArt()) {
|
if (card.getUsesVariousArt()) {
|
||||||
// different arts uses name + collector id
|
// different arts uses name + collector id
|
||||||
finalFileName = cardName + prefixType + '.' + card.getCollectorIdAsFileName() + ".full.jpg";
|
finalFileName = cardName + prefixType + '.' + card.getCollectorIdAsFileName() + ".full.jpg";
|
||||||
|
|
@ -216,54 +135,11 @@ public final class CardImageUtils {
|
||||||
finalFileName = cardName + prefixType + ".full.jpg";
|
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;
|
return setPath + finalFileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String generateFaceImagePath(String cardname, String set) {
|
public static String generateFaceImagePath(String cardName, String setCode) {
|
||||||
return getImagesDir() + File.separator + "FACE" + File.separator + fixSetNameForWindows(set) + File.separator + prepareCardNameForFile(cardname) + ".jpg";
|
return getImagesDir() + File.separator + "FACE" + File.separator + fixSetNameForWindows(setCode) + 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 Proxy getProxyFromPreferences() {
|
public static Proxy getProxyFromPreferences() {
|
||||||
|
|
@ -305,8 +181,7 @@ public final class CardImageUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void checkAndFixImageFiles() {
|
public static void checkAndFixImageFiles() {
|
||||||
// search broken files and delete it (zero size files)
|
// search broken, temp or outdated files and delete it
|
||||||
// search temp files and delete it (.tmp files from zip library)
|
|
||||||
Path rootPath = new File(CardImageUtils.getImagesDir()).toPath();
|
Path rootPath = new File(CardImageUtils.getImagesDir()).toPath();
|
||||||
if (!Files.exists(rootPath)) {
|
if (!Files.exists(rootPath)) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -314,6 +189,7 @@ public final class CardImageUtils {
|
||||||
|
|
||||||
Collection<Path> brokenFilesList = new ArrayList<>();
|
Collection<Path> brokenFilesList = new ArrayList<>();
|
||||||
Collection<Path> tempFilesList = new ArrayList<>();
|
Collection<Path> tempFilesList = new ArrayList<>();
|
||||||
|
Collection<Path> outdatedFilesList = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() {
|
Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() {
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -329,6 +205,11 @@ public final class CardImageUtils {
|
||||||
tempFilesList.add(file);
|
tempFilesList.add(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 3. outdated files delete without warning
|
||||||
|
if (file.toString().endsWith(".thumb.zip")) {
|
||||||
|
outdatedFilesList.add(file);
|
||||||
|
}
|
||||||
|
|
||||||
return FileVisitResult.CONTINUE;
|
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);
|
LOGGER.error("Can't load files list from images folder: " + rootPath.toAbsolutePath().toString(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// temp files must be deleted without errors
|
// temp and outdated files must be deleted without errors
|
||||||
for (Path tempFile : tempFilesList) {
|
Collection<Path> list = new ArrayList<>();
|
||||||
|
list.addAll(tempFilesList);
|
||||||
|
list.addAll(outdatedFilesList);
|
||||||
|
for (Path path : list) {
|
||||||
try {
|
try {
|
||||||
Files.delete(tempFile);
|
Files.delete(path);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
// ignore any error (e.g. it opened by xmage app)
|
// ignore any error (e.g. it opened by xmage app)
|
||||||
}
|
}
|
||||||
|
|
@ -353,7 +237,7 @@ public final class CardImageUtils {
|
||||||
Files.delete(brokenFile);
|
Files.delete(brokenFile);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
// stop clean on any error
|
// 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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,16 +18,16 @@ public class TokensMtgImageSourceTest {
|
||||||
public void generateTokenUrlTest() throws Exception {
|
public void generateTokenUrlTest() throws Exception {
|
||||||
CardImageSource imageSource = TokensMtgImageSource.instance;
|
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);
|
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);
|
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);
|
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);
|
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.
|
* @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) {
|
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;
|
this.originalCard = card;
|
||||||
|
|
||||||
// no information available for face down cards as long it's not a controlled face down morph 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 {
|
} else {
|
||||||
// a created token
|
// a created token
|
||||||
this.expansionSetCode = card.getExpansionSetCode();
|
this.expansionSetCode = card.getExpansionSetCode();
|
||||||
this.tokenDescriptor = card.getTokenDescriptor();
|
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// set code and card number for token copies to get the image
|
// 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) {
|
public CardView(MageObject object, Game game) {
|
||||||
super(object.getId(), "", "0", false, "", true, "");
|
super(object.getId(), "", "0", false, true);
|
||||||
this.originalCard = null;
|
this.originalCard = null;
|
||||||
|
|
||||||
this.name = object.getName();
|
this.name = object.getName();
|
||||||
|
|
@ -674,7 +673,7 @@ public class CardView extends SimpleCardView {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected CardView() {
|
protected CardView() {
|
||||||
super(null, "", "0", false, "", true, "");
|
super(null, "", "0", false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CardView(EmblemView emblem) {
|
public CardView(EmblemView emblem) {
|
||||||
|
|
@ -739,7 +738,7 @@ public class CardView extends SimpleCardView {
|
||||||
}
|
}
|
||||||
|
|
||||||
public CardView(boolean empty) {
|
public CardView(boolean empty) {
|
||||||
super(null, "", "0", false, "", "");
|
super(null, "", "0", false);
|
||||||
if (!empty) {
|
if (!empty) {
|
||||||
throw new IllegalArgumentException("Not supported.");
|
throw new IllegalArgumentException("Not supported.");
|
||||||
}
|
}
|
||||||
|
|
@ -793,9 +792,10 @@ public class CardView extends SimpleCardView {
|
||||||
}
|
}
|
||||||
|
|
||||||
CardView(Token token, Game game) {
|
CardView(Token token, Game game) {
|
||||||
super(token.getId(), "", "0", false, "", "");
|
super(token.getId(), "", "0", false);
|
||||||
this.isToken = true;
|
this.isToken = true;
|
||||||
this.id = token.getId();
|
this.id = token.getId();
|
||||||
|
this.expansionSetCode = token.getOriginalExpansionSetCode();
|
||||||
this.name = token.getName();
|
this.name = token.getName();
|
||||||
this.displayName = token.getName();
|
this.displayName = token.getName();
|
||||||
this.displayFullName = token.getName();
|
this.displayFullName = token.getName();
|
||||||
|
|
@ -814,8 +814,6 @@ public class CardView extends SimpleCardView {
|
||||||
this.manaCostRightStr = "";
|
this.manaCostRightStr = "";
|
||||||
this.rarity = Rarity.SPECIAL;
|
this.rarity = Rarity.SPECIAL;
|
||||||
this.type = token.getTokenType();
|
this.type = token.getTokenType();
|
||||||
this.tokenDescriptor = token.getTokenDescriptor();
|
|
||||||
this.tokenSetCode = token.getOriginalExpansionSetCode();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final void addTargets(Targets targets, Effects effects, Ability source, Game game) {
|
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) {
|
public LookedAtView(String name, Cards cards, Game game) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
for (Card card: cards.getCards(game)) {
|
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()) {
|
if (isToken()) {
|
||||||
original = new CardView(((PermanentToken) permanent).getToken().copy(), (Game) null);
|
original = new CardView(((PermanentToken) permanent).getToken().copy(), (Game) null);
|
||||||
original.expansionSetCode = permanent.getExpansionSetCode();
|
original.expansionSetCode = permanent.getExpansionSetCode();
|
||||||
tokenSetCode = original.getTokenSetCode();
|
expansionSetCode = permanent.getExpansionSetCode();
|
||||||
tokenDescriptor = original.getTokenDescriptor();
|
|
||||||
} else {
|
} else {
|
||||||
if (card != null) {
|
if (card != null) {
|
||||||
// original may not be face down
|
// original may not be face down
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,6 @@ public class SimpleCardView implements Serializable, SelectableObjectView {
|
||||||
@Expose
|
@Expose
|
||||||
protected UUID id;
|
protected UUID id;
|
||||||
protected String expansionSetCode;
|
protected String expansionSetCode;
|
||||||
protected String tokenSetCode;
|
|
||||||
protected String tokenDescriptor;
|
|
||||||
protected String cardNumber;
|
protected String cardNumber;
|
||||||
protected boolean usesVariousArt;
|
protected boolean usesVariousArt;
|
||||||
protected boolean gameObject;
|
protected boolean gameObject;
|
||||||
|
|
@ -26,28 +24,23 @@ public class SimpleCardView implements Serializable, SelectableObjectView {
|
||||||
public SimpleCardView(final SimpleCardView view) {
|
public SimpleCardView(final SimpleCardView view) {
|
||||||
this.id = view.id;
|
this.id = view.id;
|
||||||
this.expansionSetCode = view.expansionSetCode;
|
this.expansionSetCode = view.expansionSetCode;
|
||||||
this.tokenSetCode = view.tokenSetCode;
|
|
||||||
this.tokenDescriptor = view.tokenDescriptor;
|
|
||||||
this.cardNumber = view.cardNumber;
|
this.cardNumber = view.cardNumber;
|
||||||
this.usesVariousArt = view.usesVariousArt;
|
this.usesVariousArt = view.usesVariousArt;
|
||||||
this.gameObject = view.gameObject;
|
this.gameObject = view.gameObject;
|
||||||
|
|
||||||
this.isChoosable = view.isChoosable;
|
this.isChoosable = view.isChoosable;
|
||||||
this.isSelected = view.isSelected;
|
this.isSelected = view.isSelected;
|
||||||
this.playableStats = view.playableStats.copy();
|
this.playableStats = view.playableStats.copy();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SimpleCardView(UUID id, String expansionSetCode, String cardNumber, boolean usesVariousArt, String tokenSetCode, String tokenDescriptor) {
|
public SimpleCardView(UUID id, String expansionSetCode, String cardNumber, boolean usesVariousArt) {
|
||||||
this(id, expansionSetCode, cardNumber, usesVariousArt, tokenSetCode, false, tokenDescriptor);
|
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.id = id;
|
||||||
this.expansionSetCode = expansionSetCode;
|
this.expansionSetCode = expansionSetCode;
|
||||||
this.tokenDescriptor = tokenDescriptor;
|
|
||||||
this.cardNumber = cardNumber;
|
this.cardNumber = cardNumber;
|
||||||
this.usesVariousArt = usesVariousArt;
|
this.usesVariousArt = usesVariousArt;
|
||||||
this.tokenSetCode = tokenSetCode;
|
|
||||||
this.gameObject = isGameObject;
|
this.gameObject = isGameObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -67,14 +60,6 @@ public class SimpleCardView implements Serializable, SelectableObjectView {
|
||||||
return usesVariousArt;
|
return usesVariousArt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTokenSetCode() {
|
|
||||||
return tokenSetCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTokenDescriptor() {
|
|
||||||
return tokenDescriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isGameObject() {
|
public boolean isGameObject() {
|
||||||
return gameObject;
|
return gameObject;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,7 @@ public class SimpleCardsView extends LinkedHashMap<UUID, SimpleCardView> {
|
||||||
|
|
||||||
public SimpleCardsView(Collection<Card> cards, boolean isGameObject) {
|
public SimpleCardsView(Collection<Card> cards, boolean isGameObject) {
|
||||||
for (Card card: cards) {
|
for (Card card: cards) {
|
||||||
this.put(card.getId(), new SimpleCardView(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt(), card.getTokenSetCode(), isGameObject,
|
this.put(card.getId(), new SimpleCardView(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt(), isGameObject));
|
||||||
card.getTokenDescriptor()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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());
|
Assert.fail("Can't add card " + cardName + " - alias " + aliasName + " already exists for " + player.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
// set code for
|
// set code for card
|
||||||
String setCode = "";
|
String setCode = "";
|
||||||
String setLookup = CardUtil.substring(cardName, CardUtil.TESTS_SET_CODE_LOOKUP_LENGTH);
|
String setLookup = CardUtil.substring(cardName, CardUtil.TESTS_SET_CODE_LOOKUP_LENGTH);
|
||||||
if (setLookup.contains(":")) {
|
if (setLookup.contains(":")) {
|
||||||
|
|
|
||||||
|
|
@ -49,11 +49,6 @@ public interface Card extends MageObject {
|
||||||
List<String> getRules(Game game); // gets card rules + in game modifications
|
List<String> getRules(Game game); // gets card rules + in game modifications
|
||||||
|
|
||||||
String getExpansionSetCode();
|
String getExpansionSetCode();
|
||||||
|
|
||||||
String getTokenSetCode();
|
|
||||||
|
|
||||||
String getTokenDescriptor();
|
|
||||||
|
|
||||||
void checkForCountersToAdd(Permanent permanent, Ability source, Game game);
|
void checkForCountersToAdd(Permanent permanent, Ability source, Game game);
|
||||||
|
|
||||||
void setFaceDown(boolean value, Game game);
|
void setFaceDown(boolean value, Game game);
|
||||||
|
|
|
||||||
|
|
@ -42,8 +42,6 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
||||||
protected UUID ownerId;
|
protected UUID ownerId;
|
||||||
protected String cardNumber;
|
protected String cardNumber;
|
||||||
protected String expansionSetCode;
|
protected String expansionSetCode;
|
||||||
protected String tokenSetCode;
|
|
||||||
protected String tokenDescriptor;
|
|
||||||
protected Rarity rarity;
|
protected Rarity rarity;
|
||||||
protected Class<? extends Card> secondSideCardClazz;
|
protected Class<? extends Card> secondSideCardClazz;
|
||||||
protected Class<? extends Card> meldsWithClazz;
|
protected Class<? extends Card> meldsWithClazz;
|
||||||
|
|
@ -121,8 +119,6 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
||||||
ownerId = card.ownerId;
|
ownerId = card.ownerId;
|
||||||
cardNumber = card.cardNumber;
|
cardNumber = card.cardNumber;
|
||||||
expansionSetCode = card.expansionSetCode;
|
expansionSetCode = card.expansionSetCode;
|
||||||
tokenSetCode = card.tokenSetCode;
|
|
||||||
tokenDescriptor = card.tokenDescriptor;
|
|
||||||
rarity = card.rarity;
|
rarity = card.rarity;
|
||||||
|
|
||||||
secondSideCardClazz = card.secondSideCardClazz;
|
secondSideCardClazz = card.secondSideCardClazz;
|
||||||
|
|
@ -378,16 +374,6 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
||||||
return expansionSetCode;
|
return expansionSetCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getTokenSetCode() {
|
|
||||||
return tokenSetCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getTokenDescriptor() {
|
|
||||||
return tokenDescriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Mana> getMana() {
|
public List<Mana> getMana() {
|
||||||
List<Mana> mana = new ArrayList<>();
|
List<Mana> mana = new ArrayList<>();
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,6 @@ public class PermanentToken extends PermanentImpl {
|
||||||
this.supertype.clear();
|
this.supertype.clear();
|
||||||
this.supertype.addAll(token.getSuperType());
|
this.supertype.addAll(token.getSuperType());
|
||||||
this.subtype.copyFrom(token.getSubtype(game));
|
this.subtype.copyFrom(token.getSubtype(game));
|
||||||
this.tokenDescriptor = token.getTokenDescriptor();
|
|
||||||
this.startingLoyalty = token.getStartingLoyalty();
|
this.startingLoyalty = token.getStartingLoyalty();
|
||||||
// workaround for entersTheBattlefield replacement effects
|
// workaround for entersTheBattlefield replacement effects
|
||||||
if (this.abilities.containsClass(ChangelingAbility.class)) {
|
if (this.abilities.containsClass(ChangelingAbility.class)) {
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,6 @@ public interface Token extends MageObject {
|
||||||
@Override
|
@Override
|
||||||
Token copy();
|
Token copy();
|
||||||
|
|
||||||
String getTokenDescriptor();
|
|
||||||
|
|
||||||
String getDescription();
|
String getDescription();
|
||||||
|
|
||||||
List<UUID> getLastAddedTokenIds();
|
List<UUID> getLastAddedTokenIds();
|
||||||
|
|
|
||||||
|
|
@ -85,12 +85,6 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
|
||||||
this.tokenDescriptor = tokenDescriptor();
|
this.tokenDescriptor = tokenDescriptor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getTokenDescriptor() {
|
|
||||||
this.tokenDescriptor = tokenDescriptor();
|
|
||||||
return tokenDescriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String tokenDescriptor() {
|
private String tokenDescriptor() {
|
||||||
String strName = this.name.replaceAll("[^a-zA-Z0-9]", "");
|
String strName = this.name.replaceAll("[^a-zA-Z0-9]", "");
|
||||||
String strColor = this.color.toString().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();
|
return card.getExpansionSetCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getTokenSetCode() {
|
|
||||||
return card.getTokenSetCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getTokenDescriptor() {
|
|
||||||
return card.getTokenDescriptor();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setFaceDown(boolean value, Game game) {
|
public void setFaceDown(boolean value, Game game) {
|
||||||
faceDown = value;
|
faceDown = value;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue