mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 02:38:02 +00:00
Compare commits
1 Commits
force-8p-d
...
migrate-sp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9bf567a966 |
@@ -878,7 +878,7 @@ public class StaticData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// stream().toList() causes crash on Android 8-13, use Collectors.toList()
|
// stream().toList() causes crash on Android, use Collectors.toList()
|
||||||
List<String> NIF = new ArrayList<>(NIF_Q).stream().sorted().collect(Collectors.toList());
|
List<String> NIF = new ArrayList<>(NIF_Q).stream().sorted().collect(Collectors.toList());
|
||||||
List<String> CNI = new ArrayList<>(CNI_Q).stream().sorted().collect(Collectors.toList());
|
List<String> CNI = new ArrayList<>(CNI_Q).stream().sorted().collect(Collectors.toList());
|
||||||
List<String> TOK = new ArrayList<>(TOKEN_Q).stream().sorted().collect(Collectors.toList());
|
List<String> TOK = new ArrayList<>(TOKEN_Q).stream().sorted().collect(Collectors.toList());
|
||||||
|
|||||||
@@ -1018,13 +1018,16 @@ public final class CardEdition implements Comparable<CardEdition> {
|
|||||||
|
|
||||||
public static final Predicate<CardEdition> HAS_BOOSTER_BOX = edition -> edition.getBoosterBoxCount() > 0;
|
public static final Predicate<CardEdition> HAS_BOOSTER_BOX = edition -> edition.getBoosterBoxCount() > 0;
|
||||||
|
|
||||||
@Deprecated //Use CardEdition::hasBasicLands and a nonnull test.
|
|
||||||
public static final Predicate<CardEdition> hasBasicLands = ed -> {
|
public static final Predicate<CardEdition> hasBasicLands = ed -> {
|
||||||
if (ed == null) {
|
if (ed == null) {
|
||||||
// Happens for new sets with "???" code
|
// Happens for new sets with "???" code
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return ed.hasBasicLands();
|
for(String landName : MagicColor.Constant.BASIC_LANDS) {
|
||||||
|
if (null == StaticData.instance().getCommonCards().getCard(landName, ed.getCode(), 0))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1045,7 +1048,7 @@ public final class CardEdition implements Comparable<CardEdition> {
|
|||||||
|
|
||||||
public boolean hasBasicLands() {
|
public boolean hasBasicLands() {
|
||||||
for(String landName : MagicColor.Constant.BASIC_LANDS) {
|
for(String landName : MagicColor.Constant.BASIC_LANDS) {
|
||||||
if (this.getCardInSet(landName).isEmpty())
|
if (null == StaticData.instance().getCommonCards().getCard(landName, this.getCode(), 0))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -49,16 +49,6 @@ public class DeckRecognizer {
|
|||||||
LIMITED_CARD,
|
LIMITED_CARD,
|
||||||
CARD_FROM_NOT_ALLOWED_SET,
|
CARD_FROM_NOT_ALLOWED_SET,
|
||||||
CARD_FROM_INVALID_SET,
|
CARD_FROM_INVALID_SET,
|
||||||
/**
|
|
||||||
* Valid card request, but can't be imported because the player does not have enough copies.
|
|
||||||
* Should be replaced with a different printing if possible.
|
|
||||||
*/
|
|
||||||
CARD_NOT_IN_INVENTORY,
|
|
||||||
/**
|
|
||||||
* Valid card request for a card that isn't in the player's inventory, but new copies can be acquired freely.
|
|
||||||
* Usually used for basic lands. Should be supplied to the import controller by the editor.
|
|
||||||
*/
|
|
||||||
FREE_CARD_NOT_IN_INVENTORY,
|
|
||||||
// Warning messages
|
// Warning messages
|
||||||
WARNING_MESSAGE,
|
WARNING_MESSAGE,
|
||||||
UNKNOWN_CARD,
|
UNKNOWN_CARD,
|
||||||
@@ -73,14 +63,10 @@ public class DeckRecognizer {
|
|||||||
CARD_TYPE,
|
CARD_TYPE,
|
||||||
CARD_RARITY,
|
CARD_RARITY,
|
||||||
CARD_CMC,
|
CARD_CMC,
|
||||||
MANA_COLOUR;
|
MANA_COLOUR
|
||||||
|
|
||||||
public static final EnumSet<TokenType> CARD_TOKEN_TYPES = EnumSet.of(LEGAL_CARD, LIMITED_CARD, CARD_FROM_NOT_ALLOWED_SET, CARD_FROM_INVALID_SET, CARD_NOT_IN_INVENTORY, FREE_CARD_NOT_IN_INVENTORY);
|
|
||||||
public static final EnumSet<TokenType> IN_DECK_TOKEN_TYPES = EnumSet.of(LEGAL_CARD, LIMITED_CARD, DECK_NAME, FREE_CARD_NOT_IN_INVENTORY);
|
|
||||||
public static final EnumSet<TokenType> CARD_PLACEHOLDER_TOKEN_TYPES = EnumSet.of(CARD_TYPE, CARD_RARITY, CARD_CMC, MANA_COLOUR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum LimitedCardType {
|
public enum LimitedCardType{
|
||||||
BANNED,
|
BANNED,
|
||||||
RESTRICTED,
|
RESTRICTED,
|
||||||
}
|
}
|
||||||
@@ -122,10 +108,6 @@ public class DeckRecognizer {
|
|||||||
return new Token(TokenType.CARD_FROM_INVALID_SET, count, card, cardRequestHasSetCode);
|
return new Token(TokenType.CARD_FROM_INVALID_SET, count, card, cardRequestHasSetCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Token NotInInventoryFree(final PaperCard card, final int count, final DeckSection section) {
|
|
||||||
return new Token(TokenType.FREE_CARD_NOT_IN_INVENTORY, count, card, section, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// WARNING MESSAGES
|
// WARNING MESSAGES
|
||||||
// ================
|
// ================
|
||||||
public static Token UnknownCard(final String cardName, final String setCode, final int count) {
|
public static Token UnknownCard(final String cardName, final String setCode, final int count) {
|
||||||
@@ -144,10 +126,6 @@ public class DeckRecognizer {
|
|||||||
return new Token(TokenType.WARNING_MESSAGE, msg);
|
return new Token(TokenType.WARNING_MESSAGE, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Token NotInInventory(final PaperCard card, final int count, final DeckSection section) {
|
|
||||||
return new Token(TokenType.CARD_NOT_IN_INVENTORY, count, card, section, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* =================================
|
/* =================================
|
||||||
* DECK SECTIONS
|
* DECK SECTIONS
|
||||||
* ================================= */
|
* ================================= */
|
||||||
@@ -261,11 +239,14 @@ public class DeckRecognizer {
|
|||||||
/**
|
/**
|
||||||
* Filters all token types that have a PaperCard instance set (not null)
|
* Filters all token types that have a PaperCard instance set (not null)
|
||||||
* @return true for tokens of type:
|
* @return true for tokens of type:
|
||||||
* LEGAL_CARD, LIMITED_CARD, CARD_FROM_NOT_ALLOWED_SET and CARD_FROM_INVALID_SET, CARD_NOT_IN_INVENTORY, FREE_CARD_NOT_IN_INVENTORY.
|
* LEGAL_CARD, LIMITED_CARD, CARD_FROM_NOT_ALLOWED_SET and CARD_FROM_INVALID_SET.
|
||||||
* False otherwise.
|
* False otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean isCardToken() {
|
public boolean isCardToken() {
|
||||||
return TokenType.CARD_TOKEN_TYPES.contains(this.type);
|
return (this.type == TokenType.LEGAL_CARD ||
|
||||||
|
this.type == TokenType.LIMITED_CARD ||
|
||||||
|
this.type == TokenType.CARD_FROM_NOT_ALLOWED_SET ||
|
||||||
|
this.type == TokenType.CARD_FROM_INVALID_SET);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -274,7 +255,9 @@ public class DeckRecognizer {
|
|||||||
* LEGAL_CARD, LIMITED_CARD, DECK_NAME; false otherwise.
|
* LEGAL_CARD, LIMITED_CARD, DECK_NAME; false otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean isTokenForDeck() {
|
public boolean isTokenForDeck() {
|
||||||
return TokenType.IN_DECK_TOKEN_TYPES.contains(this.type);
|
return (this.type == TokenType.LEGAL_CARD ||
|
||||||
|
this.type == TokenType.LIMITED_CARD ||
|
||||||
|
this.type == TokenType.DECK_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -283,7 +266,7 @@ public class DeckRecognizer {
|
|||||||
* False otherwise.
|
* False otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean isCardTokenForDeck() {
|
public boolean isCardTokenForDeck() {
|
||||||
return isCardToken() && isTokenForDeck();
|
return (this.type == TokenType.LEGAL_CARD || this.type == TokenType.LIMITED_CARD);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -293,7 +276,10 @@ public class DeckRecognizer {
|
|||||||
* CARD_RARITY, CARD_CMC, CARD_TYPE, MANA_COLOUR
|
* CARD_RARITY, CARD_CMC, CARD_TYPE, MANA_COLOUR
|
||||||
*/
|
*/
|
||||||
public boolean isCardPlaceholder(){
|
public boolean isCardPlaceholder(){
|
||||||
return TokenType.CARD_PLACEHOLDER_TOKEN_TYPES.contains(this.type);
|
return (this.type == TokenType.CARD_RARITY ||
|
||||||
|
this.type == TokenType.CARD_CMC ||
|
||||||
|
this.type == TokenType.MANA_COLOUR ||
|
||||||
|
this.type == TokenType.CARD_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Determines if current token is a Deck Section token
|
/** Determines if current token is a Deck Section token
|
||||||
@@ -550,7 +536,7 @@ public class DeckRecognizer {
|
|||||||
PaperCard tokenCard = token.getCard();
|
PaperCard tokenCard = token.getCard();
|
||||||
|
|
||||||
if (isAllowed(tokenSection)) {
|
if (isAllowed(tokenSection)) {
|
||||||
if (tokenSection != referenceDeckSectionInParsing) {
|
if (!tokenSection.equals(referenceDeckSectionInParsing)) {
|
||||||
Token sectionToken = Token.DeckSection(tokenSection.name(), this.allowedDeckSections);
|
Token sectionToken = Token.DeckSection(tokenSection.name(), this.allowedDeckSections);
|
||||||
// just check that last token is stack is a card placeholder.
|
// just check that last token is stack is a card placeholder.
|
||||||
// In that case, add the new section token before the placeholder
|
// In that case, add the new section token before the placeholder
|
||||||
@@ -589,7 +575,7 @@ public class DeckRecognizer {
|
|||||||
refLine = purgeAllLinks(refLine);
|
refLine = purgeAllLinks(refLine);
|
||||||
|
|
||||||
String line;
|
String line;
|
||||||
if (refLine.startsWith(LINE_COMMENT_DELIMITER_OR_MD_HEADER))
|
if (StringUtils.startsWith(refLine, LINE_COMMENT_DELIMITER_OR_MD_HEADER))
|
||||||
line = refLine.replaceAll(LINE_COMMENT_DELIMITER_OR_MD_HEADER, "");
|
line = refLine.replaceAll(LINE_COMMENT_DELIMITER_OR_MD_HEADER, "");
|
||||||
else
|
else
|
||||||
line = refLine.trim(); // Remove any trailing formatting
|
line = refLine.trim(); // Remove any trailing formatting
|
||||||
@@ -598,7 +584,7 @@ public class DeckRecognizer {
|
|||||||
// Final fantasy cards like Summon: Choco/Mog should be ommited to be recognized. TODO: fix maybe for future cards
|
// Final fantasy cards like Summon: Choco/Mog should be ommited to be recognized. TODO: fix maybe for future cards
|
||||||
if (!line.contains("Summon:"))
|
if (!line.contains("Summon:"))
|
||||||
line = SEARCH_SINGLE_SLASH.matcher(line).replaceFirst(" // ");
|
line = SEARCH_SINGLE_SLASH.matcher(line).replaceFirst(" // ");
|
||||||
if (line.startsWith(ASTERISK)) // Markdown lists (tappedout md export)
|
if (StringUtils.startsWith(line, ASTERISK)) // markdown lists (tappedout md export)
|
||||||
line = line.substring(2);
|
line = line.substring(2);
|
||||||
|
|
||||||
// == Patches to Corner Cases
|
// == Patches to Corner Cases
|
||||||
@@ -614,8 +600,8 @@ public class DeckRecognizer {
|
|||||||
Token result = recogniseCardToken(line, referenceSection);
|
Token result = recogniseCardToken(line, referenceSection);
|
||||||
if (result == null)
|
if (result == null)
|
||||||
result = recogniseNonCardToken(line);
|
result = recogniseNonCardToken(line);
|
||||||
return result != null ? result : refLine.startsWith(DOUBLE_SLASH) ||
|
return result != null ? result : StringUtils.startsWith(refLine, DOUBLE_SLASH) ||
|
||||||
refLine.startsWith(LINE_COMMENT_DELIMITER_OR_MD_HEADER) ?
|
StringUtils.startsWith(refLine, LINE_COMMENT_DELIMITER_OR_MD_HEADER) ?
|
||||||
new Token(TokenType.COMMENT, 0, refLine) : new Token(TokenType.UNKNOWN_TEXT, 0, refLine);
|
new Token(TokenType.COMMENT, 0, refLine) : new Token(TokenType.UNKNOWN_TEXT, 0, refLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -627,7 +613,7 @@ public class DeckRecognizer {
|
|||||||
while (m.find()) {
|
while (m.find()) {
|
||||||
line = line.replaceAll(m.group(), "").trim();
|
line = line.replaceAll(m.group(), "").trim();
|
||||||
}
|
}
|
||||||
if (line.endsWith("()"))
|
if (StringUtils.endsWith(line, "()"))
|
||||||
return line.substring(0, line.length()-2);
|
return line.substring(0, line.length()-2);
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
@@ -755,12 +741,21 @@ public class DeckRecognizer {
|
|||||||
// This would save tons of time in parsing Input + would also allow to return UnsupportedCardTokens beforehand
|
// This would save tons of time in parsing Input + would also allow to return UnsupportedCardTokens beforehand
|
||||||
private DeckSection getTokenSection(String deckSec, DeckSection currentDeckSection, PaperCard card){
|
private DeckSection getTokenSection(String deckSec, DeckSection currentDeckSection, PaperCard card){
|
||||||
if (deckSec != null) {
|
if (deckSec != null) {
|
||||||
DeckSection cardSection = switch (deckSec.toUpperCase().trim()) {
|
DeckSection cardSection;
|
||||||
case "MB" -> DeckSection.Main;
|
switch (deckSec.toUpperCase().trim()) {
|
||||||
case "SB" -> DeckSection.Sideboard;
|
case "MB":
|
||||||
case "CM" -> DeckSection.Commander;
|
cardSection = DeckSection.Main;
|
||||||
default -> DeckSection.matchingSection(card);
|
break;
|
||||||
};
|
case "SB":
|
||||||
|
cardSection = DeckSection.Sideboard;
|
||||||
|
break;
|
||||||
|
case "CM":
|
||||||
|
cardSection = DeckSection.Commander;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
cardSection = DeckSection.matchingSection(card);
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (cardSection.validate(card))
|
if (cardSection.validate(card))
|
||||||
return cardSection;
|
return cardSection;
|
||||||
}
|
}
|
||||||
@@ -1022,21 +1017,51 @@ public class DeckRecognizer {
|
|||||||
private static MagicColor.Color getMagicColor(String colorName){
|
private static MagicColor.Color getMagicColor(String colorName){
|
||||||
if (colorName.toLowerCase().startsWith("multi") || colorName.equalsIgnoreCase("m"))
|
if (colorName.toLowerCase().startsWith("multi") || colorName.equalsIgnoreCase("m"))
|
||||||
return null; // will be handled separately
|
return null; // will be handled separately
|
||||||
return MagicColor.Color.fromByte(MagicColor.fromName(colorName.toLowerCase()));
|
|
||||||
|
byte color = MagicColor.fromName(colorName.toLowerCase());
|
||||||
|
switch (color) {
|
||||||
|
case MagicColor.WHITE:
|
||||||
|
return MagicColor.Color.WHITE;
|
||||||
|
case MagicColor.BLUE:
|
||||||
|
return MagicColor.Color.BLUE;
|
||||||
|
case MagicColor.BLACK:
|
||||||
|
return MagicColor.Color.BLACK;
|
||||||
|
case MagicColor.RED:
|
||||||
|
return MagicColor.Color.RED;
|
||||||
|
case MagicColor.GREEN:
|
||||||
|
return MagicColor.Color.GREEN;
|
||||||
|
default:
|
||||||
|
return MagicColor.Color.COLORLESS;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getLocalisedMagicColorName(String colorName){
|
public static String getLocalisedMagicColorName(String colorName){
|
||||||
Localizer localizer = Localizer.getInstance();
|
Localizer localizer = Localizer.getInstance();
|
||||||
return switch (colorName.toLowerCase()) {
|
switch(colorName.toLowerCase()){
|
||||||
case MagicColor.Constant.WHITE -> localizer.getMessage("lblWhite");
|
case MagicColor.Constant.WHITE:
|
||||||
case MagicColor.Constant.BLUE -> localizer.getMessage("lblBlue");
|
return localizer.getMessage("lblWhite");
|
||||||
case MagicColor.Constant.BLACK -> localizer.getMessage("lblBlack");
|
|
||||||
case MagicColor.Constant.RED -> localizer.getMessage("lblRed");
|
case MagicColor.Constant.BLUE:
|
||||||
case MagicColor.Constant.GREEN -> localizer.getMessage("lblGreen");
|
return localizer.getMessage("lblBlue");
|
||||||
case MagicColor.Constant.COLORLESS -> localizer.getMessage("lblColorless");
|
|
||||||
case "multicolour", "multicolor" -> localizer.getMessage("lblMulticolor");
|
case MagicColor.Constant.BLACK:
|
||||||
default -> "";
|
return localizer.getMessage("lblBlack");
|
||||||
};
|
|
||||||
|
case MagicColor.Constant.RED:
|
||||||
|
return localizer.getMessage("lblRed");
|
||||||
|
|
||||||
|
case MagicColor.Constant.GREEN:
|
||||||
|
return localizer.getMessage("lblGreen");
|
||||||
|
|
||||||
|
case MagicColor.Constant.COLORLESS:
|
||||||
|
return localizer.getMessage("lblColorless");
|
||||||
|
case "multicolour":
|
||||||
|
case "multicolor":
|
||||||
|
return localizer.getMessage("lblMulticolor");
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1055,6 +1080,37 @@ public class DeckRecognizer {
|
|||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static Pair<String, String> getManaNameAndSymbol(String matchedMana) {
|
||||||
|
if (matchedMana == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Localizer localizer = Localizer.getInstance();
|
||||||
|
switch (matchedMana.toLowerCase()) {
|
||||||
|
case MagicColor.Constant.WHITE:
|
||||||
|
case "w":
|
||||||
|
return Pair.of(localizer.getMessage("lblWhite"), MagicColor.Color.WHITE.getSymbol());
|
||||||
|
case MagicColor.Constant.BLUE:
|
||||||
|
case "u":
|
||||||
|
return Pair.of(localizer.getMessage("lblBlue"), MagicColor.Color.BLUE.getSymbol());
|
||||||
|
case MagicColor.Constant.BLACK:
|
||||||
|
case "b":
|
||||||
|
return Pair.of(localizer.getMessage("lblBlack"), MagicColor.Color.BLACK.getSymbol());
|
||||||
|
case MagicColor.Constant.RED:
|
||||||
|
case "r":
|
||||||
|
return Pair.of(localizer.getMessage("lblRed"), MagicColor.Color.RED.getSymbol());
|
||||||
|
case MagicColor.Constant.GREEN:
|
||||||
|
case "g":
|
||||||
|
return Pair.of(localizer.getMessage("lblGreen"), MagicColor.Color.GREEN.getSymbol());
|
||||||
|
case MagicColor.Constant.COLORLESS:
|
||||||
|
case "c":
|
||||||
|
return Pair.of(localizer.getMessage("lblColorless"), MagicColor.Color.COLORLESS.getSymbol());
|
||||||
|
default: // Multicolour
|
||||||
|
return Pair.of(localizer.getMessage("lblMulticolor"), "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isDeckName(final String lineAsIs) {
|
public static boolean isDeckName(final String lineAsIs) {
|
||||||
if (lineAsIs == null)
|
if (lineAsIs == null)
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -633,10 +633,7 @@ public class BoosterGenerator {
|
|||||||
System.out.println("Parsing from main code: " + mainCode);
|
System.out.println("Parsing from main code: " + mainCode);
|
||||||
String sheetName = StringUtils.strip(mainCode.substring(10), "()\" ");
|
String sheetName = StringUtils.strip(mainCode.substring(10), "()\" ");
|
||||||
System.out.println("Attempting to lookup: " + sheetName);
|
System.out.println("Attempting to lookup: " + sheetName);
|
||||||
PrintSheet fromSheet = tryGetStaticSheet(sheetName);
|
src = tryGetStaticSheet(sheetName).toFlatList();
|
||||||
if (fromSheet == null)
|
|
||||||
throw new RuntimeException("PrintSheet Error: " + ps.getName() + " didn't find " + sheetName + " from " + mainCode);
|
|
||||||
src = fromSheet.toFlatList();
|
|
||||||
setPred = x -> true;
|
setPred = x -> true;
|
||||||
|
|
||||||
} else if (mainCode.startsWith("promo") || mainCode.startsWith("name")) { // get exactly the named cards, that's a tiny inlined print sheet
|
} else if (mainCode.startsWith("promo") || mainCode.startsWith("name")) { // get exactly the named cards, that's a tiny inlined print sheet
|
||||||
|
|||||||
@@ -367,7 +367,7 @@ public class CardState extends GameObject implements IHasSVars, ITranslatable {
|
|||||||
public final FCollectionView<SpellAbility> getManaAbilities() {
|
public final FCollectionView<SpellAbility> getManaAbilities() {
|
||||||
FCollection<SpellAbility> newCol = new FCollection<>();
|
FCollection<SpellAbility> newCol = new FCollection<>();
|
||||||
updateSpellAbilities(newCol, true);
|
updateSpellAbilities(newCol, true);
|
||||||
// stream().toList() causes crash on Android 8-13, use Collectors.toList()
|
// stream().toList() causes crash on Android, use Collectors.toList()
|
||||||
newCol.addAll(abilities.stream().filter(SpellAbility::isManaAbility).collect(Collectors.toList()));
|
newCol.addAll(abilities.stream().filter(SpellAbility::isManaAbility).collect(Collectors.toList()));
|
||||||
card.updateSpellAbilities(newCol, this, true);
|
card.updateSpellAbilities(newCol, this, true);
|
||||||
return newCol;
|
return newCol;
|
||||||
@@ -375,7 +375,7 @@ public class CardState extends GameObject implements IHasSVars, ITranslatable {
|
|||||||
public final FCollectionView<SpellAbility> getNonManaAbilities() {
|
public final FCollectionView<SpellAbility> getNonManaAbilities() {
|
||||||
FCollection<SpellAbility> newCol = new FCollection<>();
|
FCollection<SpellAbility> newCol = new FCollection<>();
|
||||||
updateSpellAbilities(newCol, false);
|
updateSpellAbilities(newCol, false);
|
||||||
// stream().toList() causes crash on Android 8-13, use Collectors.toList()
|
// stream().toList() causes crash on Android, use Collectors.toList()
|
||||||
newCol.addAll(abilities.stream().filter(Predicate.not(SpellAbility::isManaAbility)).collect(Collectors.toList()));
|
newCol.addAll(abilities.stream().filter(Predicate.not(SpellAbility::isManaAbility)).collect(Collectors.toList()));
|
||||||
card.updateSpellAbilities(newCol, this, false);
|
card.updateSpellAbilities(newCol, this, false);
|
||||||
return newCol;
|
return newCol;
|
||||||
@@ -390,7 +390,7 @@ public class CardState extends GameObject implements IHasSVars, ITranslatable {
|
|||||||
if (null != mana) {
|
if (null != mana) {
|
||||||
leftAbilities = leftAbilities.stream()
|
leftAbilities = leftAbilities.stream()
|
||||||
.filter(mana ? SpellAbility::isManaAbility : Predicate.not(SpellAbility::isManaAbility))
|
.filter(mana ? SpellAbility::isManaAbility : Predicate.not(SpellAbility::isManaAbility))
|
||||||
// stream().toList() causes crash on Android 8-13, use Collectors.toList()
|
// stream().toList() causes crash on Android, use Collectors.toList()
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
newCol.addAll(leftAbilities);
|
newCol.addAll(leftAbilities);
|
||||||
@@ -402,7 +402,7 @@ public class CardState extends GameObject implements IHasSVars, ITranslatable {
|
|||||||
if (null != mana) {
|
if (null != mana) {
|
||||||
rightAbilities = rightAbilities.stream()
|
rightAbilities = rightAbilities.stream()
|
||||||
.filter(mana ? SpellAbility::isManaAbility : Predicate.not(SpellAbility::isManaAbility))
|
.filter(mana ? SpellAbility::isManaAbility : Predicate.not(SpellAbility::isManaAbility))
|
||||||
// stream().toList() causes crash on Android 8-13, use Collectors.toList()
|
// stream().toList() causes crash on Android, use Collectors.toList()
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
newCol.addAll(rightAbilities);
|
newCol.addAll(rightAbilities);
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package forge.game.keyword;
|
package forge.game.keyword;
|
||||||
|
|
||||||
import forge.card.CardSplitType;
|
import forge.StaticData;
|
||||||
|
import forge.game.card.Card;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@@ -223,7 +223,7 @@ public enum Keyword {
|
|||||||
displayName = displayName0;
|
displayName = displayName0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Pair<Keyword, String> getKeywordDetails(String k) {
|
public static KeywordInterface getInstance(String k) {
|
||||||
Keyword keyword = Keyword.UNDEFINED;
|
Keyword keyword = Keyword.UNDEFINED;
|
||||||
String details = k;
|
String details = k;
|
||||||
// try to get real part
|
// try to get real part
|
||||||
@@ -255,20 +255,15 @@ public enum Keyword {
|
|||||||
keyword = smartValueOf(k);
|
keyword = smartValueOf(k);
|
||||||
details = "";
|
details = "";
|
||||||
}
|
}
|
||||||
return Pair.of(keyword, details);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static KeywordInterface getInstance(String k) {
|
|
||||||
Pair<Keyword, String> p = getKeywordDetails(k);
|
|
||||||
|
|
||||||
KeywordInstance<?> inst;
|
KeywordInstance<?> inst;
|
||||||
try {
|
try {
|
||||||
inst = p.getKey().type.getConstructor().newInstance();
|
inst = keyword.type.getConstructor().newInstance();
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
inst = new UndefinedKeyword();
|
inst = new UndefinedKeyword();
|
||||||
}
|
}
|
||||||
inst.initialize(k, p.getKey(), p.getValue());
|
inst.initialize(k, keyword, details);
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,44 +278,36 @@ public enum Keyword {
|
|||||||
return keywords;
|
return keywords;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Keyword get(String k) {
|
|
||||||
if (k == null || k.isEmpty())
|
|
||||||
return Keyword.UNDEFINED;
|
|
||||||
|
|
||||||
return getKeywordDetails(k).getKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Map<String, Set<Keyword>> cardKeywordSetLookup = new HashMap<>();
|
private static final Map<String, Set<Keyword>> cardKeywordSetLookup = new HashMap<>();
|
||||||
|
|
||||||
public static Set<Keyword> getKeywordSet(PaperCard card) {
|
public static Set<Keyword> getKeywordSet(PaperCard card) {
|
||||||
String name = card.getName();
|
String key = card.getName();
|
||||||
Set<Keyword> keywordSet = cardKeywordSetLookup.get(name);
|
Set<Keyword> keywordSet = cardKeywordSetLookup.get(key);
|
||||||
if (keywordSet == null) {
|
if (keywordSet == null) {
|
||||||
CardSplitType cardSplitType = card.getRules().getSplitType();
|
keywordSet = new HashSet<>();
|
||||||
keywordSet = EnumSet.noneOf(Keyword.class);
|
for (KeywordInterface inst : Card.getCardForUi(card).getKeywords()) {
|
||||||
if (cardSplitType != CardSplitType.None && cardSplitType != CardSplitType.Split) {
|
final Keyword keyword = inst.getKeyword();
|
||||||
if (card.getRules().getOtherPart() != null) {
|
if (keyword != Keyword.UNDEFINED) {
|
||||||
if (card.getRules().getOtherPart().getKeywords() != null) {
|
keywordSet.add(keyword);
|
||||||
for (String key : card.getRules().getOtherPart().getKeywords()) {
|
|
||||||
Keyword keyword = get(key);
|
|
||||||
if (!Keyword.UNDEFINED.equals(keyword))
|
|
||||||
keywordSet.add(keyword);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (card.getRules().getMainPart().getKeywords() != null) {
|
cardKeywordSetLookup.put(card.getName(), keywordSet);
|
||||||
for (String key : card.getRules().getMainPart().getKeywords()) {
|
|
||||||
Keyword keyword = get(key);
|
|
||||||
if (!Keyword.UNDEFINED.equals(keyword))
|
|
||||||
keywordSet.add(keyword);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cardKeywordSetLookup.put(name, keywordSet);
|
|
||||||
}
|
}
|
||||||
return keywordSet;
|
return keywordSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Runnable getPreloadTask() {
|
||||||
|
if (cardKeywordSetLookup.size() < 10000) { //allow preloading even if some but not all cards loaded
|
||||||
|
return () -> {
|
||||||
|
final Collection<PaperCard> cards = StaticData.instance().getCommonCards().getUniqueCards();
|
||||||
|
for (PaperCard card : cards) {
|
||||||
|
getKeywordSet(card);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public static Keyword smartValueOf(String value) {
|
public static Keyword smartValueOf(String value) {
|
||||||
for (final Keyword v : Keyword.values()) {
|
for (final Keyword v : Keyword.values()) {
|
||||||
if (v.displayName.equalsIgnoreCase(value)) {
|
if (v.displayName.equalsIgnoreCase(value)) {
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ public class AddBasicLandsDialog {
|
|||||||
private static final int LAND_PANEL_PADDING = 3;
|
private static final int LAND_PANEL_PADDING = 3;
|
||||||
|
|
||||||
private final FComboBoxPanel<CardEdition> cbLandSet = new FComboBoxPanel<>(Localizer.getInstance().getMessage("lblLandSet") + ":", FlowLayout.CENTER,
|
private final FComboBoxPanel<CardEdition> cbLandSet = new FComboBoxPanel<>(Localizer.getInstance().getMessage("lblLandSet") + ":", FlowLayout.CENTER,
|
||||||
IterableUtil.filter(StaticData.instance().getSortedEditions(), CardEdition::hasBasicLands));
|
IterableUtil.filter(StaticData.instance().getSortedEditions(), CardEdition.Predicates.hasBasicLands));
|
||||||
|
|
||||||
private final MainPanel panel = new MainPanel();
|
private final MainPanel panel = new MainPanel();
|
||||||
private final LandPanel pnlPlains = new LandPanel("Plains");
|
private final LandPanel pnlPlains = new LandPanel("Plains");
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import forge.toolbox.*;
|
|||||||
import forge.util.Localizer;
|
import forge.util.Localizer;
|
||||||
import forge.view.FDialog;
|
import forge.view.FDialog;
|
||||||
import net.miginfocom.swing.MigLayout;
|
import net.miginfocom.swing.MigLayout;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import static forge.deck.DeckRecognizer.TokenType.*;
|
import static forge.deck.DeckRecognizer.TokenType.*;
|
||||||
|
|
||||||
@@ -522,7 +523,7 @@ public class DeckImport<TModel extends DeckBase> extends FDialog {
|
|||||||
else
|
else
|
||||||
deck.setName(currentDeckName);
|
deck.setName(currentDeckName);
|
||||||
}
|
}
|
||||||
host.getDeckController().loadDeck(deck, controller.getImportBehavior() != DeckImportController.ImportBehavior.MERGE);
|
host.getDeckController().loadDeck(deck, controller.getCreateNewDeck());
|
||||||
processWindowEvent(new WindowEvent(DeckImport.this, WindowEvent.WINDOW_CLOSING));
|
processWindowEvent(new WindowEvent(DeckImport.this, WindowEvent.WINDOW_CLOSING));
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -530,7 +531,7 @@ public class DeckImport<TModel extends DeckBase> extends FDialog {
|
|||||||
this.createNewDeckCheckbox.setSelected(false);
|
this.createNewDeckCheckbox.setSelected(false);
|
||||||
this.createNewDeckCheckbox.addActionListener(e -> {
|
this.createNewDeckCheckbox.addActionListener(e -> {
|
||||||
boolean createNewDeck = createNewDeckCheckbox.isSelected();
|
boolean createNewDeck = createNewDeckCheckbox.isSelected();
|
||||||
controller.setImportBehavior(createNewDeck ? DeckImportController.ImportBehavior.CREATE_NEW : DeckImportController.ImportBehavior.MERGE);
|
controller.setCreateNewDeck(createNewDeck);
|
||||||
String cmdAcceptLabel = createNewDeck ? CREATE_NEW_DECK_CMD_LABEL : IMPORT_CARDS_CMD_LABEL;
|
String cmdAcceptLabel = createNewDeck ? CREATE_NEW_DECK_CMD_LABEL : IMPORT_CARDS_CMD_LABEL;
|
||||||
cmdAcceptButton.setText(cmdAcceptLabel);
|
cmdAcceptButton.setText(cmdAcceptLabel);
|
||||||
String smartCardArtChboxTooltip = createNewDeck ? SMART_CARDART_TT_NO_DECK : SMART_CARDART_TT_WITH_DECK;
|
String smartCardArtChboxTooltip = createNewDeck ? SMART_CARDART_TT_NO_DECK : SMART_CARDART_TT_WITH_DECK;
|
||||||
@@ -599,7 +600,7 @@ public class DeckImport<TModel extends DeckBase> extends FDialog {
|
|||||||
if (token.getType() == LIMITED_CARD)
|
if (token.getType() == LIMITED_CARD)
|
||||||
cssClass = WARN_MSG_CLASS;
|
cssClass = WARN_MSG_CLASS;
|
||||||
String statusMsg = String.format("<span class=\"%s\" style=\"font-size: 9px;\">%s</span>", cssClass,
|
String statusMsg = String.format("<span class=\"%s\" style=\"font-size: 9px;\">%s</span>", cssClass,
|
||||||
controller.getTokenStatusMessage(token));
|
getTokenStatusMessage(token));
|
||||||
statusLbl.append(statusMsg);
|
statusLbl.append(statusMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -739,12 +740,12 @@ public class DeckImport<TModel extends DeckBase> extends FDialog {
|
|||||||
private String toHTML(final DeckRecognizer.Token token) {
|
private String toHTML(final DeckRecognizer.Token token) {
|
||||||
if (token == null)
|
if (token == null)
|
||||||
return "";
|
return "";
|
||||||
String tokenMsg = controller.getTokenMessage(token);
|
String tokenMsg = getTokenMessage(token);
|
||||||
if (tokenMsg == null)
|
if (tokenMsg == null)
|
||||||
return "";
|
return "";
|
||||||
String tokenStatus = controller.getTokenStatusMessage(token);
|
String tokenStatus = getTokenStatusMessage(token);
|
||||||
String cssClass = getTokenCSSClass(token.getType());
|
String cssClass = getTokenCSSClass(token.getType());
|
||||||
if (tokenStatus.isEmpty())
|
if (tokenStatus.length() == 0)
|
||||||
tokenMsg = padEndWithHTMLSpaces(tokenMsg, 2*PADDING_TOKEN_MSG_LENGTH+10);
|
tokenMsg = padEndWithHTMLSpaces(tokenMsg, 2*PADDING_TOKEN_MSG_LENGTH+10);
|
||||||
else {
|
else {
|
||||||
tokenMsg = padEndWithHTMLSpaces(tokenMsg, PADDING_TOKEN_MSG_LENGTH);
|
tokenMsg = padEndWithHTMLSpaces(tokenMsg, PADDING_TOKEN_MSG_LENGTH);
|
||||||
@@ -754,6 +755,11 @@ public class DeckImport<TModel extends DeckBase> extends FDialog {
|
|||||||
tokenMsg = String.format("<a class=\"%s\" href=\"%s\">%s</a>", cssClass,
|
tokenMsg = String.format("<a class=\"%s\" href=\"%s\">%s</a>", cssClass,
|
||||||
token.getKey().toString(), tokenMsg);
|
token.getKey().toString(), tokenMsg);
|
||||||
|
|
||||||
|
if (tokenStatus == null) {
|
||||||
|
String tokenTag = String.format("<td colspan=\"2\" class=\"%s\">%s</td>", cssClass, tokenMsg);
|
||||||
|
return String.format("<tr>%s</tr>", tokenTag);
|
||||||
|
}
|
||||||
|
|
||||||
String tokenTag = "<td class=\"%s\">%s</td>";
|
String tokenTag = "<td class=\"%s\">%s</td>";
|
||||||
String tokenMsgTag = String.format(tokenTag, cssClass, tokenMsg);
|
String tokenMsgTag = String.format(tokenTag, cssClass, tokenMsg);
|
||||||
String tokenStatusTag;
|
String tokenStatusTag;
|
||||||
@@ -770,6 +776,97 @@ public class DeckImport<TModel extends DeckBase> extends FDialog {
|
|||||||
return String.format("%s%s", targetMsg, spacer);
|
return String.format("%s%s", targetMsg, spacer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getTokenMessage(DeckRecognizer.Token token) {
|
||||||
|
switch (token.getType()) {
|
||||||
|
case LEGAL_CARD:
|
||||||
|
case LIMITED_CARD:
|
||||||
|
case CARD_FROM_NOT_ALLOWED_SET:
|
||||||
|
case CARD_FROM_INVALID_SET:
|
||||||
|
return String.format("%s x %s %s", token.getQuantity(), token.getText(), getTokenFoilLabel(token));
|
||||||
|
// Card Warning Msgs
|
||||||
|
case UNKNOWN_CARD:
|
||||||
|
case UNSUPPORTED_CARD:
|
||||||
|
return token.getQuantity() > 0 ? String.format("%s x %s", token.getQuantity(), token.getText())
|
||||||
|
: token.getText();
|
||||||
|
|
||||||
|
case UNSUPPORTED_DECK_SECTION:
|
||||||
|
return String.format("%s: %s", Localizer.getInstance().getMessage("lblWarningMsgPrefix"),
|
||||||
|
Localizer.getInstance()
|
||||||
|
.getMessage("lblWarnDeckSectionNotAllowedInEditor", token.getText(),
|
||||||
|
this.currentGameType));
|
||||||
|
|
||||||
|
// Special Case of Card moved into another section (e.g. Commander from Sideboard)
|
||||||
|
case WARNING_MESSAGE:
|
||||||
|
return String.format("%s: %s", Localizer.getInstance()
|
||||||
|
.getMessage("lblWarningMsgPrefix"), token.getText());
|
||||||
|
|
||||||
|
// Placeholders
|
||||||
|
case DECK_SECTION_NAME:
|
||||||
|
return String.format("%s: %s", Localizer.getInstance().getMessage("lblDeckSection"),
|
||||||
|
token.getText());
|
||||||
|
|
||||||
|
case CARD_RARITY:
|
||||||
|
return String.format("%s: %s", Localizer.getInstance().getMessage("lblRarity"),
|
||||||
|
token.getText());
|
||||||
|
|
||||||
|
case CARD_TYPE:
|
||||||
|
case CARD_CMC:
|
||||||
|
case MANA_COLOUR:
|
||||||
|
case COMMENT:
|
||||||
|
return token.getText();
|
||||||
|
|
||||||
|
case DECK_NAME:
|
||||||
|
return String.format("%s: %s", Localizer.getInstance().getMessage("lblDeckName"),
|
||||||
|
token.getText());
|
||||||
|
|
||||||
|
case UNKNOWN_TEXT:
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getTokenStatusMessage(DeckRecognizer.Token token){
|
||||||
|
if (token == null)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
switch (token.getType()) {
|
||||||
|
case LIMITED_CARD:
|
||||||
|
return String.format("%s: %s", Localizer.getInstance().getMessage("lblWarningMsgPrefix"),
|
||||||
|
Localizer.getInstance().getMessage("lblWarnLimitedCard",
|
||||||
|
StringUtils.capitalize(token.getLimitedCardType().name()), getGameFormatLabel()));
|
||||||
|
|
||||||
|
case CARD_FROM_NOT_ALLOWED_SET:
|
||||||
|
return Localizer.getInstance().getMessage("lblErrNotAllowedCard", getGameFormatLabel());
|
||||||
|
|
||||||
|
case CARD_FROM_INVALID_SET:
|
||||||
|
return Localizer.getInstance().getMessage("lblErrCardEditionDate");
|
||||||
|
|
||||||
|
case UNSUPPORTED_CARD:
|
||||||
|
return Localizer.getInstance().getMessage("lblErrUnsupportedCard", this.currentGameType);
|
||||||
|
|
||||||
|
case UNKNOWN_CARD:
|
||||||
|
return String.format("%s: %s", Localizer.getInstance().getMessage("lblWarningMsgPrefix"),
|
||||||
|
Localizer.getInstance().getMessage("lblWarnUnknownCardMsg"));
|
||||||
|
|
||||||
|
case UNSUPPORTED_DECK_SECTION:
|
||||||
|
case WARNING_MESSAGE:
|
||||||
|
case COMMENT:
|
||||||
|
case CARD_CMC:
|
||||||
|
case MANA_COLOUR:
|
||||||
|
case CARD_TYPE:
|
||||||
|
case DECK_SECTION_NAME:
|
||||||
|
case CARD_RARITY:
|
||||||
|
case DECK_NAME:
|
||||||
|
case LEGAL_CARD:
|
||||||
|
case UNKNOWN_TEXT:
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private String getTokenCSSClass(DeckRecognizer.TokenType tokenType){
|
private String getTokenCSSClass(DeckRecognizer.TokenType tokenType){
|
||||||
switch (tokenType){
|
switch (tokenType){
|
||||||
case LEGAL_CARD:
|
case LEGAL_CARD:
|
||||||
@@ -802,6 +899,17 @@ public class DeckImport<TModel extends DeckBase> extends FDialog {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getTokenFoilLabel(DeckRecognizer.Token token) {
|
||||||
|
if (!token.isCardToken())
|
||||||
|
return "";
|
||||||
|
final String foilMarker = "- (Foil)";
|
||||||
|
return token.getCard().isFoil() ? foilMarker : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getGameFormatLabel() {
|
||||||
|
return String.format("\"%s\"", this.controller.getCurrentGameFormatName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GameFormatDropdownRenderer extends JLabel implements ListCellRenderer<GameFormat> {
|
class GameFormatDropdownRenderer extends JLabel implements ListCellRenderer<GameFormat> {
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public class EntryActor extends MapActor{
|
|||||||
{
|
{
|
||||||
if(targetMap==null||targetMap.isEmpty())
|
if(targetMap==null||targetMap.isEmpty())
|
||||||
{
|
{
|
||||||
stage.exitDungeon(false, false);
|
stage.exitDungeon(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ public class PortalActor extends EntryActor {
|
|||||||
}
|
}
|
||||||
if (currentAnimationType == PortalAnimationTypes.Active) {
|
if (currentAnimationType == PortalAnimationTypes.Active) {
|
||||||
if (targetMap == null || targetMap.isEmpty()) {
|
if (targetMap == null || targetMap.isEmpty()) {
|
||||||
stage.exitDungeon(false, false);
|
stage.exitDungeon(false);
|
||||||
} else {
|
} else {
|
||||||
if (targetMap.equals(currentMap)) {
|
if (targetMap.equals(currentMap)) {
|
||||||
stage.spawn(entryTargetObject);
|
stage.spawn(entryTargetObject);
|
||||||
|
|||||||
@@ -292,7 +292,7 @@ public class AdventureEventData implements Serializable {
|
|||||||
Random placeholder = MyRandom.getRandom();
|
Random placeholder = MyRandom.getRandom();
|
||||||
MyRandom.setRandom(getEventRandom());
|
MyRandom.setRandom(getEventRandom());
|
||||||
if (draft == null && (eventStatus == AdventureEventController.EventStatus.Available || eventStatus == AdventureEventController.EventStatus.Entered)) {
|
if (draft == null && (eventStatus == AdventureEventController.EventStatus.Available || eventStatus == AdventureEventController.EventStatus.Entered)) {
|
||||||
draft = BoosterDraft.createDraft(LimitedPoolType.Block, getCardBlock(), packConfiguration, 8);
|
draft = BoosterDraft.createDraft(LimitedPoolType.Block, getCardBlock(), packConfiguration);
|
||||||
registeredDeck = draft.getHumanPlayer().getDeck();
|
registeredDeck = draft.getHumanPlayer().getDeck();
|
||||||
assignPlayerNames(draft);
|
assignPlayerNames(draft);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1077,25 +1077,6 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
return items.random();
|
return items.random();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasEquippedItem() {
|
|
||||||
for (Long id : equippedItems.values()) {
|
|
||||||
ItemData item = getEquippedItem(id);
|
|
||||||
if (item == null)
|
|
||||||
continue;
|
|
||||||
if (isHardorInsaneDifficulty()) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
switch (item.equipmentSlot) {
|
|
||||||
// limit to these for easy and normal
|
|
||||||
case "Boots", "Body", "Neck" -> {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ItemData getEquippedAbility1() {
|
public ItemData getEquippedAbility1() {
|
||||||
for (Long id : equippedItems.values()) {
|
for (Long id : equippedItems.values()) {
|
||||||
ItemData data = getEquippedItem(id);
|
ItemData data = getEquippedItem(id);
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ import forge.item.PaperCard;
|
|||||||
import forge.itemmanager.*;
|
import forge.itemmanager.*;
|
||||||
import forge.itemmanager.filters.CardColorFilter;
|
import forge.itemmanager.filters.CardColorFilter;
|
||||||
import forge.itemmanager.filters.CardTypeFilter;
|
import forge.itemmanager.filters.CardTypeFilter;
|
||||||
|
import forge.localinstance.properties.ForgePreferences;
|
||||||
|
import forge.menu.FCheckBoxMenuItem;
|
||||||
import forge.menu.FDropDownMenu;
|
import forge.menu.FDropDownMenu;
|
||||||
import forge.menu.FMenuItem;
|
import forge.menu.FMenuItem;
|
||||||
import forge.menu.FPopupMenu;
|
import forge.menu.FPopupMenu;
|
||||||
@@ -39,7 +41,6 @@ import forge.util.Utils;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
public class AdventureDeckEditor extends FDeckEditor {
|
public class AdventureDeckEditor extends FDeckEditor {
|
||||||
protected static class AdventureEditorConfig extends DeckEditorConfig {
|
protected static class AdventureEditorConfig extends DeckEditorConfig {
|
||||||
@@ -145,8 +146,7 @@ public class AdventureDeckEditor extends FDeckEditor {
|
|||||||
if(event.cardBlock != null) {
|
if(event.cardBlock != null) {
|
||||||
if(event.cardBlock.getLandSet() != null)
|
if(event.cardBlock.getLandSet() != null)
|
||||||
return List.of(event.cardBlock.getLandSet());
|
return List.of(event.cardBlock.getLandSet());
|
||||||
List<CardEdition> eventSets = new ArrayList<>(event.cardBlock.getSets());
|
List<CardEdition> eventSets = event.cardBlock.getSets();
|
||||||
eventSets.removeIf(Predicate.not(CardEdition::hasBasicLands));
|
|
||||||
if(!eventSets.isEmpty())
|
if(!eventSets.isEmpty())
|
||||||
return eventSets;
|
return eventSets;
|
||||||
}
|
}
|
||||||
@@ -558,7 +558,7 @@ public class AdventureDeckEditor extends FDeckEditor {
|
|||||||
currentEvent.participants[i].setDeck(opponentDecks[i]);
|
currentEvent.participants[i].setDeck(opponentDecks[i]);
|
||||||
}
|
}
|
||||||
currentEvent.draftedDeck = (Deck) currentEvent.registeredDeck.copyTo("Draft Deck");
|
currentEvent.draftedDeck = (Deck) currentEvent.registeredDeck.copyTo("Draft Deck");
|
||||||
if (allowAddBasic()) {
|
if (allowsAddBasic()) {
|
||||||
showAddBasicLandsDialog();
|
showAddBasicLandsDialog();
|
||||||
//Might be annoying if you haven't pruned your deck yet, but best to remind player that
|
//Might be annoying if you haven't pruned your deck yet, but best to remind player that
|
||||||
//this probably needs to be done since it's there since it's not normally part of Adventure
|
//this probably needs to be done since it's there since it's not normally part of Adventure
|
||||||
@@ -713,6 +713,27 @@ public class AdventureDeckEditor extends FDeckEditor {
|
|||||||
return this.deckHeader;
|
return this.deckHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected FPopupMenu createMoreOptionsMenu() {
|
||||||
|
return new FPopupMenu() {
|
||||||
|
@Override
|
||||||
|
protected void buildMenu() {
|
||||||
|
Localizer localizer = Forge.getLocalizer();
|
||||||
|
addItem(new FMenuItem(localizer.getMessage("btnCopyToClipboard"), Forge.hdbuttons ? FSkinImage.HDEXPORT : FSkinImage.BLANK, e1 -> FDeckViewer.copyDeckToClipboard(getDeck())));
|
||||||
|
if (allowsAddBasic()) {
|
||||||
|
FMenuItem addBasic = new FMenuItem(localizer.getMessage("lblAddBasicLands"), FSkinImage.LANDLOGO, e1 -> showAddBasicLandsDialog());
|
||||||
|
addItem(addBasic);
|
||||||
|
}
|
||||||
|
if(FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.DEV_MODE_ENABLED)) {
|
||||||
|
addItem(new FCheckBoxMenuItem(localizer.getMessage("cbEnforceDeckLegality"), shouldEnforceConformity(), e -> toggleConformity()));
|
||||||
|
String devSuffix = " (" + localizer.getMessage("lblDev") + ")";
|
||||||
|
addItem(new FMenuItem(localizer.getMessage("lblAddcard") + devSuffix, FSkinImage.HDPLUS, e -> showDevAddCardDialog()));
|
||||||
|
}
|
||||||
|
((DeckEditorPage) getSelectedPage()).buildDeckMenu(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void addChosenBasicLands(CardPool landsToAdd) {
|
protected void addChosenBasicLands(CardPool landsToAdd) {
|
||||||
if(isLimitedEditor())
|
if(isLimitedEditor())
|
||||||
@@ -744,12 +765,6 @@ public class AdventureDeckEditor extends FDeckEditor {
|
|||||||
catalog.moveCards(landsToMove, getMainDeckPage());
|
catalog.moveCards(landsToMove, getMainDeckPage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected PaperCard supplyPrintForImporter(PaperCard missingCard) {
|
|
||||||
PaperCard out = super.supplyPrintForImporter(missingCard);
|
|
||||||
return out == null ? null : out.getNoSellVersion();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void cacheTabPages() {
|
protected void cacheTabPages() {
|
||||||
super.cacheTabPages();
|
super.cacheTabPages();
|
||||||
@@ -760,9 +775,7 @@ public class AdventureDeckEditor extends FDeckEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean allowAddBasic() {
|
protected boolean allowsAddBasic() {
|
||||||
if(getEditorConfig() instanceof DeckPreviewConfig)
|
|
||||||
return false;
|
|
||||||
AdventureEventData currentEvent = getCurrentEvent();
|
AdventureEventData currentEvent = getCurrentEvent();
|
||||||
if (currentEvent == null)
|
if (currentEvent == null)
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ public class ArenaScene extends UIScene implements IAfterMatch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setWinner(boolean winner, boolean isArena) {
|
public void setWinner(boolean winner) {
|
||||||
enable = false;
|
enable = false;
|
||||||
Array<ArenaRecord> winners = new Array<>();
|
Array<ArenaRecord> winners = new Array<>();
|
||||||
Array<EnemySprite> winnersEnemies = new Array<>();
|
Array<EnemySprite> winnersEnemies = new Array<>();
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ public class DuelScene extends ForgeScene {
|
|||||||
Current.player().getStatistic().setResult(enemyName, winner);
|
Current.player().getStatistic().setResult(enemyName, winner);
|
||||||
|
|
||||||
if (last instanceof IAfterMatch) {
|
if (last instanceof IAfterMatch) {
|
||||||
((IAfterMatch) last).setWinner(winner, isArena);
|
((IAfterMatch) last).setWinner(winner);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -193,8 +193,6 @@ public class DuelScene extends ForgeScene {
|
|||||||
public void enter() {
|
public void enter() {
|
||||||
GameHUD.getInstance().unloadAudio();
|
GameHUD.getInstance().unloadAudio();
|
||||||
GameType mainGameType;
|
GameType mainGameType;
|
||||||
boolean isDeckMissing = false;
|
|
||||||
String isDeckMissingMsg = "";
|
|
||||||
if (eventData != null && eventData.eventRules != null) {
|
if (eventData != null && eventData.eventRules != null) {
|
||||||
mainGameType = eventData.eventRules.gameType;
|
mainGameType = eventData.eventRules.gameType;
|
||||||
} else {
|
} else {
|
||||||
@@ -297,12 +295,6 @@ public class DuelScene extends ForgeScene {
|
|||||||
} else {
|
} else {
|
||||||
deck = currentEnemy.copyPlayerDeck ? this.playerDeck : currentEnemy.generateDeck(Current.player().isFantasyMode(), Current.player().isUsingCustomDeck() || Current.player().isHardorInsaneDifficulty());
|
deck = currentEnemy.copyPlayerDeck ? this.playerDeck : currentEnemy.generateDeck(Current.player().isFantasyMode(), Current.player().isUsingCustomDeck() || Current.player().isHardorInsaneDifficulty());
|
||||||
}
|
}
|
||||||
if (deck == null) {
|
|
||||||
isDeckMissing = true;
|
|
||||||
isDeckMissingMsg = "Deck for " + currentEnemy.getName() + " is missing! " + (this.eventData == null ? "Genetic AI deck will be used." : "Player deck will be used.");
|
|
||||||
System.err.println(isDeckMissingMsg);
|
|
||||||
deck = this.eventData == null ? Aggregates.random(DeckProxy.getAllGeneticAIDecks()).getDeck() : this.playerDeck;
|
|
||||||
}
|
|
||||||
RegisteredPlayer aiPlayer = RegisteredPlayer.forVariants(playerCount, appliedVariants, deck, null, false, null, null);
|
RegisteredPlayer aiPlayer = RegisteredPlayer.forVariants(playerCount, appliedVariants, deck, null, false, null, null);
|
||||||
|
|
||||||
LobbyPlayer enemyPlayer = GamePlayerUtil.createAiPlayer(currentEnemy.getName(), selectAI(currentEnemy.ai));
|
LobbyPlayer enemyPlayer = GamePlayerUtil.createAiPlayer(currentEnemy.getName(), selectAI(currentEnemy.ai));
|
||||||
@@ -376,9 +368,9 @@ public class DuelScene extends ForgeScene {
|
|||||||
hostedMatch.startMatch(rules, appliedVariants, players, guiMap, bossBattle ? MusicPlaylist.BOSS : MusicPlaylist.MATCH);
|
hostedMatch.startMatch(rules, appliedVariants, players, guiMap, bossBattle ? MusicPlaylist.BOSS : MusicPlaylist.MATCH);
|
||||||
MatchController.instance.setGameView(hostedMatch.getGameView());
|
MatchController.instance.setGameView(hostedMatch.getGameView());
|
||||||
boolean showMessages = enemy.getData().boss || (enemy.getData().copyPlayerDeck && Current.player().isUsingCustomDeck());
|
boolean showMessages = enemy.getData().boss || (enemy.getData().copyPlayerDeck && Current.player().isUsingCustomDeck());
|
||||||
if (chaosBattle || showMessages || isDeckMissing) {
|
if (chaosBattle || showMessages) {
|
||||||
final FBufferedImage fb = getFBEnemyAvatar();
|
final FBufferedImage fb = getFBEnemyAvatar();
|
||||||
bossDialogue = createFOption(isDeckMissing ? isDeckMissingMsg : Forge.getLocalizer().getMessage("AdvBossIntro" + Aggregates.randomInt(1, 35)),
|
bossDialogue = createFOption(Forge.getLocalizer().getMessage("AdvBossIntro" + Aggregates.randomInt(1, 35)),
|
||||||
enemy.getName(), fb, fb::dispose);
|
enemy.getName(), fb, fb::dispose);
|
||||||
matchOverlay = new LoadingOverlay(() -> FThreads.delayInEDT(300, () -> FThreads.invokeInEdtNowOrLater(() ->
|
matchOverlay = new LoadingOverlay(() -> FThreads.delayInEDT(300, () -> FThreads.invokeInEdtNowOrLater(() ->
|
||||||
bossDialogue.show())), false, true);
|
bossDialogue.show())), false, true);
|
||||||
|
|||||||
@@ -541,7 +541,7 @@ public class EventScene extends MenuScene implements IAfterMatch {
|
|||||||
|
|
||||||
AdventureEventData.AdventureEventMatch humanMatch = null;
|
AdventureEventData.AdventureEventMatch humanMatch = null;
|
||||||
|
|
||||||
public void setWinner(boolean winner, boolean isArena) {
|
public void setWinner(boolean winner) {
|
||||||
if (winner) {
|
if (winner) {
|
||||||
humanMatch.winner = humanMatch.p1;
|
humanMatch.winner = humanMatch.p1;
|
||||||
humanMatch.p1.wins++;
|
humanMatch.p1.wins++;
|
||||||
|
|||||||
@@ -181,8 +181,8 @@ public abstract class HudScene extends Scene implements InputProcessor, IAfterMa
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setWinner(boolean winner, boolean isArena) {
|
public void setWinner(boolean winner) {
|
||||||
stage.setWinner(winner, isArena);
|
stage.setWinner(winner);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInHudOnlyMode() {
|
public boolean isInHudOnlyMode() {
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ public class ConsoleCommandInterpreter {
|
|||||||
});
|
});
|
||||||
registerCommand(new String[]{"leave"}, s -> {
|
registerCommand(new String[]{"leave"}, s -> {
|
||||||
if (!MapStage.getInstance().isInMap()) return "not on a map";
|
if (!MapStage.getInstance().isInMap()) return "not on a map";
|
||||||
MapStage.getInstance().exitDungeon(false, false);
|
MapStage.getInstance().exitDungeon(false);
|
||||||
return "Got out";
|
return "Got out";
|
||||||
});
|
});
|
||||||
registerCommand(new String[]{"debug", "collision"}, s -> {
|
registerCommand(new String[]{"debug", "collision"}, s -> {
|
||||||
|
|||||||
@@ -893,7 +893,7 @@ public class GameHUD extends Stage {
|
|||||||
@Override
|
@Override
|
||||||
public boolean act(float v) {
|
public boolean act(float v) {
|
||||||
if (exitDungeon) {
|
if (exitDungeon) {
|
||||||
MapStage.getInstance().exitDungeon(false, false);
|
MapStage.getInstance().exitDungeon(false);
|
||||||
setDisabled(exitToWorldMapActor, true, "[%120][+ExitToWorldMap]", "\u2613");
|
setDisabled(exitToWorldMapActor, true, "[%120][+ExitToWorldMap]", "\u2613");
|
||||||
setDisabled(bookmarkActor, true, "[%120][+Bookmark]", "\u2613");
|
setDisabled(bookmarkActor, true, "[%120][+Bookmark]", "\u2613");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,8 +74,8 @@ public abstract class GameStage extends Stage {
|
|||||||
private float touchY = -1;
|
private float touchY = -1;
|
||||||
private final float timer = 0;
|
private final float timer = 0;
|
||||||
private float animationTimeout = 0;
|
private float animationTimeout = 0;
|
||||||
public static float maximumScrollDistance = 1.5f;
|
public static float maximumScrollDistance=1.5f;
|
||||||
public static float minimumScrollDistance = 0.3f;
|
public static float minimumScrollDistance=0.3f;
|
||||||
|
|
||||||
private String extraAnnouncement = "";
|
private String extraAnnouncement = "";
|
||||||
|
|
||||||
@@ -97,9 +97,8 @@ public abstract class GameStage extends Stage {
|
|||||||
public void setDialogStage(Stage dialogStage) {
|
public void setDialogStage(Stage dialogStage) {
|
||||||
this.dialogStage = dialogStage;
|
this.dialogStage = dialogStage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showDialog() {
|
public void showDialog() {
|
||||||
if (dialogStage == null) {
|
if (dialogStage == null){
|
||||||
setDialogStage(GameHUD.getInstance());
|
setDialogStage(GameHUD.getInstance());
|
||||||
}
|
}
|
||||||
GameHUD.getInstance().playerIdle();
|
GameHUD.getInstance().playerIdle();
|
||||||
@@ -124,7 +123,6 @@ public abstract class GameStage extends Stage {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggered when the hud is showing a dialog, which is tracked separately
|
* Triggered when the hud is showing a dialog, which is tracked separately
|
||||||
*
|
|
||||||
* @param isShowing Whether a dialog is currently showing
|
* @param isShowing Whether a dialog is currently showing
|
||||||
*/
|
*/
|
||||||
public void hudIsShowingDialog(boolean isShowing) {
|
public void hudIsShowingDialog(boolean isShowing) {
|
||||||
@@ -250,21 +248,24 @@ public abstract class GameStage extends Stage {
|
|||||||
showDialog();
|
showDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public boolean axisMoved(Controller controller, int axisIndex, float value) {
|
public boolean axisMoved(Controller controller, int axisIndex, float value) {
|
||||||
|
|
||||||
if (MapStage.getInstance().isDialogOnlyInput() || isPaused()) {
|
if (MapStage.getInstance().isDialogOnlyInput()||isPaused()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
player.getMovementDirection().x = controller.getAxis(0);
|
player.getMovementDirection().x = controller.getAxis(0);
|
||||||
player.getMovementDirection().y = -controller.getAxis(1);
|
player.getMovementDirection().y = -controller.getAxis(1);
|
||||||
if (player.getMovementDirection().len() < 0.2) {
|
if(player.getMovementDirection().len()<0.2)
|
||||||
|
{
|
||||||
player.stop();
|
player.stop();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum PlayerModification {
|
enum PlayerModification
|
||||||
|
{
|
||||||
Sprint,
|
Sprint,
|
||||||
Hide,
|
Hide,
|
||||||
Fly
|
Fly
|
||||||
@@ -272,32 +273,29 @@ public abstract class GameStage extends Stage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
HashMap<PlayerModification, Float> currentModifications = new HashMap<>();
|
HashMap<PlayerModification,Float> currentModifications=new HashMap<>();
|
||||||
|
public void modifyPlayer(PlayerModification mod,float value) {
|
||||||
public void modifyPlayer(PlayerModification mod, float value) {
|
float currentValue=0;
|
||||||
float currentValue = 0;
|
if(currentModifications.containsKey(mod))
|
||||||
if (currentModifications.containsKey(mod)) {
|
{
|
||||||
currentValue = currentModifications.get(mod);
|
currentValue=currentModifications.get(mod);
|
||||||
}
|
}
|
||||||
currentModifications.put(mod, currentValue + value);
|
currentModifications.put(mod,currentValue+value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void flyFor(float value) {
|
public void flyFor(float value) {
|
||||||
modifyPlayer(PlayerModification.Fly, value);
|
modifyPlayer(PlayerModification.Fly,value);
|
||||||
player.playEffect(Paths.EFFECT_FLY);
|
player.playEffect(Paths.EFFECT_FLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void hideFor(float value) {
|
public void hideFor(float value) {
|
||||||
modifyPlayer(PlayerModification.Hide, value);
|
modifyPlayer(PlayerModification.Hide,value);
|
||||||
player.setColor(player.getColor().r, player.getColor().g, player.getColor().b, 0.5f);
|
player.setColor(player.getColor().r,player.getColor().g,player.getColor().b,0.5f);
|
||||||
player.playEffect(Paths.EFFECT_HIDE);
|
player.playEffect(Paths.EFFECT_HIDE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sprintFor(float value) {
|
public void sprintFor(float value) {
|
||||||
modifyPlayer(PlayerModification.Sprint, value);
|
modifyPlayer(PlayerModification.Sprint,value);
|
||||||
player.playEffect(Paths.EFFECT_SPRINT);
|
player.playEffect(Paths.EFFECT_SPRINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startPause(float i) {
|
public void startPause(float i) {
|
||||||
startPause(i, null);
|
startPause(i, null);
|
||||||
}
|
}
|
||||||
@@ -307,7 +305,6 @@ public abstract class GameStage extends Stage {
|
|||||||
animationTimeout = i;
|
animationTimeout = i;
|
||||||
player.setMovementDirection(Vector2.Zero);
|
player.setMovementDirection(Vector2.Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPaused() {
|
public boolean isPaused() {
|
||||||
return animationTimeout > 0;
|
return animationTimeout > 0;
|
||||||
}
|
}
|
||||||
@@ -333,7 +330,7 @@ public abstract class GameStage extends Stage {
|
|||||||
dialog = Controls.newDialog("");
|
dialog = Controls.newDialog("");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setWinner(boolean b, boolean a) {
|
public void setWinner(boolean b) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBounds(float width, float height) {
|
public void setBounds(float width, float height) {
|
||||||
@@ -368,13 +365,15 @@ public abstract class GameStage extends Stage {
|
|||||||
animationTimeout -= delta;
|
animationTimeout -= delta;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Array<PlayerModification> modsToRemove = new Array<>();
|
Array<PlayerModification> modsToRemove=new Array<>();
|
||||||
for (Map.Entry<PlayerModification, Float> mod : currentModifications.entrySet()) {
|
for(Map.Entry<PlayerModification, Float> mod:currentModifications.entrySet())
|
||||||
mod.setValue(mod.getValue() - delta);
|
{
|
||||||
if (mod.getValue() < 0)
|
mod.setValue(mod.getValue()-delta);
|
||||||
|
if(mod.getValue()<0)
|
||||||
modsToRemove.add(mod.getKey());
|
modsToRemove.add(mod.getKey());
|
||||||
}
|
}
|
||||||
for (PlayerModification mod : modsToRemove) {
|
for(PlayerModification mod:modsToRemove)
|
||||||
|
{
|
||||||
currentModifications.remove(mod);
|
currentModifications.remove(mod);
|
||||||
onRemoveEffect(mod);
|
onRemoveEffect(mod);
|
||||||
}
|
}
|
||||||
@@ -409,9 +408,10 @@ public abstract class GameStage extends Stage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onRemoveEffect(PlayerModification mod) {
|
private void onRemoveEffect(PlayerModification mod) {
|
||||||
switch (mod) {
|
switch (mod)
|
||||||
|
{
|
||||||
case Hide:
|
case Hide:
|
||||||
player.setColor(player.getColor().r, player.getColor().g, player.getColor().b, 1f);
|
player.setColor(player.getColor().r,player.getColor().g,player.getColor().b,1f);
|
||||||
break;
|
break;
|
||||||
case Fly:
|
case Fly:
|
||||||
player.removeEffect(Paths.EFFECT_FLY);
|
player.removeEffect(Paths.EFFECT_FLY);
|
||||||
@@ -430,16 +430,20 @@ public abstract class GameStage extends Stage {
|
|||||||
super.keyDown(keycode);
|
super.keyDown(keycode);
|
||||||
if (isPaused())
|
if (isPaused())
|
||||||
return true;
|
return true;
|
||||||
if (KeyBinding.Left.isPressed(keycode)) {
|
if (KeyBinding.Left.isPressed(keycode))
|
||||||
|
{
|
||||||
player.getMovementDirection().x = -1;
|
player.getMovementDirection().x = -1;
|
||||||
}
|
}
|
||||||
if (KeyBinding.Right.isPressed(keycode)) {
|
if (KeyBinding.Right.isPressed(keycode) )
|
||||||
|
{
|
||||||
player.getMovementDirection().x = +1;
|
player.getMovementDirection().x = +1;
|
||||||
}
|
}
|
||||||
if (KeyBinding.Up.isPressed(keycode)) {
|
if (KeyBinding.Up.isPressed(keycode))
|
||||||
|
{
|
||||||
player.getMovementDirection().y = +1;
|
player.getMovementDirection().y = +1;
|
||||||
}
|
}
|
||||||
if (KeyBinding.Down.isPressed(keycode)) {
|
if (KeyBinding.Down.isPressed(keycode))
|
||||||
|
{
|
||||||
player.getMovementDirection().y = -1;
|
player.getMovementDirection().y = -1;
|
||||||
}
|
}
|
||||||
if (keycode == Input.Keys.F5)//todo config
|
if (keycode == Input.Keys.F5)//todo config
|
||||||
@@ -479,8 +483,9 @@ public abstract class GameStage extends Stage {
|
|||||||
if (GameHUD.getInstance().isDebugMap()) {
|
if (GameHUD.getInstance().isDebugMap()) {
|
||||||
TileMapScene S = TileMapScene.instance();
|
TileMapScene S = TileMapScene.instance();
|
||||||
PointOfInterestData P = PointOfInterestData.getPointOfInterest("DEBUGZONE");
|
PointOfInterestData P = PointOfInterestData.getPointOfInterest("DEBUGZONE");
|
||||||
if (P != null) {
|
if( P != null)
|
||||||
PointOfInterest PoI = new PointOfInterest(P, new Vector2(0, 0), MyRandom.getRandom());
|
{
|
||||||
|
PointOfInterest PoI = new PointOfInterest(P,new Vector2(0,0), MyRandom.getRandom());
|
||||||
S.load(PoI);
|
S.load(PoI);
|
||||||
Forge.switchScene(S);
|
Forge.switchScene(S);
|
||||||
}
|
}
|
||||||
@@ -566,12 +571,14 @@ public abstract class GameStage extends Stage {
|
|||||||
public boolean keyUp(int keycode) {
|
public boolean keyUp(int keycode) {
|
||||||
if (isPaused())
|
if (isPaused())
|
||||||
return true;
|
return true;
|
||||||
if (KeyBinding.Left.isPressed(keycode) || KeyBinding.Right.isPressed(keycode)) {
|
if (KeyBinding.Left.isPressed(keycode)||KeyBinding.Right.isPressed(keycode))
|
||||||
|
{
|
||||||
player.getMovementDirection().x = 0;
|
player.getMovementDirection().x = 0;
|
||||||
if (!player.isMoving())
|
if (!player.isMoving())
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
if (KeyBinding.Down.isPressed(keycode) || KeyBinding.Up.isPressed(keycode)) {
|
if (KeyBinding.Down.isPressed(keycode)||KeyBinding.Up.isPressed(keycode))
|
||||||
|
{
|
||||||
player.getMovementDirection().y = 0;
|
player.getMovementDirection().y = 0;
|
||||||
if (!player.isMoving())
|
if (!player.isMoving())
|
||||||
stop();
|
stop();
|
||||||
@@ -651,16 +658,17 @@ public abstract class GameStage extends Stage {
|
|||||||
return Vector2.Zero.cpy();
|
return Vector2.Zero.cpy();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void teleported(Vector2 position) {
|
protected void teleported(Vector2 position)
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPosition(Vector2 position) {
|
public void setPosition(Vector2 position) {
|
||||||
getPlayerSprite().setPosition(position);
|
getPlayerSprite().setPosition(position);
|
||||||
teleported(position);
|
teleported(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resetPlayerLocation() {
|
public void resetPlayerLocation()
|
||||||
|
{
|
||||||
PointOfInterest poi = Current.world().findPointsOfInterest("Spawn");
|
PointOfInterest poi = Current.world().findPointsOfInterest("Spawn");
|
||||||
if (poi != null) {
|
if (poi != null) {
|
||||||
Forge.advFreezePlayerControls = true;
|
Forge.advFreezePlayerControls = true;
|
||||||
@@ -669,7 +677,7 @@ public abstract class GameStage extends Stage {
|
|||||||
Timer.schedule(new Timer.Task() {
|
Timer.schedule(new Timer.Task() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
showImageDialog(Current.generateDefeatMessage(true), getDefeatBadge(),
|
showImageDialog(Current.generateDefeatMessage(), getDefeatBadge(),
|
||||||
() -> FThreads.invokeInEdtNowOrLater(() -> Forge.setTransitionScreen(new CoverScreen(() -> {
|
() -> FThreads.invokeInEdtNowOrLater(() -> Forge.setTransitionScreen(new CoverScreen(() -> {
|
||||||
Forge.advFreezePlayerControls = false;
|
Forge.advFreezePlayerControls = false;
|
||||||
WorldStage.getInstance().setPosition(new Vector2(poi.getPosition().x - 16f, poi.getPosition().y + 16f));
|
WorldStage.getInstance().setPosition(new Vector2(poi.getPosition().x - 16f, poi.getPosition().y + 16f));
|
||||||
@@ -681,21 +689,6 @@ public abstract class GameStage extends Stage {
|
|||||||
}, 1f);
|
}, 1f);
|
||||||
}//Spawn shouldn't be null
|
}//Spawn shouldn't be null
|
||||||
}
|
}
|
||||||
|
|
||||||
public void defeatedFromBoss() {
|
|
||||||
if (!Current.player().hasEquippedItem())
|
|
||||||
return;
|
|
||||||
Forge.advFreezePlayerControls = true;
|
|
||||||
getPlayerSprite().setAnimation(CharacterSprite.AnimationTypes.Hit);
|
|
||||||
getPlayerSprite().playEffect(Paths.EFFECT_BLOOD, 0.5f);
|
|
||||||
Timer.schedule(new Timer.Task() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
showImageDialog(Current.generateDefeatMessage(false), getDefeatBadge(), () -> Forge.advFreezePlayerControls = false);
|
|
||||||
}
|
|
||||||
}, 1f);
|
|
||||||
}
|
|
||||||
|
|
||||||
private FBufferedImage getDefeatBadge() {
|
private FBufferedImage getDefeatBadge() {
|
||||||
FileHandle defeat = Config.instance().getFile("ui/defeat.png");
|
FileHandle defeat = Config.instance().getFile("ui/defeat.png");
|
||||||
if (defeat.exists()) {
|
if (defeat.exists()) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
package forge.adventure.stage;
|
package forge.adventure.stage;
|
||||||
|
|
||||||
public interface IAfterMatch {
|
public interface IAfterMatch {
|
||||||
void setWinner(boolean winner, boolean isArena);
|
void setWinner(boolean winner);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -606,7 +606,7 @@ public class MapStage extends GameStage {
|
|||||||
}));
|
}));
|
||||||
break;
|
break;
|
||||||
case "exit":
|
case "exit":
|
||||||
addMapActor(obj, new OnCollide(() -> MapStage.this.exitDungeon(false, false)));
|
addMapActor(obj, new OnCollide(() -> MapStage.this.exitDungeon(false)));
|
||||||
break;
|
break;
|
||||||
case "dialog":
|
case "dialog":
|
||||||
if (obj instanceof TiledMapTileMapObject) {
|
if (obj instanceof TiledMapTileMapObject) {
|
||||||
@@ -750,7 +750,7 @@ public class MapStage extends GameStage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean exitDungeon(boolean defeated, boolean defeatedByBoss) {
|
public boolean exitDungeon(boolean defeated) {
|
||||||
AdventureQuestController.instance().updateQuestsLeave();
|
AdventureQuestController.instance().updateQuestsLeave();
|
||||||
clearIsInMap();
|
clearIsInMap();
|
||||||
AdventureQuestController.instance().showQuestDialogs(this);
|
AdventureQuestController.instance().showQuestDialogs(this);
|
||||||
@@ -758,8 +758,6 @@ public class MapStage extends GameStage {
|
|||||||
effect = null; //Reset dungeon effects.
|
effect = null; //Reset dungeon effects.
|
||||||
if (defeated)
|
if (defeated)
|
||||||
WorldStage.getInstance().resetPlayerLocation();
|
WorldStage.getInstance().resetPlayerLocation();
|
||||||
else if (defeatedByBoss)
|
|
||||||
WorldStage.getInstance().defeatedFromBoss();
|
|
||||||
Forge.switchScene(GameScene.instance());
|
Forge.switchScene(GameScene.instance());
|
||||||
isPlayerLeavingDungeon = false;
|
isPlayerLeavingDungeon = false;
|
||||||
dialogOnlyInput = false;
|
dialogOnlyInput = false;
|
||||||
@@ -768,7 +766,7 @@ public class MapStage extends GameStage {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setWinner(boolean playerWins, boolean isArena) {
|
public void setWinner(boolean playerWins) {
|
||||||
isLoadingMatch = false;
|
isLoadingMatch = false;
|
||||||
freezeAllEnemyBehaviors = true;
|
freezeAllEnemyBehaviors = true;
|
||||||
if (playerWins) {
|
if (playerWins) {
|
||||||
@@ -807,16 +805,16 @@ public class MapStage extends GameStage {
|
|||||||
boolean defeated = Current.player().defeated();
|
boolean defeated = Current.player().defeated();
|
||||||
//If hardcore mode is added, check and redirect to game over screen here
|
//If hardcore mode is added, check and redirect to game over screen here
|
||||||
if (canFailDungeon && !defeated)
|
if (canFailDungeon && !defeated)
|
||||||
dungeonFailedDialog(true, currentMob.getData().boss && !isArena);
|
dungeonFailedDialog(true);
|
||||||
else
|
else
|
||||||
exitDungeon(defeated, currentMob.getData().boss && !isArena);
|
exitDungeon(defeated);
|
||||||
MapStage.this.stop();
|
MapStage.this.stop();
|
||||||
currentMob = null;
|
currentMob = null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dungeonFailedDialog(boolean exit, boolean defeatedByBoss) {
|
private void dungeonFailedDialog(boolean exit) {
|
||||||
dialog.getButtonTable().clear();
|
dialog.getButtonTable().clear();
|
||||||
dialog.getContentTable().clear();
|
dialog.getContentTable().clear();
|
||||||
dialog.clearListeners();
|
dialog.clearListeners();
|
||||||
@@ -836,7 +834,7 @@ public class MapStage extends GameStage {
|
|||||||
L.skipToTheEnd();
|
L.skipToTheEnd();
|
||||||
super.clicked(event, x, y);
|
super.clicked(event, x, y);
|
||||||
if (exit)
|
if (exit)
|
||||||
exitDungeon(false, defeatedByBoss);
|
exitDungeon(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
dialog.getButtonTable().add(ok).width(240f);
|
dialog.getButtonTable().add(ok).width(240f);
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ public class WorldStage extends GameStage implements SaveFileContent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setWinner(boolean playerIsWinner, boolean isArena) {
|
public void setWinner(boolean playerIsWinner) {
|
||||||
if (playerIsWinner) {
|
if (playerIsWinner) {
|
||||||
currentMob.clearCollisionHeight();
|
currentMob.clearCollisionHeight();
|
||||||
Current.player().win();
|
Current.player().win();
|
||||||
@@ -192,13 +192,10 @@ public class WorldStage extends GameStage implements SaveFileContent {
|
|||||||
boolean defeated = Current.player().defeated();
|
boolean defeated = Current.player().defeated();
|
||||||
AdventureQuestController.instance().updateQuestsLose(currentMob);
|
AdventureQuestController.instance().updateQuestsLose(currentMob);
|
||||||
AdventureQuestController.instance().showQuestDialogs(MapStage.getInstance());
|
AdventureQuestController.instance().showQuestDialogs(MapStage.getInstance());
|
||||||
boolean defeatedFromBoss = currentMob.getData().boss && !isArena;
|
|
||||||
WorldStage.this.removeEnemy(currentMob);
|
WorldStage.this.removeEnemy(currentMob);
|
||||||
currentMob = null;
|
currentMob = null;
|
||||||
if (defeated) {
|
if (defeated) {
|
||||||
WorldStage.getInstance().resetPlayerLocation();
|
WorldStage.getInstance().resetPlayerLocation();
|
||||||
} else if (defeatedFromBoss) {
|
|
||||||
WorldStage.getInstance().defeatedFromBoss();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -809,11 +809,6 @@ public class CardUtil {
|
|||||||
return generateBoosterPackAsDeck(edition);
|
return generateBoosterPackAsDeck(edition);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PaperCard getReplacement(String missingCard, String replacementCard) {
|
|
||||||
System.err.println(missingCard + " : Not found in the database.\nReplacement card: " + replacementCard);
|
|
||||||
return FModel.getMagicDb().getCommonCards().getCard(replacementCard);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static PaperCard getCardByName(String cardName) {
|
public static PaperCard getCardByName(String cardName) {
|
||||||
List<PaperCard> validCards;
|
List<PaperCard> validCards;
|
||||||
//Faster to ask the CardDB for a card name than it is to search the pool.
|
//Faster to ask the CardDB for a card name than it is to search the pool.
|
||||||
@@ -822,10 +817,6 @@ public class CardUtil {
|
|||||||
else
|
else
|
||||||
validCards = FModel.getMagicDb().getCommonCards().getUniqueCardsNoAlt(cardName);
|
validCards = FModel.getMagicDb().getCommonCards().getUniqueCardsNoAlt(cardName);
|
||||||
|
|
||||||
if (validCards.isEmpty()) {
|
|
||||||
return getReplacement(cardName, "Wastes");
|
|
||||||
}
|
|
||||||
|
|
||||||
return validCards.get(Current.world().getRandom().nextInt(validCards.size()));
|
return validCards.get(Current.world().getRandom().nextInt(validCards.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -837,7 +828,7 @@ public class CardUtil {
|
|||||||
.filter(input -> input.getEdition().equals(edition)).collect(Collectors.toList());
|
.filter(input -> input.getEdition().equals(edition)).collect(Collectors.toList());
|
||||||
|
|
||||||
if (validCards.isEmpty()) {
|
if (validCards.isEmpty()) {
|
||||||
System.err.println("Unexpected behavior: tried to call getCardByNameAndEdition for card " + cardName + " from the edition " + edition + ", but didn't find it in the DB. A random existing instance will be returned if found.");
|
System.err.println("Unexpected behavior: tried to call getCardByNameAndEdition for card " + cardName + " from the edition " + edition + ", but didn't find it in the DB. A random existing instance will be returned.");
|
||||||
return getCardByName(cardName);
|
return getCardByName(cardName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,9 +27,8 @@ public class Current {
|
|||||||
public static void setLatestDeck(Deck generateDeck) {
|
public static void setLatestDeck(Deck generateDeck) {
|
||||||
deck=generateDeck;
|
deck=generateDeck;
|
||||||
}
|
}
|
||||||
public static String generateDefeatMessage(boolean hasDied) {
|
public static String generateDefeatMessage() {
|
||||||
String key = hasDied ? "lblYouDied" : "lblYouLostTheLastGame";
|
String message = Forge.getLocalizer().getMessage("lblYouDied", player().getName());
|
||||||
String message = Forge.getLocalizer().getMessage(key, player().getName());
|
|
||||||
ItemData itemData = player().getRandomEquippedItem();
|
ItemData itemData = player().getRandomEquippedItem();
|
||||||
if (itemData != null) {
|
if (itemData != null) {
|
||||||
itemData.isCracked = true;
|
itemData.isCracked = true;
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ public class AddBasicLandsDialog extends FDialog {
|
|||||||
private final Consumer<CardPool> callback;
|
private final Consumer<CardPool> callback;
|
||||||
|
|
||||||
private final FLabel lblLandSet = add(new FLabel.Builder().text(Forge.getLocalizer().getMessage("lblLandSet") + ":").font(FSkinFont.get(12)).textColor(FLabel.getInlineLabelColor()).build());
|
private final FLabel lblLandSet = add(new FLabel.Builder().text(Forge.getLocalizer().getMessage("lblLandSet") + ":").font(FSkinFont.get(12)).textColor(FLabel.getInlineLabelColor()).build());
|
||||||
private final FComboBox<CardEdition> cbLandSet = add(new FComboBox<>(IterableUtil.filter(StaticData.instance().getSortedEditions(), CardEdition::hasBasicLands)));
|
private final FComboBox<CardEdition> cbLandSet = add(new FComboBox<>(IterableUtil.filter(StaticData.instance().getEditions(), CardEdition.Predicates.hasBasicLands)));
|
||||||
|
|
||||||
private final FScrollPane scroller = add(new FScrollPane() {
|
private final FScrollPane scroller = add(new FScrollPane() {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -81,21 +81,13 @@ public class FDeckEditor extends TabPageScreen<FDeckEditor> {
|
|||||||
public boolean allowsCardReplacement() { return hasInfiniteCardPool() || usePlayerInventory(); }
|
public boolean allowsCardReplacement() { return hasInfiniteCardPool() || usePlayerInventory(); }
|
||||||
|
|
||||||
public List<CardEdition> getBasicLandSets(Deck currentDeck) {
|
public List<CardEdition> getBasicLandSets(Deck currentDeck) {
|
||||||
if(hasInfiniteCardPool())
|
|
||||||
return FModel.getMagicDb().getSortedEditions().stream().filter(CardEdition::hasBasicLands).collect(Collectors.toList());
|
|
||||||
return List.of(DeckProxy.getDefaultLandSet(currentDeck));
|
return List.of(DeckProxy.getDefaultLandSet(currentDeck));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract IDeckController getController();
|
protected abstract IDeckController getController();
|
||||||
protected abstract DeckEditorPage[] getInitialPages();
|
protected abstract DeckEditorPage[] getInitialPages();
|
||||||
|
|
||||||
public DeckSection[] getPrimarySections() {
|
protected DeckSection[] getExtraSections() {
|
||||||
if(getGameType() != null)
|
|
||||||
return getGameType().getPrimaryDeckSections().toArray(new DeckSection[0]);
|
|
||||||
return new DeckSection[]{DeckSection.Main, DeckSection.Sideboard};
|
|
||||||
}
|
|
||||||
|
|
||||||
public DeckSection[] getExtraSections() {
|
|
||||||
if(getGameType() != null)
|
if(getGameType() != null)
|
||||||
return getGameType().getSupplimentalDeckSections().toArray(new DeckSection[0]);
|
return getGameType().getSupplimentalDeckSections().toArray(new DeckSection[0]);
|
||||||
return new DeckSection[]{DeckSection.Attractions, DeckSection.Contraptions};
|
return new DeckSection[]{DeckSection.Attractions, DeckSection.Contraptions};
|
||||||
@@ -152,7 +144,7 @@ public class FDeckEditor extends TabPageScreen<FDeckEditor> {
|
|||||||
ItemManagerConfig catalogConfig = null;
|
ItemManagerConfig catalogConfig = null;
|
||||||
ItemManagerConfig mainSectionConfig = null;
|
ItemManagerConfig mainSectionConfig = null;
|
||||||
ItemManagerConfig sideboardConfig = null;
|
ItemManagerConfig sideboardConfig = null;
|
||||||
Function<Deck, Collection<CardEdition>> fnGetBasicLandSet = null;
|
Function<Deck, CardEdition> fnGetBasicLandSet = null;
|
||||||
Supplier<ItemPool<PaperCard>> itemPoolSupplier = null;
|
Supplier<ItemPool<PaperCard>> itemPoolSupplier = null;
|
||||||
String catalogCaption = null;
|
String catalogCaption = null;
|
||||||
|
|
||||||
@@ -204,7 +196,7 @@ public class FDeckEditor extends TabPageScreen<FDeckEditor> {
|
|||||||
this.sideboardConfig = sideboardConfig;
|
this.sideboardConfig = sideboardConfig;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public GameTypeDeckEditorConfig setBasicLandSetFunction(Function<Deck, Collection<CardEdition>> fnGetBasicLandSet) {
|
public GameTypeDeckEditorConfig setBasicLandSetFunction(Function<Deck, CardEdition> fnGetBasicLandSet) {
|
||||||
this.fnGetBasicLandSet = fnGetBasicLandSet;
|
this.fnGetBasicLandSet = fnGetBasicLandSet;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -304,21 +296,9 @@ public class FDeckEditor extends TabPageScreen<FDeckEditor> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DeckSection[] getPrimarySections() {
|
protected DeckSection[] getExtraSections() {
|
||||||
return gameType.getPrimaryDeckSections().toArray(new DeckSection[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DeckSection[] getExtraSections() {
|
|
||||||
return gameType.getSupplimentalDeckSections().toArray(new DeckSection[0]);
|
return gameType.getSupplimentalDeckSections().toArray(new DeckSection[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<CardEdition> getBasicLandSets(Deck currentDeck) {
|
|
||||||
if(this.fnGetBasicLandSet != null)
|
|
||||||
return List.copyOf(fnGetBasicLandSet.apply(currentDeck));
|
|
||||||
return super.getBasicLandSets(currentDeck);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DeckEditorConfig EditorConfigConstructed = new GameTypeDeckEditorConfig(GameType.Constructed,
|
public static DeckEditorConfig EditorConfigConstructed = new GameTypeDeckEditorConfig(GameType.Constructed,
|
||||||
@@ -368,19 +348,18 @@ public class FDeckEditor extends TabPageScreen<FDeckEditor> {
|
|||||||
.setMainSectionConfig(ItemManagerConfig.QUEST_DECK_EDITOR)
|
.setMainSectionConfig(ItemManagerConfig.QUEST_DECK_EDITOR)
|
||||||
.setSideboardConfig(ItemManagerConfig.QUEST_DECK_EDITOR)
|
.setSideboardConfig(ItemManagerConfig.QUEST_DECK_EDITOR)
|
||||||
.setPlayerInventorySupplier(() -> FModel.getQuest().getCards().getCardpool())
|
.setPlayerInventorySupplier(() -> FModel.getQuest().getCards().getCardpool())
|
||||||
.setBasicLandSetFunction(d -> FModel.getQuest().getAvailableLandSets());
|
.setBasicLandSetFunction(d -> FModel.getQuest().getDefaultLandSet());
|
||||||
public static DeckEditorConfig EditorConfigQuestCommander = new GameTypeDeckEditorConfig(GameType.QuestCommander, DECK_CONTROLLER_QUEST)
|
public static DeckEditorConfig EditorConfigQuestCommander = new GameTypeDeckEditorConfig(GameType.QuestCommander, DECK_CONTROLLER_QUEST)
|
||||||
.setCatalogConfig(ItemManagerConfig.QUEST_EDITOR_POOL)
|
.setCatalogConfig(ItemManagerConfig.QUEST_EDITOR_POOL)
|
||||||
.setMainSectionConfig(ItemManagerConfig.QUEST_DECK_EDITOR)
|
.setMainSectionConfig(ItemManagerConfig.QUEST_DECK_EDITOR)
|
||||||
.setSideboardConfig(ItemManagerConfig.QUEST_DECK_EDITOR)
|
.setSideboardConfig(ItemManagerConfig.QUEST_DECK_EDITOR)
|
||||||
.setPlayerInventorySupplier(() -> FModel.getQuest().getCards().getCardpool())
|
.setPlayerInventorySupplier(() -> FModel.getQuest().getCards().getCardpool())
|
||||||
.setBasicLandSetFunction(d -> FModel.getQuest().getAvailableLandSets());
|
.setBasicLandSetFunction(d -> FModel.getQuest().getDefaultLandSet());
|
||||||
public static DeckEditorConfig EditorConfigQuestDraft = new GameTypeDeckEditorConfig(GameType.QuestDraft, DECK_CONTROLLER_QUEST_DRAFT);
|
public static DeckEditorConfig EditorConfigQuestDraft = new GameTypeDeckEditorConfig(GameType.QuestDraft, DECK_CONTROLLER_QUEST_DRAFT);
|
||||||
public static DeckEditorConfig EditorConfigPlanarConquest = new GameTypeDeckEditorConfig(GameType.PlanarConquest, DECK_CONTROLLER_PLANAR_CONQUEST)
|
public static DeckEditorConfig EditorConfigPlanarConquest = new GameTypeDeckEditorConfig(GameType.PlanarConquest, DECK_CONTROLLER_PLANAR_CONQUEST)
|
||||||
.setCatalogConfig(ItemManagerConfig.CONQUEST_COLLECTION)
|
.setCatalogConfig(ItemManagerConfig.CONQUEST_COLLECTION)
|
||||||
.setMainSectionConfig(ItemManagerConfig.CONQUEST_DECK_EDITOR)
|
.setMainSectionConfig(ItemManagerConfig.CONQUEST_DECK_EDITOR)
|
||||||
.setPlayerInventorySupplier(ConquestUtil::getAvailablePool)
|
.setPlayerInventorySupplier(ConquestUtil::getAvailablePool);
|
||||||
.setBasicLandSetFunction(ConquestUtil::getBasicLandSets);
|
|
||||||
|
|
||||||
protected static DeckSectionPage createPageForExtraSection(DeckSection deckSection, DeckEditorConfig editorConfig) {
|
protected static DeckSectionPage createPageForExtraSection(DeckSection deckSection, DeckEditorConfig editorConfig) {
|
||||||
CardManager cm = new CardManager(false);
|
CardManager cm = new CardManager(false);
|
||||||
@@ -563,7 +542,7 @@ public class FDeckEditor extends TabPageScreen<FDeckEditor> {
|
|||||||
@Override
|
@Override
|
||||||
protected void buildMenu() {
|
protected void buildMenu() {
|
||||||
final Localizer localizer = Forge.getLocalizer();
|
final Localizer localizer = Forge.getLocalizer();
|
||||||
if (allowAddBasic())
|
if (allowsAddBasic())
|
||||||
addItem(new FMenuItem(localizer.getMessage("lblAddBasicLands"), FSkinImage.LANDLOGO, e -> showAddBasicLandsDialog()));
|
addItem(new FMenuItem(localizer.getMessage("lblAddBasicLands"), FSkinImage.LANDLOGO, e -> showAddBasicLandsDialog()));
|
||||||
if (showAddExtraSectionOption()) {
|
if (showAddExtraSectionOption()) {
|
||||||
addItem(new FMenuItem(localizer.getMessage("lblAddDeckSection"), FSkinImage.CHAOS, e -> {
|
addItem(new FMenuItem(localizer.getMessage("lblAddDeckSection"), FSkinImage.CHAOS, e -> {
|
||||||
@@ -579,41 +558,28 @@ public class FDeckEditor extends TabPageScreen<FDeckEditor> {
|
|||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
if (editorConfig.hasInfiniteCardPool() || editorConfig.usePlayerInventory()) {
|
if (editorConfig.getGameType() != null && editorConfig.hasInfiniteCardPool()) {
|
||||||
addItem(new FMenuItem(localizer.getMessage("lblImportFromClipboard"), Forge.hdbuttons ? FSkinImage.HDIMPORT : FSkinImage.OPEN, e -> {
|
addItem(new FMenuItem(localizer.getMessage("lblImportFromClipboard"), Forge.hdbuttons ? FSkinImage.HDIMPORT : FSkinImage.OPEN, e -> {
|
||||||
FDeckImportDialog dialog = new FDeckImportDialog(deck, FDeckEditor.this.editorConfig);
|
FDeckImportDialog dialog = new FDeckImportDialog(!deck.isEmpty(), FDeckEditor.this.editorConfig);
|
||||||
if(editorConfig.usePlayerInventory())
|
|
||||||
dialog.setFreePrintConverter(FDeckEditor.this::supplyPrintForImporter);
|
|
||||||
dialog.setImportBannedCards(!FModel.getPreferences().getPrefBoolean(FPref.ENFORCE_DECK_LEGALITY));
|
|
||||||
dialog.setCallback(importedDeck -> {
|
dialog.setCallback(importedDeck -> {
|
||||||
if (deck != null && importedDeck.hasName()) {
|
if (deck != null && importedDeck.hasName()) {
|
||||||
deck.setName(importedDeck.getName());
|
deck.setName(importedDeck.getName());
|
||||||
setHeaderText(importedDeck.getName());
|
setHeaderText(importedDeck.getName());
|
||||||
}
|
}
|
||||||
switch (dialog.getImportBehavior()) {
|
if (dialog.createNewDeck()) {
|
||||||
case REPLACE_CURRENT:
|
for (Entry<DeckSection, CardPool> section : importedDeck) {
|
||||||
for(DeckSectionPage page : pagesBySection.values()) {
|
DeckSectionPage page = getPageForSection(section.getKey());
|
||||||
if(importedDeck.has(page.deckSection)) {
|
if (page != null)
|
||||||
page.setCards(importedDeck.get(page.deckSection));
|
page.setCards(section.getValue());
|
||||||
if(hiddenExtraSections.contains(page.deckSection))
|
}
|
||||||
showExtraSectionTab(page.deckSection);
|
} else {
|
||||||
}
|
for (Entry<DeckSection, CardPool> section : importedDeck) {
|
||||||
else
|
DeckSectionPage page = getPageForSection(section.getKey());
|
||||||
page.setCards(new CardPool());
|
if (page != null)
|
||||||
}
|
page.addCards(section.getValue());
|
||||||
break;
|
}
|
||||||
case CREATE_NEW:
|
|
||||||
deckController.setDeck(importedDeck);
|
|
||||||
break;
|
|
||||||
case MERGE:
|
|
||||||
for (Entry<DeckSection, CardPool> section : importedDeck) {
|
|
||||||
DeckSectionPage page = getPageForSection(section.getKey());
|
|
||||||
if (page != null)
|
|
||||||
page.addCards(section.getValue());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
dialog.initParse();
|
|
||||||
dialog.show();
|
dialog.show();
|
||||||
setSelectedPage(getMainDeckPage()); //select main deck page if needed so main deck if visible below dialog
|
setSelectedPage(getMainDeckPage()); //select main deck page if needed so main deck if visible below dialog
|
||||||
}));
|
}));
|
||||||
@@ -677,20 +643,6 @@ public class FDeckEditor extends TabPageScreen<FDeckEditor> {
|
|||||||
getMainDeckPage().addCards(landsToAdd);
|
getMainDeckPage().addCards(landsToAdd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* If a card is missing from a player's inventory while importing a deck, it gets run through here.
|
|
||||||
* Returning a PaperCard will let unlimited copies of that card be used as a substitute. Returning null
|
|
||||||
* will leave the card missing from the import.
|
|
||||||
*/
|
|
||||||
protected PaperCard supplyPrintForImporter(PaperCard missingCard) {
|
|
||||||
//Could support dungeons here too? Not that we really use them in the editor...
|
|
||||||
if(!missingCard.isVeryBasicLand())
|
|
||||||
return null;
|
|
||||||
List<CardEdition> basicSets = editorConfig.getBasicLandSets(deck);
|
|
||||||
String setCode = basicSets.isEmpty() ? "JMP" : basicSets.get(0).getCode();
|
|
||||||
return FModel.getMagicDb().fetchCard(missingCard.getCardName(), setCode, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean shouldEnforceConformity() {
|
protected boolean shouldEnforceConformity() {
|
||||||
if(FModel.getPreferences().getPrefBoolean(FPref.ENFORCE_DECK_LEGALITY))
|
if(FModel.getPreferences().getPrefBoolean(FPref.ENFORCE_DECK_LEGALITY))
|
||||||
return true;
|
return true;
|
||||||
@@ -743,9 +695,6 @@ public class FDeckEditor extends TabPageScreen<FDeckEditor> {
|
|||||||
showExtraSectionTab(section);
|
showExtraSectionTab(section);
|
||||||
if(pagesBySection.containsKey(section))
|
if(pagesBySection.containsKey(section))
|
||||||
setSelectedPage(pagesBySection.get(section));
|
setSelectedPage(pagesBySection.get(section));
|
||||||
else if(section == DeckSection.Main && pagesBySection.containsKey(mainDeckPage.deckSection))
|
|
||||||
//Tried to switch to the Main page in a Planar or Scheme deck.
|
|
||||||
setSelectedPage(pagesBySection.get(mainDeckPage.deckSection));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notifyNewControllerModel() {
|
public void notifyNewControllerModel() {
|
||||||
@@ -1078,7 +1027,7 @@ public class FDeckEditor extends TabPageScreen<FDeckEditor> {
|
|||||||
protected boolean allowSaveAs() {
|
protected boolean allowSaveAs() {
|
||||||
return allowSave() && allowRename();
|
return allowSave() && allowRename();
|
||||||
}
|
}
|
||||||
protected boolean allowAddBasic() {
|
protected boolean allowsAddBasic() {
|
||||||
return !isDrafting();
|
return !isDrafting();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,12 +18,11 @@
|
|||||||
package forge.deck;
|
package forge.deck;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.EnumSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import forge.Forge;
|
import forge.Forge;
|
||||||
import forge.Graphics;
|
import forge.Graphics;
|
||||||
@@ -32,15 +31,11 @@ import forge.deck.DeckRecognizer.TokenType;
|
|||||||
import forge.game.GameType;
|
import forge.game.GameType;
|
||||||
import forge.gui.FThreads;
|
import forge.gui.FThreads;
|
||||||
import forge.gui.util.SOptionPane;
|
import forge.gui.util.SOptionPane;
|
||||||
import forge.item.PaperCard;
|
|
||||||
import forge.toolbox.FCheckBox;
|
import forge.toolbox.FCheckBox;
|
||||||
import forge.toolbox.FComboBox;
|
import forge.toolbox.FComboBox;
|
||||||
import forge.toolbox.FDialog;
|
import forge.toolbox.FDialog;
|
||||||
import forge.toolbox.FOptionPane;
|
import forge.toolbox.FOptionPane;
|
||||||
import forge.toolbox.FTextArea;
|
import forge.toolbox.FTextArea;
|
||||||
import forge.util.ItemPool;
|
|
||||||
import forge.util.Localizer;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
|
|
||||||
public class FDeckImportDialog extends FDialog {
|
public class FDeckImportDialog extends FDialog {
|
||||||
@@ -50,7 +45,7 @@ public class FDeckImportDialog extends FDialog {
|
|||||||
private final FCheckBox newEditionCheck = add(new FCheckBox(Forge.getLocalizer().getMessage("lblImportLatestVersionCard"), false));
|
private final FCheckBox newEditionCheck = add(new FCheckBox(Forge.getLocalizer().getMessage("lblImportLatestVersionCard"), false));
|
||||||
private final FCheckBox dateTimeCheck = add(new FCheckBox(Forge.getLocalizer().getMessage("lblUseOnlySetsReleasedBefore"), false));
|
private final FCheckBox dateTimeCheck = add(new FCheckBox(Forge.getLocalizer().getMessage("lblUseOnlySetsReleasedBefore"), false));
|
||||||
private final FCheckBox smartCardArtCheck = add(new FCheckBox(Forge.getLocalizer().getMessage("lblUseSmartCardArt"), false));
|
private final FCheckBox smartCardArtCheck = add(new FCheckBox(Forge.getLocalizer().getMessage("lblUseSmartCardArt"), false));
|
||||||
private final FCheckBox createNewDeckCheck = add(new FCheckBox(Forge.getLocalizer().getMessage("lblReplaceDeckCheckbox"), false));
|
private final FCheckBox createNewDeckCheck = add(new FCheckBox(Forge.getLocalizer().getMessage("lblNewDeckCheckbox"), false));
|
||||||
// private final FCheckBox importInDeck = add(new FCheckBox()
|
// private final FCheckBox importInDeck = add(new FCheckBox()
|
||||||
/*setting onlyCoreExpCheck to false allow the copied cards to pass the check of deck contents
|
/*setting onlyCoreExpCheck to false allow the copied cards to pass the check of deck contents
|
||||||
forge-core\src\main\java\forge\deck\Deck.javaDeck.java starting @ Line 320 which is called by
|
forge-core\src\main\java\forge\deck\Deck.javaDeck.java starting @ Line 320 which is called by
|
||||||
@@ -62,60 +57,100 @@ public class FDeckImportDialog extends FDialog {
|
|||||||
private final FComboBox<String> monthDropdown = add(new FComboBox<>()); //don't need wrappers since skin can't change while this dialog is open
|
private final FComboBox<String> monthDropdown = add(new FComboBox<>()); //don't need wrappers since skin can't change while this dialog is open
|
||||||
private final FComboBox<Integer> yearDropdown = add(new FComboBox<>());
|
private final FComboBox<Integer> yearDropdown = add(new FComboBox<>());
|
||||||
|
|
||||||
private boolean showOptions;
|
private final boolean showOptions;
|
||||||
private final Deck currentDeck;
|
private final boolean currentDeckIsEmpty;
|
||||||
private boolean createNewDeckControl;
|
private boolean createNewDeckControl;
|
||||||
private final DeckImportController controller;
|
private final DeckImportController controller;
|
||||||
private final FDeckEditor.DeckEditorConfig editorConfig;
|
|
||||||
|
|
||||||
private final static ImmutableList<String> importOrCancel = ImmutableList.of(Forge.getLocalizer().getMessage("lblImport"), Forge.getLocalizer().getMessage("lblCancel"));
|
private final static ImmutableList<String> importOrCancel = ImmutableList.of(Forge.getLocalizer().getMessage("lblImport"), Forge.getLocalizer().getMessage("lblCancel"));
|
||||||
|
|
||||||
public FDeckImportDialog(final Deck currentDeck, final FDeckEditor.DeckEditorConfig editorConfig) {
|
public FDeckImportDialog(final boolean replacingDeck, final FDeckEditor.DeckEditorConfig editorConfig) {
|
||||||
super(Forge.getLocalizer().getMessage("lblImportFromClipboard"), 2);
|
super(Forge.getLocalizer().getMessage("lblImportFromClipboard"), 2);
|
||||||
boolean usingInventory = editorConfig.usePlayerInventory();
|
|
||||||
boolean replacingDeck = !currentDeck.isEmpty() || usingInventory;
|
|
||||||
this.currentDeck = currentDeck;
|
|
||||||
this.editorConfig = editorConfig;
|
|
||||||
ItemPool<PaperCard> cardPool = editorConfig.getCardPool(false);
|
|
||||||
controller = new DeckImportController(dateTimeCheck, monthDropdown, yearDropdown, replacingDeck);
|
controller = new DeckImportController(dateTimeCheck, monthDropdown, yearDropdown, replacingDeck);
|
||||||
String contents = Forge.getClipboard().getContents();
|
String contents = Forge.getClipboard().getContents();
|
||||||
if (contents == null)
|
if (contents == null)
|
||||||
contents = ""; //prevent NPE
|
contents = ""; //prevent NPE
|
||||||
txtInput.setText(contents);
|
txtInput.setText(contents);
|
||||||
|
|
||||||
GameType gameType = editorConfig.getGameType();
|
if (editorConfig.allowsCardReplacement()) {
|
||||||
controller.setGameFormat(gameType);
|
GameType gameType = editorConfig.getGameType();
|
||||||
List<DeckSection> supportedSections = new ArrayList<>();
|
controller.setGameFormat(gameType);
|
||||||
supportedSections.addAll(List.of(editorConfig.getPrimarySections()));
|
List<DeckSection> supportedSections = new ArrayList<>();
|
||||||
supportedSections.addAll(List.of(editorConfig.getExtraSections()));
|
supportedSections.add(DeckSection.Main);
|
||||||
controller.setAllowedSections(supportedSections);
|
supportedSections.add(DeckSection.Sideboard);
|
||||||
controller.setCurrentDeckInEditor(currentDeck);
|
if (editorConfig.hasCommander())
|
||||||
if(usingInventory)
|
supportedSections.add(DeckSection.Commander);
|
||||||
controller.setPlayerInventory(cardPool);
|
supportedSections.addAll(Lists.newArrayList(editorConfig.getExtraSections()));
|
||||||
|
controller.setAllowedSections(supportedSections);
|
||||||
|
}
|
||||||
|
|
||||||
onlyCoreExpCheck.setSelected(StaticData.instance().isCoreExpansionOnlyFilterSet());
|
onlyCoreExpCheck.setSelected(StaticData.instance().isCoreExpansionOnlyFilterSet());
|
||||||
newEditionCheck.setSelected(StaticData.instance().cardArtPreferenceIsLatest());
|
newEditionCheck.setSelected(StaticData.instance().cardArtPreferenceIsLatest());
|
||||||
smartCardArtCheck.setSelected(StaticData.instance().isEnabledCardArtSmartSelection());
|
smartCardArtCheck.setSelected(StaticData.instance().isEnabledCardArtSmartSelection());
|
||||||
createNewDeckCheck.setSelected(replacingDeck);
|
createNewDeckCheck.setSelected(replacingDeck);
|
||||||
|
this.currentDeckIsEmpty = !replacingDeck;
|
||||||
this.createNewDeckControl = replacingDeck;
|
this.createNewDeckControl = replacingDeck;
|
||||||
|
|
||||||
if(usingInventory)
|
initButton(0, Forge.getLocalizer().getMessage("lblImport"), e -> FThreads.invokeInBackgroundThread(() -> {
|
||||||
controller.setImportBehavior(DeckImportController.ImportBehavior.REPLACE_CURRENT);
|
List<DeckRecognizer.Token> tokens = controller.parseInput(txtInput.getText()); //ensure deck updated based on any changes to options
|
||||||
else
|
|
||||||
controller.setImportBehavior(createNewDeckControl ? DeckImportController.ImportBehavior.CREATE_NEW : DeckImportController.ImportBehavior.MERGE);
|
|
||||||
|
|
||||||
initButton(0, Forge.getLocalizer().getMessage("lblImport"), e -> FThreads.invokeInBackgroundThread(this::performImport));
|
if (controller.isSmartCardArtEnabled())
|
||||||
|
tokens = controller.optimiseCardArtInTokens();
|
||||||
|
|
||||||
|
//if there are any cards that cannot be imported, let user know this and give them the option to cancel
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (DeckRecognizer.Token token : tokens) {
|
||||||
|
if (token.getType() == TokenType.CARD_FROM_NOT_ALLOWED_SET
|
||||||
|
|| token.getType() == TokenType.CARD_FROM_INVALID_SET
|
||||||
|
|| token.getType() == TokenType.UNKNOWN_CARD
|
||||||
|
|| token.getType() == TokenType.UNSUPPORTED_CARD) {
|
||||||
|
if (sb.length() > 0)
|
||||||
|
sb.append("\n");
|
||||||
|
sb.append(token.getQuantity()).append(" ").append(token.getText());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sb.length() > 0) {
|
||||||
|
if (SOptionPane.showOptionDialog(Forge.getLocalizer().getMessage("lblFollowingCardsCannotBeImported") + "\n\n" + sb, Forge.getLocalizer().getMessage("lblImportRemainingCards"), SOptionPane.INFORMATION_ICON, importOrCancel) == 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final Deck deck = controller.accept(); //must accept in background thread in case a dialog is shown
|
||||||
|
if (deck == null) { return; }
|
||||||
|
|
||||||
|
FThreads.invokeInEdtLater(() -> {
|
||||||
|
hide();
|
||||||
|
if (callback != null)
|
||||||
|
callback.accept(deck);
|
||||||
|
});
|
||||||
|
}));
|
||||||
initButton(1, Forge.getLocalizer().getMessage("lblCancel"), e -> hide());
|
initButton(1, Forge.getLocalizer().getMessage("lblCancel"), e -> hide());
|
||||||
|
|
||||||
dateTimeCheck.setCommand(e -> updateDropDownEnabled());
|
List<DeckRecognizer.Token> tokens = controller.parseInput(txtInput.getText());
|
||||||
newEditionCheck.setCommand(e -> setArtPreferenceInController());
|
if (controller.isSmartCardArtEnabled())
|
||||||
onlyCoreExpCheck.setCommand(e -> setArtPreferenceInController());
|
tokens = controller.optimiseCardArtInTokens();
|
||||||
smartCardArtCheck.setCommand(e -> controller.setSmartCardArtOptimisation(smartCardArtCheck.isSelected()));
|
//ensure at least one known card found on clipboard
|
||||||
createNewDeckCheck.setCommand(e -> {
|
for (DeckRecognizer.Token token : tokens) {
|
||||||
createNewDeckControl = createNewDeckCheck.isSelected();
|
if (token.getType() == TokenType.LEGAL_CARD) {
|
||||||
controller.setImportBehavior(createNewDeckControl ? DeckImportController.ImportBehavior.CREATE_NEW : DeckImportController.ImportBehavior.MERGE);
|
showOptions = true;
|
||||||
});
|
|
||||||
setShowOptions(false);
|
dateTimeCheck.setCommand(e -> updateDropDownEnabled());
|
||||||
|
newEditionCheck.setCommand(e -> setArtPreferenceInController());
|
||||||
|
onlyCoreExpCheck.setCommand(e -> setArtPreferenceInController());
|
||||||
|
smartCardArtCheck.setCommand(e -> controller.setSmartCardArtOptimisation(smartCardArtCheck.isSelected()));
|
||||||
|
createNewDeckCheck.setCommand(e -> {
|
||||||
|
createNewDeckControl = createNewDeckCheck.isSelected();
|
||||||
|
controller.setCreateNewDeck(createNewDeckControl);
|
||||||
|
});
|
||||||
|
updateDropDownEnabled();
|
||||||
|
setArtPreferenceInController();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
showOptions = false;
|
||||||
|
setButtonEnabled(0, false);
|
||||||
|
txtInput.setText(Forge.getLocalizer().getMessage("lblNoKnownCardsOnClipboard"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setArtPreferenceInController() {
|
private void setArtPreferenceInController() {
|
||||||
@@ -125,66 +160,16 @@ public class FDeckImportDialog extends FDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateDropDownEnabled() {
|
private void updateDropDownEnabled() {
|
||||||
boolean enabled = dateTimeCheck.isSelected() && this.showOptions;
|
boolean enabled = dateTimeCheck.isSelected();
|
||||||
monthDropdown.setEnabled(enabled);
|
monthDropdown.setEnabled(enabled);
|
||||||
yearDropdown.setEnabled(enabled);
|
yearDropdown.setEnabled(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setShowOptions(boolean showOptions) {
|
|
||||||
this.showOptions = showOptions;
|
|
||||||
dateTimeCheck.setEnabled(showOptions);
|
|
||||||
newEditionCheck.setEnabled(showOptions);
|
|
||||||
onlyCoreExpCheck.setEnabled(showOptions);
|
|
||||||
newEditionCheck.setEnabled(showOptions);
|
|
||||||
smartCardArtCheck.setEnabled(showOptions);
|
|
||||||
createNewDeckCheck.setEnabled(showOptions);
|
|
||||||
updateDropDownEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCallback(Consumer<Deck> callback0){
|
public void setCallback(Consumer<Deck> callback0){
|
||||||
callback = callback0;
|
callback = callback0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFreePrintConverter(Function<PaperCard, PaperCard> freePrintConverter) {
|
public boolean createNewDeck(){ return this.createNewDeckControl; }
|
||||||
this.controller.setFreePrintConverter(freePrintConverter);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DeckImportController.ImportBehavior getImportBehavior() {
|
|
||||||
return controller.getImportBehavior();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setImportBannedCards(boolean importBannedCards) {
|
|
||||||
controller.importBannedAndRestrictedCards(importBannedCards);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initParse() {
|
|
||||||
boolean usingInventory = editorConfig.usePlayerInventory();
|
|
||||||
List<DeckRecognizer.Token> tokens = controller.parseInput(txtInput.getText());
|
|
||||||
if (usingInventory)
|
|
||||||
tokens = controller.constrainTokensToInventory();
|
|
||||||
else if (controller.isSmartCardArtEnabled())
|
|
||||||
tokens = controller.optimiseCardArtInTokens();
|
|
||||||
//ensure at least one known card found on clipboard
|
|
||||||
for (DeckRecognizer.Token token : tokens) {
|
|
||||||
if (token.getType() == TokenType.LEGAL_CARD || token.getType() == TokenType.FREE_CARD_NOT_IN_INVENTORY) {
|
|
||||||
|
|
||||||
if(usingInventory) {
|
|
||||||
//Settings aren't compatible with player inventories.
|
|
||||||
setShowOptions(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setShowOptions(true);
|
|
||||||
|
|
||||||
updateDropDownEnabled();
|
|
||||||
setArtPreferenceInController();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setButtonEnabled(0, false);
|
|
||||||
txtInput.setText(Forge.getLocalizer().getMessage("lblNoKnownCardsOnClipboard"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawOverlay(Graphics g) {
|
public void drawOverlay(Graphics g) {
|
||||||
@@ -217,7 +202,7 @@ public class FDeckImportDialog extends FDialog {
|
|||||||
yearDropdown.setBounds(x + dropDownWidth + fieldPadding, y, dropDownWidth, h);
|
yearDropdown.setBounds(x + dropDownWidth + fieldPadding, y, dropDownWidth, h);
|
||||||
y += h + fieldPadding;
|
y += h + fieldPadding;
|
||||||
|
|
||||||
if (!this.currentDeck.isEmpty()){
|
if (!this.currentDeckIsEmpty){
|
||||||
smartCardArtCheck.setBounds(x, y, w/2, h);
|
smartCardArtCheck.setBounds(x, y, w/2, h);
|
||||||
createNewDeckCheck.setBounds(x + w/2, y, w/2, h);
|
createNewDeckCheck.setBounds(x + w/2, y, w/2, h);
|
||||||
} else
|
} else
|
||||||
@@ -237,50 +222,4 @@ public class FDeckImportDialog extends FDialog {
|
|||||||
}
|
}
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final EnumSet<TokenType> MISSING_TOKENS = EnumSet.of(TokenType.CARD_FROM_NOT_ALLOWED_SET,
|
|
||||||
TokenType.CARD_FROM_INVALID_SET, TokenType.UNKNOWN_CARD, TokenType.UNSUPPORTED_CARD,
|
|
||||||
TokenType.WARNING_MESSAGE, TokenType.CARD_NOT_IN_INVENTORY);
|
|
||||||
|
|
||||||
private void performImport() {
|
|
||||||
List<DeckRecognizer.Token> tokens = controller.parseInput(txtInput.getText()); //ensure deck updated based on any changes to options
|
|
||||||
|
|
||||||
if (editorConfig.usePlayerInventory())
|
|
||||||
tokens = controller.constrainTokensToInventory();
|
|
||||||
else if (controller.isSmartCardArtEnabled())
|
|
||||||
tokens = controller.optimiseCardArtInTokens();
|
|
||||||
|
|
||||||
//if there are any cards that cannot be imported, let user know this and give them the option to cancel
|
|
||||||
// Android API StringBuilder isEmpty() is unavailable. https://developer.android.com/reference/java/lang/StringBuilder
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
for (DeckRecognizer.Token token : tokens) {
|
|
||||||
if (MISSING_TOKENS.contains(token.getType())) {
|
|
||||||
if (sb.length() != 0)
|
|
||||||
sb.append("\n");
|
|
||||||
String message = controller.getTokenMessage(token);
|
|
||||||
String statusMessage = controller.getTokenStatusMessage(token);
|
|
||||||
if(!StringUtils.isBlank(statusMessage))
|
|
||||||
sb.append(String.format("%s - (%s)", message, statusMessage));
|
|
||||||
else
|
|
||||||
sb.append(statusMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sb.length() != 0) {
|
|
||||||
Localizer localizer = Forge.getLocalizer();
|
|
||||||
if (SOptionPane.showOptionDialog(localizer.getMessage("lblFollowingCardsCannotBeImported") + "\n\n" + sb, localizer.getMessage("lblImportRemainingCards"), SOptionPane.WARNING_ICON, importOrCancel) == 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final Deck deck = controller.accept(currentDeck.getName()); //must accept in background thread in case a dialog is shown
|
|
||||||
if (deck == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FThreads.invokeInEdtLater(() -> {
|
|
||||||
hide();
|
|
||||||
if (callback != null)
|
|
||||||
callback.accept(deck);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 66 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 105 KiB |
@@ -1,11 +0,0 @@
|
|||||||
Name:Emrakul's Awakening
|
|
||||||
ManaCost:no cost
|
|
||||||
Types:Artifact
|
|
||||||
T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Command | CheckSVar$ X | SVarCompare$ LT7 | Execute$ TrigFlip | TriggerDescription$ At the beginning of your end step, if you have fewer than seven cards in hand, flip a coin. If you win the flip, draw cards equal to the difference.
|
|
||||||
SVar:TrigFlip:DB$ FlipACoin | Defined$ You | WinSubAbility$ TrigDraw
|
|
||||||
SVar:TrigDraw:DB$ Draw | Defined$ You | NumCards$ Difference
|
|
||||||
SVar:X:Count$ValidHand Card.YouOwn
|
|
||||||
SVar:Difference:Number$7/Minus.X
|
|
||||||
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Command | Execute$ TrigWish | TriggerDescription$ At the beginning of your upkeep, put a land card from your library onto the battlefield at random.
|
|
||||||
SVar:TrigWish:DB$ ChangeZone | Origin$ Library | Destination$ Battlefield | ChangeType$ Land.YouCtrl | Hidden$ True | AtRandom$ True
|
|
||||||
Oracle:At the beginning of your upkeep, put a land card from your library onto the battlefield at random.\nAt the beginning of your end step, if you have fewer than seven cards in hand, flip a coin. If you win the flip, draw cards equal to the difference.
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
Name:Emrakul's Presence
|
|
||||||
ManaCost:no cost
|
|
||||||
Types:Artifact
|
|
||||||
T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Command | CheckSVar$ X | SVarCompare$ LT8 | Execute$ TrigDraw | TriggerDescription$ At the beginning of your end step, if you have fewer than eight cards in hand, draw cards equal to the difference.
|
|
||||||
SVar:TrigDraw:DB$ Draw | Defined$ You | NumCards$ Difference
|
|
||||||
SVar:X:Count$ValidHand Card.YouOwn
|
|
||||||
SVar:Difference:Number$8/Minus.X
|
|
||||||
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Command | Execute$ TrigWish | TriggerDescription$ At the beginning of your upkeep, put a random permanent card from your graveyard or exile onto the battlefield.
|
|
||||||
SVar:TrigWish:DB$ ChangeZone | Origin$ Graveyard,Exile | Destination$ Battlefield | ChangeType$ Permanent.YouCtrl | Hidden$ True | AtRandom$ True
|
|
||||||
Oracle:At the beginning of your upkeep, put a random permanent card from your graveyard or exile onto the battlefield.\nAt the beginning of your end step, if you have fewer than eight cards in hand, draw cards equal to the difference.
|
|
||||||
@@ -1,25 +1,19 @@
|
|||||||
[metadata]
|
[metadata]
|
||||||
Name=Emrakul
|
Name=Emrakul
|
||||||
[Main]
|
[Main]
|
||||||
1 Black Lotus
|
4 Black Lotus
|
||||||
2 Vesuva
|
4 Crystal Vein
|
||||||
4 Eldrazi Temple
|
4 Eldrazi Temple
|
||||||
3 Forsaken Monument
|
3 Emrakul, the Aeons Torn
|
||||||
2 It That Betrays
|
3 Emrakul, the Promised End
|
||||||
2 Pathrazer of Ulamog
|
|
||||||
2 Void Winnower
|
|
||||||
2 Emrakul, the Aeons Torn
|
|
||||||
2 Emrakul, the Promised End
|
|
||||||
4 Expedition Map
|
4 Expedition Map
|
||||||
2 Eye of Ugin
|
2 Eye of Ugin
|
||||||
4 Ancient Tomb
|
4 Mana Vault
|
||||||
1 Strip Mine
|
|
||||||
4 All is Dust
|
|
||||||
2 Kozilek, Butcher of Truth
|
2 Kozilek, Butcher of Truth
|
||||||
2 Kozilek, the Great Distortion
|
2 Kozilek, the Great Distortion
|
||||||
1 Mana Crypt
|
4 Mana Crypt
|
||||||
1 Sol Ring
|
4 Sol Ring
|
||||||
3 Titan's Presence
|
4 Titan's Presence
|
||||||
2 Ulamog, the Ceaseless Hunger
|
2 Ulamog, the Ceaseless Hunger
|
||||||
2 Ulamog, the Infinite Gyre
|
2 Ulamog, the Infinite Gyre
|
||||||
4 Urza's Mine
|
4 Urza's Mine
|
||||||
|
|||||||
@@ -38,12 +38,7 @@
|
|||||||
<object id="49" template="../../obj/gold.tx" x="106" y="216"/>
|
<object id="49" template="../../obj/gold.tx" x="106" y="216"/>
|
||||||
<object id="50" template="../../obj/enemy.tx" x="182.772" y="284.992" width="64" height="64">
|
<object id="50" template="../../obj/enemy.tx" x="182.772" y="284.992" width="64" height="64">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="effect" value="{ "startBattleWithCardInCommandZone": [ "Emrakul's Presence"]}"/>
|
|
||||||
<property name="enemy" value="Emrakul"/>
|
<property name="enemy" value="Emrakul"/>
|
||||||
<property name="spawn.Easy" type="bool" value="false"/>
|
|
||||||
<property name="spawn.Hard" type="bool" value="true"/>
|
|
||||||
<property name="spawn.Insane" type="bool" value="true"/>
|
|
||||||
<property name="spawn.Normal" type="bool" value="false"/>
|
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="51" template="../../obj/entry_up.tx" x="209" y="480">
|
<object id="51" template="../../obj/entry_up.tx" x="209" y="480">
|
||||||
@@ -51,16 +46,6 @@
|
|||||||
<property name="teleport" value=""/>
|
<property name="teleport" value=""/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="52" template="../../obj/enemy.tx" x="182.772" y="284.992" width="64" height="64">
|
|
||||||
<properties>
|
|
||||||
<property name="effect" value="{ "startBattleWithCardInCommandZone": [ "Emrakul's Awakening"]}"/>
|
|
||||||
<property name="enemy" value="Emrakul"/>
|
|
||||||
<property name="spawn.Easy" type="bool" value="true"/>
|
|
||||||
<property name="spawn.Hard" type="bool" value="false"/>
|
|
||||||
<property name="spawn.Insane" type="bool" value="false"/>
|
|
||||||
<property name="spawn.Normal" type="bool" value="true"/>
|
|
||||||
</properties>
|
|
||||||
</object>
|
|
||||||
<object id="69" template="../../obj/enemy.tx" x="132.844" y="401.619">
|
<object id="69" template="../../obj/enemy.tx" x="132.844" y="401.619">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="dialog">[{
|
<property name="dialog">[{
|
||||||
|
|||||||
@@ -144,4 +144,3 @@ Tarkir Dragonstorm, 3/6/TDM, TDM
|
|||||||
Final Fantasy, 3/6/FIN, FIN
|
Final Fantasy, 3/6/FIN, FIN
|
||||||
Alchemy: Innistrad, 3/6/ISD, YMID
|
Alchemy: Innistrad, 3/6/ISD, YMID
|
||||||
Edge of Eternities, 3/6/EOE, EOE
|
Edge of Eternities, 3/6/EOE, EOE
|
||||||
Marvel's Spider-Man, 3/6/SPM, SPM
|
|
||||||
|
|||||||
@@ -1,233 +0,0 @@
|
|||||||
//Rank|Name|Rarity|Set
|
|
||||||
#1|Arachne, Psionic Weaver|R|SPM
|
|
||||||
#2|Origin of Spider-Man|R|SPM
|
|
||||||
#3|Spectacular Spider-Man|R|SPM
|
|
||||||
#4|Silk, Web Weaver|R|SPM
|
|
||||||
#5|Rite of Replication|M|SPM
|
|
||||||
#6|Skithiryx, the Blight Dragon|M|SPM
|
|
||||||
#7|Goblin Bombardment|M|SPM
|
|
||||||
#8|Najeela, the Blade-Blossom|M|SPM
|
|
||||||
#9|Lizard, Connors's Curse|R|SPM
|
|
||||||
#10|Sandman, Shifting Scoundrel|R|SPM
|
|
||||||
#11|Biorganic Carapace|R|SPM
|
|
||||||
#12|Doctor Octopus, Master Planner|M|SPM
|
|
||||||
#13|The Spot, Living Portal|R|SPM
|
|
||||||
#14|Agent Venom|R|SPM
|
|
||||||
#15|Gwenom, Remorseless|M|SPM
|
|
||||||
#16|Miles Morales|M|SPM
|
|
||||||
#17|Arana, Heart of the Spider|R|SPM
|
|
||||||
#18|Mister Negative|M|SPM
|
|
||||||
#19|Scarlet Spider, Ben Reilly|R|SPM
|
|
||||||
#20|Symbiote Spider-Man|R|SPM
|
|
||||||
#21|Ultimate Green Goblin|R|SPM
|
|
||||||
#22|Arasta of the Endless Web|M|SPM
|
|
||||||
#23|Mysterio, Master of Illusion|R|SPM
|
|
||||||
#24|Villainous Wrath|R|SPM
|
|
||||||
#25|Strength of Will|R|SPM
|
|
||||||
#26|Iron Spider, Stark Upgrade|R|SPM
|
|
||||||
#27|Anti-Venom, Horrifying Healer|M|SPM
|
|
||||||
#28|Friendly Neighborhood|R|SPM
|
|
||||||
#29|Peter Parker|M|SPM
|
|
||||||
#30|With Great Power|R|SPM
|
|
||||||
#31|Hydro-Man, Fluid Felon|R|SPM
|
|
||||||
#32|Impostor Syndrome|M|SPM
|
|
||||||
#33|Behold the Sinister Six!|M|SPM
|
|
||||||
#34|Black Cat, Cunning Thief|R|SPM
|
|
||||||
#35|Eddie Brock|M|SPM
|
|
||||||
#36|Morlun, Devourer of Spiders|R|SPM
|
|
||||||
#37|Spider-Punk|R|SPM
|
|
||||||
#38|Spinneret and Spiderling|R|SPM
|
|
||||||
#39|Kraven's Last Hunt|R|SPM
|
|
||||||
#40|Spider-Ham, Peter Porker|R|SPM
|
|
||||||
#41|Carnage, Crimson Chaos|R|SPM
|
|
||||||
#42|Cheering Crowd|R|SPM
|
|
||||||
#43|Cosmic Spider-Man|M|SPM
|
|
||||||
#44|Kraven the Hunter|R|SPM
|
|
||||||
#45|Mary Jane Watson|R|SPM
|
|
||||||
#46|Rhino, Barreling Brute|U|SPM
|
|
||||||
#47|Spider-Man 2099|R|SPM
|
|
||||||
#48|Mystic Confluence|M|SPM
|
|
||||||
#49|Savage Beating|M|SPM
|
|
||||||
#50|Silkguard|M|SPM
|
|
||||||
#51|Norman Osborn|M|SPM
|
|
||||||
#52|Gwen Stacy|M|SPM
|
|
||||||
#53|Green Goblin, Revenant|U|SPM
|
|
||||||
#54|Morbius the Living Vampire|U|SPM
|
|
||||||
#55|SP//Piloted by Peni|U|SPM
|
|
||||||
#56|Spider-Woman, Stunning Savior|R|SPM
|
|
||||||
#57|Doc Ock's Tentacles|R|SPM
|
|
||||||
#58|Silver Sable, Mercenary Leader|U|SPM
|
|
||||||
#59|Spectacular Tactics|C|SPM
|
|
||||||
#60|Spider-Man, Web-Slinger|C|SPM
|
|
||||||
#61|Spider-UK|U|SPM
|
|
||||||
#62|Whoosh!|C|SPM
|
|
||||||
#63|Scorpion's Sting|C|SPM
|
|
||||||
#64|Electro, Assaulting Battery|R|SPM
|
|
||||||
#65|J. Jonah Jameson|R|SPM
|
|
||||||
#66|Radioactive Spider|R|SPM
|
|
||||||
#67|Spiders-Man, Heroic Horde|U|SPM
|
|
||||||
#68|Terrific Team-Up|U|SPM
|
|
||||||
#69|Gallant Citizen|C|SPM
|
|
||||||
#70|Kraven, Proud Predator|U|SPM
|
|
||||||
#71|Superior Spider-Man|R|SPM
|
|
||||||
#72|Rocket-Powered Goblin Glider|R|SPM
|
|
||||||
#73|Urban Retreat|R|SPM
|
|
||||||
#74|Vibrant Cityscape|C|SPM
|
|
||||||
#75|Oscorp Industries|R|SPM
|
|
||||||
#76|Leyline Binding|M|SPM
|
|
||||||
#77|Lorthos, the Tidemaker|M|SPM
|
|
||||||
#78|Shock MAR|M|SPM
|
|
||||||
#79|Arachnogenesis|M|SPM
|
|
||||||
#80|Alibou, Ancient Witness|M|SPM
|
|
||||||
#81|Daily Bugle Reporters|C|SPM
|
|
||||||
#82|Web Up|C|SPM
|
|
||||||
#83|Doc Ock, Sinister Scientist|C|SPM
|
|
||||||
#84|Madame Web, Clairvoyant|U|SPM
|
|
||||||
#85|Spider-Byte, Web Warden|U|SPM
|
|
||||||
#86|The Death of Gwen Stacy|R|SPM
|
|
||||||
#87|Spider-Man Noir|U|SPM
|
|
||||||
#88|The Spot's Portal|U|SPM
|
|
||||||
#89|Tombstone, Career Criminal|U|SPM
|
|
||||||
#90|Electro's Bolt|C|SPM
|
|
||||||
#91|Shadow of the Goblin|R|SPM
|
|
||||||
#92|Shock|C|SPM
|
|
||||||
#93|Shocker, Unshakable|U|SPM
|
|
||||||
#94|Damage Control Crew|U|SPM
|
|
||||||
#95|Kapow!|C|SPM
|
|
||||||
#96|Scout the City|C|SPM
|
|
||||||
#97|Spider-Man, Brooklyn Visionary|C|SPM
|
|
||||||
#98|Wall Crawl|U|SPM
|
|
||||||
#99|Prowler, Clawed Thief|U|SPM
|
|
||||||
#100|Rhino's Rampage|U|SPM
|
|
||||||
#101|Scarlet Spider, Kaine|U|SPM
|
|
||||||
#102|Spider-Girl, Legacy Hero|U|SPM
|
|
||||||
#103|Spider-Man India|U|SPM
|
|
||||||
#104|Wraith, Vicious Vigilante|U|SPM
|
|
||||||
#105|Clever Impersonator|M|SPM
|
|
||||||
#106|Ponder|M|SPM
|
|
||||||
#107|Infernal Grasp|M|SPM
|
|
||||||
#108|Saw in Half|M|SPM
|
|
||||||
#109|Terminate|M|SPM
|
|
||||||
#110|Aunt May|U|SPM
|
|
||||||
#111|Flash Thompson, Spider-Fan|U|SPM
|
|
||||||
#112|Selfless Police Captain|C|SPM
|
|
||||||
#113|Wild Pack Squad|C|SPM
|
|
||||||
#114|Chameleon, Master of Disguise|U|SPM
|
|
||||||
#115|Flying Octobot|U|SPM
|
|
||||||
#116|Robotics Mastery|U|SPM
|
|
||||||
#117|School Daze|U|SPM
|
|
||||||
#118|Secret Identity|U|SPM
|
|
||||||
#119|Scorpion, Seething Striker|U|SPM
|
|
||||||
#120|Spider-Gwen, Free Spirit|C|SPM
|
|
||||||
#121|Spider-Islanders|C|SPM
|
|
||||||
#122|Ezekiel Sims, Spider-Totem|U|SPM
|
|
||||||
#123|Pictures of Spider-Man|U|SPM
|
|
||||||
#124|Pumpkin Bombardment|C|SPM
|
|
||||||
#125|Shriek, Treblemaker|U|SPM
|
|
||||||
#126|Spider Manifestation|C|SPM
|
|
||||||
#127|Path to Exile|M|SPM
|
|
||||||
#128|Beetle, Legacy Criminal|C|SPM
|
|
||||||
#129|The Clone Saga|R|SPM
|
|
||||||
#130|Mysterio's Phantasm|C|SPM
|
|
||||||
#131|Prison Break|U|SPM
|
|
||||||
#132|Superior Foes of Spider-Man|U|SPM
|
|
||||||
#133|Guy in the Chair|C|SPM
|
|
||||||
#134|Skyward Spider|C|SPM
|
|
||||||
#135|Spider-Bot|C|SPM
|
|
||||||
#136|Ominous Asylum|C|SPM
|
|
||||||
#137|Savage Mansion|C|SPM
|
|
||||||
#138|Sinister Hideout|C|SPM
|
|
||||||
#139|Suburban Sanctuary|C|SPM
|
|
||||||
#140|University Campus|C|SPM
|
|
||||||
#141|Reprieve|M|SPM
|
|
||||||
#142|Opposition Agent|M|SPM
|
|
||||||
#143|Relentless Assault|M|SPM
|
|
||||||
#144|City Pigeon|C|SPM
|
|
||||||
#145|Sudden Strike|U|SPM
|
|
||||||
#146|Thwip!|C|SPM
|
|
||||||
#147|Amazing Acrobatics|C|SPM
|
|
||||||
#148|Doc Ock's Henchmen|C|SPM
|
|
||||||
#149|Spider-Man No More|C|SPM
|
|
||||||
#150|Unstable Experiment|C|SPM
|
|
||||||
#151|Common Crook|C|SPM
|
|
||||||
#152|Swarm, Being of Bees|C|SPM
|
|
||||||
#153|Venom, Evil Unleashed|C|SPM
|
|
||||||
#154|Venomized Cat|C|SPM
|
|
||||||
#155|Venom's Hunger|C|SPM
|
|
||||||
#156|Angry Rabble|C|SPM
|
|
||||||
#157|Hobgoblin, Mantled Marauder|U|SPM
|
|
||||||
#158|Masked Meower|C|SPM
|
|
||||||
#159|Raging Goblinoids|U|SPM
|
|
||||||
#160|Romantic Rendezvous|C|SPM
|
|
||||||
#161|Stegron the Dinosaur Man|C|SPM
|
|
||||||
#162|Taxi Driver|C|SPM
|
|
||||||
#163|Wisecrack|U|SPM
|
|
||||||
#164|Grow Extra Arms|C|SPM
|
|
||||||
#165|Kraven's Cats|C|SPM
|
|
||||||
#166|Lurking Lizards|C|SPM
|
|
||||||
#167|Professional Wrestler|C|SPM
|
|
||||||
#168|Supportive Parents|U|SPM
|
|
||||||
#169|Mob Lookout|C|SPM
|
|
||||||
#170|Eerie Gravestone|C|SPM
|
|
||||||
#171|Living Brain, Mechanical Marvel|U|SPM
|
|
||||||
#172|Mechanical Mobster|C|SPM
|
|
||||||
#173|Spider-Slayer, Hatred Honed|U|SPM
|
|
||||||
#174|Spider-Suit|U|SPM
|
|
||||||
#175|Counterspell|M|SPM
|
|
||||||
#176|Feed the Swarm|M|SPM
|
|
||||||
#177|Thrill of Possibility|M|SPM
|
|
||||||
#178|Unexpected Windfall|M|SPM
|
|
||||||
#179|Costume Closet|U|SPM
|
|
||||||
#180|Starling, Aerial Ally|C|SPM
|
|
||||||
#181|Web-Shooters|U|SPM
|
|
||||||
#182|Oscorp Research Team|C|SPM
|
|
||||||
#183|Inner Demons Gangsters|C|SPM
|
|
||||||
#184|Merciless Enforcers|C|SPM
|
|
||||||
#185|Risky Research|C|SPM
|
|
||||||
#186|Sandman's Quicksand|U|SPM
|
|
||||||
#187|Heroes' Hangout|U|SPM
|
|
||||||
#188|Spider-Rex, Daring Dino|C|SPM
|
|
||||||
#189|Web-Warriors|U|SPM
|
|
||||||
#190|Passenger Ferry|C|SPM
|
|
||||||
#191|Subway Train|C|SPM
|
|
||||||
#192|Vulture, Scheming Scavenger|U|SPM
|
|
||||||
#193|Hot Dog Cart|C|SPM
|
|
||||||
#194|Interdimensional Web Watch|R|SPM
|
|
||||||
#195|Spider-Mobile|U|SPM
|
|
||||||
#196|Steel Wrecking Ball|C|SPM
|
|
||||||
#197|Rent Is Due|R|SPM
|
|
||||||
#198|Hide on the Ceiling|R|SPM
|
|
||||||
#199|Lady Octopus, Inspired Inventor|R|SPM
|
|
||||||
#200|Alien Symbiosis|U|SPM
|
|
||||||
#201|Molten Man, Inferno Incarnate|U|SPM
|
|
||||||
#202|Spider-Verse|M|SPM
|
|
||||||
#203|Web of Life and Destiny|M|SPM
|
|
||||||
#204|Jackal, Genius Geneticist|R|SPM
|
|
||||||
#205|Sun-Spider, Nimble Webber|U|SPM
|
|
||||||
#206|Bagel and Schmear|C|SPM
|
|
||||||
#207|Peter Parker's Camera|R|SPM
|
|
||||||
#208|Daily Bugle Building|U|SPM
|
|
||||||
#209|Multiversal Passage|R|SPM
|
|
||||||
#210|Comeuppance|M|SPM
|
|
||||||
#211|Traumatize|M|SPM
|
|
||||||
#212|Reanimate|M|SPM
|
|
||||||
#213|Heroic Intervention|M|SPM
|
|
||||||
#214|News Helicopter|C|SPM
|
|
||||||
#215|Parallel Lives|M|SPM
|
|
||||||
#216|Hex|M|SPM
|
|
||||||
#217|Tangle|M|SPM
|
|
||||||
#218|Spider-Sense|R|SPM
|
|
||||||
#219|Parker Luck|R|SPM
|
|
||||||
#220|The Soul Stone|M|SPM
|
|
||||||
#221|Maximum Carnage|R|SPM
|
|
||||||
#222|Nine Lives|M|SPM
|
|
||||||
#223|Rest in Peace|M|SPM
|
|
||||||
#224|Mindbreak Trap|M|SPM
|
|
||||||
#225|Winds of Change|M|SPM
|
|
||||||
#226|Beast Within|M|SPM
|
|
||||||
#227|Hunter's Insight|M|SPM
|
|
||||||
#228|Plains|C|SPM
|
|
||||||
#229|Island|C|SPM
|
|
||||||
#230|Swamp|C|SPM
|
|
||||||
#231|Mountain|C|SPM
|
|
||||||
#232|Forest|C|SPM
|
|
||||||
@@ -6,66 +6,6 @@ Type=Expansion
|
|||||||
ScryfallCode=SPM
|
ScryfallCode=SPM
|
||||||
DoublePick=WhenPodSizeIs4
|
DoublePick=WhenPodSizeIs4
|
||||||
RecommendedPodSize=4
|
RecommendedPodSize=4
|
||||||
#https://magic.wizards.com/en/news/feature/collecting-marvels-spider-man
|
|
||||||
BoosterSlots=Common,Common-Borderless,Uncommon,RareMythic,Land,Wildcard,WildcardFoil
|
|
||||||
Booster=6 Common, 1 Common-Borderless, 3 Uncommon, 1 RareMythic, 1 Wildcard, 1 WildcardFoil+, 1 Land
|
|
||||||
Prerelease=6 Boosters, 1 RareMythic+
|
|
||||||
BoosterBox=30
|
|
||||||
|
|
||||||
[Common]
|
|
||||||
Base=Common:fromSheet("SPM cards")
|
|
||||||
|
|
||||||
[Common-Borderless]
|
|
||||||
Base=Common:fromSheet("SPM cards")
|
|
||||||
Replace=.0416F fromSheet("SPM borderless")
|
|
||||||
|
|
||||||
[Uncommon]
|
|
||||||
Base=Uncommon:fromSheet("SPM cards")
|
|
||||||
Replace=0.0517 Uncommon:fromSheet("SPM scene cards")
|
|
||||||
|
|
||||||
[RareMythic]
|
|
||||||
Base=Rare:fromSheet("SPM cards")
|
|
||||||
Replace=.117F Mythic:fromSheet("SPM cards")
|
|
||||||
Replace=.012F Rare:fromSheet("SPM webslinger")
|
|
||||||
Replace=.004F Mythic:fromSheet("SPM webslinger")
|
|
||||||
Replace=.021F Rare:fromSheet("SPM panel cards")
|
|
||||||
Replace=.004F Mythic:fromSheet("SPM panel cards")
|
|
||||||
Replace=.01F Rare:fromSheet("SPM scene cards")
|
|
||||||
Replace=.0005F Mythic:fromSheet("SPM scene cards")
|
|
||||||
|
|
||||||
[Wildcard]
|
|
||||||
Base=Common:fromSheet("SPM cards")
|
|
||||||
Replace=0.041F Uncommon:fromSheet("SPM cards")
|
|
||||||
Replace=0.209F Rare:fromSheet("SPM cards")
|
|
||||||
Replace=0.0029F Mythic:fromSheet("SPM cards")
|
|
||||||
Replace=.0012F Rare:fromSheet("SPM webslinger")
|
|
||||||
Replace=.0004F Mythic:fromSheet("SPM webslinger")
|
|
||||||
Replace=.0021F Rare:fromSheet("SPM panel cards")
|
|
||||||
Replace=.0004F Mythic:fromSheet("SPM panel cards")
|
|
||||||
Replace=.007F Uncommon:fromSheet("SPM scene cards")
|
|
||||||
Replace=.001F Rare:fromSheet("SPM scene cards")
|
|
||||||
Replace=.00005F Mythic:fromSheet("SPM scene cards")
|
|
||||||
|
|
||||||
[WildcardFoil]
|
|
||||||
Base=Common:fromSheet("SPM cards")
|
|
||||||
Replace=0.241F Uncommon:fromSheet("SPM cards")
|
|
||||||
Replace=0.078F Rare:fromSheet("SPM cards")
|
|
||||||
Replace=0.011F Mythic:fromSheet("SPM cards")
|
|
||||||
Replace=.0012F Rare:fromSheet("SPM webslinger")
|
|
||||||
Replace=.0004F Mythic:fromSheet("SPM webslinger")
|
|
||||||
Replace=.0021F Rare:fromSheet("SPM panel cards")
|
|
||||||
Replace=.0004F Mythic:fromSheet("SPM panel cards")
|
|
||||||
Replace=.007F Uncommon:fromSheet("SPM scene cards")
|
|
||||||
Replace=.001F Rare:fromSheet("SPM scene cards")
|
|
||||||
Replace=.00005F Mythic:fromSheet("SPM scene cards")
|
|
||||||
|
|
||||||
[Land]
|
|
||||||
Base=fromSheet("SPM allied lands")
|
|
||||||
Replace=0.125F fromSheet("SPM allied lands")+
|
|
||||||
Replace=0.20F BasicLand:fromSheet("SPM full art")
|
|
||||||
Replace=0.05F BasicLand:fromSheet("SPM full art")+
|
|
||||||
Replace=0.20F BasicLand:fromSheet("SPM cards"):!fromSheet("SPM allied lands")
|
|
||||||
Replace=0.05F BasicLand:fromSheet("SPM cards"):!fromSheet("SPM allied lands")
|
|
||||||
|
|
||||||
[cards]
|
[cards]
|
||||||
1 M Anti-Venom, Horrifying Healer @Néstor Ossandón Leal
|
1 M Anti-Venom, Horrifying Healer @Néstor Ossandón Leal
|
||||||
@@ -248,28 +188,24 @@ Replace=0.05F BasicLand:fromSheet("SPM cards"):!fromSheet("SPM allied lands")
|
|||||||
178 C Subway Train @Jonas De Ro
|
178 C Subway Train @Jonas De Ro
|
||||||
179 U Daily Bugle Building @David Álvarez
|
179 U Daily Bugle Building @David Álvarez
|
||||||
180 R Multiversal Passage @Pablo Mendoza
|
180 R Multiversal Passage @Pablo Mendoza
|
||||||
181 L Ominous Asylum @Pavel Kolomeyets
|
181 C Ominous Asylum @Pavel Kolomeyets
|
||||||
182 R Oscorp Industries @Bastien Grivet
|
182 R Oscorp Industries @Bastien Grivet
|
||||||
183 L Savage Mansion @David Álvarez
|
183 C Savage Mansion @David Álvarez
|
||||||
184 L Sinister Hideout @Pavel Kolomeyets
|
184 C Sinister Hideout @Pavel Kolomeyets
|
||||||
185 L Suburban Sanctuary @David Frasheski
|
185 C Suburban Sanctuary @David Frasheski
|
||||||
186 L University Campus @David Álvarez
|
186 C University Campus @David Álvarez
|
||||||
187 R Urban Retreat @Jonas De Ro
|
187 R Urban Retreat @Jonas De Ro
|
||||||
188 C Vibrant Cityscape @Wei Guan
|
188 C Vibrant Cityscape @Wei Guan
|
||||||
194 L Plains @Jonas De Ro
|
|
||||||
195 L Island @Jonas De Ro
|
|
||||||
196 L Swamp @Jonas De Ro
|
|
||||||
197 L Mountain @Jonas De Ro
|
|
||||||
198 L Forest @Jonas De Ro
|
|
||||||
|
|
||||||
[full art]
|
|
||||||
189 L Plains @Sarah Finnigan
|
189 L Plains @Sarah Finnigan
|
||||||
190 L Island @Sarah Finnigan
|
190 L Island @Sarah Finnigan
|
||||||
191 L Swamp @Sarah Finnigan
|
191 L Swamp @Sarah Finnigan
|
||||||
192 L Mountain @Sarah Finnigan
|
192 L Mountain @Sarah Finnigan
|
||||||
193 L Forest @Sarah Finnigan
|
193 L Forest @Sarah Finnigan
|
||||||
|
194 L Plains @Jonas De Ro
|
||||||
[borderless]
|
195 L Island @Jonas De Ro
|
||||||
|
196 L Swamp @Jonas De Ro
|
||||||
|
197 L Mountain @Jonas De Ro
|
||||||
|
198 L Forest @Jonas De Ro
|
||||||
199 U SP//dr, Piloted by Peni @Jim Cheung & Jay David Ramos
|
199 U SP//dr, Piloted by Peni @Jim Cheung & Jay David Ramos
|
||||||
200 M Miles Morales @Jim Cheung & Jay David Ramos
|
200 M Miles Morales @Jim Cheung & Jay David Ramos
|
||||||
201 R Spider-Ham, Peter Porker @Jim Cheung & Jay David Ramos
|
201 R Spider-Ham, Peter Porker @Jim Cheung & Jay David Ramos
|
||||||
@@ -306,9 +242,6 @@ Replace=0.05F BasicLand:fromSheet("SPM cards"):!fromSheet("SPM allied lands")
|
|||||||
232 M Peter Parker @Jack Kirby & Steve Ditko
|
232 M Peter Parker @Jack Kirby & Steve Ditko
|
||||||
233 M Eddie Brock @Todd McFarlane & Bob Sharen
|
233 M Eddie Brock @Todd McFarlane & Bob Sharen
|
||||||
234 M Miles Morales @Sara Pichelli & Justin Ponsor
|
234 M Miles Morales @Sara Pichelli & Justin Ponsor
|
||||||
242 M The Soul Stone @Madeline Boni
|
|
||||||
|
|
||||||
[etched]
|
|
||||||
235 R Spectacular Spider-Man @Roberta Ingranata
|
235 R Spectacular Spider-Man @Roberta Ingranata
|
||||||
236 R Spectacular Spider-Man @Roberta Ingranata
|
236 R Spectacular Spider-Man @Roberta Ingranata
|
||||||
237 R Spectacular Spider-Man @Roberta Ingranata
|
237 R Spectacular Spider-Man @Roberta Ingranata
|
||||||
@@ -316,8 +249,7 @@ Replace=0.05F BasicLand:fromSheet("SPM cards"):!fromSheet("SPM allied lands")
|
|||||||
239 R Spectacular Spider-Man @Roberta Ingranata
|
239 R Spectacular Spider-Man @Roberta Ingranata
|
||||||
240 R Spectacular Spider-Man @Roberta Ingranata
|
240 R Spectacular Spider-Man @Roberta Ingranata
|
||||||
241 R Spectacular Spider-Man @Roberta Ingranata
|
241 R Spectacular Spider-Man @Roberta Ingranata
|
||||||
|
242 M The Soul Stone @Madeline Boni
|
||||||
[extended art]
|
|
||||||
243 M The Soul Stone @Leinil Francis Yu & Sunny Gho
|
243 M The Soul Stone @Leinil Francis Yu & Sunny Gho
|
||||||
244 M Anti-Venom, Horrifying Healer @Néstor Ossandón Leal
|
244 M Anti-Venom, Horrifying Healer @Néstor Ossandón Leal
|
||||||
245 R Arachne, Psionic Weaver @Steve Argyle
|
245 R Arachne, Psionic Weaver @Steve Argyle
|
||||||
@@ -359,63 +291,10 @@ Replace=0.05F BasicLand:fromSheet("SPM cards"):!fromSheet("SPM allied lands")
|
|||||||
281 R Rocket-Powered Goblin Glider @Pavel Kolomeyets
|
281 R Rocket-Powered Goblin Glider @Pavel Kolomeyets
|
||||||
282 R Oscorp Industries @Bastien Grivet
|
282 R Oscorp Industries @Bastien Grivet
|
||||||
283 R Urban Retreat @Jonas De Ro
|
283 R Urban Retreat @Jonas De Ro
|
||||||
|
|
||||||
[promo]
|
|
||||||
284 R Spider-Sense @David Álvarez
|
284 R Spider-Sense @David Álvarez
|
||||||
285 R Radioactive Spider @Toni Infante
|
285 R Radioactive Spider @Toni Infante
|
||||||
286 M Gwenom, Remorseless @Jesper Ejsing
|
286 M Gwenom, Remorseless @Jesper Ejsing
|
||||||
|
|
||||||
[allied lands]
|
|
||||||
1 Ominous Asylum|SPM
|
|
||||||
1 Savage Mansion|SPM
|
|
||||||
1 Sinister Hideout|SPM
|
|
||||||
1 Suburban Sanctuary|SPM
|
|
||||||
1 University Campus|SPM
|
|
||||||
|
|
||||||
[scene cards]
|
|
||||||
1 SP//dr, Piloted by Peni|SPM|[199]
|
|
||||||
1 Miles Morales|SPM|[200]
|
|
||||||
1 Spider-Ham, Peter Porker|SPM|[201]
|
|
||||||
1 Gwen Stacy|SPM|[202]
|
|
||||||
1 Web-Warriors|SPM|[203]
|
|
||||||
1 Spider-Man Noir|SPM|[204]
|
|
||||||
1 Spider-Man 2099|SPM|[205]
|
|
||||||
1 Multiversal Passage|SPM|[206]
|
|
||||||
1 Spider-Punk|SPM|[207]
|
|
||||||
|
|
||||||
[webslinger]
|
|
||||||
1 Peter Parker|SPM|[208]
|
|
||||||
1 Gwen Stacy|SPM|[209]
|
|
||||||
1 Spider-Punk|SPM|[210]
|
|
||||||
1 Miles Morales|SPM|[211]
|
|
||||||
1 Radioactive Spider|SPM|[212]
|
|
||||||
1 Araña, Heart of the Spider|SPM|[213]
|
|
||||||
1 Scarlet Spider, Ben Reilly|SPM|[214]
|
|
||||||
1 Silk, Web Weaver|SPM|[215]
|
|
||||||
1 Spider-Man 2099|SPM|[216]
|
|
||||||
1 Symbiote Spider-Man|SPM|[217]
|
|
||||||
|
|
||||||
[panel cards]
|
|
||||||
1 Origin of Spider-Man|SPM|[218]
|
|
||||||
1 The Clone Saga|SPM|[219]
|
|
||||||
1 Norman Osborn|SPM|[220]
|
|
||||||
1 Behold the Sinister Six!|SPM|[221]
|
|
||||||
1 Black Cat, Cunning Thief|SPM|[222]
|
|
||||||
1 The Death of Gwen Stacy|SPM|[223]
|
|
||||||
1 Eddie Brock|SPM|[224]
|
|
||||||
1 Maximum Carnage|SPM|[225]
|
|
||||||
1 Kraven's Last Hunt|SPM|[226]
|
|
||||||
1 Carnage, Crimson Chaos|SPM|[227]
|
|
||||||
1 Doctor Octopus, Master Planner|SPM|[228]
|
|
||||||
1 Mary Jane Watson|SPM|[229]
|
|
||||||
1 Spider-Woman, Stunning Savior|SPM|[230]
|
|
||||||
1 The Spot, Living Portal|SPM|[231]
|
|
||||||
|
|
||||||
[classic comic]
|
|
||||||
1 Peter Parker|SPM|[232]
|
|
||||||
1 Eddie Brock|SPM|[233]
|
|
||||||
1 Miles Morales|SPM|[234]
|
|
||||||
|
|
||||||
[tokens]
|
[tokens]
|
||||||
2 u_3_3_illusion_villain @Anthony Devine
|
2 u_3_3_illusion_villain @Anthony Devine
|
||||||
3 g_2_1_spider_reach @Domenico Cava
|
3 g_2_1_spider_reach @Domenico Cava
|
||||||
|
|||||||
@@ -6,43 +6,43 @@ Type=Online
|
|||||||
ScryfallCode=OMB
|
ScryfallCode=OMB
|
||||||
|
|
||||||
[cards]
|
[cards]
|
||||||
1 R Comeuppance @Igor Krstic
|
1 M Comeuppance @
|
||||||
2 R Leyline Binding @Cristi Balanescu
|
2 M Leyline Binding @
|
||||||
3 R Nine Lives @Paul Scott Canavan
|
3 M Nine Lives @
|
||||||
4 R Path to Exile @Todd Lockwood
|
4 M Path to Exile @
|
||||||
5 U Reprieve @Mariah Tekulve
|
5 M Reprieve @
|
||||||
6 R Rest in Peace @Jarel Threat
|
6 M Rest in Peace @
|
||||||
7 M Wedding Ring @Olena Richards
|
7 M Wedding Ring @
|
||||||
8 M Clever Impersonator @Slawomir Maniak
|
8 M Clever Impersonator @
|
||||||
9 R Counterspell @Gao Yan
|
9 M Counterspell @
|
||||||
10 M Lorthos, the Tidemaker @Kekai Kotaki
|
10 M Lorthos, the Tidemaker @
|
||||||
11 M Mindbreak Trap @Christopher Moeller
|
11 M Mindbreak Trap @
|
||||||
12 R Mystic Confluence @Kieran Yanner
|
12 M Mystic Confluence @
|
||||||
13 C Ponder @Ernanda Souza
|
13 M Ponder @
|
||||||
14 R Rite of Replication @Matt Cavotta
|
14 M Rite of Replication @
|
||||||
15 R Traumatize @Greg Staples
|
15 M Traumatize @
|
||||||
16 C Feed the Swarm @Nino Is
|
16 M Feed the Swarm @
|
||||||
17 R Hex @Michael Sutfin
|
17 M Hex @
|
||||||
18 U Infernal Grasp @Naomi Baker
|
18 M Infernal Grasp @
|
||||||
19 M Opposition Agent @Scott Murphy
|
19 M Opposition Agent @
|
||||||
20 R Reanimate @Johann Bodin
|
20 M Reanimate @
|
||||||
21 R Saw in Half @Alexander Mokhov
|
21 M Saw in Half @
|
||||||
22 M Skithiryx, the Blight Dragon @Chippy
|
22 M Skithiryx, the Blight Dragon @
|
||||||
23 R Goblin Bombardment @Dave Kendall
|
23 M Goblin Bombardment @
|
||||||
24 M Najeela, the Blade-Blossom @Matt Stewart
|
24 M Najeela, the Blade-Blossom @
|
||||||
25 R Relentless Assault @Greg Hildebrandt
|
25 M Relentless Assault @
|
||||||
26 M Savage Beating @Matt Thompson
|
26 M Savage Beating @
|
||||||
27 C Shock @Jon Foster
|
27 M Shock @
|
||||||
28 C Thrill of Possibility @Izzy
|
28 M Thrill of Possibility @
|
||||||
29 C Unexpected Windfall @Lorenzo Mastroianni
|
29 M Unexpected Windfall @
|
||||||
30 U Winds of Change @Adam Rex
|
30 M Winds of Change @
|
||||||
31 R Arachnogenesis @Johannes Voss
|
31 M Arachnogenesis @
|
||||||
32 R Arasta of the Endless Web @Sam Rowan
|
32 M Arasta of the Endless Web @
|
||||||
33 U Beast Within @Jesper Ejsing
|
33 M Beast Within @
|
||||||
34 R Heroic Intervention @James Ryman
|
34 M Heroic Intervention @
|
||||||
35 U Hunter's Insight @Jim Murray
|
35 M Hunter's Insight @
|
||||||
36 M Parallel Lives @Steve Prescott
|
36 M Parallel Lives @
|
||||||
37 R Silkguard @Dan Murayama Scott
|
37 M Silkguard @
|
||||||
38 U Tangle @Néstor Ossandón Leal
|
38 M Tangle @
|
||||||
39 M Alibou, Ancient Witness @Matt Stewart
|
39 M Alibou, Ancient Witness @
|
||||||
40 U Terminate @Wayne Reynolds
|
40 M Terminate @
|
||||||
|
|||||||
@@ -2838,7 +2838,6 @@ lblDecklistTitle=Deckliste
|
|||||||
lblSummaryStats=Gesamt-Statistik
|
lblSummaryStats=Gesamt-Statistik
|
||||||
lblDeckSection=Bereich
|
lblDeckSection=Bereich
|
||||||
lblNewDeckCheckbox=Erzeuge ein neues Deck
|
lblNewDeckCheckbox=Erzeuge ein neues Deck
|
||||||
lblReplaceDeckCheckbox=Replace Current Deck
|
|
||||||
lblImportCardsCmd=Importiere Karten
|
lblImportCardsCmd=Importiere Karten
|
||||||
lblCreateNewCmd=Neues Deck
|
lblCreateNewCmd=Neues Deck
|
||||||
lblErrNotAllowedCard=Set ist nicht erlaubt in {0}
|
lblErrNotAllowedCard=Set ist nicht erlaubt in {0}
|
||||||
@@ -2846,7 +2845,6 @@ lblWarnLimitedCard={0} in {1}
|
|||||||
lblErrCardEditionDate=Set verträgt sich nicht mit der Erscheinungsdatum-Option
|
lblErrCardEditionDate=Set verträgt sich nicht mit der Erscheinungsdatum-Option
|
||||||
lblErrUnsupportedCard=Ist nicht erlaubt in {0}
|
lblErrUnsupportedCard=Ist nicht erlaubt in {0}
|
||||||
lblWarnUnknownCardMsg=Unbekannte oder in Forge nicht unterstützte Karte
|
lblWarnUnknownCardMsg=Unbekannte oder in Forge nicht unterstützte Karte
|
||||||
lblWarnNotInInventory=Card not found in inventory
|
|
||||||
lblWarnTooManyCommanders=Aktueller {0}-Bereich enthält {1} mögliche Commander-Karten: {2}
|
lblWarnTooManyCommanders=Aktueller {0}-Bereich enthält {1} mögliche Commander-Karten: {2}
|
||||||
lblWarnCommandersInSideExtra=Bitte prüfen und, falls nötig, min. eine Karte in den Commander-Bereich verschieben.
|
lblWarnCommandersInSideExtra=Bitte prüfen und, falls nötig, min. eine Karte in den Commander-Bereich verschieben.
|
||||||
lblWarnDeckSectionNotAllowedInEditor=In {1} ist der {0}-Bereich nicht erlaubt.
|
lblWarnDeckSectionNotAllowedInEditor=In {1} ist der {0}-Bereich nicht erlaubt.
|
||||||
@@ -2938,7 +2936,6 @@ lblCardImportWarning=\nWarnung: Das Deck {0} wird umbenannt in {1}.
|
|||||||
lblConfirmCreateNewDeck=Du bist dabei das neue Deck {0} zu erzeugen. {1}\n\nWillst du fortfahren?\n\n Hinweis: \
|
lblConfirmCreateNewDeck=Du bist dabei das neue Deck {0} zu erzeugen. {1}\n\nWillst du fortfahren?\n\n Hinweis: \
|
||||||
Bitte denk daran den "Save"-Knopf im Deck-Editor zu klicken, um das neue Deck dem Deck-Katalog hinzuzufügen!
|
Bitte denk daran den "Save"-Knopf im Deck-Editor zu klicken, um das neue Deck dem Deck-Katalog hinzuzufügen!
|
||||||
lblNewDeckWarning=\nWarnung: Alle ungesicherten Änderungen am aktuellen Deck {0} werden verlorengehen.
|
lblNewDeckWarning=\nWarnung: Alle ungesicherten Änderungen am aktuellen Deck {0} werden verlorengehen.
|
||||||
lblConfirmReplaceDeck=This will replace the contents of the current deck ({0}) with the imported cards.\n\nWould you like to proceed?
|
|
||||||
lblImportCardsDialogTitle=Importiere Karten in aktuelles Deck
|
lblImportCardsDialogTitle=Importiere Karten in aktuelles Deck
|
||||||
lblNewDeckDialogTitle=Erzeuge neues Deck
|
lblNewDeckDialogTitle=Erzeuge neues Deck
|
||||||
#FNetOverlay.java
|
#FNetOverlay.java
|
||||||
|
|||||||
@@ -2898,7 +2898,6 @@ lblDecklistTitle=Decklist
|
|||||||
lblSummaryStats=Summary Statistics
|
lblSummaryStats=Summary Statistics
|
||||||
lblDeckSection=Section
|
lblDeckSection=Section
|
||||||
lblNewDeckCheckbox=Create a New Deck
|
lblNewDeckCheckbox=Create a New Deck
|
||||||
lblReplaceDeckCheckbox=Replace Current Deck
|
|
||||||
lblImportCardsCmd=Import Cards
|
lblImportCardsCmd=Import Cards
|
||||||
lblCreateNewCmd=New Deck
|
lblCreateNewCmd=New Deck
|
||||||
lblErrNotAllowedCard=Set not allowed in {0}
|
lblErrNotAllowedCard=Set not allowed in {0}
|
||||||
@@ -2906,7 +2905,6 @@ lblWarnLimitedCard={0} in {1}
|
|||||||
lblErrCardEditionDate=Set not compliant with Release Date option
|
lblErrCardEditionDate=Set not compliant with Release Date option
|
||||||
lblErrUnsupportedCard=Not allowed in {0}
|
lblErrUnsupportedCard=Not allowed in {0}
|
||||||
lblWarnUnknownCardMsg=Unknown Card or Unsupported in Forge
|
lblWarnUnknownCardMsg=Unknown Card or Unsupported in Forge
|
||||||
lblWarnNotInInventory=Card not found in inventory
|
|
||||||
lblWarnTooManyCommanders=Current {0} Section contains {1} potential Commander Cards: {2}
|
lblWarnTooManyCommanders=Current {0} Section contains {1} potential Commander Cards: {2}
|
||||||
lblWarnCommandersInSideExtra=Please check and move one to the Commander Section, in case.
|
lblWarnCommandersInSideExtra=Please check and move one to the Commander Section, in case.
|
||||||
lblWarnDeckSectionNotAllowedInEditor={0} Section is not allowed in {1}
|
lblWarnDeckSectionNotAllowedInEditor={0} Section is not allowed in {1}
|
||||||
@@ -3003,7 +3001,6 @@ lblCardImportWarning=\nWarning: The deck {0} will be renamed as {1}.
|
|||||||
lblConfirmCreateNewDeck=You are about to create a new deck {0}. {1}\n\nWould you like to proceed?\n\n Note: \
|
lblConfirmCreateNewDeck=You are about to create a new deck {0}. {1}\n\nWould you like to proceed?\n\n Note: \
|
||||||
Please remember to click on the "Save" button in the Deck Editor to add the new deck to the Catalog!
|
Please remember to click on the "Save" button in the Deck Editor to add the new deck to the Catalog!
|
||||||
lblNewDeckWarning=\nWarning: Any unsaved changes to the current deck {0} will be lost.
|
lblNewDeckWarning=\nWarning: Any unsaved changes to the current deck {0} will be lost.
|
||||||
lblConfirmReplaceDeck=This will replace the contents of the current deck ({0}) with the imported cards.\n\nWould you like to proceed?
|
|
||||||
lblImportCardsDialogTitle=Import cards in the Current Deck
|
lblImportCardsDialogTitle=Import cards in the Current Deck
|
||||||
lblNewDeckDialogTitle=Create a New Deck
|
lblNewDeckDialogTitle=Create a New Deck
|
||||||
#FNetOverlay.java
|
#FNetOverlay.java
|
||||||
|
|||||||
@@ -2847,7 +2847,6 @@ lblDecklistTitle=Decklist
|
|||||||
lblSummaryStats=Summary Statistics
|
lblSummaryStats=Summary Statistics
|
||||||
lblDeckSection=Section
|
lblDeckSection=Section
|
||||||
lblNewDeckCheckbox=Create a New Deck
|
lblNewDeckCheckbox=Create a New Deck
|
||||||
lblReplaceDeckCheckbox=Replace Current Deck
|
|
||||||
lblImportCardsCmd=Import Cards
|
lblImportCardsCmd=Import Cards
|
||||||
lblCreateNewCmd=New Deck
|
lblCreateNewCmd=New Deck
|
||||||
lblErrNotAllowedCard=Set not allowed in {0}
|
lblErrNotAllowedCard=Set not allowed in {0}
|
||||||
@@ -2855,7 +2854,6 @@ lblWarnLimitedCard={0} in {1}
|
|||||||
lblErrCardEditionDate=Set not compliant with Release Date option
|
lblErrCardEditionDate=Set not compliant with Release Date option
|
||||||
lblErrUnsupportedCard=Not allowed in {0}
|
lblErrUnsupportedCard=Not allowed in {0}
|
||||||
lblWarnUnknownCardMsg=Unknown Card or Unsupported in Forge
|
lblWarnUnknownCardMsg=Unknown Card or Unsupported in Forge
|
||||||
lblWarnNotInInventory=Card not found in inventory
|
|
||||||
lblWarnTooManyCommanders=Current {0} Section contains {1} potential Commander Cards: {2}
|
lblWarnTooManyCommanders=Current {0} Section contains {1} potential Commander Cards: {2}
|
||||||
lblWarnCommandersInSideExtra=Please check and move one to the Commander Section, in case.
|
lblWarnCommandersInSideExtra=Please check and move one to the Commander Section, in case.
|
||||||
lblWarnDeckSectionNotAllowedInEditor={0} Section is not allowed in {1}
|
lblWarnDeckSectionNotAllowedInEditor={0} Section is not allowed in {1}
|
||||||
@@ -2952,7 +2950,6 @@ lblCardImportWarning=\nWarning: The deck {0} will be renamed as {1}.
|
|||||||
lblConfirmCreateNewDeck=You are about to create a new deck {0}. {1}\n\nWould you like to proceed?\n\n Note: \
|
lblConfirmCreateNewDeck=You are about to create a new deck {0}. {1}\n\nWould you like to proceed?\n\n Note: \
|
||||||
Please remember to click on the "Save" button in the Deck Editor to add the new deck to the Catalog!
|
Please remember to click on the "Save" button in the Deck Editor to add the new deck to the Catalog!
|
||||||
lblNewDeckWarning=\nWarning: Any unsaved changes to the current deck {0} will be lost.
|
lblNewDeckWarning=\nWarning: Any unsaved changes to the current deck {0} will be lost.
|
||||||
lblConfirmReplaceDeck=This will replace the contents of the current deck ({0}) with the imported cards.\n\nWould you like to proceed?
|
|
||||||
lblImportCardsDialogTitle=Import cards in the Current Deck
|
lblImportCardsDialogTitle=Import cards in the Current Deck
|
||||||
lblNewDeckDialogTitle=Create a New Deck
|
lblNewDeckDialogTitle=Create a New Deck
|
||||||
#FNetOverlay.java
|
#FNetOverlay.java
|
||||||
|
|||||||
@@ -2840,7 +2840,6 @@ lblDecklistTitle=Liste de deck
|
|||||||
lblSummaryStats=Statistiques récapitulatives
|
lblSummaryStats=Statistiques récapitulatives
|
||||||
lblDeckSection=Section
|
lblDeckSection=Section
|
||||||
lblNewDeckCheckbox=Créer un nouveau deck
|
lblNewDeckCheckbox=Créer un nouveau deck
|
||||||
lblReplaceDeckCheckbox=Replace Current Deck
|
|
||||||
lblImportCardsCmd=Importer des cartes
|
lblImportCardsCmd=Importer des cartes
|
||||||
lblCreateNewCmd=Nouveau Deck
|
lblCreateNewCmd=Nouveau Deck
|
||||||
lblErrNotAllowedCard=Définir non autorisé dans {0}
|
lblErrNotAllowedCard=Définir non autorisé dans {0}
|
||||||
@@ -2848,7 +2847,6 @@ lblWarnLimitedCard={0} dans {1}
|
|||||||
lblErrCardEditionDate=Set non conforme avec l'option de date de sortie
|
lblErrCardEditionDate=Set non conforme avec l'option de date de sortie
|
||||||
lblErrUnsupportedCard=Non autorisé dans {0}
|
lblErrUnsupportedCard=Non autorisé dans {0}
|
||||||
lblWarnUnknownCardMsg=Carte inconnue ou non prise en charge dans Forge
|
lblWarnUnknownCardMsg=Carte inconnue ou non prise en charge dans Forge
|
||||||
lblWarnNotInInventory=Card not found in inventory
|
|
||||||
lblWarnTooManyCommanders=La section {0} actuelle contient {1} cartes de commandant potentielles : {2}
|
lblWarnTooManyCommanders=La section {0} actuelle contient {1} cartes de commandant potentielles : {2}
|
||||||
lblWarnCommandersInSideExtra=Veuillez vérifier et en déplacer un vers la section Commandant, au cas où.
|
lblWarnCommandersInSideExtra=Veuillez vérifier et en déplacer un vers la section Commandant, au cas où.
|
||||||
lblWarnDeckSectionNotAllowedInEditor={0} La section n'est pas autorisée dans {1}
|
lblWarnDeckSectionNotAllowedInEditor={0} La section n'est pas autorisée dans {1}
|
||||||
@@ -2946,7 +2944,6 @@ lblCardImportWarning=\nAttention : Le deck {0} sera renommé en {1}.
|
|||||||
lblConfirmCreateNewDeck=Vous êtes sur le point de créer un nouveau deck {0}. {1}\n\nVoulez-vous continuer ?\n\n Remarque : \
|
lblConfirmCreateNewDeck=Vous êtes sur le point de créer un nouveau deck {0}. {1}\n\nVoulez-vous continuer ?\n\n Remarque : \
|
||||||
N'oubliez pas de cliquer sur le bouton "Enregistrer" dans l'éditeur de deck pour ajouter le nouveau deck au catalogue !
|
N'oubliez pas de cliquer sur le bouton "Enregistrer" dans l'éditeur de deck pour ajouter le nouveau deck au catalogue !
|
||||||
lblNewDeckWarning=\nAttention : Toute modification non enregistrée dans le deck actuel {0} sera perdue.
|
lblNewDeckWarning=\nAttention : Toute modification non enregistrée dans le deck actuel {0} sera perdue.
|
||||||
lblConfirmReplaceDeck=This will replace the contents of the current deck ({0}) with the imported cards.\n\nWould you like to proceed?
|
|
||||||
lblImportCardsDialogTitle=Importer des cartes dans le Deck actuel
|
lblImportCardsDialogTitle=Importer des cartes dans le Deck actuel
|
||||||
lblNewDeckDialogTitle=Créer un nouveau deck
|
lblNewDeckDialogTitle=Créer un nouveau deck
|
||||||
#FNetOverlay.java
|
#FNetOverlay.java
|
||||||
|
|||||||
@@ -2836,7 +2836,6 @@ lblDecklistTitle=Lista delle Carte da Importare
|
|||||||
lblSummaryStats=Statistiche Generali
|
lblSummaryStats=Statistiche Generali
|
||||||
lblDeckSection=Sezione
|
lblDeckSection=Sezione
|
||||||
lblNewDeckCheckbox=Crea un nuovo mazzo
|
lblNewDeckCheckbox=Crea un nuovo mazzo
|
||||||
lblReplaceDeckCheckbox=Replace Current Deck
|
|
||||||
lblImportCardsCmd=Importa le carte
|
lblImportCardsCmd=Importa le carte
|
||||||
lblCreateNewCmd=Nuovo mazzo
|
lblCreateNewCmd=Nuovo mazzo
|
||||||
lblErrNotAllowedCard=Edizione non permessa in {0}
|
lblErrNotAllowedCard=Edizione non permessa in {0}
|
||||||
@@ -2844,7 +2843,6 @@ lblWarnLimitedCard={0} in {1}
|
|||||||
lblErrCardEditionDate=Edizione non valida secondo l'opzione sulla data di pubblicazione selezionata
|
lblErrCardEditionDate=Edizione non valida secondo l'opzione sulla data di pubblicazione selezionata
|
||||||
lblErrUnsupportedCard=Non Permesso in {0}
|
lblErrUnsupportedCard=Non Permesso in {0}
|
||||||
lblWarnUnknownCardMsg=Carta Sconosciuta, o non supportata in Forge
|
lblWarnUnknownCardMsg=Carta Sconosciuta, o non supportata in Forge
|
||||||
lblWarnNotInInventory=Card not found in inventory
|
|
||||||
lblWarnTooManyCommanders=La Sezione {0} contiene {1} potenziali carte Commander: {2}
|
lblWarnTooManyCommanders=La Sezione {0} contiene {1} potenziali carte Commander: {2}
|
||||||
lblWarnCommandersInSideExtra=Per favore, controlla e nel caso spostane una nella sezione Commander.
|
lblWarnCommandersInSideExtra=Per favore, controlla e nel caso spostane una nella sezione Commander.
|
||||||
lblWarnDeckSectionNotAllowedInEditor={0} Sezione non è permessa in {1}
|
lblWarnDeckSectionNotAllowedInEditor={0} Sezione non è permessa in {1}
|
||||||
@@ -2944,7 +2942,6 @@ lblCardImportWarning=\nAttenzione: Il mazzo {0} sarà rinominato come {1}.
|
|||||||
lblConfirmCreateNewDeck=Si sta per creare un nuovo mazzo {0}. {1}\n\nSi desidera procedere?\n\n Nota: \
|
lblConfirmCreateNewDeck=Si sta per creare un nuovo mazzo {0}. {1}\n\nSi desidera procedere?\n\n Nota: \
|
||||||
Non dimenticare di premere il tasto "Salva" una volta importate le carte per aggiungere il nuovo mazzo al catalogo!
|
Non dimenticare di premere il tasto "Salva" una volta importate le carte per aggiungere il nuovo mazzo al catalogo!
|
||||||
lblNewDeckWarning=\nAttenzione: Qualsiasi modifica non salvata al mazzo corrente {0} sarà persa.
|
lblNewDeckWarning=\nAttenzione: Qualsiasi modifica non salvata al mazzo corrente {0} sarà persa.
|
||||||
lblConfirmReplaceDeck=This will replace the contents of the current deck ({0}) with the imported cards.\n\nWould you like to proceed?
|
|
||||||
lblImportCardsDialogTitle=Importa le carte nel mazzo corrente
|
lblImportCardsDialogTitle=Importa le carte nel mazzo corrente
|
||||||
lblNewDeckDialogTitle=Crea un nuovo mazzo
|
lblNewDeckDialogTitle=Crea un nuovo mazzo
|
||||||
#FNetOverlay.java
|
#FNetOverlay.java
|
||||||
|
|||||||
@@ -2835,7 +2835,6 @@ lblDecklistTitle=Decklist
|
|||||||
lblSummaryStats=Summary Statistics
|
lblSummaryStats=Summary Statistics
|
||||||
lblDeckSection=Section
|
lblDeckSection=Section
|
||||||
lblNewDeckCheckbox=Create a New Deck
|
lblNewDeckCheckbox=Create a New Deck
|
||||||
lblReplaceDeckCheckbox=Replace Current Deck
|
|
||||||
lblImportCardsCmd=Import Cards
|
lblImportCardsCmd=Import Cards
|
||||||
lblCreateNewCmd=New Deck
|
lblCreateNewCmd=New Deck
|
||||||
lblErrNotAllowedCard=Set not allowed in {0}
|
lblErrNotAllowedCard=Set not allowed in {0}
|
||||||
@@ -2843,7 +2842,6 @@ lblWarnLimitedCard={0} in {1}
|
|||||||
lblErrCardEditionDate=Set not compliant with Release Date option
|
lblErrCardEditionDate=Set not compliant with Release Date option
|
||||||
lblErrUnsupportedCard=Not allowed in {0}
|
lblErrUnsupportedCard=Not allowed in {0}
|
||||||
lblWarnUnknownCardMsg=Unknown Card or Unsupported in Forge
|
lblWarnUnknownCardMsg=Unknown Card or Unsupported in Forge
|
||||||
lblWarnNotInInventory=Card not found in inventory
|
|
||||||
lblWarnTooManyCommanders=Current {0} Section contains {1} potential Commander Cards: {2}
|
lblWarnTooManyCommanders=Current {0} Section contains {1} potential Commander Cards: {2}
|
||||||
lblWarnCommandersInSideExtra=Please check and move one to the Commander Section, in case.
|
lblWarnCommandersInSideExtra=Please check and move one to the Commander Section, in case.
|
||||||
lblWarnDeckSectionNotAllowedInEditor={0} Section is not allowed in {1}
|
lblWarnDeckSectionNotAllowedInEditor={0} Section is not allowed in {1}
|
||||||
@@ -2940,7 +2938,6 @@ lblCardImportWarning=\nWarning: The deck {0} will be renamed as {1}.
|
|||||||
lblConfirmCreateNewDeck=You are about to create a new deck {0}. {1}\n\nWould you like to proceed?\n\n Note: \
|
lblConfirmCreateNewDeck=You are about to create a new deck {0}. {1}\n\nWould you like to proceed?\n\n Note: \
|
||||||
Please remember to click on the "Save" button in the Deck Editor to add the new deck to the Catalog!
|
Please remember to click on the "Save" button in the Deck Editor to add the new deck to the Catalog!
|
||||||
lblNewDeckWarning=\nWarning: Any unsaved changes to the current deck {0} will be lost.
|
lblNewDeckWarning=\nWarning: Any unsaved changes to the current deck {0} will be lost.
|
||||||
lblConfirmReplaceDeck=This will replace the contents of the current deck ({0}) with the imported cards.\n\nWould you like to proceed?
|
|
||||||
lblImportCardsDialogTitle=Import cards in the Current Deck
|
lblImportCardsDialogTitle=Import cards in the Current Deck
|
||||||
lblNewDeckDialogTitle=Create a New Deck
|
lblNewDeckDialogTitle=Create a New Deck
|
||||||
#FNetOverlay.java
|
#FNetOverlay.java
|
||||||
|
|||||||
@@ -2917,7 +2917,6 @@ lblDecklistTitle=Lista de decks
|
|||||||
lblSummaryStats=Estatísticas Resumidas
|
lblSummaryStats=Estatísticas Resumidas
|
||||||
lblDeckSection=Seção
|
lblDeckSection=Seção
|
||||||
lblNewDeckCheckbox=Criar um Novo deck
|
lblNewDeckCheckbox=Criar um Novo deck
|
||||||
lblReplaceDeckCheckbox=Replace Current Deck
|
|
||||||
lblImportCardsCmd=Importar Cartas
|
lblImportCardsCmd=Importar Cartas
|
||||||
lblCreateNewCmd=Novo Deck
|
lblCreateNewCmd=Novo Deck
|
||||||
lblErrNotAllowedCard=Coleção não permitida em {0}
|
lblErrNotAllowedCard=Coleção não permitida em {0}
|
||||||
@@ -2925,7 +2924,6 @@ lblWarnLimitedCard={0} em {1}
|
|||||||
lblErrCardEditionDate=Coleção não compatível com a opção de Data de Lançamento
|
lblErrCardEditionDate=Coleção não compatível com a opção de Data de Lançamento
|
||||||
lblErrUnsupportedCard=Não permitido em {0}
|
lblErrUnsupportedCard=Não permitido em {0}
|
||||||
lblWarnUnknownCardMsg=Carta desconhecida ou não suportada no Forge
|
lblWarnUnknownCardMsg=Carta desconhecida ou não suportada no Forge
|
||||||
lblWarnNotInInventory=Card not found in inventory
|
|
||||||
lblWarnTooManyCommanders=Seção {0} Atual contém {1} Cartas de Comandante em potencial\: {2}
|
lblWarnTooManyCommanders=Seção {0} Atual contém {1} Cartas de Comandante em potencial\: {2}
|
||||||
lblWarnCommandersInSideExtra=Verifique e mova um para a seção do Comandante.
|
lblWarnCommandersInSideExtra=Verifique e mova um para a seção do Comandante.
|
||||||
lblWarnDeckSectionNotAllowedInEditor=Seção {0} não é permitida em {1}
|
lblWarnDeckSectionNotAllowedInEditor=Seção {0} não é permitida em {1}
|
||||||
@@ -3014,7 +3012,6 @@ Deseja prosseguir?\n\
|
|||||||
Nota\: Por favor, lembre-se de clicar no botão "Salvar" no Editor do Deck para adicioná-lo ao Catálogo\!
|
Nota\: Por favor, lembre-se de clicar no botão "Salvar" no Editor do Deck para adicioná-lo ao Catálogo\!
|
||||||
lblNewDeckWarning=\n\
|
lblNewDeckWarning=\n\
|
||||||
Aviso\: Qualquer alteração não salva no deck atual {0} será perdida.
|
Aviso\: Qualquer alteração não salva no deck atual {0} será perdida.
|
||||||
lblConfirmReplaceDeck=This will replace the contents of the current deck ({0}) with the imported cards.\n\nWould you like to proceed?
|
|
||||||
lblImportCardsDialogTitle=Importar cartas no Deck Atual
|
lblImportCardsDialogTitle=Importar cartas no Deck Atual
|
||||||
lblNewDeckDialogTitle=Criar um Novo deck
|
lblNewDeckDialogTitle=Criar um Novo deck
|
||||||
#FNetOverlay.java
|
#FNetOverlay.java
|
||||||
|
|||||||
@@ -2844,7 +2844,6 @@ lblDecklistTitle=套牌列表
|
|||||||
lblSummaryStats=统计摘要
|
lblSummaryStats=统计摘要
|
||||||
lblDeckSection=部分
|
lblDeckSection=部分
|
||||||
lblNewDeckCheckbox=创建一个新套牌
|
lblNewDeckCheckbox=创建一个新套牌
|
||||||
lblReplaceDeckCheckbox=Replace Current Deck
|
|
||||||
lblImportCardsCmd=导入牌张
|
lblImportCardsCmd=导入牌张
|
||||||
lblCreateNewCmd=新建套牌
|
lblCreateNewCmd=新建套牌
|
||||||
lblErrNotAllowedCard=系列{0}不被允许
|
lblErrNotAllowedCard=系列{0}不被允许
|
||||||
@@ -2852,7 +2851,6 @@ lblWarnLimitedCard={0}中的{1}
|
|||||||
lblErrCardEditionDate=不符合上市日期选项
|
lblErrCardEditionDate=不符合上市日期选项
|
||||||
lblErrUnsupportedCard={0}不被允许
|
lblErrUnsupportedCard={0}不被允许
|
||||||
lblWarnUnknownCardMsg=未知的牌张或未被forge支持的牌张
|
lblWarnUnknownCardMsg=未知的牌张或未被forge支持的牌张
|
||||||
lblWarnNotInInventory=Card not found in inventory
|
|
||||||
lblWarnTooManyCommanders=现在{0}部分包含{1}张潜在的指挥官牌张: {2}
|
lblWarnTooManyCommanders=现在{0}部分包含{1}张潜在的指挥官牌张: {2}
|
||||||
lblWarnCommandersInSideExtra=如果确实是指挥官,请进行进行检查并将其中的一张移动到指挥官区。
|
lblWarnCommandersInSideExtra=如果确实是指挥官,请进行进行检查并将其中的一张移动到指挥官区。
|
||||||
lblWarnDeckSectionNotAllowedInEditor={0}部分中的{1}不被允许
|
lblWarnDeckSectionNotAllowedInEditor={0}部分中的{1}不被允许
|
||||||
@@ -2930,7 +2928,6 @@ lblCardImportWarning=\n警告:套牌{0}将被重命名为{1}。
|
|||||||
lblConfirmCreateNewDeck=你即将创建一个新套牌{0}。{1}\n\n你想要继续吗?\n\n 注意:请记得点击套牌编辑器中的\"保存按钮\"以\
|
lblConfirmCreateNewDeck=你即将创建一个新套牌{0}。{1}\n\n你想要继续吗?\n\n 注意:请记得点击套牌编辑器中的\"保存按钮\"以\
|
||||||
将新建的套牌保存到目录中!
|
将新建的套牌保存到目录中!
|
||||||
lblNewDeckWarning=\n警告:对于当前套牌{0}的任何未保存更改丢将被丢弃。
|
lblNewDeckWarning=\n警告:对于当前套牌{0}的任何未保存更改丢将被丢弃。
|
||||||
lblConfirmReplaceDeck=This will replace the contents of the current deck ({0}) with the imported cards.\n\nWould you like to proceed?
|
|
||||||
lblImportCardsDialogTitle=将牌张导入到当前套牌
|
lblImportCardsDialogTitle=将牌张导入到当前套牌
|
||||||
lblNewDeckDialogTitle=创建一个新套牌
|
lblNewDeckDialogTitle=创建一个新套牌
|
||||||
#FNetOverlay.java
|
#FNetOverlay.java
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
[metadata]
|
|
||||||
Name:Possibility Storm - Edge of Eternities #03
|
|
||||||
URL:https://www.cardforge.org
|
|
||||||
Goal:Win
|
|
||||||
Turns:1
|
|
||||||
Difficulty:Rare
|
|
||||||
Description:Win this turn. Your opponent has 10000 life! Deal at least that much damage this turn to win. Ensure your solution satisfies all possible blocks. Good luck!
|
|
||||||
[state]
|
|
||||||
turn=1
|
|
||||||
activeplayer=p0
|
|
||||||
activephase=MAIN1
|
|
||||||
p0life=-1
|
|
||||||
p0hand=Welcome the Darkness;Bloodthirsty Conqueror;Vayne's Treachery;Syr Vondam, Sunstar Exemplar
|
|
||||||
p0battlefield=Herald of Eternal Dawn;Jumbo Cactuar;The Masamune;Enduring Tenacity;Plains;Plains;Plains;Swamp;Swamp;Swamp;Forest;Forest
|
|
||||||
p1life=10000
|
|
||||||
p1battlefield=Zidane, Tantalus Thief;Absolute Virtue|Id:1;Pain for All|AttachedTo:1
|
|
||||||
@@ -13,25 +13,15 @@ import forge.gui.util.SOptionPane;
|
|||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.localinstance.properties.ForgePreferences;
|
import forge.localinstance.properties.ForgePreferences;
|
||||||
import forge.model.FModel;
|
import forge.model.FModel;
|
||||||
import forge.util.ItemPool;
|
|
||||||
import forge.util.Localizer;
|
import forge.util.Localizer;
|
||||||
import forge.util.StreamUtil;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
import java.text.DateFormatSymbols;
|
import java.text.DateFormatSymbols;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class DeckImportController {
|
public class DeckImportController {
|
||||||
public enum ImportBehavior {
|
private boolean createNewDeck;
|
||||||
MERGE,
|
|
||||||
CREATE_NEW,
|
|
||||||
REPLACE_CURRENT
|
|
||||||
}
|
|
||||||
|
|
||||||
private ImportBehavior importBehavior;
|
|
||||||
// Date filter
|
// Date filter
|
||||||
private final ICheckBox dateTimeCheck;
|
private final ICheckBox dateTimeCheck;
|
||||||
private final IComboBox<String> monthDropdown;
|
private final IComboBox<String> monthDropdown;
|
||||||
@@ -40,7 +30,7 @@ public class DeckImportController {
|
|||||||
private CardDb.CardArtPreference artPreference;
|
private CardDb.CardArtPreference artPreference;
|
||||||
private boolean smartCardArt;
|
private boolean smartCardArt;
|
||||||
// Block Preference Filter
|
// Block Preference Filter
|
||||||
private boolean includeBnRInDeck = false;
|
private boolean inlcludeBnRInDeck = false;
|
||||||
|
|
||||||
private final List<Token> tokens = new ArrayList<>();
|
private final List<Token> tokens = new ArrayList<>();
|
||||||
private final Map<PaperCard, Token> cardsInTokens = new HashMap<>();
|
private final Map<PaperCard, Token> cardsInTokens = new HashMap<>();
|
||||||
@@ -48,14 +38,7 @@ public class DeckImportController {
|
|||||||
private Deck currentDeckInEditor = null;
|
private Deck currentDeckInEditor = null;
|
||||||
private DeckFormat currentDeckFormat;
|
private DeckFormat currentDeckFormat;
|
||||||
private GameFormat currentGameFormat;
|
private GameFormat currentGameFormat;
|
||||||
private GameType currentGameType;
|
|
||||||
private final List<DeckSection> allowedSections = new ArrayList<>();
|
private final List<DeckSection> allowedSections = new ArrayList<>();
|
||||||
private ItemPool<PaperCard> playerInventory;
|
|
||||||
/**
|
|
||||||
* If a free card is missing from a player's inventory (e.g. a basic land), it gets run through this function, which
|
|
||||||
* can handle creation of a usable print.
|
|
||||||
*/
|
|
||||||
private Function<PaperCard, PaperCard> freePrintSupplier;
|
|
||||||
|
|
||||||
public DeckImportController(ICheckBox dateTimeCheck0,
|
public DeckImportController(ICheckBox dateTimeCheck0,
|
||||||
IComboBox<String> monthDropdown0, IComboBox<Integer> yearDropdown0,
|
IComboBox<String> monthDropdown0, IComboBox<Integer> yearDropdown0,
|
||||||
@@ -71,14 +54,13 @@ public class DeckImportController {
|
|||||||
*/
|
*/
|
||||||
this.currentDeckNotEmpty = currentDeckNotEmpty;
|
this.currentDeckNotEmpty = currentDeckNotEmpty;
|
||||||
// this option will control the "new deck" action controlled by UI widget
|
// this option will control the "new deck" action controlled by UI widget
|
||||||
this.importBehavior = ImportBehavior.MERGE;
|
createNewDeck = false;
|
||||||
|
|
||||||
// Init default parameters
|
// Init default parameters
|
||||||
this.artPreference = StaticData.instance().getCardArtPreference(); // default
|
this.artPreference = StaticData.instance().getCardArtPreference(); // default
|
||||||
this.smartCardArt = StaticData.instance().isEnabledCardArtSmartSelection();
|
this.smartCardArt = StaticData.instance().isEnabledCardArtSmartSelection();
|
||||||
this.currentDeckFormat = null;
|
this.currentDeckFormat = null;
|
||||||
this.currentGameFormat = null;
|
this.currentGameFormat = null;
|
||||||
this.currentGameType = null;
|
|
||||||
fillDateDropdowns();
|
fillDateDropdowns();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,23 +68,13 @@ public class DeckImportController {
|
|||||||
if (gameType == null){
|
if (gameType == null){
|
||||||
this.currentGameFormat = null;
|
this.currentGameFormat = null;
|
||||||
this.currentDeckFormat = null;
|
this.currentDeckFormat = null;
|
||||||
this.currentGameType = null;
|
|
||||||
} else {
|
} else {
|
||||||
// get the game format with the same name of current game type (if any)
|
// get the game format with the same name of current game type (if any)
|
||||||
this.currentDeckFormat = gameType.getDeckFormat();
|
this.currentDeckFormat = gameType.getDeckFormat();
|
||||||
this.currentGameFormat = FModel.getFormats().get(gameType.name());
|
this.currentGameFormat = FModel.getFormats().get(gameType.name());
|
||||||
this.currentGameType = gameType;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPlayerInventory(ItemPool<PaperCard> inventory) {
|
|
||||||
this.playerInventory = inventory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFreePrintConverter(Function<PaperCard, PaperCard> freePrintSupplier) {
|
|
||||||
this.freePrintSupplier = freePrintSupplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCurrentDeckInEditor(Deck deckInEditor){
|
public void setCurrentDeckInEditor(Deck deckInEditor){
|
||||||
this.currentDeckInEditor = deckInEditor;
|
this.currentDeckInEditor = deckInEditor;
|
||||||
}
|
}
|
||||||
@@ -133,13 +105,11 @@ public class DeckImportController {
|
|||||||
return this.smartCardArt;
|
return this.smartCardArt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setImportBehavior(ImportBehavior importBehavior) {
|
public void setCreateNewDeck(boolean createNewDeck){
|
||||||
this.importBehavior = importBehavior;
|
this.createNewDeck = createNewDeck;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImportBehavior getImportBehavior() {
|
public boolean getCreateNewDeck() { return this.createNewDeck; }
|
||||||
return importBehavior;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fillDateDropdowns() {
|
private void fillDateDropdowns() {
|
||||||
DateFormatSymbols dfs = new DateFormatSymbols();
|
DateFormatSymbols dfs = new DateFormatSymbols();
|
||||||
@@ -189,10 +159,10 @@ public class DeckImportController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void importBannedAndRestrictedCards(boolean includeBannedAndRestricted){
|
public void importBannedAndRestrictedCards(boolean includeBannedAndRestricted){
|
||||||
this.includeBnRInDeck = includeBannedAndRestricted;
|
this.inlcludeBnRInDeck = includeBannedAndRestricted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean importBannedAndRestrictedCards(){ return this.includeBnRInDeck; }
|
public boolean importBannedAndRestrictedCards(){ return this.inlcludeBnRInDeck; }
|
||||||
|
|
||||||
public List<Token> parseInput(String input) {
|
public List<Token> parseInput(String input) {
|
||||||
tokens.clear();
|
tokens.clear();
|
||||||
@@ -216,7 +186,7 @@ public class DeckImportController {
|
|||||||
if (!this.allowedSections.isEmpty())
|
if (!this.allowedSections.isEmpty())
|
||||||
recognizer.setAllowedDeckSections(this.allowedSections);
|
recognizer.setAllowedDeckSections(this.allowedSections);
|
||||||
// Banned and Restricted Card Policy
|
// Banned and Restricted Card Policy
|
||||||
if (this.includeBnRInDeck)
|
if (this.inlcludeBnRInDeck)
|
||||||
recognizer.forceImportBannedAndRestrictedCards();
|
recognizer.forceImportBannedAndRestrictedCards();
|
||||||
|
|
||||||
String[] lines = input.split("\n");
|
String[] lines = input.split("\n");
|
||||||
@@ -226,13 +196,8 @@ public class DeckImportController {
|
|||||||
|
|
||||||
if (this.currentGameFormatAllowsCommander()) {
|
if (this.currentGameFormatAllowsCommander()) {
|
||||||
List<Pair<Integer, Token>> commanderTokens = getTokensInSection(DeckSection.Commander);
|
List<Pair<Integer, Token>> commanderTokens = getTokensInSection(DeckSection.Commander);
|
||||||
if (commanderTokens.isEmpty()) {
|
if (commanderTokens.isEmpty()) // Check commanders in Sideboard only if the commander section is empty
|
||||||
// Check commanders in Sideboard only if the commander section is empty
|
checkAndFixCommanderIn(DeckSection.Sideboard);
|
||||||
if(!getTokensInSection(DeckSection.Sideboard).isEmpty())
|
|
||||||
checkAndFixCommanderIn(DeckSection.Sideboard);
|
|
||||||
else
|
|
||||||
checkAndFixCommanderIn(DeckSection.Main);
|
|
||||||
}
|
|
||||||
checkAndFixCommanderIn(DeckSection.Commander);
|
checkAndFixCommanderIn(DeckSection.Commander);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,7 +309,7 @@ public class DeckImportController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean currentGameFormatAllowsCommander(){
|
public boolean currentGameFormatAllowsCommander(){
|
||||||
return this.allowedSections.contains(DeckSection.Commander) || this.currentGameType == GameType.PlanarConquest;
|
return this.allowedSections.contains(DeckSection.Commander);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Token> optimiseCardArtInTokens(){
|
public List<Token> optimiseCardArtInTokens(){
|
||||||
@@ -367,8 +332,13 @@ public class DeckImportController {
|
|||||||
else
|
else
|
||||||
refTokenMap = tokensPerSectionWithSet;
|
refTokenMap = tokensPerSectionWithSet;
|
||||||
|
|
||||||
List<Token> tokensInSection = refTokenMap.computeIfAbsent(tokenSection, e -> new ArrayList<>());
|
List<Token> tokensInSection = refTokenMap.getOrDefault(tokenSection, null);
|
||||||
tokensInSection.add(token);
|
if (tokensInSection == null) {
|
||||||
|
tokensInSection = new ArrayList<>();
|
||||||
|
tokensInSection.add(token);
|
||||||
|
refTokenMap.put(tokenSection, tokensInSection);
|
||||||
|
} else
|
||||||
|
tokensInSection.add(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tokensPerSectionWithNoSet.isEmpty())
|
if (tokensPerSectionWithNoSet.isEmpty())
|
||||||
@@ -386,7 +356,7 @@ public class DeckImportController {
|
|||||||
|
|
||||||
Map<DeckSection, CardPool> referencePoolPerSection = new HashMap<>();
|
Map<DeckSection, CardPool> referencePoolPerSection = new HashMap<>();
|
||||||
|
|
||||||
if (this.currentDeckNotEmpty && this.importBehavior == ImportBehavior.MERGE && this.currentDeckInEditor != null){
|
if (this.currentDeckNotEmpty && !this.createNewDeck && this.currentDeckInEditor != null){
|
||||||
// We will always consider ONLY sections for cards needing art optimisation
|
// We will always consider ONLY sections for cards needing art optimisation
|
||||||
for (DeckSection section : tokensPerSectionWithNoSet.keySet()){
|
for (DeckSection section : tokensPerSectionWithNoSet.keySet()){
|
||||||
CardPool cardsInDeck = this.currentDeckInEditor.get(section);
|
CardPool cardsInDeck = this.currentDeckInEditor.get(section);
|
||||||
@@ -466,102 +436,6 @@ public class DeckImportController {
|
|||||||
return tokens;
|
return tokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Token> constrainTokensToInventory() {
|
|
||||||
if(this.playerInventory == null)
|
|
||||||
return tokens;
|
|
||||||
CardPool availableInventory = new CardPool(this.playerInventory);
|
|
||||||
//Map of tokens to the things we're gonna replace them with.
|
|
||||||
Map<Token, List<Token>> tokenReplacers = new LinkedHashMap<>();
|
|
||||||
//If we're adding to our existing deck, ensure we aren't counting the cards already in it.
|
|
||||||
if(this.importBehavior == ImportBehavior.MERGE && this.currentDeckInEditor != null)
|
|
||||||
availableInventory.removeAll(this.currentDeckInEditor.getAllCardsInASinglePool(true, true));
|
|
||||||
if(this.currentGameType == GameType.PlanarConquest && currentDeckInEditor != null)
|
|
||||||
availableInventory.removeAllFlat(this.currentDeckInEditor.getCommanders());
|
|
||||||
//Step 1: For each token, if it's asking for more copies of a print than we can supply, split the difference out
|
|
||||||
//into a token that's indifferent to the edition. Reduce available inventory accordingly.
|
|
||||||
for (Token token : this.tokens) {
|
|
||||||
if (!token.isCardToken())
|
|
||||||
continue;
|
|
||||||
PaperCard card = token.getCard();
|
|
||||||
int requestedAmount = token.getQuantity();
|
|
||||||
if (card == null)
|
|
||||||
continue;
|
|
||||||
if (token.cardRequestHasNoCode()) {
|
|
||||||
List<Token> list = new ArrayList<>();
|
|
||||||
tokenReplacers.put(token, list);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
int available = availableInventory.count(card);
|
|
||||||
if (available <= 0) {
|
|
||||||
List<Token> list = new ArrayList<>();
|
|
||||||
tokenReplacers.put(token, list);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
int numTaken = Math.min(requestedAmount, available);
|
|
||||||
availableInventory.remove(card, numTaken);
|
|
||||||
if (available >= requestedAmount)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
List<Token> list = new ArrayList<>();
|
|
||||||
list.add(Token.LegalCard(card, numTaken, token.getTokenSection(), true));
|
|
||||||
tokenReplacers.put(token, list);
|
|
||||||
}
|
|
||||||
if(tokenReplacers.isEmpty())
|
|
||||||
return tokens; //We have every card that was requested.
|
|
||||||
//Step 2: Try to find alternative prints for the ones that do not request an edition.
|
|
||||||
int capacity = tokens.size();
|
|
||||||
for(Map.Entry<Token, List<Token>> tokenReplacer : tokenReplacers.entrySet()) {
|
|
||||||
Token token = tokenReplacer.getKey();
|
|
||||||
DeckSection tokenSection = token.getTokenSection();
|
|
||||||
List<Token> replacementList = tokenReplacer.getValue();
|
|
||||||
PaperCard card = token.getCard();
|
|
||||||
String cardName = card.getName();
|
|
||||||
CardPool substitutes = availableInventory.getFilteredPool(c -> c.getName().equals(cardName));
|
|
||||||
// stream().toList() causes crash on Android 8-13, use Collectors.toList()
|
|
||||||
// ref: https://developer.android.com/reference/java/util/stream/Stream#toList()
|
|
||||||
List<Map.Entry<PaperCard, Integer>> sortedSubstitutes = StreamUtil.stream(substitutes).sorted(Comparator.comparingInt(Map.Entry::getValue)).collect(Collectors.toList());
|
|
||||||
int neededQuantity = token.getQuantity();
|
|
||||||
for(Token found : replacementList) {
|
|
||||||
//If there's an item in the replacement list already it means we've already found some of the needed copies.
|
|
||||||
neededQuantity -= found.getQuantity();
|
|
||||||
}
|
|
||||||
for(int i = 0; i < sortedSubstitutes.size() && neededQuantity > 0; i++) {
|
|
||||||
Map.Entry<PaperCard, Integer> item = sortedSubstitutes.get(i);
|
|
||||||
PaperCard replacement = item.getKey();
|
|
||||||
int toMove = Math.min(neededQuantity, item.getValue());
|
|
||||||
replacementList.add(Token.LegalCard(replacement, toMove, tokenSection, true));
|
|
||||||
availableInventory.remove(replacement, toMove);
|
|
||||||
neededQuantity -= toMove;
|
|
||||||
capacity++;
|
|
||||||
}
|
|
||||||
if(neededQuantity > 0) {
|
|
||||||
PaperCard freePrint = getInfiniteSupplyPrinting(card);
|
|
||||||
if(freePrint != null)
|
|
||||||
replacementList.add(Token.NotInInventoryFree(freePrint, neededQuantity, tokenSection));
|
|
||||||
else
|
|
||||||
replacementList.add(Token.NotInInventory(card, neededQuantity, tokenSection));
|
|
||||||
capacity++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Step 3: Apply the replacement list.
|
|
||||||
List<Token> newList = new ArrayList<>(capacity);
|
|
||||||
for(Token t : this.tokens) {
|
|
||||||
if(tokenReplacers.containsKey(t))
|
|
||||||
newList.addAll(tokenReplacers.get(t));
|
|
||||||
else
|
|
||||||
newList.add(t);
|
|
||||||
}
|
|
||||||
this.tokens.clear();
|
|
||||||
this.tokens.addAll(newList);
|
|
||||||
return tokens;
|
|
||||||
}
|
|
||||||
|
|
||||||
private PaperCard getInfiniteSupplyPrinting(PaperCard card) {
|
|
||||||
if(this.freePrintSupplier == null)
|
|
||||||
return null;
|
|
||||||
return freePrintSupplier.apply(card);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int countTokens(List<Token> tokensInSection){
|
private int countTokens(List<Token> tokensInSection){
|
||||||
if (tokensInSection == null || tokensInSection.isEmpty())
|
if (tokensInSection == null || tokensInSection.isEmpty())
|
||||||
return 0;
|
return 0;
|
||||||
@@ -613,31 +487,27 @@ public class DeckImportController {
|
|||||||
if (tokens.isEmpty()) { return null; }
|
if (tokens.isEmpty()) { return null; }
|
||||||
|
|
||||||
String deckName = "";
|
String deckName = "";
|
||||||
if (currentDeckName != null && !currentDeckName.trim().isEmpty())
|
if (currentDeckName != null && currentDeckName.trim().length() > 0)
|
||||||
deckName = String.format("\"%s\"", currentDeckName.trim());
|
deckName = String.format("\"%s\"", currentDeckName.trim());
|
||||||
|
|
||||||
String tokenDeckName = getTokenDeckNameIfAny();
|
String tokenDeckName = getTokenDeckNameIfAny();
|
||||||
if (!tokenDeckName.isEmpty())
|
if (tokenDeckName.length() > 0)
|
||||||
tokenDeckName = String.format("\"%s\"", tokenDeckName);
|
tokenDeckName = String.format("\"%s\"", tokenDeckName);
|
||||||
|
|
||||||
if(this.currentDeckNotEmpty) {
|
if (createNewDeck){
|
||||||
final String warning;
|
String extraWarning = currentDeckNotEmpty ? localizer.getMessage("lblNewDeckWarning", deckName) : "";
|
||||||
final String title;
|
final String warning = localizer.getMessage("lblConfirmCreateNewDeck", tokenDeckName, extraWarning);
|
||||||
if (this.importBehavior == ImportBehavior.CREATE_NEW) {
|
if (!SOptionPane.showConfirmDialog(warning, localizer.getMessage("lblNewDeckDialogTitle"),
|
||||||
String extraWarning = localizer.getMessage("lblNewDeckWarning", deckName);
|
localizer.getMessage("lblYes"), localizer.getMessage("lblNo"))) {
|
||||||
warning = localizer.getMessage("lblConfirmCreateNewDeck", tokenDeckName, extraWarning);
|
return null;
|
||||||
title = localizer.getMessage("lblNewDeckDialogTitle");
|
|
||||||
} else if (this.importBehavior == ImportBehavior.MERGE){
|
|
||||||
String extraWarning = (!tokenDeckName.isEmpty() && !tokenDeckName.equals(deckName)) ?
|
|
||||||
localizer.getMessage("lblCardImportWarning", deckName, tokenDeckName) : "";
|
|
||||||
warning = localizer.getMessage("lblConfirmCardImport", deckName, extraWarning);
|
|
||||||
title = localizer.getMessage("lblImportCardsDialogTitle");
|
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
warning = localizer.getMessage("lblConfirmReplaceDeck", deckName);
|
else if (this.currentDeckNotEmpty){
|
||||||
title = localizer.getMessage("lblNewDeckDialogTitle");
|
String extraWarning = (tokenDeckName.length() > 0 && !tokenDeckName.equals(deckName)) ?
|
||||||
}
|
localizer.getMessage("lblCardImportWarning", deckName, tokenDeckName) : "";
|
||||||
if (!SOptionPane.showConfirmDialog(warning, title,
|
final String warning = localizer.getMessage("lblConfirmCardImport", deckName, extraWarning);
|
||||||
|
if (!SOptionPane.showConfirmDialog(warning,
|
||||||
|
localizer.getMessage("lblImportCardsDialogTitle"),
|
||||||
localizer.getMessage("lblYes"), localizer.getMessage("lblNo")))
|
localizer.getMessage("lblYes"), localizer.getMessage("lblNo")))
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -646,7 +516,7 @@ public class DeckImportController {
|
|||||||
final TokenType type = t.getType();
|
final TokenType type = t.getType();
|
||||||
// only Deck Name, legal card and limited card tokens will be analysed!
|
// only Deck Name, legal card and limited card tokens will be analysed!
|
||||||
if (!t.isTokenForDeck() ||
|
if (!t.isTokenForDeck() ||
|
||||||
(type == TokenType.LIMITED_CARD && !this.includeBnRInDeck))
|
(type == TokenType.LIMITED_CARD && !this.inlcludeBnRInDeck))
|
||||||
continue; // SKIP token
|
continue; // SKIP token
|
||||||
|
|
||||||
if (type == TokenType.DECK_NAME) {
|
if (type == TokenType.DECK_NAME) {
|
||||||
@@ -677,66 +547,4 @@ public class DeckImportController {
|
|||||||
}
|
}
|
||||||
return ""; // no deck name
|
return ""; // no deck name
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTokenMessage(DeckRecognizer.Token token) {
|
|
||||||
return switch (token.getType()) {
|
|
||||||
case LEGAL_CARD, LIMITED_CARD, CARD_FROM_NOT_ALLOWED_SET, CARD_FROM_INVALID_SET,
|
|
||||||
CARD_NOT_IN_INVENTORY, FREE_CARD_NOT_IN_INVENTORY ->
|
|
||||||
String.format("%s x %s %s", token.getQuantity(), token.getText(), getTokenFoilLabel(token));
|
|
||||||
// Card Warning Msgs
|
|
||||||
case UNKNOWN_CARD, UNSUPPORTED_CARD ->
|
|
||||||
token.getQuantity() > 0 ? String.format("%s x %s", token.getQuantity(), token.getText())
|
|
||||||
: token.getText();
|
|
||||||
case UNSUPPORTED_DECK_SECTION ->
|
|
||||||
String.format("%s: %s", Localizer.getInstance().getMessage("lblWarningMsgPrefix"),
|
|
||||||
Localizer.getInstance()
|
|
||||||
.getMessage("lblWarnDeckSectionNotAllowedInEditor", token.getText(),
|
|
||||||
this.currentGameType.name()));
|
|
||||||
|
|
||||||
// Special Case of Card moved into another section (e.g. Commander from Sideboard)
|
|
||||||
case WARNING_MESSAGE -> String.format("%s: %s", Localizer.getInstance()
|
|
||||||
.getMessage("lblWarningMsgPrefix"), token.getText());
|
|
||||||
|
|
||||||
// Placeholders
|
|
||||||
case DECK_SECTION_NAME -> String.format("%s: %s", Localizer.getInstance().getMessage("lblDeckSection"),
|
|
||||||
token.getText());
|
|
||||||
case CARD_RARITY -> String.format("%s: %s", Localizer.getInstance().getMessage("lblRarity"),
|
|
||||||
token.getText());
|
|
||||||
case CARD_TYPE, CARD_CMC, MANA_COLOUR, COMMENT, UNKNOWN_TEXT -> token.getText();
|
|
||||||
case DECK_NAME -> String.format("%s: %s", Localizer.getInstance().getMessage("lblDeckName"),
|
|
||||||
token.getText());
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTokenStatusMessage(DeckRecognizer.Token token) {
|
|
||||||
if (token == null)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
final Localizer localizer = Localizer.getInstance();
|
|
||||||
return switch (token.getType()) {
|
|
||||||
case LIMITED_CARD -> String.format("%s: %s", localizer.getMessage("lblWarningMsgPrefix"),
|
|
||||||
localizer.getMessage("lblWarnLimitedCard",
|
|
||||||
StringUtils.capitalize(token.getLimitedCardType().name()), getGameFormatLabel()));
|
|
||||||
case CARD_FROM_NOT_ALLOWED_SET ->
|
|
||||||
localizer.getMessage("lblErrNotAllowedCard", getGameFormatLabel());
|
|
||||||
case CARD_FROM_INVALID_SET -> localizer.getMessage("lblErrCardEditionDate");
|
|
||||||
case UNSUPPORTED_CARD -> localizer.getMessage("lblErrUnsupportedCard", this.currentGameType);
|
|
||||||
case UNKNOWN_CARD -> String.format("%s: %s", localizer.getMessage("lblWarningMsgPrefix"),
|
|
||||||
localizer.getMessage("lblWarnUnknownCardMsg"));
|
|
||||||
case CARD_NOT_IN_INVENTORY -> localizer.getMessage("lblWarnNotInInventory");
|
|
||||||
default -> "";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private String getTokenFoilLabel(DeckRecognizer.Token token) {
|
|
||||||
if (!token.isCardToken())
|
|
||||||
return "";
|
|
||||||
final String foilMarker = "- (Foil)";
|
|
||||||
return token.getCard().isFoil() ? foilMarker : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getGameFormatLabel() {
|
|
||||||
return String.format("\"%s\"", this.getCurrentGameFormatName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -774,7 +774,7 @@ public class DeckProxy implements InventoryItem {
|
|||||||
|
|
||||||
for (PaperCard c : deck.getAllCardsInASinglePool().toFlatList()) {
|
for (PaperCard c : deck.getAllCardsInASinglePool().toFlatList()) {
|
||||||
CardEdition edition = FModel.getMagicDb().getEditions().get(c.getEdition());
|
CardEdition edition = FModel.getMagicDb().getEditions().get(c.getEdition());
|
||||||
if (edition == null || !edition.hasBasicLands())
|
if (edition == null)
|
||||||
continue;
|
continue;
|
||||||
availableEditions.add(edition);
|
availableEditions.add(edition);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -275,19 +275,15 @@ public class BoosterDraft implements IBoosterDraft {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static BoosterDraft createDraft(final LimitedPoolType draftType, final CardBlock block, final String[] boosters) {
|
public static BoosterDraft createDraft(final LimitedPoolType draftType, final CardBlock block, final String[] boosters) {
|
||||||
return createDraft(draftType, block, boosters, null);
|
// quest draft
|
||||||
}
|
|
||||||
|
|
||||||
public static BoosterDraft createDraft(final LimitedPoolType draftType, final CardBlock block, final String[] boosters, Integer numPlayers) {
|
|
||||||
final BoosterDraft draft = new BoosterDraft(draftType);
|
final BoosterDraft draft = new BoosterDraft(draftType);
|
||||||
|
|
||||||
String setCode = boosters[0];
|
String setCode = boosters[0];
|
||||||
CardEdition edition = FModel.getMagicDb().getEditions().get(setCode);
|
CardEdition edition = FModel.getMagicDb().getEditions().get(setCode);
|
||||||
// If this is metaset, edtion will be null
|
// If this is metaset, edtion will be null
|
||||||
if (edition != null) {
|
if (edition != null) {
|
||||||
// Auto choosing recommended pod size. If we've chosen the podsize it should be passed in via numPlayers
|
if (draft.getPodSize() != edition.getDraftOptions().getRecommendedPodSize()) {
|
||||||
int newPodSize = Objects.requireNonNullElseGet(numPlayers, () -> edition.getDraftOptions().getRecommendedPodSize());
|
// Auto choosing recommended pod size. In the future we may want to allow user to choose
|
||||||
if (newPodSize != draft.getPodSize()) {
|
|
||||||
draft.setPodSize(edition.getDraftOptions().getRecommendedPodSize());
|
draft.setPodSize(edition.getDraftOptions().getRecommendedPodSize());
|
||||||
}
|
}
|
||||||
draft.doublePickDuringDraft = edition.getDraftOptions().isDoublePick(draft.getPodSize());
|
draft.doublePickDuringDraft = edition.getDraftOptions().isDoublePick(draft.getPodSize());
|
||||||
@@ -441,7 +437,7 @@ public class BoosterDraft implements IBoosterDraft {
|
|||||||
CompletableFuture.allOf(futuresArray).join();
|
CompletableFuture.allOf(futuresArray).join();
|
||||||
futures.clear();
|
futures.clear();
|
||||||
}
|
}
|
||||||
// stream().toList() causes crash on Android 8-13, use Collectors.toList()
|
// stream().toList() causes crash on Android, use Collectors.toList()
|
||||||
customs.addAll(queue.stream().collect(Collectors.toList()));
|
customs.addAll(queue.stream().collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
return customs;
|
return customs;
|
||||||
|
|||||||
@@ -18,11 +18,15 @@
|
|||||||
package forge.gamemodes.planarconquest;
|
package forge.gamemodes.planarconquest;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import forge.card.CardDb;
|
import forge.card.CardDb;
|
||||||
import forge.gamemodes.planarconquest.ConquestPreferences.CQPref;
|
import forge.gamemodes.planarconquest.ConquestPreferences.CQPref;
|
||||||
@@ -195,11 +199,14 @@ public final class ConquestData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getAccessiblePlaneCount() {
|
public int getAccessiblePlaneCount() {
|
||||||
return (int) FModel.getPlanes().stream().filter(Predicate.not(ConquestPlane::isUnreachable)).count();
|
// TODO: Java 8 stream implementation of filtering
|
||||||
}
|
int i = 0;
|
||||||
|
for (ConquestPlane plane : FModel.getPlanes()) {
|
||||||
public Set<ConquestPlane> getUnlockedPlanes() {
|
if (!plane.isUnreachable()) {
|
||||||
return planeDataMap.values().stream().map(ConquestPlaneData::getLocation).map(ConquestLocation::getPlane).collect(Collectors.toSet());
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unlockPlane(ConquestPlane plane) {
|
public void unlockPlane(ConquestPlane plane) {
|
||||||
@@ -295,7 +302,7 @@ public final class ConquestData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!commandersUsingCard.isEmpty()) {
|
if (commandersUsingCard.length() > 0) {
|
||||||
SOptionPane.showMessageDialog(Localizer.getInstance().getMessage("lblCommandersCardCannotBeExiledByCard", CardTranslation.getTranslatedName(card.getName()), commandersUsingCard), title, SOptionPane.INFORMATION_ICON);
|
SOptionPane.showMessageDialog(Localizer.getInstance().getMessage("lblCommandersCardCannotBeExiledByCard", CardTranslation.getTranslatedName(card.getName()), commandersUsingCard), title, SOptionPane.INFORMATION_ICON);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ public class ConquestPlane {
|
|||||||
private FCollection<PaperCard> commanders;
|
private FCollection<PaperCard> commanders;
|
||||||
private ConquestAwardPool awardPool;
|
private ConquestAwardPool awardPool;
|
||||||
private ConquestEvent[] events;
|
private ConquestEvent[] events;
|
||||||
private final Set<CardEdition> editions = new HashSet<>();
|
|
||||||
|
|
||||||
private ConquestPlane(String name0, String description0, int regionSize0, boolean unreachable0) {
|
private ConquestPlane(String name0, String description0, int regionSize0, boolean unreachable0) {
|
||||||
name = name0;
|
name = name0;
|
||||||
@@ -154,10 +153,6 @@ public class ConquestPlane {
|
|||||||
return planeCards;
|
return planeCards;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<CardEdition> getEditions() {
|
|
||||||
return editions;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ensureRegionsLoaded() {
|
private void ensureRegionsLoaded() {
|
||||||
if (regions != null) { return; }
|
if (regions != null) { return; }
|
||||||
|
|
||||||
@@ -198,8 +193,6 @@ public class ConquestPlane {
|
|||||||
if (edition == null)
|
if (edition == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
editions.add(edition);
|
|
||||||
|
|
||||||
for (EditionEntry card : edition.getObtainableCards()) {
|
for (EditionEntry card : edition.getObtainableCards()) {
|
||||||
if (bannedCardSet == null || !bannedCardSet.contains(card.name())) {
|
if (bannedCardSet == null || !bannedCardSet.contains(card.name())) {
|
||||||
addCard(commonCards.getCard(card.name(), setCode));
|
addCard(commonCards.getCard(card.name(), setCode));
|
||||||
|
|||||||
@@ -1,16 +1,22 @@
|
|||||||
package forge.gamemodes.planarconquest;
|
package forge.gamemodes.planarconquest;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.EnumSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
import forge.card.*;
|
import forge.card.CardRarity;
|
||||||
|
import forge.card.CardRules;
|
||||||
|
import forge.card.CardType;
|
||||||
import forge.card.CardType.CoreType;
|
import forge.card.CardType.CoreType;
|
||||||
|
import forge.card.ColorSet;
|
||||||
|
import forge.card.MagicColor;
|
||||||
import forge.card.mana.ManaCostShard;
|
import forge.card.mana.ManaCostShard;
|
||||||
import forge.deck.CardPool;
|
import forge.deck.CardPool;
|
||||||
import forge.deck.Deck;
|
import forge.deck.Deck;
|
||||||
@@ -137,25 +143,6 @@ public class ConquestUtil {
|
|||||||
return pool;
|
return pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<CardEdition> getBasicLandSets(Deck currentDeck) {
|
|
||||||
ConquestData model = FModel.getConquest().getModel();
|
|
||||||
List<ConquestPlane> planes = new ArrayList<>(model.getUnlockedPlanes());
|
|
||||||
ConquestPlane currentPlane = model.getCurrentPlane();
|
|
||||||
//Move the current plane to the front.
|
|
||||||
if(currentPlane != null && planes.contains(currentPlane)) {
|
|
||||||
planes.remove(currentPlane);
|
|
||||||
planes.add(0, currentPlane);
|
|
||||||
}
|
|
||||||
//Move editions of cards already in the deck to the front.
|
|
||||||
Map<CardEdition, Integer> editionStats = currentDeck.getAllCardsInASinglePool().getCardEditionStatistics(true);
|
|
||||||
List<CardEdition> out = planes.stream()
|
|
||||||
.<CardEdition>mapMulti((p, c) -> p.getEditions().forEach(c))
|
|
||||||
.filter(CardEdition::hasBasicLands)
|
|
||||||
.sorted(Comparator.comparing(e -> editionStats.getOrDefault(e, 0)))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ConquestPlane getPlaneByName(String planeName) {
|
public static ConquestPlane getPlaneByName(String planeName) {
|
||||||
for (ConquestPlane plane : FModel.getPlanes()) {
|
for (ConquestPlane plane : FModel.getPlanes()) {
|
||||||
if (plane.getName().equals(planeName)) {
|
if (plane.getName().equals(planeName)) {
|
||||||
@@ -202,16 +189,19 @@ public class ConquestUtil {
|
|||||||
public static int getShardValue(CardRarity rarity, CQPref baseValuePref) {
|
public static int getShardValue(CardRarity rarity, CQPref baseValuePref) {
|
||||||
ConquestPreferences prefs = FModel.getConquestPreferences();
|
ConquestPreferences prefs = FModel.getConquestPreferences();
|
||||||
int baseValue = prefs.getPrefInt(baseValuePref);
|
int baseValue = prefs.getPrefInt(baseValuePref);
|
||||||
return switch (rarity) {
|
switch (rarity) {
|
||||||
case Common -> baseValue;
|
case Common:
|
||||||
case Uncommon ->
|
return baseValue;
|
||||||
Math.round((float) baseValue * (float) prefs.getPrefInt(CQPref.AETHER_UNCOMMON_MULTIPLIER));
|
case Uncommon:
|
||||||
case Rare, Special ->
|
return Math.round((float)baseValue * (float)prefs.getPrefInt(CQPref.AETHER_UNCOMMON_MULTIPLIER));
|
||||||
Math.round((float) baseValue * (float) prefs.getPrefInt(CQPref.AETHER_RARE_MULTIPLIER));
|
case Rare:
|
||||||
case MythicRare ->
|
case Special:
|
||||||
Math.round((float) baseValue * (float) prefs.getPrefInt(CQPref.AETHER_MYTHIC_MULTIPLIER));
|
return Math.round((float)baseValue * (float)prefs.getPrefInt(CQPref.AETHER_RARE_MULTIPLIER));
|
||||||
default -> 0;
|
case MythicRare:
|
||||||
};
|
return Math.round((float)baseValue * (float)prefs.getPrefInt(CQPref.AETHER_MYTHIC_MULTIPLIER));
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum AEtherFilter implements IHasSkinProp {
|
public enum AEtherFilter implements IHasSkinProp {
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ package forge.gamemodes.quest;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.eventbus.Subscribe;
|
import com.google.common.eventbus.Subscribe;
|
||||||
@@ -621,21 +620,17 @@ public class QuestController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public CardEdition getDefaultLandSet() {
|
public CardEdition getDefaultLandSet() {
|
||||||
List<CardEdition> availableEditions = getAvailableLandSets();
|
List<String> availableEditionCodes = questFormat != null ? questFormat.getAllowedSetCodes() : Lists.newArrayList(FModel.getMagicDb().getEditions().getItemNames());
|
||||||
|
List<CardEdition> availableEditions = new ArrayList<>();
|
||||||
|
|
||||||
|
for (String s : availableEditionCodes) {
|
||||||
|
availableEditions.add(FModel.getMagicDb().getEditions().get(s));
|
||||||
|
}
|
||||||
|
|
||||||
CardEdition randomLandSet = CardEdition.Predicates.getRandomSetWithAllBasicLands(availableEditions);
|
CardEdition randomLandSet = CardEdition.Predicates.getRandomSetWithAllBasicLands(availableEditions);
|
||||||
return randomLandSet == null ? FModel.getMagicDb().getEditions().get("ZEN") : randomLandSet;
|
return randomLandSet == null ? FModel.getMagicDb().getEditions().get("ZEN") : randomLandSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<CardEdition> getAvailableLandSets() {
|
|
||||||
List<String> availableEditionCodes = questFormat != null ? questFormat.getAllowedSetCodes() : Lists.newArrayList(FModel.getMagicDb().getEditions().getItemNames());
|
|
||||||
CardEdition.Collection editions = FModel.getMagicDb().getEditions();
|
|
||||||
return availableEditionCodes.stream()
|
|
||||||
.map(editions::get)
|
|
||||||
.filter(CardEdition::hasBasicLands)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCurrentDeck() {
|
public String getCurrentDeck() {
|
||||||
return model.currentDeck;
|
return model.currentDeck;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -661,7 +661,7 @@ public class QuestEventDraft implements IQuestEvent {
|
|||||||
public BoosterDraft enter() {
|
public BoosterDraft enter() {
|
||||||
FModel.getQuest().getAchievements().setCurrentDraft(this);
|
FModel.getQuest().getAchievements().setCurrentDraft(this);
|
||||||
FModel.getQuest().getAssets().subtractCredits(getEntryFee());
|
FModel.getQuest().getAssets().subtractCredits(getEntryFee());
|
||||||
return BoosterDraft.createDraft(LimitedPoolType.Block, FModel.getBlocks().get(getBlock()), getBoosterConfiguration(), 8);
|
return BoosterDraft.createDraft(LimitedPoolType.Block, FModel.getBlocks().get(getBlock()), getBoosterConfiguration());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isStarted() {
|
public boolean isStarted() {
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ public class AdvancedSearch {
|
|||||||
protected String getItemValue(PaperCard input) {
|
protected String getItemValue(PaperCard input) {
|
||||||
throw new RuntimeException("getItemValues should be called instead");
|
throw new RuntimeException("getItemValues should be called instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<String> getItemValues(PaperCard input) {
|
protected Set<String> getItemValues(PaperCard input) {
|
||||||
Set<String> names = new HashSet<>();
|
Set<String> names = new HashSet<>();
|
||||||
@@ -78,7 +77,6 @@ public class AdvancedSearch {
|
|||||||
protected String getItemValue(PaperCard input) {
|
protected String getItemValue(PaperCard input) {
|
||||||
throw new RuntimeException("getItemValues should be called instead");
|
throw new RuntimeException("getItemValues should be called instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<String> getItemValues(PaperCard input) {
|
protected Set<String> getItemValues(PaperCard input) {
|
||||||
Set<String> names = new HashSet<>();
|
Set<String> names = new HashSet<>();
|
||||||
@@ -100,9 +98,20 @@ public class AdvancedSearch {
|
|||||||
protected Keyword getItemValue(PaperCard input) {
|
protected Keyword getItemValue(PaperCard input) {
|
||||||
throw new RuntimeException("getItemValues should be called instead");
|
throw new RuntimeException("getItemValues should be called instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<Keyword> getItemValues(PaperCard input) {
|
protected Set<Keyword> getItemValues(PaperCard input) {
|
||||||
|
CardSplitType cardSplitType = input.getRules().getSplitType();
|
||||||
|
if (cardSplitType != CardSplitType.None && cardSplitType != CardSplitType.Split) {
|
||||||
|
Set<Keyword> keywords = new HashSet<>();
|
||||||
|
if (input.getRules().getOtherPart() != null) {
|
||||||
|
PaperCard otherPart = FModel.getMagicDb().getCommonCards().getCard(input.getRules().getOtherPart().getName());
|
||||||
|
if (otherPart != null) {
|
||||||
|
keywords.addAll(Keyword.getKeywordSet(otherPart));
|
||||||
|
keywords.addAll(Keyword.getKeywordSet(input));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return keywords;
|
||||||
|
}
|
||||||
return Keyword.getKeywordSet(input);
|
return Keyword.getKeywordSet(input);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
@@ -112,12 +121,11 @@ public class AdvancedSearch {
|
|||||||
return FModel.getMagicDb().getCardEdition(input.getEdition());
|
return FModel.getMagicDb().getCardEdition(input.getEdition());
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
CARD_FORMAT("lblFormat", PaperCard.class, FilterOperator.MULTI_LIST_OPS, new CustomListEvaluator<PaperCard, GameFormat>((List<GameFormat>) FModel.getFormats().getFilterList()) {
|
CARD_FORMAT("lblFormat", PaperCard.class, FilterOperator.MULTI_LIST_OPS, new CustomListEvaluator<PaperCard, GameFormat>((List<GameFormat>)FModel.getFormats().getFilterList()) {
|
||||||
@Override
|
@Override
|
||||||
protected GameFormat getItemValue(PaperCard input) {
|
protected GameFormat getItemValue(PaperCard input) {
|
||||||
throw new RuntimeException("getItemValues should be called instead");
|
throw new RuntimeException("getItemValues should be called instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<GameFormat> getItemValues(PaperCard input) {
|
protected Set<GameFormat> getItemValues(PaperCard input) {
|
||||||
return FModel.getFormats().getAllFormatsOfCard(input);
|
return FModel.getFormats().getAllFormatsOfCard(input);
|
||||||
@@ -128,7 +136,6 @@ public class AdvancedSearch {
|
|||||||
protected ConquestPlane getItemValue(PaperCard input) {
|
protected ConquestPlane getItemValue(PaperCard input) {
|
||||||
throw new RuntimeException("getItemValues should be called instead");
|
throw new RuntimeException("getItemValues should be called instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<ConquestPlane> getItemValues(PaperCard input) {
|
protected Set<ConquestPlane> getItemValues(PaperCard input) {
|
||||||
return ConquestPlane.getAllPlanesOfCard(input);
|
return ConquestPlane.getAllPlanesOfCard(input);
|
||||||
@@ -139,7 +146,6 @@ public class AdvancedSearch {
|
|||||||
protected ConquestRegion getItemValue(PaperCard input) {
|
protected ConquestRegion getItemValue(PaperCard input) {
|
||||||
throw new RuntimeException("getItemValues should be called instead");
|
throw new RuntimeException("getItemValues should be called instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<ConquestRegion> getItemValues(PaperCard input) {
|
protected Set<ConquestRegion> getItemValues(PaperCard input) {
|
||||||
return ConquestRegion.getAllRegionsOfCard(input);
|
return ConquestRegion.getAllRegionsOfCard(input);
|
||||||
@@ -150,7 +156,6 @@ public class AdvancedSearch {
|
|||||||
protected QuestWorld getItemValue(PaperCard input) {
|
protected QuestWorld getItemValue(PaperCard input) {
|
||||||
throw new RuntimeException("getItemValues should be called instead");
|
throw new RuntimeException("getItemValues should be called instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<QuestWorld> getItemValues(PaperCard input) {
|
protected Set<QuestWorld> getItemValues(PaperCard input) {
|
||||||
return QuestWorld.getAllQuestWorldsOfCard(input);
|
return QuestWorld.getAllQuestWorldsOfCard(input);
|
||||||
@@ -161,7 +166,6 @@ public class AdvancedSearch {
|
|||||||
protected MagicColor.Color getItemValue(PaperCard input) {
|
protected MagicColor.Color getItemValue(PaperCard input) {
|
||||||
throw new RuntimeException("getItemValues should be called instead");
|
throw new RuntimeException("getItemValues should be called instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<MagicColor.Color> getItemValues(PaperCard input) {
|
protected Set<MagicColor.Color> getItemValues(PaperCard input) {
|
||||||
return input.getRules().getColor().toEnumSet();
|
return input.getRules().getColor().toEnumSet();
|
||||||
@@ -172,7 +176,6 @@ public class AdvancedSearch {
|
|||||||
protected MagicColor.Color getItemValue(PaperCard input) {
|
protected MagicColor.Color getItemValue(PaperCard input) {
|
||||||
throw new RuntimeException("getItemValues should be called instead");
|
throw new RuntimeException("getItemValues should be called instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<MagicColor.Color> getItemValues(PaperCard input) {
|
protected Set<MagicColor.Color> getItemValues(PaperCard input) {
|
||||||
return input.getRules().getColorIdentity().toEnumSet();
|
return input.getRules().getColorIdentity().toEnumSet();
|
||||||
@@ -189,7 +192,6 @@ public class AdvancedSearch {
|
|||||||
protected String getItemValue(PaperCard input) {
|
protected String getItemValue(PaperCard input) {
|
||||||
throw new RuntimeException("getItemValues should be called instead");
|
throw new RuntimeException("getItemValues should be called instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<String> getItemValues(PaperCard input) {
|
protected Set<String> getItemValues(PaperCard input) {
|
||||||
final CardType type = input.getRules().getType();
|
final CardType type = input.getRules().getType();
|
||||||
@@ -226,7 +228,6 @@ public class AdvancedSearch {
|
|||||||
protected String getItemValue(PaperCard input) {
|
protected String getItemValue(PaperCard input) {
|
||||||
throw new RuntimeException("getItemValues should be called instead");
|
throw new RuntimeException("getItemValues should be called instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<String> getItemValues(PaperCard input) {
|
protected Set<String> getItemValues(PaperCard input) {
|
||||||
CardSplitType cardSplitType = input.getRules().getSplitType();
|
CardSplitType cardSplitType = input.getRules().getSplitType();
|
||||||
@@ -242,7 +243,7 @@ public class AdvancedSearch {
|
|||||||
return subtypes;
|
return subtypes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (Set<String>) input.getRules().getType().getSubtypes();
|
return (Set<String>)input.getRules().getType().getSubtypes();
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
CARD_CMC("lblCMC", PaperCard.class, FilterOperator.NUMBER_OPS, new NumericEvaluator<PaperCard>(0, 20) {
|
CARD_CMC("lblCMC", PaperCard.class, FilterOperator.NUMBER_OPS, new NumericEvaluator<PaperCard>(0, 20) {
|
||||||
@@ -293,9 +294,7 @@ public class AdvancedSearch {
|
|||||||
@Override
|
@Override
|
||||||
protected Boolean getItemValue(PaperCard input) {
|
protected Boolean getItemValue(PaperCard input) {
|
||||||
List<PaperCard> cards = FModel.getMagicDb().getCommonCards().getAllCards(input.getName());
|
List<PaperCard> cards = FModel.getMagicDb().getCommonCards().getAllCards(input.getName());
|
||||||
if (cards.size() <= 1) {
|
if (cards.size() <= 1) { return true; }
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
cards.sort(FModel.getMagicDb().getEditions().CARD_EDITION_COMPARATOR);
|
cards.sort(FModel.getMagicDb().getEditions().CARD_EDITION_COMPARATOR);
|
||||||
return cards.get(0) == input;
|
return cards.get(0) == input;
|
||||||
@@ -319,7 +318,7 @@ public class AdvancedSearch {
|
|||||||
if (!(input instanceof PaperCard)) {
|
if (!(input instanceof PaperCard)) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
return ((PaperCard) input).getRules().getOracleText();
|
return ((PaperCard)input).getRules().getOracleText();
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
INVITEM_KEYWORDS("lblKeywords", InventoryItem.class, FilterOperator.COLLECTION_OPS, new CustomListEvaluator<InventoryItem, Keyword>(Keyword.getAllKeywords()) {
|
INVITEM_KEYWORDS("lblKeywords", InventoryItem.class, FilterOperator.COLLECTION_OPS, new CustomListEvaluator<InventoryItem, Keyword>(Keyword.getAllKeywords()) {
|
||||||
@@ -327,40 +326,38 @@ public class AdvancedSearch {
|
|||||||
protected Keyword getItemValue(InventoryItem input) {
|
protected Keyword getItemValue(InventoryItem input) {
|
||||||
throw new RuntimeException("getItemValues should be called instead");
|
throw new RuntimeException("getItemValues should be called instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<Keyword> getItemValues(InventoryItem input) {
|
protected Set<Keyword> getItemValues(InventoryItem input) {
|
||||||
if (!(input instanceof PaperCard)) {
|
if (!(input instanceof PaperCard)) {
|
||||||
return new HashSet<>();
|
return new HashSet<>();
|
||||||
}
|
}
|
||||||
return Keyword.getKeywordSet((PaperCard) input);
|
return Keyword.getKeywordSet((PaperCard)input);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
INVITEM_SET("lblSet", InventoryItem.class, FilterOperator.SINGLE_LIST_OPS, new CustomListEvaluator<InventoryItem, CardEdition>(FModel.getMagicDb().getSortedEditions(), CardEdition::getCode) {
|
INVITEM_SET("lblSet", InventoryItem.class, FilterOperator.SINGLE_LIST_OPS, new CustomListEvaluator<InventoryItem, CardEdition>(FModel.getMagicDb().getSortedEditions(), CardEdition::getCode) {
|
||||||
@Override
|
@Override
|
||||||
protected CardEdition getItemValue(InventoryItem input) {
|
protected CardEdition getItemValue(InventoryItem input) {
|
||||||
if (input instanceof PaperCard) {
|
if (input instanceof PaperCard) {
|
||||||
CardEdition set = FModel.getMagicDb().getEditions().get(((PaperCard) input).getEdition());
|
CardEdition set = FModel.getMagicDb().getEditions().get(((PaperCard)input).getEdition());
|
||||||
return set;
|
return set;
|
||||||
} else if (input instanceof SealedProduct) {
|
} else if (input instanceof SealedProduct) {
|
||||||
return FModel.getMagicDb().getEditions().get(((SealedProduct) input).getEdition());
|
return FModel.getMagicDb().getEditions().get(((SealedProduct)input).getEdition());
|
||||||
} else {
|
} else {
|
||||||
return CardEdition.UNKNOWN;
|
return CardEdition.UNKNOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
INVITEM_FORMAT("lblFormat", InventoryItem.class, FilterOperator.MULTI_LIST_OPS, new CustomListEvaluator<InventoryItem, GameFormat>((List<GameFormat>) FModel.getFormats().getFilterList()) {
|
INVITEM_FORMAT("lblFormat", InventoryItem.class, FilterOperator.MULTI_LIST_OPS, new CustomListEvaluator<InventoryItem, GameFormat>((List<GameFormat>)FModel.getFormats().getFilterList()) {
|
||||||
@Override
|
@Override
|
||||||
protected GameFormat getItemValue(InventoryItem input) {
|
protected GameFormat getItemValue(InventoryItem input) {
|
||||||
throw new RuntimeException("getItemValues should be called instead");
|
throw new RuntimeException("getItemValues should be called instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<GameFormat> getItemValues(InventoryItem input) {
|
protected Set<GameFormat> getItemValues(InventoryItem input) {
|
||||||
if (!(input instanceof PaperCard)) {
|
if (!(input instanceof PaperCard)) {
|
||||||
return new HashSet<>();
|
return new HashSet<>();
|
||||||
}
|
}
|
||||||
return FModel.getFormats().getAllFormatsOfCard((PaperCard) input);
|
return FModel.getFormats().getAllFormatsOfCard((PaperCard)input);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
INVITEM_PLANE("lblPlane", InventoryItem.class, FilterOperator.MULTI_LIST_OPS, new CustomListEvaluator<InventoryItem, ConquestPlane>(ImmutableList.copyOf(FModel.getPlanes())) {
|
INVITEM_PLANE("lblPlane", InventoryItem.class, FilterOperator.MULTI_LIST_OPS, new CustomListEvaluator<InventoryItem, ConquestPlane>(ImmutableList.copyOf(FModel.getPlanes())) {
|
||||||
@@ -368,13 +365,12 @@ public class AdvancedSearch {
|
|||||||
protected ConquestPlane getItemValue(InventoryItem input) {
|
protected ConquestPlane getItemValue(InventoryItem input) {
|
||||||
throw new RuntimeException("getItemValues should be called instead");
|
throw new RuntimeException("getItemValues should be called instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<ConquestPlane> getItemValues(InventoryItem input) {
|
protected Set<ConquestPlane> getItemValues(InventoryItem input) {
|
||||||
if (!(input instanceof PaperCard)) {
|
if (!(input instanceof PaperCard)) {
|
||||||
return new HashSet<>();
|
return new HashSet<>();
|
||||||
}
|
}
|
||||||
return ConquestPlane.getAllPlanesOfCard((PaperCard) input);
|
return ConquestPlane.getAllPlanesOfCard((PaperCard)input);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
INVITEM_REGION("lblRegion", InventoryItem.class, FilterOperator.MULTI_LIST_OPS, new CustomListEvaluator<InventoryItem, ConquestRegion>(ConquestRegion.getAllRegions()) {
|
INVITEM_REGION("lblRegion", InventoryItem.class, FilterOperator.MULTI_LIST_OPS, new CustomListEvaluator<InventoryItem, ConquestRegion>(ConquestRegion.getAllRegions()) {
|
||||||
@@ -382,13 +378,12 @@ public class AdvancedSearch {
|
|||||||
protected ConquestRegion getItemValue(InventoryItem input) {
|
protected ConquestRegion getItemValue(InventoryItem input) {
|
||||||
throw new RuntimeException("getItemValues should be called instead");
|
throw new RuntimeException("getItemValues should be called instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<ConquestRegion> getItemValues(InventoryItem input) {
|
protected Set<ConquestRegion> getItemValues(InventoryItem input) {
|
||||||
if (!(input instanceof PaperCard)) {
|
if (!(input instanceof PaperCard)) {
|
||||||
return new HashSet<>();
|
return new HashSet<>();
|
||||||
}
|
}
|
||||||
return ConquestRegion.getAllRegionsOfCard((PaperCard) input);
|
return ConquestRegion.getAllRegionsOfCard((PaperCard)input);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
INVITEM_QUEST_WORLD("lblQuestWorld", InventoryItem.class, FilterOperator.MULTI_LIST_OPS, new CustomListEvaluator<InventoryItem, QuestWorld>(ImmutableList.copyOf(FModel.getWorlds())) {
|
INVITEM_QUEST_WORLD("lblQuestWorld", InventoryItem.class, FilterOperator.MULTI_LIST_OPS, new CustomListEvaluator<InventoryItem, QuestWorld>(ImmutableList.copyOf(FModel.getWorlds())) {
|
||||||
@@ -396,13 +391,12 @@ public class AdvancedSearch {
|
|||||||
protected QuestWorld getItemValue(InventoryItem input) {
|
protected QuestWorld getItemValue(InventoryItem input) {
|
||||||
throw new RuntimeException("getItemValues should be called instead");
|
throw new RuntimeException("getItemValues should be called instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<QuestWorld> getItemValues(InventoryItem input) {
|
protected Set<QuestWorld> getItemValues(InventoryItem input) {
|
||||||
if (!(input instanceof PaperCard)) {
|
if (!(input instanceof PaperCard)) {
|
||||||
return new HashSet<>();
|
return new HashSet<>();
|
||||||
}
|
}
|
||||||
return QuestWorld.getAllQuestWorldsOfCard(((PaperCard) input));
|
return QuestWorld.getAllQuestWorldsOfCard(((PaperCard)input));
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
INVITEM_COLOR("lblColor", InventoryItem.class, FilterOperator.COMBINATION_OPS, new ColorEvaluator<InventoryItem>() {
|
INVITEM_COLOR("lblColor", InventoryItem.class, FilterOperator.COMBINATION_OPS, new ColorEvaluator<InventoryItem>() {
|
||||||
@@ -410,13 +404,12 @@ public class AdvancedSearch {
|
|||||||
protected MagicColor.Color getItemValue(InventoryItem input) {
|
protected MagicColor.Color getItemValue(InventoryItem input) {
|
||||||
throw new RuntimeException("getItemValues should be called instead");
|
throw new RuntimeException("getItemValues should be called instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<MagicColor.Color> getItemValues(InventoryItem input) {
|
protected Set<MagicColor.Color> getItemValues(InventoryItem input) {
|
||||||
if (!(input instanceof PaperCard)) {
|
if (!(input instanceof PaperCard)) {
|
||||||
return new HashSet<>();
|
return new HashSet<>();
|
||||||
}
|
}
|
||||||
return ((PaperCard) input).getRules().getColor().toEnumSet();
|
return ((PaperCard)input).getRules().getColor().toEnumSet();
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
INVITEM_COLOR_IDENTITY("lblColorIdentity", InventoryItem.class, FilterOperator.COMBINATION_OPS, new ColorEvaluator<InventoryItem>() {
|
INVITEM_COLOR_IDENTITY("lblColorIdentity", InventoryItem.class, FilterOperator.COMBINATION_OPS, new ColorEvaluator<InventoryItem>() {
|
||||||
@@ -424,13 +417,12 @@ public class AdvancedSearch {
|
|||||||
protected MagicColor.Color getItemValue(InventoryItem input) {
|
protected MagicColor.Color getItemValue(InventoryItem input) {
|
||||||
throw new RuntimeException("getItemValues should be called instead");
|
throw new RuntimeException("getItemValues should be called instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<MagicColor.Color> getItemValues(InventoryItem input) {
|
protected Set<MagicColor.Color> getItemValues(InventoryItem input) {
|
||||||
if (!(input instanceof PaperCard)) {
|
if (!(input instanceof PaperCard)) {
|
||||||
return new HashSet<>();
|
return new HashSet<>();
|
||||||
}
|
}
|
||||||
return ((PaperCard) input).getRules().getColorIdentity().toEnumSet();
|
return ((PaperCard)input).getRules().getColorIdentity().toEnumSet();
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
INVITEM_COLOR_COUNT("lblColorCount", InventoryItem.class, FilterOperator.NUMBER_OPS, new NumericEvaluator<InventoryItem>(0, 5) {
|
INVITEM_COLOR_COUNT("lblColorCount", InventoryItem.class, FilterOperator.NUMBER_OPS, new NumericEvaluator<InventoryItem>(0, 5) {
|
||||||
@@ -439,7 +431,7 @@ public class AdvancedSearch {
|
|||||||
if (!(input instanceof PaperCard)) {
|
if (!(input instanceof PaperCard)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return ((PaperCard) input).getRules().getColor().countColors();
|
return ((PaperCard)input).getRules().getColor().countColors();
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
INVITEM_TYPE("lblType", InventoryItem.class, FilterOperator.COMBINATION_OPS, new CustomListEvaluator<InventoryItem, String>(CardType.getCombinedSuperAndCoreTypes()) {
|
INVITEM_TYPE("lblType", InventoryItem.class, FilterOperator.COMBINATION_OPS, new CustomListEvaluator<InventoryItem, String>(CardType.getCombinedSuperAndCoreTypes()) {
|
||||||
@@ -447,13 +439,12 @@ public class AdvancedSearch {
|
|||||||
protected String getItemValue(InventoryItem input) {
|
protected String getItemValue(InventoryItem input) {
|
||||||
throw new RuntimeException("getItemValues should be called instead");
|
throw new RuntimeException("getItemValues should be called instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<String> getItemValues(InventoryItem input) {
|
protected Set<String> getItemValues(InventoryItem input) {
|
||||||
if (!(input instanceof PaperCard)) {
|
if (!(input instanceof PaperCard)) {
|
||||||
return new HashSet<>();
|
return new HashSet<>();
|
||||||
}
|
}
|
||||||
final CardType type = ((PaperCard) input).getRules().getType();
|
final CardType type = ((PaperCard)input).getRules().getType();
|
||||||
final Set<String> types = new HashSet<>();
|
final Set<String> types = new HashSet<>();
|
||||||
for (Supertype t : type.getSupertypes()) {
|
for (Supertype t : type.getSupertypes()) {
|
||||||
types.add(t.name());
|
types.add(t.name());
|
||||||
@@ -469,13 +460,12 @@ public class AdvancedSearch {
|
|||||||
protected String getItemValue(InventoryItem input) {
|
protected String getItemValue(InventoryItem input) {
|
||||||
throw new RuntimeException("getItemValues should be called instead");
|
throw new RuntimeException("getItemValues should be called instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<String> getItemValues(InventoryItem input) {
|
protected Set<String> getItemValues(InventoryItem input) {
|
||||||
if (!(input instanceof PaperCard)) {
|
if (!(input instanceof PaperCard)) {
|
||||||
return new HashSet<>();
|
return new HashSet<>();
|
||||||
}
|
}
|
||||||
return (Set<String>) ((PaperCard) input).getRules().getType().getSubtypes();
|
return (Set<String>)((PaperCard)input).getRules().getType().getSubtypes();
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
INVITEM_CMC("lblCMC", InventoryItem.class, FilterOperator.NUMBER_OPS, new NumericEvaluator<InventoryItem>(0, 20) {
|
INVITEM_CMC("lblCMC", InventoryItem.class, FilterOperator.NUMBER_OPS, new NumericEvaluator<InventoryItem>(0, 20) {
|
||||||
@@ -484,7 +474,7 @@ public class AdvancedSearch {
|
|||||||
if (!(input instanceof PaperCard)) {
|
if (!(input instanceof PaperCard)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return ((PaperCard) input).getRules().getManaCost().getCMC();
|
return ((PaperCard)input).getRules().getManaCost().getCMC();
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
INVITEM_GENERIC_COST("lblGenericCost", InventoryItem.class, FilterOperator.NUMBER_OPS, new NumericEvaluator<InventoryItem>(0, 20) {
|
INVITEM_GENERIC_COST("lblGenericCost", InventoryItem.class, FilterOperator.NUMBER_OPS, new NumericEvaluator<InventoryItem>(0, 20) {
|
||||||
@@ -493,7 +483,7 @@ public class AdvancedSearch {
|
|||||||
if (!(input instanceof PaperCard)) {
|
if (!(input instanceof PaperCard)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return ((PaperCard) input).getRules().getManaCost().getGenericCost();
|
return ((PaperCard)input).getRules().getManaCost().getGenericCost();
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
INVITEM_POWER("lblPower", InventoryItem.class, FilterOperator.NUMBER_OPS, new NumericEvaluator<InventoryItem>(0, 20) {
|
INVITEM_POWER("lblPower", InventoryItem.class, FilterOperator.NUMBER_OPS, new NumericEvaluator<InventoryItem>(0, 20) {
|
||||||
@@ -502,7 +492,7 @@ public class AdvancedSearch {
|
|||||||
if (!(input instanceof PaperCard)) {
|
if (!(input instanceof PaperCard)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
CardRules rules = ((PaperCard) input).getRules();
|
CardRules rules = ((PaperCard)input).getRules();
|
||||||
if (rules.getType().isCreature()) {
|
if (rules.getType().isCreature()) {
|
||||||
return rules.getIntPower();
|
return rules.getIntPower();
|
||||||
}
|
}
|
||||||
@@ -515,7 +505,7 @@ public class AdvancedSearch {
|
|||||||
if (!(input instanceof PaperCard)) {
|
if (!(input instanceof PaperCard)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
CardRules rules = ((PaperCard) input).getRules();
|
CardRules rules = ((PaperCard)input).getRules();
|
||||||
if (rules.getType().isCreature()) {
|
if (rules.getType().isCreature()) {
|
||||||
return rules.getIntToughness();
|
return rules.getIntToughness();
|
||||||
}
|
}
|
||||||
@@ -528,16 +518,14 @@ public class AdvancedSearch {
|
|||||||
if (!(input instanceof PaperCard)) {
|
if (!(input instanceof PaperCard)) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
return ((PaperCard) input).getRules().getManaCost().toString();
|
return ((PaperCard)input).getRules().getManaCost().toString();
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
INVITEM_FIRST_PRINTING("lblFirstPrinting", InventoryItem.class, FilterOperator.BOOLEAN_OPS, new BooleanEvaluator<InventoryItem>() {
|
INVITEM_FIRST_PRINTING("lblFirstPrinting", InventoryItem.class, FilterOperator.BOOLEAN_OPS, new BooleanEvaluator<InventoryItem>() {
|
||||||
@Override
|
@Override
|
||||||
protected Boolean getItemValue(InventoryItem input) {
|
protected Boolean getItemValue(InventoryItem input) {
|
||||||
List<PaperCard> cards = FModel.getMagicDb().getCommonCards().getAllCards(input.getName());
|
List<PaperCard> cards = FModel.getMagicDb().getCommonCards().getAllCards(input.getName());
|
||||||
if (cards.size() <= 1) {
|
if (cards.size() <= 1) { return true; }
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
cards.sort(FModel.getMagicDb().getEditions().CARD_EDITION_COMPARATOR);
|
cards.sort(FModel.getMagicDb().getEditions().CARD_EDITION_COMPARATOR);
|
||||||
return cards.get(0) == input;
|
return cards.get(0) == input;
|
||||||
@@ -549,7 +537,7 @@ public class AdvancedSearch {
|
|||||||
if (!(input instanceof PaperCard)) {
|
if (!(input instanceof PaperCard)) {
|
||||||
return CardRarity.Special;
|
return CardRarity.Special;
|
||||||
}
|
}
|
||||||
return ((PaperCard) input).getRarity();
|
return ((PaperCard)input).getRarity();
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
INVITEM_BUY_PRICE("lblBuyPrice", InventoryItem.class, FilterOperator.NUMBER_OPS, new NumericEvaluator<InventoryItem>(0, 10000000) {
|
INVITEM_BUY_PRICE("lblBuyPrice", InventoryItem.class, FilterOperator.NUMBER_OPS, new NumericEvaluator<InventoryItem>(0, 10000000) {
|
||||||
@@ -588,12 +576,11 @@ public class AdvancedSearch {
|
|||||||
return input.isFavoriteDeck();
|
return input.isFavoriteDeck();
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
DECK_FORMAT("lblFormat", DeckProxy.class, FilterOperator.MULTI_LIST_OPS, new CustomListEvaluator<DeckProxy, GameFormat>((List<GameFormat>) FModel.getFormats().getFilterList()) {
|
DECK_FORMAT("lblFormat", DeckProxy.class, FilterOperator.MULTI_LIST_OPS, new CustomListEvaluator<DeckProxy, GameFormat>((List<GameFormat>)FModel.getFormats().getFilterList()) {
|
||||||
@Override
|
@Override
|
||||||
protected GameFormat getItemValue(DeckProxy input) {
|
protected GameFormat getItemValue(DeckProxy input) {
|
||||||
throw new RuntimeException("getItemValues should be called instead");
|
throw new RuntimeException("getItemValues should be called instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<GameFormat> getItemValues(DeckProxy input) {
|
protected Set<GameFormat> getItemValues(DeckProxy input) {
|
||||||
return input.getExhaustiveFormats();
|
return input.getExhaustiveFormats();
|
||||||
@@ -604,7 +591,6 @@ public class AdvancedSearch {
|
|||||||
protected QuestWorld getItemValue(DeckProxy input) {
|
protected QuestWorld getItemValue(DeckProxy input) {
|
||||||
throw new RuntimeException("getItemValues should be called instead");
|
throw new RuntimeException("getItemValues should be called instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<QuestWorld> getItemValues(DeckProxy input) {
|
protected Set<QuestWorld> getItemValues(DeckProxy input) {
|
||||||
return QuestWorld.getAllQuestWorldsOfDeck(input.getDeck());
|
return QuestWorld.getAllQuestWorldsOfDeck(input.getDeck());
|
||||||
@@ -615,7 +601,6 @@ public class AdvancedSearch {
|
|||||||
protected MagicColor.Color getItemValue(DeckProxy input) {
|
protected MagicColor.Color getItemValue(DeckProxy input) {
|
||||||
throw new RuntimeException("getItemValues should be called instead");
|
throw new RuntimeException("getItemValues should be called instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<MagicColor.Color> getItemValues(DeckProxy input) {
|
protected Set<MagicColor.Color> getItemValues(DeckProxy input) {
|
||||||
return input.getColor().toEnumSet();
|
return input.getColor().toEnumSet();
|
||||||
@@ -626,7 +611,6 @@ public class AdvancedSearch {
|
|||||||
protected MagicColor.Color getItemValue(DeckProxy input) {
|
protected MagicColor.Color getItemValue(DeckProxy input) {
|
||||||
throw new RuntimeException("getItemValues should be called instead");
|
throw new RuntimeException("getItemValues should be called instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<MagicColor.Color> getItemValues(DeckProxy input) {
|
protected Set<MagicColor.Color> getItemValues(DeckProxy input) {
|
||||||
return input.getColorIdentity().toEnumSet();
|
return input.getColorIdentity().toEnumSet();
|
||||||
@@ -689,7 +673,6 @@ public class AdvancedSearch {
|
|||||||
protected MagicColor.Color getItemValue(ConquestCommander input) {
|
protected MagicColor.Color getItemValue(ConquestCommander input) {
|
||||||
throw new RuntimeException("getItemValues should be called instead");
|
throw new RuntimeException("getItemValues should be called instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<MagicColor.Color> getItemValues(ConquestCommander input) {
|
protected Set<MagicColor.Color> getItemValues(ConquestCommander input) {
|
||||||
return input.getCard().getRules().getColorIdentity().toEnumSet();
|
return input.getCard().getRules().getColorIdentity().toEnumSet();
|
||||||
@@ -842,7 +825,6 @@ public class AdvancedSearch {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Set<String> inputs, List<String> values) {
|
public boolean apply(Set<String> inputs, List<String> values) {
|
||||||
if (inputs != null && !inputs.isEmpty() && !values.isEmpty()) {
|
if (inputs != null && !inputs.isEmpty() && !values.isEmpty()) {
|
||||||
@@ -864,7 +846,6 @@ public class AdvancedSearch {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Set<String> inputs, List<String> values) {
|
public boolean apply(Set<String> inputs, List<String> values) {
|
||||||
if (inputs != null && !inputs.isEmpty() && !values.isEmpty()) {
|
if (inputs != null && !inputs.isEmpty() && !values.isEmpty()) {
|
||||||
@@ -886,7 +867,6 @@ public class AdvancedSearch {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Set<String> inputs, List<String> values) {
|
public boolean apply(Set<String> inputs, List<String> values) {
|
||||||
if (inputs != null && !inputs.isEmpty() && !values.isEmpty()) {
|
if (inputs != null && !inputs.isEmpty() && !values.isEmpty()) {
|
||||||
@@ -910,7 +890,6 @@ public class AdvancedSearch {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Set<Object> inputs, List<Object> values) {
|
public boolean apply(Set<Object> inputs, List<Object> values) {
|
||||||
if (inputs != null && inputs.size() == values.size()) {
|
if (inputs != null && inputs.size() == values.size()) {
|
||||||
@@ -936,7 +915,6 @@ public class AdvancedSearch {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Set<Object> inputs, List<Object> values) {
|
public boolean apply(Set<Object> inputs, List<Object> values) {
|
||||||
if (inputs != null) {
|
if (inputs != null) {
|
||||||
@@ -961,7 +939,6 @@ public class AdvancedSearch {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Set<Object> inputs, List<Object> values) {
|
public boolean apply(Set<Object> inputs, List<Object> values) {
|
||||||
if (inputs != null) {
|
if (inputs != null) {
|
||||||
@@ -982,7 +959,6 @@ public class AdvancedSearch {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Set<Object> inputs, List<Object> values) {
|
public boolean apply(Set<Object> inputs, List<Object> values) {
|
||||||
if (inputs != null) {
|
if (inputs != null) {
|
||||||
@@ -1001,7 +977,6 @@ public class AdvancedSearch {
|
|||||||
public boolean apply(Object input, List<Object> values) {
|
public boolean apply(Object input, List<Object> values) {
|
||||||
throw new RuntimeException("shouldn't be called with a single input");
|
throw new RuntimeException("shouldn't be called with a single input");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Set<Object> inputs, List<Object> values) {
|
public boolean apply(Set<Object> inputs, List<Object> values) {
|
||||||
if (inputs != null) {
|
if (inputs != null) {
|
||||||
@@ -1019,7 +994,6 @@ public class AdvancedSearch {
|
|||||||
public boolean apply(Object input, List<Object> values) {
|
public boolean apply(Object input, List<Object> values) {
|
||||||
throw new RuntimeException("shouldn't be called with a single input");
|
throw new RuntimeException("shouldn't be called with a single input");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Set<Object> inputs, List<Object> values) {
|
public boolean apply(Set<Object> inputs, List<Object> values) {
|
||||||
if (inputs != null) {
|
if (inputs != null) {
|
||||||
@@ -1056,32 +1030,32 @@ public class AdvancedSearch {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
public static final FilterOperator[] BOOLEAN_OPS = new FilterOperator[]{
|
public static final FilterOperator[] BOOLEAN_OPS = new FilterOperator[] {
|
||||||
IS_TRUE, IS_FALSE
|
IS_TRUE, IS_FALSE
|
||||||
};
|
};
|
||||||
public static final FilterOperator[] NUMBER_OPS = new FilterOperator[]{
|
public static final FilterOperator[] NUMBER_OPS = new FilterOperator[] {
|
||||||
EQUALS, NOT_EQUALS, GREATER_THAN, LESS_THAN, GT_OR_EQUAL, LT_OR_EQUAL, BETWEEN_INCLUSIVE, BETWEEN_EXCLUSIVE
|
EQUALS, NOT_EQUALS, GREATER_THAN, LESS_THAN, GT_OR_EQUAL, LT_OR_EQUAL, BETWEEN_INCLUSIVE, BETWEEN_EXCLUSIVE
|
||||||
};
|
};
|
||||||
public static final FilterOperator[] STRING_OPS = new FilterOperator[]{
|
public static final FilterOperator[] STRING_OPS = new FilterOperator[] {
|
||||||
CONTAINS, STARTS_WITH, ENDS_WITH
|
CONTAINS, STARTS_WITH, ENDS_WITH
|
||||||
};
|
};
|
||||||
public static final FilterOperator[] STRINGS_OPS = new FilterOperator[]{
|
public static final FilterOperator[] STRINGS_OPS = new FilterOperator[] {
|
||||||
CONTAINS, STARTS_WITH, ENDS_WITH
|
CONTAINS, STARTS_WITH, ENDS_WITH
|
||||||
};
|
};
|
||||||
public static final FilterOperator[] SINGLE_LIST_OPS = new FilterOperator[]{
|
public static final FilterOperator[] SINGLE_LIST_OPS = new FilterOperator[] {
|
||||||
IS_ANY
|
IS_ANY
|
||||||
};
|
};
|
||||||
public static final FilterOperator[] MULTI_LIST_OPS = new FilterOperator[]{
|
public static final FilterOperator[] MULTI_LIST_OPS = new FilterOperator[] {
|
||||||
IS_ANY
|
IS_ANY
|
||||||
};
|
};
|
||||||
public static final FilterOperator[] COMBINATION_OPS = new FilterOperator[]{
|
public static final FilterOperator[] COMBINATION_OPS = new FilterOperator[] {
|
||||||
IS_EXACTLY, CONTAINS_ANY, CONTAINS_ALL
|
IS_EXACTLY, CONTAINS_ANY, CONTAINS_ALL
|
||||||
};
|
};
|
||||||
public static final FilterOperator[] COLLECTION_OPS = new FilterOperator[]{
|
public static final FilterOperator[] COLLECTION_OPS = new FilterOperator[] {
|
||||||
CONTAIN_ANY, CONTAIN_ALL
|
CONTAIN_ANY, CONTAIN_ALL
|
||||||
};
|
};
|
||||||
public static final FilterOperator[] DECK_CONTENT_OPS = new FilterOperator[]{
|
public static final FilterOperator[] DECK_CONTENT_OPS = new FilterOperator[] {
|
||||||
CONTAINS_CARD, CONTAINS_X_COPIES_OF_CARD
|
CONTAINS_CARD, CONTAINS_X_COPIES_OF_CARD
|
||||||
};
|
};
|
||||||
|
|
||||||
private final String caption, formatStr;
|
private final String caption, formatStr;
|
||||||
@@ -1130,8 +1104,8 @@ public class AdvancedSearch {
|
|||||||
final OperatorEvaluator<V> evaluator = (OperatorEvaluator<V>) operator.evaluator;
|
final OperatorEvaluator<V> evaluator = (OperatorEvaluator<V>) operator.evaluator;
|
||||||
Predicate<T> predicate = input -> evaluator.apply(getItemValue(input), values);
|
Predicate<T> predicate = input -> evaluator.apply(getItemValue(input), values);
|
||||||
|
|
||||||
final FilterOperator[][] manyValueOperators = {FilterOperator.MULTI_LIST_OPS,
|
final FilterOperator[][] manyValueOperators = { FilterOperator.MULTI_LIST_OPS,
|
||||||
FilterOperator.COMBINATION_OPS, FilterOperator.COLLECTION_OPS, FilterOperator.STRINGS_OPS};
|
FilterOperator.COMBINATION_OPS, FilterOperator.COLLECTION_OPS, FilterOperator.STRINGS_OPS };
|
||||||
for (FilterOperator[] oper : manyValueOperators) {
|
for (FilterOperator[] oper : manyValueOperators) {
|
||||||
if (option.operatorOptions == oper) {
|
if (option.operatorOptions == oper) {
|
||||||
predicate = input -> evaluator.apply(getItemValues(input), values);
|
predicate = input -> evaluator.apply(getItemValues(input), values);
|
||||||
@@ -1151,7 +1125,8 @@ public class AdvancedSearch {
|
|||||||
final List<V> values;
|
final List<V> values;
|
||||||
try {
|
try {
|
||||||
values = getValuesFromString(initialValueText, option, operator);
|
values = getValuesFromString(initialValueText, option, operator);
|
||||||
} catch (Exception e) {
|
}
|
||||||
|
catch(Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -1159,11 +1134,8 @@ public class AdvancedSearch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected abstract List<V> getValues(FilterOption option, FilterOperator operator);
|
protected abstract List<V> getValues(FilterOption option, FilterOperator operator);
|
||||||
|
|
||||||
protected abstract List<V> getValuesFromString(String valueText, FilterOption option, FilterOperator operator);
|
protected abstract List<V> getValuesFromString(String valueText, FilterOption option, FilterOperator operator);
|
||||||
|
|
||||||
protected abstract String getCaption(List<V> values, FilterOption option, FilterOperator operator);
|
protected abstract String getCaption(List<V> values, FilterOption option, FilterOperator operator);
|
||||||
|
|
||||||
protected abstract V getItemValue(T input);
|
protected abstract V getItemValue(T input);
|
||||||
|
|
||||||
protected Set<V> getItemValues(T input) { //available for options that have multiple inputs
|
protected Set<V> getItemValues(T input) { //available for options that have multiple inputs
|
||||||
@@ -1206,13 +1178,12 @@ public class AdvancedSearch {
|
|||||||
String message;
|
String message;
|
||||||
if (operator.valueCount == FilterValueCount.ONE) {
|
if (operator.valueCount == FilterValueCount.ONE) {
|
||||||
message = option.name + " " + operator.caption + " ?";
|
message = option.name + " " + operator.caption + " ?";
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
message = "? " + operator.caption.replace("|", " " + option.name + " ");
|
message = "? " + operator.caption.replace("|", " " + option.name + " ");
|
||||||
}
|
}
|
||||||
Integer lowerBound = SGuiChoose.getInteger(message, min, max);
|
Integer lowerBound = SGuiChoose.getInteger(message, min, max);
|
||||||
if (lowerBound == null) {
|
if (lowerBound == null) { return null; }
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<Integer> values = new ArrayList<>();
|
final List<Integer> values = new ArrayList<>();
|
||||||
values.add(lowerBound);
|
values.add(lowerBound);
|
||||||
@@ -1224,9 +1195,7 @@ public class AdvancedSearch {
|
|||||||
upperBoundMin += 2; //if exclusive, ensure it's possible to have numbers in between
|
upperBoundMin += 2; //if exclusive, ensure it's possible to have numbers in between
|
||||||
}
|
}
|
||||||
Integer upperBound = SGuiChoose.getInteger(message, upperBoundMin, max);
|
Integer upperBound = SGuiChoose.getInteger(message, upperBoundMin, max);
|
||||||
if (upperBound == null) {
|
if (upperBound == null) { return null; }
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
values.add(upperBound);
|
values.add(upperBound);
|
||||||
}
|
}
|
||||||
@@ -1257,9 +1226,7 @@ public class AdvancedSearch {
|
|||||||
protected List<String> getValues(FilterOption option, FilterOperator operator) {
|
protected List<String> getValues(FilterOption option, FilterOperator operator) {
|
||||||
String message = option.name + " " + operator.caption + " ?";
|
String message = option.name + " " + operator.caption + " ?";
|
||||||
String value = SOptionPane.showInputDialog("", message, null, initialInput);
|
String value = SOptionPane.showInputDialog("", message, null, initialInput);
|
||||||
if (value == null) {
|
if (value == null) { return null; }
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
initialInput = value; //store value as initial input for next time
|
initialInput = value; //store value as initial input for next time
|
||||||
|
|
||||||
@@ -1286,11 +1253,9 @@ public class AdvancedSearch {
|
|||||||
public CustomListEvaluator(Collection<V> choices0) {
|
public CustomListEvaluator(Collection<V> choices0) {
|
||||||
this(choices0, null, null);
|
this(choices0, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CustomListEvaluator(Collection<V> choices0, Function<V, String> toShortString0) {
|
public CustomListEvaluator(Collection<V> choices0, Function<V, String> toShortString0) {
|
||||||
this(choices0, toShortString0, null);
|
this(choices0, toShortString0, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CustomListEvaluator(Collection<V> choices0, Function<V, String> toShortString0, Function<V, String> toLongString0) {
|
public CustomListEvaluator(Collection<V> choices0, Function<V, String> toShortString0, Function<V, String> toLongString0) {
|
||||||
choices = choices0;
|
choices = choices0;
|
||||||
toShortString = toShortString0;
|
toShortString = toShortString0;
|
||||||
@@ -1311,9 +1276,9 @@ public class AdvancedSearch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean eitherStringMatches(V choice, String name) {
|
private boolean eitherStringMatches(V choice, String name) {
|
||||||
if (toLongString != null && name.equals(toLongString.apply(choice)))
|
if(toLongString != null && name.equals(toLongString.apply(choice)))
|
||||||
return true;
|
return true;
|
||||||
if (toShortString != null)
|
if(toShortString != null)
|
||||||
return name.equals(toShortString.apply(choice));
|
return name.equals(toShortString.apply(choice));
|
||||||
return name.equals(choice.toString());
|
return name.equals(choice.toString());
|
||||||
}
|
}
|
||||||
@@ -1322,16 +1287,16 @@ public class AdvancedSearch {
|
|||||||
protected String getCaption(List<V> values, FilterOption option, FilterOperator operator) {
|
protected String getCaption(List<V> values, FilterOption option, FilterOperator operator) {
|
||||||
String valuesStr;
|
String valuesStr;
|
||||||
switch (operator.valueCount) {
|
switch (operator.valueCount) {
|
||||||
case MANY:
|
case MANY:
|
||||||
valuesStr = formatValues(values, " ", " ");
|
valuesStr = formatValues(values, " ", " ");
|
||||||
break;
|
break;
|
||||||
case MANY_OR:
|
case MANY_OR:
|
||||||
valuesStr = formatValues(values, ", ", " or ");
|
valuesStr = formatValues(values, ", ", " or ");
|
||||||
break;
|
break;
|
||||||
case MANY_AND:
|
case MANY_AND:
|
||||||
default:
|
default:
|
||||||
valuesStr = formatValues(values, ", ", " and ");
|
valuesStr = formatValues(values, ", ", " and ");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return String.format(operator.formatStr, option.name, valuesStr);
|
return String.format(operator.formatStr, option.name, valuesStr);
|
||||||
}
|
}
|
||||||
@@ -1339,18 +1304,18 @@ public class AdvancedSearch {
|
|||||||
protected String formatValues(List<V> values, String delim, String finalDelim) {
|
protected String formatValues(List<V> values, String delim, String finalDelim) {
|
||||||
int valueCount = values.size();
|
int valueCount = values.size();
|
||||||
switch (valueCount) {
|
switch (valueCount) {
|
||||||
case 1:
|
case 1:
|
||||||
return formatValue(values.get(0));
|
return formatValue(values.get(0));
|
||||||
case 2:
|
case 2:
|
||||||
return formatValue(values.get(0)) + finalDelim + formatValue(values.get(1));
|
return formatValue(values.get(0)) + finalDelim + formatValue(values.get(1));
|
||||||
default:
|
default:
|
||||||
int lastValueIdx = valueCount - 1;
|
int lastValueIdx = valueCount - 1;
|
||||||
StringBuilder result = new StringBuilder(formatValue(values.get(0)));
|
StringBuilder result = new StringBuilder(formatValue(values.get(0)));
|
||||||
for (int i = 1; i < lastValueIdx; i++) {
|
for (int i = 1; i < lastValueIdx; i++) {
|
||||||
result.append(delim).append(formatValue(values.get(i)));
|
result.append(delim).append(formatValue(values.get(i)));
|
||||||
}
|
}
|
||||||
result.append(delim.trim()).append(finalDelim).append(formatValue(values.get(lastValueIdx)));
|
result.append(delim.trim()).append(finalDelim).append(formatValue(values.get(lastValueIdx)));
|
||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1385,16 +1350,12 @@ public class AdvancedSearch {
|
|||||||
protected List<Map<String, Integer>> getValues(FilterOption option, FilterOperator operator) {
|
protected List<Map<String, Integer>> getValues(FilterOption option, FilterOperator operator) {
|
||||||
String message = option.name + " " + operator.caption + " ?";
|
String message = option.name + " " + operator.caption + " ?";
|
||||||
PaperCard card = SGuiChoose.oneOrNone(message, FModel.getMagicDb().getCommonCards().getUniqueCards());
|
PaperCard card = SGuiChoose.oneOrNone(message, FModel.getMagicDb().getCommonCards().getUniqueCards());
|
||||||
if (card == null) {
|
if (card == null) { return null; }
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Integer amount = -1;
|
Integer amount = -1;
|
||||||
if (operator == FilterOperator.CONTAINS_X_COPIES_OF_CARD) { //prompt for quantity if needed
|
if (operator == FilterOperator.CONTAINS_X_COPIES_OF_CARD) { //prompt for quantity if needed
|
||||||
amount = SGuiChoose.getInteger(Localizer.getInstance().getMessage("lblHowManyCopiesOfN", CardTranslation.getTranslatedName(card.getName())), 0, 4);
|
amount = SGuiChoose.getInteger(Localizer.getInstance().getMessage("lblHowManyCopiesOfN", CardTranslation.getTranslatedName(card.getName())), 0, 4);
|
||||||
if (amount == null) {
|
if (amount == null) { return null; }
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Integer> map = new HashMap<>();
|
Map<String, Integer> map = new HashMap<>();
|
||||||
@@ -1409,12 +1370,13 @@ public class AdvancedSearch {
|
|||||||
protected List<Map<String, Integer>> getValuesFromString(String valueText, FilterOption option, FilterOperator operator) {
|
protected List<Map<String, Integer>> getValuesFromString(String valueText, FilterOption option, FilterOperator operator) {
|
||||||
int amount = -1;
|
int amount = -1;
|
||||||
String cardName;
|
String cardName;
|
||||||
if (operator == FilterOperator.CONTAINS_X_COPIES_OF_CARD) {
|
if(operator == FilterOperator.CONTAINS_X_COPIES_OF_CARD) {
|
||||||
//Take the format "2 Mountain"
|
//Take the format "2 Mountain"
|
||||||
String[] split = valueText.split(" ", 2);
|
String[] split = valueText.split(" ", 2);
|
||||||
amount = Integer.parseInt(split[0]);
|
amount = Integer.parseInt(split[0]);
|
||||||
cardName = split[1];
|
cardName = split[1];
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
cardName = valueText;
|
cardName = valueText;
|
||||||
Map<String, Integer> map = new HashMap<>();
|
Map<String, Integer> map = new HashMap<>();
|
||||||
map.put(cardName, amount);
|
map.put(cardName, amount);
|
||||||
@@ -1450,29 +1412,25 @@ public class AdvancedSearch {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
option = SGuiChoose.oneOrNone(Localizer.getInstance().getMessage("lblSelectAFilterType"), options, defaultOption, null);
|
option = SGuiChoose.oneOrNone(Localizer.getInstance().getMessage("lblSelectAFilterType"), options, defaultOption, null);
|
||||||
if (option == null) {
|
if (option == null) { return editFilter; }
|
||||||
return editFilter;
|
}
|
||||||
}
|
else {
|
||||||
} else {
|
|
||||||
option = defaultOption;
|
option = defaultOption;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (option == FilterOption.NONE) {
|
if (option == FilterOption.NONE) { return null; } //allow user to clear filter by selecting "(none)"
|
||||||
return null;
|
|
||||||
} //allow user to clear filter by selecting "(none)"
|
|
||||||
|
|
||||||
final FilterOperator operator;
|
final FilterOperator operator;
|
||||||
if (option.operatorOptions.length > 1) {
|
if (option.operatorOptions.length > 1) {
|
||||||
final FilterOperator defaultOperator = option == defaultOption ? editFilter.operator : null;
|
final FilterOperator defaultOperator = option == defaultOption ? editFilter.operator : null;
|
||||||
operator = SGuiChoose.oneOrNone(Localizer.getInstance().getMessage("lblSelectOperatorFor", option.name), option.operatorOptions, defaultOperator, null);
|
operator = SGuiChoose.oneOrNone(Localizer.getInstance().getMessage("lblSelectOperatorFor", option.name), option.operatorOptions, defaultOperator, null);
|
||||||
if (operator == null) {
|
if (operator == null) { return editFilter; }
|
||||||
return editFilter;
|
}
|
||||||
}
|
else {
|
||||||
} else {
|
|
||||||
operator = option.operatorOptions[0];
|
operator = option.operatorOptions[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
Filter<T> filter = (Filter<T>) option.evaluator.createFilter(option, operator);
|
Filter<T> filter = (Filter<T>)option.evaluator.createFilter(option, operator);
|
||||||
if (filter == null) {
|
if (filter == null) {
|
||||||
filter = editFilter;
|
filter = editFilter;
|
||||||
}
|
}
|
||||||
@@ -1482,7 +1440,8 @@ public class AdvancedSearch {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <T extends InventoryItem> Filter<T> getFilter(Class<? super T> type, String filterText) {
|
public static <T extends InventoryItem> Filter<T> getFilter(Class<? super T> type, String filterText) {
|
||||||
String[] words = filterText.split(" ", 3);
|
String[] words = filterText.split(" ", 3);
|
||||||
if (words.length < 2) {
|
if(words.length < 2)
|
||||||
|
{
|
||||||
System.out.printf("Unable to generate filter from expression '%s'%n", filterText);
|
System.out.printf("Unable to generate filter from expression '%s'%n", filterText);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -1495,7 +1454,8 @@ public class AdvancedSearch {
|
|||||||
System.out.printf("Unable to generate filter from FilterOption '%s'%n", words[0]);
|
System.out.printf("Unable to generate filter from FilterOption '%s'%n", words[0]);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (option.type != type) {
|
if(option.type != type)
|
||||||
|
{
|
||||||
System.out.printf("Unable to generate filter from FilterOption '%s' - filter type '%s' != option type '%s' %n", words[0], type, option.type);
|
System.out.printf("Unable to generate filter from FilterOption '%s' - filter type '%s' != option type '%s' %n", words[0], type, option.type);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -1555,23 +1515,14 @@ public class AdvancedSearch {
|
|||||||
|
|
||||||
public interface IFilterControl<T extends InventoryItem> {
|
public interface IFilterControl<T extends InventoryItem> {
|
||||||
IButton getBtnNotBeforeParen();
|
IButton getBtnNotBeforeParen();
|
||||||
|
|
||||||
IButton getBtnOpenParen();
|
IButton getBtnOpenParen();
|
||||||
|
|
||||||
IButton getBtnNotAfterParen();
|
IButton getBtnNotAfterParen();
|
||||||
|
|
||||||
IButton getBtnFilter();
|
IButton getBtnFilter();
|
||||||
|
|
||||||
IButton getBtnCloseParen();
|
IButton getBtnCloseParen();
|
||||||
|
|
||||||
IButton getBtnAnd();
|
IButton getBtnAnd();
|
||||||
|
|
||||||
IButton getBtnOr();
|
IButton getBtnOr();
|
||||||
|
|
||||||
Filter<T> getFilter();
|
Filter<T> getFilter();
|
||||||
|
|
||||||
void setFilter(Filter<T> filter0);
|
void setFilter(Filter<T> filter0);
|
||||||
|
|
||||||
Class<? super T> getGenericType();
|
Class<? super T> getGenericType();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1603,18 +1554,23 @@ public class AdvancedSearch {
|
|||||||
Object piece = iterator.get();
|
Object piece = iterator.get();
|
||||||
if (piece.equals(Operator.OPEN_PAREN)) {
|
if (piece.equals(Operator.OPEN_PAREN)) {
|
||||||
predPiece = getPredicatePiece(iterator.next());
|
predPiece = getPredicatePiece(iterator.next());
|
||||||
} else if (piece.equals(Operator.CLOSE_PAREN)) {
|
}
|
||||||
|
else if (piece.equals(Operator.CLOSE_PAREN)) {
|
||||||
return pred;
|
return pred;
|
||||||
} else if (piece.equals(Operator.AND)) {
|
}
|
||||||
|
else if (piece.equals(Operator.AND)) {
|
||||||
operator = Operator.AND;
|
operator = Operator.AND;
|
||||||
continue;
|
continue;
|
||||||
} else if (piece.equals(Operator.OR)) {
|
}
|
||||||
|
else if (piece.equals(Operator.OR)) {
|
||||||
operator = Operator.OR;
|
operator = Operator.OR;
|
||||||
continue;
|
continue;
|
||||||
} else if (piece.equals(Operator.NOT)) {
|
}
|
||||||
|
else if (piece.equals(Operator.NOT)) {
|
||||||
applyNot = !applyNot;
|
applyNot = !applyNot;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
predPiece = ((AdvancedSearch.Filter<T>) piece).getPredicate();
|
predPiece = ((AdvancedSearch.Filter<T>) piece).getPredicate();
|
||||||
}
|
}
|
||||||
if (applyNot) {
|
if (applyNot) {
|
||||||
@@ -1623,9 +1579,11 @@ public class AdvancedSearch {
|
|||||||
}
|
}
|
||||||
if (pred == null) {
|
if (pred == null) {
|
||||||
pred = predPiece;
|
pred = predPiece;
|
||||||
} else if (operator == Operator.AND) {
|
}
|
||||||
|
else if (operator == Operator.AND) {
|
||||||
pred = pred.and(predPiece);
|
pred = pred.and(predPiece);
|
||||||
} else if (operator == Operator.OR) {
|
}
|
||||||
|
else if (operator == Operator.OR) {
|
||||||
pred = pred.or(predPiece);
|
pred = pred.or(predPiece);
|
||||||
}
|
}
|
||||||
operator = null;
|
operator = null;
|
||||||
@@ -1668,7 +1626,16 @@ public class AdvancedSearch {
|
|||||||
control.setFilter(filter);
|
control.setFilter(filter);
|
||||||
if (filter != null) {
|
if (filter != null) {
|
||||||
control.getBtnFilter().setText(GuiBase.getInterface().encodeSymbols(filter.toString(), false));
|
control.getBtnFilter().setText(GuiBase.getInterface().encodeSymbols(filter.toString(), false));
|
||||||
} else {
|
|
||||||
|
if (filter.getOption() == FilterOption.CARD_KEYWORDS) {
|
||||||
|
//the first time the user selects keywords, preload keywords for all cards
|
||||||
|
Runnable preloadTask = Keyword.getPreloadTask();
|
||||||
|
if (preloadTask != null) {
|
||||||
|
GuiBase.getInterface().runBackgroundTask(Localizer.getInstance().getMessage("lblLoadingKeywords"), preloadTask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
control.getBtnFilter().setText(EMPTY_FILTER_TEXT);
|
control.getBtnFilter().setText(EMPTY_FILTER_TEXT);
|
||||||
}
|
}
|
||||||
if (onChange != null) {
|
if (onChange != null) {
|
||||||
@@ -1690,31 +1657,32 @@ public class AdvancedSearch {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void updateLabel() {
|
public void updateLabel() {
|
||||||
if (label == null) {
|
if (label == null) { return; }
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append("Filter: ");
|
builder.append("Filter: ");
|
||||||
if (expression.isEmpty()) {
|
if (expression.isEmpty()) {
|
||||||
builder.append("(none)");
|
builder.append("(none)");
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
int prevFilterEndIdx = -1;
|
int prevFilterEndIdx = -1;
|
||||||
AdvancedSearch.Filter<T> filter, prevFilter = null;
|
AdvancedSearch.Filter<T> filter, prevFilter = null;
|
||||||
for (Object piece : expression) {
|
for (Object piece : expression) {
|
||||||
if (piece instanceof AdvancedSearch.Filter) {
|
if (piece instanceof AdvancedSearch.Filter) {
|
||||||
filter = (AdvancedSearch.Filter<T>) piece;
|
filter = (AdvancedSearch.Filter<T>)piece;
|
||||||
if (filter.canMergeCaptionWith(prevFilter)) {
|
if (filter.canMergeCaptionWith(prevFilter)) {
|
||||||
//convert boolean operators between filters to lowercase
|
//convert boolean operators between filters to lowercase
|
||||||
builder.replace(prevFilterEndIdx, builder.length(), builder.substring(prevFilterEndIdx).toLowerCase());
|
builder.replace(prevFilterEndIdx, builder.length(), builder.substring(prevFilterEndIdx).toLowerCase());
|
||||||
//append only values for filter
|
//append only values for filter
|
||||||
builder.append(filter.extractValuesFromCaption());
|
builder.append(filter.extractValuesFromCaption());
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
builder.append(filter);
|
builder.append(filter);
|
||||||
}
|
}
|
||||||
prevFilter = filter;
|
prevFilter = filter;
|
||||||
prevFilterEndIdx = builder.length();
|
prevFilterEndIdx = builder.length();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
if (piece.equals(Operator.OPEN_PAREN) || piece.equals(Operator.CLOSE_PAREN)) {
|
if (piece.equals(Operator.OPEN_PAREN) || piece.equals(Operator.CLOSE_PAREN)) {
|
||||||
prevFilter = null; //prevent merging filters with parentheses in between
|
prevFilter = null; //prevent merging filters with parentheses in between
|
||||||
}
|
}
|
||||||
@@ -1727,9 +1695,7 @@ public class AdvancedSearch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getTooltip() {
|
public String getTooltip() {
|
||||||
if (expression.isEmpty()) {
|
if (expression.isEmpty()) { return ""; }
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append("Filter:\n");
|
builder.append("Filter:\n");
|
||||||
@@ -1752,9 +1718,7 @@ public class AdvancedSearch {
|
|||||||
expression.clear();
|
expression.clear();
|
||||||
|
|
||||||
for (IFilterControl<T> control : controls) {
|
for (IFilterControl<T> control : controls) {
|
||||||
if (control.getFilter() == null) {
|
if (control.getFilter() == null) { continue; } //skip any blank filters
|
||||||
continue;
|
|
||||||
} //skip any blank filters
|
|
||||||
|
|
||||||
if (control.getBtnNotBeforeParen().isSelected()) {
|
if (control.getBtnNotBeforeParen().isSelected()) {
|
||||||
expression.add(Operator.NOT);
|
expression.add(Operator.NOT);
|
||||||
@@ -1773,7 +1737,8 @@ public class AdvancedSearch {
|
|||||||
}
|
}
|
||||||
if (control.getBtnAnd().isSelected()) {
|
if (control.getBtnAnd().isSelected()) {
|
||||||
expression.add(Operator.AND);
|
expression.add(Operator.AND);
|
||||||
} else if (control.getBtnOr().isSelected()) {
|
}
|
||||||
|
else if (control.getBtnOr().isSelected()) {
|
||||||
expression.add(Operator.OR);
|
expression.add(Operator.OR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1783,16 +1748,13 @@ public class AdvancedSearch {
|
|||||||
|
|
||||||
private class ExpressionIterator {
|
private class ExpressionIterator {
|
||||||
private int index;
|
private int index;
|
||||||
|
|
||||||
private boolean hasNext() {
|
private boolean hasNext() {
|
||||||
return index < expression.size();
|
return index < expression.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ExpressionIterator next() {
|
private ExpressionIterator next() {
|
||||||
index++;
|
index++;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object get() {
|
private Object get() {
|
||||||
return expression.get(index);
|
return expression.get(index);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -217,8 +217,7 @@ public class SFilterUtil {
|
|||||||
}
|
}
|
||||||
entry.append(ch);
|
entry.append(ch);
|
||||||
}
|
}
|
||||||
// Android API StringBuilder isEmpty() is unavailable. https://developer.android.com/reference/java/lang/StringBuilder
|
if (entry.length() != 0) { // Android API isEmpty() is unavailable. https://developer.android.com/reference/java/lang/StringBuilder
|
||||||
if (entry.length() != 0) {
|
|
||||||
splitText.add(entry.toString());
|
splitText.add(entry.toString());
|
||||||
}
|
}
|
||||||
return splitText;
|
return splitText;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import json
|
|||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
|
||||||
def draftsimRankings(edition='SPM', extra=None):
|
def draftsimRankings(edition='FIN', extra=None):
|
||||||
edition = edition.upper()
|
edition = edition.upper()
|
||||||
url1 = 'https://draftsim.com/generated/%s/' % (edition)
|
url1 = 'https://draftsim.com/generated/%s/' % (edition)
|
||||||
url2 = '%s' % edition
|
url2 = '%s' % edition
|
||||||
|
|||||||
Reference in New Issue
Block a user