diff --git a/Mage.Client/src/main/java/mage/client/MageFrame.java b/Mage.Client/src/main/java/mage/client/MageFrame.java
index c9d69ca85f0..9752b1cd8a8 100644
--- a/Mage.Client/src/main/java/mage/client/MageFrame.java
+++ b/Mage.Client/src/main/java/mage/client/MageFrame.java
@@ -27,16 +27,20 @@
*/
package mage.client;
+import java.awt.AWTEvent;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
+import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.SplashScreen;
+import java.awt.Toolkit;
+import java.awt.event.AWTEventListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
@@ -225,6 +229,26 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
return instance;
}
+ private void handleEvent(AWTEvent event) {
+ MagePane frame = activeFrame;
+
+ // support multiple mage panes
+ Object source = event.getSource();
+ if(source instanceof Component) {
+ Component component = (Component)source;
+ while(component != null) {
+ if(component instanceof MagePane) {
+ frame = (MagePane)component;
+ break;
+ }
+ component = component.getParent();
+ }
+ }
+
+ if(frame != null)
+ frame.handleEvent(event);
+ }
+
/**
* Creates new form MageFrame
*/
@@ -240,6 +264,13 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
}
});
+ Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
+ @Override
+ public void eventDispatched(AWTEvent event) {
+ handleEvent(event);
+ }
+ }, AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK);
+
TConfig config = TConfig.current();
config.setArchiveDetector(new TArchiveDetector("zip"));
config.setAccessPreference(FsAccessOption.STORE, true);
diff --git a/Mage.Client/src/main/java/mage/client/MagePane.java b/Mage.Client/src/main/java/mage/client/MagePane.java
index 8ddadc66953..b4a4d474d6e 100644
--- a/Mage.Client/src/main/java/mage/client/MagePane.java
+++ b/Mage.Client/src/main/java/mage/client/MagePane.java
@@ -33,6 +33,7 @@
*/
package mage.client;
+import java.awt.AWTEvent;
import java.awt.KeyboardFocusManager;
import java.beans.PropertyVetoException;
import javax.swing.plaf.basic.BasicInternalFrameUI;
@@ -91,6 +92,9 @@ public abstract class MagePane extends javax.swing.JInternalFrame {
}
+ public void handleEvent(AWTEvent event) {
+ }
+
/**
* 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
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 87d1b0beb74..03ed4e96b4b 100644
--- a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form
+++ b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form
@@ -31,7 +31,7 @@
-
+
@@ -122,7 +122,7 @@
-
+
@@ -1719,7 +1719,7 @@
-
+
@@ -1744,11 +1744,11 @@
-
+
-
-
+
+
@@ -1756,6 +1756,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1902,7 +1939,7 @@
-
+
@@ -2409,11 +2446,11 @@
-
-
+
+
-
+
@@ -2504,11 +2541,11 @@
-
-
+
+
-
+
@@ -2536,7 +2573,7 @@
-
+
@@ -2549,7 +2586,7 @@
-
+
@@ -2601,11 +2638,11 @@
-
-
+
+
-
+
@@ -2633,7 +2670,7 @@
-
+
@@ -2646,7 +2683,7 @@
-
+
@@ -2696,11 +2733,11 @@
-
-
+
+
-
+
@@ -2728,7 +2765,7 @@
-
+
@@ -2793,11 +2830,11 @@
-
-
+
+
-
+
@@ -2825,7 +2862,7 @@
-
+
@@ -2888,11 +2925,11 @@
-
-
+
+
-
+
@@ -2920,7 +2957,7 @@
-
+
@@ -2985,11 +3022,11 @@
-
-
+
+
-
+
@@ -3017,7 +3054,7 @@
-
+
@@ -3080,7 +3117,199 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -3088,7 +3317,7 @@
-
+
@@ -3096,7 +3325,7 @@
-
+
@@ -3105,16 +3334,16 @@
-
+
-
+
-
+
@@ -3124,12 +3353,12 @@
-
+
-
+
@@ -3139,12 +3368,12 @@
-
+
-
+
@@ -3154,12 +3383,12 @@
-
+
-
+
@@ -3169,7 +3398,7 @@
-
+
@@ -3181,11 +3410,11 @@
-
+
-
+
@@ -3194,16 +3423,16 @@
-
+
-
+
-
+
@@ -3211,12 +3440,12 @@
-
+
-
+
@@ -3224,12 +3453,12 @@
-
+
-
+
@@ -3237,12 +3466,12 @@
-
+
-
+
@@ -3250,17 +3479,17 @@
-
+
-
+
-
+
@@ -3269,16 +3498,16 @@
-
+
-
+
-
+
@@ -3286,12 +3515,12 @@
-
+
-
+
@@ -3299,12 +3528,12 @@
-
+
-
+
@@ -3312,12 +3541,12 @@
-
+
-
+
@@ -3325,13 +3554,13 @@
-
+
-
+
@@ -4172,7 +4401,7 @@
-
+
@@ -5028,9 +5257,9 @@
-
+
-
+
@@ -5039,7 +5268,7 @@
-
+
@@ -5047,7 +5276,7 @@
-
+
@@ -5061,6 +5290,83 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -5230,83 +5536,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
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 ccc197fc18a..a949990fc88 100644
--- a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java
+++ b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java
@@ -104,7 +104,8 @@ public class PreferencesDialog extends javax.swing.JDialog {
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_SIZE = "guiCardBattlefield";
+ 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";
@@ -245,7 +246,6 @@ public class PreferencesDialog extends javax.swing.JDialog {
public static final String KEY_NEW_DECK_GENERATOR_LAND_PERCENTAGE = "newDeckGeneratorLandPercentage";
public static final String KEY_NEW_DECK_GENERATOR_ADVANCED_CMC = "newDeckGeneratorAdvancedCMC";
-
// used to save and restore the settings for the cardArea (draft, sideboarding, deck builder)
public static final String KEY_DRAFT_VIEW = "draftView";
@@ -396,8 +396,10 @@ public class PreferencesDialog extends javax.swing.JDialog {
labelCardSizeHand = new javax.swing.JLabel();
sliderCardSizeOtherZones = new javax.swing.JSlider();
labelCardSizeOtherZones = new javax.swing.JLabel();
- sliderCardSizeBattlefield = new javax.swing.JSlider();
- labelCardSizeBattlefield = new javax.swing.JLabel();
+ sliderCardSizeMinBattlefield = new javax.swing.JSlider();
+ labelCardSizeMinBattlefield = new javax.swing.JLabel();
+ sliderCardSizeMaxBattlefield = new javax.swing.JSlider();
+ labelCardSizeMaxBattlefield = new javax.swing.JLabel();
sliderStackWidth = new javax.swing.JSlider();
labelStackWidth = new javax.swing.JLabel();
sliderGameFeedbackArea = new javax.swing.JSlider();
@@ -495,6 +497,10 @@ public class PreferencesDialog extends javax.swing.JDialog {
jPanel32 = new javax.swing.JPanel();
jPanel33 = new javax.swing.JPanel();
tabConnection = new javax.swing.JPanel();
+ connection_servers = new javax.swing.JPanel();
+ lblURLServerList = new javax.swing.JLabel();
+ txtURLServerList = new javax.swing.JTextField();
+ jLabel17 = new javax.swing.JLabel();
lblProxyType = new javax.swing.JLabel();
cbProxyType = new javax.swing.JComboBox<>();
pnlProxySettings = new javax.swing.JPanel();
@@ -509,10 +515,6 @@ public class PreferencesDialog extends javax.swing.JDialog {
txtPasswordField = new javax.swing.JPasswordField();
rememberPswd = new javax.swing.JCheckBox();
jLabel11 = new javax.swing.JLabel();
- connection_servers = new javax.swing.JPanel();
- lblURLServerList = new javax.swing.JLabel();
- txtURLServerList = new javax.swing.JTextField();
- jLabel17 = new javax.swing.JLabel();
saveButton = new javax.swing.JButton();
exitButton = new javax.swing.JButton();
@@ -557,7 +559,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
.add(tooltipDelayLabel, org.jdesktop.layout.GroupLayout.DEFAULT_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(183, Short.MAX_VALUE))
+ .addContainerGap(233, Short.MAX_VALUE))
);
main_cardLayout.setVerticalGroup(
main_cardLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
@@ -917,7 +919,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
guiSizeGame.setMinimumSize(new java.awt.Dimension(600, 180));
guiSizeGame.setPreferredSize(new java.awt.Dimension(600, 180));
java.awt.GridBagLayout guiSizeGameLayout = new java.awt.GridBagLayout();
- guiSizeGameLayout.columnWeights = new double[] {1.0, 1.0, 1.0};
+ guiSizeGameLayout.columnWeights = new double[] {1.0, 1.0, 1.0, 1.0};
guiSizeGameLayout.rowWeights = new double[] {1.0, 0.2, 1.0, 0.2};
guiSizeGame.setLayout(guiSizeGameLayout);
@@ -980,34 +982,63 @@ public class PreferencesDialog extends javax.swing.JDialog {
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
guiSizeGame.add(labelCardSizeOtherZones, gridBagConstraints);
- sliderCardSizeBattlefield.setMajorTickSpacing(5);
- sliderCardSizeBattlefield.setMaximum(50);
- sliderCardSizeBattlefield.setMinimum(10);
- sliderCardSizeBattlefield.setMinorTickSpacing(1);
- sliderCardSizeBattlefield.setPaintLabels(true);
- sliderCardSizeBattlefield.setPaintTicks(true);
- sliderCardSizeBattlefield.setSnapToTicks(true);
- sliderCardSizeBattlefield.setToolTipText("The maximum size of permanents on the battlefield");
- sliderCardSizeBattlefield.setBorder(javax.swing.BorderFactory.createEtchedBorder());
- sliderCardSizeBattlefield.setMinimumSize(new java.awt.Dimension(150, 40));
+ sliderCardSizeMinBattlefield.setMajorTickSpacing(5);
+ sliderCardSizeMinBattlefield.setMaximum(50);
+ sliderCardSizeMinBattlefield.setMinimum(10);
+ sliderCardSizeMinBattlefield.setMinorTickSpacing(1);
+ sliderCardSizeMinBattlefield.setPaintLabels(true);
+ sliderCardSizeMinBattlefield.setPaintTicks(true);
+ sliderCardSizeMinBattlefield.setSnapToTicks(true);
+ sliderCardSizeMinBattlefield.setToolTipText("The maximum size of permanents on the battlefield");
+ sliderCardSizeMinBattlefield.setBorder(javax.swing.BorderFactory.createEtchedBorder());
+ sliderCardSizeMinBattlefield.setMinimumSize(new java.awt.Dimension(150, 40));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 0;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
- guiSizeGame.add(sliderCardSizeBattlefield, gridBagConstraints);
+ guiSizeGame.add(sliderCardSizeMinBattlefield, gridBagConstraints);
- labelCardSizeBattlefield.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
- labelCardSizeBattlefield.setText("Permanents");
- labelCardSizeBattlefield.setToolTipText("The maximum size of permanents on the battlefield");
+ labelCardSizeMinBattlefield.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
+ labelCardSizeMinBattlefield.setText("Permanents min size");
+ labelCardSizeMinBattlefield.setToolTipText("The minimum size of permanents on the battlefield");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 1;
gridBagConstraints.ipadx = 3;
gridBagConstraints.ipady = 3;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
- guiSizeGame.add(labelCardSizeBattlefield, gridBagConstraints);
+ guiSizeGame.add(labelCardSizeMinBattlefield, gridBagConstraints);
+
+ sliderCardSizeMaxBattlefield.setMajorTickSpacing(5);
+ sliderCardSizeMaxBattlefield.setMaximum(50);
+ sliderCardSizeMaxBattlefield.setMinimum(10);
+ sliderCardSizeMaxBattlefield.setMinorTickSpacing(1);
+ sliderCardSizeMaxBattlefield.setPaintLabels(true);
+ sliderCardSizeMaxBattlefield.setPaintTicks(true);
+ sliderCardSizeMaxBattlefield.setSnapToTicks(true);
+ sliderCardSizeMaxBattlefield.setToolTipText("The maximum size of permanents on the battlefield");
+ sliderCardSizeMaxBattlefield.setBorder(javax.swing.BorderFactory.createEtchedBorder());
+ sliderCardSizeMaxBattlefield.setMinimumSize(new java.awt.Dimension(150, 40));
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 3;
+ gridBagConstraints.gridy = 0;
+ gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
+ gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
+ guiSizeGame.add(sliderCardSizeMaxBattlefield, gridBagConstraints);
+
+ labelCardSizeMaxBattlefield.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
+ labelCardSizeMaxBattlefield.setText("Permanents max size");
+ labelCardSizeMaxBattlefield.setToolTipText("The maximum size of permanents on the battlefield");
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 3;
+ gridBagConstraints.gridy = 1;
+ gridBagConstraints.ipadx = 3;
+ gridBagConstraints.ipady = 3;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
+ guiSizeGame.add(labelCardSizeMaxBattlefield, gridBagConstraints);
sliderStackWidth.setMajorTickSpacing(20);
sliderStackWidth.setMaximum(90);
@@ -2099,7 +2130,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
tabAvatarsLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(tabAvatarsLayout.createSequentialGroup()
.add(avatarPane, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 528, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
- .add(0, 1, Short.MAX_VALUE))
+ .add(0, 0, Short.MAX_VALUE))
);
tabAvatarsLayout.setVerticalGroup(
tabAvatarsLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
@@ -2110,6 +2141,47 @@ public class PreferencesDialog extends javax.swing.JDialog {
tabsPanel.addTab("Avatars", tabAvatars);
+ connection_servers.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Servers"));
+
+ lblURLServerList.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
+ lblURLServerList.setText("URL server list:");
+ lblURLServerList.setToolTipText("");
+ lblURLServerList.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING);
+ lblURLServerList.setPreferredSize(new java.awt.Dimension(110, 16));
+ lblURLServerList.setVerticalTextPosition(javax.swing.SwingConstants.TOP);
+
+ txtURLServerList.setToolTipText("The URL XMage tries to read a server list from.");
+ txtURLServerList.setPreferredSize(new java.awt.Dimension(300, 22));
+
+ jLabel17.setFont(new java.awt.Font("Tahoma", 2, 10)); // NOI18N
+ jLabel17.setText("e.g.: http://XMage.de/files/server-list.txt");
+
+ org.jdesktop.layout.GroupLayout connection_serversLayout = new org.jdesktop.layout.GroupLayout(connection_servers);
+ connection_servers.setLayout(connection_serversLayout);
+ connection_serversLayout.setHorizontalGroup(
+ connection_serversLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+ .add(connection_serversLayout.createSequentialGroup()
+ .add(connection_serversLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+ .add(connection_serversLayout.createSequentialGroup()
+ .addContainerGap()
+ .add(lblURLServerList, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 96, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
+ .add(txtURLServerList, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 370, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
+ .add(connection_serversLayout.createSequentialGroup()
+ .add(141, 141, 141)
+ .add(jLabel17)))
+ .addContainerGap(67, Short.MAX_VALUE))
+ );
+ connection_serversLayout.setVerticalGroup(
+ connection_serversLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+ .add(connection_serversLayout.createSequentialGroup()
+ .add(connection_serversLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
+ .add(lblURLServerList, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .add(txtURLServerList, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
+ .add(jLabel17))
+ );
+
lblProxyType.setText("Proxy:");
cbProxyType.addActionListener(new java.awt.event.ActionListener() {
@@ -2219,67 +2291,26 @@ public class PreferencesDialog extends javax.swing.JDialog {
.addContainerGap())
);
- connection_servers.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Servers"));
-
- lblURLServerList.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
- lblURLServerList.setText("URL server list:");
- lblURLServerList.setToolTipText("");
- lblURLServerList.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING);
- lblURLServerList.setPreferredSize(new java.awt.Dimension(110, 16));
- lblURLServerList.setVerticalTextPosition(javax.swing.SwingConstants.TOP);
-
- txtURLServerList.setToolTipText("The URL XMage tries to read a server list from.");
- txtURLServerList.setPreferredSize(new java.awt.Dimension(300, 22));
-
- jLabel17.setFont(new java.awt.Font("Tahoma", 2, 10)); // NOI18N
- jLabel17.setText("e.g.: http://XMage.de/files/server-list.txt");
-
- org.jdesktop.layout.GroupLayout connection_serversLayout = new org.jdesktop.layout.GroupLayout(connection_servers);
- connection_servers.setLayout(connection_serversLayout);
- connection_serversLayout.setHorizontalGroup(
- connection_serversLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
- .add(connection_serversLayout.createSequentialGroup()
- .add(connection_serversLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
- .add(connection_serversLayout.createSequentialGroup()
- .addContainerGap()
- .add(lblURLServerList, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 96, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
- .add(txtURLServerList, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 370, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
- .add(connection_serversLayout.createSequentialGroup()
- .add(141, 141, 141)
- .add(jLabel17)))
- .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
- );
- connection_serversLayout.setVerticalGroup(
- connection_serversLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
- .add(connection_serversLayout.createSequentialGroup()
- .add(connection_serversLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
- .add(lblURLServerList, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
- .add(txtURLServerList, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
- .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
- .add(jLabel17))
- );
-
org.jdesktop.layout.GroupLayout tabConnectionLayout = new org.jdesktop.layout.GroupLayout(tabConnection);
tabConnection.setLayout(tabConnectionLayout);
tabConnectionLayout.setHorizontalGroup(
tabConnectionLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
- .add(tabConnectionLayout.createSequentialGroup()
+ .add(org.jdesktop.layout.GroupLayout.TRAILING, tabConnectionLayout.createSequentialGroup()
.addContainerGap()
- .add(tabConnectionLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false)
+ .add(tabConnectionLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
.add(pnlProxySettings, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(org.jdesktop.layout.GroupLayout.LEADING, tabConnectionLayout.createSequentialGroup()
.add(lblProxyType)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
.add(cbProxyType, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 126, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
.add(connection_servers, 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))
+ .addContainerGap())
);
tabConnectionLayout.setVerticalGroup(
tabConnectionLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(tabConnectionLayout.createSequentialGroup()
.addContainerGap()
- .add(connection_servers, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
+ .add(connection_servers, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(tabConnectionLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(lblProxyType)
@@ -2325,7 +2356,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(exitButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 100, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.add(6, 6, 6))
- .add(tabsPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 535, Short.MAX_VALUE)
+ .add(tabsPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 584, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
@@ -2399,8 +2430,12 @@ public class PreferencesDialog extends javax.swing.JDialog {
save(prefs, dialog.sliderCardSizeOtherZones, KEY_GUI_CARD_OTHER_ZONES_SIZE, "true", "false", UPDATE_CACHE_POLICY);
sizeGUIChanged = true;
}
- if (getCachedValue(KEY_GUI_CARD_BATTLEFIELD_SIZE, 14) != dialog.sliderCardSizeBattlefield.getValue()) {
- save(prefs, dialog.sliderCardSizeBattlefield, KEY_GUI_CARD_BATTLEFIELD_SIZE, "true", "false", UPDATE_CACHE_POLICY);
+ 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) {
@@ -2892,7 +2927,8 @@ public class PreferencesDialog extends javax.swing.JDialog {
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.sliderCardSizeBattlefield, KEY_GUI_CARD_BATTLEFIELD_SIZE, "14");
+ load(prefs, dialog.sliderCardSizeMinBattlefield, KEY_GUI_CARD_BATTLEFIELD_MIN_SIZE, "10");
+ load(prefs, dialog.sliderCardSizeMaxBattlefield, KEY_GUI_CARD_BATTLEFIELD_MAX_SIZE, "14");
}
private static void loadImagesSettings(Preferences prefs) {
@@ -3278,7 +3314,6 @@ public class PreferencesDialog extends javax.swing.JDialog {
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")
-
);
}
@@ -3374,8 +3409,9 @@ public class PreferencesDialog extends javax.swing.JDialog {
private javax.swing.JPanel jPanel31;
private javax.swing.JPanel jPanel32;
private javax.swing.JPanel jPanel33;
- private javax.swing.JLabel labelCardSizeBattlefield;
private javax.swing.JLabel labelCardSizeHand;
+ private javax.swing.JLabel labelCardSizeMaxBattlefield;
+ private javax.swing.JLabel labelCardSizeMinBattlefield;
private javax.swing.JLabel labelCardSizeOtherZones;
private javax.swing.JLabel labelDialogFont;
private javax.swing.JLabel labelEditorCardOffset;
@@ -3404,8 +3440,9 @@ public class PreferencesDialog extends javax.swing.JDialog {
private javax.swing.JCheckBox showAbilityPickerForced;
private javax.swing.JCheckBox showCardName;
private javax.swing.JCheckBox showPlayerNamesPermanently;
- private javax.swing.JSlider sliderCardSizeBattlefield;
private javax.swing.JSlider sliderCardSizeHand;
+ private javax.swing.JSlider sliderCardSizeMaxBattlefield;
+ private javax.swing.JSlider sliderCardSizeMinBattlefield;
private javax.swing.JSlider sliderCardSizeOtherZones;
private javax.swing.JSlider sliderChatFontSize;
private javax.swing.JSlider sliderDialogFont;
diff --git a/Mage.Client/src/main/java/mage/client/game/BattlefieldPanel.java b/Mage.Client/src/main/java/mage/client/game/BattlefieldPanel.java
index 14659169f15..e23e22887e0 100644
--- a/Mage.Client/src/main/java/mage/client/game/BattlefieldPanel.java
+++ b/Mage.Client/src/main/java/mage/client/game/BattlefieldPanel.java
@@ -128,7 +128,7 @@ public class BattlefieldPanel extends javax.swing.JLayeredPane {
private void setGUISize() {
jScrollPane.getVerticalScrollBar().setPreferredSize(new Dimension(GUISizeHelper.scrollBarSize, 0));
jScrollPane.getHorizontalScrollBar().setPreferredSize(new Dimension(0, GUISizeHelper.scrollBarSize));
- cardDimension = GUISizeHelper.battlefieldCardDimension;
+ cardDimension = GUISizeHelper.battlefieldCardMaxDimension;
}
public void update(Map battlefield) {
diff --git a/Mage.Client/src/main/java/mage/client/game/GamePane.java b/Mage.Client/src/main/java/mage/client/game/GamePane.java
index 06e86103cf3..b0c445fdfa1 100644
--- a/Mage.Client/src/main/java/mage/client/game/GamePane.java
+++ b/Mage.Client/src/main/java/mage/client/game/GamePane.java
@@ -33,6 +33,7 @@
*/
package mage.client.game;
+import java.awt.AWTEvent;
import java.util.UUID;
import javax.swing.SwingUtilities;
import mage.client.MagePane;
@@ -132,8 +133,12 @@ public class GamePane extends MagePane {
gamePanel.activated();
}
+ @Override
+ public void handleEvent(AWTEvent event) {
+ gamePanel.handleEvent(event);
+ }
+
private mage.client.game.GamePanel gamePanel;
private javax.swing.JScrollPane jScrollPane1;
private UUID gameId;
-
}
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 2b424627a2e..a7ab2aad802 100644
--- a/Mage.Client/src/main/java/mage/client/game/GamePanel.java
+++ b/Mage.Client/src/main/java/mage/client/game/GamePanel.java
@@ -27,6 +27,7 @@
*/
package mage.client.game;
+import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
@@ -391,6 +392,7 @@ public final class GamePanel extends javax.swing.JPanel {
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;
@@ -589,7 +591,8 @@ public final class GamePanel extends javax.swing.JPanel {
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")
+ PreferencesDialog.getCachedValue(KEY_USE_FIRST_MANA_ABILITY, "false").equals("true"),
+ holdingPriority
);
updateGame(game);
@@ -957,9 +960,9 @@ public final class GamePanel extends javax.swing.JPanel {
* @param manaPoolAutomaticRestricted
* @param useFirstManaAbility
*/
- public void setMenuStates(boolean manaPoolAutomatic, boolean manaPoolAutomaticRestricted, boolean useFirstManaAbility) {
+ public void setMenuStates(boolean manaPoolAutomatic, boolean manaPoolAutomaticRestricted, boolean useFirstManaAbility, boolean holdPriority) {
for (PlayAreaPanel playAreaPanel : players.values()) {
- playAreaPanel.setMenuStates(manaPoolAutomatic, manaPoolAutomaticRestricted, useFirstManaAbility);
+ playAreaPanel.setMenuStates(manaPoolAutomatic, manaPoolAutomaticRestricted, useFirstManaAbility, holdPriority);
}
}
@@ -1201,6 +1204,14 @@ public final class GamePanel extends javax.swing.JPanel {
}
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()) {
@@ -1340,6 +1351,14 @@ public final class GamePanel extends javax.swing.JPanel {
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
@@ -1670,7 +1689,8 @@ public final class GamePanel extends javax.swing.JPanel {
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"));
+ PreferencesDialog.getCachedValue(KEY_USE_FIRST_MANA_ABILITY, "false").equals("true"),
+ holdingPriority);
}
});
@@ -1713,7 +1733,8 @@ public final class GamePanel extends javax.swing.JPanel {
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"));
+ PreferencesDialog.getCachedValue(KEY_USE_FIRST_MANA_ABILITY, "false").equals("true"),
+ holdingPriority);
}
});
@@ -1829,6 +1850,7 @@ public final class GamePanel extends javax.swing.JPanel {
.addComponent(btnSkipToEndStepBeforeYourTurn)
)
.addGroup(gl_pnlShortCuts.createSequentialGroup()
+ .addComponent(txtHoldPriority)
.addComponent(txtSpellsCast)
.addComponent(btnSwitchHands)
.addComponent(btnCancelSkip)
@@ -1862,6 +1884,7 @@ public final class GamePanel extends javax.swing.JPanel {
.addComponent(btnSkipToEndStepBeforeYourTurn)
)
.addGroup(gl_pnlShortCuts.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(txtHoldPriority)
.addComponent(txtSpellsCast)
.addComponent(btnSwitchHands)
.addComponent(btnCancelSkip)
@@ -2343,6 +2366,48 @@ public final class GamePanel extends javax.swing.JPanel {
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;
+
+ 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)
+ session.sendPlayerAction(PlayerAction.HOLD_PRIORITY, gameId, null);
+ else
+ session.sendPlayerAction(PlayerAction.UNHOLD_PRIORITY, gameId, null);
+ }
+ }
+
+ private boolean holdingPriority;
private mage.client.components.ability.AbilityPicker abilityPicker;
private mage.client.cards.BigCard bigCard;
@@ -2397,6 +2462,7 @@ public final class GamePanel extends javax.swing.JPanel {
private JPanel jPhases;
private JPanel phasesContainer;
private javax.swing.JLabel txtSpellsCast;
+ private javax.swing.JLabel txtHoldPriority;
private HoverButton currentStep;
private Point prevPoint;
diff --git a/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java b/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java
index e7ad6fff293..9568d51b13c 100644
--- a/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java
+++ b/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java
@@ -78,6 +78,7 @@ public class PlayAreaPanel extends javax.swing.JPanel {
private JCheckBoxMenuItem manaPoolMenuItem2;
private JCheckBoxMenuItem useFirstManaAbilityItem;
private JCheckBoxMenuItem allowViewHandCardsMenuItem;
+ private JCheckBoxMenuItem holdPriorityMenuItem;
public static final int PANEL_HEIGHT = 242;
public static final int PANEL_HEIGHT_SMALL = 190;
@@ -210,6 +211,19 @@ public class PlayAreaPanel extends javax.swing.JPanel {
popupMenu.add(menuItem);
menuItem.addActionListener(skipListener);
+ holdPriorityMenuItem = new JCheckBoxMenuItem("" + (System.getProperty("os.name").contains("Mac OS X") ? "Cmd" : "Ctrl") + "+click - Hold Priority");
+ holdPriorityMenuItem.setMnemonic(KeyEvent.VK_P);
+ holdPriorityMenuItem.setToolTipText("Hold priority after casting a spell or activating an ability, instead of automatically passing priority.");
+ popupMenu.add(holdPriorityMenuItem);
+ holdPriorityMenuItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ boolean holdPriority = ((JCheckBoxMenuItem)e.getSource()).getState();
+ gamePanel.setMenuStates(manaPoolMenuItem1.getState(), manaPoolMenuItem2.getState(), useFirstManaAbilityItem.getState(), holdPriority);
+ gamePanel.holdPriority(holdPriority);
+ }
+ });
+
JMenu skipMenu = new JMenu("Skip");
skipMenu.setMnemonic(KeyEvent.VK_S);
popupMenu.add(skipMenu);
@@ -277,7 +291,7 @@ public class PlayAreaPanel extends javax.swing.JPanel {
public void actionPerformed(ActionEvent e) {
boolean manaPoolAutomatic = ((JCheckBoxMenuItem) e.getSource()).getState();
PreferencesDialog.saveValue(KEY_GAME_MANA_AUTOPAYMENT, manaPoolAutomatic ? "true" : "false");
- gamePanel.setMenuStates(manaPoolAutomatic, manaPoolMenuItem2.getState(), useFirstManaAbilityItem.getState());
+ gamePanel.setMenuStates(manaPoolAutomatic, manaPoolMenuItem2.getState(), useFirstManaAbilityItem.getState(), holdPriorityMenuItem.getState());
gamePanel.getSession().sendPlayerAction(manaPoolAutomatic ? PlayerAction.MANA_AUTO_PAYMENT_ON : PlayerAction.MANA_AUTO_PAYMENT_OFF, gameId, null);
}
});
@@ -295,7 +309,7 @@ public class PlayAreaPanel extends javax.swing.JPanel {
public void actionPerformed(ActionEvent e) {
boolean manaPoolAutomaticRestricted = ((JCheckBoxMenuItem) e.getSource()).getState();
PreferencesDialog.saveValue(KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE, manaPoolAutomaticRestricted ? "true" : "false");
- gamePanel.setMenuStates(manaPoolMenuItem1.getState(), manaPoolAutomaticRestricted, useFirstManaAbilityItem.getState());
+ gamePanel.setMenuStates(manaPoolMenuItem1.getState(), manaPoolAutomaticRestricted, useFirstManaAbilityItem.getState(), holdPriorityMenuItem.getState());
gamePanel.getSession().sendPlayerAction(manaPoolAutomaticRestricted ? PlayerAction.MANA_AUTO_PAYMENT_RESTRICTED_ON : PlayerAction.MANA_AUTO_PAYMENT_RESTRICTED_OFF, gameId, null);
}
});
@@ -313,7 +327,7 @@ public class PlayAreaPanel extends javax.swing.JPanel {
public void actionPerformed(ActionEvent e) {
boolean useFirstManaAbility = ((JCheckBoxMenuItem) e.getSource()).getState();
PreferencesDialog.saveValue(KEY_USE_FIRST_MANA_ABILITY, useFirstManaAbility ? "true" : "false");
- gamePanel.setMenuStates(manaPoolMenuItem1.getState(), manaPoolMenuItem2.getState(), useFirstManaAbility);
+ gamePanel.setMenuStates(manaPoolMenuItem1.getState(), manaPoolMenuItem2.getState(), useFirstManaAbility, holdPriorityMenuItem.getState());
gamePanel.getSession().sendPlayerAction(useFirstManaAbility ? PlayerAction.USE_FIRST_MANA_ABILITY_ON: PlayerAction.USE_FIRST_MANA_ABILITY_OFF, gameId, null);
}
});
@@ -642,7 +656,7 @@ public class PlayAreaPanel extends javax.swing.JPanel {
this.playingMode = playingMode;
}
- public void setMenuStates(boolean manaPoolAutomatic, boolean manaPoolAutomaticRestricted, boolean useFirstManaAbility) {
+ public void setMenuStates(boolean manaPoolAutomatic, boolean manaPoolAutomaticRestricted, boolean useFirstManaAbility, boolean holdPriority) {
if (manaPoolMenuItem1 != null) {
manaPoolMenuItem1.setSelected(manaPoolAutomatic);
}
@@ -652,6 +666,9 @@ public class PlayAreaPanel extends javax.swing.JPanel {
if (useFirstManaAbilityItem != null) {
useFirstManaAbilityItem.setSelected(useFirstManaAbility);
}
+ if (holdPriorityMenuItem != null) {
+ holdPriorityMenuItem.setSelected(holdPriority);
+ }
}
private mage.client.game.BattlefieldPanel battlefieldPanel;
diff --git a/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java b/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java
index 326d3a3d59b..18bdfa651e7 100644
--- a/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java
+++ b/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java
@@ -395,7 +395,8 @@ public class CallbackClientImpl implements CallbackClient {
.append("
F7 - Skip to next main phase but stop on declare attackers/blockers and something on the stack")
.append("
F9 - Skip everything until your next turn")
.append("
F11 - Skip everything until the end step just prior to your turn")
- .append("
F3 - Undo F4/F5/F7/F9/F11").toString(),
+ .append("
F3 - Undo F4/F5/F7/F9/F11")
+ .append("
").append(System.getProperty("os.name").contains("Mac OS X") ? "Cmd" : "Ctrl").append(" + click - Hold priority while casting a spell or activating an ability").toString(),
null, MessageType.USER_INFO, ChatMessage.MessageColor.BLUE);
break;
case TOURNAMENT:
diff --git a/Mage.Client/src/main/java/mage/client/util/GUISizeHelper.java b/Mage.Client/src/main/java/mage/client/util/GUISizeHelper.java
index 688a3b5dc1a..b41a55944ab 100644
--- a/Mage.Client/src/main/java/mage/client/util/GUISizeHelper.java
+++ b/Mage.Client/src/main/java/mage/client/util/GUISizeHelper.java
@@ -69,7 +69,8 @@ public class GUISizeHelper {
public static Dimension otherZonesCardDimension;
public static int otherZonesCardVerticalOffset;
- public static Dimension battlefieldCardDimension;
+ public static Dimension battlefieldCardMinDimension;
+ public static Dimension battlefieldCardMaxDimension;
public static Dimension editorCardDimension;
public static int editorCardOffsetSize;
@@ -144,8 +145,10 @@ public class GUISizeHelper {
otherZonesCardVerticalOffset = otherZonesCardDimension.height / 10;
}
- int battlefieldCardSize = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GUI_CARD_BATTLEFIELD_SIZE, 14);
- battlefieldCardDimension = new Dimension(CARD_IMAGE_WIDTH * battlefieldCardSize / 42, CARD_IMAGE_HEIGHT * battlefieldCardSize / 42);
+ int battlefieldCardMinSize = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GUI_CARD_BATTLEFIELD_MIN_SIZE, 10);
+ battlefieldCardMinDimension = new Dimension(CARD_IMAGE_WIDTH * battlefieldCardMinSize / 42, CARD_IMAGE_HEIGHT * battlefieldCardMinSize / 42);
+ int battlefieldCardMaxSize = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GUI_CARD_BATTLEFIELD_MAX_SIZE, 14);
+ battlefieldCardMaxDimension = new Dimension(CARD_IMAGE_WIDTH * battlefieldCardMaxSize / 42, CARD_IMAGE_HEIGHT * battlefieldCardMaxSize / 42);
int editorCardSize = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GUI_CARD_EDITOR_SIZE, 14);
editorCardDimension = new Dimension(CARD_IMAGE_WIDTH * editorCardSize / 42, CARD_IMAGE_HEIGHT * editorCardSize / 42);
diff --git a/Mage.Client/src/main/java/mage/client/util/layout/impl/OldCardLayoutStrategy.java b/Mage.Client/src/main/java/mage/client/util/layout/impl/OldCardLayoutStrategy.java
index 47cd0d30e87..517bab9508c 100644
--- a/Mage.Client/src/main/java/mage/client/util/layout/impl/OldCardLayoutStrategy.java
+++ b/Mage.Client/src/main/java/mage/client/util/layout/impl/OldCardLayoutStrategy.java
@@ -23,13 +23,12 @@ public class OldCardLayoutStrategy implements CardLayoutStrategy {
/**
* This offset is used once to shift all attachments
*/
- private static final int ATTACHMENTS_DX_OFFSET = 11;
+ private static final int ATTACHMENTS_MIN_DX_OFFSET = 12;
/**
* This offset is used for each attachment
*/
- private static final int ATTACHMENT_DX_OFFSET = 0;
- private static final int ATTACHMENT_DY_OFFSET = 11;
+ private static final int ATTACHMENT_MIN_DY_OFFSET = 12;
@Override
public void doLayout(JLayeredPane jLayeredPane, int width) {
@@ -56,7 +55,7 @@ public class OldCardLayoutStrategy implements CardLayoutStrategy {
perm.getLinks().clear();
Rectangle rectangleBaseCard = perm.getBounds();
if (!Plugins.getInstance().isCardPluginLoaded()) {
- for (UUID attachmentId: permanent.getAttachments()) {
+ for (UUID attachmentId : permanent.getAttachments()) {
MagePermanent link = permanents.get(attachmentId);
if (link != null) {
perm.getLinks().add(link);
@@ -67,15 +66,16 @@ public class OldCardLayoutStrategy implements CardLayoutStrategy {
}
} else {
int index = permanent.getAttachments().size();
- for (UUID attachmentId: permanent.getAttachments()) {
+ for (UUID attachmentId : permanent.getAttachments()) {
MagePermanent link = permanents.get(attachmentId);
if (link != null) {
link.setBounds(rectangleBaseCard);
perm.getLinks().add(link);
+ int dyOffset = Math.max(perm.getHeight() / 10, ATTACHMENT_MIN_DY_OFFSET);
if (index == 1) {
- rectangleBaseCard.translate(ATTACHMENTS_DX_OFFSET, ATTACHMENT_DY_OFFSET); // do it once
+ rectangleBaseCard.translate(Math.max(perm.getWidth() / 10, ATTACHMENTS_MIN_DX_OFFSET), dyOffset); // do it once
} else {
- rectangleBaseCard.translate(ATTACHMENT_DX_OFFSET, ATTACHMENT_DY_OFFSET);
+ rectangleBaseCard.translate(0, dyOffset);
}
perm.setBounds(rectangleBaseCard);
jLayeredPane.moveToFront(link);
diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/CardPluginImpl.java b/Mage.Client/src/main/java/org/mage/plugins/card/CardPluginImpl.java
index 99d5a8acf06..7a9f4950db9 100644
--- a/Mage.Client/src/main/java/org/mage/plugins/card/CardPluginImpl.java
+++ b/Mage.Client/src/main/java/org/mage/plugins/card/CardPluginImpl.java
@@ -67,7 +67,8 @@ public class CardPluginImpl implements CardPlugin {
private int landStackMax = 5;
// private int cardWidthMin = 50, cardWidthMax = Constants.CARD_SIZE_FULL.width;
- private int cardWidthMin = 50, cardWidthMax = (int) GUISizeHelper.battlefieldCardDimension.getWidth();
+ private int cardWidthMin = (int) GUISizeHelper.battlefieldCardMinDimension.getWidth();
+ private int cardWidthMax = (int) GUISizeHelper.battlefieldCardMaxDimension.getWidth();
private boolean stackVertical = false;
@@ -101,8 +102,8 @@ public class CardPluginImpl implements CardPlugin {
}
private void setGUISize() {
- cardWidthMin = 50;
- cardWidthMax = (int) GUISizeHelper.battlefieldCardDimension.getWidth();
+ cardWidthMin = (int) GUISizeHelper.battlefieldCardMinDimension.getWidth();
+ cardWidthMax = (int) GUISizeHelper.battlefieldCardMaxDimension.getWidth();
}
@Override
@@ -261,6 +262,7 @@ public class CardPluginImpl implements CardPlugin {
}
//FIXME: -1 is too slow. why not binary search?
cardWidth -= 3;
+
}
// Get size of all the rows.
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 a2a48fb1d61..203e5d45481 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
@@ -123,6 +123,8 @@ public class HumanPlayer extends PlayerImpl {
protected Map requestAutoAnswerId = new HashMap<>();
protected Map requestAutoAnswerText = new HashMap<>();
+ protected boolean holdingPriority;
+
public HumanPlayer(String name, RangeOfInfluence range, int skill) {
super(name, range);
replacementEffectChoice = new ChoiceImpl(true);
@@ -565,7 +567,7 @@ public class HumanPlayer extends PlayerImpl {
public boolean priority(Game game) {
passed = false;
if (!abort) {
- if (getJustActivatedType() != null) {
+ if (getJustActivatedType() != null && !holdingPriority) {
if (userData.isPassPriorityCast() && getJustActivatedType().equals(AbilityType.SPELL)) {
setJustActivatedType(null);
pass(game);
@@ -661,6 +663,7 @@ public class HumanPlayer extends PlayerImpl {
}
while (canRespond()) {
updateGameStatePriority("priority", game);
+ holdingPriority = false;
game.firePriorityEvent(playerId);
waitForResponse(game);
if (game.executingRollback()) {
@@ -1465,6 +1468,12 @@ public class HumanPlayer extends PlayerImpl {
case REQUEST_AUTO_ANSWER_RESET_ALL:
setRequestAutoAnswer(playerAction, game, data);
break;
+ case HOLD_PRIORITY:
+ holdingPriority = true;
+ break;
+ case UNHOLD_PRIORITY:
+ holdingPriority = false;
+ break;
default:
super.sendPlayerAction(playerAction, game, data);
}
diff --git a/Mage.Sets/src/mage/sets/eldritchmoon/ElderDeepFiend.java b/Mage.Sets/src/mage/sets/eldritchmoon/ElderDeepFiend.java
new file mode 100644
index 00000000000..53c665fa8ad
--- /dev/null
+++ b/Mage.Sets/src/mage/sets/eldritchmoon/ElderDeepFiend.java
@@ -0,0 +1,78 @@
+/*
+ * 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.eldritchmoon;
+
+import java.util.UUID;
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.common.CastSourceTriggeredAbility;
+import mage.abilities.effects.common.TapTargetEffect;
+import mage.abilities.keyword.EmergeAbility;
+import mage.abilities.keyword.FlashAbility;
+import mage.cards.CardImpl;
+import mage.constants.CardType;
+import mage.constants.Rarity;
+import mage.filter.FilterPermanent;
+import mage.target.TargetPermanent;
+
+/**
+ *
+ * @author emerald000
+ */
+public class ElderDeepFiend extends CardImpl {
+
+ public ElderDeepFiend(UUID ownerId) {
+ super(ownerId, 5, "Elder Deep-Fiend", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{8}");
+ this.expansionSetCode = "EMN";
+ this.subtype.add("Eldrazi");
+ this.subtype.add("Octopus");
+ this.power = new MageInt(5);
+ this.toughness = new MageInt(6);
+
+ // Flash
+ this.addAbility(FlashAbility.getInstance());
+
+ // Emerge {5}{U}{U}
+ this.addAbility(new EmergeAbility(this, new ManaCostsImpl<>("{5}{U}{U}")));
+
+ // When you cast Elder Deep-Fiend, tap up to four target permanents.
+ Ability ability = new CastSourceTriggeredAbility(new TapTargetEffect());
+ ability.addTarget(new TargetPermanent(0, 4, new FilterPermanent("permanents to tap"), false));
+ this.addAbility(ability);
+ }
+
+ public ElderDeepFiend(final ElderDeepFiend card) {
+ super(card);
+ }
+
+ @Override
+ public ElderDeepFiend copy() {
+ return new ElderDeepFiend(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/sets/eldritchmoon/StitchersGraft.java b/Mage.Sets/src/mage/sets/eldritchmoon/StitchersGraft.java
new file mode 100644
index 00000000000..65876b2e08f
--- /dev/null
+++ b/Mage.Sets/src/mage/sets/eldritchmoon/StitchersGraft.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.sets.eldritchmoon;
+
+import java.util.UUID;
+import mage.abilities.TriggeredAbilityImpl;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.common.UnattachedTriggeredAbility;
+import mage.abilities.costs.mana.GenericManaCost;
+import mage.abilities.effects.Effect;
+import mage.abilities.effects.common.DontUntapInControllersNextUntapStepSourceEffect;
+import mage.abilities.effects.common.SacrificeEquippedEffect;
+import mage.abilities.effects.common.continuous.BoostEquippedEffect;
+import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
+import mage.abilities.keyword.EquipAbility;
+import mage.cards.CardImpl;
+import mage.constants.AttachmentType;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.Rarity;
+import mage.constants.Zone;
+import mage.game.Game;
+import mage.game.events.GameEvent.EventType;
+import mage.game.events.GameEvent;
+
+/**
+ *
+ * @author spjspj
+ */
+public class StitchersGraft extends CardImpl {
+
+ public StitchersGraft(UUID ownerId) {
+ super(ownerId, 200, "Stitcher's Graft", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{1}");
+ this.expansionSetCode = "EMN";
+ this.subtype.add("Equipment");
+
+ // Equipped creature gets +3/+3.
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(3, 3)));
+
+ // Whenever equipped creature attacks, it doesn't untap during its controller's next untap step.
+ Effect effect = new GainAbilityAttachedEffect(new StitchersGraftTriggeredAbility(), AttachmentType.EQUIPMENT);
+ effect.setText("Equipped creature has \"Whenever equipped creature attacks, it doesn't untap during its controller's next untap step.\"");
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
+
+ // Whenever Stitcher's Graft becomes unattached from a permanent, sacrifice that permanent.
+ this.addAbility(new UnattachedTriggeredAbility(new SacrificeEquippedEffect(), false));
+
+ // Equip {2}
+ this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2)));
+ }
+
+ public StitchersGraft(final StitchersGraft card) {
+ super(card);
+ }
+
+ @Override
+ public StitchersGraft copy() {
+ return new StitchersGraft(this);
+ }
+}
+
+class StitchersGraftTriggeredAbility extends TriggeredAbilityImpl {
+
+ public StitchersGraftTriggeredAbility() {
+ super(Zone.BATTLEFIELD, new DontUntapInControllersNextUntapStepSourceEffect());
+ }
+
+ public StitchersGraftTriggeredAbility(final StitchersGraftTriggeredAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public StitchersGraftTriggeredAbility copy() {
+ return new StitchersGraftTriggeredAbility(this);
+ }
+
+ @Override
+ public boolean checkEventType(GameEvent event, Game game) {
+ return event.getType() == EventType.ATTACKER_DECLARED;
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ if (event.getType() == GameEvent.EventType.ATTACKER_DECLARED && event.getSourceId().equals(this.getSourceId())) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public String getRule() {
+ return "Whenever equipped creature attacks, it doesn't untap during its controller's next untap step";
+ }
+}
diff --git a/Mage.Sets/src/mage/sets/guildpact/EarthSurge.java b/Mage.Sets/src/mage/sets/guildpact/EarthSurge.java
new file mode 100644
index 00000000000..8406d44ee8d
--- /dev/null
+++ b/Mage.Sets/src/mage/sets/guildpact/EarthSurge.java
@@ -0,0 +1,72 @@
+/*
+ * 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.guildpact;
+
+import java.util.UUID;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.Effect;
+import mage.abilities.effects.common.continuous.BoostControlledEffect;
+import mage.cards.CardImpl;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Rarity;
+import mage.constants.Zone;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.mageobject.CardTypePredicate;
+
+/**
+ *
+ * @author Styxo
+ */
+public class EarthSurge extends CardImpl {
+
+ private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("land creatures");
+
+ static {
+ filter.add(new CardTypePredicate(CardType.LAND));
+ }
+
+ public EarthSurge(UUID ownerId) {
+ super(ownerId, 84, "Earth Surge", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}");
+ this.expansionSetCode = "GPT";
+
+ //Each land gets +2/+2 as long as it's a creature.
+ Effect effect = new BoostControlledEffect(2, 2, Duration.WhileOnBattlefield, filter, true);
+ effect.setText("Each land gets +2/+2 as long as it\'s a creature");
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
+ }
+
+ public EarthSurge(final EarthSurge card) {
+ super(card);
+ }
+
+ @Override
+ public EarthSurge copy() {
+ return new EarthSurge(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/sets/modernmasters2015/WorldheartPhoenix.java b/Mage.Sets/src/mage/sets/modernmasters2015/WorldheartPhoenix.java
index 9961f8c2b6d..bd2b489c593 100644
--- a/Mage.Sets/src/mage/sets/modernmasters2015/WorldheartPhoenix.java
+++ b/Mage.Sets/src/mage/sets/modernmasters2015/WorldheartPhoenix.java
@@ -134,7 +134,7 @@ public class WorldheartPhoenix extends CardImpl {
@Override
public boolean apply(Game game, Ability source) {
- Permanent permanent = game.getPermanent(source.getSourceId());
+ Permanent permanent = game.getPermanentEntering(source.getSourceId());
if (permanent != null) {
SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY);
if (spellAbility != null
diff --git a/Mage/src/main/java/mage/abilities/keyword/EmergeAbility.java b/Mage/src/main/java/mage/abilities/keyword/EmergeAbility.java
new file mode 100644
index 00000000000..40f610c362b
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/keyword/EmergeAbility.java
@@ -0,0 +1,116 @@
+/*
+ * 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.abilities.keyword;
+
+import java.util.UUID;
+import mage.abilities.SpellAbility;
+import mage.abilities.costs.common.SacrificeTargetCost;
+import mage.abilities.costs.mana.ManaCost;
+import mage.abilities.costs.mana.ManaCosts;
+import mage.cards.Card;
+import mage.constants.Outcome;
+import mage.constants.SpellAbilityType;
+import mage.constants.Zone;
+import mage.filter.common.FilterControlledCreaturePermanent;
+import mage.filter.predicate.mageobject.CardIdPredicate;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+import mage.target.TargetPermanent;
+import mage.target.common.TargetControlledCreaturePermanent;
+import mage.util.CardUtil;
+
+/**
+ *
+ * @author emerald000
+ */
+public class EmergeAbility extends SpellAbility {
+
+ private final ManaCosts emergeCost;
+
+ public EmergeAbility(Card card, ManaCosts emergeCost) {
+ super(emergeCost, card.getName() + " with emerge", Zone.HAND, SpellAbilityType.BASE_ALTERNATE);
+ this.getCosts().addAll(card.getSpellAbility().getCosts().copy());
+ this.getEffects().addAll(card.getSpellAbility().getEffects().copy());
+ this.getTargets().addAll(card.getSpellAbility().getTargets().copy());
+ this.timing = card.getSpellAbility().getTiming();
+ this.setRuleAtTheTop(true);
+ this.emergeCost = emergeCost.copy();
+ }
+
+ public EmergeAbility(final EmergeAbility ability) {
+ super(ability);
+ this.emergeCost = ability.emergeCost.copy();
+ }
+
+ @Override
+ public boolean canActivate(UUID playerId, Game game) {
+ Player controller = game.getPlayer(this.getControllerId());
+ if (controller != null) {
+ for (Permanent creature : game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(), this.getControllerId(), this.getSourceId(), game)) {
+ ManaCost costToPay = CardUtil.reduceCost(emergeCost.copy(), creature.getConvertedManaCost());
+ if (costToPay.canPay(this, this.getSourceId(), this.getControllerId(), game)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean activate(Game game, boolean noMana) {
+ Player controller = game.getPlayer(this.getControllerId());
+ if (controller != null) {
+ TargetPermanent target = new TargetControlledCreaturePermanent(new FilterControlledCreaturePermanent("creature to sacrifice for emerge"));
+ if (controller.choose(Outcome.Sacrifice, target, this.getSourceId(), game)) {
+ Permanent creature = game.getPermanent(target.getFirstTarget());
+ CardUtil.reduceCost(this, creature.getConvertedManaCost());
+ FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(creature.getLogName());
+ filter.add(new CardIdPredicate(creature.getId()));
+ this.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(filter)));
+ return super.activate(game, false);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public EmergeAbility copy() {
+ return new EmergeAbility(this);
+ }
+
+ @Override
+ public String getRule(boolean all) {
+ return getRule();
+ }
+
+ @Override
+ public String getRule() {
+ return "Emerge " + emergeCost.getText() + " (You may cast this spell by sacrificing a creature and paying the emerge cost reduced by that creature's converted mana cost.)";
+ }
+}
diff --git a/Mage/src/main/java/mage/constants/PlayerAction.java b/Mage/src/main/java/mage/constants/PlayerAction.java
index c21bf05d458..cbff2a13840 100644
--- a/Mage/src/main/java/mage/constants/PlayerAction.java
+++ b/Mage/src/main/java/mage/constants/PlayerAction.java
@@ -82,5 +82,6 @@ public enum PlayerAction {
CLIENT_DOWNLOAD_CARD_IMAGES,
CLIENT_RECONNECT,
CLIENT_REPLAY_ACTION,
-
+ HOLD_PRIORITY,
+ UNHOLD_PRIORITY
}
diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt
index 649624f6328..22e3ceab78a 100644
--- a/Utils/mtg-cards-data.txt
+++ b/Utils/mtg-cards-data.txt
@@ -57372,4 +57372,4 @@ Lupine Prototype|Eldritch Moon|197|R|{2}|Artifact Creature - Wolf Construct|5|5|
Soul Separator|Eldritch Moon|199|R|{3}|Artifact|||{5}, {T}, Sacrifice Soul Separator: Exile target creature card from your graveyard. Put a token onto the battlefield that's a copy of that card except it's 1/1, it's a Spirit in addition to its other types, and it has flying. Put a black Zombie creature token onto the battlefield with power equal to that card's power and toughness equal that card's toughness.|
Stitcher's Graft|Eldritch Moon|200|R|{1}|Artifact - Equipment|||Equipped creature gets +3/+3.$Whenever equipped creature attacks, it doesn't untap during its controller's next untap step.$Whenever Stitcher's Graft becomes unattached from a permanent, sacrifice that permanent.$Equip {2}|
Geier Reach Sanitarium|Eldritch Moon|203|R||Legendary Land|||{T}: Add {C} to your mana pool.${2}, {T}: Each player draws a card, then discards a card.|
-Hanweir Battlements|Eldritch Moon|204|R||Land|||{T}: Add {C} to your mana pool.${R},{T}: Target creature gains haste until end of turn.${3}{R}{R},{T}: If you both own and control Hanweir Battlements and a creature named Hanweir Garrison, exile them, then meld them into Hanweir, the Writhing Township.|
\ No newline at end of file
+Hanweir Battlements|Eldritch Moon|204|R||Land|||{T}: Add {C} to your mana pool.${R},{T}: Target creature gains haste until end of turn.${3}{R}{R},{T}: If you both own and control Hanweir Battlements and a creature named Hanweir Garrison, exile them, then meld them into Hanweir, the Writhing Township.|