1
0
Fork 0
mirror of https://github.com/correl/mage.git synced 2025-04-09 01:01:06 -09:00

Merge branch 'master' into implement-zilortha

# Conflicts:
#	Mage/src/main/java/mage/game/GameImpl.java
This commit is contained in:
htrajan 2020-04-16 15:55:24 -07:00
commit a08bd34582
332 changed files with 1928 additions and 589 deletions
Mage.Client/src/main/java/mage/client
Mage.Server.Plugins
Mage.Deck.Constructed/src/mage/deck
Mage.Game.BrawlDuel/src/mage/game
Mage.Game.BrawlFreeForAll/src/mage/game
Mage.Game.CommanderDuel/src/mage/game
Mage.Game.CommanderFreeForAll/src/mage/game
Mage.Game.FreeForAll/src/mage/game
Mage.Game.FreeformCommanderDuel/src/mage/game
Mage.Game.FreeformCommanderFreeForAll/src/mage/game
Mage.Game.MomirDuel/src/mage/game
Mage.Game.MomirGame/src/mage/game
Mage.Game.OathbreakerFreeForAll/src/mage/game
Mage.Game.PennyDreadfulCommanderFreeForAll/src/mage/game
Mage.Game.TwoPlayerDuel/src/mage/game
Mage.Sets/src/mage/cards
a
b
c
d
e
f

View file

@ -324,10 +324,12 @@
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="btnFindMain" min="-2" pref="90" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="btnFindUs" min="-2" pref="90" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="btnFindMain" min="-2" pref="80" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnFindEU" min="-2" pref="80" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnFindUs" min="-2" pref="80" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnFindBeta" min="-2" pref="90" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="btnFindLocal" min="-2" pref="90" max="-2" attributes="0"/>
@ -347,6 +349,7 @@
<Component id="btnFindUs" alignment="3" min="-2" pref="30" max="-2" attributes="0"/>
<Component id="btnFindBeta" alignment="3" min="-2" pref="30" max="-2" attributes="0"/>
<Component id="btnFindOther" alignment="3" min="-2" pref="30" max="-2" attributes="0"/>
<Component id="btnFindEU" alignment="3" min="-2" pref="30" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group>
@ -360,8 +363,7 @@
<Image iconType="3" name="/flags/de.png"/>
</Property>
<Property name="text" type="java.lang.String" value="X"/>
<Property name="toolTipText" type="java.lang.String" value="Connect to xmage.de (Europe, most popular, registration needs)"/>
<Property name="actionCommand" type="java.lang.String" value="connectXmageDe"/>
<Property name="toolTipText" type="java.lang.String" value="Connect to xmage.de (first Europe server, most popular, registration needs)"/>
<Property name="alignmentY" type="float" value="0.0"/>
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
<Insets value="[2, 2, 2, 2]"/>
@ -372,32 +374,29 @@
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[42, 23]"/>
</Property>
<Property name="name" type="java.lang.String" value="connectXmageDeBtn" noResource="true"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[23, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="connectXmageDe"/>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnFindMainActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnFindLocal">
<Properties>
<Property name="text" type="java.lang.String" value="LOCAL, AI"/>
<Property name="toolTipText" type="java.lang.String" value="Connect to localhost, AI enabled (run local server from launcher)"/>
<Property name="actionCommand" type="java.lang.String" value="connectLocalhost"/>
<Property name="alignmentY" type="float" value="0.0"/>
<Property name="horizontalTextPosition" type="int" value="0"/>
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
<Insets value="[2, 2, 2, 2]"/>
</Property>
<Property name="name" type="java.lang.String" value="connectLocalhostBtn" noResource="true"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[23, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="connectLocalhost"/>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnFindLocalActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnFindBeta">
@ -414,7 +413,7 @@
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnFindBetaconnectLocalhost"/>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnFindBetaActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnFindUs">
@ -424,29 +423,51 @@
</Property>
<Property name="text" type="java.lang.String" value="US"/>
<Property name="toolTipText" type="java.lang.String" value="Connect to us.xmage.today (USA, use any username without registration)"/>
<Property name="actionCommand" type="java.lang.String" value="connectXmageus"/>
<Property name="alignmentY" type="float" value="0.0"/>
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
<Insets value="[2, 2, 2, 2]"/>
</Property>
<Property name="name" type="java.lang.String" value="connectXmageusBtn" noResource="true"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[23, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="connectXmageus"/>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnFindUsActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnFindOther">
<Properties>
<Property name="text" type="java.lang.String" value="Other servers..."/>
<Property name="text" type="java.lang.String" value="Other..."/>
<Property name="toolTipText" type="java.lang.String" value="Choose server from full servers list"/>
<Property name="horizontalTextPosition" type="int" value="0"/>
<Property name="name" type="java.lang.String" value="findServerBtn" noResource="true"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="findPublicServerActionPerformed"/>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnFindOtherActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnFindEU">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/flags/europeanunion.png"/>
</Property>
<Property name="text" type="java.lang.String" value="EU"/>
<Property name="toolTipText" type="java.lang.String" value="Connect to eu.xmage.today (second Europe server, use any username without registration)"/>
<Property name="alignmentY" type="float" value="0.0"/>
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
<Insets value="[2, 2, 2, 2]"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[42, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[42, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[23, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnFindEUActionPerformed"/>
</Events>
</Component>
</SubComponents>
@ -463,7 +484,7 @@
<EmptySpace max="-2" attributes="0"/>
<Component id="txtPort" min="-2" pref="75" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnCheckStatus" pref="205" max="32767" attributes="0"/>
<Component id="btnCheckStatus" max="32767" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group>
</Group>

View file

@ -92,6 +92,118 @@ public class ConnectDialog extends MageDialog {
// last settings for reconnect
MagePreferences.saveLastServer();
}
private void setServerSettings(String address, String port, boolean needRegistration) {
this.txtServer.setText(address);
this.txtPort.setText(port);
this.txtUserName.setText(MagePreferences.getUserName(address));
if (needRegistration) {
this.txtPassword.setText(MagePreferences.getPassword(address));
} else {
this.txtPassword.setText("");
}
}
private void chooseAndSetServerSettingsFromOther() {
BufferedReader in = null;
Writer output = null;
try {
String serverUrl = PreferencesDialog.getCachedValue(KEY_CONNECTION_URL_SERVER_LIST, "http://xmage.de/files/server-list.txt");
if (serverUrl.contains("xmage.info/files/")) {
serverUrl = serverUrl.replace("xmage.info/files/", "xmage.de/files/"); // replace old URL if still saved
PreferencesDialog.saveValue(KEY_CONNECTION_URL_SERVER_LIST, serverUrl);
}
URL serverListURL = new URL(serverUrl);
Connection.ProxyType configProxyType = Connection.ProxyType.valueByText(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PROXY_TYPE, "None"));
Proxy p = null;
Proxy.Type type = Proxy.Type.DIRECT;
switch (configProxyType) {
case HTTP:
type = Proxy.Type.HTTP;
break;
case SOCKS:
type = Proxy.Type.SOCKS;
break;
case NONE:
default:
p = Proxy.NO_PROXY;
break;
}
if (p == null || !p.equals(Proxy.NO_PROXY)) {
try {
String address = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PROXY_ADDRESS, "");
Integer port = Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PROXY_PORT, "80"));
p = new Proxy(type, new InetSocketAddress(address, port));
} catch (Exception ex) {
throw new RuntimeException("Gui_DownloadPictures : error 1 - " + ex);
}
}
if (p == null) {
JOptionPane.showMessageDialog(null, "Couldn't configure Proxy object!", "Error", JOptionPane.ERROR_MESSAGE);
return;
}
boolean URLNotFound = false;
try {
in = new BufferedReader(new InputStreamReader(serverListURL.openConnection(p).getInputStream()));
} catch (SocketTimeoutException | FileNotFoundException | UnknownHostException ex) {
logger.warn("Could not read serverlist from: " + serverListURL.toString());
File f = new File("serverlist.txt");
if (f.exists() && !f.isDirectory()) {
logger.info("Using buffered serverlist: serverlist.txt");
URLNotFound = true;
in = new BufferedReader(new FileReader("serverlist.txt"));
}
}
List<String> servers = new ArrayList<>();
if (in != null) {
if (!URLNotFound) {
// write serverlist to be able to read if URL is not available
File file = new File("serverlist.txt");
if (file.exists() && !file.isDirectory()) {
file.delete();
}
output = new BufferedWriter(new FileWriter(file));
}
String inputLine;
while ((inputLine = in.readLine()) != null) {
logger.debug("Found server: " + inputLine);
servers.add(inputLine);
if (output != null) {
output.append(inputLine).append('\n');
}
}
}
if (servers.isEmpty()) {
JOptionPane.showMessageDialog(null, "Couldn't find any server.");
return;
}
String selectedServer = (String) JOptionPane.showInputDialog(null,
"Choose XMage Public Server:", "Input",
JOptionPane.INFORMATION_MESSAGE, null, servers.toArray(),
servers.get(0));
if (selectedServer != null) {
String[] params = selectedServer.split(":");
if (params.length == 3) {
setServerSettings(params[1], params[2], true);
} else {
JOptionPane.showMessageDialog(null, "Wrong server data format.");
}
}
} catch (Exception ex) {
logger.error(ex, ex);
} finally {
StreamUtils.closeQuietly(in);
StreamUtils.closeQuietly(output);
}
}
/**
* This method is called from within the constructor to initialize the form.
@ -127,6 +239,7 @@ public class ConnectDialog extends MageDialog {
btnFindBeta = new javax.swing.JButton();
btnFindUs = new javax.swing.JButton();
btnFindOther = new javax.swing.JButton();
btnFindEU = new javax.swing.JButton();
panelServer = new javax.swing.JPanel();
txtServer = new javax.swing.JTextField();
txtPort = new javax.swing.JTextField();
@ -242,31 +355,27 @@ public class ConnectDialog extends MageDialog {
btnFindMain.setIcon(new javax.swing.ImageIcon(getClass().getResource("/flags/de.png"))); // NOI18N
btnFindMain.setText("X");
btnFindMain.setToolTipText("Connect to xmage.de (Europe, most popular, registration needs)");
btnFindMain.setActionCommand("connectXmageDe");
btnFindMain.setToolTipText("Connect to xmage.de (first Europe server, most popular, registration needs)");
btnFindMain.setAlignmentY(0.0F);
btnFindMain.setMargin(new java.awt.Insets(2, 2, 2, 2));
btnFindMain.setMaximumSize(new java.awt.Dimension(42, 23));
btnFindMain.setMinimumSize(new java.awt.Dimension(42, 23));
btnFindMain.setName("connectXmageDeBtn"); // NOI18N
btnFindMain.setPreferredSize(new java.awt.Dimension(23, 23));
btnFindMain.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
connectXmageDe(evt);
btnFindMainActionPerformed(evt);
}
});
btnFindLocal.setText("LOCAL, AI");
btnFindLocal.setToolTipText("Connect to localhost, AI enabled (run local server from launcher)");
btnFindLocal.setActionCommand("connectLocalhost");
btnFindLocal.setAlignmentY(0.0F);
btnFindLocal.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
btnFindLocal.setMargin(new java.awt.Insets(2, 2, 2, 2));
btnFindLocal.setName("connectLocalhostBtn"); // NOI18N
btnFindLocal.setPreferredSize(new java.awt.Dimension(23, 23));
btnFindLocal.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
connectLocalhost(evt);
btnFindLocalActionPerformed(evt);
}
});
@ -278,31 +387,42 @@ public class ConnectDialog extends MageDialog {
btnFindBeta.setPreferredSize(new java.awt.Dimension(23, 23));
btnFindBeta.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnFindBetaconnectLocalhost(evt);
btnFindBetaActionPerformed(evt);
}
});
btnFindUs.setIcon(new javax.swing.ImageIcon(getClass().getResource("/flags/us.png"))); // NOI18N
btnFindUs.setText("US");
btnFindUs.setToolTipText("Connect to us.xmage.today (USA, use any username without registration)");
btnFindUs.setActionCommand("connectXmageus");
btnFindUs.setAlignmentY(0.0F);
btnFindUs.setMargin(new java.awt.Insets(2, 2, 2, 2));
btnFindUs.setName("connectXmageusBtn"); // NOI18N
btnFindUs.setPreferredSize(new java.awt.Dimension(23, 23));
btnFindUs.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
connectXmageus(evt);
btnFindUsActionPerformed(evt);
}
});
btnFindOther.setText("Other servers...");
btnFindOther.setText("Other...");
btnFindOther.setToolTipText("Choose server from full servers list");
btnFindOther.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
btnFindOther.setName("findServerBtn"); // NOI18N
btnFindOther.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
findPublicServerActionPerformed(evt);
btnFindOtherActionPerformed(evt);
}
});
btnFindEU.setIcon(new javax.swing.ImageIcon(getClass().getResource("/flags/europeanunion.png"))); // NOI18N
btnFindEU.setText("EU");
btnFindEU.setToolTipText("Connect to eu.xmage.today (second Europe server, use any username without registration)");
btnFindEU.setAlignmentY(0.0F);
btnFindEU.setMargin(new java.awt.Insets(2, 2, 2, 2));
btnFindEU.setMaximumSize(new java.awt.Dimension(42, 23));
btnFindEU.setMinimumSize(new java.awt.Dimension(42, 23));
btnFindEU.setPreferredSize(new java.awt.Dimension(23, 23));
btnFindEU.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnFindEUActionPerformed(evt);
}
});
@ -312,9 +432,11 @@ public class ConnectDialog extends MageDialog {
panelFastLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelFastLayout.createSequentialGroup()
.addGap(0, 0, 0)
.addComponent(btnFindMain, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnFindMain, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnFindUs, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnFindEU, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnFindUs, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnFindBeta, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
@ -332,7 +454,8 @@ public class ConnectDialog extends MageDialog {
.addComponent(btnFindLocal, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnFindUs, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnFindBeta, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnFindOther, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(btnFindOther, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnFindEU, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(0, 0, 0))
);
@ -368,7 +491,7 @@ public class ConnectDialog extends MageDialog {
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnCheckStatus, javax.swing.GroupLayout.DEFAULT_SIZE, 205, Short.MAX_VALUE)
.addComponent(btnCheckStatus, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGap(0, 0, 0))
);
panelServerLayout.setVerticalGroup(
@ -615,110 +738,7 @@ public class ConnectDialog extends MageDialog {
}//GEN-LAST:event_chkAutoConnectActionPerformed
private void findPublicServerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
BufferedReader in = null;
Writer output = null;
try {
String serverUrl = PreferencesDialog.getCachedValue(KEY_CONNECTION_URL_SERVER_LIST, "http://xmage.de/files/server-list.txt");
if (serverUrl.contains("xmage.info/files/")) {
serverUrl = serverUrl.replace("xmage.info/files/", "xmage.de/files/"); // replace old URL if still saved
PreferencesDialog.saveValue(KEY_CONNECTION_URL_SERVER_LIST, serverUrl);
}
URL serverListURL = new URL(serverUrl);
Connection.ProxyType configProxyType = Connection.ProxyType.valueByText(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PROXY_TYPE, "None"));
Proxy p = null;
Proxy.Type type = Proxy.Type.DIRECT;
switch (configProxyType) {
case HTTP:
type = Proxy.Type.HTTP;
break;
case SOCKS:
type = Proxy.Type.SOCKS;
break;
case NONE:
default:
p = Proxy.NO_PROXY;
break;
}
if (p == null || !p.equals(Proxy.NO_PROXY)) {
try {
String address = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PROXY_ADDRESS, "");
Integer port = Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PROXY_PORT, "80"));
p = new Proxy(type, new InetSocketAddress(address, port));
} catch (Exception ex) {
throw new RuntimeException("Gui_DownloadPictures : error 1 - " + ex);
}
}
if (p == null) {
JOptionPane.showMessageDialog(null, "Couldn't configure Proxy object!", "Error", JOptionPane.ERROR_MESSAGE);
return;
}
boolean URLNotFound = false;
try {
in = new BufferedReader(new InputStreamReader(serverListURL.openConnection(p).getInputStream()));
} catch (SocketTimeoutException | FileNotFoundException | UnknownHostException ex) {
logger.warn("Could not read serverlist from: " + serverListURL.toString());
File f = new File("serverlist.txt");
if (f.exists() && !f.isDirectory()) {
logger.info("Using buffered serverlist: serverlist.txt");
URLNotFound = true;
in = new BufferedReader(new FileReader("serverlist.txt"));
}
}
List<String> servers = new ArrayList<>();
if (in != null) {
if (!URLNotFound) {
// write serverlist to be able to read if URL is not available
File file = new File("serverlist.txt");
if (file.exists() && !file.isDirectory()) {
file.delete();
}
output = new BufferedWriter(new FileWriter(file));
}
String inputLine;
while ((inputLine = in.readLine()) != null) {
logger.debug("Found server: " + inputLine);
servers.add(inputLine);
if (output != null) {
output.append(inputLine).append('\n');
}
}
}
if (servers.isEmpty()) {
JOptionPane.showMessageDialog(null, "Couldn't find any server.");
return;
}
String selectedServer = (String) JOptionPane.showInputDialog(null,
"Choose XMage Public Server:", "Input",
JOptionPane.INFORMATION_MESSAGE, null, servers.toArray(),
servers.get(0));
if (selectedServer != null) {
String[] params = selectedServer.split(":");
if (params.length == 3) {
String serverAddress = params[1];
this.txtServer.setText(serverAddress);
this.txtPort.setText(params[2]);
// Update userName and password according to the chosen server.
this.txtUserName.setText(MagePreferences.getUserName(serverAddress));
this.txtPassword.setText(MagePreferences.getPassword(serverAddress));
} else {
JOptionPane.showMessageDialog(null, "Wrong server data format.");
}
}
} catch (Exception ex) {
logger.error(ex, ex);
} finally {
StreamUtils.closeQuietly(in);
StreamUtils.closeQuietly(output);
}
}//GEN-LAST:event_jButton1ActionPerformed
private void jProxySettingsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jProxySettingsButtonActionPerformed
@ -786,10 +806,6 @@ public class ConnectDialog extends MageDialog {
doFastFlagSearch();
}//GEN-LAST:event_btnFlagSearchActionPerformed
private void btnFindBetaconnectLocalhost(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnFindBetaconnectLocalhost
connectBeta(evt);
}//GEN-LAST:event_btnFindBetaconnectLocalhost
private void btnCheckStatusActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCheckStatusActionPerformed
if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
try {
@ -804,6 +820,30 @@ public class ConnectDialog extends MageDialog {
MageFrame.getInstance().showWhatsNewDialog(true);
}//GEN-LAST:event_btnWhatsNewActionPerformed
private void btnFindMainActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnFindMainActionPerformed
setServerSettings("xmage.de", "17171", true);
}//GEN-LAST:event_btnFindMainActionPerformed
private void btnFindEUActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnFindEUActionPerformed
setServerSettings("eu.xmage.today", "17171", false);
}//GEN-LAST:event_btnFindEUActionPerformed
private void btnFindUsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnFindUsActionPerformed
setServerSettings("us.xmage.today", "17171", false);
}//GEN-LAST:event_btnFindUsActionPerformed
private void btnFindBetaActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnFindBetaActionPerformed
setServerSettings("beta.xmage.today", "17171", false);
}//GEN-LAST:event_btnFindBetaActionPerformed
private void btnFindLocalActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnFindLocalActionPerformed
setServerSettings("localhost", "17171", false);
}//GEN-LAST:event_btnFindLocalActionPerformed
private void btnFindOtherActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnFindOtherActionPerformed
chooseAndSetServerSettingsFromOther();
}//GEN-LAST:event_btnFindOtherActionPerformed
private void doFastFlagSearch() {
Choice choice = new ChoiceImpl(false);
@ -852,6 +892,7 @@ public class ConnectDialog extends MageDialog {
private javax.swing.JButton btnCheckStatus;
private javax.swing.JButton btnConnect;
private javax.swing.JButton btnFindBeta;
private javax.swing.JButton btnFindEU;
private javax.swing.JButton btnFindLocal;
private javax.swing.JButton btnFindMain;
private javax.swing.JButton btnFindOther;

View file

@ -400,7 +400,7 @@ class TestGame extends GameImpl {
private int numPlayers;
public TestGame(MultiplayerAttackOption attackOption, RangeOfInfluence range, Mulligan mulligan, int startLife) {
super(attackOption, range, mulligan, startLife);
super(attackOption, range, mulligan, startLife, 60);
}
public TestGame(final TestGame game) {

View file

@ -582,6 +582,7 @@ public class TablesPanel extends javax.swing.JPanel {
Dimension newDimension = new Dimension((int) jPanelBottom.getPreferredSize().getWidth(), GUISizeHelper.menuFont.getSize() + 28);
jPanelBottom.setMinimumSize(newDimension);
jPanelBottom.setPreferredSize(newDimension);
buttonWhatsNew.setFont(GUISizeHelper.menuFont);
buttonNextMessage.setFont(GUISizeHelper.menuFont);
labelMessageHeader.setFont(new Font(GUISizeHelper.menuFont.getName(), Font.BOLD, GUISizeHelper.menuFont.getSize()));
labelMessageText.setFont(GUISizeHelper.menuFont);
@ -1569,7 +1570,7 @@ public class TablesPanel extends javax.swing.JPanel {
jPanelBottom.setPreferredSize(new java.awt.Dimension(516, 37));
jPanelBottom.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));
buttonWhatsNew.setText("Show that's new");
buttonWhatsNew.setText("Show what's new");
buttonWhatsNew.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
buttonWhatsNew.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
buttonWhatsNew.setOpaque(false);

View file

@ -151,7 +151,7 @@ public class Brawl extends Constructed {
for (Ability ability : companion.getAbilities()) {
if (ability instanceof CompanionAbility) {
CompanionAbility companionAbility = (CompanionAbility) ability;
if (!companionAbility.isLegal(cards)) {
if (!companionAbility.isLegal(cards, getDeckMinSize())) {
invalid.put(companion.getName(), "Deck invalid for companion");
valid = false;
}

View file

@ -234,7 +234,7 @@ public class Commander extends Constructed {
for (Ability ability : companion.getAbilities()) {
if (ability instanceof CompanionAbility) {
CompanionAbility companionAbility = (CompanionAbility) ability;
if (!companionAbility.isLegal(cards)) {
if (!companionAbility.isLegal(cards, getDeckMinSize())) {
invalid.put(companion.getName(), "Deck invalid for companion");
valid = false;
}

View file

@ -158,7 +158,7 @@ public class FreeformCommander extends Constructed {
for (Ability ability : companion.getAbilities()) {
if (ability instanceof CompanionAbility) {
CompanionAbility companionAbility = (CompanionAbility) ability;
if (!companionAbility.isLegal(cards)) {
if (!companionAbility.isLegal(cards, getDeckMinSize())) {
invalid.put(companion.getName(), "Deck invalid for companion");
valid = false;
}

View file

@ -189,7 +189,7 @@ public class PennyDreadfulCommander extends Constructed {
for (Ability ability : companion.getAbilities()) {
if (ability instanceof CompanionAbility) {
CompanionAbility companionAbility = (CompanionAbility) ability;
if (!companionAbility.isLegal(cards)) {
if (!companionAbility.isLegal(cards, getDeckMinSize())) {
invalid.put(companion.getName(), "Deck invalid for companion");
valid = false;
}

View file

@ -10,7 +10,7 @@ import mage.game.mulligan.Mulligan;
public class BrawlDuel extends GameCommanderImpl {
public BrawlDuel(MultiplayerAttackOption attackOption, RangeOfInfluence range, Mulligan mulligan, int startLife) {
super(attackOption, range, mulligan, startLife);
super(attackOption, range, mulligan, startLife, 60);
}
public BrawlDuel(final BrawlDuel game) {

View file

@ -17,7 +17,7 @@ public class BrawlFreeForAll extends GameCommanderImpl {
private int numPlayers;
public BrawlFreeForAll(MultiplayerAttackOption attackOption, RangeOfInfluence range, Mulligan mulligan, int startLife) {
super(attackOption, range, mulligan, startLife);
super(attackOption, range, mulligan, startLife, 60);
}
public BrawlFreeForAll(final BrawlFreeForAll game) {

View file

@ -10,7 +10,7 @@ import mage.game.mulligan.Mulligan;
public class CommanderDuel extends GameCommanderImpl {
public CommanderDuel(MultiplayerAttackOption attackOption, RangeOfInfluence range, Mulligan mulligan, int startLife) {
super(attackOption, range, mulligan, startLife);
super(attackOption, range, mulligan, startLife, 100);
}
public CommanderDuel(final CommanderDuel game) {

View file

@ -2,14 +2,14 @@
package mage.game;
import java.util.UUID;
import mage.constants.MultiplayerAttackOption;
import mage.constants.RangeOfInfluence;
import mage.game.match.MatchType;
import mage.game.mulligan.Mulligan;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public class CommanderFreeForAll extends GameCommanderImpl {
@ -17,7 +17,7 @@ public class CommanderFreeForAll extends GameCommanderImpl {
private int numPlayers;
public CommanderFreeForAll(MultiplayerAttackOption attackOption, RangeOfInfluence range, Mulligan mulligan, int startLife) {
super(attackOption, range, mulligan, startLife);
super(attackOption, range, mulligan, startLife, 100);
}
public CommanderFreeForAll(final CommanderFreeForAll game) {
@ -28,7 +28,7 @@ public class CommanderFreeForAll extends GameCommanderImpl {
@Override
protected void init(UUID choosingPlayerId) {
startingPlayerSkipsDraw = false;
super.init(choosingPlayerId);
super.init(choosingPlayerId);
}
@Override

View file

@ -15,7 +15,7 @@ public class FreeForAll extends GameImpl {
private int numPlayers;
public FreeForAll(MultiplayerAttackOption attackOption, RangeOfInfluence range, Mulligan mulligan, int startLife) {
super(attackOption, range, mulligan, startLife);
super(attackOption, range, mulligan, startLife, 60);
}
public FreeForAll(final FreeForAll game) {

View file

@ -11,7 +11,7 @@ import mage.game.mulligan.Mulligan;
public class FreeformCommanderDuel extends GameCommanderImpl {
public FreeformCommanderDuel(MultiplayerAttackOption attackOption, RangeOfInfluence range, Mulligan mulligan, int startLife) {
super(attackOption, range, mulligan, startLife);
super(attackOption, range, mulligan, startLife, 60);
}
public FreeformCommanderDuel(final FreeformCommanderDuel game) {

View file

@ -17,7 +17,7 @@ public class FreeformCommanderFreeForAll extends GameCommanderImpl {
private int numPlayers;
public FreeformCommanderFreeForAll(MultiplayerAttackOption attackOption, RangeOfInfluence range, Mulligan mulligan, int startLife) {
super(attackOption, range, mulligan, startLife);
super(attackOption, range, mulligan, startLife, 60);
}
public FreeformCommanderFreeForAll(final FreeformCommanderFreeForAll game) {

View file

@ -24,7 +24,7 @@ import mage.players.Player;
public class MomirDuel extends GameImpl {
public MomirDuel(MultiplayerAttackOption attackOption, RangeOfInfluence range, Mulligan mulligan, int startLife) {
super(attackOption, range, mulligan, startLife);
super(attackOption, range, mulligan, startLife, 60);
}
public MomirDuel(final MomirDuel game) {

View file

@ -26,7 +26,7 @@ public class MomirGame extends GameImpl {
private int numPlayers;
public MomirGame(MultiplayerAttackOption attackOption, RangeOfInfluence range, Mulligan mulligan, int startLife) {
super(attackOption, range, mulligan, startLife);
super(attackOption, range, mulligan, startLife, 60);
}
public MomirGame(final MomirGame game) {

View file

@ -32,7 +32,7 @@ public class OathbreakerFreeForAll extends GameCommanderImpl {
private static final String COMMANDER_NAME_SIGNATURE_SPELL = "Signature Spell";
public OathbreakerFreeForAll(MultiplayerAttackOption attackOption, RangeOfInfluence range, Mulligan mulligan, int startLife) {
super(attackOption, range, mulligan, startLife);
super(attackOption, range, mulligan, startLife, 100);
this.startingPlayerSkipsDraw = false;
}

View file

@ -17,7 +17,7 @@ public class PennyDreadfulCommanderFreeForAll extends GameCommanderImpl {
private int numPlayers;
public PennyDreadfulCommanderFreeForAll(MultiplayerAttackOption attackOption, RangeOfInfluence range, Mulligan mulligan, int startLife) {
super(attackOption, range, mulligan, startLife);
super(attackOption, range, mulligan, startLife, 60);
}
public PennyDreadfulCommanderFreeForAll(final PennyDreadfulCommanderFreeForAll game) {

View file

@ -1,4 +1,3 @@
package mage.game;
import mage.constants.MultiplayerAttackOption;
@ -13,7 +12,11 @@ import java.util.UUID;
public class TwoPlayerDuel extends GameImpl {
public TwoPlayerDuel(MultiplayerAttackOption attackOption, RangeOfInfluence range, Mulligan mulligan, int startLife) {
super(attackOption, range, mulligan, startLife);
this(attackOption, range, mulligan, startLife, 60);
}
public TwoPlayerDuel(MultiplayerAttackOption attackOption, RangeOfInfluence range, Mulligan mulligan, int startLife, int startingSize) {
super(attackOption, range, mulligan, startLife, startingSize);
}
public TwoPlayerDuel(final TwoPlayerDuel game) {

View file

@ -6,7 +6,6 @@ import mage.game.match.MatchOptions;
import mage.game.mulligan.Mulligan;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class TwoPlayerMatch extends MatchImpl {
@ -18,7 +17,7 @@ public class TwoPlayerMatch extends MatchImpl {
@Override
public void startGame() throws GameException {
Mulligan mulligan = options.getMulliganType().getMulligan(options.getFreeMulligans());
TwoPlayerDuel game = new TwoPlayerDuel(options.getAttackOption(), options.getRange(), mulligan, 20);
TwoPlayerDuel game = new TwoPlayerDuel(options.getAttackOption(), options.getRange(), mulligan, 20, options.isLimited() ? 40 : 60);
// Sets a start message about the match score
game.setStartMessage(this.createGameStartMessage());
initGame(game);

View file

@ -80,7 +80,7 @@ class AkoumFlameseekerEffect extends OneShotEffect {
if (controller != null) {
Cards cards = controller.discard(1, false, source, game);
if (!cards.isEmpty()) {
controller.drawCards(1, game);
controller.drawCards(1, source.getSourceId(), game);
}
return true;
}

View file

@ -75,7 +75,7 @@ class AladdinsLampEffect extends ReplacementEffectImpl {
}
controller.putCardsOnBottomOfLibrary(cards, game, source, false);
game.applyEffects();
controller.drawCards(1, game, event.getAppliedEffects());
controller.drawCards(1, event.getSourceId(), game, event.getAppliedEffects());
discard();
return true;
}

View file

@ -98,7 +98,7 @@ class AlhammarretsArchiveReplacementEffect extends ReplacementEffectImpl {
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
controller.drawCards(2, game, event.getAppliedEffects());
controller.drawCards(2, event.getSourceId(), game, event.getAppliedEffects());
}
return true;
}

View file

@ -74,8 +74,8 @@ class AlmsCollectorReplacementEffect extends ReplacementEffectImpl {
Player controller = game.getPlayer(source.getControllerId());
Player opponent = game.getPlayer(event.getPlayerId());
if (controller != null && opponent != null) {
controller.drawCards(1, game, event.getAppliedEffects());
opponent.drawCards(1, game, event.getAppliedEffects());
controller.drawCards(1, source.getSourceId(), game, event.getAppliedEffects());
opponent.drawCards(1, source.getSourceId(), game, event.getAppliedEffects());
return true;
}
return false;

View file

@ -63,7 +63,7 @@ class AmassTheComponentsEffect extends OneShotEffect {
return false;
}
player.drawCards(3, game);
player.drawCards(3, source.getSourceId(), game);
if (!player.getHand().isEmpty()) {
FilterCard filter = new FilterCard("card from your hand to put on the bottom of your library");
TargetCard target = new TargetCard(Zone.HAND, filter);

View file

@ -98,7 +98,7 @@ class AminatouPlusEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
player.drawCards(1, game);
player.drawCards(1, source.getSourceId(), game);
putOnLibrary(player, source, game);
return true;
}

View file

@ -63,7 +63,7 @@ class AncientExcavationEffect extends OneShotEffect {
if (player != null) {
DynamicValue numCards = CardsInControllerHandCount.instance;
int amount = numCards.calculate(game, source, this);
player.drawCards(amount, game);
player.drawCards(amount, source.getSourceId(), game);
player.discard(amount, false, source, game);
return true;
}

View file

@ -57,7 +57,7 @@ class AnvilOfBogardanEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source));
if (targetPlayer != null) {
targetPlayer.drawCards(1, game);
targetPlayer.drawCards(1, source.getSourceId(), game);
targetPlayer.discard(1, false, source, game);
return true;
}

View file

@ -90,7 +90,7 @@ class ArcaneArtisanCreateTokenEffect extends OneShotEffect {
if (player == null) {
return false;
}
player.drawCards(1, game);
player.drawCards(1, source.getSourceId(), game);
TargetCard target = new TargetCardInHand(1, StaticFilters.FILTER_CARD);
if (!player.chooseTarget(Outcome.Exile, player.getHand(), target, source, game)) {
return false;

View file

@ -64,7 +64,7 @@ class ArjunTheShiftingFlameEffect extends OneShotEffect {
if (you != null) {
int count = you.getHand().size();
you.putCardsOnBottomOfLibrary(you.getHand(), game, source, true);
you.drawCards(count, game);
you.drawCards(count, source.getSourceId(), game);
}
return true;
}

View file

@ -168,7 +168,7 @@ class AzorTheLawbringerAttacksEffect extends OneShotEffect {
if (cost.pay(source, game, source.getSourceId(), source.getControllerId(), false, null)) {
controller.resetStoredBookmark(game); // otherwise you can undo the payment
controller.gainLife(costX, game, source);
controller.drawCards(costX, game);
controller.drawCards(costX, source.getSourceId(), game);
return true;
}
}

View file

@ -78,7 +78,7 @@ class AzorsGatewayEffect extends OneShotEffect {
UUID exileId = CardUtil.getCardExileZoneId(game, source);
MageObject sourceObject = source.getSourceObject(game);
if (controller != null && exileId != null && sourceObject != null) {
controller.drawCards(1, game);
controller.drawCards(1, source.getSourceId(), game);
TargetCardInHand target = new TargetCardInHand();
controller.choose(outcome, target, source.getSourceId(), game);
Card cardToExile = game.getCard(target.getFirstTarget());

View file

@ -84,7 +84,7 @@ class AzraBladeseekerEffect extends OneShotEffect {
}
for (PlayerCard playerCard : playerCardList) {
if (playerCard.getPlayer().discard(playerCard.getCard(), source, game)) {
playerCard.getPlayer().drawCards(1, game);
playerCard.getPlayer().drawCards(1, source.getSourceId(), game);
}
}
return true;

View file

@ -59,7 +59,7 @@ class BalanceOfPowerEffect extends OneShotEffect {
Player opponent = game.getPlayer(source.getFirstTarget());
if (opponent != null && player != null && opponent.getHand().size() > player.getHand().size()) {
player.drawCards(opponent.getHand().size() - player.getHand().size(), game);
player.drawCards(opponent.getHand().size() - player.getHand().size(), source.getSourceId(), game);
return true;
}

View file

@ -70,7 +70,7 @@ class BalefulStareEffect extends OneShotEffect {
count++;
}
}
controller.drawCards(count, game);
controller.drawCards(count, source.getSourceId(), game);
return true;
}
return false;

View file

@ -106,7 +106,7 @@ class BaneAlleyBrokerDrawExileEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
controller.drawCards(1, game);
controller.drawCards(1, source.getSourceId(), game);
Target target = new TargetCardInHand(new FilterCard("card to exile"));
if (controller.chooseTarget(outcome, target, source, game)) {
Card card = game.getCard(target.getFirstTarget());

View file

@ -70,7 +70,7 @@ class BarbedShockerEffect extends OneShotEffect {
for (Card card : targetPlayer.getHand().getCards(game)) {
targetPlayer.discard(card, source, game);
}
targetPlayer.drawCards(count, game);
targetPlayer.drawCards(count, source.getSourceId(), game);
return false;
}
return true;

View file

@ -63,7 +63,7 @@ class BiomanticMasteryEffect extends OneShotEffect {
Player player = game.getPlayer(playerId);
if (player != null) {
int creatures = game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_CREATURE, playerId, game);
controller.drawCards(creatures, game);
controller.drawCards(creatures, source.getSourceId(), game);
}
}
return true;

View file

@ -59,7 +59,7 @@ class BlastOfGeniusEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
player.drawCards(3, game);
player.drawCards(3, source.getSourceId(), game);
TargetDiscard target = new TargetDiscard(player.getId());
if (target.canChoose(source.getSourceId(), player.getId(), game)) {
player.choose(Outcome.Discard, target, source.getSourceId(), game);

View file

@ -70,7 +70,7 @@ class BloodScrivenerReplacementEffect extends ReplacementEffectImpl {
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Player player = game.getPlayer(event.getPlayerId());
if (player != null) {
player.drawCards(2, game, event.getAppliedEffects());
player.drawCards(2, event.getSourceId(), game, event.getAppliedEffects());
player.loseLife(1, game, false);
}
return true;

View file

@ -73,7 +73,7 @@ class BondersOrnamentEffect extends OneShotEffect {
.noneMatch("Bonder's Ornament"::equals)) {
continue;
}
player.drawCards(1, game);
player.drawCards(1, source.getSourceId(), game);
}
return true;
}

View file

@ -80,7 +80,7 @@ class BountyOfTheLuxaEffect extends OneShotEffect {
if (bountyOfLuxa != null) {
new AddCountersSourceEffect(CounterType.FLOOD.createInstance()).apply(game, source);
}
controller.drawCards(1, game);
controller.drawCards(1, source.getSourceId(), game);
}
return true;
}

View file

@ -67,7 +67,7 @@ class BrainPryEffect extends OneShotEffect {
}
}
if (!hasDiscarded) {
controller.drawCards(1, game);
controller.drawCards(1, source.getSourceId(), game);
}
controller.lookAtCards(sourceObject.getName() + " Hand", targetPlayer.getHand(), game);
}

View file

@ -68,7 +68,7 @@ class BreathstealersCryptEffect extends ReplacementEffectImpl {
Player player = game.getPlayer(event.getPlayerId());
if (player != null) {
Cards oldHand = player.getHand().copy();
if (player.drawCards(1, game, event.getAppliedEffects()) > 0) {
if (player.drawCards(1, event.getSourceId(), game, event.getAppliedEffects()) > 0) {
Cards drawnCards = player.getHand().copy();
drawnCards.removeAll(oldHand);
player.revealCards(source, "The card drawn from " + player.getName() + "'s library.", drawnCards, game);

View file

@ -80,7 +80,7 @@ class BrowbeatDrawEffect extends OneShotEffect {
if (targetPlayer != null) {
Player player = game.getPlayer(targetPlayer);
if (player != null) {
player.drawCards(3, game);
player.drawCards(3, source.getSourceId(), game);
}
}
}

View file

@ -98,6 +98,6 @@ class BushmeatPoacherEffect extends OneShotEffect {
if (amount > 0) {
player.gainLife(amount, game, source);
}
return player.drawCards(1, game) > 0;
return player.drawCards(1, source.getSourceId(), game) > 0;
}
}

View file

@ -67,7 +67,7 @@ class CallToHeelEffect extends OneShotEffect {
if (permanent != null) {
Player controller = game.getPlayer(permanent.getControllerId());
if (controller != null) {
controller.drawCards(1, game);
controller.drawCards(1, source.getSourceId(), game);
return true;
}
}

View file

@ -67,7 +67,7 @@ class CamaraderieEffect extends OneShotEffect {
source.getSourceId(), source.getControllerId(), game
);
player.gainLife(xValue, game, source);
player.drawCards(xValue, game);
player.drawCards(xValue, source.getSourceId(), game);
game.addEffect(new BoostControlledEffect(1, 1, Duration.EndOfTurn), source);
return true;
}

View file

@ -0,0 +1,128 @@
package mage.cards.c;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCardInLibrary;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class CartographersHawk extends CardImpl {
public CartographersHawk(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}");
this.subtype.add(SubType.BIRD);
this.power = new MageInt(2);
this.toughness = new MageInt(1);
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Cartographer's Hawk deals combat damage to a player who controls more lands than you, return it to its owner's hand. If you do, you may search your library for a Plains card, put it onto the battlefield tapped, then shuffle your library.
this.addAbility(new CartographersHawkTriggeredAbility());
}
private CartographersHawk(final CartographersHawk card) {
super(card);
}
@Override
public CartographersHawk copy() {
return new CartographersHawk(this);
}
}
class CartographersHawkTriggeredAbility extends TriggeredAbilityImpl {
CartographersHawkTriggeredAbility() {
super(Zone.BATTLEFIELD, new CartographersHawkEffect(), false);
}
private CartographersHawkTriggeredAbility(final CartographersHawkTriggeredAbility ability) {
super(ability);
}
@Override
public CartographersHawkTriggeredAbility copy() {
return new CartographersHawkTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return event.getSourceId().equals(this.getSourceId())
&& game.getBattlefield().countAll(
StaticFilters.FILTER_LAND, this.getControllerId(), game
) < game.getBattlefield().countAll(
StaticFilters.FILTER_LAND, event.getTargetId(), game
);
}
@Override
public String getRule() {
return "When {this} deals combat damage to a player who controls more lands than you, " +
"return it to its owner's hand. If you do, you may search your library for a Plains card, " +
"put it onto the battlefield tapped, then shuffle your library.";
}
}
class CartographersHawkEffect extends OneShotEffect {
private static final FilterCard filter = new FilterCard("a Plains card");
static {
filter.add(SubType.PLAINS.getPredicate());
}
CartographersHawkEffect() {
super(Outcome.Benefit);
}
private CartographersHawkEffect(final CartographersHawkEffect effect) {
super(effect);
}
@Override
public CartographersHawkEffect copy() {
return new CartographersHawkEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
Player player = game.getPlayer(source.getControllerId());
if (permanent == null || player == null) {
return false;
}
if (!player.moveCards(permanent, Zone.HAND, source, game)) {
return false;
}
if (!player.chooseUse(Outcome.PutLandInPlay, "Search your library for Plains card?", source, game)) {
return true;
}
return new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter)).apply(game, source);
}
}

View file

@ -109,7 +109,7 @@ class CavalierOfFlameEffect extends OneShotEffect {
.map(uuid -> game.getCard(uuid))
.mapToInt(card -> card != null && player.discard(card, source, game) ? 1 : 0)
.sum();
player.drawCards(counter, game);
player.drawCards(counter, source.getSourceId(), game);
}
return true;
}

View file

@ -64,7 +64,7 @@ class CemeteryRecruitmentEffect extends OneShotEffect {
if (card != null) {
if (controller.moveCards(card, Zone.HAND, source, game)
&& card.hasSubtype(SubType.ZOMBIE, game)) {
controller.drawCards(1, game);
controller.drawCards(1, source.getSourceId(), game);
}
}
return true;

View file

@ -112,7 +112,7 @@ class ChandraDrawEffect extends OneShotEffect {
for (Card card : cardsInHand) {
player.discard(card, source, game);
}
player.drawCards(amount + 1, game);
player.drawCards(amount + 1, source.getSourceId(), game);
return true;
}
return false;

View file

@ -84,7 +84,7 @@ class ChandrasDefeatEffect extends OneShotEffect {
if (filter.match(permanent, game) && controller != null
&& controller.chooseUse(outcome, "Discard a card and draw a card?", source, game)) {
controller.discard(1, false, source, game);
controller.drawCards(1, game);
controller.drawCards(1, source.getSourceId(), game);
}
return true;
}

View file

@ -67,7 +67,7 @@ class ChanneledForceEffect extends OneShotEffect {
}
Player player = game.getPlayer(source.getTargets().get(0).getFirstTarget());
if (player != null) {
player.drawCards(xValue, game);
player.drawCards(xValue, source.getSourceId(), game);
}
game.damagePlayerOrPlaneswalker(
source.getTargets().get(1).getFirstTarget(), xValue,

View file

@ -75,7 +75,7 @@ class ChroniclerOfHeroesEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
if (new PermanentsOnTheBattlefieldCondition(filter).apply(game, source)) {
controller.drawCards(1, game);
controller.drawCards(1, source.getSourceId(), game);
}
return true;
}

View file

@ -16,13 +16,10 @@ import mage.cards.h.HomicidalBruteWatcher;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.WatcherScope;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.watchers.Watcher;
/**
* @author nantuko
@ -77,7 +74,7 @@ class CivilizedScholarEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
player.drawCards(1, game);
player.drawCards(1, source.getSourceId(), game);
Card card = player.discardOne(false, source, game);
if (card != null && card.isCreature()) {
Permanent permanent = game.getPermanent(source.getSourceId());

View file

@ -114,7 +114,7 @@ class ClackbridgeTrollEffect extends OneShotEffect {
sourcePerm.tap(game);
}
controller.gainLife(3, game, source);
controller.drawCards(1, game);
controller.drawCards(1, source.getSourceId(), game);
}
return true;
}

View file

@ -72,7 +72,7 @@ class ClingToDustEffect extends OneShotEffect {
if (isCreature) {
player.gainLife(3, game, source);
} else {
player.drawCards(1, game);
player.drawCards(1, source.getSourceId(), game);
}
return true;
}

View file

@ -69,7 +69,7 @@ class CoercedConfessionMillEffect extends OneShotEffect {
if (foundCreatures > 0) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
controller.drawCards(foundCreatures, game);
controller.drawCards(foundCreatures, source.getSourceId(), game);
}
}
return true;

View file

@ -77,7 +77,7 @@ class CoercivePortalEffect extends OneShotEffect {
new SacrificeSourceEffect().apply(game, source);
new DestroyAllEffect(new FilterNonlandPermanent()).apply(game, source);
} else {
controller.drawCards(1, game);
controller.drawCards(1, source.getSourceId(), game);
}
return true;
}

View file

@ -68,7 +68,7 @@ class ColdEyeSelkieEffect extends OneShotEffect {
if (amount > 0) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
controller.drawCards(amount, game);
controller.drawCards(amount, source.getSourceId(), game);
return true;
}
}

View file

@ -95,7 +95,7 @@ class CollectiveDefianceEffect extends OneShotEffect {
for (Card card : targetPlayer.getHand().getCards(game)) {
targetPlayer.discard(card, source, game);
}
targetPlayer.drawCards(count, game);
targetPlayer.drawCards(count, source.getSourceId(), game);
return true;
}
return false;

View file

@ -60,7 +60,7 @@ class CommenceTheEndgameEffect extends OneShotEffect {
if (player == null) {
return false;
}
player.drawCards(2, game);
player.drawCards(2, source.getSourceId(), game);
return new AmassEffect(player.getHand().size()).apply(game, source);
}
}

View file

@ -64,7 +64,7 @@ class ConchHornEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
player.drawCards(2, game);
player.drawCards(2, source.getSourceId(), game);
putOnLibrary(player, source, game);
return true;
}

View file

@ -74,12 +74,12 @@ class CovenantOfMindsEffect extends OneShotEffect {
player.moveCards(cards, Zone.HAND, source, game);
} else {
player.moveCards(cards, Zone.GRAVEYARD, source, game);
player.drawCards(5, game);
player.drawCards(5, source.getSourceId(), game);
}
} else {
if (!opponent.chooseUse(Outcome.Benefit, player.getLogName() + "'s library is empty? Do you want them to draw five cards?", source, game)) {
player.drawCards(5, game);
player.drawCards(5, source.getSourceId(), game);
}
}

View file

@ -71,7 +71,7 @@ class CranialArchiveEffect extends OneShotEffect {
}
targetPlayer.shuffleLibrary(source, game);
}
controller.drawCards(1, game);
controller.drawCards(1, source.getSourceId(), game);
return true;
}
return false;

View file

@ -79,7 +79,7 @@ class CreditVoucherEffect extends OneShotEffect {
}
controller.shuffleLibrary(source, game);
if (amountShuffled > 0) {
controller.drawCards(amountShuffled, game);
controller.drawCards(amountShuffled, source.getSourceId(), game);
}
return true;
}

View file

@ -66,7 +66,7 @@ class CullingDaisEffect extends OneShotEffect {
Player player = game.getPlayer(source.getControllerId());
if (p != null && player != null) {
int count = p.getCounters(game).getCount(CounterType.CHARGE);
player.drawCards(count, game);
player.drawCards(count, source.getSourceId(), game);
return true;
}
return false;

View file

@ -115,7 +115,7 @@ class CurseOfChaosEffect extends OneShotEffect {
if (attacker != null) {
if (!attacker.getHand().isEmpty() && attacker.chooseUse(outcome, "Discard a card and draw a card?", source, game)) {
attacker.discard(1, false, source, game);
attacker.drawCards(1, game);
attacker.drawCards(1, source.getSourceId(), game);
}
return true;
}

View file

@ -157,7 +157,7 @@ class CurseOfVengeanceDrawLifeEffect extends OneShotEffect {
Permanent sourceObject = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (sourceObject != null && controller != null) {
if (sourceObject.getCounters(game).containsKey(CounterType.SPITE)) {
controller.drawCards(sourceObject.getCounters(game).getCount(CounterType.SPITE), game);
controller.drawCards(sourceObject.getCounters(game).getCount(CounterType.SPITE), source.getSourceId(), game);
controller.gainLife(sourceObject.getCounters(game).getCount(CounterType.SPITE), game, source);
}
return true;

View file

@ -52,7 +52,7 @@ class DamnablePactEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source));
if (targetPlayer != null) {
targetPlayer.drawCards(source.getManaCostsToPay().getX(), game);
targetPlayer.drawCards(source.getManaCostsToPay().getX(), source.getSourceId(), game);
targetPlayer.loseLife(source.getManaCostsToPay().getX(), game, false);
return true;
}

View file

@ -79,7 +79,7 @@ class DaredevilDragsterEffect extends OneShotEffect {
permanent.addCounters(CounterType.VELOCITY.createInstance(), source, game);
if (permanent.getCounters(game).getCount(CounterType.VELOCITY) >= 2) {
permanent.sacrifice(source.getSourceId(), game);
controller.drawCards(2, game);
controller.drawCards(2, source.getSourceId(), game);
}
return true;
}

View file

@ -101,7 +101,7 @@ class DarettiDiscardDrawEffect extends OneShotEffect {
count++;
}
}
controller.drawCards(count, game);
controller.drawCards(count, source.getSourceId(), game);
return true;
}
return false;

View file

@ -5,7 +5,6 @@ import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import com.j256.ormlite.stmt.query.In;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
@ -72,7 +71,7 @@ class DarkDealEffect extends OneShotEffect {
for (Map.Entry<UUID, Integer> toDrawByPlayer : cardsToDraw.entrySet()) {
Player player = game.getPlayer(toDrawByPlayer.getKey());
if (player != null) {
player.drawCards(toDrawByPlayer.getValue(), game);
player.drawCards(toDrawByPlayer.getValue(), source.getSourceId(), game);
}
}
return true;

View file

@ -128,7 +128,7 @@ class DarkIntimationsEffect extends OneShotEffect {
}
controller.moveCards(card, Zone.HAND, source, game);
}
controller.drawCards(1, game);
controller.drawCards(1, source.getSourceId(), game);
return true;
}
}

View file

@ -73,7 +73,7 @@ class DecreeOfPainEffect extends OneShotEffect {
}
}
if (destroyedCreature > 0) {
controller.drawCards(destroyedCreature, game);
controller.drawCards(destroyedCreature, source.getSourceId(), game);
}
return true;
}

View file

@ -62,7 +62,7 @@ class DesperateRavingsEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
player.drawCards(2, game);
player.drawCards(2, source.getSourceId(), game);
Cards hand = player.getHand();
Card card = hand.getRandom(game);
player.discard(card, source, game);

View file

@ -72,7 +72,7 @@ class DiminishingReturnsEffect extends OneShotEffect {
Player player = game.getPlayer(playerId);
if (player != null) {
int cardsToDrawCount = player.getAmount(0, 7, "How many cards to draw (up to 7)?", game);
player.drawCards(cardsToDrawCount, game);
player.drawCards(cardsToDrawCount, source.getSourceId(), game);
}
}
}

View file

@ -59,7 +59,7 @@ class DimirCutpurseEffect extends OneShotEffect {
damagedPlayer.discard(1, false,source, game);
}
if (you != null) {
you.drawCards(1, game);
you.drawCards(1, source.getSourceId(), game);
}
return true;
}

View file

@ -75,7 +75,7 @@ class DiscipleOfBolasEffect extends OneShotEffect {
sacrificed.sacrifice(source.getSourceId(), game);
int power = sacrificed.getPower().getValue();
controller.gainLife(power, game, source);
controller.drawCards(power, game);
controller.drawCards(power, source.getSourceId(), game);
}
}
return true;

View file

@ -85,7 +85,7 @@ class DistantMemoriesEffect extends OneShotEffect {
if (putInHand) {
controller.moveCards(card, Zone.HAND, source, game);
} else {
controller.drawCards(3, game);
controller.drawCards(3, source.getSourceId(), game);
}
return true;
}

View file

@ -64,8 +64,8 @@ class DivinerSpiritEffect extends OneShotEffect {
if (sourceController != null && damagedPlayer != null) {
int amount = (Integer) getValue("damage");
if (amount > 0) {
sourceController.drawCards(amount, game);
damagedPlayer.drawCards(amount, game);
sourceController.drawCards(amount, source.getSourceId(), game);
damagedPlayer.drawCards(amount, source.getSourceId(), game);
return true;
}
}

View file

@ -84,7 +84,7 @@ class DivinersLockboxEffect extends OneShotEffect {
player.revealCards(source, new CardsImpl(card), game);
if (choice.getChoice().equals(card.getName())) {
sacEffect.apply(game, source);
player.drawCards(3, game);
player.drawCards(3, source.getSourceId(), game);
}
return true;
}

View file

@ -96,7 +96,7 @@ class DoomForetoldEffect extends OneShotEffect {
}
player.discard(1, false, source, game);
player.loseLife(2, game, false);
controller.drawCards(1, game);
controller.drawCards(1, source.getSourceId(), game);
controller.gainLife(2, game, source);
effect1.apply(game, source);
effect2.apply(game, source);

View file

@ -51,7 +51,7 @@ class DrasticRevelationEffect extends OneShotEffect {
Player you = game.getPlayer(source.getControllerId());
if (you != null) {
you.discard(you.getHand().size(), false, source, game);
you.drawCards(7, game);
you.drawCards(7, source.getSourceId(), game);
Cards hand = you.getHand();
for (int i = 0; i < 3; i++) {
Card card = hand.getRandom(game);

View file

@ -58,7 +58,7 @@ class DreamCacheEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
controller.drawCards(3, game);
controller.drawCards(3, source.getSourceId(), game);
boolean putOnTop = controller.chooseUse(Outcome.Neutral, "Put cards on top?", source, game);
TargetCardInHand target = new TargetCardInHand(2, 2, new FilterCard());
controller.chooseTarget(Outcome.Detriment, target, source, game);

View file

@ -70,7 +70,7 @@ class DreamFractureEffect extends OneShotEffect {
countered = true;
}
if (controller != null) {
controller.drawCards(1, game);
controller.drawCards(1, source.getSourceId(), game);
}
return countered;
}

View file

@ -3,7 +3,6 @@ package mage.cards.d;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
@ -97,7 +96,7 @@ class DreamSalvageEffect extends OneShotEffect {
&& controller != null
&& watcher != null
&& watcher.getAmountCardsDiscarded(targetOpponent.getId()) > 0) {
controller.drawCards(watcher.getAmountCardsDiscarded(targetOpponent.getId()), game);
controller.drawCards(watcher.getAmountCardsDiscarded(targetOpponent.getId()), source.getSourceId(), game);
return true;
}
return false;

View file

@ -67,7 +67,7 @@ class ExcavationEffect extends OneShotEffect {
if (source instanceof ActivatedAbilityImpl) {
Player activator = game.getPlayer(((ActivatedAbilityImpl) source).getActivatorId());
if (activator != null) {
activator.drawCards(1, game);
activator.drawCards(1, source.getSourceId(), game);
return true;
}

View file

@ -85,7 +85,7 @@ class ExplosionEffect extends OneShotEffect {
effect.apply(game, source);
Player player = game.getPlayer(source.getTargets().get(1).getFirstTarget());
if (player != null) {
player.drawCards(xValue, game);
player.drawCards(xValue, source.getSourceId(), game);
}
return true;
}

View file

@ -71,7 +71,7 @@ class FaadiyahSeerEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Card card = controller.getLibrary().getFromTop(game);
controller.drawCards(1, game);
controller.drawCards(1, source.getSourceId(), game);
controller.revealCards("Fa'adiyah Seer", new CardsImpl(card), game);
if (!filter.match(card, game)) {
controller.discard(card, source, game);

View file

@ -67,7 +67,7 @@ class FatalLoreEffect extends OneShotEffect {
if (controller != null
&& chosenOpponent != null) {
if (chosenOpponent.chooseUse(Outcome.Neutral, "If you choose Yes, the controller draws three cards. If no, the controller gets to destroy up to two target creatures that you control and you get to draw up to 3 cards. Those creatures can't be regenerated.", source, game)) {
controller.drawCards(3, game);
controller.drawCards(3, source.getSourceId(), game);
} else {
FilterCreaturePermanent filter = new FilterCreaturePermanent("chosen opponent's creature");
filter.add(new ControllerIdPredicate(chosenOpponent.getId()));

View file

@ -60,7 +60,7 @@ class FecundityEffect extends OneShotEffect {
Player controller = game.getPlayer(permanent.getControllerId());
if (controller != null) {
if (controller.chooseUse(outcome, "Draw a card?", source, game)) {
controller.drawCards(1, game);
controller.drawCards(1, source.getSourceId(), game);
}
return true;
}

View file

@ -54,7 +54,7 @@ class FeveredVisionsEffect extends OneShotEffect {
UUID activePlayerId = game.getActivePlayerId();
Player player = game.getPlayer(activePlayerId);
if (controller != null && player != null) {
player.drawCards(1, game);
player.drawCards(1, source.getSourceId(), game);
Set<UUID> opponents = game.getOpponents(source.getControllerId());
if (opponents.contains(player.getId()) && player.getHand().size() > 3) {
player.damage(2, source.getSourceId(), game);

View file

@ -81,7 +81,7 @@ class FieryGambitEffect extends OneShotEffect {
new DamagePlayersEffect(6, TargetController.OPPONENT).apply(game, source);
}
if (flipsWon > 2) {
controller.drawCards(9, game);
controller.drawCards(9, source.getSourceId(), game);
new UntapAllLandsControllerEffect().apply(game, source);
}
} else {

View file

@ -63,7 +63,7 @@ class FiligreeFractureEffect extends OneShotEffect {
permanent.destroy(source.getSourceId(), game, true);
game.applyEffects();
if (permanent.getColor(game).isBlack() || permanent.getColor(game).isBlue()) {
player.drawCards(1, game);
player.drawCards(1, source.getSourceId(), game);
}
return true;
}

View file

@ -66,11 +66,11 @@ class FinaleOfRevelationEffect extends OneShotEffect {
int xValue = source.getManaCostsToPay().getX();
if (xValue < 10) {
player.drawCards(xValue, game);
player.drawCards(xValue, source.getSourceId(), game);
} else {
player.putCardsOnTopOfLibrary(player.getGraveyard(), game, source, false);
player.shuffleLibrary(source, game);
player.drawCards(xValue, game);
player.drawCards(xValue, source.getSourceId(), game);
new UntapLandsEffect(5).apply(game, source);
game.addEffect(new MaximumHandSizeControllerEffect(
Integer.MAX_VALUE, Duration.EndOfGame,

View file

@ -74,7 +74,7 @@ class FireProphecyEffect extends OneShotEffect {
return false;
}
player.getLibrary().putOnBottom(card, game);
player.drawCards(1, game);
player.drawCards(1, source.getSourceId(), game);
return true;
}
}

View file

@ -61,7 +61,7 @@ class FluxEffect extends OneShotEffect {
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);
player.drawCards(numToDiscard, source.getSourceId(), game);
}
}
return true;

Some files were not shown because too many files have changed in this diff Show more