mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 10:48:00 +00:00
Store cards by collectorNumber instead of artIndex; PaperCard flag support (#7240)
* Refactor - Unknown set code to constant * Refactor - Support for multiple initial selections for getChoices * Covert noSell and marked color identities into serializable flags * Fix cards in deck not being converted to newer noSell format * unused imports * Fix NPE * Cleanup card filter * Remove 14-year-old check that shouldn't be possible anymore * CRLF -> LF --------- Co-authored-by: Jetz <Jetz722@gmail.com>
This commit is contained in:
@@ -158,7 +158,7 @@ public class ComputerUtilMana {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Mana abilities on the same card
|
// Mana abilities on the same card
|
||||||
String shardMana = shard.toString().replaceAll("\\{", "").replaceAll("\\}", "");
|
String shardMana = shard.toShortString();
|
||||||
|
|
||||||
boolean payWithAb1 = ability1.getManaPart().mana(ability1).contains(shardMana);
|
boolean payWithAb1 = ability1.getManaPart().mana(ability1).contains(shardMana);
|
||||||
boolean payWithAb2 = ability2.getManaPart().mana(ability2).contains(shardMana);
|
boolean payWithAb2 = ability2.getManaPart().mana(ability2).contains(shardMana);
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ import java.util.stream.Stream;
|
|||||||
public final class CardDb implements ICardDatabase, IDeckGenPool {
|
public final class CardDb implements ICardDatabase, IDeckGenPool {
|
||||||
public final static String foilSuffix = "+";
|
public final static String foilSuffix = "+";
|
||||||
public final static char NameSetSeparator = '|';
|
public final static char NameSetSeparator = '|';
|
||||||
public final static String colorIDPrefix = "#";
|
public final static String FlagPrefix = "#";
|
||||||
|
public static final String FlagSeparator = "\t";
|
||||||
private final String exlcudedCardName = "Concentrate";
|
private final String exlcudedCardName = "Concentrate";
|
||||||
private final String exlcudedCardSet = "DS0";
|
private final String exlcudedCardSet = "DS0";
|
||||||
|
|
||||||
@@ -93,19 +94,19 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
|
|||||||
public int artIndex;
|
public int artIndex;
|
||||||
public boolean isFoil;
|
public boolean isFoil;
|
||||||
public String collectorNumber;
|
public String collectorNumber;
|
||||||
public Set<String> colorID;
|
public Map<String, String> flags;
|
||||||
|
|
||||||
private CardRequest(String name, String edition, int artIndex, boolean isFoil, String collectorNumber) {
|
private CardRequest(String name, String edition, int artIndex, boolean isFoil, String collectorNumber) {
|
||||||
this(name, edition, artIndex, isFoil, collectorNumber, null);
|
this(name, edition, artIndex, isFoil, collectorNumber, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CardRequest(String name, String edition, int artIndex, boolean isFoil, String collectorNumber, Set<String> colorID) {
|
private CardRequest(String name, String edition, int artIndex, boolean isFoil, String collectorNumber, Map<String, String> flags) {
|
||||||
cardName = name;
|
cardName = name;
|
||||||
this.edition = edition;
|
this.edition = edition;
|
||||||
this.artIndex = artIndex;
|
this.artIndex = artIndex;
|
||||||
this.isFoil = isFoil;
|
this.isFoil = isFoil;
|
||||||
this.collectorNumber = collectorNumber;
|
this.collectorNumber = collectorNumber;
|
||||||
this.colorID = colorID;
|
this.flags = flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isFoilCardName(final String cardName){
|
public static boolean isFoilCardName(final String cardName){
|
||||||
@@ -120,7 +121,8 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String compose(String cardName, String setCode) {
|
public static String compose(String cardName, String setCode) {
|
||||||
setCode = setCode != null ? setCode : "";
|
if(setCode == null || StringUtils.isBlank(setCode) || setCode.equals(CardEdition.UNKNOWN_CODE))
|
||||||
|
setCode = "";
|
||||||
cardName = cardName != null ? cardName : "";
|
cardName = cardName != null ? cardName : "";
|
||||||
if (cardName.indexOf(NameSetSeparator) != -1)
|
if (cardName.indexOf(NameSetSeparator) != -1)
|
||||||
// If cardName is another RequestString, just get card name and forget about the rest.
|
// If cardName is another RequestString, just get card name and forget about the rest.
|
||||||
@@ -134,14 +136,6 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
|
|||||||
return requestInfo + NameSetSeparator + artIndex;
|
return requestInfo + NameSetSeparator + artIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String compose(String cardName, String setCode, int artIndex, Set<String> colorID) {
|
|
||||||
String requestInfo = compose(cardName, setCode);
|
|
||||||
artIndex = Math.max(artIndex, IPaperCard.DEFAULT_ART_INDEX);
|
|
||||||
String cid = colorID == null ? "" : NameSetSeparator +
|
|
||||||
colorID.toString().replace("[", colorIDPrefix).replace(", ", colorIDPrefix).replace("]", "");
|
|
||||||
return requestInfo + NameSetSeparator + artIndex + cid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String compose(String cardName, String setCode, String collectorNumber) {
|
public static String compose(String cardName, String setCode, String collectorNumber) {
|
||||||
String requestInfo = compose(cardName, setCode);
|
String requestInfo = compose(cardName, setCode);
|
||||||
// CollectorNumber will be wrapped in square brackets
|
// CollectorNumber will be wrapped in square brackets
|
||||||
@@ -149,6 +143,34 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
|
|||||||
return requestInfo + NameSetSeparator + collectorNumber;
|
return requestInfo + NameSetSeparator + collectorNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String compose(String cardName, String setCode, int artIndex, Map<String, String> flags) {
|
||||||
|
String requestInfo = compose(cardName, setCode);
|
||||||
|
artIndex = Math.max(artIndex, IPaperCard.DEFAULT_ART_INDEX);
|
||||||
|
if(flags == null)
|
||||||
|
return requestInfo + NameSetSeparator + artIndex;
|
||||||
|
return requestInfo + NameSetSeparator + artIndex + getFlagSegment(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String compose(String cardName, String setCode, String collectorNumber, Map<String, String> flags) {
|
||||||
|
String requestInfo = compose(cardName, setCode);
|
||||||
|
collectorNumber = preprocessCollectorNumber(collectorNumber);
|
||||||
|
if(flags == null || flags.isEmpty())
|
||||||
|
return requestInfo + NameSetSeparator + collectorNumber;
|
||||||
|
return requestInfo + NameSetSeparator + collectorNumber + getFlagSegment(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String compose(PaperCard card) {
|
||||||
|
String name = compose(card.getName(), card.isFoil());
|
||||||
|
return compose(name, card.getEdition(), card.getCollectorNumber(), card.getMarkedFlags().toMap());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String compose(String cardName, String setCode, int artIndex, String collectorNumber) {
|
||||||
|
String requestInfo = compose(cardName, setCode, artIndex);
|
||||||
|
// CollectorNumber will be wrapped in square brackets
|
||||||
|
collectorNumber = preprocessCollectorNumber(collectorNumber);
|
||||||
|
return requestInfo + NameSetSeparator + collectorNumber;
|
||||||
|
}
|
||||||
|
|
||||||
private static String preprocessCollectorNumber(String collectorNumber) {
|
private static String preprocessCollectorNumber(String collectorNumber) {
|
||||||
if (collectorNumber == null)
|
if (collectorNumber == null)
|
||||||
return "";
|
return "";
|
||||||
@@ -160,19 +182,21 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
|
|||||||
return collectorNumber;
|
return collectorNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String compose(String cardName, String setCode, int artIndex, String collectorNumber) {
|
private static String getFlagSegment(Map<String, String> flags) {
|
||||||
String requestInfo = compose(cardName, setCode, artIndex);
|
if(flags == null)
|
||||||
// CollectorNumber will be wrapped in square brackets
|
return "";
|
||||||
collectorNumber = preprocessCollectorNumber(collectorNumber);
|
String flagText = flags.entrySet().stream()
|
||||||
return requestInfo + NameSetSeparator + collectorNumber;
|
.map(e -> e.getKey() + "=" + e.getValue())
|
||||||
|
.collect(Collectors.joining(FlagSeparator));
|
||||||
|
return NameSetSeparator + FlagPrefix + "{" + flagText + "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isCollectorNumber(String s) {
|
private static boolean isCollectorNumber(String s) {
|
||||||
return s.startsWith("[") && s.endsWith("]");
|
return s.startsWith("[") && s.endsWith("]");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isColorIDString(String s) {
|
private static boolean isFlagSegment(String s) {
|
||||||
return s.startsWith(colorIDPrefix);
|
return s.startsWith(FlagPrefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isArtIndex(String s) {
|
private static boolean isArtIndex(String s) {
|
||||||
@@ -201,44 +225,36 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
String[] info = TextUtil.split(reqInfo, NameSetSeparator);
|
String[] info = TextUtil.split(reqInfo, NameSetSeparator);
|
||||||
int setPos;
|
int index = 1;
|
||||||
int artPos;
|
|
||||||
int cNrPos;
|
|
||||||
int clrPos;
|
|
||||||
if (info.length >= 4) { // name|set|artIndex|[collNr]
|
|
||||||
setPos = isSetCode(info[1]) ? 1 : -1;
|
|
||||||
artPos = isArtIndex(info[2]) ? 2 : -1;
|
|
||||||
cNrPos = isCollectorNumber(info[3]) ? 3 : -1;
|
|
||||||
int pos = cNrPos > 0 ? -1 : 3;
|
|
||||||
clrPos = pos > 0 ? isColorIDString(info[pos]) ? pos : -1 : -1;
|
|
||||||
} else if (info.length == 3) { // name|set|artIndex (or CollNr)
|
|
||||||
setPos = isSetCode(info[1]) ? 1 : -1;
|
|
||||||
artPos = isArtIndex(info[2]) ? 2 : -1;
|
|
||||||
cNrPos = isCollectorNumber(info[2]) ? 2 : -1;
|
|
||||||
int pos = cNrPos > 0 ? -1 : 2;
|
|
||||||
clrPos = pos > 0 ? isColorIDString(info[pos]) ? pos : -1 : -1;
|
|
||||||
} else if (info.length == 2) { // name|set (or artIndex, even if not possible via compose)
|
|
||||||
setPos = isSetCode(info[1]) ? 1 : -1;
|
|
||||||
artPos = isArtIndex(info[1]) ? 1 : -1;
|
|
||||||
cNrPos = -1;
|
|
||||||
clrPos = -1;
|
|
||||||
} else {
|
|
||||||
setPos = -1;
|
|
||||||
artPos = -1;
|
|
||||||
cNrPos = -1;
|
|
||||||
clrPos = -1;
|
|
||||||
}
|
|
||||||
String cardName = info[0];
|
String cardName = info[0];
|
||||||
boolean isFoil = false;
|
boolean isFoil = false;
|
||||||
|
int artIndex = IPaperCard.NO_ART_INDEX;
|
||||||
|
String setCode = null;
|
||||||
|
String collectorNumber = IPaperCard.NO_COLLECTOR_NUMBER;
|
||||||
|
Map<String, String> flags = null;
|
||||||
if (isFoilCardName(cardName)) {
|
if (isFoilCardName(cardName)) {
|
||||||
cardName = cardName.substring(0, cardName.length() - foilSuffix.length());
|
cardName = cardName.substring(0, cardName.length() - foilSuffix.length());
|
||||||
isFoil = true;
|
isFoil = true;
|
||||||
}
|
}
|
||||||
int artIndex = artPos > 0 ? Integer.parseInt(info[artPos]) : IPaperCard.NO_ART_INDEX; // default: no art index
|
|
||||||
String collectorNumber = cNrPos > 0 ? info[cNrPos].substring(1, info[cNrPos].length() - 1) : IPaperCard.NO_COLLECTOR_NUMBER;
|
if(info.length > index && isSetCode(info[index])) {
|
||||||
String setCode = setPos > 0 ? info[setPos] : null;
|
setCode = info[index];
|
||||||
Set<String> colorID = clrPos > 0 ? Arrays.stream(info[clrPos].substring(1).split(colorIDPrefix)).collect(Collectors.toSet()) : null;
|
index++;
|
||||||
if (setCode != null && setCode.equals(CardEdition.UNKNOWN.getCode())) { // ???
|
}
|
||||||
|
if(info.length > index && isArtIndex(info[index])) {
|
||||||
|
artIndex = Integer.parseInt(info[index]);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
if(info.length > index && isCollectorNumber(info[index])) {
|
||||||
|
collectorNumber = info[index].substring(1, info[index].length() - 1);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
if (info.length > index && isFlagSegment(info[index])) {
|
||||||
|
String flagText = info[index].substring(FlagPrefix.length());
|
||||||
|
flags = parseRequestFlags(flagText);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CardEdition.UNKNOWN_CODE.equals(setCode)) { // ???
|
||||||
setCode = null;
|
setCode = null;
|
||||||
}
|
}
|
||||||
if (setCode == null) {
|
if (setCode == null) {
|
||||||
@@ -253,7 +269,29 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
|
|||||||
// finally, check whether any between artIndex and CollectorNumber has been set
|
// finally, check whether any between artIndex and CollectorNumber has been set
|
||||||
if (collectorNumber.equals(IPaperCard.NO_COLLECTOR_NUMBER) && artIndex == IPaperCard.NO_ART_INDEX)
|
if (collectorNumber.equals(IPaperCard.NO_COLLECTOR_NUMBER) && artIndex == IPaperCard.NO_ART_INDEX)
|
||||||
artIndex = IPaperCard.DEFAULT_ART_INDEX;
|
artIndex = IPaperCard.DEFAULT_ART_INDEX;
|
||||||
return new CardRequest(cardName, setCode, artIndex, isFoil, collectorNumber, colorID);
|
return new CardRequest(cardName, setCode, artIndex, isFoil, collectorNumber, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, String> parseRequestFlags(String flagText) {
|
||||||
|
flagText = flagText.trim();
|
||||||
|
if(flagText.isEmpty())
|
||||||
|
return null;
|
||||||
|
if(!flagText.startsWith("{")) {
|
||||||
|
//Legacy form for marked colors. They'll be of the form "W#B#R"
|
||||||
|
Map<String, String> flags = new HashMap<>();
|
||||||
|
String normalizedColorString = ColorSet.fromNames(flagText.split(FlagPrefix)).toString();
|
||||||
|
flags.put("markedColors", String.join("", normalizedColorString));
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
flagText = flagText.substring(1, flagText.length() - 1); //Trim the braces.
|
||||||
|
//List of flags, a series of "key=value" text broken up by tabs.
|
||||||
|
return Arrays.stream(flagText.split(FlagSeparator))
|
||||||
|
.map(f -> f.split("=", 2))
|
||||||
|
.filter(f -> f.length > 0)
|
||||||
|
.collect(Collectors.toMap(
|
||||||
|
entry -> entry[0],
|
||||||
|
entry -> entry.length > 1 ? entry[1] : "true" //If there's no '=' in the entry, treat it as a boolean flag.
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,7 +444,7 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
|
|||||||
addCard(new PaperCard(cr, upcomingSet.getCode(), CardRarity.Unknown));
|
addCard(new PaperCard(cr, upcomingSet.getCode(), CardRarity.Unknown));
|
||||||
} else if (enableUnknownCards && !this.filtered.contains(cr.getName())) {
|
} else if (enableUnknownCards && !this.filtered.contains(cr.getName())) {
|
||||||
System.err.println("The card " + cr.getName() + " was not assigned to any set. Adding it to UNKNOWN set... to fix see res/editions/ folder. ");
|
System.err.println("The card " + cr.getName() + " was not assigned to any set. Adding it to UNKNOWN set... to fix see res/editions/ folder. ");
|
||||||
addCard(new PaperCard(cr, CardEdition.UNKNOWN.getCode(), CardRarity.Special));
|
addCard(new PaperCard(cr, CardEdition.UNKNOWN_CODE, CardRarity.Special));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
System.err.println("The custom card " + cr.getName() + " was not assigned to any set. Adding it to custom USER set, and will try to load custom art from USER edition.");
|
System.err.println("The custom card " + cr.getName() + " was not assigned to any set. Adding it to custom USER set, and will try to load custom art from USER edition.");
|
||||||
@@ -592,15 +630,8 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PaperCard getCard(final String cardName, String setCode, int artIndex, String collectorNumber) {
|
public PaperCard getCard(final String cardName, String setCode, int artIndex, Map<String, String> flags) {
|
||||||
String reqInfo = CardRequest.compose(cardName, setCode, artIndex, collectorNumber);
|
String reqInfo = CardRequest.compose(cardName, setCode, artIndex, flags);
|
||||||
CardRequest request = CardRequest.fromString(reqInfo);
|
|
||||||
return tryGetCard(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PaperCard getCard(final String cardName, String setCode, int artIndex, Set<String> colorID) {
|
|
||||||
String reqInfo = CardRequest.compose(cardName, setCode, artIndex, colorID);
|
|
||||||
CardRequest request = CardRequest.fromString(reqInfo);
|
CardRequest request = CardRequest.fromString(reqInfo);
|
||||||
return tryGetCard(request);
|
return tryGetCard(request);
|
||||||
}
|
}
|
||||||
@@ -611,14 +642,17 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
|
|||||||
return null;
|
return null;
|
||||||
// 1. First off, try using all possible search parameters, to narrow down the actual cards looked for.
|
// 1. First off, try using all possible search parameters, to narrow down the actual cards looked for.
|
||||||
String reqEditionCode = request.edition;
|
String reqEditionCode = request.edition;
|
||||||
if (reqEditionCode != null && reqEditionCode.length() > 0) {
|
if (reqEditionCode != null && !reqEditionCode.isEmpty()) {
|
||||||
// This get is robust even against expansion aliases (e.g. TE and TMP both valid for Tempest) -
|
// This get is robust even against expansion aliases (e.g. TE and TMP both valid for Tempest) -
|
||||||
// MOST of the extensions have two short codes, 141 out of 221 (so far)
|
// MOST of the extensions have two short codes, 141 out of 221 (so far)
|
||||||
// ALSO: Set Code are always UpperCase
|
// ALSO: Set Code are always UpperCase
|
||||||
CardEdition edition = editions.get(reqEditionCode.toUpperCase());
|
CardEdition edition = editions.get(reqEditionCode.toUpperCase());
|
||||||
|
|
||||||
return this.getCardFromSet(request.cardName, edition, request.artIndex,
|
PaperCard cardFromSet = this.getCardFromSet(request.cardName, edition, request.artIndex, request.collectorNumber, request.isFoil);
|
||||||
request.collectorNumber, request.isFoil, request.colorID);
|
if(cardFromSet != null && request.flags != null)
|
||||||
|
cardFromSet = cardFromSet.copyWithFlags(request.flags);
|
||||||
|
|
||||||
|
return cardFromSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Card lookup in edition with specified filter didn't work.
|
// 2. Card lookup in edition with specified filter didn't work.
|
||||||
@@ -661,11 +695,6 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PaperCard getCardFromSet(String cardName, CardEdition edition, int artIndex, String collectorNumber, boolean isFoil) {
|
public PaperCard getCardFromSet(String cardName, CardEdition edition, int artIndex, String collectorNumber, boolean isFoil) {
|
||||||
return getCardFromSet(cardName, edition, artIndex, collectorNumber, isFoil, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PaperCard getCardFromSet(String cardName, CardEdition edition, int artIndex, String collectorNumber, boolean isFoil, Set<String> colorID) {
|
|
||||||
if (edition == null || cardName == null) // preview cards
|
if (edition == null || cardName == null) // preview cards
|
||||||
return null; // No cards will be returned
|
return null; // No cards will be returned
|
||||||
|
|
||||||
@@ -674,18 +703,18 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
|
|||||||
cardName = cardNameRequest.cardName;
|
cardName = cardNameRequest.cardName;
|
||||||
isFoil = isFoil || cardNameRequest.isFoil;
|
isFoil = isFoil || cardNameRequest.isFoil;
|
||||||
|
|
||||||
List<PaperCard> candidates = getAllCards(cardName, c -> {
|
String code1 = edition.getCode(), code2 = edition.getCode2();
|
||||||
boolean artIndexFilter = true;
|
|
||||||
boolean collectorNumberFilter = true;
|
Predicate<PaperCard> filter = (c) -> {
|
||||||
boolean setFilter = c.getEdition().equalsIgnoreCase(edition.getCode()) ||
|
String ed = c.getEdition();
|
||||||
c.getEdition().equalsIgnoreCase(edition.getCode2());
|
return ed.equalsIgnoreCase(code1) || ed.equalsIgnoreCase(code2);
|
||||||
if (artIndex > 0)
|
};
|
||||||
artIndexFilter = (c.getArtIndex() == artIndex);
|
if (artIndex > 0)
|
||||||
if ((collectorNumber != null) && (collectorNumber.length() > 0)
|
filter = filter.and((c) -> artIndex == c.getArtIndex());
|
||||||
&& !(collectorNumber.equals(IPaperCard.NO_COLLECTOR_NUMBER)))
|
if (collectorNumber != null && !collectorNumber.isEmpty() && !collectorNumber.equals(IPaperCard.NO_COLLECTOR_NUMBER))
|
||||||
collectorNumberFilter = (c.getCollectorNumber().equals(collectorNumber));
|
filter = filter.and((c) -> collectorNumber.equals(c.getCollectorNumber()));
|
||||||
return setFilter && artIndexFilter && collectorNumberFilter;
|
|
||||||
});
|
List<PaperCard> candidates = getAllCards(cardName, filter);
|
||||||
if (candidates.isEmpty())
|
if (candidates.isEmpty())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@@ -699,7 +728,7 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
|
|||||||
while (!candidate.hasImage() && candidatesIterator.hasNext())
|
while (!candidate.hasImage() && candidatesIterator.hasNext())
|
||||||
candidate = candidatesIterator.next();
|
candidate = candidatesIterator.next();
|
||||||
candidate = candidate.hasImage() ? candidate : firstCandidate;
|
candidate = candidate.hasImage() ? candidate : firstCandidate;
|
||||||
return isFoil ? candidate.getFoiled().getColorIDVersion(colorID) : candidate.getColorIDVersion(colorID);
|
return isFoil ? candidate.getFoiled() : candidate;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -742,11 +771,6 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
|
|||||||
return this.tryToGetCardFromEditions(cardInfo, artPreference, artIndex, filter);
|
return this.tryToGetCardFromEditions(cardInfo, artPreference, artIndex, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public PaperCard getCardFromEditions(final String cardInfo, final CardArtPreference artPreference, int artIndex, Set<String> colorID) {
|
|
||||||
return this.tryToGetCardFromEditions(cardInfo, artPreference, artIndex, null, false, null, colorID);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ===============================================
|
* ===============================================
|
||||||
* 4. SPECIALISED CARD LOOKUP BASED ON
|
* 4. SPECIALISED CARD LOOKUP BASED ON
|
||||||
@@ -820,12 +844,7 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private PaperCard tryToGetCardFromEditions(String cardInfo, CardArtPreference artPreference, int artIndex,
|
private PaperCard tryToGetCardFromEditions(String cardInfo, CardArtPreference artPreference, int artIndex,
|
||||||
Date releaseDate, boolean releasedBeforeFlag, Predicate<PaperCard> filter){
|
Date releaseDate, boolean releasedBeforeFlag, Predicate<PaperCard> filter) {
|
||||||
return this.tryToGetCardFromEditions(cardInfo, artPreference, artIndex, releaseDate, releasedBeforeFlag, filter, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private PaperCard tryToGetCardFromEditions(String cardInfo, CardArtPreference artPreference, int artIndex,
|
|
||||||
Date releaseDate, boolean releasedBeforeFlag, Predicate<PaperCard> filter, Set<String> colorID){
|
|
||||||
if (cardInfo == null)
|
if (cardInfo == null)
|
||||||
return null;
|
return null;
|
||||||
final CardRequest cr = CardRequest.fromString(cardInfo);
|
final CardRequest cr = CardRequest.fromString(cardInfo);
|
||||||
@@ -865,7 +884,7 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
|
|||||||
for (PaperCard card : cards) {
|
for (PaperCard card : cards) {
|
||||||
String setCode = card.getEdition();
|
String setCode = card.getEdition();
|
||||||
CardEdition ed;
|
CardEdition ed;
|
||||||
if (setCode.equals(CardEdition.UNKNOWN.getCode()))
|
if (setCode.equals(CardEdition.UNKNOWN_CODE))
|
||||||
ed = CardEdition.UNKNOWN;
|
ed = CardEdition.UNKNOWN;
|
||||||
else
|
else
|
||||||
ed = editions.get(card.getEdition());
|
ed = editions.get(card.getEdition());
|
||||||
@@ -906,7 +925,7 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
|
|||||||
}
|
}
|
||||||
candidate = candidate.hasImage() ? candidate : firstCandidate;
|
candidate = candidate.hasImage() ? candidate : firstCandidate;
|
||||||
//If any, we're sure that at least one candidate is always returned despite it having any image
|
//If any, we're sure that at least one candidate is always returned despite it having any image
|
||||||
return cr.isFoil ? candidate.getFoiled().getColorIDVersion(colorID) : candidate.getColorIDVersion(colorID);
|
return cr.isFoil ? candidate.getFoiled() : candidate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1126,29 +1145,6 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
|
|||||||
.anyMatch(rarity::equals);
|
.anyMatch(rarity::equals);
|
||||||
}
|
}
|
||||||
|
|
||||||
public StringBuilder appendCardToStringBuilder(PaperCard card, StringBuilder sb) {
|
|
||||||
final boolean hasBadSetInfo = card.getEdition().equals(CardEdition.UNKNOWN.getCode()) || StringUtils.isBlank(card.getEdition());
|
|
||||||
sb.append(card.getName());
|
|
||||||
if (card.isFoil()) {
|
|
||||||
sb.append(CardDb.foilSuffix);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasBadSetInfo) {
|
|
||||||
int artCount = getArtCount(card.getName(), card.getEdition(), card.getFunctionalVariant());
|
|
||||||
sb.append(CardDb.NameSetSeparator).append(card.getEdition());
|
|
||||||
if (artCount >= IPaperCard.DEFAULT_ART_INDEX) {
|
|
||||||
sb.append(CardDb.NameSetSeparator).append(card.getArtIndex()); // indexes start at 1 to match image file name conventions
|
|
||||||
}
|
|
||||||
if (card.getColorID() != null) {
|
|
||||||
sb.append(CardDb.NameSetSeparator);
|
|
||||||
for (String color : card.getColorID())
|
|
||||||
sb.append(CardDb.colorIDPrefix).append(color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PaperCard createUnsupportedCard(String cardRequest) {
|
public PaperCard createUnsupportedCard(String cardRequest) {
|
||||||
CardRequest request = CardRequest.fromString(cardRequest);
|
CardRequest request = CardRequest.fromString(cardRequest);
|
||||||
CardEdition cardEdition = CardEdition.UNKNOWN;
|
CardEdition cardEdition = CardEdition.UNKNOWN;
|
||||||
@@ -1250,7 +1246,7 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (paperCards.isEmpty()) {
|
if (paperCards.isEmpty()) {
|
||||||
paperCards.add(new PaperCard(rules, CardEdition.UNKNOWN.getCode(), CardRarity.Special));
|
paperCards.add(new PaperCard(rules, CardEdition.UNKNOWN_CODE, CardRarity.Special));
|
||||||
}
|
}
|
||||||
// 2. add them to db
|
// 2. add them to db
|
||||||
for (PaperCard paperCard : paperCards) {
|
for (PaperCard paperCard : paperCards) {
|
||||||
|
|||||||
@@ -262,7 +262,11 @@ public final class CardEdition implements Comparable<CardEdition> {
|
|||||||
|
|
||||||
private final static SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
|
private final static SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
|
||||||
public static final CardEdition UNKNOWN = new CardEdition("1990-01-01", "???", "??", Type.UNKNOWN, "Undefined", FoilType.NOT_SUPPORTED, new CardInSet[]{});
|
/**
|
||||||
|
* Equivalent to the set code of CardEdition.UNKNOWN
|
||||||
|
*/
|
||||||
|
public static final String UNKNOWN_CODE = "???";
|
||||||
|
public static final CardEdition UNKNOWN = new CardEdition("1990-01-01", UNKNOWN_CODE, "??", Type.UNKNOWN, "Undefined", FoilType.NOT_SUPPORTED, new CardInSet[]{});
|
||||||
private Date date;
|
private Date date;
|
||||||
private String code;
|
private String code;
|
||||||
private String code2;
|
private String code2;
|
||||||
|
|||||||
@@ -396,6 +396,7 @@ public final class CardRules implements ICardCharacteristics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getSetColorID() {
|
public int getSetColorID() {
|
||||||
|
//Could someday generalize this to support other kinds of markings.
|
||||||
return setColorID;
|
return setColorID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ import forge.util.BinaryUtil;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>CardColor class.</p>
|
* <p>CardColor class.</p>
|
||||||
@@ -291,14 +293,8 @@ public final class ColorSet implements Comparable<ColorSet>, Iterable<Byte>, Ser
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
if (this.orderWeight == -1) {
|
final ManaCostShard[] orderedShards = getOrderedShards();
|
||||||
return "n/a";
|
return Arrays.stream(orderedShards).map(ManaCostShard::toShortString).collect(Collectors.joining());
|
||||||
}
|
|
||||||
final String toReturn = MagicColor.toLongString(myColor);
|
|
||||||
if (toReturn.equals(MagicColor.Constant.COLORLESS) && myColor != 0) {
|
|
||||||
return "multi";
|
|
||||||
}
|
|
||||||
return toReturn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -376,6 +372,10 @@ public final class ColorSet implements Comparable<ColorSet>, Iterable<Byte>, Ser
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Stream<MagicColor.Color> stream() {
|
||||||
|
return this.toEnumSet().stream();
|
||||||
|
}
|
||||||
|
|
||||||
//Get array of mana cost shards for color set in the proper order
|
//Get array of mana cost shards for color set in the proper order
|
||||||
public ManaCostShard[] getOrderedShards() {
|
public ManaCostShard[] getOrderedShards() {
|
||||||
return shardOrderLookup[myColor];
|
return shardOrderLookup[myColor];
|
||||||
|
|||||||
@@ -5,43 +5,42 @@ import forge.item.PaperCard;
|
|||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Magic Cards Database.
|
||||||
|
* --------------------
|
||||||
|
* This interface defines the general API for Database Access and Cards' Lookup.
|
||||||
|
* <p>
|
||||||
|
* Methods for single Card's lookup currently support three alternative strategies:
|
||||||
|
* 1. [getCard]: Card search based on a single card's attributes
|
||||||
|
* (i.e. name, edition, art, collectorNumber)
|
||||||
|
* <p>
|
||||||
|
* 2. [getCardFromSet]: Card Lookup from a single Expansion set.
|
||||||
|
* Particularly useful in Deck Editors when a specific Set is specified.
|
||||||
|
* <p>
|
||||||
|
* 3. [getCardFromEditions]: Card search considering a predefined `SetPreference` policy and/or a specified Date
|
||||||
|
* when no expansion is specified for a card.
|
||||||
|
* This method is particularly useful for Re-prints whenever no specific
|
||||||
|
* Expansion is specified (e.g. in Deck Import) and a decision should be made
|
||||||
|
* on which card to pick. This methods allows to adopt a SetPreference selection
|
||||||
|
* policy to make this decision.
|
||||||
|
* <p>
|
||||||
|
* The API also includes methods to fetch Collection of Card (i.e. PaperCard instances):
|
||||||
|
* - all cards (no filter)
|
||||||
|
* - all unique cards (by name)
|
||||||
|
* - all prints of a single card
|
||||||
|
* - all cards from a single Expansion Set
|
||||||
|
* - all cards compliant with a filter condition (i.e. Predicate)
|
||||||
|
* <p>
|
||||||
|
* Finally, various utility methods are supported:
|
||||||
|
* - Get the foil version of a Card (if Any)
|
||||||
|
* - Get the Order Number of a Card in an Expansion Set
|
||||||
|
* - Get the number of Print/Arts for a card in a Set (useful for those exp. having multiple arts)
|
||||||
|
* */
|
||||||
public interface ICardDatabase extends Iterable<PaperCard> {
|
public interface ICardDatabase extends Iterable<PaperCard> {
|
||||||
/**
|
|
||||||
* Magic Cards Database.
|
|
||||||
* --------------------
|
|
||||||
* This interface defines the general API for Database Access and Cards' Lookup.
|
|
||||||
*
|
|
||||||
* Methods for single Card's lookup currently support three alternative strategies:
|
|
||||||
* 1. [getCard]: Card search based on a single card's attributes
|
|
||||||
* (i.e. name, edition, art, collectorNumber)
|
|
||||||
*
|
|
||||||
* 2. [getCardFromSet]: Card Lookup from a single Expansion set.
|
|
||||||
* Particularly useful in Deck Editors when a specific Set is specified.
|
|
||||||
*
|
|
||||||
* 3. [getCardFromEditions]: Card search considering a predefined `SetPreference` policy and/or a specified Date
|
|
||||||
* when no expansion is specified for a card.
|
|
||||||
* This method is particularly useful for Re-prints whenever no specific
|
|
||||||
* Expansion is specified (e.g. in Deck Import) and a decision should be made
|
|
||||||
* on which card to pick. This methods allows to adopt a SetPreference selection
|
|
||||||
* policy to make this decision.
|
|
||||||
*
|
|
||||||
* The API also includes methods to fetch Collection of Card (i.e. PaperCard instances):
|
|
||||||
* - all cards (no filter)
|
|
||||||
* - all unique cards (by name)
|
|
||||||
* - all prints of a single card
|
|
||||||
* - all cards from a single Expansion Set
|
|
||||||
* - all cards compliant with a filter condition (i.e. Predicate)
|
|
||||||
*
|
|
||||||
* Finally, various utility methods are supported:
|
|
||||||
* - Get the foil version of a Card (if Any)
|
|
||||||
* - Get the Order Number of a Card in an Expansion Set
|
|
||||||
* - Get the number of Print/Arts for a card in a Set (useful for those exp. having multiple arts)
|
|
||||||
* */
|
|
||||||
|
|
||||||
/* SINGLE CARD RETRIEVAL METHODS
|
/* SINGLE CARD RETRIEVAL METHODS
|
||||||
* ============================= */
|
* ============================= */
|
||||||
// 1. Card Lookup by attributes
|
// 1. Card Lookup by attributes
|
||||||
@@ -50,22 +49,19 @@ public interface ICardDatabase extends Iterable<PaperCard> {
|
|||||||
PaperCard getCard(String cardName, String edition, int artIndex);
|
PaperCard getCard(String cardName, String edition, int artIndex);
|
||||||
// [NEW Methods] Including the card CollectorNumber as criterion for DB lookup
|
// [NEW Methods] Including the card CollectorNumber as criterion for DB lookup
|
||||||
PaperCard getCard(String cardName, String edition, String collectorNumber);
|
PaperCard getCard(String cardName, String edition, String collectorNumber);
|
||||||
PaperCard getCard(String cardName, String edition, int artIndex, String collectorNumber);
|
PaperCard getCard(String cardName, String edition, int artIndex, Map<String, String> flags);
|
||||||
PaperCard getCard(String cardName, String edition, int artIndex, Set<String> colorID);
|
|
||||||
|
|
||||||
// 2. Card Lookup from a single Expansion Set
|
// 2. Card Lookup from a single Expansion Set
|
||||||
PaperCard getCardFromSet(String cardName, CardEdition edition, boolean isFoil); // NOT yet used, included for API symmetry
|
PaperCard getCardFromSet(String cardName, CardEdition edition, boolean isFoil); // NOT yet used, included for API symmetry
|
||||||
PaperCard getCardFromSet(String cardName, CardEdition edition, String collectorNumber, boolean isFoil);
|
PaperCard getCardFromSet(String cardName, CardEdition edition, String collectorNumber, boolean isFoil);
|
||||||
PaperCard getCardFromSet(String cardName, CardEdition edition, int artIndex, boolean isFoil);
|
PaperCard getCardFromSet(String cardName, CardEdition edition, int artIndex, boolean isFoil);
|
||||||
PaperCard getCardFromSet(String cardName, CardEdition edition, int artIndex, String collectorNumber, boolean isFoil);
|
PaperCard getCardFromSet(String cardName, CardEdition edition, int artIndex, String collectorNumber, boolean isFoil);
|
||||||
PaperCard getCardFromSet(String cardName, CardEdition edition, int artIndex, String collectorNumber, boolean isFoil, Set<String> colorID);
|
|
||||||
|
|
||||||
// 3. Card lookup based on CardArtPreference Selection Policy
|
// 3. Card lookup based on CardArtPreference Selection Policy
|
||||||
PaperCard getCardFromEditions(String cardName, CardArtPreference artPreference);
|
PaperCard getCardFromEditions(String cardName, CardArtPreference artPreference);
|
||||||
PaperCard getCardFromEditions(String cardName, CardArtPreference artPreference, Predicate<PaperCard> filter);
|
PaperCard getCardFromEditions(String cardName, CardArtPreference artPreference, Predicate<PaperCard> filter);
|
||||||
PaperCard getCardFromEditions(String cardName, CardArtPreference artPreference, int artIndex);
|
PaperCard getCardFromEditions(String cardName, CardArtPreference artPreference, int artIndex);
|
||||||
PaperCard getCardFromEditions(String cardName, CardArtPreference artPreference, int artIndex, Predicate<PaperCard> filter);
|
PaperCard getCardFromEditions(String cardName, CardArtPreference artPreference, int artIndex, Predicate<PaperCard> filter);
|
||||||
PaperCard getCardFromEditions(String cardName, CardArtPreference artPreference, int artIndex, Set<String> colorID);
|
|
||||||
|
|
||||||
// 4. Specialised Card Lookup on CardArtPreference Selection and Release Date
|
// 4. Specialised Card Lookup on CardArtPreference Selection and Release Date
|
||||||
PaperCard getCardFromEditionsReleasedBefore(String cardName, CardArtPreference artPreference, Date releaseDate);
|
PaperCard getCardFromEditionsReleasedBefore(String cardName, CardArtPreference artPreference, Date releaseDate);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package forge.card;
|
package forge.card;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import forge.deck.DeckRecognizer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds byte values for each color magic has.
|
* Holds byte values for each color magic has.
|
||||||
@@ -187,6 +188,12 @@ public final class MagicColor {
|
|||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getLocalizedName() {
|
||||||
|
//Should probably move some of this logic back here, or at least to a more general location.
|
||||||
|
return DeckRecognizer.getLocalisedMagicColorName(getName());
|
||||||
|
}
|
||||||
|
|
||||||
public byte getColormask() {
|
public byte getColormask() {
|
||||||
return colormask;
|
return colormask;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ public enum ManaCostShard {
|
|||||||
/** The cmpc. */
|
/** The cmpc. */
|
||||||
private final float cmpc;
|
private final float cmpc;
|
||||||
private final String stringValue;
|
private final String stringValue;
|
||||||
|
private final String shortStringValue;
|
||||||
|
|
||||||
/** The image key. */
|
/** The image key. */
|
||||||
private final String imageKey;
|
private final String imageKey;
|
||||||
@@ -125,6 +126,7 @@ public enum ManaCostShard {
|
|||||||
this.cmc = this.getCMC();
|
this.cmc = this.getCMC();
|
||||||
this.cmpc = this.getCmpCost();
|
this.cmpc = this.getCmpCost();
|
||||||
this.stringValue = "{" + sValue + "}";
|
this.stringValue = "{" + sValue + "}";
|
||||||
|
this.shortStringValue = sValue;
|
||||||
this.imageKey = imgKey;
|
this.imageKey = imgKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,16 +234,21 @@ public enum ManaCostShard {
|
|||||||
return ManaCostShard.valueOf(atoms);
|
return ManaCostShard.valueOf(atoms);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* (non-Javadoc)
|
* @return the string representation of this shard - e.g. "{W}" "{2/U}" "{G/P}"
|
||||||
*
|
|
||||||
* @see java.lang.Object#toString()
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public final String toString() {
|
public final String toString() {
|
||||||
return this.stringValue;
|
return this.stringValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The string representation of this shard without brackets - e.g. "W" "2/U" "G/P"
|
||||||
|
*/
|
||||||
|
public final String toShortString() {
|
||||||
|
return this.shortStringValue;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the cmc.
|
* Gets the cmc.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public class CardPool extends ItemPool<PaperCard> {
|
|||||||
|
|
||||||
public void add(final String cardRequest, final int amount) {
|
public void add(final String cardRequest, final int amount) {
|
||||||
CardDb.CardRequest request = CardDb.CardRequest.fromString(cardRequest);
|
CardDb.CardRequest request = CardDb.CardRequest.fromString(cardRequest);
|
||||||
this.add(CardDb.CardRequest.compose(request.cardName, request.isFoil), request.edition, request.artIndex, amount, false, request.colorID);
|
this.add(CardDb.CardRequest.compose(request.cardName, request.isFoil), request.edition, request.artIndex, amount, false, request.flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(final String cardName, final String setCode) {
|
public void add(final String cardName, final String setCode) {
|
||||||
@@ -71,7 +71,7 @@ public class CardPool extends ItemPool<PaperCard> {
|
|||||||
public void add(String cardName, String setCode, int artIndex, final int amount) {
|
public void add(String cardName, String setCode, int artIndex, final int amount) {
|
||||||
this.add(cardName, setCode, artIndex, amount, false, null);
|
this.add(cardName, setCode, artIndex, amount, false, null);
|
||||||
}
|
}
|
||||||
public void add(String cardName, String setCode, int artIndex, final int amount, boolean addAny, Set<String> colorID) {
|
public void add(String cardName, String setCode, int artIndex, final int amount, boolean addAny, Map<String, String> flags) {
|
||||||
Map<String, CardDb> dbs = StaticData.instance().getAvailableDatabases();
|
Map<String, CardDb> dbs = StaticData.instance().getAvailableDatabases();
|
||||||
PaperCard paperCard = null;
|
PaperCard paperCard = null;
|
||||||
String selectedDbName = "";
|
String selectedDbName = "";
|
||||||
@@ -81,7 +81,7 @@ public class CardPool extends ItemPool<PaperCard> {
|
|||||||
for (Map.Entry<String, CardDb> entry: dbs.entrySet()){
|
for (Map.Entry<String, CardDb> entry: dbs.entrySet()){
|
||||||
String dbName = entry.getKey();
|
String dbName = entry.getKey();
|
||||||
CardDb db = entry.getValue();
|
CardDb db = entry.getValue();
|
||||||
paperCard = db.getCard(cardName, setCode, artIndex, colorID);
|
paperCard = db.getCard(cardName, setCode, artIndex, flags);
|
||||||
if (paperCard != null) {
|
if (paperCard != null) {
|
||||||
selectedDbName = dbName;
|
selectedDbName = dbName;
|
||||||
break;
|
break;
|
||||||
@@ -123,7 +123,7 @@ public class CardPool extends ItemPool<PaperCard> {
|
|||||||
int cnt = artGroups[i - 1];
|
int cnt = artGroups[i - 1];
|
||||||
if (cnt <= 0)
|
if (cnt <= 0)
|
||||||
continue;
|
continue;
|
||||||
PaperCard randomCard = cardDb.getCard(cardName, setCode, i, colorID);
|
PaperCard randomCard = cardDb.getCard(cardName, setCode, i, flags);
|
||||||
this.add(randomCard, cnt);
|
this.add(randomCard, cnt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -430,7 +430,6 @@ public class CardPool extends ItemPool<PaperCard> {
|
|||||||
public String toCardList(String separator) {
|
public String toCardList(String separator) {
|
||||||
List<Entry<PaperCard, Integer>> main2sort = Lists.newArrayList(this);
|
List<Entry<PaperCard, Integer>> main2sort = Lists.newArrayList(this);
|
||||||
main2sort.sort(ItemPoolSorter.BY_NAME_THEN_SET);
|
main2sort.sort(ItemPoolSorter.BY_NAME_THEN_SET);
|
||||||
final CardDb commonDb = StaticData.instance().getCommonCards();
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
boolean isFirst = true;
|
boolean isFirst = true;
|
||||||
@@ -441,10 +440,8 @@ public class CardPool extends ItemPool<PaperCard> {
|
|||||||
else
|
else
|
||||||
isFirst = false;
|
isFirst = false;
|
||||||
|
|
||||||
CardDb db = !e.getKey().getRules().isVariant() ? commonDb : StaticData.instance().getVariantCards();
|
|
||||||
sb.append(e.getValue()).append(" ");
|
sb.append(e.getValue()).append(" ");
|
||||||
db.appendCardToStringBuilder(e.getKey(), sb);
|
sb.append(CardDb.CardRequest.compose(e.getKey()));
|
||||||
|
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
@@ -463,20 +460,4 @@ public class CardPool extends ItemPool<PaperCard> {
|
|||||||
}
|
}
|
||||||
return filteredPool;
|
return filteredPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies a predicate to this CardPool's cards.
|
|
||||||
* @param predicate the Predicate to apply to this CardPool
|
|
||||||
* @return a new CardPool made from this CardPool with only the cards that agree with the provided Predicate
|
|
||||||
*/
|
|
||||||
public CardPool getFilteredPoolWithCardsCount(Predicate<PaperCard> predicate) {
|
|
||||||
CardPool filteredPool = new CardPool();
|
|
||||||
for (Entry<PaperCard, Integer> entry : this.items.entrySet()) {
|
|
||||||
PaperCard pc = entry.getKey();
|
|
||||||
int count = entry.getValue();
|
|
||||||
if (predicate.test(pc))
|
|
||||||
filteredPool.add(pc, count);
|
|
||||||
}
|
|
||||||
return filteredPool;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -247,7 +247,7 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
|
|||||||
|
|
||||||
Map<String, List<String>> referenceDeckLoadingMap;
|
Map<String, List<String>> referenceDeckLoadingMap;
|
||||||
if (deferredSections != null) {
|
if (deferredSections != null) {
|
||||||
this.validateDeferredSections();
|
this.normalizeDeferredSections();
|
||||||
referenceDeckLoadingMap = new HashMap<>(this.deferredSections);
|
referenceDeckLoadingMap = new HashMap<>(this.deferredSections);
|
||||||
} else
|
} else
|
||||||
referenceDeckLoadingMap = new HashMap<>(loadedSections);
|
referenceDeckLoadingMap = new HashMap<>(loadedSections);
|
||||||
@@ -267,7 +267,7 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
|
|||||||
continue;
|
continue;
|
||||||
final List<String> cardsInSection = s.getValue();
|
final List<String> cardsInSection = s.getValue();
|
||||||
ArrayList<String> cardNamesWithNoEdition = getAllCardNamesWithNoSpecifiedEdition(cardsInSection);
|
ArrayList<String> cardNamesWithNoEdition = getAllCardNamesWithNoSpecifiedEdition(cardsInSection);
|
||||||
if (cardNamesWithNoEdition.size() > 0) {
|
if (!cardNamesWithNoEdition.isEmpty()) {
|
||||||
includeCardsFromUnspecifiedSet = true;
|
includeCardsFromUnspecifiedSet = true;
|
||||||
if (smartCardArtSelection)
|
if (smartCardArtSelection)
|
||||||
cardsWithNoEdition.put(sec, cardNamesWithNoEdition);
|
cardsWithNoEdition.put(sec, cardNamesWithNoEdition);
|
||||||
@@ -281,10 +281,10 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
|
|||||||
optimiseCardArtSelectionInDeckSections(cardsWithNoEdition);
|
optimiseCardArtSelectionInDeckSections(cardsWithNoEdition);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateDeferredSections() {
|
private void normalizeDeferredSections() {
|
||||||
/*
|
/*
|
||||||
Construct a temporary (DeckSection, CardPool) Maps, to be sanitised and finalised
|
Construct a temporary (DeckSection, CardPool) Maps, to be sanitised and finalised
|
||||||
before copying into `this.parts`. This sanitisation is applied because of the
|
before copying into `this.parts`. This sanitization is applied because of the
|
||||||
validation schema introduced in DeckSections.
|
validation schema introduced in DeckSections.
|
||||||
*/
|
*/
|
||||||
Map<String, List<String>> validatedSections = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
Map<String, List<String>> validatedSections = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||||
@@ -296,61 +296,33 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
|
|||||||
}
|
}
|
||||||
|
|
||||||
final List<String> cardsInSection = s.getValue();
|
final List<String> cardsInSection = s.getValue();
|
||||||
List<Pair<String, Integer>> originalCardRequests = CardPool.processCardList(cardsInSection);
|
|
||||||
CardPool pool = CardPool.fromCardList(cardsInSection);
|
CardPool pool = CardPool.fromCardList(cardsInSection);
|
||||||
if (pool.countDistinct() == 0)
|
if (pool.countDistinct() == 0)
|
||||||
continue; // pool empty, no card has been found!
|
continue; // pool empty, no card has been found!
|
||||||
|
|
||||||
// Filter pool by applying DeckSection Validation schema for Card Types (to avoid inconsistencies)
|
List<String> validatedSection = validatedSections.computeIfAbsent(s.getKey(), (k) -> new ArrayList<>());
|
||||||
CardPool filteredPool = pool.getFilteredPoolWithCardsCount(deckSection::validate);
|
for (Entry<PaperCard, Integer> entry : pool) {
|
||||||
// Add all the cards from ValidPool anyway!
|
PaperCard card = entry.getKey();
|
||||||
List<String> whiteList = validatedSections.getOrDefault(s.getKey(), null);
|
String normalizedRequest = getPoolRequest(entry);
|
||||||
if (whiteList == null)
|
if(deckSection.validate(card))
|
||||||
whiteList = new ArrayList<>();
|
validatedSection.add(normalizedRequest);
|
||||||
for (Entry<PaperCard, Integer> entry : filteredPool) {
|
else {
|
||||||
String poolRequest = getPoolRequest(entry, originalCardRequests);
|
// Card was in the wrong section. Move it to the right section.
|
||||||
whiteList.add(poolRequest);
|
DeckSection cardSection = DeckSection.matchingSection(card);
|
||||||
|
assert(cardSection.validate(card)); //Card doesn't fit in the matchingSection?
|
||||||
|
List<String> sectionCardList = validatedSections.computeIfAbsent(cardSection.name(), (k) -> new ArrayList<>());
|
||||||
|
sectionCardList.add(normalizedRequest);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
validatedSections.put(s.getKey(), whiteList);
|
|
||||||
|
|
||||||
if (filteredPool.countDistinct() != pool.countDistinct()) {
|
|
||||||
CardPool blackList = pool.getFilteredPoolWithCardsCount(input -> !(deckSection.validate(input)));
|
|
||||||
|
|
||||||
for (Entry<PaperCard, Integer> entry : blackList) {
|
|
||||||
DeckSection cardSection = DeckSection.matchingSection(entry.getKey());
|
|
||||||
String poolRequest = getPoolRequest(entry, originalCardRequests);
|
|
||||||
List<String> sectionCardList = validatedSections.getOrDefault(cardSection.name(), null);
|
|
||||||
if (sectionCardList == null)
|
|
||||||
sectionCardList = new ArrayList<>();
|
|
||||||
sectionCardList.add(poolRequest);
|
|
||||||
validatedSections.put(cardSection.name(), sectionCardList);
|
|
||||||
} // end for blacklist
|
|
||||||
} // end if
|
|
||||||
} // end main for on deferredSections
|
} // end main for on deferredSections
|
||||||
|
|
||||||
// Overwrite deferredSections
|
// Overwrite deferredSections
|
||||||
this.deferredSections = validatedSections;
|
this.deferredSections = validatedSections;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getPoolRequest(Entry<PaperCard, Integer> entry, List<Pair<String, Integer>> originalCardRequests) {
|
private String getPoolRequest(Entry<PaperCard, Integer> entry) {
|
||||||
PaperCard card = entry.getKey();
|
|
||||||
int amount = entry.getValue();
|
int amount = entry.getValue();
|
||||||
String poolCardRequest = CardDb.CardRequest.compose(
|
String poolCardRequest = CardDb.CardRequest.compose(entry.getKey());
|
||||||
card.isFoil() ? CardDb.CardRequest.compose(card.getName(), true) : card.getName(),
|
|
||||||
card.getEdition(), card.getArtIndex(), card.getColorID());
|
|
||||||
String originalRequestCandidate = null;
|
|
||||||
for (Pair<String, Integer> originalRequest : originalCardRequests){
|
|
||||||
String cardRequest = originalRequest.getLeft();
|
|
||||||
if (!StringUtils.startsWithIgnoreCase(poolCardRequest, cardRequest))
|
|
||||||
continue;
|
|
||||||
originalRequestCandidate = cardRequest;
|
|
||||||
int cardAmount = originalRequest.getRight();
|
|
||||||
if (amount == cardAmount)
|
|
||||||
return String.format("%d %s", cardAmount, cardRequest);
|
|
||||||
}
|
|
||||||
// This is just in case, it should never happen as we're
|
|
||||||
if (originalRequestCandidate != null)
|
|
||||||
return String.format("%d %s", amount, originalRequestCandidate);
|
|
||||||
return String.format("%d %s", amount, poolCardRequest);
|
return String.format("%d %s", amount, poolCardRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -987,7 +987,7 @@ public class DeckRecognizer {
|
|||||||
private static String getMagicColourLabel(MagicColor.Color magicColor) {
|
private static String getMagicColourLabel(MagicColor.Color magicColor) {
|
||||||
if (magicColor == null) // Multicolour
|
if (magicColor == null) // Multicolour
|
||||||
return String.format("%s {W}{U}{B}{R}{G}", getLocalisedMagicColorName("Multicolour"));
|
return String.format("%s {W}{U}{B}{R}{G}", getLocalisedMagicColorName("Multicolour"));
|
||||||
return String.format("%s %s", getLocalisedMagicColorName(magicColor.getName()), magicColor.getSymbol());
|
return String.format("%s %s", magicColor.getLocalizedName(), magicColor.getSymbol());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final HashMap<Integer, String> manaSymbolsMap = new HashMap<Integer, String>() {{
|
private static final HashMap<Integer, String> manaSymbolsMap = new HashMap<Integer, String>() {{
|
||||||
@@ -1006,8 +1006,8 @@ public class DeckRecognizer {
|
|||||||
if (magicColor2 == null || magicColor2 == MagicColor.Color.COLORLESS
|
if (magicColor2 == null || magicColor2 == MagicColor.Color.COLORLESS
|
||||||
|| magicColor1 == MagicColor.Color.COLORLESS)
|
|| magicColor1 == MagicColor.Color.COLORLESS)
|
||||||
return String.format("%s // %s", getMagicColourLabel(magicColor1), getMagicColourLabel(magicColor2));
|
return String.format("%s // %s", getMagicColourLabel(magicColor1), getMagicColourLabel(magicColor2));
|
||||||
String localisedName1 = getLocalisedMagicColorName(magicColor1.getName());
|
String localisedName1 = magicColor1.getLocalizedName();
|
||||||
String localisedName2 = getLocalisedMagicColorName(magicColor2.getName());
|
String localisedName2 = magicColor2.getLocalizedName();
|
||||||
String comboManaSymbol = manaSymbolsMap.get(magicColor1.getColormask() | magicColor2.getColormask());
|
String comboManaSymbol = manaSymbolsMap.get(magicColor1.getColormask() | magicColor2.getColormask());
|
||||||
return String.format("%s/%s {%s}", localisedName1, localisedName2, comboManaSymbol);
|
return String.format("%s/%s {%s}", localisedName1, localisedName2, comboManaSymbol);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ public enum DeckSection {
|
|||||||
CardType t = card.getRules().getType();
|
CardType t = card.getRules().getType();
|
||||||
// NOTE: Same rules applies to both Deck and Side, despite "Conspiracy cards" are allowed
|
// NOTE: Same rules applies to both Deck and Side, despite "Conspiracy cards" are allowed
|
||||||
// in the SideBoard (see Rule 313.2)
|
// in the SideBoard (see Rule 313.2)
|
||||||
// Those will be matched later, in case (see `Deck::validateDeferredSections`)
|
// Those will be matched later, in case (see `Deck::normalizeDeferredSections`)
|
||||||
return !t.isConspiracy() && !t.isDungeon() && !t.isPhenomenon() && !t.isPlane() && !t.isScheme() && !t.isVanguard();
|
return !t.isConspiracy() && !t.isDungeon() && !t.isPhenomenon() && !t.isPlane() && !t.isScheme() && !t.isVanguard();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,8 @@ public class DeckSerializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(Entry<DeckSection, CardPool> s : d) {
|
for(Entry<DeckSection, CardPool> s : d) {
|
||||||
|
if(s.getValue().isEmpty())
|
||||||
|
continue;
|
||||||
out.add(TextUtil.enclosedBracket(s.getKey().toString()));
|
out.add(TextUtil.enclosedBracket(s.getKey().toString()));
|
||||||
out.add(s.getValue().toCardList(System.lineSeparator()));
|
out.add(s.getValue().toCardList(System.lineSeparator()));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ package forge.item;
|
|||||||
|
|
||||||
import forge.card.CardRarity;
|
import forge.card.CardRarity;
|
||||||
import forge.card.CardRules;
|
import forge.card.CardRules;
|
||||||
|
import forge.card.ColorSet;
|
||||||
import forge.card.ICardFace;
|
import forge.card.ICardFace;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public interface IPaperCard extends InventoryItem, Serializable {
|
public interface IPaperCard extends InventoryItem, Serializable {
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ public interface IPaperCard extends InventoryItem, Serializable {
|
|||||||
String getEdition();
|
String getEdition();
|
||||||
String getCollectorNumber();
|
String getCollectorNumber();
|
||||||
String getFunctionalVariant();
|
String getFunctionalVariant();
|
||||||
Set<String> getColorID();
|
ColorSet getMarkedColors();
|
||||||
int getArtIndex();
|
int getArtIndex();
|
||||||
boolean isFoil();
|
boolean isFoil();
|
||||||
boolean isToken();
|
boolean isToken();
|
||||||
|
|||||||
@@ -28,8 +28,10 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.ObjectInputStream;
|
import java.io.ObjectInputStream;
|
||||||
import java.util.Optional;
|
import java.io.ObjectStreamException;
|
||||||
import java.util.Set;
|
import java.io.Serial;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A lightweight version of a card that matches real-world cards, to use outside of games (eg. inventory, decks, trade).
|
* A lightweight version of a card that matches real-world cards, to use outside of games (eg. inventory, decks, trade).
|
||||||
@@ -39,6 +41,7 @@ import java.util.Set;
|
|||||||
* @author Forge
|
* @author Forge
|
||||||
*/
|
*/
|
||||||
public class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet, IPaperCard {
|
public class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet, IPaperCard {
|
||||||
|
@Serial
|
||||||
private static final long serialVersionUID = 2942081982620691205L;
|
private static final long serialVersionUID = 2942081982620691205L;
|
||||||
|
|
||||||
// Reference to rules
|
// Reference to rules
|
||||||
@@ -55,16 +58,15 @@ public class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet,
|
|||||||
private String artist;
|
private String artist;
|
||||||
private final int artIndex;
|
private final int artIndex;
|
||||||
private final boolean foil;
|
private final boolean foil;
|
||||||
private Boolean hasImage;
|
private final PaperCardFlags flags;
|
||||||
private final boolean noSell;
|
private final String sortableName;
|
||||||
private Set<String> colorID;
|
|
||||||
private String sortableName;
|
|
||||||
private final String functionalVariant;
|
private final String functionalVariant;
|
||||||
|
|
||||||
// Calculated fields are below:
|
// Calculated fields are below:
|
||||||
private transient CardRarity rarity; // rarity is given in ctor when set is assigned
|
private transient CardRarity rarity; // rarity is given in ctor when set is assigned
|
||||||
// Reference to a new instance of Self, but foiled!
|
// Reference to a new instance of Self, but foiled!
|
||||||
private transient PaperCard foiledVersion, noSellVersion;
|
private transient PaperCard foiledVersion, noSellVersion, flaglessVersion;
|
||||||
|
private transient Boolean hasImage;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
@@ -89,8 +91,8 @@ public class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getColorID() {
|
public ColorSet getMarkedColors() {
|
||||||
return colorID;
|
return this.flags.markedColors;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -147,32 +149,32 @@ public class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet,
|
|||||||
return unFoiledVersion;
|
return unFoiledVersion;
|
||||||
}
|
}
|
||||||
public PaperCard getNoSellVersion() {
|
public PaperCard getNoSellVersion() {
|
||||||
if (this.noSell)
|
if (this.flags.noSellValue)
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
if (this.noSellVersion == null) {
|
if (this.noSellVersion == null)
|
||||||
this.noSellVersion = new PaperCard(this.rules, this.edition, this.rarity,
|
this.noSellVersion = new PaperCard(this, this.flags.withNoSellValueFlag(true));
|
||||||
this.artIndex, this.foil, String.valueOf(collectorNumber), this.artist, this.functionalVariant, true);
|
|
||||||
}
|
|
||||||
return this.noSellVersion;
|
return this.noSellVersion;
|
||||||
}
|
}
|
||||||
public PaperCard getSellable() {
|
|
||||||
if (!this.noSell)
|
|
||||||
return this;
|
|
||||||
|
|
||||||
PaperCard sellable = new PaperCard(this.rules, this.edition, this.rarity,
|
public PaperCard copyWithoutFlags() {
|
||||||
this.artIndex, this.foil, String.valueOf(collectorNumber), this.artist, this.functionalVariant, false);
|
if(this.flaglessVersion == null) {
|
||||||
return sellable;
|
if(this.flags == PaperCardFlags.IDENTITY_FLAGS)
|
||||||
|
this.flaglessVersion = this;
|
||||||
|
else
|
||||||
|
this.flaglessVersion = new PaperCard(this, null);
|
||||||
|
}
|
||||||
|
return flaglessVersion;
|
||||||
}
|
}
|
||||||
public PaperCard getColorIDVersion(Set<String> colors) {
|
public PaperCard copyWithFlags(Map<String, String> flags) {
|
||||||
if (colors == null && this.colorID == null)
|
if(flags == null || flags.isEmpty())
|
||||||
|
return this.copyWithoutFlags();
|
||||||
|
return new PaperCard(this, new PaperCardFlags(flags));
|
||||||
|
}
|
||||||
|
public PaperCard copyWithMarkedColors(ColorSet colors) {
|
||||||
|
if(Objects.equals(colors, this.flags.markedColors))
|
||||||
return this;
|
return this;
|
||||||
if (this.colorID != null && this.colorID.equals(colors))
|
return new PaperCard(this, this.flags.withMarkedColors(colors));
|
||||||
return this;
|
|
||||||
if (colors != null && colors.equals(this.colorID))
|
|
||||||
return this;
|
|
||||||
return new PaperCard(this.rules, this.edition, this.rarity,
|
|
||||||
this.artIndex, this.foil, String.valueOf(collectorNumber), this.artist, this.functionalVariant, this.noSell, colors);
|
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public String getItemType() {
|
public String getItemType() {
|
||||||
@@ -180,8 +182,12 @@ public class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet,
|
|||||||
return localizer.getMessage("lblCard");
|
return localizer.getMessage("lblCard");
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isNoSell() {
|
public PaperCardFlags getMarkedFlags() {
|
||||||
return noSell;
|
return this.flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasNoSellValue() {
|
||||||
|
return this.flags.noSellValue;
|
||||||
}
|
}
|
||||||
public boolean hasImage() {
|
public boolean hasImage() {
|
||||||
return hasImage(false);
|
return hasImage(false);
|
||||||
@@ -198,38 +204,41 @@ public class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet,
|
|||||||
IPaperCard.NO_COLLECTOR_NUMBER, IPaperCard.NO_ARTIST_NAME, IPaperCard.NO_FUNCTIONAL_VARIANT);
|
IPaperCard.NO_COLLECTOR_NUMBER, IPaperCard.NO_ARTIST_NAME, IPaperCard.NO_FUNCTIONAL_VARIANT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PaperCard(final PaperCard copyFrom, final PaperCardFlags flags) {
|
||||||
|
this(copyFrom.rules, copyFrom.edition, copyFrom.rarity, copyFrom.artIndex, copyFrom.foil, copyFrom.collectorNumber,
|
||||||
|
copyFrom.artist, copyFrom.functionalVariant, flags);
|
||||||
|
this.flaglessVersion = copyFrom.flaglessVersion;
|
||||||
|
}
|
||||||
|
|
||||||
public PaperCard(final CardRules rules0, final String edition0, final CardRarity rarity0,
|
public PaperCard(final CardRules rules0, final String edition0, final CardRarity rarity0,
|
||||||
final int artIndex0, final boolean foil0, final String collectorNumber0,
|
final int artIndex0, final boolean foil0, final String collectorNumber0,
|
||||||
final String artist0, final String functionalVariant) {
|
final String artist0, final String functionalVariant) {
|
||||||
this(rules0, edition0, rarity0, artIndex0, foil0, collectorNumber0, artist0, functionalVariant, false);
|
this(rules0, edition0, rarity0, artIndex0, foil0, collectorNumber0, artist0, functionalVariant, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PaperCard(final CardRules rules0, final String edition0, final CardRarity rarity0,
|
protected PaperCard(final CardRules rules, final String edition, final CardRarity rarity,
|
||||||
final int artIndex0, final boolean foil0, final String collectorNumber0,
|
final int artIndex, final boolean foil, final String collectorNumber,
|
||||||
final String artist0, final String functionalVariant, final boolean noSell0) {
|
final String artist, final String functionalVariant, final PaperCardFlags flags) {
|
||||||
this(rules0, edition0, rarity0, artIndex0, foil0, collectorNumber0, artist0, functionalVariant, noSell0, null);
|
if (rules == null || edition == null || rarity == null) {
|
||||||
}
|
|
||||||
|
|
||||||
public PaperCard(final CardRules rules0, final String edition0, final CardRarity rarity0,
|
|
||||||
final int artIndex0, final boolean foil0, final String collectorNumber0,
|
|
||||||
final String artist0, final String functionalVariant, final boolean noSell0, final Set<String> colorID0) {
|
|
||||||
if (rules0 == null || edition0 == null || rarity0 == null) {
|
|
||||||
throw new IllegalArgumentException("Cannot create card without rules, edition or rarity");
|
throw new IllegalArgumentException("Cannot create card without rules, edition or rarity");
|
||||||
}
|
}
|
||||||
rules = rules0;
|
this.rules = rules;
|
||||||
name = rules0.getName();
|
name = rules.getName();
|
||||||
edition = edition0;
|
this.edition = edition;
|
||||||
artIndex = Math.max(artIndex0, IPaperCard.DEFAULT_ART_INDEX);
|
this.artIndex = Math.max(artIndex, IPaperCard.DEFAULT_ART_INDEX);
|
||||||
foil = foil0;
|
this.foil = foil;
|
||||||
rarity = rarity0;
|
this.rarity = rarity;
|
||||||
artist = TextUtil.normalizeText(artist0);
|
this.artist = TextUtil.normalizeText(artist);
|
||||||
collectorNumber = (collectorNumber0 != null) && (collectorNumber0.length() > 0) ? collectorNumber0 : IPaperCard.NO_COLLECTOR_NUMBER;
|
this.collectorNumber = (collectorNumber != null && !collectorNumber.isEmpty()) ? collectorNumber : IPaperCard.NO_COLLECTOR_NUMBER;
|
||||||
// If the user changes the language this will make cards sort by the old language until they restart the game.
|
// If the user changes the language this will make cards sort by the old language until they restart the game.
|
||||||
// This is a good tradeoff
|
// This is a good tradeoff
|
||||||
sortableName = TextUtil.toSortableName(CardTranslation.getTranslatedName(rules0.getName()));
|
sortableName = TextUtil.toSortableName(CardTranslation.getTranslatedName(rules.getName()));
|
||||||
this.functionalVariant = functionalVariant != null ? functionalVariant : IPaperCard.NO_FUNCTIONAL_VARIANT;
|
this.functionalVariant = functionalVariant != null ? functionalVariant : IPaperCard.NO_FUNCTIONAL_VARIANT;
|
||||||
noSell = noSell0;
|
|
||||||
colorID = colorID0;
|
if(flags == null || flags.equals(PaperCardFlags.IDENTITY_FLAGS))
|
||||||
|
this.flags = PaperCardFlags.IDENTITY_FLAGS;
|
||||||
|
else
|
||||||
|
this.flags = flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PaperCard FAKE_CARD = new PaperCard(CardRules.getUnsupportedCardNamed("Fake Card"), "Fake Edition", CardRarity.Common);
|
public static PaperCard FAKE_CARD = new PaperCard(CardRules.getUnsupportedCardNamed("Fake Card"), "Fake Edition", CardRarity.Common);
|
||||||
@@ -256,8 +265,7 @@ public class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet,
|
|||||||
}
|
}
|
||||||
if (!getCollectorNumber().equals(other.getCollectorNumber()))
|
if (!getCollectorNumber().equals(other.getCollectorNumber()))
|
||||||
return false;
|
return false;
|
||||||
// colorID can be NULL
|
if (!Objects.equals(flags, other.flags))
|
||||||
if (getColorID() != other.getColorID())
|
|
||||||
return false;
|
return false;
|
||||||
return (other.foil == foil) && (other.artIndex == artIndex);
|
return (other.foil == foil) && (other.artIndex == artIndex);
|
||||||
}
|
}
|
||||||
@@ -269,13 +277,7 @@ public class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet,
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int code = (name.hashCode() * 11) + (edition.hashCode() * 59) +
|
return Objects.hash(name, edition, collectorNumber, artIndex, foil, flags);
|
||||||
(artIndex * 2) + (getCollectorNumber().hashCode() * 383);
|
|
||||||
final int id = Optional.ofNullable(colorID).map(Set::hashCode).orElse(0);
|
|
||||||
if (foil) {
|
|
||||||
return code + id + 1;
|
|
||||||
}
|
|
||||||
return code + id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Check
|
// FIXME: Check
|
||||||
@@ -339,6 +341,7 @@ public class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet,
|
|||||||
return Integer.compare(artIndex, o.getArtIndex());
|
return Integer.compare(artIndex, o.getArtIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Serial
|
||||||
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
|
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
|
||||||
// default deserialization
|
// default deserialization
|
||||||
ois.defaultReadObject();
|
ois.defaultReadObject();
|
||||||
@@ -354,6 +357,14 @@ public class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet,
|
|||||||
rarity = pc.getRarity();
|
rarity = pc.getRarity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private Object readResolve() throws ObjectStreamException {
|
||||||
|
//If we deserialize an old PaperCard with no flags, reinitialize as a fresh copy to set default flags.
|
||||||
|
if(this.flags == null)
|
||||||
|
return new PaperCard(this, null);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getImageKey(boolean altState) {
|
public String getImageKey(boolean altState) {
|
||||||
String normalizedName = StringUtils.stripAccents(name);
|
String normalizedName = StringUtils.stripAccents(name);
|
||||||
@@ -493,4 +504,85 @@ public class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet,
|
|||||||
public boolean isRebalanced() {
|
public boolean isRebalanced() {
|
||||||
return StaticData.instance().isRebalanced(name);
|
return StaticData.instance().isRebalanced(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains properties of a card which distinguish it from an otherwise identical copy of the card with the same
|
||||||
|
* name, edition, and collector number. Examples include permanent markings on the card, and flags for Adventure
|
||||||
|
* mode.
|
||||||
|
*/
|
||||||
|
public static class PaperCardFlags {
|
||||||
|
/**
|
||||||
|
* Chosen colors, for cards like Cryptic Spires.
|
||||||
|
*/
|
||||||
|
public final ColorSet markedColors;
|
||||||
|
/**
|
||||||
|
* Removes the sell value of the card in Adventure mode.
|
||||||
|
*/
|
||||||
|
public final boolean noSellValue;
|
||||||
|
|
||||||
|
//TODO: Could probably move foil here.
|
||||||
|
|
||||||
|
static final PaperCardFlags IDENTITY_FLAGS = new PaperCardFlags(Map.of());
|
||||||
|
|
||||||
|
protected PaperCardFlags(Map<String, String> flags) {
|
||||||
|
if(flags.containsKey("markedColors"))
|
||||||
|
markedColors = ColorSet.fromNames(flags.get("markedColors").split(""));
|
||||||
|
else
|
||||||
|
markedColors = null;
|
||||||
|
noSellValue = flags.containsKey("noSellValue");
|
||||||
|
}
|
||||||
|
|
||||||
|
//Copy constructor. There are some better ways to do this, and they should be explored once we have more than 4
|
||||||
|
//or 5 fields here. Just need to ensure it's impossible to accidentally change a field while the PaperCardFlags
|
||||||
|
//object is in use.
|
||||||
|
private PaperCardFlags(PaperCardFlags copyFrom, ColorSet markedColors, Boolean noSellValue) {
|
||||||
|
if(markedColors == null)
|
||||||
|
markedColors = copyFrom.markedColors;
|
||||||
|
else if(markedColors.isColorless())
|
||||||
|
markedColors = null;
|
||||||
|
this.markedColors = markedColors;
|
||||||
|
this.noSellValue = noSellValue != null ? noSellValue : copyFrom.noSellValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PaperCardFlags withMarkedColors(ColorSet markedColors) {
|
||||||
|
if(markedColors == null)
|
||||||
|
markedColors = ColorSet.getNullColor();
|
||||||
|
return new PaperCardFlags(this, markedColors, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PaperCardFlags withNoSellValueFlag(boolean noSellValue) {
|
||||||
|
return new PaperCardFlags(this, null, noSellValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, String> asMap;
|
||||||
|
public Map<String, String> toMap() {
|
||||||
|
if(asMap != null)
|
||||||
|
return asMap;
|
||||||
|
Map<String, String> out = new HashMap<>();
|
||||||
|
if(markedColors != null && !markedColors.isColorless())
|
||||||
|
out.put("markedColors", markedColors.toString());
|
||||||
|
if(noSellValue)
|
||||||
|
out.put("noSellValue", "true");
|
||||||
|
asMap = out;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.toMap().entrySet().stream()
|
||||||
|
.map((e) -> e.getKey() + "=" + e.getValue())
|
||||||
|
.collect(Collectors.joining("\t"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (!(o instanceof PaperCardFlags that)) return false;
|
||||||
|
return noSellValue == that.noSellValue && Objects.equals(markedColors, that.markedColors);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(markedColors, noSellValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class PaperToken implements InventoryItemFromSet, IPaperCard {
|
public class PaperToken implements InventoryItemFromSet, IPaperCard {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
@@ -153,7 +152,7 @@ public class PaperToken implements InventoryItemFromSet, IPaperCard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getColorID() {
|
public ColorSet getMarkedColors() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -269,6 +269,13 @@ public class ItemPool<T extends InventoryItem> implements Iterable<Entry<T, Inte
|
|||||||
// need not set out-of-sync: either remove did set, or nothing was removed
|
// need not set out-of-sync: either remove did set, or nothing was removed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void removeIf(Predicate<T> test) {
|
||||||
|
for (final T item : items.keySet()) {
|
||||||
|
if (test.test(item))
|
||||||
|
remove(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
items.clear();
|
items.clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import forge.GameCommand;
|
|||||||
import forge.StaticData;
|
import forge.StaticData;
|
||||||
import forge.card.CardStateName;
|
import forge.card.CardStateName;
|
||||||
import forge.card.CardType.Supertype;
|
import forge.card.CardType.Supertype;
|
||||||
|
import forge.card.ColorSet;
|
||||||
import forge.card.GamePieceType;
|
import forge.card.GamePieceType;
|
||||||
import forge.card.MagicColor;
|
import forge.card.MagicColor;
|
||||||
import forge.deck.DeckSection;
|
import forge.deck.DeckSection;
|
||||||
@@ -541,8 +542,8 @@ public class GameAction {
|
|||||||
game.addLeftGraveyardThisTurn(lastKnownInfo);
|
game.addLeftGraveyardThisTurn(lastKnownInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c.hasChosenColorSpire()) {
|
if (c.hasMarkedColor()) {
|
||||||
copied.setChosenColorID(ImmutableSet.copyOf(c.getChosenColorID()));
|
copied.setMarkedColors(c.getMarkedColors());
|
||||||
}
|
}
|
||||||
|
|
||||||
copied.updateStateForView();
|
copied.updateStateForView();
|
||||||
@@ -2414,15 +2415,14 @@ public class GameAction {
|
|||||||
for (Card c : spires) {
|
for (Card c : spires) {
|
||||||
// TODO: only do this for the AI, for the player part, get the encoded color from the deck file and pass
|
// TODO: only do this for the AI, for the player part, get the encoded color from the deck file and pass
|
||||||
// it to either player or the papercard object so it feels like rule based for the player side..
|
// it to either player or the papercard object so it feels like rule based for the player side..
|
||||||
if (!c.hasChosenColorSpire()) {
|
if (!c.hasMarkedColor()) {
|
||||||
if (takesAction.isAI()) {
|
if (takesAction.isAI()) {
|
||||||
List<String> colorChoices = new ArrayList<>(MagicColor.Constant.ONLY_COLORS);
|
|
||||||
String prompt = CardTranslation.getTranslatedName(c.getName()) + ": " +
|
String prompt = CardTranslation.getTranslatedName(c.getName()) + ": " +
|
||||||
Localizer.getInstance().getMessage("lblChooseNColors", Lang.getNumeral(2));
|
Localizer.getInstance().getMessage("lblChooseNColors", Lang.getNumeral(2));
|
||||||
SpellAbility sa = new SpellAbility.EmptySa(ApiType.ChooseColor, c, takesAction);
|
SpellAbility sa = new SpellAbility.EmptySa(ApiType.ChooseColor, c, takesAction);
|
||||||
sa.putParam("AILogic", "MostProminentInComputerDeck");
|
sa.putParam("AILogic", "MostProminentInComputerDeck");
|
||||||
Set<String> chosenColors = new HashSet<>(takesAction.getController().chooseColors(prompt, sa, 2, 2, colorChoices));
|
ColorSet chosenColors = ColorSet.fromNames(takesAction.getController().chooseColors(prompt, sa, 2, 2, MagicColor.Constant.ONLY_COLORS));
|
||||||
c.setChosenColorID(chosenColors);
|
c.setMarkedColors(chosenColors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ public class CloneEffect extends SpellAbilityEffect {
|
|||||||
tgtCard.addRemembered(cardToCopy);
|
tgtCard.addRemembered(cardToCopy);
|
||||||
}
|
}
|
||||||
// spire
|
// spire
|
||||||
tgtCard.setChosenColorID(cardToCopy.getChosenColorID());
|
tgtCard.setMarkedColors(cardToCopy.getMarkedColors());
|
||||||
|
|
||||||
game.fireEvent(new GameEventCardStatsChanged(tgtCard));
|
game.fireEvent(new GameEventCardStatsChanged(tgtCard));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -314,7 +314,7 @@ public class CopyPermanentEffect extends TokenEffectBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// spire
|
// spire
|
||||||
copy.setChosenColorID(original.getChosenColorID());
|
copy.setMarkedColors(original.getMarkedColors());
|
||||||
|
|
||||||
copy.setTokenSpawningAbility(sa);
|
copy.setTokenSpawningAbility(sa);
|
||||||
copy.setGamePieceType(GamePieceType.TOKEN);
|
copy.setGamePieceType(GamePieceType.TOKEN);
|
||||||
|
|||||||
@@ -296,7 +296,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
|
|||||||
private String chosenType2 = "";
|
private String chosenType2 = "";
|
||||||
private List<String> notedTypes = new ArrayList<>();
|
private List<String> notedTypes = new ArrayList<>();
|
||||||
private List<String> chosenColors;
|
private List<String> chosenColors;
|
||||||
private Set<String> chosenColorID;
|
private ColorSet markedColor;
|
||||||
private List<String> chosenName = new ArrayList<>();
|
private List<String> chosenName = new ArrayList<>();
|
||||||
private Integer chosenNumber;
|
private Integer chosenNumber;
|
||||||
private Player chosenPlayer;
|
private Player chosenPlayer;
|
||||||
@@ -409,7 +409,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
|
|||||||
view.updateClassLevel(this);
|
view.updateClassLevel(this);
|
||||||
view.updateDraftAction(this);
|
view.updateDraftAction(this);
|
||||||
if (paperCard != null)
|
if (paperCard != null)
|
||||||
setChosenColorID(paperCard.getColorID());
|
setMarkedColors(paperCard.getMarkedColors());
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getHiddenId() {
|
public int getHiddenId() {
|
||||||
@@ -2231,18 +2231,18 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
|
|||||||
public boolean hasChosenColor(String s) {
|
public boolean hasChosenColor(String s) {
|
||||||
return chosenColors != null && chosenColors.contains(s);
|
return chosenColors != null && chosenColors.contains(s);
|
||||||
}
|
}
|
||||||
public final Set<String> getChosenColorID() {
|
public final ColorSet getMarkedColors() {
|
||||||
if (chosenColorID == null) {
|
if (markedColor == null) {
|
||||||
return Sets.newHashSet();
|
return ColorSet.getNullColor();
|
||||||
}
|
}
|
||||||
return chosenColorID;
|
return markedColor;
|
||||||
}
|
}
|
||||||
public final void setChosenColorID(final Set<String> s) {
|
public final void setMarkedColors(final ColorSet s) {
|
||||||
chosenColorID = s;
|
markedColor = s;
|
||||||
view.updateChosenColorID(this);
|
view.updateMarkedColors(this);
|
||||||
}
|
}
|
||||||
public boolean hasChosenColorSpire() {
|
public boolean hasMarkedColor() {
|
||||||
return chosenColorID != null && !chosenColorID.isEmpty();
|
return markedColor != null && !markedColor.isColorless();
|
||||||
}
|
}
|
||||||
public final Card getChosenCard() {
|
public final Card getChosenCard() {
|
||||||
return getChosenCards().getFirst();
|
return getChosenCards().getFirst();
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ public class CardState extends GameObject implements IHasSVars, ITranslatable {
|
|||||||
private KeywordCollection cachedKeywords = new KeywordCollection();
|
private KeywordCollection cachedKeywords = new KeywordCollection();
|
||||||
|
|
||||||
private CardRarity rarity = CardRarity.Unknown;
|
private CardRarity rarity = CardRarity.Unknown;
|
||||||
private String setCode = CardEdition.UNKNOWN.getCode();
|
private String setCode = CardEdition.UNKNOWN_CODE;
|
||||||
|
|
||||||
private final CardStateView view;
|
private final CardStateView view;
|
||||||
private final Card card;
|
private final Card card;
|
||||||
|
|||||||
@@ -433,11 +433,11 @@ public class CardView extends GameEntityView {
|
|||||||
void updateChosenColors(Card c) {
|
void updateChosenColors(Card c) {
|
||||||
set(TrackableProperty.ChosenColors, c.getChosenColors());
|
set(TrackableProperty.ChosenColors, c.getChosenColors());
|
||||||
}
|
}
|
||||||
public Set<String> getChosenColorID() {
|
public ColorSet getMarkedColors() {
|
||||||
return get(TrackableProperty.ChosenColorID);
|
return get(TrackableProperty.MarkedColors);
|
||||||
}
|
}
|
||||||
void updateChosenColorID(Card c) {
|
void updateMarkedColors(Card c) {
|
||||||
set(TrackableProperty.ChosenColorID, c.getChosenColorID());
|
set(TrackableProperty.MarkedColors, c.getMarkedColors());
|
||||||
}
|
}
|
||||||
public FCollectionView<CardView> getMergedCardsCollection() {
|
public FCollectionView<CardView> getMergedCardsCollection() {
|
||||||
return get(TrackableProperty.MergedCardsCollection);
|
return get(TrackableProperty.MergedCardsCollection);
|
||||||
|
|||||||
@@ -703,10 +703,10 @@ public class AbilityManaPart implements java.io.Serializable {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
Card card = sa.getHostCard();
|
Card card = sa.getHostCard();
|
||||||
if (card != null && card.hasChosenColorSpire()) {
|
if (card != null && card.hasMarkedColor()) {
|
||||||
StringBuilder values = new StringBuilder();
|
StringBuilder values = new StringBuilder();
|
||||||
for (String s : card.getChosenColorID()) {
|
for (byte c : card.getMarkedColors()) {
|
||||||
values.append(MagicColor.toShortString(MagicColor.fromName(s))).append(" ");
|
values.append(MagicColor.toShortString(c)).append(" ");
|
||||||
}
|
}
|
||||||
return values.toString();
|
return values.toString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,6 @@ public enum TrackableProperty {
|
|||||||
ChosenType2(TrackableTypes.StringType),
|
ChosenType2(TrackableTypes.StringType),
|
||||||
NotedTypes(TrackableTypes.StringListType),
|
NotedTypes(TrackableTypes.StringListType),
|
||||||
ChosenColors(TrackableTypes.StringListType),
|
ChosenColors(TrackableTypes.StringListType),
|
||||||
ChosenColorID(TrackableTypes.StringSetType),
|
|
||||||
ChosenCards(TrackableTypes.CardViewCollectionType),
|
ChosenCards(TrackableTypes.CardViewCollectionType),
|
||||||
ChosenNumber(TrackableTypes.StringType),
|
ChosenNumber(TrackableTypes.StringType),
|
||||||
StoredRolls(TrackableTypes.StringListType),
|
StoredRolls(TrackableTypes.StringListType),
|
||||||
@@ -102,6 +101,7 @@ public enum TrackableProperty {
|
|||||||
NeedsTransformAnimation(TrackableTypes.BooleanType, FreezeMode.IgnoresFreeze),
|
NeedsTransformAnimation(TrackableTypes.BooleanType, FreezeMode.IgnoresFreeze),
|
||||||
NeedsUntapAnimation(TrackableTypes.BooleanType, FreezeMode.IgnoresFreeze),
|
NeedsUntapAnimation(TrackableTypes.BooleanType, FreezeMode.IgnoresFreeze),
|
||||||
NeedsTapAnimation(TrackableTypes.BooleanType, FreezeMode.IgnoresFreeze),
|
NeedsTapAnimation(TrackableTypes.BooleanType, FreezeMode.IgnoresFreeze),
|
||||||
|
MarkedColors(TrackableTypes.ColorSetType),
|
||||||
|
|
||||||
ImprintedCards(TrackableTypes.CardViewCollectionType),
|
ImprintedCards(TrackableTypes.CardViewCollectionType),
|
||||||
ExiledCards(TrackableTypes.CardViewCollectionType),
|
ExiledCards(TrackableTypes.CardViewCollectionType),
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ public class GuiDesktop implements IGuiBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices, final T selected, final Function<T, String> display) {
|
public <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices, final Collection<T> selected, final Function<T, String> display) {
|
||||||
/*if ((choices != null && !choices.isEmpty() && choices.iterator().next() instanceof GameObject) || selected instanceof GameObject) {
|
/*if ((choices != null && !choices.isEmpty() && choices.iterator().next() instanceof GameObject) || selected instanceof GameObject) {
|
||||||
System.err.println("Warning: GameObject passed to GUI! Printing stack trace.");
|
System.err.println("Warning: GameObject passed to GUI! Printing stack trace.");
|
||||||
Thread.dumpStack();
|
Thread.dumpStack();
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ public class CardDetailPanel extends SkinnedPanel {
|
|||||||
set = state.getSetCode();
|
set = state.getSetCode();
|
||||||
rarity = state.getRarity();
|
rarity = state.getRarity();
|
||||||
} else {
|
} else {
|
||||||
set = CardEdition.UNKNOWN.getCode();
|
set = CardEdition.UNKNOWN_CODE;
|
||||||
rarity = CardRarity.Unknown;
|
rarity = CardRarity.Unknown;
|
||||||
}
|
}
|
||||||
setInfoLabel.setText(set);
|
setInfoLabel.setText(set);
|
||||||
|
|||||||
@@ -134,10 +134,10 @@ public class GuiChoose {
|
|||||||
return getChoices(message, min, max, choices, null, null);
|
return getChoices(message, min, max, choices, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices, final T selected, final Function<T, String> display) {
|
public static <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices, final Collection<T> selected, final Function<T, String> display) {
|
||||||
return getChoices(message, min, max, choices, selected, display, null);
|
return getChoices(message, min, max, choices, selected, display, null);
|
||||||
}
|
}
|
||||||
public static <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices, final T selected, final Function<T, String> display, final CMatchUI matchUI) {
|
public static <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices, final Collection<T> selected, final Function<T, String> display, final CMatchUI matchUI) {
|
||||||
if (choices == null || choices.isEmpty()) {
|
if (choices == null || choices.isEmpty()) {
|
||||||
if (min == 0) {
|
if (min == 0) {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
|
|||||||
@@ -152,16 +152,13 @@ public class ListChooser<T> {
|
|||||||
|
|
||||||
/** @return boolean */
|
/** @return boolean */
|
||||||
public boolean show() {
|
public boolean show() {
|
||||||
return show(list.get(0));
|
return show(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows the dialog and returns after the dialog was closed.
|
* Shows the dialog and returns after the dialog was closed.
|
||||||
*
|
|
||||||
* @param index0 index to select when shown
|
|
||||||
* @return a boolean.
|
|
||||||
*/
|
*/
|
||||||
public boolean show(final T item) {
|
public boolean show(final Collection<T> item) {
|
||||||
if (this.called) {
|
if (this.called) {
|
||||||
throw new IllegalStateException("Already shown");
|
throw new IllegalStateException("Already shown");
|
||||||
}
|
}
|
||||||
@@ -169,8 +166,12 @@ public class ListChooser<T> {
|
|||||||
do {
|
do {
|
||||||
//invoke later so selected item not set until dialog open
|
//invoke later so selected item not set until dialog open
|
||||||
SwingUtilities.invokeLater(() -> {
|
SwingUtilities.invokeLater(() -> {
|
||||||
if (list.contains(item)) {
|
if (item != null) {
|
||||||
lstChoices.setSelectedValue(item, true);
|
int[] indices = item.stream()
|
||||||
|
.mapToInt(list::indexOf)
|
||||||
|
.filter(i -> i >= 0)
|
||||||
|
.toArray();
|
||||||
|
lstChoices.setSelectedIndices(indices);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
lstChoices.setSelectedIndex(0);
|
lstChoices.setSelectedIndex(0);
|
||||||
|
|||||||
@@ -20,16 +20,15 @@ package forge.screens.deckeditor.controllers;
|
|||||||
import java.awt.Toolkit;
|
import java.awt.Toolkit;
|
||||||
import java.awt.event.InputEvent;
|
import java.awt.event.InputEvent;
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import javax.swing.JMenu;
|
import javax.swing.JMenu;
|
||||||
import javax.swing.JPopupMenu;
|
import javax.swing.JPopupMenu;
|
||||||
import javax.swing.KeyStroke;
|
import javax.swing.KeyStroke;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
|
|
||||||
|
import forge.card.ColorSet;
|
||||||
import forge.card.MagicColor;
|
import forge.card.MagicColor;
|
||||||
import forge.deck.CardPool;
|
import forge.deck.CardPool;
|
||||||
import forge.deck.Deck;
|
import forge.deck.Deck;
|
||||||
@@ -582,9 +581,9 @@ public abstract class ACEditorBase<TItem extends InventoryItem, TModel extends D
|
|||||||
int val;
|
int val;
|
||||||
if ((val = existingCard.getRules().getSetColorID()) > 0) {
|
if ((val = existingCard.getRules().getSetColorID()) > 0) {
|
||||||
GuiUtils.addMenuItem(menu, label, null, () -> {
|
GuiUtils.addMenuItem(menu, label, null, () -> {
|
||||||
Set<String> colors = new HashSet<>(GuiChoose.getChoices(localizer.getMessage("lblChooseNColors", Lang.getNumeral(val)), val, val, MagicColor.Constant.ONLY_COLORS));
|
List<String> colors = GuiChoose.getChoices(localizer.getMessage("lblChooseNColors", Lang.getNumeral(val)), val, val, MagicColor.Constant.ONLY_COLORS);
|
||||||
// make an updated version
|
// make an updated version
|
||||||
PaperCard updated = existingCard.getColorIDVersion(colors);
|
PaperCard updated = existingCard.copyWithMarkedColors(ColorSet.fromNames(colors));
|
||||||
// remove *quantity* instances of existing card
|
// remove *quantity* instances of existing card
|
||||||
CDeckEditorUI.SINGLETON_INSTANCE.removeSelectedCards(false, 1);
|
CDeckEditorUI.SINGLETON_INSTANCE.removeSelectedCards(false, 1);
|
||||||
// add *quantity* into the deck and set them as selected
|
// add *quantity* into the deck and set them as selected
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import java.awt.image.BufferedImage;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
@@ -1072,7 +1071,7 @@ public final class CMatchUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> List<T> getChoices(final String message, final int min, final int max, final List<T> choices, final T selected, final Function<T, String> display) {
|
public <T> List<T> getChoices(final String message, final int min, final int max, final List<T> choices, final List<T> selected, final Function<T, String> display) {
|
||||||
/*if ((choices != null && !choices.isEmpty() && choices.iterator().next() instanceof GameObject) || selected instanceof GameObject) {
|
/*if ((choices != null && !choices.isEmpty() && choices.iterator().next() instanceof GameObject) || selected instanceof GameObject) {
|
||||||
System.err.println("Warning: GameObject passed to GUI! Printing stack trace.");
|
System.err.println("Warning: GameObject passed to GUI! Printing stack trace.");
|
||||||
Thread.dumpStack();
|
Thread.dumpStack();
|
||||||
|
|||||||
@@ -277,21 +277,6 @@ public class CardDbCardMockTestCase extends CardMockTestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetCardByNameSetArtIndexAndCollectorNumber() {
|
|
||||||
// MultiArt Card
|
|
||||||
PaperCard card;
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
int artIndex = i + 1;
|
|
||||||
card = this.cardDb.getCard(cardNameHymnToTourach, editionHymnToTourach, artIndex,
|
|
||||||
collectorNumbersHymnToTourach[i]);
|
|
||||||
assertEquals(card.getName(), cardNameHymnToTourach);
|
|
||||||
assertEquals(card.getEdition(), editionHymnToTourach);
|
|
||||||
assertEquals(card.getCollectorNumber(), collectorNumbersHymnToTourach[i]);
|
|
||||||
assertEquals(card.getArtIndex(), artIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNullIsReturnedWithWrongInfo() {
|
public void testNullIsReturnedWithWrongInfo() {
|
||||||
String wrongEditionCode = "M11";
|
String wrongEditionCode = "M11";
|
||||||
@@ -307,11 +292,6 @@ public class CardDbCardMockTestCase extends CardMockTestCase {
|
|||||||
// Wrong collector number
|
// Wrong collector number
|
||||||
card = this.cardDb.getCard(cardNameShivanDragon, editionShivanDragon, "wrongCN");
|
card = this.cardDb.getCard(cardNameShivanDragon, editionShivanDragon, "wrongCN");
|
||||||
assertNull(card);
|
assertNull(card);
|
||||||
// wrong artIndex or collector number in getCard Full Info
|
|
||||||
card = this.cardDb.getCard(cardNameShivanDragon, editionShivanDragon, 3, collNrShivanDragon);
|
|
||||||
assertNull(card);
|
|
||||||
card = this.cardDb.getCard(cardNameShivanDragon, editionShivanDragon, 1, "wrongCN");
|
|
||||||
assertNull(card);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -2105,7 +2085,7 @@ public class CardDbCardMockTestCase extends CardMockTestCase {
|
|||||||
public void testGetCardFromUnknownSet() {
|
public void testGetCardFromUnknownSet() {
|
||||||
String unknownCardName = "Unknown Card Name";
|
String unknownCardName = "Unknown Card Name";
|
||||||
PaperCard unknownCard = new PaperCard(CardRules.getUnsupportedCardNamed(unknownCardName),
|
PaperCard unknownCard = new PaperCard(CardRules.getUnsupportedCardNamed(unknownCardName),
|
||||||
CardEdition.UNKNOWN.getCode(), CardRarity.Unknown);
|
CardEdition.UNKNOWN_CODE, CardRarity.Unknown);
|
||||||
this.cardDb.addCard(unknownCard);
|
this.cardDb.addCard(unknownCard);
|
||||||
assertTrue(this.cardDb.getAllCards().contains(unknownCard));
|
assertTrue(this.cardDb.getAllCards().contains(unknownCard));
|
||||||
assertNotNull(this.cardDb.getAllCards(unknownCardName));
|
assertNotNull(this.cardDb.getAllCards(unknownCardName));
|
||||||
@@ -2114,7 +2094,7 @@ public class CardDbCardMockTestCase extends CardMockTestCase {
|
|||||||
PaperCard retrievedPaperCard = this.cardDb.getCard(unknownCardName);
|
PaperCard retrievedPaperCard = this.cardDb.getCard(unknownCardName);
|
||||||
assertNotNull(retrievedPaperCard);
|
assertNotNull(retrievedPaperCard);
|
||||||
assertEquals(retrievedPaperCard.getName(), unknownCardName);
|
assertEquals(retrievedPaperCard.getName(), unknownCardName);
|
||||||
assertEquals(retrievedPaperCard.getEdition(), CardEdition.UNKNOWN.getCode());
|
assertEquals(retrievedPaperCard.getEdition(), CardEdition.UNKNOWN_CODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ public class GuiMobile implements IGuiBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices, final T selected, final Function<T, String> display) {
|
public <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices, final Collection<T> selected, final Function<T, String> display) {
|
||||||
return new WaitCallback<List<T>>() {
|
return new WaitCallback<List<T>>() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|||||||
@@ -120,7 +120,6 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
statistic.clear();
|
statistic.clear();
|
||||||
newCards.clear();
|
newCards.clear();
|
||||||
autoSellCards.clear();
|
autoSellCards.clear();
|
||||||
noSellCards.clear();
|
|
||||||
AdventureEventController.clear();
|
AdventureEventController.clear();
|
||||||
AdventureQuestController.clear();
|
AdventureQuestController.clear();
|
||||||
}
|
}
|
||||||
@@ -134,7 +133,6 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
|
|
||||||
private final ItemPool<PaperCard> newCards = new ItemPool<>(PaperCard.class);
|
private final ItemPool<PaperCard> newCards = new ItemPool<>(PaperCard.class);
|
||||||
public final ItemPool<PaperCard> autoSellCards = new ItemPool<>(PaperCard.class);
|
public final ItemPool<PaperCard> autoSellCards = new ItemPool<>(PaperCard.class);
|
||||||
public final ItemPool<PaperCard> noSellCards = new ItemPool<>(PaperCard.class);
|
|
||||||
|
|
||||||
public void create(String n, Deck startingDeck, boolean male, int race, int avatar, boolean isFantasy, boolean isUsingCustomDeck, DifficultyData difficultyData) {
|
public void create(String n, Deck startingDeck, boolean male, int race, int avatar, boolean isFantasy, boolean isUsingCustomDeck, DifficultyData difficultyData) {
|
||||||
clear();
|
clear();
|
||||||
@@ -471,10 +469,43 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (data.containsKey("noSellCards")) {
|
if (data.containsKey("noSellCards")) {
|
||||||
|
//Legacy list of unsellable cards. Now done via CardRequest flags. Convert the corresponding cards.
|
||||||
PaperCard[] items = (PaperCard[]) data.readObject("noSellCards");
|
PaperCard[] items = (PaperCard[]) data.readObject("noSellCards");
|
||||||
for (PaperCard item : items) {
|
CardPool noSellPool = new CardPool();
|
||||||
if (item != null)
|
noSellPool.addAllFlat(List.of(items));
|
||||||
noSellCards.add(item.getNoSellVersion());
|
for (Map.Entry<PaperCard, Integer> noSellEntry : noSellPool) {
|
||||||
|
PaperCard item = noSellEntry.getKey();
|
||||||
|
if (item == null)
|
||||||
|
continue;
|
||||||
|
int totalCopies = cards.count(item);
|
||||||
|
int noSellCopies = Math.min(noSellEntry.getValue(), totalCopies);
|
||||||
|
if (!cards.remove(item, noSellCopies)) {
|
||||||
|
System.err.printf("Failed to update noSellValue flag - %s%n", item);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int remainingSellableCopies = totalCopies - noSellCopies;
|
||||||
|
|
||||||
|
PaperCard noSellVersion = item.getNoSellVersion();
|
||||||
|
cards.add(noSellVersion, noSellCopies);
|
||||||
|
|
||||||
|
System.out.printf("Converted legacy noSellCards item - %s (%d / %d copies)%n", item, noSellCopies, totalCopies);
|
||||||
|
|
||||||
|
//Also go through their decks and update cards there.
|
||||||
|
for (Deck deck : decks) {
|
||||||
|
int inUse = 0;
|
||||||
|
for (Map.Entry<DeckSection, CardPool> section : deck) {
|
||||||
|
CardPool pool = section.getValue();
|
||||||
|
inUse += pool.count(item);
|
||||||
|
if(inUse > remainingSellableCopies) {
|
||||||
|
int toConvert = inUse - remainingSellableCopies;
|
||||||
|
pool.remove(item, toConvert);
|
||||||
|
pool.add(noSellVersion, toConvert);
|
||||||
|
System.out.printf("- Converted %d copies in deck - %s/%s%n", toConvert, deck.getName(), section.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (data.containsKey("autoSellCards")) {
|
if (data.containsKey("autoSellCards")) {
|
||||||
@@ -582,7 +613,6 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
|
|
||||||
data.storeObject("newCards", newCards.toFlatList().toArray(new PaperCard[0]));
|
data.storeObject("newCards", newCards.toFlatList().toArray(new PaperCard[0]));
|
||||||
data.storeObject("autoSellCards", autoSellCards.toFlatList().toArray(new PaperCard[0]));
|
data.storeObject("autoSellCards", autoSellCards.toFlatList().toArray(new PaperCard[0]));
|
||||||
data.storeObject("noSellCards", noSellCards.toFlatList().toArray(new PaperCard[0]));
|
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
@@ -636,11 +666,6 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
if (reward.isAutoSell()) {
|
if (reward.isAutoSell()) {
|
||||||
autoSellCards.add(reward.getCard());
|
autoSellCards.add(reward.getCard());
|
||||||
refreshEditor();
|
refreshEditor();
|
||||||
} else if (reward.isNoSell()) {
|
|
||||||
if (reward.getCard() != null) {
|
|
||||||
noSellCards.add(reward.getCard().getNoSellVersion());
|
|
||||||
refreshEditor();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Gold:
|
case Gold:
|
||||||
@@ -908,8 +933,7 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int cardSellPrice(PaperCard card) {
|
public int cardSellPrice(PaperCard card) {
|
||||||
int valuable = cards.count(card) - noSellCards.count(card);
|
if (card.hasNoSellValue()) {
|
||||||
if (valuable == 0) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -920,23 +944,13 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int sellCard(PaperCard card, Integer result, boolean addGold) {
|
public int sellCard(PaperCard card, Integer result, boolean addGold) {
|
||||||
// When selling cards, always try to sell cards worth something before selling cards that aren't worth anything
|
if (result == null || result < 1)
|
||||||
if (result == null || result < 1) return 0;
|
return 0;
|
||||||
|
|
||||||
float earned = 0;
|
int amountToSell = Math.min(result, cards.count(card));
|
||||||
|
if(!cards.remove(card, amountToSell))
|
||||||
int valuableCount = cards.count(card) - noSellCards.count(card);
|
return 0; //Failed to sell?
|
||||||
int noValueToSell = result - valuableCount;
|
float earned = cardSellPrice(card) * amountToSell;
|
||||||
int amountValuableToSell = Math.min(result, valuableCount);
|
|
||||||
|
|
||||||
if (amountValuableToSell > 0) {
|
|
||||||
earned += cardSellPrice(card) * amountValuableToSell;
|
|
||||||
cards.remove(card, amountValuableToSell);
|
|
||||||
}
|
|
||||||
if (noValueToSell > 0) {
|
|
||||||
cards.remove(card, noValueToSell);
|
|
||||||
noSellCards.remove(card, noValueToSell);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addGold) {
|
if (addGold) {
|
||||||
addGold((int) earned);
|
addGold((int) earned);
|
||||||
@@ -1198,10 +1212,6 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
return autoSellCards;
|
return autoSellCards;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ItemPool<PaperCard> getNoSellCards() {
|
|
||||||
return noSellCards;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ItemPool<PaperCard> getSellableCards() {
|
public ItemPool<PaperCard> getSellableCards() {
|
||||||
ItemPool<PaperCard> sellableCards = new ItemPool<>(PaperCard.class);
|
ItemPool<PaperCard> sellableCards = new ItemPool<>(PaperCard.class);
|
||||||
sellableCards.addAllFlat(cards.toFlatList());
|
sellableCards.addAllFlat(cards.toFlatList());
|
||||||
@@ -1236,7 +1246,6 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
collectionCards.addAll(cards);
|
collectionCards.addAll(cards);
|
||||||
if (!allCards) {
|
if (!allCards) {
|
||||||
collectionCards.removeAll(autoSellCards);
|
collectionCards.removeAll(autoSellCards);
|
||||||
collectionCards.removeAll(noSellCards);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return collectionCards;
|
return collectionCards;
|
||||||
|
|||||||
@@ -211,14 +211,13 @@ public class AdventureDeckEditor extends TabPageScreen<AdventureDeckEditor> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
int noSellCount = Current.player().noSellCards.count(card);
|
|
||||||
int autoSellCount = Current.player().autoSellCards.count(card);
|
int autoSellCount = Current.player().autoSellCards.count(card);
|
||||||
int sellableCount = Current.player().getSellableCards().count(card);
|
int sellableCount = Current.player().getSellableCards().count(card);
|
||||||
|
|
||||||
if (noSellCount > 0) {
|
if (card.hasNoSellValue()) {
|
||||||
FMenuItem unsellableCount = new FMenuItem(Forge.getLocalizer().getMessage("lblUnsellableCount", noSellCount), null, null);
|
FMenuItem unsellableIndicator = new FMenuItem(Forge.getLocalizer().getMessage("lblUnsellable"), null, null);
|
||||||
unsellableCount.setEnabled(false);
|
unsellableIndicator.setEnabled(false);
|
||||||
menu.addItem(unsellableCount);
|
menu.addItem(unsellableIndicator);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sellableCount > 0) {
|
if (sellableCount > 0) {
|
||||||
@@ -248,12 +247,13 @@ public class AdventureDeckEditor extends TabPageScreen<AdventureDeckEditor> {
|
|||||||
if (showCollectionCards) {
|
if (showCollectionCards) {
|
||||||
collectionPool.addAllFlat(AdventurePlayer.current().getCollectionCards(false).toFlatList());
|
collectionPool.addAllFlat(AdventurePlayer.current().getCollectionCards(false).toFlatList());
|
||||||
}
|
}
|
||||||
if (showNoSellCards) {
|
else if(showNoSellCards) {
|
||||||
collectionPool.addAllFlat(AdventurePlayer.current().getNoSellCards().toFlatList());
|
collectionPool.addAll(AdventurePlayer.current().getCollectionCards(false).getFilteredPool(PaperCard::hasNoSellValue));
|
||||||
collectionPool.removeAllFlat(cardsInUse.toFlatList());
|
}
|
||||||
} else {
|
|
||||||
cardsInUse.removeAllFlat(AdventurePlayer.current().getNoSellCards().toFlatList());
|
collectionPool.removeAllFlat(cardsInUse.toFlatList());
|
||||||
collectionPool.removeAllFlat(cardsInUse.toFlatList());
|
if (!showNoSellCards) {
|
||||||
|
collectionPool.removeIf(PaperCard::hasNoSellValue);
|
||||||
}
|
}
|
||||||
if (showAutoSellCards) {
|
if (showAutoSellCards) {
|
||||||
collectionPool.addAllFlat(AdventurePlayer.current().getAutoSellCards().toFlatList());
|
collectionPool.addAllFlat(AdventurePlayer.current().getAutoSellCards().toFlatList());
|
||||||
@@ -1120,12 +1120,13 @@ public class AdventureDeckEditor extends TabPageScreen<AdventureDeckEditor> {
|
|||||||
if (showCollectionCards) {
|
if (showCollectionCards) {
|
||||||
adventurePool.addAll(AdventurePlayer.current().getCollectionCards(false));
|
adventurePool.addAll(AdventurePlayer.current().getCollectionCards(false));
|
||||||
}
|
}
|
||||||
if (showNoSellCards) {
|
else if(showNoSellCards) {
|
||||||
adventurePool.addAll(AdventurePlayer.current().getNoSellCards());
|
adventurePool.addAll(AdventurePlayer.current().getCollectionCards(false).getFilteredPool(PaperCard::hasNoSellValue));
|
||||||
adventurePool.removeAll(cardsInUse);
|
}
|
||||||
} else {
|
|
||||||
cardsInUse.removeAll(AdventurePlayer.current().getNoSellCards());
|
adventurePool.removeAll(cardsInUse);
|
||||||
adventurePool.removeAll(cardsInUse);
|
if (!showNoSellCards) {
|
||||||
|
adventurePool.removeIf(PaperCard::hasNoSellValue);
|
||||||
}
|
}
|
||||||
if (showAutoSellCards) {
|
if (showAutoSellCards) {
|
||||||
adventurePool.addAll(AdventurePlayer.current().getAutoSellCards());
|
adventurePool.addAll(AdventurePlayer.current().getAutoSellCards());
|
||||||
|
|||||||
@@ -223,7 +223,6 @@ public class ConsoleCommandInterpreter {
|
|||||||
PaperCard card = StaticData.instance().getCommonCards().getCard(s[0]);
|
PaperCard card = StaticData.instance().getCommonCards().getCard(s[0]);
|
||||||
if (card == null) return "Cannot find card: " + s[0];
|
if (card == null) return "Cannot find card: " + s[0];
|
||||||
Current.player().addCard(card.getNoSellVersion());
|
Current.player().addCard(card.getNoSellVersion());
|
||||||
Current.player().noSellCards.add(card.getNoSellVersion());
|
|
||||||
return "Added card: " + s[0];
|
return "Added card: " + s[0];
|
||||||
});
|
});
|
||||||
registerCommand(new String[]{"give", "item"}, s -> {
|
registerCommand(new String[]{"give", "item"}, s -> {
|
||||||
|
|||||||
@@ -356,7 +356,7 @@ public class Config {
|
|||||||
final List<String> lines = FileUtil.readAllLines(new InputStreamReader(fileInputStream, Charset.forName(CardStorageReader.DEFAULT_CHARSET_NAME)), true);
|
final List<String> lines = FileUtil.readAllLines(new InputStreamReader(fileInputStream, Charset.forName(CardStorageReader.DEFAULT_CHARSET_NAME)), true);
|
||||||
CardRules rules = rulesReader.readCard(lines, com.google.common.io.Files.getNameWithoutExtension(cardFile.getName()));
|
CardRules rules = rulesReader.readCard(lines, com.google.common.io.Files.getNameWithoutExtension(cardFile.getName()));
|
||||||
rules.setCustom();
|
rules.setCustom();
|
||||||
PaperCard card = new PaperCard(rules, CardEdition.UNKNOWN.getCode(), CardRarity.Special) {
|
PaperCard card = new PaperCard(rules, CardEdition.UNKNOWN_CODE, CardRarity.Special) {
|
||||||
@Override
|
@Override
|
||||||
public String getImageKey(boolean altState) {
|
public String getImageKey(boolean altState) {
|
||||||
return ImageKeys.ADVENTURECARD_PREFIX + getName();
|
return ImageKeys.ADVENTURECARD_PREFIX + getName();
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ public class Reward {
|
|||||||
this.card = card;
|
this.card = card;
|
||||||
count = 0;
|
count = 0;
|
||||||
this.isNoSell = isNoSell;
|
this.isNoSell = isNoSell;
|
||||||
|
if(isNoSell)
|
||||||
|
this.card = card.getNoSellVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Reward(Type type, int count) {
|
public Reward(Type type, int count) {
|
||||||
@@ -60,6 +62,10 @@ public class Reward {
|
|||||||
this.deck = deck;
|
this.deck = deck;
|
||||||
count = 0;
|
count = 0;
|
||||||
this.isNoSell = isNoSell;
|
this.isNoSell = isNoSell;
|
||||||
|
if(isNoSell)
|
||||||
|
deck.getTags().add("noSell");
|
||||||
|
//Could go through the deck and replace everything in it with the noSellValue version but the tag should
|
||||||
|
//handle that later.
|
||||||
}
|
}
|
||||||
|
|
||||||
public PaperCard getCard() {
|
public PaperCard getCard() {
|
||||||
|
|||||||
@@ -1143,7 +1143,7 @@ public class CardImageRenderer {
|
|||||||
String set = state.getSetCode();
|
String set = state.getSetCode();
|
||||||
CardRarity rarity = state.getRarity();
|
CardRarity rarity = state.getRarity();
|
||||||
if (!canShow) {
|
if (!canShow) {
|
||||||
set = CardEdition.UNKNOWN.getCode();
|
set = CardEdition.UNKNOWN_CODE;
|
||||||
rarity = CardRarity.Unknown;
|
rarity = CardRarity.Unknown;
|
||||||
}
|
}
|
||||||
if (!StringUtils.isEmpty(set)) {
|
if (!StringUtils.isEmpty(set)) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import forge.Forge.KeyInputAdapter;
|
|||||||
import forge.Graphics;
|
import forge.Graphics;
|
||||||
import forge.assets.*;
|
import forge.assets.*;
|
||||||
import forge.card.CardEdition;
|
import forge.card.CardEdition;
|
||||||
|
import forge.card.ColorSet;
|
||||||
import forge.card.MagicColor;
|
import forge.card.MagicColor;
|
||||||
import forge.deck.io.DeckPreferences;
|
import forge.deck.io.DeckPreferences;
|
||||||
import forge.gamemodes.limited.BoosterDraft;
|
import forge.gamemodes.limited.BoosterDraft;
|
||||||
@@ -1767,8 +1768,7 @@ public class FDeckEditor extends TabPageScreen<FDeckEditor> {
|
|||||||
CardManagerPage cardSourceSection;
|
CardManagerPage cardSourceSection;
|
||||||
DeckSection destination = DeckSection.matchingSection(card);
|
DeckSection destination = DeckSection.matchingSection(card);
|
||||||
final DeckSectionPage destinationPage = parentScreen.getPageForSection(destination);
|
final DeckSectionPage destinationPage = parentScreen.getPageForSection(destination);
|
||||||
// val for colorID setup
|
int markedColorCount = card.getRules().getSetColorID();
|
||||||
int val;
|
|
||||||
switch (deckSection) {
|
switch (deckSection) {
|
||||||
default:
|
default:
|
||||||
case Main:
|
case Main:
|
||||||
@@ -1811,14 +1811,18 @@ public class FDeckEditor extends TabPageScreen<FDeckEditor> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
addCommanderItems(menu, card);
|
addCommanderItems(menu, card);
|
||||||
if ((val = card.getRules().getSetColorID()) > 0) {
|
if (markedColorCount > 0) {
|
||||||
menu.addItem(new FMenuItem(Forge.getLocalizer().getMessage("lblColorIdentity"), Forge.hdbuttons ? FSkinImage.HDPREFERENCE : FSkinImage.SETTINGS, e -> {
|
menu.addItem(new FMenuItem(Forge.getLocalizer().getMessage("lblColorIdentity"), Forge.hdbuttons ? FSkinImage.HDPREFERENCE : FSkinImage.SETTINGS, e -> {
|
||||||
//sort options so current option is on top and selected by default
|
Set<String> currentColors;
|
||||||
Set<String> colorChoices = new HashSet<>(MagicColor.Constant.ONLY_COLORS);
|
if(card.getMarkedColors() != null)
|
||||||
GuiChoose.getChoices(Forge.getLocalizer().getMessage("lblChooseAColor", Lang.getNumeral(val)), val, val, colorChoices, new Callback<>() {
|
currentColors = card.getMarkedColors().stream().map(MagicColor.Color::getName).collect(Collectors.toSet());
|
||||||
|
else
|
||||||
|
currentColors = null;
|
||||||
|
String prompt = Forge.getLocalizer().getMessage("lblChooseAColor", Lang.getNumeral(markedColorCount));
|
||||||
|
GuiChoose.getChoices(prompt, markedColorCount, markedColorCount, MagicColor.Constant.ONLY_COLORS, currentColors, null, new Callback<>() {
|
||||||
@Override
|
@Override
|
||||||
public void run(List<String> result) {
|
public void run(List<String> result) {
|
||||||
addCard(card.getColorIDVersion(new HashSet<>(result)));
|
addCard(card.copyWithMarkedColors(ColorSet.fromNames(result)));
|
||||||
removeCard(card);
|
removeCard(card);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1863,14 +1867,18 @@ public class FDeckEditor extends TabPageScreen<FDeckEditor> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
addCommanderItems(menu, card);
|
addCommanderItems(menu, card);
|
||||||
if ((val = card.getRules().getSetColorID()) > 0) {
|
if (markedColorCount > 0) {
|
||||||
menu.addItem(new FMenuItem(Forge.getLocalizer().getMessage("lblColorIdentity"), Forge.hdbuttons ? FSkinImage.HDPREFERENCE : FSkinImage.SETTINGS, e -> {
|
menu.addItem(new FMenuItem(Forge.getLocalizer().getMessage("lblColorIdentity"), Forge.hdbuttons ? FSkinImage.HDPREFERENCE : FSkinImage.SETTINGS, e -> {
|
||||||
//sort options so current option is on top and selected by default
|
Set<String> currentColors;
|
||||||
Set<String> colorChoices = new HashSet<>(MagicColor.Constant.ONLY_COLORS);
|
if(card.getMarkedColors() != null)
|
||||||
GuiChoose.getChoices(Forge.getLocalizer().getMessage("lblChooseAColor", Lang.getNumeral(val)), val, val, colorChoices, new Callback<>() {
|
currentColors = card.getMarkedColors().stream().map(MagicColor.Color::getName).collect(Collectors.toSet());
|
||||||
|
else
|
||||||
|
currentColors = null;
|
||||||
|
String prompt = Forge.getLocalizer().getMessage("lblChooseAColor", Lang.getNumeral(markedColorCount));
|
||||||
|
GuiChoose.getChoices(prompt, markedColorCount, markedColorCount, MagicColor.Constant.ONLY_COLORS, currentColors, null, new Callback<>() {
|
||||||
@Override
|
@Override
|
||||||
public void run(List<String> result) {
|
public void run(List<String> result) {
|
||||||
addCard(card.getColorIDVersion(new HashSet<>(result)));
|
addCard(card.copyWithMarkedColors(ColorSet.fromNames(result)));
|
||||||
removeCard(card);
|
removeCard(card);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import forge.assets.*;
|
|||||||
import forge.assets.FSkinColor.Colors;
|
import forge.assets.FSkinColor.Colors;
|
||||||
import forge.card.*;
|
import forge.card.*;
|
||||||
import forge.card.CardRenderer.CardStackPosition;
|
import forge.card.CardRenderer.CardStackPosition;
|
||||||
|
import forge.card.mana.ManaCostShard;
|
||||||
import forge.deck.*;
|
import forge.deck.*;
|
||||||
import forge.deck.io.DeckPreferences;
|
import forge.deck.io.DeckPreferences;
|
||||||
import forge.game.card.CardView;
|
import forge.game.card.CardView;
|
||||||
@@ -34,11 +35,8 @@ import forge.util.ImageUtil;
|
|||||||
import forge.util.TextUtil;
|
import forge.util.TextUtil;
|
||||||
import forge.util.Utils;
|
import forge.util.Utils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.TreeMap;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
@@ -980,7 +978,7 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
|
|||||||
private boolean selected, deckSelectMode, showRanking;
|
private boolean selected, deckSelectMode, showRanking;
|
||||||
private final float IMAGE_SIZE = CardRenderer.MANA_SYMBOL_SIZE;
|
private final float IMAGE_SIZE = CardRenderer.MANA_SYMBOL_SIZE;
|
||||||
private DeckProxy deckProxy = null;
|
private DeckProxy deckProxy = null;
|
||||||
private String colorID = null;
|
private String markedColors = null;
|
||||||
private FImageComplex deckCover = null;
|
private FImageComplex deckCover = null;
|
||||||
private Texture dpImg = null;
|
private Texture dpImg = null;
|
||||||
//private TextureRegion tr;
|
//private TextureRegion tr;
|
||||||
@@ -1007,8 +1005,10 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
|
|||||||
draftRankImage = FSkinImage.DRAFTRANK_C;
|
draftRankImage = FSkinImage.DRAFTRANK_C;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (((PaperCard) item).getColorID() != null) {
|
if (((PaperCard) item).getMarkedColors() != null) {
|
||||||
colorID = ((PaperCard) item).getColorID().stream().map(MagicColor::toSymbol).collect(Collectors.joining());
|
markedColors = Arrays.stream(((PaperCard) item).getMarkedColors().getOrderedShards())
|
||||||
|
.map(ManaCostShard::toString)
|
||||||
|
.collect(Collectors.joining());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1082,7 +1082,7 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
|
|||||||
cardPrice = ((ShopScene) Forge.getCurrentScene()).getCardPrice((PaperCard) item);
|
cardPrice = ((ShopScene) Forge.getCurrentScene()).getCardPrice((PaperCard) item);
|
||||||
drawCardLabel(g, "$" + cardPrice, Color.GOLD, x, y ,w ,h);
|
drawCardLabel(g, "$" + cardPrice, Color.GOLD, x, y ,w ,h);
|
||||||
} else {
|
} else {
|
||||||
if (((PaperCard) item).isNoSell() && itemManager.showNFSWatermark() && !Config.instance().getSettingData().disableNotForSale) {
|
if (((PaperCard) item).hasNoSellValue() && itemManager.showNFSWatermark() && !Config.instance().getSettingData().disableNotForSale) {
|
||||||
Texture nfs = Forge.getAssets().getTexture(getDefaultSkinFile("nfs.png"), false);
|
Texture nfs = Forge.getAssets().getTexture(getDefaultSkinFile("nfs.png"), false);
|
||||||
if (nfs != null)
|
if (nfs != null)
|
||||||
g.drawImage(nfs, x, y, w, h);
|
g.drawImage(nfs, x, y, w, h);
|
||||||
@@ -1092,8 +1092,8 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// spire colors
|
// spire colors
|
||||||
if (colorID != null && !colorID.isEmpty()) {
|
if (markedColors != null && !markedColors.isEmpty()) {
|
||||||
textRenderer.drawText(g, colorID, FSkinFont.forHeight(w / 5), Color.WHITE, x, y + h / 4, w, h, y, h, false, Align.center, true);
|
textRenderer.drawText(g, markedColors, FSkinFont.forHeight(w / 5), Color.WHITE, x, y + h / 4, w, h, y, h, false, Align.center, true);
|
||||||
}
|
}
|
||||||
} else if (item instanceof ConquestCommander) {
|
} else if (item instanceof ConquestCommander) {
|
||||||
CardRenderer.drawCard(g, ((ConquestCommander) item).getCard(), x, y, w, h, pos);
|
CardRenderer.drawCard(g, ((ConquestCommander) item).getCard(), x, y, w, h, pos);
|
||||||
|
|||||||
@@ -660,7 +660,7 @@ public class MatchController extends AbstractGuiGame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> List<T> getChoices(final String message, final int min, final int max, final List<T> choices, final T selected, final Function<T, String> display) {
|
public <T> List<T> getChoices(final String message, final int min, final int max, final List<T> choices, final List<T> selected, final Function<T, String> display) {
|
||||||
return GuiBase.getInterface().getChoices(message, min, max, choices, selected, display);
|
return GuiBase.getInterface().getChoices(message, min, max, choices, selected, display);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -355,7 +355,7 @@ public class ConquestAEtherScreen extends FScreen {
|
|||||||
caption = caption0;
|
caption = caption0;
|
||||||
options = ImmutableList.copyOf(options0);
|
options = ImmutableList.copyOf(options0);
|
||||||
setSelectedOption(options.get(0));
|
setSelectedOption(options.get(0));
|
||||||
setCommand(e -> GuiChoose.getChoices(Forge.getLocalizer().getMessage("lblSelectCaptionFilter", caption), 0, 1, options, selectedOption, null, new Callback<List<AEtherFilter>>() {
|
setCommand(e -> GuiChoose.getChoices(Forge.getLocalizer().getMessage("lblSelectCaptionFilter", caption), 0, 1, options, Set.of(selectedOption), null, new Callback<>() {
|
||||||
@Override
|
@Override
|
||||||
public void run(List<AEtherFilter> result) {
|
public void run(List<AEtherFilter> result) {
|
||||||
if (!result.isEmpty()) {
|
if (!result.isEmpty()) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package forge.toolbox;
|
|||||||
import static forge.card.CardRenderer.MANA_SYMBOL_SIZE;
|
import static forge.card.CardRenderer.MANA_SYMBOL_SIZE;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -271,6 +272,14 @@ public class FChoiceList<T> extends FList<T> implements ActivateHandler {
|
|||||||
setSelectedIndex(getIndexOf(choice));
|
setSelectedIndex(getIndexOf(choice));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSelectedItems(Collection<T> items) {
|
||||||
|
selectedIndices.clear();
|
||||||
|
items.stream().mapToInt(this::getIndexOf).filter(i -> i >= 0).forEach(selectedIndices::add);
|
||||||
|
if(!items.isEmpty())
|
||||||
|
scrollIntoView(getIndexOf(items.iterator().next()));
|
||||||
|
onSelectionChange();
|
||||||
|
}
|
||||||
|
|
||||||
protected String getChoiceText(T choice) {
|
protected String getChoiceText(T choice) {
|
||||||
return choice.toString();
|
return choice.toString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ public class GuiChoose {
|
|||||||
getChoices(message, min, max, choices, null, null, callback);
|
getChoices(message, min, max, choices, null, null, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> void getChoices(final String message, final int min, final int max, final Collection<T> choices, final T selected, final Function<T, String> display, final Callback<List<T>> callback) {
|
public static <T> void getChoices(final String message, final int min, final int max, final Collection<T> choices, final Collection<T> selected, final Function<T, String> display, final Callback<List<T>> callback) {
|
||||||
if (choices == null || choices.isEmpty()) {
|
if (choices == null || choices.isEmpty()) {
|
||||||
if (min == 0) {
|
if (min == 0) {
|
||||||
callback.run(new ArrayList<>());
|
callback.run(new ArrayList<>());
|
||||||
|
|||||||
@@ -201,11 +201,8 @@ public class ListChooser<T> extends FContainer {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows the dialog and returns after the dialog was closed.
|
* Shows the dialog and returns after the dialog was closed.
|
||||||
*
|
|
||||||
* @param index0 index to select when shown
|
|
||||||
* @return a boolean.
|
|
||||||
*/
|
*/
|
||||||
public void show(final T item, final boolean selectMax) {
|
public void show(final Collection<T> item, final boolean selectMax) {
|
||||||
if (called) {
|
if (called) {
|
||||||
throw new IllegalStateException("Already shown");
|
throw new IllegalStateException("Already shown");
|
||||||
}
|
}
|
||||||
@@ -226,7 +223,7 @@ public class ListChooser<T> extends FContainer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
lstChoices.setSelectedItem(item);
|
lstChoices.setSelectedItems(item);
|
||||||
}
|
}
|
||||||
optionPane.show();
|
optionPane.show();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3462,7 +3462,7 @@ AdvBossIntro34=Es gibt kein Zurück!
|
|||||||
AdvBossIntro35=Jetzt geht es um alles oder nichts!
|
AdvBossIntro35=Jetzt geht es um alles oder nichts!
|
||||||
lblYouDied={0}, du bist gestorben!!!
|
lblYouDied={0}, du bist gestorben!!!
|
||||||
lblSellFor=Verkaufen für
|
lblSellFor=Verkaufen für
|
||||||
lblUnsellableCount=Unverkäuflich ({0})
|
lblUnsellable=Unverkäuflich
|
||||||
lblAutoSell=AUTOVERKAUF
|
lblAutoSell=AUTOVERKAUF
|
||||||
lblNoSell=NICHT VERKAUFEN
|
lblNoSell=NICHT VERKAUFEN
|
||||||
lbltoSell=Zu verkaufen ({0}/{1})
|
lbltoSell=Zu verkaufen ({0}/{1})
|
||||||
|
|||||||
@@ -3210,7 +3210,7 @@ AdvBossIntro34=There's no turning back!
|
|||||||
AdvBossIntro35=It's all or nothing now!
|
AdvBossIntro35=It's all or nothing now!
|
||||||
lblYouDied={0}, You Died!!!
|
lblYouDied={0}, You Died!!!
|
||||||
lblSellFor=Sell for
|
lblSellFor=Sell for
|
||||||
lblUnsellableCount=Unsellable ({0})
|
lblUnsellable=Unsellable
|
||||||
lblAutoSell=AUTO-SELL
|
lblAutoSell=AUTO-SELL
|
||||||
lblNoSell=NO-SELL
|
lblNoSell=NO-SELL
|
||||||
lbltoSell=To Sell ({0}/{1})
|
lbltoSell=To Sell ({0}/{1})
|
||||||
|
|||||||
@@ -3473,7 +3473,7 @@ AdvBossIntro34=¡No hay marcha atrás!
|
|||||||
AdvBossIntro35=¡Ahora es todo o nada!
|
AdvBossIntro35=¡Ahora es todo o nada!
|
||||||
lblYouDied={0}, ¡¡¡Moriste!!!
|
lblYouDied={0}, ¡¡¡Moriste!!!
|
||||||
lblSellFor=Vender por
|
lblSellFor=Vender por
|
||||||
lblUnsellableCount=No vendible ({0})
|
lblUnsellable=No vendible
|
||||||
lblAutoSell=AUTOVENTA
|
lblAutoSell=AUTOVENTA
|
||||||
lblNoSell=NO VENDER
|
lblNoSell=NO VENDER
|
||||||
lbltoSell=Para vender ({0}/{1})
|
lbltoSell=Para vender ({0}/{1})
|
||||||
|
|||||||
@@ -3467,7 +3467,7 @@ AdvBossIntro34=Il n'y a pas de retour en arrière!
|
|||||||
AdvBossIntro35=C'est tout ou rien maintenant !
|
AdvBossIntro35=C'est tout ou rien maintenant !
|
||||||
lblYouDied={0}, tu es mort !!!
|
lblYouDied={0}, tu es mort !!!
|
||||||
lblSellFor=Vendre pour
|
lblSellFor=Vendre pour
|
||||||
lblUnsellableCount=Invendable ({0})
|
lblUnsellable=Invendable
|
||||||
lblAutoSell=VENTE AUTOMATIQUE
|
lblAutoSell=VENTE AUTOMATIQUE
|
||||||
lblNoSell=NON-VENTE
|
lblNoSell=NON-VENTE
|
||||||
lbltoSell=À vendre ({0}/{1})
|
lbltoSell=À vendre ({0}/{1})
|
||||||
|
|||||||
@@ -3465,7 +3465,7 @@ AdvBossIntro34=Non si può tornare indietro!
|
|||||||
AdvBossIntro35=Adesso è tutto o niente!
|
AdvBossIntro35=Adesso è tutto o niente!
|
||||||
lblYouDied={0}, sei morto!!!
|
lblYouDied={0}, sei morto!!!
|
||||||
lblSellFor=Vendi per
|
lblSellFor=Vendi per
|
||||||
lblUnsellableCount=Invendibile ({0})
|
lblUnsellable=Invendibile
|
||||||
lblAutoSell=AUTOVENDITA
|
lblAutoSell=AUTOVENDITA
|
||||||
lblNoSell=NON VENDITA
|
lblNoSell=NON VENDITA
|
||||||
lbltoSell=Da vendere ({0}/{1})
|
lbltoSell=Da vendere ({0}/{1})
|
||||||
|
|||||||
@@ -3461,7 +3461,7 @@ AdvBossIntro34=もう後戻りはできない!
|
|||||||
AdvBossIntro35=もう、オール・オア・ナッシングだ!
|
AdvBossIntro35=もう、オール・オア・ナッシングだ!
|
||||||
lblYouDied={0}、死んだ!!!
|
lblYouDied={0}、死んだ!!!
|
||||||
lblSellFor=で売る
|
lblSellFor=で売る
|
||||||
lblUnsellableCount=販売不可 ({0})
|
lblUnsellable=販売不可
|
||||||
lblAutoSell=自動販売
|
lblAutoSell=自動販売
|
||||||
lblNoSell=販売禁止
|
lblNoSell=販売禁止
|
||||||
lbltoSell=販売する ({0}/{1})
|
lbltoSell=販売する ({0}/{1})
|
||||||
|
|||||||
@@ -3551,7 +3551,7 @@ AdvBossIntro34=Não há como voltar atrás!
|
|||||||
AdvBossIntro35=É tudo ou nada agora!
|
AdvBossIntro35=É tudo ou nada agora!
|
||||||
lblYouDied={0}, você morreu!!!
|
lblYouDied={0}, você morreu!!!
|
||||||
lblSellFor=Vender por
|
lblSellFor=Vender por
|
||||||
lblUnsellableCount=Invendável ({0})
|
lblUnsellable=Invendável
|
||||||
lblAutoSell=VENDA AUTOMÁTICA
|
lblAutoSell=VENDA AUTOMÁTICA
|
||||||
lblNoSell=NÃO VENDER
|
lblNoSell=NÃO VENDER
|
||||||
lbltoSell=Para Vender ({0}/{1})
|
lbltoSell=Para Vender ({0}/{1})
|
||||||
|
|||||||
@@ -3452,7 +3452,7 @@ AdvBossIntro34=没有回头路了!
|
|||||||
AdvBossIntro35=现在要么全有要么全无!
|
AdvBossIntro35=现在要么全有要么全无!
|
||||||
lblYouDied={0},你死了!!!
|
lblYouDied={0},你死了!!!
|
||||||
lblSellFor=售价为
|
lblSellFor=售价为
|
||||||
lblUnsellableCount=无法出售({0})
|
lblUnsellable=无法出售
|
||||||
lblAutoSell=自动销售
|
lblAutoSell=自动销售
|
||||||
lblNoSell=不卖
|
lblNoSell=不卖
|
||||||
lbltoSell=出售({0}/{1})
|
lbltoSell=出售({0}/{1})
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public enum ProtocolMethod {
|
|||||||
showOptionDialog (Mode.SERVER, Integer.TYPE, String.class, String.class, FSkinProp.class, List/*String*/.class, Integer.TYPE),
|
showOptionDialog (Mode.SERVER, Integer.TYPE, String.class, String.class, FSkinProp.class, List/*String*/.class, Integer.TYPE),
|
||||||
showInputDialog (Mode.SERVER, String.class, String.class, String.class, FSkinProp.class, String.class, List/*String*/.class, Boolean.TYPE),
|
showInputDialog (Mode.SERVER, String.class, String.class, String.class, FSkinProp.class, String.class, List/*String*/.class, Boolean.TYPE),
|
||||||
confirm (Mode.SERVER, Boolean.TYPE, CardView.class, String.class, Boolean.TYPE, List/*String*/.class),
|
confirm (Mode.SERVER, Boolean.TYPE, CardView.class, String.class, Boolean.TYPE, List/*String*/.class),
|
||||||
getChoices (Mode.SERVER, List.class, String.class, Integer.TYPE, Integer.TYPE, List.class, Object.class, Function.class),
|
getChoices (Mode.SERVER, List.class, String.class, Integer.TYPE, Integer.TYPE, List.class, List.class, Function.class),
|
||||||
order (Mode.SERVER, List.class, String.class, String.class, Integer.TYPE, Integer.TYPE, List.class, List.class, CardView.class, Boolean.TYPE),
|
order (Mode.SERVER, List.class, String.class, String.class, Integer.TYPE, Integer.TYPE, List.class, List.class, CardView.class, Boolean.TYPE),
|
||||||
sideboard (Mode.SERVER, List.class, CardPool.class, CardPool.class, String.class),
|
sideboard (Mode.SERVER, List.class, CardPool.class, CardPool.class, String.class),
|
||||||
chooseSingleEntityForEffect(Mode.SERVER, GameEntityView.class, String.class, List.class, DelayedReveal.class, Boolean.TYPE),
|
chooseSingleEntityForEffect(Mode.SERVER, GameEntityView.class, String.class, List.class, DelayedReveal.class, Boolean.TYPE),
|
||||||
|
|||||||
@@ -246,7 +246,7 @@ public class NetGuiGame extends AbstractGuiGame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> List<T> getChoices(final String message, final int min, final int max, final List<T> choices, final T selected, final Function<T, String> display) {
|
public <T> List<T> getChoices(final String message, final int min, final int max, final List<T> choices, final List<T> selected, final Function<T, String> display) {
|
||||||
return sendAndWait(ProtocolMethod.getChoices, message, min, max, choices, selected, display);
|
return sendAndWait(ProtocolMethod.getChoices, message, min, max, choices, selected, display);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
@@ -510,11 +511,11 @@ public class QuestWinLoseController {
|
|||||||
final List<GameFormat> formats = new ArrayList<>();
|
final List<GameFormat> formats = new ArrayList<>();
|
||||||
final String preferredFormat = FModel.getQuestPreferences().getPref(QPref.BOOSTER_FORMAT);
|
final String preferredFormat = FModel.getQuestPreferences().getPref(QPref.BOOSTER_FORMAT);
|
||||||
|
|
||||||
GameFormat pref = null;
|
Collection<GameFormat> pref = null;
|
||||||
for (final GameFormat f : FModel.getFormats().getSanctionedList()) {
|
for (final GameFormat f : FModel.getFormats().getSanctionedList()) {
|
||||||
formats.add(f);
|
formats.add(f);
|
||||||
if (f.toString().equals(preferredFormat)) {
|
if (f.toString().equals(preferredFormat)) {
|
||||||
pref = f;
|
pref = List.of(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ public class CardDetailUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String getCurrentColors(final CardStateView c) {
|
public static String getCurrentColors(final CardStateView c) {
|
||||||
return c.getColors().toEnumSet().stream().map(MagicColor.Color::getSymbol).collect(Collectors.joining());
|
return c.getColors().stream().map(MagicColor.Color::getSymbol).collect(Collectors.joining());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DetailColors getRarityColor(final CardRarity rarity) {
|
public static DetailColors getRarityColor(final CardRarity rarity) {
|
||||||
@@ -450,10 +450,10 @@ public class CardDetailUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// chosen spire
|
// chosen spire
|
||||||
if (card.getChosenColorID() != null && !card.getChosenColorID().isEmpty()) {
|
if (card.getMarkedColors() != null && !card.getMarkedColors().isColorless()) {
|
||||||
area.append("\n");
|
area.append("\n");
|
||||||
area.append("(").append(Localizer.getInstance().getMessage("lblSelected")).append(": ");
|
area.append("(").append(Localizer.getInstance().getMessage("lblSelected")).append(": ");
|
||||||
area.append(Lang.joinHomogenous(card.getChosenColorID().stream().map(DeckRecognizer::getLocalisedMagicColorName).collect(Collectors.toList())));
|
area.append(Lang.joinHomogenous(card.getMarkedColors().stream().map(MagicColor.Color::getLocalizedName).collect(Collectors.toList())));
|
||||||
area.append(")");
|
area.append(")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public class GuiDownloadSetPicturesLQ extends GuiDownloadService {
|
|||||||
}
|
}
|
||||||
final String setCode2 = setMapping.get(setCode3);
|
final String setCode2 = setMapping.get(setCode3);
|
||||||
|
|
||||||
if (StringUtils.isBlank(setCode3) || CardEdition.UNKNOWN.getCode().equals(setCode3)) {
|
if (StringUtils.isBlank(setCode3) || CardEdition.UNKNOWN_CODE.equals(setCode3)) {
|
||||||
// we don't want cards from unknown sets
|
// we don't want cards from unknown sets
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public interface IGuiBase {
|
|||||||
void showImageDialog(ISkinImage image, String message, String title);
|
void showImageDialog(ISkinImage image, String message, String title);
|
||||||
int showOptionDialog(String message, String title, FSkinProp icon, List<String> options, int defaultOption);
|
int showOptionDialog(String message, String title, FSkinProp icon, List<String> options, int defaultOption);
|
||||||
String showInputDialog(String message, String title, FSkinProp icon, String initialInput, List<String> inputOptions, boolean isNumeric);
|
String showInputDialog(String message, String title, FSkinProp icon, String initialInput, List<String> inputOptions, boolean isNumeric);
|
||||||
<T> List<T> getChoices(String message, int min, int max, Collection<T> choices, T selected, Function<T, String> display);
|
<T> List<T> getChoices(String message, int min, int max, Collection<T> choices, Collection<T> selected, Function<T, String> display);
|
||||||
<T> List<T> order(String title, String top, int remainingObjectsMin, int remainingObjectsMax, List<T> sourceChoices, List<T> destChoices);
|
<T> List<T> order(String title, String top, int remainingObjectsMin, int remainingObjectsMax, List<T> sourceChoices, List<T> destChoices);
|
||||||
String showFileDialog(String title, String defaultDir);
|
String showFileDialog(String title, String defaultDir);
|
||||||
File getSaveFile(File defaultFile);
|
File getSaveFile(File defaultFile);
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ public interface IGuiGame {
|
|||||||
|
|
||||||
<T> List<T> getChoices(String message, int min, int max, List<T> choices);
|
<T> List<T> getChoices(String message, int min, int max, List<T> choices);
|
||||||
|
|
||||||
<T> List<T> getChoices(String message, int min, int max, List<T> choices, T selected, Function<T, String> display);
|
<T> List<T> getChoices(String message, int min, int max, List<T> choices, List<T> selected, Function<T, String> display);
|
||||||
|
|
||||||
// Get Integer in range
|
// Get Integer in range
|
||||||
Integer getInteger(String message, int min);
|
Integer getInteger(String message, int min);
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public class SGuiChoose {
|
|||||||
if ((choices == null) || choices.isEmpty()) {
|
if ((choices == null) || choices.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final List<T> choice = SGuiChoose.getChoices(message, 0, 1, choices, selected, display);
|
final List<T> choice = SGuiChoose.getChoices(message, 0, 1, choices, selected == null ? null : List.of(selected), display);
|
||||||
return choice.isEmpty() ? null : choice.get(0);
|
return choice.isEmpty() ? null : choice.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,12 +147,12 @@ public class SGuiChoose {
|
|||||||
return getChoices(message, min, max, Arrays.asList(choices), null, null);
|
return getChoices(message, min, max, Arrays.asList(choices), null, null);
|
||||||
}
|
}
|
||||||
public static <T> List<T> getChoices(final String message, final int min, final int max, final T[] choices, final T selected, final Function<T, String> display) {
|
public static <T> List<T> getChoices(final String message, final int min, final int max, final T[] choices, final T selected, final Function<T, String> display) {
|
||||||
return getChoices(message, min, max, Arrays.asList(choices), selected, display);
|
return getChoices(message, min, max, Arrays.asList(choices), selected == null ? null : List.of(selected), display);
|
||||||
}
|
}
|
||||||
public static <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices) {
|
public static <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices) {
|
||||||
return getChoices(message, min, max, choices, null, null);
|
return getChoices(message, min, max, choices, null, null);
|
||||||
}
|
}
|
||||||
public static <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices, final T selected, final Function<T, String> display) {
|
public static <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices, final Collection<T> selected, final Function<T, String> display) {
|
||||||
return GuiBase.getInterface().getChoices(message, min, max, choices, selected, display);
|
return GuiBase.getInterface().getChoices(message, min, max, choices, selected, display);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ public enum ColumnDef {
|
|||||||
NAME("lblName", "lblName", 180, false, SortState.ASC,
|
NAME("lblName", "lblName", 180, false, SortState.ASC,
|
||||||
from -> {
|
from -> {
|
||||||
if (from.getKey() instanceof PaperCard) {
|
if (from.getKey() instanceof PaperCard) {
|
||||||
String spire = ((PaperCard) from.getKey()).getColorID() == null ? "" : ((PaperCard) from.getKey()).getColorID().toString();
|
String spire = ((PaperCard) from.getKey()).getMarkedColors() == null ? "" : ((PaperCard) from.getKey()).getMarkedColors().toString();
|
||||||
String sortableName = ((PaperCard)from.getKey()).getSortableName();
|
String sortableName = ((PaperCard)from.getKey()).getSortableName();
|
||||||
return sortableName == null ? TextUtil.toSortableName(from.getKey().getName() + spire) : sortableName + spire;
|
return sortableName == null ? TextUtil.toSortableName(from.getKey().getName() + spire) : sortableName + spire;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user