From e5d2b805ea9cfc72b3c03df39842565f171e95d5 Mon Sep 17 00:00:00 2001 From: RumbleBBU Date: Fri, 5 Oct 2012 11:47:56 +0000 Subject: [PATCH] Added experimental 'limited Quest mode'. If selected, it will impose format-based restrictions on the available cards during the game. Current exceptions: theme decks in spell stores (deliberate). enemy decks (more in-format enemy decks would be needed first). --- .gitattributes | 1 + src/main/java/forge/card/CardEdition.java | 24 ++ src/main/java/forge/game/GameFormat.java | 18 ++ src/main/java/forge/game/GameFormatQuest.java | 221 ++++++++++++++++++ .../gui/home/quest/CSubmenuQuestData.java | 2 +- .../gui/home/quest/VSubmenuQuestData.java | 15 +- .../forge/gui/match/QuestWinLoseHandler.java | 65 ++++-- .../java/forge/quest/QuestController.java | 26 ++- src/main/java/forge/quest/QuestUtilCards.java | 62 ++++- src/main/java/forge/quest/data/QuestData.java | 24 +- src/main/java/forge/quest/io/QuestDataIO.java | 56 ++++- 11 files changed, 485 insertions(+), 29 deletions(-) create mode 100644 src/main/java/forge/game/GameFormatQuest.java diff --git a/.gitattributes b/.gitattributes index 3934187c470..a1c2934aefb 100644 --- a/.gitattributes +++ b/.gitattributes @@ -12592,6 +12592,7 @@ src/main/java/forge/error/ExceptionHandler.java svneol=native#text/plain src/main/java/forge/error/package-info.java svneol=native#text/plain src/main/java/forge/game/GameEndReason.java -text src/main/java/forge/game/GameFormat.java -text +src/main/java/forge/game/GameFormatQuest.java -text src/main/java/forge/game/GameLossReason.java -text src/main/java/forge/game/GameNew.java -text src/main/java/forge/game/GamePlayerRating.java -text diff --git a/src/main/java/forge/card/CardEdition.java b/src/main/java/forge/card/CardEdition.java index 1c9f83fd8a1..5d24ce7720d 100644 --- a/src/main/java/forge/card/CardEdition.java +++ b/src/main/java/forge/card/CardEdition.java @@ -22,6 +22,7 @@ import com.google.common.base.Predicate; import forge.Singletons; import forge.game.GameFormat; +import forge.game.GameFormatQuest; import forge.util.FileSection; import forge.util.StorageReaderFile; @@ -223,6 +224,29 @@ public final class CardEdition implements Comparable { // immutable return this.format.isSetLegal(subject.getCode()); } } + + /** + * Checks if is legal in quest format. + * + * @param qFormat the format + * @return the predicate + */ + public static final Predicate isLegalInFormatQuest(final GameFormatQuest qFormat) { + return new LegalInFormatQuest(qFormat); + } + + private static class LegalInFormatQuest implements Predicate { + private final GameFormatQuest qFormat; + + public LegalInFormatQuest(final GameFormatQuest fmt) { + this.qFormat = fmt; + } + + @Override + public boolean apply(final CardEdition subject) { + return this.qFormat.isSetLegal(subject.getCode()); + } + } } public static class Reader extends StorageReaderFile { diff --git a/src/main/java/forge/game/GameFormat.java b/src/main/java/forge/game/GameFormat.java index fcbe20c0acf..acabc24f32a 100644 --- a/src/main/java/forge/game/GameFormat.java +++ b/src/main/java/forge/game/GameFormat.java @@ -83,6 +83,24 @@ public final class GameFormat { return this.name; } + /** + * Gets the set list (for GameFormatQuest). + * + * @return list of allowed set codes + */ + public List getAllowedSetCodes() { + return this.allowedSetCodes; + } + + /** + * Gets the banned cards (for GameFormatQuest). + * + * @return list of banned card names + */ + public List getBannedCardNames() { + return this.bannedCardNames; + } + /** * Gets the filter rules. * diff --git a/src/main/java/forge/game/GameFormatQuest.java b/src/main/java/forge/game/GameFormatQuest.java new file mode 100644 index 00000000000..21b1730c587 --- /dev/null +++ b/src/main/java/forge/game/GameFormatQuest.java @@ -0,0 +1,221 @@ +/* + * Forge: Play Magic: the Gathering. + * Copyright (C) 2011 Forge Team + * + * 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.game; + +import java.util.List; +import java.util.ArrayList; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; + +import forge.card.CardRulesPredicates; +import forge.item.CardPrinted; + + +/** + * This is an alternate game format type, the main difference is that this + * is not immutable. This class is necessary because we may wish to update + * its contents in certain circumstances, and it was safer to create a new + * class than to make the preset game formats modifiable. + */ +public final class GameFormatQuest { + + private final String name; + // contains allowed sets, when empty allows all sets + private List allowedSetCodes; + private List bannedCardNames; + + private Predicate filterRules; + private Predicate filterPrinted; + + /** + * Instantiates a new game format based on an existing format. + * + * @param toCopy + * an existing format + */ + public GameFormatQuest(final GameFormat toCopy) { + this.name = new String(toCopy.getName()); + + this.allowedSetCodes = new ArrayList(); + allowedSetCodes.addAll(toCopy.getAllowedSetCodes()); + + this.bannedCardNames = new ArrayList(); + bannedCardNames.addAll(toCopy.getBannedCardNames()); + + this.filterRules = this.buildFilterRules(); + this.filterPrinted = this.buildFilterPrinted(); + } + + /** + * Instantiates an empty new game format. + * + * @param newName + * String, the name + */ + public GameFormatQuest(final String newName) { + this.name = new String(newName); + + this.allowedSetCodes = new ArrayList(); + this.bannedCardNames = new ArrayList(); + } + + + /** + * Instantiates a new game format based on two lists. + * + * @param newName + * String, the name + * @param setsToAllow + * List, these are the allowed sets + * @param cardsToBan + * List, these will be the banned cards + */ + public GameFormatQuest(final String newName, final List setsToAllow, final List cardsToBan) { + this.name = new String(newName); + + this.allowedSetCodes = new ArrayList(); + allowedSetCodes.addAll(setsToAllow); + + this.bannedCardNames = new ArrayList(); + bannedCardNames.addAll(cardsToBan); + + this.filterRules = this.buildFilterRules(); + this.filterPrinted = this.buildFilterPrinted(); + } + + private Predicate buildFilterPrinted() { + final Predicate banNames = CardPrinted.Predicates.namesExcept(this.bannedCardNames); + if (this.allowedSetCodes == null || this.allowedSetCodes.isEmpty()) { + return banNames; + } + return Predicates.and(banNames, CardPrinted.Predicates.printedInSets(this.allowedSetCodes, true)); + } + + private Predicate buildFilterRules() { + final Predicate banNames = CardPrinted.Predicates.namesExcept(this.bannedCardNames); + if (this.allowedSetCodes == null || this.allowedSetCodes.isEmpty()) { + return banNames; + } + return Predicates.and(banNames, Predicates.compose(CardRulesPredicates.wasPrintedInSets(this.allowedSetCodes), CardPrinted.FN_GET_RULES)); + } + + /** + * + * Updates the filters based on the current list data. + */ + public void updateFilters() { + this.filterRules = this.buildFilterRules(); + this.filterPrinted = this.buildFilterPrinted(); + } + + /** + * @param setCode + * the set code to add + */ + public void addAllowedSet(final String setCode) { + if (!allowedSetCodes.contains(setCode)) { + allowedSetCodes.add(setCode); + } + } + + /** + * @param banCard + * the card to ban + */ + public void addBannedCard(final String banCard) { + if (!bannedCardNames.contains(banCard)) { + bannedCardNames.add(banCard); + } + } + + /** + * Gets the name. + * + * @return the name + */ + public String getName() { + return this.name; + } + + /** + * Gets the filter rules. + * + * @return the filter rules + */ + public Predicate getFilterRules() { + return this.filterRules; + } + + /** + * Gets the filter printed. + * + * @return the filter printed + */ + public Predicate getFilterPrinted() { + return this.filterPrinted; + } + + /** + * Gets the set list. + * + * @return list of allowed set codes + */ + public List getAllowedSetCodes() { + return this.allowedSetCodes; + } + + /** + * Gets the banned cards. + * + * @return list of banned card names + */ + public List getBannedCardNames() { + return this.bannedCardNames; + } + + /** + * Checks if is sets the legal. + * + * @param setCode + * the set code + * @return true, if is sets the legal + */ + public boolean isSetLegal(final String setCode) { + return this.allowedSetCodes.isEmpty() || this.allowedSetCodes.contains(setCode); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return this.name + " (format)"; + } + + public static final Function FN_GET_NAME = new Function() { + @Override + public String apply(GameFormat arg1) { + return arg1.getName(); + } + }; + +} diff --git a/src/main/java/forge/gui/home/quest/CSubmenuQuestData.java b/src/main/java/forge/gui/home/quest/CSubmenuQuestData.java index bc0fcba1e8f..5d67a412bb3 100644 --- a/src/main/java/forge/gui/home/quest/CSubmenuQuestData.java +++ b/src/main/java/forge/gui/home/quest/CSubmenuQuestData.java @@ -158,7 +158,7 @@ public enum CSubmenuQuestData implements ICDoc { } // Give the user a few cards to build a deck - AllZone.getQuest().newGame(questName, difficulty, mode, startPool, rotatingFormat, startPrecon); + AllZone.getQuest().newGame(questName, difficulty, mode, startPool, rotatingFormat, startPrecon, view.getBoxPersist().isSelected()); AllZone.getQuest().save(); // Save in preferences. diff --git a/src/main/java/forge/gui/home/quest/VSubmenuQuestData.java b/src/main/java/forge/gui/home/quest/VSubmenuQuestData.java index d20c6f19b8a..d14ad82a324 100644 --- a/src/main/java/forge/gui/home/quest/VSubmenuQuestData.java +++ b/src/main/java/forge/gui/home/quest/VSubmenuQuestData.java @@ -61,6 +61,7 @@ public enum VSubmenuQuestData implements IVSubmenu { private final JRadioButton radExpert = new FRadioButton("Expert"); private final JCheckBox boxFantasy = new FCheckBox("Fantasy Mode"); + private final JCheckBox boxFormatPersist = new FCheckBox("Enforce format during quest"); private final JRadioButton radCompleteStart = new FRadioButton("Unrestricted Starting Pool"); private final JRadioButton radRotatingStart = new FRadioButton("Format: "); @@ -113,6 +114,7 @@ public enum VSubmenuQuestData implements IVSubmenu { public void actionPerformed(ActionEvent actionEvent) { cbxPrecon.setEnabled(radPreconStart.isSelected()); cbxFormat.setEnabled(radRotatingStart.isSelected()); + boxFormatPersist.setEnabled(radRotatingStart.isSelected()); } }; @@ -155,6 +157,8 @@ public enum VSubmenuQuestData implements IVSubmenu { radRotatingStart.addActionListener(preconListener); group3.add(radPreconStart); cbxFormat.setEnabled(false); + boxFormatPersist.setSelected(true); + boxFormatPersist.setEnabled(false); radPreconStart.addActionListener(preconListener); radCompleteStart.setSelected(true); cbxPrecon.setEnabled(false); @@ -177,9 +181,9 @@ public enum VSubmenuQuestData implements IVSubmenu { pnlOptions.add(radRotatingStart, constraints + ", wrap"); pnlOptions.add(radExpert, constraints + ", gap 7.5% 2.5% 0 0 "); pnlOptions.add(cbxFormat, constraints + ", gap 20 0, w 30%!, wrap"); + pnlOptions.add(boxFormatPersist, constraints + ", wrap, skip"); pnlOptions.add(radPreconStart, constraints + ", wrap, skip"); pnlOptions.add(cbxPrecon, "gap 20 0, w 30%!, h 35px!, wrap, skip"); - pnlOptions.add(btnEmbark, "w 40%!, h 30px!, gap 30% 0 20px 0, span 3 1"); // Final layout @@ -197,7 +201,7 @@ public enum VSubmenuQuestData implements IVSubmenu { pnlViewport.add(scr, "w 96%!, pushy, growy, gap 2% 0 0 30px"); pnlViewport.add(pnlTitleNew, "w 96%, h 36px!, gap 2% 0 0 10px"); - pnlViewport.add(pnlOptions, "w 96%!, h 250px!, gap 2% 0 0 20px"); + pnlViewport.add(pnlOptions, "w 96%!, h 280px!, gap 2% 0 0 20px"); scrContent.setBorder(null); } @@ -277,6 +281,13 @@ public enum VSubmenuQuestData implements IVSubmenu { return boxFantasy; } + /** + * @return {@link javax.swing.JCheckBox} + */ + public JCheckBox getBoxPersist() { + return boxFormatPersist; + } + /** * @return {@link javax.swing.JRadioButton} */ diff --git a/src/main/java/forge/gui/match/QuestWinLoseHandler.java b/src/main/java/forge/gui/match/QuestWinLoseHandler.java index 4adb1a35217..68c93729d1a 100644 --- a/src/main/java/forge/gui/match/QuestWinLoseHandler.java +++ b/src/main/java/forge/gui/match/QuestWinLoseHandler.java @@ -553,21 +553,9 @@ public class QuestWinLoseHandler extends ControlWinLose { */ private void awardBooster() { - // Do not enable booster selection in this way... - final boolean allowSetSelection = false; - - final List boosterTypes = new ArrayList(); - boosterTypes.add("Format"); - boosterTypes.add("Set"); - - final String prompt = "Choose bonus booster type:"; - Object o = null; - if (allowSetSelection) { - o = GuiChoose.one(prompt, boosterTypes); - } List cardsWon = null; - if (o == null || o.toString().equals(boosterTypes.get(0))) { + if (qData.getFormat() == null) { final List formats = new ArrayList(); String prefferedFormat = Singletons.getModel().getQuestPreferences().getPreference(QPref.BOOSTER_FORMAT); @@ -595,14 +583,59 @@ public class QuestWinLoseHandler extends ControlWinLose { final List sets = new ArrayList(); for (BoosterData bd : Singletons.getModel().getBoosters()) { - sets.add(bd.getEdition()); + if (qData.getFormat().isSetLegal(bd.getEdition())) { + sets.add(bd.getEdition()); + } } + + List chooseSets = new ArrayList(); + + int maxChoices = 1; + + if (this.wonMatch) { + maxChoices++; + final int wins = qData.getAchievements().getWin(); + if (wins > 0 && wins % 5 == 0) { maxChoices++; } + if (wins > 0 && wins % 20 == 0) { maxChoices++; } + if (wins > 0 && wins % 50 == 0) { maxChoices++; } + } + + if (sets.size() > maxChoices) { + if (maxChoices > 1) { + Boolean[] choices = new Boolean[sets.size()]; + for (int i = 0; i < sets.size(); i++) { + choices[i] = false; + } + + int toEnable = maxChoices; + + while (toEnable > 0) { + int index = MyRandom.getRandom().nextInt(sets.size()); + if (!choices[index]) { + choices[index] = true; + toEnable--; + } + } + + for (int i = 0; i < sets.size(); i++) { + if (choices[i]) { + chooseSets.add(sets.get(i)); + } + } + } else { + chooseSets.add(sets.get(MyRandom.getRandom().nextInt(sets.size()))); + } + + } else { + chooseSets.addAll(sets); + } + final String setPrompt = "Choose bonus booster set:"; - final String chSet = GuiChoose.one(setPrompt, sets); + final String chSet = GuiChoose.one(setPrompt, chooseSets); cardsWon = (new UnOpenedProduct(Singletons.getModel().getBoosters().get(chSet))).open(); qData.getCards().addAllCards(cardsWon); - this.lblTemp1 = new TitleLabel("Bonus booster pack from the \"" + chSet + "\" booster!"); + this.lblTemp1 = new TitleLabel("Bonus \"" + chSet + "\" booster pack!"); } if (cardsWon != null) { diff --git a/src/main/java/forge/quest/QuestController.java b/src/main/java/forge/quest/QuestController.java index 37302341f8a..5bf03af1369 100644 --- a/src/main/java/forge/quest/QuestController.java +++ b/src/main/java/forge/quest/QuestController.java @@ -25,6 +25,7 @@ import com.google.common.base.Predicates; import forge.Singletons; import forge.deck.Deck; +import forge.game.GameFormatQuest; import forge.item.CardPrinted; import forge.item.PreconDeck; import forge.properties.ForgeProps; @@ -54,6 +55,8 @@ public class QuestController { // complex private QuestUtilCards myCards; + private GameFormatQuest questFormat; + private QuestEvent currentEvent; /** The decks. */ @@ -125,6 +128,15 @@ public class QuestController { return this.decks; } + /** + * Gets the current format if any. + * + * @return GameFormatQuest, the game format (if persistent). + */ + public GameFormatQuest getFormat() { + return this.questFormat; + } + /** * Gets the current event. * @@ -162,8 +174,12 @@ public class QuestController { // These are helper classes that hold no data. this.decks = this.model == null ? null : this.model.getAssets().getDeckStorage(); this.myCards = this.model == null ? null : new QuestUtilCards(this); + this.questFormat = this.model == null ? null : this.model.getFormat(); this.currentEvent = null; + // if (questFormat == null) { System.out.println("No quest."); } + // else { System.out.println("Quest = " + questFormat.getName()); } + this.getChallengesManager().randomizeOpponents(); this.getDuelsManager().randomizeOpponents(); } @@ -195,11 +211,17 @@ public class QuestController { * @param startPool the start type * @param startFormat the format of starting pool * @param preconName the precon name + * @param persist + * enforce the format for the whole quest */ public void newGame(final String name, final int diff, final QuestMode mode, final QuestStartPool startPool, - final String startFormat, final String preconName) { + final String startFormat, final String preconName, final boolean persist) { - this.load(new QuestData(name, diff, mode)); + if (persist && startPool == QuestStartPool.Rotating) { + this.load(new QuestData(name, diff, mode, startFormat)); + } else { + this.load(new QuestData(name, diff, mode, null)); + } final Predicate filter; switch (startPool) { diff --git a/src/main/java/forge/quest/QuestUtilCards.java b/src/main/java/forge/quest/QuestUtilCards.java index 07dcd8bab61..0d04321ee78 100644 --- a/src/main/java/forge/quest/QuestUtilCards.java +++ b/src/main/java/forge/quest/QuestUtilCards.java @@ -20,8 +20,11 @@ package forge.quest; import forge.Singletons; import forge.card.BoosterGenerator; import forge.card.CardEdition; +import forge.card.CardRules; +import forge.card.CardRulesPredicates; import forge.card.FormatCollection; import forge.deck.Deck; +import forge.game.GameFormatQuest; import forge.item.*; import forge.quest.bazaar.QuestItemType; import forge.quest.data.QuestAssets; @@ -145,7 +148,12 @@ public final class QuestUtilCards { * @return the card printed */ public CardPrinted addRandomRare() { - final CardPrinted card = Aggregates.random(Iterables.filter(CardDb.instance().getAllCards(), QuestUtilCards.RARE_PREDICATE)); + Predicate myFilter = QuestUtilCards.RARE_PREDICATE; + + if (qc.getFormat() != null) { + myFilter = Predicates.and(QuestUtilCards.RARE_PREDICATE, qc.getFormat().getFilterPrinted()); + } + final CardPrinted card = Aggregates.random(Iterables.filter(CardDb.instance().getAllCards(), myFilter)); this.addSingleCard(card); return card; } @@ -158,7 +166,13 @@ public final class QuestUtilCards { * @return the list */ public List addRandomRare(final int n) { - final List newCards = Aggregates.random(Iterables.filter(CardDb.instance().getAllCards(), QuestUtilCards.RARE_PREDICATE), n); + Predicate myFilter = QuestUtilCards.RARE_PREDICATE; + + if (qc.getFormat() != null) { + myFilter = Predicates.and(QuestUtilCards.RARE_PREDICATE, qc.getFormat().getFilterPrinted()); + } + + final List newCards = Aggregates.random(Iterables.filter(CardDb.instance().getAllCards(), myFilter), n); this.addAllCards(newCards); return newCards; } @@ -338,6 +352,17 @@ public final class QuestUtilCards { private final Predicate filterNotExt = Predicates.and(CardEdition.Predicates.CAN_MAKE_BOOSTER, Predicates.not(this.filterExt)); + /** + * Helper predicate for shops: is legal in quest format. + * + * @param qFormat + * the quest format + * @return the predicate + */ + public static Predicate isLegalInQuestFormat(final GameFormatQuest qFormat) { + return CardEdition.Predicates.isLegalInFormatQuest(qFormat); + } + /** * Generate boosters in shop. * @@ -347,8 +372,11 @@ public final class QuestUtilCards { public void generateBoostersInShop(final int count) { for (int i = 0; i < count; i++) { final int rollD100 = MyRandom.getRandom().nextInt(100); - final Predicate filter = rollD100 < 40 ? this.filterT2booster + Predicate filter = rollD100 < 40 ? this.filterT2booster : (rollD100 < 75 ? this.filterExtButT2 : this.filterNotExt); + if (qc.getFormat() != null) { + filter = isLegalInQuestFormat(qc.getFormat()); + } Iterable rightEditions = Iterables.filter(Singletons.getModel().getEditions(), filter); this.qa.getShopList().add(BoosterPack.FN_FROM_SET.apply(Aggregates.random(rightEditions))); } @@ -361,12 +389,26 @@ public final class QuestUtilCards { * the count */ public void generateTournamentsInShop(final int count) { - Iterable rightEditions = Iterables.filter(Singletons.getModel().getEditions(), CardEdition.Predicates.HAS_TOURNAMENT_PACK); + Predicate formatFilter = CardEdition.Predicates.HAS_TOURNAMENT_PACK; + if (qc.getFormat() != null) { + formatFilter = Predicates.and(formatFilter, isLegalInQuestFormat(qc.getFormat())); + } + Iterable rightEditions = Iterables.filter(Singletons.getModel().getEditions(), formatFilter); this.qa.getShopList().addAllFlat(Aggregates.random(Iterables.transform(rightEditions, TournamentPack.FN_FROM_SET), count)); } + /** + * Generate precons in shop. + * + * @param count + * the count + */ public void generateFatPacksInShop(final int count) { - Iterable rightEditions = Iterables.filter(Singletons.getModel().getEditions(), CardEdition.Predicates.HAS_FAT_PACK); + Predicate formatFilter = CardEdition.Predicates.HAS_FAT_PACK; + if (qc.getFormat() != null) { + formatFilter = Predicates.and(formatFilter, isLegalInQuestFormat(qc.getFormat())); + } + Iterable rightEditions = Iterables.filter(Singletons.getModel().getEditions(), formatFilter); this.qa.getShopList().addAllFlat(Aggregates.random(Iterables.transform(rightEditions, FatPack.FN_FROM_SET), count)); } @@ -390,7 +432,15 @@ public final class QuestUtilCards { * Generate cards in shop. */ public void generateCardsInShop() { - final BoosterGenerator pack = new BoosterGenerator(CardDb.instance().getAllCards()); + + Iterable cardList = null; + if (qc.getFormat() == null) { + cardList = CardDb.instance().getAllCards(); } + else { + cardList = Iterables.filter(CardDb.instance().getAllCards(), qc.getFormat().getFilterPrinted()); + } + + final BoosterGenerator pack = new BoosterGenerator(cardList); int nLevel = this.qc.getAchievements().getLevel(); diff --git a/src/main/java/forge/quest/data/QuestData.java b/src/main/java/forge/quest/data/QuestData.java index 2866def2221..91d5c28a880 100644 --- a/src/main/java/forge/quest/data/QuestData.java +++ b/src/main/java/forge/quest/data/QuestData.java @@ -17,6 +17,8 @@ */ package forge.quest.data; +import forge.Singletons; +import forge.game.GameFormatQuest; import forge.quest.QuestMode; import forge.quest.io.QuestDataIO; @@ -43,6 +45,7 @@ public final class QuestData { /** The version number. */ private int versionNumber = QuestData.CURRENT_VERSION_NUMBER; + private GameFormatQuest format; private final String name; // Quest mode - there should be an enum :( @@ -58,12 +61,22 @@ public final class QuestData { /** * Instantiates a new quest data. * @param mode2 + * quest mode * @param diff + * achievement diff * @param name2 + * quest name + * @param formatString + * String, persistent format for the quest (null if none). */ - public QuestData(String name2, int diff, QuestMode mode2) { + public QuestData(String name2, int diff, QuestMode mode2, final String formatString) { this.name = name2; + if (formatString == null) { + format = null; + } else { + format = new GameFormatQuest(Singletons.getModel().getFormats().getFormat(formatString)); + } this.mode = mode2; this.achievements = new QuestAchievements(diff); this.assets = new QuestAssets(); @@ -78,6 +91,15 @@ public final class QuestData { return this.mode; } + /** + * Gets the persistent format, null if not assigned. + * + * @return GameFormatQuest, the persistent format + */ + public GameFormatQuest getFormat() { + return this.format; + } + // SERIALIZATION - related things // This must be called by XML-serializer via reflection diff --git a/src/main/java/forge/quest/io/QuestDataIO.java b/src/main/java/forge/quest/io/QuestDataIO.java index d082a675408..6d7900bc218 100644 --- a/src/main/java/forge/quest/io/QuestDataIO.java +++ b/src/main/java/forge/quest/io/QuestDataIO.java @@ -57,6 +57,7 @@ import forge.card.CardEdition; import forge.deck.DeckSection; import forge.error.ErrorViewer; import forge.game.GameType; +import forge.game.GameFormatQuest; import forge.item.BoosterPack; import forge.item.CardDb; import forge.item.CardPrinted; @@ -98,6 +99,7 @@ public class QuestDataIO { xStream.registerConverter(new ItemPoolToXml()); xStream.registerConverter(new DeckSectionToXml()); xStream.registerConverter(new GameTypeToXml()); + xStream.registerConverter(new GameFormatQuestToXml()); xStream.registerConverter(new QuestModeToXml()); xStream.autodetectAnnotations(true); xStream.alias("CardPool", ItemPool.class); @@ -351,7 +353,7 @@ public class QuestDataIO { final File f = new File(ForgeProps.getFile(NewConstants.Quest.DATA_DIR), qd.getName()); QuestDataIO.savePacked(f + ".dat", xStream, qd); - //QuestDataIO.saveUnpacked(f + ".xml", xStream, qd); + // QuestDataIO.saveUnpacked(f + ".xml", xStream, qd); } catch (final Exception ex) { ErrorViewer.showError(ex, "Error saving Quest Data."); @@ -375,6 +377,58 @@ public class QuestDataIO { boutUnp.close(); } + private static class GameFormatQuestToXml implements Converter { + @SuppressWarnings("rawtypes") + @Override + public boolean canConvert(final Class clasz) { + return clasz.equals(GameFormatQuest.class); + } + + @Override + public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) { + + writer.startNode("format"); + GameFormatQuest format = (GameFormatQuest) source; + writer.addAttribute("name", format.getName()); + writer.endNode(); + + for (String set : format.getAllowedSetCodes()) { + writer.startNode("set"); + writer.addAttribute("s", set); + writer.endNode(); + } + for (String ban : format.getBannedCardNames()) { + writer.startNode("ban"); + writer.addAttribute("s", ban); + writer.endNode(); + } + } + + @Override + public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) { + reader.moveDown(); + GameFormatQuest format = new GameFormatQuest(reader.getAttribute("name")); + reader.moveUp(); + while (reader.hasMoreChildren()) { + reader.moveDown(); + final String nodename = reader.getNodeName(); + if (nodename.equals("ban")) { + String toBan = reader.getAttribute("s"); + format.addBannedCard(toBan); + // System.out.println("Added + " + toBan + " to banned cards"); + } + else if (nodename.equals("set")) { + String toSets = reader.getAttribute("s"); + format.addAllowedSet(toSets); + // System.out.println("Added + " + toSets + " to legal sets"); + } + reader.moveUp(); + } + format.updateFilters(); + return format; + } + } + private static class GameTypeToXml implements Converter { @SuppressWarnings("rawtypes") @Override