diff --git a/.gitignore b/.gitignore index 8c1d40ad0d7..d9d5853e3f8 100644 --- a/.gitignore +++ b/.gitignore @@ -77,6 +77,11 @@ Mage/target Mage.Updater/target mage.updater.client/target +# Mage.Verify +Mage.Verify/target +Mage.Verify/AllCards.json.zip +Mage.Verify/AllSets.json.zip + releases Utils/author.txt .DS_Store diff --git a/Mage.Client/serverlist.txt b/Mage.Client/serverlist.txt index a049832b42d..e4c7e0a490c 100644 --- a/Mage.Client/serverlist.txt +++ b/Mage.Client/serverlist.txt @@ -1,6 +1,6 @@ XMage.de 1 (Europe/Germany) fast :xmage.de:17171 woogerworks (North America/USA) :xmage.woogerworks.com:17171 -woogerworks replacement (North America/USA) :158.69.192.238:17171 +woogerworks replacment (North America/USA) :158.69.192.238:17171 XMage.tahiti :xmage.tahiti.one:443 Seedds Server (Asia) :115.29.203.80:17171 localhost -> connect to your local server (must be started):localhost:17171 diff --git a/Mage.Client/src/main/java/mage/client/cards/DragCardGrid.java b/Mage.Client/src/main/java/mage/client/cards/DragCardGrid.java index ee968304b7f..125023b4e5b 100644 --- a/Mage.Client/src/main/java/mage/client/cards/DragCardGrid.java +++ b/Mage.Client/src/main/java/mage/client/cards/DragCardGrid.java @@ -576,7 +576,7 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg void cardsSelected(); void hideCards(Collection card); - + void duplicateCards(Collection cards); void showAll(); @@ -1094,6 +1094,7 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg l.duplicateCards(toDuplicate); } } + private void showAll() { for (DragCardGridListener l : listeners) { l.showAll(); @@ -1381,7 +1382,6 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg while (m.find()) { System.out.println("0=" + m.group(0) + ",,,1=" + m.group(1) + ",,,2=" + m.group(2) + ",,,3=" + m.group(3)); str = "Add" + m.group(1) + m.group(3) + "to your mana pool"; - System.out.println("Found " + m.group(2) + " in " + card.getName()); int num = 1; if (manaCounts.get(m.group(2)) != null) { num = manaCounts.get(m.group(2)); @@ -1675,7 +1675,7 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg // And add it cardContent.add(cardPanel); cardViews.put(card.getId(), cardPanel); - + if (duplicated) { sortIntoGrid(card); eventSource.addSpecificCard(card, "add-specific-card"); diff --git a/Mage.Client/src/main/java/mage/client/components/KeyBindButton.java b/Mage.Client/src/main/java/mage/client/components/KeyBindButton.java new file mode 100644 index 00000000000..ea16158ad19 --- /dev/null +++ b/Mage.Client/src/main/java/mage/client/components/KeyBindButton.java @@ -0,0 +1,116 @@ +package mage.client.components; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPopupMenu; +import mage.client.dialog.PreferencesDialog; + +/** + * + * @author Campbell Suter + */ +public class KeyBindButton extends JButton implements ActionListener { + + private final PreferencesDialog preferences; + private final String key; + private PopupItem item; + private JPopupMenu menu; + private int keyCode; + private String text; + + /** + * For the IDE only, do not use! + */ + public KeyBindButton() { + this(null, null); + } + + public KeyBindButton(PreferencesDialog preferences, String key) { + this.preferences = preferences; + this.key = key; + addActionListener(this); + fixText(); + } + + private JPopupMenu getMenu() { + menu = new JPopupMenu(); + menu.add(item = new PopupItem()); + return menu; + } + + private void applyNewKeycode(int code) { + preferences.getKeybindButtons().stream() + .filter(b -> b != KeyBindButton.this) + .filter(b -> b.getKeyCode() == code) + .forEach(b -> b.setKeyCode(0)); + + setKeyCode(code); + menu.setVisible(false); + } + + private void fixText() { + if (keyCode == 0) { + text = ""; + } else { + text = KeyEvent.getKeyText(keyCode); + } + repaint(); + } + + public void setKeyCode(int keyCode) { + this.keyCode = keyCode; + switch (keyCode) { + case KeyEvent.VK_ESCAPE: + case KeyEvent.VK_SPACE: + keyCode = 0; + } + fixText(); + setSize(getPreferredSize()); + } + + public int getKeyCode() { + return keyCode; + } + + @Override + public String getText() { + return text; + } + + public String getKey() { + return key; + } + + @Override + public void actionPerformed(ActionEvent e) { + getMenu().show(this, 0, 0); + item.requestFocusInWindow(); + } + + private class PopupItem extends JLabel implements KeyListener { + + public PopupItem() { + super("Press a key"); + addKeyListener(this); + setFocusable(true); + } + + @Override + public void keyTyped(KeyEvent e) { + } + + @Override + public void keyPressed(KeyEvent e) { + applyNewKeycode(e.getKeyCode()); + } + + @Override + public void keyReleased(KeyEvent e) { + } + + } +} diff --git a/Mage.Client/src/main/java/mage/client/components/KeyboundButton.java b/Mage.Client/src/main/java/mage/client/components/KeyboundButton.java new file mode 100644 index 00000000000..c1f806cd712 --- /dev/null +++ b/Mage.Client/src/main/java/mage/client/components/KeyboundButton.java @@ -0,0 +1,40 @@ +package mage.client.components; + +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics; +import javax.swing.JButton; +import mage.client.dialog.PreferencesDialog; + +/** + * + * @author Campbell Suter + */ +public class KeyboundButton extends JButton { + + private final String text; + private static final Font keyFont = new Font(Font.SANS_SERIF, Font.BOLD, 13); + + public KeyboundButton(String key) { + text = PreferencesDialog.getCachedKeyText(key); + } + + @Override + protected void paintComponent(Graphics g) { + if (ui != null && g != null) { + Graphics sg = g.create(); + try { + ui.update(sg, this); + sg.setColor(Color.white); + sg.setFont(keyFont); + + int textWidth = sg.getFontMetrics(keyFont).stringWidth(text); + int centerX = (getWidth() - textWidth) / 2; + + sg.drawString(text, centerX, 28); + } finally { + sg.dispose(); + } + } + } +} diff --git a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form index 4cf0b3303cc..763fa551592 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form +++ b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form @@ -3949,7 +3949,7 @@ - + @@ -4171,7 +4171,7 @@ - + @@ -4230,7 +4230,7 @@ - + @@ -4744,7 +4744,7 @@ - + @@ -5655,7 +5655,7 @@ - + @@ -5874,6 +5874,251 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java index 57ab43e6e32..1b3978f35c9 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java @@ -37,11 +37,14 @@ import java.awt.BorderLayout; import java.awt.Color; import java.awt.Image; import java.awt.Rectangle; +import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import java.io.File; +import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.prefs.BackingStoreException; import java.util.prefs.Preferences; @@ -56,10 +59,12 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JSlider; import javax.swing.JTextField; +import javax.swing.KeyStroke; import javax.swing.border.Border; import javax.swing.filechooser.FileFilter; import mage.client.MageFrame; import mage.client.SessionHandler; +import mage.client.components.KeyBindButton; import mage.client.util.Config; import mage.client.util.GUISizeHelper; import mage.client.util.ImageHelper; @@ -82,297 +87,308 @@ import org.apache.log4j.Logger; */ public class PreferencesDialog extends javax.swing.JDialog { - private static final Logger logger = Logger.getLogger(PreferencesDialog.class); + private static final Logger logger = Logger.getLogger(PreferencesDialog.class); - public static final String KEY_SHOW_TOOLTIPS_DELAY = "showTooltipsDelay"; - public static final String KEY_SHOW_CARD_NAMES = "showCardNames"; - public static final String KEY_PERMANENTS_IN_ONE_PILE = "nonLandPermanentsInOnePile"; - public static final String KEY_SHOW_PLAYER_NAMES_PERMANENTLY = "showPlayerNamesPermanently"; - public static final String KEY_SHOW_ABILITY_PICKER_FORCED = "showAbilityPicker"; - public static final String KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS = "gameAllowRequestShowHandCards"; - public static final String KEY_GAME_SHOW_STORM_COUNTER = "gameShowStormCounter"; - public static final String KEY_GAME_CONFIRM_EMPTY_MANA_POOL = "gameConfirmEmptyManaPool"; - public static final String KEY_GAME_ASK_MOVE_TO_GRAVE_ORDER = "gameAskMoveToGraveORder"; + public static final String KEY_SHOW_TOOLTIPS_DELAY = "showTooltipsDelay"; + public static final String KEY_SHOW_CARD_NAMES = "showCardNames"; + public static final String KEY_PERMANENTS_IN_ONE_PILE = "nonLandPermanentsInOnePile"; + public static final String KEY_SHOW_PLAYER_NAMES_PERMANENTLY = "showPlayerNamesPermanently"; + public static final String KEY_SHOW_ABILITY_PICKER_FORCED = "showAbilityPicker"; + public static final String KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS = "gameAllowRequestShowHandCards"; + public static final String KEY_GAME_SHOW_STORM_COUNTER = "gameShowStormCounter"; + public static final String KEY_GAME_CONFIRM_EMPTY_MANA_POOL = "gameConfirmEmptyManaPool"; + public static final String KEY_GAME_ASK_MOVE_TO_GRAVE_ORDER = "gameAskMoveToGraveORder"; - public static final String KEY_GUI_TABLE_FONT_SIZE = "guiTableFontSize"; - public static final String KEY_GUI_CHAT_FONT_SIZE = "guiChatFontSize"; - public static final String KEY_GUI_CARD_HAND_SIZE = "guiCardHandSize"; - public static final String KEY_GUI_CARD_EDITOR_SIZE = "guiCardEditorSize"; - public static final String KEY_GUI_CARD_OFFSET_SIZE = "guiCardOffsetSize"; - public static final String KEY_GUI_ENLARGED_IMAGE_SIZE = "guiEnlargedImageSize"; + public static final String KEY_GUI_TABLE_FONT_SIZE = "guiTableFontSize"; + public static final String KEY_GUI_CHAT_FONT_SIZE = "guiChatFontSize"; + public static final String KEY_GUI_CARD_HAND_SIZE = "guiCardHandSize"; + public static final String KEY_GUI_CARD_EDITOR_SIZE = "guiCardEditorSize"; + public static final String KEY_GUI_CARD_OFFSET_SIZE = "guiCardOffsetSize"; + public static final String KEY_GUI_ENLARGED_IMAGE_SIZE = "guiEnlargedImageSize"; - public static final String KEY_GUI_STACK_WIDTH = "guiStackWidth"; - public static final String KEY_GUI_TOOLTIP_SIZE = "guiTooltipSize"; - public static final String KEY_GUI_DIALOG_FONT_SIZE = "guiDialogFontSize"; - public static final String KEY_GUI_FEEDBACK_AREA_SIZE = "guiFeedbackAreaSize"; - public static final String KEY_GUI_CARD_OTHER_ZONES_SIZE = "guiCardOtherZonesSize"; - public static final String KEY_GUI_CARD_BATTLEFIELD_MIN_SIZE = "guiCardBattlefieldMinSize"; - public static final String KEY_GUI_CARD_BATTLEFIELD_MAX_SIZE = "guiCardBattlefieldMaxSize"; + public static final String KEY_GUI_STACK_WIDTH = "guiStackWidth"; + public static final String KEY_GUI_TOOLTIP_SIZE = "guiTooltipSize"; + public static final String KEY_GUI_DIALOG_FONT_SIZE = "guiDialogFontSize"; + public static final String KEY_GUI_FEEDBACK_AREA_SIZE = "guiFeedbackAreaSize"; + public static final String KEY_GUI_CARD_OTHER_ZONES_SIZE = "guiCardOtherZonesSize"; + public static final String KEY_GUI_CARD_BATTLEFIELD_MIN_SIZE = "guiCardBattlefieldMinSize"; + public static final String KEY_GUI_CARD_BATTLEFIELD_MAX_SIZE = "guiCardBattlefieldMaxSize"; - public static final String KEY_GAME_LOG_AUTO_SAVE = "gameLogAutoSave"; - public static final String KEY_DRAFT_LOG_AUTO_SAVE = "draftLogAutoSave"; + public static final String KEY_GAME_LOG_AUTO_SAVE = "gameLogAutoSave"; + public static final String KEY_DRAFT_LOG_AUTO_SAVE = "draftLogAutoSave"; - public static final String KEY_CARD_IMAGES_USE_DEFAULT = "cardImagesUseDefault"; - public static final String KEY_CARD_IMAGES_PATH = "cardImagesPath"; - public static final String KEY_CARD_IMAGES_THREADS = "cardImagesThreads"; - public static final String KEY_CARD_IMAGES_CHECK = "cardImagesCheck"; - public static final String KEY_CARD_IMAGES_SAVE_TO_ZIP = "cardImagesSaveToZip"; - public static final String KEY_CARD_IMAGES_PREF_LANGUAGE = "cardImagesPreferedImageLaguage"; + public static final String KEY_CARD_IMAGES_USE_DEFAULT = "cardImagesUseDefault"; + public static final String KEY_CARD_IMAGES_PATH = "cardImagesPath"; + public static final String KEY_CARD_IMAGES_THREADS = "cardImagesThreads"; + public static final String KEY_CARD_IMAGES_CHECK = "cardImagesCheck"; + public static final String KEY_CARD_IMAGES_SAVE_TO_ZIP = "cardImagesSaveToZip"; + public static final String KEY_CARD_IMAGES_PREF_LANGUAGE = "cardImagesPreferedImageLaguage"; - public static final String KEY_CARD_RENDERING_FALLBACK = "cardRenderingFallback"; - public static final String KEY_CARD_RENDERING_REMINDER_TEXT = "cardRenderingReminderText"; - public static final String KEY_CARD_RENDERING_SET_SYMBOL = "cardRenderingSetSymbol"; - - public static final String KEY_BACKGROUND_IMAGE = "backgroundImage"; - public static final String KEY_BATTLEFIELD_IMAGE = "battlefieldImage"; - public static final String KEY_BACKGROUND_IMAGE_DEFAULT = "backgroundImagedDefault"; - public static final String KEY_BATTLEFIELD_IMAGE_RANDOM = "battlefieldImagerandom"; - public static final String KEY_BATTLEFIELD_IMAGE_DEFAULT = "battlefieldImageDefault"; + public static final String KEY_CARD_RENDERING_FALLBACK = "cardRenderingFallback"; + public static final String KEY_CARD_RENDERING_REMINDER_TEXT = "cardRenderingReminderText"; + public static final String KEY_CARD_RENDERING_SET_SYMBOL = "cardRenderingSetSymbol"; - public static final String KEY_SOUNDS_GAME_ON = "soundsOn"; - public static final String KEY_SOUNDS_DRAFT_ON = "soundsDraftOn"; - public static final String KEY_SOUNDS_SKIP_BUTTONS_ON = "soundsSkipButtonsOn"; - public static final String KEY_SOUNDS_OTHER_ON = "soundsOtherOn"; - public static final String KEY_SOUNDS_MATCH_MUSIC_ON = "soundsMatchMusicOn"; - public static final String KEY_SOUNDS_MATCH_MUSIC_PATH = "soundsMatchMusicPath"; + public static final String KEY_BACKGROUND_IMAGE = "backgroundImage"; + public static final String KEY_BATTLEFIELD_IMAGE = "battlefieldImage"; + public static final String KEY_BACKGROUND_IMAGE_DEFAULT = "backgroundImagedDefault"; + public static final String KEY_BATTLEFIELD_IMAGE_RANDOM = "battlefieldImagerandom"; + public static final String KEY_BATTLEFIELD_IMAGE_DEFAULT = "battlefieldImageDefault"; - public static final String KEY_BIG_CARD_TOGGLED = "bigCardToggled"; + public static final String KEY_SOUNDS_GAME_ON = "soundsOn"; + public static final String KEY_SOUNDS_DRAFT_ON = "soundsDraftOn"; + public static final String KEY_SOUNDS_SKIP_BUTTONS_ON = "soundsSkipButtonsOn"; + public static final String KEY_SOUNDS_OTHER_ON = "soundsOtherOn"; + public static final String KEY_SOUNDS_MATCH_MUSIC_ON = "soundsMatchMusicOn"; + public static final String KEY_SOUNDS_MATCH_MUSIC_PATH = "soundsMatchMusicPath"; - // Phases - public static final String UPKEEP_YOU = "upkeepYou"; - public static final String DRAW_YOU = "drawYou"; - public static final String MAIN_YOU = "mainYou"; - public static final String BEFORE_COMBAT_YOU = "beforeCombatYou"; - public static final String END_OF_COMBAT_YOU = "endOfCombatYou"; - public static final String MAIN_TWO_YOU = "main2You"; - public static final String END_OF_TURN_YOU = "endOfTurnYou"; + public static final String KEY_BIG_CARD_TOGGLED = "bigCardToggled"; - public static final String UPKEEP_OTHERS = "upkeepOthers"; - public static final String DRAW_OTHERS = "drawOthers"; - public static final String MAIN_OTHERS = "mainOthers"; - public static final String BEFORE_COMBAT_OTHERS = "beforeCombatOthers"; - public static final String END_OF_COMBAT_OTHERS = "endOfCombatOthers"; - public static final String MAIN_TWO_OTHERS = "main2Others"; - public static final String END_OF_TURN_OTHERS = "endOfTurnOthers"; + // Phases + public static final String UPKEEP_YOU = "upkeepYou"; + public static final String DRAW_YOU = "drawYou"; + public static final String MAIN_YOU = "mainYou"; + public static final String BEFORE_COMBAT_YOU = "beforeCombatYou"; + public static final String END_OF_COMBAT_YOU = "endOfCombatYou"; + public static final String MAIN_TWO_YOU = "main2You"; + public static final String END_OF_TURN_YOU = "endOfTurnYou"; - public static final String KEY_STOP_ATTACK = "stopDeclareAttacksStep"; - public static final String KEY_STOP_BLOCK = "stopDeclareBlockersStep"; - public static final String KEY_STOP_ALL_MAIN_PHASES = "stopOnAllMainPhases"; - public static final String KEY_STOP_ALL_END_PHASES = "stopOnAllEndPhases"; - public static final String KEY_PASS_PRIORITY_CAST = "passPriorityCast"; - public static final String KEY_PASS_PRIORITY_ACTIVATION = "passPriorityActivation"; - public static final String KEY_AUTO_ORDER_TRIGGER = "autoOrderTrigger"; - public static final String KEY_USE_FIRST_MANA_ABILITY = "useFirstManaAbility"; + public static final String UPKEEP_OTHERS = "upkeepOthers"; + public static final String DRAW_OTHERS = "drawOthers"; + public static final String MAIN_OTHERS = "mainOthers"; + public static final String BEFORE_COMBAT_OTHERS = "beforeCombatOthers"; + public static final String END_OF_COMBAT_OTHERS = "endOfCombatOthers"; + public static final String MAIN_TWO_OTHERS = "main2Others"; + public static final String END_OF_TURN_OTHERS = "endOfTurnOthers"; - // mana auto payment - public static final String KEY_GAME_MANA_AUTOPAYMENT = "gameManaAutopayment"; - public static final String KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE = "gameManaAutopaymentOnlyOne"; + public static final String KEY_STOP_ATTACK = "stopDeclareAttacksStep"; + public static final String KEY_STOP_BLOCK = "stopDeclareBlockersStep"; + public static final String KEY_STOP_ALL_MAIN_PHASES = "stopOnAllMainPhases"; + public static final String KEY_STOP_ALL_END_PHASES = "stopOnAllEndPhases"; + public static final String KEY_PASS_PRIORITY_CAST = "passPriorityCast"; + public static final String KEY_PASS_PRIORITY_ACTIVATION = "passPriorityActivation"; + public static final String KEY_AUTO_ORDER_TRIGGER = "autoOrderTrigger"; + public static final String KEY_USE_FIRST_MANA_ABILITY = "useFirstManaAbility"; - // Size of frame to check if divider locations should be used - public static final String KEY_MAGE_PANEL_LAST_SIZE = "gamepanelLastSize"; + // mana auto payment + public static final String KEY_GAME_MANA_AUTOPAYMENT = "gameManaAutopayment"; + public static final String KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE = "gameManaAutopaymentOnlyOne"; - // pref settings of table settings and filtering - public static final String KEY_TABLES_FILTER_SETTINGS = "tablePanelFilterSettings"; - public static final String KEY_TABLES_COLUMNS_WIDTH = "tablePanelColumnWidth"; - public static final String KEY_TABLES_COLUMNS_ORDER = "tablePanelColumnSort"; + // Size of frame to check if divider locations should be used + public static final String KEY_MAGE_PANEL_LAST_SIZE = "gamepanelLastSize"; - // last sort settings used in deck editor - public static final String KEY_DECK_EDITOR_LAST_SORT = "deckEditorLastSort"; - public static final String KEY_DECK_EDITOR_LAST_SEPARATE_CREATURES = "deckEditorLastSeparateCreatures"; + // pref settings of table settings and filtering + public static final String KEY_TABLES_FILTER_SETTINGS = "tablePanelFilterSettings"; + public static final String KEY_TABLES_COLUMNS_WIDTH = "tablePanelColumnWidth"; + public static final String KEY_TABLES_COLUMNS_ORDER = "tablePanelColumnSort"; - // positions of divider bars - public static final String KEY_TABLES_DIVIDER_LOCATION_1 = "tablePanelDividerLocation1"; - public static final String KEY_TABLES_DIVIDER_LOCATION_2 = "tablePanelDividerLocation2"; - public static final String KEY_TABLES_DIVIDER_LOCATION_3 = "tablePanelDividerLocation3"; + // last sort settings used in deck editor + public static final String KEY_DECK_EDITOR_LAST_SORT = "deckEditorLastSort"; + public static final String KEY_DECK_EDITOR_LAST_SEPARATE_CREATURES = "deckEditorLastSeparateCreatures"; - // Positions of deck editor divider bars - public static final String KEY_EDITOR_HORIZONTAL_DIVIDER_LOCATION = "editorHorizontalDividerLocation"; - public static final String KEY_EDITOR_DECKAREA_SETTINGS = "editorDeckAreaSettings"; + // positions of divider bars + public static final String KEY_TABLES_DIVIDER_LOCATION_1 = "tablePanelDividerLocation1"; + public static final String KEY_TABLES_DIVIDER_LOCATION_2 = "tablePanelDividerLocation2"; + public static final String KEY_TABLES_DIVIDER_LOCATION_3 = "tablePanelDividerLocation3"; - // user list - public static final String KEY_USERS_COLUMNS_WIDTH = "userPanelColumnWidth"; - public static final String KEY_USERS_COLUMNS_ORDER = "userPanelColumnSort"; - // table waiting dialog - public static final String KEY_TABLE_WAITING_WIDTH = "tableWaitingPanelWidth"; - public static final String KEY_TABLE_WAITING_HEIGHT = "tableWaitingPanelHeight"; - public static final String KEY_TABLE_WAITING_COLUMNS_WIDTH = "tableWaitingPanelColumnWidth"; - public static final String KEY_TABLE_WAITING_COLUMNS_ORDER = "tableWaitingPanelColumnSort"; + // Positions of deck editor divider bars + public static final String KEY_EDITOR_HORIZONTAL_DIVIDER_LOCATION = "editorHorizontalDividerLocation"; + public static final String KEY_EDITOR_DECKAREA_SETTINGS = "editorDeckAreaSettings"; - public static final String KEY_GAMEPANEL_DIVIDER_LOCATION_0 = "gamepanelDividerLocation0"; - public static final String KEY_GAMEPANEL_DIVIDER_LOCATION_1 = "gamepanelDividerLocation1"; - public static final String KEY_GAMEPANEL_DIVIDER_LOCATION_2 = "gamepanelDividerLocation2"; + // user list + public static final String KEY_USERS_COLUMNS_WIDTH = "userPanelColumnWidth"; + public static final String KEY_USERS_COLUMNS_ORDER = "userPanelColumnSort"; + // table waiting dialog + public static final String KEY_TABLE_WAITING_WIDTH = "tableWaitingPanelWidth"; + public static final String KEY_TABLE_WAITING_HEIGHT = "tableWaitingPanelHeight"; + public static final String KEY_TABLE_WAITING_COLUMNS_WIDTH = "tableWaitingPanelColumnWidth"; + public static final String KEY_TABLE_WAITING_COLUMNS_ORDER = "tableWaitingPanelColumnSort"; - public static final String KEY_TOURNAMENT_PLAYER_COLUMNS_WIDTH = "tournamentPlayerPanelColumnWidth"; - public static final String KEY_TOURNAMENT_PLAYER_COLUMNS_ORDER = "tournamentPlayerPanelColumnSort"; - public static final String KEY_TOURNAMENT_MATCH_COLUMNS_WIDTH = "tournamentMatchPanelColumnWidth"; - public static final String KEY_TOURNAMENT_MATCH_COLUMNS_ORDER = "tournamentMatchPanelColumnSort"; - public static final String KEY_TOURNAMENT_DIVIDER_LOCATION_1 = "tournamentPanelDividerLocation1"; - public static final String KEY_TOURNAMENT_DIVIDER_LOCATION_2 = "tournamentPanelDividerLocation2"; + public static final String KEY_GAMEPANEL_DIVIDER_LOCATION_0 = "gamepanelDividerLocation0"; + public static final String KEY_GAMEPANEL_DIVIDER_LOCATION_1 = "gamepanelDividerLocation1"; + public static final String KEY_GAMEPANEL_DIVIDER_LOCATION_2 = "gamepanelDividerLocation2"; - // pref setting for new table dialog - public static final String KEY_NEW_TABLE_NAME = "newTableName"; - public static final String KEY_NEW_TABLE_PASSWORD = "newTablePassword"; - public static final String KEY_NEW_TABLE_PASSWORD_JOIN = "newTablePasswordJoin"; - public static final String KEY_NEW_TABLE_DECK_TYPE = "newTableDeckType"; - public static final String KEY_NEW_TABLE_TIME_LIMIT = "newTableTimeLimit"; - public static final String KEY_NEW_TABLE_GAME_TYPE = "newTableGameType"; - public static final String KEY_NEW_TABLE_NUMBER_OF_WINS = "newTableNumberOfWins"; - public static final String KEY_NEW_TABLE_ROLLBACK_TURNS_ALLOWED = "newTableRollbackTurnsAllowed"; - public static final String KEY_NEW_TABLE_NUMBER_OF_FREE_MULLIGANS = "newTableNumberOfFreeMulligans"; - public static final String KEY_NEW_TABLE_DECK_FILE = "newTableDeckFile"; - public static final String KEY_NEW_TABLE_RANGE = "newTableRange"; - public static final String KEY_NEW_TABLE_ATTACK_OPTION = "newTableAttackOption"; - public static final String KEY_NEW_TABLE_SKILL_LEVEL = "newTableSkillLevel"; - public static final String KEY_NEW_TABLE_NUMBER_PLAYERS = "newTableNumberPlayers"; - public static final String KEY_NEW_TABLE_PLAYER_TYPES = "newTablePlayerTypes"; - public static final String KEY_NEW_TABLE_QUIT_RATIO = "newTableQuitRatio"; - public static final String KEY_NEW_TABLE_RATED = "newTableRated"; + public static final String KEY_TOURNAMENT_PLAYER_COLUMNS_WIDTH = "tournamentPlayerPanelColumnWidth"; + public static final String KEY_TOURNAMENT_PLAYER_COLUMNS_ORDER = "tournamentPlayerPanelColumnSort"; + public static final String KEY_TOURNAMENT_MATCH_COLUMNS_WIDTH = "tournamentMatchPanelColumnWidth"; + public static final String KEY_TOURNAMENT_MATCH_COLUMNS_ORDER = "tournamentMatchPanelColumnSort"; + public static final String KEY_TOURNAMENT_DIVIDER_LOCATION_1 = "tournamentPanelDividerLocation1"; + public static final String KEY_TOURNAMENT_DIVIDER_LOCATION_2 = "tournamentPanelDividerLocation2"; - // pref setting for new tournament dialog - public static final String KEY_NEW_TOURNAMENT_NAME = "newTournamentName"; - public static final String KEY_NEW_TOURNAMENT_PASSWORD = "newTournamentPassword"; - public static final String KEY_NEW_TOURNAMENT_TIME_LIMIT = "newTournamentTimeLimit"; - public static final String KEY_NEW_TOURNAMENT_CONSTR_TIME = "newTournamentConstructionTime"; - public static final String KEY_NEW_TOURNAMENT_TYPE = "newTournamentType"; - public static final String KEY_NEW_TOURNAMENT_NUMBER_OF_FREE_MULLIGANS = "newTournamentNumberOfFreeMulligans"; - public static final String KEY_NEW_TOURNAMENT_NUMBER_OF_WINS = "newTournamentNumberOfWins"; - public static final String KEY_NEW_TOURNAMENT_PACKS_SEALED = "newTournamentPacksSealed"; - public static final String KEY_NEW_TOURNAMENT_PACKS_DRAFT = "newTournamentPacksDraft"; - public static final String KEY_NEW_TOURNAMENT_PACKS_RANDOM_DRAFT = "newTournamentPacksRandomDraft"; - public static final String KEY_NEW_TOURNAMENT_PLAYERS_SEALED = "newTournamentPlayersSealed"; - public static final String KEY_NEW_TOURNAMENT_PLAYERS_DRAFT = "newTournamentPlayersDraft"; - public static final String KEY_NEW_TOURNAMENT_DRAFT_TIMING = "newTournamentDraftTiming"; - public static final String KEY_NEW_TOURNAMENT_ALLOW_SPECTATORS = "newTournamentAllowSpectators"; - public static final String KEY_NEW_TOURNAMENT_ALLOW_ROLLBACKS = "newTournamentAllowRollbacks"; - public static final String KEY_NEW_TOURNAMENT_DECK_FILE = "newTournamentDeckFile"; - public static final String KEY_NEW_TOURNAMENT_QUIT_RATIO = "newTournamentQuitRatio"; - public static final String KEY_NEW_TOURNAMENT_RATED = "newTournamentRated"; + // pref setting for new table dialog + public static final String KEY_NEW_TABLE_NAME = "newTableName"; + public static final String KEY_NEW_TABLE_PASSWORD = "newTablePassword"; + public static final String KEY_NEW_TABLE_PASSWORD_JOIN = "newTablePasswordJoin"; + public static final String KEY_NEW_TABLE_DECK_TYPE = "newTableDeckType"; + public static final String KEY_NEW_TABLE_TIME_LIMIT = "newTableTimeLimit"; + public static final String KEY_NEW_TABLE_GAME_TYPE = "newTableGameType"; + public static final String KEY_NEW_TABLE_NUMBER_OF_WINS = "newTableNumberOfWins"; + public static final String KEY_NEW_TABLE_ROLLBACK_TURNS_ALLOWED = "newTableRollbackTurnsAllowed"; + public static final String KEY_NEW_TABLE_NUMBER_OF_FREE_MULLIGANS = "newTableNumberOfFreeMulligans"; + public static final String KEY_NEW_TABLE_DECK_FILE = "newTableDeckFile"; + public static final String KEY_NEW_TABLE_RANGE = "newTableRange"; + public static final String KEY_NEW_TABLE_ATTACK_OPTION = "newTableAttackOption"; + public static final String KEY_NEW_TABLE_SKILL_LEVEL = "newTableSkillLevel"; + public static final String KEY_NEW_TABLE_NUMBER_PLAYERS = "newTableNumberPlayers"; + public static final String KEY_NEW_TABLE_PLAYER_TYPES = "newTablePlayerTypes"; + public static final String KEY_NEW_TABLE_QUIT_RATIO = "newTableQuitRatio"; + public static final String KEY_NEW_TABLE_RATED = "newTableRated"; - // pref setting for deck generator - public static final String KEY_NEW_DECK_GENERATOR_DECK_SIZE = "newDeckGeneratorDeckSize"; - public static final String KEY_NEW_DECK_GENERATOR_SET = "newDeckGeneratorSet"; - public static final String KEY_NEW_DECK_GENERATOR_SINGLETON = "newDeckGeneratorSingleton"; - public static final String KEY_NEW_DECK_GENERATOR_ARTIFACTS = "newDeckGeneratorArtifacts"; - public static final String KEY_NEW_DECK_GENERATOR_NON_BASIC_LANDS = "newDeckGeneratorNonBasicLands"; - public static final String KEY_NEW_DECK_GENERATOR_COLORLESS = "newDeckGeneratorColorless"; - public static final String KEY_NEW_DECK_GENERATOR_ADVANCED = "newDeckGeneratorAdvanced"; - public static final String KEY_NEW_DECK_GENERATOR_CREATURE_PERCENTAGE = "newDeckGeneratorCreaturePercentage"; - public static final String KEY_NEW_DECK_GENERATOR_NON_CREATURE_PERCENTAGE = "newDeckGeneratorNonCreaturePercentage"; - public static final String KEY_NEW_DECK_GENERATOR_LAND_PERCENTAGE = "newDeckGeneratorLandPercentage"; - public static final String KEY_NEW_DECK_GENERATOR_ADVANCED_CMC = "newDeckGeneratorAdvancedCMC"; + // pref setting for new tournament dialog + public static final String KEY_NEW_TOURNAMENT_NAME = "newTournamentName"; + public static final String KEY_NEW_TOURNAMENT_PASSWORD = "newTournamentPassword"; + public static final String KEY_NEW_TOURNAMENT_TIME_LIMIT = "newTournamentTimeLimit"; + public static final String KEY_NEW_TOURNAMENT_CONSTR_TIME = "newTournamentConstructionTime"; + public static final String KEY_NEW_TOURNAMENT_TYPE = "newTournamentType"; + public static final String KEY_NEW_TOURNAMENT_NUMBER_OF_FREE_MULLIGANS = "newTournamentNumberOfFreeMulligans"; + public static final String KEY_NEW_TOURNAMENT_NUMBER_OF_WINS = "newTournamentNumberOfWins"; + public static final String KEY_NEW_TOURNAMENT_PACKS_SEALED = "newTournamentPacksSealed"; + public static final String KEY_NEW_TOURNAMENT_PACKS_DRAFT = "newTournamentPacksDraft"; + public static final String KEY_NEW_TOURNAMENT_PACKS_RANDOM_DRAFT = "newTournamentPacksRandomDraft"; + public static final String KEY_NEW_TOURNAMENT_PLAYERS_SEALED = "newTournamentPlayersSealed"; + public static final String KEY_NEW_TOURNAMENT_PLAYERS_DRAFT = "newTournamentPlayersDraft"; + public static final String KEY_NEW_TOURNAMENT_DRAFT_TIMING = "newTournamentDraftTiming"; + public static final String KEY_NEW_TOURNAMENT_ALLOW_SPECTATORS = "newTournamentAllowSpectators"; + public static final String KEY_NEW_TOURNAMENT_ALLOW_ROLLBACKS = "newTournamentAllowRollbacks"; + public static final String KEY_NEW_TOURNAMENT_DECK_FILE = "newTournamentDeckFile"; + public static final String KEY_NEW_TOURNAMENT_QUIT_RATIO = "newTournamentQuitRatio"; + public static final String KEY_NEW_TOURNAMENT_RATED = "newTournamentRated"; - // used to save and restore the settings for the cardArea (draft, sideboarding, deck builder) - public static final String KEY_DRAFT_VIEW = "draftView"; + // pref setting for deck generator + public static final String KEY_NEW_DECK_GENERATOR_DECK_SIZE = "newDeckGeneratorDeckSize"; + public static final String KEY_NEW_DECK_GENERATOR_SET = "newDeckGeneratorSet"; + public static final String KEY_NEW_DECK_GENERATOR_SINGLETON = "newDeckGeneratorSingleton"; + public static final String KEY_NEW_DECK_GENERATOR_ARTIFACTS = "newDeckGeneratorArtifacts"; + public static final String KEY_NEW_DECK_GENERATOR_NON_BASIC_LANDS = "newDeckGeneratorNonBasicLands"; + public static final String KEY_NEW_DECK_GENERATOR_COLORLESS = "newDeckGeneratorColorless"; + public static final String KEY_NEW_DECK_GENERATOR_ADVANCED = "newDeckGeneratorAdvanced"; + public static final String KEY_NEW_DECK_GENERATOR_CREATURE_PERCENTAGE = "newDeckGeneratorCreaturePercentage"; + public static final String KEY_NEW_DECK_GENERATOR_NON_CREATURE_PERCENTAGE = "newDeckGeneratorNonCreaturePercentage"; + public static final String KEY_NEW_DECK_GENERATOR_LAND_PERCENTAGE = "newDeckGeneratorLandPercentage"; + public static final String KEY_NEW_DECK_GENERATOR_ADVANCED_CMC = "newDeckGeneratorAdvancedCMC"; - public static final String KEY_DRAFT_SORT_BY = "draftSortBy"; - public static final String KEY_DRAFT_SORT_INDEX = "draftSortIndex"; - public static final String KEY_DRAFT_SORT_ASCENDING = "draftSortAscending"; - public static final String KEY_DRAFT_PILES_TOGGLE = "draftPilesToggle"; + // used to save and restore the settings for the cardArea (draft, sideboarding, deck builder) + public static final String KEY_DRAFT_VIEW = "draftView"; - public static final String KEY_BASE_SORT_BY = "baseSortBy"; - public static final String KEY_BASE_SORT_INDEX = "baseSortIndex"; - public static final String KEY_BASE_SORT_ASCENDING = "baseSortAscending"; - public static final String KEY_BASE_PILES_TOGGLE = "basePilesToggle"; + public static final String KEY_DRAFT_SORT_BY = "draftSortBy"; + public static final String KEY_DRAFT_SORT_INDEX = "draftSortIndex"; + public static final String KEY_DRAFT_SORT_ASCENDING = "draftSortAscending"; + public static final String KEY_DRAFT_PILES_TOGGLE = "draftPilesToggle"; - public static final String KEY_SIDEBOARD_SORT_BY = "sideboardSortBy"; - public static final String KEY_SIDEBOARD_SORT_INDEX = "sideboardSortIndex"; - public static final String KEY_SIDEBOARD_SORT_ASCENDING = "sideboardSortAscending"; - public static final String KEY_SIDEBOARD_PILES_TOGGLE = "sideboardPilesToggle"; + public static final String KEY_BASE_SORT_BY = "baseSortBy"; + public static final String KEY_BASE_SORT_INDEX = "baseSortIndex"; + public static final String KEY_BASE_SORT_ASCENDING = "baseSortAscending"; + public static final String KEY_BASE_PILES_TOGGLE = "basePilesToggle"; - public static final String KEY_DECK_SORT_BY = "deckSortBy"; - public static final String KEY_DECK_SORT_INDEX = "deckSortIndex"; - public static final String KEY_DECK_SORT_ASCENDING = "deckSortAscending"; - public static final String KEY_DECK_PILES_TOGGLE = "deckPilesToggle"; + public static final String KEY_SIDEBOARD_SORT_BY = "sideboardSortBy"; + public static final String KEY_SIDEBOARD_SORT_INDEX = "sideboardSortIndex"; + public static final String KEY_SIDEBOARD_SORT_ASCENDING = "sideboardSortAscending"; + public static final String KEY_SIDEBOARD_PILES_TOGGLE = "sideboardPilesToggle"; - public static final String KEY_PROXY_ADDRESS = "proxyAddress"; - public static final String KEY_PROXY_PORT = "proxyPort"; - public static final String KEY_PROXY_USERNAME = "proxyUsername"; - public static final String KEY_PROXY_REMEMBER = "proxyRemember"; - public static final String KEY_PROXY_TYPE = "proxyType"; - public static final String KEY_PROXY_PSWD = "proxyPassword"; - public static final String KEY_CONNECTION_URL_SERVER_LIST = "connectionURLServerList"; + public static final String KEY_DECK_SORT_BY = "deckSortBy"; + public static final String KEY_DECK_SORT_INDEX = "deckSortIndex"; + public static final String KEY_DECK_SORT_ASCENDING = "deckSortAscending"; + public static final String KEY_DECK_PILES_TOGGLE = "deckPilesToggle"; - public static final String KEY_AVATAR = "selectedId"; + public static final String KEY_PROXY_ADDRESS = "proxyAddress"; + public static final String KEY_PROXY_PORT = "proxyPort"; + public static final String KEY_PROXY_USERNAME = "proxyUsername"; + public static final String KEY_PROXY_REMEMBER = "proxyRemember"; + public static final String KEY_PROXY_TYPE = "proxyType"; + public static final String KEY_PROXY_PSWD = "proxyPassword"; + public static final String KEY_CONNECTION_URL_SERVER_LIST = "connectionURLServerList"; - public static final String KEY_CONNECT_AUTO_CONNECT = "autoConnect"; - public static final String KEY_CONNECT_FLAG = "connectFlag"; + // controls + public static final String KEY_CONTROL_CONFIRM = "controlConfirm"; + public static final String KEY_CONTROL_CANCEL_SKIP = "controlCancelSkip"; + public static final String KEY_CONTROL_NEXT_TURN = "controlNextTurn"; + public static final String KEY_CONTROL_END_STEP = "controlEndStep"; + public static final String KEY_CONTROL_SKIP_STEP = "controlSkipTurn"; + public static final String KEY_CONTROL_MAIN_STEP = "controlMainStep"; + public static final String KEY_CONTROL_YOUR_TURN = "controlYourTurn"; + public static final String KEY_CONTROL_SKIP_STACK = "controlSkipStack"; + public static final String KEY_CONTROL_PRIOR_END = "controlPriorEnd"; - private static final Map CACHE = new HashMap<>(); + public static final String KEY_AVATAR = "selectedId"; - private static final Boolean UPDATE_CACHE_POLICY = Boolean.TRUE; + public static final String KEY_CONNECT_AUTO_CONNECT = "autoConnect"; + public static final String KEY_CONNECT_FLAG = "connectFlag"; - public static final String OPEN_CONNECTION_TAB = "Open-Connection-Tab"; - public static final String OPEN_PHASES_TAB = "Open-Phases-Tab"; + private static final Map CACHE = new HashMap<>(); - public static String PHASE_ON = "on"; - public static String PHASE_OFF = "off"; + private static final Boolean UPDATE_CACHE_POLICY = Boolean.TRUE; - private static final Map PANELS = new HashMap<>(); + public static final String OPEN_CONNECTION_TAB = "Open-Connection-Tab"; + public static final String OPEN_PHASES_TAB = "Open-Phases-Tab"; - private static final Border GREEN_BORDER = BorderFactory.createLineBorder(Color.GREEN, 3); - private static final Border BLACK_BORDER = BorderFactory.createLineBorder(Color.BLACK, 3); + public static String PHASE_ON = "on"; + public static String PHASE_OFF = "off"; - private static int selectedAvatarId; + private static final Map PANELS = new HashMap<>(); - private final JFileChooser fc = new JFileChooser(); + private static final Border GREEN_BORDER = BorderFactory.createLineBorder(Color.GREEN, 3); + private static final Border BLACK_BORDER = BorderFactory.createLineBorder(Color.BLACK, 3); - { - fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - } + private static int selectedAvatarId; - private final JFileChooser fc_i = new JFileChooser(); + private final JFileChooser fc = new JFileChooser(); - { - fc_i.setAcceptAllFileFilterUsed(false); - fc_i.addChoosableFileFilter(new ImageFileFilter()); - } + { + fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + } - private static class ImageFileFilter extends FileFilter { + private final JFileChooser fc_i = new JFileChooser(); - @Override - public boolean accept(File f) { - String filename = f.getName(); - if (f.isDirectory()) { - return true; - } - if (filename != null) { - if (filename.endsWith(".jpg") || filename.endsWith(".jpeg") - || filename.endsWith(".png") || filename.endsWith(".bmp")) { - return true; - } - } - return false; - } + { + fc_i.setAcceptAllFileFilterUsed(false); + fc_i.addChoosableFileFilter(new ImageFileFilter()); + } - @Override - public String getDescription() { - return "*.png | *.bmp |*.jpg | *.jpeg"; - } - } + private static class ImageFileFilter extends FileFilter { - /** - * Creates new form PreferencesDialog - * - * @param parent - * @param modal - */ - public PreferencesDialog(java.awt.Frame parent, boolean modal) { - super(parent, modal); - initComponents(); - txtImageFolderPath.setEditable(false); - cbProxyType.setModel(new DefaultComboBoxModel<>(Connection.ProxyType.values())); - addAvatars(); + @Override + public boolean accept(File f) { + String filename = f.getName(); + if (f.isDirectory()) { + return true; + } + if (filename != null) { + if (filename.endsWith(".jpg") || filename.endsWith(".jpeg") + || filename.endsWith(".png") || filename.endsWith(".bmp")) { + return true; + } + } + return false; + } - cbPreferedImageLanguage.setModel(new DefaultComboBoxModel<>(new String[]{"en", "de", "fr", "it", "es", "pt", "jp", "cn", "ru", "tw", "ko"})); - cbNumberOfDownloadThreads.setModel(new DefaultComboBoxModel<>(new String[]{"10", "9", "8", "7", "6", "5", "4", "3", "2", "1"})); - } + @Override + public String getDescription() { + return "*.png | *.bmp |*.jpg | *.jpeg"; + } + } - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - @SuppressWarnings("unchecked") + /** + * Creates new form PreferencesDialog + * + * @param parent + * @param modal + */ + public PreferencesDialog(java.awt.Frame parent, boolean modal) { + super(parent, modal); + initComponents(); + txtImageFolderPath.setEditable(false); + cbProxyType.setModel(new DefaultComboBoxModel<>(Connection.ProxyType.values())); + addAvatars(); + + cbPreferedImageLanguage.setModel(new DefaultComboBoxModel<>(new String[]{"en", "de", "fr", "it", "es", "pt", "jp", "cn", "ru", "tw", "ko"})); + cbNumberOfDownloadThreads.setModel(new DefaultComboBoxModel<>(new String[]{"10", "9", "8", "7", "6", "5", "4", "3", "2", "1"})); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") // //GEN-BEGIN:initComponents private void initComponents() { java.awt.GridBagConstraints gridBagConstraints; @@ -538,6 +554,27 @@ public class PreferencesDialog extends javax.swing.JDialog { txtPasswordField = new javax.swing.JPasswordField(); rememberPswd = new javax.swing.JCheckBox(); jLabel11 = new javax.swing.JLabel(); + tabControls = new javax.swing.JPanel(); + labelNextTurn = new javax.swing.JLabel(); + labelEndStep = new javax.swing.JLabel(); + labelMainStep = new javax.swing.JLabel(); + labelYourTurn = new javax.swing.JLabel(); + lebelSkip = new javax.swing.JLabel(); + labelPriorEnd = new javax.swing.JLabel(); + labelCancel = new javax.swing.JLabel(); + keyCancelSkip = new KeyBindButton(this, KEY_CONTROL_CANCEL_SKIP); + keyNextTurn = new KeyBindButton(this, KEY_CONTROL_NEXT_TURN); + keyMainStep = new KeyBindButton(this, KEY_CONTROL_MAIN_STEP); + keyEndStep = new KeyBindButton(this, KEY_CONTROL_END_STEP); + keyYourTurn = new KeyBindButton(this, KEY_CONTROL_YOUR_TURN); + keySkipStack = new KeyBindButton(this, KEY_CONTROL_SKIP_STACK); + keyPriorEnd = new KeyBindButton(this, KEY_CONTROL_PRIOR_END); + keySkipStep = new KeyBindButton(this, KEY_CONTROL_SKIP_STEP); + labelSkipStep = new javax.swing.JLabel(); + keyConfirm = new KeyBindButton(this, KEY_CONTROL_CONFIRM); + labelConfirm = new javax.swing.JLabel(); + controlsDescriptionLabel = new javax.swing.JLabel(); + bttnResetControls = new javax.swing.JButton(); saveButton = new javax.swing.JButton(); exitButton = new javax.swing.JButton(); @@ -579,7 +616,7 @@ public class PreferencesDialog extends javax.swing.JDialog { .add(main_cardLayout.createSequentialGroup() .add(6, 6, 6) .add(main_cardLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false) - .add(tooltipDelayLabel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 308, Short.MAX_VALUE) + .add(tooltipDelayLabel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 308, Short.MAX_VALUE) .add(org.jdesktop.layout.GroupLayout.LEADING, showCardName) .add(tooltipDelay, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) @@ -1402,7 +1439,7 @@ public class PreferencesDialog extends javax.swing.JDialog { .add(jLabelEndOfTurn) .add(checkBoxEndTurnOthers)) .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED) - .add(phases_stopSettings, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 266, Short.MAX_VALUE) + .add(phases_stopSettings, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 356, Short.MAX_VALUE) .addContainerGap()) ); @@ -1481,7 +1518,7 @@ public class PreferencesDialog extends javax.swing.JDialog { .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(cbNumberOfDownloadThreads, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 153, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))) .add(cbUseDefaultImageFolder)) - .add(0, 231, Short.MAX_VALUE))) + .add(0, 270, Short.MAX_VALUE))) .addContainerGap()) ); panelCardImagesLayout.setVerticalGroup( @@ -1676,7 +1713,7 @@ public class PreferencesDialog extends javax.swing.JDialog { .add(panelCardImages, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(panelBackgroundImages, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) - .addContainerGap(53, Short.MAX_VALUE)) + .addContainerGap(125, Short.MAX_VALUE)) ); tabsPanel.addTab("Images", tabImages); @@ -2251,7 +2288,7 @@ public class PreferencesDialog extends javax.swing.JDialog { tabAvatarsLayout.setVerticalGroup( tabAvatarsLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(tabAvatarsLayout.createSequentialGroup() - .add(avatarPane, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 484, Short.MAX_VALUE) + .add(avatarPane, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 584, Short.MAX_VALUE) .addContainerGap()) ); @@ -2286,7 +2323,7 @@ public class PreferencesDialog extends javax.swing.JDialog { .add(connection_serversLayout.createSequentialGroup() .add(141, 141, 141) .add(jLabel17))) - .addContainerGap(91, Short.MAX_VALUE)) + .addContainerGap(198, Short.MAX_VALUE)) ); connection_serversLayout.setVerticalGroup( connection_serversLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) @@ -2440,6 +2477,137 @@ public class PreferencesDialog extends javax.swing.JDialog { tabsPanel.addTab("Connection", tabConnection); + labelNextTurn.setText("Next Turn"); + + labelEndStep.setText("End Step"); + + labelMainStep.setText("Main Step"); + + labelYourTurn.setText("Your Turn"); + + lebelSkip.setText("Skip Stack"); + + labelPriorEnd.setText("Prior End"); + + labelCancel.setText("Cancel Skip"); + + keyCancelSkip.setText("keyBindButton1"); + + keyNextTurn.setText("keyBindButton1"); + + keyMainStep.setText("keyBindButton1"); + + keyEndStep.setText("keyBindButton1"); + + keyYourTurn.setText("keyBindButton1"); + + keySkipStack.setText("keyBindButton1"); + + keyPriorEnd.setText("keyBindButton1"); + + keySkipStep.setText("keyBindButton1"); + + labelSkipStep.setText("Skip Step"); + + keyConfirm.setText("keyBindButton1"); + + labelConfirm.setText("Confirm"); + + controlsDescriptionLabel.setText("Click on a button and press a key to change a keybind.
Space and ESC are not available, and will set the keybind to nothing.
If you are currently playing a game, the changes will not take effect until you start a new game."); + controlsDescriptionLabel.setVerticalAlignment(javax.swing.SwingConstants.TOP); + + bttnResetControls.setText("Reset to default"); + bttnResetControls.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + bttnResetControlsActionPerformed(evt); + } + }); + + org.jdesktop.layout.GroupLayout tabControlsLayout = new org.jdesktop.layout.GroupLayout(tabControls); + tabControls.setLayout(tabControlsLayout); + tabControlsLayout.setHorizontalGroup( + tabControlsLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(tabControlsLayout.createSequentialGroup() + .addContainerGap() + .add(tabControlsLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(tabControlsLayout.createSequentialGroup() + .add(bttnResetControls) + .add(0, 0, Short.MAX_VALUE)) + .add(tabControlsLayout.createSequentialGroup() + .add(tabControlsLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(labelCancel) + .add(labelNextTurn) + .add(labelEndStep) + .add(labelMainStep) + .add(labelYourTurn) + .add(lebelSkip) + .add(labelPriorEnd) + .add(labelSkipStep) + .add(labelConfirm)) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED) + .add(tabControlsLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(keyConfirm, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .add(keyCancelSkip, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .add(keyNextTurn, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .add(keySkipStack, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .add(keyYourTurn, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .add(keyMainStep, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .add(keyPriorEnd, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .add(keySkipStep, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .add(keyEndStep, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(controlsDescriptionLabel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 498, Short.MAX_VALUE))) + .addContainerGap()) + ); + tabControlsLayout.setVerticalGroup( + tabControlsLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(tabControlsLayout.createSequentialGroup() + .addContainerGap() + .add(tabControlsLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false) + .add(org.jdesktop.layout.GroupLayout.LEADING, controlsDescriptionLabel) + .add(org.jdesktop.layout.GroupLayout.LEADING, tabControlsLayout.createSequentialGroup() + .add(tabControlsLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) + .add(labelConfirm) + .add(keyConfirm, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED) + .add(tabControlsLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) + .add(labelCancel) + .add(keyCancelSkip, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED) + .add(tabControlsLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) + .add(labelNextTurn) + .add(keyNextTurn, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED) + .add(tabControlsLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) + .add(labelEndStep) + .add(keyEndStep, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED) + .add(tabControlsLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) + .add(labelSkipStep) + .add(keySkipStep, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED) + .add(tabControlsLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) + .add(labelMainStep) + .add(keyMainStep, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED) + .add(tabControlsLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) + .add(labelYourTurn) + .add(keyYourTurn, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED) + .add(tabControlsLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) + .add(lebelSkip) + .add(keySkipStack, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED) + .add(tabControlsLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) + .add(labelPriorEnd) + .add(keyPriorEnd, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED) + .add(bttnResetControls) + .addContainerGap()) + ); + + tabsPanel.addTab("Controls", tabControls); + saveButton.setLabel("Save"); saveButton.setMaximumSize(new java.awt.Dimension(100, 30)); saveButton.setMinimumSize(new java.awt.Dimension(100, 30)); @@ -2492,182 +2660,193 @@ public class PreferencesDialog extends javax.swing.JDialog { }//
//GEN-END:initComponents private void saveButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveButtonActionPerformed - Preferences prefs = MageFrame.getPreferences(); + Preferences prefs = MageFrame.getPreferences(); - // main - save(prefs, dialog.tooltipDelay, KEY_SHOW_TOOLTIPS_DELAY, "true", "false", UPDATE_CACHE_POLICY); - save(prefs, dialog.showCardName, KEY_SHOW_CARD_NAMES, "true", "false", UPDATE_CACHE_POLICY); - save(prefs, dialog.nonLandPermanentsInOnePile, KEY_PERMANENTS_IN_ONE_PILE, "true", "false", UPDATE_CACHE_POLICY); - save(prefs, dialog.showPlayerNamesPermanently, KEY_SHOW_PLAYER_NAMES_PERMANENTLY, "true", "false", UPDATE_CACHE_POLICY); - save(prefs, dialog.showAbilityPickerForced, KEY_SHOW_ABILITY_PICKER_FORCED, "true", "false", UPDATE_CACHE_POLICY); - save(prefs, dialog.cbAllowRequestToShowHandCards, KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS, "true", "false", UPDATE_CACHE_POLICY); - save(prefs, dialog.cbShowStormCounter, KEY_GAME_SHOW_STORM_COUNTER, "true", "false", UPDATE_CACHE_POLICY); - save(prefs, dialog.cbConfirmEmptyManaPool, KEY_GAME_CONFIRM_EMPTY_MANA_POOL, "true", "false", UPDATE_CACHE_POLICY); - save(prefs, dialog.cbAskMoveToGraveOrder, KEY_GAME_ASK_MOVE_TO_GRAVE_ORDER, "true", "false", UPDATE_CACHE_POLICY); - save(prefs, dialog.cbGameLogAutoSave, KEY_GAME_LOG_AUTO_SAVE, "true", "false", UPDATE_CACHE_POLICY); - save(prefs, dialog.cbDraftLogAutoSave, KEY_DRAFT_LOG_AUTO_SAVE, "true", "false", UPDATE_CACHE_POLICY); + // main + save(prefs, dialog.tooltipDelay, KEY_SHOW_TOOLTIPS_DELAY, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.showCardName, KEY_SHOW_CARD_NAMES, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.nonLandPermanentsInOnePile, KEY_PERMANENTS_IN_ONE_PILE, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.showPlayerNamesPermanently, KEY_SHOW_PLAYER_NAMES_PERMANENTLY, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.showAbilityPickerForced, KEY_SHOW_ABILITY_PICKER_FORCED, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbAllowRequestToShowHandCards, KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbShowStormCounter, KEY_GAME_SHOW_STORM_COUNTER, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbConfirmEmptyManaPool, KEY_GAME_CONFIRM_EMPTY_MANA_POOL, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbAskMoveToGraveOrder, KEY_GAME_ASK_MOVE_TO_GRAVE_ORDER, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbGameLogAutoSave, KEY_GAME_LOG_AUTO_SAVE, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbDraftLogAutoSave, KEY_DRAFT_LOG_AUTO_SAVE, "true", "false", UPDATE_CACHE_POLICY); - // GUI Size - boolean sizeGUIChanged = false; - if (getCachedValue(KEY_GUI_TABLE_FONT_SIZE, 14) != dialog.sliderFontSize.getValue()) { - save(prefs, dialog.sliderFontSize, KEY_GUI_TABLE_FONT_SIZE, "true", "false", UPDATE_CACHE_POLICY); - sizeGUIChanged = true; - } - if (getCachedValue(KEY_GUI_CHAT_FONT_SIZE, 14) != dialog.sliderChatFontSize.getValue()) { - save(prefs, dialog.sliderChatFontSize, KEY_GUI_CHAT_FONT_SIZE, "true", "false", UPDATE_CACHE_POLICY); - sizeGUIChanged = true; - } - if (getCachedValue(KEY_GUI_CARD_HAND_SIZE, 14) != dialog.sliderCardSizeHand.getValue()) { - save(prefs, dialog.sliderCardSizeHand, KEY_GUI_CARD_HAND_SIZE, "true", "false", UPDATE_CACHE_POLICY); - sizeGUIChanged = true; - } - if (getCachedValue(KEY_GUI_CARD_EDITOR_SIZE, 14) != dialog.sliderEditorCardSize.getValue()) { - save(prefs, dialog.sliderEditorCardSize, KEY_GUI_CARD_EDITOR_SIZE, "true", "false", UPDATE_CACHE_POLICY); - sizeGUIChanged = true; - } - if (getCachedValue(KEY_GUI_CARD_OFFSET_SIZE, 14) != dialog.sliderEditorCardOffset.getValue()) { - save(prefs, dialog.sliderEditorCardOffset, KEY_GUI_CARD_OFFSET_SIZE, "true", "false", UPDATE_CACHE_POLICY); - sizeGUIChanged = true; - } - if (getCachedValue(KEY_GUI_ENLARGED_IMAGE_SIZE, 20) != dialog.sliderEnlargedImageSize.getValue()) { - save(prefs, dialog.sliderEnlargedImageSize, KEY_GUI_ENLARGED_IMAGE_SIZE, "true", "false", UPDATE_CACHE_POLICY); - sizeGUIChanged = true; - } - if (getCachedValue(KEY_GUI_STACK_WIDTH, 30) != dialog.sliderStackWidth.getValue()) { - save(prefs, dialog.sliderStackWidth, KEY_GUI_STACK_WIDTH, "true", "false", UPDATE_CACHE_POLICY); - sizeGUIChanged = true; - } - if (getCachedValue(KEY_GUI_TOOLTIP_SIZE, 14) != dialog.sliderTooltipSize.getValue()) { - save(prefs, dialog.sliderTooltipSize, KEY_GUI_TOOLTIP_SIZE, "true", "false", UPDATE_CACHE_POLICY); - sizeGUIChanged = true; - } - if (getCachedValue(KEY_GUI_DIALOG_FONT_SIZE, 14) != dialog.sliderDialogFont.getValue()) { - save(prefs, dialog.sliderDialogFont, KEY_GUI_DIALOG_FONT_SIZE, "true", "false", UPDATE_CACHE_POLICY); - sizeGUIChanged = true; - } - if (getCachedValue(KEY_GUI_FEEDBACK_AREA_SIZE, 14) != dialog.sliderGameFeedbackArea.getValue()) { - save(prefs, dialog.sliderGameFeedbackArea, KEY_GUI_FEEDBACK_AREA_SIZE, "true", "false", UPDATE_CACHE_POLICY); - sizeGUIChanged = true; - } - if (getCachedValue(KEY_GUI_CARD_OTHER_ZONES_SIZE, 14) != dialog.sliderCardSizeOtherZones.getValue()) { - save(prefs, dialog.sliderCardSizeOtherZones, KEY_GUI_CARD_OTHER_ZONES_SIZE, "true", "false", UPDATE_CACHE_POLICY); - sizeGUIChanged = true; - } - if (getCachedValue(KEY_GUI_CARD_BATTLEFIELD_MIN_SIZE, 10) != dialog.sliderCardSizeMaxBattlefield.getValue()) { - save(prefs, dialog.sliderCardSizeMinBattlefield, KEY_GUI_CARD_BATTLEFIELD_MIN_SIZE, "true", "false", UPDATE_CACHE_POLICY); - sizeGUIChanged = true; - } - if (getCachedValue(KEY_GUI_CARD_BATTLEFIELD_MAX_SIZE, 14) != dialog.sliderCardSizeMaxBattlefield.getValue()) { - save(prefs, dialog.sliderCardSizeMaxBattlefield, KEY_GUI_CARD_BATTLEFIELD_MAX_SIZE, "true", "false", UPDATE_CACHE_POLICY); - sizeGUIChanged = true; - } - if (sizeGUIChanged) { - // do as worker job - GUISizeHelper.changeGUISize(); - } + // GUI Size + boolean sizeGUIChanged = false; + if (getCachedValue(KEY_GUI_TABLE_FONT_SIZE, 14) != dialog.sliderFontSize.getValue()) { + save(prefs, dialog.sliderFontSize, KEY_GUI_TABLE_FONT_SIZE, "true", "false", UPDATE_CACHE_POLICY); + sizeGUIChanged = true; + } + if (getCachedValue(KEY_GUI_CHAT_FONT_SIZE, 14) != dialog.sliderChatFontSize.getValue()) { + save(prefs, dialog.sliderChatFontSize, KEY_GUI_CHAT_FONT_SIZE, "true", "false", UPDATE_CACHE_POLICY); + sizeGUIChanged = true; + } + if (getCachedValue(KEY_GUI_CARD_HAND_SIZE, 14) != dialog.sliderCardSizeHand.getValue()) { + save(prefs, dialog.sliderCardSizeHand, KEY_GUI_CARD_HAND_SIZE, "true", "false", UPDATE_CACHE_POLICY); + sizeGUIChanged = true; + } + if (getCachedValue(KEY_GUI_CARD_EDITOR_SIZE, 14) != dialog.sliderEditorCardSize.getValue()) { + save(prefs, dialog.sliderEditorCardSize, KEY_GUI_CARD_EDITOR_SIZE, "true", "false", UPDATE_CACHE_POLICY); + sizeGUIChanged = true; + } + if (getCachedValue(KEY_GUI_CARD_OFFSET_SIZE, 14) != dialog.sliderEditorCardOffset.getValue()) { + save(prefs, dialog.sliderEditorCardOffset, KEY_GUI_CARD_OFFSET_SIZE, "true", "false", UPDATE_CACHE_POLICY); + sizeGUIChanged = true; + } + if (getCachedValue(KEY_GUI_ENLARGED_IMAGE_SIZE, 20) != dialog.sliderEnlargedImageSize.getValue()) { + save(prefs, dialog.sliderEnlargedImageSize, KEY_GUI_ENLARGED_IMAGE_SIZE, "true", "false", UPDATE_CACHE_POLICY); + sizeGUIChanged = true; + } + if (getCachedValue(KEY_GUI_STACK_WIDTH, 30) != dialog.sliderStackWidth.getValue()) { + save(prefs, dialog.sliderStackWidth, KEY_GUI_STACK_WIDTH, "true", "false", UPDATE_CACHE_POLICY); + sizeGUIChanged = true; + } + if (getCachedValue(KEY_GUI_TOOLTIP_SIZE, 14) != dialog.sliderTooltipSize.getValue()) { + save(prefs, dialog.sliderTooltipSize, KEY_GUI_TOOLTIP_SIZE, "true", "false", UPDATE_CACHE_POLICY); + sizeGUIChanged = true; + } + if (getCachedValue(KEY_GUI_DIALOG_FONT_SIZE, 14) != dialog.sliderDialogFont.getValue()) { + save(prefs, dialog.sliderDialogFont, KEY_GUI_DIALOG_FONT_SIZE, "true", "false", UPDATE_CACHE_POLICY); + sizeGUIChanged = true; + } + if (getCachedValue(KEY_GUI_FEEDBACK_AREA_SIZE, 14) != dialog.sliderGameFeedbackArea.getValue()) { + save(prefs, dialog.sliderGameFeedbackArea, KEY_GUI_FEEDBACK_AREA_SIZE, "true", "false", UPDATE_CACHE_POLICY); + sizeGUIChanged = true; + } + if (getCachedValue(KEY_GUI_CARD_OTHER_ZONES_SIZE, 14) != dialog.sliderCardSizeOtherZones.getValue()) { + save(prefs, dialog.sliderCardSizeOtherZones, KEY_GUI_CARD_OTHER_ZONES_SIZE, "true", "false", UPDATE_CACHE_POLICY); + sizeGUIChanged = true; + } + if (getCachedValue(KEY_GUI_CARD_BATTLEFIELD_MIN_SIZE, 10) != dialog.sliderCardSizeMaxBattlefield.getValue()) { + save(prefs, dialog.sliderCardSizeMinBattlefield, KEY_GUI_CARD_BATTLEFIELD_MIN_SIZE, "true", "false", UPDATE_CACHE_POLICY); + sizeGUIChanged = true; + } + if (getCachedValue(KEY_GUI_CARD_BATTLEFIELD_MAX_SIZE, 14) != dialog.sliderCardSizeMaxBattlefield.getValue()) { + save(prefs, dialog.sliderCardSizeMaxBattlefield, KEY_GUI_CARD_BATTLEFIELD_MAX_SIZE, "true", "false", UPDATE_CACHE_POLICY); + sizeGUIChanged = true; + } + if (sizeGUIChanged) { + // do as worker job + GUISizeHelper.changeGUISize(); + } - // Phases & Priority - save(prefs, dialog.checkBoxUpkeepYou, UPKEEP_YOU); - save(prefs, dialog.checkBoxDrawYou, DRAW_YOU); - save(prefs, dialog.checkBoxMainYou, MAIN_YOU); - save(prefs, dialog.checkBoxBeforeCYou, BEFORE_COMBAT_YOU); - save(prefs, dialog.checkBoxEndOfCYou, END_OF_COMBAT_YOU); - save(prefs, dialog.checkBoxMain2You, MAIN_TWO_YOU); - save(prefs, dialog.checkBoxEndTurnYou, END_OF_TURN_YOU); + // Phases & Priority + save(prefs, dialog.checkBoxUpkeepYou, UPKEEP_YOU); + save(prefs, dialog.checkBoxDrawYou, DRAW_YOU); + save(prefs, dialog.checkBoxMainYou, MAIN_YOU); + save(prefs, dialog.checkBoxBeforeCYou, BEFORE_COMBAT_YOU); + save(prefs, dialog.checkBoxEndOfCYou, END_OF_COMBAT_YOU); + save(prefs, dialog.checkBoxMain2You, MAIN_TWO_YOU); + save(prefs, dialog.checkBoxEndTurnYou, END_OF_TURN_YOU); - save(prefs, dialog.checkBoxUpkeepOthers, UPKEEP_OTHERS); - save(prefs, dialog.checkBoxDrawOthers, DRAW_OTHERS); - save(prefs, dialog.checkBoxMainOthers, MAIN_OTHERS); - save(prefs, dialog.checkBoxBeforeCOthers, BEFORE_COMBAT_OTHERS); - save(prefs, dialog.checkBoxEndOfCOthers, END_OF_COMBAT_OTHERS); - save(prefs, dialog.checkBoxMain2Others, MAIN_TWO_OTHERS); - save(prefs, dialog.checkBoxEndTurnOthers, END_OF_TURN_OTHERS); + save(prefs, dialog.checkBoxUpkeepOthers, UPKEEP_OTHERS); + save(prefs, dialog.checkBoxDrawOthers, DRAW_OTHERS); + save(prefs, dialog.checkBoxMainOthers, MAIN_OTHERS); + save(prefs, dialog.checkBoxBeforeCOthers, BEFORE_COMBAT_OTHERS); + save(prefs, dialog.checkBoxEndOfCOthers, END_OF_COMBAT_OTHERS); + save(prefs, dialog.checkBoxMain2Others, MAIN_TWO_OTHERS); + save(prefs, dialog.checkBoxEndTurnOthers, END_OF_TURN_OTHERS); - save(prefs, dialog.cbStopAttack, KEY_STOP_ATTACK, "true", "false", UPDATE_CACHE_POLICY); - save(prefs, dialog.cbStopBlock, KEY_STOP_BLOCK, "true", "false", UPDATE_CACHE_POLICY); - save(prefs, dialog.cbStopOnAllMain, KEY_STOP_ALL_MAIN_PHASES, "true", "false", UPDATE_CACHE_POLICY); - save(prefs, dialog.cbStopOnAllEnd, KEY_STOP_ALL_END_PHASES, "true", "false", UPDATE_CACHE_POLICY); - save(prefs, dialog.cbPassPriorityCast, KEY_PASS_PRIORITY_CAST, "true", "false", UPDATE_CACHE_POLICY); - save(prefs, dialog.cbPassPriorityActivation, KEY_PASS_PRIORITY_ACTIVATION, "true", "false", UPDATE_CACHE_POLICY); - save(prefs, dialog.cbAutoOrderTrigger, KEY_AUTO_ORDER_TRIGGER, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbStopAttack, KEY_STOP_ATTACK, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbStopBlock, KEY_STOP_BLOCK, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbStopOnAllMain, KEY_STOP_ALL_MAIN_PHASES, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbStopOnAllEnd, KEY_STOP_ALL_END_PHASES, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbPassPriorityCast, KEY_PASS_PRIORITY_CAST, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbPassPriorityActivation, KEY_PASS_PRIORITY_ACTIVATION, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbAutoOrderTrigger, KEY_AUTO_ORDER_TRIGGER, "true", "false", UPDATE_CACHE_POLICY); - // images - save(prefs, dialog.cbUseDefaultImageFolder, KEY_CARD_IMAGES_USE_DEFAULT, "true", "false", UPDATE_CACHE_POLICY); - saveImagesPath(prefs); - save(prefs, dialog.cbCheckForNewImages, KEY_CARD_IMAGES_CHECK, "true", "false", UPDATE_CACHE_POLICY); - save(prefs, dialog.cbSaveToZipFiles, KEY_CARD_IMAGES_SAVE_TO_ZIP, "true", "false", UPDATE_CACHE_POLICY); - save(prefs, dialog.cbNumberOfDownloadThreads, KEY_CARD_IMAGES_THREADS); - save(prefs, dialog.cbPreferedImageLanguage, KEY_CARD_IMAGES_PREF_LANGUAGE); + // images + save(prefs, dialog.cbUseDefaultImageFolder, KEY_CARD_IMAGES_USE_DEFAULT, "true", "false", UPDATE_CACHE_POLICY); + saveImagesPath(prefs); + save(prefs, dialog.cbCheckForNewImages, KEY_CARD_IMAGES_CHECK, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbSaveToZipFiles, KEY_CARD_IMAGES_SAVE_TO_ZIP, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbNumberOfDownloadThreads, KEY_CARD_IMAGES_THREADS); + save(prefs, dialog.cbPreferedImageLanguage, KEY_CARD_IMAGES_PREF_LANGUAGE); - save(prefs, dialog.cbUseDefaultBackground, KEY_BACKGROUND_IMAGE_DEFAULT, "true", "false", UPDATE_CACHE_POLICY); - save(prefs, dialog.cbUseDefaultBattleImage, KEY_BATTLEFIELD_IMAGE_DEFAULT, "true", "false", UPDATE_CACHE_POLICY); - save(prefs, dialog.cbUseRandomBattleImage, KEY_BATTLEFIELD_IMAGE_RANDOM, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbUseDefaultBackground, KEY_BACKGROUND_IMAGE_DEFAULT, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbUseDefaultBattleImage, KEY_BATTLEFIELD_IMAGE_DEFAULT, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbUseRandomBattleImage, KEY_BATTLEFIELD_IMAGE_RANDOM, "true", "false", UPDATE_CACHE_POLICY); - // rendering - save(prefs, dialog.cbCardRenderImageFallback, KEY_CARD_RENDERING_FALLBACK, "true", "false", UPDATE_CACHE_POLICY); - save(prefs, dialog.cbCardRenderHideSetSymbol, KEY_CARD_RENDERING_SET_SYMBOL, "true", "false", UPDATE_CACHE_POLICY); - save(prefs, dialog.cbCardRenderShowReminderText, KEY_CARD_RENDERING_REMINDER_TEXT, "true", "false", UPDATE_CACHE_POLICY); - - // sounds - save(prefs, dialog.cbEnableGameSounds, KEY_SOUNDS_GAME_ON, "true", "false", UPDATE_CACHE_POLICY); - save(prefs, dialog.cbEnableDraftSounds, KEY_SOUNDS_DRAFT_ON, "true", "false", UPDATE_CACHE_POLICY); - save(prefs, dialog.cbEnableSkipButtonsSounds, KEY_SOUNDS_SKIP_BUTTONS_ON, "true", "false", UPDATE_CACHE_POLICY); - save(prefs, dialog.cbEnableOtherSounds, KEY_SOUNDS_OTHER_ON, "true", "false", UPDATE_CACHE_POLICY); - save(prefs, dialog.cbEnableBattlefieldBGM, KEY_SOUNDS_MATCH_MUSIC_ON, "true", "false", UPDATE_CACHE_POLICY); - saveSoundPath(prefs); + // rendering + save(prefs, dialog.cbCardRenderImageFallback, KEY_CARD_RENDERING_FALLBACK, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbCardRenderHideSetSymbol, KEY_CARD_RENDERING_SET_SYMBOL, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbCardRenderShowReminderText, KEY_CARD_RENDERING_REMINDER_TEXT, "true", "false", UPDATE_CACHE_POLICY); - // connection - save(prefs, dialog.cbProxyType, KEY_PROXY_TYPE); - save(prefs, dialog.txtProxyServer, KEY_PROXY_ADDRESS); - save(prefs, dialog.txtProxyPort, KEY_PROXY_PORT); - save(prefs, dialog.txtProxyUserName, KEY_PROXY_USERNAME); - save(prefs, dialog.rememberPswd, KEY_PROXY_REMEMBER, "true", "false", UPDATE_CACHE_POLICY); - if (dialog.rememberPswd.isSelected()) { - char[] input = txtPasswordField.getPassword(); - prefs.put(KEY_PROXY_PSWD, new String(input)); - } - save(prefs, dialog.txtURLServerList, KEY_CONNECTION_URL_SERVER_LIST); + // sounds + save(prefs, dialog.cbEnableGameSounds, KEY_SOUNDS_GAME_ON, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbEnableDraftSounds, KEY_SOUNDS_DRAFT_ON, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbEnableSkipButtonsSounds, KEY_SOUNDS_SKIP_BUTTONS_ON, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbEnableOtherSounds, KEY_SOUNDS_OTHER_ON, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbEnableBattlefieldBGM, KEY_SOUNDS_MATCH_MUSIC_ON, "true", "false", UPDATE_CACHE_POLICY); + saveSoundPath(prefs); - // Avatar - if (selectedAvatarId < MIN_AVATAR_ID || selectedAvatarId > MAX_AVATAR_ID) { - selectedAvatarId = DEFAULT_AVATAR_ID; - } - prefs.put(KEY_AVATAR, String.valueOf(selectedAvatarId)); - updateCache(KEY_AVATAR, String.valueOf(selectedAvatarId)); + // connection + save(prefs, dialog.cbProxyType, KEY_PROXY_TYPE); + save(prefs, dialog.txtProxyServer, KEY_PROXY_ADDRESS); + save(prefs, dialog.txtProxyPort, KEY_PROXY_PORT); + save(prefs, dialog.txtProxyUserName, KEY_PROXY_USERNAME); + save(prefs, dialog.rememberPswd, KEY_PROXY_REMEMBER, "true", "false", UPDATE_CACHE_POLICY); + if (dialog.rememberPswd.isSelected()) { + char[] input = txtPasswordField.getPassword(); + prefs.put(KEY_PROXY_PSWD, new String(input)); + } + save(prefs, dialog.txtURLServerList, KEY_CONNECTION_URL_SERVER_LIST); - try { - SessionHandler.updatePreferencesForServer(getUserData()); + // controls + save(prefs, dialog.keyConfirm); + save(prefs, dialog.keyCancelSkip); + save(prefs, dialog.keyNextTurn); + save(prefs, dialog.keyEndStep); + save(prefs, dialog.keySkipStep); + save(prefs, dialog.keyMainStep); + save(prefs, dialog.keyYourTurn); + save(prefs, dialog.keySkipStack); + save(prefs, dialog.keyPriorEnd); - prefs.flush(); - } catch (BackingStoreException ex) { - logger.error("Error: couldn't save preferences", ex); - UserRequestMessage message = new UserRequestMessage("Error", "Error: couldn't save preferences. Please try once again."); - message.setButton1("OK", null); - MageFrame.getInstance().showUserRequestDialog(message); - } + // Avatar + if (selectedAvatarId < MIN_AVATAR_ID || selectedAvatarId > MAX_AVATAR_ID) { + selectedAvatarId = DEFAULT_AVATAR_ID; + } + prefs.put(KEY_AVATAR, String.valueOf(selectedAvatarId)); + updateCache(KEY_AVATAR, String.valueOf(selectedAvatarId)); - dialog.setVisible(false); + try { + SessionHandler.updatePreferencesForServer(getUserData()); + + prefs.flush(); + } catch (BackingStoreException ex) { + logger.error("Error: couldn't save preferences", ex); + UserRequestMessage message = new UserRequestMessage("Error", "Error: couldn't save preferences. Please try once again."); + message.setButton1("OK", null); + MageFrame.getInstance().showUserRequestDialog(message); + } + + dialog.setVisible(false); }//GEN-LAST:event_saveButtonActionPerformed private void exitButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exitButtonActionPerformed - dialog.setVisible(false); + dialog.setVisible(false); }//GEN-LAST:event_exitButtonActionPerformed - private void useDefaultPath() { - txtImageFolderPath.setText("./plugins/images/"); - txtImageFolderPath.setEnabled(false); - btnBrowseImageLocation.setEnabled(false); - } + private void useDefaultPath() { + txtImageFolderPath.setText("./plugins/images/"); + txtImageFolderPath.setEnabled(false); + btnBrowseImageLocation.setEnabled(false); + } - private void useConfigurablePath() { - String path = CACHE.get(KEY_CARD_IMAGES_PATH); - dialog.txtImageFolderPath.setText(path); - txtImageFolderPath.setEnabled(true); - btnBrowseImageLocation.setEnabled(true); - } + private void useConfigurablePath() { + String path = CACHE.get(KEY_CARD_IMAGES_PATH); + dialog.txtImageFolderPath.setText(path); + txtImageFolderPath.setEnabled(true); + btnBrowseImageLocation.setEnabled(true); + } private void cbProxyTypeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbProxyTypeActionPerformed - this.showProxySettings(); + this.showProxySettings(); }//GEN-LAST:event_cbProxyTypeActionPerformed private void txtPasswordFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtPasswordFieldActionPerformed @@ -2680,128 +2859,128 @@ public class PreferencesDialog extends javax.swing.JDialog { }//GEN-LAST:event_rememberPswdActionPerformed private void cbEnableGameSoundsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbEnableGameSoundsActionPerformed - // TODO add your handling code here: + // TODO add your handling code here: }//GEN-LAST:event_cbEnableGameSoundsActionPerformed private void cbEnableBattlefieldBGMActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbEnableBattlefieldBGMActionPerformed - if (cbEnableBattlefieldBGM.isSelected()) { - txtBattlefieldIBGMPath.setEnabled(true); - btnBattlefieldBGMBrowse.setEnabled(true); - } else { - txtBattlefieldIBGMPath.setEnabled(false); - btnBattlefieldBGMBrowse.setEnabled(false); - } + if (cbEnableBattlefieldBGM.isSelected()) { + txtBattlefieldIBGMPath.setEnabled(true); + btnBattlefieldBGMBrowse.setEnabled(true); + } else { + txtBattlefieldIBGMPath.setEnabled(false); + btnBattlefieldBGMBrowse.setEnabled(false); + } }//GEN-LAST:event_cbEnableBattlefieldBGMActionPerformed - private void cbUseDefaultBackgroundActionPerformed(java.awt.event.ActionEvent evt) { - if (cbUseDefaultBackground.isSelected()) { - useDefaultBackgroundImage(); - } else { - useSelectBackgroundImage(); - } - } + private void cbUseDefaultBackgroundActionPerformed(java.awt.event.ActionEvent evt) { + if (cbUseDefaultBackground.isSelected()) { + useDefaultBackgroundImage(); + } else { + useSelectBackgroundImage(); + } + } - private void useDefaultBackgroundImage() { - txtBackgroundImagePath.setEnabled(false); - btnBrowseBackgroundImage.setEnabled(false); - txtBackgroundImagePath.setText(""); - } + private void useDefaultBackgroundImage() { + txtBackgroundImagePath.setEnabled(false); + btnBrowseBackgroundImage.setEnabled(false); + txtBackgroundImagePath.setText(""); + } - private void useSelectBackgroundImage() { - String path = CACHE.get(KEY_BACKGROUND_IMAGE); - dialog.txtBackgroundImagePath.setText(path); - txtBackgroundImagePath.setEnabled(true); - btnBrowseBackgroundImage.setEnabled(true); - } + private void useSelectBackgroundImage() { + String path = CACHE.get(KEY_BACKGROUND_IMAGE); + dialog.txtBackgroundImagePath.setText(path); + txtBackgroundImagePath.setEnabled(true); + btnBrowseBackgroundImage.setEnabled(true); + } - private void cbUseDefaultBattleImageActionPerformed(java.awt.event.ActionEvent evt) { - if (cbUseDefaultBattleImage.isSelected()) { - useDefaultBattlefield(); - } else { - useSelectedOrRandom(); - } - } + private void cbUseDefaultBattleImageActionPerformed(java.awt.event.ActionEvent evt) { + if (cbUseDefaultBattleImage.isSelected()) { + useDefaultBattlefield(); + } else { + useSelectedOrRandom(); + } + } - private void useDefaultBattlefield() { - cbUseRandomBattleImage.setEnabled(false); - txtBattlefieldImagePath.setEnabled(false); - btnBrowseBattlefieldImage.setEnabled(false); - } + private void useDefaultBattlefield() { + cbUseRandomBattleImage.setEnabled(false); + txtBattlefieldImagePath.setEnabled(false); + btnBrowseBattlefieldImage.setEnabled(false); + } - private void useSelectedOrRandom() { - cbUseRandomBattleImage.setEnabled(true); - String temp = CACHE.get(KEY_BATTLEFIELD_IMAGE_RANDOM); - if (temp != null) { - if (temp.equals("true")) { - useRandomBattleField(); - cbUseRandomBattleImage.setSelected(true); - } else { - useSelectedBattleField(); - cbUseRandomBattleImage.setSelected(false); - } - } else { - useSelectedBattleField(); - cbUseRandomBattleImage.setSelected(false); - } - } + private void useSelectedOrRandom() { + cbUseRandomBattleImage.setEnabled(true); + String temp = CACHE.get(KEY_BATTLEFIELD_IMAGE_RANDOM); + if (temp != null) { + if (temp.equals("true")) { + useRandomBattleField(); + cbUseRandomBattleImage.setSelected(true); + } else { + useSelectedBattleField(); + cbUseRandomBattleImage.setSelected(false); + } + } else { + useSelectedBattleField(); + cbUseRandomBattleImage.setSelected(false); + } + } - private void cbUseRandomBattleImageActionPerformed(java.awt.event.ActionEvent evt) { - if (cbUseRandomBattleImage.isSelected()) { - useRandomBattleField(); - } else { - useSelectedBattleField(); - } - } + private void cbUseRandomBattleImageActionPerformed(java.awt.event.ActionEvent evt) { + if (cbUseRandomBattleImage.isSelected()) { + useRandomBattleField(); + } else { + useSelectedBattleField(); + } + } - private void useRandomBattleField() { - txtBattlefieldImagePath.setEnabled(false); - btnBrowseBattlefieldImage.setEnabled(false); - } + private void useRandomBattleField() { + txtBattlefieldImagePath.setEnabled(false); + btnBrowseBattlefieldImage.setEnabled(false); + } - private void useSelectedBattleField() { - txtBattlefieldImagePath.setEnabled(true); - btnBrowseBattlefieldImage.setEnabled(true); - } + private void useSelectedBattleField() { + txtBattlefieldImagePath.setEnabled(true); + btnBrowseBattlefieldImage.setEnabled(true); + } - private void btnBrowseBackgroundImageActionPerformed(java.awt.event.ActionEvent evt) { - int returnVal = fc_i.showOpenDialog(PreferencesDialog.this); - if (returnVal == JFileChooser.APPROVE_OPTION) { - File file = fc_i.getSelectedFile(); - txtBackgroundImagePath.setText(file.getAbsolutePath()); - } - } + private void btnBrowseBackgroundImageActionPerformed(java.awt.event.ActionEvent evt) { + int returnVal = fc_i.showOpenDialog(PreferencesDialog.this); + if (returnVal == JFileChooser.APPROVE_OPTION) { + File file = fc_i.getSelectedFile(); + txtBackgroundImagePath.setText(file.getAbsolutePath()); + } + } - private void btnBrowseBattlefieldImageActionPerformed(java.awt.event.ActionEvent evt) { - int returnVal = fc_i.showOpenDialog(PreferencesDialog.this); - if (returnVal == JFileChooser.APPROVE_OPTION) { - File file = fc_i.getSelectedFile(); - txtBattlefieldImagePath.setText(file.getAbsolutePath()); - } - } + private void btnBrowseBattlefieldImageActionPerformed(java.awt.event.ActionEvent evt) { + int returnVal = fc_i.showOpenDialog(PreferencesDialog.this); + if (returnVal == JFileChooser.APPROVE_OPTION) { + File file = fc_i.getSelectedFile(); + txtBattlefieldImagePath.setText(file.getAbsolutePath()); + } + } private void txtBackgroundImagePathActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtBackgroundImagePathActionPerformed - // TODO add your handling code here: + // TODO add your handling code here: }//GEN-LAST:event_txtBackgroundImagePathActionPerformed private void txtBattlefieldImagePathActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtBattlefieldImagePathActionPerformed - // TODO add your handling code here: + // TODO add your handling code here: }//GEN-LAST:event_txtBattlefieldImagePathActionPerformed private void txtBattlefieldIBGMPathActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtBattlefieldIBGMPathActionPerformed - // TODO add your handling code here: + // TODO add your handling code here: }//GEN-LAST:event_txtBattlefieldIBGMPathActionPerformed private void btnBattlefieldBGMBrowseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnBattlefieldBGMBrowseActionPerformed - // TODO add your handling code here: - int returnVal = fc.showOpenDialog(PreferencesDialog.this); - if (returnVal == JFileChooser.APPROVE_OPTION) { - File file = fc.getSelectedFile(); - txtBattlefieldIBGMPath.setText(file.getAbsolutePath()); - } + // TODO add your handling code here: + int returnVal = fc.showOpenDialog(PreferencesDialog.this); + if (returnVal == JFileChooser.APPROVE_OPTION) { + File file = fc.getSelectedFile(); + txtBattlefieldIBGMPath.setText(file.getAbsolutePath()); + } }//GEN-LAST:event_btnBattlefieldBGMBrowseActionPerformed private void cbGameLogAutoSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbGameLogAutoSaveActionPerformed - // TODO add your handling code here: + // TODO add your handling code here: }//GEN-LAST:event_cbGameLogAutoSaveActionPerformed private void nonLandPermanentsInOnePileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nonLandPermanentsInOnePileActionPerformed @@ -2809,7 +2988,7 @@ public class PreferencesDialog extends javax.swing.JDialog { }//GEN-LAST:event_nonLandPermanentsInOnePileActionPerformed private void showPlayerNamesPermanentlyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showPlayerNamesPermanentlyActionPerformed - // TODO add your handling code here: + // TODO add your handling code here: }//GEN-LAST:event_showPlayerNamesPermanentlyActionPerformed private void showCardNameActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showCardNameActionPerformed @@ -2817,653 +2996,738 @@ public class PreferencesDialog extends javax.swing.JDialog { }//GEN-LAST:event_showCardNameActionPerformed private void showAbilityPickerForcedActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showAbilityPickerForcedActionPerformed - // TODO add your handling code here: + // TODO add your handling code here: }//GEN-LAST:event_showAbilityPickerForcedActionPerformed private void cbEnableOtherSoundsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbEnableOtherSoundsActionPerformed - // TODO add your handling code here: + // TODO add your handling code here: }//GEN-LAST:event_cbEnableOtherSoundsActionPerformed private void cbStopAttackActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbStopAttackActionPerformed - // TODO add your handling code here: + // TODO add your handling code here: }//GEN-LAST:event_cbStopAttackActionPerformed private void cbStopBlockActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbStopBlockActionPerformed - // TODO add your handling code here: + // TODO add your handling code here: }//GEN-LAST:event_cbStopBlockActionPerformed private void cbStopOnAllMainActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbStopOnAllMainActionPerformed - // TODO add your handling code here: + // TODO add your handling code here: }//GEN-LAST:event_cbStopOnAllMainActionPerformed private void cbStopOnAllEndActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbStopOnAllEndActionPerformed - // TODO add your handling code here: + // TODO add your handling code here: }//GEN-LAST:event_cbStopOnAllEndActionPerformed private void cbEnableDraftSoundsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbEnableDraftSoundsActionPerformed - // TODO add your handling code here: + // TODO add your handling code here: }//GEN-LAST:event_cbEnableDraftSoundsActionPerformed private void cbEnableSkipButtonsSoundsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbEnableSkipButtonsSoundsActionPerformed - // TODO add your handling code here: + // TODO add your handling code here: }//GEN-LAST:event_cbEnableSkipButtonsSoundsActionPerformed private void cbAllowRequestToShowHandCardsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbAllowRequestToShowHandCardsActionPerformed - // TODO add your handling code here: + // TODO add your handling code here: }//GEN-LAST:event_cbAllowRequestToShowHandCardsActionPerformed private void cbShowStormCounterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbShowStormCounterActionPerformed - // TODO add your handling code here: + // TODO add your handling code here: }//GEN-LAST:event_cbShowStormCounterActionPerformed private void cbConfirmEmptyManaPoolActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbConfirmEmptyManaPoolActionPerformed - // TODO add your handling code here: + // TODO add your handling code here: }//GEN-LAST:event_cbConfirmEmptyManaPoolActionPerformed private void cbAskMoveToGraveOrderActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbAskMoveToGraveOrderActionPerformed - // TODO add your handling code here: + // TODO add your handling code here: }//GEN-LAST:event_cbAskMoveToGraveOrderActionPerformed private void cbDraftLogAutoSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbDraftLogAutoSaveActionPerformed - // TODO add your handling code here: + // TODO add your handling code here: }//GEN-LAST:event_cbDraftLogAutoSaveActionPerformed private void cbPassPriorityCastActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbPassPriorityCastActionPerformed - // TODO add your handling code here: + // TODO add your handling code here: }//GEN-LAST:event_cbPassPriorityCastActionPerformed private void cbPassPriorityActivationActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbPassPriorityActivationActionPerformed - // TODO add your handling code here: + // TODO add your handling code here: }//GEN-LAST:event_cbPassPriorityActivationActionPerformed private void cbAutoOrderTriggerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbAutoOrderTriggerActionPerformed - // TODO add your handling code here: + // TODO add your handling code here: }//GEN-LAST:event_cbAutoOrderTriggerActionPerformed private void cbCardRenderImageFallbackActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbCardRenderImageFallbackActionPerformed - // TODO add your handling code here: + // TODO add your handling code here: }//GEN-LAST:event_cbCardRenderImageFallbackActionPerformed private void cbCardRenderShowReminderTextActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbCardRenderShowReminderTextActionPerformed - // TODO add your handling code here: + // TODO add your handling code here: }//GEN-LAST:event_cbCardRenderShowReminderTextActionPerformed private void cbSaveToZipFilesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbSaveToZipFilesActionPerformed - // TODO add your handling code here: + // TODO add your handling code here: }//GEN-LAST:event_cbSaveToZipFilesActionPerformed private void cbCheckForNewImagesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbCheckForNewImagesActionPerformed - // TODO add your handling code here: + // TODO add your handling code here: }//GEN-LAST:event_cbCheckForNewImagesActionPerformed private void btnBrowseImageLocationActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnBrowseImageLocationActionPerformed - int returnVal = fc.showOpenDialog(PreferencesDialog.this); + int returnVal = fc.showOpenDialog(PreferencesDialog.this); - if (returnVal == JFileChooser.APPROVE_OPTION) { - File file = fc.getSelectedFile(); - txtImageFolderPath.setText(file.getAbsolutePath()); - } + if (returnVal == JFileChooser.APPROVE_OPTION) { + File file = fc.getSelectedFile(); + txtImageFolderPath.setText(file.getAbsolutePath()); + } }//GEN-LAST:event_btnBrowseImageLocationActionPerformed private void cbUseDefaultImageFolderActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbUseDefaultImageFolderActionPerformed - if (cbUseDefaultImageFolder.isSelected()) { - useDefaultPath(); - } else { - useConfigurablePath(); - } + if (cbUseDefaultImageFolder.isSelected()) { + useDefaultPath(); + } else { + useConfigurablePath(); + } }//GEN-LAST:event_cbUseDefaultImageFolderActionPerformed private void cbCardRenderHideSetSymbolActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbCardRenderHideSetSymbolActionPerformed - // TODO add your handling code here: + // TODO add your handling code here: }//GEN-LAST:event_cbCardRenderHideSetSymbolActionPerformed - private void showProxySettings() { - Connection.ProxyType proxyType = (Connection.ProxyType) cbProxyType.getSelectedItem(); - switch (proxyType) { - case SOCKS: - this.pnlProxy.setVisible(true); - this.pnlProxySettings.setVisible(true); - break; - case HTTP: - this.pnlProxy.setVisible(true); - this.pnlProxySettings.setVisible(true); - break; - case NONE: - this.pnlProxy.setVisible(false); - this.pnlProxySettings.setVisible(false); - break; - default: - break; - } - this.pack(); - this.repaint(); - } + private void bttnResetControlsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bttnResetControlsActionPerformed + getKeybindButtons().stream().forEach((bttn) -> { + String id = bttn.getKey(); + int keyCode = getDefaultControlKey(id); + bttn.setKeyCode(keyCode); + }); + }//GEN-LAST:event_bttnResetControlsActionPerformed - public static void setProxyInformation(Connection connection) { - ProxyType configProxyType = Connection.ProxyType.valueByText(getCachedValue(KEY_PROXY_TYPE, "None")); - if (configProxyType == null) { - return; - } + private void showProxySettings() { + Connection.ProxyType proxyType = (Connection.ProxyType) cbProxyType.getSelectedItem(); + switch (proxyType) { + case SOCKS: + this.pnlProxy.setVisible(true); + this.pnlProxySettings.setVisible(true); + break; + case HTTP: + this.pnlProxy.setVisible(true); + this.pnlProxySettings.setVisible(true); + break; + case NONE: + this.pnlProxy.setVisible(false); + this.pnlProxySettings.setVisible(false); + break; + default: + break; + } + this.pack(); + this.repaint(); + } - connection.setProxyType(configProxyType); - if (!configProxyType.equals(ProxyType.NONE)) { - String host = getCachedValue(KEY_PROXY_ADDRESS, ""); - String port = getCachedValue(KEY_PROXY_PORT, ""); - if (!host.isEmpty() && !port.isEmpty()) { - connection.setProxyHost(host); - connection.setProxyPort(Integer.valueOf(port)); - String username = getCachedValue(KEY_PROXY_USERNAME, ""); - connection.setProxyUsername(username); - if (getCachedValue(KEY_PROXY_REMEMBER, "false").equals("true")) { - String password = getCachedValue(KEY_PROXY_PSWD, ""); - connection.setProxyPassword(password); - } - } else { - logger.warn("host or\\and port are empty: host=" + host + ", port=" + port); - } - } - } + public static void setProxyInformation(Connection connection) { + ProxyType configProxyType = Connection.ProxyType.valueByText(getCachedValue(KEY_PROXY_TYPE, "None")); + if (configProxyType == null) { + return; + } - /** - * @param args the command line arguments - */ - public static void main(String args[]) { - int param = 0; - if (args.length > 0) { - String param1 = args[0]; - if (param1.equals(OPEN_CONNECTION_TAB)) { - param = 4; - } - if (param1.equals(OPEN_PHASES_TAB)) { - param = 1; - } - } - final int openedTab = param; - java.awt.EventQueue.invokeLater(new Runnable() { - @Override - public void run() { - if (!dialog.isVisible()) { - Preferences prefs = MageFrame.getPreferences(); + connection.setProxyType(configProxyType); + if (!configProxyType.equals(ProxyType.NONE)) { + String host = getCachedValue(KEY_PROXY_ADDRESS, ""); + String port = getCachedValue(KEY_PROXY_PORT, ""); + if (!host.isEmpty() && !port.isEmpty()) { + connection.setProxyHost(host); + connection.setProxyPort(Integer.valueOf(port)); + String username = getCachedValue(KEY_PROXY_USERNAME, ""); + connection.setProxyUsername(username); + if (getCachedValue(KEY_PROXY_REMEMBER, "false").equals("true")) { + String password = getCachedValue(KEY_PROXY_PSWD, ""); + connection.setProxyPassword(password); + } + } else { + logger.warn("host or\\and port are empty: host=" + host + ", port=" + port); + } + } + } - // Main & Phases - loadPhases(prefs); + /** + * @param args the command line arguments + */ + public static void main(String args[]) { + int param = 0; + if (args.length > 0) { + String param1 = args[0]; + if (param1.equals(OPEN_CONNECTION_TAB)) { + param = 4; + } + if (param1.equals(OPEN_PHASES_TAB)) { + param = 1; + } + } + final int openedTab = param; + java.awt.EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + if (!dialog.isVisible()) { + Preferences prefs = MageFrame.getPreferences(); - // Gui Size - loadGuiSize(prefs); + // Main & Phases + loadPhases(prefs); - // Images - loadImagesSettings(prefs); + // Gui Size + loadGuiSize(prefs); - // Sounds - loadSoundSettings(prefs); + // Images + loadImagesSettings(prefs); - // Connection - loadProxySettings(prefs); + // Sounds + loadSoundSettings(prefs); - // Selected avatar - loadSelectedAvatar(prefs); + // Connection + loadProxySettings(prefs); - dialog.reset(); - // open specified tab before displaying - openTab(openedTab); + // Controls + loadControlSettings(prefs); - dialog.setLocation(300, 200); + // Selected avatar + loadSelectedAvatar(prefs); - dialog.setVisible(true); - } else { - dialog.requestFocus(); - } - } - }); - } + dialog.reset(); + // open specified tab before displaying + openTab(openedTab); - private static void loadPhases(Preferences prefs) { - load(prefs, dialog.tooltipDelay, KEY_SHOW_TOOLTIPS_DELAY, "300"); - load(prefs, dialog.showCardName, KEY_SHOW_CARD_NAMES, "true"); - load(prefs, dialog.nonLandPermanentsInOnePile, KEY_PERMANENTS_IN_ONE_PILE, "true"); - load(prefs, dialog.showPlayerNamesPermanently, KEY_SHOW_PLAYER_NAMES_PERMANENTLY, "true"); - load(prefs, dialog.showAbilityPickerForced, KEY_SHOW_ABILITY_PICKER_FORCED, "true"); - load(prefs, dialog.cbAllowRequestToShowHandCards, KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS, "true"); - load(prefs, dialog.cbShowStormCounter, KEY_GAME_SHOW_STORM_COUNTER, "true"); - load(prefs, dialog.cbConfirmEmptyManaPool, KEY_GAME_CONFIRM_EMPTY_MANA_POOL, "true"); - load(prefs, dialog.cbAskMoveToGraveOrder, KEY_GAME_ASK_MOVE_TO_GRAVE_ORDER, "true"); + dialog.setLocation(300, 200); - load(prefs, dialog.cbGameLogAutoSave, KEY_GAME_LOG_AUTO_SAVE, "true"); - load(prefs, dialog.cbDraftLogAutoSave, KEY_DRAFT_LOG_AUTO_SAVE, "true"); + dialog.setVisible(true); + } else { + dialog.requestFocus(); + } + } + }); + } - load(prefs, dialog.checkBoxUpkeepYou, UPKEEP_YOU, "on", "on"); - load(prefs, dialog.checkBoxDrawYou, DRAW_YOU, "on", "on"); - load(prefs, dialog.checkBoxMainYou, MAIN_YOU, "on", "on"); - load(prefs, dialog.checkBoxBeforeCYou, BEFORE_COMBAT_YOU, "on", "on"); - load(prefs, dialog.checkBoxEndOfCYou, END_OF_COMBAT_YOU, "on", "on"); - load(prefs, dialog.checkBoxMain2You, MAIN_TWO_YOU, "on", "on"); - load(prefs, dialog.checkBoxEndTurnYou, END_OF_TURN_YOU, "on", "on"); + private static void loadPhases(Preferences prefs) { + load(prefs, dialog.tooltipDelay, KEY_SHOW_TOOLTIPS_DELAY, "300"); + load(prefs, dialog.showCardName, KEY_SHOW_CARD_NAMES, "true"); + load(prefs, dialog.nonLandPermanentsInOnePile, KEY_PERMANENTS_IN_ONE_PILE, "true"); + load(prefs, dialog.showPlayerNamesPermanently, KEY_SHOW_PLAYER_NAMES_PERMANENTLY, "true"); + load(prefs, dialog.showAbilityPickerForced, KEY_SHOW_ABILITY_PICKER_FORCED, "true"); + load(prefs, dialog.cbAllowRequestToShowHandCards, KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS, "true"); + load(prefs, dialog.cbShowStormCounter, KEY_GAME_SHOW_STORM_COUNTER, "true"); + load(prefs, dialog.cbConfirmEmptyManaPool, KEY_GAME_CONFIRM_EMPTY_MANA_POOL, "true"); + load(prefs, dialog.cbAskMoveToGraveOrder, KEY_GAME_ASK_MOVE_TO_GRAVE_ORDER, "true"); - load(prefs, dialog.checkBoxUpkeepOthers, UPKEEP_OTHERS, "on", "on"); - load(prefs, dialog.checkBoxDrawOthers, DRAW_OTHERS, "on", "on"); - load(prefs, dialog.checkBoxMainOthers, MAIN_OTHERS, "on", "on"); - load(prefs, dialog.checkBoxBeforeCOthers, BEFORE_COMBAT_OTHERS, "on", "on"); - load(prefs, dialog.checkBoxEndOfCOthers, END_OF_COMBAT_OTHERS, "on", "on"); - load(prefs, dialog.checkBoxMain2Others, MAIN_TWO_OTHERS, "on", "on"); - load(prefs, dialog.checkBoxEndTurnOthers, END_OF_TURN_OTHERS, "on", "on"); + load(prefs, dialog.cbGameLogAutoSave, KEY_GAME_LOG_AUTO_SAVE, "true"); + load(prefs, dialog.cbDraftLogAutoSave, KEY_DRAFT_LOG_AUTO_SAVE, "true"); - load(prefs, dialog.cbStopAttack, KEY_STOP_ATTACK, "true", "true"); - load(prefs, dialog.cbStopBlock, KEY_STOP_BLOCK, "true", "true"); - load(prefs, dialog.cbStopOnAllMain, KEY_STOP_ALL_MAIN_PHASES, "true", "false"); - load(prefs, dialog.cbStopOnAllEnd, KEY_STOP_ALL_END_PHASES, "true", "false"); - load(prefs, dialog.cbPassPriorityCast, KEY_PASS_PRIORITY_CAST, "true", "false"); - load(prefs, dialog.cbPassPriorityActivation, KEY_PASS_PRIORITY_ACTIVATION, "true", "false"); - load(prefs, dialog.cbAutoOrderTrigger, KEY_AUTO_ORDER_TRIGGER, "true", "true"); + load(prefs, dialog.checkBoxUpkeepYou, UPKEEP_YOU, "on", "on"); + load(prefs, dialog.checkBoxDrawYou, DRAW_YOU, "on", "on"); + load(prefs, dialog.checkBoxMainYou, MAIN_YOU, "on", "on"); + load(prefs, dialog.checkBoxBeforeCYou, BEFORE_COMBAT_YOU, "on", "on"); + load(prefs, dialog.checkBoxEndOfCYou, END_OF_COMBAT_YOU, "on", "on"); + load(prefs, dialog.checkBoxMain2You, MAIN_TWO_YOU, "on", "on"); + load(prefs, dialog.checkBoxEndTurnYou, END_OF_TURN_YOU, "on", "on"); - } + load(prefs, dialog.checkBoxUpkeepOthers, UPKEEP_OTHERS, "on", "on"); + load(prefs, dialog.checkBoxDrawOthers, DRAW_OTHERS, "on", "on"); + load(prefs, dialog.checkBoxMainOthers, MAIN_OTHERS, "on", "on"); + load(prefs, dialog.checkBoxBeforeCOthers, BEFORE_COMBAT_OTHERS, "on", "on"); + load(prefs, dialog.checkBoxEndOfCOthers, END_OF_COMBAT_OTHERS, "on", "on"); + load(prefs, dialog.checkBoxMain2Others, MAIN_TWO_OTHERS, "on", "on"); + load(prefs, dialog.checkBoxEndTurnOthers, END_OF_TURN_OTHERS, "on", "on"); - private static void loadGuiSize(Preferences prefs) { - load(prefs, dialog.sliderFontSize, KEY_GUI_TABLE_FONT_SIZE, "14"); - load(prefs, dialog.sliderChatFontSize, KEY_GUI_CHAT_FONT_SIZE, "14"); - load(prefs, dialog.sliderCardSizeHand, KEY_GUI_CARD_HAND_SIZE, "14"); - load(prefs, dialog.sliderEditorCardSize, KEY_GUI_CARD_EDITOR_SIZE, "14"); - load(prefs, dialog.sliderEditorCardOffset, KEY_GUI_CARD_OFFSET_SIZE, "14"); - load(prefs, dialog.sliderEnlargedImageSize, KEY_GUI_ENLARGED_IMAGE_SIZE, "20"); - load(prefs, dialog.sliderStackWidth, KEY_GUI_STACK_WIDTH, "14"); - load(prefs, dialog.sliderDialogFont, KEY_GUI_DIALOG_FONT_SIZE, "14"); - load(prefs, dialog.sliderTooltipSize, KEY_GUI_TOOLTIP_SIZE, "14"); - load(prefs, dialog.sliderGameFeedbackArea, KEY_GUI_FEEDBACK_AREA_SIZE, "14"); - load(prefs, dialog.sliderCardSizeOtherZones, KEY_GUI_CARD_OTHER_ZONES_SIZE, "14"); - load(prefs, dialog.sliderCardSizeMinBattlefield, KEY_GUI_CARD_BATTLEFIELD_MIN_SIZE, "10"); - load(prefs, dialog.sliderCardSizeMaxBattlefield, KEY_GUI_CARD_BATTLEFIELD_MAX_SIZE, "14"); - } + load(prefs, dialog.cbStopAttack, KEY_STOP_ATTACK, "true", "true"); + load(prefs, dialog.cbStopBlock, KEY_STOP_BLOCK, "true", "true"); + load(prefs, dialog.cbStopOnAllMain, KEY_STOP_ALL_MAIN_PHASES, "true", "false"); + load(prefs, dialog.cbStopOnAllEnd, KEY_STOP_ALL_END_PHASES, "true", "false"); + load(prefs, dialog.cbPassPriorityCast, KEY_PASS_PRIORITY_CAST, "true", "false"); + load(prefs, dialog.cbPassPriorityActivation, KEY_PASS_PRIORITY_ACTIVATION, "true", "false"); + load(prefs, dialog.cbAutoOrderTrigger, KEY_AUTO_ORDER_TRIGGER, "true", "true"); - private static void loadImagesSettings(Preferences prefs) { - String prop = prefs.get(KEY_CARD_IMAGES_USE_DEFAULT, "true"); - if (prop.equals("true")) { - dialog.cbUseDefaultImageFolder.setSelected(true); - dialog.useDefaultPath(); - } else { - dialog.cbUseDefaultImageFolder.setSelected(false); - dialog.useConfigurablePath(); - String path = prefs.get(KEY_CARD_IMAGES_PATH, ""); - dialog.txtImageFolderPath.setText(path); - updateCache(KEY_CARD_IMAGES_PATH, path); - } - load(prefs, dialog.cbCheckForNewImages, KEY_CARD_IMAGES_CHECK, "true"); - load(prefs, dialog.cbSaveToZipFiles, KEY_CARD_IMAGES_SAVE_TO_ZIP, "true"); - dialog.cbNumberOfDownloadThreads.setSelectedItem(MageFrame.getPreferences().get(KEY_CARD_IMAGES_THREADS, "10")); - dialog.cbPreferedImageLanguage.setSelectedItem(MageFrame.getPreferences().get(KEY_CARD_IMAGES_PREF_LANGUAGE, "en")); + } - // rendering settings - load(prefs, dialog.cbCardRenderImageFallback, KEY_CARD_RENDERING_FALLBACK, "true"); - load(prefs, dialog.cbCardRenderHideSetSymbol, KEY_CARD_RENDERING_SET_SYMBOL, "true"); - load(prefs, dialog.cbCardRenderShowReminderText, KEY_CARD_RENDERING_REMINDER_TEXT, "true"); - - //add background load precedure - prop = prefs.get(KEY_BACKGROUND_IMAGE_DEFAULT, "true"); - if (prop.equals("true")) { - dialog.cbUseDefaultBackground.setSelected(true); - dialog.useDefaultBackgroundImage(); - } else { - dialog.cbUseDefaultBackground.setSelected(false); - dialog.useSelectBackgroundImage(); - String path = prefs.get(KEY_BACKGROUND_IMAGE, ""); - dialog.txtBackgroundImagePath.setText(path); - updateCache(KEY_BACKGROUND_IMAGE, path); - } - prop = prefs.get(KEY_BATTLEFIELD_IMAGE_DEFAULT, "true"); - if (prop.equals("true")) { - dialog.cbUseDefaultBattleImage.setSelected(true); - dialog.useDefaultBattlefield(); - } else { - dialog.cbUseDefaultBattleImage.setSelected(false); - dialog.useSelectedOrRandom(); - } - prop = prefs.get(KEY_BATTLEFIELD_IMAGE_RANDOM, "true"); + private static void loadGuiSize(Preferences prefs) { + load(prefs, dialog.sliderFontSize, KEY_GUI_TABLE_FONT_SIZE, "14"); + load(prefs, dialog.sliderChatFontSize, KEY_GUI_CHAT_FONT_SIZE, "14"); + load(prefs, dialog.sliderCardSizeHand, KEY_GUI_CARD_HAND_SIZE, "14"); + load(prefs, dialog.sliderEditorCardSize, KEY_GUI_CARD_EDITOR_SIZE, "14"); + load(prefs, dialog.sliderEditorCardOffset, KEY_GUI_CARD_OFFSET_SIZE, "14"); + load(prefs, dialog.sliderEnlargedImageSize, KEY_GUI_ENLARGED_IMAGE_SIZE, "20"); + load(prefs, dialog.sliderStackWidth, KEY_GUI_STACK_WIDTH, "14"); + load(prefs, dialog.sliderDialogFont, KEY_GUI_DIALOG_FONT_SIZE, "14"); + load(prefs, dialog.sliderTooltipSize, KEY_GUI_TOOLTIP_SIZE, "14"); + load(prefs, dialog.sliderGameFeedbackArea, KEY_GUI_FEEDBACK_AREA_SIZE, "14"); + load(prefs, dialog.sliderCardSizeOtherZones, KEY_GUI_CARD_OTHER_ZONES_SIZE, "14"); + load(prefs, dialog.sliderCardSizeMinBattlefield, KEY_GUI_CARD_BATTLEFIELD_MIN_SIZE, "10"); + load(prefs, dialog.sliderCardSizeMaxBattlefield, KEY_GUI_CARD_BATTLEFIELD_MAX_SIZE, "14"); + } - if (dialog.cbUseRandomBattleImage.isEnabled()) { - if (prop.equals("true")) { - dialog.cbUseRandomBattleImage.setSelected(true); - dialog.useRandomBattleField(); - } else { - dialog.cbUseRandomBattleImage.setSelected(false); - dialog.useSelectedBattleField(); - String path = prefs.get(KEY_BATTLEFIELD_IMAGE, ""); - dialog.txtBattlefieldImagePath.setText(path); - updateCache(KEY_BATTLEFIELD_IMAGE, path); - } - } - } + private static void loadImagesSettings(Preferences prefs) { + String prop = prefs.get(KEY_CARD_IMAGES_USE_DEFAULT, "true"); + if (prop.equals("true")) { + dialog.cbUseDefaultImageFolder.setSelected(true); + dialog.useDefaultPath(); + } else { + dialog.cbUseDefaultImageFolder.setSelected(false); + dialog.useConfigurablePath(); + String path = prefs.get(KEY_CARD_IMAGES_PATH, ""); + dialog.txtImageFolderPath.setText(path); + updateCache(KEY_CARD_IMAGES_PATH, path); + } + load(prefs, dialog.cbCheckForNewImages, KEY_CARD_IMAGES_CHECK, "true"); + load(prefs, dialog.cbSaveToZipFiles, KEY_CARD_IMAGES_SAVE_TO_ZIP, "true"); + dialog.cbNumberOfDownloadThreads.setSelectedItem(MageFrame.getPreferences().get(KEY_CARD_IMAGES_THREADS, "10")); + dialog.cbPreferedImageLanguage.setSelectedItem(MageFrame.getPreferences().get(KEY_CARD_IMAGES_PREF_LANGUAGE, "en")); - private static void loadSoundSettings(Preferences prefs) { - dialog.cbEnableGameSounds.setSelected(prefs.get(KEY_SOUNDS_GAME_ON, "true").equals("true")); - dialog.cbEnableDraftSounds.setSelected(prefs.get(KEY_SOUNDS_DRAFT_ON, "true").equals("true")); - dialog.cbEnableSkipButtonsSounds.setSelected(prefs.get(KEY_SOUNDS_SKIP_BUTTONS_ON, "true").equals("true")); - dialog.cbEnableOtherSounds.setSelected(prefs.get(KEY_SOUNDS_OTHER_ON, "true").equals("true")); + // rendering settings + load(prefs, dialog.cbCardRenderImageFallback, KEY_CARD_RENDERING_FALLBACK, "true"); + load(prefs, dialog.cbCardRenderHideSetSymbol, KEY_CARD_RENDERING_SET_SYMBOL, "true"); + load(prefs, dialog.cbCardRenderShowReminderText, KEY_CARD_RENDERING_REMINDER_TEXT, "true"); - // Match music - dialog.cbEnableBattlefieldBGM.setSelected(prefs.get(KEY_SOUNDS_MATCH_MUSIC_ON, "true").equals("true")); - dialog.txtBattlefieldIBGMPath.setEnabled(dialog.cbEnableBattlefieldBGM.isSelected()); - dialog.btnBattlefieldBGMBrowse.setEnabled(dialog.cbEnableBattlefieldBGM.isSelected()); - // load and save the path always, so you can reactivate music without selecting path again - String path = prefs.get(KEY_SOUNDS_MATCH_MUSIC_PATH, ""); - dialog.txtBattlefieldIBGMPath.setText(path); + //add background load precedure + prop = prefs.get(KEY_BACKGROUND_IMAGE_DEFAULT, "true"); + if (prop.equals("true")) { + dialog.cbUseDefaultBackground.setSelected(true); + dialog.useDefaultBackgroundImage(); + } else { + dialog.cbUseDefaultBackground.setSelected(false); + dialog.useSelectBackgroundImage(); + String path = prefs.get(KEY_BACKGROUND_IMAGE, ""); + dialog.txtBackgroundImagePath.setText(path); + updateCache(KEY_BACKGROUND_IMAGE, path); + } + prop = prefs.get(KEY_BATTLEFIELD_IMAGE_DEFAULT, "true"); + if (prop.equals("true")) { + dialog.cbUseDefaultBattleImage.setSelected(true); + dialog.useDefaultBattlefield(); + } else { + dialog.cbUseDefaultBattleImage.setSelected(false); + dialog.useSelectedOrRandom(); + } + prop = prefs.get(KEY_BATTLEFIELD_IMAGE_RANDOM, "true"); - updateCache(KEY_SOUNDS_MATCH_MUSIC_PATH, path); - } + if (dialog.cbUseRandomBattleImage.isEnabled()) { + if (prop.equals("true")) { + dialog.cbUseRandomBattleImage.setSelected(true); + dialog.useRandomBattleField(); + } else { + dialog.cbUseRandomBattleImage.setSelected(false); + dialog.useSelectedBattleField(); + String path = prefs.get(KEY_BATTLEFIELD_IMAGE, ""); + dialog.txtBattlefieldImagePath.setText(path); + updateCache(KEY_BATTLEFIELD_IMAGE, path); + } + } + } - private static void loadProxySettings(Preferences prefs) { - dialog.cbProxyType.setSelectedItem(Connection.ProxyType.valueOf(MageFrame.getPreferences().get(KEY_PROXY_TYPE, "NONE").toUpperCase())); + private static void loadSoundSettings(Preferences prefs) { + dialog.cbEnableGameSounds.setSelected(prefs.get(KEY_SOUNDS_GAME_ON, "true").equals("true")); + dialog.cbEnableDraftSounds.setSelected(prefs.get(KEY_SOUNDS_DRAFT_ON, "true").equals("true")); + dialog.cbEnableSkipButtonsSounds.setSelected(prefs.get(KEY_SOUNDS_SKIP_BUTTONS_ON, "true").equals("true")); + dialog.cbEnableOtherSounds.setSelected(prefs.get(KEY_SOUNDS_OTHER_ON, "true").equals("true")); - load(prefs, dialog.txtProxyServer, KEY_PROXY_ADDRESS, Config.serverName); - load(prefs, dialog.txtProxyPort, KEY_PROXY_PORT, Integer.toString(Config.port)); - load(prefs, dialog.txtProxyUserName, KEY_PROXY_USERNAME, ""); - load(prefs, dialog.rememberPswd, KEY_PROXY_REMEMBER, "true", "false"); - if (dialog.rememberPswd.isSelected()) { - load(prefs, dialog.txtPasswordField, KEY_PROXY_PSWD, ""); - } - load(prefs, dialog.txtURLServerList, KEY_CONNECTION_URL_SERVER_LIST, "http://XMage.de/files/server-list.txt"); - } + // Match music + dialog.cbEnableBattlefieldBGM.setSelected(prefs.get(KEY_SOUNDS_MATCH_MUSIC_ON, "true").equals("true")); + dialog.txtBattlefieldIBGMPath.setEnabled(dialog.cbEnableBattlefieldBGM.isSelected()); + dialog.btnBattlefieldBGMBrowse.setEnabled(dialog.cbEnableBattlefieldBGM.isSelected()); + // load and save the path always, so you can reactivate music without selecting path again + String path = prefs.get(KEY_SOUNDS_MATCH_MUSIC_PATH, ""); + dialog.txtBattlefieldIBGMPath.setText(path); - private static void loadSelectedAvatar(Preferences prefs) { - getSelectedAvatar(); - dialog.setSelectedId(selectedAvatarId); - } + updateCache(KEY_SOUNDS_MATCH_MUSIC_PATH, path); + } - public static int getSelectedAvatar() { - try { - selectedAvatarId = Integer.valueOf(MageFrame.getPreferences().get(KEY_AVATAR, String.valueOf(DEFAULT_AVATAR_ID))); - } catch (NumberFormatException n) { - selectedAvatarId = DEFAULT_AVATAR_ID; - } finally { - if (selectedAvatarId < MIN_AVATAR_ID || selectedAvatarId > MAX_AVATAR_ID) { - selectedAvatarId = DEFAULT_AVATAR_ID; - } - } - return selectedAvatarId; - } + private static void loadProxySettings(Preferences prefs) { + dialog.cbProxyType.setSelectedItem(Connection.ProxyType.valueOf(MageFrame.getPreferences().get(KEY_PROXY_TYPE, "NONE").toUpperCase())); - public static UserSkipPrioritySteps getUserSkipPrioritySteps() { - if (!dialog.isVisible()) { - loadPhases(MageFrame.getPreferences()); - } - UserSkipPrioritySteps userSkipPrioritySteps = new UserSkipPrioritySteps(); + load(prefs, dialog.txtProxyServer, KEY_PROXY_ADDRESS, Config.serverName); + load(prefs, dialog.txtProxyPort, KEY_PROXY_PORT, Integer.toString(Config.port)); + load(prefs, dialog.txtProxyUserName, KEY_PROXY_USERNAME, ""); + load(prefs, dialog.rememberPswd, KEY_PROXY_REMEMBER, "true", "false"); + if (dialog.rememberPswd.isSelected()) { + load(prefs, dialog.txtPasswordField, KEY_PROXY_PSWD, ""); + } + load(prefs, dialog.txtURLServerList, KEY_CONNECTION_URL_SERVER_LIST, "http://XMage.de/files/server-list.txt"); + } - userSkipPrioritySteps.getYourTurn().setUpkeep(dialog.checkBoxUpkeepYou.isSelected()); - userSkipPrioritySteps.getYourTurn().setDraw(dialog.checkBoxDrawYou.isSelected()); - userSkipPrioritySteps.getYourTurn().setMain1(dialog.checkBoxMainYou.isSelected()); - userSkipPrioritySteps.getYourTurn().setBeforeCombat(dialog.checkBoxBeforeCYou.isSelected()); - userSkipPrioritySteps.getYourTurn().setEndOfCombat(dialog.checkBoxEndOfCYou.isSelected()); - userSkipPrioritySteps.getYourTurn().setMain2(dialog.checkBoxMain2You.isSelected()); - userSkipPrioritySteps.getYourTurn().setEndOfTurn(dialog.checkBoxEndTurnYou.isSelected()); + private static void loadControlSettings(Preferences prefs) { + load(prefs, dialog.keyConfirm); + load(prefs, dialog.keyCancelSkip); + load(prefs, dialog.keyNextTurn); + load(prefs, dialog.keyEndStep); + load(prefs, dialog.keySkipStep); + load(prefs, dialog.keyMainStep); + load(prefs, dialog.keyYourTurn); + load(prefs, dialog.keySkipStack); + load(prefs, dialog.keyPriorEnd); + } - userSkipPrioritySteps.getOpponentTurn().setUpkeep(dialog.checkBoxUpkeepOthers.isSelected()); - userSkipPrioritySteps.getOpponentTurn().setDraw(dialog.checkBoxDrawOthers.isSelected()); - userSkipPrioritySteps.getOpponentTurn().setMain1(dialog.checkBoxMainOthers.isSelected()); - userSkipPrioritySteps.getOpponentTurn().setBeforeCombat(dialog.checkBoxBeforeCOthers.isSelected()); - userSkipPrioritySteps.getOpponentTurn().setEndOfCombat(dialog.checkBoxEndOfCOthers.isSelected()); - userSkipPrioritySteps.getOpponentTurn().setMain2(dialog.checkBoxMain2Others.isSelected()); - userSkipPrioritySteps.getOpponentTurn().setEndOfTurn(dialog.checkBoxEndTurnOthers.isSelected()); + private static void loadSelectedAvatar(Preferences prefs) { + getSelectedAvatar(); + dialog.setSelectedId(selectedAvatarId); + } - userSkipPrioritySteps.setStopOnDeclareAttackersDuringSkipActions(dialog.cbStopAttack.isSelected()); - userSkipPrioritySteps.setStopOnDeclareBlockerIfNoneAvailable(dialog.cbStopBlock.isSelected()); - userSkipPrioritySteps.setStopOnAllEndPhases(dialog.cbStopOnAllEnd.isSelected()); - userSkipPrioritySteps.setStopOnAllMainPhases(dialog.cbStopOnAllMain.isSelected()); + public static int getSelectedAvatar() { + try { + selectedAvatarId = Integer.valueOf(MageFrame.getPreferences().get(KEY_AVATAR, String.valueOf(DEFAULT_AVATAR_ID))); + } catch (NumberFormatException n) { + selectedAvatarId = DEFAULT_AVATAR_ID; + } finally { + if (selectedAvatarId < MIN_AVATAR_ID || selectedAvatarId > MAX_AVATAR_ID) { + selectedAvatarId = DEFAULT_AVATAR_ID; + } + } + return selectedAvatarId; + } - return userSkipPrioritySteps; - } + public static UserSkipPrioritySteps getUserSkipPrioritySteps() { + if (!dialog.isVisible()) { + loadPhases(MageFrame.getPreferences()); + } + UserSkipPrioritySteps userSkipPrioritySteps = new UserSkipPrioritySteps(); - private static void openTab(int index) { - try { - if (index > 0) { - dialog.tabsPanel.setSelectedIndex(index); - } - } catch (Exception e) { - logger.error("Error during open tab", e); - } - } + userSkipPrioritySteps.getYourTurn().setUpkeep(dialog.checkBoxUpkeepYou.isSelected()); + userSkipPrioritySteps.getYourTurn().setDraw(dialog.checkBoxDrawYou.isSelected()); + userSkipPrioritySteps.getYourTurn().setMain1(dialog.checkBoxMainYou.isSelected()); + userSkipPrioritySteps.getYourTurn().setBeforeCombat(dialog.checkBoxBeforeCYou.isSelected()); + userSkipPrioritySteps.getYourTurn().setEndOfCombat(dialog.checkBoxEndOfCYou.isSelected()); + userSkipPrioritySteps.getYourTurn().setMain2(dialog.checkBoxMain2You.isSelected()); + userSkipPrioritySteps.getYourTurn().setEndOfTurn(dialog.checkBoxEndTurnYou.isSelected()); - private static void saveImagesPath(Preferences prefs) { - if (!dialog.cbUseDefaultImageFolder.isSelected()) { - String path = dialog.txtImageFolderPath.getText(); - prefs.put(KEY_CARD_IMAGES_PATH, path); - updateCache(KEY_CARD_IMAGES_PATH, path); - } - // background path save precedure - if (!dialog.cbUseDefaultBackground.isSelected()) { - String path = dialog.txtBackgroundImagePath.getText(); - prefs.put(KEY_BACKGROUND_IMAGE, path); - updateCache(KEY_BACKGROUND_IMAGE, path); - } - if (!dialog.cbUseDefaultBattleImage.isSelected() && !dialog.cbUseRandomBattleImage.isSelected()) { - String path = dialog.txtBattlefieldImagePath.getText(); - prefs.put(KEY_BATTLEFIELD_IMAGE, path); - updateCache(KEY_BATTLEFIELD_IMAGE, path); - } - } + userSkipPrioritySteps.getOpponentTurn().setUpkeep(dialog.checkBoxUpkeepOthers.isSelected()); + userSkipPrioritySteps.getOpponentTurn().setDraw(dialog.checkBoxDrawOthers.isSelected()); + userSkipPrioritySteps.getOpponentTurn().setMain1(dialog.checkBoxMainOthers.isSelected()); + userSkipPrioritySteps.getOpponentTurn().setBeforeCombat(dialog.checkBoxBeforeCOthers.isSelected()); + userSkipPrioritySteps.getOpponentTurn().setEndOfCombat(dialog.checkBoxEndOfCOthers.isSelected()); + userSkipPrioritySteps.getOpponentTurn().setMain2(dialog.checkBoxMain2Others.isSelected()); + userSkipPrioritySteps.getOpponentTurn().setEndOfTurn(dialog.checkBoxEndTurnOthers.isSelected()); - private static void saveSoundPath(Preferences prefs) { - String path = dialog.txtBattlefieldIBGMPath.getText(); - prefs.put(KEY_SOUNDS_MATCH_MUSIC_PATH, path); - updateCache(KEY_SOUNDS_MATCH_MUSIC_PATH, path); - } + userSkipPrioritySteps.setStopOnDeclareAttackersDuringSkipActions(dialog.cbStopAttack.isSelected()); + userSkipPrioritySteps.setStopOnDeclareBlockerIfNoneAvailable(dialog.cbStopBlock.isSelected()); + userSkipPrioritySteps.setStopOnAllEndPhases(dialog.cbStopOnAllEnd.isSelected()); + userSkipPrioritySteps.setStopOnAllMainPhases(dialog.cbStopOnAllMain.isSelected()); - public static boolean isSaveImagesToZip() { - return PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_SAVE_TO_ZIP, "true").equals("true"); - } + return userSkipPrioritySteps; + } - private static void load(Preferences prefs, JCheckBox checkBox, String propName, String yesValue) { - String prop = prefs.get(propName, yesValue); - checkBox.setSelected(prop.equals(yesValue)); - } + private static void openTab(int index) { + try { + if (index > 0) { + dialog.tabsPanel.setSelectedIndex(index); + } + } catch (Exception e) { + logger.error("Error during open tab", e); + } + } - private static void load(Preferences prefs, JCheckBox checkBox, String propName, String yesValue, String defaultValue) { - String prop = prefs.get(propName, defaultValue); - checkBox.setSelected(prop.equals(yesValue)); - updateCache(propName, prop); - } + private static void saveImagesPath(Preferences prefs) { + if (!dialog.cbUseDefaultImageFolder.isSelected()) { + String path = dialog.txtImageFolderPath.getText(); + prefs.put(KEY_CARD_IMAGES_PATH, path); + updateCache(KEY_CARD_IMAGES_PATH, path); + } + // background path save precedure + if (!dialog.cbUseDefaultBackground.isSelected()) { + String path = dialog.txtBackgroundImagePath.getText(); + prefs.put(KEY_BACKGROUND_IMAGE, path); + updateCache(KEY_BACKGROUND_IMAGE, path); + } + if (!dialog.cbUseDefaultBattleImage.isSelected() && !dialog.cbUseRandomBattleImage.isSelected()) { + String path = dialog.txtBattlefieldImagePath.getText(); + prefs.put(KEY_BATTLEFIELD_IMAGE, path); + updateCache(KEY_BATTLEFIELD_IMAGE, path); + } + } - private static void load(Preferences prefs, JTextField field, String propName, String defaultValue) { - String prop = prefs.get(propName, defaultValue); - field.setText(prop); - } + private static void saveSoundPath(Preferences prefs) { + String path = dialog.txtBattlefieldIBGMPath.getText(); + prefs.put(KEY_SOUNDS_MATCH_MUSIC_PATH, path); + updateCache(KEY_SOUNDS_MATCH_MUSIC_PATH, path); + } - private static void load(Preferences prefs, JSlider field, String propName, String defaultValue) { - String prop = prefs.get(propName, defaultValue); - int value; - try { - value = Integer.parseInt(prop); - } catch (NumberFormatException e) { - // It's OK to ignore "e" here because returning a default value is the documented behaviour on invalid input. - value = Integer.parseInt(defaultValue); - } - field.setValue(value); - } + public static boolean isSaveImagesToZip() { + return PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_SAVE_TO_ZIP, "true").equals("true"); + } - private static void load(Preferences prefs, JComboBox field, String propName, String defaultValue) { - String prop = prefs.get(propName, defaultValue); - field.setSelectedItem(prop); - } + private static void load(Preferences prefs, JCheckBox checkBox, String propName, String yesValue) { + String prop = prefs.get(propName, yesValue); + checkBox.setSelected(prop.equals(yesValue)); + } - private static void load(Preferences prefs, JCheckBox checkBox, String propName) { - load(prefs, checkBox, propName, PHASE_ON); - } + private static void load(Preferences prefs, JCheckBox checkBox, String propName, String yesValue, String defaultValue) { + String prop = prefs.get(propName, defaultValue); + checkBox.setSelected(prop.equals(yesValue)); + updateCache(propName, prop); + } - private static void save(Preferences prefs, JCheckBox checkBox, String propName) { - save(prefs, checkBox, propName, PHASE_ON, PHASE_OFF, false); - } + private static void load(Preferences prefs, JTextField field, String propName, String defaultValue) { + String prop = prefs.get(propName, defaultValue); + field.setText(prop); + } - public static void setPrefValue(String key, boolean value) { - switch (key) { - case KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS: - dialog.cbAllowRequestToShowHandCards.setSelected(value); - save(MageFrame.getPreferences(), dialog.cbAllowRequestToShowHandCards, KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS, "true", "false", UPDATE_CACHE_POLICY); - break; - } - } + private static void load(Preferences prefs, JSlider field, String propName, String defaultValue) { + String prop = prefs.get(propName, defaultValue); + int value; + try { + value = Integer.parseInt(prop); + } catch (NumberFormatException e) { + // It's OK to ignore "e" here because returning a default value is the documented behaviour on invalid input. + value = Integer.parseInt(defaultValue); + } + field.setValue(value); + } - private static void save(Preferences prefs, JCheckBox checkBox, String propName, String yesValue, String noValue, boolean updateCache) { - prefs.put(propName, checkBox.isSelected() ? yesValue : noValue); - if (updateCache) { - updateCache(propName, checkBox.isSelected() ? yesValue : noValue); - } - } + private static void load(Preferences prefs, JComboBox field, String propName, String defaultValue) { + String prop = prefs.get(propName, defaultValue); + field.setSelectedItem(prop); + } - private static void save(Preferences prefs, JSlider slider, String propName, String yesValue, String noValue, boolean updateCache) { - prefs.put(propName, Integer.toString(slider.getValue())); - if (updateCache) { - updateCache(propName, Integer.toString(slider.getValue())); - } - } + private static void load(Preferences prefs, JCheckBox checkBox, String propName) { + load(prefs, checkBox, propName, PHASE_ON); + } - private static void save(Preferences prefs, JTextField textField, String propName) { - prefs.put(propName, textField.getText().trim()); - updateCache(propName, textField.getText().trim()); - } + private static void load(Preferences prefs, KeyBindButton button) { + String key = button.getKey(); + int prop = prefs.getInt(key, getDefaultControlKey(key)); + button.setKeyCode(prop); + } - private static void save(Preferences prefs, JComboBox comboBox, String propName) { - prefs.put(propName, comboBox.getSelectedItem().toString().trim()); - updateCache(propName, comboBox.getSelectedItem().toString().trim()); - } + private static void save(Preferences prefs, JCheckBox checkBox, String propName) { + save(prefs, checkBox, propName, PHASE_ON, PHASE_OFF, false); + } - public void reset() { - tabsPanel.setSelectedIndex(0); - } + public static void setPrefValue(String key, boolean value) { + switch (key) { + case KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS: + dialog.cbAllowRequestToShowHandCards.setSelected(value); + save(MageFrame.getPreferences(), dialog.cbAllowRequestToShowHandCards, KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS, "true", "false", UPDATE_CACHE_POLICY); + break; + } + } - public static int getCachedValue(String key, int def) { - String stringValue = getCachedValue(key, String.valueOf(def)); - int value; - try { - value = Integer.parseInt(stringValue); - } catch (NumberFormatException e) { - // It's OK to ignore "e" here because returning a default value is the documented behaviour on invalid input. - value = def; - } - return value; - } + private static void save(Preferences prefs, JCheckBox checkBox, String propName, String yesValue, String noValue, boolean updateCache) { + prefs.put(propName, checkBox.isSelected() ? yesValue : noValue); + if (updateCache) { + updateCache(propName, checkBox.isSelected() ? yesValue : noValue); + } + } - public static String getCachedValue(String key, String def) { - if (CACHE.containsKey(key)) { - return CACHE.get(key); - } else { - Preferences prefs = MageFrame.getPreferences(); - String value = prefs.get(key, def); - if (value == null) { - return null; - } - CACHE.put(key, value); - return value; - } - } + private static void save(Preferences prefs, JSlider slider, String propName, String yesValue, String noValue, boolean updateCache) { + prefs.put(propName, Integer.toString(slider.getValue())); + if (updateCache) { + updateCache(propName, Integer.toString(slider.getValue())); + } + } - private static void updateCache(String key, String value) { - CACHE.put(key, value); - } + private static void save(Preferences prefs, JTextField textField, String propName) { + prefs.put(propName, textField.getText().trim()); + updateCache(propName, textField.getText().trim()); + } - public static void saveValue(String key, String value) { - Preferences prefs = MageFrame.getPreferences(); - prefs.put(key, value); - try { - prefs.flush(); - } catch (BackingStoreException ex) { - ex.printStackTrace(); - JOptionPane.showMessageDialog(null, "Error: couldn't save preferences. Please try once again."); - } - updateCache(key, value); - } + private static void save(Preferences prefs, JComboBox comboBox, String propName) { + prefs.put(propName, comboBox.getSelectedItem().toString().trim()); + updateCache(propName, comboBox.getSelectedItem().toString().trim()); + } - private void addAvatars() { - try { - addAvatar(jPanel10, 10, true, false); - addAvatar(jPanel11, 11, false, false); - addAvatar(jPanel12, 12, false, false); - addAvatar(jPanel13, 13, false, false); - addAvatar(jPanel14, 14, false, false); - addAvatar(jPanel15, 15, false, false); - addAvatar(jPanel16, 16, false, false); - addAvatar(jPanel17, 17, false, false); - addAvatar(jPanel18, 18, false, false); - addAvatar(jPanel19, 19, false, false); - addAvatar(jPanel20, 20, false, false); - addAvatar(jPanel21, 21, false, false); - addAvatar(jPanel22, 22, false, false); - addAvatar(jPanel23, 23, false, false); - addAvatar(jPanel24, 24, false, false); - addAvatar(jPanel25, 25, false, false); - addAvatar(jPanel26, 26, false, false); - addAvatar(jPanel27, 27, false, false); - addAvatar(jPanel28, 28, false, false); - addAvatar(jPanel29, 29, false, false); - addAvatar(jPanel30, 30, false, false); - addAvatar(jPanel31, 31, false, false); - addAvatar(jPanel32, 32, false, false); + private static void save(Preferences prefs, KeyBindButton button) { + int code = button.getKeyCode(); + String key = button.getKey(); + prefs.putInt(key, code); + updateCache(key, Integer.toString(code)); + } - } catch (Exception e) { - logger.error(e, e); - } - } + public void reset() { + tabsPanel.setSelectedIndex(0); + } - public void setSelectedId(int id) { - if (id >= MIN_AVATAR_ID && id <= MAX_AVATAR_ID) { - for (JPanel panel : PANELS.values()) { - panel.setBorder(BLACK_BORDER); - } - PreferencesDialog.selectedAvatarId = id; - PANELS.get(PreferencesDialog.selectedAvatarId).setBorder(GREEN_BORDER); - } - } + public static int getCachedValue(String key, int def) { + String stringValue = getCachedValue(key, String.valueOf(def)); + int value; + try { + value = Integer.parseInt(stringValue); + } catch (NumberFormatException e) { + // It's OK to ignore "e" here because returning a default value is the documented behaviour on invalid input. + value = def; + } + return value; + } - private void addAvatar(JPanel jPanel, final int id, boolean selected, boolean locked) { - String path = "/avatars/" + String.valueOf(id) + ".jpg"; - PANELS.put(id, jPanel); - Image image = ImageHelper.getImageFromResources(path); + public static String getCachedValue(String key, String def) { + if (CACHE.containsKey(key)) { + return CACHE.get(key); + } else { + Preferences prefs = MageFrame.getPreferences(); + String value = prefs.get(key, def); + if (value == null) { + return null; + } + CACHE.put(key, value); + return value; + } + } - Rectangle r = new Rectangle(jPanel.getWidth() - 5, jPanel.getHeight() - 5); - BufferedImage bufferedImage; - if (!locked) { - bufferedImage = BufferedImageBuilder.bufferImage(image, BufferedImage.TYPE_INT_ARGB); - } else { - bufferedImage = BufferedImageBuilder.bufferImage(image, BufferedImage.TYPE_INT_ARGB, new Color(150, 150, 150, 170)); - } - BufferedImage resized = ImageHelper.getResizedImage(bufferedImage, r); - final JLabel jLabel = new JLabel(); - jLabel.setIcon(new ImageIcon(resized)); - if (selected) { - jPanel.setBorder(GREEN_BORDER); - } else { - jPanel.setBorder(BLACK_BORDER); - } - jPanel.setLayout(new BorderLayout()); - jPanel.add(jLabel); - if (!locked) { - jLabel.addMouseListener(new MouseAdapter() { - @Override - public void mousePressed(MouseEvent e) { - if (selectedAvatarId != id) { - setSelectedId(id); - SessionHandler.updatePreferencesForServer(getUserData()); - } - } - }); - } - } + private static int getDefaultControlKey(String key) { + switch (key) { + case KEY_CONTROL_CONFIRM: + return KeyEvent.VK_F2; + case KEY_CONTROL_CANCEL_SKIP: + return KeyEvent.VK_F3; + case KEY_CONTROL_NEXT_TURN: + return KeyEvent.VK_F4; + case KEY_CONTROL_END_STEP: + return KeyEvent.VK_F5; + case KEY_CONTROL_SKIP_STEP: + return KeyEvent.VK_F6; + case KEY_CONTROL_MAIN_STEP: + return KeyEvent.VK_F7; + case KEY_CONTROL_YOUR_TURN: + return KeyEvent.VK_F9; + case KEY_CONTROL_SKIP_STACK: + return KeyEvent.VK_F10; + case KEY_CONTROL_PRIOR_END: + return KeyEvent.VK_F11; + default: + return 0; + } + } - public static UserData getUserData() { - if (selectedAvatarId == 0) { - getSelectedAvatar(); - } - return new UserData(UserGroup.PLAYER, - PreferencesDialog.selectedAvatarId, - PreferencesDialog.getCachedValue(PreferencesDialog.KEY_SHOW_ABILITY_PICKER_FORCED, "true").equals("true"), - PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS, "true").equals("true"), - PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_CONFIRM_EMPTY_MANA_POOL, "true").equals("true"), - getUserSkipPrioritySteps(), - MageFrame.getPreferences().get(KEY_CONNECT_FLAG, "world"), - PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_ASK_MOVE_TO_GRAVE_ORDER, "false").equals("true"), - PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_MANA_AUTOPAYMENT, "true").equals("true"), - PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE, "true").equals("true"), - PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PASS_PRIORITY_CAST, "true").equals("true"), - PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PASS_PRIORITY_ACTIVATION, "true").equals("true"), - PreferencesDialog.getCachedValue(PreferencesDialog.KEY_AUTO_ORDER_TRIGGER, "true").equals("true"), - PreferencesDialog.getCachedValue(PreferencesDialog.KEY_USE_FIRST_MANA_ABILITY, "false").equals("true") - ); - } + public static KeyStroke getCachedKeystroke(String key) { + int code = getCachedValue(key, getDefaultControlKey(key)); + return KeyStroke.getKeyStroke(code, 0); + } + + public static String getCachedKeyText(String key) { + int code = getCachedValue(key, getDefaultControlKey(key)); + return KeyEvent.getKeyText(code); + } + + private static void updateCache(String key, String value) { + CACHE.put(key, value); + } + + public static void saveValue(String key, String value) { + Preferences prefs = MageFrame.getPreferences(); + prefs.put(key, value); + try { + prefs.flush(); + } catch (BackingStoreException ex) { + ex.printStackTrace(); + JOptionPane.showMessageDialog(null, "Error: couldn't save preferences. Please try once again."); + } + updateCache(key, value); + } + + private void addAvatars() { + try { + addAvatar(jPanel10, 10, true, false); + addAvatar(jPanel11, 11, false, false); + addAvatar(jPanel12, 12, false, false); + addAvatar(jPanel13, 13, false, false); + addAvatar(jPanel14, 14, false, false); + addAvatar(jPanel15, 15, false, false); + addAvatar(jPanel16, 16, false, false); + addAvatar(jPanel17, 17, false, false); + addAvatar(jPanel18, 18, false, false); + addAvatar(jPanel19, 19, false, false); + addAvatar(jPanel20, 20, false, false); + addAvatar(jPanel21, 21, false, false); + addAvatar(jPanel22, 22, false, false); + addAvatar(jPanel23, 23, false, false); + addAvatar(jPanel24, 24, false, false); + addAvatar(jPanel25, 25, false, false); + addAvatar(jPanel26, 26, false, false); + addAvatar(jPanel27, 27, false, false); + addAvatar(jPanel28, 28, false, false); + addAvatar(jPanel29, 29, false, false); + addAvatar(jPanel30, 30, false, false); + addAvatar(jPanel31, 31, false, false); + addAvatar(jPanel32, 32, false, false); + + } catch (Exception e) { + logger.error(e, e); + } + } + + public void setSelectedId(int id) { + if (id >= MIN_AVATAR_ID && id <= MAX_AVATAR_ID) { + for (JPanel panel : PANELS.values()) { + panel.setBorder(BLACK_BORDER); + } + PreferencesDialog.selectedAvatarId = id; + PANELS.get(PreferencesDialog.selectedAvatarId).setBorder(GREEN_BORDER); + } + } + + private void addAvatar(JPanel jPanel, final int id, boolean selected, boolean locked) { + String path = "/avatars/" + String.valueOf(id) + ".jpg"; + PANELS.put(id, jPanel); + Image image = ImageHelper.getImageFromResources(path); + + Rectangle r = new Rectangle(jPanel.getWidth() - 5, jPanel.getHeight() - 5); + BufferedImage bufferedImage; + if (!locked) { + bufferedImage = BufferedImageBuilder.bufferImage(image, BufferedImage.TYPE_INT_ARGB); + } else { + bufferedImage = BufferedImageBuilder.bufferImage(image, BufferedImage.TYPE_INT_ARGB, new Color(150, 150, 150, 170)); + } + BufferedImage resized = ImageHelper.getResizedImage(bufferedImage, r); + final JLabel jLabel = new JLabel(); + jLabel.setIcon(new ImageIcon(resized)); + if (selected) { + jPanel.setBorder(GREEN_BORDER); + } else { + jPanel.setBorder(BLACK_BORDER); + } + jPanel.setLayout(new BorderLayout()); + jPanel.add(jLabel); + if (!locked) { + jLabel.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + if (selectedAvatarId != id) { + setSelectedId(id); + SessionHandler.updatePreferencesForServer(getUserData()); + } + } + }); + } + } + + public static UserData getUserData() { + if (selectedAvatarId == 0) { + getSelectedAvatar(); + } + return new UserData(UserGroup.PLAYER, + PreferencesDialog.selectedAvatarId, + PreferencesDialog.getCachedValue(PreferencesDialog.KEY_SHOW_ABILITY_PICKER_FORCED, "true").equals("true"), + PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS, "true").equals("true"), + PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_CONFIRM_EMPTY_MANA_POOL, "true").equals("true"), + getUserSkipPrioritySteps(), + MageFrame.getPreferences().get(KEY_CONNECT_FLAG, "world"), + PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_ASK_MOVE_TO_GRAVE_ORDER, "false").equals("true"), + PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_MANA_AUTOPAYMENT, "true").equals("true"), + PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE, "true").equals("true"), + PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PASS_PRIORITY_CAST, "true").equals("true"), + PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PASS_PRIORITY_ACTIVATION, "true").equals("true"), + PreferencesDialog.getCachedValue(PreferencesDialog.KEY_AUTO_ORDER_TRIGGER, "true").equals("true"), + PreferencesDialog.getCachedValue(PreferencesDialog.KEY_USE_FIRST_MANA_ABILITY, "false").equals("true") + ); + } + + public List getKeybindButtons() { + return Arrays.asList( + keyCancelSkip, + keyConfirm, + keyEndStep, + keyMainStep, + keyNextTurn, + keyPriorEnd, + keySkipStack, + keySkipStep, + keyYourTurn + ); + } // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JScrollPane avatarPane; @@ -3472,6 +3736,7 @@ public class PreferencesDialog extends javax.swing.JDialog { private javax.swing.JButton btnBrowseBackgroundImage; private javax.swing.JButton btnBrowseBattlefieldImage; private javax.swing.JButton btnBrowseImageLocation; + private javax.swing.JButton bttnResetControls; private javax.swing.JCheckBox cbAllowRequestToShowHandCards; private javax.swing.JCheckBox cbAskMoveToGraveOrder; private javax.swing.JCheckBox cbAutoOrderTrigger; @@ -3518,6 +3783,7 @@ public class PreferencesDialog extends javax.swing.JDialog { private javax.swing.JCheckBox checkBoxUpkeepOthers; private javax.swing.JCheckBox checkBoxUpkeepYou; private javax.swing.JPanel connection_servers; + private javax.swing.JLabel controlsDescriptionLabel; private javax.swing.JButton exitButton; private javax.swing.JLabel fontSizeLabel; private javax.swing.JPanel guiSizeBasic; @@ -3562,25 +3828,43 @@ public class PreferencesDialog extends javax.swing.JDialog { private javax.swing.JPanel jPanel31; private javax.swing.JPanel jPanel32; private javax.swing.JPanel jPanel33; + private mage.client.components.KeyBindButton keyCancelSkip; + private mage.client.components.KeyBindButton keyConfirm; + private mage.client.components.KeyBindButton keyEndStep; + private mage.client.components.KeyBindButton keyMainStep; + private mage.client.components.KeyBindButton keyNextTurn; + private mage.client.components.KeyBindButton keyPriorEnd; + private mage.client.components.KeyBindButton keySkipStack; + private mage.client.components.KeyBindButton keySkipStep; + private mage.client.components.KeyBindButton keyYourTurn; + private javax.swing.JLabel labelCancel; private javax.swing.JLabel labelCardSizeHand; private javax.swing.JLabel labelCardSizeMaxBattlefield; private javax.swing.JLabel labelCardSizeMinBattlefield; private javax.swing.JLabel labelCardSizeOtherZones; + private javax.swing.JLabel labelConfirm; private javax.swing.JLabel labelDialogFont; private javax.swing.JLabel labelEditorCardOffset; private javax.swing.JLabel labelEditorCardSize; + private javax.swing.JLabel labelEndStep; private javax.swing.JLabel labelEnlargedImageSize; private javax.swing.JLabel labelGameFeedback; + private javax.swing.JLabel labelMainStep; + private javax.swing.JLabel labelNextTurn; private javax.swing.JLabel labelNumberOfDownloadThreads; private javax.swing.JLabel labelPreferedImageLanguage; + private javax.swing.JLabel labelPriorEnd; + private javax.swing.JLabel labelSkipStep; private javax.swing.JLabel labelStackWidth; private javax.swing.JLabel labelTooltipSize; + private javax.swing.JLabel labelYourTurn; private javax.swing.JLabel lblProxyPassword; private javax.swing.JLabel lblProxyPort; private javax.swing.JLabel lblProxyServer; private javax.swing.JLabel lblProxyType; private javax.swing.JLabel lblProxyUserName; private javax.swing.JLabel lblURLServerList; + private javax.swing.JLabel lebelSkip; private javax.swing.JPanel main_card; private javax.swing.JPanel main_game; private javax.swing.JPanel main_gamelog; @@ -3612,6 +3896,7 @@ public class PreferencesDialog extends javax.swing.JDialog { private javax.swing.JPanel sounds_clips; private javax.swing.JPanel tabAvatars; private javax.swing.JPanel tabConnection; + private javax.swing.JPanel tabControls; private javax.swing.JPanel tabGuiSize; private javax.swing.JPanel tabImages; private javax.swing.JPanel tabMain; @@ -3631,9 +3916,9 @@ public class PreferencesDialog extends javax.swing.JDialog { private javax.swing.JTextField txtURLServerList; // End of variables declaration//GEN-END:variables - private static final PreferencesDialog dialog = new PreferencesDialog(new javax.swing.JFrame(), true); + private static final PreferencesDialog dialog = new PreferencesDialog(new javax.swing.JFrame(), true); - static { - dialog.setResizable(false); - } + static { + dialog.setResizable(false); + } } diff --git a/Mage.Client/src/main/java/mage/client/game/GamePanel.java b/Mage.Client/src/main/java/mage/client/game/GamePanel.java index 4508045ac9f..729ab26b029 100644 --- a/Mage.Client/src/main/java/mage/client/game/GamePanel.java +++ b/Mage.Client/src/main/java/mage/client/game/GamePanel.java @@ -90,6 +90,7 @@ import mage.client.cards.BigCard; import mage.client.chat.ChatPanelBasic; import mage.client.combat.CombatManager; import mage.client.components.HoverButton; +import mage.client.components.KeyboundButton; import mage.client.components.MageComponents; import mage.client.components.ext.dlg.DialogManager; import mage.client.components.layout.RelativeLayout; @@ -99,9 +100,7 @@ import mage.client.dialog.PickChoiceDialog; import mage.client.dialog.PickNumberDialog; import mage.client.dialog.PickPileDialog; import mage.client.dialog.PreferencesDialog; -import static mage.client.dialog.PreferencesDialog.KEY_GAME_MANA_AUTOPAYMENT; -import static mage.client.dialog.PreferencesDialog.KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE; -import static mage.client.dialog.PreferencesDialog.KEY_USE_FIRST_MANA_ABILITY; +import static mage.client.dialog.PreferencesDialog.*; import mage.client.dialog.ShowCardsDialog; import mage.client.game.FeedbackPanel.FeedbackMode; import mage.client.plugins.adapters.MageActionCallback; @@ -146,2353 +145,2360 @@ import org.mage.plugins.card.utils.impl.ImageManagerImpl; */ public final class GamePanel extends javax.swing.JPanel { - private static final Logger logger = Logger.getLogger(GamePanel.class); - private static final String YOUR_HAND = "Your hand"; - private static final int X_PHASE_WIDTH = 55; - private static final int STACK_MIN_CARDS_OFFSET_Y = 7; // TODO: Size bui GUISize value - - private static final String CMD_AUTO_ORDER_FIRST = "cmdAutoOrderFirst"; - private static final String CMD_AUTO_ORDER_LAST = "cmdAutoOrderLast"; - private static final String CMD_AUTO_ORDER_NAME_FIRST = "cmdAutoOrderNameFirst"; - private static final String CMD_AUTO_ORDER_NAME_LAST = "cmdAutoOrderNameLast"; - private static final String CMD_AUTO_ORDER_RESET_ALL = "cmdAutoOrderResetAll"; - - private final Map players = new HashMap<>(); - private final Map playersWhoLeft = new HashMap<>(); - - // non modal frames - private final Map exiles = new HashMap<>(); - private final Map revealed = new HashMap<>(); - private final Map lookedAt = new HashMap<>(); - private final Map graveyardWindows = new HashMap<>(); - private final Map graveyards = new HashMap<>(); - - private final ArrayList pickTarget = new ArrayList<>(); - private UUID gameId; - private UUID playerId; // playerId of the player - GamePane gamePane; - private ReplayTask replayTask; - private final PickNumberDialog pickNumber; - private JLayeredPane jLayeredPane; - private String chosenHandKey = "You"; - private boolean smallMode = false; - private boolean initialized = false; - - private boolean menuNameSet = false; - private boolean handCardsOfOpponentAvailable = false; - - private Map loadedCards = new HashMap<>(); - - private int storedHeight; - private Map hoverButtons; - - private MageDialogState choiceWindowState; - - private boolean initComponents; - - private Timer resizeTimer; - - private enum PopUpMenuType { - - TRIGGER_ORDER - } - // CardView popupMenu was invoked last - private CardView cardViewPopupMenu; - - // popup menu for triggered abilities order - private JPopupMenu popupMenuTriggerOrder; - - public GamePanel() { - initComponents = true; - initComponents(); - - pickNumber = new PickNumberDialog(); - MageFrame.getDesktop().add(pickNumber, JLayeredPane.MODAL_LAYER); - - this.feedbackPanel.setConnectedChatPanel(this.userChatPanel); - - this.stackObjects.setMinOffsetY(STACK_MIN_CARDS_OFFSET_Y); - - // Override layout (I can't edit generated code) - this.setLayout(new BorderLayout()); - final JLayeredPane jLayeredBackgroundPane = new JLayeredPane(); - jLayeredBackgroundPane.setSize(1024, 768); - this.add(jLayeredBackgroundPane); - jLayeredBackgroundPane.add(jSplitPane0, JLayeredPane.DEFAULT_LAYER); - - Map myUi = getUIComponents(jLayeredBackgroundPane); - Plugins.getInstance().updateGamePanel(myUi); - - // Enlarge jlayeredpane on resize of game panel - addComponentListener(new ComponentAdapter() { - @Override - public void componentResized(ComponentEvent e) { - int width = ((JComponent) e.getSource()).getWidth(); - int height = ((JComponent) e.getSource()).getHeight(); - jLayeredBackgroundPane.setSize(width, height); - jSplitPane0.setSize(width, height); - - if (height < storedHeight) { - pnlBattlefield.setSize(0, 200); - } - storedHeight = height; - - sizeToScreen(); - - if (!initialized) { - String state = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_BIG_CARD_TOGGLED, null); - if (state != null && state.equals("down")) { - jSplitPane0.setDividerLocation(1.0); - } - initialized = true; - } - - } - }); - // Resize the width of the stack area if the size of the play area is changed - ComponentAdapter componentAdapterPlayField = new ComponentAdapter() { - @Override - public void componentResized(ComponentEvent e) { - if (!initComponents) { - if (resizeTimer.isRunning()) { - resizeTimer.restart(); - } else { - resizeTimer.start(); - } - } - } - }; - - resizeTimer = new Timer(1000, new ActionListener() { - @Override - public void actionPerformed(ActionEvent evt) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - resizeTimer.stop(); - setGUISize(); - feedbackPanel.changeGUISize(); - - } - }); - } - }); - - pnlHelperHandButtonsStackArea.addComponentListener(componentAdapterPlayField); - initComponents = false; - } - - private Map getUIComponents(JLayeredPane jLayeredPane) { - Map components = new HashMap<>(); - - components.put("jSplitPane1", jSplitPane1); - components.put("pnlBattlefield", pnlBattlefield); - components.put("pnlHelperHandButtonsStackArea", pnlHelperHandButtonsStackArea); - components.put("hand", handContainer); - components.put("gameChatPanel", gameChatPanel); - components.put("userChatPanel", userChatPanel); - components.put("jLayeredPane", jLayeredPane); - components.put("gamePanel", this); - - return components; - } - - public void cleanUp() { - MageFrame.removeGame(gameId); - saveDividerLocations(); - this.gameChatPanel.disconnect(); - this.userChatPanel.disconnect(); - - this.removeListener(); - - this.handContainer.cleanUp(); - this.stackObjects.cleanUp(); - for (Map.Entry playAreaPanelEntry : players.entrySet()) { - playAreaPanelEntry.getValue().CleanUp(); - } - this.players.clear(); - this.playersWhoLeft.clear(); - - jLayeredPane.remove(abilityPicker); - this.abilityPicker.cleanUp(); - - jLayeredPane.remove(DialogManager.getManager(gameId)); - DialogManager.removeGame(gameId); - - if (pickNumber != null) { - pickNumber.removeDialog(); - } - for (CardInfoWindowDialog exileDialog : exiles.values()) { - exileDialog.cleanUp(); - exileDialog.removeDialog(); - } - for (CardInfoWindowDialog graveyardDialog : graveyardWindows.values()) { - graveyardDialog.cleanUp(); - graveyardDialog.removeDialog(); - } - for (CardInfoWindowDialog revealDialog : revealed.values()) { - revealDialog.cleanUp(); - revealDialog.removeDialog(); - } - for (CardInfoWindowDialog lookedAtDialog : lookedAt.values()) { - lookedAtDialog.cleanUp(); - lookedAtDialog.removeDialog(); - } - for (ShowCardsDialog pickTargetDialog : pickTarget) { - pickTargetDialog.cleanUp(); - pickTargetDialog.removeDialog(); - } - Plugins.getInstance().getActionCallback().hideTooltipPopup(); - try { - Component popupContainer = MageFrame.getUI().getComponent(MageComponents.POPUP_CONTAINER); - popupContainer.setVisible(false); - } catch (InterruptedException ex) { - logger.fatal("popupContainer error:", ex); - } - jPanel2.remove(bigCard); - this.bigCard = null; - } - - public void changeGUISize() { - initComponents = true; - setGUISize(); - stackObjects.changeGUISize(); - feedbackPanel.changeGUISize(); - handContainer.changeGUISize(); - for (PlayAreaPanel playAreaPanel : players.values()) { - playAreaPanel.changeGUISize(); - } - - for (CardInfoWindowDialog cardInfoWindowDialog : exiles.values()) { - cardInfoWindowDialog.changeGUISize(); - } - for (CardInfoWindowDialog cardInfoWindowDialog : revealed.values()) { - cardInfoWindowDialog.changeGUISize(); - } - for (CardInfoWindowDialog cardInfoWindowDialog : lookedAt.values()) { - cardInfoWindowDialog.changeGUISize(); - } - for (CardInfoWindowDialog cardInfoWindowDialog : graveyardWindows.values()) { - cardInfoWindowDialog.changeGUISize(); - } - for (ShowCardsDialog showCardsDialog : pickTarget) { - showCardsDialog.changeGUISize(); - } - - this.revalidate(); - this.repaint(); - initComponents = false; - } - - private void setGUISize() { - jSplitPane0.setDividerSize(GUISizeHelper.dividerBarSize); - jSplitPane1.setDividerSize(GUISizeHelper.dividerBarSize); - jSplitPane2.setDividerSize(GUISizeHelper.dividerBarSize); - stackObjects.setCardDimension(GUISizeHelper.handCardDimension); - - txtSpellsCast.setFont(new Font(GUISizeHelper.gameDialogAreaFont.getFontName(), Font.BOLD, GUISizeHelper.gameDialogAreaFont.getSize())); - txtHoldPriority.setFont(new Font(GUISizeHelper.gameDialogAreaFont.getFontName(), Font.BOLD, GUISizeHelper.gameDialogAreaFont.getSize())); - GUISizeHelper.changePopupMenuFont(popupMenuTriggerOrder); - - int newStackWidth = pnlHelperHandButtonsStackArea.getWidth() * GUISizeHelper.stackWidth / 100; - if (newStackWidth < 410) { - newStackWidth = 410; - } - Dimension newDimension = new Dimension(pnlHelperHandButtonsStackArea.getWidth() - newStackWidth, GUISizeHelper.handCardDimension.height + GUISizeHelper.scrollBarSize); - handContainer.setPreferredSize(newDimension); - handContainer.setMaximumSize(newDimension); - - newDimension = new Dimension(newStackWidth, STACK_MIN_CARDS_OFFSET_Y + GUISizeHelper.handCardDimension.height + GUISizeHelper.scrollBarSize); - stackObjects.setPreferredSize(newDimension); - stackObjects.setMinimumSize(newDimension); - stackObjects.setMaximumSize(newDimension); - - newDimension = new Dimension(newStackWidth, (int) pnlShortCuts.getPreferredSize().getHeight()); - pnlShortCuts.setPreferredSize(newDimension); - pnlShortCuts.setMinimumSize(newDimension); - pnlShortCuts.setMaximumSize(newDimension); - } - - private void saveDividerLocations() { - // save panel sizes and divider locations. - Rectangle rec = MageFrame.getDesktop().getBounds(); - String sb = Double.toString(rec.getWidth()) + "x" + Double.toString(rec.getHeight()); - PreferencesDialog.saveValue(PreferencesDialog.KEY_MAGE_PANEL_LAST_SIZE, sb); - PreferencesDialog.saveValue(PreferencesDialog.KEY_GAMEPANEL_DIVIDER_LOCATION_0, Integer.toString(this.jSplitPane0.getDividerLocation())); - PreferencesDialog.saveValue(PreferencesDialog.KEY_GAMEPANEL_DIVIDER_LOCATION_1, Integer.toString(this.jSplitPane1.getDividerLocation())); - PreferencesDialog.saveValue(PreferencesDialog.KEY_GAMEPANEL_DIVIDER_LOCATION_2, Integer.toString(this.jSplitPane2.getDividerLocation())); - } - - private void restoreDividerLocations() { - Rectangle rec = MageFrame.getDesktop().getBounds(); - if (rec != null) { - String size = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_MAGE_PANEL_LAST_SIZE, null); - String sb = Double.toString(rec.getWidth()) + "x" + Double.toString(rec.getHeight()); - // use divider positions only if screen size is the same as it was the time the settings were saved - if (size != null && size.equals(sb)) { - - String location = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAMEPANEL_DIVIDER_LOCATION_0, null); - if (location != null && jSplitPane0 != null) { - jSplitPane0.setDividerLocation(Integer.parseInt(location)); - } - location = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAMEPANEL_DIVIDER_LOCATION_1, null); - if (location != null && jSplitPane1 != null) { - jSplitPane1.setDividerLocation(Integer.parseInt(location)); - } - location = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAMEPANEL_DIVIDER_LOCATION_2, null); - if (location != null && jSplitPane2 != null) { - jSplitPane2.setDividerLocation(Integer.parseInt(location)); - } - } - } - } - - private void sizeToScreen() { - Rectangle rect = this.getBounds(); - - if (rect.height < 720) { - if (!smallMode) { - smallMode = true; - Dimension bbDimension = new Dimension(128, 184); - bigCard.setMaximumSize(bbDimension); - bigCard.setMinimumSize(bbDimension); - bigCard.setPreferredSize(bbDimension); - pnlShortCuts.revalidate(); - pnlShortCuts.repaint(); - for (PlayAreaPanel p : players.values()) { - p.sizePlayer(smallMode); - } - } - } else if (smallMode) { - smallMode = false; - Dimension bbDimension = new Dimension(256, 367); - bigCard.setMaximumSize(bbDimension); - bigCard.setMinimumSize(bbDimension); - bigCard.setPreferredSize(bbDimension); - pnlShortCuts.revalidate(); - pnlShortCuts.repaint(); - for (PlayAreaPanel p : players.values()) { - p.sizePlayer(smallMode); - } - } - - ArrowBuilder.getBuilder().setSize(rect.width, rect.height); - - DialogManager.getManager(gameId).setScreenWidth(rect.width); - DialogManager.getManager(gameId).setScreenHeight(rect.height); - DialogManager.getManager(gameId).setBounds(0, 0, rect.width, rect.height); - } - - public synchronized void showGame(UUID gameId, UUID playerId, GamePane gamePane) { - this.gameId = gameId; - this.gamePane = gamePane; - this.playerId = playerId; - MageFrame.addGame(gameId, this); - this.feedbackPanel.init(gameId); - this.feedbackPanel.clear(); - this.abilityPicker.init(gameId); - - this.btnConcede.setVisible(true); - this.btnStopWatching.setVisible(false); - this.btnSwitchHands.setVisible(false); - this.btnCancelSkip.setVisible(true); - - this.btnSkipToNextTurn.setVisible(true); - this.btnSkipToEndTurn.setVisible(true); - this.btnSkipToNextMain.setVisible(true); - this.btnSkipStack.setVisible(true); - this.btnSkipToYourTurn.setVisible(true); - this.btnSkipToEndStepBeforeYourTurn.setVisible(true); - - this.pnlReplay.setVisible(false); - - this.gameChatPanel.clear(); - this.gameChatPanel.connect(SessionHandler.getGameChatId(gameId)); - if (!SessionHandler.joinGame(gameId)) { - removeGame(); - } else { - // play start sound - AudioManager.playYourGameStarted(); - } - } - - public synchronized void watchGame(UUID gameId, GamePane gamePane) { - this.gameId = gameId; - this.gamePane = gamePane; - this.playerId = null; - MageFrame.addGame(gameId, this); - this.feedbackPanel.init(gameId); - this.feedbackPanel.clear(); - - this.btnConcede.setVisible(false); - this.btnStopWatching.setVisible(true); - this.btnSwitchHands.setVisible(false); - this.chosenHandKey = ""; - this.btnCancelSkip.setVisible(false); - - this.btnSkipToNextTurn.setVisible(false); - this.btnSkipToEndTurn.setVisible(false); - this.btnSkipToNextMain.setVisible(false); - this.btnSkipStack.setVisible(false); - this.btnSkipToYourTurn.setVisible(false); - this.btnSkipToEndStepBeforeYourTurn.setVisible(false); - - this.pnlReplay.setVisible(false); - this.gameChatPanel.clear(); - this.gameChatPanel.connect(SessionHandler.getGameChatId(gameId)); - if (!SessionHandler.watchGame(gameId)) { - removeGame(); - } - for (PlayAreaPanel panel : getPlayers().values()) { - panel.setPlayingMode(false); - } - } - - public synchronized void replayGame(UUID gameId) { - this.gameId = gameId; - this.playerId = null; - MageFrame.addGame(gameId, this); - this.feedbackPanel.init(gameId); - this.feedbackPanel.clear(); - this.btnConcede.setVisible(false); - this.btnSkipToNextTurn.setVisible(false); - this.btnSwitchHands.setVisible(false); - this.btnStopWatching.setVisible(false); - this.pnlReplay.setVisible(true); - this.gameChatPanel.clear(); - if (!SessionHandler.startReplay(gameId)) { - removeGame(); - } - for (PlayAreaPanel panel : getPlayers().values()) { - panel.setPlayingMode(false); - } - } - - /** - * Closes the game and it's resources - */ - public void removeGame() { - Component c = this.getParent(); - while (c != null && !(c instanceof GamePane)) { - c = c.getParent(); - } - if (c != null) { - ((GamePane) c).removeGame(); - } - } - - public synchronized void init(GameView game) { - addPlayers(game); - // default menu states - setMenuStates( - PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT, "true").equals("true"), - PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE, "true").equals("true"), - PreferencesDialog.getCachedValue(KEY_USE_FIRST_MANA_ABILITY, "false").equals("true"), - holdingPriority - ); - - updateGame(game); - } - - private void addPlayers(GameView game) { - this.players.clear(); - this.playersWhoLeft.clear(); - this.pnlBattlefield.removeAll(); - //arrange players in a circle with the session player at the bottom left - int numSeats = game.getPlayers().size(); - int numColumns = (numSeats + 1) / 2; - boolean oddNumber = (numColumns > 1 && numSeats % 2 == 1); - int col = 0; - int row = 1; - int playerSeat = 0; - if (playerId != null) { - for (PlayerView player : game.getPlayers()) { - if (playerId.equals(player.getPlayerId())) { - break; - } - playerSeat++; - } - } - PlayerView player = game.getPlayers().get(playerSeat); - PlayAreaPanel playAreaPanel = new PlayAreaPanel(player, bigCard, gameId, game.getPriorityTime(), this, - new PlayAreaPanelOptions(game.isPlayer(), game.isPlayer(), game.isRollbackTurnsAllowed(), row == 0)); - players.put(player.getPlayerId(), playAreaPanel); - playersWhoLeft.put(player.getPlayerId(), false); - GridBagConstraints c = new GridBagConstraints(); - c.fill = GridBagConstraints.BOTH; - c.weightx = 0.5; - c.weighty = 0.5; - if (oddNumber) { - c.gridwidth = 2; - } - c.gridx = col; - c.gridy = 0; - - // Top panel (row=0) - JPanel topPanel = new JPanel(); - topPanel.setOpaque(false); - - // Bottom panel (row=1) - JPanel bottomPanel = new JPanel(); - bottomPanel.setOpaque(false); - topPanel.setLayout(new GridBagLayout()); - bottomPanel.setLayout(new GridBagLayout()); - - bottomPanel.add(playAreaPanel, c); - playAreaPanel.setVisible(true); - if (oddNumber) { - col++; - } - int playerNum = playerSeat + 1; - if (playerNum >= numSeats) { - playerNum = 0; - } - while (true) { - if (row == 1) { - col++; - } else { - col--; - } - if (col >= numColumns) { - row = 0; - col = numColumns - 1; - } - player = game.getPlayers().get(playerNum); - PlayAreaPanel playerPanel = new PlayAreaPanel(player, bigCard, gameId, game.getPriorityTime(), this, - new PlayAreaPanelOptions(game.isPlayer(), false, game.isRollbackTurnsAllowed(), row == 0)); - players.put(player.getPlayerId(), playerPanel); - playersWhoLeft.put(player.getPlayerId(), false); - c = new GridBagConstraints(); - c.fill = GridBagConstraints.BOTH; - c.weightx = 0.5; - c.weighty = 0.5; - c.gridx = col; - c.gridy = 0; - - if (row == 0) { - topPanel.add(playerPanel, c); - } else { - bottomPanel.add(playerPanel, c); - } - - playerPanel.setVisible(true); - playerNum++; - if (playerNum >= numSeats) { - playerNum = 0; - } - if (playerNum == playerSeat) { - break; - } - } - for (PlayAreaPanel p : players.values()) { - p.sizePlayer(smallMode); - } - - GridBagConstraints panelC = new GridBagConstraints(); - panelC.fill = GridBagConstraints.BOTH; - panelC.weightx = 0.5; - panelC.weighty = 0.5; - panelC.gridwidth = 1; - panelC.gridy = 0; - this.pnlBattlefield.add(topPanel, panelC); - panelC.gridy = 1; - this.pnlBattlefield.add(bottomPanel, panelC); - } - - public synchronized void updateGame(GameView game) { - updateGame(game, null); - } - - public synchronized void updateGame(GameView game, Map options) { - if (playerId == null && game.getWatchedHands() == null) { - this.handContainer.setVisible(false); - } else { - this.handContainer.setVisible(true); - handCards.clear(); - if (game.getWatchedHands() != null) { - for (Map.Entry hand : game.getWatchedHands().entrySet()) { - handCards.put(hand.getKey(), CardsViewUtil.convertSimple(hand.getValue(), loadedCards)); - } - } - if (playerId != null) { - handCards.put(YOUR_HAND, game.getHand()); - // Mark playable - if (game.getCanPlayInHand() != null) { - for (CardView card : handCards.get(YOUR_HAND).values()) { - if (game.getCanPlayInHand().contains(card.getId())) { - card.setPlayable(true); - } - } - } - // Get opponents hand cards if available (only possible for players) - if (game.getOpponentHands() != null) { - for (Map.Entry hand : game.getOpponentHands().entrySet()) { - handCards.put(hand.getKey(), CardsViewUtil.convertSimple(hand.getValue(), loadedCards)); - } - } - if (!handCards.containsKey(chosenHandKey)) { - chosenHandKey = YOUR_HAND; - } - } else if (chosenHandKey.isEmpty() && handCards.size() > 0) { - chosenHandKey = handCards.keySet().iterator().next(); - } - if (chosenHandKey != null && handCards.containsKey(chosenHandKey)) { - handContainer.loadCards(handCards.get(chosenHandKey), bigCard, gameId); - } - - hideAll(); - - if (playerId != null) { - // set visible only if we have any other hand visible than ours - btnSwitchHands.setVisible(handCards.size() > 1); - boolean change = (handCardsOfOpponentAvailable != (game.getOpponentHands() != null)); - if (change) { - handCardsOfOpponentAvailable = !handCardsOfOpponentAvailable; - if (handCardsOfOpponentAvailable) { - JOptionPane.showMessageDialog(null, "You control other player's turn. \nUse \"Switch Hand\" button to switch between cards in different hands."); - } else { - JOptionPane.showMessageDialog(null, "You lost control on other player's turn."); - } - } - } else { - btnSwitchHands.setVisible(!handCards.isEmpty()); - } - } - - if (game.getPhase() != null) { - this.txtPhase.setText(game.getPhase().toString()); - } else { - this.txtPhase.setText(""); - } - - if (game.getStep() != null) { - updatePhases(game.getStep()); - this.txtStep.setText(game.getStep().toString()); - } else { - logger.debug("Step is empty"); - this.txtStep.setText(""); - } - if (game.getSpellsCastCurrentTurn() > 0 && PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_SHOW_STORM_COUNTER, "true").equals("true")) { - this.txtSpellsCast.setVisible(true); - this.txtSpellsCast.setText(" " + Integer.toString(game.getSpellsCastCurrentTurn()) + " "); - } else { - this.txtSpellsCast.setVisible(false); - } - - this.txtActivePlayer.setText(game.getActivePlayerName()); - this.txtPriority.setText(game.getPriorityPlayerName()); - this.txtTurn.setText(Integer.toString(game.getTurn())); - - List possibleAttackers = new ArrayList<>(); - if (options != null && options.containsKey(Constants.Option.POSSIBLE_ATTACKERS)) { - if (options.get(Constants.Option.POSSIBLE_ATTACKERS) instanceof List) { - possibleAttackers.addAll((List) options.get(Constants.Option.POSSIBLE_ATTACKERS)); - } - } - - for (PlayerView player : game.getPlayers()) { - if (players.containsKey(player.getPlayerId())) { - if (!possibleAttackers.isEmpty()) { - for (UUID permanentId : possibleAttackers) { - if (player.getBattlefield().containsKey(permanentId)) { - player.getBattlefield().get(permanentId).setCanAttack(true); - } - } - } - players.get(player.getPlayerId()).update(player); - if (player.getPlayerId().equals(playerId)) { - updateSkipButtons(player.isPassedTurn(), player.isPassedUntilEndOfTurn(), player.isPassedUntilNextMain(), player.isPassedAllTurns(), player.isPassedUntilStackResolved(), - player.isPassedUntilEndStepBeforeMyTurn()); - } - // update open or remove closed graveyard windows - graveyards.put(player.getName(), player.getGraveyard()); - if (graveyardWindows.containsKey(player.getName())) { - CardInfoWindowDialog cardInfoWindowDialog = graveyardWindows.get(player.getName()); - if (cardInfoWindowDialog.isClosed()) { - graveyardWindows.remove(player.getName()); - } else { - cardInfoWindowDialog.loadCards(player.getGraveyard(), bigCard, gameId, false); - } - } - // show top card window - if (player.getTopCard() != null) { - CardsView cardsView = new CardsView(); - cardsView.put(player.getTopCard().getId(), player.getTopCard()); - handleGameInfoWindow(revealed, ShowType.REVEAL_TOP_LIBRARY, player.getName() + "'s top library card", cardsView); - } - } else { - logger.warn("Couldn't find player."); - logger.warn(" uuid:" + player.getPlayerId()); - logger.warn(" players:"); - for (PlayAreaPanel p : players.values()) { - logger.warn("" + p); - } - } - } - if (!menuNameSet) { - StringBuilder sb = new StringBuilder(); - if (playerId == null) { - sb.append("Watching: "); - } else { - sb.append("Playing: "); - } - boolean first = true; - for (PlayerView player : game.getPlayers()) { - if (first) { - first = false; - } else { - sb.append(" - "); - } - sb.append(player.getName()); - } - menuNameSet = true; - gamePane.setTitle(sb.toString()); - } - - GameManager.getInstance().setStackSize(game.getStack().size()); - displayStack(game, bigCard, feedbackPanel, gameId); - - for (ExileView exile : game.getExile()) { - if (!exiles.containsKey(exile.getId())) { - CardInfoWindowDialog newExile = new CardInfoWindowDialog(ShowType.EXILE, exile.getName()); - exiles.put(exile.getId(), newExile); - MageFrame.getDesktop().add(newExile, JLayeredPane.MODAL_LAYER); - newExile.show(); - } - exiles.get(exile.getId()).loadCards(exile, bigCard, gameId); - } - - showRevealed(game); - showLookedAt(game); - if (game.getCombat().size() > 0) { - CombatManager.getInstance().showCombat(game.getCombat(), gameId); - } else { - CombatManager.getInstance().hideCombat(gameId); - } - - for (PlayerView player : game.getPlayers()) { - if (player.hasLeft() && !playersWhoLeft.get(player.getPlayerId())) { - PlayAreaPanel playerLeftPanel = players.get(player.getPlayerId()); - playersWhoLeft.put(player.getPlayerId(), true); - - Container parent = playerLeftPanel.getParent(); - GridBagLayout layout = (GridBagLayout) parent.getLayout(); - - for (Component otherPanel : parent.getComponents()) { - - if (otherPanel instanceof PlayAreaPanel) { - GridBagConstraints gbc = layout.getConstraints(otherPanel); - if (gbc.weightx > 0.1) { - gbc.weightx = 0.99; - } - gbc.fill = GridBagConstraints.BOTH; - gbc.anchor = GridBagConstraints.WEST; - if (gbc.gridx > 0) { - gbc.anchor = GridBagConstraints.EAST; - } - if (otherPanel == playerLeftPanel) { - gbc.weightx = 0.01; - Dimension d = playerLeftPanel.getPreferredSize(); - d.width = 95; - otherPanel.setPreferredSize(d); - } - parent.remove(otherPanel); - parent.add(otherPanel, gbc); - } - } - - parent.validate(); - parent.repaint(); - } - } - - feedbackPanel.disableUndo(); - - this.revalidate(); - this.repaint(); - } - - static final int BORDER_SIZE = 2; - - private void updateSkipButtons(boolean turn, boolean endOfTurn, boolean nextMain, boolean allTurns, boolean stack, boolean endStepBeforeYourStep) { - if (turn) { //F4 - btnSkipToNextTurn.setBorder(new LineBorder(Color.orange, BORDER_SIZE)); - } else { - btnSkipToNextTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); - } - if (endOfTurn) { // F5 - btnSkipToEndTurn.setBorder(new LineBorder(Color.orange, BORDER_SIZE)); - } else { - btnSkipToEndTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); - } - if (nextMain) { // F7 - btnSkipToNextMain.setBorder(new LineBorder(Color.orange, BORDER_SIZE)); - } else { - btnSkipToNextMain.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); - } - if (stack) { // F8 - btnSkipStack.setBorder(new LineBorder(Color.orange, BORDER_SIZE)); - } else { - btnSkipStack.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); - } - if (allTurns) { // F9 - btnSkipToYourTurn.setBorder(new LineBorder(Color.orange, BORDER_SIZE)); - } else { - btnSkipToYourTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); - } - - if (endStepBeforeYourStep) { // F11 - btnSkipToEndStepBeforeYourTurn.setBorder(new LineBorder(Color.orange, BORDER_SIZE)); - } else { - btnSkipToEndStepBeforeYourTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); - } - - } - - /** - * Set the same state for menu selections to all player areas. - * - * @param manaPoolAutomatic - * @param manaPoolAutomaticRestricted - * @param useFirstManaAbility - */ - public void setMenuStates(boolean manaPoolAutomatic, boolean manaPoolAutomaticRestricted, boolean useFirstManaAbility, boolean holdPriority) { - for (PlayAreaPanel playAreaPanel : players.values()) { - playAreaPanel.setMenuStates(manaPoolAutomatic, manaPoolAutomaticRestricted, useFirstManaAbility, holdPriority); - } - } - - private void displayStack(GameView game, BigCard bigCard, FeedbackPanel feedbackPanel, UUID gameId) { - this.stackObjects.loadCards(game.getStack(), bigCard, gameId, true); - } - - /** - * Update phase buttons\labels. - */ - private void updatePhases(PhaseStep step) { - if (step == null) { - logger.warn("step is null"); - return; - } - if (currentStep != null) { - currentStep.setLocation(prevPoint); - } - switch (step) { - case UNTAP: - updateButton("Untap"); - break; - case UPKEEP: - updateButton("Upkeep"); - break; - case DRAW: - updateButton("Draw"); - break; - case PRECOMBAT_MAIN: - updateButton("Main1"); - break; - case BEGIN_COMBAT: - updateButton("Combat_Start"); - break; - case DECLARE_ATTACKERS: - updateButton("Combat_Attack"); - break; - case DECLARE_BLOCKERS: - updateButton("Combat_Block"); - break; - case FIRST_COMBAT_DAMAGE: - case COMBAT_DAMAGE: - updateButton("Combat_Damage"); - break; - case END_COMBAT: - updateButton("Combat_End"); - break; - case POSTCOMBAT_MAIN: - updateButton("Main2"); - break; - case END_TURN: - updateButton("Cleanup"); - break; - } - } - - private void updateButton(String name) { - if (hoverButtons.containsKey(name)) { - currentStep = hoverButtons.get(name); - prevPoint = currentStep.getLocation(); - currentStep.setLocation(prevPoint.x - 15, prevPoint.y); - } - } - - // Called if the game frame is deactivated because the tabled the deck editor or other frames go to foreground - public void deactivated() { - // hide the non modal windows (because otherwise they are shown on top of the new active pane) - for (CardInfoWindowDialog exileDialog : exiles.values()) { - exileDialog.hideDialog(); - } - for (CardInfoWindowDialog graveyardDialog : graveyardWindows.values()) { - graveyardDialog.hideDialog(); - } - for (CardInfoWindowDialog revealDialog : revealed.values()) { - revealDialog.hideDialog(); - } - for (CardInfoWindowDialog lookedAtDialog : lookedAt.values()) { - lookedAtDialog.hideDialog(); - } - } - - // Called if the game frame comes to front again - public void activated() { - // hide the non modal windows (because otherwise they are shown on top of the new active pane) - for (CardInfoWindowDialog exileDialog : exiles.values()) { - exileDialog.show(); - } - for (CardInfoWindowDialog graveyardDialog : graveyardWindows.values()) { - graveyardDialog.show(); - } - for (CardInfoWindowDialog revealDialog : revealed.values()) { - revealDialog.show(); - } - for (CardInfoWindowDialog lookedAtDialog : lookedAt.values()) { - lookedAtDialog.show(); - } - } - - public void openGraveyardWindow(String playerName) { - if (graveyardWindows.containsKey(playerName)) { - CardInfoWindowDialog cardInfoWindowDialog = graveyardWindows.get(playerName); - if (cardInfoWindowDialog.isVisible()) { - cardInfoWindowDialog.hideDialog(); - } else { - cardInfoWindowDialog.show(); - } - return; - } - CardInfoWindowDialog newGraveyard = new CardInfoWindowDialog(ShowType.GRAVEYARD, playerName); - graveyardWindows.put(playerName, newGraveyard); - MageFrame.getDesktop().add(newGraveyard, JLayeredPane.MODAL_LAYER); - newGraveyard.loadCards(graveyards.get(playerName), bigCard, gameId, false); - } - - public void openTopLibraryWindow(String playerName) { - String title = playerName + "'s top library card"; - if (revealed.containsKey(title)) { - CardInfoWindowDialog cardInfoWindowDialog = revealed.get(title); - if (cardInfoWindowDialog.isVisible()) { - cardInfoWindowDialog.hideDialog(); - } else { - cardInfoWindowDialog.show(); - } - } - } - - private void showRevealed(GameView game) { - for (RevealedView revealView : game.getRevealed()) { - handleGameInfoWindow(revealed, ShowType.REVEAL, revealView.getName(), revealView.getCards()); - } - removeClosedCardInfoWindows(revealed); - } - - private void showLookedAt(GameView game) { - for (LookedAtView lookedAtView : game.getLookedAt()) { - handleGameInfoWindow(lookedAt, ShowType.LOOKED_AT, lookedAtView.getName(), lookedAtView.getCards()); - } - removeClosedCardInfoWindows(lookedAt); - } - - private void handleGameInfoWindow(Map windowMap, ShowType showType, String name, LinkedHashMap cardsView) { - CardInfoWindowDialog cardInfoWindowDialog; - if (!windowMap.containsKey(name)) { - cardInfoWindowDialog = new CardInfoWindowDialog(showType, name); - windowMap.put(name, cardInfoWindowDialog); - MageFrame.getDesktop().add(cardInfoWindowDialog, JLayeredPane.MODAL_LAYER); - } else { - cardInfoWindowDialog = windowMap.get(name); - } - - if (cardInfoWindowDialog != null && !cardInfoWindowDialog.isClosed()) { - switch (showType) { - case REVEAL: - case REVEAL_TOP_LIBRARY: - cardInfoWindowDialog.loadCards((CardsView) cardsView, bigCard, gameId); - break; - case LOOKED_AT: - cardInfoWindowDialog.loadCards((SimpleCardsView) cardsView, bigCard, gameId); - break; - } - } - } - - private void removeClosedCardInfoWindows(Map windowMap) { - // Remove closed window objects from the maps - for (Iterator> iterator = windowMap.entrySet().iterator(); iterator.hasNext();) { - Map.Entry entry = iterator.next(); - if (entry.getValue().isClosed()) { - iterator.remove(); - } - } - } - - public void ask(String question, GameView gameView, int messageId, Map options) { - updateGame(gameView); - this.feedbackPanel.getFeedback(FeedbackMode.QUESTION, question, false, options, messageId); - } - - /** - * Shows a pick target dialog and allows the player to pick a target (e.g. - * the pick triggered ability) - * - * @param message - * @param cardView - * @param gameView - * @param targets - * @param required - * @param options - * @param messageId - */ - public void pickTarget(String message, CardsView cardView, GameView gameView, Set targets, boolean required, Map options, int messageId) { - PopUpMenuType popupMenuType = null; - if (options != null) { - if (options.containsKey("targetZone")) { - if (Zone.HAND.equals(options.get("targetZone"))) { // mark selectable target cards in hand - List choosen = null; - if (options.containsKey("chosen")) { - choosen = (List) options.get("chosen"); - } - for (CardView card : gameView.getHand().values()) { - if (targets == null || targets.isEmpty()) { - card.setPlayable(false); - card.setChoosable(true); - } else if (targets.contains(card.getId())) { - card.setPlayable(false); - card.setChoosable(true); - } - if (choosen != null && choosen.contains(card.getId())) { - card.setSelected(true); - } - } - } - } - if (options.containsKey("queryType") && PlayerQueryEvent.QueryType.PICK_ABILITY.equals(options.get("queryType"))) { - popupMenuType = PopUpMenuType.TRIGGER_ORDER; - } - } - updateGame(gameView); - Map options0 = options == null ? new HashMap<>() : options; - ShowCardsDialog dialog = null; - if (cardView != null && cardView.size() > 0) { - dialog = showCards(message, cardView, required, options0, popupMenuType); - options0.put("dialog", dialog); - } - this.feedbackPanel.getFeedback(required ? FeedbackMode.INFORM : FeedbackMode.CANCEL, message, gameView.getSpecial(), options0, messageId); - if (dialog != null) { - this.pickTarget.add(dialog); - } - } - - public void inform(String information, GameView gameView, int messageId) { - updateGame(gameView); - this.feedbackPanel.getFeedback(FeedbackMode.INFORM, information, gameView.getSpecial(), null, messageId); - } - - public void endMessage(String message, int messageId) { - this.feedbackPanel.getFeedback(FeedbackMode.END, message, false, null, messageId); - ArrowBuilder.getBuilder().removeAllArrows(gameId); - } - - public void select(String message, GameView gameView, int messageId, Map options) { - holdingPriority = false; - txtHoldPriority.setVisible(false); - setMenuStates( - PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT, "true").equals("true"), - PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE, "true").equals("true"), - PreferencesDialog.getCachedValue(KEY_USE_FIRST_MANA_ABILITY, "false").equals("true"), - false); - - updateGame(gameView, options); - boolean controllingPlayer = false; - for (PlayerView playerView : gameView.getPlayers()) { - if (playerView.getPlayerId().equals(playerId)) { - // magenoxx: because of uncaught bug with saving state, rolling back and stack - // undo is allowed only for empty stack - controllingPlayer = !gameView.getPriorityPlayerName().equals(playerView.getName()); - if (playerView.getStatesSavedSize() > 0 && gameView.getStack().isEmpty()) { - feedbackPanel.allowUndo(playerView.getStatesSavedSize()); - } - break; - } - - } - Map panelOptions = new HashMap<>(); - if (options != null) { - panelOptions.putAll(options); - } - panelOptions.put("your_turn", true); - String activePlayerText; - if (gameView.getActivePlayerId().equals(playerId)) { - activePlayerText = "Your turn"; - } else { - activePlayerText = gameView.getActivePlayerName() + "'s turn"; - } - String priorityPlayerText = ""; - if (controllingPlayer) { - priorityPlayerText = " / priority " + gameView.getPriorityPlayerName(); - } - String messageToDisplay = message + FeedbackPanel.getSmallText(activePlayerText + " / " + gameView.getStep().toString() + priorityPlayerText); - this.feedbackPanel.getFeedback(FeedbackMode.SELECT, messageToDisplay, gameView.getSpecial(), panelOptions, messageId); - } - - public void playMana(String message, GameView gameView, Map options, int messageId) { - updateGame(gameView); - DialogManager.getManager(gameId).fadeOut(); - this.feedbackPanel.getFeedback(FeedbackMode.CANCEL, message, gameView.getSpecial(), options, messageId); - } - - public void playXMana(String message, GameView gameView, int messageId) { - updateGame(gameView); - DialogManager.getManager(gameId).fadeOut(); - this.feedbackPanel.getFeedback(FeedbackMode.CONFIRM, message, gameView.getSpecial(), null, messageId); - } - - public void replayMessage(String message) { - //TODO: implement this - } - - public void pickAbility(AbilityPickerView choices) { - hideAll(); - DialogManager.getManager(gameId).fadeOut(); - this.abilityPicker.show(choices, MageFrame.getDesktop().getMousePosition()); - } - - private void hideAll() { - ActionCallback callback = Plugins.getInstance().getActionCallback(); - ((MageActionCallback) callback).hideGameUpdate(gameId); - } - - private ShowCardsDialog showCards(String title, CardsView cards, boolean required, Map options, PopUpMenuType popupMenuType) { - hideAll(); - ShowCardsDialog showCards = new ShowCardsDialog(); - JPopupMenu popupMenu = null; - if (PopUpMenuType.TRIGGER_ORDER.equals(popupMenuType)) { - popupMenu = popupMenuTriggerOrder; - } - showCards.loadCards(title, cards, bigCard, gameId, required, options, popupMenu, getShowCardsEventListener(showCards)); - return showCards; - } - - public void getAmount(int min, int max, String message) { - pickNumber.showDialog(min, max, message); - if (pickNumber.isCancel()) { - SessionHandler.sendPlayerBoolean(gameId, false); - } else { - SessionHandler.sendPlayerInteger(gameId, pickNumber.getAmount()); - } - } - - public void getChoice(Choice choice, UUID objectId) { - hideAll(); - PickChoiceDialog pickChoice = new PickChoiceDialog(); - pickChoice.showDialog(choice, objectId, choiceWindowState); - if (choice.isKeyChoice()) { - if (pickChoice.isAutoSelect()) { - SessionHandler.sendPlayerString(gameId, "#" + choice.getChoiceKey()); - } else { - SessionHandler.sendPlayerString(gameId, choice.getChoiceKey()); - } - } else { - SessionHandler.sendPlayerString(gameId, choice.getChoice()); - } - choiceWindowState = new MageDialogState(pickChoice); - pickChoice.removeDialog(); - } - - public void pickPile(String message, CardsView pile1, CardsView pile2) { - hideAll(); - PickPileDialog pickPileDialog = new PickPileDialog(); - pickPileDialog.loadCards(message, pile1, pile2, bigCard, gameId); - SessionHandler.sendPlayerBoolean(gameId, pickPileDialog.isPickedPile1()); - pickPileDialog.cleanUp(); - pickPileDialog.removeDialog(); - } - - public Map getPlayers() { - return players; - } - - @SuppressWarnings("unchecked") - private void initComponents() { - - abilityPicker = new mage.client.components.ability.AbilityPicker(); - jSplitPane1 = new javax.swing.JSplitPane(); - jSplitPane0 = new javax.swing.JSplitPane(); - jPanel2 = new javax.swing.JPanel(); - pnlHelperHandButtonsStackArea = new javax.swing.JPanel(); - pnlShortCuts = new javax.swing.JPanel(); - lblPhase = new javax.swing.JLabel(); - txtPhase = new javax.swing.JLabel(); - lblStep = new javax.swing.JLabel(); - txtStep = new javax.swing.JLabel(); - lblTurn = new javax.swing.JLabel(); - txtTurn = new javax.swing.JLabel(); - txtActivePlayer = new javax.swing.JLabel(); - lblActivePlayer = new javax.swing.JLabel(); - txtPriority = new javax.swing.JLabel(); - lblPriority = new javax.swing.JLabel(); - feedbackPanel = new mage.client.game.FeedbackPanel(); - - txtSpellsCast = new javax.swing.JLabel(); - Border paddingBorder = BorderFactory.createEmptyBorder(4, 4, 4, 4); - Border border = BorderFactory.createLineBorder(Color.DARK_GRAY, 2); - txtSpellsCast.setBorder(BorderFactory.createCompoundBorder(border, paddingBorder)); - txtSpellsCast.setBackground(Color.LIGHT_GRAY); - txtSpellsCast.setOpaque(true); - txtSpellsCast.setToolTipText("spells cast during the current turn"); - - txtHoldPriority = new javax.swing.JLabel(); - txtHoldPriority.setText("Hold"); - txtHoldPriority.setBorder(BorderFactory.createCompoundBorder(border, paddingBorder)); - txtHoldPriority.setBackground(Color.LIGHT_GRAY); - txtHoldPriority.setOpaque(true); - txtHoldPriority.setToolTipText("Holding priority after the next spell cast or ability activation"); - txtHoldPriority.setVisible(false); - - btnCancelSkip = new javax.swing.JButton(); // F3 - btnSkipToNextTurn = new javax.swing.JButton(); // F4 - btnSkipToEndTurn = new javax.swing.JButton(); // F5 - btnSkipToNextMain = new javax.swing.JButton(); // F7 - btnSkipStack = new javax.swing.JButton(); // F8 - btnSkipToYourTurn = new javax.swing.JButton(); // F9 - btnSkipToEndStepBeforeYourTurn = new javax.swing.JButton(); // F11 - - btnConcede = new javax.swing.JButton(); - btnSwitchHands = new javax.swing.JButton(); - btnStopWatching = new javax.swing.JButton(); - - bigCard = new mage.client.cards.BigCard(); - pnlReplay = new javax.swing.JPanel(); - btnStopReplay = new javax.swing.JButton(); - btnNextPlay = new javax.swing.JButton(); - btnPlay = new javax.swing.JButton(); - btnSkipForward = new javax.swing.JButton(); - btnPreviousPlay = new javax.swing.JButton(); - pnlBattlefield = new javax.swing.JPanel(); - gameChatPanel = new mage.client.chat.ChatPanelBasic(); - gameChatPanel.useExtendedView(ChatPanelBasic.VIEW_MODE.GAME); - userChatPanel = new mage.client.chat.ChatPanelBasic(); - userChatPanel.setParentChat(gameChatPanel); - userChatPanel.useExtendedView(ChatPanelBasic.VIEW_MODE.CHAT); - userChatPanel.setChatType(ChatPanelBasic.ChatType.GAME); - gameChatPanel.setConnectedChat(userChatPanel); - gameChatPanel.disableInput(); - gameChatPanel.setMinimumSize(new java.awt.Dimension(100, 48)); - gameChatPanel.enableHyperlinks(); - jSplitPane2 = new javax.swing.JSplitPane(); - handContainer = new HandPanel(); - handCards = new HashMap<>(); - - pnlShortCuts.setOpaque(false); - pnlShortCuts.setPreferredSize(new Dimension(410, 72)); - - stackObjects = new mage.client.cards.Cards(); - - jSplitPane1.setBorder(null); - jSplitPane1.setDividerSize(7); - jSplitPane1.setResizeWeight(1.0); - jSplitPane1.setOneTouchExpandable(true); - jSplitPane1.setMinimumSize(new java.awt.Dimension(26, 48)); - - jSplitPane0.setBorder(null); - jSplitPane0.setDividerSize(7); - jSplitPane0.setResizeWeight(1.0); - jSplitPane0.setOneTouchExpandable(true); - - restoreDividerLocations(); - - lblPhase.setLabelFor(txtPhase); - lblPhase.setText("Phase:"); - - txtPhase.setText("Phase"); - txtPhase.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(153, 153, 153), 1, true)); - txtPhase.setMinimumSize(new java.awt.Dimension(0, 16)); - - lblStep.setLabelFor(txtStep); - lblStep.setText("Step:"); - - txtStep.setText("Step"); - txtStep.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(153, 153, 153), 1, true)); - txtStep.setMinimumSize(new java.awt.Dimension(0, 16)); - - lblTurn.setLabelFor(txtTurn); - lblTurn.setText("Turn:"); - - txtTurn.setText("Turn"); - txtTurn.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(153, 153, 153), 1, true)); - txtTurn.setMinimumSize(new java.awt.Dimension(0, 16)); - - txtActivePlayer.setText("Active Player"); - txtActivePlayer.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(153, 153, 153), 1, true)); - txtActivePlayer.setMinimumSize(new java.awt.Dimension(0, 16)); - - lblActivePlayer.setLabelFor(txtActivePlayer); - lblActivePlayer.setText("Active Player:"); - - txtPriority.setText("Priority Player"); - txtPriority.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(153, 153, 153), 1, true)); - txtPriority.setMinimumSize(new java.awt.Dimension(0, 16)); - - lblPriority.setLabelFor(txtPriority); - lblPriority.setText("Priority Player:"); - - bigCard.setBorder(new LineBorder(Color.black, 1, true)); - - int c = JComponent.WHEN_IN_FOCUSED_WINDOW; - - KeyStroke ks3 = KeyStroke.getKeyStroke(KeyEvent.VK_F3, 0); - this.getInputMap(c).put(ks3, "F3_PRESS"); - this.getActionMap().put("F3_PRESS", new AbstractAction() { - @Override - public void actionPerformed(ActionEvent actionEvent) { - restorePriorityActionPerformed(actionEvent); - } - }); - - btnCancelSkip.setContentAreaFilled(false); - btnCancelSkip.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); - btnCancelSkip.setIcon(new ImageIcon(ImageManagerImpl.getInstance().getCancelSkipButtonImage())); - btnCancelSkip.setToolTipText("Cancel all skip actions (F3)."); - btnCancelSkip.setFocusable(false); - btnCancelSkip.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent evt) { - if (evt.getButton() == MouseEvent.BUTTON1) { - restorePriorityActionPerformed(null); - } - } - }); - - btnSkipToNextTurn.setContentAreaFilled(false); - btnSkipToNextTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); - btnSkipToNextTurn.setIcon(new ImageIcon(ImageManagerImpl.getInstance().getSkipNextTurnButtonImage())); - btnSkipToNextTurn.setToolTipText("Skip to next turn (F4)."); - btnSkipToNextTurn.setFocusable(false); - btnSkipToNextTurn.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent evt) { - if (evt.getButton() == MouseEvent.BUTTON1) { - btnEndTurnActionPerformed(null); - } - } - }); - - KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_F4, 0); - this.getInputMap(c).put(ks, "F4_PRESS"); - this.getActionMap().put("F4_PRESS", new AbstractAction() { - @Override - public void actionPerformed(ActionEvent actionEvent) { - btnEndTurnActionPerformed(actionEvent); - } - }); - - btnSkipToEndTurn.setContentAreaFilled(false); - btnSkipToEndTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); - btnSkipToEndTurn.setIcon(new ImageIcon(ImageManagerImpl.getInstance().getSkipEndTurnButtonImage())); - btnSkipToEndTurn.setToolTipText("Skip to (opponents/next) end of turn step (F5) - adjust using preferences."); - btnSkipToEndTurn.setFocusable(false); - btnSkipToEndTurn.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent evt) { - if (evt.getButton() == MouseEvent.BUTTON1) { - btnUntilEndOfTurnActionPerformed(null); - } - } - }); - - ks = KeyStroke.getKeyStroke(KeyEvent.VK_F5, 0); - this.getInputMap(c).put(ks, "F5_PRESS"); - this.getActionMap().put("F5_PRESS", new AbstractAction() { - @Override - public void actionPerformed(ActionEvent actionEvent) { - btnUntilEndOfTurnActionPerformed(actionEvent); - } - }); - - ks = KeyStroke.getKeyStroke(KeyEvent.VK_F6, 0); - this.getInputMap(c).put(ks, "F6_PRESS"); - this.getActionMap().put("F6_PRESS", new AbstractAction() { - @Override - public void actionPerformed(ActionEvent actionEvent) { - btnEndTurnSkipStackActionPerformed(actionEvent); - } - }); - - btnSkipToNextMain.setContentAreaFilled(false); - btnSkipToNextMain.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); - btnSkipToNextMain.setIcon(new ImageIcon(ImageManagerImpl.getInstance().getSkipMainButtonImage())); - btnSkipToNextMain.setToolTipText("Skip to (your) next main phase (F7) - adjust using preferences."); - btnSkipToNextMain.setFocusable(false); - btnSkipToNextMain.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent evt) { - if (evt.getButton() == MouseEvent.BUTTON1) { - btnUntilNextMainPhaseActionPerformed(null); - } - } - }); - - ks = KeyStroke.getKeyStroke(KeyEvent.VK_F7, 0); - this.getInputMap(c).put(ks, "F7_PRESS"); - this.getActionMap().put("F7_PRESS", new AbstractAction() { - @Override - public void actionPerformed(ActionEvent actionEvent) { - btnUntilNextMainPhaseActionPerformed(actionEvent); - } - }); - - btnSkipToYourTurn.setContentAreaFilled(false); - btnSkipToYourTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); - btnSkipToYourTurn.setIcon(new ImageIcon(ImageManagerImpl.getInstance().getSkipYourNextTurnButtonImage())); - btnSkipToYourTurn.setToolTipText("Skip to your next turn (F9)."); - btnSkipToYourTurn.setFocusable(false); - btnSkipToYourTurn.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent evt) { - if (evt.getButton() == MouseEvent.BUTTON1) { - btnPassPriorityUntilNextYourTurnActionPerformed(null); - } - } - }); - - KeyStroke ks9 = KeyStroke.getKeyStroke(KeyEvent.VK_F9, 0); - this.getInputMap(c).put(ks9, "F9_PRESS"); - this.getActionMap().put("F9_PRESS", new AbstractAction() { - @Override - public void actionPerformed(ActionEvent actionEvent) { - btnPassPriorityUntilNextYourTurnActionPerformed(actionEvent); - } - }); - - btnSkipToEndStepBeforeYourTurn.setContentAreaFilled(false); - btnSkipToEndStepBeforeYourTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); - btnSkipToEndStepBeforeYourTurn.setIcon(new ImageIcon(ImageManagerImpl.getInstance().getSkipEndStepBeforeYourTurnButtonImage())); - btnSkipToEndStepBeforeYourTurn.setToolTipText("Skip to the end step before your turn (F11) - adjust using preferences."); - btnSkipToEndStepBeforeYourTurn.setFocusable(false); - btnSkipToEndStepBeforeYourTurn.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent evt) { - if (evt.getButton() == MouseEvent.BUTTON1) { - btnSkipToEndStepBeforeYourTurnActionPerformed(null); - } - } - }); - - KeyStroke ks11 = KeyStroke.getKeyStroke(KeyEvent.VK_F11, 0); - this.getInputMap(c).put(ks11, "F11_PRESS"); - this.getActionMap().put("F11_PRESS", new AbstractAction() { - @Override - public void actionPerformed(ActionEvent actionEvent) { - btnSkipToEndStepBeforeYourTurnActionPerformed(actionEvent); - } - }); - - btnSkipStack.setContentAreaFilled(false); - btnSkipStack.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); - btnSkipStack.setIcon(new ImageIcon(ImageManagerImpl.getInstance().getSkipStackButtonImage())); - btnSkipStack.setToolTipText("Skip until stack is resolved (F10)."); - btnSkipStack.setFocusable(false); - btnSkipStack.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent evt) { - if (evt.getButton() == MouseEvent.BUTTON1) { - btnPassPriorityUntilStackResolvedActionPerformed(null); - } - } - }); - - ks = KeyStroke.getKeyStroke(KeyEvent.VK_F10, 0); - this.getInputMap(c).put(ks, "F10_PRESS"); - this.getActionMap().put("F10_PRESS", new AbstractAction() { - @Override - public void actionPerformed(ActionEvent actionEvent) { - btnPassPriorityUntilStackResolvedActionPerformed(actionEvent); - } - }); - - btnConcede.setContentAreaFilled(false); - btnConcede.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); - btnConcede.setIcon(new ImageIcon(ImageManagerImpl.getInstance().getConcedeButtonImage())); - btnConcede.setToolTipText("Concede the current game."); - btnConcede.setFocusable(false); - btnConcede.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent evt) { - if (evt.getButton() == MouseEvent.BUTTON1) { - btnConcedeActionPerformed(null); - } - } - }); - - KeyStroke ks2 = KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0); - this.getInputMap(c).put(ks2, "F2_PRESS"); - this.getActionMap().put("F2_PRESS", new AbstractAction() { - @Override - public void actionPerformed(ActionEvent actionEvent) { - if (feedbackPanel != null) { - feedbackPanel.pressOKYesOrDone(); - } - } - }); - - KeyStroke ksAltE = KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.ALT_MASK); - this.getInputMap(c).put(ksAltE, "ENLARGE"); - this.getActionMap().put("ENLARGE", new AbstractAction() { - @Override - public void actionPerformed(ActionEvent actionEvent) { - ActionCallback callback = Plugins.getInstance().getActionCallback(); - ((MageActionCallback) callback).enlargeCard(EnlargeMode.NORMAL); - } - }); - - KeyStroke ksAltS = KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.ALT_MASK); - this.getInputMap(c).put(ksAltS, "ENLARGE_SOURCE"); - this.getActionMap().put("ENLARGE_SOURCE", new AbstractAction() { - @Override - public void actionPerformed(ActionEvent actionEvent) { - ActionCallback callback = Plugins.getInstance().getActionCallback(); - ((MageActionCallback) callback).enlargeCard(EnlargeMode.ALTERNATE); - } - }); - - KeyStroke ksAltD = KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.ALT_MASK); - this.getInputMap(c).put(ksAltD, "BIG_IMAGE"); - this.getActionMap().put("BIG_IMAGE", new AbstractAction() { - @Override - public void actionPerformed(ActionEvent actionEvent) { - imagePanelState = !imagePanelState; - if (!imagePanelState) { - jSplitPane0.resetToPreferredSizes(); - jSplitPane0.setDividerLocation(jSplitPane0.getSize().width - jSplitPane0.getInsets().right - jSplitPane0.getDividerSize() - 260); - } else { - jSplitPane0.setDividerLocation(1.0); - } - } - }); - - KeyStroke ksAlt1 = KeyStroke.getKeyStroke(KeyEvent.VK_1, InputEvent.ALT_MASK); - this.getInputMap(c).put(ksAlt1, "USEFIRSTMANAABILITY"); - this.getActionMap().put("USEFIRSTMANAABILITY", new AbstractAction() { - @Override - public void actionPerformed(ActionEvent actionEvent) { - SessionHandler.sendPlayerAction(PlayerAction.USE_FIRST_MANA_ABILITY_ON, gameId, null); - setMenuStates( - PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT, "true").equals("true"), - PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE, "true").equals("true"), - PreferencesDialog.getCachedValue(KEY_USE_FIRST_MANA_ABILITY, "false").equals("true"), - holdingPriority); - } - }); - - final BasicSplitPaneUI myUi = (BasicSplitPaneUI) jSplitPane0.getUI(); - final BasicSplitPaneDivider divider = myUi.getDivider(); - final JButton upArrowButton = (JButton) divider.getComponent(0); - upArrowButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent actionEvent) { - PreferencesDialog.saveValue(PreferencesDialog.KEY_BIG_CARD_TOGGLED, "up"); - } - }); - - final JButton downArrowButton = (JButton) divider.getComponent(1); - downArrowButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent actionEvent) { - PreferencesDialog.saveValue(PreferencesDialog.KEY_BIG_CARD_TOGGLED, "down"); - } - }); - - KeyStroke ksAltEReleased = KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.ALT_MASK, true); - this.getInputMap(c).put(ksAltEReleased, "ENLARGE_RELEASE"); - KeyStroke ksAltSReleased = KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.ALT_MASK, true); - this.getInputMap(c).put(ksAltSReleased, "ENLARGE_RELEASE"); - this.getActionMap().put("ENLARGE_RELEASE", new AbstractAction() { - @Override - public void actionPerformed(ActionEvent actionEvent) { - ActionCallback callback = Plugins.getInstance().getActionCallback(); - ((MageActionCallback) callback).hideEnlargedCard(); - } - }); - - KeyStroke ksAlt1Released = KeyStroke.getKeyStroke(KeyEvent.VK_1, InputEvent.ALT_MASK, true); - this.getInputMap(c).put(ksAlt1Released, "USEFIRSTMANAABILITY_RELEASE"); - this.getActionMap().put("USEFIRSTMANAABILITY_RELEASE", new AbstractAction() { - @Override - public void actionPerformed(ActionEvent actionEvent) { - SessionHandler.sendPlayerAction(PlayerAction.USE_FIRST_MANA_ABILITY_OFF, gameId, null); - setMenuStates( - PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT, "true").equals("true"), - PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE, "true").equals("true"), - PreferencesDialog.getCachedValue(KEY_USE_FIRST_MANA_ABILITY, "false").equals("true"), - holdingPriority); - } - }); - - btnSwitchHands.setContentAreaFilled(false); - btnSwitchHands.setBorder(new EmptyBorder(0, 0, 0, 0)); - btnSwitchHands.setIcon(new ImageIcon(ImageManagerImpl.getInstance().getSwitchHandsButtonImage())); - btnSwitchHands.setFocusable(false); - btnSwitchHands.setToolTipText("Switch between your hand cards and hand cards of controlled players."); - btnSwitchHands.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent evt) { - if (evt.getButton() == MouseEvent.BUTTON1) { - btnSwitchHandActionPerformed(null); - } - } - }); - - btnStopWatching.setContentAreaFilled(false); - btnStopWatching.setBorder(new EmptyBorder(0, 0, 0, 0)); - btnStopWatching.setIcon(new ImageIcon(ImageManagerImpl.getInstance().getStopWatchButtonImage())); - btnStopWatching.setFocusable(false); - btnStopWatching.setToolTipText("Stop watching this game."); - btnStopWatching.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent evt) { - if (evt.getButton() == MouseEvent.BUTTON1) { - btnStopWatchingActionPerformed(null); - } - } - }); - - stackObjects.setBackgroundColor(new Color(0, 0, 0, 40)); - - btnStopReplay.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/control_stop.png"))); - btnStopReplay.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnStopReplayActionPerformed(evt); - } - }); - - btnNextPlay.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/control_stop_right.png"))); - btnNextPlay.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnNextPlayActionPerformed(evt); - } - }); - - btnPlay.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/control_right.png"))); - btnPlay.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnPlayActionPerformed(evt); - } - }); - - btnSkipForward.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/control_double_stop_right.png"))); - btnSkipForward.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnSkipForwardActionPerformed(evt); - } - }); - - btnPreviousPlay.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/control_stop_left.png"))); - btnPreviousPlay.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnPreviousPlayActionPerformed(evt); - } - }); - - initPopupMenuTriggerOrder(); - - setGUISize(); - - // Replay panel to control replay of games - javax.swing.GroupLayout gl_pnlReplay = new javax.swing.GroupLayout(pnlReplay); - pnlReplay.setLayout(gl_pnlReplay); - gl_pnlReplay.setHorizontalGroup( - gl_pnlReplay.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(gl_pnlReplay.createSequentialGroup() - .addComponent(btnPreviousPlay, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnPlay, javax.swing.GroupLayout.PREFERRED_SIZE, 35, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(btnStopReplay, javax.swing.GroupLayout.PREFERRED_SIZE, 38, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnNextPlay, javax.swing.GroupLayout.PREFERRED_SIZE, 36, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnSkipForward, javax.swing.GroupLayout.PREFERRED_SIZE, 39, javax.swing.GroupLayout.PREFERRED_SIZE)) - ); - gl_pnlReplay.setVerticalGroup( - gl_pnlReplay.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(btnSkipForward, 0, 0, Short.MAX_VALUE) - .addComponent(btnNextPlay, 0, 0, Short.MAX_VALUE) - .addComponent(btnStopReplay, 0, 0, Short.MAX_VALUE) - .addComponent(btnPlay, 0, 0, Short.MAX_VALUE) - .addComponent(btnPreviousPlay, javax.swing.GroupLayout.PREFERRED_SIZE, 31, Short.MAX_VALUE) - ); - - // Game info panel (buttons on the right panel) - javax.swing.GroupLayout gl_pnlShortCuts = new javax.swing.GroupLayout(pnlShortCuts); - pnlShortCuts.setLayout(gl_pnlShortCuts); - gl_pnlShortCuts.setHorizontalGroup(gl_pnlShortCuts.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addGroup(gl_pnlShortCuts.createSequentialGroup() - .addComponent(btnSkipToNextTurn) - .addComponent(btnSkipToEndTurn) - .addComponent(btnSkipToNextMain) - .addComponent(btnSkipToYourTurn) - .addComponent(btnSkipStack) - .addComponent(btnSkipToEndStepBeforeYourTurn) - ) - .addGroup(gl_pnlShortCuts.createSequentialGroup() - .addComponent(txtHoldPriority) - .addComponent(txtSpellsCast) - .addComponent(btnSwitchHands) - .addComponent(btnCancelSkip) - .addComponent(btnConcede) - .addComponent(btnStopWatching) - ) - //.addComponent(bigCard, javax.swing.GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE) - //.addComponent(feedbackPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE) - //.addComponent(stack, javax.swing.GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE) - - .addGroup(gl_pnlShortCuts.createSequentialGroup() - .addContainerGap() - .addComponent(pnlReplay, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(51, Short.MAX_VALUE)) - ); - gl_pnlShortCuts.setVerticalGroup(gl_pnlShortCuts.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(gl_pnlShortCuts.createSequentialGroup() - //.addComponent(bigCard, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - //.addGap(1, 1, 1) - //.addComponent(feedbackPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 109, javax.swing.GroupLayout.PREFERRED_SIZE) - //.addComponent(stack, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 164, Short.MAX_VALUE) - .addComponent(pnlReplay, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(gl_pnlShortCuts.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(btnSkipToNextTurn) - .addComponent(btnSkipToEndTurn) - .addComponent(btnSkipToNextMain) - .addComponent(btnSkipToYourTurn) - .addComponent(btnSkipStack) - .addComponent(btnSkipToEndStepBeforeYourTurn) - ) - .addGroup(gl_pnlShortCuts.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(txtHoldPriority) - .addComponent(txtSpellsCast) - .addComponent(btnSwitchHands) - .addComponent(btnCancelSkip) - .addComponent(btnConcede) - .addComponent(btnStopWatching) - ) - ) - ); - - pnlBattlefield.setLayout(new java.awt.GridBagLayout()); - - jPhases = new JPanel(); - jPhases.setBackground(new Color(0, 0, 0, 0)); - jPhases.setLayout(null); - jPhases.setPreferredSize(new Dimension(X_PHASE_WIDTH, 435)); - - MouseAdapter phasesMouseAdapter = new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent evt) { - mouseClickPhaseBar(evt); - } - }; - String[] phases = {"Untap", "Upkeep", "Draw", "Main1", - "Combat_Start", "Combat_Attack", "Combat_Block", "Combat_Damage", "Combat_End", - "Main2", "Cleanup", "Next_Turn"}; - for (String name : phases) { - createPhaseButton(name, phasesMouseAdapter); - } - - int i = 0; - for (String name : hoverButtons.keySet()) { - HoverButton hoverButton = hoverButtons.get(name); - hoverButton.setAlignmentX(LEFT_ALIGNMENT); - hoverButton.setBounds(X_PHASE_WIDTH - 36, i * 36, 36, 36); - jPhases.add(hoverButton); - i++; - } - jPhases.addMouseListener(phasesMouseAdapter); - - pnlReplay.setOpaque(false); - - helper = new HelperPanel(); - feedbackPanel.setHelperPanel(helper); - - jSplitPane2.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); - jSplitPane2.setResizeWeight(0.5); - jSplitPane2.setLeftComponent(userChatPanel); - jSplitPane2.setBottomComponent(gameChatPanel); - - phasesContainer = new JPanel(); - phasesContainer.setLayout(new RelativeLayout(RelativeLayout.Y_AXIS)); - phasesContainer.setBackground(new Color(0, 0, 0, 0)); - Float ratio = (float) 1; - JPanel empty1 = new JPanel(); - empty1.setBackground(new Color(0, 0, 0, 0)); - phasesContainer.add(empty1, ratio); - phasesContainer.add(jPhases); - - javax.swing.GroupLayout gl_helperHandButtonsStackArea = new javax.swing.GroupLayout(pnlHelperHandButtonsStackArea); - gl_helperHandButtonsStackArea.setHorizontalGroup( - gl_helperHandButtonsStackArea.createParallelGroup(Alignment.LEADING) - .addGroup(gl_helperHandButtonsStackArea.createSequentialGroup() - // .addGap(0) - .addGroup(gl_helperHandButtonsStackArea.createParallelGroup(Alignment.LEADING) - .addGroup(gl_helperHandButtonsStackArea.createSequentialGroup() - .addGroup(gl_helperHandButtonsStackArea.createParallelGroup(Alignment.LEADING) - .addComponent(helper, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(handContainer, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - ) - .addGroup(gl_helperHandButtonsStackArea.createParallelGroup(Alignment.LEADING) - .addComponent(pnlShortCuts, 410, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE) - .addComponent(stackObjects, 410, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE) - ) - ) - .addGap(0) - //.addComponent(jPhases, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(gl_helperHandButtonsStackArea.createSequentialGroup() - .addComponent(pnlBattlefield, GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE) - .addComponent(phasesContainer, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - ))) - ); - gl_helperHandButtonsStackArea.setVerticalGroup( - gl_helperHandButtonsStackArea.createParallelGroup(Alignment.TRAILING) - .addGroup(gl_helperHandButtonsStackArea.createSequentialGroup() - .addGroup(gl_helperHandButtonsStackArea.createParallelGroup(Alignment.LEADING) - .addComponent(pnlBattlefield, GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE) - .addComponent(phasesContainer, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - ) - //.addPreferredGap(ComponentPlacement.RELATED) - .addGroup(gl_helperHandButtonsStackArea.createParallelGroup(Alignment.LEADING) - .addGroup(gl_helperHandButtonsStackArea.createSequentialGroup() - .addGap(2) - .addComponent(pnlShortCuts, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addComponent(stackObjects, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - ) - .addGroup(gl_helperHandButtonsStackArea.createSequentialGroup() - .addComponent(helper, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addComponent(handContainer, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - ) - ) - ) - ); - pnlHelperHandButtonsStackArea.setLayout(gl_helperHandButtonsStackArea); - - jSplitPane1.setLeftComponent(pnlHelperHandButtonsStackArea); - jSplitPane1.setRightComponent(jSplitPane2); - - // Set individual area sizes of big card pane - GridBagLayout gbl = new GridBagLayout(); - jPanel2.setLayout(gbl); - - GridBagConstraints gbc = new GridBagConstraints(); - gbc.fill = GridBagConstraints.BOTH; - gbc.gridx = 0; - gbc.gridy = 0; - gbc.gridwidth = 1; - gbc.gridheight = 4; // size 4/5 - gbc.weightx = 1.0; - gbc.weighty = 1.0; - gbl.setConstraints(bigCard, gbc); - jPanel2.add(bigCard); - - jPanel2.setOpaque(false); - - // game pane and chat/log pane - jSplitPane0.setLeftComponent(jSplitPane1); - // big card and buttons - jSplitPane0.setRightComponent(jPanel2); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jSplitPane0, javax.swing.GroupLayout.DEFAULT_SIZE, 1078, Short.MAX_VALUE) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jSplitPane0, javax.swing.GroupLayout.DEFAULT_SIZE, 798, Short.MAX_VALUE) - ); - } - - private void removeListener() { - for (MouseListener ml : this.getMouseListeners()) { - this.removeMouseListener(ml); - } - for (MouseListener ml : this.btnCancelSkip.getMouseListeners()) { - this.btnCancelSkip.removeMouseListener(ml); - } - for (MouseListener ml : this.btnConcede.getMouseListeners()) { - this.btnConcede.removeMouseListener(ml); - } - for (MouseListener ml : this.btnSkipToYourTurn.getMouseListeners()) { - this.btnSkipToYourTurn.removeMouseListener(ml); - } - for (MouseListener ml : this.btnSkipStack.getMouseListeners()) { - this.btnSkipStack.removeMouseListener(ml); - } - for (MouseListener ml : this.btnSkipToEndStepBeforeYourTurn.getMouseListeners()) { - this.btnSkipToEndStepBeforeYourTurn.removeMouseListener(ml); - } - for (MouseListener ml : this.btnSkipToEndTurn.getMouseListeners()) { - this.btnSkipToEndTurn.removeMouseListener(ml); - } - for (MouseListener ml : this.btnSkipToNextMain.getMouseListeners()) { - this.btnSkipToNextMain.removeMouseListener(ml); - } - for (MouseListener ml : this.btnSkipToNextTurn.getMouseListeners()) { - this.btnSkipToNextTurn.removeMouseListener(ml); - } - for (MouseListener ml : this.btnSwitchHands.getMouseListeners()) { - this.btnSwitchHands.removeMouseListener(ml); - } - for (MouseListener ml : this.btnStopWatching.getMouseListeners()) { - this.btnStopWatching.removeMouseListener(ml); - } - for (MouseListener ml : this.jPhases.getMouseListeners()) { - this.jPhases.removeMouseListener(ml); - } - for (String name : hoverButtons.keySet()) { - HoverButton hoverButton = hoverButtons.get(name); - for (MouseListener ml : hoverButton.getMouseListeners()) { - hoverButton.removeMouseListener(ml); - } - } - for (ActionListener al : this.btnPlay.getActionListeners()) { - this.btnPlay.removeActionListener(al); - } - for (ActionListener al : this.btnStopReplay.getActionListeners()) { - this.btnStopReplay.removeActionListener(al); - } - for (ActionListener al : this.btnNextPlay.getActionListeners()) { - this.btnNextPlay.removeActionListener(al); - } - for (ActionListener al : this.btnNextPlay.getActionListeners()) { - this.btnNextPlay.removeActionListener(al); - } - for (ActionListener al : this.btnPreviousPlay.getActionListeners()) { - this.btnPreviousPlay.removeActionListener(al); - } - for (ActionListener al : this.btnSkipForward.getActionListeners()) { - this.btnSkipForward.removeActionListener(al); - } - - final BasicSplitPaneUI myUi = (BasicSplitPaneUI) jSplitPane0.getUI(); - final BasicSplitPaneDivider divider = myUi.getDivider(); - final JButton upArrowButton = (JButton) divider.getComponent(0); - for (ActionListener al : upArrowButton.getActionListeners()) { - upArrowButton.removeActionListener(al); - } - final JButton downArrowButton = (JButton) divider.getComponent(1); - for (ActionListener al : downArrowButton.getActionListeners()) { - downArrowButton.removeActionListener(al); - } - - for (ComponentListener cl : this.getComponentListeners()) { - this.removeComponentListener(cl); - } - } - - private void btnConcedeActionPerformed(java.awt.event.ActionEvent evt) { - UserRequestMessage message = new UserRequestMessage("Confirm concede", "Are you sure you want to concede?"); - message.setButton1("No", null); - message.setButton2("Yes", PlayerAction.CLIENT_CONCEDE_GAME); - message.setGameId(gameId); - MageFrame.getInstance().showUserRequestDialog(message); - } - - private void btnEndTurnActionPerformed(java.awt.event.ActionEvent evt) { - SessionHandler.sendPlayerAction(PlayerAction.PASS_PRIORITY_UNTIL_NEXT_TURN, gameId, null); - AudioManager.playOnSkipButton(); - updateSkipButtons(true, false, false, false, false, false); - } - - private void btnUntilEndOfTurnActionPerformed(java.awt.event.ActionEvent evt) { - SessionHandler.sendPlayerAction(PlayerAction.PASS_PRIORITY_UNTIL_TURN_END_STEP, gameId, null); - AudioManager.playOnSkipButton(); - updateSkipButtons(false, true, false, false, false, false); - } - - private void btnEndTurnSkipStackActionPerformed(java.awt.event.ActionEvent evt) { - SessionHandler.sendPlayerAction(PlayerAction.PASS_PRIORITY_UNTIL_NEXT_TURN_SKIP_STACK, gameId, null); - AudioManager.playOnSkipButton(); - updateSkipButtons(true, false, false, false, true, false); - } - - private void btnUntilNextMainPhaseActionPerformed(java.awt.event.ActionEvent evt) { - SessionHandler.sendPlayerAction(PlayerAction.PASS_PRIORITY_UNTIL_NEXT_MAIN_PHASE, gameId, null); - AudioManager.playOnSkipButton(); - updateSkipButtons(false, false, true, false, false, false); - } - - private void btnPassPriorityUntilNextYourTurnActionPerformed(java.awt.event.ActionEvent evt) { - SessionHandler.sendPlayerAction(PlayerAction.PASS_PRIORITY_UNTIL_MY_NEXT_TURN, gameId, null); - AudioManager.playOnSkipButton(); - updateSkipButtons(false, false, false, true, false, false); - } - - private void btnPassPriorityUntilStackResolvedActionPerformed(java.awt.event.ActionEvent evt) { - SessionHandler.sendPlayerAction(PlayerAction.PASS_PRIORITY_UNTIL_STACK_RESOLVED, gameId, null); - AudioManager.playOnSkipButton(); - updateSkipButtons(false, false, false, false, true, false); - } - - private void btnSkipToEndStepBeforeYourTurnActionPerformed(java.awt.event.ActionEvent evt) { - SessionHandler.sendPlayerAction(PlayerAction.PASS_PRIORITY_UNTIL_END_STEP_BEFORE_MY_NEXT_TURN, gameId, null); - AudioManager.playOnSkipButton(); - updateSkipButtons(false, false, false, false, false, true); - } - - private void restorePriorityActionPerformed(java.awt.event.ActionEvent evt) { - SessionHandler.sendPlayerAction(PlayerAction.PASS_PRIORITY_CANCEL_ALL_ACTIONS, gameId, null); - AudioManager.playOnSkipButtonCancel(); - updateSkipButtons(false, false, false, false, false, false); - } - - private void mouseClickPhaseBar(MouseEvent evt) { - if (evt.getButton() == MouseEvent.BUTTON1) { // Left button - PreferencesDialog.main(new String[]{PreferencesDialog.OPEN_PHASES_TAB}); - } - } - - private void btnSwitchHandActionPerformed(java.awt.event.ActionEvent evt) { - String[] choices = handCards.keySet().toArray(new String[0]); - - String newChosenHandKey = (String) JOptionPane.showInputDialog( - this, - "Choose hand to display:", "Switch between hands", - JOptionPane.PLAIN_MESSAGE, - null, - choices, - this.chosenHandKey); - - if (newChosenHandKey != null && newChosenHandKey.length() > 0) { - this.chosenHandKey = newChosenHandKey; - CardsView cards = handCards.get(chosenHandKey); - handContainer.loadCards(cards, bigCard, gameId); - } - } + private static final Logger logger = Logger.getLogger(GamePanel.class); + private static final String YOUR_HAND = "Your hand"; + private static final int X_PHASE_WIDTH = 55; + private static final int STACK_MIN_CARDS_OFFSET_Y = 7; // TODO: Size bui GUISize value + + private static final String CMD_AUTO_ORDER_FIRST = "cmdAutoOrderFirst"; + private static final String CMD_AUTO_ORDER_LAST = "cmdAutoOrderLast"; + private static final String CMD_AUTO_ORDER_NAME_FIRST = "cmdAutoOrderNameFirst"; + private static final String CMD_AUTO_ORDER_NAME_LAST = "cmdAutoOrderNameLast"; + private static final String CMD_AUTO_ORDER_RESET_ALL = "cmdAutoOrderResetAll"; + + private final Map players = new HashMap<>(); + private final Map playersWhoLeft = new HashMap<>(); + + // non modal frames + private final Map exiles = new HashMap<>(); + private final Map revealed = new HashMap<>(); + private final Map lookedAt = new HashMap<>(); + private final Map graveyardWindows = new HashMap<>(); + private final Map graveyards = new HashMap<>(); + + private final ArrayList pickTarget = new ArrayList<>(); + private UUID gameId; + private UUID playerId; // playerId of the player + GamePane gamePane; + private ReplayTask replayTask; + private final PickNumberDialog pickNumber; + private JLayeredPane jLayeredPane; + private String chosenHandKey = "You"; + private boolean smallMode = false; + private boolean initialized = false; + + private boolean menuNameSet = false; + private boolean handCardsOfOpponentAvailable = false; + + private Map loadedCards = new HashMap<>(); + + private int storedHeight; + private Map hoverButtons; + + private MageDialogState choiceWindowState; + + private boolean initComponents; + + private Timer resizeTimer; + + private enum PopUpMenuType { + + TRIGGER_ORDER + } + // CardView popupMenu was invoked last + private CardView cardViewPopupMenu; + + // popup menu for triggered abilities order + private JPopupMenu popupMenuTriggerOrder; + + public GamePanel() { + initComponents = true; + initComponents(); + + pickNumber = new PickNumberDialog(); + MageFrame.getDesktop().add(pickNumber, JLayeredPane.MODAL_LAYER); + + this.feedbackPanel.setConnectedChatPanel(this.userChatPanel); + + this.stackObjects.setMinOffsetY(STACK_MIN_CARDS_OFFSET_Y); + + // Override layout (I can't edit generated code) + this.setLayout(new BorderLayout()); + final JLayeredPane jLayeredBackgroundPane = new JLayeredPane(); + jLayeredBackgroundPane.setSize(1024, 768); + this.add(jLayeredBackgroundPane); + jLayeredBackgroundPane.add(jSplitPane0, JLayeredPane.DEFAULT_LAYER); + + Map myUi = getUIComponents(jLayeredBackgroundPane); + Plugins.getInstance().updateGamePanel(myUi); + + // Enlarge jlayeredpane on resize of game panel + addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(ComponentEvent e) { + int width = ((JComponent) e.getSource()).getWidth(); + int height = ((JComponent) e.getSource()).getHeight(); + jLayeredBackgroundPane.setSize(width, height); + jSplitPane0.setSize(width, height); + + if (height < storedHeight) { + pnlBattlefield.setSize(0, 200); + } + storedHeight = height; + + sizeToScreen(); + + if (!initialized) { + String state = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_BIG_CARD_TOGGLED, null); + if (state != null && state.equals("down")) { + jSplitPane0.setDividerLocation(1.0); + } + initialized = true; + } + + } + }); + // Resize the width of the stack area if the size of the play area is changed + ComponentAdapter componentAdapterPlayField = new ComponentAdapter() { + @Override + public void componentResized(ComponentEvent e) { + if (!initComponents) { + if (resizeTimer.isRunning()) { + resizeTimer.restart(); + } else { + resizeTimer.start(); + } + } + } + }; + + resizeTimer = new Timer(1000, new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + resizeTimer.stop(); + setGUISize(); + feedbackPanel.changeGUISize(); + + } + }); + } + }); + + pnlHelperHandButtonsStackArea.addComponentListener(componentAdapterPlayField); + initComponents = false; + } + + private Map getUIComponents(JLayeredPane jLayeredPane) { + Map components = new HashMap<>(); + + components.put("jSplitPane1", jSplitPane1); + components.put("pnlBattlefield", pnlBattlefield); + components.put("pnlHelperHandButtonsStackArea", pnlHelperHandButtonsStackArea); + components.put("hand", handContainer); + components.put("gameChatPanel", gameChatPanel); + components.put("userChatPanel", userChatPanel); + components.put("jLayeredPane", jLayeredPane); + components.put("gamePanel", this); + + return components; + } + + public void cleanUp() { + MageFrame.removeGame(gameId); + saveDividerLocations(); + this.gameChatPanel.disconnect(); + this.userChatPanel.disconnect(); + + this.removeListener(); + + this.handContainer.cleanUp(); + this.stackObjects.cleanUp(); + for (Map.Entry playAreaPanelEntry : players.entrySet()) { + playAreaPanelEntry.getValue().CleanUp(); + } + this.players.clear(); + this.playersWhoLeft.clear(); + + jLayeredPane.remove(abilityPicker); + this.abilityPicker.cleanUp(); + + jLayeredPane.remove(DialogManager.getManager(gameId)); + DialogManager.removeGame(gameId); + + if (pickNumber != null) { + pickNumber.removeDialog(); + } + for (CardInfoWindowDialog exileDialog : exiles.values()) { + exileDialog.cleanUp(); + exileDialog.removeDialog(); + } + for (CardInfoWindowDialog graveyardDialog : graveyardWindows.values()) { + graveyardDialog.cleanUp(); + graveyardDialog.removeDialog(); + } + for (CardInfoWindowDialog revealDialog : revealed.values()) { + revealDialog.cleanUp(); + revealDialog.removeDialog(); + } + for (CardInfoWindowDialog lookedAtDialog : lookedAt.values()) { + lookedAtDialog.cleanUp(); + lookedAtDialog.removeDialog(); + } + for (ShowCardsDialog pickTargetDialog : pickTarget) { + pickTargetDialog.cleanUp(); + pickTargetDialog.removeDialog(); + } + Plugins.getInstance().getActionCallback().hideTooltipPopup(); + try { + Component popupContainer = MageFrame.getUI().getComponent(MageComponents.POPUP_CONTAINER); + popupContainer.setVisible(false); + } catch (InterruptedException ex) { + logger.fatal("popupContainer error:", ex); + } + jPanel2.remove(bigCard); + this.bigCard = null; + } + + public void changeGUISize() { + initComponents = true; + setGUISize(); + stackObjects.changeGUISize(); + feedbackPanel.changeGUISize(); + handContainer.changeGUISize(); + for (PlayAreaPanel playAreaPanel : players.values()) { + playAreaPanel.changeGUISize(); + } + + for (CardInfoWindowDialog cardInfoWindowDialog : exiles.values()) { + cardInfoWindowDialog.changeGUISize(); + } + for (CardInfoWindowDialog cardInfoWindowDialog : revealed.values()) { + cardInfoWindowDialog.changeGUISize(); + } + for (CardInfoWindowDialog cardInfoWindowDialog : lookedAt.values()) { + cardInfoWindowDialog.changeGUISize(); + } + for (CardInfoWindowDialog cardInfoWindowDialog : graveyardWindows.values()) { + cardInfoWindowDialog.changeGUISize(); + } + for (ShowCardsDialog showCardsDialog : pickTarget) { + showCardsDialog.changeGUISize(); + } + + this.revalidate(); + this.repaint(); + initComponents = false; + } + + private void setGUISize() { + jSplitPane0.setDividerSize(GUISizeHelper.dividerBarSize); + jSplitPane1.setDividerSize(GUISizeHelper.dividerBarSize); + jSplitPane2.setDividerSize(GUISizeHelper.dividerBarSize); + stackObjects.setCardDimension(GUISizeHelper.handCardDimension); + + txtSpellsCast.setFont(new Font(GUISizeHelper.gameDialogAreaFont.getFontName(), Font.BOLD, GUISizeHelper.gameDialogAreaFont.getSize())); + txtHoldPriority.setFont(new Font(GUISizeHelper.gameDialogAreaFont.getFontName(), Font.BOLD, GUISizeHelper.gameDialogAreaFont.getSize())); + GUISizeHelper.changePopupMenuFont(popupMenuTriggerOrder); + + int newStackWidth = pnlHelperHandButtonsStackArea.getWidth() * GUISizeHelper.stackWidth / 100; + if (newStackWidth < 410) { + newStackWidth = 410; + } + Dimension newDimension = new Dimension(pnlHelperHandButtonsStackArea.getWidth() - newStackWidth, GUISizeHelper.handCardDimension.height + GUISizeHelper.scrollBarSize); + handContainer.setPreferredSize(newDimension); + handContainer.setMaximumSize(newDimension); + + newDimension = new Dimension(newStackWidth, STACK_MIN_CARDS_OFFSET_Y + GUISizeHelper.handCardDimension.height + GUISizeHelper.scrollBarSize); + stackObjects.setPreferredSize(newDimension); + stackObjects.setMinimumSize(newDimension); + stackObjects.setMaximumSize(newDimension); + + newDimension = new Dimension(newStackWidth, (int) pnlShortCuts.getPreferredSize().getHeight()); + pnlShortCuts.setPreferredSize(newDimension); + pnlShortCuts.setMinimumSize(newDimension); + pnlShortCuts.setMaximumSize(newDimension); + } + + private void saveDividerLocations() { + // save panel sizes and divider locations. + Rectangle rec = MageFrame.getDesktop().getBounds(); + String sb = Double.toString(rec.getWidth()) + "x" + Double.toString(rec.getHeight()); + PreferencesDialog.saveValue(PreferencesDialog.KEY_MAGE_PANEL_LAST_SIZE, sb); + PreferencesDialog.saveValue(PreferencesDialog.KEY_GAMEPANEL_DIVIDER_LOCATION_0, Integer.toString(this.jSplitPane0.getDividerLocation())); + PreferencesDialog.saveValue(PreferencesDialog.KEY_GAMEPANEL_DIVIDER_LOCATION_1, Integer.toString(this.jSplitPane1.getDividerLocation())); + PreferencesDialog.saveValue(PreferencesDialog.KEY_GAMEPANEL_DIVIDER_LOCATION_2, Integer.toString(this.jSplitPane2.getDividerLocation())); + } + + private void restoreDividerLocations() { + Rectangle rec = MageFrame.getDesktop().getBounds(); + if (rec != null) { + String size = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_MAGE_PANEL_LAST_SIZE, null); + String sb = Double.toString(rec.getWidth()) + "x" + Double.toString(rec.getHeight()); + // use divider positions only if screen size is the same as it was the time the settings were saved + if (size != null && size.equals(sb)) { + + String location = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAMEPANEL_DIVIDER_LOCATION_0, null); + if (location != null && jSplitPane0 != null) { + jSplitPane0.setDividerLocation(Integer.parseInt(location)); + } + location = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAMEPANEL_DIVIDER_LOCATION_1, null); + if (location != null && jSplitPane1 != null) { + jSplitPane1.setDividerLocation(Integer.parseInt(location)); + } + location = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAMEPANEL_DIVIDER_LOCATION_2, null); + if (location != null && jSplitPane2 != null) { + jSplitPane2.setDividerLocation(Integer.parseInt(location)); + } + } + } + } + + private void sizeToScreen() { + Rectangle rect = this.getBounds(); + + if (rect.height < 720) { + if (!smallMode) { + smallMode = true; + Dimension bbDimension = new Dimension(128, 184); + bigCard.setMaximumSize(bbDimension); + bigCard.setMinimumSize(bbDimension); + bigCard.setPreferredSize(bbDimension); + pnlShortCuts.revalidate(); + pnlShortCuts.repaint(); + for (PlayAreaPanel p : players.values()) { + p.sizePlayer(smallMode); + } + } + } else if (smallMode) { + smallMode = false; + Dimension bbDimension = new Dimension(256, 367); + bigCard.setMaximumSize(bbDimension); + bigCard.setMinimumSize(bbDimension); + bigCard.setPreferredSize(bbDimension); + pnlShortCuts.revalidate(); + pnlShortCuts.repaint(); + for (PlayAreaPanel p : players.values()) { + p.sizePlayer(smallMode); + } + } + + ArrowBuilder.getBuilder().setSize(rect.width, rect.height); + + DialogManager.getManager(gameId).setScreenWidth(rect.width); + DialogManager.getManager(gameId).setScreenHeight(rect.height); + DialogManager.getManager(gameId).setBounds(0, 0, rect.width, rect.height); + } + + public synchronized void showGame(UUID gameId, UUID playerId, GamePane gamePane) { + this.gameId = gameId; + this.gamePane = gamePane; + this.playerId = playerId; + MageFrame.addGame(gameId, this); + this.feedbackPanel.init(gameId); + this.feedbackPanel.clear(); + this.abilityPicker.init(gameId); + + this.btnConcede.setVisible(true); + this.btnStopWatching.setVisible(false); + this.btnSwitchHands.setVisible(false); + this.btnCancelSkip.setVisible(true); + + this.btnSkipToNextTurn.setVisible(true); + this.btnSkipToEndTurn.setVisible(true); + this.btnSkipToNextMain.setVisible(true); + this.btnSkipStack.setVisible(true); + this.btnSkipToYourTurn.setVisible(true); + this.btnSkipToEndStepBeforeYourTurn.setVisible(true); + + this.pnlReplay.setVisible(false); + + this.gameChatPanel.clear(); + this.gameChatPanel.connect(SessionHandler.getGameChatId(gameId)); + if (!SessionHandler.joinGame(gameId)) { + removeGame(); + } else { + // play start sound + AudioManager.playYourGameStarted(); + } + } + + public synchronized void watchGame(UUID gameId, GamePane gamePane) { + this.gameId = gameId; + this.gamePane = gamePane; + this.playerId = null; + MageFrame.addGame(gameId, this); + this.feedbackPanel.init(gameId); + this.feedbackPanel.clear(); + + this.btnConcede.setVisible(false); + this.btnStopWatching.setVisible(true); + this.btnSwitchHands.setVisible(false); + this.chosenHandKey = ""; + this.btnCancelSkip.setVisible(false); + + this.btnSkipToNextTurn.setVisible(false); + this.btnSkipToEndTurn.setVisible(false); + this.btnSkipToNextMain.setVisible(false); + this.btnSkipStack.setVisible(false); + this.btnSkipToYourTurn.setVisible(false); + this.btnSkipToEndStepBeforeYourTurn.setVisible(false); + + this.pnlReplay.setVisible(false); + this.gameChatPanel.clear(); + this.gameChatPanel.connect(SessionHandler.getGameChatId(gameId)); + if (!SessionHandler.watchGame(gameId)) { + removeGame(); + } + for (PlayAreaPanel panel : getPlayers().values()) { + panel.setPlayingMode(false); + } + } + + public synchronized void replayGame(UUID gameId) { + this.gameId = gameId; + this.playerId = null; + MageFrame.addGame(gameId, this); + this.feedbackPanel.init(gameId); + this.feedbackPanel.clear(); + this.btnConcede.setVisible(false); + this.btnSkipToNextTurn.setVisible(false); + this.btnSwitchHands.setVisible(false); + this.btnStopWatching.setVisible(false); + this.pnlReplay.setVisible(true); + this.gameChatPanel.clear(); + if (!SessionHandler.startReplay(gameId)) { + removeGame(); + } + for (PlayAreaPanel panel : getPlayers().values()) { + panel.setPlayingMode(false); + } + } + + /** + * Closes the game and it's resources + */ + public void removeGame() { + Component c = this.getParent(); + while (c != null && !(c instanceof GamePane)) { + c = c.getParent(); + } + if (c != null) { + ((GamePane) c).removeGame(); + } + } + + public synchronized void init(GameView game) { + addPlayers(game); + // default menu states + setMenuStates( + PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT, "true").equals("true"), + PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE, "true").equals("true"), + PreferencesDialog.getCachedValue(KEY_USE_FIRST_MANA_ABILITY, "false").equals("true"), + holdingPriority + ); + + updateGame(game); + } + + private void addPlayers(GameView game) { + this.players.clear(); + this.playersWhoLeft.clear(); + this.pnlBattlefield.removeAll(); + //arrange players in a circle with the session player at the bottom left + int numSeats = game.getPlayers().size(); + int numColumns = (numSeats + 1) / 2; + boolean oddNumber = (numColumns > 1 && numSeats % 2 == 1); + int col = 0; + int row = 1; + int playerSeat = 0; + if (playerId != null) { + for (PlayerView player : game.getPlayers()) { + if (playerId.equals(player.getPlayerId())) { + break; + } + playerSeat++; + } + } + PlayerView player = game.getPlayers().get(playerSeat); + PlayAreaPanel playAreaPanel = new PlayAreaPanel(player, bigCard, gameId, game.getPriorityTime(), this, + new PlayAreaPanelOptions(game.isPlayer(), game.isPlayer(), game.isRollbackTurnsAllowed(), row == 0)); + players.put(player.getPlayerId(), playAreaPanel); + playersWhoLeft.put(player.getPlayerId(), false); + GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.BOTH; + c.weightx = 0.5; + c.weighty = 0.5; + if (oddNumber) { + c.gridwidth = 2; + } + c.gridx = col; + c.gridy = 0; + + // Top panel (row=0) + JPanel topPanel = new JPanel(); + topPanel.setOpaque(false); + + // Bottom panel (row=1) + JPanel bottomPanel = new JPanel(); + bottomPanel.setOpaque(false); + topPanel.setLayout(new GridBagLayout()); + bottomPanel.setLayout(new GridBagLayout()); + + bottomPanel.add(playAreaPanel, c); + playAreaPanel.setVisible(true); + if (oddNumber) { + col++; + } + int playerNum = playerSeat + 1; + if (playerNum >= numSeats) { + playerNum = 0; + } + while (true) { + if (row == 1) { + col++; + } else { + col--; + } + if (col >= numColumns) { + row = 0; + col = numColumns - 1; + } + player = game.getPlayers().get(playerNum); + PlayAreaPanel playerPanel = new PlayAreaPanel(player, bigCard, gameId, game.getPriorityTime(), this, + new PlayAreaPanelOptions(game.isPlayer(), false, game.isRollbackTurnsAllowed(), row == 0)); + players.put(player.getPlayerId(), playerPanel); + playersWhoLeft.put(player.getPlayerId(), false); + c = new GridBagConstraints(); + c.fill = GridBagConstraints.BOTH; + c.weightx = 0.5; + c.weighty = 0.5; + c.gridx = col; + c.gridy = 0; + + if (row == 0) { + topPanel.add(playerPanel, c); + } else { + bottomPanel.add(playerPanel, c); + } + + playerPanel.setVisible(true); + playerNum++; + if (playerNum >= numSeats) { + playerNum = 0; + } + if (playerNum == playerSeat) { + break; + } + } + for (PlayAreaPanel p : players.values()) { + p.sizePlayer(smallMode); + } + + GridBagConstraints panelC = new GridBagConstraints(); + panelC.fill = GridBagConstraints.BOTH; + panelC.weightx = 0.5; + panelC.weighty = 0.5; + panelC.gridwidth = 1; + panelC.gridy = 0; + this.pnlBattlefield.add(topPanel, panelC); + panelC.gridy = 1; + this.pnlBattlefield.add(bottomPanel, panelC); + } + + public synchronized void updateGame(GameView game) { + updateGame(game, null); + } + + public synchronized void updateGame(GameView game, Map options) { + if (playerId == null && game.getWatchedHands() == null) { + this.handContainer.setVisible(false); + } else { + this.handContainer.setVisible(true); + handCards.clear(); + if (game.getWatchedHands() != null) { + for (Map.Entry hand : game.getWatchedHands().entrySet()) { + handCards.put(hand.getKey(), CardsViewUtil.convertSimple(hand.getValue(), loadedCards)); + } + } + if (playerId != null) { + handCards.put(YOUR_HAND, game.getHand()); + // Mark playable + if (game.getCanPlayInHand() != null) { + for (CardView card : handCards.get(YOUR_HAND).values()) { + if (game.getCanPlayInHand().contains(card.getId())) { + card.setPlayable(true); + } + } + } + // Get opponents hand cards if available (only possible for players) + if (game.getOpponentHands() != null) { + for (Map.Entry hand : game.getOpponentHands().entrySet()) { + handCards.put(hand.getKey(), CardsViewUtil.convertSimple(hand.getValue(), loadedCards)); + } + } + if (!handCards.containsKey(chosenHandKey)) { + chosenHandKey = YOUR_HAND; + } + } else if (chosenHandKey.isEmpty() && handCards.size() > 0) { + chosenHandKey = handCards.keySet().iterator().next(); + } + if (chosenHandKey != null && handCards.containsKey(chosenHandKey)) { + handContainer.loadCards(handCards.get(chosenHandKey), bigCard, gameId); + } + + hideAll(); + + if (playerId != null) { + // set visible only if we have any other hand visible than ours + btnSwitchHands.setVisible(handCards.size() > 1); + boolean change = (handCardsOfOpponentAvailable != (game.getOpponentHands() != null)); + if (change) { + handCardsOfOpponentAvailable = !handCardsOfOpponentAvailable; + if (handCardsOfOpponentAvailable) { + JOptionPane.showMessageDialog(null, "You control other player's turn. \nUse \"Switch Hand\" button to switch between cards in different hands."); + } else { + JOptionPane.showMessageDialog(null, "You lost control on other player's turn."); + } + } + } else { + btnSwitchHands.setVisible(!handCards.isEmpty()); + } + } + + if (game.getPhase() != null) { + this.txtPhase.setText(game.getPhase().toString()); + } else { + this.txtPhase.setText(""); + } + + if (game.getStep() != null) { + updatePhases(game.getStep()); + this.txtStep.setText(game.getStep().toString()); + } else { + logger.debug("Step is empty"); + this.txtStep.setText(""); + } + if (game.getSpellsCastCurrentTurn() > 0 && PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_SHOW_STORM_COUNTER, "true").equals("true")) { + this.txtSpellsCast.setVisible(true); + this.txtSpellsCast.setText(" " + Integer.toString(game.getSpellsCastCurrentTurn()) + " "); + } else { + this.txtSpellsCast.setVisible(false); + } + + this.txtActivePlayer.setText(game.getActivePlayerName()); + this.txtPriority.setText(game.getPriorityPlayerName()); + this.txtTurn.setText(Integer.toString(game.getTurn())); + + List possibleAttackers = new ArrayList<>(); + if (options != null && options.containsKey(Constants.Option.POSSIBLE_ATTACKERS)) { + if (options.get(Constants.Option.POSSIBLE_ATTACKERS) instanceof List) { + possibleAttackers.addAll((List) options.get(Constants.Option.POSSIBLE_ATTACKERS)); + } + } + + for (PlayerView player : game.getPlayers()) { + if (players.containsKey(player.getPlayerId())) { + if (!possibleAttackers.isEmpty()) { + for (UUID permanentId : possibleAttackers) { + if (player.getBattlefield().containsKey(permanentId)) { + player.getBattlefield().get(permanentId).setCanAttack(true); + } + } + } + players.get(player.getPlayerId()).update(player); + if (player.getPlayerId().equals(playerId)) { + updateSkipButtons(player.isPassedTurn(), player.isPassedUntilEndOfTurn(), player.isPassedUntilNextMain(), player.isPassedAllTurns(), player.isPassedUntilStackResolved(), + player.isPassedUntilEndStepBeforeMyTurn()); + } + // update open or remove closed graveyard windows + graveyards.put(player.getName(), player.getGraveyard()); + if (graveyardWindows.containsKey(player.getName())) { + CardInfoWindowDialog cardInfoWindowDialog = graveyardWindows.get(player.getName()); + if (cardInfoWindowDialog.isClosed()) { + graveyardWindows.remove(player.getName()); + } else { + cardInfoWindowDialog.loadCards(player.getGraveyard(), bigCard, gameId, false); + } + } + // show top card window + if (player.getTopCard() != null) { + CardsView cardsView = new CardsView(); + cardsView.put(player.getTopCard().getId(), player.getTopCard()); + handleGameInfoWindow(revealed, ShowType.REVEAL_TOP_LIBRARY, player.getName() + "'s top library card", cardsView); + } + } else { + logger.warn("Couldn't find player."); + logger.warn(" uuid:" + player.getPlayerId()); + logger.warn(" players:"); + for (PlayAreaPanel p : players.values()) { + logger.warn("" + p); + } + } + } + if (!menuNameSet) { + StringBuilder sb = new StringBuilder(); + if (playerId == null) { + sb.append("Watching: "); + } else { + sb.append("Playing: "); + } + boolean first = true; + for (PlayerView player : game.getPlayers()) { + if (first) { + first = false; + } else { + sb.append(" - "); + } + sb.append(player.getName()); + } + menuNameSet = true; + gamePane.setTitle(sb.toString()); + } + + GameManager.getInstance().setStackSize(game.getStack().size()); + displayStack(game, bigCard, feedbackPanel, gameId); + + for (ExileView exile : game.getExile()) { + if (!exiles.containsKey(exile.getId())) { + CardInfoWindowDialog newExile = new CardInfoWindowDialog(ShowType.EXILE, exile.getName()); + exiles.put(exile.getId(), newExile); + MageFrame.getDesktop().add(newExile, JLayeredPane.MODAL_LAYER); + newExile.show(); + } + exiles.get(exile.getId()).loadCards(exile, bigCard, gameId); + } + + showRevealed(game); + showLookedAt(game); + if (game.getCombat().size() > 0) { + CombatManager.getInstance().showCombat(game.getCombat(), gameId); + } else { + CombatManager.getInstance().hideCombat(gameId); + } + + for (PlayerView player : game.getPlayers()) { + if (player.hasLeft() && !playersWhoLeft.get(player.getPlayerId())) { + PlayAreaPanel playerLeftPanel = players.get(player.getPlayerId()); + playersWhoLeft.put(player.getPlayerId(), true); + + Container parent = playerLeftPanel.getParent(); + GridBagLayout layout = (GridBagLayout) parent.getLayout(); + + for (Component otherPanel : parent.getComponents()) { + + if (otherPanel instanceof PlayAreaPanel) { + GridBagConstraints gbc = layout.getConstraints(otherPanel); + if (gbc.weightx > 0.1) { + gbc.weightx = 0.99; + } + gbc.fill = GridBagConstraints.BOTH; + gbc.anchor = GridBagConstraints.WEST; + if (gbc.gridx > 0) { + gbc.anchor = GridBagConstraints.EAST; + } + if (otherPanel == playerLeftPanel) { + gbc.weightx = 0.01; + Dimension d = playerLeftPanel.getPreferredSize(); + d.width = 95; + otherPanel.setPreferredSize(d); + } + parent.remove(otherPanel); + parent.add(otherPanel, gbc); + } + } + + parent.validate(); + parent.repaint(); + } + } + + feedbackPanel.disableUndo(); + + this.revalidate(); + this.repaint(); + } + + static final int BORDER_SIZE = 2; + + private void updateSkipButtons(boolean turn, boolean endOfTurn, boolean nextMain, boolean allTurns, boolean stack, boolean endStepBeforeYourStep) { + if (turn) { //F4 + btnSkipToNextTurn.setBorder(new LineBorder(Color.orange, BORDER_SIZE)); + } else { + btnSkipToNextTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); + } + if (endOfTurn) { // F5 + btnSkipToEndTurn.setBorder(new LineBorder(Color.orange, BORDER_SIZE)); + } else { + btnSkipToEndTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); + } + if (nextMain) { // F7 + btnSkipToNextMain.setBorder(new LineBorder(Color.orange, BORDER_SIZE)); + } else { + btnSkipToNextMain.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); + } + if (stack) { // F8 + btnSkipStack.setBorder(new LineBorder(Color.orange, BORDER_SIZE)); + } else { + btnSkipStack.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); + } + if (allTurns) { // F9 + btnSkipToYourTurn.setBorder(new LineBorder(Color.orange, BORDER_SIZE)); + } else { + btnSkipToYourTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); + } + + if (endStepBeforeYourStep) { // F11 + btnSkipToEndStepBeforeYourTurn.setBorder(new LineBorder(Color.orange, BORDER_SIZE)); + } else { + btnSkipToEndStepBeforeYourTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); + } + + } + + /** + * Set the same state for menu selections to all player areas. + * + * @param manaPoolAutomatic + * @param manaPoolAutomaticRestricted + * @param useFirstManaAbility + */ + public void setMenuStates(boolean manaPoolAutomatic, boolean manaPoolAutomaticRestricted, boolean useFirstManaAbility, boolean holdPriority) { + for (PlayAreaPanel playAreaPanel : players.values()) { + playAreaPanel.setMenuStates(manaPoolAutomatic, manaPoolAutomaticRestricted, useFirstManaAbility, holdPriority); + } + } + + private void displayStack(GameView game, BigCard bigCard, FeedbackPanel feedbackPanel, UUID gameId) { + this.stackObjects.loadCards(game.getStack(), bigCard, gameId, true); + } + + /** + * Update phase buttons\labels. + */ + private void updatePhases(PhaseStep step) { + if (step == null) { + logger.warn("step is null"); + return; + } + if (currentStep != null) { + currentStep.setLocation(prevPoint); + } + switch (step) { + case UNTAP: + updateButton("Untap"); + break; + case UPKEEP: + updateButton("Upkeep"); + break; + case DRAW: + updateButton("Draw"); + break; + case PRECOMBAT_MAIN: + updateButton("Main1"); + break; + case BEGIN_COMBAT: + updateButton("Combat_Start"); + break; + case DECLARE_ATTACKERS: + updateButton("Combat_Attack"); + break; + case DECLARE_BLOCKERS: + updateButton("Combat_Block"); + break; + case FIRST_COMBAT_DAMAGE: + case COMBAT_DAMAGE: + updateButton("Combat_Damage"); + break; + case END_COMBAT: + updateButton("Combat_End"); + break; + case POSTCOMBAT_MAIN: + updateButton("Main2"); + break; + case END_TURN: + updateButton("Cleanup"); + break; + } + } + + private void updateButton(String name) { + if (hoverButtons.containsKey(name)) { + currentStep = hoverButtons.get(name); + prevPoint = currentStep.getLocation(); + currentStep.setLocation(prevPoint.x - 15, prevPoint.y); + } + } + + // Called if the game frame is deactivated because the tabled the deck editor or other frames go to foreground + public void deactivated() { + // hide the non modal windows (because otherwise they are shown on top of the new active pane) + for (CardInfoWindowDialog exileDialog : exiles.values()) { + exileDialog.hideDialog(); + } + for (CardInfoWindowDialog graveyardDialog : graveyardWindows.values()) { + graveyardDialog.hideDialog(); + } + for (CardInfoWindowDialog revealDialog : revealed.values()) { + revealDialog.hideDialog(); + } + for (CardInfoWindowDialog lookedAtDialog : lookedAt.values()) { + lookedAtDialog.hideDialog(); + } + } + + // Called if the game frame comes to front again + public void activated() { + // hide the non modal windows (because otherwise they are shown on top of the new active pane) + for (CardInfoWindowDialog exileDialog : exiles.values()) { + exileDialog.show(); + } + for (CardInfoWindowDialog graveyardDialog : graveyardWindows.values()) { + graveyardDialog.show(); + } + for (CardInfoWindowDialog revealDialog : revealed.values()) { + revealDialog.show(); + } + for (CardInfoWindowDialog lookedAtDialog : lookedAt.values()) { + lookedAtDialog.show(); + } + } + + public void openGraveyardWindow(String playerName) { + if (graveyardWindows.containsKey(playerName)) { + CardInfoWindowDialog cardInfoWindowDialog = graveyardWindows.get(playerName); + if (cardInfoWindowDialog.isVisible()) { + cardInfoWindowDialog.hideDialog(); + } else { + cardInfoWindowDialog.show(); + } + return; + } + CardInfoWindowDialog newGraveyard = new CardInfoWindowDialog(ShowType.GRAVEYARD, playerName); + graveyardWindows.put(playerName, newGraveyard); + MageFrame.getDesktop().add(newGraveyard, JLayeredPane.MODAL_LAYER); + newGraveyard.loadCards(graveyards.get(playerName), bigCard, gameId, false); + } + + public void openTopLibraryWindow(String playerName) { + String title = playerName + "'s top library card"; + if (revealed.containsKey(title)) { + CardInfoWindowDialog cardInfoWindowDialog = revealed.get(title); + if (cardInfoWindowDialog.isVisible()) { + cardInfoWindowDialog.hideDialog(); + } else { + cardInfoWindowDialog.show(); + } + } + } + + private void showRevealed(GameView game) { + for (RevealedView revealView : game.getRevealed()) { + handleGameInfoWindow(revealed, ShowType.REVEAL, revealView.getName(), revealView.getCards()); + } + removeClosedCardInfoWindows(revealed); + } + + private void showLookedAt(GameView game) { + for (LookedAtView lookedAtView : game.getLookedAt()) { + handleGameInfoWindow(lookedAt, ShowType.LOOKED_AT, lookedAtView.getName(), lookedAtView.getCards()); + } + removeClosedCardInfoWindows(lookedAt); + } + + private void handleGameInfoWindow(Map windowMap, ShowType showType, String name, LinkedHashMap cardsView) { + CardInfoWindowDialog cardInfoWindowDialog; + if (!windowMap.containsKey(name)) { + cardInfoWindowDialog = new CardInfoWindowDialog(showType, name); + windowMap.put(name, cardInfoWindowDialog); + MageFrame.getDesktop().add(cardInfoWindowDialog, JLayeredPane.MODAL_LAYER); + } else { + cardInfoWindowDialog = windowMap.get(name); + } + + if (cardInfoWindowDialog != null && !cardInfoWindowDialog.isClosed()) { + switch (showType) { + case REVEAL: + case REVEAL_TOP_LIBRARY: + cardInfoWindowDialog.loadCards((CardsView) cardsView, bigCard, gameId); + break; + case LOOKED_AT: + cardInfoWindowDialog.loadCards((SimpleCardsView) cardsView, bigCard, gameId); + break; + } + } + } + + private void removeClosedCardInfoWindows(Map windowMap) { + // Remove closed window objects from the maps + for (Iterator> iterator = windowMap.entrySet().iterator(); iterator.hasNext();) { + Map.Entry entry = iterator.next(); + if (entry.getValue().isClosed()) { + iterator.remove(); + } + } + } + + public void ask(String question, GameView gameView, int messageId, Map options) { + updateGame(gameView); + this.feedbackPanel.getFeedback(FeedbackMode.QUESTION, question, false, options, messageId); + } + + /** + * Shows a pick target dialog and allows the player to pick a target (e.g. + * the pick triggered ability) + * + * @param message + * @param cardView + * @param gameView + * @param targets + * @param required + * @param options + * @param messageId + */ + public void pickTarget(String message, CardsView cardView, GameView gameView, Set targets, boolean required, Map options, int messageId) { + PopUpMenuType popupMenuType = null; + if (options != null) { + if (options.containsKey("targetZone")) { + if (Zone.HAND.equals(options.get("targetZone"))) { // mark selectable target cards in hand + List choosen = null; + if (options.containsKey("chosen")) { + choosen = (List) options.get("chosen"); + } + for (CardView card : gameView.getHand().values()) { + if (targets == null || targets.isEmpty()) { + card.setPlayable(false); + card.setChoosable(true); + } else if (targets.contains(card.getId())) { + card.setPlayable(false); + card.setChoosable(true); + } + if (choosen != null && choosen.contains(card.getId())) { + card.setSelected(true); + } + } + } + } + if (options.containsKey("queryType") && PlayerQueryEvent.QueryType.PICK_ABILITY.equals(options.get("queryType"))) { + popupMenuType = PopUpMenuType.TRIGGER_ORDER; + } + } + updateGame(gameView); + Map options0 = options == null ? new HashMap<>() : options; + ShowCardsDialog dialog = null; + if (cardView != null && cardView.size() > 0) { + dialog = showCards(message, cardView, required, options0, popupMenuType); + options0.put("dialog", dialog); + } + this.feedbackPanel.getFeedback(required ? FeedbackMode.INFORM : FeedbackMode.CANCEL, message, gameView.getSpecial(), options0, messageId); + if (dialog != null) { + this.pickTarget.add(dialog); + } + } + + public void inform(String information, GameView gameView, int messageId) { + updateGame(gameView); + this.feedbackPanel.getFeedback(FeedbackMode.INFORM, information, gameView.getSpecial(), null, messageId); + } + + public void endMessage(String message, int messageId) { + this.feedbackPanel.getFeedback(FeedbackMode.END, message, false, null, messageId); + ArrowBuilder.getBuilder().removeAllArrows(gameId); + } + + public void select(String message, GameView gameView, int messageId, Map options) { + holdingPriority = false; + txtHoldPriority.setVisible(false); + setMenuStates( + PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT, "true").equals("true"), + PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE, "true").equals("true"), + PreferencesDialog.getCachedValue(KEY_USE_FIRST_MANA_ABILITY, "false").equals("true"), + false); + + updateGame(gameView, options); + boolean controllingPlayer = false; + for (PlayerView playerView : gameView.getPlayers()) { + if (playerView.getPlayerId().equals(playerId)) { + // magenoxx: because of uncaught bug with saving state, rolling back and stack + // undo is allowed only for empty stack + controllingPlayer = !gameView.getPriorityPlayerName().equals(playerView.getName()); + if (playerView.getStatesSavedSize() > 0 && gameView.getStack().isEmpty()) { + feedbackPanel.allowUndo(playerView.getStatesSavedSize()); + } + break; + } + + } + Map panelOptions = new HashMap<>(); + if (options != null) { + panelOptions.putAll(options); + } + panelOptions.put("your_turn", true); + String activePlayerText; + if (gameView.getActivePlayerId().equals(playerId)) { + activePlayerText = "Your turn"; + } else { + activePlayerText = gameView.getActivePlayerName() + "'s turn"; + } + String priorityPlayerText = ""; + if (controllingPlayer) { + priorityPlayerText = " / priority " + gameView.getPriorityPlayerName(); + } + String messageToDisplay = message + FeedbackPanel.getSmallText(activePlayerText + " / " + gameView.getStep().toString() + priorityPlayerText); + this.feedbackPanel.getFeedback(FeedbackMode.SELECT, messageToDisplay, gameView.getSpecial(), panelOptions, messageId); + } + + public void playMana(String message, GameView gameView, Map options, int messageId) { + updateGame(gameView); + DialogManager.getManager(gameId).fadeOut(); + this.feedbackPanel.getFeedback(FeedbackMode.CANCEL, message, gameView.getSpecial(), options, messageId); + } + + public void playXMana(String message, GameView gameView, int messageId) { + updateGame(gameView); + DialogManager.getManager(gameId).fadeOut(); + this.feedbackPanel.getFeedback(FeedbackMode.CONFIRM, message, gameView.getSpecial(), null, messageId); + } + + public void replayMessage(String message) { + //TODO: implement this + } + + public void pickAbility(AbilityPickerView choices) { + hideAll(); + DialogManager.getManager(gameId).fadeOut(); + this.abilityPicker.show(choices, MageFrame.getDesktop().getMousePosition()); + } + + private void hideAll() { + ActionCallback callback = Plugins.getInstance().getActionCallback(); + ((MageActionCallback) callback).hideGameUpdate(gameId); + } + + private ShowCardsDialog showCards(String title, CardsView cards, boolean required, Map options, PopUpMenuType popupMenuType) { + hideAll(); + ShowCardsDialog showCards = new ShowCardsDialog(); + JPopupMenu popupMenu = null; + if (PopUpMenuType.TRIGGER_ORDER.equals(popupMenuType)) { + popupMenu = popupMenuTriggerOrder; + } + showCards.loadCards(title, cards, bigCard, gameId, required, options, popupMenu, getShowCardsEventListener(showCards)); + return showCards; + } + + public void getAmount(int min, int max, String message) { + pickNumber.showDialog(min, max, message); + if (pickNumber.isCancel()) { + SessionHandler.sendPlayerBoolean(gameId, false); + } else { + SessionHandler.sendPlayerInteger(gameId, pickNumber.getAmount()); + } + } + + public void getChoice(Choice choice, UUID objectId) { + hideAll(); + PickChoiceDialog pickChoice = new PickChoiceDialog(); + pickChoice.showDialog(choice, objectId, choiceWindowState); + if (choice.isKeyChoice()) { + if (pickChoice.isAutoSelect()) { + SessionHandler.sendPlayerString(gameId, "#" + choice.getChoiceKey()); + } else { + SessionHandler.sendPlayerString(gameId, choice.getChoiceKey()); + } + } else { + SessionHandler.sendPlayerString(gameId, choice.getChoice()); + } + choiceWindowState = new MageDialogState(pickChoice); + pickChoice.removeDialog(); + } + + public void pickPile(String message, CardsView pile1, CardsView pile2) { + hideAll(); + PickPileDialog pickPileDialog = new PickPileDialog(); + pickPileDialog.loadCards(message, pile1, pile2, bigCard, gameId); + SessionHandler.sendPlayerBoolean(gameId, pickPileDialog.isPickedPile1()); + pickPileDialog.cleanUp(); + pickPileDialog.removeDialog(); + } + + public Map getPlayers() { + return players; + } + + @SuppressWarnings("unchecked") + private void initComponents() { + + abilityPicker = new mage.client.components.ability.AbilityPicker(); + jSplitPane1 = new javax.swing.JSplitPane(); + jSplitPane0 = new javax.swing.JSplitPane(); + jPanel2 = new javax.swing.JPanel(); + pnlHelperHandButtonsStackArea = new javax.swing.JPanel(); + pnlShortCuts = new javax.swing.JPanel(); + lblPhase = new javax.swing.JLabel(); + txtPhase = new javax.swing.JLabel(); + lblStep = new javax.swing.JLabel(); + txtStep = new javax.swing.JLabel(); + lblTurn = new javax.swing.JLabel(); + txtTurn = new javax.swing.JLabel(); + txtActivePlayer = new javax.swing.JLabel(); + lblActivePlayer = new javax.swing.JLabel(); + txtPriority = new javax.swing.JLabel(); + lblPriority = new javax.swing.JLabel(); + feedbackPanel = new mage.client.game.FeedbackPanel(); + + txtSpellsCast = new javax.swing.JLabel(); + Border paddingBorder = BorderFactory.createEmptyBorder(4, 4, 4, 4); + Border border = BorderFactory.createLineBorder(Color.DARK_GRAY, 2); + txtSpellsCast.setBorder(BorderFactory.createCompoundBorder(border, paddingBorder)); + txtSpellsCast.setBackground(Color.LIGHT_GRAY); + txtSpellsCast.setOpaque(true); + txtSpellsCast.setToolTipText("spells cast during the current turn"); + + txtHoldPriority = new javax.swing.JLabel(); + txtHoldPriority.setText("Hold"); + txtHoldPriority.setBorder(BorderFactory.createCompoundBorder(border, paddingBorder)); + txtHoldPriority.setBackground(Color.LIGHT_GRAY); + txtHoldPriority.setOpaque(true); + txtHoldPriority.setToolTipText("Holding priority after the next spell cast or ability activation"); + txtHoldPriority.setVisible(false); + + btnCancelSkip = new KeyboundButton(KEY_CONTROL_CANCEL_SKIP); // F3 + btnSkipToNextTurn = new KeyboundButton(KEY_CONTROL_NEXT_TURN); // F4 + btnSkipToEndTurn = new KeyboundButton(KEY_CONTROL_END_STEP); // F5 + btnSkipToNextMain = new KeyboundButton(KEY_CONTROL_MAIN_STEP); // F7 + btnSkipStack = new KeyboundButton(KEY_CONTROL_SKIP_STACK); // F10 + btnSkipToYourTurn = new KeyboundButton(KEY_CONTROL_YOUR_TURN); // F9 + btnSkipToEndStepBeforeYourTurn = new KeyboundButton(KEY_CONTROL_PRIOR_END); // F11 + + btnConcede = new javax.swing.JButton(); + btnSwitchHands = new javax.swing.JButton(); + btnStopWatching = new javax.swing.JButton(); + + bigCard = new mage.client.cards.BigCard(); + pnlReplay = new javax.swing.JPanel(); + btnStopReplay = new javax.swing.JButton(); + btnNextPlay = new javax.swing.JButton(); + btnPlay = new javax.swing.JButton(); + btnSkipForward = new javax.swing.JButton(); + btnPreviousPlay = new javax.swing.JButton(); + pnlBattlefield = new javax.swing.JPanel(); + gameChatPanel = new mage.client.chat.ChatPanelBasic(); + gameChatPanel.useExtendedView(ChatPanelBasic.VIEW_MODE.GAME); + userChatPanel = new mage.client.chat.ChatPanelBasic(); + userChatPanel.setParentChat(gameChatPanel); + userChatPanel.useExtendedView(ChatPanelBasic.VIEW_MODE.CHAT); + userChatPanel.setChatType(ChatPanelBasic.ChatType.GAME); + gameChatPanel.setConnectedChat(userChatPanel); + gameChatPanel.disableInput(); + gameChatPanel.setMinimumSize(new java.awt.Dimension(100, 48)); + gameChatPanel.enableHyperlinks(); + jSplitPane2 = new javax.swing.JSplitPane(); + handContainer = new HandPanel(); + handCards = new HashMap<>(); + + pnlShortCuts.setOpaque(false); + pnlShortCuts.setPreferredSize(new Dimension(410, 72)); + + stackObjects = new mage.client.cards.Cards(); + + jSplitPane1.setBorder(null); + jSplitPane1.setDividerSize(7); + jSplitPane1.setResizeWeight(1.0); + jSplitPane1.setOneTouchExpandable(true); + jSplitPane1.setMinimumSize(new java.awt.Dimension(26, 48)); + + jSplitPane0.setBorder(null); + jSplitPane0.setDividerSize(7); + jSplitPane0.setResizeWeight(1.0); + jSplitPane0.setOneTouchExpandable(true); + + restoreDividerLocations(); + + lblPhase.setLabelFor(txtPhase); + lblPhase.setText("Phase:"); + + txtPhase.setText("Phase"); + txtPhase.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(153, 153, 153), 1, true)); + txtPhase.setMinimumSize(new java.awt.Dimension(0, 16)); + + lblStep.setLabelFor(txtStep); + lblStep.setText("Step:"); + + txtStep.setText("Step"); + txtStep.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(153, 153, 153), 1, true)); + txtStep.setMinimumSize(new java.awt.Dimension(0, 16)); + + lblTurn.setLabelFor(txtTurn); + lblTurn.setText("Turn:"); + + txtTurn.setText("Turn"); + txtTurn.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(153, 153, 153), 1, true)); + txtTurn.setMinimumSize(new java.awt.Dimension(0, 16)); + + txtActivePlayer.setText("Active Player"); + txtActivePlayer.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(153, 153, 153), 1, true)); + txtActivePlayer.setMinimumSize(new java.awt.Dimension(0, 16)); + + lblActivePlayer.setLabelFor(txtActivePlayer); + lblActivePlayer.setText("Active Player:"); + + txtPriority.setText("Priority Player"); + txtPriority.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(153, 153, 153), 1, true)); + txtPriority.setMinimumSize(new java.awt.Dimension(0, 16)); + + lblPriority.setLabelFor(txtPriority); + lblPriority.setText("Priority Player:"); + + bigCard.setBorder(new LineBorder(Color.black, 1, true)); + + int c = JComponent.WHEN_IN_FOCUSED_WINDOW; + + KeyStroke ks3 = getCachedKeystroke(KEY_CONTROL_CANCEL_SKIP); + this.getInputMap(c).put(ks3, "F3_PRESS"); + this.getActionMap().put("F3_PRESS", new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + restorePriorityActionPerformed(actionEvent); + } + }); + + btnCancelSkip.setContentAreaFilled(false); + btnCancelSkip.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); + btnCancelSkip.setIcon(new ImageIcon(ImageManagerImpl.getInstance().getCancelSkipButtonImage())); + btnCancelSkip.setToolTipText("Cancel all skip actions (" + + getCachedKeyText(KEY_CONTROL_CANCEL_SKIP) + ")."); + btnCancelSkip.setFocusable(false); + btnCancelSkip.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent evt) { + if (evt.getButton() == MouseEvent.BUTTON1) { + restorePriorityActionPerformed(null); + } + } + }); + + btnSkipToNextTurn.setContentAreaFilled(false); + btnSkipToNextTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); + btnSkipToNextTurn.setIcon(new ImageIcon(ImageManagerImpl.getInstance().getSkipNextTurnButtonImage())); + btnSkipToNextTurn.setToolTipText("Skip to next turn (" + + getCachedKeyText(KEY_CONTROL_NEXT_TURN) + ")."); + btnSkipToNextTurn.setFocusable(false); + btnSkipToNextTurn.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent evt) { + if (evt.getButton() == MouseEvent.BUTTON1) { + btnEndTurnActionPerformed(null); + } + } + }); + + KeyStroke ks = getCachedKeystroke(KEY_CONTROL_NEXT_TURN); + this.getInputMap(c).put(ks, "F4_PRESS"); + this.getActionMap().put("F4_PRESS", new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + btnEndTurnActionPerformed(actionEvent); + } + }); + + btnSkipToEndTurn.setContentAreaFilled(false); + btnSkipToEndTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); + btnSkipToEndTurn.setIcon(new ImageIcon(ImageManagerImpl.getInstance().getSkipEndTurnButtonImage())); + btnSkipToEndTurn.setToolTipText("Skip to (opponents/next) end of turn step (" + + getCachedKeyText(KEY_CONTROL_END_STEP) + ") - adjust using preferences."); + btnSkipToEndTurn.setFocusable(false); + btnSkipToEndTurn.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent evt) { + if (evt.getButton() == MouseEvent.BUTTON1) { + btnUntilEndOfTurnActionPerformed(null); + } + } + }); + + ks = getCachedKeystroke(KEY_CONTROL_END_STEP); + this.getInputMap(c).put(ks, "F5_PRESS"); + this.getActionMap().put("F5_PRESS", new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + btnUntilEndOfTurnActionPerformed(actionEvent); + } + }); + + ks = getCachedKeystroke(KEY_CONTROL_SKIP_STEP); + this.getInputMap(c).put(ks, "F6_PRESS"); + this.getActionMap().put("F6_PRESS", new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + btnEndTurnSkipStackActionPerformed(actionEvent); + } + }); + + btnSkipToNextMain.setContentAreaFilled(false); + btnSkipToNextMain.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); + btnSkipToNextMain.setIcon(new ImageIcon(ImageManagerImpl.getInstance().getSkipMainButtonImage())); + btnSkipToNextMain.setToolTipText("Skip to (your) next main phase (" + + getCachedKeyText(KEY_CONTROL_MAIN_STEP) + ") - adjust using preferences."); + btnSkipToNextMain.setFocusable(false); + btnSkipToNextMain.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent evt) { + if (evt.getButton() == MouseEvent.BUTTON1) { + btnUntilNextMainPhaseActionPerformed(null); + } + } + }); + + ks = getCachedKeystroke(KEY_CONTROL_MAIN_STEP); + this.getInputMap(c).put(ks, "F7_PRESS"); + this.getActionMap().put("F7_PRESS", new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + btnUntilNextMainPhaseActionPerformed(actionEvent); + } + }); + + btnSkipToYourTurn.setContentAreaFilled(false); + btnSkipToYourTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); + btnSkipToYourTurn.setIcon(new ImageIcon(ImageManagerImpl.getInstance().getSkipYourNextTurnButtonImage())); + btnSkipToYourTurn.setToolTipText("Skip to your next turn (" + + getCachedKeyText(KEY_CONTROL_YOUR_TURN) + ")."); + btnSkipToYourTurn.setFocusable(false); + btnSkipToYourTurn.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent evt) { + if (evt.getButton() == MouseEvent.BUTTON1) { + btnPassPriorityUntilNextYourTurnActionPerformed(null); + } + } + }); + + KeyStroke ks9 = getCachedKeystroke(KEY_CONTROL_YOUR_TURN); + this.getInputMap(c).put(ks9, "F9_PRESS"); + this.getActionMap().put("F9_PRESS", new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + btnPassPriorityUntilNextYourTurnActionPerformed(actionEvent); + } + }); + + btnSkipToEndStepBeforeYourTurn.setContentAreaFilled(false); + btnSkipToEndStepBeforeYourTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); + btnSkipToEndStepBeforeYourTurn.setIcon(new ImageIcon(ImageManagerImpl.getInstance().getSkipEndStepBeforeYourTurnButtonImage())); + btnSkipToEndStepBeforeYourTurn.setToolTipText("Skip to the end step before your turn (" + + getCachedKeyText(KEY_CONTROL_PRIOR_END) + ") - adjust using preferences."); + btnSkipToEndStepBeforeYourTurn.setFocusable(false); + btnSkipToEndStepBeforeYourTurn.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent evt) { + if (evt.getButton() == MouseEvent.BUTTON1) { + btnSkipToEndStepBeforeYourTurnActionPerformed(null); + } + } + }); + + KeyStroke ks11 = getCachedKeystroke(KEY_CONTROL_PRIOR_END); + this.getInputMap(c).put(ks11, "F11_PRESS"); + this.getActionMap().put("F11_PRESS", new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + btnSkipToEndStepBeforeYourTurnActionPerformed(actionEvent); + } + }); + + btnSkipStack.setContentAreaFilled(false); + btnSkipStack.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); + btnSkipStack.setIcon(new ImageIcon(ImageManagerImpl.getInstance().getSkipStackButtonImage())); + btnSkipStack.setToolTipText("Skip until stack is resolved (" + + getCachedKeyText(KEY_CONTROL_SKIP_STACK) + ")."); + btnSkipStack.setFocusable(false); + btnSkipStack.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent evt) { + if (evt.getButton() == MouseEvent.BUTTON1) { + btnPassPriorityUntilStackResolvedActionPerformed(null); + } + } + }); + + ks = getCachedKeystroke(KEY_CONTROL_SKIP_STACK); + this.getInputMap(c).put(ks, "F10_PRESS"); + this.getActionMap().put("F10_PRESS", new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + btnPassPriorityUntilStackResolvedActionPerformed(actionEvent); + } + }); + + btnConcede.setContentAreaFilled(false); + btnConcede.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE)); + btnConcede.setIcon(new ImageIcon(ImageManagerImpl.getInstance().getConcedeButtonImage())); + btnConcede.setToolTipText("Concede the current game."); + btnConcede.setFocusable(false); + btnConcede.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent evt) { + if (evt.getButton() == MouseEvent.BUTTON1) { + btnConcedeActionPerformed(null); + } + } + }); + + KeyStroke ks2 = getCachedKeystroke(KEY_CONTROL_CONFIRM); + this.getInputMap(c).put(ks2, "F2_PRESS"); + this.getActionMap().put("F2_PRESS", new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + if (feedbackPanel != null) { + feedbackPanel.pressOKYesOrDone(); + } + } + }); + + KeyStroke ksAltE = KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.ALT_MASK); + this.getInputMap(c).put(ksAltE, "ENLARGE"); + this.getActionMap().put("ENLARGE", new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + ActionCallback callback = Plugins.getInstance().getActionCallback(); + ((MageActionCallback) callback).enlargeCard(EnlargeMode.NORMAL); + } + }); + + KeyStroke ksAltS = KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.ALT_MASK); + this.getInputMap(c).put(ksAltS, "ENLARGE_SOURCE"); + this.getActionMap().put("ENLARGE_SOURCE", new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + ActionCallback callback = Plugins.getInstance().getActionCallback(); + ((MageActionCallback) callback).enlargeCard(EnlargeMode.ALTERNATE); + } + }); + + KeyStroke ksAltD = KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.ALT_MASK); + this.getInputMap(c).put(ksAltD, "BIG_IMAGE"); + this.getActionMap().put("BIG_IMAGE", new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + imagePanelState = !imagePanelState; + if (!imagePanelState) { + jSplitPane0.resetToPreferredSizes(); + jSplitPane0.setDividerLocation(jSplitPane0.getSize().width - jSplitPane0.getInsets().right - jSplitPane0.getDividerSize() - 260); + } else { + jSplitPane0.setDividerLocation(1.0); + } + } + }); + + KeyStroke ksAlt1 = KeyStroke.getKeyStroke(KeyEvent.VK_1, InputEvent.ALT_MASK); + this.getInputMap(c).put(ksAlt1, "USEFIRSTMANAABILITY"); + this.getActionMap().put("USEFIRSTMANAABILITY", new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + SessionHandler.sendPlayerAction(PlayerAction.USE_FIRST_MANA_ABILITY_ON, gameId, null); + setMenuStates( + PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT, "true").equals("true"), + PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE, "true").equals("true"), + PreferencesDialog.getCachedValue(KEY_USE_FIRST_MANA_ABILITY, "false").equals("true"), + holdingPriority); + } + }); + + final BasicSplitPaneUI myUi = (BasicSplitPaneUI) jSplitPane0.getUI(); + final BasicSplitPaneDivider divider = myUi.getDivider(); + final JButton upArrowButton = (JButton) divider.getComponent(0); + upArrowButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + PreferencesDialog.saveValue(PreferencesDialog.KEY_BIG_CARD_TOGGLED, "up"); + } + }); + + final JButton downArrowButton = (JButton) divider.getComponent(1); + downArrowButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + PreferencesDialog.saveValue(PreferencesDialog.KEY_BIG_CARD_TOGGLED, "down"); + } + }); + + KeyStroke ksAltEReleased = KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.ALT_MASK, true); + this.getInputMap(c).put(ksAltEReleased, "ENLARGE_RELEASE"); + KeyStroke ksAltSReleased = KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.ALT_MASK, true); + this.getInputMap(c).put(ksAltSReleased, "ENLARGE_RELEASE"); + this.getActionMap().put("ENLARGE_RELEASE", new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + ActionCallback callback = Plugins.getInstance().getActionCallback(); + ((MageActionCallback) callback).hideEnlargedCard(); + } + }); + + KeyStroke ksAlt1Released = KeyStroke.getKeyStroke(KeyEvent.VK_1, InputEvent.ALT_MASK, true); + this.getInputMap(c).put(ksAlt1Released, "USEFIRSTMANAABILITY_RELEASE"); + this.getActionMap().put("USEFIRSTMANAABILITY_RELEASE", new AbstractAction() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + SessionHandler.sendPlayerAction(PlayerAction.USE_FIRST_MANA_ABILITY_OFF, gameId, null); + setMenuStates( + PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT, "true").equals("true"), + PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE, "true").equals("true"), + PreferencesDialog.getCachedValue(KEY_USE_FIRST_MANA_ABILITY, "false").equals("true"), + holdingPriority); + } + }); + + btnSwitchHands.setContentAreaFilled(false); + btnSwitchHands.setBorder(new EmptyBorder(0, 0, 0, 0)); + btnSwitchHands.setIcon(new ImageIcon(ImageManagerImpl.getInstance().getSwitchHandsButtonImage())); + btnSwitchHands.setFocusable(false); + btnSwitchHands.setToolTipText("Switch between your hand cards and hand cards of controlled players."); + btnSwitchHands.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent evt) { + if (evt.getButton() == MouseEvent.BUTTON1) { + btnSwitchHandActionPerformed(null); + } + } + }); + + btnStopWatching.setContentAreaFilled(false); + btnStopWatching.setBorder(new EmptyBorder(0, 0, 0, 0)); + btnStopWatching.setIcon(new ImageIcon(ImageManagerImpl.getInstance().getStopWatchButtonImage())); + btnStopWatching.setFocusable(false); + btnStopWatching.setToolTipText("Stop watching this game."); + btnStopWatching.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent evt) { + if (evt.getButton() == MouseEvent.BUTTON1) { + btnStopWatchingActionPerformed(null); + } + } + }); + + stackObjects.setBackgroundColor(new Color(0, 0, 0, 40)); + + btnStopReplay.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/control_stop.png"))); + btnStopReplay.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnStopReplayActionPerformed(evt); + } + }); + + btnNextPlay.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/control_stop_right.png"))); + btnNextPlay.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnNextPlayActionPerformed(evt); + } + }); + + btnPlay.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/control_right.png"))); + btnPlay.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnPlayActionPerformed(evt); + } + }); + + btnSkipForward.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/control_double_stop_right.png"))); + btnSkipForward.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnSkipForwardActionPerformed(evt); + } + }); + + btnPreviousPlay.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/control_stop_left.png"))); + btnPreviousPlay.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnPreviousPlayActionPerformed(evt); + } + }); + + initPopupMenuTriggerOrder(); + + setGUISize(); + + // Replay panel to control replay of games + javax.swing.GroupLayout gl_pnlReplay = new javax.swing.GroupLayout(pnlReplay); + pnlReplay.setLayout(gl_pnlReplay); + gl_pnlReplay.setHorizontalGroup( + gl_pnlReplay.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(gl_pnlReplay.createSequentialGroup() + .addComponent(btnPreviousPlay, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnPlay, javax.swing.GroupLayout.PREFERRED_SIZE, 35, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnStopReplay, javax.swing.GroupLayout.PREFERRED_SIZE, 38, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnNextPlay, javax.swing.GroupLayout.PREFERRED_SIZE, 36, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnSkipForward, javax.swing.GroupLayout.PREFERRED_SIZE, 39, javax.swing.GroupLayout.PREFERRED_SIZE)) + ); + gl_pnlReplay.setVerticalGroup( + gl_pnlReplay.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(btnSkipForward, 0, 0, Short.MAX_VALUE) + .addComponent(btnNextPlay, 0, 0, Short.MAX_VALUE) + .addComponent(btnStopReplay, 0, 0, Short.MAX_VALUE) + .addComponent(btnPlay, 0, 0, Short.MAX_VALUE) + .addComponent(btnPreviousPlay, javax.swing.GroupLayout.PREFERRED_SIZE, 31, Short.MAX_VALUE) + ); + + // Game info panel (buttons on the right panel) + javax.swing.GroupLayout gl_pnlShortCuts = new javax.swing.GroupLayout(pnlShortCuts); + pnlShortCuts.setLayout(gl_pnlShortCuts); + gl_pnlShortCuts.setHorizontalGroup(gl_pnlShortCuts.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(gl_pnlShortCuts.createSequentialGroup() + .addComponent(btnSkipToNextTurn) + .addComponent(btnSkipToEndTurn) + .addComponent(btnSkipToNextMain) + .addComponent(btnSkipToYourTurn) + .addComponent(btnSkipStack) + .addComponent(btnSkipToEndStepBeforeYourTurn) + ) + .addGroup(gl_pnlShortCuts.createSequentialGroup() + .addComponent(txtHoldPriority) + .addComponent(txtSpellsCast) + .addComponent(btnSwitchHands) + .addComponent(btnCancelSkip) + .addComponent(btnConcede) + .addComponent(btnStopWatching) + ) + //.addComponent(bigCard, javax.swing.GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE) + //.addComponent(feedbackPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE) + //.addComponent(stack, javax.swing.GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE) + + .addGroup(gl_pnlShortCuts.createSequentialGroup() + .addContainerGap() + .addComponent(pnlReplay, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(51, Short.MAX_VALUE)) + ); + gl_pnlShortCuts.setVerticalGroup(gl_pnlShortCuts.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(gl_pnlShortCuts.createSequentialGroup() + //.addComponent(bigCard, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + //.addGap(1, 1, 1) + //.addComponent(feedbackPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 109, javax.swing.GroupLayout.PREFERRED_SIZE) + //.addComponent(stack, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 164, Short.MAX_VALUE) + .addComponent(pnlReplay, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(gl_pnlShortCuts.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(btnSkipToNextTurn) + .addComponent(btnSkipToEndTurn) + .addComponent(btnSkipToNextMain) + .addComponent(btnSkipToYourTurn) + .addComponent(btnSkipStack) + .addComponent(btnSkipToEndStepBeforeYourTurn) + ) + .addGroup(gl_pnlShortCuts.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(txtHoldPriority) + .addComponent(txtSpellsCast) + .addComponent(btnSwitchHands) + .addComponent(btnCancelSkip) + .addComponent(btnConcede) + .addComponent(btnStopWatching) + ) + ) + ); + + pnlBattlefield.setLayout(new java.awt.GridBagLayout()); + + jPhases = new JPanel(); + jPhases.setBackground(new Color(0, 0, 0, 0)); + jPhases.setLayout(null); + jPhases.setPreferredSize(new Dimension(X_PHASE_WIDTH, 435)); + + MouseAdapter phasesMouseAdapter = new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent evt) { + mouseClickPhaseBar(evt); + } + }; + String[] phases = {"Untap", "Upkeep", "Draw", "Main1", + "Combat_Start", "Combat_Attack", "Combat_Block", "Combat_Damage", "Combat_End", + "Main2", "Cleanup", "Next_Turn"}; + for (String name : phases) { + createPhaseButton(name, phasesMouseAdapter); + } + + int i = 0; + for (String name : hoverButtons.keySet()) { + HoverButton hoverButton = hoverButtons.get(name); + hoverButton.setAlignmentX(LEFT_ALIGNMENT); + hoverButton.setBounds(X_PHASE_WIDTH - 36, i * 36, 36, 36); + jPhases.add(hoverButton); + i++; + } + jPhases.addMouseListener(phasesMouseAdapter); + + pnlReplay.setOpaque(false); + + helper = new HelperPanel(); + feedbackPanel.setHelperPanel(helper); + + jSplitPane2.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); + jSplitPane2.setResizeWeight(0.5); + jSplitPane2.setLeftComponent(userChatPanel); + jSplitPane2.setBottomComponent(gameChatPanel); + + phasesContainer = new JPanel(); + phasesContainer.setLayout(new RelativeLayout(RelativeLayout.Y_AXIS)); + phasesContainer.setBackground(new Color(0, 0, 0, 0)); + Float ratio = (float) 1; + JPanel empty1 = new JPanel(); + empty1.setBackground(new Color(0, 0, 0, 0)); + phasesContainer.add(empty1, ratio); + phasesContainer.add(jPhases); + + javax.swing.GroupLayout gl_helperHandButtonsStackArea = new javax.swing.GroupLayout(pnlHelperHandButtonsStackArea); + gl_helperHandButtonsStackArea.setHorizontalGroup( + gl_helperHandButtonsStackArea.createParallelGroup(Alignment.LEADING) + .addGroup(gl_helperHandButtonsStackArea.createSequentialGroup() + // .addGap(0) + .addGroup(gl_helperHandButtonsStackArea.createParallelGroup(Alignment.LEADING) + .addGroup(gl_helperHandButtonsStackArea.createSequentialGroup() + .addGroup(gl_helperHandButtonsStackArea.createParallelGroup(Alignment.LEADING) + .addComponent(helper, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(handContainer, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ) + .addGroup(gl_helperHandButtonsStackArea.createParallelGroup(Alignment.LEADING) + .addComponent(pnlShortCuts, 410, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE) + .addComponent(stackObjects, 410, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE) + ) + ) + .addGap(0) + //.addComponent(jPhases, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(gl_helperHandButtonsStackArea.createSequentialGroup() + .addComponent(pnlBattlefield, GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE) + .addComponent(phasesContainer, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + ))) + ); + gl_helperHandButtonsStackArea.setVerticalGroup( + gl_helperHandButtonsStackArea.createParallelGroup(Alignment.TRAILING) + .addGroup(gl_helperHandButtonsStackArea.createSequentialGroup() + .addGroup(gl_helperHandButtonsStackArea.createParallelGroup(Alignment.LEADING) + .addComponent(pnlBattlefield, GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE) + .addComponent(phasesContainer, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + ) + //.addPreferredGap(ComponentPlacement.RELATED) + .addGroup(gl_helperHandButtonsStackArea.createParallelGroup(Alignment.LEADING) + .addGroup(gl_helperHandButtonsStackArea.createSequentialGroup() + .addGap(2) + .addComponent(pnlShortCuts, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addComponent(stackObjects, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + ) + .addGroup(gl_helperHandButtonsStackArea.createSequentialGroup() + .addComponent(helper, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addComponent(handContainer, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + ) + ) + ) + ); + pnlHelperHandButtonsStackArea.setLayout(gl_helperHandButtonsStackArea); + + jSplitPane1.setLeftComponent(pnlHelperHandButtonsStackArea); + jSplitPane1.setRightComponent(jSplitPane2); + + // Set individual area sizes of big card pane + GridBagLayout gbl = new GridBagLayout(); + jPanel2.setLayout(gbl); + + GridBagConstraints gbc = new GridBagConstraints(); + gbc.fill = GridBagConstraints.BOTH; + gbc.gridx = 0; + gbc.gridy = 0; + gbc.gridwidth = 1; + gbc.gridheight = 4; // size 4/5 + gbc.weightx = 1.0; + gbc.weighty = 1.0; + gbl.setConstraints(bigCard, gbc); + jPanel2.add(bigCard); + + jPanel2.setOpaque(false); + + // game pane and chat/log pane + jSplitPane0.setLeftComponent(jSplitPane1); + // big card and buttons + jSplitPane0.setRightComponent(jPanel2); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jSplitPane0, javax.swing.GroupLayout.DEFAULT_SIZE, 1078, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jSplitPane0, javax.swing.GroupLayout.DEFAULT_SIZE, 798, Short.MAX_VALUE) + ); + } + + private void removeListener() { + for (MouseListener ml : this.getMouseListeners()) { + this.removeMouseListener(ml); + } + for (MouseListener ml : this.btnCancelSkip.getMouseListeners()) { + this.btnCancelSkip.removeMouseListener(ml); + } + for (MouseListener ml : this.btnConcede.getMouseListeners()) { + this.btnConcede.removeMouseListener(ml); + } + for (MouseListener ml : this.btnSkipToYourTurn.getMouseListeners()) { + this.btnSkipToYourTurn.removeMouseListener(ml); + } + for (MouseListener ml : this.btnSkipStack.getMouseListeners()) { + this.btnSkipStack.removeMouseListener(ml); + } + for (MouseListener ml : this.btnSkipToEndStepBeforeYourTurn.getMouseListeners()) { + this.btnSkipToEndStepBeforeYourTurn.removeMouseListener(ml); + } + for (MouseListener ml : this.btnSkipToEndTurn.getMouseListeners()) { + this.btnSkipToEndTurn.removeMouseListener(ml); + } + for (MouseListener ml : this.btnSkipToNextMain.getMouseListeners()) { + this.btnSkipToNextMain.removeMouseListener(ml); + } + for (MouseListener ml : this.btnSkipToNextTurn.getMouseListeners()) { + this.btnSkipToNextTurn.removeMouseListener(ml); + } + for (MouseListener ml : this.btnSwitchHands.getMouseListeners()) { + this.btnSwitchHands.removeMouseListener(ml); + } + for (MouseListener ml : this.btnStopWatching.getMouseListeners()) { + this.btnStopWatching.removeMouseListener(ml); + } + for (MouseListener ml : this.jPhases.getMouseListeners()) { + this.jPhases.removeMouseListener(ml); + } + for (String name : hoverButtons.keySet()) { + HoverButton hoverButton = hoverButtons.get(name); + for (MouseListener ml : hoverButton.getMouseListeners()) { + hoverButton.removeMouseListener(ml); + } + } + for (ActionListener al : this.btnPlay.getActionListeners()) { + this.btnPlay.removeActionListener(al); + } + for (ActionListener al : this.btnStopReplay.getActionListeners()) { + this.btnStopReplay.removeActionListener(al); + } + for (ActionListener al : this.btnNextPlay.getActionListeners()) { + this.btnNextPlay.removeActionListener(al); + } + for (ActionListener al : this.btnNextPlay.getActionListeners()) { + this.btnNextPlay.removeActionListener(al); + } + for (ActionListener al : this.btnPreviousPlay.getActionListeners()) { + this.btnPreviousPlay.removeActionListener(al); + } + for (ActionListener al : this.btnSkipForward.getActionListeners()) { + this.btnSkipForward.removeActionListener(al); + } + + final BasicSplitPaneUI myUi = (BasicSplitPaneUI) jSplitPane0.getUI(); + final BasicSplitPaneDivider divider = myUi.getDivider(); + final JButton upArrowButton = (JButton) divider.getComponent(0); + for (ActionListener al : upArrowButton.getActionListeners()) { + upArrowButton.removeActionListener(al); + } + final JButton downArrowButton = (JButton) divider.getComponent(1); + for (ActionListener al : downArrowButton.getActionListeners()) { + downArrowButton.removeActionListener(al); + } + + for (ComponentListener cl : this.getComponentListeners()) { + this.removeComponentListener(cl); + } + } + + private void btnConcedeActionPerformed(java.awt.event.ActionEvent evt) { + UserRequestMessage message = new UserRequestMessage("Confirm concede", "Are you sure you want to concede?"); + message.setButton1("No", null); + message.setButton2("Yes", PlayerAction.CLIENT_CONCEDE_GAME); + message.setGameId(gameId); + MageFrame.getInstance().showUserRequestDialog(message); + } + + private void btnEndTurnActionPerformed(java.awt.event.ActionEvent evt) { + SessionHandler.sendPlayerAction(PlayerAction.PASS_PRIORITY_UNTIL_NEXT_TURN, gameId, null); + AudioManager.playOnSkipButton(); + updateSkipButtons(true, false, false, false, false, false); + } + + private void btnUntilEndOfTurnActionPerformed(java.awt.event.ActionEvent evt) { + SessionHandler.sendPlayerAction(PlayerAction.PASS_PRIORITY_UNTIL_TURN_END_STEP, gameId, null); + AudioManager.playOnSkipButton(); + updateSkipButtons(false, true, false, false, false, false); + } + + private void btnEndTurnSkipStackActionPerformed(java.awt.event.ActionEvent evt) { + SessionHandler.sendPlayerAction(PlayerAction.PASS_PRIORITY_UNTIL_NEXT_TURN_SKIP_STACK, gameId, null); + AudioManager.playOnSkipButton(); + updateSkipButtons(true, false, false, false, true, false); + } + + private void btnUntilNextMainPhaseActionPerformed(java.awt.event.ActionEvent evt) { + SessionHandler.sendPlayerAction(PlayerAction.PASS_PRIORITY_UNTIL_NEXT_MAIN_PHASE, gameId, null); + AudioManager.playOnSkipButton(); + updateSkipButtons(false, false, true, false, false, false); + } + + private void btnPassPriorityUntilNextYourTurnActionPerformed(java.awt.event.ActionEvent evt) { + SessionHandler.sendPlayerAction(PlayerAction.PASS_PRIORITY_UNTIL_MY_NEXT_TURN, gameId, null); + AudioManager.playOnSkipButton(); + updateSkipButtons(false, false, false, true, false, false); + } + + private void btnPassPriorityUntilStackResolvedActionPerformed(java.awt.event.ActionEvent evt) { + SessionHandler.sendPlayerAction(PlayerAction.PASS_PRIORITY_UNTIL_STACK_RESOLVED, gameId, null); + AudioManager.playOnSkipButton(); + updateSkipButtons(false, false, false, false, true, false); + } + + private void btnSkipToEndStepBeforeYourTurnActionPerformed(java.awt.event.ActionEvent evt) { + SessionHandler.sendPlayerAction(PlayerAction.PASS_PRIORITY_UNTIL_END_STEP_BEFORE_MY_NEXT_TURN, gameId, null); + AudioManager.playOnSkipButton(); + updateSkipButtons(false, false, false, false, false, true); + } + + private void restorePriorityActionPerformed(java.awt.event.ActionEvent evt) { + SessionHandler.sendPlayerAction(PlayerAction.PASS_PRIORITY_CANCEL_ALL_ACTIONS, gameId, null); + AudioManager.playOnSkipButtonCancel(); + updateSkipButtons(false, false, false, false, false, false); + } + + private void mouseClickPhaseBar(MouseEvent evt) { + if (evt.getButton() == MouseEvent.BUTTON1) { // Left button + PreferencesDialog.main(new String[]{PreferencesDialog.OPEN_PHASES_TAB}); + } + } + + private void btnSwitchHandActionPerformed(java.awt.event.ActionEvent evt) { + String[] choices = handCards.keySet().toArray(new String[0]); + + String newChosenHandKey = (String) JOptionPane.showInputDialog( + this, + "Choose hand to display:", "Switch between hands", + JOptionPane.PLAIN_MESSAGE, + null, + choices, + this.chosenHandKey); + + if (newChosenHandKey != null && newChosenHandKey.length() > 0) { + this.chosenHandKey = newChosenHandKey; + CardsView cards = handCards.get(chosenHandKey); + handContainer.loadCards(cards, bigCard, gameId); + } + } private void btnStopWatchingActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnStopWatchingActionPerformed - UserRequestMessage message = new UserRequestMessage("Stop watching", "Are you sure you want to stop watching?"); - message.setButton1("No", null); - message.setButton2("Yes", PlayerAction.CLIENT_STOP_WATCHING); - message.setGameId(gameId); - MageFrame.getInstance().showUserRequestDialog(message); + UserRequestMessage message = new UserRequestMessage("Stop watching", "Are you sure you want to stop watching?"); + message.setButton1("No", null); + message.setButton2("Yes", PlayerAction.CLIENT_STOP_WATCHING); + message.setGameId(gameId); + MageFrame.getInstance().showUserRequestDialog(message); }//GEN-LAST:event_btnStopWatchingActionPerformed private void btnStopReplayActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnStopReplayActionPerformed - if (replayTask != null && !replayTask.isDone()) { - replayTask.cancel(true); - } else { - UserRequestMessage message = new UserRequestMessage("Stop replay", "Are you sure you want to stop replay?"); - message.setButton1("No", null); - message.setButton2("Yes", PlayerAction.CLIENT_REPLAY_ACTION); - message.setGameId(gameId); - MageFrame.getInstance().showUserRequestDialog(message); - } + if (replayTask != null && !replayTask.isDone()) { + replayTask.cancel(true); + } else { + UserRequestMessage message = new UserRequestMessage("Stop replay", "Are you sure you want to stop replay?"); + message.setButton1("No", null); + message.setButton2("Yes", PlayerAction.CLIENT_REPLAY_ACTION); + message.setGameId(gameId); + MageFrame.getInstance().showUserRequestDialog(message); + } }//GEN-LAST:event_btnStopReplayActionPerformed private void btnNextPlayActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnNextPlayActionPerformed - SessionHandler.nextPlay(gameId); + SessionHandler.nextPlay(gameId); }//GEN-LAST:event_btnNextPlayActionPerformed private void btnPreviousPlayActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnPreviousPlayActionPerformed - SessionHandler.previousPlay(gameId); + SessionHandler.previousPlay(gameId); }//GEN-LAST:event_btnPreviousPlayActionPerformed private void btnPlayActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnPlayActionPerformed - if (replayTask == null || replayTask.isDone()) { - replayTask = new ReplayTask(gameId); - replayTask.execute(); - } + if (replayTask == null || replayTask.isDone()) { + replayTask = new ReplayTask(gameId); + replayTask.execute(); + } }//GEN-LAST:event_btnPlayActionPerformed private void btnSkipForwardActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSkipForwardActionPerformed - SessionHandler.skipForward(gameId, 10); + SessionHandler.skipForward(gameId, 10); }//GEN-LAST:event_btnSkipForwardActionPerformed - public void setJLayeredPane(JLayeredPane jLayeredPane) { - this.jLayeredPane = jLayeredPane; - } + public void setJLayeredPane(JLayeredPane jLayeredPane) { + this.jLayeredPane = jLayeredPane; + } - public void installComponents() { - jLayeredPane.setOpaque(false); - jLayeredPane.add(abilityPicker); - jLayeredPane.add(DialogManager.getManager(gameId), JLayeredPane.MODAL_LAYER, 0); - abilityPicker.setVisible(false); - } + public void installComponents() { + jLayeredPane.setOpaque(false); + jLayeredPane.add(abilityPicker); + jLayeredPane.add(DialogManager.getManager(gameId), JLayeredPane.MODAL_LAYER, 0); + abilityPicker.setVisible(false); + } - private void createPhaseButton(String name, MouseAdapter mouseAdapter) { - if (hoverButtons == null) { - hoverButtons = new LinkedHashMap<>(); - } - Rectangle rect = new Rectangle(36, 36); - HoverButton button = new HoverButton("", ImageManagerImpl.getInstance().getPhaseImage(name), rect); - button.setToolTipText(name.replaceAll("_", " ")); - button.setPreferredSize(new Dimension(36, 36)); - button.addMouseListener(mouseAdapter); - hoverButtons.put(name, button); - } + private void createPhaseButton(String name, MouseAdapter mouseAdapter) { + if (hoverButtons == null) { + hoverButtons = new LinkedHashMap<>(); + } + Rectangle rect = new Rectangle(36, 36); + HoverButton button = new HoverButton("", ImageManagerImpl.getInstance().getPhaseImage(name), rect); + button.setToolTipText(name.replaceAll("_", " ")); + button.setPreferredSize(new Dimension(36, 36)); + button.addMouseListener(mouseAdapter); + hoverButtons.put(name, button); + } - // Event listener for the ShowCardsDialog - private Listener getShowCardsEventListener(final ShowCardsDialog dialog) { - return new Listener() { - @Override - public void event(Event event) { - if (event.getEventName().equals("show-popup-menu")) { - if (event.getComponent() != null && event.getComponent() instanceof CardPanel) { - JPopupMenu menu = ((CardPanel) event.getComponent()).getPopupMenu(); - if (menu != null) { - cardViewPopupMenu = ((CardView) event.getSource()); - menu.show(event.getComponent(), event.getxPos(), event.getyPos()); - } - } - } - if (event.getEventName().equals("action-consumed")) { - dialog.removeDialog(); - } - } - }; - } + // Event listener for the ShowCardsDialog + private Listener getShowCardsEventListener(final ShowCardsDialog dialog) { + return new Listener() { + @Override + public void event(Event event) { + if (event.getEventName().equals("show-popup-menu")) { + if (event.getComponent() != null && event.getComponent() instanceof CardPanel) { + JPopupMenu menu = ((CardPanel) event.getComponent()).getPopupMenu(); + if (menu != null) { + cardViewPopupMenu = ((CardView) event.getSource()); + menu.show(event.getComponent(), event.getxPos(), event.getyPos()); + } + } + } + if (event.getEventName().equals("action-consumed")) { + dialog.removeDialog(); + } + } + }; + } - public void handleTriggerOrderPopupMenuEvent(ActionEvent e) { - UUID abilityId = null; - String abilityRuleText = null; - if (cardViewPopupMenu instanceof CardView && cardViewPopupMenu.getAbility() != null) { - abilityId = cardViewPopupMenu.getAbility().getId(); - if (!cardViewPopupMenu.getAbility().getRules().isEmpty() - && !cardViewPopupMenu.getAbility().getRules().get(0).isEmpty()) { - abilityRuleText = cardViewPopupMenu.getAbility().getRules().get(0); - } - } - switch (e.getActionCommand()) { - case CMD_AUTO_ORDER_FIRST: - SessionHandler.sendPlayerAction(TRIGGER_AUTO_ORDER_ABILITY_FIRST, gameId, abilityId); - SessionHandler.sendPlayerUUID(gameId, abilityId); - break; - case CMD_AUTO_ORDER_LAST: - SessionHandler.sendPlayerAction(TRIGGER_AUTO_ORDER_ABILITY_LAST, gameId, abilityId); - SessionHandler.sendPlayerUUID(gameId, null); // Don't use this but refresh the displayed abilities - break; - case CMD_AUTO_ORDER_NAME_FIRST: - if (abilityRuleText != null) { - SessionHandler.sendPlayerAction(TRIGGER_AUTO_ORDER_NAME_FIRST, gameId, abilityRuleText); - SessionHandler.sendPlayerUUID(gameId, abilityId); - } - break; - case CMD_AUTO_ORDER_NAME_LAST: - if (abilityRuleText != null) { - SessionHandler.sendPlayerAction(TRIGGER_AUTO_ORDER_NAME_LAST, gameId, abilityRuleText); - SessionHandler.sendPlayerUUID(gameId, null); // Don't use this but refresh the displayed abilities - } - break; - case CMD_AUTO_ORDER_RESET_ALL: - SessionHandler.sendPlayerAction(TRIGGER_AUTO_ORDER_RESET_ALL, gameId, null); - break; - } - for (ShowCardsDialog dialog : pickTarget) { - dialog.removeDialog(); - } - } + public void handleTriggerOrderPopupMenuEvent(ActionEvent e) { + UUID abilityId = null; + String abilityRuleText = null; + if (cardViewPopupMenu instanceof CardView && cardViewPopupMenu.getAbility() != null) { + abilityId = cardViewPopupMenu.getAbility().getId(); + if (!cardViewPopupMenu.getAbility().getRules().isEmpty() + && !cardViewPopupMenu.getAbility().getRules().get(0).isEmpty()) { + abilityRuleText = cardViewPopupMenu.getAbility().getRules().get(0); + } + } + switch (e.getActionCommand()) { + case CMD_AUTO_ORDER_FIRST: + SessionHandler.sendPlayerAction(TRIGGER_AUTO_ORDER_ABILITY_FIRST, gameId, abilityId); + SessionHandler.sendPlayerUUID(gameId, abilityId); + break; + case CMD_AUTO_ORDER_LAST: + SessionHandler.sendPlayerAction(TRIGGER_AUTO_ORDER_ABILITY_LAST, gameId, abilityId); + SessionHandler.sendPlayerUUID(gameId, null); // Don't use this but refresh the displayed abilities + break; + case CMD_AUTO_ORDER_NAME_FIRST: + if (abilityRuleText != null) { + SessionHandler.sendPlayerAction(TRIGGER_AUTO_ORDER_NAME_FIRST, gameId, abilityRuleText); + SessionHandler.sendPlayerUUID(gameId, abilityId); + } + break; + case CMD_AUTO_ORDER_NAME_LAST: + if (abilityRuleText != null) { + SessionHandler.sendPlayerAction(TRIGGER_AUTO_ORDER_NAME_LAST, gameId, abilityRuleText); + SessionHandler.sendPlayerUUID(gameId, null); // Don't use this but refresh the displayed abilities + } + break; + case CMD_AUTO_ORDER_RESET_ALL: + SessionHandler.sendPlayerAction(TRIGGER_AUTO_ORDER_RESET_ALL, gameId, null); + break; + } + for (ShowCardsDialog dialog : pickTarget) { + dialog.removeDialog(); + } + } - private void initPopupMenuTriggerOrder() { + private void initPopupMenuTriggerOrder() { - ActionListener actionListener = new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - handleTriggerOrderPopupMenuEvent(e); - } - }; + ActionListener actionListener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + handleTriggerOrderPopupMenuEvent(e); + } + }; - popupMenuTriggerOrder = new JPopupMenu(); + popupMenuTriggerOrder = new JPopupMenu(); - // String tooltipText = ""; - JMenuItem menuItem; - menuItem = new JMenuItem("Put this ability always first on the stack"); - menuItem.setActionCommand(CMD_AUTO_ORDER_FIRST); - menuItem.addActionListener(actionListener); - popupMenuTriggerOrder.add(menuItem); + // String tooltipText = ""; + JMenuItem menuItem; + menuItem = new JMenuItem("Put this ability always first on the stack"); + menuItem.setActionCommand(CMD_AUTO_ORDER_FIRST); + menuItem.addActionListener(actionListener); + popupMenuTriggerOrder.add(menuItem); - menuItem = new JMenuItem("Put this ability always last on the stack"); - menuItem.setActionCommand(CMD_AUTO_ORDER_LAST); - menuItem.addActionListener(actionListener); - popupMenuTriggerOrder.add(menuItem); + menuItem = new JMenuItem("Put this ability always last on the stack"); + menuItem.setActionCommand(CMD_AUTO_ORDER_LAST); + menuItem.addActionListener(actionListener); + popupMenuTriggerOrder.add(menuItem); - menuItem = new JMenuItem("Put all abilities with that rule text always first on the stack"); - menuItem.setActionCommand(CMD_AUTO_ORDER_NAME_FIRST); - menuItem.addActionListener(actionListener); - popupMenuTriggerOrder.add(menuItem); + menuItem = new JMenuItem("Put all abilities with that rule text always first on the stack"); + menuItem.setActionCommand(CMD_AUTO_ORDER_NAME_FIRST); + menuItem.addActionListener(actionListener); + popupMenuTriggerOrder.add(menuItem); - menuItem = new JMenuItem("Put all abilities with that rule text always last on the stack"); - menuItem.setActionCommand(CMD_AUTO_ORDER_NAME_LAST); - menuItem.addActionListener(actionListener); - popupMenuTriggerOrder.add(menuItem); + menuItem = new JMenuItem("Put all abilities with that rule text always last on the stack"); + menuItem.setActionCommand(CMD_AUTO_ORDER_NAME_LAST); + menuItem.addActionListener(actionListener); + popupMenuTriggerOrder.add(menuItem); - menuItem = new JMenuItem("Reset all order settings for triggered abilities"); - menuItem.setActionCommand(CMD_AUTO_ORDER_RESET_ALL); - menuItem.addActionListener(actionListener); - popupMenuTriggerOrder.add(menuItem); - } + menuItem = new JMenuItem("Reset all order settings for triggered abilities"); + menuItem.setActionCommand(CMD_AUTO_ORDER_RESET_ALL); + menuItem.addActionListener(actionListener); + popupMenuTriggerOrder.add(menuItem); + } - public String getGameLog() { - return gameChatPanel.getText(); - } + public String getGameLog() { + return gameChatPanel.getText(); + } - public Map getLoadedCards() { - return loadedCards; - } + public Map getLoadedCards() { + return loadedCards; + } - public void setLoadedCards(Map loadedCards) { - this.loadedCards = loadedCards; - } + public void setLoadedCards(Map loadedCards) { + this.loadedCards = loadedCards; + } - public FeedbackPanel getFeedbackPanel() { - return feedbackPanel; - } + public FeedbackPanel getFeedbackPanel() { + return feedbackPanel; + } - // Use Cmd on OSX since Ctrl+click is already used to simulate right click - private static int holdPriorityMask = System.getProperty("os.name").contains("Mac OS X") ? InputEvent.META_DOWN_MASK : InputEvent.CTRL_DOWN_MASK; + // Use Cmd on OSX since Ctrl+click is already used to simulate right click + private static int holdPriorityMask = System.getProperty("os.name").contains("Mac OS X") ? InputEvent.META_DOWN_MASK : InputEvent.CTRL_DOWN_MASK; - public void handleEvent(AWTEvent event) { - if (event instanceof InputEvent) { - int id = event.getID(); - boolean isActionEvent = false; - if (id == MouseEvent.MOUSE_PRESSED) { - isActionEvent = true; - } else if (id == KeyEvent.KEY_PRESSED) { - KeyEvent key = (KeyEvent) event; - int keyCode = key.getKeyCode(); - if (keyCode == KeyEvent.VK_ENTER || keyCode == KeyEvent.VK_SPACE) { - isActionEvent = true; - } - } - if (isActionEvent) { - InputEvent input = (InputEvent) event; - if ((input.getModifiersEx() & holdPriorityMask) != 0) { - setMenuStates( - PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT, "true").equals("true"), - PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE, "true").equals("true"), - PreferencesDialog.getCachedValue(KEY_USE_FIRST_MANA_ABILITY, "false").equals("true"), - true); - holdPriority(true); - } - } - } - } + public void handleEvent(AWTEvent event) { + if (event instanceof InputEvent) { + int id = event.getID(); + boolean isActionEvent = false; + if (id == MouseEvent.MOUSE_PRESSED) { + isActionEvent = true; + } else if (id == KeyEvent.KEY_PRESSED) { + KeyEvent key = (KeyEvent) event; + int keyCode = key.getKeyCode(); + if (keyCode == KeyEvent.VK_ENTER || keyCode == KeyEvent.VK_SPACE) { + isActionEvent = true; + } + } + if (isActionEvent) { + InputEvent input = (InputEvent) event; + if ((input.getModifiersEx() & holdPriorityMask) != 0) { + setMenuStates( + PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT, "true").equals("true"), + PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE, "true").equals("true"), + PreferencesDialog.getCachedValue(KEY_USE_FIRST_MANA_ABILITY, "false").equals("true"), + true); + holdPriority(true); + } + } + } + } - public void holdPriority(boolean holdPriority) { - if (holdingPriority != holdPriority) { - holdingPriority = holdPriority; - txtHoldPriority.setVisible(holdPriority); - if (holdPriority) { - SessionHandler.sendPlayerAction(PlayerAction.HOLD_PRIORITY, gameId, null); - } else { - SessionHandler.sendPlayerAction(PlayerAction.UNHOLD_PRIORITY, gameId, null); - } - } - } + public void holdPriority(boolean holdPriority) { + if (holdingPriority != holdPriority) { + holdingPriority = holdPriority; + txtHoldPriority.setVisible(holdPriority); + if (holdPriority) { + SessionHandler.sendPlayerAction(PlayerAction.HOLD_PRIORITY, gameId, null); + } else { + SessionHandler.sendPlayerAction(PlayerAction.UNHOLD_PRIORITY, gameId, null); + } + } + } - private boolean holdingPriority; - private mage.client.components.ability.AbilityPicker abilityPicker; - private mage.client.cards.BigCard bigCard; + private boolean holdingPriority; + private mage.client.components.ability.AbilityPicker abilityPicker; + private mage.client.cards.BigCard bigCard; // private JPanel cancelSkipPanel; - private javax.swing.JButton btnCancelSkip; - private javax.swing.JButton btnSkipToNextTurn; // F4 - private javax.swing.JButton btnSkipToEndTurn; // F5 - private javax.swing.JButton btnSkipToNextMain; // F7 - private javax.swing.JButton btnSkipStack; // F8 - private javax.swing.JButton btnSkipToYourTurn; // F9 - private javax.swing.JButton btnSkipToEndStepBeforeYourTurn; // F11 + private KeyboundButton btnCancelSkip; + private KeyboundButton btnSkipToNextTurn; // F4 + private KeyboundButton btnSkipToEndTurn; // F5 + private KeyboundButton btnSkipToNextMain; // F7 + private KeyboundButton btnSkipStack; // F8 + private KeyboundButton btnSkipToYourTurn; // F9 + private KeyboundButton btnSkipToEndStepBeforeYourTurn; // F11 - private javax.swing.JButton btnConcede; - private javax.swing.JButton btnSwitchHands; + private javax.swing.JButton btnConcede; + private javax.swing.JButton btnSwitchHands; - private javax.swing.JButton btnNextPlay; - private javax.swing.JButton btnPlay; - private javax.swing.JButton btnPreviousPlay; - private javax.swing.JButton btnSkipForward; - private javax.swing.JButton btnStopReplay; + private javax.swing.JButton btnNextPlay; + private javax.swing.JButton btnPlay; + private javax.swing.JButton btnPreviousPlay; + private javax.swing.JButton btnSkipForward; + private javax.swing.JButton btnStopReplay; - private javax.swing.JButton btnStopWatching; + private javax.swing.JButton btnStopWatching; - private mage.client.chat.ChatPanelBasic gameChatPanel; - private mage.client.game.FeedbackPanel feedbackPanel; - private HelperPanel helper; - private mage.client.chat.ChatPanelBasic userChatPanel; - private javax.swing.JPanel jPanel2; - private javax.swing.JPanel pnlHelperHandButtonsStackArea; - private javax.swing.JSplitPane jSplitPane0; - private javax.swing.JSplitPane jSplitPane1; - private javax.swing.JLabel lblActivePlayer; - private javax.swing.JLabel lblPhase; - private javax.swing.JLabel lblPriority; - private javax.swing.JLabel lblStep; - private javax.swing.JLabel lblTurn; - private javax.swing.JPanel pnlBattlefield; - private javax.swing.JPanel pnlShortCuts; - private javax.swing.JPanel pnlReplay; - private javax.swing.JLabel txtActivePlayer; - private javax.swing.JLabel txtPhase; - private javax.swing.JLabel txtPriority; - private javax.swing.JLabel txtStep; - private javax.swing.JLabel txtTurn; + private mage.client.chat.ChatPanelBasic gameChatPanel; + private mage.client.game.FeedbackPanel feedbackPanel; + private HelperPanel helper; + private mage.client.chat.ChatPanelBasic userChatPanel; + private javax.swing.JPanel jPanel2; + private javax.swing.JPanel pnlHelperHandButtonsStackArea; + private javax.swing.JSplitPane jSplitPane0; + private javax.swing.JSplitPane jSplitPane1; + private javax.swing.JLabel lblActivePlayer; + private javax.swing.JLabel lblPhase; + private javax.swing.JLabel lblPriority; + private javax.swing.JLabel lblStep; + private javax.swing.JLabel lblTurn; + private javax.swing.JPanel pnlBattlefield; + private javax.swing.JPanel pnlShortCuts; + private javax.swing.JPanel pnlReplay; + private javax.swing.JLabel txtActivePlayer; + private javax.swing.JLabel txtPhase; + private javax.swing.JLabel txtPriority; + private javax.swing.JLabel txtStep; + private javax.swing.JLabel txtTurn; - private Map handCards; + private Map handCards; - private mage.client.cards.Cards stackObjects; - private HandPanel handContainer; + private mage.client.cards.Cards stackObjects; + private HandPanel handContainer; - private javax.swing.JSplitPane jSplitPane2; - private JPanel jPhases; - private JPanel phasesContainer; - private javax.swing.JLabel txtSpellsCast; - private javax.swing.JLabel txtHoldPriority; + private javax.swing.JSplitPane jSplitPane2; + private JPanel jPhases; + private JPanel phasesContainer; + private javax.swing.JLabel txtSpellsCast; + private javax.swing.JLabel txtHoldPriority; - private HoverButton currentStep; - private Point prevPoint; + private HoverButton currentStep; + private Point prevPoint; - private boolean imagePanelState; + private boolean imagePanelState; } class ReplayTask extends SwingWorker> { - private final UUID gameId; + private final UUID gameId; - private static final Logger logger = Logger.getLogger(ReplayTask.class); + private static final Logger logger = Logger.getLogger(ReplayTask.class); - ReplayTask(UUID gameId) { - this.gameId = gameId; - } + ReplayTask(UUID gameId) { + this.gameId = gameId; + } - @Override - protected Void doInBackground() throws Exception { - while (!isCancelled()) { - SessionHandler.nextPlay(gameId); - Thread.sleep(1000); - } - return null; - } + @Override + protected Void doInBackground() throws Exception { + while (!isCancelled()) { + SessionHandler.nextPlay(gameId); + Thread.sleep(1000); + } + return null; + } - @Override - protected void done() { - try { - get(); - } catch (InterruptedException ex) { - logger.fatal("Replay Match Task error", ex); - } catch (ExecutionException ex) { - logger.fatal("Replay Match Task error", ex); - } catch (CancellationException ex) { - } - } + @Override + protected void done() { + try { + get(); + } catch (InterruptedException ex) { + logger.fatal("Replay Match Task error", ex); + } catch (ExecutionException ex) { + logger.fatal("Replay Match Task error", ex); + } catch (CancellationException ex) { + } + } } diff --git a/Mage.Client/src/main/resources/buttons/cancel_skip.png b/Mage.Client/src/main/resources/buttons/cancel_skip.png index 30755df9317..4df1d6db2f7 100644 Binary files a/Mage.Client/src/main/resources/buttons/cancel_skip.png and b/Mage.Client/src/main/resources/buttons/cancel_skip.png differ diff --git a/Mage.Client/src/main/resources/buttons/skip_all.png b/Mage.Client/src/main/resources/buttons/skip_all.png index 53c01378ade..2120e016d97 100644 Binary files a/Mage.Client/src/main/resources/buttons/skip_all.png and b/Mage.Client/src/main/resources/buttons/skip_all.png differ diff --git a/Mage.Client/src/main/resources/buttons/skip_stack.png b/Mage.Client/src/main/resources/buttons/skip_stack.png index 06816b1f393..2ddce1c39b3 100644 Binary files a/Mage.Client/src/main/resources/buttons/skip_stack.png and b/Mage.Client/src/main/resources/buttons/skip_stack.png differ diff --git a/Mage.Client/src/main/resources/buttons/skip_to_end.png b/Mage.Client/src/main/resources/buttons/skip_to_end.png index 86df3bcf7c4..4a609a06252 100644 Binary files a/Mage.Client/src/main/resources/buttons/skip_to_end.png and b/Mage.Client/src/main/resources/buttons/skip_to_end.png differ diff --git a/Mage.Client/src/main/resources/buttons/skip_to_main.png b/Mage.Client/src/main/resources/buttons/skip_to_main.png index 0d1b2bf1155..d1bbef6b864 100644 Binary files a/Mage.Client/src/main/resources/buttons/skip_to_main.png and b/Mage.Client/src/main/resources/buttons/skip_to_main.png differ diff --git a/Mage.Client/src/main/resources/buttons/skip_to_previous_end.png b/Mage.Client/src/main/resources/buttons/skip_to_previous_end.png index 2e93fd55bbb..03043c96b7c 100644 Binary files a/Mage.Client/src/main/resources/buttons/skip_to_previous_end.png and b/Mage.Client/src/main/resources/buttons/skip_to_previous_end.png differ diff --git a/Mage.Client/src/main/resources/buttons/skip_turn.png b/Mage.Client/src/main/resources/buttons/skip_turn.png index c7c3bfe393b..8f9ad5432ae 100644 Binary files a/Mage.Client/src/main/resources/buttons/skip_turn.png and b/Mage.Client/src/main/resources/buttons/skip_turn.png differ diff --git a/Mage.Common/src/mage/utils/MageVersion.java b/Mage.Common/src/mage/utils/MageVersion.java index 020bd898a61..70173cb480b 100644 --- a/Mage.Common/src/mage/utils/MageVersion.java +++ b/Mage.Common/src/mage/utils/MageVersion.java @@ -41,7 +41,7 @@ public class MageVersion implements Serializable, Comparable { public final static int MAGE_VERSION_MAJOR = 1; public final static int MAGE_VERSION_MINOR = 4; public final static int MAGE_VERSION_PATCH = 16; - public final static String MAGE_VERSION_MINOR_PATCH = "v3"; + public final static String MAGE_VERSION_MINOR_PATCH = "v4"; public final static String MAGE_VERSION_INFO = ""; private final int major; diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer7.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer7.java index a49c7ca7a07..c1ff29cb746 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer7.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer7.java @@ -1,16 +1,16 @@ /* * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR @@ -20,12 +20,11 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.player.ai; import java.util.LinkedList; @@ -53,9 +52,6 @@ import mage.game.turn.PostCombatMainStep; import mage.game.turn.Step; import org.apache.log4j.Logger; - - - /** * * @author ayratn @@ -91,10 +87,10 @@ public class ComputerPlayer7 extends ComputerPlayer6 { private boolean priorityPlay(Game game) { if (lastLoggedTurn != game.getTurnNum()) { lastLoggedTurn = game.getTurnNum(); - logger.info("======================= Turn: "+ game.getTurnNum() + " ["+ game.getPlayer(game.getActivePlayerId()).getName() +"] ========================================="); + logger.info("======================= Turn: " + game.getTurnNum() + " [" + game.getPlayer(game.getActivePlayerId()).getName() + "] ========================================="); } logState(game); - logger.debug("Priority -- Step: " + (game.getTurn().getStepType() + " ").substring(0,25) + " ActivePlayer-" + game.getPlayer(game.getActivePlayerId()).getName() + " PriorityPlayer-" + name); + logger.debug("Priority -- Step: " + (game.getTurn().getStepType() + " ").substring(0, 25) + " ActivePlayer-" + game.getPlayer(game.getActivePlayerId()).getName() + " PriorityPlayer-" + name); game.getState().setPriorityPlayerId(playerId); game.firePriorityEvent(playerId); switch (game.getTurn().getStepType()) { @@ -111,8 +107,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 { } act(game); return true; - } - else { + } else { pass(game); } return false; @@ -128,8 +123,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 { } act(game); return true; - } - else { + } else { pass(game); } return false; @@ -141,12 +135,12 @@ public class ComputerPlayer7 extends ComputerPlayer6 { return false; case POSTCOMBAT_MAIN: // if (game.getActivePlayerId().equals(playerId)) { - printOutState(game); - if (actions.isEmpty()) { - calculatePostCombatActions(game); - } - act(game); - return true; + printOutState(game); + if (actions.isEmpty()) { + calculatePostCombatActions(game); + } + act(game); + return true; // } // else { // pass(game); @@ -161,24 +155,24 @@ public class ComputerPlayer7 extends ComputerPlayer6 { return false; } - protected void calculatePreCombatActions(Game game) { + protected void calculatePreCombatActions(Game game) { if (!getNextAction(game)) { currentScore = GameStateEvaluator2.evaluate(playerId, game); Game sim = createSimulation(game); SimulationNode2.resetCount(); root = new SimulationNode2(null, sim, maxDepth, playerId); - + addActionsTimed(); logger.trace("After add actions timed: root.children.size = " + root.children.size()); if (root.children.size() > 0) { root = root.children.get(0); // int bestScore = root.getScore(); // if (bestScore > currentScore || allowBadMoves) { - + // prevent repeating always the same action with no cost boolean doThis = true; if (root.abilities.size() == 1) { - for (Ability ability:root.abilities) { + for (Ability ability : root.abilities) { if (ability.getManaCosts().convertedManaCost() == 0 && ability.getCosts().isEmpty()) { if (actionCache.contains(ability.getRule() + "_" + ability.getSourceId())) { doThis = false; // don't do it again @@ -217,7 +211,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 { actions = new LinkedList<>(root.abilities); combat = root.combat; } else { - logger.debug("[" + game.getPlayer(playerId).getName() + "] no better score current: " + currentScore + " bestScore: " + bestScore ); + logger.debug("[" + game.getPlayer(playerId).getName() + "] no better score current: " + currentScore + " bestScore: " + bestScore); } } else { logger.debug("[" + game.getPlayer(playerId).getName() + "][post] Action: skip"); @@ -229,7 +223,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 { protected int addActions(SimulationNode2 node, int depth, int alpha, int beta) { boolean stepFinished = false; int val; - if (logger.isTraceEnabled() && node !=null && node.getAbilities() != null && !node.getAbilities().toString().equals("[Pass]")){ + if (logger.isTraceEnabled() && node != null && node.getAbilities() != null && !node.getAbilities().toString().equals("[Pass]")) { logger.trace("Add Action [" + depth + "] " + node.getAbilities().toString() + " a: " + alpha + " b: " + beta); } Game game = node.getGame(); @@ -243,42 +237,39 @@ public class ComputerPlayer7 extends ComputerPlayer6 { val = GameStateEvaluator2.evaluate(playerId, game); if (logger.isTraceEnabled()) { StringBuilder sb = new StringBuilder("Add Actions -- reached end state <").append(val).append(">"); - SimulationNode2 logNode = node; + SimulationNode2 logNode = node; do { - sb.append(new StringBuilder(" <- ["+logNode.getDepth()+"]" + (logNode.getAbilities() != null ? logNode.getAbilities().toString():"[empty]"))); + sb.append(new StringBuilder(" <- [" + logNode.getDepth() + "]" + (logNode.getAbilities() != null ? logNode.getAbilities().toString() : "[empty]"))); logNode = logNode.getParent(); - } while((logNode.getParent() != null)); + } while ((logNode.getParent() != null)); logger.trace(sb); } } else if (node.getChildren().size() > 0) { if (logger.isDebugEnabled()) { StringBuilder sb = new StringBuilder("Add Action [").append(depth) .append("] -- something added children ") - .append(node.getAbilities() != null ? node.getAbilities().toString():"null") + .append(node.getAbilities() != null ? node.getAbilities().toString() : "null") .append(" added children: ").append(node.getChildren().size()).append(" ("); - for (SimulationNode2 logNode: node.getChildren()) { - sb.append(logNode.getAbilities() != null ? logNode.getAbilities().toString():"null").append(", "); + for (SimulationNode2 logNode : node.getChildren()) { + sb.append(logNode.getAbilities() != null ? logNode.getAbilities().toString() : "null").append(", "); } sb.append(")"); logger.debug(sb); } - val = minimaxAB(node, depth-1, alpha, beta); - } - else { + val = minimaxAB(node, depth - 1, alpha, beta); + } else { logger.trace("Add Action -- alpha: " + alpha + " beta: " + beta + " depth:" + depth + " step:" + game.getTurn().getStepType() + " for player:" + game.getPlayer(game.getPlayerList().get()).getName()); if (allPassed(game)) { if (!game.getStack().isEmpty()) { resolve(node, depth, game); - } - else { + } else { stepFinished = true; } } if (game.gameOver(null)) { val = GameStateEvaluator2.evaluate(playerId, game); - } - else if (stepFinished) { + } else if (stepFinished) { logger.debug("Step finished"); int testScore = GameStateEvaluator2.evaluate(playerId, game); if (game.getActivePlayerId().equals(playerId)) { @@ -286,8 +277,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 { // if score at end of step is worse than original score don't check further //logger.debug("Add Action -- abandoning check, no immediate benefit"); val = testScore; - } - else { + } else { /*switch (game.getTurn().getStepType()) { case PRECOMBAT_MAIN: val = simulateCombat(game, node, depth-1, alpha, beta, false); @@ -301,32 +291,29 @@ public class ComputerPlayer7 extends ComputerPlayer6 { }*/ val = GameStateEvaluator2.evaluate(playerId, game); } - } - else { + } else { val = GameStateEvaluator2.evaluate(playerId, game); /*if (game.getTurn().getStepType() == PhaseStep.DECLARE_ATTACKERS) val = simulateBlockers(game, node, playerId, depth-1, alpha, beta, true); else val = GameStateEvaluator2.evaluate(playerId, game); - */ + */ } - } - else if (node.getChildren().size() > 0) { + } else if (node.getChildren().size() > 0) { if (logger.isDebugEnabled()) { StringBuilder sb = new StringBuilder("Add Action [").append(depth) .append("] -- trigger ") - .append(node.getAbilities() != null ? node.getAbilities().toString():"null") + .append(node.getAbilities() != null ? node.getAbilities().toString() : "null") .append(" added children: ").append(node.getChildren().size()).append(" ("); - for (SimulationNode2 logNode: node.getChildren()) { - sb.append(logNode.getAbilities() != null ? logNode.getAbilities().toString():"null").append(", "); + for (SimulationNode2 logNode : node.getChildren()) { + sb.append(logNode.getAbilities() != null ? logNode.getAbilities().toString() : "null").append(", "); } sb.append(")"); logger.debug(sb); } val = minimaxAB(node, depth, alpha, beta); - } - else { + } else { val = simulatePriority(node, game, depth, alpha, beta); } } @@ -353,25 +340,20 @@ public class ComputerPlayer7 extends ComputerPlayer6 { if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARING_ATTACKERS, game.getActivePlayerId(), game.getActivePlayerId()))) { val = simulateAttackers(game, node, game.getActivePlayerId(), depth, alpha, beta, counter); } - } - else if (!counter) { + } else if (!counter) { simulateToEnd(game); val = simulatePostCombatMain(game, node, depth, alpha, beta); } } - } - else { - if (!game.getStep().skipStep(game, game.getActivePlayerId())) { - game.fireEvent(new GameEvent(GameEvent.EventType.DECLARE_BLOCKERS_STEP_PRE, null, null, game.getActivePlayerId())); - if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARING_BLOCKERS, game.getActivePlayerId(), game.getActivePlayerId()))) { - //only suitable for two player games - only simulates blocks for 1st defender - val = simulateBlockers(game, node, game.getCombat().getDefenders().iterator().next(), depth, alpha, beta, counter); - } - } - else if (!counter) { - finishCombat(game); - ///val = simulateCounterAttack(game, node, depth, alpha, beta); + } else if (!game.getStep().skipStep(game, game.getActivePlayerId())) { + game.fireEvent(new GameEvent(GameEvent.EventType.DECLARE_BLOCKERS_STEP_PRE, null, null, game.getActivePlayerId())); + if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARING_BLOCKERS, game.getActivePlayerId(), game.getActivePlayerId()))) { + //only suitable for two player games - only simulates blocks for 1st defender + val = simulateBlockers(game, node, game.getCombat().getDefenders().iterator().next(), depth, alpha, beta, counter); } + } else if (!counter) { + finishCombat(game); + ///val = simulateCounterAttack(game, node, depth, alpha, beta); } if (val == null) { val = GameStateEvaluator2.evaluate(playerId, game); @@ -382,7 +364,6 @@ public class ComputerPlayer7 extends ComputerPlayer6 { return val; } - protected int simulateAttackers(Game game, SimulationNode2 node, UUID attackerId, int depth, int alpha, int beta, boolean counter) { if (ALLOW_INTERRUPT && Thread.interrupted()) { Thread.currentThread().interrupt(); @@ -396,7 +377,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 { if (logger.isDebugEnabled()) { logger.debug(attacker.getName() + "'s possible attackers: " + attacker.getAvailableAttackers(defenderId, game)); } - for (Combat engagement: attacker.addAttackers(game)) { + for (Combat engagement : attacker.addAttackers(game)) { if (logger.isDebugEnabled()) { logger.debug("Sim Attackers: " + engagement.getAttackers() + ", blockers: " + engagement.getBlockers()); } @@ -404,9 +385,9 @@ public class ComputerPlayer7 extends ComputerPlayer6 { logger.debug("Sim Attackers -- pruning attackers"); break; } - Game sim = game.copy(); - for (CombatGroup group: engagement.getGroups()) { - for (UUID attackId: group.getAttackers()) { + Game sim = game.copy(); + for (CombatGroup group : engagement.getGroups()) { + for (UUID attackId : group.getAttackers()) { sim.getPlayer(attackerId).declareAttacker(attackId, defenderId, sim, false); } } @@ -424,7 +405,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 { sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARE_ATTACKERS_STEP_POST, sim.getActivePlayerId(), sim.getActivePlayerId())); Combat simCombat = sim.getCombat().copy(); sim.getPhase().setStep(new DeclareBlockersStep()); - val = simulateCombat(sim, newNode, depth-1, alpha, beta, counter); + val = simulateCombat(sim, newNode, depth - 1, alpha, beta, counter); if (!attackerId.equals(playerId)) { if (val < beta) { beta = val; @@ -434,15 +415,12 @@ public class ComputerPlayer7 extends ComputerPlayer6 { bestNode.setCombat(newNode.getChildren().get(0).getCombat()); } } - } - else { - if (val > alpha) { - alpha = val; - bestNode = newNode; - bestNode.setScore(val); - if (newNode.getChildren().size() > 0) { - bestNode.setCombat(newNode.getChildren().get(0).getCombat()); - } + } else if (val > alpha) { + alpha = val; + bestNode = newNode; + bestNode.setScore(val); + if (newNode.getChildren().size() > 0) { + bestNode.setCombat(newNode.getChildren().get(0).getCombat()); } } } @@ -475,16 +453,16 @@ public class ComputerPlayer7 extends ComputerPlayer6 { logger.debug(defender.getName() + "'s possible blockers: " + defender.getAvailableBlockers(game)); } List combats = defender.addBlockers(game); - for (Combat engagement: combats) { + for (Combat engagement : combats) { if (alpha >= beta) { logger.debug("Sim blockers -- pruning blockers"); break; } Game sim = game.copy(); - for (CombatGroup group: engagement.getGroups()) { + for (CombatGroup group : engagement.getGroups()) { if (group.getAttackers().size() > 0) { UUID attackerId = group.getAttackers().get(0); - for (UUID blockerId: group.getBlockers()) { + for (UUID blockerId : group.getBlockers()) { sim.getPlayer(defenderId).declareBlocker(defenderId, blockerId, attackerId, sim); } } @@ -505,11 +483,9 @@ public class ComputerPlayer7 extends ComputerPlayer6 { finishCombat(sim); if (sim.gameOver(null)) { val = GameStateEvaluator2.evaluate(playerId, sim); - } - else if (!counter) { - val = simulatePostCombatMain(sim, newNode, depth-1, alpha, beta); - } - else { + } else if (!counter) { + val = simulatePostCombatMain(sim, newNode, depth - 1, alpha, beta); + } else { val = GameStateEvaluator2.evaluate(playerId, sim); } if (!defenderId.equals(playerId)) { @@ -519,14 +495,11 @@ public class ComputerPlayer7 extends ComputerPlayer6 { bestNode.setScore(val); bestNode.setCombat(simCombat); } - } - else { - if (val > alpha) { - alpha = val; - bestNode = newNode; - bestNode.setScore(val); - bestNode.setCombat(simCombat); - } + } else if (val > alpha) { + alpha = val; + bestNode = newNode; + bestNode.setScore(val); + bestNode.setCombat(simCombat); } } } @@ -570,7 +543,6 @@ public class ComputerPlayer7 extends ComputerPlayer6 { val = GameStateEvaluator2.evaluate(playerId, game); return val; }*/ - protected void simulateStep(Game game, Step step) { if (ALLOW_INTERRUPT && Thread.interrupted()) { Thread.currentThread().interrupt(); diff --git a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java index 03ca681e47f..8d05903ba05 100644 --- a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java @@ -65,9 +65,14 @@ import mage.constants.ManaType; import mage.constants.Outcome; import mage.constants.PhaseStep; import mage.constants.PlayerAction; +import static mage.constants.PlayerAction.HOLD_PRIORITY; +import static mage.constants.PlayerAction.REQUEST_AUTO_ANSWER_ID_NO; import static mage.constants.PlayerAction.REQUEST_AUTO_ANSWER_RESET_ALL; +import static mage.constants.PlayerAction.TRIGGER_AUTO_ORDER_NAME_LAST; import static mage.constants.PlayerAction.TRIGGER_AUTO_ORDER_RESET_ALL; import mage.constants.RangeOfInfluence; +import static mage.constants.SpellAbilityType.SPLIT; +import static mage.constants.SpellAbilityType.SPLIT_FUSED; import mage.constants.Zone; import mage.filter.common.FilterAttackingCreature; import mage.filter.common.FilterBlockingCreature; @@ -730,12 +735,14 @@ public class HumanPlayer extends PlayerImpl { } private boolean checkPassStep(Game game) { - if (game.getStep() != null) { + try { if (playerId.equals(game.getActivePlayerId())) { return !this.getUserData().getUserSkipPrioritySteps().getYourTurn().isPhaseStepSet(game.getStep().getType()); } else { return !this.getUserData().getUserSkipPrioritySteps().getOpponentTurn().isPhaseStepSet(game.getStep().getType()); } + } catch (NullPointerException ex) { + logger.error("null pointer exception UserData = " + userData == null ? "null" : "not null"); } return true; } @@ -1459,6 +1466,11 @@ public class HumanPlayer extends PlayerImpl { protected void updateGameStatePriority(String methodName, Game game) { if (game.getState().getPriorityPlayerId() != null) { // don't do it if priority was set to null before (e.g. discard in cleanaup) + if (getId() == null) { + logger.fatal("Player with no ID: " + name); + this.quit(game); + return; + } logger.debug("Setting game priority to " + getId() + " [" + methodName + "]"); game.getState().setPriorityPlayerId(getId()); } diff --git a/Mage.Sets/src/mage/cards/a/Arena.java b/Mage.Sets/src/mage/cards/a/Arena.java index 77897647db7..9bbd8eeef01 100644 --- a/Mage.Sets/src/mage/cards/a/Arena.java +++ b/Mage.Sets/src/mage/cards/a/Arena.java @@ -58,7 +58,7 @@ public class Arena extends CardImpl { Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ArenaEffect(), new GenericManaCost(3)); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetControlledCreaturePermanent()); - ability.addTarget(new TargetOpponentsChoicePermanent(new FilterControlledCreaturePermanent())); + ability.addTarget(new TargetOpponentsChoicePermanent(1, 1, new FilterControlledCreaturePermanent(), false, true)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/CloakingDevice.java b/Mage.Sets/src/mage/cards/c/CloakingDevice.java index 5db33ff4a7e..a5126fcff8a 100644 --- a/Mage.Sets/src/mage/cards/c/CloakingDevice.java +++ b/Mage.Sets/src/mage/cards/c/CloakingDevice.java @@ -28,13 +28,14 @@ package mage.cards.c; import java.util.UUID; -import mage.MageObject; import mage.abilities.Ability; +import mage.abilities.Mode; import mage.abilities.common.AttacksAttachedTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.AttachEffect; -import mage.abilities.effects.common.LoseLifeDefendingPlayerEffect; import mage.abilities.effects.common.combat.CantBeBlockedAttachedEffect; import mage.abilities.keyword.EnchantAbility; import mage.cards.CardImpl; @@ -43,8 +44,6 @@ import mage.constants.AttachmentType; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Zone; -import mage.counters.Counter; -import mage.filter.FilterPermanent; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -58,7 +57,7 @@ import mage.target.common.TargetCreaturePermanent; public class CloakingDevice extends CardImpl { public CloakingDevice(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}"); this.subtype.add("Aura"); // Enchant creature @@ -72,7 +71,7 @@ public class CloakingDevice extends CardImpl { this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantBeBlockedAttachedEffect(AttachmentType.AURA))); // Whenever enchanted creature attacks, defending player loses 1 life. - this.addAbility(new AttacksAttachedTriggeredAbility(new LoseLifeDefendingPlayerEffect(1, true), AttachmentType.AURA, false)); + this.addAbility(new AttacksAttachedTriggeredAbility(new CloakingDeviceLoseLifeDefendingPlayerEffect(1, true), AttachmentType.AURA, false)); } @@ -85,3 +84,54 @@ public class CloakingDevice extends CardImpl { return new CloakingDevice(this); } } + +class CloakingDeviceLoseLifeDefendingPlayerEffect extends OneShotEffect { + + private DynamicValue amount; + private boolean attackerIsSource; + + /** + * + * @param amount + * @param attackerIsSource true if the source.getSourceId() contains the + * attacker false if attacker has to be taken from targetPointer + */ + public CloakingDeviceLoseLifeDefendingPlayerEffect(int amount, boolean attackerIsSource) { + this(new StaticValue(amount), attackerIsSource); + } + + public CloakingDeviceLoseLifeDefendingPlayerEffect(DynamicValue amount, boolean attackerIsSource) { + super(Outcome.Damage); + this.amount = amount; + this.attackerIsSource = attackerIsSource; + } + + public CloakingDeviceLoseLifeDefendingPlayerEffect(final CloakingDeviceLoseLifeDefendingPlayerEffect effect) { + super(effect); + this.amount = effect.amount.copy(); + this.attackerIsSource = effect.attackerIsSource; + } + + @Override + public CloakingDeviceLoseLifeDefendingPlayerEffect copy() { + return new CloakingDeviceLoseLifeDefendingPlayerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent enchantment = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (enchantment != null && enchantment.getAttachedTo() != null) { + Player defender = game.getPlayer(game.getCombat().getDefendingPlayerId(enchantment.getAttachedTo(), game)); + if (defender != null) { + defender.loseLife(amount.calculate(game, source, this), game, false); + } + } + return true; + } + + @Override + public String getText(Mode mode) { + return "defending player loses " + amount + " life"; + } + +} diff --git a/Mage.Sets/src/mage/cards/d/DarkDecision.java b/Mage.Sets/src/mage/cards/d/DarkDecision.java index 73ae0adcd39..b4f402f3497 100644 --- a/Mage.Sets/src/mage/cards/d/DarkDecision.java +++ b/Mage.Sets/src/mage/cards/d/DarkDecision.java @@ -55,7 +55,7 @@ import mage.target.targetpointer.FixedTarget; public class DarkDecision extends CardImpl { public DarkDecision(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{B}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{B}{R}"); // As an additional cost to cast Dark Decision, pay 1 life. this.getSpellAbility().addCost(new PayLifeCost(1)); @@ -103,7 +103,7 @@ class DarkDecisionEffect extends OneShotEffect { if (card != null) { controller.moveCardsToExile(card, source, game, true, source.getSourceId(), sourceObject.getIdName()); ContinuousEffect effect = new DarkDecisionMayPlayExiledEffect(); - effect.setTargetPointer(new FixedTarget(card.getId())); + effect.setTargetPointer(new FixedTarget(card.getId(), game)); game.addEffect(effect, source); } controller.shuffleLibrary(source, game); @@ -137,7 +137,7 @@ class DarkDecisionMayPlayExiledEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - if (objectId.equals(getTargetPointer().getFirst(game, source)) && affectedControllerId.equals(source.getSourceId())) { + if (objectId.equals(getTargetPointer().getFirst(game, source)) && affectedControllerId.equals(source.getControllerId())) { ExileZone exileZone = game.getExile().getExileZone(source.getSourceId()); return exileZone != null && exileZone.contains(getTargetPointer().getFirst(game, source)); } diff --git a/Mage.Sets/src/mage/cards/d/DiaochanArtfulBeauty.java b/Mage.Sets/src/mage/cards/d/DiaochanArtfulBeauty.java index 079a72c15e9..00f50eb31d4 100644 --- a/Mage.Sets/src/mage/cards/d/DiaochanArtfulBeauty.java +++ b/Mage.Sets/src/mage/cards/d/DiaochanArtfulBeauty.java @@ -64,7 +64,7 @@ public class DiaochanArtfulBeauty extends CardImpl { // {tap}: Destroy target creature of your choice, then destroy target creature of an opponent's choice. Activate this ability only during your turn, before attackers are declared. Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new DiaochanArtfulBeautyDestroyEffect(), new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.getInstance()); ability.addTarget(new TargetCreaturePermanent()); - ability.addTarget(new TargetOpponentsChoicePermanent(new FilterCreaturePermanent())); + ability.addTarget(new TargetOpponentsChoicePermanent(1, 1, new FilterCreaturePermanent(), false, true)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DoublingSeason.java b/Mage.Sets/src/mage/cards/d/DoublingSeason.java index 8cbd0a541e0..7e9f3671232 100644 --- a/Mage.Sets/src/mage/cards/d/DoublingSeason.java +++ b/Mage.Sets/src/mage/cards/d/DoublingSeason.java @@ -49,7 +49,7 @@ import mage.game.stack.StackObject; public class DoublingSeason extends CardImpl { public DoublingSeason(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{4}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{G}"); // If an effect would put one or more tokens onto the battlefield under your control, it puts twice that many of those tokens onto the battlefield instead. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DoublingSeasonTokenEffect())); @@ -91,16 +91,8 @@ class DoublingSeasonTokenEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - StackObject spell = game.getStack().getStackObject(event.getSourceId()); - if (spell != null && spell.getControllerId().equals(source.getControllerId())) { - return true; - } - return false; - } - - @Override - public boolean apply(Game game, Ability source) { - return true; + StackObject stackObject = game.getStack().getStackObject(event.getSourceId()); + return stackObject != null && event.getPlayerId().equals(source.getControllerId()); } @Override @@ -139,10 +131,7 @@ class DoublingSeasonCounterEffect extends ReplacementEffectImpl { if (permanent == null) { permanent = game.getPermanentEntering(event.getTargetId()); } - if (permanent != null && permanent.getControllerId().equals(source.getControllerId())) { - return true; - } - return false; + return permanent != null && permanent.getControllerId().equals(source.getControllerId()); } @Override diff --git a/Mage.Sets/src/mage/cards/e/EmrakulThePromisedEnd.java b/Mage.Sets/src/mage/cards/e/EmrakulThePromisedEnd.java index cda0e45b44d..175adfd6be0 100644 --- a/Mage.Sets/src/mage/cards/e/EmrakulThePromisedEnd.java +++ b/Mage.Sets/src/mage/cards/e/EmrakulThePromisedEnd.java @@ -34,7 +34,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.SpellAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CastSourceTriggeredAbility; import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.abilities.effects.common.turn.ControlTargetPlayerNextTurnEffect; @@ -64,12 +63,13 @@ import mage.util.CardUtil; public class EmrakulThePromisedEnd extends CardImpl { private static final FilterCard filter = new FilterCard("instants"); + static { filter.add(new CardTypePredicate(CardType.INSTANT)); } public EmrakulThePromisedEnd(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{13}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{13}"); this.supertype.add("Legendary"); this.subtype.add("Eldrazi"); this.power = new MageInt(13); diff --git a/Mage.Sets/src/mage/cards/e/ErsatzGnomes.java b/Mage.Sets/src/mage/cards/e/ErsatzGnomes.java index 9aa42cb980e..59bedb0ea96 100644 --- a/Mage.Sets/src/mage/cards/e/ErsatzGnomes.java +++ b/Mage.Sets/src/mage/cards/e/ErsatzGnomes.java @@ -49,17 +49,17 @@ import mage.target.TargetSpell; public class ErsatzGnomes extends CardImpl { public ErsatzGnomes(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{3}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}"); this.subtype.add("Gnome"); this.power = new MageInt(1); this.toughness = new MageInt(1); - // {tap}: Target spell becomes colorless. + // {T}: Target spell becomes colorless. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesColorTargetEffect(new ObjectColor(), Duration.Custom), new TapSourceCost()); ability.addTarget(new TargetSpell()); this.addAbility(ability); - // {tap}: Target permanent becomes colorless until end of turn. + // {T}: Target permanent becomes colorless until end of turn. ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesColorTargetEffect(new ObjectColor(), Duration.EndOfTurn), new TapSourceCost()); ability.addTarget(new TargetPermanent()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/e/Evangelize.java b/Mage.Sets/src/mage/cards/e/Evangelize.java new file mode 100644 index 00000000000..74ad62887d9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/Evangelize.java @@ -0,0 +1,69 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.e; + +import java.util.UUID; +import mage.abilities.effects.common.continuous.GainControlTargetEffect; +import mage.abilities.keyword.BuybackAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.target.common.TargetOpponentsChoicePermanent; + +/** + * + * @author spjspj + */ +public class Evangelize extends CardImpl { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); + + public Evangelize(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{W}"); + + // Buyback {2}{W}{W} + this.addAbility(new BuybackAbility("{2}{W}{W}")); + + // Gain control of target creature of an opponent's choice that he or she controls. + GainControlTargetEffect effect = new GainControlTargetEffect(Duration.EndOfGame); + effect.setText("Gain control of target creature of an opponent's choice that he or she controls"); + this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addTarget(new TargetOpponentsChoicePermanent(1, 1, filter, false, true)); + } + + public Evangelize(final Evangelize card) { + super(card); + } + + @Override + public Evangelize copy() { + return new Evangelize(this); + } +} diff --git a/Mage.Sets/src/mage/cards/e/Exogorth.java b/Mage.Sets/src/mage/cards/e/Exogorth.java index 165f16787b0..dcbe49f4ee3 100644 --- a/Mage.Sets/src/mage/cards/e/Exogorth.java +++ b/Mage.Sets/src/mage/cards/e/Exogorth.java @@ -29,19 +29,12 @@ package mage.cards.e; import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.RestrictionEffect; +import mage.abilities.keyword.CanBlockSpaceflightAbility; import mage.abilities.keyword.FlashAbility; -import mage.abilities.keyword.SpaceflightAbility; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.permanent.Permanent; /** * @@ -50,7 +43,7 @@ import mage.game.permanent.Permanent; public class Exogorth extends CardImpl { public Exogorth(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{G}{G}"); this.subtype.add("Slug"); this.power = new MageInt(7); this.toughness = new MageInt(7); @@ -61,8 +54,8 @@ public class Exogorth extends CardImpl { // Trample this.addAbility(TrampleAbility.getInstance()); - // Exogorth can block only creatures with spaceflight. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CanBlockOnlySpaceflightEffect())); + // Exogorth can block creatures with spaceflight. + this.addAbility(CanBlockSpaceflightAbility.getInstance()); } public Exogorth(final Exogorth card) { @@ -74,31 +67,3 @@ public class Exogorth extends CardImpl { return new Exogorth(this); } } - -class CanBlockOnlySpaceflightEffect extends RestrictionEffect { - - public CanBlockOnlySpaceflightEffect() { - super(Duration.EndOfTurn); - this.staticText = "{this} can block only creatures with spaceflight"; - } - - public CanBlockOnlySpaceflightEffect(final CanBlockOnlySpaceflightEffect effect) { - super(effect); - } - - @Override - public boolean applies(Permanent permanent, Ability source, Game game) { - return permanent.getId().equals(source.getSourceId()); - } - - @Override - public boolean canBlock(Permanent attacker, Permanent blocker, Ability source, Game game) { - return attacker.getAbilities().contains(SpaceflightAbility.getInstance()); - } - - @Override - public CanBlockOnlySpaceflightEffect copy() { - return new CanBlockOnlySpaceflightEffect(this); - } - -} diff --git a/Mage.Sets/src/mage/cards/f/Flux.java b/Mage.Sets/src/mage/cards/f/Flux.java new file mode 100644 index 00000000000..e213929da8b --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/Flux.java @@ -0,0 +1,95 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.f; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author emerald000 + */ +public class Flux extends CardImpl { + + public Flux(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{U}"); + + // Each player discards any number of cards, then draws that many cards. + this.getSpellAbility().addEffect(new FluxEffect()); + + // Draw a card. + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); + } + + public Flux(final Flux card) { + super(card); + } + + @Override + public Flux copy() { + return new Flux(this); + } +} + +class FluxEffect extends OneShotEffect { + + FluxEffect() { + super(Outcome.DrawCard); + this.staticText = "Each player discards any number of cards, then draws that many cards"; + } + + FluxEffect(final FluxEffect effect) { + super(effect); + } + + @Override + public FluxEffect copy() { + return new FluxEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + int numToDiscard = player.getAmount(0, player.getHand().size(), "Discard how many cards?", game); + player.discard(numToDiscard, false, source, game); + player.drawCards(numToDiscard, game); + } + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/f/ForceAdept.java b/Mage.Sets/src/mage/cards/f/ForceAdept.java index 553622b1866..7d0b1b83e57 100644 --- a/Mage.Sets/src/mage/cards/f/ForceAdept.java +++ b/Mage.Sets/src/mage/cards/f/ForceAdept.java @@ -63,7 +63,7 @@ public class ForceAdept extends CardImpl { } public ForceAdept(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{G}{U}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{U}{W}"); this.subtype.add("Mirialan"); this.subtype.add("Jedi"); this.power = new MageInt(2); @@ -74,8 +74,8 @@ public class ForceAdept extends CardImpl { // When Force Adept enters the battlefield, return another target creature you control and target creature you don't control to their owner's hands. Ability ability = new EntersBattlefieldTriggeredAbility(new ForceAdeptEffect()); - this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(filter1)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter2)); + ability.addTarget(new TargetControlledCreaturePermanent(filter1)); + ability.addTarget(new TargetCreaturePermanent(filter2)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GlintNestCrane.java b/Mage.Sets/src/mage/cards/g/GlintNestCrane.java index fe6e83eb947..4261ffcaf2c 100644 --- a/Mage.Sets/src/mage/cards/g/GlintNestCrane.java +++ b/Mage.Sets/src/mage/cards/g/GlintNestCrane.java @@ -36,6 +36,7 @@ import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.predicate.mageobject.CardTypePredicate; @@ -48,11 +49,11 @@ public class GlintNestCrane extends CardImpl { private static final FilterCard filter = new FilterCard("an artifact card"); static { - filter.add(new CardTypePredicate(CardType.ARTIFACT)); + filter.add(new CardTypePredicate(CardType.ARTIFACT)); } public GlintNestCrane(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); this.subtype.add("Bird"); this.power = new MageInt(1); this.toughness = new MageInt(3); @@ -62,7 +63,8 @@ public class GlintNestCrane extends CardImpl { // When Glint-Nest Crane enters the battlefield, look at the top four cards of your library. You may reveal an artifact card from among them and // put it into your hand. Put the rest on the bottom of your library in any order. - this.addAbility(new EntersBattlefieldTriggeredAbility(new LookLibraryAndPickControllerEffect(new StaticValue(4), false, new StaticValue(1), filter, false))); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new LookLibraryAndPickControllerEffect(new StaticValue(4), false, new StaticValue(1), filter, Zone.LIBRARY, false, true, false, Zone.HAND, true))); } public GlintNestCrane(final GlintNestCrane card) { diff --git a/Mage.Sets/src/mage/cards/g/Grindclock.java b/Mage.Sets/src/mage/cards/g/Grindclock.java index fae092d35fa..8a3acf2e2c8 100644 --- a/Mage.Sets/src/mage/cards/g/Grindclock.java +++ b/Mage.Sets/src/mage/cards/g/Grindclock.java @@ -25,13 +25,9 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.cards.g; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Zone; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; @@ -39,9 +35,12 @@ import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.CardType; import mage.constants.Outcome; +import mage.constants.Zone; import mage.counters.CounterType; import mage.game.Game; +import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPlayer; @@ -51,15 +50,16 @@ import mage.target.TargetPlayer; */ public class Grindclock extends CardImpl { - public Grindclock (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}"); + public Grindclock(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), new TapSourceCost())); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GrindclockEffect(), new TapSourceCost()); ability.addTarget(new TargetPlayer()); this.addAbility(ability); } - public Grindclock (final Grindclock card) { + public Grindclock(final Grindclock card) { super(card); } @@ -71,6 +71,7 @@ public class Grindclock extends CardImpl { } class GrindclockEffect extends OneShotEffect { + public GrindclockEffect() { super(Outcome.Detriment); staticText = "Target player puts the top X cards of his or her library into his or her graveyard, where X is the number of charge counters on {this}"; @@ -82,11 +83,14 @@ class GrindclockEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - int amount = game.getPermanent(source.getSourceId()).getCounters(game).getCount(CounterType.CHARGE); - Player targetPlayer = game.getPlayer(source.getFirstTarget()); - if (targetPlayer != null) { - targetPlayer.moveCards(targetPlayer.getLibrary().getTopCards(game, amount), Zone.GRAVEYARD, source, game); - return true; + Permanent sourceObject = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (sourceObject != null) { + int amount = sourceObject.getCounters(game).getCount(CounterType.CHARGE); + Player targetPlayer = game.getPlayer(source.getFirstTarget()); + if (targetPlayer != null) { + targetPlayer.moveCards(targetPlayer.getLibrary().getTopCards(game, amount), Zone.GRAVEYARD, source, game); + return true; + } } return false; } @@ -96,4 +100,4 @@ class GrindclockEffect extends OneShotEffect { return new GrindclockEffect(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/g/GunganCaptain.java b/Mage.Sets/src/mage/cards/g/GunganCaptain.java index b74a9f328bd..19faa03e27e 100644 --- a/Mage.Sets/src/mage/cards/g/GunganCaptain.java +++ b/Mage.Sets/src/mage/cards/g/GunganCaptain.java @@ -44,7 +44,7 @@ import mage.constants.CardType; public class GunganCaptain extends CardImpl { public GunganCaptain(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); this.subtype.add("Gungan"); this.subtype.add("Warrior"); this.power = new MageInt(1); diff --git a/Mage.Sets/src/mage/cards/m/MagusOfTheArena.java b/Mage.Sets/src/mage/cards/m/MagusOfTheArena.java index c772c80dfd4..79082571e4f 100644 --- a/Mage.Sets/src/mage/cards/m/MagusOfTheArena.java +++ b/Mage.Sets/src/mage/cards/m/MagusOfTheArena.java @@ -64,7 +64,7 @@ public class MagusOfTheArena extends CardImpl { Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MagusOfTheArenaEffect(), new GenericManaCost(3)); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetControlledCreaturePermanent()); - ability.addTarget(new TargetOpponentsChoicePermanent(new FilterControlledCreaturePermanent())); + ability.addTarget(new TargetOpponentsChoicePermanent(1, 1, new FilterControlledCreaturePermanent(), false, true)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/p/PaintersServant.java b/Mage.Sets/src/mage/cards/p/PaintersServant.java index 8fdb6e4750a..b84c9b18a61 100644 --- a/Mage.Sets/src/mage/cards/p/PaintersServant.java +++ b/Mage.Sets/src/mage/cards/p/PaintersServant.java @@ -59,7 +59,7 @@ import mage.sets.Commander; public class PaintersServant extends CardImpl { public PaintersServant(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{2}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{2}"); this.subtype.add("Scarecrow"); this.power = new MageInt(1); @@ -97,24 +97,23 @@ class PaintersServantEffect extends ContinuousEffectImpl { if (color == null) { return false; } - String colorString = color.toString(); for (Permanent perm : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) { - setObjectColor(perm, colorString, game); + perm.getColor(game).addColor(color); } // Stack for (MageObject object : game.getStack()) { if (object instanceof Spell) { - setObjectColor(object, colorString, game); + object.getColor(game).addColor(color); } } // Exile for (Card card : game.getExile().getAllCards(game)) { - setCardColor(card, colorString, game); + game.getState().getCreateCardAttribute(card).getColor().addColor(color); } // Command for (CommandObject commandObject : game.getState().getCommand()) { if (commandObject instanceof Commander) { - setObjectColor(commandObject, colorString, game); + commandObject.getColor(game).addColor(color); } } @@ -123,15 +122,15 @@ class PaintersServantEffect extends ContinuousEffectImpl { if (player != null) { // Hand for (Card card : player.getHand().getCards(game)) { - setCardColor(card, colorString, game); + game.getState().getCreateCardAttribute(card).getColor().addColor(color); } // Library for (Card card : player.getLibrary().getCards(game)) { - setCardColor(card, colorString, game); + game.getState().getCreateCardAttribute(card).getColor().addColor(color); } // Graveyard for (Card card : player.getGraveyard().getCards(game)) { - setCardColor(card, colorString, game); + game.getState().getCreateCardAttribute(card).getColor().addColor(color); } } } @@ -140,47 +139,6 @@ class PaintersServantEffect extends ContinuousEffectImpl { return false; } - protected static void setCardColor(Card card, String colorString, Game game) { - ObjectColor color = game.getState().getCreateCardAttribute(card).getColor(); - switch (colorString) { - case "W": - color.setWhite(true); - break; - case "B": - color.setBlack(true); - break; - case "U": - color.setBlue(true); - break; - case "G": - color.setGreen(true); - break; - case "R": - color.setRed(true); - break; - } - } - - protected static void setObjectColor(MageObject obj, String colorString, Game game) { - switch (colorString) { - case "W": - obj.getColor(game).setWhite(true); - break; - case "B": - obj.getColor(game).setBlack(true); - break; - case "U": - obj.getColor(game).setBlue(true); - break; - case "G": - obj.getColor(game).setGreen(true); - break; - case "R": - obj.getColor(game).setRed(true); - break; - } - } - @Override public PaintersServantEffect copy() { return new PaintersServantEffect(this); diff --git a/Mage.Sets/src/mage/cards/p/Preacher.java b/Mage.Sets/src/mage/cards/p/Preacher.java index 706d6b23a0f..cf59a2aad1b 100644 --- a/Mage.Sets/src/mage/cards/p/Preacher.java +++ b/Mage.Sets/src/mage/cards/p/Preacher.java @@ -69,7 +69,7 @@ public class Preacher extends CardImpl { // {tap}: Gain control of target creature of an opponent's choice that he or she controls for as long as Preacher remains tapped. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PreacherEffect(), new TapSourceCost()); - ability.addTarget(new TargetOpponentsChoicePermanent(new FilterControlledCreaturePermanent())); + ability.addTarget(new TargetOpponentsChoicePermanent(1, 1, new FilterControlledCreaturePermanent(), false, true)); this.addAbility(ability); @@ -127,4 +127,4 @@ class PreacherEffect extends OneShotEffect { } return false; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/p/PrizedAmalgam.java b/Mage.Sets/src/mage/cards/p/PrizedAmalgam.java index 620bfd6666e..e0ac8f96fd6 100644 --- a/Mage.Sets/src/mage/cards/p/PrizedAmalgam.java +++ b/Mage.Sets/src/mage/cards/p/PrizedAmalgam.java @@ -33,7 +33,7 @@ import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; -import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -45,6 +45,7 @@ import mage.filter.predicate.other.OwnerPredicate; import mage.game.Game; import mage.game.events.EntersTheBattlefieldEvent; import mage.game.events.GameEvent; +import mage.target.targetpointer.FixedTarget; import mage.watchers.common.CastFromGraveyardWatcher; /** @@ -60,14 +61,16 @@ public class PrizedAmalgam extends CardImpl { } public PrizedAmalgam(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{B}"); this.subtype.add("Zombie"); this.power = new MageInt(3); this.toughness = new MageInt(3); // Whenever a creature enters the battlefield, if it entered from your graveyard or you cast it from your graveyard, return Prized Amalgam from your graveyard to the battlefield tapped at the beginning of the next end step. + Effect effect = new ReturnFromGraveyardToBattlefieldTargetEffect(true); + effect.setText("return {this} from your graveyard to the battlefield tapped at the beginning of the next end step"); this.addAbility(new PrizedAmalgamTriggerdAbility(new CreateDelayedTriggeredAbilityEffect( - new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ReturnSourceFromGraveyardToBattlefieldEffect(true))), filter), + new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect)), filter), new CastFromGraveyardWatcher()); } @@ -98,20 +101,32 @@ class PrizedAmalgamTriggerdAbility extends EntersBattlefieldAllTriggeredAbility @Override public boolean checkTrigger(GameEvent event, Game game) { + /** + * 4/8/2016 Prized Amalgam’s ability triggers only if it’s in your + * graveyard immediately after a creature enters the battlefield from + * your graveyard or you cast a creature from your graveyard. A Prized + * Amalgam that’s already on the battlefield won’t be returned at the + * beginning of the next end step if it’s put into your graveyard later. + */ + boolean result = false; if (super.checkTrigger(event, game)) { EntersTheBattlefieldEvent entersEvent = (EntersTheBattlefieldEvent) event; if (entersEvent.getFromZone().equals(Zone.GRAVEYARD)) { - return true; - } - if (entersEvent.getFromZone().equals(Zone.STACK) && entersEvent.getTarget().getControllerId().equals(getControllerId())) { + result = true; + } else if (entersEvent.getFromZone().equals(Zone.STACK) && entersEvent.getTarget().getControllerId().equals(getControllerId())) { CastFromGraveyardWatcher watcher = (CastFromGraveyardWatcher) game.getState().getWatchers().get(CastFromGraveyardWatcher.class.getName()); if (watcher != null) { int zcc = game.getState().getZoneChangeCounter(event.getSourceId()); - return watcher.spellWasCastFromGraveyard(event.getSourceId(), zcc - 1); + result = watcher.spellWasCastFromGraveyard(event.getSourceId(), zcc - 1); } } } - return false; + if (result) { + for (Effect effect : getEffects()) { + effect.setTargetPointer(new FixedTarget(getSourceId(), game.getState().getZoneChangeCounter(getSourceId()))); + } + } + return result; } @Override diff --git a/Mage.Sets/src/mage/cards/s/SalvageSlasher.java b/Mage.Sets/src/mage/cards/s/SalvageSlasher.java index 2f449ad8630..6d691405d84 100644 --- a/Mage.Sets/src/mage/cards/s/SalvageSlasher.java +++ b/Mage.Sets/src/mage/cards/s/SalvageSlasher.java @@ -28,9 +28,6 @@ package mage.cards.s; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Zone; import mage.MageInt; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount; @@ -38,6 +35,9 @@ import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; import mage.filter.common.FilterArtifactCard; /** @@ -47,13 +47,15 @@ import mage.filter.common.FilterArtifactCard; public class SalvageSlasher extends CardImpl { public SalvageSlasher(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{1}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{1}{B}"); this.subtype.add("Human"); this.subtype.add("Rogue"); this.power = new MageInt(1); this.toughness = new MageInt(1); - BoostSourceEffect effect = new BoostSourceEffect(new CardsInControllerGraveyardCount(new FilterArtifactCard()), + + // Salvage Slasher gets +1/+0 for each artifact card in your graveyard. + BoostSourceEffect effect = new BoostSourceEffect(new CardsInControllerGraveyardCount(new FilterArtifactCard("artifact card")), new StaticValue(0), Duration.WhileOnBattlefield); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); diff --git a/Mage.Sets/src/mage/cards/s/SithMarauder.java b/Mage.Sets/src/mage/cards/s/SithMarauder.java index b3520da7799..73817f9334a 100644 --- a/Mage.Sets/src/mage/cards/s/SithMarauder.java +++ b/Mage.Sets/src/mage/cards/s/SithMarauder.java @@ -47,13 +47,13 @@ import mage.watchers.common.LifeLossOtherFromCombatWatcher; public class SithMarauder extends CardImpl { public SithMarauder(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{R}"); this.subtype.add("Human"); this.subtype.add("Sith"); this.power = new MageInt(5); this.toughness = new MageInt(4); - // Hate — When Sith Marauder enters the battlefield, if opponent lost life from source other than combat damage this turn, Sith Marauder deals 3 damage to target creature or player. + // Hate — When Sith Marauder enters the battlefield, if an opponent lost life from a source other than combat damage this turn, Sith Marauder deals 3 damage to target creature or player. Ability ability = new ConditionalTriggeredAbility( new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(3)), HateCondition.getInstance(), diff --git a/Mage.Sets/src/mage/cards/t/TezzeretTheSeeker.java b/Mage.Sets/src/mage/cards/t/TezzeretTheSeeker.java index 8df2200fdbe..6b46fb04743 100644 --- a/Mage.Sets/src/mage/cards/t/TezzeretTheSeeker.java +++ b/Mage.Sets/src/mage/cards/t/TezzeretTheSeeker.java @@ -63,7 +63,7 @@ import mage.target.common.TargetCardInLibrary; public class TezzeretTheSeeker extends CardImpl { public TezzeretTheSeeker(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.PLANESWALKER},"{3}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{3}{U}{U}"); this.subtype.add("Tezzeret"); this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(4)); @@ -118,7 +118,7 @@ class TezzeretTheSeekerEffect2 extends OneShotEffect { } } - FilterArtifactCard filter = new FilterArtifactCard(new StringBuilder("artifact card with converted mana cost ").append(cmc).append(" or less").toString()); + FilterArtifactCard filter = new FilterArtifactCard("artifact card with converted mana cost " + cmc + " or less"); filter.add(new ConvertedManaCostPredicate(ComparisonType.LessThan, cmc + 1)); TargetCardInLibrary target = new TargetCardInLibrary(filter); diff --git a/Mage.Sets/src/mage/cards/t/TradeFederationBattleship.java b/Mage.Sets/src/mage/cards/t/TradeFederationBattleship.java index 7b126eee537..4cfac14e8db 100644 --- a/Mage.Sets/src/mage/cards/t/TradeFederationBattleship.java +++ b/Mage.Sets/src/mage/cards/t/TradeFederationBattleship.java @@ -62,10 +62,10 @@ public class TradeFederationBattleship extends CardImpl { } public TradeFederationBattleship(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{3}{W}{U}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}{W}{U}{B}"); this.subtype.add("Starship"); - this.power = new MageInt(2); - this.toughness = new MageInt(2); + this.power = new MageInt(0); + this.toughness = new MageInt(6); // Spaceflight this.addAbility(SpaceflightAbility.getInstance()); diff --git a/Mage.Sets/src/mage/cards/v/VaporSnag.java b/Mage.Sets/src/mage/cards/v/VaporSnag.java index 40506bc8d15..53357b11c8f 100644 --- a/Mage.Sets/src/mage/cards/v/VaporSnag.java +++ b/Mage.Sets/src/mage/cards/v/VaporSnag.java @@ -25,16 +25,14 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.cards.v; import java.util.UUID; - -import mage.constants.CardType; import mage.abilities.effects.common.LoseLifeTargetControllerEffect; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.CardType; import mage.target.common.TargetCreaturePermanent; /** @@ -43,17 +41,16 @@ import mage.target.common.TargetCreaturePermanent; */ public class VaporSnag extends CardImpl { - public VaporSnag (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{U}"); + public VaporSnag(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}"); - // Return target creature to its owner's hand. Its controller loses 1 life. this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()); this.getSpellAbility().addEffect(new LoseLifeTargetControllerEffect(1)); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } - public VaporSnag (final VaporSnag card) { + public VaporSnag(final VaporSnag card) { super(card); } diff --git a/Mage.Sets/src/mage/cards/v/VolcanicOffering.java b/Mage.Sets/src/mage/cards/v/VolcanicOffering.java index ee3f2080f8b..2313bd7358f 100644 --- a/Mage.Sets/src/mage/cards/v/VolcanicOffering.java +++ b/Mage.Sets/src/mage/cards/v/VolcanicOffering.java @@ -86,12 +86,12 @@ public class VolcanicOffering extends CardImpl { FilterLandPermanent filterLandForOpponent = new FilterLandPermanent("nonbasic land not controlled by " + controller.getLogName()); filterLandForOpponent.add(Predicates.not(new SupertypePredicate("Basic"))); filterLandForOpponent.add(Predicates.not(new ControllerIdPredicate(controller.getId()))); - ability.addTarget(new TargetOpponentsChoicePermanent(filterLandForOpponent)); + ability.addTarget(new TargetOpponentsChoicePermanent(1, 1, filterLandForOpponent, false, true)); ability.addTarget(new TargetPermanent(filterCreature)); FilterCreaturePermanent filterCreatureForOpponent = new FilterCreaturePermanent("creature not controlled by " + controller.getLogName()); filterCreatureForOpponent.add(Predicates.not(new ControllerIdPredicate(controller.getId()))); - ability.addTarget(new TargetOpponentsChoicePermanent(filterCreatureForOpponent)); + ability.addTarget(new TargetOpponentsChoicePermanent(1, 1, filterCreatureForOpponent, false, true)); } } diff --git a/Mage.Sets/src/mage/cards/w/Withdraw.java b/Mage.Sets/src/mage/cards/w/Withdraw.java new file mode 100644 index 00000000000..b56eadce608 --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/Withdraw.java @@ -0,0 +1,119 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.w; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.costs.Cost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.AnotherTargetPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.Target; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author emerald000 + */ +public class Withdraw extends CardImpl { + + public Withdraw(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}{U}"); + + // Return target creature to its owner's hand. Then return another target creature to its owner's hand unless its controller pays {1}. + this.getSpellAbility().addEffect(new WithdrawEffect()); + Target target = new TargetCreaturePermanent(new FilterCreaturePermanent("creature to return unconditionally")); + target.setTargetTag(1); + this.getSpellAbility().addTarget(target); + + FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature to return unless {1} is paid"); + filter.add(new AnotherTargetPredicate(2)); + target = new TargetCreaturePermanent(filter); + target.setTargetTag(2); + this.getSpellAbility().addTarget(target); + } + + public Withdraw(final Withdraw card) { + super(card); + } + + @Override + public Withdraw copy() { + return new Withdraw(this); + } +} + +class WithdrawEffect extends OneShotEffect { + + WithdrawEffect() { + super(Outcome.ReturnToHand); + this.staticText = "Return target creature to its owner's hand. Then return another target creature to its owner's hand unless its controller pays {1}"; + } + + WithdrawEffect(final WithdrawEffect effect) { + super(effect); + } + + @Override + public WithdrawEffect copy() { + return new WithdrawEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Effect effect = new ReturnToHandTargetEffect(); + effect.setTargetPointer(new FixedTarget(source.getFirstTarget())); + effect.apply(game, source); + Permanent secondCreature = game.getPermanent(source.getTargets().get(1).getFirstTarget()); + if (secondCreature != null) { + Player creatureController = game.getPlayer(secondCreature.getControllerId()); + if (creatureController != null) { + Cost cost = new GenericManaCost(1); + if (creatureController.chooseUse(Outcome.Benefit, "Pay {1}? (Otherwise " + secondCreature.getName() + " will be returned to its owner's hand)", source, game)) { + cost.pay(source, game, source.getSourceId(), creatureController.getId(), false); + } + if (!cost.isPaid()) { + creatureController.moveCards(secondCreature, Zone.HAND, source, game); + } + } + } + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/Portal.java b/Mage.Sets/src/mage/sets/Portal.java index 1d7eae6edfc..4bc69093273 100644 --- a/Mage.Sets/src/mage/sets/Portal.java +++ b/Mage.Sets/src/mage/sets/Portal.java @@ -1,273 +1,274 @@ -/* - * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of BetaSteward_at_googlemail.com. - */ - -package mage.sets; - -import mage.cards.ExpansionSet; -import mage.constants.SetType; -import mage.constants.Rarity; -import mage.cards.CardGraphicInfo; - -/** - * - * @author Plopman - */ - -public class Portal extends ExpansionSet { - - private static final Portal fINSTANCE = new Portal(); - - /** - * - * @return - */ - public static Portal getInstance() { - return fINSTANCE; - } - - private Portal() { - super("Portal", "POR", ExpansionSet.buildDate(1997, 5, 1), SetType.SUPPLEMENTAL); - this.blockName = "Beginner"; - this.hasBasicLands = true; - this.hasBoosters = true; - this.numBoosterLands = 0; - this.numBoosterCommon = 11; - this.numBoosterUncommon = 3; - this.numBoosterRare = 1; - this.ratioBoosterMythic = 0; - cards.add(new SetCardInfo("Alabaster Dragon", 163, Rarity.RARE, mage.cards.a.AlabasterDragon.class)); - cards.add(new SetCardInfo("Alluring Scent", 80, Rarity.RARE, mage.cards.a.AlluringScent.class)); - cards.add(new SetCardInfo("Anaconda", 81, Rarity.UNCOMMON, mage.cards.a.Anaconda.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Anaconda", 82, Rarity.UNCOMMON, mage.cards.a.Anaconda.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Ancestral Memories", 41, Rarity.RARE, mage.cards.a.AncestralMemories.class)); - cards.add(new SetCardInfo("Angelic Blessing", 164, Rarity.COMMON, mage.cards.a.AngelicBlessing.class)); - cards.add(new SetCardInfo("Archangel", 165, Rarity.RARE, mage.cards.a.Archangel.class)); - cards.add(new SetCardInfo("Ardent Militia", 166, Rarity.UNCOMMON, mage.cards.a.ArdentMilitia.class)); - cards.add(new SetCardInfo("Armageddon", 167, Rarity.RARE, mage.cards.a.Armageddon.class)); - cards.add(new SetCardInfo("Armored Pegasus", 168, Rarity.COMMON, mage.cards.a.ArmoredPegasus.class)); - cards.add(new SetCardInfo("Arrogant Vampire", 1, Rarity.UNCOMMON, mage.cards.a.ArrogantVampire.class)); - cards.add(new SetCardInfo("Balance of Power", 42, Rarity.RARE, mage.cards.b.BalanceOfPower.class)); - cards.add(new SetCardInfo("Baleful Stare", 43, Rarity.UNCOMMON, mage.cards.b.BalefulStare.class)); - cards.add(new SetCardInfo("Bee Sting", 83, Rarity.UNCOMMON, mage.cards.b.BeeSting.class)); - cards.add(new SetCardInfo("Blaze", 122, Rarity.UNCOMMON, mage.cards.b.Blaze.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Blaze", 123, Rarity.UNCOMMON, mage.cards.b.Blaze.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Blessed Reversal", 169, Rarity.RARE, mage.cards.b.BlessedReversal.class)); - cards.add(new SetCardInfo("Blinding Light", 170, Rarity.RARE, mage.cards.b.BlindingLight.class)); - cards.add(new SetCardInfo("Bog Imp", 3, Rarity.COMMON, mage.cards.b.BogImp.class)); - cards.add(new SetCardInfo("Bog Raiders", 4, Rarity.COMMON, mage.cards.b.BogRaiders.class)); - cards.add(new SetCardInfo("Bog Wraith", 5, Rarity.UNCOMMON, mage.cards.b.BogWraith.class)); - cards.add(new SetCardInfo("Boiling Seas", 124, Rarity.UNCOMMON, mage.cards.b.BoilingSeas.class)); - cards.add(new SetCardInfo("Border Guard", 171, Rarity.COMMON, mage.cards.b.BorderGuard.class)); - cards.add(new SetCardInfo("Breath of Life", 172, Rarity.COMMON, mage.cards.b.BreathOfLife.class)); - cards.add(new SetCardInfo("Bull Hippo", 84, Rarity.UNCOMMON, mage.cards.b.BullHippo.class)); - cards.add(new SetCardInfo("Burning Cloak", 125, Rarity.COMMON, mage.cards.b.BurningCloak.class)); - cards.add(new SetCardInfo("Capricious Sorcerer", 44, Rarity.RARE, mage.cards.c.CapriciousSorcerer.class)); - cards.add(new SetCardInfo("Charging Bandits", 6, Rarity.UNCOMMON, mage.cards.c.ChargingBandits.class)); - cards.add(new SetCardInfo("Charging Paladin", 173, Rarity.UNCOMMON, mage.cards.c.ChargingPaladin.class)); - cards.add(new SetCardInfo("Charging Rhino", 85, Rarity.RARE, mage.cards.c.ChargingRhino.class)); - cards.add(new SetCardInfo("Cloak of Feathers", 45, Rarity.COMMON, mage.cards.c.CloakOfFeathers.class)); - cards.add(new SetCardInfo("Cloud Dragon", 46, Rarity.RARE, mage.cards.c.CloudDragon.class)); - cards.add(new SetCardInfo("Cloud Pirates", 47, Rarity.COMMON, mage.cards.c.CloudPirates.class)); - cards.add(new SetCardInfo("Cloud Spirit", 48, Rarity.UNCOMMON, mage.cards.c.CloudSpirit.class)); - cards.add(new SetCardInfo("Coral Eel", 50, Rarity.COMMON, mage.cards.c.CoralEel.class)); - cards.add(new SetCardInfo("Craven Giant", 126, Rarity.COMMON, mage.cards.c.CravenGiant.class)); - cards.add(new SetCardInfo("Craven Knight", 7, Rarity.COMMON, mage.cards.c.CravenKnight.class)); - cards.add(new SetCardInfo("Cruel Bargain", 8, Rarity.RARE, mage.cards.c.CruelBargain.class)); - cards.add(new SetCardInfo("Cruel Tutor", 9, Rarity.RARE, mage.cards.c.CruelTutor.class)); - cards.add(new SetCardInfo("Deep-Sea Serpent", 52, Rarity.UNCOMMON, mage.cards.d.DeepSeaSerpent.class)); - cards.add(new SetCardInfo("Deja Vu", 53, Rarity.COMMON, mage.cards.d.DejaVu.class)); - cards.add(new SetCardInfo("Desert Drake", 127, Rarity.UNCOMMON, mage.cards.d.DesertDrake.class)); - cards.add(new SetCardInfo("Devastation", 128, Rarity.RARE, mage.cards.d.Devastation.class)); - cards.add(new SetCardInfo("Devoted Hero", 175, Rarity.COMMON, mage.cards.d.DevotedHero.class)); - cards.add(new SetCardInfo("Djinn of the Lamp", 54, Rarity.RARE, mage.cards.d.DjinnOfTheLamp.class)); - cards.add(new SetCardInfo("Dread Reaper", 11, Rarity.RARE, mage.cards.d.DreadReaper.class)); - cards.add(new SetCardInfo("Dry Spell", 12, Rarity.UNCOMMON, mage.cards.d.DrySpell1.class)); - cards.add(new SetCardInfo("Earthquake", 129, Rarity.RARE, mage.cards.e.Earthquake.class)); - cards.add(new SetCardInfo("Ebon Dragon", 13, Rarity.RARE, mage.cards.e.EbonDragon.class)); - cards.add(new SetCardInfo("Elite Cat Warrior", 87, Rarity.COMMON, mage.cards.e.EliteCatWarrior1.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Elite Cat Warrior", 88, Rarity.COMMON, mage.cards.e.EliteCatWarrior1.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Elven Cache", 89, Rarity.COMMON, mage.cards.e.ElvenCache.class)); - cards.add(new SetCardInfo("Elvish Ranger", 90, Rarity.COMMON, mage.cards.e.ElvishRanger.class)); - cards.add(new SetCardInfo("Endless Cockroaches", 14, Rarity.RARE, mage.cards.e.EndlessCockroaches.class)); - cards.add(new SetCardInfo("Exhaustion", 55, Rarity.RARE, mage.cards.e.Exhaustion.class)); - cards.add(new SetCardInfo("False Peace", 176, Rarity.COMMON, mage.cards.f.FalsePeace.class)); - cards.add(new SetCardInfo("Feral Shadow", 15, Rarity.COMMON, mage.cards.f.FeralShadow.class)); - cards.add(new SetCardInfo("Final Strike", 16, Rarity.RARE, mage.cards.f.FinalStrike.class)); - cards.add(new SetCardInfo("Fire Dragon", 130, Rarity.RARE, mage.cards.f.FireDragon.class)); - cards.add(new SetCardInfo("Fire Imp", 131, Rarity.UNCOMMON, mage.cards.f.FireImp.class)); - cards.add(new SetCardInfo("Fire Snake", 132, Rarity.COMMON, mage.cards.f.FireSnake.class)); - cards.add(new SetCardInfo("Fire Tempest", 133, Rarity.RARE, mage.cards.f.FireTempest.class)); - cards.add(new SetCardInfo("Flashfires", 134, Rarity.UNCOMMON, mage.cards.f.Flashfires.class)); - cards.add(new SetCardInfo("Fleet-Footed Monk", 177, Rarity.COMMON, mage.cards.f.FleetFootedMonk.class)); - cards.add(new SetCardInfo("Foot Soldiers", 178, Rarity.COMMON, mage.cards.f.FootSoldiers.class)); - cards.add(new SetCardInfo("Forest", 203, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Forest", 204, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Forest", 205, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Forest", 206, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Fruition", 91, Rarity.COMMON, mage.cards.f.Fruition.class)); - cards.add(new SetCardInfo("Giant Octopus", 57, Rarity.COMMON, mage.cards.g.GiantOctopus.class)); - cards.add(new SetCardInfo("Giant Spider", 92, Rarity.COMMON, mage.cards.g.GiantSpider.class)); - cards.add(new SetCardInfo("Gift of Estates", 179, Rarity.RARE, mage.cards.g.GiftOfEstates.class)); - cards.add(new SetCardInfo("Goblin Bully", 136, Rarity.COMMON, mage.cards.g.GoblinBully.class)); - cards.add(new SetCardInfo("Gorilla Warrior", 93, Rarity.COMMON, mage.cards.g.GorillaWarrior.class)); - cards.add(new SetCardInfo("Gravedigger", 17, Rarity.UNCOMMON, mage.cards.g.Gravedigger.class)); - cards.add(new SetCardInfo("Grizzly Bears", 94, Rarity.COMMON, mage.cards.g.GrizzlyBears.class)); - cards.add(new SetCardInfo("Hand of Death", 18, Rarity.COMMON, mage.cards.h.HandOfDeath.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Hand of Death", 19, Rarity.COMMON, mage.cards.h.HandOfDeath.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Highland Giant", 137, Rarity.COMMON, mage.cards.h.HighlandGiant.class)); - cards.add(new SetCardInfo("Hill Giant", 138, Rarity.COMMON, mage.cards.h.HillGiant.class)); - cards.add(new SetCardInfo("Horned Turtle", 58, Rarity.COMMON, mage.cards.h.HornedTurtle.class)); - cards.add(new SetCardInfo("Howling Fury", 20, Rarity.COMMON, mage.cards.h.HowlingFury.class)); - cards.add(new SetCardInfo("Hulking Cyclops", 139, Rarity.UNCOMMON, mage.cards.h.HulkingCyclops.class)); - cards.add(new SetCardInfo("Hulking Goblin", 140, Rarity.COMMON, mage.cards.h.HulkingGoblin.class)); - cards.add(new SetCardInfo("Hurricane", 95, Rarity.RARE, mage.cards.h.Hurricane.class)); - cards.add(new SetCardInfo("Ingenious Thief", 59, Rarity.UNCOMMON, mage.cards.i.IngeniousThief.class)); - cards.add(new SetCardInfo("Island", 207, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Island", 208, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Island", 209, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Island", 210, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Jungle Lion", 96, Rarity.COMMON, mage.cards.j.JungleLion.class)); - cards.add(new SetCardInfo("Keen-Eyed Archers", 181, Rarity.COMMON, mage.cards.k.KeenEyedArchers.class)); - cards.add(new SetCardInfo("King's Assassin", 21, Rarity.RARE, mage.cards.k.KingsAssassin.class)); - cards.add(new SetCardInfo("Knight Errant", 182, Rarity.COMMON, mage.cards.k.KnightErrant.class)); - cards.add(new SetCardInfo("Last Chance", 141, Rarity.RARE, mage.cards.l.LastChance.class)); - cards.add(new SetCardInfo("Lava Axe", 142, Rarity.COMMON, mage.cards.l.LavaAxe.class)); - cards.add(new SetCardInfo("Lava Flow", 143, Rarity.UNCOMMON, mage.cards.l.LavaFlow.class)); - cards.add(new SetCardInfo("Lizard Warrior", 144, Rarity.COMMON, mage.cards.l.LizardWarrior.class)); - cards.add(new SetCardInfo("Man-o'-War", 60, Rarity.UNCOMMON, mage.cards.m.ManOWar.class)); - cards.add(new SetCardInfo("Mercenary Knight", 22, Rarity.RARE, mage.cards.m.MercenaryKnight.class)); - cards.add(new SetCardInfo("Merfolk of the Pearl Trident", 61, Rarity.COMMON, mage.cards.m.MerfolkOfThePearlTrident.class)); - cards.add(new SetCardInfo("Mind Knives", 23, Rarity.COMMON, mage.cards.m.MindKnives.class)); - cards.add(new SetCardInfo("Mind Rot", 24, Rarity.COMMON, mage.cards.m.MindRot.class)); - cards.add(new SetCardInfo("Minotaur Warrior", 145, Rarity.COMMON, mage.cards.m.MinotaurWarrior.class)); - cards.add(new SetCardInfo("Mobilize", 97, Rarity.COMMON, mage.cards.m.Mobilize.class)); - cards.add(new SetCardInfo("Monstrous Growth", 98, Rarity.COMMON, mage.cards.m.MonstrousGrowth.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Monstrous Growth", 99, Rarity.COMMON, mage.cards.m.MonstrousGrowth.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Moon Sprite", 100, Rarity.UNCOMMON, mage.cards.m.MoonSprite.class)); - cards.add(new SetCardInfo("Mountain", 211, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Mountain", 212, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Mountain", 213, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Mountain", 214, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Mountain Goat", 146, Rarity.UNCOMMON, mage.cards.m.MountainGoat.class)); - cards.add(new SetCardInfo("Muck Rats", 25, Rarity.COMMON, mage.cards.m.MuckRats.class)); - cards.add(new SetCardInfo("Mystic Denial", 62, Rarity.UNCOMMON, mage.cards.m.MysticDenial.class)); - cards.add(new SetCardInfo("Natural Order", 101, Rarity.RARE, mage.cards.n.NaturalOrder.class)); - cards.add(new SetCardInfo("Natural Spring", 102, Rarity.UNCOMMON, mage.cards.n.NaturalSpring.class)); - cards.add(new SetCardInfo("Nature's Cloak", 103, Rarity.RARE, mage.cards.n.NaturesCloak.class)); - cards.add(new SetCardInfo("Nature's Lore", 104, Rarity.COMMON, mage.cards.n.NaturesLore.class)); - cards.add(new SetCardInfo("Nature's Ruin", 26, Rarity.UNCOMMON, mage.cards.n.NaturesRuin.class)); - cards.add(new SetCardInfo("Needle Storm", 105, Rarity.UNCOMMON, mage.cards.n.NeedleStorm.class)); - cards.add(new SetCardInfo("Noxious Toad", 27, Rarity.UNCOMMON, mage.cards.n.NoxiousToad.class)); - cards.add(new SetCardInfo("Omen", 63, Rarity.COMMON, mage.cards.o.Omen.class)); - cards.add(new SetCardInfo("Owl Familiar", 64, Rarity.COMMON, mage.cards.o.OwlFamiliar.class)); - cards.add(new SetCardInfo("Panther Warriors", 106, Rarity.COMMON, mage.cards.p.PantherWarriors.class)); - cards.add(new SetCardInfo("Personal Tutor", 65, Rarity.UNCOMMON, mage.cards.p.PersonalTutor.class)); - cards.add(new SetCardInfo("Phantom Warrior", 66, Rarity.RARE, mage.cards.p.PhantomWarrior.class)); - cards.add(new SetCardInfo("Pillaging Horde", 147, Rarity.RARE, mage.cards.p.PillagingHorde.class)); - cards.add(new SetCardInfo("Plains", 215, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Plains", 216, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Plains", 217, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Plains", 218, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Plant Elemental", 107, Rarity.UNCOMMON, mage.cards.p.PlantElemental.class)); - cards.add(new SetCardInfo("Primeval Force", 108, Rarity.RARE, mage.cards.p.PrimevalForce.class)); - cards.add(new SetCardInfo("Prosperity", 67, Rarity.RARE, mage.cards.p.Prosperity.class)); - cards.add(new SetCardInfo("Pyroclasm", 148, Rarity.RARE, mage.cards.p.Pyroclasm.class)); - cards.add(new SetCardInfo("Python", 28, Rarity.COMMON, mage.cards.p.Python.class)); - cards.add(new SetCardInfo("Raging Cougar", 149, Rarity.COMMON, mage.cards.r.RagingCougar.class)); - cards.add(new SetCardInfo("Raging Goblin", 150, Rarity.COMMON, mage.cards.r.RagingGoblin.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Raging Goblin", 151, Rarity.COMMON, mage.cards.r.RagingGoblin.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Raging Minotaur", 152, Rarity.COMMON, mage.cards.r.RagingMinotaur.class)); - cards.add(new SetCardInfo("Rain of Salt", 153, Rarity.UNCOMMON, mage.cards.r.RainOfSalt.class)); - cards.add(new SetCardInfo("Rain of Tears", 29, Rarity.UNCOMMON, mage.cards.r.RainOfTears.class)); - cards.add(new SetCardInfo("Raise Dead", 30, Rarity.COMMON, mage.cards.r.RaiseDead.class)); - cards.add(new SetCardInfo("Redwood Treefolk", 109, Rarity.COMMON, mage.cards.r.RedwoodTreefolk.class)); - cards.add(new SetCardInfo("Regal Unicorn", 184, Rarity.COMMON, mage.cards.r.RegalUnicorn.class)); - cards.add(new SetCardInfo("Renewing Dawn", 185, Rarity.UNCOMMON, mage.cards.r.RenewingDawn.class)); - cards.add(new SetCardInfo("Rowan Treefolk", 110, Rarity.COMMON, mage.cards.r.RowanTreefolk.class)); - cards.add(new SetCardInfo("Sacred Knight", 186, Rarity.COMMON, mage.cards.s.SacredKnight.class)); - cards.add(new SetCardInfo("Sacred Nectar", 187, Rarity.COMMON, mage.cards.s.SacredNectar.class)); - cards.add(new SetCardInfo("Scorching Spear", 154, Rarity.COMMON, mage.cards.s.ScorchingSpear.class)); - cards.add(new SetCardInfo("Seasoned Marshal", 188, Rarity.UNCOMMON, mage.cards.s.SeasonedMarshal.class)); - cards.add(new SetCardInfo("Serpent Assassin", 31, Rarity.RARE, mage.cards.s.SerpentAssassin.class)); - cards.add(new SetCardInfo("Serpent Warrior", 32, Rarity.COMMON, mage.cards.s.SerpentWarrior.class)); - cards.add(new SetCardInfo("Skeletal Crocodile", 33, Rarity.COMMON, mage.cards.s.SkeletalCrocodile.class)); - cards.add(new SetCardInfo("Skeletal Snake", 34, Rarity.COMMON, mage.cards.s.SkeletalSnake.class)); - cards.add(new SetCardInfo("Snapping Drake", 68, Rarity.COMMON, mage.cards.s.SnappingDrake.class)); - cards.add(new SetCardInfo("Sorcerous Sight", 69, Rarity.COMMON, mage.cards.s.SorcerousSight.class)); - cards.add(new SetCardInfo("Soul Shred", 35, Rarity.COMMON, mage.cards.s.SoulShred.class)); - cards.add(new SetCardInfo("Spined Wurm", 111, Rarity.COMMON, mage.cards.s.SpinedWurm.class)); - cards.add(new SetCardInfo("Spiritual Guardian", 189, Rarity.RARE, mage.cards.s.SpiritualGuardian.class)); - cards.add(new SetCardInfo("Spitting Earth", 156, Rarity.COMMON, mage.cards.s.SpittingEarth.class)); - cards.add(new SetCardInfo("Spotted Griffin", 190, Rarity.COMMON, mage.cards.s.SpottedGriffin.class)); - cards.add(new SetCardInfo("Stalking Tiger", 112, Rarity.COMMON, mage.cards.s.StalkingTiger.class)); - cards.add(new SetCardInfo("Starlight", 191, Rarity.UNCOMMON, mage.cards.s.Starlight.class)); - cards.add(new SetCardInfo("Starlit Angel", 192, Rarity.UNCOMMON, mage.cards.s.StarlitAngel.class)); - cards.add(new SetCardInfo("Steadfastness", 193, Rarity.COMMON, mage.cards.s.Steadfastness.class)); - cards.add(new SetCardInfo("Stern Marshal", 194, Rarity.RARE, mage.cards.s.SternMarshal.class)); - cards.add(new SetCardInfo("Stone Rain", 157, Rarity.COMMON, mage.cards.s.StoneRain.class)); - cards.add(new SetCardInfo("Storm Crow", 70, Rarity.COMMON, mage.cards.s.StormCrow.class)); - cards.add(new SetCardInfo("Summer Bloom", 113, Rarity.RARE, mage.cards.s.SummerBloom.class)); - cards.add(new SetCardInfo("Swamp", 219, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Swamp", 220, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Swamp", 221, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Swamp", 222, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Sylvan Tutor", 114, Rarity.RARE, mage.cards.s.SylvanTutor.class)); - cards.add(new SetCardInfo("Symbol of Unsummoning", 71, Rarity.COMMON, mage.cards.s.SymbolOfUnsummoning.class)); - cards.add(new SetCardInfo("Taunt", 72, Rarity.RARE, mage.cards.t.Taunt.class)); - cards.add(new SetCardInfo("Theft of Dreams", 73, Rarity.UNCOMMON, mage.cards.t.TheftOfDreams.class)); - cards.add(new SetCardInfo("Thing from the Deep", 74, Rarity.RARE, mage.cards.t.ThingFromTheDeep.class)); - cards.add(new SetCardInfo("Thundering Wurm", 115, Rarity.RARE, mage.cards.t.ThunderingWurm.class)); - cards.add(new SetCardInfo("Thundermare", 158, Rarity.RARE, mage.cards.t.Thundermare.class)); - cards.add(new SetCardInfo("Tidal Surge", 75, Rarity.COMMON, mage.cards.t.TidalSurge.class)); - cards.add(new SetCardInfo("Time Ebb", 76, Rarity.COMMON, mage.cards.t.TimeEbb.class)); - cards.add(new SetCardInfo("Touch of Brilliance", 77, Rarity.COMMON, mage.cards.t.TouchOfBrilliance.class)); - cards.add(new SetCardInfo("Undying Beast", 36, Rarity.COMMON, mage.cards.u.UndyingBeast.class)); - cards.add(new SetCardInfo("Untamed Wilds", 117, Rarity.UNCOMMON, mage.cards.u.UntamedWilds.class)); - cards.add(new SetCardInfo("Valorous Charge", 196, Rarity.UNCOMMON, mage.cards.v.ValorousCharge.class)); - cards.add(new SetCardInfo("Vampiric Feast", 37, Rarity.UNCOMMON, mage.cards.v.VampiricFeast.class)); - cards.add(new SetCardInfo("Vampiric Touch", 38, Rarity.COMMON, mage.cards.v.VampiricTouch.class)); - cards.add(new SetCardInfo("Venerable Monk", 197, Rarity.UNCOMMON, mage.cards.v.VenerableMonk.class)); - cards.add(new SetCardInfo("Vengeance", 198, Rarity.UNCOMMON, mage.cards.v.Vengeance.class)); - cards.add(new SetCardInfo("Virtue's Ruin", 39, Rarity.UNCOMMON, mage.cards.v.VirtuesRuin.class)); - cards.add(new SetCardInfo("Volcanic Dragon", 159, Rarity.RARE, mage.cards.v.VolcanicDragon.class)); - cards.add(new SetCardInfo("Volcanic Hammer", 160, Rarity.COMMON, mage.cards.v.VolcanicHammer.class)); - cards.add(new SetCardInfo("Wall of Granite", 161, Rarity.UNCOMMON, mage.cards.w.WallOfGranite.class)); - cards.add(new SetCardInfo("Wall of Swords", 199, Rarity.UNCOMMON, mage.cards.w.WallOfSwords.class)); - cards.add(new SetCardInfo("Warrior's Charge", 200, Rarity.COMMON, mage.cards.w.WarriorsCharge1.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Warrior's Charge", 201, Rarity.COMMON, mage.cards.w.WarriorsCharge1.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Whiptail Wurm", 118, Rarity.UNCOMMON, mage.cards.w.WhiptailWurm.class)); - cards.add(new SetCardInfo("Wicked Pact", 40, Rarity.RARE, mage.cards.w.WickedPact.class)); - cards.add(new SetCardInfo("Willow Dryad", 119, Rarity.COMMON, mage.cards.w.WillowDryad.class)); - cards.add(new SetCardInfo("Wind Drake", 78, Rarity.COMMON, mage.cards.w.WindDrake.class)); - cards.add(new SetCardInfo("Winds of Change", 162, Rarity.RARE, mage.cards.w.WindsOfChange.class)); - cards.add(new SetCardInfo("Winter's Grasp", 120, Rarity.UNCOMMON, mage.cards.w.WintersGrasp.class)); - cards.add(new SetCardInfo("Withering Gaze", 79, Rarity.UNCOMMON, mage.cards.w.WitheringGaze.class)); - cards.add(new SetCardInfo("Wood Elves", 121, Rarity.RARE, mage.cards.w.WoodElves.class)); - cards.add(new SetCardInfo("Wrath of God", 202, Rarity.RARE, mage.cards.w.WrathOfGod.class)); - } +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.sets; + +import mage.cards.ExpansionSet; +import mage.constants.SetType; +import mage.constants.Rarity; +import mage.cards.CardGraphicInfo; + +/** + * + * @author Plopman + */ + +public class Portal extends ExpansionSet { + + private static final Portal fINSTANCE = new Portal(); + + /** + * + * @return + */ + public static Portal getInstance() { + return fINSTANCE; + } + + private Portal() { + super("Portal", "POR", ExpansionSet.buildDate(1997, 5, 1), SetType.SUPPLEMENTAL); + this.blockName = "Beginner"; + this.hasBasicLands = true; + this.hasBoosters = true; + this.numBoosterLands = 0; + this.numBoosterCommon = 11; + this.numBoosterUncommon = 3; + this.numBoosterRare = 1; + this.ratioBoosterMythic = 0; + cards.add(new SetCardInfo("Alabaster Dragon", 163, Rarity.RARE, mage.cards.a.AlabasterDragon.class)); + cards.add(new SetCardInfo("Alluring Scent", 80, Rarity.RARE, mage.cards.a.AlluringScent.class)); + cards.add(new SetCardInfo("Anaconda", 81, Rarity.UNCOMMON, mage.cards.a.Anaconda.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Anaconda", 82, Rarity.UNCOMMON, mage.cards.a.Anaconda.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Ancestral Memories", 41, Rarity.RARE, mage.cards.a.AncestralMemories.class)); + cards.add(new SetCardInfo("Angelic Blessing", 164, Rarity.COMMON, mage.cards.a.AngelicBlessing.class)); + cards.add(new SetCardInfo("Archangel", 165, Rarity.RARE, mage.cards.a.Archangel.class)); + cards.add(new SetCardInfo("Ardent Militia", 166, Rarity.UNCOMMON, mage.cards.a.ArdentMilitia.class)); + cards.add(new SetCardInfo("Armageddon", 167, Rarity.RARE, mage.cards.a.Armageddon.class)); + cards.add(new SetCardInfo("Armored Pegasus", 168, Rarity.COMMON, mage.cards.a.ArmoredPegasus.class)); + cards.add(new SetCardInfo("Arrogant Vampire", 1, Rarity.UNCOMMON, mage.cards.a.ArrogantVampire.class)); + cards.add(new SetCardInfo("Balance of Power", 42, Rarity.RARE, mage.cards.b.BalanceOfPower.class)); + cards.add(new SetCardInfo("Baleful Stare", 43, Rarity.UNCOMMON, mage.cards.b.BalefulStare.class)); + cards.add(new SetCardInfo("Bee Sting", 83, Rarity.UNCOMMON, mage.cards.b.BeeSting.class)); + cards.add(new SetCardInfo("Blaze", 122, Rarity.UNCOMMON, mage.cards.b.Blaze.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Blaze", 123, Rarity.UNCOMMON, mage.cards.b.Blaze.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Blessed Reversal", 169, Rarity.RARE, mage.cards.b.BlessedReversal.class)); + cards.add(new SetCardInfo("Blinding Light", 170, Rarity.RARE, mage.cards.b.BlindingLight.class)); + cards.add(new SetCardInfo("Bog Imp", 3, Rarity.COMMON, mage.cards.b.BogImp.class)); + cards.add(new SetCardInfo("Bog Raiders", 4, Rarity.COMMON, mage.cards.b.BogRaiders.class)); + cards.add(new SetCardInfo("Bog Wraith", 5, Rarity.UNCOMMON, mage.cards.b.BogWraith.class)); + cards.add(new SetCardInfo("Boiling Seas", 124, Rarity.UNCOMMON, mage.cards.b.BoilingSeas.class)); + cards.add(new SetCardInfo("Border Guard", 171, Rarity.COMMON, mage.cards.b.BorderGuard.class)); + cards.add(new SetCardInfo("Breath of Life", 172, Rarity.COMMON, mage.cards.b.BreathOfLife.class)); + cards.add(new SetCardInfo("Bull Hippo", 84, Rarity.UNCOMMON, mage.cards.b.BullHippo.class)); + cards.add(new SetCardInfo("Burning Cloak", 125, Rarity.COMMON, mage.cards.b.BurningCloak.class)); + cards.add(new SetCardInfo("Capricious Sorcerer", 44, Rarity.RARE, mage.cards.c.CapriciousSorcerer.class)); + cards.add(new SetCardInfo("Charging Bandits", 6, Rarity.UNCOMMON, mage.cards.c.ChargingBandits.class)); + cards.add(new SetCardInfo("Charging Paladin", 173, Rarity.UNCOMMON, mage.cards.c.ChargingPaladin.class)); + cards.add(new SetCardInfo("Charging Rhino", 85, Rarity.RARE, mage.cards.c.ChargingRhino.class)); + cards.add(new SetCardInfo("Cloak of Feathers", 45, Rarity.COMMON, mage.cards.c.CloakOfFeathers.class)); + cards.add(new SetCardInfo("Cloud Dragon", 46, Rarity.RARE, mage.cards.c.CloudDragon.class)); + cards.add(new SetCardInfo("Cloud Pirates", 47, Rarity.COMMON, mage.cards.c.CloudPirates.class)); + cards.add(new SetCardInfo("Cloud Spirit", 48, Rarity.UNCOMMON, mage.cards.c.CloudSpirit.class)); + cards.add(new SetCardInfo("Coral Eel", 50, Rarity.COMMON, mage.cards.c.CoralEel.class)); + cards.add(new SetCardInfo("Craven Giant", 126, Rarity.COMMON, mage.cards.c.CravenGiant.class)); + cards.add(new SetCardInfo("Craven Knight", 7, Rarity.COMMON, mage.cards.c.CravenKnight.class)); + cards.add(new SetCardInfo("Cruel Bargain", 8, Rarity.RARE, mage.cards.c.CruelBargain.class)); + cards.add(new SetCardInfo("Cruel Tutor", 9, Rarity.RARE, mage.cards.c.CruelTutor.class)); + cards.add(new SetCardInfo("Deep-Sea Serpent", 52, Rarity.UNCOMMON, mage.cards.d.DeepSeaSerpent.class)); + cards.add(new SetCardInfo("Deja Vu", 53, Rarity.COMMON, mage.cards.d.DejaVu.class)); + cards.add(new SetCardInfo("Desert Drake", 127, Rarity.UNCOMMON, mage.cards.d.DesertDrake.class)); + cards.add(new SetCardInfo("Devastation", 128, Rarity.RARE, mage.cards.d.Devastation.class)); + cards.add(new SetCardInfo("Devoted Hero", 175, Rarity.COMMON, mage.cards.d.DevotedHero.class)); + cards.add(new SetCardInfo("Djinn of the Lamp", 54, Rarity.RARE, mage.cards.d.DjinnOfTheLamp.class)); + cards.add(new SetCardInfo("Dread Reaper", 11, Rarity.RARE, mage.cards.d.DreadReaper.class)); + cards.add(new SetCardInfo("Dry Spell", 12, Rarity.UNCOMMON, mage.cards.d.DrySpell1.class)); + cards.add(new SetCardInfo("Earthquake", 129, Rarity.RARE, mage.cards.e.Earthquake.class)); + cards.add(new SetCardInfo("Ebon Dragon", 13, Rarity.RARE, mage.cards.e.EbonDragon.class)); + cards.add(new SetCardInfo("Elite Cat Warrior", 87, Rarity.COMMON, mage.cards.e.EliteCatWarrior1.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Elite Cat Warrior", 88, Rarity.COMMON, mage.cards.e.EliteCatWarrior1.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Elven Cache", 89, Rarity.COMMON, mage.cards.e.ElvenCache.class)); + cards.add(new SetCardInfo("Elvish Ranger", 90, Rarity.COMMON, mage.cards.e.ElvishRanger.class)); + cards.add(new SetCardInfo("Endless Cockroaches", 14, Rarity.RARE, mage.cards.e.EndlessCockroaches.class)); + cards.add(new SetCardInfo("Exhaustion", 55, Rarity.RARE, mage.cards.e.Exhaustion.class)); + cards.add(new SetCardInfo("False Peace", 176, Rarity.COMMON, mage.cards.f.FalsePeace.class)); + cards.add(new SetCardInfo("Feral Shadow", 15, Rarity.COMMON, mage.cards.f.FeralShadow.class)); + cards.add(new SetCardInfo("Final Strike", 16, Rarity.RARE, mage.cards.f.FinalStrike.class)); + cards.add(new SetCardInfo("Fire Dragon", 130, Rarity.RARE, mage.cards.f.FireDragon.class)); + cards.add(new SetCardInfo("Fire Imp", 131, Rarity.UNCOMMON, mage.cards.f.FireImp.class)); + cards.add(new SetCardInfo("Fire Snake", 132, Rarity.COMMON, mage.cards.f.FireSnake.class)); + cards.add(new SetCardInfo("Fire Tempest", 133, Rarity.RARE, mage.cards.f.FireTempest.class)); + cards.add(new SetCardInfo("Flashfires", 134, Rarity.UNCOMMON, mage.cards.f.Flashfires.class)); + cards.add(new SetCardInfo("Fleet-Footed Monk", 177, Rarity.COMMON, mage.cards.f.FleetFootedMonk.class)); + cards.add(new SetCardInfo("Flux", 56, Rarity.UNCOMMON, mage.cards.f.Flux.class)); + cards.add(new SetCardInfo("Foot Soldiers", 178, Rarity.COMMON, mage.cards.f.FootSoldiers.class)); + cards.add(new SetCardInfo("Forest", 203, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Forest", 204, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Forest", 205, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Forest", 206, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Fruition", 91, Rarity.COMMON, mage.cards.f.Fruition.class)); + cards.add(new SetCardInfo("Giant Octopus", 57, Rarity.COMMON, mage.cards.g.GiantOctopus.class)); + cards.add(new SetCardInfo("Giant Spider", 92, Rarity.COMMON, mage.cards.g.GiantSpider.class)); + cards.add(new SetCardInfo("Gift of Estates", 179, Rarity.RARE, mage.cards.g.GiftOfEstates.class)); + cards.add(new SetCardInfo("Goblin Bully", 136, Rarity.COMMON, mage.cards.g.GoblinBully.class)); + cards.add(new SetCardInfo("Gorilla Warrior", 93, Rarity.COMMON, mage.cards.g.GorillaWarrior.class)); + cards.add(new SetCardInfo("Gravedigger", 17, Rarity.UNCOMMON, mage.cards.g.Gravedigger.class)); + cards.add(new SetCardInfo("Grizzly Bears", 94, Rarity.COMMON, mage.cards.g.GrizzlyBears.class)); + cards.add(new SetCardInfo("Hand of Death", 18, Rarity.COMMON, mage.cards.h.HandOfDeath.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Hand of Death", 19, Rarity.COMMON, mage.cards.h.HandOfDeath.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Highland Giant", 137, Rarity.COMMON, mage.cards.h.HighlandGiant.class)); + cards.add(new SetCardInfo("Hill Giant", 138, Rarity.COMMON, mage.cards.h.HillGiant.class)); + cards.add(new SetCardInfo("Horned Turtle", 58, Rarity.COMMON, mage.cards.h.HornedTurtle.class)); + cards.add(new SetCardInfo("Howling Fury", 20, Rarity.COMMON, mage.cards.h.HowlingFury.class)); + cards.add(new SetCardInfo("Hulking Cyclops", 139, Rarity.UNCOMMON, mage.cards.h.HulkingCyclops.class)); + cards.add(new SetCardInfo("Hulking Goblin", 140, Rarity.COMMON, mage.cards.h.HulkingGoblin.class)); + cards.add(new SetCardInfo("Hurricane", 95, Rarity.RARE, mage.cards.h.Hurricane.class)); + cards.add(new SetCardInfo("Ingenious Thief", 59, Rarity.UNCOMMON, mage.cards.i.IngeniousThief.class)); + cards.add(new SetCardInfo("Island", 207, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Island", 208, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Island", 209, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Island", 210, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Jungle Lion", 96, Rarity.COMMON, mage.cards.j.JungleLion.class)); + cards.add(new SetCardInfo("Keen-Eyed Archers", 181, Rarity.COMMON, mage.cards.k.KeenEyedArchers.class)); + cards.add(new SetCardInfo("King's Assassin", 21, Rarity.RARE, mage.cards.k.KingsAssassin.class)); + cards.add(new SetCardInfo("Knight Errant", 182, Rarity.COMMON, mage.cards.k.KnightErrant.class)); + cards.add(new SetCardInfo("Last Chance", 141, Rarity.RARE, mage.cards.l.LastChance.class)); + cards.add(new SetCardInfo("Lava Axe", 142, Rarity.COMMON, mage.cards.l.LavaAxe.class)); + cards.add(new SetCardInfo("Lava Flow", 143, Rarity.UNCOMMON, mage.cards.l.LavaFlow.class)); + cards.add(new SetCardInfo("Lizard Warrior", 144, Rarity.COMMON, mage.cards.l.LizardWarrior.class)); + cards.add(new SetCardInfo("Man-o'-War", 60, Rarity.UNCOMMON, mage.cards.m.ManOWar.class)); + cards.add(new SetCardInfo("Mercenary Knight", 22, Rarity.RARE, mage.cards.m.MercenaryKnight.class)); + cards.add(new SetCardInfo("Merfolk of the Pearl Trident", 61, Rarity.COMMON, mage.cards.m.MerfolkOfThePearlTrident.class)); + cards.add(new SetCardInfo("Mind Knives", 23, Rarity.COMMON, mage.cards.m.MindKnives.class)); + cards.add(new SetCardInfo("Mind Rot", 24, Rarity.COMMON, mage.cards.m.MindRot.class)); + cards.add(new SetCardInfo("Minotaur Warrior", 145, Rarity.COMMON, mage.cards.m.MinotaurWarrior.class)); + cards.add(new SetCardInfo("Mobilize", 97, Rarity.COMMON, mage.cards.m.Mobilize.class)); + cards.add(new SetCardInfo("Monstrous Growth", 98, Rarity.COMMON, mage.cards.m.MonstrousGrowth.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Monstrous Growth", 99, Rarity.COMMON, mage.cards.m.MonstrousGrowth.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Moon Sprite", 100, Rarity.UNCOMMON, mage.cards.m.MoonSprite.class)); + cards.add(new SetCardInfo("Mountain", 211, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Mountain", 212, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Mountain", 213, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Mountain", 214, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Mountain Goat", 146, Rarity.UNCOMMON, mage.cards.m.MountainGoat.class)); + cards.add(new SetCardInfo("Muck Rats", 25, Rarity.COMMON, mage.cards.m.MuckRats.class)); + cards.add(new SetCardInfo("Mystic Denial", 62, Rarity.UNCOMMON, mage.cards.m.MysticDenial.class)); + cards.add(new SetCardInfo("Natural Order", 101, Rarity.RARE, mage.cards.n.NaturalOrder.class)); + cards.add(new SetCardInfo("Natural Spring", 102, Rarity.UNCOMMON, mage.cards.n.NaturalSpring.class)); + cards.add(new SetCardInfo("Nature's Cloak", 103, Rarity.RARE, mage.cards.n.NaturesCloak.class)); + cards.add(new SetCardInfo("Nature's Lore", 104, Rarity.COMMON, mage.cards.n.NaturesLore.class)); + cards.add(new SetCardInfo("Nature's Ruin", 26, Rarity.UNCOMMON, mage.cards.n.NaturesRuin.class)); + cards.add(new SetCardInfo("Needle Storm", 105, Rarity.UNCOMMON, mage.cards.n.NeedleStorm.class)); + cards.add(new SetCardInfo("Noxious Toad", 27, Rarity.UNCOMMON, mage.cards.n.NoxiousToad.class)); + cards.add(new SetCardInfo("Omen", 63, Rarity.COMMON, mage.cards.o.Omen.class)); + cards.add(new SetCardInfo("Owl Familiar", 64, Rarity.COMMON, mage.cards.o.OwlFamiliar.class)); + cards.add(new SetCardInfo("Panther Warriors", 106, Rarity.COMMON, mage.cards.p.PantherWarriors.class)); + cards.add(new SetCardInfo("Personal Tutor", 65, Rarity.UNCOMMON, mage.cards.p.PersonalTutor.class)); + cards.add(new SetCardInfo("Phantom Warrior", 66, Rarity.RARE, mage.cards.p.PhantomWarrior.class)); + cards.add(new SetCardInfo("Pillaging Horde", 147, Rarity.RARE, mage.cards.p.PillagingHorde.class)); + cards.add(new SetCardInfo("Plains", 215, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Plains", 216, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Plains", 217, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Plains", 218, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Plant Elemental", 107, Rarity.UNCOMMON, mage.cards.p.PlantElemental.class)); + cards.add(new SetCardInfo("Primeval Force", 108, Rarity.RARE, mage.cards.p.PrimevalForce.class)); + cards.add(new SetCardInfo("Prosperity", 67, Rarity.RARE, mage.cards.p.Prosperity.class)); + cards.add(new SetCardInfo("Pyroclasm", 148, Rarity.RARE, mage.cards.p.Pyroclasm.class)); + cards.add(new SetCardInfo("Python", 28, Rarity.COMMON, mage.cards.p.Python.class)); + cards.add(new SetCardInfo("Raging Cougar", 149, Rarity.COMMON, mage.cards.r.RagingCougar.class)); + cards.add(new SetCardInfo("Raging Goblin", 150, Rarity.COMMON, mage.cards.r.RagingGoblin.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Raging Goblin", 151, Rarity.COMMON, mage.cards.r.RagingGoblin.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Raging Minotaur", 152, Rarity.COMMON, mage.cards.r.RagingMinotaur.class)); + cards.add(new SetCardInfo("Rain of Salt", 153, Rarity.UNCOMMON, mage.cards.r.RainOfSalt.class)); + cards.add(new SetCardInfo("Rain of Tears", 29, Rarity.UNCOMMON, mage.cards.r.RainOfTears.class)); + cards.add(new SetCardInfo("Raise Dead", 30, Rarity.COMMON, mage.cards.r.RaiseDead.class)); + cards.add(new SetCardInfo("Redwood Treefolk", 109, Rarity.COMMON, mage.cards.r.RedwoodTreefolk.class)); + cards.add(new SetCardInfo("Regal Unicorn", 184, Rarity.COMMON, mage.cards.r.RegalUnicorn.class)); + cards.add(new SetCardInfo("Renewing Dawn", 185, Rarity.UNCOMMON, mage.cards.r.RenewingDawn.class)); + cards.add(new SetCardInfo("Rowan Treefolk", 110, Rarity.COMMON, mage.cards.r.RowanTreefolk.class)); + cards.add(new SetCardInfo("Sacred Knight", 186, Rarity.COMMON, mage.cards.s.SacredKnight.class)); + cards.add(new SetCardInfo("Sacred Nectar", 187, Rarity.COMMON, mage.cards.s.SacredNectar.class)); + cards.add(new SetCardInfo("Scorching Spear", 154, Rarity.COMMON, mage.cards.s.ScorchingSpear.class)); + cards.add(new SetCardInfo("Seasoned Marshal", 188, Rarity.UNCOMMON, mage.cards.s.SeasonedMarshal.class)); + cards.add(new SetCardInfo("Serpent Assassin", 31, Rarity.RARE, mage.cards.s.SerpentAssassin.class)); + cards.add(new SetCardInfo("Serpent Warrior", 32, Rarity.COMMON, mage.cards.s.SerpentWarrior.class)); + cards.add(new SetCardInfo("Skeletal Crocodile", 33, Rarity.COMMON, mage.cards.s.SkeletalCrocodile.class)); + cards.add(new SetCardInfo("Skeletal Snake", 34, Rarity.COMMON, mage.cards.s.SkeletalSnake.class)); + cards.add(new SetCardInfo("Snapping Drake", 68, Rarity.COMMON, mage.cards.s.SnappingDrake.class)); + cards.add(new SetCardInfo("Sorcerous Sight", 69, Rarity.COMMON, mage.cards.s.SorcerousSight.class)); + cards.add(new SetCardInfo("Soul Shred", 35, Rarity.COMMON, mage.cards.s.SoulShred.class)); + cards.add(new SetCardInfo("Spined Wurm", 111, Rarity.COMMON, mage.cards.s.SpinedWurm.class)); + cards.add(new SetCardInfo("Spiritual Guardian", 189, Rarity.RARE, mage.cards.s.SpiritualGuardian.class)); + cards.add(new SetCardInfo("Spitting Earth", 156, Rarity.COMMON, mage.cards.s.SpittingEarth.class)); + cards.add(new SetCardInfo("Spotted Griffin", 190, Rarity.COMMON, mage.cards.s.SpottedGriffin.class)); + cards.add(new SetCardInfo("Stalking Tiger", 112, Rarity.COMMON, mage.cards.s.StalkingTiger.class)); + cards.add(new SetCardInfo("Starlight", 191, Rarity.UNCOMMON, mage.cards.s.Starlight.class)); + cards.add(new SetCardInfo("Starlit Angel", 192, Rarity.UNCOMMON, mage.cards.s.StarlitAngel.class)); + cards.add(new SetCardInfo("Steadfastness", 193, Rarity.COMMON, mage.cards.s.Steadfastness.class)); + cards.add(new SetCardInfo("Stern Marshal", 194, Rarity.RARE, mage.cards.s.SternMarshal.class)); + cards.add(new SetCardInfo("Stone Rain", 157, Rarity.COMMON, mage.cards.s.StoneRain.class)); + cards.add(new SetCardInfo("Storm Crow", 70, Rarity.COMMON, mage.cards.s.StormCrow.class)); + cards.add(new SetCardInfo("Summer Bloom", 113, Rarity.RARE, mage.cards.s.SummerBloom.class)); + cards.add(new SetCardInfo("Swamp", 219, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Swamp", 220, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Swamp", 221, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Swamp", 222, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Sylvan Tutor", 114, Rarity.RARE, mage.cards.s.SylvanTutor.class)); + cards.add(new SetCardInfo("Symbol of Unsummoning", 71, Rarity.COMMON, mage.cards.s.SymbolOfUnsummoning.class)); + cards.add(new SetCardInfo("Taunt", 72, Rarity.RARE, mage.cards.t.Taunt.class)); + cards.add(new SetCardInfo("Theft of Dreams", 73, Rarity.UNCOMMON, mage.cards.t.TheftOfDreams.class)); + cards.add(new SetCardInfo("Thing from the Deep", 74, Rarity.RARE, mage.cards.t.ThingFromTheDeep.class)); + cards.add(new SetCardInfo("Thundering Wurm", 115, Rarity.RARE, mage.cards.t.ThunderingWurm.class)); + cards.add(new SetCardInfo("Thundermare", 158, Rarity.RARE, mage.cards.t.Thundermare.class)); + cards.add(new SetCardInfo("Tidal Surge", 75, Rarity.COMMON, mage.cards.t.TidalSurge.class)); + cards.add(new SetCardInfo("Time Ebb", 76, Rarity.COMMON, mage.cards.t.TimeEbb.class)); + cards.add(new SetCardInfo("Touch of Brilliance", 77, Rarity.COMMON, mage.cards.t.TouchOfBrilliance.class)); + cards.add(new SetCardInfo("Undying Beast", 36, Rarity.COMMON, mage.cards.u.UndyingBeast.class)); + cards.add(new SetCardInfo("Untamed Wilds", 117, Rarity.UNCOMMON, mage.cards.u.UntamedWilds.class)); + cards.add(new SetCardInfo("Valorous Charge", 196, Rarity.UNCOMMON, mage.cards.v.ValorousCharge.class)); + cards.add(new SetCardInfo("Vampiric Feast", 37, Rarity.UNCOMMON, mage.cards.v.VampiricFeast.class)); + cards.add(new SetCardInfo("Vampiric Touch", 38, Rarity.COMMON, mage.cards.v.VampiricTouch.class)); + cards.add(new SetCardInfo("Venerable Monk", 197, Rarity.UNCOMMON, mage.cards.v.VenerableMonk.class)); + cards.add(new SetCardInfo("Vengeance", 198, Rarity.UNCOMMON, mage.cards.v.Vengeance.class)); + cards.add(new SetCardInfo("Virtue's Ruin", 39, Rarity.UNCOMMON, mage.cards.v.VirtuesRuin.class)); + cards.add(new SetCardInfo("Volcanic Dragon", 159, Rarity.RARE, mage.cards.v.VolcanicDragon.class)); + cards.add(new SetCardInfo("Volcanic Hammer", 160, Rarity.COMMON, mage.cards.v.VolcanicHammer.class)); + cards.add(new SetCardInfo("Wall of Granite", 161, Rarity.UNCOMMON, mage.cards.w.WallOfGranite.class)); + cards.add(new SetCardInfo("Wall of Swords", 199, Rarity.UNCOMMON, mage.cards.w.WallOfSwords.class)); + cards.add(new SetCardInfo("Warrior's Charge", 200, Rarity.COMMON, mage.cards.w.WarriorsCharge1.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Warrior's Charge", 201, Rarity.COMMON, mage.cards.w.WarriorsCharge1.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Whiptail Wurm", 118, Rarity.UNCOMMON, mage.cards.w.WhiptailWurm.class)); + cards.add(new SetCardInfo("Wicked Pact", 40, Rarity.RARE, mage.cards.w.WickedPact.class)); + cards.add(new SetCardInfo("Willow Dryad", 119, Rarity.COMMON, mage.cards.w.WillowDryad.class)); + cards.add(new SetCardInfo("Wind Drake", 78, Rarity.COMMON, mage.cards.w.WindDrake.class)); + cards.add(new SetCardInfo("Winds of Change", 162, Rarity.RARE, mage.cards.w.WindsOfChange.class)); + cards.add(new SetCardInfo("Winter's Grasp", 120, Rarity.UNCOMMON, mage.cards.w.WintersGrasp.class)); + cards.add(new SetCardInfo("Withering Gaze", 79, Rarity.UNCOMMON, mage.cards.w.WitheringGaze.class)); + cards.add(new SetCardInfo("Wood Elves", 121, Rarity.RARE, mage.cards.w.WoodElves.class)); + cards.add(new SetCardInfo("Wrath of God", 202, Rarity.RARE, mage.cards.w.WrathOfGod.class)); + } } \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/Prophecy.java b/Mage.Sets/src/mage/sets/Prophecy.java index e4a7e8f3bcf..de90cb1fc1f 100644 --- a/Mage.Sets/src/mage/sets/Prophecy.java +++ b/Mage.Sets/src/mage/sets/Prophecy.java @@ -1,153 +1,154 @@ -/* - * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of BetaSteward_at_googlemail.com. - */ -package mage.sets; - -import mage.cards.ExpansionSet; -import mage.constants.SetType; -import mage.constants.Rarity; - -/** - * - * @author North - */ -public class Prophecy extends ExpansionSet { - - private static final Prophecy fINSTANCE = new Prophecy(); - - public static Prophecy getInstance() { - return fINSTANCE; - } - - private Prophecy() { - super("Prophecy", "PCY", ExpansionSet.buildDate(2000, 4, 27), SetType.EXPANSION); - this.blockName = "Masques"; - this.parentSet = MercadianMasques.getInstance(); - this.hasBasicLands = false; - this.hasBoosters = true; - this.numBoosterLands = 0; - this.numBoosterCommon = 11; - this.numBoosterUncommon = 3; - this.numBoosterRare = 1; - this.ratioBoosterMythic = 0; - cards.add(new SetCardInfo("Abolish", 1, Rarity.UNCOMMON, mage.cards.a.Abolish.class)); - cards.add(new SetCardInfo("Agent of Shauku", 55, Rarity.COMMON, mage.cards.a.AgentOfShauku.class)); - cards.add(new SetCardInfo("Alexi's Cloak", 29, Rarity.COMMON, mage.cards.a.AlexisCloak.class)); - cards.add(new SetCardInfo("Alexi, Zephyr Mage", 28, Rarity.RARE, mage.cards.a.AlexiZephyrMage.class)); - cards.add(new SetCardInfo("Aura Fracture", 2, Rarity.COMMON, mage.cards.a.AuraFracture.class)); - cards.add(new SetCardInfo("Avatar of Fury", 82, Rarity.RARE, mage.cards.a.AvatarOfFury.class)); - cards.add(new SetCardInfo("Avatar of Hope", 3, Rarity.RARE, mage.cards.a.AvatarOfHope.class)); - cards.add(new SetCardInfo("Avatar of Might", 109, Rarity.RARE, mage.cards.a.AvatarOfMight.class)); - cards.add(new SetCardInfo("Avatar of Will", 30, Rarity.RARE, mage.cards.a.AvatarOfWill.class)); - cards.add(new SetCardInfo("Avatar of Woe", 56, Rarity.RARE, mage.cards.a.AvatarOfWoe.class)); - cards.add(new SetCardInfo("Barbed Field", 83, Rarity.UNCOMMON, mage.cards.b.BarbedField.class)); - cards.add(new SetCardInfo("Blessed Wind", 4, Rarity.RARE, mage.cards.b.BlessedWind.class)); - cards.add(new SetCardInfo("Bog Elemental", 57, Rarity.RARE, mage.cards.b.BogElemental.class)); - cards.add(new SetCardInfo("Bog Glider", 58, Rarity.COMMON, mage.cards.b.BogGlider.class)); - cards.add(new SetCardInfo("Calming Verse", 110, Rarity.COMMON, mage.cards.c.CalmingVerse.class)); - cards.add(new SetCardInfo("Chilling Apparition", 59, Rarity.UNCOMMON, mage.cards.c.ChillingApparition.class)); - cards.add(new SetCardInfo("Chimeric Idol", 136, Rarity.UNCOMMON, mage.cards.c.ChimericIdol.class)); - cards.add(new SetCardInfo("Coastal Hornclaw", 31, Rarity.COMMON, mage.cards.c.CoastalHornclaw.class)); - cards.add(new SetCardInfo("Darba", 111, Rarity.UNCOMMON, mage.cards.d.Darba.class)); - cards.add(new SetCardInfo("Denying Wind", 32, Rarity.RARE, mage.cards.d.DenyingWind.class)); - cards.add(new SetCardInfo("Despoil", 62, Rarity.COMMON, mage.cards.d.Despoil.class)); - cards.add(new SetCardInfo("Devastate", 87, Rarity.COMMON, mage.cards.d.Devastate.class)); - cards.add(new SetCardInfo("Diving Griffin", 6, Rarity.COMMON, mage.cards.d.DivingGriffin.class)); - cards.add(new SetCardInfo("Excavation", 33, Rarity.UNCOMMON, mage.cards.e.Excavation.class)); - cards.add(new SetCardInfo("Fault Riders", 88, Rarity.COMMON, mage.cards.f.FaultRiders.class)); - cards.add(new SetCardInfo("Fen Stalker", 64, Rarity.COMMON, mage.cards.f.FenStalker.class)); - cards.add(new SetCardInfo("Flameshot", 90, Rarity.UNCOMMON, mage.cards.f.Flameshot.class)); - cards.add(new SetCardInfo("Flowering Field", 9, Rarity.UNCOMMON, mage.cards.f.FloweringField.class)); - cards.add(new SetCardInfo("Foil", 34, Rarity.UNCOMMON, mage.cards.f.Foil.class)); - cards.add(new SetCardInfo("Greel's Caress", 67, Rarity.COMMON, mage.cards.g.GreelsCaress.class)); - cards.add(new SetCardInfo("Gulf Squid", 35, Rarity.COMMON, mage.cards.g.GulfSquid.class)); - cards.add(new SetCardInfo("Hazy Homunculus", 36, Rarity.COMMON, mage.cards.h.HazyHomunculus.class)); - cards.add(new SetCardInfo("Heightened Awareness", 37, Rarity.RARE, mage.cards.h.HeightenedAwareness.class)); - cards.add(new SetCardInfo("Infernal Genesis", 68, Rarity.RARE, mage.cards.i.InfernalGenesis.class)); - cards.add(new SetCardInfo("Inflame", 91, Rarity.COMMON, mage.cards.i.Inflame.class)); - cards.add(new SetCardInfo("Jeweled Spirit", 12, Rarity.RARE, mage.cards.j.JeweledSpirit.class)); - cards.add(new SetCardInfo("Jolrael, Empress of Beasts", 115, Rarity.RARE, mage.cards.j.JolraelEmpressOfBeasts.class)); - cards.add(new SetCardInfo("Jolrael's Favor", 116, Rarity.COMMON, mage.cards.j.JolraelsFavor.class)); - cards.add(new SetCardInfo("Keldon Arsonist", 92, Rarity.UNCOMMON, mage.cards.k.KeldonArsonist.class)); - cards.add(new SetCardInfo("Latulla, Keldon Overseer", 95, Rarity.RARE, mage.cards.l.LatullaKeldonOverseer.class)); - cards.add(new SetCardInfo("Lesser Gargadon", 97, Rarity.UNCOMMON, mage.cards.l.LesserGargadon.class)); - cards.add(new SetCardInfo("Living Terrain", 117, Rarity.UNCOMMON, mage.cards.l.LivingTerrain.class)); - cards.add(new SetCardInfo("Mageta's Boon", 14, Rarity.COMMON, mage.cards.m.MagetasBoon.class)); - cards.add(new SetCardInfo("Mageta the Lion", 13, Rarity.RARE, mage.cards.m.MagetaTheLion.class)); - cards.add(new SetCardInfo("Marsh Boa", 118, Rarity.COMMON, mage.cards.m.MarshBoa.class)); - cards.add(new SetCardInfo("Mercenary Informer", 15, Rarity.RARE, mage.cards.m.MercenaryInformer.class)); - cards.add(new SetCardInfo("Mine Bearer", 16, Rarity.COMMON, mage.cards.m.MineBearer.class)); - cards.add(new SetCardInfo("Mungha Wurm", 119, Rarity.RARE, mage.cards.m.MunghaWurm.class)); - cards.add(new SetCardInfo("Nakaya Shade", 69, Rarity.UNCOMMON, mage.cards.n.NakayaShade.class)); - cards.add(new SetCardInfo("Noxious Field", 70, Rarity.UNCOMMON, mage.cards.n.NoxiousField.class)); - cards.add(new SetCardInfo("Outbreak", 71, Rarity.UNCOMMON, mage.cards.o.Outbreak.class)); - cards.add(new SetCardInfo("Overburden", 39, Rarity.RARE, mage.cards.o.Overburden.class)); - cards.add(new SetCardInfo("Panic Attack", 98, Rarity.COMMON, mage.cards.p.PanicAttack.class)); - cards.add(new SetCardInfo("Pit Raptor", 72, Rarity.UNCOMMON, mage.cards.p.PitRaptor.class)); - cards.add(new SetCardInfo("Plague Fiend", 73, Rarity.COMMON, mage.cards.p.PlagueFiend.class)); - cards.add(new SetCardInfo("Plague Wind", 74, Rarity.RARE, mage.cards.p.PlagueWind.class)); - cards.add(new SetCardInfo("Pygmy Razorback", 120, Rarity.COMMON, mage.cards.p.PygmyRazorback.class)); - cards.add(new SetCardInfo("Quicksilver Wall", 41, Rarity.UNCOMMON, mage.cards.q.QuicksilverWall.class)); - cards.add(new SetCardInfo("Rebel Informer", 75, Rarity.RARE, mage.cards.r.RebelInformer.class)); - cards.add(new SetCardInfo("Rethink", 42, Rarity.COMMON, mage.cards.r.Rethink.class)); - cards.add(new SetCardInfo("Rhystic Circle", 19, Rarity.COMMON, mage.cards.r.RhysticCircle.class)); - cards.add(new SetCardInfo("Rhystic Study", 45, Rarity.COMMON, mage.cards.r.RhysticStudy.class)); - cards.add(new SetCardInfo("Rhystic Tutor", 77, Rarity.RARE, mage.cards.r.RhysticTutor.class)); - cards.add(new SetCardInfo("Ribbon Snake", 46, Rarity.COMMON, mage.cards.r.RibbonSnake.class)); - cards.add(new SetCardInfo("Rib Cage Spider", 121, Rarity.COMMON, mage.cards.r.RibCageSpider.class)); - cards.add(new SetCardInfo("Ridgeline Rager", 100, Rarity.COMMON, mage.cards.r.RidgelineRager.class)); - cards.add(new SetCardInfo("Root Cage", 122, Rarity.UNCOMMON, mage.cards.r.RootCage.class)); - cards.add(new SetCardInfo("Scoria Cat", 101, Rarity.UNCOMMON, mage.cards.s.ScoriaCat.class)); - cards.add(new SetCardInfo("Searing Wind", 103, Rarity.RARE, mage.cards.s.SearingWind.class)); - cards.add(new SetCardInfo("Shield Dancer", 23, Rarity.UNCOMMON, mage.cards.s.ShieldDancer.class)); - cards.add(new SetCardInfo("Silt Crawler", 123, Rarity.COMMON, mage.cards.s.SiltCrawler.class)); - cards.add(new SetCardInfo("Spiketail Drake", 48, Rarity.UNCOMMON, mage.cards.s.SpiketailDrake.class)); - cards.add(new SetCardInfo("Spiketail Hatchling", 49, Rarity.COMMON, mage.cards.s.SpiketailHatchling.class)); - cards.add(new SetCardInfo("Spitting Spider", 125, Rarity.UNCOMMON, mage.cards.s.SpittingSpider.class)); - cards.add(new SetCardInfo("Spore Frog", 126, Rarity.COMMON, mage.cards.s.SporeFrog.class)); - cards.add(new SetCardInfo("Spur Grappler", 104, Rarity.COMMON, mage.cards.s.SpurGrappler.class)); - cards.add(new SetCardInfo("Squirrel Wrangler", 127, Rarity.RARE, mage.cards.s.SquirrelWrangler.class)); - cards.add(new SetCardInfo("Steal Strength", 79, Rarity.COMMON, mage.cards.s.StealStrength.class)); - cards.add(new SetCardInfo("Stormwatch Eagle", 50, Rarity.COMMON, mage.cards.s.StormwatchEagle.class)); - cards.add(new SetCardInfo("Sunken Field", 51, Rarity.UNCOMMON, mage.cards.s.SunkenField.class)); - cards.add(new SetCardInfo("Sword Dancer", 25, Rarity.UNCOMMON, mage.cards.s.SwordDancer.class)); - cards.add(new SetCardInfo("Thrive", 129, Rarity.COMMON, mage.cards.t.Thrive.class)); - cards.add(new SetCardInfo("Trenching Steed", 26, Rarity.COMMON, mage.cards.t.TrenchingSteed.class)); - cards.add(new SetCardInfo("Troubled Healer", 27, Rarity.COMMON, mage.cards.t.TroubledHealer.class)); - cards.add(new SetCardInfo("Troublesome Spirit", 52, Rarity.RARE, mage.cards.t.TroublesomeSpirit.class)); - cards.add(new SetCardInfo("Verdant Field", 130, Rarity.UNCOMMON, mage.cards.v.VerdantField.class)); - cards.add(new SetCardInfo("Vintara Elephant", 131, Rarity.COMMON, mage.cards.v.VintaraElephant.class)); - cards.add(new SetCardInfo("Vintara Snapper", 132, Rarity.UNCOMMON, mage.cards.v.VintaraSnapper.class)); - cards.add(new SetCardInfo("Well of Discovery", 140, Rarity.RARE, mage.cards.w.WellOfDiscovery.class)); - cards.add(new SetCardInfo("Well of Life", 141, Rarity.UNCOMMON, mage.cards.w.WellOfLife.class)); - cards.add(new SetCardInfo("Whip Sergeant", 107, Rarity.UNCOMMON, mage.cards.w.WhipSergeant.class)); - cards.add(new SetCardInfo("Whipstitched Zombie", 81, Rarity.COMMON, mage.cards.w.WhipstitchedZombie.class)); - cards.add(new SetCardInfo("Wild Might", 134, Rarity.COMMON, mage.cards.w.WildMight.class)); - cards.add(new SetCardInfo("Wintermoon Mesa", 143, Rarity.RARE, mage.cards.w.WintermoonMesa.class)); - cards.add(new SetCardInfo("Zerapa Minotaur", 108, Rarity.COMMON, mage.cards.z.ZerapaMinotaur.class)); - } -} +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets; + +import mage.cards.ExpansionSet; +import mage.constants.Rarity; +import mage.constants.SetType; + +/** + * + * @author North + */ +public class Prophecy extends ExpansionSet { + + private static final Prophecy fINSTANCE = new Prophecy(); + + public static Prophecy getInstance() { + return fINSTANCE; + } + + private Prophecy() { + super("Prophecy", "PCY", ExpansionSet.buildDate(2000, 4, 27), SetType.EXPANSION); + this.blockName = "Masques"; + this.parentSet = MercadianMasques.getInstance(); + this.hasBasicLands = false; + this.hasBoosters = true; + this.numBoosterLands = 0; + this.numBoosterCommon = 11; + this.numBoosterUncommon = 3; + this.numBoosterRare = 1; + this.ratioBoosterMythic = 0; + cards.add(new SetCardInfo("Abolish", 1, Rarity.UNCOMMON, mage.cards.a.Abolish.class)); + cards.add(new SetCardInfo("Agent of Shauku", 55, Rarity.COMMON, mage.cards.a.AgentOfShauku.class)); + cards.add(new SetCardInfo("Alexi's Cloak", 29, Rarity.COMMON, mage.cards.a.AlexisCloak.class)); + cards.add(new SetCardInfo("Alexi, Zephyr Mage", 28, Rarity.RARE, mage.cards.a.AlexiZephyrMage.class)); + cards.add(new SetCardInfo("Aura Fracture", 2, Rarity.COMMON, mage.cards.a.AuraFracture.class)); + cards.add(new SetCardInfo("Avatar of Fury", 82, Rarity.RARE, mage.cards.a.AvatarOfFury.class)); + cards.add(new SetCardInfo("Avatar of Hope", 3, Rarity.RARE, mage.cards.a.AvatarOfHope.class)); + cards.add(new SetCardInfo("Avatar of Might", 109, Rarity.RARE, mage.cards.a.AvatarOfMight.class)); + cards.add(new SetCardInfo("Avatar of Will", 30, Rarity.RARE, mage.cards.a.AvatarOfWill.class)); + cards.add(new SetCardInfo("Avatar of Woe", 56, Rarity.RARE, mage.cards.a.AvatarOfWoe.class)); + cards.add(new SetCardInfo("Barbed Field", 83, Rarity.UNCOMMON, mage.cards.b.BarbedField.class)); + cards.add(new SetCardInfo("Blessed Wind", 4, Rarity.RARE, mage.cards.b.BlessedWind.class)); + cards.add(new SetCardInfo("Bog Elemental", 57, Rarity.RARE, mage.cards.b.BogElemental.class)); + cards.add(new SetCardInfo("Bog Glider", 58, Rarity.COMMON, mage.cards.b.BogGlider.class)); + cards.add(new SetCardInfo("Calming Verse", 110, Rarity.COMMON, mage.cards.c.CalmingVerse.class)); + cards.add(new SetCardInfo("Chilling Apparition", 59, Rarity.UNCOMMON, mage.cards.c.ChillingApparition.class)); + cards.add(new SetCardInfo("Chimeric Idol", 136, Rarity.UNCOMMON, mage.cards.c.ChimericIdol.class)); + cards.add(new SetCardInfo("Coastal Hornclaw", 31, Rarity.COMMON, mage.cards.c.CoastalHornclaw.class)); + cards.add(new SetCardInfo("Darba", 111, Rarity.UNCOMMON, mage.cards.d.Darba.class)); + cards.add(new SetCardInfo("Denying Wind", 32, Rarity.RARE, mage.cards.d.DenyingWind.class)); + cards.add(new SetCardInfo("Despoil", 62, Rarity.COMMON, mage.cards.d.Despoil.class)); + cards.add(new SetCardInfo("Devastate", 87, Rarity.COMMON, mage.cards.d.Devastate.class)); + cards.add(new SetCardInfo("Diving Griffin", 6, Rarity.COMMON, mage.cards.d.DivingGriffin.class)); + cards.add(new SetCardInfo("Excavation", 33, Rarity.UNCOMMON, mage.cards.e.Excavation.class)); + cards.add(new SetCardInfo("Fault Riders", 88, Rarity.COMMON, mage.cards.f.FaultRiders.class)); + cards.add(new SetCardInfo("Fen Stalker", 64, Rarity.COMMON, mage.cards.f.FenStalker.class)); + cards.add(new SetCardInfo("Flameshot", 90, Rarity.UNCOMMON, mage.cards.f.Flameshot.class)); + cards.add(new SetCardInfo("Flowering Field", 9, Rarity.UNCOMMON, mage.cards.f.FloweringField.class)); + cards.add(new SetCardInfo("Foil", 34, Rarity.UNCOMMON, mage.cards.f.Foil.class)); + cards.add(new SetCardInfo("Greel's Caress", 67, Rarity.COMMON, mage.cards.g.GreelsCaress.class)); + cards.add(new SetCardInfo("Gulf Squid", 35, Rarity.COMMON, mage.cards.g.GulfSquid.class)); + cards.add(new SetCardInfo("Hazy Homunculus", 36, Rarity.COMMON, mage.cards.h.HazyHomunculus.class)); + cards.add(new SetCardInfo("Heightened Awareness", 37, Rarity.RARE, mage.cards.h.HeightenedAwareness.class)); + cards.add(new SetCardInfo("Infernal Genesis", 68, Rarity.RARE, mage.cards.i.InfernalGenesis.class)); + cards.add(new SetCardInfo("Inflame", 91, Rarity.COMMON, mage.cards.i.Inflame.class)); + cards.add(new SetCardInfo("Jeweled Spirit", 12, Rarity.RARE, mage.cards.j.JeweledSpirit.class)); + cards.add(new SetCardInfo("Jolrael, Empress of Beasts", 115, Rarity.RARE, mage.cards.j.JolraelEmpressOfBeasts.class)); + cards.add(new SetCardInfo("Jolrael's Favor", 116, Rarity.COMMON, mage.cards.j.JolraelsFavor.class)); + cards.add(new SetCardInfo("Keldon Arsonist", 92, Rarity.UNCOMMON, mage.cards.k.KeldonArsonist.class)); + cards.add(new SetCardInfo("Latulla, Keldon Overseer", 95, Rarity.RARE, mage.cards.l.LatullaKeldonOverseer.class)); + cards.add(new SetCardInfo("Lesser Gargadon", 97, Rarity.UNCOMMON, mage.cards.l.LesserGargadon.class)); + cards.add(new SetCardInfo("Living Terrain", 117, Rarity.UNCOMMON, mage.cards.l.LivingTerrain.class)); + cards.add(new SetCardInfo("Mageta's Boon", 14, Rarity.COMMON, mage.cards.m.MagetasBoon.class)); + cards.add(new SetCardInfo("Mageta the Lion", 13, Rarity.RARE, mage.cards.m.MagetaTheLion.class)); + cards.add(new SetCardInfo("Marsh Boa", 118, Rarity.COMMON, mage.cards.m.MarshBoa.class)); + cards.add(new SetCardInfo("Mercenary Informer", 15, Rarity.RARE, mage.cards.m.MercenaryInformer.class)); + cards.add(new SetCardInfo("Mine Bearer", 16, Rarity.COMMON, mage.cards.m.MineBearer.class)); + cards.add(new SetCardInfo("Mungha Wurm", 119, Rarity.RARE, mage.cards.m.MunghaWurm.class)); + cards.add(new SetCardInfo("Nakaya Shade", 69, Rarity.UNCOMMON, mage.cards.n.NakayaShade.class)); + cards.add(new SetCardInfo("Noxious Field", 70, Rarity.UNCOMMON, mage.cards.n.NoxiousField.class)); + cards.add(new SetCardInfo("Outbreak", 71, Rarity.UNCOMMON, mage.cards.o.Outbreak.class)); + cards.add(new SetCardInfo("Overburden", 39, Rarity.RARE, mage.cards.o.Overburden.class)); + cards.add(new SetCardInfo("Panic Attack", 98, Rarity.COMMON, mage.cards.p.PanicAttack.class)); + cards.add(new SetCardInfo("Pit Raptor", 72, Rarity.UNCOMMON, mage.cards.p.PitRaptor.class)); + cards.add(new SetCardInfo("Plague Fiend", 73, Rarity.COMMON, mage.cards.p.PlagueFiend.class)); + cards.add(new SetCardInfo("Plague Wind", 74, Rarity.RARE, mage.cards.p.PlagueWind.class)); + cards.add(new SetCardInfo("Pygmy Razorback", 120, Rarity.COMMON, mage.cards.p.PygmyRazorback.class)); + cards.add(new SetCardInfo("Quicksilver Wall", 41, Rarity.UNCOMMON, mage.cards.q.QuicksilverWall.class)); + cards.add(new SetCardInfo("Rebel Informer", 75, Rarity.RARE, mage.cards.r.RebelInformer.class)); + cards.add(new SetCardInfo("Rethink", 42, Rarity.COMMON, mage.cards.r.Rethink.class)); + cards.add(new SetCardInfo("Rhystic Circle", 19, Rarity.COMMON, mage.cards.r.RhysticCircle.class)); + cards.add(new SetCardInfo("Rhystic Study", 45, Rarity.COMMON, mage.cards.r.RhysticStudy.class)); + cards.add(new SetCardInfo("Rhystic Tutor", 77, Rarity.RARE, mage.cards.r.RhysticTutor.class)); + cards.add(new SetCardInfo("Ribbon Snake", 46, Rarity.COMMON, mage.cards.r.RibbonSnake.class)); + cards.add(new SetCardInfo("Rib Cage Spider", 121, Rarity.COMMON, mage.cards.r.RibCageSpider.class)); + cards.add(new SetCardInfo("Ridgeline Rager", 100, Rarity.COMMON, mage.cards.r.RidgelineRager.class)); + cards.add(new SetCardInfo("Root Cage", 122, Rarity.UNCOMMON, mage.cards.r.RootCage.class)); + cards.add(new SetCardInfo("Scoria Cat", 101, Rarity.UNCOMMON, mage.cards.s.ScoriaCat.class)); + cards.add(new SetCardInfo("Searing Wind", 103, Rarity.RARE, mage.cards.s.SearingWind.class)); + cards.add(new SetCardInfo("Shield Dancer", 23, Rarity.UNCOMMON, mage.cards.s.ShieldDancer.class)); + cards.add(new SetCardInfo("Silt Crawler", 123, Rarity.COMMON, mage.cards.s.SiltCrawler.class)); + cards.add(new SetCardInfo("Spiketail Drake", 48, Rarity.UNCOMMON, mage.cards.s.SpiketailDrake.class)); + cards.add(new SetCardInfo("Spiketail Hatchling", 49, Rarity.COMMON, mage.cards.s.SpiketailHatchling.class)); + cards.add(new SetCardInfo("Spitting Spider", 125, Rarity.UNCOMMON, mage.cards.s.SpittingSpider.class)); + cards.add(new SetCardInfo("Spore Frog", 126, Rarity.COMMON, mage.cards.s.SporeFrog.class)); + cards.add(new SetCardInfo("Spur Grappler", 104, Rarity.COMMON, mage.cards.s.SpurGrappler.class)); + cards.add(new SetCardInfo("Squirrel Wrangler", 127, Rarity.RARE, mage.cards.s.SquirrelWrangler.class)); + cards.add(new SetCardInfo("Steal Strength", 79, Rarity.COMMON, mage.cards.s.StealStrength.class)); + cards.add(new SetCardInfo("Stormwatch Eagle", 50, Rarity.COMMON, mage.cards.s.StormwatchEagle.class)); + cards.add(new SetCardInfo("Sunken Field", 51, Rarity.UNCOMMON, mage.cards.s.SunkenField.class)); + cards.add(new SetCardInfo("Sword Dancer", 25, Rarity.UNCOMMON, mage.cards.s.SwordDancer.class)); + cards.add(new SetCardInfo("Thrive", 129, Rarity.COMMON, mage.cards.t.Thrive.class)); + cards.add(new SetCardInfo("Trenching Steed", 26, Rarity.COMMON, mage.cards.t.TrenchingSteed.class)); + cards.add(new SetCardInfo("Troubled Healer", 27, Rarity.COMMON, mage.cards.t.TroubledHealer.class)); + cards.add(new SetCardInfo("Troublesome Spirit", 52, Rarity.RARE, mage.cards.t.TroublesomeSpirit.class)); + cards.add(new SetCardInfo("Verdant Field", 130, Rarity.UNCOMMON, mage.cards.v.VerdantField.class)); + cards.add(new SetCardInfo("Vintara Elephant", 131, Rarity.COMMON, mage.cards.v.VintaraElephant.class)); + cards.add(new SetCardInfo("Vintara Snapper", 132, Rarity.UNCOMMON, mage.cards.v.VintaraSnapper.class)); + cards.add(new SetCardInfo("Well of Discovery", 140, Rarity.RARE, mage.cards.w.WellOfDiscovery.class)); + cards.add(new SetCardInfo("Well of Life", 141, Rarity.UNCOMMON, mage.cards.w.WellOfLife.class)); + cards.add(new SetCardInfo("Whip Sergeant", 107, Rarity.UNCOMMON, mage.cards.w.WhipSergeant.class)); + cards.add(new SetCardInfo("Whipstitched Zombie", 81, Rarity.COMMON, mage.cards.w.WhipstitchedZombie.class)); + cards.add(new SetCardInfo("Wild Might", 134, Rarity.COMMON, mage.cards.w.WildMight.class)); + cards.add(new SetCardInfo("Wintermoon Mesa", 143, Rarity.RARE, mage.cards.w.WintermoonMesa.class)); + cards.add(new SetCardInfo("Withdraw", 54, Rarity.COMMON, mage.cards.w.Withdraw.class)); + cards.add(new SetCardInfo("Zerapa Minotaur", 108, Rarity.COMMON, mage.cards.z.ZerapaMinotaur.class)); + } +} diff --git a/Mage.Sets/src/mage/sets/TimeSpiral.java b/Mage.Sets/src/mage/sets/TimeSpiral.java index 206faf76cec..89a8cecf563 100644 --- a/Mage.Sets/src/mage/sets/TimeSpiral.java +++ b/Mage.Sets/src/mage/sets/TimeSpiral.java @@ -86,6 +86,7 @@ public class TimeSpiral extends ExpansionSet { cards.add(new SetCardInfo("Errant Doomsayers", 15, Rarity.COMMON, mage.cards.e.ErrantDoomsayers.class)); cards.add(new SetCardInfo("Errant Ephemeron", 60, Rarity.COMMON, mage.cards.e.ErrantEphemeron.class)); cards.add(new SetCardInfo("Eternity Snare", 61, Rarity.COMMON, mage.cards.e.EternitySnare.class)); + cards.add(new SetCardInfo("Evangelize", 16, Rarity.RARE, mage.cards.e.Evangelize.class)); cards.add(new SetCardInfo("Evil Eye of Urborg", 107, Rarity.UNCOMMON, mage.cards.e.EvilEyeOfUrborg.class)); cards.add(new SetCardInfo("Faceless Devourer", 108, Rarity.UNCOMMON, mage.cards.f.FacelessDevourer.class)); cards.add(new SetCardInfo("Fallen Ideal", 109, Rarity.UNCOMMON, mage.cards.f.FallenIdeal.class)); diff --git a/Mage.Sets/src/mage/sets/Weatherlight.java b/Mage.Sets/src/mage/sets/Weatherlight.java index fe13584ad56..d87b3a3450a 100644 --- a/Mage.Sets/src/mage/sets/Weatherlight.java +++ b/Mage.Sets/src/mage/sets/Weatherlight.java @@ -1,193 +1,194 @@ -/* -* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, are -* permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this list of -* conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, this list -* of conditions and the following disclaimer in the documentation and/or other materials -* provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED -* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR -* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -* The views and conclusions contained in the software and documentation are those of the -* authors and should not be interpreted as representing official policies, either expressed -* or implied, of BetaSteward_at_googlemail.com. -*/ - -package mage.sets; - -import mage.constants.SetType; -import mage.cards.ExpansionSet; - -import mage.constants.Rarity; - -/** - * - * @author noxx - */ -public class Weatherlight extends ExpansionSet { - - private static final Weatherlight fINSTANCE = new Weatherlight(); - - public static Weatherlight getInstance() { - return fINSTANCE; - } - - private Weatherlight() { - super("Weatherlight", "WTH", ExpansionSet.buildDate(1997, 5, 31), SetType.EXPANSION); - this.blockName = "Mirage"; - this.parentSet = Mirage.getInstance(); - this.hasBasicLands = false; - this.hasBoosters = true; - this.numBoosterLands = 0; - this.numBoosterCommon = 11; - this.numBoosterUncommon = 3; - this.numBoosterRare = 1; - this.ratioBoosterMythic = 0; - cards.add(new SetCardInfo("Abduction", 30, Rarity.UNCOMMON, mage.cards.a.Abduction.class)); - cards.add(new SetCardInfo("Abeyance", 117, Rarity.RARE, mage.cards.a.Abeyance.class)); - cards.add(new SetCardInfo("Abjure", 31, Rarity.COMMON, mage.cards.a.Abjure.class)); - cards.add(new SetCardInfo("Abyssal Gatekeeper", 1, Rarity.COMMON, mage.cards.a.AbyssalGatekeeper.class)); - cards.add(new SetCardInfo("Aether Flash", 88, Rarity.UNCOMMON, mage.cards.a.AetherFlash.class)); - cards.add(new SetCardInfo("Agonizing Memories", 2, Rarity.UNCOMMON, mage.cards.a.AgonizingMemories.class)); - cards.add(new SetCardInfo("Alabaster Dragon", 118, Rarity.RARE, mage.cards.a.AlabasterDragon.class)); - cards.add(new SetCardInfo("Alms", 119, Rarity.COMMON, mage.cards.a.Alms.class)); - cards.add(new SetCardInfo("Ancestral Knowledge", 32, Rarity.RARE, mage.cards.a.AncestralKnowledge.class)); - cards.add(new SetCardInfo("Angelic Renewal", 120, Rarity.COMMON, mage.cards.a.AngelicRenewal.class)); - cards.add(new SetCardInfo("Arctic Wolves", 60, Rarity.UNCOMMON, mage.cards.a.ArcticWolves.class)); - cards.add(new SetCardInfo("Ardent Militia", 121, Rarity.COMMON, mage.cards.a.ArdentMilitia.class)); - cards.add(new SetCardInfo("Argivian Find", 122, Rarity.UNCOMMON, mage.cards.a.ArgivianFind.class)); - cards.add(new SetCardInfo("Argivian Restoration", 34, Rarity.UNCOMMON, mage.cards.a.ArgivianRestoration.class)); - cards.add(new SetCardInfo("Aura of Silence", 123, Rarity.UNCOMMON, mage.cards.a.AuraOfSilence.class)); - cards.add(new SetCardInfo("Barrow Ghoul", 3, Rarity.COMMON, mage.cards.b.BarrowGhoul.class)); - cards.add(new SetCardInfo("Benalish Knight", 125, Rarity.COMMON, mage.cards.b.BenalishKnight.class)); - cards.add(new SetCardInfo("Benalish Missionary", 126, Rarity.COMMON, mage.cards.b.BenalishMissionary.class)); - cards.add(new SetCardInfo("Bloodrock Cyclops", 90, Rarity.COMMON, mage.cards.b.BloodrockCyclops.class)); - cards.add(new SetCardInfo("Blossoming Wreath", 62, Rarity.COMMON, mage.cards.b.BlossomingWreath.class)); - cards.add(new SetCardInfo("Bogardan Firefiend", 91, Rarity.COMMON, mage.cards.b.BogardanFirefiend.class)); - cards.add(new SetCardInfo("Boiling Blood", 92, Rarity.COMMON, mage.cards.b.BoilingBlood.class)); - cards.add(new SetCardInfo("Bone Dancer", 4, Rarity.RARE, mage.cards.b.BoneDancer.class)); - cards.add(new SetCardInfo("Briar Shield", 63, Rarity.COMMON, mage.cards.b.BriarShield.class)); - cards.add(new SetCardInfo("Bubble Matrix", 147, Rarity.RARE, mage.cards.b.BubbleMatrix.class)); - cards.add(new SetCardInfo("Buried Alive", 5, Rarity.UNCOMMON, mage.cards.b.BuriedAlive.class)); - cards.add(new SetCardInfo("Call of the Wild", 64, Rarity.RARE, mage.cards.c.CallOfTheWild.class)); - cards.add(new SetCardInfo("Chimeric Sphere", 148, Rarity.UNCOMMON, mage.cards.c.ChimericSphere.class)); - cards.add(new SetCardInfo("Cinder Giant", 93, Rarity.UNCOMMON, mage.cards.c.CinderGiant.class)); - cards.add(new SetCardInfo("Cinder Wall", 94, Rarity.COMMON, mage.cards.c.CinderWall.class)); - cards.add(new SetCardInfo("Cloud Djinn", 36, Rarity.UNCOMMON, mage.cards.c.CloudDjinn.class)); - cards.add(new SetCardInfo("Cone of Flame", 95, Rarity.UNCOMMON, mage.cards.c.ConeOfFlame.class)); - cards.add(new SetCardInfo("Debt of Loyalty", 127, Rarity.RARE, mage.cards.d.DebtOfLoyalty.class)); - cards.add(new SetCardInfo("Dense Foliage", 66, Rarity.RARE, mage.cards.d.DenseFoliage.class)); - cards.add(new SetCardInfo("Disrupt", 37, Rarity.COMMON, mage.cards.d.Disrupt.class)); - cards.add(new SetCardInfo("Doomsday", 8, Rarity.RARE, mage.cards.d.Doomsday.class)); - cards.add(new SetCardInfo("Downdraft", 67, Rarity.UNCOMMON, mage.cards.d.Downdraft.class)); - cards.add(new SetCardInfo("Duskrider Falcon", 128, Rarity.COMMON, mage.cards.d.DuskriderFalcon.class)); - cards.add(new SetCardInfo("Dwarven Berserker", 97, Rarity.COMMON, mage.cards.d.DwarvenBerserker.class)); - cards.add(new SetCardInfo("Dwarven Thaumaturgist", 98, Rarity.RARE, mage.cards.d.DwarvenThaumaturgist.class)); - cards.add(new SetCardInfo("Empyrial Armor", 129, Rarity.COMMON, mage.cards.e.EmpyrialArmor.class)); - cards.add(new SetCardInfo("Fallow Wurm", 68, Rarity.UNCOMMON, mage.cards.f.FallowWurm.class)); - cards.add(new SetCardInfo("Familiar Ground", 69, Rarity.UNCOMMON, mage.cards.f.FamiliarGround.class)); - cards.add(new SetCardInfo("Fatal Blow", 9, Rarity.COMMON, mage.cards.f.FatalBlow.class)); - cards.add(new SetCardInfo("Fervor", 99, Rarity.RARE, mage.cards.f.Fervor.class)); - cards.add(new SetCardInfo("Festering Evil", 10, Rarity.UNCOMMON, mage.cards.f.FesteringEvil.class)); - cards.add(new SetCardInfo("Firestorm", 101, Rarity.RARE, mage.cards.f.Firestorm.class)); - cards.add(new SetCardInfo("Fire Whip", 100, Rarity.COMMON, mage.cards.f.FireWhip.class)); - cards.add(new SetCardInfo("Fit of Rage", 102, Rarity.COMMON, mage.cards.f.FitOfRage.class)); - cards.add(new SetCardInfo("Fledgling Djinn", 11, Rarity.COMMON, mage.cards.f.FledglingDjinn.class)); - cards.add(new SetCardInfo("Fog Elemental", 40, Rarity.COMMON, mage.cards.f.FogElemental.class)); - cards.add(new SetCardInfo("Foriysian Brigade", 130, Rarity.UNCOMMON, mage.cards.f.ForiysianBrigade.class)); - cards.add(new SetCardInfo("Gaea's Blessing", 71, Rarity.UNCOMMON, mage.cards.g.GaeasBlessing.class)); - cards.add(new SetCardInfo("Gallowbraid", 12, Rarity.RARE, mage.cards.g.Gallowbraid.class)); - cards.add(new SetCardInfo("Gemstone Mine", 164, Rarity.UNCOMMON, mage.cards.g.GemstoneMine.class)); - cards.add(new SetCardInfo("Gerrard's Wisdom", 131, Rarity.UNCOMMON, mage.cards.g.GerrardsWisdom.class)); - cards.add(new SetCardInfo("Goblin Bomb", 103, Rarity.RARE, mage.cards.g.GoblinBomb.class)); - cards.add(new SetCardInfo("Goblin Grenadiers", 104, Rarity.UNCOMMON, mage.cards.g.GoblinGrenadiers.class)); - cards.add(new SetCardInfo("Goblin Vandal", 105, Rarity.COMMON, mage.cards.g.GoblinVandal.class)); - cards.add(new SetCardInfo("Guided Strike", 132, Rarity.COMMON, mage.cards.g.GuidedStrike.class)); - cards.add(new SetCardInfo("Harvest Wurm", 72, Rarity.COMMON, mage.cards.h.HarvestWurm.class)); - cards.add(new SetCardInfo("Haunting Misery", 13, Rarity.COMMON, mage.cards.h.HauntingMisery.class)); - cards.add(new SetCardInfo("Heavy Ballista", 133, Rarity.COMMON, mage.cards.h.HeavyBallista.class)); - cards.add(new SetCardInfo("Hidden Horror", 14, Rarity.UNCOMMON, mage.cards.h.HiddenHorror.class)); - cards.add(new SetCardInfo("Hurloon Shaman", 108, Rarity.UNCOMMON, mage.cards.h.HurloonShaman.class)); - cards.add(new SetCardInfo("Jabari's Banner", 150, Rarity.UNCOMMON, mage.cards.j.JabarisBanner.class)); - cards.add(new SetCardInfo("Lava Hounds", 109, Rarity.UNCOMMON, mage.cards.l.LavaHounds.class)); - cards.add(new SetCardInfo("Llanowar Behemoth", 74, Rarity.UNCOMMON, mage.cards.l.LlanowarBehemoth.class)); - cards.add(new SetCardInfo("Llanowar Druid", 75, Rarity.COMMON, mage.cards.l.LlanowarDruid.class)); - cards.add(new SetCardInfo("Llanowar Sentinel", 76, Rarity.COMMON, mage.cards.l.LlanowarSentinel.class)); - cards.add(new SetCardInfo("Lotus Vale", 165, Rarity.RARE, mage.cards.l.LotusVale.class)); - cards.add(new SetCardInfo("Mana Chains", 41, Rarity.COMMON, mage.cards.m.ManaChains.class)); - cards.add(new SetCardInfo("Mana Web", 152, Rarity.RARE, mage.cards.m.ManaWeb.class)); - cards.add(new SetCardInfo("Manta Ray", 42, Rarity.COMMON, mage.cards.m.MantaRay.class)); - cards.add(new SetCardInfo("Maraxus of Keld", 111, Rarity.RARE, mage.cards.m.MaraxusOfKeld.class)); - cards.add(new SetCardInfo("Master of Arms", 136, Rarity.UNCOMMON, mage.cards.m.MasterOfArms.class)); - cards.add(new SetCardInfo("Merfolk Traders", 43, Rarity.COMMON, mage.cards.m.MerfolkTraders.class)); - cards.add(new SetCardInfo("Mind Stone", 153, Rarity.COMMON, mage.cards.m.MindStone.class)); - cards.add(new SetCardInfo("Mischievous Poltergeist", 16, Rarity.UNCOMMON, mage.cards.m.MischievousPoltergeist.class)); - cards.add(new SetCardInfo("Mistmoon Griffin", 137, Rarity.UNCOMMON, mage.cards.m.MistmoonGriffin.class)); - cards.add(new SetCardInfo("Morinfen", 17, Rarity.RARE, mage.cards.m.Morinfen.class)); - cards.add(new SetCardInfo("Mwonvuli Ooze", 77, Rarity.RARE, mage.cards.m.MwonvuliOoze.class)); - cards.add(new SetCardInfo("Nature's Kiss", 78, Rarity.COMMON, mage.cards.n.NaturesKiss.class)); - cards.add(new SetCardInfo("Nature's Resurgence", 79, Rarity.RARE, mage.cards.n.NaturesResurgence.class)); - cards.add(new SetCardInfo("Necratog", 18, Rarity.UNCOMMON, mage.cards.n.Necratog.class)); - cards.add(new SetCardInfo("Null Rod", 154, Rarity.RARE, mage.cards.n.NullRod.class)); - cards.add(new SetCardInfo("Odylic Wraith", 19, Rarity.UNCOMMON, mage.cards.o.OdylicWraith.class)); - cards.add(new SetCardInfo("Ophidian", 45, Rarity.COMMON, mage.cards.o.Ophidian.class)); - cards.add(new SetCardInfo("Orcish Settlers", 112, Rarity.UNCOMMON, mage.cards.o.OrcishSettlers.class)); - cards.add(new SetCardInfo("Paradigm Shift", 46, Rarity.RARE, mage.cards.p.ParadigmShift.class)); - cards.add(new SetCardInfo("Peacekeeper", 138, Rarity.RARE, mage.cards.p.Peacekeeper.class)); - cards.add(new SetCardInfo("Pendrell Mists", 47, Rarity.RARE, mage.cards.p.PendrellMists.class)); - cards.add(new SetCardInfo("Phantom Warrior", 48, Rarity.UNCOMMON, mage.cards.p.PhantomWarrior.class)); - cards.add(new SetCardInfo("Phantom Wings", 49, Rarity.COMMON, mage.cards.p.PhantomWings.class)); - cards.add(new SetCardInfo("Phyrexian Furnace", 155, Rarity.UNCOMMON, mage.cards.p.PhyrexianFurnace.class)); - cards.add(new SetCardInfo("Psychic Vortex", 50, Rarity.RARE, mage.cards.p.PsychicVortex.class)); - cards.add(new SetCardInfo("Razortooth Rats", 20, Rarity.COMMON, mage.cards.r.RazortoothRats.class)); - cards.add(new SetCardInfo("Redwood Treefolk", 80, Rarity.COMMON, mage.cards.r.RedwoodTreefolk.class)); - cards.add(new SetCardInfo("Relearn", 51, Rarity.UNCOMMON, mage.cards.r.Relearn.class)); - cards.add(new SetCardInfo("Revered Unicorn", 139, Rarity.UNCOMMON, mage.cards.r.ReveredUnicorn.class)); - cards.add(new SetCardInfo("Roc Hatchling", 113, Rarity.UNCOMMON, mage.cards.r.RocHatchling.class)); - cards.add(new SetCardInfo("Rogue Elephant", 81, Rarity.COMMON, mage.cards.r.RogueElephant.class)); - cards.add(new SetCardInfo("Sage Owl", 52, Rarity.COMMON, mage.cards.s.SageOwl.class)); - cards.add(new SetCardInfo("Scorched Ruins", 166, Rarity.RARE, mage.cards.s.ScorchedRuins.class)); - cards.add(new SetCardInfo("Serenity", 140, Rarity.RARE, mage.cards.s.Serenity.class)); - cards.add(new SetCardInfo("Serra's Blessing", 141, Rarity.UNCOMMON, mage.cards.s.SerrasBlessing.class)); - cards.add(new SetCardInfo("Serrated Biskelion", 156, Rarity.UNCOMMON, mage.cards.s.SerratedBiskelion.class)); - cards.add(new SetCardInfo("Shadow Rider", 21, Rarity.COMMON, mage.cards.s.ShadowRider.class)); - cards.add(new SetCardInfo("Soul Shepherd", 142, Rarity.COMMON, mage.cards.s.SoulShepherd.class)); - cards.add(new SetCardInfo("Southern Paladin", 143, Rarity.RARE, mage.cards.s.SouthernPaladin.class)); - cards.add(new SetCardInfo("Spinning Darkness", 23, Rarity.COMMON, mage.cards.s.SpinningDarkness.class)); - cards.add(new SetCardInfo("Steel Golem", 157, Rarity.UNCOMMON, mage.cards.s.SteelGolem.class)); - cards.add(new SetCardInfo("Strands of Night", 24, Rarity.UNCOMMON, mage.cards.s.StrandsOfNight.class)); - cards.add(new SetCardInfo("Straw Golem", 158, Rarity.UNCOMMON, mage.cards.s.StrawGolem.class)); - cards.add(new SetCardInfo("Striped Bears", 82, Rarity.COMMON, mage.cards.s.StripedBears.class)); - cards.add(new SetCardInfo("Tariff", 144, Rarity.RARE, mage.cards.t.Tariff.class)); - cards.add(new SetCardInfo("Tendrils of Despair", 25, Rarity.COMMON, mage.cards.t.TendrilsOfDespair.class)); - cards.add(new SetCardInfo("Thunderbolt", 115, Rarity.COMMON, mage.cards.t.Thunderbolt.class)); - cards.add(new SetCardInfo("Thundermare", 116, Rarity.RARE, mage.cards.t.Thundermare.class)); - cards.add(new SetCardInfo("Tolarian Drake", 55, Rarity.COMMON, mage.cards.t.TolarianDrake.class)); - cards.add(new SetCardInfo("Tolarian Entrancer", 56, Rarity.RARE, mage.cards.t.TolarianEntrancer.class)); - cards.add(new SetCardInfo("Tolarian Serpent", 57, Rarity.RARE, mage.cards.t.TolarianSerpent.class)); - cards.add(new SetCardInfo("Touchstone", 161, Rarity.UNCOMMON, mage.cards.t.Touchstone.class)); - cards.add(new SetCardInfo("Tranquil Grove", 84, Rarity.RARE, mage.cards.t.TranquilGrove.class)); - cards.add(new SetCardInfo("Uktabi Efreet", 85, Rarity.COMMON, mage.cards.u.UktabiEfreet.class)); - cards.add(new SetCardInfo("Urborg Justice", 26, Rarity.RARE, mage.cards.u.UrborgJustice.class)); - cards.add(new SetCardInfo("Veteran Explorer", 86, Rarity.UNCOMMON, mage.cards.v.VeteranExplorer.class)); - cards.add(new SetCardInfo("Vitalize", 87, Rarity.COMMON, mage.cards.v.Vitalize.class)); - cards.add(new SetCardInfo("Vodalian Illusionist", 58, Rarity.UNCOMMON, mage.cards.v.VodalianIllusionist.class)); - cards.add(new SetCardInfo("Winding Canyons", 167, Rarity.RARE, mage.cards.w.WindingCanyons.class)); - cards.add(new SetCardInfo("Xanthic Statue", 163, Rarity.RARE, mage.cards.x.XanthicStatue.class)); - cards.add(new SetCardInfo("Zombie Scavengers", 29, Rarity.COMMON, mage.cards.z.ZombieScavengers.class)); - } - -} +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +package mage.sets; + +import mage.constants.SetType; +import mage.cards.ExpansionSet; + +import mage.constants.Rarity; + +/** + * + * @author noxx + */ +public class Weatherlight extends ExpansionSet { + + private static final Weatherlight fINSTANCE = new Weatherlight(); + + public static Weatherlight getInstance() { + return fINSTANCE; + } + + private Weatherlight() { + super("Weatherlight", "WTH", ExpansionSet.buildDate(1997, 5, 31), SetType.EXPANSION); + this.blockName = "Mirage"; + this.parentSet = Mirage.getInstance(); + this.hasBasicLands = false; + this.hasBoosters = true; + this.numBoosterLands = 0; + this.numBoosterCommon = 11; + this.numBoosterUncommon = 3; + this.numBoosterRare = 1; + this.ratioBoosterMythic = 0; + cards.add(new SetCardInfo("Abduction", 30, Rarity.UNCOMMON, mage.cards.a.Abduction.class)); + cards.add(new SetCardInfo("Abeyance", 117, Rarity.RARE, mage.cards.a.Abeyance.class)); + cards.add(new SetCardInfo("Abjure", 31, Rarity.COMMON, mage.cards.a.Abjure.class)); + cards.add(new SetCardInfo("Abyssal Gatekeeper", 1, Rarity.COMMON, mage.cards.a.AbyssalGatekeeper.class)); + cards.add(new SetCardInfo("Aether Flash", 88, Rarity.UNCOMMON, mage.cards.a.AetherFlash.class)); + cards.add(new SetCardInfo("Agonizing Memories", 2, Rarity.UNCOMMON, mage.cards.a.AgonizingMemories.class)); + cards.add(new SetCardInfo("Alabaster Dragon", 118, Rarity.RARE, mage.cards.a.AlabasterDragon.class)); + cards.add(new SetCardInfo("Alms", 119, Rarity.COMMON, mage.cards.a.Alms.class)); + cards.add(new SetCardInfo("Ancestral Knowledge", 32, Rarity.RARE, mage.cards.a.AncestralKnowledge.class)); + cards.add(new SetCardInfo("Angelic Renewal", 120, Rarity.COMMON, mage.cards.a.AngelicRenewal.class)); + cards.add(new SetCardInfo("Arctic Wolves", 60, Rarity.UNCOMMON, mage.cards.a.ArcticWolves.class)); + cards.add(new SetCardInfo("Ardent Militia", 121, Rarity.COMMON, mage.cards.a.ArdentMilitia.class)); + cards.add(new SetCardInfo("Argivian Find", 122, Rarity.UNCOMMON, mage.cards.a.ArgivianFind.class)); + cards.add(new SetCardInfo("Argivian Restoration", 34, Rarity.UNCOMMON, mage.cards.a.ArgivianRestoration.class)); + cards.add(new SetCardInfo("Aura of Silence", 123, Rarity.UNCOMMON, mage.cards.a.AuraOfSilence.class)); + cards.add(new SetCardInfo("Barrow Ghoul", 3, Rarity.COMMON, mage.cards.b.BarrowGhoul.class)); + cards.add(new SetCardInfo("Benalish Knight", 125, Rarity.COMMON, mage.cards.b.BenalishKnight.class)); + cards.add(new SetCardInfo("Benalish Missionary", 126, Rarity.COMMON, mage.cards.b.BenalishMissionary.class)); + cards.add(new SetCardInfo("Bloodrock Cyclops", 90, Rarity.COMMON, mage.cards.b.BloodrockCyclops.class)); + cards.add(new SetCardInfo("Blossoming Wreath", 62, Rarity.COMMON, mage.cards.b.BlossomingWreath.class)); + cards.add(new SetCardInfo("Bogardan Firefiend", 91, Rarity.COMMON, mage.cards.b.BogardanFirefiend.class)); + cards.add(new SetCardInfo("Boiling Blood", 92, Rarity.COMMON, mage.cards.b.BoilingBlood.class)); + cards.add(new SetCardInfo("Bone Dancer", 4, Rarity.RARE, mage.cards.b.BoneDancer.class)); + cards.add(new SetCardInfo("Briar Shield", 63, Rarity.COMMON, mage.cards.b.BriarShield.class)); + cards.add(new SetCardInfo("Bubble Matrix", 147, Rarity.RARE, mage.cards.b.BubbleMatrix.class)); + cards.add(new SetCardInfo("Buried Alive", 5, Rarity.UNCOMMON, mage.cards.b.BuriedAlive.class)); + cards.add(new SetCardInfo("Call of the Wild", 64, Rarity.RARE, mage.cards.c.CallOfTheWild.class)); + cards.add(new SetCardInfo("Chimeric Sphere", 148, Rarity.UNCOMMON, mage.cards.c.ChimericSphere.class)); + cards.add(new SetCardInfo("Cinder Giant", 93, Rarity.UNCOMMON, mage.cards.c.CinderGiant.class)); + cards.add(new SetCardInfo("Cinder Wall", 94, Rarity.COMMON, mage.cards.c.CinderWall.class)); + cards.add(new SetCardInfo("Cloud Djinn", 36, Rarity.UNCOMMON, mage.cards.c.CloudDjinn.class)); + cards.add(new SetCardInfo("Cone of Flame", 95, Rarity.UNCOMMON, mage.cards.c.ConeOfFlame.class)); + cards.add(new SetCardInfo("Debt of Loyalty", 127, Rarity.RARE, mage.cards.d.DebtOfLoyalty.class)); + cards.add(new SetCardInfo("Dense Foliage", 66, Rarity.RARE, mage.cards.d.DenseFoliage.class)); + cards.add(new SetCardInfo("Disrupt", 37, Rarity.COMMON, mage.cards.d.Disrupt.class)); + cards.add(new SetCardInfo("Doomsday", 8, Rarity.RARE, mage.cards.d.Doomsday.class)); + cards.add(new SetCardInfo("Downdraft", 67, Rarity.UNCOMMON, mage.cards.d.Downdraft.class)); + cards.add(new SetCardInfo("Duskrider Falcon", 128, Rarity.COMMON, mage.cards.d.DuskriderFalcon.class)); + cards.add(new SetCardInfo("Dwarven Berserker", 97, Rarity.COMMON, mage.cards.d.DwarvenBerserker.class)); + cards.add(new SetCardInfo("Dwarven Thaumaturgist", 98, Rarity.RARE, mage.cards.d.DwarvenThaumaturgist.class)); + cards.add(new SetCardInfo("Empyrial Armor", 129, Rarity.COMMON, mage.cards.e.EmpyrialArmor.class)); + cards.add(new SetCardInfo("Fallow Wurm", 68, Rarity.UNCOMMON, mage.cards.f.FallowWurm.class)); + cards.add(new SetCardInfo("Familiar Ground", 69, Rarity.UNCOMMON, mage.cards.f.FamiliarGround.class)); + cards.add(new SetCardInfo("Fatal Blow", 9, Rarity.COMMON, mage.cards.f.FatalBlow.class)); + cards.add(new SetCardInfo("Fervor", 99, Rarity.RARE, mage.cards.f.Fervor.class)); + cards.add(new SetCardInfo("Festering Evil", 10, Rarity.UNCOMMON, mage.cards.f.FesteringEvil.class)); + cards.add(new SetCardInfo("Firestorm", 101, Rarity.RARE, mage.cards.f.Firestorm.class)); + cards.add(new SetCardInfo("Fire Whip", 100, Rarity.COMMON, mage.cards.f.FireWhip.class)); + cards.add(new SetCardInfo("Fit of Rage", 102, Rarity.COMMON, mage.cards.f.FitOfRage.class)); + cards.add(new SetCardInfo("Fledgling Djinn", 11, Rarity.COMMON, mage.cards.f.FledglingDjinn.class)); + cards.add(new SetCardInfo("Flux", 27, Rarity.COMMON, mage.cards.f.Flux.class)); + cards.add(new SetCardInfo("Fog Elemental", 40, Rarity.COMMON, mage.cards.f.FogElemental.class)); + cards.add(new SetCardInfo("Foriysian Brigade", 130, Rarity.UNCOMMON, mage.cards.f.ForiysianBrigade.class)); + cards.add(new SetCardInfo("Gaea's Blessing", 71, Rarity.UNCOMMON, mage.cards.g.GaeasBlessing.class)); + cards.add(new SetCardInfo("Gallowbraid", 12, Rarity.RARE, mage.cards.g.Gallowbraid.class)); + cards.add(new SetCardInfo("Gemstone Mine", 164, Rarity.UNCOMMON, mage.cards.g.GemstoneMine.class)); + cards.add(new SetCardInfo("Gerrard's Wisdom", 131, Rarity.UNCOMMON, mage.cards.g.GerrardsWisdom.class)); + cards.add(new SetCardInfo("Goblin Bomb", 103, Rarity.RARE, mage.cards.g.GoblinBomb.class)); + cards.add(new SetCardInfo("Goblin Grenadiers", 104, Rarity.UNCOMMON, mage.cards.g.GoblinGrenadiers.class)); + cards.add(new SetCardInfo("Goblin Vandal", 105, Rarity.COMMON, mage.cards.g.GoblinVandal.class)); + cards.add(new SetCardInfo("Guided Strike", 132, Rarity.COMMON, mage.cards.g.GuidedStrike.class)); + cards.add(new SetCardInfo("Harvest Wurm", 72, Rarity.COMMON, mage.cards.h.HarvestWurm.class)); + cards.add(new SetCardInfo("Haunting Misery", 13, Rarity.COMMON, mage.cards.h.HauntingMisery.class)); + cards.add(new SetCardInfo("Heavy Ballista", 133, Rarity.COMMON, mage.cards.h.HeavyBallista.class)); + cards.add(new SetCardInfo("Hidden Horror", 14, Rarity.UNCOMMON, mage.cards.h.HiddenHorror.class)); + cards.add(new SetCardInfo("Hurloon Shaman", 108, Rarity.UNCOMMON, mage.cards.h.HurloonShaman.class)); + cards.add(new SetCardInfo("Jabari's Banner", 150, Rarity.UNCOMMON, mage.cards.j.JabarisBanner.class)); + cards.add(new SetCardInfo("Lava Hounds", 109, Rarity.UNCOMMON, mage.cards.l.LavaHounds.class)); + cards.add(new SetCardInfo("Llanowar Behemoth", 74, Rarity.UNCOMMON, mage.cards.l.LlanowarBehemoth.class)); + cards.add(new SetCardInfo("Llanowar Druid", 75, Rarity.COMMON, mage.cards.l.LlanowarDruid.class)); + cards.add(new SetCardInfo("Llanowar Sentinel", 76, Rarity.COMMON, mage.cards.l.LlanowarSentinel.class)); + cards.add(new SetCardInfo("Lotus Vale", 165, Rarity.RARE, mage.cards.l.LotusVale.class)); + cards.add(new SetCardInfo("Mana Chains", 41, Rarity.COMMON, mage.cards.m.ManaChains.class)); + cards.add(new SetCardInfo("Mana Web", 152, Rarity.RARE, mage.cards.m.ManaWeb.class)); + cards.add(new SetCardInfo("Manta Ray", 42, Rarity.COMMON, mage.cards.m.MantaRay.class)); + cards.add(new SetCardInfo("Maraxus of Keld", 111, Rarity.RARE, mage.cards.m.MaraxusOfKeld.class)); + cards.add(new SetCardInfo("Master of Arms", 136, Rarity.UNCOMMON, mage.cards.m.MasterOfArms.class)); + cards.add(new SetCardInfo("Merfolk Traders", 43, Rarity.COMMON, mage.cards.m.MerfolkTraders.class)); + cards.add(new SetCardInfo("Mind Stone", 153, Rarity.COMMON, mage.cards.m.MindStone.class)); + cards.add(new SetCardInfo("Mischievous Poltergeist", 16, Rarity.UNCOMMON, mage.cards.m.MischievousPoltergeist.class)); + cards.add(new SetCardInfo("Mistmoon Griffin", 137, Rarity.UNCOMMON, mage.cards.m.MistmoonGriffin.class)); + cards.add(new SetCardInfo("Morinfen", 17, Rarity.RARE, mage.cards.m.Morinfen.class)); + cards.add(new SetCardInfo("Mwonvuli Ooze", 77, Rarity.RARE, mage.cards.m.MwonvuliOoze.class)); + cards.add(new SetCardInfo("Nature's Kiss", 78, Rarity.COMMON, mage.cards.n.NaturesKiss.class)); + cards.add(new SetCardInfo("Nature's Resurgence", 79, Rarity.RARE, mage.cards.n.NaturesResurgence.class)); + cards.add(new SetCardInfo("Necratog", 18, Rarity.UNCOMMON, mage.cards.n.Necratog.class)); + cards.add(new SetCardInfo("Null Rod", 154, Rarity.RARE, mage.cards.n.NullRod.class)); + cards.add(new SetCardInfo("Odylic Wraith", 19, Rarity.UNCOMMON, mage.cards.o.OdylicWraith.class)); + cards.add(new SetCardInfo("Ophidian", 45, Rarity.COMMON, mage.cards.o.Ophidian.class)); + cards.add(new SetCardInfo("Orcish Settlers", 112, Rarity.UNCOMMON, mage.cards.o.OrcishSettlers.class)); + cards.add(new SetCardInfo("Paradigm Shift", 46, Rarity.RARE, mage.cards.p.ParadigmShift.class)); + cards.add(new SetCardInfo("Peacekeeper", 138, Rarity.RARE, mage.cards.p.Peacekeeper.class)); + cards.add(new SetCardInfo("Pendrell Mists", 47, Rarity.RARE, mage.cards.p.PendrellMists.class)); + cards.add(new SetCardInfo("Phantom Warrior", 48, Rarity.UNCOMMON, mage.cards.p.PhantomWarrior.class)); + cards.add(new SetCardInfo("Phantom Wings", 49, Rarity.COMMON, mage.cards.p.PhantomWings.class)); + cards.add(new SetCardInfo("Phyrexian Furnace", 155, Rarity.UNCOMMON, mage.cards.p.PhyrexianFurnace.class)); + cards.add(new SetCardInfo("Psychic Vortex", 50, Rarity.RARE, mage.cards.p.PsychicVortex.class)); + cards.add(new SetCardInfo("Razortooth Rats", 20, Rarity.COMMON, mage.cards.r.RazortoothRats.class)); + cards.add(new SetCardInfo("Redwood Treefolk", 80, Rarity.COMMON, mage.cards.r.RedwoodTreefolk.class)); + cards.add(new SetCardInfo("Relearn", 51, Rarity.UNCOMMON, mage.cards.r.Relearn.class)); + cards.add(new SetCardInfo("Revered Unicorn", 139, Rarity.UNCOMMON, mage.cards.r.ReveredUnicorn.class)); + cards.add(new SetCardInfo("Roc Hatchling", 113, Rarity.UNCOMMON, mage.cards.r.RocHatchling.class)); + cards.add(new SetCardInfo("Rogue Elephant", 81, Rarity.COMMON, mage.cards.r.RogueElephant.class)); + cards.add(new SetCardInfo("Sage Owl", 52, Rarity.COMMON, mage.cards.s.SageOwl.class)); + cards.add(new SetCardInfo("Scorched Ruins", 166, Rarity.RARE, mage.cards.s.ScorchedRuins.class)); + cards.add(new SetCardInfo("Serenity", 140, Rarity.RARE, mage.cards.s.Serenity.class)); + cards.add(new SetCardInfo("Serra's Blessing", 141, Rarity.UNCOMMON, mage.cards.s.SerrasBlessing.class)); + cards.add(new SetCardInfo("Serrated Biskelion", 156, Rarity.UNCOMMON, mage.cards.s.SerratedBiskelion.class)); + cards.add(new SetCardInfo("Shadow Rider", 21, Rarity.COMMON, mage.cards.s.ShadowRider.class)); + cards.add(new SetCardInfo("Soul Shepherd", 142, Rarity.COMMON, mage.cards.s.SoulShepherd.class)); + cards.add(new SetCardInfo("Southern Paladin", 143, Rarity.RARE, mage.cards.s.SouthernPaladin.class)); + cards.add(new SetCardInfo("Spinning Darkness", 23, Rarity.COMMON, mage.cards.s.SpinningDarkness.class)); + cards.add(new SetCardInfo("Steel Golem", 157, Rarity.UNCOMMON, mage.cards.s.SteelGolem.class)); + cards.add(new SetCardInfo("Strands of Night", 24, Rarity.UNCOMMON, mage.cards.s.StrandsOfNight.class)); + cards.add(new SetCardInfo("Straw Golem", 158, Rarity.UNCOMMON, mage.cards.s.StrawGolem.class)); + cards.add(new SetCardInfo("Striped Bears", 82, Rarity.COMMON, mage.cards.s.StripedBears.class)); + cards.add(new SetCardInfo("Tariff", 144, Rarity.RARE, mage.cards.t.Tariff.class)); + cards.add(new SetCardInfo("Tendrils of Despair", 25, Rarity.COMMON, mage.cards.t.TendrilsOfDespair.class)); + cards.add(new SetCardInfo("Thunderbolt", 115, Rarity.COMMON, mage.cards.t.Thunderbolt.class)); + cards.add(new SetCardInfo("Thundermare", 116, Rarity.RARE, mage.cards.t.Thundermare.class)); + cards.add(new SetCardInfo("Tolarian Drake", 55, Rarity.COMMON, mage.cards.t.TolarianDrake.class)); + cards.add(new SetCardInfo("Tolarian Entrancer", 56, Rarity.RARE, mage.cards.t.TolarianEntrancer.class)); + cards.add(new SetCardInfo("Tolarian Serpent", 57, Rarity.RARE, mage.cards.t.TolarianSerpent.class)); + cards.add(new SetCardInfo("Touchstone", 161, Rarity.UNCOMMON, mage.cards.t.Touchstone.class)); + cards.add(new SetCardInfo("Tranquil Grove", 84, Rarity.RARE, mage.cards.t.TranquilGrove.class)); + cards.add(new SetCardInfo("Uktabi Efreet", 85, Rarity.COMMON, mage.cards.u.UktabiEfreet.class)); + cards.add(new SetCardInfo("Urborg Justice", 26, Rarity.RARE, mage.cards.u.UrborgJustice.class)); + cards.add(new SetCardInfo("Veteran Explorer", 86, Rarity.UNCOMMON, mage.cards.v.VeteranExplorer.class)); + cards.add(new SetCardInfo("Vitalize", 87, Rarity.COMMON, mage.cards.v.Vitalize.class)); + cards.add(new SetCardInfo("Vodalian Illusionist", 58, Rarity.UNCOMMON, mage.cards.v.VodalianIllusionist.class)); + cards.add(new SetCardInfo("Winding Canyons", 167, Rarity.RARE, mage.cards.w.WindingCanyons.class)); + cards.add(new SetCardInfo("Xanthic Statue", 163, Rarity.RARE, mage.cards.x.XanthicStatue.class)); + cards.add(new SetCardInfo("Zombie Scavengers", 29, Rarity.COMMON, mage.cards.z.ZombieScavengers.class)); + } + +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BloodthirstTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BloodthirstTest.java index dcafcdaf8be..7b64a638947 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BloodthirstTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BloodthirstTest.java @@ -67,7 +67,7 @@ public class BloodthirstTest extends CardTestPlayerBase { public void testBloodlord() { addCard(Zone.BATTLEFIELD, playerA, "Swamp", 8); addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); - // Bloodthirst 3 + // Bloodthirst 3 (If an opponent was dealt damage this turn, this creature enters the battlefield with 3 +1/+1 counters) // Whenever you cast a Vampire creature spell, it gains bloodthirst 3 addCard(Zone.HAND, playerA, "Bloodlord of Vaasgoth"); // {3}{B}{B} addCard(Zone.HAND, playerA, "Barony Vampire"); // 3/2 {2}{B} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/ErsatzGnomesTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/ErsatzGnomesTest.java new file mode 100644 index 00000000000..3f0982b20c9 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/ErsatzGnomesTest.java @@ -0,0 +1,162 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package org.mage.test.cards.continuous; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import mage.game.permanent.Permanent; +import org.junit.Assert; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class ErsatzGnomesTest extends CardTestPlayerBase { + + /** + * Ersatz Gnomes is incorrectly used I targeted a spell which is a permanent + * to colorless. When it enters the field its suppose to be colorless not go + * back to normal. It's colorless until it leaves the battlefield when you + * make a permanent spell colorless when you cast it. + */ + @Test + public void testColorlessSpellCreatesColorlessPermanent() { + addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); + addCard(Zone.HAND, playerA, "Silvercoat Lion", 1); + + // {T}: Target spell becomes colorless. + // {T}: Target permanent becomes colorless until end of turn. + addCard(Zone.BATTLEFIELD, playerA, "Ersatz Gnomes"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Silvercoat Lion"); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Target spell", "Silvercoat Lion"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Silvercoat Lion", 1); + assertTapped("Ersatz Gnomes", true); + Permanent lion = getPermanent("Silvercoat Lion", playerA); + Assert.assertTrue("Silvercoat lion has to be colorless", lion.getColor(currentGame).isColorless()); + } + + @Test + public void testColorlessSpellCreatesColorlessPermanentUntilItBattlefieldLeft() { + addCard(Zone.BATTLEFIELD, playerA, "Plains", 4); + addCard(Zone.HAND, playerA, "Silvercoat Lion", 1); + + // {T}: Target spell becomes colorless. + // {T}: Target permanent becomes colorless until end of turn. + addCard(Zone.BATTLEFIELD, playerA, "Ersatz Gnomes"); + + addCard(Zone.BATTLEFIELD, playerB, "Island", 1); + addCard(Zone.HAND, playerB, "Unsummon"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Silvercoat Lion"); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Target spell", "Silvercoat Lion"); + + castSpell(1, PhaseStep.END_COMBAT, playerB, "Unsummon", "Silvercoat Lion"); + + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Silvercoat Lion"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertGraveyardCount(playerB, "Unsummon", 1); + assertHandCount(playerA, "Silvercoat Lion", 0); + assertPermanentCount(playerA, "Silvercoat Lion", 1); + assertTapped("Ersatz Gnomes", true); + Permanent lion = getPermanent("Silvercoat Lion", playerA); + Assert.assertTrue("Silvercoat lion has to be white", lion.getColor(currentGame).isWhite()); + } + + @Test + public void testChangeColorOfBestowSpell() { + addCard(Zone.BATTLEFIELD, playerA, "Plains", 4); + addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); + // Bestow {3}{W} + // Lifelink + // Echanted creature gets +1/+1 and has lifelink. + addCard(Zone.HAND, playerA, "Hopeful Eidolon");// Creature {W} + + // {T}: Target spell becomes colorless. + // {T}: Target permanent becomes colorless until end of turn. + addCard(Zone.BATTLEFIELD, playerA, "Ersatz Gnomes"); + + addCard(Zone.BATTLEFIELD, playerB, "Island", 1); + addCard(Zone.HAND, playerB, "Unsummon"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Hopeful Eidolon using bestow", "Silvercoat Lion"); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Target spell", "Hopeful Eidolon"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertHandCount(playerA, "Hopeful Eidolon", 0); + assertPermanentCount(playerA, "Hopeful Eidolon", 1); + assertPowerToughness(playerA, "Silvercoat Lion", 3, 3); + assertTapped("Ersatz Gnomes", true); + Permanent eidolon = getPermanent("Hopeful Eidolon", playerA); + Assert.assertTrue("Hopeful Eidolon Enchantment has to be colorless", eidolon.getColor(currentGame).isColorless()); + } + + @Test + public void testChangeColorOfBestowSpellUnsummon() { + addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); + // Bestow {3}{W} + // Lifelink + // Echanted creature gets +1/+1 and has lifelink. + addCard(Zone.HAND, playerA, "Hopeful Eidolon");// Creature {W} + + // {T}: Target spell becomes colorless. + // {T}: Target permanent becomes colorless until end of turn. + addCard(Zone.BATTLEFIELD, playerA, "Ersatz Gnomes"); + + addCard(Zone.BATTLEFIELD, playerB, "Island", 1); + addCard(Zone.HAND, playerB, "Unsummon"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Hopeful Eidolon"); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Target spell", "Hopeful Eidolon"); + + castSpell(1, PhaseStep.END_COMBAT, playerB, "Unsummon", "Hopeful Eidolon"); + + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Hopeful Eidolon"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertGraveyardCount(playerB, "Unsummon", 1); + assertHandCount(playerA, "Hopeful Eidolon", 0); + assertPermanentCount(playerA, "Hopeful Eidolon", 1); + assertTapped("Ersatz Gnomes", true); + Permanent lion = getPermanent("Hopeful Eidolon", playerA); + Assert.assertTrue("Hopeful Eidolon has to be white", lion.getColor(currentGame).isWhite()); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/turnmod/ExtraTurnsTest.java b/Mage.Tests/src/test/java/org/mage/test/turnmod/ExtraTurnsTest.java new file mode 100644 index 00000000000..347e271c08e --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/turnmod/ExtraTurnsTest.java @@ -0,0 +1,70 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package org.mage.test.turnmod; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Assert; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class ExtraTurnsTest extends CardTestPlayerBase { + + /** + * Emrakul, the Promised End not giving an extra turn when cast in the + * opponent's turn + */ + @Test + public void testEmrakulCastOnOpponentsTurn() { + addCard(Zone.BATTLEFIELD, playerA, "Island", 12); + addCard(Zone.GRAVEYARD, playerA, "Island", 1); + // Emrakul, the Promised End costs {1} less to cast for each card type among cards in your graveyard. + // When you cast Emrakul, you gain control of target opponent during that player's next turn. After that turn, that player takes an extra turn. + // Flying + // Trample + // Protection from instants + addCard(Zone.HAND, playerA, "Emrakul, the Promised End", 1); // {13} + // Flash (You may cast this spell any time you could cast an instant.) + // Creature cards you own that aren't on the battlefield have flash. + // Each opponent can cast spells only any time he or she could cast a sorcery. + addCard(Zone.BATTLEFIELD, playerA, "Teferi, Mage of Zhalfir", 1); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Emrakul, the Promised End"); + + setStopAt(3, PhaseStep.UPKEEP); + execute(); + + assertPermanentCount(playerA, "Emrakul, the Promised End", 1); + + Assert.assertTrue("For extra turn, playerB has to be the active player ", currentGame.getActivePlayerId().equals(playerB.getId())); + } +} diff --git a/Mage.Verify/pom.xml b/Mage.Verify/pom.xml new file mode 100644 index 00000000000..64e0d4c0e9e --- /dev/null +++ b/Mage.Verify/pom.xml @@ -0,0 +1,76 @@ + + + 4.0.0 + + + org.mage + mage-root + 1.4.16 + + + mage-verify + jar + Mage Verify + + + + ${project.groupId} + mage + ${mage-version} + + + ${project.groupId} + mage-sets + ${mage-version} + + + junit + junit + test + + + com.fasterxml.jackson.core + jackson-databind + 2.6.3 + + + + log4j + log4j + jar + + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + -Dfile.encoding=UTF-8 + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + maven-resources-plugin + + UTF-8 + + + + + mage-verify + + + + + diff --git a/Mage.Verify/src/main/java/mage/verify/JsonCard.java b/Mage.Verify/src/main/java/mage/verify/JsonCard.java new file mode 100644 index 00000000000..ac0c0dc0691 --- /dev/null +++ b/Mage.Verify/src/main/java/mage/verify/JsonCard.java @@ -0,0 +1,40 @@ +package mage.verify; + +import java.util.List; + +class JsonCard { + public String layout; + public String name; + public List names; // flip cards + public String manaCost; + public int cmc; + public List colors; + public List colorIdentity; + public String type; + public List supertypes; + public List types; + public List subtypes; + public String text; + public String power; + public String toughness; + public int loyalty; + public String imageName; + public boolean starter; // only available in boxed sets and not in boosters + public int hand; // vanguard + public int life; // vanguard + public String mciNumber; + + // only available in AllSets.json + public String artist; + public String flavor; + public String id; + public int multiverseid; + public String rarity; + public boolean reserved; + public int[] variations; + public String number; + public String releaseDate; // promos + public String border; + public String watermark; + public boolean timeshifted; +} diff --git a/Mage.Verify/src/main/java/mage/verify/JsonSet.java b/Mage.Verify/src/main/java/mage/verify/JsonSet.java new file mode 100644 index 00000000000..4a56a5bd301 --- /dev/null +++ b/Mage.Verify/src/main/java/mage/verify/JsonSet.java @@ -0,0 +1,23 @@ +package mage.verify; + +import java.util.List; +import java.util.Map; + +class JsonSet { + public String name; + public String code; + public String oldCode; + public String gathererCode; + public String magicCardsInfoCode; + public String[] magicRaritiesCodes; + public String releaseDate; + public String border; + public String type; + public List booster; // [String|[String]] + public List cards; + public String block; + public boolean onlineOnly; + public String mkm_id; + public String mkm_name; + public Map translations; +} diff --git a/Mage.Verify/src/main/java/mage/verify/MtgJson.java b/Mage.Verify/src/main/java/mage/verify/MtgJson.java new file mode 100644 index 00000000000..04488fdfe66 --- /dev/null +++ b/Mage.Verify/src/main/java/mage/verify/MtgJson.java @@ -0,0 +1,109 @@ +package mage.verify; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import java.text.Normalizer; +import java.util.HashMap; +import java.util.Map; +import java.util.zip.ZipInputStream; + +public class MtgJson { + private MtgJson() {} + + private static class CardHolder { + private static final Map cards; + static { + try { + cards = loadAllCards(); + addAliases(cards); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + private static class SetHolder { + private static final Map sets; + static { + try { + sets = loadAllSets(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + private static Map loadAllCards() throws IOException { + return readFromZip("AllCards.json.zip", new TypeReference>() {}); + } + + private static Map loadAllSets() throws IOException { + return readFromZip("AllSets.json.zip", new TypeReference>() {}); + } + + private static T readFromZip(String filename, TypeReference ref) throws IOException { + InputStream stream = MtgJson.class.getResourceAsStream(filename); + if (stream == null) { + File file = new File(filename); + if (!file.exists()) { + InputStream download = new URL("http://mtgjson.com/json/" + filename).openStream(); + Files.copy(download, file.toPath(), StandardCopyOption.REPLACE_EXISTING); + System.out.println("Downloaded " + filename + " to " + file.getAbsolutePath()); + } else { + System.out.println("Using " + filename + " from " + file.getAbsolutePath()); + } + stream = new FileInputStream(file); + } + ZipInputStream zipInputStream = new ZipInputStream(stream); + zipInputStream.getNextEntry(); + return new ObjectMapper().readValue(zipInputStream, ref); + } + + public static Map sets() { + return SetHolder.sets; + } + + public static JsonCard card(String name) { + return findReference(CardHolder.cards, name); + } + + private static T findReference(Map reference, String name) { + T ref = reference.get(name); + if (ref == null) { + name = name.replaceFirst("\\bA[Ee]", "Æ"); + ref = reference.get(name); + } + if (ref == null) { + name = name.replace("'", "\""); // for Kongming, "Sleeping Dragon" & Pang Tong, "Young Phoenix" + ref = reference.get(name); + } + return ref; + } + + private static void addAliases(Map reference) { + Map aliases = new HashMap<>(); + for (String name : reference.keySet()) { + String unaccented = stripAccents(name); + if (!name.equals(unaccented)) { + aliases.put(name, unaccented); + } + } + for (Map.Entry mapping : aliases.entrySet()) { + reference.put(mapping.getValue(), reference.get(mapping.getKey())); + } + } + + private static String stripAccents(String str) { + String decomposed = Normalizer.normalize(str, Normalizer.Form.NFKD); + return decomposed.replaceAll("[\\p{InCombiningDiacriticalMarks}]", ""); + } + +} diff --git a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java new file mode 100644 index 00000000000..d2fd8a0d570 --- /dev/null +++ b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java @@ -0,0 +1,232 @@ +package mage.verify; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Paths; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import mage.ObjectColor; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.ExpansionSet; +import mage.cards.Sets; +import mage.cards.SplitCard; +import mage.cards.basiclands.BasicLand; +import mage.constants.CardType; +import org.junit.Assert; +import org.junit.Test; + +public class VerifyCardDataTest { + + // right now this is very noisy, and not useful enough to make any assertions on + private static final boolean CHECK_SOURCE_TOKENS = false; + + public static List allCards() { + Collection sets = Sets.getInstance().values(); + List cards = new ArrayList<>(); + for (ExpansionSet set : sets) { + if (set.isCustomSet()) { + continue; + } + for (ExpansionSet.SetCardInfo setInfo : set.getSetCardInfo()) { + cards.add(CardImpl.createCard(setInfo.getCardClass(), new CardSetInfo(setInfo.getName(), set.getCode(), + setInfo.getCardNumber(), setInfo.getRarity(), setInfo.getGraphicInfo()))); + } + } + return cards; + } + + private void warn(Card card, String message) { + System.out.println("Warning: " + message + " for " + card.getName()); + } + + private void fail(Card card, String category, String message) { + failed++; + System.out.println("Error: (" + category + ") " + message + " for " + card.getName()); + } + + private int failed = 0; + + @Test + public void verifyCards() throws IOException { + for (Card card : allCards()) { + Set tokens = findSourceTokens(card.getClass()); + if (card.isSplitCard()) { + check(((SplitCard) card).getLeftHalfCard(), null); + check(((SplitCard) card).getRightHalfCard(), null); + } else { + check(card, tokens); + } + } + if (failed > 0) { + Assert.fail(failed + " Errors"); + } + } + + private static final Pattern SHORT_JAVA_STRING = Pattern.compile("(?<=\")[A-Z][a-z]+(?=\")"); + + private Set findSourceTokens(Class c) throws IOException { + if (!CHECK_SOURCE_TOKENS || BasicLand.class.isAssignableFrom(c)) { + return null; + } + String path = "../Mage.Sets/src/" + c.getName().replace(".", "/") + ".java"; + try { + String source = new String(Files.readAllBytes(Paths.get(path)), StandardCharsets.UTF_8); + Matcher matcher = SHORT_JAVA_STRING.matcher(source); + Set tokens = new HashSet<>(); + while (matcher.find()) { + tokens.add(matcher.group()); + } + return tokens; + } catch (NoSuchFileException e) { + System.out.println("failed to read " + path); + return null; + } + } + + private void check(Card card, Set tokens) { + JsonCard ref = MtgJson.card(card.getName()); + if (ref == null) { + warn(card, "Missing card reference"); + return; + } + checkAll(card, ref); + if (tokens != null) { + JsonCard ref2 = null; + if (card.isFlipCard()) { + ref2 = MtgJson.card(card.getFlipCardName()); + } + for (String token : tokens) { + if (!(token.equals(card.getName()) + || containsInTypesOrText(ref, token) + || containsInTypesOrText(ref, token.toLowerCase()) + || (ref2 != null && (containsInTypesOrText(ref2, token) || containsInTypesOrText(ref2, token.toLowerCase()))))) { + System.out.println("unexpected token " + token + " in " + card); + } + } + } + } + + private boolean containsInTypesOrText(JsonCard ref, String token) { + return contains(ref.types, token) + || contains(ref.subtypes, token) + || contains(ref.supertypes, token) + || ref.text.contains(token); + } + + private boolean contains(Collection options, String value) { + return options != null && options.contains(value); + } + + private void checkAll(Card card, JsonCard ref) { + checkCost(card, ref); + checkPT(card, ref); + checkSubtypes(card, ref); + checkSupertypes(card, ref); + checkTypes(card, ref); + checkColors(card, ref); + } + + private void checkColors(Card card, JsonCard ref) { + // gatherer is missing the color indicator on one card: + if ("Ulrich, Uncontested Alpha".equals(ref.name)) { + return; + } + Collection expected = ref.colors; + ObjectColor color = card.getColor(null); + if (expected == null) { + expected = Collections.emptyList(); + } + if (expected.size() != color.getColorCount() + || (color.isBlack() && !expected.contains("Black")) + || (color.isBlue() && !expected.contains("Blue")) + || (color.isGreen() && !expected.contains("Green")) + || (color.isRed() && !expected.contains("Red")) + || (color.isWhite() && !expected.contains("White"))) { + fail(card, "colors", color + " != " + expected); + } + } + + private void checkSubtypes(Card card, JsonCard ref) { + Collection expected = ref.subtypes; + if (expected != null && expected.contains("Urza’s")) { + expected = new ArrayList<>(expected); + for (ListIterator it = ((List) expected).listIterator(); it.hasNext();) { + if (it.next().equals("Urza’s")) { + it.set("Urza's"); + } + } + } + if (!eqSet(card.getSubtype(null), expected)) { + fail(card, "subtypes", card.getSubtype(null) + " != " + expected); + } + } + + private void checkSupertypes(Card card, JsonCard ref) { + Collection expected = ref.supertypes; + if (!eqSet(card.getSupertype(), expected)) { + fail(card, "supertypes", card.getSupertype() + " != " + expected); + } + } + + private void checkTypes(Card card, JsonCard ref) { + Collection expected = ref.types; + List type = new ArrayList<>(); + for (CardType cardType : card.getCardType()) { + type.add(cardType.toString()); + } + if (!eqSet(type, expected)) { + fail(card, "types", type + " != " + expected); + } + } + + private static boolean eqSet(Collection a, Collection b) { + if (a == null || a.isEmpty()) { + return b == null || b.isEmpty(); + } + return b != null && a.size() == b.size() && a.containsAll(b); + } + + private void checkPT(Card card, JsonCard ref) { + if (!eqPT(card.getPower().toString(), ref.power) || !eqPT(card.getToughness().toString(), ref.toughness)) { + String pt = card.getPower() + "/" + card.getToughness(); + String expected = ref.power + "/" + ref.toughness; + fail(card, "pt", pt + " != " + expected); + } + } + + private boolean eqPT(String found, String expected) { + if (expected == null) { + return "0".equals(found); + } else { + return found.equals(expected) || expected.contains("*"); + } + } + + private void checkCost(Card card, JsonCard ref) { + String expected = ref.manaCost; + String cost = join(card.getManaCost().getSymbols()); + if ("".equals(cost)) { + cost = null; + } + if (cost != null) { + cost = cost.replaceAll("P\\}", "/P}"); + } + if (!Objects.equals(cost, expected)) { + fail(card, "cost", cost + " != " + expected); + } + } + + private String join(Iterable items) { + StringBuilder result = new StringBuilder(); + for (Object item : items) { + result.append(item); + } + return result.toString(); + } + +} diff --git a/Mage/src/main/java/mage/ObjectColor.java b/Mage/src/main/java/mage/ObjectColor.java index 60827481e64..4c4e1eb01fe 100644 --- a/Mage/src/main/java/mage/ObjectColor.java +++ b/Mage/src/main/java/mage/ObjectColor.java @@ -81,19 +81,20 @@ public class ObjectColor implements Serializable, Copyable, Compara red = color.red; green = color.green; } - + /** * Returns a new color which contains all of the colors of this ObjectColor * in addition to all of the colors of the other ObjectColor. + * * @param other The other ObjectColor to union with * @return A new color which is the union of this and other */ public ObjectColor union(ObjectColor other) { ObjectColor newColor = new ObjectColor(); newColor.white = white | other.white; - newColor.blue = blue | other.blue; + newColor.blue = blue | other.blue; newColor.black = black | other.black; - newColor.red = red | other.red; + newColor.red = red | other.red; newColor.green = green | other.green; return newColor; } @@ -146,6 +147,24 @@ public class ObjectColor implements Serializable, Copyable, Compara this.setWhite(color.isWhite()); } + public void addColor(ObjectColor color) { + if (color.isWhite()) { + setWhite(true); + } + if (color.isBlue()) { + setBlue(true); + } + if (color.isBlack()) { + setBlack(true); + } + if (color.isRed()) { + setRed(true); + } + if (color.isGreen()) { + setGreen(true); + } + } + public boolean isColorless() { return !(hasColor()); } diff --git a/Mage/src/main/java/mage/abilities/AbilityImpl.java b/Mage/src/main/java/mage/abilities/AbilityImpl.java index cf82795eff0..3e4ecc12036 100644 --- a/Mage/src/main/java/mage/abilities/AbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/AbilityImpl.java @@ -328,13 +328,16 @@ public abstract class AbilityImpl implements Ability { if (sourceObject != null && !this.getAbilityType().equals(AbilityType.TRIGGERED)) { // triggered abilities check this already in playerImpl.triggerAbility sourceObject.adjustTargets(this, game); } - // Flashback abilities haven't made the choices the underlying spell might need for targetting. - if (!(this instanceof FlashbackAbility) && getTargets().size() > 0 && getTargets().chooseTargets( - getEffects().get(0).getOutcome(), this.controllerId, this, noMana, game) == false) { - if ((variableManaCost != null || announceString != null) && !game.isSimulation()) { - game.informPlayer(controller, (sourceObject != null ? sourceObject.getIdName() : "") + ": no valid targets with this value of X"); + // Flashback abilities haven't made the choices the underlying spell might need for targeting. + if (!(this instanceof FlashbackAbility) + && getTargets().size() > 0) { + Outcome outcome = getEffects().isEmpty() ? Outcome.Detriment : getEffects().get(0).getOutcome(); + if (getTargets().chooseTargets(outcome, this.controllerId, this, noMana, game) == false) { + if ((variableManaCost != null || announceString != null) && !game.isSimulation()) { + game.informPlayer(controller, (sourceObject != null ? sourceObject.getIdName() : "") + ": no valid targets with this value of X"); + } + return false; // when activation of ability is canceled during target selection } - return false; // when activation of ability is canceled during target selection } } // end modes diff --git a/Mage/src/main/java/mage/abilities/effects/common/AddConditionalManaOfAnyColorEffect.java b/Mage/src/main/java/mage/abilities/effects/common/AddConditionalManaOfAnyColorEffect.java index e0275a85c62..8259edb065d 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/AddConditionalManaOfAnyColorEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/AddConditionalManaOfAnyColorEffect.java @@ -85,10 +85,12 @@ public class AddConditionalManaOfAnyColorEffect extends ManaEffect { int value = amount.calculate(game, source, this); boolean result = false; - ChoiceColor choice = new ChoiceColor(false); + ChoiceColor choice = new ChoiceColor(true); + for (int i = 0; i < value; i++) { - if (!choice.isChosen()) { - if (!controller.choose(outcome, choice, game)) { + while (!choice.isChosen()) { + controller.choose(outcome, choice, game); + if (!controller.isInGame()) { return false; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/LookLibraryAndPickControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/LookLibraryAndPickControllerEffect.java index 33ec7787cc9..aea63e004de 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/LookLibraryAndPickControllerEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/LookLibraryAndPickControllerEffect.java @@ -75,12 +75,33 @@ public class LookLibraryAndPickControllerEffect extends LookLibraryControllerEff this(new StaticValue(numberOfCards), false, new StaticValue(numberToPick), pickFilter, Zone.LIBRARY, false, true, upTo); } + /** + * + * @param numberOfCards + * @param numberToPick + * @param pickFilter + * @param reveal + * @param upTo + * @param targetZonePickedCards + * @param optional + */ public LookLibraryAndPickControllerEffect(int numberOfCards, int numberToPick, FilterCard pickFilter, boolean reveal, boolean upTo, Zone targetZonePickedCards, boolean optional) { this(new StaticValue(numberOfCards), false, new StaticValue(numberToPick), pickFilter, Zone.LIBRARY, false, reveal, upTo, targetZonePickedCards, optional); } + /** + * + * @param numberOfCards + * @param mayShuffleAfter + * @param numberToPick + * @param pickFilter + * @param targetZoneLookedCards + * @param putOnTop + * @param reveal + * @param upTo + */ public LookLibraryAndPickControllerEffect(DynamicValue numberOfCards, boolean mayShuffleAfter, DynamicValue numberToPick, FilterCard pickFilter, Zone targetZoneLookedCards, boolean putOnTop, boolean reveal, boolean upTo) { this(numberOfCards, mayShuffleAfter, numberToPick, pickFilter, targetZoneLookedCards, putOnTop, reveal, upTo, Zone.HAND, false); diff --git a/Mage/src/main/java/mage/abilities/effects/common/ReturnFromGraveyardToBattlefieldTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ReturnFromGraveyardToBattlefieldTargetEffect.java index dd2e2797041..cc449d0cecb 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/ReturnFromGraveyardToBattlefieldTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ReturnFromGraveyardToBattlefieldTargetEffect.java @@ -27,6 +27,8 @@ */ package mage.abilities.effects.common; +import java.util.HashSet; +import java.util.Set; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.Mode; @@ -70,12 +72,14 @@ public class ReturnFromGraveyardToBattlefieldTargetEffect extends OneShotEffect public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { + Set cardsToMove = new HashSet<>(); for (UUID targetId : getTargetPointer().getTargets(game, source)) { Card card = game.getCard(targetId); if (card != null) { - controller.moveCards(card, Zone.BATTLEFIELD, source, game, tapped, false, false, null); + cardsToMove.add(card); } } + controller.moveCards(cardsToMove, Zone.BATTLEFIELD, source, game, tapped, false, false, null); return true; } return false; diff --git a/Mage/src/main/java/mage/abilities/effects/common/counter/RemoveCounterSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/counter/RemoveCounterSourceEffect.java index a371859fc5a..6322b59d121 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/counter/RemoveCounterSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/counter/RemoveCounterSourceEffect.java @@ -57,20 +57,26 @@ public class RemoveCounterSourceEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null && permanent.getCounters(game).getCount(counter.getName()) >= counter.getCount()) { - permanent.removeCounters(counter.getName(), counter.getCount(), game); - if (!game.isSimulation()) { - game.informPlayers("Removed " + counter.getCount() + " " + counter.getName() + " counter from " + permanent.getLogName()); + if (permanent != null) { + int toRemove = Math.min(counter.getCount(), permanent.getCounters(game).getCount(counter.getName())); + if (toRemove > 0) { + permanent.removeCounters(counter.getName(), toRemove, game); + if (!game.isSimulation()) { + game.informPlayers("Removed " + toRemove + " " + counter.getName() + " counter from " + permanent.getLogName()); + } } return true; } Card card = game.getCard(source.getSourceId()); - if (card != null && card.getCounters(game).getCount(counter.getName()) >= counter.getCount()) { - card.removeCounters(counter.getName(), counter.getCount(), game); - if (!game.isSimulation()) { - game.informPlayers("Removed " + counter.getCount() + " " + counter.getName() - + " counter from " + card.getLogName() - + " (" + card.getCounters(game).getCount(counter.getName()) + " left)"); + if (card != null) { + int toRemove = Math.min(counter.getCount(), card.getCounters(game).getCount(counter.getName())); + if (toRemove > 0) { + card.removeCounters(counter.getName(), toRemove, game); + if (!game.isSimulation()) { + game.informPlayers("Removed " + toRemove + " " + counter.getName() + + " counter from " + card.getLogName() + + " (" + card.getCounters(game).getCount(counter.getName()) + " left)"); + } } return true; } diff --git a/Mage/src/main/java/mage/abilities/keyword/CanBlockSpaceflightAbility.java b/Mage/src/main/java/mage/abilities/keyword/CanBlockSpaceflightAbility.java new file mode 100644 index 00000000000..b65edc61292 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/keyword/CanBlockSpaceflightAbility.java @@ -0,0 +1,43 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.abilities.keyword; + +import java.io.ObjectStreamException; +import mage.abilities.MageSingleton; +import mage.abilities.StaticAbility; +import mage.constants.Zone; + +/** + * + * @author LevelX2 + */ +public class CanBlockSpaceflightAbility extends StaticAbility implements MageSingleton { + + private static final CanBlockSpaceflightAbility fINSTANCE = new CanBlockSpaceflightAbility(); + + private Object readResolve() throws ObjectStreamException { + return fINSTANCE; + } + + public static CanBlockSpaceflightAbility getInstance() { + return fINSTANCE; + } + + private CanBlockSpaceflightAbility() { + super(Zone.ALL, null); + } + + @Override + public String getRule() { + return "{this} can block creatures with spaceflight."; + } + + @Override + public CanBlockSpaceflightAbility copy() { + return fINSTANCE; + } + +} diff --git a/Mage/src/main/java/mage/abilities/keyword/SpaceflightAbility.java b/Mage/src/main/java/mage/abilities/keyword/SpaceflightAbility.java index c0e080ad1af..f4a84542c02 100644 --- a/Mage/src/main/java/mage/abilities/keyword/SpaceflightAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/SpaceflightAbility.java @@ -90,7 +90,8 @@ class SpaceFlightEffect extends RestrictionEffect implements MageSingleton { @Override public boolean canBeBlocked(Permanent attacker, Permanent blocker, Ability source, Game game) { - return blocker.getAbilities().containsKey(SpaceflightAbility.getInstance().getId()); + return blocker.getAbilities().containsKey(SpaceflightAbility.getInstance().getId()) + || blocker.getAbilities().containsKey(CanBlockSpaceflightAbility.getInstance().getId()); } @Override diff --git a/Mage/src/main/java/mage/cards/ExpansionSet.java b/Mage/src/main/java/mage/cards/ExpansionSet.java index 4ea414f18bd..8a94962d239 100644 --- a/Mage/src/main/java/mage/cards/ExpansionSet.java +++ b/Mage/src/main/java/mage/cards/ExpansionSet.java @@ -193,8 +193,11 @@ public abstract class ExpansionSet implements Serializable { if (15 > theBooster.size()) { List commons = getCardsByRarity(Rarity.COMMON); - while (15 > theBooster.size()) { + while (15 > theBooster.size() && !commons.isEmpty()) { addToBooster(theBooster, commons); + if (commons.isEmpty()) { + commons = getCardsByRarity(Rarity.COMMON); + } } } diff --git a/Mage/src/main/java/mage/cards/repository/CardRepository.java b/Mage/src/main/java/mage/cards/repository/CardRepository.java index f1108943dd4..35f30921e8c 100644 --- a/Mage/src/main/java/mage/cards/repository/CardRepository.java +++ b/Mage/src/main/java/mage/cards/repository/CardRepository.java @@ -64,7 +64,7 @@ public enum CardRepository { // raise this if db structure was changed private static final long CARD_DB_VERSION = 47; // raise this if new cards were added to the server - private static final long CARD_CONTENT_VERSION = 63; + private static final long CARD_CONTENT_VERSION = 64; private Dao cardDao; private Set classNames; diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index 9fd14a95530..eecb0914418 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -1499,6 +1499,17 @@ public abstract class GameImpl implements Game, Serializable { @Override public void addTriggeredAbility(TriggeredAbility ability) { + if (ability.getControllerId() == null) { + String sourceName = "no sourceId"; + if (ability.getSourceId() != null) { + MageObject mageObject = getObject(ability.getSourceId()); + if (mageObject != null) { + sourceName = mageObject.getName(); + } + } + logger.fatal("Added triggered ability without controller: " + sourceName + " rule: " + ability.getRule()); + return; + } if (ability instanceof TriggeredManaAbility || ability instanceof DelayedTriggeredManaAbility) { // 20110715 - 605.4 Ability manaAbiltiy = ability.copy(); diff --git a/Mage/src/main/java/mage/game/ZonesHandler.java b/Mage/src/main/java/mage/game/ZonesHandler.java index a57df07facd..f78a74e9ee7 100644 --- a/Mage/src/main/java/mage/game/ZonesHandler.java +++ b/Mage/src/main/java/mage/game/ZonesHandler.java @@ -208,6 +208,8 @@ public class ZonesHandler { // If we can't find the card we can't remove it. return false; } + // If needed take attributes from the spell (e.g. color of spell was changed) + card = takeAttributesFromSpell(card, event, game); boolean success = false; if (info.faceDown) { card.setFaceDown(true, game); @@ -282,4 +284,23 @@ public class ZonesHandler { order.add(cards.getCards(game).iterator().next()); return order; } + + private static Card takeAttributesFromSpell(Card card, ZoneChangeEvent event, Game game) { + if (Zone.STACK.equals(event.getFromZone())) { + Spell spell = game.getStack().getSpell(event.getTargetId()); + if (spell != null) { + boolean doCopy = false; + if (!card.getColor(game).equals(spell.getColor(game))) { + doCopy = true; + } + if (doCopy) { + // the card that is referenced to in the permanent is copied and the spell attributes are set to this copied card + card = card.copy(); + card.getColor(game).setColor(spell.getColor(game)); + } + } + } + return card; + } + } diff --git a/Mage/src/main/java/mage/game/permanent/PermanentCard.java b/Mage/src/main/java/mage/game/permanent/PermanentCard.java index 017a5093866..9ff7eb7578a 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentCard.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentCard.java @@ -132,7 +132,7 @@ public class PermanentCard extends PermanentImpl { transformable = card.isTransformable(); if (transformable) { this.nightCard = card.isNightCard(); - if (! this.nightCard) { + if (!this.nightCard) { this.secondSideCard = card.getSecondCardFace(); this.secondSideCardClazz = this.secondSideCard.getClass(); } diff --git a/Mage/src/main/java/mage/game/permanent/PermanentMeld.java b/Mage/src/main/java/mage/game/permanent/PermanentMeld.java index dd28172322b..6cba02c680e 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentMeld.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentMeld.java @@ -27,15 +27,9 @@ */ package mage.game.permanent; -import java.util.ArrayList; import java.util.UUID; import mage.cards.Card; -import mage.cards.CardsImpl; -import mage.cards.MeldCard; -import mage.constants.Zone; import mage.game.Game; -import mage.game.events.ZoneChangeEvent; -import mage.players.Player; /** * diff --git a/Mage/src/main/java/mage/game/stack/Spell.java b/Mage/src/main/java/mage/game/stack/Spell.java index 69dfb83d4be..cc9b47a99e3 100644 --- a/Mage/src/main/java/mage/game/stack/Spell.java +++ b/Mage/src/main/java/mage/game/stack/Spell.java @@ -899,7 +899,7 @@ public class Spell extends StackObjImpl implements Card { @Override public void checkForCountersToAdd(Permanent permanent, Game game) { - throw new UnsupportedOperationException("Not supported for Spell"); + card.checkForCountersToAdd(permanent, game); } @Override diff --git a/Mage/src/main/java/mage/game/turn/TurnMods.java b/Mage/src/main/java/mage/game/turn/TurnMods.java index 932b6f2c366..ee9baa5b38d 100644 --- a/Mage/src/main/java/mage/game/turn/TurnMods.java +++ b/Mage/src/main/java/mage/game/turn/TurnMods.java @@ -1,16 +1,16 @@ /* * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR @@ -20,20 +20,18 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.game.turn; -import mage.constants.PhaseStep; -import mage.constants.TurnPhase; - import java.util.ArrayList; import java.util.ListIterator; import java.util.UUID; +import mage.constants.PhaseStep; +import mage.constants.TurnPhase; /** * @@ -41,10 +39,11 @@ import java.util.UUID; */ public class TurnMods extends ArrayList { - public TurnMods() {} + public TurnMods() { + } public TurnMods(final TurnMods mods) { - for (TurnMod mod: mods) { + for (TurnMod mod : mods) { this.add(mod.copy()); } } @@ -95,7 +94,7 @@ public class TurnMods extends ArrayList { it.remove(); } } - // now delete all other - control next turn effect is not cumulative + // now delete all other effects that control current active player - control next turn of player effects are not cumulative it = this.listIterator(this.size()); while (it.hasPrevious()) { TurnMod turnMod = it.previous(); diff --git a/Mage/src/main/java/mage/target/common/TargetOpponentsChoicePermanent.java b/Mage/src/main/java/mage/target/common/TargetOpponentsChoicePermanent.java index 46b934cd724..8169667f3b4 100644 --- a/Mage/src/main/java/mage/target/common/TargetOpponentsChoicePermanent.java +++ b/Mage/src/main/java/mage/target/common/TargetOpponentsChoicePermanent.java @@ -3,7 +3,6 @@ * To change this template file, choose Tools | Templates * and open the template in the editor. */ - package mage.target.common; import java.util.UUID; @@ -11,6 +10,7 @@ import mage.abilities.Ability; import mage.constants.Outcome; import mage.filter.FilterPermanent; import mage.game.Game; +import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPermanent; @@ -21,20 +21,23 @@ import mage.target.TargetPermanent; public class TargetOpponentsChoicePermanent extends TargetPermanent { protected UUID opponentId = null; + private boolean dontTargetPlayer = false; public TargetOpponentsChoicePermanent(FilterPermanent filter) { super(1, 1, filter, false); this.targetName = filter.getMessage(); } - - public TargetOpponentsChoicePermanent(int minNumTargets, int maxNumTargets, FilterPermanent filter, boolean notTarget) { + + public TargetOpponentsChoicePermanent(int minNumTargets, int maxNumTargets, FilterPermanent filter, boolean notTarget, boolean dontTargetPlayer) { super(minNumTargets, maxNumTargets, filter, notTarget); this.targetName = filter.getMessage(); + this.dontTargetPlayer = dontTargetPlayer; } public TargetOpponentsChoicePermanent(final TargetOpponentsChoicePermanent target) { super(target); this.opponentId = target.opponentId; + this.dontTargetPlayer = target.dontTargetPlayer; } @Override @@ -47,8 +50,22 @@ public class TargetOpponentsChoicePermanent extends TargetPermanent { @Override public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) { + Permanent permanent = game.getPermanent(id); if (opponentId != null) { - return super.canTarget(opponentId, id, source, game); + if (permanent != null) { + if (source != null) { + boolean canSourceControllerTarget = true; + if (!isNotTarget()) { + if (!permanent.canBeTargetedBy(game.getObject(source.getId()), controllerId, game) + || !permanent.canBeTargetedBy(game.getObject(source.getSourceId()), controllerId, game)) { + canSourceControllerTarget = false; + } + } + canSourceControllerTarget &= super.canTarget(opponentId, id, source, game); + canSourceControllerTarget &= filter.match(permanent, source.getSourceId(), opponentId, game); + return canSourceControllerTarget; + } + } } return false; } @@ -65,7 +82,7 @@ public class TargetOpponentsChoicePermanent extends TargetPermanent { private UUID getOpponentId(UUID playerId, Ability source, Game game) { if (opponentId == null) { - TargetOpponent target = new TargetOpponent(); + TargetOpponent target = new TargetOpponent(dontTargetPlayer); Player player = game.getPlayer(playerId); if (player != null) { if (player.chooseTarget(Outcome.Detriment, target, source, game)) { diff --git a/Mage/src/main/java/mage/watchers/common/LifeLossOtherFromCombatWatcher.java b/Mage/src/main/java/mage/watchers/common/LifeLossOtherFromCombatWatcher.java index c409d1a977f..ebf698bdd45 100644 --- a/Mage/src/main/java/mage/watchers/common/LifeLossOtherFromCombatWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/LifeLossOtherFromCombatWatcher.java @@ -50,6 +50,7 @@ public class LifeLossOtherFromCombatWatcher extends Watcher { public LifeLossOtherFromCombatWatcher(final LifeLossOtherFromCombatWatcher watcher) { super(watcher); + this.players.addAll(watcher.players); } @Override diff --git a/pom.xml b/pom.xml index 9c20bd429b2..65e49f22b24 100644 --- a/pom.xml +++ b/pom.xml @@ -61,6 +61,7 @@ Mage.Tests Mage.Updater Mage.Stats + Mage.Verify