From 52b659e9028469458478aaca28297e9dba60db7b Mon Sep 17 00:00:00 2001 From: KrazyTheFox Date: Wed, 17 Oct 2018 20:40:01 -0400 Subject: [PATCH 01/21] Implement initial version of random edition selection --- .../quest/DialogChoosePoolDistribution.java | 21 +- .../screens/home/quest/DialogChooseSets.java | 201 +++++++++++++++++- 2 files changed, 201 insertions(+), 21 deletions(-) diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/quest/DialogChoosePoolDistribution.java b/forge-gui-desktop/src/main/java/forge/screens/home/quest/DialogChoosePoolDistribution.java index a1970457c21..e46e0e37420 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/quest/DialogChoosePoolDistribution.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/quest/DialogChoosePoolDistribution.java @@ -33,6 +33,8 @@ public class DialogChoosePoolDistribution { private final FRadioButton radSurpriseMe = new FRadioButton("Surprise Me"); private final FRadioButton radBoosters = new FRadioButton("Boosters"); + private final ButtonGroup poolTypeButtonGroup = new ButtonGroup(); + private final FTextField numberOfBoostersField = new FTextField.Builder().text("0").maxLength(10).build(); private final FButton btnOk = new FButton("OK"); @@ -42,6 +44,13 @@ public class DialogChoosePoolDistribution { @SuppressWarnings("serial") public DialogChoosePoolDistribution(final List preferredColors, final PoolType poolType, final boolean includeArtifacts) { + if (poolTypeButtonGroup.getButtonCount() == 0) { + poolTypeButtonGroup.add(radBalanced); + poolTypeButtonGroup.add(radRandom); + poolTypeButtonGroup.add(radSurpriseMe); + poolTypeButtonGroup.add(radBoosters); + } + for (Byte color : preferredColors) { switch (color) { case MagicColor.BLACK: @@ -70,26 +79,14 @@ public class DialogChoosePoolDistribution { switch (poolType) { case BALANCED: radBalanced.setSelected(true); - radRandom.setSelected(false); - radSurpriseMe.setSelected(false); - radBoosters.setSelected(false); break; case RANDOM: - radBalanced.setSelected(false); radRandom.setSelected(true); - radSurpriseMe.setSelected(false); - radBoosters.setSelected(false); break; case RANDOM_BALANCED: - radBalanced.setSelected(false); - radRandom.setSelected(false); radSurpriseMe.setSelected(true); - radBoosters.setSelected(false); break; case BOOSTERS: - radBalanced.setSelected(false); - radRandom.setSelected(false); - radSurpriseMe.setSelected(false); radBoosters.setSelected(true); break; } diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/quest/DialogChooseSets.java b/forge-gui-desktop/src/main/java/forge/screens/home/quest/DialogChooseSets.java index fc8969b9134..adf0529a464 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/quest/DialogChooseSets.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/quest/DialogChooseSets.java @@ -2,6 +2,7 @@ package forge.screens.home.quest; import forge.assets.FSkinProp; import forge.card.CardEdition; +import forge.game.GameFormat; import forge.gui.SOverlayUtils; import forge.model.FModel; import forge.toolbox.*; @@ -9,13 +10,12 @@ import forge.util.TextUtil; import net.miginfocom.swing.MigLayout; import javax.swing.*; - +import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; +import java.util.*; import java.util.List; +import java.util.function.Predicate; public class DialogChooseSets { @@ -64,16 +64,199 @@ public class DialogChooseSets { } - FPanel panel = new FPanel(new MigLayout("insets 0, gap 0, center, wrap 3")); + //FPanel panel = new FPanel(new MigLayout("insets 15, gap 0, center, wrap 3")); + FPanel panel = new FPanel(new MigLayout("insets 10, gap 5, center, wrap 3")); panel.setOpaque(false); panel.setBackgroundTexture(FSkin.getIcon(FSkinProp.BG_TEXTURE)); - panel.add(new FLabel.Builder().text("Choose sets").fontSize(18).build(), "center, span, wrap, gaptop 10"); + FTextField coreField = new FTextField.Builder().text("0").maxLength(3).build(); + FTextField expansionField = new FTextField.Builder().text("0").maxLength(3).build(); + FTextField otherField = new FTextField.Builder().text("0").maxLength(3).build(); + + JPanel optionsPanel = new JPanel(new MigLayout("insets 10, gap 5, center, wrap 2")); + optionsPanel.setVisible(false); + optionsPanel.setOpaque(false); + optionsPanel.add(new JSeparator(SwingConstants.HORIZONTAL), "w 100%, span 2, growx"); + optionsPanel.add(new FLabel.Builder().text("Select Random Sets").fontSize(17).fontStyle(Font.BOLD).build(), "h 40!, span 2"); + + JPanel leftOptionsPanel = new JPanel(new MigLayout("insets 10, gap 5, center, wrap 2")); + leftOptionsPanel.setOpaque(false); + leftOptionsPanel.add(new FLabel.Builder().text("Number to Select:").fontSize(14).fontStyle(Font.BOLD).build(), " span 2"); + leftOptionsPanel.add(new FLabel.Builder().text("Core:").build()); + leftOptionsPanel.add(coreField, "w 40!"); + leftOptionsPanel.add(new FLabel.Builder().text("Expansion:").build()); + leftOptionsPanel.add(expansionField, "w 40!"); + leftOptionsPanel.add(new FLabel.Builder().text("Other:").build()); + leftOptionsPanel.add(otherField, "w 40!"); + + JPanel rightOptionsPanel = new JPanel(new MigLayout("insets 10, gap 25 5, center, wrap 2")); + rightOptionsPanel.setOpaque(false); + rightOptionsPanel.add(new FLabel.Builder().text("Format Restrictions:").fontSize(14).fontStyle(Font.BOLD).build(), "span 2"); + + ButtonGroup formatButtonGroup = new ButtonGroup(); + List gameFormats = new ArrayList<>(); + FModel.getFormats().getSanctionedList().forEach(gameFormats::add); + + gameFormats.forEach(item -> { + if (item.getName().equals("Legacy")) { + FRadioButton button = new FRadioButton("Legacy/Vintage"); + button.setActionCommand(item.getName()); + formatButtonGroup.add(button); + rightOptionsPanel.add(button); + } else if (!item.getName().equals("Vintage")) { + FRadioButton button = new FRadioButton(item.getName()); + button.setActionCommand(item.getName()); + formatButtonGroup.add(button); + rightOptionsPanel.add(button); + } + }); + + FRadioButton button = new FRadioButton("Modern Card Frame"); + button.setActionCommand("Modern Card Frame"); + formatButtonGroup.add(button); + rightOptionsPanel.add(button); + + FRadioButton noFormatSelectionButton = new FRadioButton("No Format Restriction"); + formatButtonGroup.add(noFormatSelectionButton); + rightOptionsPanel.add(noFormatSelectionButton); + noFormatSelectionButton.setSelected(true); + + optionsPanel.add(leftOptionsPanel, "w 33%:40%:78%"); + optionsPanel.add(rightOptionsPanel, "w 33%:60%:78%"); + + FButton randomSelectionButton = new FButton("Randomize Sets"); + randomSelectionButton.addActionListener(actionEvent -> { + + int numberOfCoreSets = Integer.parseInt(coreField.getText()); + int numberOfExpansionSets = Integer.parseInt(expansionField.getText()); + int numberOfOtherSets = Integer.parseInt(otherField.getText()); + + for (FCheckBox coreSet : coreSets) { + coreSet.setSelected(false); + } + for (FCheckBox expansionSet : expansionSets) { + expansionSet.setSelected(false); + } + for (FCheckBox otherSet : otherSets) { + otherSet.setSelected(false); + } + + Predicate formatPredicate = null; + if (!noFormatSelectionButton.isSelected()) { + for (GameFormat gameFormat : gameFormats) { + if (gameFormat.getName().equals(formatButtonGroup.getSelection().getActionCommand())) { + formatPredicate = edition -> gameFormat.editionLegalPredicate.apply(edition); + } else if (formatButtonGroup.getSelection().getActionCommand().equals("Modern Card Frame")) { + formatPredicate = edition -> edition.getDate().after(new Date(1059350399L * 1000L)); + } + } + } + + List filteredCoreSets = new ArrayList<>(); + for (CardEdition edition : editions) { + if (edition.getType() == CardEdition.Type.CORE) { + if (formatPredicate != null && formatPredicate.test(edition)) { + filteredCoreSets.add(edition); + } + } + } + + List filteredExpansionSets = new ArrayList<>(); + for (CardEdition edition : editions) { + if (edition.getType() == CardEdition.Type.EXPANSION) { + if (formatPredicate != null && formatPredicate.test(edition)) { + filteredExpansionSets.add(edition); + } + } + } + + List filteredOtherSets = new ArrayList<>(); + for (CardEdition edition : editions) { + if (edition.getType() != CardEdition.Type.CORE && edition.getType() != CardEdition.Type.EXPANSION) { + if (formatPredicate != null && formatPredicate.test(edition)) { + filteredOtherSets.add(edition); + } + } + } + + Collections.shuffle(filteredCoreSets); + Collections.shuffle(filteredExpansionSets); + Collections.shuffle(filteredOtherSets); + + for (int i = 0; i < numberOfCoreSets && i < filteredCoreSets.size(); i++) { + String name = TextUtil.concatWithSpace(filteredCoreSets.get(i).getName(), TextUtil.enclosedParen(filteredCoreSets.get(i).getCode())); + for (FCheckBox set : coreSets) { + if (set.getText().equals(name)) { + set.setSelected(true); + } + } + } + + for (int i = 0; i < numberOfExpansionSets && i < filteredExpansionSets.size(); i++) { + String name = TextUtil.concatWithSpace(filteredExpansionSets.get(i).getName(), TextUtil.enclosedParen(filteredExpansionSets.get(i).getCode())); + for (FCheckBox set : expansionSets) { + if (set.getText().equals(name)) { + set.setSelected(true); + } + } + } + + for (int i = 0; i < numberOfOtherSets && i < filteredOtherSets.size(); i++) { + String name = TextUtil.concatWithSpace(filteredOtherSets.get(i).getName(), TextUtil.enclosedParen(filteredOtherSets.get(i).getCode())); + for (FCheckBox set : otherSets) { + if (set.getText().equals(name)) { + set.setSelected(true); + } + } + } + + panel.repaintSelf(); + + }); + + FButton clearSelectionButton = new FButton("Clear Selection"); + clearSelectionButton.addActionListener(actionEvent -> { + for (FCheckBox coreSet : coreSets) { + coreSet.setSelected(false); + } + for (FCheckBox expansionSet : expansionSets) { + expansionSet.setSelected(false); + } + for (FCheckBox otherSet : otherSets) { + otherSet.setSelected(false); + } + panel.repaintSelf(); + }); + + FButton showOptionsButton = new FButton("Show Options"); + showOptionsButton.addActionListener(actionEvent -> { + optionsPanel.setVisible(true); + showOptionsButton.setVisible(false); + }); + + FButton hideOptionsButton = new FButton("Hide Options"); + hideOptionsButton.addActionListener(actionEvent -> { + optionsPanel.setVisible(false); + showOptionsButton.setVisible(true); + }); + + JPanel buttonPanel = new JPanel(new MigLayout("h 50!, center, gap 10, insets 0, ay center")); + buttonPanel.setOpaque(false); + buttonPanel.add(randomSelectionButton, "w 175!, h 28!"); + buttonPanel.add(clearSelectionButton, "w 175!, h 28!"); + buttonPanel.add(hideOptionsButton, " w 175!, h 28!"); + + optionsPanel.add(buttonPanel, "span 2, growx"); + optionsPanel.add(new JSeparator(SwingConstants.HORIZONTAL), "w 100%, span 2, growx"); + + panel.add(new FLabel.Builder().text("Choose sets").fontSize(20).build(), "center, span, wrap, gaptop 10"); String constraints = "aligny top"; panel.add(makeCheckBoxList(coreSets, "Core sets", true), constraints); panel.add(makeCheckBoxList(expansionSets, "Expansions", false), constraints); panel.add(makeCheckBoxList(otherSets, "Other sets", false), constraints); + panel.add(showOptionsButton, "center, w 230!, h 30!, gap 10 0 20 0, span 3, hidemode 3"); + panel.add(optionsPanel, "center, w 100, span 3, growx, hidemode 3"); final JPanel overlay = FOverlay.SINGLETON_INSTANCE.getPanel(); overlay.setLayout(new MigLayout("insets 0, gap 0, wrap, ax center, ay center")); @@ -102,13 +285,13 @@ public class DialogChooseSets { } }); - JPanel southPanel = new JPanel(new MigLayout("insets 10, gap 20, ax center")); + JPanel southPanel = new JPanel(new MigLayout("insets 10, gap 30, ax center")); southPanel.setOpaque(false); if (showWantReprintsCheckbox) { southPanel.add(cbWantReprints, "center, span, wrap"); } - southPanel.add(btnOk, "center, w 40%, h 20!"); - southPanel.add(btnCancel, "center, w 40%, h 20!"); + southPanel.add(btnOk, "center, w 200!, h 30!"); + southPanel.add(btnCancel, "center, w 200!, h 30!"); panel.add(southPanel, "dock south, gapBottom 10"); From 8d4854bd5dfeb767bf556a2198e2d9d666385c67 Mon Sep 17 00:00:00 2001 From: KrazyTheFox Date: Fri, 1 Feb 2019 20:39:57 -0500 Subject: [PATCH 02/21] Saving progress --- .../screens/home/quest/DialogChooseSets.java | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/quest/DialogChooseSets.java b/forge-gui-desktop/src/main/java/forge/screens/home/quest/DialogChooseSets.java index adf0529a464..1b75493bbd3 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/quest/DialogChooseSets.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/quest/DialogChooseSets.java @@ -64,7 +64,6 @@ public class DialogChooseSets { } - //FPanel panel = new FPanel(new MigLayout("insets 15, gap 0, center, wrap 3")); FPanel panel = new FPanel(new MigLayout("insets 10, gap 5, center, wrap 3")); panel.setOpaque(false); panel.setBackgroundTexture(FSkin.getIcon(FSkinProp.BG_TEXTURE)); @@ -117,6 +116,7 @@ public class DialogChooseSets { rightOptionsPanel.add(button); FRadioButton noFormatSelectionButton = new FRadioButton("No Format Restriction"); + noFormatSelectionButton.setActionCommand("No Format Restriction"); formatButtonGroup.add(noFormatSelectionButton); rightOptionsPanel.add(noFormatSelectionButton); noFormatSelectionButton.setSelected(true); @@ -142,13 +142,13 @@ public class DialogChooseSets { } Predicate formatPredicate = null; - if (!noFormatSelectionButton.isSelected()) { - for (GameFormat gameFormat : gameFormats) { - if (gameFormat.getName().equals(formatButtonGroup.getSelection().getActionCommand())) { - formatPredicate = edition -> gameFormat.editionLegalPredicate.apply(edition); - } else if (formatButtonGroup.getSelection().getActionCommand().equals("Modern Card Frame")) { - formatPredicate = edition -> edition.getDate().after(new Date(1059350399L * 1000L)); - } + for (GameFormat gameFormat : gameFormats) { + if (gameFormat.getName().equals(formatButtonGroup.getSelection().getActionCommand())) { + formatPredicate = edition -> gameFormat.editionLegalPredicate.apply(edition) && (unselectableSets == null || !unselectableSets.contains(edition.getCode())); + } else if (formatButtonGroup.getSelection().getActionCommand().equals("Modern Card Frame")) { + formatPredicate = edition -> edition.getDate().after(new Date(1059350399L * 1000L)) && (unselectableSets == null || !unselectableSets.contains(edition.getCode())); + } else if (formatButtonGroup.getSelection().getActionCommand().equals("No Format Restriction")) { + formatPredicate = edition -> unselectableSets == null || !unselectableSets.contains(edition.getCode()); } } @@ -247,6 +247,11 @@ public class DialogChooseSets { buttonPanel.add(hideOptionsButton, " w 175!, h 28!"); optionsPanel.add(buttonPanel, "span 2, growx"); + + if (showWantReprintsCheckbox) { + optionsPanel.add(cbWantReprints, "center, span, wrap"); + } + optionsPanel.add(new JSeparator(SwingConstants.HORIZONTAL), "w 100%, span 2, growx"); panel.add(new FLabel.Builder().text("Choose sets").fontSize(20).build(), "center, span, wrap, gaptop 10"); @@ -287,9 +292,6 @@ public class DialogChooseSets { JPanel southPanel = new JPanel(new MigLayout("insets 10, gap 30, ax center")); southPanel.setOpaque(false); - if (showWantReprintsCheckbox) { - southPanel.add(cbWantReprints, "center, span, wrap"); - } southPanel.add(btnOk, "center, w 200!, h 30!"); southPanel.add(btnCancel, "center, w 200!, h 30!"); From d781b6ba613d5092bd8f0cbd7b341e0fbdae7c10 Mon Sep 17 00:00:00 2001 From: churrufli Date: Fri, 22 Feb 2019 15:10:54 +0100 Subject: [PATCH 03/21] Translating hard-coded text to res en-US.properties --- .../java/forge/screens/home/settings/VSubmenuPreferences.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuPreferences.java b/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuPreferences.java index 5d0a836410a..87d53c5e766 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuPreferences.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuPreferences.java @@ -383,7 +383,7 @@ public enum VSubmenuPreferences implements IVSubmenu { */ @Override public String getMenuTitle() { - return "Preferences"; + return localizer.getMessage("Preferences"); } /* (non-Javadoc) From 231b2da573c23a696a8d9606e540c1817637c670 Mon Sep 17 00:00:00 2001 From: churrufli Date: Fri, 22 Feb 2019 15:28:02 +0100 Subject: [PATCH 04/21] Translating hard-coded text to res en-US.properties --- .../java/forge/screens/home/settings/VSubmenuPreferences.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuPreferences.java b/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuPreferences.java index 87d53c5e766..7dd0f70ae1f 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuPreferences.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuPreferences.java @@ -383,8 +383,7 @@ public enum VSubmenuPreferences implements IVSubmenu { */ @Override public String getMenuTitle() { - return localizer.getMessage("Preferences"); - } + return localizer.getMessage("Preferences"); } /* (non-Javadoc) * @see forge.gui.home.IVSubmenu#getItemEnum() From f7134f0a543411eb1b5c591d0a3e6106246c50f3 Mon Sep 17 00:00:00 2001 From: churrufli Date: Fri, 22 Feb 2019 16:53:57 +0100 Subject: [PATCH 05/21] Translating hard-coded text to res en-US.properties --- .../deckeditor/AddBasicLandsDialog.java | 28 +++++++++-------- .../forge/screens/match/menus/GameMenu.java | 31 ++++++++++++------- forge-gui/res/languages/en-US.properties | 29 ++++++++++++++++- 3 files changed, 63 insertions(+), 25 deletions(-) diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/AddBasicLandsDialog.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/AddBasicLandsDialog.java index 7b0dbe9978b..863f9fdd5f5 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/AddBasicLandsDialog.java +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/AddBasicLandsDialog.java @@ -58,10 +58,12 @@ import forge.toolbox.FSkin.SkinnedPanel; import forge.view.arcane.CardPanel; import java.awt.event.MouseEvent; import java.util.Map; +import forge.util.Localizer; @SuppressWarnings("serial") public class AddBasicLandsDialog { + final Localizer localizer = Localizer.getInstance(); private static final int WIDTH = 800; private static final int HEIGHT = 370; private static final int ADD_BTN_SIZE = 30; @@ -70,11 +72,11 @@ public class AddBasicLandsDialog { private final FComboBoxPanel cbLandSet = new FComboBoxPanel("Land Set:", FlowLayout.CENTER, Iterables.filter(StaticData.instance().getEditions(), CardEdition.Predicates.hasBasicLands)); private final MainPanel panel = new MainPanel(); - private final LandPanel pnlPlains = new LandPanel("Plains"); - private final LandPanel pnlIsland = new LandPanel("Island"); - private final LandPanel pnlSwamp = new LandPanel("Swamp"); - private final LandPanel pnlMountain = new LandPanel("Mountain"); - private final LandPanel pnlForest = new LandPanel("Forest"); + private final LandPanel pnlPlains = new LandPanel(localizer.getMessage("Plains")); + private final LandPanel pnlIsland = new LandPanel(localizer.getMessage("Island")); + private final LandPanel pnlSwamp = new LandPanel(localizer.getMessage("Swamp")); + private final LandPanel pnlMountain = new LandPanel(localizer.getMessage("Mountain")); + private final LandPanel pnlForest = new LandPanel(localizer.getMessage("Forest")); private final FHtmlViewer lblDeckInfo = new FHtmlViewer(); @@ -123,7 +125,7 @@ public class AddBasicLandsDialog { updateDeckInfoLabel(); } }); - lblDeckInfo.setToolTipText("Deck statistics. Double click to auto-suggest basic lands."); + lblDeckInfo.setToolTipText(localizer.getMessage("lblLandsDeckStatistics")); cbLandSet.addActionListener(new ActionListener() { @Override @@ -215,7 +217,7 @@ public class AddBasicLandsDialog { } public CardPool show() { - optionPane = new FOptionPane(null, "Add Basic Lands", null, panel, ImmutableList.of("OK", "Cancel"), 0); + optionPane = new FOptionPane(null, localizer.getMessage("lblAddBasicLands"), null, panel, ImmutableList.of(localizer.getMessage("lblOk"), localizer.getMessage("lblCancel")), 0); panel.revalidate(); panel.repaint(); optionPane.setVisible(true); @@ -246,10 +248,10 @@ public class AddBasicLandsDialog { } int newTotalCount = nonLandCount + oldLandCount + newLandCount; lblDeckInfo.setText(FSkin.encodeSymbols("
" + - nonLandCount + " non-lands + " + - oldLandCount + " lands + " + - newLandCount + " added lands = " + - newTotalCount + " cards
" + + nonLandCount + localizer.getMessage("lblNonLands") +" + " + + oldLandCount + localizer.getMessage("lblLands") +" + " + + newLandCount + localizer.getMessage("lblAddedLands") + " = " + + newTotalCount + localizer.getMessage("lblCards") + "
" + "{W} " + integer.format(pnlPlains.symbolCount) + " (" + percent.format(pnlPlains.symbolCount / totalSymbolCount) + ") | " + "{U} " + integer.format(pnlIsland.symbolCount) + " (" + percent.format(pnlIsland.symbolCount / totalSymbolCount) + ") | " + "{B} " + integer.format(pnlSwamp.symbolCount) + " (" + percent.format(pnlSwamp.symbolCount / totalSymbolCount) + ") | " + @@ -382,9 +384,9 @@ public class AddBasicLandsDialog { if (landSet == null) { return; } int artChoiceCount = FModel.getMagicDb().getCommonCards().getArtCount(cardName, landSet.getCode()); - cbLandArt.addItem("Assorted Art"); + cbLandArt.addItem(localizer.getMessage("lblAssortedArt")); for (int i = 1; i <= artChoiceCount; i++) { - cbLandArt.addItem("Card Art " + i); + cbLandArt.addItem(localizer.getMessage("lblCardArt") + "" + i); } } diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/menus/GameMenu.java b/forge-gui-desktop/src/main/java/forge/screens/match/menus/GameMenu.java index b64fefeee31..c241a6113b2 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/menus/GameMenu.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/menus/GameMenu.java @@ -22,6 +22,7 @@ import forge.toolbox.FSkin.SkinnedCheckBoxMenuItem; import forge.toolbox.FSkin.SkinnedMenu; import forge.toolbox.FSkin.SkinnedMenuItem; import forge.toolbox.FSkin.SkinnedRadioButtonMenuItem; +import forge.util.Localizer; /** * Returns a JMenu containing options associated with current game. @@ -38,7 +39,8 @@ public final class GameMenu { private static boolean showIcons; public JMenu getMenu() { - final JMenu menu = new JMenu("Game"); + final Localizer localizer = Localizer.getInstance(); + final JMenu menu = new JMenu(localizer.getMessage("lblGame")); menu.setMnemonic(KeyEvent.VK_G); menu.add(getMenuItem_Undo()); menu.add(getMenuItem_Concede()); @@ -56,7 +58,8 @@ public final class GameMenu { } private static SkinnedCheckBoxMenuItem getMenuItem_GameSoundEffects() { - SkinnedCheckBoxMenuItem menuItem = new SkinnedCheckBoxMenuItem("Sound Effects"); + final Localizer localizer = Localizer.getInstance(); + SkinnedCheckBoxMenuItem menuItem = new SkinnedCheckBoxMenuItem(localizer.getMessage("lblSoundEffects")); menuItem.setState(prefs.getPrefBoolean(FPref.UI_ENABLE_SOUNDS)); menuItem.addActionListener(getSoundEffectsAction()); return menuItem; @@ -76,7 +79,8 @@ public final class GameMenu { } private SkinnedMenuItem getMenuItem_Undo() { - final SkinnedMenuItem menuItem = new SkinnedMenuItem("Undo"); + final Localizer localizer = Localizer.getInstance(); + final SkinnedMenuItem menuItem = new SkinnedMenuItem(localizer.getMessage("lblUndo")); menuItem.setAccelerator(MenuUtil.getAcceleratorKey(KeyEvent.VK_Z)); menuItem.addActionListener(getUndoAction()); return menuItem; @@ -109,7 +113,8 @@ public final class GameMenu { } private SkinnedMenuItem getMenuItem_AlphaStrike() { - final SkinnedMenuItem menuItem = new SkinnedMenuItem("Alpha Strike"); + final Localizer localizer = Localizer.getInstance(); + final SkinnedMenuItem menuItem = new SkinnedMenuItem(localizer.getMessage("lblAlphaStrike")); menuItem.setIcon((showIcons ? MenuUtil.getMenuIcon(FSkinProp.ICO_ALPHASTRIKE) : null)); menuItem.setAccelerator(MenuUtil.getAcceleratorKey(KeyEvent.VK_A)); menuItem.addActionListener(getAlphaStrikeAction()); @@ -126,7 +131,8 @@ public final class GameMenu { } private SkinnedMenuItem getMenuItem_EndTurn() { - final SkinnedMenuItem menuItem = new SkinnedMenuItem("End Turn"); + final Localizer localizer = Localizer.getInstance(); + final SkinnedMenuItem menuItem = new SkinnedMenuItem(localizer.getMessage("lblEndTurn")); menuItem.setIcon((showIcons ? MenuUtil.getMenuIcon(FSkinProp.ICO_ENDTURN) : null)); menuItem.setAccelerator(MenuUtil.getAcceleratorKey(KeyEvent.VK_E)); menuItem.addActionListener(getEndTurnAction()); @@ -143,7 +149,8 @@ public final class GameMenu { } private SkinnedMenu getMenuItem_TargetingArcs() { - final SkinnedMenu menu = new SkinnedMenu("Targeting Arcs"); + final Localizer localizer = Localizer.getInstance(); + final SkinnedMenu menu = new SkinnedMenu(localizer.getMessage("lblTargetingArcs")); final ButtonGroup group = new ButtonGroup(); SkinIcon menuIcon = MenuUtil.getMenuIcon(FSkinProp.ICO_ARCSOFF); @@ -155,15 +162,15 @@ public final class GameMenu { } SkinnedRadioButtonMenuItem menuItem; - menuItem = getTargetingArcRadioButton("Off", FSkinProp.ICO_ARCSOFF, ArcState.OFF); + menuItem = getTargetingArcRadioButton(localizer.getMessage("lblOff"), FSkinProp.ICO_ARCSOFF, ArcState.OFF); if (menuItem.isSelected()) { menuIcon = MenuUtil.getMenuIcon(FSkinProp.ICO_ARCSOFF); } group.add(menuItem); menu.add(menuItem); - menuItem = getTargetingArcRadioButton("Card mouseover", FSkinProp.ICO_ARCSHOVER, ArcState.MOUSEOVER); + menuItem = getTargetingArcRadioButton(localizer.getMessage("lblCardMouseOver"), FSkinProp.ICO_ARCSHOVER, ArcState.MOUSEOVER); if (menuItem.isSelected()) { menuIcon = MenuUtil.getMenuIcon(FSkinProp.ICO_ARCSHOVER); } group.add(menuItem); menu.add(menuItem); - menuItem = getTargetingArcRadioButton("Always On", FSkinProp.ICO_ARCSON, ArcState.ON); + menuItem = getTargetingArcRadioButton(localizer.getMessage("lblAlwaysOn"), FSkinProp.ICO_ARCSON, ArcState.ON); if (menuItem.isSelected()) { menuIcon = MenuUtil.getMenuIcon(FSkinProp.ICO_ARCSON); } group.add(menuItem); @@ -200,7 +207,8 @@ public final class GameMenu { } private SkinnedMenuItem getMenuItem_AutoYields() { - final SkinnedMenuItem menuItem = new SkinnedMenuItem("Auto-Yields"); + final Localizer localizer = Localizer.getInstance(); + final SkinnedMenuItem menuItem = new SkinnedMenuItem(localizer.getMessage("lblAutoYields")); menuItem.setIcon((showIcons ? MenuUtil.getMenuIcon(FSkinProp.ICO_WARNING) : null)); menuItem.addActionListener(getAutoYieldsAction()); return menuItem; @@ -217,7 +225,8 @@ public final class GameMenu { } private SkinnedMenuItem getMenuItem_ViewDeckList() { - final SkinnedMenuItem menuItem = new SkinnedMenuItem("Deck List"); + final Localizer localizer = Localizer.getInstance(); + final SkinnedMenuItem menuItem = new SkinnedMenuItem(localizer.getMessage("lblDeckList")); menuItem.setIcon((showIcons ? MenuUtil.getMenuIcon(FSkinProp.ICO_DECKLIST) : null)); menuItem.addActionListener(getViewDeckListAction()); return menuItem; diff --git a/forge-gui/res/languages/en-US.properties b/forge-gui/res/languages/en-US.properties index 7c57b271f98..d0727832432 100644 --- a/forge-gui/res/languages/en-US.properties +++ b/forge-gui/res/languages/en-US.properties @@ -230,4 +230,31 @@ lblArticles=Articles lblGettingStarted=Getting Started lblHowtoPlay=How to Play lblForgeLicense=Forge License -lblReleaseNotes=Release Notes \ No newline at end of file +lblReleaseNotes=Release Notes +#GameMenu.java +lblGame=Game +lblSoundEffects=Sound Effects +lblUndo=Undo +lblAlphaStrike=Alpha Strike +lblEndTurn=End Turn +lblTargetingArcs=Targeting Arcs +lblOff=Off +lblCardMouseOver=Card Mouseover +lblAlwaysOn=Always On +lblAutoYields=Auto-Yields +lblDeckList = Deck List +#AddBasicLandsDialog.java +Plains=Plains +Island=Island +Swamp=Swamp +Mountain=Mountain +Forest=Forest +lblLandsDeckStatistics=Deck statistics. Double click to auto-suggest basic lands. +lblCancel=Cancel +lblOk=Ok +lblNon-lands=non-lands +lblLands = lands +lblAddedLands =added lands +lblCards=Cards +lblAssortedArt = Assorted Art +lblCardArt = Card Art \ No newline at end of file From 2e70ab329e40e8960511a543698e25e91be61022 Mon Sep 17 00:00:00 2001 From: churrufli Date: Fri, 22 Feb 2019 17:26:44 +0100 Subject: [PATCH 06/21] undo translation in AddBasicLandsDialog.java --- .../deckeditor/AddBasicLandsDialog.java | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/AddBasicLandsDialog.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/AddBasicLandsDialog.java index 863f9fdd5f5..7b0dbe9978b 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/AddBasicLandsDialog.java +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/AddBasicLandsDialog.java @@ -58,12 +58,10 @@ import forge.toolbox.FSkin.SkinnedPanel; import forge.view.arcane.CardPanel; import java.awt.event.MouseEvent; import java.util.Map; -import forge.util.Localizer; @SuppressWarnings("serial") public class AddBasicLandsDialog { - final Localizer localizer = Localizer.getInstance(); private static final int WIDTH = 800; private static final int HEIGHT = 370; private static final int ADD_BTN_SIZE = 30; @@ -72,11 +70,11 @@ public class AddBasicLandsDialog { private final FComboBoxPanel cbLandSet = new FComboBoxPanel("Land Set:", FlowLayout.CENTER, Iterables.filter(StaticData.instance().getEditions(), CardEdition.Predicates.hasBasicLands)); private final MainPanel panel = new MainPanel(); - private final LandPanel pnlPlains = new LandPanel(localizer.getMessage("Plains")); - private final LandPanel pnlIsland = new LandPanel(localizer.getMessage("Island")); - private final LandPanel pnlSwamp = new LandPanel(localizer.getMessage("Swamp")); - private final LandPanel pnlMountain = new LandPanel(localizer.getMessage("Mountain")); - private final LandPanel pnlForest = new LandPanel(localizer.getMessage("Forest")); + private final LandPanel pnlPlains = new LandPanel("Plains"); + private final LandPanel pnlIsland = new LandPanel("Island"); + private final LandPanel pnlSwamp = new LandPanel("Swamp"); + private final LandPanel pnlMountain = new LandPanel("Mountain"); + private final LandPanel pnlForest = new LandPanel("Forest"); private final FHtmlViewer lblDeckInfo = new FHtmlViewer(); @@ -125,7 +123,7 @@ public class AddBasicLandsDialog { updateDeckInfoLabel(); } }); - lblDeckInfo.setToolTipText(localizer.getMessage("lblLandsDeckStatistics")); + lblDeckInfo.setToolTipText("Deck statistics. Double click to auto-suggest basic lands."); cbLandSet.addActionListener(new ActionListener() { @Override @@ -217,7 +215,7 @@ public class AddBasicLandsDialog { } public CardPool show() { - optionPane = new FOptionPane(null, localizer.getMessage("lblAddBasicLands"), null, panel, ImmutableList.of(localizer.getMessage("lblOk"), localizer.getMessage("lblCancel")), 0); + optionPane = new FOptionPane(null, "Add Basic Lands", null, panel, ImmutableList.of("OK", "Cancel"), 0); panel.revalidate(); panel.repaint(); optionPane.setVisible(true); @@ -248,10 +246,10 @@ public class AddBasicLandsDialog { } int newTotalCount = nonLandCount + oldLandCount + newLandCount; lblDeckInfo.setText(FSkin.encodeSymbols("
" + - nonLandCount + localizer.getMessage("lblNonLands") +" + " + - oldLandCount + localizer.getMessage("lblLands") +" + " + - newLandCount + localizer.getMessage("lblAddedLands") + " = " + - newTotalCount + localizer.getMessage("lblCards") + "
" + + nonLandCount + " non-lands + " + + oldLandCount + " lands + " + + newLandCount + " added lands = " + + newTotalCount + " cards
" + "{W} " + integer.format(pnlPlains.symbolCount) + " (" + percent.format(pnlPlains.symbolCount / totalSymbolCount) + ") | " + "{U} " + integer.format(pnlIsland.symbolCount) + " (" + percent.format(pnlIsland.symbolCount / totalSymbolCount) + ") | " + "{B} " + integer.format(pnlSwamp.symbolCount) + " (" + percent.format(pnlSwamp.symbolCount / totalSymbolCount) + ") | " + @@ -384,9 +382,9 @@ public class AddBasicLandsDialog { if (landSet == null) { return; } int artChoiceCount = FModel.getMagicDb().getCommonCards().getArtCount(cardName, landSet.getCode()); - cbLandArt.addItem(localizer.getMessage("lblAssortedArt")); + cbLandArt.addItem("Assorted Art"); for (int i = 1; i <= artChoiceCount; i++) { - cbLandArt.addItem(localizer.getMessage("lblCardArt") + "" + i); + cbLandArt.addItem("Card Art " + i); } } From f87f6bdebe1a1cc2bf51462ed414db869cfd77db Mon Sep 17 00:00:00 2001 From: churrufli Date: Fri, 22 Feb 2019 17:35:37 +0100 Subject: [PATCH 07/21] undo translation in AddBasicLandsDialog.java --- .../forge/screens/deckeditor/AddBasicLandsDialog.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/AddBasicLandsDialog.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/AddBasicLandsDialog.java index 7b0dbe9978b..59491730936 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/AddBasicLandsDialog.java +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/AddBasicLandsDialog.java @@ -6,12 +6,12 @@ * 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 . */ @@ -119,7 +119,7 @@ public class AddBasicLandsDialog { pnlSwamp.lblCount.setText(String.valueOf(pnlSwamp.count)); pnlMountain.lblCount.setText(String.valueOf(pnlMountain.count)); pnlForest.lblCount.setText(String.valueOf(pnlForest.count)); - + updateDeckInfoLabel(); } }); @@ -254,7 +254,7 @@ public class AddBasicLandsDialog { "{U} " + integer.format(pnlIsland.symbolCount) + " (" + percent.format(pnlIsland.symbolCount / totalSymbolCount) + ") | " + "{B} " + integer.format(pnlSwamp.symbolCount) + " (" + percent.format(pnlSwamp.symbolCount / totalSymbolCount) + ") | " + "{R} " + integer.format(pnlMountain.symbolCount) + " (" + percent.format(pnlMountain.symbolCount / totalSymbolCount) + ") | " + - "{G} " + integer.format(pnlForest.symbolCount) + " (" + percent.format(pnlForest.symbolCount / totalSymbolCount) + ")" + + "{G} " + integer.format(pnlForest.symbolCount) + " (" + percent.format(pnlForest.symbolCount / totalSymbolCount) + ")" + "
", false)); } From 6ef9f4bc7be8aad10dcbeb5168457b0d6332c12b Mon Sep 17 00:00:00 2001 From: churrufli Date: Sat, 23 Feb 2019 19:47:52 +0100 Subject: [PATCH 08/21] undo translation in AddBasicLandsDialog.java --- forge-gui/res/languages/en-US.properties | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/forge-gui/res/languages/en-US.properties b/forge-gui/res/languages/en-US.properties index d0727832432..9efb2ce5d6b 100644 --- a/forge-gui/res/languages/en-US.properties +++ b/forge-gui/res/languages/en-US.properties @@ -242,19 +242,4 @@ lblOff=Off lblCardMouseOver=Card Mouseover lblAlwaysOn=Always On lblAutoYields=Auto-Yields -lblDeckList = Deck List -#AddBasicLandsDialog.java -Plains=Plains -Island=Island -Swamp=Swamp -Mountain=Mountain -Forest=Forest -lblLandsDeckStatistics=Deck statistics. Double click to auto-suggest basic lands. -lblCancel=Cancel -lblOk=Ok -lblNon-lands=non-lands -lblLands = lands -lblAddedLands =added lands -lblCards=Cards -lblAssortedArt = Assorted Art -lblCardArt = Card Art \ No newline at end of file +lblDeckList = Deck List \ No newline at end of file From a546339ea2fd4f9a97f23163e47124ce9f064bcd Mon Sep 17 00:00:00 2001 From: churrufli Date: Wed, 27 Feb 2019 19:58:25 +0100 Subject: [PATCH 09/21] Merge branch 'master' of https://git.cardforge.org/core-developers/forge --- .../java/forge/control/KeyboardShortcuts.java | 29 ++++++++-------- .../forge/screens/match/VAssignDamage.java | 22 +++++++------ forge-gui/res/languages/en-US.properties | 33 ++++++++++++++++++- .../match/input/InputConfirmMulligan.java | 13 +++++--- 4 files changed, 67 insertions(+), 30 deletions(-) diff --git a/forge-gui-desktop/src/main/java/forge/control/KeyboardShortcuts.java b/forge-gui-desktop/src/main/java/forge/control/KeyboardShortcuts.java index 15a18e1a94d..72ecf54fb83 100644 --- a/forge-gui-desktop/src/main/java/forge/control/KeyboardShortcuts.java +++ b/forge-gui-desktop/src/main/java/forge/control/KeyboardShortcuts.java @@ -26,6 +26,7 @@ import forge.properties.ForgePreferences; import forge.properties.ForgePreferences.FPref; import forge.screens.home.settings.VSubmenuPreferences.KeyboardShortcutField; import forge.screens.match.CMatchUI; +import forge.util.Localizer; /** * Consolidates keyboard shortcut assembly into one location @@ -35,7 +36,6 @@ import forge.screens.match.CMatchUI; * and you're done. */ public class KeyboardShortcuts { - public static List getKeyboardShortcuts() { return attachKeyboardShortcuts(null); } @@ -200,20 +200,21 @@ public class KeyboardShortcuts { } }; + final Localizer localizer = Localizer.getInstance(); //========== Instantiate shortcut objects and add to list. - list.add(new Shortcut(FPref.SHORTCUT_SHOWSTACK, "Match: show stack panel", actShowStack, am, im)); - list.add(new Shortcut(FPref.SHORTCUT_SHOWCOMBAT, "Match: show combat panel", actShowCombat, am, im)); - list.add(new Shortcut(FPref.SHORTCUT_SHOWCONSOLE, "Match: show console panel", actShowConsole, am, im)); - list.add(new Shortcut(FPref.SHORTCUT_SHOWDEV, "Match: show dev panel", actShowDev, am, im)); - list.add(new Shortcut(FPref.SHORTCUT_CONCEDE, "Match: concede game", actConcede, am, im)); - list.add(new Shortcut(FPref.SHORTCUT_ENDTURN, "Match: pass priority until EOT or next stack event", actEndTurn, am, im)); - list.add(new Shortcut(FPref.SHORTCUT_ALPHASTRIKE, "Match: Alpha Strike (attack with all available)", actAllAttack, am, im)); - list.add(new Shortcut(FPref.SHORTCUT_SHOWTARGETING, "Match: toggle targeting visual overlay", actTgtOverlay, am, im)); - list.add(new Shortcut(FPref.SHORTCUT_AUTOYIELD_ALWAYS_YES, "Match: auto-yield ability on stack (Always Yes)", actAutoYieldAndYes, am, im)); - list.add(new Shortcut(FPref.SHORTCUT_AUTOYIELD_ALWAYS_NO, "Match: auto-yield ability on stack (Always No)", actAutoYieldAndNo, am, im)); - list.add(new Shortcut(FPref.SHORTCUT_MACRO_RECORD, "Match: record a macro sequence of actions", actMacroRecord, am, im)); - list.add(new Shortcut(FPref.SHORTCUT_MACRO_NEXT_ACTION, "Match: execute next action in a recorded macro", actMacroNextAction, am, im)); - list.add(new Shortcut(FPref.SHORTCUT_CARD_ZOOM, "Match: zoom the currently selected card", actZoomCard, am, im)); + list.add(new Shortcut(FPref.SHORTCUT_SHOWSTACK, localizer.getMessage("lblSHORTCUT_SHOWSTACK"), actShowStack, am, im)); + list.add(new Shortcut(FPref.SHORTCUT_SHOWCOMBAT, localizer.getMessage("lblSHORTCUT_SHOWCOMBAT"), actShowCombat, am, im)); + list.add(new Shortcut(FPref.SHORTCUT_SHOWCONSOLE, localizer.getMessage("lblSHORTCUT_SHOWCONSOLE"), actShowConsole, am, im)); + list.add(new Shortcut(FPref.SHORTCUT_SHOWDEV, localizer.getMessage("lblSHORTCUT_SHOWDEV"), actShowDev, am, im)); + list.add(new Shortcut(FPref.SHORTCUT_CONCEDE, localizer.getMessage("lblSHORTCUT_CONCEDE"), actConcede, am, im)); + list.add(new Shortcut(FPref.SHORTCUT_ENDTURN, localizer.getMessage("lblSHORTCUT_ENDTURN"), actEndTurn, am, im)); + list.add(new Shortcut(FPref.SHORTCUT_ALPHASTRIKE, localizer.getMessage("lblSHORTCUT_ALPHASTRIKE"), actAllAttack, am, im)); + list.add(new Shortcut(FPref.SHORTCUT_SHOWTARGETING, localizer.getMessage("lblSHORTCUT_SHOWTARGETING"), actTgtOverlay, am, im)); + list.add(new Shortcut(FPref.SHORTCUT_AUTOYIELD_ALWAYS_YES, localizer.getMessage("lblSHORTCUT_AUTOYIELD_ALWAYS_YES"), actAutoYieldAndYes, am, im)); + list.add(new Shortcut(FPref.SHORTCUT_AUTOYIELD_ALWAYS_NO, localizer.getMessage("lblSHORTCUT_AUTOYIELD_ALWAYS_NO"), actAutoYieldAndNo, am, im)); + list.add(new Shortcut(FPref.SHORTCUT_MACRO_RECORD, localizer.getMessage("lblSHORTCUT_MACRO_RECORD"), actMacroRecord, am, im)); + list.add(new Shortcut(FPref.SHORTCUT_MACRO_NEXT_ACTION, localizer.getMessage("lblSHORTCUT_MACRO_NEXT_ACTION"), actMacroNextAction, am, im)); + list.add(new Shortcut(FPref.SHORTCUT_CARD_ZOOM, localizer.getMessage("lblSHORTCUT_CARD_ZOOM"), actZoomCard, am, im)); return list; } // End initMatchShortcuts() diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/VAssignDamage.java b/forge-gui-desktop/src/main/java/forge/screens/match/VAssignDamage.java index 55f26f96155..e60359a11f2 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/VAssignDamage.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/VAssignDamage.java @@ -50,6 +50,7 @@ import forge.toolbox.FSkin; import forge.toolbox.FSkin.SkinnedPanel; import forge.view.FDialog; import forge.view.arcane.CardPanel; +import forge.util.Localizer; /** * Assembles Swing components of assign damage dialog. @@ -61,6 +62,7 @@ import forge.view.arcane.CardPanel; *

(V at beginning of class name denotes a view class.) */ public class VAssignDamage { + final Localizer localizer = Localizer.getInstance(); private final CMatchUI matchUI; // Width and height of blocker dialog @@ -78,12 +80,12 @@ public class VAssignDamage { private final GameEntityView defender; - private final JLabel lblTotalDamage = new FLabel.Builder().text("Available damage points: Unknown").build(); - private final JLabel lblAssignRemaining = new FLabel.Builder().text("Distribute the remaining damage points among lethally wounded entities").build(); + private final JLabel lblTotalDamage = new FLabel.Builder().text(localizer.getMessage("lblTotalDamageText")).build(); + private final JLabel lblAssignRemaining = new FLabel.Builder().text(localizer.getMessage("lblAssignRemainingText")).build(); // Label Buttons - private final FButton btnOK = new FButton("OK"); - private final FButton btnReset = new FButton("Reset"); - private final FButton btnAuto = new FButton("Auto"); + private final FButton btnOK = new FButton(localizer.getMessage("lblOk")); + private final FButton btnReset = new FButton(localizer.getMessage("lblReset")); + private final FButton btnAuto = new FButton(localizer.getMessage("lblAuto")); private static class DamageTarget { @@ -141,8 +143,8 @@ public class VAssignDamage { public VAssignDamage(final CMatchUI matchUI, final CardView attacker, final List blockers, final int damage0, final GameEntityView defender0, boolean overrideOrder) { this.matchUI = matchUI; - - dlg.setTitle("Assign damage dealt by " + attacker); + String s = localizer.getMessage("lbLAssignDamageDealtBy"); + dlg.setTitle(s.replace("%s",attacker.toString())); // Set damage storage vars totalDamageToAssign = damage0; @@ -165,8 +167,8 @@ public class VAssignDamage { final JPanel pnlInfo = new JPanel(new MigLayout("insets 0, gap 0, wrap")); pnlInfo.setOpaque(false); pnlInfo.add(lblTotalDamage, "gap 0 0 20px 5px"); - pnlInfo.add(new FLabel.Builder().text("Left click: Assign 1 damage. (Left Click + Control): Assign remaining damage up to lethal").build(), "gap 0 0 0 5px"); - pnlInfo.add(new FLabel.Builder().text("Right click: Unassign 1 damage. (Right Click + Control): Unassign all damage.").build(), "gap 0 0 0 5px"); + pnlInfo.add(new FLabel.Builder().text(localizer.getMessage("lblLClickDamageMessage")).build(), "gap 0 0 0 5px"); + pnlInfo.add(new FLabel.Builder().text(localizer.getMessage("lblRClickDamageMessage")).build(), "gap 0 0 0 5px"); // Defenders area final JPanel pnlDefenders = new JPanel(); @@ -401,7 +403,7 @@ public class VAssignDamage { StringBuilder sb = new StringBuilder(); sb.append(dmg); if( overkill >= 0 ) { - sb.append(" (Lethal"); + sb.append(" (" +localizer.getMessage("lblLethal")); if( overkill > 0 ) sb.append(" +").append(overkill); sb.append(")"); diff --git a/forge-gui/res/languages/en-US.properties b/forge-gui/res/languages/en-US.properties index 4365dccfd1b..b143e5d2118 100644 --- a/forge-gui/res/languages/en-US.properties +++ b/forge-gui/res/languages/en-US.properties @@ -253,4 +253,35 @@ lblRemoveArtifacts=Remove artifact cards in generated decks. PreventNonLandDuplicates=Prevent non-land duplicates in generated decks. #PlayerPanel.java lblName=Name -lblTeam=Team \ No newline at end of file +lblTeam=Team +#InputConfirmMulligan.java +lblKeep=Keep +lblYouAreGoingFirst=you are going first! +lblIsGoingFirst=is going first +lblYouAreGoing=you are going +lblMulligan=Mulligan +lblDoYouWantToKeepYourHand=Do you want to keep your hand? +lblOk=Ok +lblReset=Reset +lblAuto=Auto +#VAssignDamage.java +lbLAssignDamageDealtBy=Assign damage dealt by %s +lblLClickDamageMessage=Left click: Assign 1 damage. (Left Click + Control): Assign remaining damage up to lethal +lblRClickDamageMessage=Right click: Unassign 1 damage. (Right Click + Control): Unassign all damage. +lblTotalDamageText=Available damage points: Unknown +lblAssignRemainingText=Distribute the remaining damage points among lethally wounded entities +lblLethal=Lethal +#KeyboardShortcuts.java +lblSHORTCUT_SHOWSTACK=Match: show stack panel +lblSHORTCUT_SHOWCOMBAT=Match: show combat panel +lblSHORTCUT_SHOWCONSOLE=Match: show console panel +lblSHORTCUT_SHOWDEV=Match: show dev panel +lblSHORTCUT_CONCEDE=Match: concede game +lblSHORTCUT_ENDTURN=Match: pass priority until EOT or next stack event +lblSHORTCUT_ALPHASTRIKE=Match: Alpha Strike (attack with all available) +lblSHORTCUT_SHOWTARGETING=Match: toggle targeting visual overlay +lblSHORTCUT_AUTOYIELD_ALWAYS_YES=Match: auto-yield ability on stack (Always Yes) +lblSHORTCUT_AUTOYIELD_ALWAYS_NO=Match: auto-yield ability on stack (Always No) +lblSHORTCUT_MACRO_RECORD=Match: record a macro sequence of actions +lblSHORTCUT_MACRO_NEXT_ACTION=Match: execute next action in a recorded macro +lblSHORTCUT_CARD_ZOOM=Match: zoom the currently selected card \ No newline at end of file diff --git a/forge-gui/src/main/java/forge/match/input/InputConfirmMulligan.java b/forge-gui/src/main/java/forge/match/input/InputConfirmMulligan.java index c39a3b40fe6..ef8f454ecdd 100644 --- a/forge-gui/src/main/java/forge/match/input/InputConfirmMulligan.java +++ b/forge-gui/src/main/java/forge/match/input/InputConfirmMulligan.java @@ -29,7 +29,9 @@ import forge.game.zone.ZoneType; import forge.player.PlayerControllerHuman; import forge.util.ITriggerEvent; import forge.util.Lang; +import forge.util.Localizer; import forge.util.ThreadUtil; +import forge.util.Localizer; /** *

@@ -58,19 +60,20 @@ public class InputConfirmMulligan extends InputSyncronizedBase { /** {@inheritDoc} */ @Override public final void showMessage() { + final Localizer localizer = Localizer.getInstance(); final Game game = player.getGame(); final StringBuilder sb = new StringBuilder(); if (startingPlayer == player) { - sb.append(player).append(", you are going first!\n\n"); + sb.append(player).append(", "+ localizer.getMessage("lblYouAreGoingFirst") +"\n\n"); } else { - sb.append(startingPlayer.getName()).append(" is going first.\n"); - sb.append(player).append(", you are going ").append(Lang.getOrdinal(game.getPosition(player, startingPlayer))).append(".\n\n"); + sb.append(startingPlayer.getName()).append(" " + localizer.getMessage("lblIsGoingFirst") +".\n"); + sb.append(player).append(", "+ localizer.getMessage("lblYouAreGoing") +"").append(Lang.getOrdinal(game.getPosition(player, startingPlayer))).append(".\n\n"); } - getController().getGui().updateButtons(getOwner(), "Keep", "Mulligan", true, true, true); - sb.append("Do you want to keep your hand?"); + getController().getGui().updateButtons(getOwner(), localizer.getMessage("lblKeep"), localizer.getMessage("lblMulligan"), true, true, true); + sb.append(localizer.getMessage("lblDoYouWantToKeepYourHand")); showMessage(sb.toString()); } From da5b1a18bf6f247aea209148a9356cd0f25f7ec4 Mon Sep 17 00:00:00 2001 From: churrufli Date: Wed, 27 Feb 2019 20:13:44 +0100 Subject: [PATCH 10/21] Merge branch 'master' of https://git.cardforge.org/core-developers/forge --- .../src/main/java/forge/match/input/InputConfirmMulligan.java | 1 - 1 file changed, 1 deletion(-) diff --git a/forge-gui/src/main/java/forge/match/input/InputConfirmMulligan.java b/forge-gui/src/main/java/forge/match/input/InputConfirmMulligan.java index ef8f454ecdd..cd59ca3c93f 100644 --- a/forge-gui/src/main/java/forge/match/input/InputConfirmMulligan.java +++ b/forge-gui/src/main/java/forge/match/input/InputConfirmMulligan.java @@ -31,7 +31,6 @@ import forge.util.ITriggerEvent; import forge.util.Lang; import forge.util.Localizer; import forge.util.ThreadUtil; -import forge.util.Localizer; /** *

From 34380befaf10f1e2b58a562340db54120f5db538 Mon Sep 17 00:00:00 2001 From: Churrufli Date: Wed, 27 Feb 2019 19:36:16 +0000 Subject: [PATCH 11/21] Update AddBasicLandsDialog.java --- .../forge/screens/deckeditor/AddBasicLandsDialog.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/AddBasicLandsDialog.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/AddBasicLandsDialog.java index 59491730936..7b0dbe9978b 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/AddBasicLandsDialog.java +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/AddBasicLandsDialog.java @@ -6,12 +6,12 @@ * 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 . */ @@ -119,7 +119,7 @@ public class AddBasicLandsDialog { pnlSwamp.lblCount.setText(String.valueOf(pnlSwamp.count)); pnlMountain.lblCount.setText(String.valueOf(pnlMountain.count)); pnlForest.lblCount.setText(String.valueOf(pnlForest.count)); - + updateDeckInfoLabel(); } }); @@ -254,7 +254,7 @@ public class AddBasicLandsDialog { "{U} " + integer.format(pnlIsland.symbolCount) + " (" + percent.format(pnlIsland.symbolCount / totalSymbolCount) + ") | " + "{B} " + integer.format(pnlSwamp.symbolCount) + " (" + percent.format(pnlSwamp.symbolCount / totalSymbolCount) + ") | " + "{R} " + integer.format(pnlMountain.symbolCount) + " (" + percent.format(pnlMountain.symbolCount / totalSymbolCount) + ") | " + - "{G} " + integer.format(pnlForest.symbolCount) + " (" + percent.format(pnlForest.symbolCount / totalSymbolCount) + ")" + + "{G} " + integer.format(pnlForest.symbolCount) + " (" + percent.format(pnlForest.symbolCount / totalSymbolCount) + ")" + "

", false)); } From eedbdeca999bea5157e9edd806464413dfa6adbb Mon Sep 17 00:00:00 2001 From: KrazyTheFox Date: Wed, 27 Feb 2019 20:55:37 -0500 Subject: [PATCH 12/21] Add release notes --- forge-gui/release-files/CHANGES.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/forge-gui/release-files/CHANGES.txt b/forge-gui/release-files/CHANGES.txt index 05f0bf1829e..1e2551918a7 100644 --- a/forge-gui/release-files/CHANGES.txt +++ b/forge-gui/release-files/CHANGES.txt @@ -1,2 +1,6 @@ +- Set Selection Randomizer - +There's a new randomizer available when Forge asks you to choose sets. Given a few options, it will pick out a selection of random sets for use in either the deck editor or in quest mode. + + - Bug fixes - As always, this release of Forge features an assortment of bug fixes and improvements based on user feedback during the previous release run. From c091eefc840a4c780fe69b9b74a5b01342ef887c Mon Sep 17 00:00:00 2001 From: Chris H Date: Sat, 2 Mar 2019 21:20:47 -0500 Subject: [PATCH 13/21] Add gitlab templates --- .gitlab/issue_templates/Bug.md | 30 ++++++++++++++++++++++++++++++ .gitlab/issue_templates/Feature.md | 15 +++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 .gitlab/issue_templates/Bug.md create mode 100644 .gitlab/issue_templates/Feature.md diff --git a/.gitlab/issue_templates/Bug.md b/.gitlab/issue_templates/Bug.md new file mode 100644 index 00000000000..05014a331ce --- /dev/null +++ b/.gitlab/issue_templates/Bug.md @@ -0,0 +1,30 @@ +Summary + +(Summarize the bug encountered concisely) + + +Steps to reproduce + +(How one can reproduce the issue - this is very important. Specific cards and specific actions especially) + + +What is the current bug behavior? + +(What actually happens) + + +What is the expected correct behavior? + +(What you should see instead) + + +Relevant logs and/or screenshots + +(Paste/Attach your game.log from the crash - please use code blocks (```)) Also, provide screenshots of the current state. + + +Possible fixes + +(If you can, link to the line of code that might be responsible for the problem) + +/label ~needs-investigation \ No newline at end of file diff --git a/.gitlab/issue_templates/Feature.md b/.gitlab/issue_templates/Feature.md new file mode 100644 index 00000000000..712f6a75065 --- /dev/null +++ b/.gitlab/issue_templates/Feature.md @@ -0,0 +1,15 @@ +Summary + +(Summarize the feature you wish concisely) + + +Example screenshots + +(If this is a UI change, please provide an example screenshot of how this feature might work) + + +Feature type + +(Where in Forge does this belong? e.g. Quest Mode, Deck Editor, Limited, Constructed, etc.) + +/label ~feature request \ No newline at end of file From 93bd90f139c8f748e1bea08cf4e07b71d58cc41c Mon Sep 17 00:00:00 2001 From: Sol Date: Sun, 3 Mar 2019 17:47:01 +0000 Subject: [PATCH 14/21] Update Bug.md --- .gitlab/issue_templates/Bug.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitlab/issue_templates/Bug.md b/.gitlab/issue_templates/Bug.md index 05014a331ce..c2804f08ab3 100644 --- a/.gitlab/issue_templates/Bug.md +++ b/.gitlab/issue_templates/Bug.md @@ -8,6 +8,9 @@ Steps to reproduce (How one can reproduce the issue - this is very important. Specific cards and specific actions especially) +Which version of Forge are you on (Release, Snapshot? Desktop, Android?) + + What is the current bug behavior? (What actually happens) From 888f5953b129c4dd5ddf2f4beae1202f40b74699 Mon Sep 17 00:00:00 2001 From: Chris H Date: Sun, 3 Mar 2019 21:47:28 -0500 Subject: [PATCH 15/21] If a DeckList references a bogus card set/art combo ignore parts of it until it works --- .../src/main/java/forge/StaticData.java | 5 +- .../src/main/java/forge/card/CardDb.java | 26 ++++---- .../src/main/java/forge/deck/CardPool.java | 64 ++++++++++++------- 3 files changed, 58 insertions(+), 37 deletions(-) diff --git a/forge-core/src/main/java/forge/StaticData.java b/forge-core/src/main/java/forge/StaticData.java index 9e8629baf20..a984f68288e 100644 --- a/forge-core/src/main/java/forge/StaticData.java +++ b/forge-core/src/main/java/forge/StaticData.java @@ -2,10 +2,10 @@ package forge; import com.google.common.base.Predicate; import forge.card.CardDb; +import forge.card.CardDb.CardRequest; import forge.card.CardEdition; import forge.card.CardRules; import forge.card.PrintSheet; -import forge.card.CardDb.CardRequest; import forge.item.BoosterBox; import forge.item.FatPack; import forge.item.PaperCard; @@ -131,7 +131,7 @@ public class StaticData { return foil ? commonCards.getFoiled(card) : card; } - public void attemptToLoadCard(String encodedCardName, String setCode) { + public CardRules attemptToLoadCard(String encodedCardName, String setCode) { CardDb.CardRequest r = CardRequest.fromString(encodedCardName); String cardName = r.cardName; CardRules rules = cardReader.attemptToLoadCard(cardName, setCode); @@ -142,6 +142,7 @@ public class StaticData { commonCards.loadCard(cardName, rules); } } + return rules; } /** @return {@link forge.util.storage.IStorage}<{@link forge.item.SealedProduct.Template}> */ diff --git a/forge-core/src/main/java/forge/card/CardDb.java b/forge-core/src/main/java/forge/card/CardDb.java index 16af453f57a..4f8ea7a33f1 100644 --- a/forge-core/src/main/java/forge/card/CardDb.java +++ b/forge-core/src/main/java/forge/card/CardDb.java @@ -18,18 +18,15 @@ package forge.card; import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; -import com.google.common.collect.ListMultimap; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Multimaps; - +import com.google.common.collect.*; import forge.card.CardEdition.CardInSet; import forge.card.CardEdition.Type; import forge.deck.generation.IDeckGenPool; import forge.item.PaperCard; -import forge.util.*; - +import forge.util.CollectionSuppliers; +import forge.util.Lang; +import forge.util.MyRandom; +import forge.util.TextUtil; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; @@ -340,7 +337,7 @@ public final class CardDb implements ICardDatabase, IDeckGenPool { } if (request.artIndex <= 0) { // this stands for 'random art' - Collection candidates; + List candidates; if (reqEdition == null) { candidates = new ArrayList(cards); } @@ -355,12 +352,15 @@ public final class CardDb implements ICardDatabase, IDeckGenPool { if (candidates.isEmpty()) { return null; } - result = Aggregates.random(candidates); + + Collections.shuffle(candidates); //if card image doesn't exist for chosen candidate, try another one if possible - while (candidates.size() > 1 && !result.hasImage()) { - candidates.remove(result); - result = Aggregates.random(candidates); + for(PaperCard candidate : candidates) { + result = candidate; + if (result.hasImage()) { + break; + } } } else { diff --git a/forge-core/src/main/java/forge/deck/CardPool.java b/forge-core/src/main/java/forge/deck/CardPool.java index b484f31ab98..e9f3b7171a9 100644 --- a/forge-core/src/main/java/forge/deck/CardPool.java +++ b/forge-core/src/main/java/forge/deck/CardPool.java @@ -21,6 +21,7 @@ import com.google.common.base.Predicate; import com.google.common.collect.Lists; import forge.StaticData; import forge.card.CardDb; +import forge.card.CardRules; import forge.item.PaperCard; import forge.util.ItemPool; import forge.util.ItemPoolSorter; @@ -73,29 +74,12 @@ public class CardPool extends ItemPool { // NOTE: ART indices are "1" -based public void add(String cardName, String setCode, final int artIndex, final int amount) { + PaperCard paperCard = determineRequestedPaperCard(cardName, setCode, artIndex); - PaperCard paperCard = StaticData.instance().getCommonCards().getCard(cardName, setCode, artIndex); - final boolean isCommonCard = paperCard != null; - - if (!isCommonCard) { - paperCard = StaticData.instance().getVariantCards().getCard(cardName, setCode); - if (paperCard == null) { - StaticData.instance().attemptToLoadCard(cardName, setCode); - paperCard = StaticData.instance().getVariantCards().getCard(cardName, setCode); - } - } - - int artCount = 1; - if (paperCard != null) { - setCode = paperCard.getEdition(); - cardName = paperCard.getName(); - artCount = isCommonCard ? StaticData.instance().getCommonCards().getArtCount(cardName, setCode) : 1; - } else { - System.err.print("An unsupported card was requested: \"" + cardName + "\" from \"" + setCode + "\". "); - paperCard = StaticData.instance().getCommonCards().createUnsupportedCard(cardName); - } - - boolean artIndexExplicitlySet = artIndex > 0 || Character.isDigit(cardName.charAt(cardName.length() - 1)) && cardName.charAt(cardName.length() - 2) == CardDb.NameSetSeparator; + int artCount = Math.max(StaticData.instance().getCommonCards().getArtCount(cardName, setCode), 1); + boolean artIndexExplicitlySet = artIndex > 0 || + Character.isDigit(cardName.charAt(cardName.length() - 1)) && + cardName.charAt(cardName.length() - 2) == CardDb.NameSetSeparator; if (artIndexExplicitlySet || artCount <= 1) { // either a specific art index is specified, or there is only one art, so just add the card @@ -114,7 +98,43 @@ public class CardPool extends ItemPool { } } + private PaperCard determineRequestedPaperCard(String cardName, String setCode, final int artIndex) { + // Does Forge even know this card exists? + PaperCard uniqueCard = StaticData.instance().getCommonCards().getUniqueByName(cardName); + if (uniqueCard == null) { + uniqueCard = StaticData.instance().getVariantCards().getUniqueByName(cardName); + } + CardDb db = null; + boolean isCommonCard = true; + if (uniqueCard == null) { + // Both database lookups failed, made up card OR lazy loading? + CardRules rules = StaticData.instance().attemptToLoadCard(cardName, setCode); + if (rules == null) { + // Failed to find a common/variant/or unloaded version of that card + System.err.print("An unsupported card was requested: \"" + cardName + "\" from \"" + setCode + "\". "); + return StaticData.instance().getCommonCards().createUnsupportedCard(cardName); + } + isCommonCard = !rules.isVariant(); + + db = isCommonCard ? StaticData.instance().getCommonCards() : StaticData.instance().getVariantCards(); + uniqueCard = db.getUniqueByName(cardName); + } else { + isCommonCard = !uniqueCard.getRules().isVariant(); + db = isCommonCard ? StaticData.instance().getCommonCards() : StaticData.instance().getVariantCards(); + } + + PaperCard paperCard = db.getCard(cardName, setCode, artIndex); + if (paperCard == null) { + paperCard = db.getCard(cardName, setCode); + } + + if (paperCard == null) { + paperCard = uniqueCard; + } + + return paperCard; + } /** * Add all from a List of CardPrinted. From 063ebf2f705b3fcdb6a9bc92c6e2769e355b452a Mon Sep 17 00:00:00 2001 From: Agetian Date: Mon, 4 Mar 2019 15:04:21 +0300 Subject: [PATCH 16/21] - Added puzzle PS_RNA5. --- .../src/main/java/forge/ai/GameState.java | 30 +++++++++++++++++++ forge-gui/res/puzzle/PS_RNA5.pzl | 18 +++++++++++ 2 files changed, 48 insertions(+) create mode 100644 forge-gui/res/puzzle/PS_RNA5.pzl diff --git a/forge-ai/src/main/java/forge/ai/GameState.java b/forge-ai/src/main/java/forge/ai/GameState.java index db79263a93e..bd4c26c19b0 100644 --- a/forge-ai/src/main/java/forge/ai/GameState.java +++ b/forge-ai/src/main/java/forge/ai/GameState.java @@ -74,6 +74,7 @@ public abstract class GameState { private final Map cardToEnchantPlayerId = new HashMap<>(); private final Map markedDamage = new HashMap<>(); private final Map> cardToChosenClrs = new HashMap<>(); + private final Map cardToChosenCards = new HashMap<>(); private final Map cardToChosenType = new HashMap<>(); private final Map> cardToRememberedId = new HashMap<>(); private final Map> cardToImprintedId = new HashMap<>(); @@ -211,6 +212,10 @@ public abstract class GameState { // Remember the IDs of imprinted cards cardsReferencedByID.add(i); } + for (Card i : card.getChosenCards()) { + // Remember the IDs of chosen cards + cardsReferencedByID.add(i); + } if (game.getCombat() != null && game.getCombat().isAttacking(card)) { // Remember the IDs of attacked planeswalkers GameEntity def = game.getCombat().getDefenderByAttacker(card); @@ -312,6 +317,17 @@ public abstract class GameState { newText.append("|NamedCard:").append(c.getNamedCard()); } + List chosenCardIds = Lists.newArrayList(); + for (Object obj : c.getChosenCards()) { + if (obj instanceof Card) { + int id = ((Card)obj).getId(); + chosenCardIds.add(String.valueOf(id)); + } + } + if (!chosenCardIds.isEmpty()) { + newText.append("|ChosenCards:").append(TextUtil.join(chosenCardIds, ",")); + } + List rememberedCardIds = Lists.newArrayList(); for (Object obj : c.getRemembered()) { if (obj instanceof Card) { @@ -552,6 +568,7 @@ public abstract class GameState { cardToExiledWithId.clear(); markedDamage.clear(); cardToChosenClrs.clear(); + cardToChosenCards.clear(); cardToChosenType.clear(); cardToScript.clear(); cardAttackMap.clear(); @@ -947,6 +964,12 @@ public abstract class GameState { Card c = entry.getKey(); c.setNamedCard(entry.getValue()); } + + // Chosen cards + for (Entry entry : cardToChosenCards.entrySet()) { + Card c = entry.getKey(); + c.setChosenCards(entry.getValue()); + } } private void handleCardAttachments() { @@ -1143,6 +1166,13 @@ public abstract class GameState { cardToChosenClrs.put(c, Arrays.asList(info.substring(info.indexOf(':') + 1).split(","))); } else if (info.startsWith("ChosenType:")) { cardToChosenType.put(c, info.substring(info.indexOf(':') + 1)); + } else if (info.startsWith("ChosenCards:")) { + CardCollection chosen = new CardCollection(); + String[] idlist = info.substring(info.indexOf(':') + 1).split(","); + for (String id : idlist) { + chosen.add(idToCard.get(Integer.parseInt(id))); + } + cardToChosenCards.put(c, chosen); } else if (info.startsWith("NamedCard:")) { cardToNamedCard.put(c, info.substring(info.indexOf(':') + 1)); } else if (info.startsWith("ExecuteScript:")) { diff --git a/forge-gui/res/puzzle/PS_RNA5.pzl b/forge-gui/res/puzzle/PS_RNA5.pzl new file mode 100644 index 00000000000..c66ddea8afa --- /dev/null +++ b/forge-gui/res/puzzle/PS_RNA5.pzl @@ -0,0 +1,18 @@ +[metadata] +Name:Possibility Storm - Ravnica Allegiance #05 +URL:http://www.possibilitystorm.com/wp-content/uploads/2019/02/102.-RNA5.jpg +Goal:Win +Turns:1 +Difficulty:Rare +Description:What the... you have no lands? Who did that? (You did that.) Start at the beginning of your first main phase as you choose targets for Fall of the Thran's second chapter ability. You just drew the final card in your library. Win this turn. +[state] +humanlife=17 +ailife=16 +turn=1 +activeplayer=human +activephase=DRAW +activephaseadvance=MAIN1 +humanhand=Enter the Unknown;Wildgrowth Walker;Depths of Desire;Merfolk Branchwalker;Song of Freyalise;Rallying Roar +humangraveyard=Plains;Hallowed Fountain;Forest;Swamp;Island;Temple Garden +humanbattlefield=Jace, Ingenious Mind-Mage|Counters:LOYALTY=3;Famished Paladin;Vona, Butcher of Magan;Tenth District Guard;Cacophodon;Path of Discovery;Fall of the Thran|Counters:LORE=1 +aibattlefield=Temple Altisaur;Everdawn Champion;Baird, Steward of Argive;Imperial Ceratops|Id:1;Dauntless Bodyguard|ChosenCards:1 From 0b997a2937badeef8845277b88e0879ab8db0b81 Mon Sep 17 00:00:00 2001 From: Sol Date: Mon, 4 Mar 2019 13:13:35 +0000 Subject: [PATCH 17/21] Android max size image cache --- forge-gui-mobile/src/forge/assets/ImageCache.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/forge-gui-mobile/src/forge/assets/ImageCache.java b/forge-gui-mobile/src/forge/assets/ImageCache.java index 1cab15dc9da..681e1dec9b3 100644 --- a/forge-gui-mobile/src/forge/assets/ImageCache.java +++ b/forge-gui-mobile/src/forge/assets/ImageCache.java @@ -22,18 +22,17 @@ import com.badlogic.gdx.graphics.Pixmap.Format; import com.badlogic.gdx.graphics.Texture; import com.google.common.cache.CacheBuilder; import com.google.common.cache.LoadingCache; - import forge.ImageKeys; import forge.game.player.IHasIcon; import forge.item.InventoryItem; import forge.properties.ForgeConstants; import forge.util.ImageUtil; - import org.apache.commons.lang3.StringUtils; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; /** * This class stores ALL card images in a cache with soft values. this means @@ -53,7 +52,10 @@ public class ImageCache { // short prefixes to save memory private static final Set missingIconKeys = new HashSet(); - private static final LoadingCache cache = CacheBuilder.newBuilder().softValues().build(new ImageLoader()); + private static final LoadingCache cache = CacheBuilder.newBuilder() + .maximumSize(400) + .expireAfterAccess(15,TimeUnit.MINUTES) + .build(new ImageLoader()); public static final Texture defaultImage; private static boolean imageLoaded, delayLoadRequested; From 7da2316c0a6ebe7dfc23dcc77a87404c90ced92c Mon Sep 17 00:00:00 2001 From: Agetian Date: Mon, 4 Mar 2019 16:34:33 +0300 Subject: [PATCH 18/21] - Preparing Forge for Android publish 1.6.21.002 [incremental]. --- forge-gui-android/pom.xml | 2 +- forge-gui-ios/pom.xml | 2 +- forge-gui-mobile/src/forge/Forge.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/forge-gui-android/pom.xml b/forge-gui-android/pom.xml index 41868952585..42e2ce10dc8 100644 --- a/forge-gui-android/pom.xml +++ b/forge-gui-android/pom.xml @@ -6,7 +6,7 @@ jar -Xms1024m -Xmx1536m - 1.6.21.001 + 1.6.21.002 keystore alias storepass diff --git a/forge-gui-ios/pom.xml b/forge-gui-ios/pom.xml index 732d114fe9c..31c7a084629 100644 --- a/forge-gui-ios/pom.xml +++ b/forge-gui-ios/pom.xml @@ -6,7 +6,7 @@ jar -Xms128m -Xmx2048m - 1.6.21.001 + 1.6.21.002 diff --git a/forge-gui-mobile/src/forge/Forge.java b/forge-gui-mobile/src/forge/Forge.java index 38206affce0..ffb171f9447 100644 --- a/forge-gui-mobile/src/forge/Forge.java +++ b/forge-gui-mobile/src/forge/Forge.java @@ -34,7 +34,7 @@ import java.util.List; import java.util.Stack; public class Forge implements ApplicationListener { - public static final String CURRENT_VERSION = "1.6.21.001"; + public static final String CURRENT_VERSION = "1.6.21.002"; private static final ApplicationListener app = new Forge(); private static Clipboard clipboard; From 8a9c27f9aef383e49dabe444cb391247e88812bb Mon Sep 17 00:00:00 2001 From: Sol Date: Mon, 4 Mar 2019 15:58:06 +0000 Subject: [PATCH 19/21] Revert "Merge branch 'fix-bad-art-deck-art-corruption' into 'master'" This reverts merge request !1440 --- .../src/main/java/forge/StaticData.java | 5 +- .../src/main/java/forge/card/CardDb.java | 26 ++++---- .../src/main/java/forge/deck/CardPool.java | 64 +++++++------------ 3 files changed, 37 insertions(+), 58 deletions(-) diff --git a/forge-core/src/main/java/forge/StaticData.java b/forge-core/src/main/java/forge/StaticData.java index a984f68288e..9e8629baf20 100644 --- a/forge-core/src/main/java/forge/StaticData.java +++ b/forge-core/src/main/java/forge/StaticData.java @@ -2,10 +2,10 @@ package forge; import com.google.common.base.Predicate; import forge.card.CardDb; -import forge.card.CardDb.CardRequest; import forge.card.CardEdition; import forge.card.CardRules; import forge.card.PrintSheet; +import forge.card.CardDb.CardRequest; import forge.item.BoosterBox; import forge.item.FatPack; import forge.item.PaperCard; @@ -131,7 +131,7 @@ public class StaticData { return foil ? commonCards.getFoiled(card) : card; } - public CardRules attemptToLoadCard(String encodedCardName, String setCode) { + public void attemptToLoadCard(String encodedCardName, String setCode) { CardDb.CardRequest r = CardRequest.fromString(encodedCardName); String cardName = r.cardName; CardRules rules = cardReader.attemptToLoadCard(cardName, setCode); @@ -142,7 +142,6 @@ public class StaticData { commonCards.loadCard(cardName, rules); } } - return rules; } /** @return {@link forge.util.storage.IStorage}<{@link forge.item.SealedProduct.Template}> */ diff --git a/forge-core/src/main/java/forge/card/CardDb.java b/forge-core/src/main/java/forge/card/CardDb.java index 4f8ea7a33f1..16af453f57a 100644 --- a/forge-core/src/main/java/forge/card/CardDb.java +++ b/forge-core/src/main/java/forge/card/CardDb.java @@ -18,15 +18,18 @@ package forge.card; import com.google.common.base.Predicate; -import com.google.common.collect.*; +import com.google.common.collect.Iterables; +import com.google.common.collect.ListMultimap; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimaps; + import forge.card.CardEdition.CardInSet; import forge.card.CardEdition.Type; import forge.deck.generation.IDeckGenPool; import forge.item.PaperCard; -import forge.util.CollectionSuppliers; -import forge.util.Lang; -import forge.util.MyRandom; -import forge.util.TextUtil; +import forge.util.*; + import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; @@ -337,7 +340,7 @@ public final class CardDb implements ICardDatabase, IDeckGenPool { } if (request.artIndex <= 0) { // this stands for 'random art' - List candidates; + Collection candidates; if (reqEdition == null) { candidates = new ArrayList(cards); } @@ -352,15 +355,12 @@ public final class CardDb implements ICardDatabase, IDeckGenPool { if (candidates.isEmpty()) { return null; } - - Collections.shuffle(candidates); + result = Aggregates.random(candidates); //if card image doesn't exist for chosen candidate, try another one if possible - for(PaperCard candidate : candidates) { - result = candidate; - if (result.hasImage()) { - break; - } + while (candidates.size() > 1 && !result.hasImage()) { + candidates.remove(result); + result = Aggregates.random(candidates); } } else { diff --git a/forge-core/src/main/java/forge/deck/CardPool.java b/forge-core/src/main/java/forge/deck/CardPool.java index e9f3b7171a9..b484f31ab98 100644 --- a/forge-core/src/main/java/forge/deck/CardPool.java +++ b/forge-core/src/main/java/forge/deck/CardPool.java @@ -21,7 +21,6 @@ import com.google.common.base.Predicate; import com.google.common.collect.Lists; import forge.StaticData; import forge.card.CardDb; -import forge.card.CardRules; import forge.item.PaperCard; import forge.util.ItemPool; import forge.util.ItemPoolSorter; @@ -74,12 +73,29 @@ public class CardPool extends ItemPool { // NOTE: ART indices are "1" -based public void add(String cardName, String setCode, final int artIndex, final int amount) { - PaperCard paperCard = determineRequestedPaperCard(cardName, setCode, artIndex); - int artCount = Math.max(StaticData.instance().getCommonCards().getArtCount(cardName, setCode), 1); - boolean artIndexExplicitlySet = artIndex > 0 || - Character.isDigit(cardName.charAt(cardName.length() - 1)) && - cardName.charAt(cardName.length() - 2) == CardDb.NameSetSeparator; + PaperCard paperCard = StaticData.instance().getCommonCards().getCard(cardName, setCode, artIndex); + final boolean isCommonCard = paperCard != null; + + if (!isCommonCard) { + paperCard = StaticData.instance().getVariantCards().getCard(cardName, setCode); + if (paperCard == null) { + StaticData.instance().attemptToLoadCard(cardName, setCode); + paperCard = StaticData.instance().getVariantCards().getCard(cardName, setCode); + } + } + + int artCount = 1; + if (paperCard != null) { + setCode = paperCard.getEdition(); + cardName = paperCard.getName(); + artCount = isCommonCard ? StaticData.instance().getCommonCards().getArtCount(cardName, setCode) : 1; + } else { + System.err.print("An unsupported card was requested: \"" + cardName + "\" from \"" + setCode + "\". "); + paperCard = StaticData.instance().getCommonCards().createUnsupportedCard(cardName); + } + + boolean artIndexExplicitlySet = artIndex > 0 || Character.isDigit(cardName.charAt(cardName.length() - 1)) && cardName.charAt(cardName.length() - 2) == CardDb.NameSetSeparator; if (artIndexExplicitlySet || artCount <= 1) { // either a specific art index is specified, or there is only one art, so just add the card @@ -98,43 +114,7 @@ public class CardPool extends ItemPool { } } - private PaperCard determineRequestedPaperCard(String cardName, String setCode, final int artIndex) { - // Does Forge even know this card exists? - PaperCard uniqueCard = StaticData.instance().getCommonCards().getUniqueByName(cardName); - if (uniqueCard == null) { - uniqueCard = StaticData.instance().getVariantCards().getUniqueByName(cardName); - } - CardDb db = null; - boolean isCommonCard = true; - if (uniqueCard == null) { - // Both database lookups failed, made up card OR lazy loading? - CardRules rules = StaticData.instance().attemptToLoadCard(cardName, setCode); - if (rules == null) { - // Failed to find a common/variant/or unloaded version of that card - System.err.print("An unsupported card was requested: \"" + cardName + "\" from \"" + setCode + "\". "); - return StaticData.instance().getCommonCards().createUnsupportedCard(cardName); - } - isCommonCard = !rules.isVariant(); - - db = isCommonCard ? StaticData.instance().getCommonCards() : StaticData.instance().getVariantCards(); - uniqueCard = db.getUniqueByName(cardName); - } else { - isCommonCard = !uniqueCard.getRules().isVariant(); - db = isCommonCard ? StaticData.instance().getCommonCards() : StaticData.instance().getVariantCards(); - } - - PaperCard paperCard = db.getCard(cardName, setCode, artIndex); - if (paperCard == null) { - paperCard = db.getCard(cardName, setCode); - } - - if (paperCard == null) { - paperCard = uniqueCard; - } - - return paperCard; - } /** * Add all from a List of CardPrinted. From cc13020b4b6bc580bc8f40a4eba5906539c0e105 Mon Sep 17 00:00:00 2001 From: Agetian Date: Tue, 5 Mar 2019 08:35:36 +0300 Subject: [PATCH 20/21] - Preparing Forge for Android publish 1.6.21.003 [hotfix]. --- forge-gui-android/pom.xml | 2 +- forge-gui-ios/pom.xml | 2 +- forge-gui-mobile/src/forge/Forge.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/forge-gui-android/pom.xml b/forge-gui-android/pom.xml index 42e2ce10dc8..bb9023e6c52 100644 --- a/forge-gui-android/pom.xml +++ b/forge-gui-android/pom.xml @@ -6,7 +6,7 @@ jar -Xms1024m -Xmx1536m - 1.6.21.002 + 1.6.21.003 keystore alias storepass diff --git a/forge-gui-ios/pom.xml b/forge-gui-ios/pom.xml index 31c7a084629..a3ede2b57bf 100644 --- a/forge-gui-ios/pom.xml +++ b/forge-gui-ios/pom.xml @@ -6,7 +6,7 @@ jar -Xms128m -Xmx2048m - 1.6.21.002 + 1.6.21.003 diff --git a/forge-gui-mobile/src/forge/Forge.java b/forge-gui-mobile/src/forge/Forge.java index ffb171f9447..f5708da10fe 100644 --- a/forge-gui-mobile/src/forge/Forge.java +++ b/forge-gui-mobile/src/forge/Forge.java @@ -34,7 +34,7 @@ import java.util.List; import java.util.Stack; public class Forge implements ApplicationListener { - public static final String CURRENT_VERSION = "1.6.21.002"; + public static final String CURRENT_VERSION = "1.6.21.003"; private static final ApplicationListener app = new Forge(); private static Clipboard clipboard; From 3f15be27320f576a1e39d9e3d800a1c46bb370ed Mon Sep 17 00:00:00 2001 From: Agetian Date: Tue, 5 Mar 2019 09:10:48 +0300 Subject: [PATCH 21/21] - Fix inverse logic in TokenEffect (fixes e.g. Estrid, the Masked -1 ability) --- .../src/main/java/forge/game/ability/effects/TokenEffect.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/forge-game/src/main/java/forge/game/ability/effects/TokenEffect.java b/forge-game/src/main/java/forge/game/ability/effects/TokenEffect.java index 1636c8f6cc7..b1a59467e76 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/TokenEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/TokenEffect.java @@ -499,7 +499,7 @@ public class TokenEffect extends SpellAbilityEffect { // TODO update when doing Attach Update boolean canAttach = lki.isAttachment(); - if (canAttach && ge.canBeAttached(lki)) { + if (canAttach && !ge.canBeAttached(lki)) { canAttach = false; } @@ -507,7 +507,7 @@ public class TokenEffect extends SpellAbilityEffect { game.getAction().checkStaticAbilities(false); if (!canAttach) { - // Token can't attach it + // Token can't attach to it return false; }