diff --git a/.gitattributes b/.gitattributes index fb4fbce83c8..ee1d2ca7ad4 100644 --- a/.gitattributes +++ b/.gitattributes @@ -15,6 +15,7 @@ res/blockdata/blocks.txt svneol=native#text/plain res/blockdata/fantasyblocks.txt -text res/blockdata/fatpacks.txt -text res/blockdata/formats.txt -text +res/blockdata/printsheets.txt -text res/blockdata/setdata.txt svneol=native#text/plain res/blockdata/starters.txt -text res/cardsfolder/a/a_display_of_my_dark_power.txt -text @@ -14418,6 +14419,7 @@ src/main/java/forge/util/storage/IStorage.java -text src/main/java/forge/util/storage/IStorageView.java -text src/main/java/forge/util/storage/StorageImmediatelySerialized.java svneol=native#text/plain src/main/java/forge/util/storage/StorageReaderFile.java -text +src/main/java/forge/util/storage/StorageReaderFileSections.java -text src/main/java/forge/util/storage/StorageReaderFolder.java -text src/main/java/forge/util/storage/StorageView.java -text src/main/java/forge/util/storage/package-info.java -text diff --git a/res/blockdata/boosters.txt b/res/blockdata/boosters.txt index 4fa1a1e521e..14bb384ccf1 100644 --- a/res/blockdata/boosters.txt +++ b/res/blockdata/boosters.txt @@ -20,7 +20,7 @@ CFX: 3 covers, 10 Common, 3 Uncommon, 1 Rare, 1 BasicLand ALA CHK: 5 covers, 11 Common, 3 Uncommon, 1 Rare CHR: 1 covers, 9 Common, 3 UncommonRare CSP: 3 covers, 11 Common, 3 Uncommon, 1 Rare -DGM: 3 covers, 10 Common, 3 Uncommon, 1 Rare:!name("Maze's End"), 1 MazeLand +DGM: 3 covers, 10 Common, 3 Uncommon, 1 Rare:!name("Maze's End"), 1 Custom("Dragon's Maze Lands") DIS: 3 covers, 11 Common, 3 Uncommon, 1 Rare DKA: 3 covers, 9 Common:!dfc, 3 Uncommon:!dfc, 1 Rare:!dfc, 1 Any:dfc, 1 BasicLand ISD DRK: 1 covers, 6 Common, 2 UncommonRare diff --git a/res/blockdata/printsheets.txt b/res/blockdata/printsheets.txt new file mode 100644 index 00000000000..2e5e032c531 --- /dev/null +++ b/res/blockdata/printsheets.txt @@ -0,0 +1,23 @@ +[Dragon's Maze Lands] +# Uncomment all after DGM set is added to setdata.txt +#10 Azorius Guildgate|DGM +#10 Boros Guildgate|DGM +#10 Dimir Guildgate|DGM +#10 Golgari Guildgate|DGM +#10 Gruul Guildgate|DGM +#10 Izzet Guildgate|DGM +#10 Orzhov Guildgate|DGM +#10 Rakdos Guildgate|DGM +#10 Selesnya Guildgate|DGM +#10 Simic Guildgate|DGM +2 Blood Crypt|RTR +2 Hallowed Fountain|RTR +2 Overgrown Tomb|RTR +2 Steam Vents|RTR +2 Temple Garden|RTR +2 Breeding Pool|GTC +2 Godless Shrine|GTC +2 Sacred Foundry|GTC +2 Stomping Ground|GTC +2 Watery Grave|GTC +#1 Maze's End|DGM \ No newline at end of file diff --git a/src/main/java/forge/card/BoosterGenerator.java b/src/main/java/forge/card/BoosterGenerator.java index 38c54e9f11b..75b68437a23 100644 --- a/src/main/java/forge/card/BoosterGenerator.java +++ b/src/main/java/forge/card/BoosterGenerator.java @@ -31,10 +31,12 @@ import com.google.common.base.Predicates; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; +import forge.Singletons; import forge.item.CardDb; import forge.item.CardPrinted; import forge.item.IPaperCard; import forge.item.PrintSheet; +import forge.model.FModel; import forge.util.TextUtil; /** @@ -86,7 +88,7 @@ public class BoosterGenerator { @SuppressWarnings("unchecked") private static final PrintSheet makeSheet(String sheetKey, Iterable src) { - PrintSheet ps = new PrintSheet(); + PrintSheet ps = new PrintSheet(sheetKey); String[] sKey = TextUtil.splitWithParenthesis(sheetKey, ' ', '(', ')', 2); String[] operators = TextUtil.splitWithParenthesis(sKey[0], ':', '(', ')'); @@ -148,8 +150,9 @@ public class BoosterGenerator { Predicate predicate = Predicates.and( setPred, IPaperCard.Predicates.Presets.IS_SPECIAL, extraPred ); ps.addAll(Iterables.filter(src, predicate)); - } else if ( mainCode.equalsIgnoreCase("mazeland") ) { - + } else if ( mainCode.equalsIgnoreCase("custom(") ) { + String sheetName = StringUtils.strip(mainCode.substring(6), "()\" "); + return Singletons.getModel().getPrintSheets().get(sheetName); } return ps; } diff --git a/src/main/java/forge/deck/CardPool.java b/src/main/java/forge/deck/CardPool.java index b66d50372e6..d1847eac0fc 100644 --- a/src/main/java/forge/deck/CardPool.java +++ b/src/main/java/forge/deck/CardPool.java @@ -17,10 +17,15 @@ */ package forge.deck; +import java.util.Iterator; import java.util.List; import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.NoSuchElementException; +import org.apache.commons.lang3.StringUtils; + import forge.Card; import forge.item.CardDb; import forge.item.CardPrinted; @@ -49,19 +54,6 @@ public class CardPool extends ItemPool { this.addAll(cards); } - /** - * Sets the. - * - * @param cardNames - * the card names - */ - public void set(final Iterable cardNames) { - this.clear(); - for (final String name : cardNames) { - this.add(name); - } - } - /** * Adds the. * @@ -71,7 +63,7 @@ public class CardPool extends ItemPool { public void add(final Card card) { this.add(CardDb.getCard(card)); } - + /** * Adds the. * @@ -131,13 +123,13 @@ public class CardPool extends ItemPool { * * @param cardName the card name */ - public void add(final String cardName) { + public void add(final String cardName, int cnt) { CardPrinted cp = CardDb.instance().tryGetCard(cardName); if ( cp == null ) cp = CardDb.variants().tryGetCard(cardName); if ( cp != null) - this.add(cp); + this.add(cp, cnt); else throw new NoSuchElementException(String.format("Card %s is not supported by Forge, as it's neither a known common card nor one of casual variants' card.", cardName)); } @@ -171,4 +163,32 @@ public class CardPool extends ItemPool { } return sb.append(']').toString(); } + + + public static CardPool fromCardList(final Iterable lines) { + CardPool pool = new CardPool(); + final Pattern p = Pattern.compile("((\\d+)\\s+)?(.*?)"); + + if (lines == null) { + return pool; + } + + final Iterator lineIterator = lines.iterator(); + while (lineIterator.hasNext()) { + final String line = lineIterator.next(); + if (line.startsWith(";") || line.startsWith("#")) { continue; } // that is a comment or not-yet-supported card + + final Matcher m = p.matcher(line.trim()); + m.matches(); + final String sCnt = m.group(2); + final String cardName = m.group(3); + if (StringUtils.isBlank(cardName)) { + continue; + } + + final int count = sCnt == null ? 1 : Integer.parseInt(sCnt); + pool.add(cardName, count); + } + return pool; + } } diff --git a/src/main/java/forge/deck/Deck.java b/src/main/java/forge/deck/Deck.java index 7d73c5b87e6..9ad3b367b34 100644 --- a/src/main/java/forge/deck/Deck.java +++ b/src/main/java/forge/deck/Deck.java @@ -27,9 +27,6 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeSet; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - import org.apache.commons.lang3.StringUtils; import com.google.common.base.Function; @@ -185,9 +182,7 @@ public class Deck extends DeckBase implements Iterable readCardList(final List lines) { - final List result = new ArrayList(); - final Pattern p = Pattern.compile("((\\d+)\\s+)?(.*?)"); - if (lines == null) { - return result; - } - - final Iterator lineIterator = lines.iterator(); - while (lineIterator.hasNext()) { - final String line = lineIterator.next(); - if (line.startsWith(";") || line.startsWith("#")) { continue; } // that is a comment or not-yet-supported card - - final Matcher m = p.matcher(line.trim()); - m.matches(); - final String sCnt = m.group(2); - final String cardName = m.group(3); - if (StringUtils.isBlank(cardName)) { - continue; - } - - final int count = sCnt == null ? 1 : Integer.parseInt(sCnt); - for (int i = 0; i < count; i++) { - result.add(cardName); - } - } - return result; - } private static List writeCardPool(final ItemPoolView pool) { final List> main2sort = pool.getOrderedList(); diff --git a/src/main/java/forge/gui/deckeditor/controllers/CDeckgen.java b/src/main/java/forge/gui/deckeditor/controllers/CDeckgen.java index f75f303de82..87d24410459 100644 --- a/src/main/java/forge/gui/deckeditor/controllers/CDeckgen.java +++ b/src/main/java/forge/gui/deckeditor/controllers/CDeckgen.java @@ -84,12 +84,12 @@ public enum CDeckgen implements ICDoc { Iterable source = Iterables.filter(CardDb.instance().getUniqueCards(), notBasicLand); randomDeck.getMain().addAllFlat(Aggregates.random(source, 15 * 5)); - randomDeck.getMain().add("Plains"); - randomDeck.getMain().add("Island"); - randomDeck.getMain().add("Swamp"); - randomDeck.getMain().add("Mountain"); - randomDeck.getMain().add("Forest"); - randomDeck.getMain().add("Terramorphic Expanse"); + randomDeck.getMain().add("Plains", 1); + randomDeck.getMain().add("Island", 1); + randomDeck.getMain().add("Swamp", 1); + randomDeck.getMain().add("Mountain", 1); + randomDeck.getMain().add("Forest", 1); + randomDeck.getMain().add("Terramorphic Expanse", 1); final ACEditorBase ed = (ACEditorBase) CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController(); diff --git a/src/main/java/forge/item/PrintSheet.java b/src/main/java/forge/item/PrintSheet.java index 36abe27081e..59ec78617ad 100644 --- a/src/main/java/forge/item/PrintSheet.java +++ b/src/main/java/forge/item/PrintSheet.java @@ -1,10 +1,16 @@ package forge.item; +import java.io.File; import java.util.List; import java.util.Map.Entry; import java.util.ArrayList; import java.util.Collection; + +import com.google.common.base.Function; + +import forge.deck.CardPool; import forge.util.MyRandom; +import forge.util.storage.StorageReaderFileSections; /** @@ -12,8 +18,23 @@ import forge.util.MyRandom; * */ public class PrintSheet { - private final ItemPool cardsWithWeights = new ItemPool(CardPrinted.class); + public static final Function FN_GET_KEY = new Function() { + @Override public final String apply(PrintSheet sheet) { return sheet.name; } + }; + + private final ItemPool cardsWithWeights; + + + private final String name; + public PrintSheet(String name0) { + this(name0, null); + } + + private PrintSheet(String name0, ItemPool pool) { + name = name0; + cardsWithWeights = pool != null ? pool : new ItemPool(CardPrinted.class); + } public void add(CardPrinted card) { add(card,1); @@ -67,5 +88,16 @@ public class PrintSheet { return result; } + public static class Reader extends StorageReaderFileSections { + public Reader(String fileName) { + super(fileName, PrintSheet.FN_GET_KEY); + } + + @Override + protected PrintSheet read(String title, Iterable body, int idx) { + return new PrintSheet(title, CardPool.fromCardList(body)); + } + + } } diff --git a/src/main/java/forge/model/FModel.java b/src/main/java/forge/model/FModel.java index 7a6e1ae4ebd..2c39f620ffa 100644 --- a/src/main/java/forge/model/FModel.java +++ b/src/main/java/forge/model/FModel.java @@ -42,6 +42,7 @@ import forge.game.MatchController; import forge.game.limited.GauntletMini; import forge.gauntlet.GauntletData; import forge.item.CardDb; +import forge.item.PrintSheet; import forge.properties.ForgePreferences; import forge.properties.ForgePreferences.FPref; import forge.properties.NewConstants; @@ -89,6 +90,7 @@ public enum FModel { private final IStorageView blocks; private final IStorageView fantasyBlocks; private final IStorageView worlds; + private final IStorageView printSheets; /** * Constructor. @@ -170,6 +172,8 @@ public enum FModel { this.decks = new CardCollections(); this.quest = new QuestController(); + + this.printSheets = new StorageView(new PrintSheet.Reader("res/blockdata/printsheets.txt")); } public final QuestController getQuest() { @@ -373,6 +377,10 @@ public enum FModel { return boosters; } + public IStorageView getPrintSheets() { + return printSheets; + } + /** * TODO: Write javadoc for this method. * @param data0 {@link forge.gauntlet.GauntletData} @@ -392,4 +400,6 @@ public enum FModel { } return gauntlet; } + + } diff --git a/src/main/java/forge/util/storage/StorageReaderFileSections.java b/src/main/java/forge/util/storage/StorageReaderFileSections.java new file mode 100644 index 00000000000..ef9d451816b --- /dev/null +++ b/src/main/java/forge/util/storage/StorageReaderFileSections.java @@ -0,0 +1,136 @@ +/* + * 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 . + */ +package forge.util.storage; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import javax.swing.JOptionPane; + +import org.apache.commons.lang3.StringUtils; + +import com.google.common.base.Function; + +import forge.util.FileUtil; +import forge.util.IItemReader; + +/** + * This class treats every line of a given file as a source for a named object. + * + * @param + * the generic type + */ +public abstract class StorageReaderFileSections implements IItemReader { + + private final File file; + private final Function keySelector; + + public StorageReaderFileSections(final String pathname, final Function keySelector0) { + this(new File(pathname), keySelector0); + } + + public StorageReaderFileSections(final File file0, final Function keySelector0) { + this.file = file0; + this.keySelector = keySelector0; + } + + /* (non-Javadoc) + * @see forge.util.IItemReader#readAll() + */ + @Override + public Map readAll() { + final Map result = new TreeMap(); + + int idx = 0; + Iterable file = FileUtil.readFile(this.file); + + List accumulator = new ArrayList(); + String header = null; + + for (final String s : file) { + if (!this.lineContainsObject(s)) { + continue; + } + + if(s.charAt(0) == '[') { + if( header != null ) { + // read previously collected item + T item = readItem(header, accumulator, idx); + if( item != null ) { + result.put(this.keySelector.apply(item), item); + idx++; + } + } + + header = StringUtils.strip(s, "[] "); + accumulator.clear(); + } else + accumulator.add(s); + } + + // store the last item + if ( !accumulator.isEmpty() ) { + T item = readItem(header, accumulator, idx); + if( item != null ) { + result.put(this.keySelector.apply(item), item); + } + } + return result; + } + + private final T readItem(String header, Iterable accumulator, int idx) { + final T item = this.read(header, accumulator, idx); + if (null != item) return item; + + final String msg = "An object stored in " + this.file.getPath() + " failed to load.\nPlease submit this as a bug with the mentioned file attached."; + JOptionPane.showMessageDialog(null, msg); + return null; + } + + /** + * TODO: Write javadoc for this method. + * + * @param line + * the line + * @return the t + */ + protected abstract T read(String title, Iterable body, int idx); + + /** + * Line contains object. + * + * @param line + * the line + * @return true, if successful + */ + protected boolean lineContainsObject(final String line) { + return !StringUtils.isBlank(line) && !line.trim().startsWith("#"); + } + + /* (non-Javadoc) + * @see forge.util.IItemReader#getItemKey(java.lang.Object) + */ + @Override + public String getItemKey(final T item) { + return this.keySelector.apply(item); + } + +}