Merge branch 'historicformats' into 'master'

Formatting and preparation of historicformats

See merge request core-developers/forge!342
This commit is contained in:
Sol
2018-05-16 01:40:34 +00:00
663 changed files with 5593 additions and 90 deletions

View File

@@ -0,0 +1,160 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Nate
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.util.storage;
import com.google.common.base.Function;
import forge.util.TextUtil;
import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.*;
/**
* This class treats every file in the given folder as a source for a named
* object. The descendant should implement read method to deserialize a single
* item. So that readAll will return a map of Name => Object as read from disk
*
* @param <T> the generic type
*/
public abstract class StorageReaderRecursiveFolderWithUserFolder<T> extends StorageReaderBase<T> {
/**
* @return the directory
*/
public File getDirectory() {
return directory;
}
@Override
public String getFullPath() {
return directory.getPath();
}
protected final File directory;
protected final File userDirectory;
/**
* Instantiates a new storage reader folder.
*
* @param itemDir0 the item dir0
*/
public StorageReaderRecursiveFolderWithUserFolder(final File itemDir0, final File userItemDir0, Function<? super T, String> keySelector0) {
super(keySelector0);
this.directory = itemDir0;
this.userDirectory = userItemDir0;
if (this.directory == null) {
throw new IllegalArgumentException("No directory specified");
}
try {
if (this.directory.isFile()) {
throw new IOException("Not a directory");
} else {
this.directory.mkdirs();
if (!this.directory.isDirectory()) {
throw new IOException("Directory can't be created");
}
}
} catch (final IOException ex) {
throw new RuntimeException("StorageReaderFolder.ctor() error, " + ex.getMessage());
}
}
public final List<String> objectsThatFailedToLoad = new ArrayList<String>();
/* (non-Javadoc)
* @see forge.util.IItemReader#readAll()
*/
@Override
public Map<String, T> readAll() {
final Map<String, T> result = new TreeMap<String, T>();
Collection<File> forgeFormats = listFileTree(directory);
Collection<File> customFormats = listFileTree(userDirectory);
forgeFormats.addAll(customFormats);
final File[] files = forgeFormats.toArray(new File[forgeFormats.size()]);
for (final File file : files) {
try {
final T newDeck = this.read(file);
if (null == newDeck) {
final String msg = "An object stored in " + file.getPath() + " failed to load.\nPlease submit this as a bug with the mentioned file/directory attached.";
continue;//skip format completely - perhaps non format file
}
String newKey = keySelector.apply(newDeck);
if (result.containsKey(newKey)) {
System.err.println("StorageReaderFolder: Overwriting an object with key " + newKey);
}
result.put(newKey, newDeck);
} catch (final NoSuchElementException ex) {
final String message = TextUtil.concatWithSpace( file.getName(),"failed to load because ----", ex.getMessage());
objectsThatFailedToLoad.add(message);
}
}
return result;
}
private Collection<File> listFileTree(File dir) {
Set<File> fileTree = new HashSet<File>();
if(dir==null||dir.listFiles(getFileFilter())==null){
return fileTree;
}
for (File entry : dir.listFiles(getFileFilter())) {
if (entry.isFile()) fileTree.add(entry);
else fileTree.addAll(listFileTree(entry));
}
return fileTree;
}
/**
* Read the object from file.
*
* @param file the file
* @return the object deserialized by inherited class
*/
protected abstract T read(File file);
/**
* TODO: Write javadoc for this method.
*
* @return FilenameFilter to pick only relevant objects for deserialization
*/
protected abstract FilenameFilter getFileFilter();
@Override
public String getItemKey(T item) {
return keySelector.apply(item);
}
// methods handling nested folders are provided. It's up to consumer whether to use these or not.
@Override
public Iterable<File> getSubFolders() {
File[] list = this.directory.listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
return file.isDirectory() && !file.isHidden();
}
});
return Arrays.asList(list);
}
}

View File

@@ -34,28 +34,39 @@ import forge.item.PaperCard;
import forge.util.FileSection;
import forge.util.FileUtil;
import forge.util.storage.StorageBase;
import forge.util.storage.StorageReaderFolder;
import forge.util.storage.StorageReaderRecursiveFolderWithUserFolder;
import java.io.File;
import java.io.FilenameFilter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Map.Entry;
public class GameFormat implements Comparable<GameFormat> {
private final String name;
public enum FormatType {Sanctioned, Casual, Historic, Custom}
public enum FormatType {Sanctioned, Casual, Historic, Digital, Custom}
public enum FormatSubType {Block, Standard, Extended, Modern, Legacy, Vintage, Commander, Planechase, Videogame, MTGO, Custom}
// contains allowed sets, when empty allows all sets
private FormatType formatType;
private FormatSubType formatSubType;
protected final List<String> allowedSetCodes; // this is mutable to support quest mode set unlocks
protected final List<CardRarity> allowedRarities;
protected final List<String> bannedCardNames;
protected final List<String> restrictedCardNames;
protected final List<String> additionalCardNames; // for cards that are legal but not reprinted in any of the allowed Sets
protected boolean restrictedLegendary = false;
private Date effectiveDate;
private final static SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
private final static String DEFAULTDATE = "1990-01-01";
protected final transient List<String> allowedSetCodes_ro;
protected final transient List<String> bannedCardNames_ro;
protected final transient List<String> restrictedCardNames_ro;
protected final transient List<String> additionalCardNames_ro;
protected final transient Predicate<PaperCard> filterRules;
protected final transient Predicate<PaperCard> filterPrinted;
@@ -63,24 +74,46 @@ public class GameFormat implements Comparable<GameFormat> {
private final int index;
public GameFormat(final String fName, final Iterable<String> sets, final List<String> bannedCards) {
this(fName, sets, bannedCards, null, null, 0, FormatType.Custom);
this(fName, parseDate(DEFAULTDATE), sets, bannedCards, null, false, null, null, 0, FormatType.Custom, FormatSubType.Custom);
}
public static final GameFormat NoFormat = new GameFormat("(none)", null, null, null, null, Integer.MAX_VALUE, FormatType.Custom);
public static final GameFormat NoFormat = new GameFormat("(none)", parseDate(DEFAULTDATE) , null, null, null, false
, null, null, Integer.MAX_VALUE, FormatType.Custom, FormatSubType.Custom);
public GameFormat(final String fName, final Iterable<String> sets, final List<String> bannedCards,
final List<String> restrictedCards, final List<CardRarity> rarities, int compareIdx, FormatType formatType) {
public GameFormat(final String fName, final Date effectiveDate, final Iterable<String> sets, final List<String> bannedCards,
final List<String> restrictedCards, Boolean restrictedLegendary, final List<String> additionalCards,
final List<CardRarity> rarities, int compareIdx, FormatType formatType, FormatSubType formatSubType) {
this.index = compareIdx;
this.formatType = formatType;
this.formatSubType = formatSubType;
this.name = fName;
allowedSetCodes = sets == null ? new ArrayList<String>() : Lists.newArrayList(sets);
this.effectiveDate = effectiveDate;
if(sets != null) {
Set<String> parsedSets = new HashSet<>();
for (String set : sets) {
if (StaticData.instance().getEditions().get(set) == null) {
System.out.println("Set " + set + " in format " + fName + " does not match any valid editions!");
continue;
}
parsedSets.add(set);
}
allowedSetCodes = Lists.newArrayList(parsedSets);
}else{
allowedSetCodes = new ArrayList<String>();
}
bannedCardNames = bannedCards == null ? new ArrayList<String>() : Lists.newArrayList(bannedCards);
restrictedCardNames = restrictedCards == null ? new ArrayList<String>() : Lists.newArrayList(restrictedCards);
allowedRarities = rarities == null ? new ArrayList<CardRarity>() : rarities;
this.restrictedLegendary = restrictedLegendary;
additionalCardNames = additionalCards == null ? new ArrayList<String>() : Lists.newArrayList(additionalCards);
this.allowedSetCodes_ro = Collections.unmodifiableList(allowedSetCodes);
this.bannedCardNames_ro = Collections.unmodifiableList(bannedCardNames);
this.restrictedCardNames_ro = Collections.unmodifiableList(restrictedCardNames);
this.additionalCardNames_ro = Collections.unmodifiableList(additionalCardNames);
this.filterRules = this.buildFilterRules();
this.filterPrinted = this.buildFilterPrinted();
@@ -99,6 +132,9 @@ public class GameFormat implements Comparable<GameFormat> {
}
p = Predicates.and(p, Predicates.or(crp));
}
if (!this.additionalCardNames_ro.isEmpty()) {
p = Predicates.or(p, IPaperCard.Predicates.names(this.additionalCardNames_ro));
}
return p;
}
@@ -114,10 +150,26 @@ public class GameFormat implements Comparable<GameFormat> {
return this.name;
}
private static Date parseDate(String date) {
if( date.length() <= 7 )
date = date + "-01";
try {
return formatter.parse(date);
} catch (ParseException e) {
return new Date();
}
}
public Date getEffectiveDate() { return effectiveDate; }
public FormatType getFormatType() {
return this.formatType;
}
public FormatSubType getFormatSubType() {
return this.formatSubType;
}
public List<String> getAllowedSetCodes() {
return this.allowedSetCodes_ro;
}
@@ -129,6 +181,15 @@ public class GameFormat implements Comparable<GameFormat> {
public List<String> getRestrictedCards() {
return restrictedCardNames_ro;
}
public Boolean isRestrictedLegendary() {
return restrictedLegendary;
}
public List<String> getAdditionalCards() {
return additionalCardNames_ro;
}
public List<CardRarity> getAllowedRarities() {
return allowedRarities;
}
@@ -171,9 +232,11 @@ public class GameFormat implements Comparable<GameFormat> {
}
}
if(!restrictedCardNames_ro.isEmpty() ) {
if(!restrictedCardNames_ro.isEmpty() || restrictedLegendary ) {
for (Entry<PaperCard, Integer> poolEntry : allCards) {
if( poolEntry.getValue().intValue() > 1 && restrictedCardNames_ro.contains(poolEntry.getKey().getName()))
if( poolEntry.getValue().intValue() > 1 && (restrictedCardNames_ro.contains(poolEntry.getKey().getName())
|| (poolEntry.getKey().getRules().getType().isLegendary()
&& !poolEntry.getKey().getRules().getType().isPlaneswalker() && restrictedLegendary)))
return false;
}
}
@@ -201,36 +264,80 @@ public class GameFormat implements Comparable<GameFormat> {
if (null == other) {
return 1;
}
return index - other.index;
if (other.formatType != formatType){
return formatType.compareTo(other.formatType);
}else{
if (other.formatSubType != formatSubType){
return formatSubType.compareTo(other.formatSubType);
}
}
if (formatType.equals(FormatType.Historic)){
if(effectiveDate!=other.effectiveDate) {//for matching dates or default dates default to name sorting
return other.effectiveDate.compareTo(effectiveDate);
}
}
return name.compareTo(other.name);
//return index - other.index;
}
public int getIndex() {
return index;
}
public static class Reader extends StorageReaderFolder<GameFormat> {
public static class Reader extends StorageReaderRecursiveFolderWithUserFolder<GameFormat> {
List<GameFormat> naturallyOrdered = new ArrayList<GameFormat>();
boolean includeHistoric;
private List<String> coreFormats = new ArrayList<>();
{
coreFormats.add("Standard.txt");
coreFormats.add("Modern.txt");
coreFormats.add("Legacy.txt");
coreFormats.add("Vintage.txt");
coreFormats.add("Commander.txt");
public Reader(File file0) {
super(file0, GameFormat.FN_GET_NAME);
}
public Reader(File forgeFormats, File customFormats, boolean includeHistoric) {
super(forgeFormats, customFormats, GameFormat.FN_GET_NAME);
this.includeHistoric=includeHistoric;
}
@Override
protected GameFormat read(File file) {
if(!includeHistoric && !coreFormats.contains(file.getName())){
return null;
}
final Map<String, List<String>> contents = FileSection.parseSections(FileUtil.readFile(file));
List<String> sets = null; // default: all sets allowed
List<String> bannedCards = null; // default: nothing banned
List<String> restrictedCards = null; // default: nothing restricted
Boolean restrictedLegendary = false;
List<String> additionalCards = null; // default: nothing additional
List<CardRarity> rarities = null;
FileSection section = FileSection.parse(contents.get("format"), ":");
List<String> formatStrings = contents.get("format");
if (formatStrings == null){
return null;
}
FileSection section = FileSection.parse(formatStrings, ":");
String title = section.get("name");
FormatType formatType;
try {
formatType = FormatType.valueOf(section.get("type"));
} catch (IllegalArgumentException e) {
} catch (Exception e) {
formatType = FormatType.Custom;
}
FormatSubType formatsubType;
try {
formatsubType = FormatSubType.valueOf(section.get("subtype"));
} catch (Exception e) {
formatsubType = FormatSubType.Custom;
}
Integer idx = section.getInt("order");
String dateStr = section.get("effective");
if (dateStr == null){
dateStr = DEFAULTDATE;
}
Date date = parseDate(dateStr);
String strSets = section.get("sets");
if ( null != strSets ) {
sets = Arrays.asList(strSets.split(", "));
@@ -245,6 +352,16 @@ public class GameFormat implements Comparable<GameFormat> {
restrictedCards = Arrays.asList(strCars.split("; "));
}
Boolean strRestrictedLegendary = section.getBoolean("restrictedlegendary");
if ( strRestrictedLegendary != null ) {
restrictedLegendary = strRestrictedLegendary;
}
strCars = section.get("additional");
if ( strCars != null ) {
additionalCards = Arrays.asList(strCars.split("; "));
}
strCars = section.get("rarities");
if ( strCars != null ) {
CardRarity cr;
@@ -257,7 +374,7 @@ public class GameFormat implements Comparable<GameFormat> {
}
}
GameFormat result = new GameFormat(title, sets, bannedCards, restrictedCards, rarities, idx, formatType);
GameFormat result = new GameFormat(title, date, sets, bannedCards, restrictedCards, restrictedLegendary, additionalCards, rarities, idx, formatType,formatsubType);
naturallyOrdered.add(result);
return result;
}
@@ -270,24 +387,31 @@ public class GameFormat implements Comparable<GameFormat> {
public static final FilenameFilter TXT_FILE_FILTER = new FilenameFilter() {
@Override
public boolean accept(final File dir, final String name) {
return name.endsWith(".txt");
return name.endsWith(".txt") || dir.isDirectory();
}
};
}
public static class Collection extends StorageBase<GameFormat> {
private List<GameFormat> naturallyOrdered;
private List<GameFormat> reverseDateOrdered;
public Collection(GameFormat.Reader reader) {
super("Format collections", reader);
naturallyOrdered = reader.naturallyOrdered;
reverseDateOrdered = new ArrayList<>(naturallyOrdered);
Collections.sort(naturallyOrdered);
Collections.sort(reverseDateOrdered, new InverseDateComparator());
}
public Iterable<GameFormat> getOrderedList() {
return naturallyOrdered;
}
public Iterable<GameFormat> getReverseDateOrderedList() {
return reverseDateOrdered;
}
public Iterable<GameFormat> getSanctionedList() {
List<GameFormat> coreList = new ArrayList<>();
for(GameFormat format: naturallyOrdered){
@@ -298,6 +422,41 @@ public class GameFormat implements Comparable<GameFormat> {
return coreList;
}
public Iterable<GameFormat> getFilterList() {
List<GameFormat> coreList = new ArrayList<>();
for(GameFormat format: naturallyOrdered){
if(!format.getFormatType().equals(FormatType.Historic)
&&!format.getFormatType().equals(FormatType.Digital)){
coreList.add(format);
}
}
return coreList;
}
public Iterable<GameFormat> getHistoricList() {
List<GameFormat> coreList = new ArrayList<>();
for(GameFormat format: naturallyOrdered){
if(format.getFormatType().equals(FormatType.Historic)){
coreList.add(format);
}
}
return coreList;
}
public Map<String, List<GameFormat>> getHistoricMap() {
Map<String, List<GameFormat>> coreList = new HashMap<>();
for(GameFormat format: naturallyOrdered){
if(format.getFormatType().equals(FormatType.Historic)){
String alpha = format.getName().substring(0,1);
if(!coreList.containsKey(alpha)){
coreList.put(alpha,new ArrayList<>());
}
coreList.get(alpha).add(format);
}
}
return coreList;
}
public GameFormat getStandard() {
return this.map.get("Standard");
}
@@ -315,7 +474,7 @@ public class GameFormat implements Comparable<GameFormat> {
}
public GameFormat getFormatOfDeck(Deck deck) {
for(GameFormat gf : naturallyOrdered) {
for(GameFormat gf : reverseDateOrdered) {
if ( gf.isDeckLegal(deck) )
return gf;
}
@@ -336,11 +495,26 @@ public class GameFormat implements Comparable<GameFormat> {
}
public Set<GameFormat> getAllFormatsOfDeck(Deck deck) {
return getAllFormatsOfDeck(deck, false);
}
public Set<GameFormat> getAllFormatsOfDeck(Deck deck, Boolean exhaustive) {
SortedSet<GameFormat> result = new TreeSet<GameFormat>();
Set<FormatSubType> coveredTypes = new HashSet<>();
CardPool allCards = deck.getAllCardsInASinglePool();
for(GameFormat gf : naturallyOrdered) {
for(GameFormat gf : reverseDateOrdered) {
if (gf.getFormatType().equals(FormatType.Digital) && !exhaustive){
//exclude Digital formats from lists for now
continue;
}
if (gf.getFormatType().equals(FormatType.Historic) && coveredTypes.contains(gf.getFormatSubType())
&& !exhaustive){
//exclude duplicate formats - only keep first of e.g. Standard historical
continue;
}
if (gf.isPoolLegal(allCards)) {
result.add(gf);
coveredTypes.add(gf.getFormatSubType());
}
}
if (result.isEmpty()) {
@@ -355,6 +529,27 @@ public class GameFormat implements Comparable<GameFormat> {
}
}
public static class InverseDateComparator implements Comparator<GameFormat> {
public int compare(GameFormat gf1, GameFormat gf2){
if ((null == gf1) || (null == gf2)) {
return 1;
}
if (gf2.formatType != gf1.formatType){
return gf1.formatType.compareTo(gf2.formatType);
}else{
if (gf2.formatSubType != gf1.formatSubType){
return gf1.formatSubType.compareTo(gf2.formatSubType);
}
}
if (gf1.formatType.equals(FormatType.Historic)){
if(gf1.effectiveDate!=gf2.effectiveDate) {//for matching dates or default dates default to name sorting
return gf1.effectiveDate.compareTo(gf2.effectiveDate);
}
}
return gf1.name.compareTo(gf2.name);
}
}
public final Predicate<CardEdition> editionLegalPredicate = new Predicate<CardEdition>() {
@Override
public boolean apply(final CardEdition subject) {

View File

@@ -7,10 +7,13 @@ import forge.itemmanager.filters.*;
import forge.model.FModel;
import forge.quest.QuestWorld;
import forge.quest.data.QuestPreferences;
import forge.screens.home.quest.DialogChooseFormats;
import forge.screens.home.quest.DialogChooseSets;
import forge.screens.match.controllers.CDetailPicture;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
@@ -82,7 +85,7 @@ public class CardManager extends ItemManager<PaperCard> {
GuiUtils.addSeparator(menu); //separate from current search item
JMenu fmt = GuiUtils.createMenu("Format");
for (final GameFormat f : FModel.getFormats().getOrderedList()) {
for (final GameFormat f : FModel.getFormats().getFilterList()) {
GuiUtils.addMenuItem(fmt, f.getName(), null, new Runnable() {
@Override
public void run() {
@@ -92,6 +95,27 @@ public class CardManager extends ItemManager<PaperCard> {
}
menu.add(fmt);
GuiUtils.addMenuItem(menu, "Formats...", null, new Runnable() {
@Override public void run() {
final CardSetFilter existingFilter = itemManager.getFilter(CardSetFilter.class);
if (existingFilter != null) {
existingFilter.edit();
} else {
final DialogChooseFormats dialog = new DialogChooseFormats();
dialog.setOkCallback(new Runnable() {
@Override public void run() {
final List<GameFormat> formats = dialog.getSelectedFormats();
if (!formats.isEmpty()) {
for(GameFormat format: formats) {
itemManager.addFilter(new CardFormatFilter(itemManager, format));
}
}
}
});
}
}
});
GuiUtils.addMenuItem(menu, "Sets...", null, new Runnable() {
@Override
public void run() {

View File

@@ -4,18 +4,15 @@ import java.awt.Component;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.util.HashMap;
import java.util.TreeSet;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import java.util.SortedSet;
import javax.swing.JMenu;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import forge.screens.home.quest.DialogChooseFormats;
import org.apache.commons.lang3.StringUtils;
import forge.Singletons;
@@ -176,7 +173,7 @@ public final class DeckManager extends ItemManager<DeckProxy> implements IHasGam
menu.add(folder);
final JMenu fmt = GuiUtils.createMenu("Format");
for (final GameFormat f : FModel.getFormats().getOrderedList()) {
for (final GameFormat f : FModel.getFormats().getFilterList()) {
GuiUtils.addMenuItem(fmt, f.getName(), null, new Runnable() {
@Override
public void run() {
@@ -186,6 +183,29 @@ public final class DeckManager extends ItemManager<DeckProxy> implements IHasGam
}
menu.add(fmt);
GuiUtils.addMenuItem(menu, "Formats...", null, new Runnable() {
@Override public void run() {
final DeckFormatFilter existingFilter = getFilter(DeckFormatFilter.class);
if (existingFilter != null) {
existingFilter.edit();
} else {
final DialogChooseFormats dialog = new DialogChooseFormats();
dialog.setOkCallback(new Runnable() {
@Override public void run() {
final List<GameFormat> formats = dialog.getSelectedFormats();
if (!formats.isEmpty()) {
for(GameFormat format: formats) {
addFilter(new DeckFormatFilter(DeckManager.this, format));
}
}
}
});
}
}
});
GuiUtils.addMenuItem(menu, "Sets...", null, new Runnable() {
@Override public void run() {
final DeckSetFilter existingFilter = getFilter(DeckSetFilter.class);

View File

@@ -6,6 +6,7 @@ import forge.game.GameFormat;
import forge.deck.DeckProxy;
import forge.itemmanager.ItemManager;
import forge.itemmanager.SFilterUtil;
import forge.screens.home.quest.DialogChooseFormats;
public class DeckFormatFilter extends FormatFilter<DeckProxy> {
@@ -27,4 +28,16 @@ public class DeckFormatFilter extends FormatFilter<DeckProxy> {
protected final Predicate<DeckProxy> buildPredicate() {
return DeckProxy.createPredicate(SFilterUtil.buildFormatFilter(this.formats, this.allowReprints));
}
public void edit() {
final DialogChooseFormats dialog = new DialogChooseFormats(this.formats);
dialog.setOkCallback(new Runnable() {
@Override
public void run() {
allowReprints = dialog.getWantReprints();
formats.clear();
formats.addAll(dialog.getSelectedFormats());
}
});
}
}

View File

@@ -27,6 +27,7 @@ public abstract class FormatFilter<T extends InventoryItem> extends ListLabelFil
protected String getTooltip() {
Set<String> sets = new HashSet<String>();
Set<String> bannedCards = new HashSet<String>();
Set<String> additionalCards = new HashSet<>();
for (GameFormat format : this.formats) {
List<String> formatSets = format.getAllowedSetCodes();
@@ -37,6 +38,10 @@ public abstract class FormatFilter<T extends InventoryItem> extends ListLabelFil
if (formatBannedCards != null) {
bannedCards.addAll(formatBannedCards);
}
List<String> formatAdditionalCards = format.getAdditionalCards();
if (formatAdditionalCards != null) {
additionalCards.addAll(formatAdditionalCards);
}
}
//use HTML tooltips so we can insert line breaks
@@ -58,7 +63,9 @@ public abstract class FormatFilter<T extends InventoryItem> extends ListLabelFil
}
CardEdition edition = editions.get(code);
tooltip.append(" ").append(edition.getName()).append(" (").append(code).append("),");
if(edition!=null) {
tooltip.append(" ").append(edition.getName()).append(" (").append(code).append("),");
}
lineLen = tooltip.length() - lastLen;
}
@@ -90,6 +97,27 @@ public abstract class FormatFilter<T extends InventoryItem> extends ListLabelFil
// chop off last semicolon
tooltip.delete(tooltip.length() - 1, tooltip.length());
}
if (!additionalCards.isEmpty()) {
tooltip.append("<br><br>Additional:");
lastLen += lineLen;
lineLen = 0;
for (String cardName : additionalCards) {
// don't let a single line get too long
if (50 < lineLen) {
tooltip.append("<br>");
lastLen += lineLen;
lineLen = 0;
}
tooltip.append(" ").append(cardName).append(";");
lineLen = tooltip.length() - lastLen;
}
// chop off last semicolon
tooltip.delete(tooltip.length() - 1, tooltip.length());
}
tooltip.append("</html>");
return tooltip.toString();
}

View File

@@ -90,6 +90,24 @@ public enum CSubmenuQuestData implements ICDoc {
}
});
view.getBtnSelectFormat().setCommand(new UiCommand() {
@Override
public void run() {
final DialogChooseFormats dialog = new DialogChooseFormats();
dialog.setOkCallback(new Runnable() {
@Override
public void run() {
customFormatCodes.clear();
Set<String> sets = new HashSet<String>();
for(GameFormat format:dialog.getSelectedFormats()){
sets.addAll(format.getAllowedSetCodes());
}
customFormatCodes.addAll(sets);
}
});
}
});
view.getBtnPrizeCustomFormat().setCommand(new UiCommand() {
@Override
public void run() {
@@ -104,6 +122,24 @@ public enum CSubmenuQuestData implements ICDoc {
}
});
view.getBtnPrizeSelectFormat().setCommand(new UiCommand() {
@Override
public void run() {
final DialogChooseFormats dialog = new DialogChooseFormats();
dialog.setOkCallback(new Runnable() {
@Override
public void run() {
customPrizeFormatCodes.clear();
Set<String> sets = new HashSet<String>();
for(GameFormat format:dialog.getSelectedFormats()){
sets.addAll(format.getAllowedSetCodes());
}
customPrizeFormatCodes.addAll(sets);
}
});
}
});
view.getBtnPreferredColors().setCommand(new UiCommand() {
@Override
public void run() {
@@ -197,10 +233,11 @@ public enum CSubmenuQuestData implements ICDoc {
if (worldFormat == null) {
switch(view.getStartingPoolType()) {
case Rotating:
case Sanctioned:
fmtStartPool = view.getRotatingFormat();
break;
case Casual:
case CustomFormat:
if (customFormatCodes.isEmpty()) {
if (!FOptionPane.showConfirmDialog("You have defined a custom format that doesn't contain any sets.\nThis will start a game without restriction.\n\nContinue?")) {
@@ -257,6 +294,7 @@ public enum CSubmenuQuestData implements ICDoc {
case Complete:
fmtPrizes = null;
break;
case Casual:
case CustomFormat:
if (customPrizeFormatCodes.isEmpty()) {
if (!FOptionPane.showConfirmDialog("You have defined custom format as containing no sets.\nThis will choose all editions without restriction as prizes.\n\nContinue?")) {
@@ -265,7 +303,7 @@ public enum CSubmenuQuestData implements ICDoc {
}
fmtPrizes = customPrizeFormatCodes.isEmpty() ? null : new GameFormat("Custom Prizes", customPrizeFormatCodes, null); // chosen sets and no banned cards
break;
case Rotating:
case Sanctioned:
fmtPrizes = view.getPrizedRotatingFormat();
break;
default:

View File

@@ -0,0 +1,160 @@
package forge.screens.home.quest;
import forge.assets.FSkinProp;
import forge.card.CardEdition;
import forge.game.GameFormat;
import forge.gui.SOverlayUtils;
import forge.model.FModel;
import forge.toolbox.*;
import forge.util.TextUtil;
import net.miginfocom.swing.MigLayout;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
public class DialogChooseFormats {
private List<GameFormat> selectedFormats = new ArrayList<>() ;
private boolean wantReprints = true;
private Runnable okCallback;
private final List<FCheckBox> choices = new ArrayList<>();
private final FCheckBox cbWantReprints = new FCheckBox("Allow compatible reprints from other sets");
public DialogChooseFormats(){
this(null);
}
public DialogChooseFormats(Set<GameFormat> preselectedFormats) {
List<FCheckBox> sanctioned = new ArrayList<>();
List<FCheckBox> casual = new ArrayList<>();
List<FCheckBox> historic = new ArrayList<>();
for (GameFormat format : FModel.getFormats().getOrderedList()){
FCheckBox box = new FCheckBox(format.getName());
box.setName(format.getName());
switch (format.getFormatType()){
case Sanctioned:
sanctioned.add(box);
break;
case Historic:
historic.add(box);
break;
case Custom:
case Casual:
case Digital:
default:
casual.add(box);
break;
}
box.setSelected(null != preselectedFormats && preselectedFormats.contains(format));
}
FPanel panel = new FPanel(new MigLayout("insets 0, gap 0, center, wrap 3"));
panel.setOpaque(false);
panel.setBackgroundTexture(FSkin.getIcon(FSkinProp.BG_TEXTURE));
panel.add(new FLabel.Builder().text("Choose formats").fontSize(18).build(), "center, span, wrap, gaptop 10");
String constraints = "aligny top";
panel.add(makeCheckBoxList(sanctioned, "Sanctioned", true), constraints);
panel.add(makeCheckBoxList(casual, "Other", false), constraints);
panel.add(makeCheckBoxList(historic, "Historic", false), constraints);
final JPanel overlay = FOverlay.SINGLETON_INSTANCE.getPanel();
overlay.setLayout(new MigLayout("insets 0, gap 0, wrap, ax center, ay center"));
final Runnable cleanup = new Runnable() {
@Override
public void run() {
SOverlayUtils.hideOverlay();
}
};
FButton btnOk = new FButton("OK");
btnOk.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
cleanup.run();
handleOk();
}
});
FButton btnCancel = new FButton("Cancel");
btnCancel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
cleanup.run();
}
});
JPanel southPanel = new JPanel(new MigLayout("insets 10, gap 20, ax center"));
southPanel.setOpaque(false);
southPanel.add(cbWantReprints, "center, span, wrap");
southPanel.add(btnOk, "center, w 40%, h 20!");
southPanel.add(btnCancel, "center, w 40%, h 20!");
panel.add(southPanel, "dock south, gapBottom 10");
overlay.add(panel);
panel.getRootPane().setDefaultButton(btnOk);
SOverlayUtils.showOverlay();
}
public void setOkCallback(Runnable onOk) {
okCallback = onOk;
}
public List<GameFormat> getSelectedFormats() {
return selectedFormats;
}
public boolean getWantReprints() {
return wantReprints;
}
private JPanel makeCheckBoxList(List<FCheckBox> formats, String title, boolean focused) {
choices.addAll(formats);
final FCheckBoxList<FCheckBox> cbl = new FCheckBoxList<>(false);
cbl.setListData(formats.toArray(new FCheckBox[formats.size()]));
cbl.setVisibleRowCount(Math.min(20, formats.size()));
if (focused) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
cbl.requestFocusInWindow();
}
});
}
JPanel pnl = new JPanel(new MigLayout("center, wrap"));
pnl.setOpaque(false);
pnl.add(new FLabel.Builder().text(title).build());
pnl.add(new FScrollPane(cbl, true));
return pnl;
}
private void handleOk() {
for (FCheckBox box : choices) {
if (box.isSelected()) {
selectedFormats.add(FModel.getFormats().getFormat(box.getName()));
}
wantReprints = cbWantReprints.isSelected();
}
if (null != okCallback) {
okCallback.run();
}
}
}

View File

@@ -82,6 +82,8 @@ public enum VSubmenuQuestData implements IVSubmenu<CSubmenuQuestData> {
private final FComboBoxWrapper<Deck> cbxCustomDeck = new FComboBoxWrapper<>();
private final FLabel btnDefineCustomFormat = new FLabel.Builder().opaque(true).hoverable(true).text("Define custom format").build();
private final FLabel btnSelectFormat = new FLabel.Builder().opaque(true).hoverable(true).text("Select format").build();
private final FCheckBox boxCompleteSet = new FCheckBox("Start with all cards in selected sets");
private final FCheckBox boxAllowDuplicates = new FCheckBox("Allow duplicate cards");
@@ -91,6 +93,8 @@ public enum VSubmenuQuestData implements IVSubmenu<CSubmenuQuestData> {
private final FLabel btnPrizeDefineCustomFormat = new FLabel.Builder().opaque(true).hoverable(true).text("Define custom format").build();
private final FLabel btnPrizeSelectFormat = new FLabel.Builder().opaque(true).hoverable(true).text("Select format").build();
private final FLabel lblPrizedCards = new FLabel.Builder().text("Prized cards:").build();
private final FComboBoxWrapper<Object> cbxPrizedCards = new FComboBoxWrapper<>();
@@ -116,10 +120,11 @@ public enum VSubmenuQuestData implements IVSubmenu<CSubmenuQuestData> {
lblPreconDeck.setVisible(newVal == StartingPoolType.Precon);
cbxPreconDeck.setVisible(newVal == StartingPoolType.Precon);
lblFormat.setVisible(newVal == StartingPoolType.Rotating);
cbxFormat.setVisible(newVal == StartingPoolType.Rotating);
lblFormat.setVisible(newVal == StartingPoolType.Sanctioned);
cbxFormat.setVisible(newVal == StartingPoolType.Sanctioned);
btnDefineCustomFormat.setVisible(newVal == StartingPoolType.CustomFormat);
btnSelectFormat.setVisible(newVal == StartingPoolType.Casual);
final boolean usesDeckList = newVal == StartingPoolType.SealedDeck || newVal == StartingPoolType.DraftDeck || newVal == StartingPoolType.Cube;
@@ -152,9 +157,10 @@ public enum VSubmenuQuestData implements IVSubmenu<CSubmenuQuestData> {
lblPrizeUnrestricted.setVisible(newVal == StartingPoolType.Complete);
cboAllowUnlocks.setVisible(newVal != StartingPoolType.Complete);
lblPrizeFormat.setVisible(newVal == StartingPoolType.Rotating);
cbxPrizeFormat.setVisible(newVal == StartingPoolType.Rotating);
lblPrizeFormat.setVisible(newVal == StartingPoolType.Sanctioned);
cbxPrizeFormat.setVisible(newVal == StartingPoolType.Sanctioned);
btnPrizeDefineCustomFormat.setVisible(newVal == StartingPoolType.CustomFormat);
btnPrizeSelectFormat.setVisible(newVal == StartingPoolType.Casual);
lblPrizeSameAsStarting.setVisible(newVal == null);
}
};
@@ -200,7 +206,8 @@ public enum VSubmenuQuestData implements IVSubmenu<CSubmenuQuestData> {
boxAllowDuplicates.setToolTipText("When your starting pool is generated, duplicates of cards may be included.");
cbxStartingPool.addItem(StartingPoolType.Complete);
cbxStartingPool.addItem(StartingPoolType.Rotating);
cbxStartingPool.addItem(StartingPoolType.Sanctioned);
cbxStartingPool.addItem(StartingPoolType.Casual);
cbxStartingPool.addItem(StartingPoolType.CustomFormat);
cbxStartingPool.addItem(StartingPoolType.Precon);
cbxStartingPool.addItem(StartingPoolType.DraftDeck);
@@ -214,11 +221,12 @@ public enum VSubmenuQuestData implements IVSubmenu<CSubmenuQuestData> {
cbxPrizedCards.addItem("Same as starting pool");
cbxPrizedCards.addItem(StartingPoolType.Complete);
cbxPrizedCards.addItem(StartingPoolType.Rotating);
cbxPrizedCards.addItem(StartingPoolType.Sanctioned);
cbxPrizedCards.addItem(StartingPoolType.Casual);
cbxPrizedCards.addItem(StartingPoolType.CustomFormat);
cbxPrizedCards.addActionListener(alPrizesPool);
for (final GameFormat gf : FModel.getFormats().getOrderedList()) {
for (final GameFormat gf : FModel.getFormats().getSanctionedList()) {
cbxFormat.addItem(gf);
cbxPrizeFormat.addItem(gf);
}
@@ -311,6 +319,7 @@ public enum VSubmenuQuestData implements IVSubmenu<CSubmenuQuestData> {
cbxFormat.addTo(pnlRestrictions, constraints + cboWidthStart + " cell 1 1");
pnlRestrictions.add(btnDefineCustomFormat, btnStartingCustomFormatWidth + constraints + hidemode + " cell 1 1");
pnlRestrictions.add(btnSelectFormat, btnStartingCustomFormatWidth + constraints + hidemode + " cell 1 1");
pnlRestrictions.add(boxAllowDuplicates, "h 15px!, cell 1 2");
pnlRestrictions.add(boxCompleteSet, "h 15px!, cell 1 3");
@@ -325,6 +334,7 @@ public enum VSubmenuQuestData implements IVSubmenu<CSubmenuQuestData> {
pnlRestrictions.add(lblPrizeFormat, constraints + hidemode + "cell 0 6");
cbxPrizeFormat.addTo(pnlRestrictions, constraints + cboWidthStart + "cell 1 6"); // , skip 1
pnlRestrictions.add(btnPrizeDefineCustomFormat, btnStartingCustomFormatWidth + constraints + hidemode + "cell 1 6");
pnlRestrictions.add(btnPrizeSelectFormat, btnStartingCustomFormatWidth + constraints + hidemode + "cell 1 6");
pnlRestrictions.add(lblPrizeSameAsStarting, constraints + hidemode + "cell 1 6");
pnlRestrictions.add(lblPrizeUnrestricted, constraints + hidemode + "cell 1 6");
@@ -498,9 +508,23 @@ public enum VSubmenuQuestData implements IVSubmenu<CSubmenuQuestData> {
return cbxPrizeFormat.getSelectedItem();
}
public GameFormat getCasualFormat() {
return cbxFormat.getSelectedItem();
}
public GameFormat getPrizedCasualFormat() {
return cbxPrizeFormat.getSelectedItem();
}
public FLabel getBtnCustomFormat() {
return btnDefineCustomFormat;
}
public FLabel getBtnSelectFormat() {
return btnSelectFormat;
}
public FLabel getBtnPrizeSelectFormat() {
return btnPrizeSelectFormat;
}
public FLabel getBtnPrizeCustomFormat() {
return btnPrizeDefineCustomFormat;
}

View File

@@ -134,6 +134,9 @@ public enum CSubmenuPreferences implements ICDoc {
lstControls.add(Pair.of(view.getCbLoadCardsLazily(), FPref.LOAD_CARD_SCRIPTS_LAZILY));
lstControls.add(Pair.of(view.getCbLoadHistoricFormats(), FPref.LOAD_HISTORIC_FORMATS));
for(final Pair<JCheckBox, FPref> kv : lstControls) {
kv.getKey().addItemListener(new ItemListener() {
@Override

View File

@@ -65,6 +65,7 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
private final JCheckBox cbManaLostPrompt = new OptionsCheckBox("Prompt Mana Pool Emptying");
private final JCheckBox cbDevMode = new OptionsCheckBox("Developer Mode");
private final JCheckBox cbLoadCardsLazily = new OptionsCheckBox("Load Card Scripts Lazily");
private final JCheckBox cbLoadHistoricFormats = new OptionsCheckBox("Load Historic Formats");
private final JCheckBox cbWorkshopSyntax = new OptionsCheckBox("Workshop Syntax Checker");
private final JCheckBox cbEnforceDeckLegality = new OptionsCheckBox("Deck Conformance");
private final JCheckBox cbImageFetcher = new OptionsCheckBox("Automatically Download Missing Card Art");
@@ -239,6 +240,9 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
pnlPrefs.add(cbLoadCardsLazily, titleConstraints);
pnlPrefs.add(new NoteLabel("If turned on, Forge will load card scripts as they're needed instead of at start up. (Warning: Experimental)"), descriptionConstraints);
pnlPrefs.add(cbLoadHistoricFormats, titleConstraints);
pnlPrefs.add(new NoteLabel("If turned on, Forge will load all historic format definitions, this may take slightly longer to load at startup."), descriptionConstraints);
// Graphic Options
pnlPrefs.add(new SectionLabel("Graphic Options"), sectionConstraints + ", gaptop 2%");
@@ -586,6 +590,11 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
return cbLoadCardsLazily;
}
/** @return {@link javax.swing.JCheckBox} */
public JCheckBox getCbLoadHistoricFormats() {
return cbLoadHistoricFormats;
}
public JCheckBox getCbWorkshopSyntax() {
return cbWorkshopSyntax;
}

View File

@@ -22,11 +22,7 @@ import forge.util.Callback;
import forge.util.TextUtil;
import forge.util.Utils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;
import com.badlogic.gdx.graphics.g2d.BitmapFont.HAlignment;
@@ -42,9 +38,10 @@ public abstract class FormatFilter<T extends InventoryItem> extends ItemFilter<T
cbxFormats.setFont(FSkinFont.get(12));
cbxFormats.addItem("All Sets/Formats");
for (GameFormat format : FModel.getFormats().getOrderedList()) {
for (GameFormat format : FModel.getFormats().getFilterList()) {
cbxFormats.addItem(format);
}
cbxFormats.addItem("Other Formats...");
cbxFormats.addItem("Choose Sets...");
selectedFormat = cbxFormats.getText();
@@ -61,6 +58,21 @@ public abstract class FormatFilter<T extends InventoryItem> extends ItemFilter<T
format = null;
applyChange();
}
else if (index == cbxFormats.getItemCount() - 2) {
preventHandling = true;
cbxFormats.setText(selectedFormat); //restore previous selection by default
preventHandling = false;
HistoricFormatSelect historicFormatSelect = new HistoricFormatSelect();
historicFormatSelect.setOnCloseCallBack(new Runnable(){
@Override
public void run() {
format = historicFormatSelect.getSelectedFormat();
cbxFormats.setText(format.getName());
applyChange();
}
});
Forge.openScreen(historicFormatSelect);
}
else if (index == cbxFormats.getItemCount() - 1) {
preventHandling = true;
cbxFormats.setText(selectedFormat); //restore previous selection by default

View File

@@ -0,0 +1,141 @@
package forge.itemmanager.filters;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import forge.Forge;
import forge.Graphics;
import forge.assets.FSkinColor;
import forge.assets.FSkinFont;
import forge.game.GameFormat;
import forge.model.FModel;
import forge.screens.FScreen;
import forge.screens.settings.SettingsScreen;
import forge.toolbox.FGroupList;
import forge.toolbox.FList;
import forge.util.Callback;
import forge.util.Utils;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
* Created by maustin on 16/04/2018.
*/
public class HistoricFormatSelect extends FScreen {
private GameFormat selectedFormat;
private final FGroupList<GameFormat> lstFormats = add(new FGroupList<GameFormat>());
private final Set<GameFormat.FormatSubType> historicSubTypes = new HashSet<>(Arrays.asList(GameFormat.FormatSubType.Block,
GameFormat.FormatSubType.Standard,GameFormat.FormatSubType.Extended,GameFormat.FormatSubType.Modern,
GameFormat.FormatSubType.Legacy, GameFormat.FormatSubType.Vintage));
private Runnable onCloseCallBack;
public HistoricFormatSelect() {
super("Choose Format");
for (GameFormat.FormatType group:GameFormat.FormatType.values()){
if (group == GameFormat.FormatType.Historic){
for (GameFormat.FormatSubType subgroup:GameFormat.FormatSubType.values()){
if (historicSubTypes.contains(subgroup)){
lstFormats.addGroup(group.name() + "-" + subgroup.name());
}
}
}else {
lstFormats.addGroup(group.name());
}
}
for (GameFormat format: FModel.getFormats().getOrderedList()){
switch(format.getFormatType()){
case Sanctioned:
lstFormats.addItem(format, 0);
break;
case Casual:
lstFormats.addItem(format, 1);
break;
case Historic:
switch (format.getFormatSubType()){
case Block:
lstFormats.addItem(format, 2);
break;
case Standard:
lstFormats.addItem(format, 3);
break;
case Extended:
lstFormats.addItem(format, 4);
break;
case Modern:
lstFormats.addItem(format, 5);
break;
case Legacy:
lstFormats.addItem(format, 6);
break;
case Vintage:
lstFormats.addItem(format, 7);
break;
}
break;
case Digital:
lstFormats.addItem(format, 8);
break;
case Custom:
lstFormats.addItem(format, 9);
}
}
lstFormats.setListItemRenderer(new FormatRenderer());
}
public GameFormat getSelectedFormat() {
return selectedFormat;
}
public void setOnCloseCallBack(Runnable onCloseCallBack) {
this.onCloseCallBack = onCloseCallBack;
}
@Override
public void onClose(Callback<Boolean> canCloseCallback) {
if (selectedFormat != null) {
if (onCloseCallBack != null) {
onCloseCallBack.run();
}
}
super.onClose(canCloseCallback);
}
@Override
protected void doLayout(float startY, float width, float height) {
lstFormats.setBounds(0, startY, width, height - startY);
}
private class FormatRenderer extends FList.ListItemRenderer<GameFormat>{
@Override
public float getItemHeight() {
return Utils.AVG_FINGER_HEIGHT;
}
@Override
public boolean tap(Integer index, GameFormat value, float x, float y, int count) {
selectedFormat=value;
Forge.back();
return true;
}
@Override
public void drawValue(Graphics g, Integer index, GameFormat value, FSkinFont font, FSkinColor foreColor, FSkinColor backColor, boolean pressed, float x, float y, float w, float h) {
float offset = SettingsScreen.getInsets(w) - FList.PADDING; //increase padding for settings items
x += offset;
y += offset;
w -= 2 * offset;
h -= 2 * offset;
float textHeight = h;
h *= 0.66f;
g.drawText(value.toString(), font, foreColor, x, y, w - h - FList.PADDING, textHeight, false, BitmapFont.HAlignment.LEFT, true);
x += w - h;
y += (textHeight - h) / 2;
}
}
}

View File

@@ -3,6 +3,7 @@ package forge.screens.quest;
import com.badlogic.gdx.graphics.g2d.BitmapFont.HAlignment;
import forge.FThreads;
import forge.Forge;
import forge.UiCommand;
import forge.assets.FSkinFont;
import forge.assets.FSkinImage;
@@ -13,6 +14,7 @@ import forge.deck.DeckSection;
import forge.game.GameFormat;
import forge.item.PaperCard;
import forge.item.PreconDeck;
import forge.itemmanager.filters.HistoricFormatSelect;
import forge.model.CardCollections;
import forge.model.FModel;
import forge.properties.ForgeConstants;
@@ -123,13 +125,13 @@ public class NewQuestScreen extends FScreen {
private final FLabel lblPreconDeck = scroller.add(new FLabel.Builder().text("Starter/Event deck:").build());
private final FComboBox<String> cbxPreconDeck = scroller.add(new FComboBox<String>());
private final FLabel lblFormat = scroller.add(new FLabel.Builder().text("Sanctioned format:").build());
private final FLabel lblFormat = scroller.add(new FLabel.Builder().text("Select format:").build());
private final FComboBox<GameFormat> cbxFormat = scroller.add(new FComboBox<GameFormat>());
private final FLabel lblCustomDeck = scroller.add(new FLabel.Builder().text("Custom deck:").build());
private final FComboBox<Deck> cbxCustomDeck = scroller.add(new FComboBox<Deck>());
private final FLabel btnDefineCustomFormat = scroller.add(new FLabel.ButtonBuilder().text("Define custom format").build());
private final FLabel btnSelectFormat = scroller.add(new FLabel.ButtonBuilder().text("Choose format").build());
private final FLabel lblPoolDistribution = scroller.add(new FLabel.Builder().text("Starting pool distribution:").build());
private final FRadioButton radBalanced = scroller.add(new FRadioButton("Balanced"));
@@ -155,12 +157,12 @@ public class NewQuestScreen extends FScreen {
private final FLabel lblPrizedCards = scroller.add(new FLabel.Builder().text("Prized cards:").build());
private final FComboBox<Object> cbxPrizedCards = scroller.add(new FComboBox<>());
private final FLabel lblPrizeFormat = scroller.add(new FLabel.Builder().text("Sanctioned format:").build());
private final FLabel lblPrizeFormat = scroller.add(new FLabel.Builder().text("Defined format:").build());
private final FComboBox<GameFormat> cbxPrizeFormat = scroller.add(new FComboBox<GameFormat>());
private final FLabel lblPrizeUnrestricted = scroller.add(new FLabel.Builder().align(HAlignment.RIGHT).font(FSkinFont.get(12)).text("All cards will be available to win.").build());
private final FLabel lblPrizeSameAsStarting = scroller.add(new FLabel.Builder().align(HAlignment.RIGHT).font(FSkinFont.get(12)).text("Only sets found in starting pool will be available.").build());
private final FLabel btnPrizeDefineCustomFormat = scroller.add(new FLabel.ButtonBuilder().text("Define custom format").build());
private final FLabel btnPrizeSelectFormat = scroller.add(new FLabel.ButtonBuilder().text("Choose format").build());
private final FCheckBox cbAllowUnlocks = scroller.add(new FCheckBox("Allow unlock of additional editions"));
private final FCheckBox cbFantasy = scroller.add(new FCheckBox("Fantasy Mode"));
@@ -183,8 +185,8 @@ public class NewQuestScreen extends FScreen {
super(null, NewGameMenu.getMenu());
cbxStartingPool.addItem(StartingPoolType.Complete);
cbxStartingPool.addItem(StartingPoolType.Rotating);
cbxStartingPool.addItem(StartingPoolType.CustomFormat);
cbxStartingPool.addItem(StartingPoolType.Sanctioned);
cbxStartingPool.addItem(StartingPoolType.Casual);
cbxStartingPool.addItem(StartingPoolType.Precon);
cbxStartingPool.addItem(StartingPoolType.DraftDeck);
cbxStartingPool.addItem(StartingPoolType.SealedDeck);
@@ -199,8 +201,8 @@ public class NewQuestScreen extends FScreen {
cbxPrizedCards.addItem("Same as starting pool");
cbxPrizedCards.addItem(StartingPoolType.Complete);
cbxPrizedCards.addItem(StartingPoolType.Rotating);
cbxPrizedCards.addItem(StartingPoolType.CustomFormat);
cbxPrizedCards.addItem(StartingPoolType.Sanctioned);
cbxPrizedCards.addItem(StartingPoolType.Casual);
cbxPrizedCards.setChangedHandler(new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
@@ -209,7 +211,7 @@ public class NewQuestScreen extends FScreen {
}
});
for (GameFormat gf : FModel.getFormats().getOrderedList()) {
for (GameFormat gf : FModel.getFormats().getSanctionedList()) {
cbxFormat.addItem(gf);
cbxPrizeFormat.addItem(gf);
}
@@ -275,10 +277,6 @@ public class NewQuestScreen extends FScreen {
preconDescriptions.put(name, description);
}
//TODO: Support defining custom format
btnDefineCustomFormat.setEnabled(false);
btnPrizeDefineCustomFormat.setEnabled(false);
// disable the very powerful sets -- they can be unlocked later for a high price
final List<String> unselectableSets = new ArrayList<>();
unselectableSets.add("LEA");
@@ -288,31 +286,45 @@ public class NewQuestScreen extends FScreen {
unselectableSets.add("ARC");
unselectableSets.add("PC2");
btnDefineCustomFormat.setCommand(new FEventHandler() {
btnSelectFormat.setCommand(new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
/*final DialogChooseSets dialog = new DialogChooseSets(customFormatCodes, unselectableSets, false);
dialog.setOkCallback(new Runnable() {
HistoricFormatSelect historicFormatSelect = new HistoricFormatSelect();
historicFormatSelect.setOnCloseCallBack(new Runnable() {
@Override
public void run() {
customFormatCodes.clear();
customFormatCodes.addAll(dialog.getSelectedSets());
btnSelectFormat.setText(historicFormatSelect.getSelectedFormat().getName());
List<String> setsToAdd = historicFormatSelect.getSelectedFormat().getAllowedSetCodes();
for (String setName:setsToAdd){
if(!unselectableSets.contains(setName)){
customFormatCodes.add(setName);
}
}
}
});*/
});
Forge.openScreen(historicFormatSelect);
}
});
btnPrizeDefineCustomFormat.setCommand(new FEventHandler() {
btnPrizeSelectFormat.setCommand(new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
/*final DialogChooseSets dialog = new DialogChooseSets(customPrizeFormatCodes, unselectableSets, false);
dialog.setOkCallback(new Runnable() {
HistoricFormatSelect historicFormatSelect = new HistoricFormatSelect();
historicFormatSelect.setOnCloseCallBack(new Runnable() {
@Override
public void run() {
customPrizeFormatCodes.clear();
customPrizeFormatCodes.addAll(dialog.getSelectedSets());
btnPrizeSelectFormat.setText(historicFormatSelect.getSelectedFormat().getName());
List<String> setsToAdd = historicFormatSelect.getSelectedFormat().getAllowedSetCodes();
for (String setName:setsToAdd){
if(!unselectableSets.contains(setName)){
customPrizeFormatCodes.add(setName);
}
}
}
});*/
});
Forge.openScreen(historicFormatSelect);
}
});
@@ -329,10 +341,10 @@ public class NewQuestScreen extends FScreen {
lblPreconDeck.setVisible(newVal == StartingPoolType.Precon);
cbxPreconDeck.setVisible(newVal == StartingPoolType.Precon);
lblFormat.setVisible(newVal == StartingPoolType.Rotating);
cbxFormat.setVisible(newVal == StartingPoolType.Rotating);
lblFormat.setVisible(newVal == StartingPoolType.Sanctioned);
cbxFormat.setVisible(newVal == StartingPoolType.Sanctioned);
btnDefineCustomFormat.setVisible(newVal == StartingPoolType.CustomFormat);
btnSelectFormat.setVisible(newVal == StartingPoolType.Casual);
boolean usesDeckList = newVal == StartingPoolType.SealedDeck || newVal == StartingPoolType.DraftDeck || newVal == StartingPoolType.Cube;
lblCustomDeck.setVisible(usesDeckList);
@@ -368,9 +380,9 @@ public class NewQuestScreen extends FScreen {
lblPrizeUnrestricted.setVisible(newVal == StartingPoolType.Complete);
cbAllowUnlocks.setVisible(newVal != StartingPoolType.Complete);
lblPrizeFormat.setVisible(newVal == StartingPoolType.Rotating);
cbxPrizeFormat.setVisible(newVal == StartingPoolType.Rotating);
btnPrizeDefineCustomFormat.setVisible(newVal == StartingPoolType.CustomFormat);
lblPrizeFormat.setVisible(newVal == StartingPoolType.Sanctioned);
cbxPrizeFormat.setVisible(newVal == StartingPoolType.Sanctioned);
btnPrizeSelectFormat.setVisible(newVal == StartingPoolType.Casual);
lblPrizeSameAsStarting.setVisible(newVal == null);
scroller.revalidate();
@@ -385,6 +397,8 @@ public class NewQuestScreen extends FScreen {
cbxStartingPool.setEnabled(qw.getFormat() == null);
cbxFormat.setEnabled(qw.getFormat() == null);
cbxCustomDeck.setEnabled(qw.getFormat() == null);
btnSelectFormat.setEnabled(qw.getFormat() == null);
// Do NOT disable the following...
// cbxPrizeFormat.setEnabled(qw.getFormat() == null);
// cboAllowUnlocks.setEnabled(qw.getFormat() == null);
@@ -478,7 +492,7 @@ public class NewQuestScreen extends FScreen {
}
public GameFormat getRotatingFormat() {
public GameFormat getSanctionedFormat() {
return cbxFormat.getSelectedItem();
}
@@ -503,10 +517,11 @@ public class NewQuestScreen extends FScreen {
if (worldFormat == null) {
switch(getStartingPoolType()) {
case Rotating:
fmtStartPool = getRotatingFormat();
case Sanctioned:
fmtStartPool = getSanctionedFormat();
break;
case Casual:
case CustomFormat:
if (customFormatCodes.isEmpty()) {
if (!SOptionPane.showConfirmDialog(
@@ -567,6 +582,7 @@ public class NewQuestScreen extends FScreen {
case Complete:
fmtPrizes = null;
break;
case Casual:
case CustomFormat:
if (customPrizeFormatCodes.isEmpty()) {
if (!SOptionPane.showConfirmDialog(
@@ -576,7 +592,7 @@ public class NewQuestScreen extends FScreen {
}
fmtPrizes = customPrizeFormatCodes.isEmpty() ? null : new GameFormat("Custom Prizes", customPrizeFormatCodes, null); // chosen sets and no banned cards
break;
case Rotating:
case Sanctioned:
fmtPrizes = getPrizedRotatingFormat();
break;
default:

View File

@@ -187,6 +187,9 @@ public class SettingsPage extends TabPage<SettingsScreen> {
lstSettings.addItem(new BooleanSetting(FPref.LOAD_CARD_SCRIPTS_LAZILY,
"Load Card Scripts Lazily",
"If turned on, Forge will load card scripts as they're needed instead of at start up. (Warning: Experimental)"), 3);
lstSettings.addItem(new BooleanSetting(FPref.LOAD_HISTORIC_FORMATS,
"Load Historic Formats",
"If turned on, Forge will load all historic format definitions, this may take slightly longer to load at startup."), 3);
//Graphic Options
lstSettings.addItem(new BooleanSetting(FPref.UI_OVERLAY_FOIL_EFFECT,

View File

@@ -0,0 +1,6 @@
[format]
Name:Amonkhet Block
Type:Historic
Subtype:Block
Order:112
Sets:HOU, AKH

View File

@@ -0,0 +1,6 @@
[format]
Name:Battle for Zendikar Block
Type:Historic
Subtype:Block
Order:115
Sets:OGW, BFZ

View File

@@ -0,0 +1,7 @@
[format]
Name:Ice Age Block
Type:Historic
Subtype:Block
Order:135
Sets:CSP, ALL, ICE
Banned:Amulet of Quoz; Thawing Glaciers; Zuran Orb

View File

@@ -0,0 +1,7 @@
[format]
Name:Innistrad-Avacyn Restored Block
Type:Historic
Subtype:Block
Order:119
Sets:ISD, AVR, DKA
Banned:Intangible Virtue; Lingering Souls

View File

@@ -0,0 +1,6 @@
[format]
Name:Invasion Block
Type:Historic
Subtype:Block
Order:130
Sets:APC, PLS, INV

View File

@@ -0,0 +1,6 @@
[format]
Name:Ixalan Block
Type:Historic
Subtype:Block
Order:111
Sets:XLN, RIX

View File

@@ -1,5 +1,6 @@
[format]
Name:Kaladesh Block
Type:Historic
Order:109
Sets:KLD, AER
Subtype:Block
Order:113
Sets:AER, KLD

View File

@@ -0,0 +1,6 @@
[format]
Name:Kamigawa Block
Type:Historic
Subtype:Block
Order:126
Sets:SOK, BOK, CHK

View File

@@ -0,0 +1,6 @@
[format]
Name:Khans of Tarkir Block
Type:Historic
Subtype:Block
Order:116
Sets:DTK, FRF, KTK

View File

@@ -0,0 +1,6 @@
[format]
Name:Lorwyn-Shadowmoor Block
Type:Historic
Subtype:Block
Order:123
Sets:EVE, SHM, MOR, LRW

View File

@@ -0,0 +1,7 @@
[format]
Name:Masques Block
Type:Historic
Subtype:Block
Order:131
Sets:PCY, NMS, MMA
Banned:Lin Sivvi, Defiant Hero; Rishadan Port

View File

@@ -0,0 +1,7 @@
[format]
Name:Mirage Block
Type:Historic
Subtype:Block
Order:134
Sets:VIS, WTH, MIR
Banned:Squandered Resources

View File

@@ -0,0 +1,7 @@
[format]
Name:Mirrodin Block
Type:Historic
Subtype:Block
Order:127
Sets:5DN, DST, MRD
Banned:Aether Vial; Ancient Den; Arcbound Ravager; Darksteel Citadel; Disciple of the Vault; Great Furnace; Seat of the Synod; Tree of Tales; Vault of Whispers; Skullclamp

View File

@@ -0,0 +1,6 @@
[format]
Name:Odyssey Block
Type:Historic
Subtype:Block
Order:129
Sets:JUD, TOR, ODY

View File

@@ -0,0 +1,6 @@
[format]
Name:Onslaught Block
Type:Historic
Subtype:Block
Order:128
Sets:SCG, LGN, ONS

View File

@@ -0,0 +1,6 @@
[format]
Name:Ravnica Block
Type:Historic
Subtype:Block
Order:125
Sets:DIS, GPT, RAV

View File

@@ -0,0 +1,6 @@
[format]
Name:Return to Ravnica Block
Type:Historic
Subtype:Block
Order:118
Sets:DGM, GTC, RTR

View File

@@ -0,0 +1,6 @@
[format]
Name:Scars of Mirrodin Block
Type:Historic
Subtype:Block
Order:120
Sets:NPH, MBS, SOM

View File

@@ -0,0 +1,6 @@
[format]
Name:Shadows over Innistrad Block
Type:Historic
Subtype:Block
Order:114
Sets:EMN, SOI

View File

@@ -0,0 +1,6 @@
[format]
Name:Shards of Alara Block
Type:Historic
Subtype:Block
Order:122
Sets:ARB, CFX, ALA

View File

@@ -0,0 +1,7 @@
[format]
Name:Tempest Block
Type:Historic
Subtype:Block
Order:133
Sets:EXO, STH, TMP
Banned:Cursed Scroll

View File

@@ -0,0 +1,6 @@
[format]
Name:Theros Block
Type:Historic
Subtype:Block
Order:117
Sets:JOU, BNG, THS

View File

@@ -0,0 +1,6 @@
[format]
Name:Time Spiral Block
Type:Historic
Subtype:Block
Order:124
Sets:FUT, PLC, TSP, TSB

View File

@@ -0,0 +1,7 @@
[format]
Name:Urza Block
Type:Historic
Subtype:Block
Order:132
Sets:UDS, ULG, USG
Banned:Gaea's Cradle; Memory Jar; Serra's Sanctum; Time Spiral; Tolarian Academy; Voltaic Key; Windfall

View File

@@ -0,0 +1,6 @@
[format]
Name:Zendikar Block
Type:Historic
Subtype:Block
Order:121
Sets:ROE, WWK, ZEN

View File

@@ -1,5 +1,6 @@
[format]
Name:Commander
Type:Casual
Order:106
Banned:Adriana's Valor; Advantageous Proclamation; Ashnod's Coupon; Assemble the Rank and Vile; Backup Plan; Brago's Favor; Double Cross; Double Deal; Double Dip; Double Play; Double Stroke; Double Take; Echoing Boon; Emissary's Ploy; Enter the Dungeon; Hired Heist; Hold the Perimeter; Hymn of the Wilds; Immediate Action; Incendiary Dissent; Iterative Analysis; Magical Hacker; Mox Lotus; Muzzio's Preparations; Natural Unity; Once More with Feeling; Power Play; R&D's Secret Lair; Richard Garfield, Ph.D.; Secret Summoning; Secrets of Paradise; Sentinel Dispatch; Sovereign's Realm; Staying Power; Summoner's Bond; Time Machine; Unexpected Potential; Weight Advantage; Worldknit; Amulet of Quoz; Bronze Tablet; Contract from Below; Darkpact; Demonic Attorney; Jeweled Bird; Rebirth; Tempest Efreet; Timmerian Fiends; Ancestral Recall; Balance; Biorhythm; Black Lotus; Braids, Cabal Minion; Chaos Orb; Coalition Victory; Channel; Emrakul, the Aeons Torn; Erayo, Soratami Ascendant; Falling Star; Fastbond; Gifts Ungiven; Griselbrand; Karakas; Leovold, Emissary of Trest; Library of Alexandria; Limited Resources; Mox Emerald; Mox Jet; Mox Pearl; Mox Ruby; Mox Sapphire; Painter's Servant; Panoptic Mirror; Primeval Titan; Prophet of Kruphix; Recurring Nightmare; Rofellos, Llanowar Emissary; Shahrazad; Staying Power; Sundering Titan; Sway of the Stars; Sylvan Primordial; Time Machine; Time Vault; Time Walk; Tinker; Tolarian Academy; Trade Secrets; Upheaval; Worldfire; Yawgmoth's Bargain
Subtype:Commander
Order:137
Banned:Adriana's Valor; Advantageous Proclamation; Ashnod's Coupon; Assemble the Rank and Vile; Backup Plan; Brago's Favor; Double Cross; Double Deal; Double Dip; Double Play; Double Stroke; Double Take; Echoing Boon; Emissary's Ploy; Enter the Dungeon; Hired Heist; Hold the Perimeter; Hymn of the Wilds; Immediate Action; Incendiary Dissent; Iterative Analysis; Magical Hacker; Mox Lotus; Muzzio's Preparations; Natural Unity; Once More with Feeling; Power Play; R&D's Secret Lair; Richard Garfield, Ph.D.; Secret Summoning; Secrets of Paradise; Sentinel Dispatch; Sovereign's Realm; Staying Power; Summoner's Bond; Time Machine; Unexpected Potential; Weight Advantage; Worldknit; Amulet of Quoz; Bronze Tablet; Contract from Below; Darkpact; Demonic Attorney; Jeweled Bird; Rebirth; Tempest Efreet; Timmerian Fiends; Ancestral Recall; Balance; Biorhythm; Black Lotus; Braids, Cabal Minion; Chaos Orb; Coalition Victory; Channel; Emrakul, the Aeons Torn; Erayo, Soratami Ascendant; Falling Star; Fastbond; Gifts Ungiven; Griselbrand; Karakas; Leovold, Emissary of Trest; Library of Alexandria; Limited Resources; Mox Emerald; Mox Jet; Mox Pearl; Mox Ruby; Mox Sapphire; Painter's Servant; Panoptic Mirror; Primeval Titan; Prophet of Kruphix; Recurring Nightmare; Rofellos, Llanowar Emissary; Shahrazad; Sundering Titan; Sway of the Stars; Sylvan Primordial; Time Vault; Time Walk; Tinker; Tolarian Academy; Trace Secrets; Upheaval; Worldfire; Yawgmoth's Bargain

View File

@@ -0,0 +1,6 @@
[format]
Name:Conspiracy
Type:Historic
Subtype:Custom
Order:138
Sets:CNS, CN2

View File

@@ -0,0 +1,6 @@
[format]
Name:Un-Sets
Type:Historic
Subtype:Custom
Order:136
Sets:UST, UNH, UGL

View File

@@ -1,5 +1,6 @@
[format]
Name:Pauper
Order:108
Subtype:Custom
Type:Casual
Rarities:L, C

View File

@@ -0,0 +1,6 @@
[format]
Name:Duels
Type:Digital
Subtype:Videogame
Order:140
Sets:ORI, BFZ, OGW, SOI, EMN, KLD, AER, AKH

View File

@@ -0,0 +1,6 @@
[format]
Name:MTGO
Type:Digital
Subtype:MTGO
Order:139
Sets:ALL, MIR, VIS, WTH, TMP, STH, EXO, USG, UDS, MMQ, NMS, PCY, INV, PLS, 7ED, APC, ODY, TOR, JUD, 8ED, MRD, DST, 5DN, CHK, BOK, SOK, 9ED, RAV, GPT, DIS, CSP, TSP, TSB, PLC, FUT, 10E, MED, LRW, MOR, SHM, EVE, ME2, ALA, CFX, ARB, M10, TD0, FVE, ME3, ZEN, WWK, ROE, M11, SOM, TD1, MBED, ME4, MBS, NPH, M12, ISD, DKA, AVR, M13, RTR, TD2, GTC, DGM, M14, THS, BNG, JOU, VMA, M15, KTK, FRF, DTK, TPR, MM2, ORI, BFZ, OGW, PZ1, OGW, EMA, EMN, PZ2, YMC, AER, MM3, AKH, HOU, XLN

View File

@@ -0,0 +1,8 @@
[format]
Name:MicroProse
Type:Digital
Subtype:Videogame
Order:110
Sets:MTG, STA, AST, DOTP, MTG_R, STA_R, DOTP_R
Banned:Channel; Mind Twist; Bronze Tablet; Contract from Below; Darkpact; Demonic Attorney; Jeweled Bird; Rebirth; Tempest Efreet
Restricted:Ancestral Recall; Balance; Berserk; Black Lotus; Black Vise; Braingeyser; Demonic Tutor; Fastbond; Fork; Ivory Tower; Library of Alexandria; Mox Emerald; Mox Jet; Mox Pearl; Mox Ruby; Mox Sapphire; Regrowth; Sol Ring; Time Walk; Timetwister; Wheel of Fortune

View File

View File

@@ -0,0 +1,8 @@
[format]
Name:Ice Age, 10/01/95
Type:Historic
Subtype:Block
Effective:1995-10-01
Sets:ICE
Restricted:Zuran Orb
Banned:Amulet of Quoz

View File

@@ -0,0 +1,8 @@
[format]
Name:Ice Age/Alliances, 10/01/96
Type:Historic
Subtype:Block
Effective:1996-10-01
Sets:ICE, ALL
Restricted:Zuran Orb
Banned:Amulet of Quoz

View File

@@ -0,0 +1,7 @@
[format]
Name:Ice Age, 05/01/97
Type:Historic
Subtype:Block
Effective:1997-05-01
Sets:ICE
Banned:Amulet of Quoz, Thawing Glaciers, Zuran Orb

View File

@@ -0,0 +1,7 @@
[format]
Name:Ice Age/Homelands/Alliances, 07/01/97
Type:Historic
Subtype:Block
Effective:1997-07-01
Sets:ICE, HML, ALL
Banned:Amulet of Quoz, Thawing Glaciers, Timmerian Fiends, Zuran Orb

View File

@@ -0,0 +1,6 @@
[format]
Name:Invasion Block, Invasion
Type:Historic
Subtype:Block
Effective:2000-11-01
Sets:INV

View File

@@ -0,0 +1,6 @@
[format]
Name:Invasion Block, Planeshift
Type:Historic
Subtype:Block
Effective:2001-03-01
Sets:INV, PLS

View File

@@ -0,0 +1,6 @@
[format]
Name:Invasion Block, Apocalypse
Type:Historic
Subtype:Block
Effective:2001-07-01
Sets:INV, PLS, APC

View File

@@ -0,0 +1,6 @@
[format]
Name:Kamigawa Block, Champions of Kamigawa
Type:Historic
Subtype:Block
Effective:2004-10-20
Sets:CHK

View File

@@ -0,0 +1,6 @@
[format]
Name:Kamigawa Block, Betrayers of Kamigawa
Type:Historic
Subtype:Block
Effective:2005-02-20
Sets:CHK, BOK

View File

@@ -0,0 +1,6 @@
[format]
Name:Kamigawa Block, Saviors of Kamigawa
Type:Historic
Subtype:Block
Effective:2005-06-20
Sets:CHK, BOK, SOK

View File

@@ -0,0 +1,6 @@
[format]
Name:Masques Block, Mercadian Masques
Type:Historic
Subtype:Block
Effective:1999-11-01
Sets:MMQ

View File

@@ -0,0 +1,6 @@
[format]
Name:Masques Block, Nemesis
Type:Historic
Subtype:Block
Effective:2000-03-01
Sets:MMQ, NMS

View File

@@ -0,0 +1,7 @@
[format]
Name:Masques Block, Prophecy
Type:Historic
Subtype:Block
Effective:2000-07-01
Sets:MMQ, NMS, PCY
Banned:Lin Sivvi, Defiant Hero; Rishadan Port

View File

@@ -0,0 +1,7 @@
[format]
Name:Mirage/Visions/Weatherlight Block, Weatherlight
Type:Historic
Subtype:Block
Effective:1997-07-01
Sets:MIR, VIS, WTH
Banned:Squandered Resources

View File

@@ -0,0 +1,6 @@
[format]
Name:Mirrodin Block, Mirrodin
Type:Historic
Subtype:Block
Effective:2003-10-20
Sets:MRD

View File

@@ -0,0 +1,6 @@
[format]
Name:Mirrodin Block, Darksteel
Type:Historic
Subtype:Block
Effective:2004-02-20
Sets:MRD, DST

View File

@@ -0,0 +1,7 @@
[format]
Name:Mirrodin Block, Fifth Dawn
Type:Historic
Subtype:Block
Effective:2004-06-20
Sets:MRD, DST, 5DN
Banned:Skullclamp

View File

@@ -0,0 +1,6 @@
[format]
Name:Odyssey Block, Odyssey
Type:Historic
Subtype:Block
Effective:2001-11-01
Sets:ODY

View File

@@ -0,0 +1,6 @@
[format]
Name:Odyssey Block, Torment
Type:Historic
Subtype:Block
Effective:2002-03-01
Sets:ODY, TOR

View File

@@ -0,0 +1,6 @@
[format]
Name:Odyssey Block, Judgment
Type:Historic
Subtype:Block
Effective:2002-07-01
Sets:ODY, TOR, JUD

View File

@@ -0,0 +1,6 @@
[format]
Name:Onslaught Block, Onslaught
Type:Historic
Subtype:Block
Effective:2002-11-01
Sets:ONS

View File

@@ -0,0 +1,6 @@
[format]
Name:Onslaught Block, Legions
Type:Historic
Subtype:Block
Effective:2003-03-01
Sets:ONS, LGN

View File

@@ -0,0 +1,6 @@
[format]
Name:Onslaught Block, Scourge
Type:Historic
Subtype:Block
Effective:2003-07-01
Sets:ONS, LGN, SCG

View File

@@ -0,0 +1,6 @@
[format]
Name:Tempest Block, Tempest
Type:Historic
Subtype:Block
Effective:1997-11-01
Sets:TMP

View File

@@ -0,0 +1,6 @@
[format]
Name:Tempest/Stronghold Block, Stronghold
Type:Historic
Subtype:Block
Effective:1998-04-01
Sets:TMP, STH

View File

@@ -0,0 +1,7 @@
[format]
Name:Tempest/Stronghold/Exodus Block, Exodus
Type:Historic
Subtype:Block
Effective:1998-07-01
Sets:TMP, STH, EXO
Banned:Cursed Scroll

View File

@@ -0,0 +1,6 @@
[format]
Name:Ravnica Block, Ravnica: City of Guilds
Type:Historic
Subtype:Block
Effective:2005-10-20
Sets:RAV

View File

@@ -0,0 +1,6 @@
[format]
Name:Urza's Saga Standalone, 01/01/99
Type:Historic
Subtype:Block
Effective:1999-01-01
Sets:USG

View File

@@ -0,0 +1,6 @@
[format]
Name:Urza's Saga/Urza's Legacy Standalone, Urza's Legacy
Type:Historic
Subtype:Block
Effective:1999-03-01
Sets:USG, ULG

View File

@@ -0,0 +1,7 @@
[format]
Name:Urza Block, 04/01/99
Type:Historic
Subtype:Block
Effective:1999-04-01
Sets:USG, ULG
Banned:Memory Jar, Time Spiral, Windfall

View File

@@ -0,0 +1,7 @@
[format]
Name:Urza Block, Urza's Destiny
Type:Historic
Subtype:Block
Effective:1999-07-01
Sets:USG, ULG, UDS
Banned:Gaea's Cradle, Memory Jar, Serra's Sanctum, Time Spiral, Tolarian Academy, Voltaic Key, Windfall

View File

@@ -0,0 +1,7 @@
[format]
Name:Extended, Weatherlight
Type:Historic
Subtype:Extended
Effective:1997-07-01
Sets:3ED, DRK, ARENA, FEM, WW, SHC, FS, 4ED, ICE, CHR, HML, ALL, MIR, VIS, 5ED, WTH
Banned:Amulet of Quoz, Balance, Black Vise, Braingeyser, Bronze Tablet, Channel, Contract from Below, Darkpact, Demonic Attorney, Demonic Tutor, Fastbond, Ivory Tower, Jeweled Bird, Juggernaut, Kird Ape, Mana Crypt, Maze of Ith, Mind Twist, Rebirth, Regrowth, Serendib Efreet, Sol Ring, Strip Mine, Tempest Efreet, Timmerian Fiends, Wheel of Fortune, Zuran Orb

View File

@@ -0,0 +1,7 @@
[format]
Name:Extended, 10/01/97
Type:Historic
Subtype:Extended
Effective:1997-10-01
Sets:3ED, DRK, ARENA, FEM, WW, SHC, FS, 4ED, ICE, CHR, HML, ALL, MIR, VIS, 5ED, WTH
Banned:Amulet of Quoz, Balance, Black Vise, Braingeyser, Bronze Tablet, Channel, Contract from Below, Darkpact, Demonic Attorney, Demonic Tutor, Fastbond, Hypnotic Specter, Ivory Tower, Jeweled Bird, Juggernaut, Kird Ape, Mana Crypt, Maze of Ith, Mind Twist, Rebirth, Regrowth, Serendib Efreet, Sol Ring, Strip Mine, Tempest Efreet, Timmerian Fiends, Wheel of Fortune, Zuran Orb

View File

@@ -0,0 +1,7 @@
[format]
Name:Extended, Tempest
Type:Historic
Subtype:Extended
Effective:1997-11-01
Sets:3ED, DRK, ARENA, FEM, WW, SHC, FS, 4ED, ICE, CHR, HML, ALL, MIR, VIS, 5ED, WTH, TMP
Banned:Amulet of Quoz, Balance, Black Vise, Braingeyser, Bronze Tablet, Channel, Contract from Below, Darkpact, Demonic Attorney, Demonic Tutor, Fastbond, Hypnotic Specter, Ivory Tower, Jeweled Bird, Juggernaut, Kird Ape, Mana Crypt, Maze of Ith, Mind Twist, Rebirth, Regrowth, Serendib Efreet, Sol Ring, Strip Mine, Tempest Efreet, Timmerian Fiends, Wheel of Fortune, Zuran Orb

View File

@@ -0,0 +1,7 @@
[format]
Name:Extended, Stronghold
Type:Historic
Subtype:Extended
Effective:1998-04-01
Sets:3ED, DRK, ARENA, FEM, WW, SHC, FS, 4ED, ICE, CHR, HML, ALL, MIR, VIS, 5ED, WTH, TMP, STH
Banned:Amulet of Quoz, Balance, Black Vise, Braingeyser, Bronze Tablet, Channel, Contract from Below, Darkpact, Demonic Attorney, Demonic Tutor, Fastbond, Hypnotic Specter, Ivory Tower, Jeweled Bird, Juggernaut, Kird Ape, Mana Crypt, Maze of Ith, Mind Twist, Rebirth, Regrowth, Serendib Efreet, Sol Ring, Strip Mine, Tempest Efreet, Timmerian Fiends, Wheel of Fortune, Zuran Orb

View File

@@ -0,0 +1,7 @@
[format]
Name:Extended, Exodus
Type:Historic
Subtype:Extended
Effective:1998-07-01
Sets:3ED, DRK, ARENA, FEM, WW, SHC, FS, 4ED, ICE, CHR, HML, ALL, MIR, VIS, 5ED, WTH, TMP, STH, EXO
Banned:Amulet of Quoz, Balance, Black Vise, Braingeyser, Bronze Tablet, Channel, Contract from Below, Darkpact, Demonic Attorney, Demonic Tutor, Fastbond, Hypnotic Specter, Ivory Tower, Jeweled Bird, Kird Ape, Land Tax, Mana Crypt, Maze of Ith, Mind Twist, Rebirth, Regrowth, Serendib Efreet, Sol Ring, Strip Mine, Tempest Efreet, Timmerian Fiends, Wheel of Fortune, Zuran Orb

View File

@@ -0,0 +1,7 @@
[format]
Name:Extended, Urza's Saga
Type:Historic
Subtype:Extended
Effective:1998-11-01
Sets:3ED, DRK, ARENA, FEM, WW, SHC, FS, 4ED, ICE, CHR, HML, ALL, MIR, VIS, 5ED, WTH, TMP, STH, EXO, USG
Banned:Amulet of Quoz, Balance, Black Vise, Braingeyser, Bronze Tablet, Channel, Contract from Below, Darkpact, Demonic Attorney, Demonic Tutor, Fastbond, Hypnotic Specter, Ivory Tower, Jeweled Bird, Kird Ape, Land Tax, Mana Crypt, Maze of Ith, Mind Twist, Rebirth, Regrowth, Serendib Efreet, Sol Ring, Strip Mine, Tempest Efreet, Timmerian Fiends, Wheel of Fortune, Zuran Orb

View File

@@ -0,0 +1,7 @@
[format]
Name:Extended, 01/01/99
Type:Historic
Subtype:Extended
Effective:1999-01-01
Sets:3ED, DRK, ARENA, FEM, WW, SHC, FS, 4ED, ICE, CHR, HML, ALL, MIR, VIS, 5ED, WTH, TMP, STH, EXO, USG
Banned:Amulet of Quoz, Balance, Black Vise, Bronze Tablet, Channel, Contract from Below, Darkpact, Demonic Attorney, Demonic Tutor, Fastbond, Hypnotic Specter, Ivory Tower, Jeweled Bird, Kird Ape, Land Tax, Mana Crypt, Maze of Ith, Mind Twist, Rebirth, Regrowth, Serendib Efreet, Sol Ring, Strip Mine, Tempest Efreet, Timmerian Fiends, Tolarian Academy, Wheel of Fortune, Windfall, Zuran Orb

View File

@@ -0,0 +1,7 @@
[format]
Name:Extended, Urza's Legacy
Type:Historic
Subtype:Extended
Effective:1999-03-01
Sets:3ED, DRK, ARENA, FEM, WW, SHC, FS, 4ED, ICE, CHR, HML, ALL, MIR, VIS, 5ED, WTH, TMP, STH, EXO, USG, ULG
Banned:Amulet of Quoz, Balance, Black Vise, Bronze Tablet, Channel, Contract from Below, Darkpact, Demonic Attorney, Demonic Tutor, Fastbond, Hypnotic Specter, Ivory Tower, Jeweled Bird, Kird Ape, Land Tax, Mana Crypt, Maze of Ith, Mind Twist, Rebirth, Regrowth, Serendib Efreet, Sol Ring, Strip Mine, Tempest Efreet, Timmerian Fiends, Tolarian Academy, Wheel of Fortune, Windfall, Zuran Orb

View File

@@ -0,0 +1,7 @@
[format]
Name:Extended, 04/01/99
Type:Historic
Subtype:Extended
Effective:1999-04-01
Sets:3ED, DRK, ARENA, FEM, WW, SHC, FS, 4ED, ICE, CHR, HML, ALL, MIR, VIS, 5ED, WTH, TMP, STH, EXO, USG, ULG
Banned:Amulet of Quoz, Balance, Black Vise, Bronze Tablet, Channel, Contract from Below, Darkpact, Demonic Attorney, Demonic Tutor, Fastbond, Hypnotic Specter, Ivory Tower, Jeweled Bird, Kird Ape, Land Tax, Mana Crypt, Maze of Ith, Memory Jar, Mind Twist, Rebirth, Regrowth, Serendib Efreet, Sol Ring, Strip Mine, Tempest Efreet, Timmerian Fiends, Tolarian Academy, Wheel of Fortune, Windfall, Zuran Orb

View File

@@ -0,0 +1,7 @@
[format]
Name:Extended, Classic Sixth Edition
Type:Historic
Subtype:Extended
Effective:1999-06-01
Sets:3ED, DRK, ARENA, FEM, WW, SHC, FS, 4ED, ICE, CHR, HML, ALL, MIR, VIS, 5ED, WTH, TMP, STH, EXO, USG, ULG, 6ED
Banned:Amulet of Quoz, Balance, Black Vise, Bronze Tablet, Channel, Contract from Below, Darkpact, Demonic Attorney, Demonic Tutor, Fastbond, Hypnotic Specter, Ivory Tower, Jeweled Bird, Kird Ape, Land Tax, Mana Crypt, Maze of Ith, Memory Jar, Mind Twist, Rebirth, Regrowth, Serendib Efreet, Sol Ring, Strip Mine, Tempest Efreet, Timmerian Fiends, Tolarian Academy, Wheel of Fortune, Windfall, Zuran Orb

View File

@@ -0,0 +1,7 @@
[format]
Name:Extended, Urza's Destiny
Type:Historic
Subtype:Extended
Effective:1999-07-01
Sets:3ED, DRK, ARENA, FEM, WW, SHC, FS, 4ED, ICE, CHR, HML, ALL, MIR, VIS, 5ED, WTH, TMP, STH, EXO, USG, ULG, 6ED, UDS
Banned:Amulet of Quoz, Balance, Black Vise, Bronze Tablet, Channel, Contract from Below, Darkpact, Demonic Attorney, Demonic Tutor, Fastbond, Hypnotic Specter, Ivory Tower, Jeweled Bird, Kird Ape, Land Tax, Mana Crypt, Maze of Ith, Memory Jar, Mind Twist, Rebirth, Regrowth, Serendib Efreet, Sol Ring, Strip Mine, Tempest Efreet, Time Spiral, Timmerian Fiends, Tolarian Academy, Wheel of Fortune, Windfall, Zuran Orb

View File

@@ -0,0 +1,7 @@
[format]
Name:Extended, 08/01/99
Type:Historic
Subtype:Extended
Effective:1999-08-01
Sets:3ED, DRK, ARENA, FEM, WW, SHC, FS, 4ED, ICE, CHR, HML, ALL, MIR, VIS, 5ED, WTH, TMP, STH, EXO, USG, ULG, 6ED, UDS
Banned:Amulet of Quoz, Balance, Black Vise, Bronze Tablet, Channel, Contract from Below, Darkpact, Demonic Attorney, Demonic Tutor, Fastbond, Hypnotic Specter, Ivory Tower, Jeweled Bird, Kird Ape, Land Tax, Mana Crypt, Maze of Ith, Memory Jar, Mind Twist, Rebirth, Regrowth, Serendib Efreet, Sol Ring, Strip Mine, Tempest Efreet, Time Spiral, Timmerian Fiends, Tolarian Academy, Wheel of Fortune, Windfall, Yawgmoth's Bargain, Zuran Orb

View File

@@ -0,0 +1,8 @@
[format]
Name:Extended, 10/01/99
Type:Historic
Subtype:Extended
Effective:1999-10-01
Sets:ICE, HML, ALL, MIR, VIS, 5ED, WTH, TMP, STH, EXO, USG, ULG, 6ED, UDS
Banned:Amulet of Quoz, Dream Halls, Earthcraft, Lotus Petal, Memory Jar, Mind Over Matter, Time Spiral, Timmerian Fiends, Tolarian Academy, Windfall, Yawgmoth's Bargain, Yawgmoth's Will, Zuran Orb
Additional:Badlands, Bayou, Plateau, Savannah, Scrubland, Taiga, Tropical Island, Tundra, Underground Sea, Volcanic Island

View File

@@ -0,0 +1,8 @@
[format]
Name:Extended, Mercadian Masques
Type:Historic
Subtype:Extended
Effective:1999-11-01
Sets:ICE, HML, ALL, MIR, VIS, 5ED, WTH, TMP, STH, EXO, USG, ULG, 6ED, UDS, MMQ
Banned:Amulet of Quoz, Dream Halls, Earthcraft, Lotus Petal, Memory Jar, Mind Over Matter, Time Spiral, Timmerian Fiends, Tolarian Academy, Windfall, Yawgmoth's Bargain, Yawgmoth's Will, Zuran Orb
Additional:Badlands, Bayou, Plateau, Savannah, Scrubland, Taiga, Tropical Island, Tundra, Underground Sea, Volcanic Island

View File

@@ -0,0 +1,8 @@
[format]
Name:Extended, Nemesis
Type:Historic
Subtype:Extended
Effective:2000-03-01
Sets:ICE, HML, ALL, MIR, VIS, 5ED, WTH, TMP, STH, EXO, USG, ULG, 6ED, UDS, MMQ, NMS
Banned:Amulet of Quoz, Dream Halls, Earthcraft, Lotus Petal, Memory Jar, Mind Over Matter, Time Spiral, Timmerian Fiends, Tolarian Academy, Windfall, Yawgmoth's Bargain, Yawgmoth's Will, Zuran Orb
Additional:Badlands, Bayou, Plateau, Savannah, Scrubland, Taiga, Tropical Island, Tundra, Underground Sea, Volcanic Island

View File

@@ -0,0 +1,8 @@
[format]
Name:Extended, 04/01/00
Type:Historic
Subtype:Extended
Effective:2000-04-01
Sets:ICE, HML, ALL, MIR, VIS, 5ED, WTH, TMP, STH, EXO, USG, ULG, 6ED, UDS, MMQ, NMS
Banned:Amulet of Quoz, Dark Ritual, Dream Halls, Earthcraft, Lotus Petal, Mana Vault, Memory Jar, Mind Over Matter, Time Spiral, Timmerian Fiends, Tolarian Academy, Windfall, Yawgmoth's Bargain, Yawgmoth's Will, Zuran Orb
Additional:Badlands, Bayou, Plateau, Savannah, Scrubland, Taiga, Tropical Island, Tundra, Underground Sea, Volcanic Island

View File

@@ -0,0 +1,8 @@
[format]
Name:Extended, Prophecy
Type:Historic
Subtype:Extended
Effective:2000-07-01
Sets:ICE, HML, ALL, MIR, VIS, 5ED, WTH, TMP, STH, EXO, USG, ULG, 6ED, UDS, MMQ, NMS, PCY
Banned:Amulet of Quoz, Dark Ritual, Dream Halls, Earthcraft, Lotus Petal, Mana Vault, Memory Jar, Mind Over Matter, Time Spiral, Timmerian Fiends, Tolarian Academy, Windfall, Yawgmoth's Bargain, Yawgmoth's Will, Zuran Orb
Additional:Badlands, Bayou, Plateau, Savannah, Scrubland, Taiga, Tropical Island, Tundra, Underground Sea, Volcanic Island

View File

@@ -0,0 +1,8 @@
[format]
Name:Extended, Invasion
Type:Historic
Subtype:Extended
Effective:2000-11-01
Sets:ICE, HML, ALL, MIR, VIS, 5ED, WTH, TMP, STH, EXO, USG, ULG, 6ED, UDS, MMQ, NMS, PCY, INV
Banned:Amulet of Quoz, Dark Ritual, Dream Halls, Earthcraft, Lotus Petal, Mana Vault, Memory Jar, Mind Over Matter, Time Spiral, Timmerian Fiends, Tolarian Academy, Windfall, Yawgmoth's Bargain, Yawgmoth's Will, Zuran Orb
Additional:Badlands, Bayou, Plateau, Savannah, Scrubland, Taiga, Tropical Island, Tundra, Underground Sea, Volcanic Island

View File

@@ -0,0 +1,8 @@
[format]
Name:Extended, Planeshift
Type:Historic
Subtype:Extended
Effective:2001-03-01
Sets:ICE, HML, ALL, MIR, VIS, 5ED, WTH, TMP, STH, EXO, USG, ULG, 6ED, UDS, MMQ, NMS, PCY, INV, PLS
Banned:Amulet of Quoz, Dark Ritual, Dream Halls, Earthcraft, Lotus Petal, Mana Vault, Memory Jar, Mind Over Matter, Time Spiral, Timmerian Fiends, Tolarian Academy, Windfall, Yawgmoth's Bargain, Yawgmoth's Will, Zuran Orb
Additional:Badlands, Bayou, Plateau, Savannah, Scrubland, Taiga, Tropical Island, Tundra, Underground Sea, Volcanic Island

View File

@@ -0,0 +1,8 @@
[format]
Name:Extended, 04/01/01
Type:Historic
Subtype:Extended
Effective:2001-04-01
Sets:ICE, HML, ALL, MIR, VIS, 5ED, WTH, TMP, STH, EXO, USG, ULG, 6ED, UDS, MMQ, NMS, PCY, INV, PLS
Banned:Amulet of Quoz, Dark Ritual, Demonic Consultation, Dream Halls, Earthcraft, Lotus Petal, Mana Vault, Memory Jar, Mind Over Matter, Necropotence, Replenish, Survival of the Fittest, Time Spiral, Timmerian Fiends, Tolarian Academy, Windfall, Yawgmoth's Bargain, Yawgmoth's Will, Zuran Orb
Additional:Badlands, Bayou, Plateau, Savannah, Scrubland, Taiga, Tropical Island, Tundra, Underground Sea, Volcanic Island

View File

@@ -0,0 +1,8 @@
[format]
Name:Extended, Seventh Edition
Type:Historic
Subtype:Extended
Effective:2001-05-01
Sets:ICE, HML, ALL, MIR, VIS, 5ED, WTH, TMP, STH, EXO, USG, ULG, 6ED, UDS, MMQ, NMS, PCY, INV, PLS, 7ED
Banned:Amulet of Quoz, Dark Ritual, Demonic Consultation, Dream Halls, Earthcraft, Lotus Petal, Mana Vault, Memory Jar, Mind Over Matter, Necropotence, Replenish, Survival of the Fittest, Time Spiral, Timmerian Fiends, Tolarian Academy, Windfall, Yawgmoth's Bargain, Yawgmoth's Will, Zuran Orb
Additional:Badlands, Bayou, Plateau, Savannah, Scrubland, Taiga, Tropical Island, Tundra, Underground Sea, Volcanic Island

Some files were not shown because too many files have changed in this diff Show More