diff --git a/.gitattributes b/.gitattributes index 096e0b7e24d..2f4433abc0d 100644 --- a/.gitattributes +++ b/.gitattributes @@ -820,6 +820,8 @@ forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorDraf forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorLimited.java -text forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuest.java -text forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuestCardShop.java -text +forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuestDraftingProcess.java -text +forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuestLimited.java -text forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorVariant.java -text forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CProbabilities.java -text forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CStatistics.java -text @@ -858,10 +860,13 @@ forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuChallenges.java forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuDuels.java -text forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestData.java -text forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestDecks.java -text +forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestDraft.java -text forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestPrefs.java -text forge-gui-desktop/src/main/java/forge/screens/home/quest/DialogChooseSets.java -text forge-gui-desktop/src/main/java/forge/screens/home/quest/IVQuestStats.java -text +forge-gui-desktop/src/main/java/forge/screens/home/quest/PnlDraftEvent.java -text forge-gui-desktop/src/main/java/forge/screens/home/quest/PnlEvent.java -text +forge-gui-desktop/src/main/java/forge/screens/home/quest/QuestDraftUtils.java -text forge-gui-desktop/src/main/java/forge/screens/home/quest/QuestFileLister.java -text forge-gui-desktop/src/main/java/forge/screens/home/quest/QuestPreferencesHandler.java -text forge-gui-desktop/src/main/java/forge/screens/home/quest/SSubmenuQuestUtil.java -text @@ -869,6 +874,7 @@ forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuChallenges.java forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuDuels.java -text forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuQuestData.java -text forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuQuestDecks.java -text +forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuQuestDraft.java -text forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuQuestPrefs.java -text forge-gui-desktop/src/main/java/forge/screens/home/quest/ViewItem.java -text forge-gui-desktop/src/main/java/forge/screens/home/quest/ViewStall.java -text @@ -896,6 +902,7 @@ forge-gui-desktop/src/main/java/forge/screens/match/ControlWinLose.java -text forge-gui-desktop/src/main/java/forge/screens/match/GameLogPanel.java -text forge-gui-desktop/src/main/java/forge/screens/match/GauntletWinLose.java -text forge-gui-desktop/src/main/java/forge/screens/match/LimitedWinLose.java -text +forge-gui-desktop/src/main/java/forge/screens/match/QuestDraftWinLose.java -text forge-gui-desktop/src/main/java/forge/screens/match/QuestWinLose.java -text forge-gui-desktop/src/main/java/forge/screens/match/QuestWinLoseCardViewer.java -text forge-gui-desktop/src/main/java/forge/screens/match/TargetingOverlay.java -text @@ -16437,10 +16444,12 @@ forge-gui/src/main/java/forge/properties/package-info.java svneol=native#text/pl forge-gui/src/main/java/forge/quest/BoosterUtils.java svneol=native#text/plain forge-gui/src/main/java/forge/quest/IQuestRewardCard.java -text forge-gui/src/main/java/forge/quest/QuestController.java -text +forge-gui/src/main/java/forge/quest/QuestDeckGroupMap.java -text forge-gui/src/main/java/forge/quest/QuestDeckMap.java -text forge-gui/src/main/java/forge/quest/QuestEvent.java -text forge-gui/src/main/java/forge/quest/QuestEventChallenge.java svneol=native#text/plain forge-gui/src/main/java/forge/quest/QuestEventDifficulty.java -text +forge-gui/src/main/java/forge/quest/QuestEventDraft.java -text forge-gui/src/main/java/forge/quest/QuestEventDuel.java svneol=native#text/plain forge-gui/src/main/java/forge/quest/QuestEventDuelManager.java -text forge-gui/src/main/java/forge/quest/QuestMode.java -text @@ -16473,6 +16482,7 @@ forge-gui/src/main/java/forge/quest/data/GameFormatQuest.java -text forge-gui/src/main/java/forge/quest/data/QuestAchievements.java -text forge-gui/src/main/java/forge/quest/data/QuestAssets.java -text forge-gui/src/main/java/forge/quest/data/QuestData.java svneol=native#text/plain +forge-gui/src/main/java/forge/quest/data/QuestEventDraftContainer.java -text forge-gui/src/main/java/forge/quest/data/QuestItemCondition.java -text forge-gui/src/main/java/forge/quest/data/QuestPreferences.java svneol=native#text/plain forge-gui/src/main/java/forge/quest/data/package-info.java svneol=native#text/plain diff --git a/forge-game/src/main/java/forge/game/GameType.java b/forge-game/src/main/java/forge/game/GameType.java index cb4678a2f95..203a082f1f0 100644 --- a/forge-game/src/main/java/forge/game/GameType.java +++ b/forge-game/src/main/java/forge/game/GameType.java @@ -13,6 +13,7 @@ public enum GameType { Draft (DeckFormat.Limited, true, true, true, "Draft"), Gauntlet (DeckFormat.Limited, true, true, true, "Gauntlet"), Quest (DeckFormat.QuestDeck, true, true, false, "Quest"), + QuestDraft (DeckFormat.Limited, true, true, true, "Quest Draft"), Constructed (DeckFormat.Constructed, false, true, true, "Constructed"), Vanguard (DeckFormat.Vanguard, true, true, true, "Vanguard"), Commander (DeckFormat.Commander, false, false, false, "Commander"), diff --git a/forge-gui-desktop/src/main/java/forge/GuiDesktop.java b/forge-gui-desktop/src/main/java/forge/GuiDesktop.java index e1c3217a9a0..cac34d5e0f8 100644 --- a/forge-gui-desktop/src/main/java/forge/GuiDesktop.java +++ b/forge-gui-desktop/src/main/java/forge/GuiDesktop.java @@ -75,6 +75,9 @@ import forge.util.BuildInfo; import forge.util.ITriggerEvent; public class GuiDesktop implements IGuiBase { + + private boolean showOverlay = true; + @Override public void invokeInEdtLater(Runnable proc) { SwingUtilities.invokeLater(proc); @@ -212,11 +215,23 @@ public class GuiDesktop implements IGuiBase { h.getLayoutControl().updateHand(); } } + + @Override + public void disableOverlay() { + showOverlay = false; + } + + @Override + public void enableOverlay() { + showOverlay = true; + } @Override public void finishGame() { new ViewWinLose(Singletons.getControl().getObservedGame()); - SOverlayUtils.showOverlay(); + if (showOverlay) { + SOverlayUtils.showOverlay(); + } } @Override diff --git a/forge-gui-desktop/src/main/java/forge/gui/framework/EDocID.java b/forge-gui-desktop/src/main/java/forge/gui/framework/EDocID.java index cfc03353213..987e78bc41f 100644 --- a/forge-gui-desktop/src/main/java/forge/gui/framework/EDocID.java +++ b/forge-gui-desktop/src/main/java/forge/gui/framework/EDocID.java @@ -43,6 +43,7 @@ public enum EDocID { /** */ WORKSHOP_CARDDESIGNER (VCardDesigner.SINGLETON_INSTANCE), /** */ WORKSHOP_CARDSCRIPT (VCardScript.SINGLETON_INSTANCE), /** */ + HOME_QUESTDRAFTS (VSubmenuQuestDraft.SINGLETON_INSTANCE), /** */ HOME_QUESTCHALLENGES (VSubmenuChallenges.SINGLETON_INSTANCE), /** */ HOME_QUESTDUELS (VSubmenuDuels.SINGLETON_INSTANCE), /** */ HOME_QUESTDATA (VSubmenuQuestData.SINGLETON_INSTANCE), /** */ diff --git a/forge-gui-desktop/src/main/java/forge/gui/framework/FScreen.java b/forge-gui-desktop/src/main/java/forge/gui/framework/FScreen.java index cf542c5d0d5..977259b14a1 100644 --- a/forge-gui-desktop/src/main/java/forge/gui/framework/FScreen.java +++ b/forge-gui-desktop/src/main/java/forge/gui/framework/FScreen.java @@ -113,6 +113,14 @@ public enum FScreen { true, "Close Editor", ForgeConstants.EDITOR_LAYOUT_FILE), + DECK_EDITOR_QUEST_TOURNAMENT( + VDeckEditorUI.SINGLETON_INSTANCE, + CDeckEditorUI.SINGLETON_INSTANCE, + "Quest Tournament Deck Editor", + FSkin.getImage(FSkinProp.IMG_PACK), + true, + "Close Editor", + ForgeConstants.EDITOR_LAYOUT_FILE), QUEST_CARD_SHOP( VDeckEditorUI.SINGLETON_INSTANCE, CDeckEditorUI.SINGLETON_INSTANCE, diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuestDraftingProcess.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuestDraftingProcess.java new file mode 100644 index 00000000000..ebf346d85d3 --- /dev/null +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuestDraftingProcess.java @@ -0,0 +1,318 @@ +/* + * 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.screens.deckeditor.controllers; + +import java.util.Map.Entry; + +import forge.card.MagicColor; +import forge.deck.Deck; +import forge.deck.DeckGroup; +import forge.deck.DeckSection; +import forge.gui.framework.DragCell; +import forge.gui.framework.FScreen; +import forge.item.PaperCard; +import forge.itemmanager.CardManager; +import forge.itemmanager.ItemManagerConfig; +import forge.limited.BoosterDraft; +import forge.limited.IBoosterDraft; +import forge.model.FModel; +import forge.properties.ForgePreferences.FPref; +import forge.screens.deckeditor.views.VAllDecks; +import forge.screens.deckeditor.views.VCurrentDeck; +import forge.screens.deckeditor.views.VDeckgen; +import forge.screens.home.quest.CSubmenuQuestDraft; +import forge.toolbox.FOptionPane; +import forge.util.ItemPool; +import forge.util.MyRandom; + +/** + * Updates the deck editor UI as necessary draft selection mode. + * + *

(C at beginning of class name denotes a control class.) + * + * @author Forge + * @version $Id: CEditorDraftingProcess.java 24872 2014-02-17 07:35:47Z drdev $ + */ +public class CEditorQuestDraftingProcess extends ACEditorBase { + + private CSubmenuQuestDraft testDraftQuest; + + public void setDraftQuest(CSubmenuQuestDraft testDraftQuest) { + this.testDraftQuest = testDraftQuest; + } + + private IBoosterDraft boosterDraft; + + private String ccAddLabel = "Add card"; + private DragCell allDecksParent = null; + private DragCell deckGenParent = null; + private boolean saved = false; + + //========== Constructor + + /** + * Updates the deck editor UI as necessary draft selection mode. + */ + public CEditorQuestDraftingProcess() { + super(FScreen.DRAFTING_PROCESS); + + final CardManager catalogManager = new CardManager(false); + final CardManager deckManager = new CardManager(false); + + //hide filters and options panel so more of pack is visible by default + catalogManager.setHideViewOptions(1, true); + + deckManager.setCaption("Draft Picks"); + + catalogManager.setAlwaysNonUnique(true); + deckManager.setAlwaysNonUnique(true); + + this.setCatalogManager(catalogManager); + this.setDeckManager(deckManager); + } + + /** + * Show gui. + * + * @param inBoosterDraft + * the in_booster draft + */ + public final void showGui(final IBoosterDraft inBoosterDraft) { + this.boosterDraft = inBoosterDraft; + } + + /* (non-Javadoc) + * @see forge.gui.deckeditor.ACEditorBase#onAddItems() + */ + @Override + protected void onAddItems(Iterable> items, boolean toAlternate) { + if (toAlternate) { return; } + + // can only draft one at a time, regardless of the requested quantity + PaperCard card = items.iterator().next().getKey(); + this.getDeckManager().addItem(card, 1); + + // get next booster pack + this.boosterDraft.setChoice(card); + + if (this.boosterDraft.hasNextChoice()) { + this.showChoices(this.boosterDraft.nextChoice()); + } + else { + this.boosterDraft.finishedDrafting(); + this.saveDraft(); + } + } + + /* (non-Javadoc) + * @see forge.gui.deckeditor.ACEditorBase#onRemoveItems() + */ + @Override + protected void onRemoveItems(Iterable> items, boolean toAlternate) { + } + + @Override + protected void buildAddContextMenu(EditorContextMenuBuilder cmb) { + cmb.addMoveItems("Draft", null); + } + + @Override + protected void buildRemoveContextMenu(EditorContextMenuBuilder cmb) { + // no valid remove options + } + + /** + *

+ * showChoices. + *

+ * + * @param list + * a {@link forge.CardList} object. + */ + private void showChoices(final ItemPool list) { + int packNumber = ((BoosterDraft) boosterDraft).getCurrentBoosterIndex() + 1; + + this.getCatalogManager().setCaption("Pack " + packNumber + " - Cards"); + this.getCatalogManager().setPool(list); + } // showChoices() + + /** + *

+ * getPlayersDeck. + *

+ * + * @return a {@link forge.deck.Deck} object. + */ + public Deck getPlayersDeck() { + final Deck deck = new Deck(); + + // add sideboard to deck + deck.getOrCreate(DeckSection.Sideboard).addAll(this.getDeckManager().getPool()); + + final String landSet = IBoosterDraft.LAND_SET_CODE[0].getCode(); + final boolean isZendikarSet = landSet.equals("ZEN"); // we want to generate one kind of Zendikar lands at a time only + final boolean zendikarSetMode = MyRandom.getRandom().nextBoolean(); + + final int landsCount = 10; + + for(String landName : MagicColor.Constant.BASIC_LANDS) { + int numArt = FModel.getMagicDb().getCommonCards().getArtCount(landName, landSet); + int minArtIndex = isZendikarSet ? (zendikarSetMode ? 1 : 5) : 1; + int maxArtIndex = isZendikarSet ? minArtIndex + 3 : numArt; + + if (FModel.getPreferences().getPrefBoolean(FPref.UI_RANDOM_ART_IN_POOLS)) { + for (int i = minArtIndex; i <= maxArtIndex; i++) { + deck.get(DeckSection.Sideboard).add(landName, landSet, i, numArt > 1 ? landsCount : 30); + } + } else { + deck.get(DeckSection.Sideboard).add(landName, landSet, 30); + } + } + + return deck; + } // getPlayersDeck() + + /** + *

+ * saveDraft. + *

+ */ + private void saveDraft() { + + String s = "Tournament Deck"; + + saved = true; + + // Construct computer's decks and save draft + final Deck[] computer = this.boosterDraft.getDecks(); + + final DeckGroup finishedDraft = new DeckGroup(s); + finishedDraft.setHumanDeck((Deck) this.getPlayersDeck().copyTo(s)); + finishedDraft.addAiDecks(computer); + + CSubmenuQuestDraft.SINGLETON_INSTANCE.update(); + FScreen.DRAFTING_PROCESS.close(); + + testDraftQuest.setCompletedDraft(finishedDraft, s); + + } + + //========== Overridden from ACEditorBase + + @Override + protected CardLimit getCardLimit() { + return CardLimit.None; + } + + /* + * (non-Javadoc) + * + * @see forge.gui.deckeditor.ACEditorBase#getController() + */ + @Override + public DeckController getDeckController() { + return null; + } + + /* + * (non-Javadoc) + * + * @see forge.gui.deckeditor.ACEditorBase#updateView() + */ + @Override + public void resetTables() { + } + + /* + * (non-Javadoc) + * + * @see forge.gui.deckeditor.ACEditorBase#show(forge.Command) + */ + @Override + public void update() { + this.getCatalogManager().setup(ItemManagerConfig.DRAFT_PACK); + this.getDeckManager().setup(ItemManagerConfig.DRAFT_POOL); + + ccAddLabel = this.getBtnAdd().getText(); + + if (this.getDeckManager().getPool() == null) { //avoid showing next choice or resetting pool if just switching back to Draft screen + this.showChoices(this.boosterDraft.nextChoice()); + this.getDeckManager().setPool((Iterable) null); + } + else { + this.showChoices(this.getCatalogManager().getPool()); + } + + //Remove buttons + this.getBtnAdd().setVisible(false); + this.getBtnAdd4().setVisible(false); + this.getBtnRemove().setVisible(false); + this.getBtnRemove4().setVisible(false); + + this.getBtnCycleSection().setVisible(false); + + VCurrentDeck.SINGLETON_INSTANCE.getPnlHeader().setVisible(false); + + deckGenParent = removeTab(VDeckgen.SINGLETON_INSTANCE); + allDecksParent = removeTab(VAllDecks.SINGLETON_INSTANCE); + + // set catalog table to single-selection only mode + getCatalogManager().setAllowMultipleSelections(false); + } + + /* (non-Javadoc) + * @see forge.gui.deckeditor.controllers.ACEditorBase#canSwitchAway() + */ + @Override + public boolean canSwitchAway(boolean isClosing) { + if (isClosing && !saved) { + String userPrompt = + "This will end the current draft and you will not be able to resume.\n\n" + + "Leave anyway?"; + return FOptionPane.showConfirmDialog(userPrompt, "Leave Draft?", "Leave", "Cancel", false); + } + return true; + } + + /* (non-Javadoc) + * @see forge.gui.deckeditor.controllers.ACEditorBase#resetUIChanges() + */ + @Override + public void resetUIChanges() { + //Re-rename buttons + this.getBtnAdd().setText(ccAddLabel); + + //Re-add buttons + this.getBtnAdd4().setVisible(true); + this.getBtnRemove().setVisible(true); + this.getBtnRemove4().setVisible(true); + + VCurrentDeck.SINGLETON_INSTANCE.getPnlHeader().setVisible(true); + + //Re-add tabs + if (deckGenParent != null) { + deckGenParent.addDoc(VDeckgen.SINGLETON_INSTANCE); + } + if (allDecksParent != null) { + allDecksParent.addDoc(VAllDecks.SINGLETON_INSTANCE); + } + + // set catalog table back to free-selection mode + getCatalogManager().setAllowMultipleSelections(true); + } +} diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuestLimited.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuestLimited.java new file mode 100644 index 00000000000..db155bfd4c0 --- /dev/null +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuestLimited.java @@ -0,0 +1,299 @@ +/* + * 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.screens.deckeditor.controllers; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; + +import forge.deck.Deck; +import forge.deck.DeckGroup; +import forge.deck.DeckSection; +import forge.gui.framework.DragCell; +import forge.gui.framework.FScreen; +import forge.item.InventoryItem; +import forge.item.PaperCard; +import forge.itemmanager.CardManager; +import forge.itemmanager.ColumnDef; +import forge.itemmanager.ItemManagerConfig; +import forge.itemmanager.views.ItemTableColumn; +import forge.model.FModel; +import forge.properties.ForgePreferences.FPref; +import forge.quest.QuestController; +import forge.quest.QuestEventDraft; +import forge.screens.deckeditor.SEditorIO; +import forge.screens.deckeditor.views.VAllDecks; +import forge.screens.deckeditor.views.VCurrentDeck; +import forge.screens.deckeditor.views.VDeckgen; +import forge.screens.home.quest.CSubmenuQuestDecks; + +//import forge.quest.data.QuestBoosterPack; + +/** + * Child controller for quest deck editor UI. + *

+ * Card catalog and decks are drawn from a QuestController object. + * + *

(C at beginning of class name denotes a control class.) + * + * @author Forge + * @version $Id: CEditorQuest.java 24868 2014-02-17 05:08:05Z drdev $ + */ +public final class CEditorQuestLimited extends ACEditorBase { + private final QuestController questData; + private final DeckController controller; + private final List allSections = new ArrayList(); + private DragCell allDecksParent = null; + private DragCell deckGenParent = null; + + private Map decksUsingMyCards; + + private final Function, Comparable> fnDeckCompare = new Function, Comparable>() { + @Override + public Comparable apply(final Entry from) { + final Integer iValue = decksUsingMyCards.get(from.getKey()); + return iValue == null ? Integer.valueOf(0) : iValue; + } + }; + + private final Function, Object> fnDeckGet = new Function, Object>() { + @Override + public Object apply(final Entry from) { + final Integer iValue = decksUsingMyCards.get(from.getKey()); + return iValue == null ? "" : iValue.toString(); + } + }; + + /** + * Child controller for quest deck editor UI. + *

+ * Card catalog and decks are drawn from a QuestController object. + * + * @param questData0   {@link forge.quest.QuestController} + */ + public CEditorQuestLimited(final QuestController questData0) { + + super(FScreen.DECK_EDITOR_QUEST_TOURNAMENT); + + allSections.add(DeckSection.Main); + allSections.add(DeckSection.Sideboard); + + this.questData = questData0; + + final CardManager catalogManager = new CardManager(false); + final CardManager deckManager = new CardManager(false); + + catalogManager.setCaption("Sideboard"); + + catalogManager.setAlwaysNonUnique(true); + deckManager.setAlwaysNonUnique(true); + + this.setCatalogManager(catalogManager); + this.setDeckManager(deckManager); + + final Supplier newCreator = new Supplier() { + @Override + public DeckGroup get() { + return new DeckGroup(""); + } + }; + + this.controller = new DeckController(questData0.getDraftDecks(), this, newCreator); + controller.getView().getDeckManager().setup(ItemManagerConfig.DRAFT_POOL); + controller.setModel(questData0.getDraftDecks().get(QuestEventDraft.DECK_NAME)); + + } + + /** + * Adds any card to the catalog and data pool. + * + * @param card {@link forge.item.PaperCard} + */ + public void addCheatCard(final PaperCard card, int qty) { + this.getCatalogManager().addItem(card, qty); + this.questData.getCards().getCardpool().add(card, qty); + } + + // fills number of decks using each card + private Map countDecksForEachCard() { + final Map result = new HashMap(); + for (final Deck deck : this.questData.getMyDecks()) { + for (final Entry e : deck.getMain()) { + final PaperCard card = e.getKey(); + final Integer amount = result.get(card); + result.put(card, Integer.valueOf(amount == null ? 1 : 1 + amount.intValue())); + } + } + return result; + } + + //=========== Overridden from ACEditorBase + + @Override + protected CardLimit getCardLimit() { + if (FModel.getPreferences().getPrefBoolean(FPref.ENFORCE_DECK_LEGALITY)) { + return CardLimit.Default; + } + return CardLimit.None; //if not enforcing deck legality, don't enforce default limit + } + + /* (non-Javadoc) + * @see forge.gui.deckeditor.ACEditorBase#onAddItems() + */ + @Override + protected void onAddItems(Iterable> items, boolean toAlternate) { + if (toAlternate) { return; } + + // update view + this.getDeckManager().addItems(items); + this.getCatalogManager().removeItems(items); + this.getDeckController().notifyModelChanged(); + } + + /* (non-Javadoc) + * @see forge.gui.deckeditor.ACEditorBase#onRemoveItems() + */ + @Override + protected void onRemoveItems(Iterable> items, boolean toAlternate) { + if (toAlternate) { return; } + + // update view + this.getCatalogManager().addItems(items); + this.getDeckManager().removeItems(items); + this.getDeckController().notifyModelChanged(); + } + + /* (non-Javadoc) + * @see forge.gui.deckeditor.ACEditorBase#buildAddContextMenu() + */ + @Override + protected void buildAddContextMenu(EditorContextMenuBuilder cmb) { + cmb.addMoveItems("Move", "to deck"); + } + + /* (non-Javadoc) + * @see forge.gui.deckeditor.ACEditorBase#buildRemoveContextMenu() + */ + @Override + protected void buildRemoveContextMenu(EditorContextMenuBuilder cmb) { + cmb.addMoveItems("Move", "to sideboard"); + } + + private Deck getSelectedDeck(final DeckGroup model) { + return model.getHumanDeck(); + } + + /* + * (non-Javadoc) + * + * @see forge.gui.deckeditor.ACEditorBase#updateView() + */ + @Override + public void resetTables() { + final Deck toEdit = this.getSelectedDeck(this.controller.getModel()); + this.getCatalogManager().setPool(toEdit.getOrCreate(DeckSection.Sideboard)); + this.getDeckManager().setPool(toEdit.getMain()); + } + + //=========== Overridden from ACEditorBase + + /* + * (non-Javadoc) + * + * @see forge.gui.deckeditor.ACEditorBase#getController() + */ + @Override + public DeckController getDeckController() { + return this.controller; + } + + @Override + public void update() { + + this.getCatalogManager().setup(getScreen() == FScreen.DECK_EDITOR_DRAFT ? ItemManagerConfig.DRAFT_POOL : ItemManagerConfig.SEALED_POOL); + this.getDeckManager().setup(ItemManagerConfig.DECK_EDITOR); + + this.decksUsingMyCards = this.countDecksForEachCard(); + + final Map colOverridesCatalog = new HashMap(); + final Map colOverridesDeck = new HashMap(); + + ItemTableColumn.addColOverride(ItemManagerConfig.QUEST_EDITOR_POOL, colOverridesCatalog, ColumnDef.NEW, this.questData.getCards().getFnNewCompare(), this.questData.getCards().getFnNewGet()); + ItemTableColumn.addColOverride(ItemManagerConfig.QUEST_DECK_EDITOR, colOverridesDeck, ColumnDef.NEW, this.questData.getCards().getFnNewCompare(), this.questData.getCards().getFnNewGet()); + ItemTableColumn.addColOverride(ItemManagerConfig.QUEST_DECK_EDITOR, colOverridesDeck, ColumnDef.DECKS, this.fnDeckCompare, this.fnDeckGet); + + this.getCatalogManager().setup(ItemManagerConfig.QUEST_EDITOR_POOL, colOverridesCatalog); + this.getDeckManager().setup(ItemManagerConfig.QUEST_DECK_EDITOR, colOverridesDeck); + + resetUI(); + + VCurrentDeck.SINGLETON_INSTANCE.getBtnSave().setVisible(true); + VCurrentDeck.SINGLETON_INSTANCE.getBtnImport().setVisible(false); + VCurrentDeck.SINGLETON_INSTANCE.getTxfTitle().setEnabled(false); + + deckGenParent = removeTab(VDeckgen.SINGLETON_INSTANCE); + allDecksParent = removeTab(VAllDecks.SINGLETON_INSTANCE); + + if (this.controller.getModel() == null) { + throw new RuntimeException("Expected deck group but found none!"); + } + else { + this.controller.refreshModel(); + } + } + + /* (non-Javadoc) + * @see forge.gui.deckeditor.controllers.ACEditorBase#canSwitchAway() + */ + @Override + public boolean canSwitchAway(boolean isClosing) { + if (SEditorIO.confirmSaveChanges(FScreen.DECK_EDITOR_QUEST_TOURNAMENT, isClosing)) { + FModel.getQuest().save(); + return true; + } + return false; + } + + /* (non-Javadoc) + * @see forge.gui.deckeditor.controllers.ACEditorBase#resetUIChanges() + */ + @Override + public void resetUIChanges() { + CSubmenuQuestDecks.SINGLETON_INSTANCE.update(); + //Re-add tabs + if (deckGenParent != null) { + deckGenParent.addDoc(VDeckgen.SINGLETON_INSTANCE); + } + if (allDecksParent != null) { + allDecksParent.addDoc(VAllDecks.SINGLETON_INSTANCE); + } + } + + /** + * TODO: Write javadoc for this method. + * @param d0 + */ + /*public void load(Deck deck) { + controller.setModel(deck); + }*/ +} diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/VHomeUI.java b/forge-gui-desktop/src/main/java/forge/screens/home/VHomeUI.java index 65edee31638..085176ca173 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/VHomeUI.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/VHomeUI.java @@ -118,6 +118,7 @@ public enum VHomeUI implements IVTopLevelUI { allSubmenus.add(VSubmenuDuels.SINGLETON_INSTANCE); allSubmenus.add(VSubmenuChallenges.SINGLETON_INSTANCE); + allSubmenus.add(VSubmenuQuestDraft.SINGLETON_INSTANCE); allSubmenus.add(VSubmenuQuestDecks.SINGLETON_INSTANCE); allSubmenus.add(VSubmenuQuestData.SINGLETON_INSTANCE); allSubmenus.add(VSubmenuQuestPrefs.SINGLETON_INSTANCE); diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestDraft.java b/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestDraft.java new file mode 100644 index 00000000000..6dd06788f6e --- /dev/null +++ b/forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestDraft.java @@ -0,0 +1,384 @@ +package forge.screens.home.quest; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.text.DecimalFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import javax.swing.JRadioButton; +import javax.swing.SwingUtilities; + +import forge.Singletons; +import forge.UiCommand; +import forge.assets.FSkinProp; +import forge.deck.CardPool; +import forge.deck.Deck; +import forge.deck.DeckGroup; +import forge.deck.DeckSection; +import forge.game.GameType; +import forge.gui.framework.EDocID; +import forge.gui.framework.FScreen; +import forge.gui.framework.ICDoc; +import forge.itemmanager.DeckManager; +import forge.limited.BoosterDraft; +import forge.limited.LimitedPoolType; +import forge.model.FModel; +import forge.properties.ForgePreferences.FPref; +import forge.quest.QuestController; +import forge.quest.QuestEventDraft; +import forge.quest.data.QuestAchievements; +import forge.screens.deckeditor.CDeckEditorUI; +import forge.screens.deckeditor.controllers.CEditorQuestDraftingProcess; +import forge.screens.deckeditor.controllers.CEditorQuestLimited; +import forge.screens.deckeditor.views.VCurrentDeck; +import forge.screens.home.CHomeUI; +import forge.screens.home.quest.VSubmenuQuestDraft.Mode; +import forge.screens.home.sanctioned.CSubmenuDraft; +import forge.toolbox.FOptionPane; +import forge.toolbox.FSkin; +import forge.toolbox.JXButtonPanel; +import forge.util.storage.IStorage; + +/** + * Controls the quest draft submenu in the home UI. + * + *

(C at beginning of class name denotes a control class.) + * + */ +public enum CSubmenuQuestDraft implements ICDoc { + + SINGLETON_INSTANCE; + + private static final DecimalFormat NUMBER_FORMATTER = new DecimalFormat("#,###"); + + @SuppressWarnings("serial") + @Override + public void initialize() { + + final VSubmenuQuestDraft view = VSubmenuQuestDraft.SINGLETON_INSTANCE; + + if (FModel.getQuest().getDraftDecks() == null || !FModel.getQuest().getDraftDecks().contains(QuestEventDraft.DECK_NAME)) { + view.setMode(Mode.SELECT_TOURNAMENT); + } else if (!FModel.getQuest().getAchievements().isTournamentActive()) { + view.setMode(Mode.PREPARE_DECK); + } else { + view.setMode(Mode.TOURNAMENT_ACTIVE); + } + + view.getBtnStartDraft().addActionListener(selectTournamentStart); + view.getBtnStartTournament().addActionListener(prepareDeckStart); + view.getBtnStartMatch().addActionListener(nextMatchStart); + + view.getBtnEditDeck().setCommand( + new UiCommand() { @Override + public void run() { CSubmenuQuestDraft.this.editDeck(); } }); + + view.getBtnLeaveTournament().setCommand( + new UiCommand() { @Override + public void run() { CSubmenuQuestDraft.this.TEMP_END_TOURNAMENT(); } }); + + } + + private void TEMP_END_TOURNAMENT() { + + // TODO Integrate better + + Deck deck = FModel.getQuest().getDraftDecks().get(QuestEventDraft.DECK_NAME).getHumanDeck(); + + FModel.getQuest().getCards().addAllCards(deck.getAllCardsInASinglePool().toFlatList()); + + if (FOptionPane.showOptionDialog("Add this draft to normal mode?", "Add Draft?", FSkin.getImage(FSkinProp.ICO_QUESTION), new String[] { "Yes", "No" }) == 0) { + + String tournamentName = FModel.getQuest().getName() + " Tournament Deck " + new SimpleDateFormat("EEE d MMM yyyy HH-mm-ss").format(new Date()); + + DeckGroup original = FModel.getQuest().getDraftDecks().get(QuestEventDraft.DECK_NAME); + DeckGroup output = new DeckGroup(tournamentName); + for (Deck aiDeck : original.getAiDecks()) { + output.addAiDeck(copyDeck(aiDeck)); + } + output.setHumanDeck(copyDeck(original.getHumanDeck(), tournamentName)); + FModel.getDecks().getDraft().add(output); + CSubmenuDraft.SINGLETON_INSTANCE.update(); + } + + if (deck.get(DeckSection.Main).countAll() > 0) { + FModel.getQuest().getMyDecks().add(FModel.getQuest().getDraftDecks().get(QuestEventDraft.DECK_NAME).getHumanDeck()); + FModel.getQuest().getMyDecks().get(QuestEventDraft.DECK_NAME).get(DeckSection.Sideboard).clear(); + } + + FModel.getQuest().getDraftDecks().delete(QuestEventDraft.DECK_NAME); + FModel.getQuest().getAchievements().endCurrentTournament(); + FModel.getQuest().save(); + + VSubmenuQuestDraft view = VSubmenuQuestDraft.SINGLETON_INSTANCE; + view.setMode(Mode.SELECT_TOURNAMENT); + view.populate(); + CSubmenuQuestDraft.SINGLETON_INSTANCE.update(); + + } + + private final ActionListener selectTournamentStart = new ActionListener() { + @Override + public void actionPerformed(ActionEvent event) { + CSubmenuQuestDraft.this.startDraft(); + } + }; + + private final ActionListener prepareDeckStart = new ActionListener() { + @Override + public void actionPerformed(ActionEvent event) { + //TODO Refactor the deck getting to a single method + String message = GameType.QuestDraft.getDecksFormat().getDeckConformanceProblem(FModel.getQuest().getAssets().getDraftDeckStorage().get(QuestEventDraft.DECK_NAME).getHumanDeck()); + if (message != null) { + //TODO Pref for allowing non-conformant decks + FOptionPane.showMessageDialog(message, "Deck Invalid"); + return; + } + CSubmenuQuestDraft.this.startTournament(); + } + }; + + private final ActionListener nextMatchStart = new ActionListener() { + @Override + public void actionPerformed(ActionEvent event) { + QuestDraftUtils.startNextMatch(); + } + }; + + private final KeyAdapter startOnEnter = new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (KeyEvent.VK_ENTER == e.getKeyChar()) { + VSubmenuQuestDraft.SINGLETON_INSTANCE.getBtnStartDraft().doClick(); + } + } + }; + + private final MouseAdapter startOnDblClick = new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (MouseEvent.BUTTON1 == e.getButton() && 2 == e.getClickCount()) { + VSubmenuQuestDraft.SINGLETON_INSTANCE.getBtnStartDraft().doClick(); + } + } + }; + + @Override + public void update() { + + VSubmenuQuestDraft view = VSubmenuQuestDraft.SINGLETON_INSTANCE; + + if (FModel.getQuest().getAchievements() == null) { + return; + } + + QuestDraftUtils.update(); + + QuestAchievements achievements = FModel.getQuest().getAchievements(); + achievements.generateNewTournaments(); + + switch (view.getMode()) { + + case SELECT_TOURNAMENT: + updateSelectTournament(); + break; + + case PREPARE_DECK: + updatePrepareDeck(); + break; + + case TOURNAMENT_ACTIVE: + updateTournamentActive(); + break; + + default: + break; + + } + + } + + private void updateSelectTournament() { + + VSubmenuQuestDraft view = VSubmenuQuestDraft.SINGLETON_INSTANCE; + + view.getLblCredits().setText("Available Credits: " + NUMBER_FORMATTER.format(FModel.getQuest().getAssets().getCredits())); + + FModel.getQuest().getAchievements().generateNewTournaments(); + + view.getPnlTournaments().removeAll(); + JXButtonPanel grpPanel = new JXButtonPanel(); + + boolean firstPanel = true; + + for (QuestEventDraft draft : FModel.getQuest().getAchievements().getDraftEvents()) { + + PnlDraftEvent draftPanel = new PnlDraftEvent(draft); + final JRadioButton button = draftPanel.getRadioButton(); + + if (firstPanel) { + button.setSelected(true); + SwingUtilities.invokeLater(new Runnable() { + @Override public void run() { button.requestFocusInWindow(); } + }); + firstPanel = false; + } + + grpPanel.add(draftPanel, button, "w 100%!, h 135px!, gapy 15px"); + + button.addKeyListener(startOnEnter); + button.addMouseListener(startOnDblClick); + + } + + view.getPnlTournaments().add(grpPanel, "w 100%!"); + + } + + private void updatePrepareDeck() { + } + + private void updateTournamentActive() { + + VSubmenuQuestDraft view = VSubmenuQuestDraft.SINGLETON_INSTANCE; + + if (FModel.getQuest().getAchievements().getCurrentDraft() == null) { + return; + } + + for (int i = 0; i < 15; i++) { + + String playerID = FModel.getQuest().getAchievements().getCurrentDraft().getStandings()[i]; + + if (playerID.equals(QuestEventDraft.HUMAN)) { + playerID = FModel.getPreferences().getPref(FPref.PLAYER_NAME); + } else if (playerID.equals(QuestEventDraft.UNDETERMINED)) { + playerID = "Undetermined"; + } else { + playerID = FModel.getQuest().getAchievements().getCurrentDraft().getAINames()[Integer.parseInt(playerID) - 1]; + } + + view.getLblsStandings()[i].setText(playerID); + + } + + } + + public void setCompletedDraft(DeckGroup finishedDraft, String s) { + + List aiDecks = new ArrayList(finishedDraft.getAiDecks()); + finishedDraft.getAiDecks().clear(); + + for (int i = 0; i < aiDecks.size(); i++) { + Deck oldDeck = aiDecks.get(i); + Deck namedDeck = new Deck("AI Deck " + i); + namedDeck.putSection(DeckSection.Main, oldDeck.get(DeckSection.Main)); + namedDeck.putSection(DeckSection.Sideboard, oldDeck.get(DeckSection.Sideboard)); + finishedDraft.getAiDecks().add(namedDeck); + } + + IStorage draft = FModel.getQuest().getDraftDecks(); + draft.add(finishedDraft); + + Singletons.getControl().setCurrentScreen(FScreen.DECK_EDITOR_QUEST_TOURNAMENT); + CDeckEditorUI.SINGLETON_INSTANCE.setEditorController(new CEditorQuestLimited(FModel.getQuest())); + + FModel.getQuest().save(); + + VSubmenuQuestDraft.SINGLETON_INSTANCE.setMode(Mode.PREPARE_DECK); + VSubmenuQuestDraft.SINGLETON_INSTANCE.populate(); + + } + + private void editDeck() { + VCurrentDeck.SINGLETON_INSTANCE.setItemManager(new DeckManager(GameType.Draft)); + Singletons.getControl().setCurrentScreen(FScreen.DECK_EDITOR_QUEST_TOURNAMENT); + CDeckEditorUI.SINGLETON_INSTANCE.setEditorController(new CEditorQuestLimited(FModel.getQuest())); + FModel.getQuest().save(); + } + + private void startDraft() { + + QuestEventDraft draftEvent = SSubmenuQuestUtil.getDraftEvent(); + + /*long creditsAvailable = FModel.getQuest().getAssets().getCredits(); + if (creditsAvailable < draftEvent.getEntryFee()) { + FOptionPane.showMessageDialog("You need " + NUMBER_FORMATTER.format(draftEvent.getEntryFee() - creditsAvailable) + " more credits to enter this tournament.", "Not Enough Credits"); + return; + }*/ + + boolean okayToEnter = FOptionPane.showConfirmDialog("This tournament costs " + draftEvent.getEntryFee() + " credits to enter.\nAre you sure you wish to enter?", "Enter Draft Tournament?"); + + if (!okayToEnter) { + return; + } + + FModel.getQuest().getAchievements().setCurrentDraft(draftEvent); + + //TODO What happens when the draft is quit early + + FModel.getQuest().getAssets().subtractCredits(draftEvent.getEntryFee()); + + BoosterDraft draft = BoosterDraft.createDraft(LimitedPoolType.Block, FModel.getBlocks().get(draftEvent.getBlock()), draftEvent.getBoosterConfiguration()); + + final CEditorQuestDraftingProcess draftController = new CEditorQuestDraftingProcess(); + draftController.showGui(draft); + + draftController.setDraftQuest(CSubmenuQuestDraft.this); + + Singletons.getControl().setCurrentScreen(FScreen.DRAFTING_PROCESS); + CDeckEditorUI.SINGLETON_INSTANCE.setEditorController(draftController); + + } + + private void startTournament() { + VSubmenuQuestDraft.SINGLETON_INSTANCE.setMode(Mode.TOURNAMENT_ACTIVE); + VSubmenuQuestDraft.SINGLETON_INSTANCE.populate(); + update(); + // TODO All the stuff needed for the tournament itself + } + + private Deck copyDeck(final Deck deck) { + + Deck outputDeck = new Deck(deck.getName()); + + outputDeck.putSection(DeckSection.Main, new CardPool(deck.get(DeckSection.Main))); + outputDeck.putSection(DeckSection.Sideboard, new CardPool(deck.get(DeckSection.Sideboard))); + + return outputDeck; + + } + + private Deck copyDeck(final Deck deck, final String deckName) { + + Deck outputDeck = new Deck(deckName); + + outputDeck.putSection(DeckSection.Main, new CardPool(deck.get(DeckSection.Main))); + outputDeck.putSection(DeckSection.Sideboard, new CardPool(deck.get(DeckSection.Sideboard))); + + return outputDeck; + + } + + @Override + public UiCommand getCommandOnSelect() { + final QuestController qc = FModel.getQuest(); + return new UiCommand() { + private static final long serialVersionUID = 6153589785507038445L; + @Override + public void run() { + if (qc.getAchievements() == null) { + CHomeUI.SINGLETON_INSTANCE.itemClick(EDocID.HOME_QUESTDATA); + } + } + }; + } + +} diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/quest/PnlDraftEvent.java b/forge-gui-desktop/src/main/java/forge/screens/home/quest/PnlDraftEvent.java new file mode 100644 index 00000000000..b089b244eeb --- /dev/null +++ b/forge-gui-desktop/src/main/java/forge/screens/home/quest/PnlDraftEvent.java @@ -0,0 +1,88 @@ +package forge.screens.home.quest; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.text.DecimalFormat; + +import javax.swing.JPanel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import net.miginfocom.swing.MigLayout; +import forge.model.FModel; +import forge.quest.QuestEventDraft; +import forge.toolbox.FRadioButton; +import forge.toolbox.FSkin; +import forge.toolbox.FSkin.SkinColor; +import forge.toolbox.FTextArea; + +public class PnlDraftEvent extends JPanel { + + private static final long serialVersionUID = 7348489421342846451L; + private static final DecimalFormat NUMBER_FORMATTER = new DecimalFormat("#,###"); + + private final Color clr2 = new Color(255, 255, 0, 0); + private final SkinColor clr3 = FSkin.getColor(FSkin.Colors.CLR_THEME2).alphaColor(200); + + private final FRadioButton radButton; + + public PnlDraftEvent(final QuestEventDraft event) { + + super(); + + radButton = new FRadioButton(event.getTitle()); + radButton.setFont(FSkin.getBoldFont(20)); + radButton.setIconTextGap(10); + + final FTextArea eventBoosters = new FTextArea(); + final FTextArea eventFee = new FTextArea(); + + String boosterList = ""; + for (int i = 0; i < event.getBoosterConfiguration().length; i++) { + boosterList += FModel.getMagicDb().getEditions().get(event.getBoosterConfiguration()[i]).getName(); + if (i != event.getBoosterConfiguration().length - 1) { + boosterList += " | "; + } + } + + eventBoosters.setText(boosterList); + eventBoosters.setFont(FSkin.getFont(12)); + + eventFee.setText(NUMBER_FORMATTER.format(event.getEntryFee()) + " Credit Entry Fee"); + eventFee.setFont(FSkin.getFont(12)); + + radButton.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent arg0) { + if (radButton.isSelected()) { + SSubmenuQuestUtil.setDraftEvent(event); + } + } + }); + + this.setOpaque(false); + this.setLayout(new MigLayout("insets 0, gap 0, wrap")); + this.add(radButton, "gap 25px 0 20px 0"); + this.add(eventBoosters, "w 100% - 25px!, gap 25px 0 15px 0"); + this.add(eventFee, "w 100% - 25px!, gap 25px 0 10px 0"); + + } + + public FRadioButton getRadioButton() { + return radButton; + } + + @Override + public void paintComponent(final Graphics g) { + + Graphics2D g2d = (Graphics2D) g.create(); + + FSkin.setGraphicsGradientPaint(g2d, 0, 0, clr3, (int) (getWidth() * 0.75), 0, clr2); + g2d.fillRect(0, 0, (int) (getWidth() * 0.75), getHeight()); + + g2d.dispose(); + + } + +} diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/quest/QuestDraftUtils.java b/forge-gui-desktop/src/main/java/forge/screens/home/quest/QuestDraftUtils.java new file mode 100644 index 00000000000..4d00a73f776 --- /dev/null +++ b/forge-gui-desktop/src/main/java/forge/screens/home/quest/QuestDraftUtils.java @@ -0,0 +1,181 @@ +package forge.screens.home.quest; + +import java.util.ArrayList; +import java.util.List; + +import javax.swing.SwingUtilities; + +import forge.GuiBase; +import forge.Singletons; +import forge.deck.DeckGroup; +import forge.game.Game; +import forge.game.GameType; +import forge.game.player.RegisteredPlayer; +import forge.gui.SOverlayUtils; +import forge.gui.framework.FScreen; +import forge.model.FModel; +import forge.quest.QuestEventDraft; + +public class QuestDraftUtils { + + private static List matchups = new ArrayList(); + + public static boolean matchInProgress = false; + private static boolean waitForUserInput = false; + + public static void continueMatch(Game lastGame) { + + if (lastGame.getMatch().isMatchOver()) { + matchInProgress = false; + } + + if (!matchInProgress) { + // Reset other stuff + Singletons.getControl().endCurrentGame(); + Singletons.getControl().setCurrentScreen(FScreen.HOME_SCREEN); + } else { + Singletons.getControl().endCurrentGame(); + Singletons.getControl().startGameWithUi(lastGame.getMatch()); + } + + } + + public static void startNextMatch() { + + matchups.clear(); + + QuestEventDraft draft = FModel.getQuest().getAchievements().getCurrentDraft(); + String[] currentStandings = draft.getStandings(); + + int currentSet = -1; + + for (int i = currentStandings.length - 1; i >= 0; i--) { + if (!currentStandings[i].equals(QuestEventDraft.UNDETERMINED)) { + currentSet = i; + break; + } + } + + switch (currentSet) { + + case 7: + addMatchup(0, 1, draft); + addMatchup(2, 3, draft); + addMatchup(4, 5, draft); + addMatchup(6, 7, draft); + break; + + case 11: + addMatchup(8, 9, draft); + addMatchup(10, 11, draft); + break; + + case 13: + addMatchup(12, 13, draft); + break; + + case 14: + default: + return; + + } + + update(); + + } + + private static void addMatchup(final int player1, final int player2, final QuestEventDraft draft) { + + DraftMatchup matchup = new DraftMatchup(); + DeckGroup decks = FModel.getQuest().getAssets().getDraftDeckStorage().get(QuestEventDraft.DECK_NAME); + + int humanIndex = -1; + int aiIndex = -1; + + if (draft.getStandings()[player1].equals(QuestEventDraft.HUMAN)) { + humanIndex = player1; + aiIndex = player2; + } else if (draft.getStandings()[player2].equals(QuestEventDraft.HUMAN)) { + humanIndex = player2; + aiIndex = player1; + } + + if (humanIndex > -1) { + + matchup.hasHumanPlayer = true; + matchup.matchStarter.add(new RegisteredPlayer(decks.getHumanDeck()).setPlayer(GuiBase.getInterface().getGuiPlayer())); + + int aiName = Integer.parseInt(draft.getStandings()[aiIndex]) - 1; + + int aiDeckIndex = Integer.parseInt(draft.getStandings()[aiIndex]) - 1; + matchup.matchStarter.add(new RegisteredPlayer(decks.getAiDecks().get(aiDeckIndex)).setPlayer(GuiBase.getInterface().createAiPlayer(draft.getAINames()[aiName], draft.getAIIcons()[aiName]))); + + } else { + + int aiName1 = Integer.parseInt(draft.getStandings()[player1]) - 1; + int aiName2 = Integer.parseInt(draft.getStandings()[player2]) - 1; + + int aiDeckIndex = Integer.parseInt(draft.getStandings()[player1]) - 1; + matchup.matchStarter.add(new RegisteredPlayer(decks.getAiDecks().get(aiDeckIndex)).setPlayer(GuiBase.getInterface().createAiPlayer(draft.getAINames()[aiName1], draft.getAIIcons()[aiName1]))); + + aiDeckIndex = Integer.parseInt(draft.getStandings()[player2]) - 1; + matchup.matchStarter.add(new RegisteredPlayer(decks.getAiDecks().get(aiDeckIndex)).setPlayer(GuiBase.getInterface().createAiPlayer(draft.getAINames()[aiName2], draft.getAIIcons()[aiName2]))); + + } + + matchups.add(matchup); + + } + + public static void update() { + + if (matchups.isEmpty()) { + return; + } + + if (waitForUserInput) { + return; + } + + if (matchInProgress) { + return; + } + + GuiBase.getInterface().enableOverlay(); + + DraftMatchup nextMatch = matchups.remove(0); + + matchInProgress = true; + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + SOverlayUtils.startGameOverlay(); + SOverlayUtils.showOverlay(); + } + }); + + if (!nextMatch.hasHumanPlayer) { + GuiBase.getInterface().disableOverlay(); + waitForUserInput = false; + } else { + waitForUserInput = true; + } + + GuiBase.getInterface().startMatch(GameType.QuestDraft, nextMatch.matchStarter); + + } + + public static void continueMatches() { + waitForUserInput = false; + update(); + } + + private static class DraftMatchup { + + private List matchStarter = new ArrayList(); + private boolean hasHumanPlayer = false; + + } + +} diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/quest/SSubmenuQuestUtil.java b/forge-gui-desktop/src/main/java/forge/screens/home/quest/SSubmenuQuestUtil.java index 23e563b7ce6..5add06eb023 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/quest/SSubmenuQuestUtil.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/quest/SSubmenuQuestUtil.java @@ -45,6 +45,7 @@ import java.util.List; */ public class SSubmenuQuestUtil { private static QuestEvent event; + private static QuestEventDraft draftEvent; /** *

@@ -240,6 +241,14 @@ public class SSubmenuQuestUtil { public static void setEvent(final QuestEvent event0) { SSubmenuQuestUtil.event = event0; } + + public static void setDraftEvent(final QuestEventDraft event0) { + SSubmenuQuestUtil.draftEvent = event0; + } + + public static QuestEventDraft getDraftEvent() { + return draftEvent; + } public static boolean checkActiveQuest(String location) { QuestController qc = FModel.getQuest(); diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuQuestDraft.java b/forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuQuestDraft.java new file mode 100644 index 00000000000..ba33ef4a05b --- /dev/null +++ b/forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuQuestDraft.java @@ -0,0 +1,238 @@ +package forge.screens.home.quest; + +import java.awt.Font; + +import javax.swing.JLabel; +import javax.swing.ScrollPaneConstants; +import javax.swing.SwingConstants; + +import net.miginfocom.swing.MigLayout; +import forge.assets.FSkinProp; +import forge.gui.framework.DragCell; +import forge.gui.framework.DragTab; +import forge.gui.framework.EDocID; +import forge.screens.home.EMenuGroup; +import forge.screens.home.IVSubmenu; +import forge.screens.home.LblHeader; +import forge.screens.home.StartButton; +import forge.screens.home.VHomeUI; +import forge.toolbox.FLabel; +import forge.toolbox.FScrollPanel; +import forge.toolbox.FSkin; + +/** + * Assembles Swing components of quest draft submenu singleton. + * + *

(V at beginning of class name denotes a view class.) + */ +public enum VSubmenuQuestDraft implements IVSubmenu { + + SINGLETON_INSTANCE; + + protected static enum Mode { + SELECT_TOURNAMENT, + PREPARE_DECK, + TOURNAMENT_ACTIVE + } + + private final DragTab tab = new DragTab("Tournaments"); + + private final LblHeader lblTitle = new LblHeader("Quest Mode: Draft Tournament"); + + private final FLabel lblCredits = new FLabel.Builder() + .icon(FSkin.getIcon(FSkinProp.ICO_QUEST_COINSTACK)) + .iconScaleFactor(0.75) + .fontSize(13).build(); + + private final FScrollPanel pnlTournaments = new FScrollPanel(new MigLayout("insets 0, gap 0, wrap, ax center"), true, + ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + + private final JLabel lblInfo = new FLabel.Builder().text("Select a tournament to join:") + .fontStyle(Font.BOLD).fontSize(16) + .fontAlign(SwingConstants.LEFT).build(); + + private final StartButton btnStartDraft = new StartButton(); + private final StartButton btnStartTournament = new StartButton(); + private final StartButton btnStartMatch = new StartButton(); + + private final FLabel btnEditDeck = new FLabel.ButtonBuilder().text("Edit Deck").fontSize(24).build(); + private final FLabel btnLeaveTournament = new FLabel.ButtonBuilder().text("Leave Tournament").fontSize(14).build(); + + private final JLabel lblsStandings[] = new JLabel[15]; + + private Mode mode = Mode.SELECT_TOURNAMENT; + + private DragCell parentCell; + + private VSubmenuQuestDraft() { + for (int i = 0; i < 15; i++) { + lblsStandings[i] = new FLabel.Builder().text("Standing Slot: " + i) + .fontStyle(Font.BOLD).fontSize(14) + .fontAlign(SwingConstants.LEFT).build(); + } + } + + public LblHeader getLblTitle() { + return lblTitle; + } + + public FLabel getLblCredits() { + return lblCredits; + } + + public FScrollPanel getPnlTournaments() { + return pnlTournaments; + } + + public StartButton getBtnStartDraft() { + return btnStartDraft; + } + + public StartButton getBtnStartTournament() { + return btnStartTournament; + } + + public StartButton getBtnStartMatch() { + return btnStartMatch; + } + + public FLabel getBtnEditDeck() { + return btnEditDeck; + } + + public FLabel getBtnLeaveTournament() { + return btnLeaveTournament; + } + + public JLabel[] getLblsStandings() { + return lblsStandings; + } + + public void setMode(Mode mode) { + this.mode = mode; + } + + public Mode getMode() { + return mode; + } + + @Override + public EDocID getDocumentID() { + return EDocID.HOME_QUESTDRAFTS; + } + + @Override + public DragTab getTabLabel() { + return tab; + } + + @Override + public CSubmenuQuestDraft getLayoutControl() { + return CSubmenuQuestDraft.SINGLETON_INSTANCE; + } + + @Override + public void setParentCell(DragCell cell0) { + this.parentCell = cell0; + } + + @Override + public DragCell getParentCell() { + return parentCell; + } + + @Override + public EMenuGroup getGroupEnum() { + return EMenuGroup.QUEST; + } + + @Override + public String getMenuTitle() { + return "Tournaments"; + } + + @Override + public EDocID getItemEnum() { + return EDocID.HOME_QUESTDRAFTS; + } + + @Override + public void populate() { + + VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().removeAll(); + + switch (mode) { + + case SELECT_TOURNAMENT: + populateSelectTournament(); + break; + case PREPARE_DECK: + populatePrepareDeck(); + break; + case TOURNAMENT_ACTIVE: + populateTournamentActive(); + break; + default: + break; + + } + + VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().repaintSelf(); + VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().revalidate(); + + } + + private void populateSelectTournament() { + VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().setLayout(new MigLayout("insets 0, gap 0, ax right, wrap")); + VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().add(lblTitle, "w 80%!, h 40px!, gap 0 0 15px 35px, ax right"); + VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().add(lblCredits, "h 25px!, gap 0 0 30px"); + VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().add(lblInfo, "h 30px!, gap 0 0 5px"); + VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().add(pnlTournaments, "w 95%, pushy, growy"); + VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().add(btnStartDraft, "gap 0 6% 30px 30px, ax center"); + } + + private void populatePrepareDeck() { + VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().setLayout(new MigLayout("insets 0, gap 0, ax center, wrap")); + VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().add(lblTitle, "w 80%!, h 40px!, gap 20% 0 15px 35px, ax right"); + VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().add(btnEditDeck, "w 150px, h 50px, gap 0 0 35% 0, ax center"); + VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().add(btnStartTournament, "gap 0 0 30px 0, ax center"); + VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().add(btnLeaveTournament, "w 100px, h 35px, gap 0 0 100px 0, ax center"); + } + + private void populateTournamentActive() { + + VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().setLayout(new MigLayout("insets 0, gap 0, ax center, wrap")); + VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().add(lblTitle, "w 80%!, h 40px!, gap 20% 0 15px 35px, ax right"); + + FScrollPanel panel = new FScrollPanel(new MigLayout("insets 0, gap 0, wrap 4, ax center"), true, + ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); + + String constraints = "w 200px!, h 30px!, ay center"; + String groupingGap = ", gap 0 0 0 50px"; + + panel.add(lblsStandings[0], constraints); + panel.add(lblsStandings[8], constraints + ", span 1 2"); + panel.add(lblsStandings[12], constraints + ", span 1 4"); + panel.add(lblsStandings[14], constraints + ", span 1 8"); + panel.add(lblsStandings[1], constraints + groupingGap); + panel.add(lblsStandings[2], constraints); + panel.add(lblsStandings[9], constraints + ", span 1 2"); + panel.add(lblsStandings[3], constraints + groupingGap); + panel.add(lblsStandings[4], constraints); + panel.add(lblsStandings[10], constraints + ", span 1 2"); + panel.add(lblsStandings[13], constraints + ", span 1 4"); + panel.add(lblsStandings[5], constraints + groupingGap); + panel.add(lblsStandings[6], constraints); + panel.add(lblsStandings[11], constraints + ", span 1 2"); + panel.add(lblsStandings[7], constraints); + + VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().add(panel, "gap 0 0 30px 0, ax center"); + + /*for (JLabel label : lblsStandings) { + VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().add(label, "h 30px!, gap 0 0 5px"); + }*/ + VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().add(btnStartMatch, "gap 0 0 30px 0, ax center"); + VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().add(btnLeaveTournament, "w 120px, h 35px, gap 0 0 100px 0, ax center"); + } + +} diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/QuestDraftWinLose.java b/forge-gui-desktop/src/main/java/forge/screens/match/QuestDraftWinLose.java new file mode 100644 index 00000000000..3d5b56d9ad3 --- /dev/null +++ b/forge-gui-desktop/src/main/java/forge/screens/match/QuestDraftWinLose.java @@ -0,0 +1,151 @@ +/** 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.screens.match; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; + +import forge.GuiBase; +import forge.LobbyPlayer; +import forge.Singletons; +import forge.game.Game; +import forge.game.player.Player; +import forge.gui.SOverlayUtils; +import forge.gui.framework.FScreen; +import forge.model.FModel; +import forge.quest.QuestController; +import forge.screens.home.quest.CSubmenuChallenges; +import forge.screens.home.quest.CSubmenuDuels; +import forge.screens.home.quest.CSubmenuQuestDraft; +import forge.screens.home.quest.QuestDraftUtils; +import forge.screens.home.quest.VSubmenuQuestDraft; + +/** + *

+ * QuestWinLose. + *

+ * Processes win/lose presentation for Quest events. This presentation is + * displayed by WinLoseFrame. Components to be added to pnlCustom in + * WinLoseFrame should use MigLayout. + * + */ +public class QuestDraftWinLose extends ControlWinLose { + private final transient ViewWinLose view; + + private final transient QuestController qData; + + /** + * Instantiates a new quest win lose handler. + * + * @param view0 ViewWinLose object + * @param match2 + */ + public QuestDraftWinLose(final ViewWinLose view0, Game lastGame) { + super(view0, lastGame); + this.view = view0; + qData = FModel.getQuest(); + } + + /** + *

+ * populateCustomPanel. + *

+ * Checks conditions of win and fires various reward display methods + * accordingly. + * + * @return true, if successful + */ + @Override + public final boolean populateCustomPanel() { + + QuestController quest = FModel.getQuest(); + + final LobbyPlayer questLobbyPlayer = GuiBase.getInterface().getQuestPlayer(); + List players = lastGame.getRegisteredPlayers(); + boolean gameHadHumanPlayer = false; + for (Player p : players) { + if (p.getLobbyPlayer().equals(questLobbyPlayer)) { + gameHadHumanPlayer = true; + break; + } + } + + if (lastGame.getMatch().isMatchOver()) { + + String winner = lastGame.getOutcome().getWinningPlayer().getName(); + + quest.getAchievements().getCurrentDraft().setWinner(winner); + quest.save(); + + } + + if (!gameHadHumanPlayer) { + + if (lastGame.getMatch().isMatchOver()) { + this.actionOnQuitMatch(); + QuestDraftUtils.matchInProgress = false; + QuestDraftUtils.update(); + } else { + this.actionOnContinue(); + QuestDraftUtils.update(); + } + return false; + + } + + view.getBtnRestart().setEnabled(false); + + if (lastGame.getMatch().isMatchOver()) { + view.getBtnContinue().setEnabled(false); + //TODO Add match quit to quit button listeners before match is officially over + view.getBtnQuit().addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent e) { + QuestDraftUtils.matchInProgress = false; + QuestDraftUtils.continueMatches(); + } + }); + } else { + view.getBtnQuit().setEnabled(false); + } + + CSubmenuQuestDraft.SINGLETON_INSTANCE.update(); + VSubmenuQuestDraft.SINGLETON_INSTANCE.populate(); + + return false; //We're not awarding anything, so never display the custom panel. + + } + + public final void actionOnQuitMatch() { + + CSubmenuDuels.SINGLETON_INSTANCE.update(); + CSubmenuChallenges.SINGLETON_INSTANCE.update(); + + qData.setCurrentEvent(null); + qData.save(); + FModel.getQuestPreferences().save(); + Singletons.getControl().writeMatchPreferences(); + + Singletons.getControl().endCurrentGame(); + Singletons.getControl().setCurrentScreen(FScreen.HOME_SCREEN); + + SOverlayUtils.hideOverlay(); + + } + +} diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/ViewWinLose.java b/forge-gui-desktop/src/main/java/forge/screens/match/ViewWinLose.java index 3e4f76bb15b..6a4a45e1a43 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/ViewWinLose.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/ViewWinLose.java @@ -1,18 +1,32 @@ package forge.screens.match; +import java.awt.Color; +import java.awt.Font; +import java.awt.Point; +import java.awt.Toolkit; +import java.awt.datatransfer.StringSelection; + +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; + +import net.miginfocom.swing.MigLayout; import forge.UiCommand; -import forge.game.*; +import forge.game.Game; +import forge.game.GameLog; +import forge.game.GameLogEntry; +import forge.game.GameLogEntryType; +import forge.game.GameOutcome; import forge.game.player.Player; import forge.model.FModel; -import forge.toolbox.*; +import forge.toolbox.FButton; +import forge.toolbox.FLabel; +import forge.toolbox.FOverlay; +import forge.toolbox.FScrollPane; +import forge.toolbox.FSkin; import forge.toolbox.FSkin.SkinnedLabel; import forge.toolbox.FSkin.SkinnedPanel; -import net.miginfocom.swing.MigLayout; - -import javax.swing.*; - -import java.awt.*; -import java.awt.datatransfer.StringSelection; +import forge.toolbox.FTextArea; public class ViewWinLose { @@ -24,7 +38,7 @@ public class ViewWinLose { private final JPanel pnlOutcomes = new JPanel(new MigLayout("wrap, align center")); private final Game game; - + @SuppressWarnings("serial") public ViewWinLose(final Game game0) { @@ -48,6 +62,9 @@ public class ViewWinLose { case Quest: control = new QuestWinLose(this, game0); break; + case QuestDraft: + control = new QuestDraftWinLose(this, game0); + break; case Draft: if (!FModel.getGauntletMini().isGauntletDraft()) { break; diff --git a/forge-gui-desktop/src/main/java/forge/view/arcane/PlayArea.java b/forge-gui-desktop/src/main/java/forge/view/arcane/PlayArea.java index 601816be3d7..2b6880ec2bb 100644 --- a/forge-gui-desktop/src/main/java/forge/view/arcane/PlayArea.java +++ b/forge-gui-desktop/src/main/java/forge/view/arcane/PlayArea.java @@ -19,8 +19,6 @@ package forge.view.arcane; import forge.FThreads; import forge.game.card.Card; -import forge.model.FModel; -import forge.properties.ForgePreferences.FPref; import forge.screens.match.CMatchUI; import forge.screens.match.controllers.CPrompt; import forge.toolbox.FScrollPane; @@ -58,7 +56,7 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen /** Constant STACK_SPACING_Y=0.07f. */ private static final float STACK_SPACING_Y = 0.07f; - private final int creatureStackMax = 4; + //private final int creatureStackMax = 4; private final int landStackMax = 5; private final int tokenStackMax = 5; private final int othersStackMax = 4; @@ -186,7 +184,7 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen return allTokens; } - private final CardStackRow collectAllCreatures() { + /*private final CardStackRow collectAllCreatures() { final CardStackRow allCreatures = new CardStackRow(); outerLoop: // @@ -236,7 +234,7 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen allCreatures.add(insertIndex == -1 ? allCreatures.size() : insertIndex, stack); } return allCreatures; - } + }*/ @Override public final CardPanel addCard(final Card card) { diff --git a/forge-gui-mobile/src/forge/GuiMobile.java b/forge-gui-mobile/src/forge/GuiMobile.java index b385edaa01c..d72afe10de8 100644 --- a/forge-gui-mobile/src/forge/GuiMobile.java +++ b/forge-gui-mobile/src/forge/GuiMobile.java @@ -53,7 +53,9 @@ import forge.util.WaitRunnable; import forge.util.gui.SGuiChoose; public class GuiMobile implements IGuiBase { + private final String assetsDir; + public GuiMobile(String assetsDir0) { assetsDir = assetsDir0; } @@ -204,6 +206,14 @@ public class GuiMobile implements IGuiBase { public void updatePlayerControl() { //TODO } + + @Override + public void disableOverlay() { + } + + @Override + public void enableOverlay() { + } @Override public void finishGame() { diff --git a/forge-gui/src/main/java/forge/interfaces/IGuiBase.java b/forge-gui/src/main/java/forge/interfaces/IGuiBase.java index cffaee449e9..b05fb989489 100644 --- a/forge-gui/src/main/java/forge/interfaces/IGuiBase.java +++ b/forge-gui/src/main/java/forge/interfaces/IGuiBase.java @@ -64,6 +64,8 @@ public interface IGuiBase { void updatePhase(); void updateTurn(GameEventTurnBegan event, Game game); void updatePlayerControl(); + void enableOverlay(); + void disableOverlay(); void finishGame(); void updateStack(); void updateZones(List> zonesToUpdate); diff --git a/forge-gui/src/main/java/forge/limited/BoosterDraft.java b/forge-gui/src/main/java/forge/limited/BoosterDraft.java index 2456cb27d4d..cd829617229 100644 --- a/forge-gui/src/main/java/forge/limited/BoosterDraft.java +++ b/forge-gui/src/main/java/forge/limited/BoosterDraft.java @@ -154,6 +154,23 @@ public final class BoosterDraft implements IBoosterDraft { draft.pack = draft.get8BoosterPack(); return draft; } + + public static BoosterDraft createDraft(final LimitedPoolType draftType, final CardBlock block, final String[] boosters) { + + BoosterDraft draft = new BoosterDraft(draftType); + + final int nPacks = boosters.length; + + for (int i = 0; i < nPacks; i++) { + draft.product.add(block.getBooster(boosters[i])); + } + + IBoosterDraft.LAND_SET_CODE[0] = block.getLandSet(); + + draft.pack = draft.get8BoosterPack(); + return draft; + + } /** *

diff --git a/forge-gui/src/main/java/forge/quest/QuestController.java b/forge-gui/src/main/java/forge/quest/QuestController.java index fe3280a50d8..6db9df700bf 100644 --- a/forge-gui/src/main/java/forge/quest/QuestController.java +++ b/forge-gui/src/main/java/forge/quest/QuestController.java @@ -17,12 +17,20 @@ */ package forge.quest; +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.eventbus.Subscribe; import forge.GuiBase; import forge.deck.Deck; +import forge.deck.DeckGroup; import forge.game.GameFormat; import forge.game.event.GameEvent; import forge.game.event.GameEventMulligan; @@ -43,9 +51,6 @@ import forge.quest.io.QuestChallengeReader; import forge.util.storage.IStorage; import forge.util.storage.StorageBase; -import java.io.File; -import java.util.*; - /** * TODO: Write javadoc for this type. * @@ -76,6 +81,9 @@ public class QuestController { // This is used by shop. Had no idea where else to place this private static transient IStorage preconManager = null; + + private transient IStorage draftDecks; + /** The Constant RANK_TITLES. */ public static final String[] RANK_TITLES = new String[] { "Level 0 - Confused Wizard", "Level 1 - Mana Mage", @@ -91,8 +99,7 @@ public class QuestController { /** */ public static final int MAX_PET_SLOTS = 2; - - + /** * * TODO: Write javadoc for this method. @@ -142,6 +149,10 @@ public class QuestController { public IStorage getMyDecks() { return this.decks; } + + public IStorage getDraftDecks() { + return draftDecks; + } /** * Gets the current format if any. @@ -209,6 +220,8 @@ public class QuestController { this.myCards = this.model == null ? null : new QuestUtilCards(this); this.questFormat = this.model == null ? null : this.model.getFormat(); this.currentEvent = null; + + this.draftDecks = this.model == null ? null : this.model.getAssets().getDraftDeckStorage(); this.resetDuelsManager(); this.resetChallengesManager(); diff --git a/forge-gui/src/main/java/forge/quest/QuestDeckGroupMap.java b/forge-gui/src/main/java/forge/quest/QuestDeckGroupMap.java new file mode 100644 index 00000000000..ad1095fe4e6 --- /dev/null +++ b/forge-gui/src/main/java/forge/quest/QuestDeckGroupMap.java @@ -0,0 +1,60 @@ +/* + * 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.quest; + +import java.util.HashMap; +import java.util.Map; + +import forge.deck.DeckGroup; +import forge.util.storage.StorageBase; + +/** + * TODO: Write javadoc for this type. + * + */ +public class QuestDeckGroupMap extends StorageBase { + + /** + * Instantiates a new quest deck map. + */ + public QuestDeckGroupMap(Map in) { + super("Quest draft decks", in == null ? new HashMap() : in); + } + + + /* + * (non-Javadoc) + * + * @see forge.util.IFolderMap#add(forge.util.IHasName) + */ + @Override + public void add(final DeckGroup deck) { + this.map.put(deck.getName(), deck); + } + + /* + * (non-Javadoc) + * + * @see forge.util.IFolderMap#delete(java.lang.String) + */ + @Override + public void delete(final String deckName) { + this.map.remove(deckName); + } + +} diff --git a/forge-gui/src/main/java/forge/quest/QuestEventDraft.java b/forge-gui/src/main/java/forge/quest/QuestEventDraft.java new file mode 100644 index 00000000000..8d7a8855b66 --- /dev/null +++ b/forge-gui/src/main/java/forge/quest/QuestEventDraft.java @@ -0,0 +1,459 @@ +/* + * 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.quest; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Stack; + +import org.apache.commons.lang3.ArrayUtils; + +import com.google.common.base.Function; + +import forge.GuiBase; +import forge.card.CardEdition; +import forge.limited.LimitedPoolType; +import forge.model.CardBlock; +import forge.model.FModel; +import forge.quest.io.ReadPriceList; +import forge.util.NameGenerator; +import forge.util.storage.IStorage; + +/** + *

+ * QuestEvent. + *

+ * + * MODEL - A basic event instance in Quest mode. Can be extended for use in + * unique event types: battles, quests, and others. + */ +public class QuestEventDraft { + + public static final String UNDETERMINED = "quest_draft_undetermined_place"; + public static final String HUMAN = "quest_draft_human_place"; + public static final String DECK_NAME = "Tournament Deck"; + + public static final Function FN_GET_NAME = new Function() { + @Override public final String apply(QuestEventDraft qe) { return qe.title; } + }; + + private static transient final ReadPriceList PRICE_LIST_READER = new ReadPriceList(); + private static transient final Map MAP_PRICES = PRICE_LIST_READER.getPriceList(); + + private String title = "Mystery Draft"; + private String boosterConfiguration = ""; + private String block = ""; + + private int entryFee = 0; + + private String[] standings = new String[15]; + private String[] aiNames = new String[7]; + + private int[] aiIcons = new int[7]; + + public QuestEventDraft(final String title) { + this.title = title; + } + + public final String getTitle() { + return this.title; + } + + public final String[] getBoosterConfiguration() { + return boosterConfiguration.split("/"); + } + + public final void setBoosterConfiguration(final String boosterConfiguration) { + this.boosterConfiguration = boosterConfiguration; + } + + public final void setEntryFee(final int entryFee) { + this.entryFee = entryFee; + } + + public final int getEntryFee() { + return entryFee; + } + + public final void setBlock(final String block) { + this.block = block; + } + + public final String getBlock() { + return block; + } + + public void setTitle(final String title0) { + this.title = title0; + } + + public void setStanding(int position, String player) { + standings[position] = player; + } + + public void setStandings(String[] standings) { + this.standings = standings; + } + + public String[] getStandings() { + return standings; + } + + public String[] getAINames() { + return aiNames; + } + + public void setAINames(final String[] names) { + aiNames = names; + } + + public int[] getAIIcons() { + return aiIcons; + } + + public void setAIIcons(final int[] icons) { + aiIcons = icons; + } + + public int getHumanLatestStanding() { + int humanIndex = 0; + for (int i = getStandings().length - 1; i >= 0; i--) { + if (getStandings()[i].equals(HUMAN)) { + humanIndex = i; + break; + } + } + return humanIndex; + } + + public int getOpponentIndex(int playerIndex) { + int result = (playerIndex % 2 == 0) ? playerIndex + 1 : playerIndex - 1; + if (result == 15) { + result = -1; + } + return result; + } + + public void setWinner(String playerName) { + + boolean isHumanPlayer = true; + + for (String name : aiNames) { + if (playerName.equals(name)) { + isHumanPlayer = false; + } + } + + int playerIndex = -1; + + if (isHumanPlayer) { + for (int i = standings.length - 1; i >= 0; i--) { + if (standings[i].equals(HUMAN)) { + playerIndex = i; + break; + } + } + } else { + + String aiIndex = ""; + + for (int i = aiNames.length - 1; i >= 0; i--) { + if (aiNames[i].equals(playerName)) { + aiIndex = "" + (i + 1); + break; + } + } + + for (int i = standings.length - 1; i >= 0; i--) { + if (standings[i].equals(aiIndex)) { + playerIndex = i; + break; + } + } + + } + + switch (playerIndex) { + case 0: + case 1: + standings[8] = standings[playerIndex]; + break; + case 2: + case 3: + standings[9] = standings[playerIndex]; + break; + case 4: + case 5: + standings[10] = standings[playerIndex]; + break; + case 6: + case 7: + standings[11] = standings[playerIndex]; + break; + case 8: + case 9: + standings[12] = standings[playerIndex]; + break; + case 10: + case 11: + standings[13] = standings[playerIndex]; + break; + case 12: + case 13: + standings[14] = standings[playerIndex]; + break; + } + + } + + @Override + public String toString() { + return title; + } + + /** + * Generates a random draft event based on the provided quest's limitations. + * Returns null in the event no draft could be created. + * @param quest + * @return + */ + public static QuestEventDraft getRandomDraftOrNull(final QuestController quest) { + + List possibleBlocks = new ArrayList(); + List allowedQuestSets = new ArrayList(); + + boolean questUsesLimitedCardPool = quest.getFormat() != null; + + if (questUsesLimitedCardPool) { + + List allowedSetCodes = quest.getFormat().getAllowedSetCodes(); + + for (String setCode : allowedSetCodes) { + allowedQuestSets.add(FModel.getMagicDb().getEditions().get(setCode)); + } + + } + + LimitedPoolType draftType = LimitedPoolType.Block; + + List blocks = new ArrayList(); + IStorage storage = draftType == LimitedPoolType.Block ? FModel.getBlocks() : FModel.getFantasyBlocks(); + + for (CardBlock b : storage) { + if (b.getCntBoostersDraft() > 0) { + blocks.add(b); + } + } + + if (questUsesLimitedCardPool) { + for (CardBlock block : blocks) { + + boolean blockAllowed = true; + + for (CardEdition set : block.getSets()) { + if (!allowedQuestSets.contains(set)) { + blockAllowed = false; + break; + } + } + + if (blockAllowed) { + possibleBlocks.add(block); + } + + } + } else { + possibleBlocks.addAll(blocks); + } + + if (possibleBlocks.isEmpty()) { + return null; + } + + Collections.shuffle(possibleBlocks); + CardBlock selectedBlock = possibleBlocks.get(0); + + final Stack sets = new Stack(); + for (int k = selectedBlock.getSets().length - 1; k >= 0; k--) { + sets.add(selectedBlock.getSets()[k].getCode()); + } + + for (String setCode : selectedBlock.getMetaSetNames()) { + if (selectedBlock.getMetaSet(setCode).isDraftable()) { + sets.push(setCode); + } + } + + QuestEventDraft event = new QuestEventDraft(selectedBlock.getName()); + + if (selectedBlock.getNumberSets() == 1) { + String boosterConfiguration = ""; + for (int i = 0; i < selectedBlock.getCntBoostersDraft(); i++) { + boosterConfiguration += selectedBlock.getSets()[0].getCode(); + if (i != selectedBlock.getCntBoostersDraft() - 1) { + boosterConfiguration += "/"; + } + event.boosterConfiguration = boosterConfiguration; + } + } else { + List possibleSetCombinations = getSetCombos(sets); + Collections.shuffle(possibleSetCombinations); + event.boosterConfiguration = possibleSetCombinations.get(0); + } + + event.block = selectedBlock.getName(); + event.entryFee = calculateEntryFee(event.boosterConfiguration.split("/")); + + List players = new ArrayList(); + players.add(HUMAN); + players.add("1"); + players.add("2"); + players.add("3"); + players.add("4"); + players.add("5"); + players.add("6"); + players.add("7"); + + Collections.shuffle(players); + + for (int i = 0; i < players.size(); i++) { + event.standings[i] = players.get(i); + } + + for (int i = 8; i < event.standings.length; i++) { + event.standings[i] = UNDETERMINED; + } + + List usedNames = new ArrayList(); + usedNames.add(GuiBase.getInterface().getGuiPlayer().getName()); + + for (int i = 0; i < 7; i++) { + event.aiNames[i] = NameGenerator.getRandomName("Any", "Any", usedNames); + usedNames.add(event.aiNames[i]); + } + + int numberOfIcons = GuiBase.getInterface().getAvatarCount(); + List usedIcons = new ArrayList(); + + for (int i = 0; i < 7; i++) { + + int icon = -1; + int attempts = 50; + + do { + icon = (int) Math.floor(Math.random() * numberOfIcons); + } while ((icon < 0 || usedIcons.contains(icon)) && attempts-- > 0); + + event.aiIcons[i] = icon; + usedNames.add(event.aiNames[i]); + + } + + return event; + + } + + private static int calculateEntryFee(String[] boosters) { + + int entryFee = 0; + + for (String boosterSet : boosters) { + + int value = 0; + String boosterName = FModel.getMagicDb().getEditions().get(boosterSet).getName() + " Booster Pack"; + + if (MAP_PRICES.containsKey(boosterName)) { + value = MAP_PRICES.get(boosterName); + } else { + value = 395; + } + + entryFee += value; + + } + + return (int) (entryFee * 1.5); + + } + + private static List getSetCombos(final List setz) { + String[] sets = setz.toArray(ArrayUtils.EMPTY_STRING_ARRAY); + List setCombos = new ArrayList(); + if (sets.length >= 2) { + setCombos.add(String.format("%s/%s/%s", sets[0], sets[0], sets[0])); + setCombos.add(String.format("%s/%s/%s", sets[0], sets[0], sets[1])); + setCombos.add(String.format("%s/%s/%s", sets[0], sets[1], sets[1])); + if (sets.length >= 3) { + setCombos.add(String.format("%s/%s/%s", sets[0], sets[1], sets[2])); + setCombos.add(String.format("%s/%s/%s", sets[0], sets[2], sets[2])); + } + setCombos.add(String.format("%s/%s/%s", sets[1], sets[0], sets[0])); + setCombos.add(String.format("%s/%s/%s", sets[1], sets[1], sets[0])); + setCombos.add(String.format("%s/%s/%s", sets[1], sets[1], sets[1])); + if (sets.length >= 3) { + setCombos.add(String.format("%s/%s/%s", sets[1], sets[1], sets[2])); + setCombos.add(String.format("%s/%s/%s", sets[1], sets[2], sets[2])); + } + } + if (sets.length >= 3) { + setCombos.add(String.format("%s/%s/%s", sets[2], sets[1], sets[0])); + setCombos.add(String.format("%s/%s/%s", sets[2], sets[2], sets[0])); + setCombos.add(String.format("%s/%s/%s", sets[2], sets[2], sets[1])); + setCombos.add(String.format("%s/%s/%s", sets[2], sets[2], sets[2])); + } // Beyond 3, skimp on the choice configurations, or the list will be enormous! + if (sets.length >= 4) { + setCombos.add(String.format("%s/%s/%s", sets[3], sets[1], sets[0])); + setCombos.add(String.format("%s/%s/%s", sets[3], sets[2], sets[1])); + } + if (sets.length >= 5) { + setCombos.add(String.format("%s/%s/%s", sets[4], sets[1], sets[0])); + setCombos.add(String.format("%s/%s/%s", sets[4], sets[3], sets[2])); + setCombos.add(String.format("%s/%s/%s", sets[4], sets[2], sets[0])); + } + if (sets.length >= 6) { + setCombos.add(String.format("%s/%s/%s", sets[5], sets[1], sets[0])); + setCombos.add(String.format("%s/%s/%s", sets[5], sets[3], sets[2])); + setCombos.add(String.format("%s/%s/%s", sets[5], sets[4], sets[3])); + setCombos.add(String.format("%s/%s/%s", sets[5], sets[2], sets[0])); + } + if (sets.length >= 7) { + setCombos.add(String.format("%s/%s/%s", sets[6], sets[1], sets[0])); + setCombos.add(String.format("%s/%s/%s", sets[6], sets[3], sets[2])); + setCombos.add(String.format("%s/%s/%s", sets[6], sets[5], sets[4])); + setCombos.add(String.format("%s/%s/%s", sets[6], sets[3], sets[0])); + } + if (sets.length >= 8) { + setCombos.add(String.format("%s/%s/%s", sets[7], sets[1], sets[0])); + setCombos.add(String.format("%s/%s/%s", sets[7], sets[3], sets[2])); + setCombos.add(String.format("%s/%s/%s", sets[7], sets[5], sets[4])); + setCombos.add(String.format("%s/%s/%s", sets[7], sets[6], sets[5])); + setCombos.add(String.format("%s/%s/%s", sets[7], sets[3], sets[0])); + } + if (sets.length >= 9) { + setCombos.add(String.format("%s/%s/%s", sets[8], sets[1], sets[0])); + setCombos.add(String.format("%s/%s/%s", sets[8], sets[3], sets[2])); + setCombos.add(String.format("%s/%s/%s", sets[8], sets[5], sets[4])); + setCombos.add(String.format("%s/%s/%s", sets[8], sets[7], sets[6])); + setCombos.add(String.format("%s/%s/%s", sets[8], sets[4], sets[0])); + } + return setCombos; + } + +} diff --git a/forge-gui/src/main/java/forge/quest/data/QuestAchievements.java b/forge-gui/src/main/java/forge/quest/data/QuestAchievements.java index e27dc406759..edf213c2c23 100644 --- a/forge-gui/src/main/java/forge/quest/data/QuestAchievements.java +++ b/forge-gui/src/main/java/forge/quest/data/QuestAchievements.java @@ -1,11 +1,12 @@ package forge.quest.data; -import forge.model.FModel; -import forge.quest.data.QuestPreferences.DifficultyPrefs; - import java.util.ArrayList; import java.util.List; +import forge.model.FModel; +import forge.quest.QuestEventDraft; +import forge.quest.data.QuestPreferences.DifficultyPrefs; + /** * TODO: Write javadoc for this type. * @@ -18,6 +19,11 @@ public class QuestAchievements { private List completedChallenges = new ArrayList(); private List currentChallenges = new ArrayList(); + + private QuestEventDraftContainer drafts = new QuestEventDraftContainer(); + private int currentDraft = -1; + private int draftTokensAvailable = 3; + private int winCountAtEndOfDraft = 0; private int win; private int winstreakBest = 0; @@ -34,6 +40,17 @@ public class QuestAchievements { public QuestAchievements(int diff) { difficulty = diff; } + + public void deleteDraft(QuestEventDraft draft) { + drafts.remove(draft); + } + + public void endCurrentTournament() { + drafts.remove(drafts.get(currentDraft)); + currentDraft = -1; + winCountAtEndOfDraft = win; + FModel.getQuest().save(); + } /** * TODO: Write javadoc for Constructor. @@ -45,6 +62,13 @@ public class QuestAchievements { public void addWin() { // changes getRank() this.win++; this.winstreakCurrent++; + + //Every 5 wins, allow a tournament to be generated. + if ((win - winCountAtEndOfDraft) % 5 == 0) { + if (draftTokensAvailable < 3) { + draftTokensAvailable++; + } + } if (this.winstreakCurrent > this.winstreakBest) { this.winstreakBest = this.winstreakCurrent; @@ -176,4 +200,48 @@ public class QuestAchievements { return this.difficulty; } + public QuestEventDraftContainer getDraftEvents() { + return drafts; + } + + public boolean isTournamentActive() { + return currentDraft >= 0; + } + + public void generateNewTournaments() { + + if (drafts == null) { + drafts = new QuestEventDraftContainer(); + draftTokensAvailable = 3; + } + + int draftsToGenerate = 3 - drafts.size(); + if (draftsToGenerate > draftTokensAvailable) { + draftsToGenerate = draftTokensAvailable; + } + + for (int i = 0; i < draftsToGenerate; i++) { + QuestEventDraft draft = QuestEventDraft.getRandomDraftOrNull(FModel.getQuest()); + if (draft != null) { + drafts.add(draft); + draftTokensAvailable--; + } + } + + FModel.getQuest().save(); + + } + + public void addDraftToken() { + draftTokensAvailable++; + } + + public void setCurrentDraft(final QuestEventDraft draft) { + currentDraft = drafts.indexOf(draft); + } + + public QuestEventDraft getCurrentDraft() { + return drafts.get(currentDraft); + } + } diff --git a/forge-gui/src/main/java/forge/quest/data/QuestAssets.java b/forge-gui/src/main/java/forge/quest/data/QuestAssets.java index 88dad00a87c..91a3138d1d6 100644 --- a/forge-gui/src/main/java/forge/quest/data/QuestAssets.java +++ b/forge-gui/src/main/java/forge/quest/data/QuestAssets.java @@ -17,10 +17,16 @@ */ package forge.quest.data; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Map; + import forge.deck.Deck; +import forge.deck.DeckGroup; import forge.item.InventoryItem; import forge.item.PaperCard; import forge.model.FModel; +import forge.quest.QuestDeckGroupMap; import forge.quest.QuestDeckMap; import forge.quest.QuestMode; import forge.quest.QuestUtilCards; @@ -28,10 +34,6 @@ import forge.quest.bazaar.QuestItemType; import forge.quest.data.QuestPreferences.QPref; import forge.util.ItemPool; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.Map; - /** */ public class QuestAssets { @@ -62,6 +64,8 @@ public class QuestAssets { // Much the same like other map, but keyed by string (to support a lot of custom pets) private final Map combatPets = new HashMap(); + + private final HashMap draftDecks = new HashMap(); /** * Checks for item. * @@ -263,4 +267,11 @@ public class QuestAssets { return new QuestDeckMap(this.myDecks); } + /** + * @return the tournament deck storage + */ + public QuestDeckGroupMap getDraftDeckStorage() { + return new QuestDeckGroupMap(this.draftDecks); + } + } diff --git a/forge-gui/src/main/java/forge/quest/data/QuestData.java b/forge-gui/src/main/java/forge/quest/data/QuestData.java index e0fd8674af4..b80725e12be 100644 --- a/forge-gui/src/main/java/forge/quest/data/QuestData.java +++ b/forge-gui/src/main/java/forge/quest/data/QuestData.java @@ -41,7 +41,7 @@ import java.util.Map; */ public final class QuestData { /** Holds the latest version of the Quest Data. */ - public static final int CURRENT_VERSION_NUMBER = 8; + public static final int CURRENT_VERSION_NUMBER = 9; // This field places the version number into QD instance, // but only when the object is created through the constructor diff --git a/forge-gui/src/main/java/forge/quest/data/QuestEventDraftContainer.java b/forge-gui/src/main/java/forge/quest/data/QuestEventDraftContainer.java new file mode 100644 index 00000000000..725f43fa624 --- /dev/null +++ b/forge-gui/src/main/java/forge/quest/data/QuestEventDraftContainer.java @@ -0,0 +1,9 @@ +package forge.quest.data; + +import java.util.ArrayList; + +import forge.quest.QuestEventDraft; + +public class QuestEventDraftContainer extends ArrayList { + private static final long serialVersionUID = -417036762608756613L; +} diff --git a/forge-gui/src/main/java/forge/quest/io/QuestDataIO.java b/forge-gui/src/main/java/forge/quest/io/QuestDataIO.java index 0abb09ce95b..0f9e0732e92 100644 --- a/forge-gui/src/main/java/forge/quest/io/QuestDataIO.java +++ b/forge-gui/src/main/java/forge/quest/io/QuestDataIO.java @@ -27,12 +27,14 @@ import com.thoughtworks.xstream.io.HierarchicalStreamWriter; import forge.card.CardEdition; import forge.deck.CardPool; import forge.deck.Deck; +import forge.deck.DeckGroup; import forge.deck.DeckSection; import forge.error.BugReporter; import forge.item.*; import forge.model.FModel; import forge.properties.ForgeConstants; import forge.quest.QuestController; +import forge.quest.QuestEventDraft; import forge.quest.QuestMode; import forge.quest.bazaar.QuestItemType; import forge.quest.data.*; @@ -79,6 +81,7 @@ public class QuestDataIO { final XStream xStream = isIgnoring ? new IgnoringXStream() : new XStream(); xStream.registerConverter(new ItemPoolToXml()); xStream.registerConverter(new DeckToXml()); + xStream.registerConverter(new DraftTournamentToXml()); xStream.registerConverter(new GameFormatQuestToXml()); xStream.registerConverter(new QuestModeToXml()); xStream.autodetectAnnotations(true); @@ -184,10 +187,10 @@ public class QuestDataIO { QuestDataIO.setFinalField(QuestData.class, "petSlots", newData, new HashMap()); } - if(saveVersion < 8) { + if (saveVersion < 8) { QuestDataIO.setFinalField(QuestData.class, "isCharmActive", newData, false); } - + final QuestAssets qS = newData.getAssets(); final QuestAchievements qA = newData.getAchievements(); @@ -316,7 +319,10 @@ public class QuestDataIO { if (!(lc instanceof String)) qA.getCurrentChallenges().set(i, lc.toString()); } - + + case 8: + QuestDataIO.setFinalField(QuestAssets.class, "draftDecks", qS, new HashMap()); + default: break; } @@ -469,6 +475,161 @@ public class QuestDataIO { return QuestMode.smartValueOf(value, QuestMode.Classic); } } + + private static class DraftTournamentToXml implements Converter { + + @SuppressWarnings("rawtypes") + @Override + public boolean canConvert(Class type) { + return type.equals(QuestEventDraftContainer.class); + } + + @Override + public void marshal(Object source, HierarchicalStreamWriter writer, + MarshallingContext context) { + + QuestEventDraftContainer drafts = (QuestEventDraftContainer) source; + + for (QuestEventDraft draft : drafts) { + + writer.startNode("draft"); + + writer.startNode("title"); + writer.setValue(draft.getTitle()); + writer.endNode(); + + writer.startNode("packs"); + String output = ""; + for (int i = 0; i < draft.getBoosterConfiguration().length; i++) { + output += draft.getBoosterConfiguration()[i]; + if (i != draft.getBoosterConfiguration().length - 1) { + output += "/"; + } + } + writer.setValue(output); + writer.endNode(); + + writer.startNode("entryFee"); + writer.setValue(String.valueOf(draft.getEntryFee())); + writer.endNode(); + + writer.startNode("block"); + writer.setValue(draft.getBlock()); + writer.endNode(); + + writer.startNode("standings"); + int i = 0; + for (String standing : draft.getStandings()) { + writer.startNode("s" + i++); + writer.setValue(standing); + writer.endNode(); + } + writer.endNode(); + + writer.startNode("aiNames"); + i = 0; + for (String name : draft.getAINames()) { + writer.startNode("ain" + i++); + writer.setValue(name); + writer.endNode(); + } + writer.endNode(); + + writer.startNode("aiIcons"); + i = 0; + for (int icon : draft.getAIIcons()) { + writer.startNode("aii" + i++); + writer.setValue(icon + ""); + writer.endNode(); + } + writer.endNode(); + + writer.endNode(); + + } + + } + + @Override + public Object unmarshal(HierarchicalStreamReader reader, + UnmarshallingContext context) { + + QuestEventDraftContainer output = new QuestEventDraftContainer(); + + while (reader.hasMoreChildren()) { + + reader.moveDown(); + + //TODO Use switch and hasMoreChildren() + + reader.moveDown(); + String draftName = reader.getValue(); + reader.moveUp(); + + reader.moveDown(); + String boosterConfiguration = reader.getValue(); + reader.moveUp(); + + reader.moveDown(); + int entryFee = Integer.parseInt(reader.getValue()); + reader.moveUp(); + + reader.moveDown(); + String block = reader.getValue(); + reader.moveUp(); + + String[] standings = new String[15]; + + reader.moveDown(); + int i = 0; + while (reader.hasMoreChildren()) { + reader.moveDown(); + standings[i++] = reader.getValue(); + reader.moveUp(); + } + reader.moveUp(); + + String[] aiNames = new String[7]; + + reader.moveDown(); + i = 0; + while (reader.hasMoreChildren()) { + reader.moveDown(); + aiNames[i++] = reader.getValue(); + reader.moveUp(); + } + reader.moveUp(); + + int[] aiIcons = new int[7]; + + reader.moveDown(); + i = 0; + while (reader.hasMoreChildren()) { + reader.moveDown(); + aiIcons[i++] = Integer.parseInt(reader.getValue()); + reader.moveUp(); + } + reader.moveUp(); + + QuestEventDraft draft = new QuestEventDraft(draftName); + draft.setBoosterConfiguration(boosterConfiguration); + draft.setEntryFee(entryFee); + draft.setBlock(block); + draft.setStandings(standings); + draft.setAINames(aiNames); + draft.setAIIcons(aiIcons); + + output.add(draft); + + reader.moveUp(); + + } + + return output; + + } + + } private static class DeckToXml extends ItemPoolToXml {