This commit is contained in:
maurer.it 2010-12-29 13:40:36 -05:00
commit 4653a53078
127 changed files with 3754 additions and 788 deletions

View file

@ -50,23 +50,17 @@ import java.util.logging.Logger;
import java.util.prefs.Preferences; import java.util.prefs.Preferences;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import javax.swing.Box; import javax.swing.*;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JToolBar.Separator; import javax.swing.JToolBar.Separator;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import com.sun.java.swing.Painter;
import mage.cards.decks.Deck;
import mage.client.cards.CardsStorage; import mage.client.cards.CardsStorage;
import mage.client.components.MageComponents; import mage.client.components.MageComponents;
import mage.client.components.MageJDesktop;
import mage.client.components.MageRoundPane;
import mage.client.components.arcane.ManaSymbols; import mage.client.components.arcane.ManaSymbols;
import mage.client.constants.Constants.DeckEditorMode;
import mage.client.dialog.*; import mage.client.dialog.*;
import mage.client.plugins.impl.Plugins; import mage.client.plugins.impl.Plugins;
import mage.client.remote.Session; import mage.client.remote.Session;
@ -122,6 +116,7 @@ public class MageFrame extends javax.swing.JFrame {
}); });
try { try {
UIManager.put("desktop", new Color(0,0,0,0));
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"); UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
//MageSynthStyleFactory f = new MageSynthStyleFactory(SynthLookAndFeel.getStyleFactory()); //MageSynthStyleFactory f = new MageSynthStyleFactory(SynthLookAndFeel.getStyleFactory());
//SynthLookAndFeel.setStyleFactory(f); //SynthLookAndFeel.setStyleFactory(f);
@ -145,60 +140,12 @@ public class MageFrame extends javax.swing.JFrame {
desktopPane.add(pickNumber, JLayeredPane.POPUP_LAYER); desktopPane.add(pickNumber, JLayeredPane.POPUP_LAYER);
session.getUI().addComponent(MageComponents.DESKTOP_PANE, desktopPane); session.getUI().addComponent(MageComponents.DESKTOP_PANE, desktopPane);
JComponent cardInfoPane = Plugins.getInstance().getCardInfoPane();
cardInfoPane.setSize(161, 221);
cardInfoPane.setPreferredSize(new Dimension(161, 221));
cardInfoPane.setVisible(false);
session.getUI().addComponent(MageComponents.CARD_INFO_PANE, cardInfoPane);
desktopPane.add(cardInfoPane, JLayeredPane.POPUP_LAYER);
ManaSymbols.loadImages(); ManaSymbols.loadImages();
String filename = "/background.jpg"; addTooltipContainer();
try { setBackground();
if (Plugins.getInstance().isThemePluginLoaded()) { addMageLabel();
Map<String, JComponent> ui = new HashMap<String, JComponent>(); setAppIcon();
backgroundPane = (ImagePanel) Plugins.getInstance().updateTablePanel(ui);
} else {
InputStream is = this.getClass().getResourceAsStream(filename);
BufferedImage background = ImageIO.read(is);
backgroundPane = new ImagePanel(background, ImagePanel.SCALED);
}
backgroundPane.setSize(1024, 768);
desktopPane.add(backgroundPane, JLayeredPane.DEFAULT_LAYER);
} catch (IOException e) {
e.printStackTrace();
}
filename = "/label-mage.png";
try {
InputStream is = this.getClass().getResourceAsStream(filename);
float ratio = 1179.0f / 678.0f;
titleRectangle = new Rectangle(640, (int)(640 / ratio));
if (is != null) {
BufferedImage image = ImageIO.read(is);
//ImageIcon resized = new ImageIcon(image.getScaledInstance(titleRectangle.width, titleRectangle.height, java.awt.Image.SCALE_SMOOTH));
title = new JLabel();
title.setIcon(new ImageIcon(image));
backgroundPane.setLayout(null);
backgroundPane.add(title);
}
} catch (IOException e) {
e.printStackTrace();
}
filename = "/icon-mage.png";
try {
InputStream is = this.getClass().getResourceAsStream(filename);
if (is != null) {
BufferedImage image = ImageIO.read(is);
setIconImage(image);
}
} catch (IOException e) {
e.printStackTrace();
}
desktopPane.add(ArrowBuilder.getArrowsPanel(), JLayeredPane.DRAG_LAYER); desktopPane.add(ArrowBuilder.getArrowsPanel(), JLayeredPane.DRAG_LAYER);
@ -271,6 +218,77 @@ public class MageFrame extends javax.swing.JFrame {
}); });
} }
private void addTooltipContainer() {
final JEditorPane cardInfoPane = (JEditorPane) Plugins.getInstance().getCardInfoPane();
cardInfoPane.setSize(320, 201);
cardInfoPane.setLocation(40, 40);
cardInfoPane.setBackground(new Color(0,0,0,0));
MageRoundPane popupContainer = new MageRoundPane();
popupContainer.setLayout(null);
popupContainer.add(cardInfoPane);
popupContainer.setVisible(false);
popupContainer.setBounds(0, 0, 320 + 80, 201 + 80);
desktopPane.add(popupContainer, JLayeredPane.POPUP_LAYER);
session.getUI().addComponent(MageComponents.CARD_INFO_PANE, cardInfoPane);
session.getUI().addComponent(MageComponents.POPUP_CONTAINER, popupContainer);
}
private void setBackground() {
String filename = "/background.jpg";
try {
if (Plugins.getInstance().isThemePluginLoaded()) {
Map<String, JComponent> ui = new HashMap<String, JComponent>();
backgroundPane = (ImagePanel) Plugins.getInstance().updateTablePanel(ui);
} else {
InputStream is = this.getClass().getResourceAsStream(filename);
BufferedImage background = ImageIO.read(is);
backgroundPane = new ImagePanel(background, ImagePanel.SCALED);
}
backgroundPane.setSize(1024, 768);
desktopPane.add(backgroundPane, JLayeredPane.DEFAULT_LAYER);
} catch (IOException e) {
e.printStackTrace();
}
}
private void addMageLabel() {
String filename = "/label-mage.png";
try {
InputStream is = this.getClass().getResourceAsStream(filename);
float ratio = 1179.0f / 678.0f;
titleRectangle = new Rectangle(640, (int)(640 / ratio));
if (is != null) {
BufferedImage image = ImageIO.read(is);
//ImageIcon resized = new ImageIcon(image.getScaledInstance(titleRectangle.width, titleRectangle.height, java.awt.Image.SCALE_SMOOTH));
title = new JLabel();
title.setIcon(new ImageIcon(image));
backgroundPane.setLayout(null);
backgroundPane.add(title);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void setAppIcon() {
String filename = "/icon-mage.png";
try {
InputStream is = this.getClass().getResourceAsStream(filename);
if (is != null) {
BufferedImage image = ImageIO.read(is);
setIconImage(image);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void btnImagesActionPerformed(java.awt.event.ActionEvent evt) { private void btnImagesActionPerformed(java.awt.event.ActionEvent evt) {
Plugins.getInstance().downloadImage(CardsStorage.getAllCards()); Plugins.getInstance().downloadImage(CardsStorage.getAllCards());
} }
@ -337,7 +355,7 @@ public class MageFrame extends javax.swing.JFrame {
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() { private void initComponents() {
desktopPane = new javax.swing.JDesktopPane(); desktopPane = new MageJDesktop();
tablesPane = new mage.client.table.TablesPane(); tablesPane = new mage.client.table.TablesPane();
gamePane = new mage.client.game.GamePane(); gamePane = new mage.client.game.GamePane();
deckEditorPane = new mage.client.deckeditor.DeckEditorPane(); deckEditorPane = new mage.client.deckeditor.DeckEditorPane();
@ -486,11 +504,10 @@ public class MageFrame extends javax.swing.JFrame {
private void btnDeckEditorActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDeckEditorActionPerformed private void btnDeckEditorActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDeckEditorActionPerformed
this.gamePane.setVisible(false); this.gamePane.setVisible(false);
this.tablesPane.setVisible(false); this.tablesPane.setVisible(false);
this.deckEditorPane.setVisible(true); showDeckEditor(DeckEditorMode.Constructed, null, null);
this.deckEditorPane.showTables();
}//GEN-LAST:event_btnDeckEditorActionPerformed }//GEN-LAST:event_btnDeckEditorActionPerformed
private void btnPreferencesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDeckEditorActionPerformed private void btnPreferencesActionPerformed(java.awt.event.ActionEvent evt) {
PhasesDialog.main(new String[]{}); PhasesDialog.main(new String[]{});
} }
@ -546,6 +563,11 @@ public class MageFrame extends javax.swing.JFrame {
this.deckEditorPane.setVisible(false); this.deckEditorPane.setVisible(false);
} }
public void showDeckEditor(DeckEditorMode mode, Deck deck, UUID tableId) {
this.deckEditorPane.setVisible(true);
this.deckEditorPane.show(mode, deck, tableId);
}
public static CombatDialog getCombatDialog() { public static CombatDialog getCombatDialog() {
return combat; return combat;
} }
@ -595,7 +617,7 @@ public class MageFrame extends javax.swing.JFrame {
private javax.swing.JButton btnExit; private javax.swing.JButton btnExit;
private javax.swing.JButton btnGames; private javax.swing.JButton btnGames;
private mage.client.deckeditor.DeckEditorPane deckEditorPane; private mage.client.deckeditor.DeckEditorPane deckEditorPane;
private static javax.swing.JDesktopPane desktopPane; private static MageJDesktop desktopPane;
private mage.client.game.GamePane gamePane; private mage.client.game.GamePane gamePane;
private javax.swing.JToolBar.Separator jSeparator1; private javax.swing.JToolBar.Separator jSeparator1;
private javax.swing.JToolBar.Separator jSeparator2; private javax.swing.JToolBar.Separator jSeparator2;

View file

@ -6,7 +6,8 @@ public enum MageComponents {
NEW_TABLE_OK_BUTTON("btnOK"), NEW_TABLE_OK_BUTTON("btnOK"),
TABLE_WAITING_START_BUTTON("btnStart"), TABLE_WAITING_START_BUTTON("btnStart"),
DESKTOP_PANE("desktopPane"), DESKTOP_PANE("desktopPane"),
CARD_INFO_PANE("cardInfoPane"); CARD_INFO_PANE("cardInfoPane"),
POPUP_CONTAINER("popupContainer");
private String name; private String name;
MageComponents(String name) { MageComponents(String name) {

View file

@ -0,0 +1,34 @@
package mage.client.components;
import com.sun.java.swing.Painter;
import javax.swing.*;
import java.awt.*;
/**
* Overrides JDesktopPane settings for Nimbus LAF.
*
* @author nantuko
*/
public class MageJDesktop extends JDesktopPane {
@Override
public void updateUI() {
if ("Nimbus".equals(UIManager.getLookAndFeel().getName())) {
UIDefaults map = new UIDefaults();
Painter painter = new Painter() {
Color color = null;
@Override
public void paint(Graphics2D g, Object c, int w, int h) {
g.setColor(color == null ? UIManager.getDefaults().getColor("desktop") : color);
g.fillRect(0,0,w,h);
}
};
map.put("DesktopPane[Enabled].backgroundPainter", painter);
putClientProperty("Nimbus.Overrides", map);
}
super.updateUI();
}
}

View file

@ -0,0 +1,97 @@
package mage.client.components;
import org.jdesktop.swingx.graphics.GraphicsUtilities;
import org.jdesktop.swingx.graphics.ShadowRenderer;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
/**
* Mage round pane with transparency.
* Used for tooltips.
*
* @author nantuko
*/
public class MageRoundPane extends JPanel {
private static int X_OFFSET = 30;
private static int Y_OFFSET = 30;
private BufferedImage shadow = null;
private Color backgroundColor = new Color(255, 255, 255, 220);
private int alpha = 0;
@Override
protected void paintComponent(Graphics g) {
int x = X_OFFSET;
int y = Y_OFFSET;
int w = getWidth() - 2 * X_OFFSET;
int h = getHeight() - 2 * Y_OFFSET;
int arc = 10;
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
if (shadow != null) {
int xOffset = (shadow.getWidth() - w) / 2;
int yOffset = (shadow.getHeight() - h) / 2;
g2.drawImage(shadow, x - xOffset, y - yOffset, null);
}
//////////////////////////////////////////////////////////////////
// fill content
/**
* Add white translucent substrate
*/
/*if (alpha != 0) {
g2.setColor(new Color(255, 255, 255, alpha));
g2.fillRoundRect(x, y, w, h, arc, arc);
}*/
g2.setColor(backgroundColor);
g2.fillRoundRect(x, y, w, h, arc, arc);
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// draw border
g2.setStroke(new BasicStroke(1.5f));
g2.setColor(Color.BLACK);
g2.drawRoundRect(x, y, w, h, arc, arc);
// ////////////////////////////////////////////////////////////////
g2.dispose();
}
@Override
public void setBounds(int x, int y, int width, int height) {
super.setBounds(x, y, width, height);
int w = getWidth() - 2 * X_OFFSET;
int h = getHeight() - 2 * Y_OFFSET;
int arc = 10;
int shadowSize = 50;
shadow = GraphicsUtilities.createCompatibleTranslucentImage(w, h);
Graphics2D g2 = shadow.createGraphics();
g2.setColor(Color.WHITE);
g2.fillRoundRect(0, 0, w, h, arc, arc);
g2.dispose();
ShadowRenderer renderer = new ShadowRenderer(shadowSize, 0.5f,
Color.GRAY);
shadow = renderer.createShadow(shadow);
}
public void showDialog(boolean bShow) {
setVisible(bShow);
}
/**
* Default UID.
*/
private static final long serialVersionUID = 1L;
}

View file

@ -82,4 +82,11 @@ public final class Constants {
public static final String imageBaseDir = "plugins" + File.separator + "images" + File.separator; public static final String imageBaseDir = "plugins" + File.separator + "images" + File.separator;
public static final String IMAGE_PROPERTIES_FILE = "image.url.properties"; public static final String IMAGE_PROPERTIES_FILE = "image.url.properties";
} }
public enum DeckEditorMode {
Constructed,
Limited,
Sideboard
}
} }

View file

@ -46,6 +46,8 @@ public class DeckGenerator {
private static final int MIN_SOURCE = 16; private static final int MIN_SOURCE = 16;
private static final int MAX_NON_BASIC_SOURCE = DECK_LANDS / 2; private static final int MAX_NON_BASIC_SOURCE = DECK_LANDS / 2;
private static final boolean GENERATE_RANDOM_BASIC_LAND = true;
private static Deck deck = new Deck(); private static Deck deck = new Deck();
private static String manaSource; private static String manaSource;
@ -283,19 +285,19 @@ public class DeckGenerator {
private static Card getBestBasicLand(ColoredManaSymbol color) { private static Card getBestBasicLand(ColoredManaSymbol color) {
manaSource = color.toString(); manaSource = color.toString();
if (color.equals(ColoredManaSymbol.G)) { if (color.equals(ColoredManaSymbol.G)) {
return CardImpl.createCard(Sets.findCard("Forest")); return CardImpl.createCard(Sets.findCard("Forest", GENERATE_RANDOM_BASIC_LAND));
} }
if (color.equals(ColoredManaSymbol.R)) { if (color.equals(ColoredManaSymbol.R)) {
return CardImpl.createCard(Sets.findCard("Mountain")); return CardImpl.createCard(Sets.findCard("Mountain", GENERATE_RANDOM_BASIC_LAND));
} }
if (color.equals(ColoredManaSymbol.B)) { if (color.equals(ColoredManaSymbol.B)) {
return CardImpl.createCard(Sets.findCard("Swamp")); return CardImpl.createCard(Sets.findCard("Swamp", GENERATE_RANDOM_BASIC_LAND));
} }
if (color.equals(ColoredManaSymbol.U)) { if (color.equals(ColoredManaSymbol.U)) {
return CardImpl.createCard(Sets.findCard("Island")); return CardImpl.createCard(Sets.findCard("Island", GENERATE_RANDOM_BASIC_LAND));
} }
if (color.equals(ColoredManaSymbol.W)) { if (color.equals(ColoredManaSymbol.W)) {
return CardImpl.createCard(Sets.findCard("Plains")); return CardImpl.createCard(Sets.findCard("Plains", GENERATE_RANDOM_BASIC_LAND));
} }
return null; return null;

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.1" encoding="UTF-8" ?>
<Form version="1.3" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JInternalFrameFormInfo"> <Form version="1.3" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JInternalFrameFormInfo">
<SyntheticProperties> <SyntheticProperties>

View file

@ -37,10 +37,13 @@ package mage.client.deckeditor;
import java.awt.Component; import java.awt.Component;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.UUID;
import javax.swing.JComponent; import javax.swing.JComponent;
import mage.cards.decks.Deck;
import mage.client.MagePane; import mage.client.MagePane;
import mage.client.constants.Constants.DeckEditorMode;
import mage.client.plugins.impl.Plugins; import mage.client.plugins.impl.Plugins;
/** /**
@ -70,8 +73,8 @@ public class DeckEditorPane extends MagePane {
} }
} }
public void showTables() { public void show(DeckEditorMode mode, Deck deck, UUID tableId) {
this.deckEditorPanel1.showDeckEditor(); this.deckEditorPanel1.showDeckEditor(mode, deck, tableId);
this.repaint(); this.repaint();
} }

View file

@ -36,7 +36,6 @@ package mage.client.deckeditor;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.decks.Deck; import mage.cards.decks.Deck;
import mage.cards.decks.DeckCardLists;
import mage.client.MageFrame; import mage.client.MageFrame;
import mage.client.plugins.impl.Plugins; import mage.client.plugins.impl.Plugins;
import mage.client.util.Event; import mage.client.util.Event;
@ -49,14 +48,13 @@ import mage.view.CardsView;
import javax.swing.*; import javax.swing.*;
import javax.swing.filechooser.FileFilter; import javax.swing.filechooser.FileFilter;
import java.awt.*; import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.util.UUID; import java.util.UUID;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import mage.client.constants.Constants.DeckEditorMode;
import mage.sets.Sets; import mage.sets.Sets;
/** /**
@ -69,6 +67,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
private JFileChooser fcImportDeck; private JFileChooser fcImportDeck;
private Deck deck = new Deck(); private Deck deck = new Deck();
private boolean isShowCardInfo = false; private boolean isShowCardInfo = false;
private UUID tableId;
/** Creates new form DeckEditorPanel */ /** Creates new form DeckEditorPanel */
public DeckEditorPanel() { public DeckEditorPanel() {
@ -85,10 +84,18 @@ public class DeckEditorPanel extends javax.swing.JPanel {
jSplitPane1.setOpaque(false); jSplitPane1.setOpaque(false);
} }
public void showDeckEditor() { public void showDeckEditor(DeckEditorMode mode, Deck deck, UUID tableId) {
if (deck != null)
this.deck = deck;
this.tableId = tableId;
showDeckEditor(mode);
}
public void showDeckEditor(DeckEditorMode mode) {
this.cardSelector.loadCards(this.bigCard); this.cardSelector.loadCards(this.bigCard);
this.cardSelector.setVisible(true); this.cardSelector.setVisible(true);
this.jPanel1.setVisible(true); this.jPanel1.setVisible(true);
this.btnSubmit.setVisible(mode == DeckEditorMode.Sideboard);
this.cardSelector.getCardsList().clearCardEventListeners(); this.cardSelector.getCardsList().clearCardEventListeners();
this.cardSelector.getCardsList().addCardEventListener( this.cardSelector.getCardsList().addCardEventListener(
new Listener<Event> () { new Listener<Event> () {
@ -132,6 +139,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
} }
} }
); );
refreshDeck();
this.setVisible(true); this.setVisible(true);
this.repaint(); this.repaint();
} }
@ -172,6 +180,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
btnNew = new javax.swing.JButton(); btnNew = new javax.swing.JButton();
btnExit = new javax.swing.JButton(); btnExit = new javax.swing.JButton();
btnImport = new javax.swing.JButton(); btnImport = new javax.swing.JButton();
btnSubmit = new javax.swing.JButton();
jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
jSplitPane1.setResizeWeight(0.5); jSplitPane1.setResizeWeight(0.5);
@ -229,6 +238,14 @@ public class DeckEditorPanel extends javax.swing.JPanel {
} }
}); });
btnSubmit.setText("Submit");
btnSubmit.setName("btnSubmit"); // NOI18N
btnSubmit.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnSubmitActionPerformed(evt);
}
});
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout); jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup( jPanel1Layout.setHorizontalGroup(
@ -253,7 +270,9 @@ public class DeckEditorPanel extends javax.swing.JPanel {
.addComponent(btnExit)) .addComponent(btnExit))
.addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(btnImport))) .addComponent(btnImport)
.addContainerGap()
.addComponent(btnSubmit)))
.addContainerGap()) .addContainerGap())
); );
jPanel1Layout.setVerticalGroup( jPanel1Layout.setVerticalGroup(
@ -270,7 +289,9 @@ public class DeckEditorPanel extends javax.swing.JPanel {
.addComponent(btnNew) .addComponent(btnNew)
.addComponent(btnExit)) .addComponent(btnExit))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnImport) .addComponent(btnImport)
.addComponent(btnSubmit))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, isShowCardInfo ? 30 : 159, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, isShowCardInfo ? 30 : 159, Short.MAX_VALUE)
.addComponent(cardInfoPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(cardInfoPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(bigCard, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(bigCard, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
@ -383,6 +404,11 @@ public class DeckEditorPanel extends javax.swing.JPanel {
fcImportDeck.setSelectedFile(null); fcImportDeck.setSelectedFile(null);
}//GEN-LAST:event_btnImportActionPerformed }//GEN-LAST:event_btnImportActionPerformed
private void btnSubmitActionPerformed(java.awt.event.ActionEvent evt) {
MageFrame.getSession().submitDeck(tableId, deck.getDeckCardLists());
this.setVisible(false);
}
public DeckImporter getDeckImporter(String file) { public DeckImporter getDeckImporter(String file) {
if (file.toLowerCase().endsWith("dec")) if (file.toLowerCase().endsWith("dec"))
return new DecDeckImporter(); return new DecDeckImporter();
@ -410,6 +436,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
// End of variables declaration//GEN-END:variables // End of variables declaration//GEN-END:variables
private JComponent cardInfoPane; private JComponent cardInfoPane;
private javax.swing.JButton btnSubmit;
} }
class DeckFilter extends FileFilter { class DeckFilter extends FileFilter {

View file

@ -138,7 +138,6 @@ public class JoinTableDialog extends MageDialog {
private void btnOKActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOKActionPerformed private void btnOKActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOKActionPerformed
Session session = MageFrame.getSession(); Session session = MageFrame.getSession();
try { try {
PhaseManager.getInstance().setName(this.newPlayerPanel.getPlayerName());
joined = session.joinTable(roomId, tableId, this.newPlayerPanel.getPlayerName(), Sets.loadDeck(this.newPlayerPanel.getDeckFile())); joined = session.joinTable(roomId, tableId, this.newPlayerPanel.getPlayerName(), Sets.loadDeck(this.newPlayerPanel.getDeckFile()));
} catch (Exception ex) { } catch (Exception ex) {
handleError(ex); handleError(ex);

View file

@ -23,7 +23,7 @@
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0"> <Group type="102" alignment="1" attributes="0">
<EmptySpace pref="358" max="32767" attributes="0"/> <EmptySpace pref="395" max="32767" attributes="0"/>
<Component id="btnOK" min="-2" max="-2" attributes="0"/> <Component id="btnOK" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="btnCancel" min="-2" max="-2" attributes="0"/> <Component id="btnCancel" min="-2" max="-2" attributes="0"/>
@ -32,7 +32,7 @@
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="lbDeckType" min="-2" max="-2" attributes="0"/> <Component id="lbDeckType" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="426" max="32767" attributes="0"/> <EmptySpace pref="463" max="32767" attributes="0"/>
</Group> </Group>
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
@ -41,17 +41,22 @@
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="lblNumPlayers" min="-2" max="-2" attributes="0"/> <Component id="lblNumPlayers" min="-2" max="-2" attributes="0"/>
<Component id="spnNumPlayers" min="-2" pref="90" max="-2" attributes="0"/> <Component id="spnNumPlayers" min="-2" pref="57" max="-2" attributes="0"/>
</Group> </Group>
<EmptySpace type="separate" min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="lblRange" min="-2" max="-2" attributes="1"/> <Component id="lblRange" min="-2" max="-2" attributes="1"/>
<Component id="cbRange" min="-2" pref="141" max="-2" attributes="1"/> <Component id="cbRange" min="-2" pref="143" max="-2" attributes="1"/>
</Group> </Group>
<EmptySpace type="separate" min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="lblAttack" min="-2" max="-2" attributes="0"/> <Component id="lblAttack" min="-2" max="-2" attributes="0"/>
<Component id="cbAttackOption" alignment="0" min="-2" pref="199" max="-2" attributes="0"/> <Component id="cbAttackOption" pref="235" max="32767" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="spnNumWins" min="-2" pref="50" max="-2" attributes="0"/>
<Component id="lblNumWins" alignment="0" min="-2" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
<Component id="lblGameType" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="lblGameType" alignment="0" min="-2" max="-2" attributes="0"/>
@ -61,34 +66,34 @@
</Group> </Group>
<Group type="102" alignment="1" attributes="0"> <Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="jSeparator2" pref="466" max="32767" attributes="0"/> <Component id="jSeparator2" pref="503" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
</Group> </Group>
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/> <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="396" max="32767" attributes="0"/> <EmptySpace pref="433" max="32767" attributes="0"/>
</Group> </Group>
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="player1Panel" pref="466" max="32767" attributes="0"/> <Component id="player1Panel" pref="503" max="32767" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
</Group> </Group>
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="jLabel2" min="-2" max="-2" attributes="0"/> <Component id="jLabel2" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="399" max="32767" attributes="0"/> <EmptySpace pref="436" max="32767" attributes="0"/>
</Group> </Group>
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="jSeparator1" pref="466" max="32767" attributes="0"/> <Component id="jSeparator1" pref="503" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
</Group> </Group>
<Component id="pnlOtherPlayers" alignment="0" min="-2" pref="486" max="-2" attributes="0"/> <Component id="pnlOtherPlayers" alignment="0" min="-2" pref="486" max="-2" attributes="0"/>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0"> <Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="jSeparator3" pref="466" max="32767" attributes="0"/> <Component id="jSeparator3" pref="503" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
@ -105,13 +110,9 @@
<Component id="lblGameType" min="-2" max="-2" attributes="0"/> <Component id="lblGameType" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/> <EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="cbGameType" min="-2" max="-2" attributes="0"/> <Component id="cbGameType" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="103" groupAlignment="1" attributes="0"> <Group type="103" groupAlignment="1" attributes="0">
<Group type="102" alignment="1" attributes="0">
<Component id="lblAttack" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="cbAttackOption" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="1" attributes="0"> <Group type="102" alignment="1" attributes="0">
<Component id="lblNumPlayers" min="-2" max="-2" attributes="0"/> <Component id="lblNumPlayers" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/> <EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
@ -122,8 +123,19 @@
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/> <EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="cbRange" min="-2" max="-2" attributes="0"/> <Component id="cbRange" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<Group type="102" attributes="0">
<Component id="lblAttack" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="cbAttackOption" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<EmptySpace min="-2" max="-2" attributes="0"/> </Group>
<Group type="102" attributes="0">
<Component id="lblNumWins" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="spnNumWins" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="jSeparator2" min="-2" max="-2" attributes="0"/> <Component id="jSeparator2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/> <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
@ -132,21 +144,21 @@
<EmptySpace type="unrelated" max="-2" attributes="0"/> <EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="jLabel2" min="-2" max="-2" attributes="0"/> <Component id="jLabel2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="pnlOtherPlayers" pref="83" max="32767" attributes="0"/> <Component id="pnlOtherPlayers" pref="97" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="jSeparator1" pref="4" max="32767" attributes="0"/> <Component id="jSeparator1" pref="19" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0"> <Group type="103" groupAlignment="3" attributes="0">
<Component id="btnCancel" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="btnCancel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnOK" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="btnOK" alignment="3" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/> <EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
</Group> </Group>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0"> <Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="223" max="-2" attributes="0"/> <EmptySpace min="-2" pref="223" max="-2" attributes="0"/>
<Component id="jSeparator3" min="-2" max="-2" attributes="0"/> <Component id="jSeparator3" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="149" max="32767" attributes="0"/> <EmptySpace pref="159" max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
</Group> </Group>
@ -260,5 +272,18 @@
<Property name="text" type="java.lang.String" value="Other Players"/> <Property name="text" type="java.lang.String" value="Other Players"/>
</Properties> </Properties>
</Component> </Component>
<Component class="javax.swing.JLabel" name="lblNumWins">
<Properties>
<Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
<ComponentRef name="spnNumWins"/>
</Property>
<Property name="text" type="java.lang.String" value="Wins"/>
</Properties>
</Component>
<Component class="javax.swing.JSpinner" name="spnNumWins">
<Events>
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="spnNumWinsnumPlayersChanged"/>
</Events>
</Component>
</SubComponents> </SubComponents>
</Form> </Form>

View file

@ -53,6 +53,7 @@ import mage.client.remote.Session;
import mage.client.table.TablePlayerPanel; import mage.client.table.TablePlayerPanel;
import mage.client.util.Event; import mage.client.util.Event;
import mage.client.util.Listener; import mage.client.util.Listener;
import mage.game.match.MatchOptions;
import mage.sets.Sets; import mage.sets.Sets;
import mage.util.Logging; import mage.util.Logging;
import mage.view.GameTypeView; import mage.view.GameTypeView;
@ -77,6 +78,7 @@ public class NewTableDialog extends MageDialog {
/** Creates new form NewTableDialog */ /** Creates new form NewTableDialog */
public NewTableDialog() { public NewTableDialog() {
initComponents(); initComponents();
this.spnNumWins.setModel(new SpinnerNumberModel(1, 1, 5, 1));
} }
/** This method is called from within the constructor to /** This method is called from within the constructor to
@ -107,6 +109,8 @@ public class NewTableDialog extends MageDialog {
jLabel1 = new javax.swing.JLabel(); jLabel1 = new javax.swing.JLabel();
jSeparator3 = new javax.swing.JSeparator(); jSeparator3 = new javax.swing.JSeparator();
jLabel2 = new javax.swing.JLabel(); jLabel2 = new javax.swing.JLabel();
lblNumWins = new javax.swing.JLabel();
spnNumWins = new javax.swing.JSpinner();
setTitle("New Table"); setTitle("New Table");
@ -157,12 +161,21 @@ public class NewTableDialog extends MageDialog {
jLabel2.setFont(new java.awt.Font("Tahoma", 1, 11)); jLabel2.setFont(new java.awt.Font("Tahoma", 1, 11));
jLabel2.setText("Other Players"); jLabel2.setText("Other Players");
lblNumWins.setLabelFor(spnNumWins);
lblNumWins.setText("Wins");
spnNumWins.addChangeListener(new javax.swing.event.ChangeListener() {
public void stateChanged(javax.swing.event.ChangeEvent evt) {
spnNumWinsnumPlayersChanged(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout); getContentPane().setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap(358, Short.MAX_VALUE) .addContainerGap(395, Short.MAX_VALUE)
.addComponent(btnOK) .addComponent(btnOK)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnCancel) .addComponent(btnCancel)
@ -170,7 +183,7 @@ public class NewTableDialog extends MageDialog {
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(lbDeckType) .addComponent(lbDeckType)
.addContainerGap(426, Short.MAX_VALUE)) .addContainerGap(463, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
@ -178,43 +191,47 @@ public class NewTableDialog extends MageDialog {
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lblNumPlayers) .addComponent(lblNumPlayers)
.addComponent(spnNumPlayers, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(spnNumPlayers, javax.swing.GroupLayout.PREFERRED_SIZE, 57, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(18, 18, 18) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lblRange) .addComponent(lblRange)
.addComponent(cbRange, javax.swing.GroupLayout.PREFERRED_SIZE, 141, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(cbRange, javax.swing.GroupLayout.PREFERRED_SIZE, 143, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(18, 18, 18) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lblAttack) .addComponent(lblAttack)
.addComponent(cbAttackOption, javax.swing.GroupLayout.PREFERRED_SIZE, 199, javax.swing.GroupLayout.PREFERRED_SIZE))) .addComponent(cbAttackOption, 0, 235, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblNumWins)))
.addComponent(lblGameType) .addComponent(lblGameType)
.addComponent(cbDeckType, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addComponent(cbDeckType, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(jSeparator2, javax.swing.GroupLayout.DEFAULT_SIZE, 466, Short.MAX_VALUE) .addComponent(jSeparator2, javax.swing.GroupLayout.DEFAULT_SIZE, 503, Short.MAX_VALUE)
.addContainerGap()) .addContainerGap())
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(jLabel1) .addComponent(jLabel1)
.addContainerGap(396, Short.MAX_VALUE)) .addContainerGap(433, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(player1Panel, javax.swing.GroupLayout.DEFAULT_SIZE, 466, Short.MAX_VALUE) .addComponent(player1Panel, javax.swing.GroupLayout.DEFAULT_SIZE, 503, Short.MAX_VALUE)
.addContainerGap()) .addContainerGap())
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(jLabel2) .addComponent(jLabel2)
.addContainerGap(399, Short.MAX_VALUE)) .addContainerGap(436, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(jSeparator1, javax.swing.GroupLayout.DEFAULT_SIZE, 466, Short.MAX_VALUE) .addComponent(jSeparator1, javax.swing.GroupLayout.DEFAULT_SIZE, 503, Short.MAX_VALUE)
.addContainerGap()) .addContainerGap())
.addComponent(pnlOtherPlayers, javax.swing.GroupLayout.PREFERRED_SIZE, 486, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(pnlOtherPlayers, javax.swing.GroupLayout.PREFERRED_SIZE, 486, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(jSeparator3, javax.swing.GroupLayout.DEFAULT_SIZE, 466, Short.MAX_VALUE) .addComponent(jSeparator3, javax.swing.GroupLayout.DEFAULT_SIZE, 503, Short.MAX_VALUE)
.addContainerGap())) .addContainerGap()))
); );
layout.setVerticalGroup( layout.setVerticalGroup(
@ -229,11 +246,8 @@ public class NewTableDialog extends MageDialog {
.addGap(0, 0, 0) .addGap(0, 0, 0)
.addComponent(cbGameType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(cbGameType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(layout.createSequentialGroup()
.addComponent(lblAttack)
.addGap(0, 0, 0)
.addComponent(cbAttackOption, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(lblNumPlayers) .addComponent(lblNumPlayers)
.addGap(0, 0, 0) .addGap(0, 0, 0)
@ -241,7 +255,15 @@ public class NewTableDialog extends MageDialog {
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(lblRange) .addComponent(lblRange)
.addGap(0, 0, 0) .addGap(0, 0, 0)
.addComponent(cbRange, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) .addComponent(cbRange, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addComponent(lblAttack)
.addGap(0, 0, 0)
.addComponent(cbAttackOption, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGroup(layout.createSequentialGroup()
.addComponent(lblNumWins)
.addGap(0, 0, 0)
.addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
@ -251,19 +273,19 @@ public class NewTableDialog extends MageDialog {
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jLabel2) .addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(pnlOtherPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, 83, Short.MAX_VALUE) .addComponent(pnlOtherPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, 97, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jSeparator1, javax.swing.GroupLayout.DEFAULT_SIZE, 4, Short.MAX_VALUE) .addComponent(jSeparator1, javax.swing.GroupLayout.DEFAULT_SIZE, 19, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnCancel) .addComponent(btnCancel)
.addComponent(btnOK)) .addComponent(btnOK))
.addGap(0, 0, 0)) .addGap(6, 6, 6))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addGap(223, 223, 223) .addGap(223, 223, 223)
.addComponent(jSeparator3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jSeparator3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(149, Short.MAX_VALUE))) .addContainerGap(159, Short.MAX_VALUE)))
); );
pack(); pack();
@ -277,18 +299,16 @@ public class NewTableDialog extends MageDialog {
private void btnOKActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOKActionPerformed private void btnOKActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOKActionPerformed
GameTypeView gameType = (GameTypeView) cbGameType.getSelectedItem(); GameTypeView gameType = (GameTypeView) cbGameType.getSelectedItem();
List<String> playerTypes = new ArrayList<String>(); MatchOptions options = new MatchOptions("Quick Start Game", gameType.getName());
playerTypes.add("Human"); options.getPlayerTypes().add("Human");
for (TablePlayerPanel player: players) { for (TablePlayerPanel player: players) {
playerTypes.add(player.getPlayerType()); options.getPlayerTypes().add(player.getPlayerType());
} }
table = session.createTable( options.setDeckType((String) this.cbDeckType.getSelectedItem());
roomId, options.setAttackOption((MultiplayerAttackOption) this.cbAttackOption.getSelectedItem());
gameType.getName(), options.setRange((RangeOfInfluence) this.cbRange.getSelectedItem());
(String)this.cbDeckType.getSelectedItem(), options.setWinsNeeded((Integer)this.spnNumWins.getValue());
playerTypes, table = session.createTable(roomId, options);
(MultiplayerAttackOption)this.cbAttackOption.getSelectedItem(),
(RangeOfInfluence)this.cbRange.getSelectedItem());
try { try {
if (session.joinTable(roomId, table.getTableId(), this.player1Panel.getPlayerName(), Sets.loadDeck(this.player1Panel.getDeckFile()))) { if (session.joinTable(roomId, table.getTableId(), this.player1Panel.getPlayerName(), Sets.loadDeck(this.player1Panel.getDeckFile()))) {
for (TablePlayerPanel player: players) { for (TablePlayerPanel player: players) {
@ -325,6 +345,10 @@ public class NewTableDialog extends MageDialog {
createPlayers(numPlayers); createPlayers(numPlayers);
}//GEN-LAST:event_numPlayersChanged }//GEN-LAST:event_numPlayersChanged
private void spnNumWinsnumPlayersChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spnNumWinsnumPlayersChanged
// TODO add your handling code here:
}//GEN-LAST:event_spnNumWinsnumPlayersChanged
private void setGameOptions() { private void setGameOptions() {
GameTypeView gameType = (GameTypeView) cbGameType.getSelectedItem(); GameTypeView gameType = (GameTypeView) cbGameType.getSelectedItem();
this.spnNumPlayers.setModel(new SpinnerNumberModel(gameType.getMinPlayers(), gameType.getMinPlayers(), gameType.getMaxPlayers(), 1)); this.spnNumPlayers.setModel(new SpinnerNumberModel(gameType.getMinPlayers(), gameType.getMinPlayers(), gameType.getMaxPlayers(), 1));
@ -423,10 +447,12 @@ public class NewTableDialog extends MageDialog {
private javax.swing.JLabel lblAttack; private javax.swing.JLabel lblAttack;
private javax.swing.JLabel lblGameType; private javax.swing.JLabel lblGameType;
private javax.swing.JLabel lblNumPlayers; private javax.swing.JLabel lblNumPlayers;
private javax.swing.JLabel lblNumWins;
private javax.swing.JLabel lblRange; private javax.swing.JLabel lblRange;
private mage.client.table.NewPlayerPanel player1Panel; private mage.client.table.NewPlayerPanel player1Panel;
private javax.swing.JPanel pnlOtherPlayers; private javax.swing.JPanel pnlOtherPlayers;
private javax.swing.JSpinner spnNumPlayers; private javax.swing.JSpinner spnNumPlayers;
private javax.swing.JSpinner spnNumWins;
// End of variables declaration//GEN-END:variables // End of variables declaration//GEN-END:variables
} }

View file

@ -98,12 +98,12 @@ public class BattlefieldPanel extends javax.swing.JLayeredPane {
public void update(Map<UUID, PermanentView> battlefield) { public void update(Map<UUID, PermanentView> battlefield) {
boolean changed = false; boolean changed = false;
List<PermanentView> permanentsToAdd = new ArrayList<PermanentView>();
for (PermanentView permanent: battlefield.values()) { for (PermanentView permanent: battlefield.values()) {
if (!permanents.containsKey(permanent.getId())) { if (!permanents.containsKey(permanent.getId())) {
addPermanent(permanent); permanentsToAdd.add(permanent);
changed = true; changed = true;
} } else {
else {
MagePermanent p = permanents.get(permanent.getId()); MagePermanent p = permanents.get(permanent.getId());
if (!changed) { if (!changed) {
int s1 = permanent.getAttachments() == null ? 0 : permanent.getAttachments().size(); int s1 = permanent.getAttachments() == null ? 0 : permanent.getAttachments().size();
@ -115,10 +115,15 @@ public class BattlefieldPanel extends javax.swing.JLayeredPane {
permanents.get(permanent.getId()).update(permanent); permanents.get(permanent.getId()).update(permanent);
} }
} }
int count = permanentsToAdd.size();
for (PermanentView permanent : permanentsToAdd) {
addPermanent(permanent, count);
}
for (Iterator<Entry<UUID, MagePermanent>> i = permanents.entrySet().iterator(); i.hasNext();) { for (Iterator<Entry<UUID, MagePermanent>> i = permanents.entrySet().iterator(); i.hasNext();) {
Entry<UUID, MagePermanent> entry = i.next(); Entry<UUID, MagePermanent> entry = i.next();
if (!battlefield.containsKey(entry.getKey())) { if (!battlefield.containsKey(entry.getKey())) {
removePermanent(entry.getKey()); removePermanent(entry.getKey(), 1);
i.remove(); i.remove();
changed = true; changed = true;
} }
@ -150,12 +155,12 @@ public class BattlefieldPanel extends javax.swing.JLayeredPane {
repaint(); repaint();
} }
private void addPermanent(PermanentView permanent) { private void addPermanent(PermanentView permanent, final int count) {
final MagePermanent perm = Plugins.getInstance().getMagePermanent(permanent, bigCard, Config.dimensions, gameId); final MagePermanent perm = Plugins.getInstance().getMagePermanent(permanent, bigCard, Config.dimensions, gameId);
if (!Plugins.getInstance().isCardPluginLoaded()) { if (!Plugins.getInstance().isCardPluginLoaded()) {
perm.setBounds(findEmptySpace(new Dimension(Config.dimensions.frameWidth, Config.dimensions.frameHeight))); perm.setBounds(findEmptySpace(new Dimension(Config.dimensions.frameWidth, Config.dimensions.frameHeight)));
} else { } else {
perm.setAlpha(0); //perm.setAlpha(0);
} }
permanents.put(permanent.getId(), perm); permanents.put(permanent.getId(), perm);
@ -164,15 +169,16 @@ public class BattlefieldPanel extends javax.swing.JLayeredPane {
moveToFront(perm); moveToFront(perm);
perm.update(permanent); perm.update(permanent);
} else { } else {
Thread t = new Thread(new Runnable() { Plugins.getInstance().onAddCard(perm, 1);
/*Thread t = new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
Plugins.getInstance().onAddCard(perm); Plugins.getInstance().onAddCard(perm, count);
} }
}); });
synchronized (this) { synchronized (this) {
threads.add(t); threads.add(t);
} }*/
} }
} }
@ -208,7 +214,7 @@ public class BattlefieldPanel extends javax.swing.JLayeredPane {
} }
private void removePermanent(UUID permanentId) { private void removePermanent(UUID permanentId, final int count) {
for (Component c: this.getComponents()) { for (Component c: this.getComponents()) {
final Component comp = c; final Component comp = c;
if (comp instanceof Permanent) { if (comp instanceof Permanent) {
@ -220,7 +226,7 @@ public class BattlefieldPanel extends javax.swing.JLayeredPane {
Thread t = new Thread(new Runnable() { Thread t = new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
Plugins.getInstance().onRemoveCard((MagePermanent)comp); Plugins.getInstance().onRemoveCard((MagePermanent)comp, count);
BattlefieldPanel.this.remove(comp); BattlefieldPanel.this.remove(comp);
} }
}); });

View file

@ -32,7 +32,7 @@ public interface MagePlugins {
int getGamesPlayed(); int getGamesPlayed();
void addGamesPlayed(); void addGamesPlayed();
Image getManaSymbolImage(String symbol); Image getManaSymbolImage(String symbol);
void onAddCard(MagePermanent card); void onAddCard(MagePermanent card, int count);
void onRemoveCard(MagePermanent card); void onRemoveCard(MagePermanent card, int count);
JComponent getCardInfoPane(); JComponent getCardInfoPane();
} }

View file

@ -4,6 +4,7 @@ import java.awt.*;
import java.awt.event.MouseAdapter; import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.InterruptedIOException;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@ -16,6 +17,7 @@ import mage.cards.action.TransferData;
import mage.client.MageFrame; import mage.client.MageFrame;
import mage.client.cards.BigCard; import mage.client.cards.BigCard;
import mage.client.components.MageComponents; import mage.client.components.MageComponents;
import mage.client.components.MageRoundPane;
import mage.client.game.PlayAreaPanel; import mage.client.game.PlayAreaPanel;
import mage.client.plugins.impl.Plugins; import mage.client.plugins.impl.Plugins;
import mage.client.remote.Session; import mage.client.remote.Session;
@ -130,9 +132,6 @@ public class MageActionCallback implements ActionCallback {
popup.show(); popup.show();
} else { } else {
ThreadUtils.threadPool2.submit(new Runnable() {
@Override
public void run() {
ThreadUtils.threadPool2.submit(new Runnable() { ThreadUtils.threadPool2.submit(new Runnable() {
@Override @Override
public void run() { public void run() {
@ -142,38 +141,41 @@ public class MageActionCallback implements ActionCallback {
return; return;
} }
/*PopupFactory factory = PopupFactory.getSharedInstance();
((CardInfoPane)cardInfoPane).setCard(data.card);
cardInfoPane.setSize(161, 221);
cardInfoPane.setPreferredSize(new Dimension(161, 221));
popup = factory.getPopup(data.component, cardInfoPane, (int) data.locationOnScreen.getX() + data.popupOffsetX, (int) data.locationOnScreen.getY() + data.popupOffsetY + 40);
popup.show();
*/
try { try {
final Component popupContainer = session.getUI().getComponent(MageComponents.POPUP_CONTAINER);
Component popup2 = session.getUI().getComponent(MageComponents.CARD_INFO_PANE); Component popup2 = session.getUI().getComponent(MageComponents.CARD_INFO_PANE);
((CardInfoPane) popup2).setCard(data.card); ((CardInfoPane) popup2).setCard(data.card);
Point location = new Point((int) data.locationOnScreen.getX() + data.popupOffsetX, (int) data.locationOnScreen.getY() + data.popupOffsetY + 40); Point location = new Point((int) data.locationOnScreen.getX() + data.popupOffsetX - 40, (int) data.locationOnScreen.getY() + data.popupOffsetY - 40);
location = GuiDisplayUtil.keepComponentInsideParent(location, parentPoint, popup2, parentComponent); location = GuiDisplayUtil.keepComponentInsideParent(location, parentPoint, popup2, parentComponent);
location.translate(-parentPoint.x, -parentPoint.y); location.translate(-parentPoint.x, -parentPoint.y);
popup2.setLocation(location); popupContainer.setLocation(location);
ThreadUtils.sleep(200); ThreadUtils.sleep(200);
popup2.setVisible(true); final Component c = session.getUI().getComponent(MageComponents.DESKTOP_PANE);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
popupContainer.setVisible(true);
c.repaint();
}
}
);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
}); });
}
});
} }
} }
@Override @Override
public void mouseMoved(MouseEvent e, TransferData data) { public void mouseMoved(MouseEvent e, TransferData data) {
if (!Plugins.getInstance().isCardPluginLoaded()) {return;} if (!Plugins.getInstance().isCardPluginLoaded()) {
if (bigCard == null) {return;} return;
}
if (bigCard == null) {
return;
}
MageCard card = (MageCard) data.component; MageCard card = (MageCard) data.component;
if (card.getOriginal().getId() != bigCard.getCardId()) { if (card.getOriginal().getId() != bigCard.getCardId()) {
@ -188,7 +190,8 @@ public class MageActionCallback implements ActionCallback {
bigCard.showTextComponent(); bigCard.showTextComponent();
} else { } else {
bigCard.hideTextComponent(); bigCard.hideTextComponent();
}; }
;
} else { } else {
JXPanel panel = GuiDisplayUtil.getDescription(card.getOriginal(), bigCard.getWidth(), bigCard.getHeight()); JXPanel panel = GuiDisplayUtil.getDescription(card.getOriginal(), bigCard.getWidth(), bigCard.getHeight());
panel.setVisible(true); panel.setVisible(true);
@ -209,10 +212,10 @@ public class MageActionCallback implements ActionCallback {
jPopupMenu.setVisible(false); jPopupMenu.setVisible(false);
} }
try { try {
Component popup2 = session.getUI().getComponent(MageComponents.CARD_INFO_PANE); Component popupContainer = session.getUI().getComponent(MageComponents.POPUP_CONTAINER);
popup2.setVisible(false); popupContainer.setVisible(false);
} catch (Exception e2) { } catch (Exception e2) {
e2.printStackTrace();; e2.printStackTrace();
} }
} }

View file

@ -169,16 +169,16 @@ public class Plugins implements MagePlugins {
} }
@Override @Override
public void onAddCard(MagePermanent card) { public void onAddCard(MagePermanent card, int count) {
if (this.cardPlugin != null) { if (this.cardPlugin != null) {
this.cardPlugin.onAddCard(card); this.cardPlugin.onAddCard(card, count);
} }
} }
@Override @Override
public void onRemoveCard(MagePermanent card) { public void onRemoveCard(MagePermanent card, int count) {
if (this.cardPlugin != null) { if (this.cardPlugin != null) {
this.cardPlugin.onRemoveCard(card); this.cardPlugin.onRemoveCard(card, count);
} }
} }

View file

@ -33,9 +33,12 @@ import java.util.UUID;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import mage.cards.decks.Deck;
import mage.client.MageFrame; import mage.client.MageFrame;
import mage.client.chat.ChatPanel; import mage.client.chat.ChatPanel;
import mage.client.constants.Constants.DeckEditorMode;
import mage.client.plugins.impl.Plugins; import mage.client.plugins.impl.Plugins;
import mage.client.util.GameManager;
import mage.interfaces.callback.CallbackClient; import mage.interfaces.callback.CallbackClient;
import mage.interfaces.callback.ClientCallback; import mage.interfaces.callback.ClientCallback;
import mage.util.Logging; import mage.util.Logging;
@ -43,6 +46,7 @@ import mage.view.AbilityPickerView;
import mage.view.ChatMessage; import mage.view.ChatMessage;
import mage.view.GameClientMessage; import mage.view.GameClientMessage;
import mage.view.GameView; import mage.view.GameView;
import mage.view.TableClientMessage;
/** /**
* *
@ -72,8 +76,9 @@ public class Client implements CallbackClient {
logger.info(callback.getMessageId() + " - " + callback.getMethod()); logger.info(callback.getMessageId() + " - " + callback.getMethod());
try { try {
if (callback.getMethod().equals("startGame")) { if (callback.getMethod().equals("startGame")) {
UUID[] data = (UUID[]) callback.getData(); TableClientMessage message = (TableClientMessage) callback.getData();
gameStarted(data[0], data[1]); GameManager.getInstance().setCurrentPlayerUUID(message.getPlayerId());
gameStarted(message.getGameId(), message.getPlayerId());
} }
else if (callback.getMethod().equals("replayGame")) { else if (callback.getMethod().equals("replayGame")) {
replayGame(); replayGame();
@ -152,6 +157,10 @@ public class Client implements CallbackClient {
logger.warning("message out of sequence - ignoring"); logger.warning("message out of sequence - ignoring");
} }
} }
else if (callback.getMethod().equals("sideboard")) {
TableClientMessage message = (TableClientMessage) callback.getData();
sideboard(message.getDeck(), message.getTableId());
}
messageId = callback.getMessageId(); messageId = callback.getMessageId();
} }
catch (Exception ex) { catch (Exception ex) {
@ -197,6 +206,10 @@ public class Client implements CallbackClient {
} }
} }
protected void sideboard(Deck deck, UUID tableId) {
frame.showDeckEditor(DeckEditorMode.Sideboard, deck, tableId);
}
private void handleException(Exception ex) { private void handleException(Exception ex) {
logger.log(Level.SEVERE, "Client error\n", ex); logger.log(Level.SEVERE, "Client error\n", ex);
JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Unrecoverable client error. Disconnecting", "Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Unrecoverable client error. Disconnecting", "Error", JOptionPane.ERROR_MESSAGE);

View file

@ -40,8 +40,6 @@ import java.util.UUID;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import mage.Constants.MultiplayerAttackOption;
import mage.Constants.RangeOfInfluence;
import mage.cards.decks.DeckCardLists; import mage.cards.decks.DeckCardLists;
import mage.client.MageFrame; import mage.client.MageFrame;
import mage.client.chat.ChatPanel; import mage.client.chat.ChatPanel;
@ -50,6 +48,7 @@ import mage.client.game.GamePanel;
import mage.client.util.Config; import mage.client.util.Config;
import mage.game.GameException; import mage.game.GameException;
import mage.interfaces.MageException; import mage.interfaces.MageException;
import mage.game.match.MatchOptions;
import mage.interfaces.Server; import mage.interfaces.Server;
import mage.interfaces.ServerState; import mage.interfaces.ServerState;
import mage.interfaces.callback.CallbackClientDaemon; import mage.interfaces.callback.CallbackClientDaemon;
@ -396,9 +395,9 @@ public class Session {
return false; return false;
} }
public TableView createTable(UUID roomId, String gameType, String deckType, List<String> playerTypes, MultiplayerAttackOption attackOption, RangeOfInfluence range) { public TableView createTable(UUID roomId, MatchOptions matchOptions) {
try { try {
return server.createTable(sessionId, roomId, gameType, deckType, playerTypes, attackOption, range); return server.createTable(sessionId, roomId, matchOptions);
} catch (RemoteException ex) { } catch (RemoteException ex) {
handleRemoteException(ex); handleRemoteException(ex);
} catch (MageException ex) { } catch (MageException ex) {
@ -456,7 +455,7 @@ public class Session {
public boolean startGame(UUID roomId, UUID tableId) { public boolean startGame(UUID roomId, UUID tableId) {
try { try {
server.startGame(sessionId, roomId, tableId); server.startMatch(sessionId, roomId, tableId);
return true; return true;
} catch (RemoteException ex) { } catch (RemoteException ex) {
handleRemoteException(ex); handleRemoteException(ex);
@ -466,6 +465,20 @@ public class Session {
return false; return false;
} }
public boolean submitDeck(UUID tableId, DeckCardLists deck) {
try {
server.submitDeck(sessionId, tableId, deck);
return true;
} catch (RemoteException ex) {
handleRemoteException(ex);
} catch (MageException ex) {
handleMageException(ex);
} catch (GameException ex) {
handleGameException(ex);
}
return false;
}
public boolean concedeGame(UUID gameId) { public boolean concedeGame(UUID gameId) {
try { try {
server.concedeGame(gameId, sessionId); server.concedeGame(gameId, sessionId);

View file

@ -37,9 +37,7 @@ package mage.client.table;
import java.awt.Color; import java.awt.Color;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Observable; import java.util.Observable;
import java.util.Observer; import java.util.Observer;
@ -53,8 +51,9 @@ import javax.swing.JComponent;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.Timer; import javax.swing.Timer;
import javax.swing.table.AbstractTableModel; import javax.swing.table.AbstractTableModel;
import mage.Constants.MultiplayerAttackOption;
import mage.Constants.RangeOfInfluence;
import mage.cards.decks.DeckCardLists;
import mage.client.MageFrame; import mage.client.MageFrame;
import mage.client.components.MageComponents; import mage.client.components.MageComponents;
import mage.client.dialog.JoinTableDialog; import mage.client.dialog.JoinTableDialog;
@ -63,6 +62,7 @@ import mage.client.dialog.TableWaitingDialog;
import mage.client.remote.MageRemoteException; import mage.client.remote.MageRemoteException;
import mage.client.remote.Session; import mage.client.remote.Session;
import mage.client.util.ButtonColumn; import mage.client.util.ButtonColumn;
import mage.game.match.MatchOptions;
import mage.sets.Sets; import mage.sets.Sets;
import mage.util.Logging; import mage.util.Logging;
import mage.view.TableView; import mage.view.TableView;
@ -280,16 +280,14 @@ public class TablesPanel extends javax.swing.JPanel implements Observer {
private void btnQuickStartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnQuickStartActionPerformed private void btnQuickStartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnQuickStartActionPerformed
TableView table; TableView table;
try { try {
List<String> playerTypes = new ArrayList<String>(); MatchOptions options = new MatchOptions("1", "Two Player Duel");
playerTypes.add("Human"); options.getPlayerTypes().add("Human");
playerTypes.add("Computer - default"); options.getPlayerTypes().add("Computer - default");
table = session.createTable( options.setDeckType("Limited");
roomId, options.setAttackOption(MultiplayerAttackOption.LEFT);
"Two Player Duel", options.setRange(RangeOfInfluence.ALL);
"Constructed", options.setWinsNeeded(1);
playerTypes, table = session.createTable(roomId, options);
null, null
);
session.joinTable( session.joinTable(
roomId, roomId,
table.getTableId(), table.getTableId(),

View file

@ -1,5 +1,7 @@
package mage.client.util; package mage.client.util;
import java.util.UUID;
/** /**
* Controls game state on client side. * Controls game state on client side.
* *
@ -7,15 +9,27 @@ package mage.client.util;
*/ */
public class GameManager { public class GameManager {
private static GameManager fInstance = new GameManager(); private static GameManager fInstance = new GameManager();
public static GameManager getInstance() { public static GameManager getInstance() {
return fInstance; return fInstance;
} }
public void setStackSize(int stackSize) { public void setStackSize(int stackSize) {
this.stackSize = stackSize; this.stackSize = stackSize;
} }
public int getStackSize() { public int getStackSize() {
return stackSize; return stackSize;
} }
private int stackSize; public UUID getCurrentPlayerUUID() {
return currentPlayerUUID;
}
public void setCurrentPlayerUUID(UUID currentPlayerUUID) {
this.currentPlayerUUID = currentPlayerUUID;
}
private int stackSize;
private UUID currentPlayerUUID;
} }

View file

@ -2,9 +2,11 @@ package mage.client.util;
import mage.client.MageFrame; import mage.client.MageFrame;
import mage.view.GameView; import mage.view.GameView;
import mage.view.PlayerView;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.UUID;
import java.util.prefs.Preferences; import java.util.prefs.Preferences;
public class PhaseManager { public class PhaseManager {
@ -51,21 +53,27 @@ public class PhaseManager {
put("End Turn - play instants and activated abilities.", END_OF_TURN_OTHERS); put("End Turn - play instants and activated abilities.", END_OF_TURN_OTHERS);
}}; }};
private String yourName;
public static PhaseManager getInstance() { public static PhaseManager getInstance() {
return fInstance; return fInstance;
} }
public void setName(String yourName) {
this.yourName = yourName;
}
public boolean isSkip(GameView gameView, String message) { public boolean isSkip(GameView gameView, String message) {
if (GameManager.getInstance().getStackSize() > 0) { if (GameManager.getInstance().getStackSize() > 0) {
return false; return false;
} }
Map<String, String> map = gameView.getActivePlayerName().equals(DEFAULT_PLAYER_NAME) ? mapYou : mapOthers; UUID activePlayer = null;
Map<String, String> map = mapOthers;
for (PlayerView playerView : gameView.getPlayers()) {
if (playerView.isActive()) {
activePlayer = playerView.getPlayerId();
if (activePlayer.equals(GameManager.getInstance().getCurrentPlayerUUID())) {
map = mapYou;
}
}
}
if (activePlayer == null) {
throw new IllegalStateException("No active player found.");
}
for (Map.Entry<String, String> entry : map.entrySet()) { for (Map.Entry<String, String> entry : map.entrySet()) {
if (message.equals(entry.getKey())) { if (message.equals(entry.getKey())) {
Preferences prefs = MageFrame.getPreferences(); Preferences prefs = MageFrame.getPreferences();

View file

@ -14,7 +14,8 @@ import org.jdesktop.swingx.JXPanel;
public class GuiDisplayUtil { public class GuiDisplayUtil {
private static final Font cardNameFont = new Font("Calibri", Font.BOLD, 15); private static final Font cardNameFont = new Font("Calibri", Font.BOLD, 15);
private static Insets DEFAULT_INSETS = new Insets(0,0, 68, 15); private static Insets DEFAULT_INSETS = new Insets(0, 0, 70, 25);
private static Insets COMPONENT_INSETS = new Insets(0, 0, 40, 40);
public static JXPanel getDescription(CardView card, int width, int height) { public static JXPanel getDescription(CardView card, int width, int height) {
JXPanel descriptionPanel = new JXPanel(); JXPanel descriptionPanel = new JXPanel();
@ -127,12 +128,12 @@ public class GuiDisplayUtil {
} }
public static Point keepComponentInsideParent(Point l, Point parentPoint, Component c, Component parent) { public static Point keepComponentInsideParent(Point l, Point parentPoint, Component c, Component parent) {
int dx = parentPoint.x + parent.getWidth() - DEFAULT_INSETS.right; int dx = parentPoint.x + parent.getWidth() - DEFAULT_INSETS.right - COMPONENT_INSETS.right;
if (l.x + c.getWidth() > dx) { if (l.x + c.getWidth() > dx) {
l.x = dx - c.getWidth(); l.x = dx - c.getWidth();
} }
int dy = parentPoint.y + parent.getHeight() - DEFAULT_INSETS.bottom; int dy = parentPoint.y + parent.getHeight() - DEFAULT_INSETS.bottom - COMPONENT_INSETS.bottom;
if (l.y + c.getHeight() > dy) { if (l.y + c.getHeight() > dy) {
l.y = Math.max(10, dy - c.getHeight()); l.y = Math.max(10, dy - c.getHeight());
} }

View file

@ -28,16 +28,14 @@
package mage.interfaces; package mage.interfaces;
import mage.game.match.MatchOptions;
import java.rmi.Remote; import java.rmi.Remote;
import java.rmi.RemoteException; import java.rmi.RemoteException;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import mage.Constants.MultiplayerAttackOption;
import mage.Constants.RangeOfInfluence;
import mage.cards.decks.DeckCardLists; import mage.cards.decks.DeckCardLists;
import mage.game.GameException; import mage.game.GameException;
import mage.interfaces.callback.CallbackServer; import mage.interfaces.callback.CallbackServer;
import mage.view.GameTypeView;
import mage.view.TableView; import mage.view.TableView;
import mage.view.GameView; import mage.view.GameView;
@ -54,8 +52,9 @@ public interface Server extends Remote, CallbackServer {
public ServerState getServerState() throws RemoteException, MageException; public ServerState getServerState() throws RemoteException, MageException;
//table methods //table methods
public TableView createTable(UUID sessionId, UUID roomId, String gameType, String deckType, List<String> playerTypes, MultiplayerAttackOption attackOption, RangeOfInfluence range) throws RemoteException, MageException; public TableView createTable(UUID sessionId, UUID roomId, MatchOptions matchOptions) throws RemoteException, MageException;
public boolean joinTable(UUID sessionId, UUID roomId, UUID tableId, String name, DeckCardLists deckList) throws RemoteException, MageException, GameException; public boolean joinTable(UUID sessionId, UUID roomId, UUID tableId, String name, DeckCardLists deckList) throws RemoteException, MageException, GameException;
public boolean submitDeck(UUID sessionId, UUID tableId, DeckCardLists deckList) throws RemoteException, MageException, GameException;
public boolean watchTable(UUID sessionId, UUID roomId, UUID tableId) throws RemoteException, MageException; public boolean watchTable(UUID sessionId, UUID roomId, UUID tableId) throws RemoteException, MageException;
public boolean replayTable(UUID sessionId, UUID roomId, UUID tableId) throws RemoteException, MageException; public boolean replayTable(UUID sessionId, UUID roomId, UUID tableId) throws RemoteException, MageException;
public void leaveTable(UUID sessionId, UUID roomId, UUID tableId) throws RemoteException, MageException; public void leaveTable(UUID sessionId, UUID roomId, UUID tableId) throws RemoteException, MageException;
@ -77,7 +76,7 @@ public interface Server extends Remote, CallbackServer {
public UUID getMainRoomId() throws RemoteException, MageException; public UUID getMainRoomId() throws RemoteException, MageException;
//game methods //game methods
public void startGame(UUID sessionId, UUID roomId, UUID tableId) throws RemoteException, MageException; public void startMatch(UUID sessionId, UUID roomId, UUID tableId) throws RemoteException, MageException;
public void joinGame(UUID gameId, UUID sessionId) throws RemoteException, MageException; public void joinGame(UUID gameId, UUID sessionId) throws RemoteException, MageException;
public void watchGame(UUID gameId, UUID sessionId) throws RemoteException, MageException; public void watchGame(UUID gameId, UUID sessionId) throws RemoteException, MageException;
public void stopWatching(UUID gameId, UUID sessionId) throws RemoteException, MageException; public void stopWatching(UUID gameId, UUID sessionId) throws RemoteException, MageException;

View file

@ -31,7 +31,7 @@ public interface CardPlugin extends Plugin {
void downloadImages(Set<Card> allCards); void downloadImages(Set<Card> allCards);
void downloadSymbols(); void downloadSymbols();
Image getManaSymbolImage(String symbol); Image getManaSymbolImage(String symbol);
void onAddCard(MagePermanent card); void onAddCard(MagePermanent card, int count);
void onRemoveCard(MagePermanent card); void onRemoveCard(MagePermanent card, int count);
JComponent getCardInfoPane(); JComponent getCardInfoPane();
} }

View file

@ -48,7 +48,7 @@ public class AbilityView extends CardView {
this.sourceName = sourceName; this.sourceName = sourceName;
this.sourceCard = sourceCard; this.sourceCard = sourceCard;
this.rules = new ArrayList<String>(); this.rules = new ArrayList<String>();
rules.add(formatRule(ability.getRule())); rules.add(ability.getRule(sourceName));
this.power = ""; this.power = "";
this.toughness = ""; this.toughness = "";
this.loyalty = ""; this.loyalty = "";
@ -60,13 +60,6 @@ public class AbilityView extends CardView {
this.art = ""; this.art = "";
} }
@Override
protected String formatRule(String rule) {
String newRule = rule.replace("{this}", this.sourceName);
newRule.replace("{source}", this.sourceName);
return newRule;
}
public CardView getSourceCard() { public CardView getSourceCard() {
return this.sourceCard; return this.sourceCard;
} }

View file

@ -76,7 +76,7 @@ public class CardView implements Serializable {
public CardView(Card card) { public CardView(Card card) {
this.id = card.getId(); this.id = card.getId();
this.name = card.getName(); this.name = card.getName();
this.rules = formatRules(card.getRules()); this.rules = card.getRules();
if (card instanceof Permanent) { if (card instanceof Permanent) {
this.power = Integer.toString(card.getPower().getValue()); this.power = Integer.toString(card.getPower().getValue());
this.toughness = Integer.toString(card.getToughness().getValue()); this.toughness = Integer.toString(card.getToughness().getValue());
@ -118,7 +118,7 @@ public class CardView implements Serializable {
CardView(Token token) { CardView(Token token) {
this.id = token.getId(); this.id = token.getId();
this.name = token.getName(); this.name = token.getName();
this.rules = formatRules(token.getAbilities().getRules()); this.rules = token.getAbilities().getRules(this.name);
this.power = token.getPower().toString(); this.power = token.getPower().toString();
this.toughness = token.getToughness().toString(); this.toughness = token.getToughness().toString();
this.loyalty = token.getLoyalty().toString(); this.loyalty = token.getLoyalty().toString();
@ -143,19 +143,19 @@ public class CardView implements Serializable {
} }
} }
protected List<String> formatRules(List<String> rules) { // protected List<String> formatRules(List<String> rules) {
List<String> newRules = new ArrayList<String>(); // List<String> newRules = new ArrayList<String>();
for (String rule: rules) { // for (String rule: rules) {
newRules.add(formatRule(rule)); // newRules.add(formatRule(rule));
} // }
return newRules; // return newRules;
} // }
//
protected String formatRule(String rule) { // protected String formatRule(String rule) {
String replace = rule.replace("{this}", this.name); // String replace = rule.replace("{this}", this.name);
replace = replace.replace("{source}", this.name); // replace = replace.replace("{source}", this.name);
return replace; // return replace;
} // }
public String getName() { public String getName() {
return name; return name;

View file

@ -29,7 +29,7 @@
package mage.view; package mage.view;
import java.io.Serializable; import java.io.Serializable;
import mage.game.GameType; import mage.game.match.MatchType;
/** /**
* *
@ -45,7 +45,7 @@ public class GameTypeView implements Serializable {
private boolean useRange; private boolean useRange;
private boolean useAttackOption; private boolean useAttackOption;
public GameTypeView(GameType gameType) { public GameTypeView(MatchType gameType) {
this.name = gameType.getName(); this.name = gameType.getName();
this.minPlayers = gameType.getMinPlayers(); this.minPlayers = gameType.getMinPlayers();
this.maxPlayers = gameType.getMaxPlayers(); this.maxPlayers = gameType.getMaxPlayers();

View file

@ -47,7 +47,7 @@ public class StackAbilityView extends CardView {
this.sourceName = sourceName; this.sourceName = sourceName;
this.sourceCard = sourceCard; this.sourceCard = sourceCard;
this.rules = new ArrayList<String>(); this.rules = new ArrayList<String>();
rules.add(formatRule(ability.getRule())); rules.add(ability.getRule(sourceName));
this.power = ability.getPower().toString(); this.power = ability.getPower().toString();
this.toughness = ability.getToughness().toString(); this.toughness = ability.getToughness().toString();
this.loyalty = ability.getLoyalty().toString(); this.loyalty = ability.getLoyalty().toString();
@ -60,13 +60,6 @@ public class StackAbilityView extends CardView {
setTargets(ability.getTargets()); setTargets(ability.getTargets());
} }
@Override
protected String formatRule(String rule) {
String newRule = rule.replace("{this}", this.sourceName);
newRule.replace("{source}", this.sourceName);
return newRule;
}
public CardView getSourceCard() { public CardView getSourceCard() {
return this.sourceCard; return this.sourceCard;
} }

View file

@ -26,63 +26,46 @@
* or implied, of BetaSteward_at_googlemail.com. * or implied, of BetaSteward_at_googlemail.com.
*/ */
package mage.game; package mage.view;
import java.util.ArrayList; import java.io.Serializable;
import java.util.List; import java.util.UUID;
import mage.cards.decks.Deck; import mage.cards.decks.Deck;
import mage.players.Player;
/** /**
* *
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class MatchImpl implements Match { public class TableClientMessage implements Serializable {
protected List<MatchPlayer> players = new ArrayList<MatchPlayer>(); private Deck deck;
protected List<Game> games = new ArrayList<Game>(); private UUID tableId;
protected int winsNeeded; private UUID gameId;
protected int maxPlayers; private UUID playerId;
protected int minPlayers;
public MatchImpl(int winsNeeded) { public TableClientMessage(Deck deck, UUID tableId) {
this.winsNeeded = winsNeeded; this.deck = deck;
this.tableId = tableId;
} }
@Override public TableClientMessage(UUID gameId, UUID playerId) {
public List<MatchPlayer> getPlayers() { this.gameId = gameId;
return players; this.playerId = playerId;
} }
@Override public Deck getDeck() {
public void addPlayer(Player player, Deck deck) { return deck;
MatchPlayer mPlayer = new MatchPlayer(player, deck);
players.add(mPlayer);
} }
@Override public UUID getTableId() {
public void startMatch() { return tableId;
} }
@Override public UUID getGameId() {
public boolean isMatchOver() { return gameId;
for (MatchPlayer player: players) {
if (player.getWins() >= winsNeeded) {
return true;
}
}
return false;
} }
@Override public UUID getPlayerId() {
public int getMaxPlayers() { return playerId;
return this.maxPlayers;
} }
@Override
public int getMinPlayers() {
return this.minPlayers;
}
} }

View file

@ -287,8 +287,11 @@ abstract public class Animation {
} }
} }
static public void showCard(final MagePermanent card) { static public void showCard(final MagePermanent card, int count) {
new Animation(600) { if (count == 0) {
count = 1;
}
new Animation(600 / count) {
protected void start () { protected void start () {
} }
@ -304,8 +307,11 @@ abstract public class Animation {
}; };
} }
static public void hideCard(final MagePermanent card) { static public void hideCard(final MagePermanent card, int count) {
new Animation(600) { if (count == 0) {
count = 1;
}
new Animation(600 / count) {
protected void start () { protected void start () {
} }

View file

@ -65,9 +65,8 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
static private final float rotCenterToBottomCorner = 0.7071067811865475244008443621048f; static private final float rotCenterToBottomCorner = 0.7071067811865475244008443621048f;
public CardView gameCard; public CardView gameCard;
public PermanentView gamePermanent; //public List<CardPanel> attachedPanels = new ArrayList();
public CardPanel attachedToPanel; private List<MagePermanent> links = new ArrayList<MagePermanent>();
public List<CardPanel> attachedPanels = new ArrayList();
public double tappedAngle = 0; public double tappedAngle = 0;
public ScaledImagePanel imagePanel; public ScaledImagePanel imagePanel;
public ImagePanel overlayPanel; public ImagePanel overlayPanel;
@ -101,8 +100,7 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
this.isPermanent = this.gameCard instanceof PermanentView; this.isPermanent = this.gameCard instanceof PermanentView;
if (isPermanent) { if (isPermanent) {
this.gamePermanent = (PermanentView) this.gameCard; this.hasSickness = ((PermanentView) this.gameCard).hasSummoningSickness();
this.hasSickness = this.gamePermanent.hasSummoningSickness();
} }
//for container debug (don't remove) //for container debug (don't remove)
@ -416,6 +414,13 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
@Override @Override
public void setAlpha(float alpha) { public void setAlpha(float alpha) {
this.alpha = alpha; this.alpha = alpha;
if (alpha == 0) {
this.ptText.setVisible(false);
this.titleText.setVisible(false);
} else if (alpha == 1.0f) {
this.ptText.setVisible(true);
this.titleText.setVisible(true);
}
} }
public float getAlpha() { public float getAlpha() {
@ -449,12 +454,7 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
@Override @Override
public List<MagePermanent> getLinks() { public List<MagePermanent> getLinks() {
List<MagePermanent> list = new ArrayList<MagePermanent>(); return links;
if (attachedPanels == null) return list;
for (MagePermanent p : attachedPanels) {
list.add(p);
}
return list;
} }
@Override @Override

View file

@ -438,9 +438,9 @@ public class CardPluginImpl implements CardPlugin {
} }
@Override @Override
public void onAddCard(MagePermanent card) { public void onAddCard(MagePermanent card, int count) {
if (card != null) { if (card != null) {
Animation.showCard((CardPanel) card); Animation.showCard((CardPanel) card, count > 0 ? count : 1);
try { try {
while ((card).getAlpha() + 0.05f < 1) { while ((card).getAlpha() + 0.05f < 1) {
Thread.sleep(30); Thread.sleep(30);
@ -452,9 +452,9 @@ public class CardPluginImpl implements CardPlugin {
} }
@Override @Override
public void onRemoveCard(MagePermanent card) { public void onRemoveCard(MagePermanent card, int count) {
if (card != null) { if (card != null) {
Animation.hideCard((CardPanel) card); Animation.hideCard((CardPanel) card, count > 0 ? count : 1);
try { try {
while ((card).getAlpha() - 0.05f > 0) { while ((card).getAlpha() - 0.05f > 0) {
Thread.sleep(30); Thread.sleep(30);

View file

@ -26,7 +26,6 @@ public class CardInfoPaneImpl extends JEditorPane implements CardInfoPane {
UI.setHTMLEditorKit(this); UI.setHTMLEditorKit(this);
setEditable(false); setEditable(false);
setBackground(Color.white); setBackground(Color.white);
setSize(170, Integer.MAX_VALUE);
} }
public void setCard(final CardView card) { public void setCard(final CardView card) {
@ -76,12 +75,12 @@ public class CardInfoPaneImpl extends JEditorPane implements CardInfoPane {
buffer.append("px'>"); buffer.append("px'>");
buffer.append(castingCost); buffer.append(castingCost);
buffer.append("</td></tr></table>"); buffer.append("</td></tr></table>");
buffer.append("<table cellspacing=0 cellpadding=0 border=0 width='100%'><tr><td>"); buffer.append("<table cellspacing=0 cellpadding=0 border=0 width='100%'><tr><td style='margin-left: 1px'>");
buffer.append(getTypes(card)); buffer.append(getTypes(card));
buffer.append("</td><td align='right'>"); buffer.append("</td><td align='right'>");
switch (card.getRarity()) { switch (card.getRarity()) {
case RARE: case RARE:
buffer.append("<b color='#E1D519'>"); buffer.append("<b color='#FFBF00'>");
break; break;
case UNCOMMON: case UNCOMMON:
buffer.append("<b color='silver'>"); buffer.append("<b color='silver'>");
@ -96,6 +95,20 @@ public class CardInfoPaneImpl extends JEditorPane implements CardInfoPane {
buffer.append(card.getExpansionSetCode().toUpperCase()); buffer.append(card.getExpansionSetCode().toUpperCase());
buffer.append("</td></tr></table>"); buffer.append("</td></tr></table>");
String pt = "";
if (CardUtil.isCreature(card)) {
pt = card.getPower() + "/" + card.getToughness();
} else if (CardUtil.isPlaneswalker(card)) {
pt = card.getLoyalty().toString();
}
if (pt.length() > 0) {
buffer.append("<table cellspacing=0 cellpadding=0 border=0 width='100%' valign='bottom'><tr><td>");
buffer.append("<b>");
buffer.append(pt);
buffer.append("</b>");
buffer.append("</td></tr></table>");
}
String legal = ""; String legal = "";
if (rulings.size() > 0) { if (rulings.size() > 0) {
legal = legal.replaceAll("#([^#]+)#", "<i>$1</i>"); legal = legal.replaceAll("#([^#]+)#", "<i>$1</i>");
@ -110,27 +123,12 @@ public class CardInfoPaneImpl extends JEditorPane implements CardInfoPane {
} }
if (legal.length() > 0) { if (legal.length() > 0) {
buffer.append("<br>"); //buffer.append("<br>");
legal = legal.replaceAll("\\{this\\}", card.getName()); legal = legal.replaceAll("\\{this\\}", card.getName());
legal = legal.replaceAll("\\{source\\}", card.getName()); legal = legal.replaceAll("\\{source\\}", card.getName());
buffer.append(ManaSymbols.replaceSymbolsWithHTML(legal, smallImages)); buffer.append(ManaSymbols.replaceSymbolsWithHTML(legal, smallImages));
} }
String pt = "";
if (CardUtil.isCreature(card)) {
pt = card.getPower() + "/" + card.getToughness();
} else if (CardUtil.isPlaneswalker(card)) {
pt = card.getLoyalty().toString();
}
if (pt.length() > 0) {
buffer.append("<table cellspacing=0 cellpadding=0 border=0 width='100%' valign='bottom'><tr><td>");
buffer.append("</td><td align='right'>");
buffer.append("<b>");
buffer.append(pt);
buffer.append("</b>");
buffer.append("</td></tr></table>");
}
buffer.append("<br></body></html>"); buffer.append("<br></body></html>");
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {

View file

@ -28,6 +28,7 @@
package mage.game; package mage.game;
import mage.game.match.MatchType;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -59,7 +60,7 @@ public class FreeForAll extends GameImpl<FreeForAll> {
} }
@Override @Override
public GameType getGameType() { public MatchType getGameType() {
return new FreeForAllType(); return new FreeForAllType();
} }

View file

@ -0,0 +1,51 @@
/*
* 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.game;
import mage.game.match.MatchImpl;
import mage.game.match.MatchOptions;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class FreeForAllMatch extends MatchImpl<FreeForAll> {
public FreeForAllMatch(MatchOptions options) {
super(options);
}
@Override
public void startGame() throws GameException {
FreeForAll game = new FreeForAll(options.getAttackOption(), options.getRange());
initGame(game);
games.add(game);
}
}

View file

@ -28,11 +28,13 @@
package mage.game; package mage.game;
import mage.game.match.MatchType;
/** /**
* *
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class FreeForAllType extends GameType { public class FreeForAllType extends MatchType<FreeForAllType> {
public FreeForAllType() { public FreeForAllType() {
this.name = "Free For All"; this.name = "Free For All";
@ -42,4 +44,13 @@ public class FreeForAllType extends GameType {
this.useAttackOption = true; this.useAttackOption = true;
this.useRange = true; this.useRange = true;
} }
protected FreeForAllType(final FreeForAllType matchType) {
super(matchType);
}
@Override
public FreeForAllType copy() {
return new FreeForAllType(this);
}
} }

View file

@ -28,6 +28,7 @@
package mage.game; package mage.game;
import mage.game.match.MatchType;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
@ -39,7 +40,7 @@ import mage.game.turn.TurnMod;
public class TwoPlayerDuel extends GameImpl<TwoPlayerDuel> { public class TwoPlayerDuel extends GameImpl<TwoPlayerDuel> {
public TwoPlayerDuel(MultiplayerAttackOption attackOption, RangeOfInfluence range) { public TwoPlayerDuel(MultiplayerAttackOption attackOption, RangeOfInfluence range) {
super(MultiplayerAttackOption.LEFT, RangeOfInfluence.ALL); super(attackOption, range);
} }
public TwoPlayerDuel(final TwoPlayerDuel game) { public TwoPlayerDuel(final TwoPlayerDuel game) {
@ -47,7 +48,7 @@ public class TwoPlayerDuel extends GameImpl<TwoPlayerDuel> {
} }
@Override @Override
public GameType getGameType() { public MatchType getGameType() {
return new TwoPlayerDuelType(); return new TwoPlayerDuelType();
} }
@ -62,8 +63,8 @@ public class TwoPlayerDuel extends GameImpl<TwoPlayerDuel> {
} }
@Override @Override
public void init() { protected void init(UUID choosingPlayerId) {
super.init(); super.init(choosingPlayerId);
state.getTurnMods().add(new TurnMod(startingPlayerId, PhaseStep.DRAW)); state.getTurnMods().add(new TurnMod(startingPlayerId, PhaseStep.DRAW));
} }

View file

@ -28,11 +28,13 @@
package mage.game; package mage.game;
import mage.game.match.MatchType;
/** /**
* *
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class TwoPlayerDuelType extends GameType { public class TwoPlayerDuelType extends MatchType<TwoPlayerDuelType> {
public TwoPlayerDuelType() { public TwoPlayerDuelType() {
this.name = "Two Player Duel"; this.name = "Two Player Duel";
@ -43,4 +45,13 @@ public class TwoPlayerDuelType extends GameType {
this.useRange = false; this.useRange = false;
} }
protected TwoPlayerDuelType(final TwoPlayerDuelType matchType) {
super(matchType);
}
@Override
public TwoPlayerDuelType copy() {
return new TwoPlayerDuelType(this);
}
} }

View file

@ -0,0 +1,51 @@
/*
* 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.game;
import mage.game.match.MatchImpl;
import mage.game.match.MatchOptions;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class TwoPlayerMatch extends MatchImpl<TwoPlayerDuel> {
public TwoPlayerMatch(MatchOptions options) {
super(options);
}
@Override
public void startGame() throws GameException {
TwoPlayerDuel game = new TwoPlayerDuel(options.getAttackOption(), options.getRange());
initGame(game);
games.add(game);
}
}

View file

@ -86,6 +86,7 @@ import mage.filter.common.FilterCreaturePermanent;
import mage.filter.common.FilterLandCard; import mage.filter.common.FilterLandCard;
import mage.filter.common.FilterNonlandCard; import mage.filter.common.FilterNonlandCard;
import mage.game.Game; import mage.game.Game;
import mage.game.Table;
import mage.game.combat.CombatGroup; import mage.game.combat.CombatGroup;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
@ -111,7 +112,6 @@ import mage.util.TreeNode;
public class ComputerPlayer<T extends ComputerPlayer<T>> extends PlayerImpl<T> implements Player { public class ComputerPlayer<T extends ComputerPlayer<T>> extends PlayerImpl<T> implements Player {
private final static transient Logger logger = Logging.getLogger(ComputerPlayer.class.getName()); private final static transient Logger logger = Logging.getLogger(ComputerPlayer.class.getName());
private boolean abort;
private transient Map<Mana, Card> unplayable = new TreeMap<Mana, Card>(); private transient Map<Mana, Card> unplayable = new TreeMap<Mana, Card>();
private transient List<Card> playableNonInstant = new ArrayList<Card>(); private transient List<Card> playableNonInstant = new ArrayList<Card>();
private transient List<Card> playableInstant = new ArrayList<Card>(); private transient List<Card> playableInstant = new ArrayList<Card>();
@ -128,7 +128,6 @@ public class ComputerPlayer<T extends ComputerPlayer<T>> extends PlayerImpl<T> i
public ComputerPlayer(final ComputerPlayer player) { public ComputerPlayer(final ComputerPlayer player) {
super(player); super(player);
this.abort = player.abort;
} }
@Override @Override
@ -768,6 +767,12 @@ public class ComputerPlayer<T extends ComputerPlayer<T>> extends PlayerImpl<T> i
return super.getAvailableManaProducers(game); return super.getAvailableManaProducers(game);
} }
@Override
public void sideboard(Table table) {
//TODO: improve this
table.fireSubmitDeckEvent(playerId, deck);
}
protected Attackers getPotentialAttackers(Game game) { protected Attackers getPotentialAttackers(Game game) {
logger.fine("getAvailableAttackers"); logger.fine("getAvailableAttackers");
Attackers attackers = new Attackers(); Attackers attackers = new Attackers();

View file

@ -53,6 +53,7 @@ import mage.cards.decks.Deck;
import mage.choices.ChoiceImpl; import mage.choices.ChoiceImpl;
import mage.filter.common.FilterCreatureForCombat; import mage.filter.common.FilterCreatureForCombat;
import mage.game.Game; import mage.game.Game;
import mage.game.Table;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.target.Target; import mage.target.Target;
import mage.target.TargetAmount; import mage.target.TargetAmount;
@ -71,8 +72,6 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
final transient PlayerResponse response = new PlayerResponse(); final transient PlayerResponse response = new PlayerResponse();
private boolean abort;
protected static FilterCreatureForCombat filter = new FilterCreatureForCombat(); protected static FilterCreatureForCombat filter = new FilterCreatureForCombat();
protected static Choice replacementEffectChoice = new ChoiceImpl(true); protected static Choice replacementEffectChoice = new ChoiceImpl(true);
@ -89,7 +88,6 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
public HumanPlayer(final HumanPlayer player) { public HumanPlayer(final HumanPlayer player) {
super(player); super(player);
this.abort = player.abort;
} }
protected void waitForResponse() { protected void waitForResponse() {
@ -474,6 +472,11 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
return response.getInteger(); return response.getInteger();
} }
@Override
public void sideboard(Table table) {
table.fireSideboardEvent(playerId);
}
protected void specialAction(Game game) { protected void specialAction(Game game) {
Map<UUID, SpecialAction> specialActions = game.getState().getSpecialActions().getControlledBy(playerId); Map<UUID, SpecialAction> specialActions = game.getState().getSpecialActions().getControlledBy(playerId);
game.fireGetChoiceEvent(playerId, name, specialActions.values()); game.fireGetChoiceEvent(playerId, name, specialActions.values());
@ -540,6 +543,8 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
} }
} }
@Override @Override
public HumanPlayer copy() { public HumanPlayer copy() {
return new HumanPlayer(this); return new HumanPlayer(this);

View file

@ -9,8 +9,8 @@
<playerType name="Computer - minimax hybrid" jar="mage-player-aiminimax.jar" className="mage.player.ai.ComputerPlayer3"/> <playerType name="Computer - minimax hybrid" jar="mage-player-aiminimax.jar" className="mage.player.ai.ComputerPlayer3"/>
</playerTypes> </playerTypes>
<gameTypes> <gameTypes>
<gameType name="Two Player Duel" jar="mage-game-twoplayerduel.jar" className="mage.game.TwoPlayerDuel" typeName="mage.game.TwoPlayerDuelType"/> <gameType name="Two Player Duel" jar="mage-game-twoplayerduel.jar" className="mage.game.TwoPlayerMatch" typeName="mage.game.TwoPlayerDuelType"/>
<gameType name="Free For All" jar="mage-game-freeforall.jar" className="mage.game.FreeForAll" typeName="mage.game.FreeForAllType"/> <gameType name="Free For All" jar="mage-game-freeforall.jar" className="mage.game.FreeForAllMatch" typeName="mage.game.FreeForAllType"/>
</gameTypes> </gameTypes>
<deckTypes> <deckTypes>
<deckType name="Constructed" jar="mage-deck-constructed.jar" className="mage.deck.Constructed"/> <deckType name="Constructed" jar="mage-deck-constructed.jar" className="mage.deck.Constructed"/>

View file

@ -35,7 +35,7 @@ import java.io.FilenameFilter;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import mage.game.GameType; import mage.game.match.MatchType;
import mage.server.game.DeckValidatorFactory; import mage.server.game.DeckValidatorFactory;
import mage.server.game.GameFactory; import mage.server.game.GameFactory;
import mage.server.game.PlayerFactory; import mage.server.game.PlayerFactory;
@ -119,11 +119,11 @@ public class Main {
return null; return null;
} }
private static GameType loadGameType(GamePlugin plugin) { private static MatchType loadGameType(GamePlugin plugin) {
try { try {
classLoader.addURL(new File(pluginFolder + "/" + plugin.getJar()).toURI().toURL()); classLoader.addURL(new File(pluginFolder + "/" + plugin.getJar()).toURI().toURL());
logger.info("Loading game type: " + plugin.getClassName()); logger.info("Loading game type: " + plugin.getClassName());
return (GameType) Class.forName(plugin.getTypeName(), true, classLoader).newInstance(); return (MatchType) Class.forName(plugin.getTypeName(), true, classLoader).newInstance();
} catch (ClassNotFoundException ex) { } catch (ClassNotFoundException ex) {
logger.log(Level.SEVERE, "Game type not found:" + plugin.getJar() + " - check plugin folder"); logger.log(Level.SEVERE, "Game type not found:" + plugin.getJar() + " - check plugin folder");
} catch (Exception ex) { } catch (Exception ex) {

View file

@ -39,11 +39,10 @@ import java.util.UUID;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import mage.Constants.MultiplayerAttackOption;
import mage.Constants.RangeOfInfluence;
import mage.cards.decks.DeckCardLists; import mage.cards.decks.DeckCardLists;
import mage.game.GameException; import mage.game.GameException;
import mage.interfaces.MageException; import mage.interfaces.MageException;
import mage.game.match.MatchOptions;
import mage.interfaces.Server; import mage.interfaces.Server;
import mage.interfaces.ServerState; import mage.interfaces.ServerState;
import mage.interfaces.callback.ClientCallback; import mage.interfaces.callback.ClientCallback;
@ -56,7 +55,6 @@ import mage.server.game.ReplayManager;
import mage.server.game.TableManager; import mage.server.game.TableManager;
import mage.server.util.ThreadExecutor; import mage.server.util.ThreadExecutor;
import mage.util.Logging; import mage.util.Logging;
import mage.view.CardView;
import mage.view.ChatMessage.MessageColor; import mage.view.ChatMessage.MessageColor;
import mage.view.GameView; import mage.view.GameView;
import mage.view.TableView; import mage.view.TableView;
@ -117,9 +115,9 @@ public class ServerImpl extends RemoteServer implements Server {
} }
@Override @Override
public TableView createTable(UUID sessionId, UUID roomId, String gameType, String deckType, List<String> playerTypes, MultiplayerAttackOption attackOption, RangeOfInfluence range) throws MageException { public TableView createTable(UUID sessionId, UUID roomId, MatchOptions options) throws MageException {
try { try {
TableView table = GamesRoomManager.getInstance().getRoom(roomId).createTable(sessionId, gameType, deckType, playerTypes, attackOption, range); TableView table = GamesRoomManager.getInstance().getRoom(roomId).createTable(sessionId, options);
logger.info("Table " + table.getTableId() + " created"); logger.info("Table " + table.getTableId() + " created");
return table; return table;
} }
@ -161,6 +159,21 @@ public class ServerImpl extends RemoteServer implements Server {
return false; return false;
} }
@Override
public boolean submitDeck(UUID sessionId, UUID tableId, DeckCardLists deckList) throws MageException, GameException {
try {
boolean ret = TableManager.getInstance().submitDeck(sessionId, tableId, deckList);
logger.info("Session " + sessionId + " submitted deck");
return ret;
}
catch (Exception ex) {
if (ex instanceof GameException)
throw (GameException)ex;
handleException(ex);
}
return false;
}
@Override @Override
public List<TableView> getTables(UUID roomId) throws MageException { public List<TableView> getTables(UUID roomId) throws MageException {
try { try {
@ -202,13 +215,13 @@ public class ServerImpl extends RemoteServer implements Server {
} }
@Override @Override
public void startGame(final UUID sessionId, final UUID roomId, final UUID tableId) throws MageException { public void startMatch(final UUID sessionId, final UUID roomId, final UUID tableId) throws MageException {
try { try {
rmiExecutor.execute( rmiExecutor.execute(
new Runnable() { new Runnable() {
@Override @Override
public void run() { public void run() {
TableManager.getInstance().startGame(sessionId, roomId, tableId); TableManager.getInstance().startMatch(sessionId, roomId, tableId);
} }
} }
); );

View file

@ -31,11 +31,13 @@ package mage.server;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.UUID; import java.util.UUID;
import java.util.logging.Logger; import java.util.logging.Logger;
import mage.cards.decks.Deck;
import mage.interfaces.callback.CallbackServerSession; import mage.interfaces.callback.CallbackServerSession;
import mage.interfaces.callback.ClientCallback; import mage.interfaces.callback.ClientCallback;
import mage.server.game.GameManager; import mage.server.game.GameManager;
import mage.server.game.TableManager; import mage.server.game.TableManager;
import mage.util.Logging; import mage.util.Logging;
import mage.view.TableClientMessage;
/** /**
* *
@ -90,7 +92,11 @@ public class Session {
} }
public void gameStarted(final UUID gameId, final UUID playerId) { public void gameStarted(final UUID gameId, final UUID playerId) {
fireCallback(new ClientCallback("startGame", new UUID[] {gameId, playerId})); fireCallback(new ClientCallback("startGame", new TableClientMessage(gameId, playerId)));
}
public void sideboard(final Deck deck, final UUID tableId) {
fireCallback(new ClientCallback("sideboard", new TableClientMessage(deck, tableId)));
} }
public void watchGame(final UUID gameId) { public void watchGame(final UUID gameId) {

View file

@ -82,15 +82,17 @@ public class GameController implements GameCallback {
private Game game; private Game game;
private UUID chatId; private UUID chatId;
private UUID tableId; private UUID tableId;
private UUID choosingPlayerId;
private Future<?> gameFuture; private Future<?> gameFuture;
public GameController(Game game, ConcurrentHashMap<UUID, UUID> sessionPlayerMap, UUID tableId) { public GameController(Game game, ConcurrentHashMap<UUID, UUID> sessionPlayerMap, UUID tableId, UUID choosingPlayerId) {
gameSessionId = UUID.randomUUID(); gameSessionId = UUID.randomUUID();
this.sessionPlayerMap = sessionPlayerMap; this.sessionPlayerMap = sessionPlayerMap;
chatId = ChatManager.getInstance().createChatSession(); chatId = ChatManager.getInstance().createChatSession();
this.game = game; this.game = game;
this.tableId = tableId; this.tableId = tableId;
this.choosingPlayerId = choosingPlayerId;
init(); init();
} }
@ -186,7 +188,7 @@ public class GameController implements GameCallback {
return; return;
} }
} }
GameWorker worker = new GameWorker(game, this); GameWorker worker = new GameWorker(game, choosingPlayerId, this);
gameFuture = gameExecutor.submit(worker); gameFuture = gameExecutor.submit(worker);
} }
} }

View file

@ -30,17 +30,15 @@ package mage.server.game;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import mage.Constants.MultiplayerAttackOption; import mage.game.match.Match;
import mage.Constants.RangeOfInfluence; import mage.game.match.MatchOptions;
import mage.game.Game;
import mage.util.Logging; import mage.util.Logging;
import mage.game.GameType; import mage.game.match.MatchType;
import mage.view.GameTypeView; import mage.view.GameTypeView;
/** /**
@ -52,8 +50,8 @@ public class GameFactory {
private final static GameFactory INSTANCE = new GameFactory(); private final static GameFactory INSTANCE = new GameFactory();
private final static Logger logger = Logging.getLogger(GameFactory.class.getName()); private final static Logger logger = Logging.getLogger(GameFactory.class.getName());
private Map<String, Class<Game>> games = new HashMap<String, Class<Game>>(); private Map<String, Class<Match>> games = new HashMap<String, Class<Match>>();
private Map<String, GameType> gameTypes = new HashMap<String, GameType>(); private Map<String, MatchType> gameTypes = new HashMap<String, MatchType>();
private List<GameTypeView> gameTypeViews = new ArrayList<GameTypeView>(); private List<GameTypeView> gameTypeViews = new ArrayList<GameTypeView>();
@ -63,31 +61,31 @@ public class GameFactory {
private GameFactory() {} private GameFactory() {}
public Game createGame(String gameType, MultiplayerAttackOption attackOption, RangeOfInfluence range) { public Match createMatch(String gameType, MatchOptions options) {
Game game; Match match;
Constructor<Game> con; Constructor<Match> con;
try { try {
con = games.get(gameType).getConstructor(new Class[]{MultiplayerAttackOption.class, RangeOfInfluence.class}); con = games.get(gameType).getConstructor(new Class[]{MatchOptions.class});
game = con.newInstance(new Object[] {attackOption, range}); match = con.newInstance(new Object[] {options});
} catch (Exception ex) { } catch (Exception ex) {
logger.log(Level.SEVERE, null, ex); logger.log(Level.SEVERE, null, ex);
return null; return null;
} }
logger.info("Game created: " + game.getId().toString()); logger.info("Game created: " + gameType); // + game.getId().toString());
return game; return match;
} }
public List<GameTypeView> getGameTypes() { public List<GameTypeView> getGameTypes() {
return gameTypeViews; return gameTypeViews;
} }
public void addGameType(String name, GameType gameType, Class game) { public void addGameType(String name, MatchType matchType, Class game) {
if (game != null) { if (game != null) {
this.games.put(name, game); this.games.put(name, game);
this.gameTypes.put(name, gameType); this.gameTypes.put(name, matchType);
this.gameTypeViews.add(new GameTypeView(gameType)); this.gameTypeViews.add(new GameTypeView(matchType));
} }
} }

View file

@ -49,8 +49,8 @@ public class GameManager {
private ConcurrentHashMap<UUID, GameController> gameControllers = new ConcurrentHashMap<UUID, GameController>(); private ConcurrentHashMap<UUID, GameController> gameControllers = new ConcurrentHashMap<UUID, GameController>();
public UUID createGameSession(Game game, ConcurrentHashMap<UUID, UUID> sessionPlayerMap, UUID tableId) { public UUID createGameSession(Game game, ConcurrentHashMap<UUID, UUID> sessionPlayerMap, UUID tableId, UUID choosingPlayerId) {
GameController gameController = new GameController(game, sessionPlayerMap, tableId); GameController gameController = new GameController(game, sessionPlayerMap, tableId, choosingPlayerId);
gameControllers.put(game.getId(), gameController); gameControllers.put(game.getId(), gameController);
return gameController.getSessionId(); return gameController.getSessionId();
} }

View file

@ -28,6 +28,7 @@
package mage.server.game; package mage.server.game;
import java.util.UUID;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -44,16 +45,18 @@ public class GameWorker implements Callable {
private GameCallback result; private GameCallback result;
private Game game; private Game game;
private UUID choosingPlayerId;
public GameWorker(Game game, GameCallback result) { public GameWorker(Game game, UUID choosingPlayerId, GameCallback result) {
this.game = game; this.game = game;
this.choosingPlayerId = choosingPlayerId;
this.result = result; this.result = result;
} }
@Override @Override
public Object call() { public Object call() {
try { try {
game.start(); game.start(choosingPlayerId);
result.gameResult(game.getWinner()); result.gameResult(game.getWinner());
} catch (Exception ex) { } catch (Exception ex) {
logger.log(Level.SEVERE, null, ex); logger.log(Level.SEVERE, null, ex);

View file

@ -30,10 +30,9 @@ package mage.server.game;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import mage.Constants.MultiplayerAttackOption;
import mage.Constants.RangeOfInfluence;
import mage.cards.decks.DeckCardLists; import mage.cards.decks.DeckCardLists;
import mage.game.GameException; import mage.game.GameException;
import mage.game.match.MatchOptions;
import mage.view.TableView; import mage.view.TableView;
/** /**
@ -44,7 +43,7 @@ public interface GamesRoom extends Room {
public List<TableView> getTables(); public List<TableView> getTables();
public boolean joinTable(UUID sessionId, UUID tableId, String name, DeckCardLists deckList) throws GameException; public boolean joinTable(UUID sessionId, UUID tableId, String name, DeckCardLists deckList) throws GameException;
public TableView createTable(UUID sessionId, String gameType, String deckType, List<String> playerTypes, MultiplayerAttackOption attackOption, RangeOfInfluence range); public TableView createTable(UUID sessionId, MatchOptions options);
public void removeTable(UUID sessionId, UUID tableId); public void removeTable(UUID sessionId, UUID tableId);
public TableView getTable(UUID tableId); public TableView getTable(UUID tableId);
public void leaveTable(UUID sessionId, UUID tableId); public void leaveTable(UUID sessionId, UUID tableId);

View file

@ -35,10 +35,9 @@ import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger; import java.util.logging.Logger;
import mage.Constants.MultiplayerAttackOption;
import mage.Constants.RangeOfInfluence;
import mage.cards.decks.DeckCardLists; import mage.cards.decks.DeckCardLists;
import mage.game.GameException; import mage.game.GameException;
import mage.game.match.MatchOptions;
import mage.util.Logging; import mage.util.Logging;
import mage.view.TableView; import mage.view.TableView;
@ -71,8 +70,8 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable {
} }
@Override @Override
public TableView createTable(UUID sessionId, String gameType, String deckType, List<String> playerTypes, MultiplayerAttackOption attackOption, RangeOfInfluence range) { public TableView createTable(UUID sessionId, MatchOptions options) {
Table table = TableManager.getInstance().createTable(sessionId, gameType, deckType, playerTypes, attackOption, range); Table table = TableManager.getInstance().createTable(sessionId, options);
tables.put(table.getId(), table); tables.put(table.getId(), table);
return new TableView(table); return new TableView(table);
} }

View file

@ -39,7 +39,6 @@ import java.io.ObjectInput;
import java.io.ObjectOutput; import java.io.ObjectOutput;
import java.io.ObjectOutputStream; import java.io.ObjectOutputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.List;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -47,15 +46,18 @@ import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream; import java.util.zip.GZIPOutputStream;
import mage.Constants.MultiplayerAttackOption;
import mage.Constants.RangeOfInfluence;
import mage.Constants.TableState; import mage.Constants.TableState;
import mage.cards.decks.Deck; import mage.cards.decks.Deck;
import mage.cards.decks.DeckCardLists; import mage.cards.decks.DeckCardLists;
import mage.game.Game; import mage.game.Game;
import mage.game.GameException; import mage.game.GameException;
import mage.game.GameStates; import mage.game.GameStates;
import mage.game.match.Match;
import mage.game.Seat; import mage.game.Seat;
import mage.game.events.Listener;
import mage.game.events.TableEvent;
import mage.game.match.MatchOptions;
import mage.game.match.MatchPlayer;
import mage.players.Player; import mage.players.Player;
import mage.server.ChatManager; import mage.server.ChatManager;
import mage.server.Main; import mage.server.Main;
@ -73,17 +75,36 @@ public class TableController {
private UUID sessionId; private UUID sessionId;
private UUID chatId; private UUID chatId;
private UUID gameId;
private Table table; private Table table;
private Game game; private Match match;
private MatchOptions options;
private ConcurrentHashMap<UUID, UUID> sessionPlayerMap = new ConcurrentHashMap<UUID, UUID>(); private ConcurrentHashMap<UUID, UUID> sessionPlayerMap = new ConcurrentHashMap<UUID, UUID>();
public TableController(UUID sessionId, String gameType, String deckType, List<String> playerTypes, MultiplayerAttackOption attackOption, RangeOfInfluence range) { public TableController(UUID sessionId, MatchOptions options) {
this.sessionId = sessionId; this.sessionId = sessionId;
chatId = ChatManager.getInstance().createChatSession(); chatId = ChatManager.getInstance().createChatSession();
game = GameFactory.getInstance().createGame(gameType, attackOption, range); this.options = options;
gameId = game.getId(); match = GameFactory.getInstance().createMatch(options.getGameType(), options);
table = new Table(gameType, DeckValidatorFactory.getInstance().createDeckValidator(deckType), playerTypes); table = new Table(options.getGameType(), options.getName(), DeckValidatorFactory.getInstance().createDeckValidator(options.getDeckType()), options.getPlayerTypes());
init();
}
private void init() {
table.addTableEventListener(
new Listener<TableEvent> () {
@Override
public void event(TableEvent event) {
switch (event.getEventType()) {
case SIDEBOARD:
sideboard(event.getPlayerId());
break;
case SUBMIT_DECK:
submitDeck(event.getPlayerId(), event.getDeck());
break;
}
}
}
);
} }
public synchronized boolean joinTable(UUID sessionId, String name, DeckCardLists deckList) throws GameException { public synchronized boolean joinTable(UUID sessionId, String name, DeckCardLists deckList) throws GameException {
@ -100,8 +121,7 @@ public class TableController {
} }
Player player = createPlayer(name, deck, seat.getPlayerType()); Player player = createPlayer(name, deck, seat.getPlayerType());
game.loadCards(deck.getCards(), player.getId()); match.addPlayer(player, deck);
game.loadCards(deck.getSideboard(), player.getId());
table.joinTable(player, seat); table.joinTable(player, seat);
logger.info("player joined " + player.getId()); logger.info("player joined " + player.getId());
//only add human players to sessionPlayerMap //only add human players to sessionPlayerMap
@ -112,11 +132,29 @@ public class TableController {
return true; return true;
} }
public synchronized boolean submitDeck(UUID sessionId, DeckCardLists deckList) throws GameException {
if (table.getState() != TableState.SIDEBOARDING) {
return false;
}
MatchPlayer player = match.getPlayer(sessionPlayerMap.get(sessionId));
Deck deck = Deck.load(deckList);
if (!Main.server.isTestMode() && !validDeck(deck)) {
throw new GameException(player.getPlayer().getName() + " has an invalid deck for this format");
}
submitDeck(sessionPlayerMap.get(sessionId), deck);
return true;
}
private void submitDeck(UUID playerId, Deck deck) {
MatchPlayer player = match.getPlayer(playerId);
player.submitDeck(deck);
}
public boolean watchTable(UUID sessionId) { public boolean watchTable(UUID sessionId) {
if (table.getState() != TableState.DUELING) { if (table.getState() != TableState.DUELING) {
return false; return false;
} }
SessionManager.getInstance().getSession(sessionId).watchGame(game.getId()); SessionManager.getInstance().getSession(sessionId).watchGame(match.getGame().getId());
return true; return true;
} }
@ -141,7 +179,7 @@ public class TableController {
} }
private Player createPlayer(String name, Deck deck, String playerType) { private Player createPlayer(String name, Deck deck, String playerType) {
Player player = PlayerFactory.getInstance().createPlayer(playerType, name, deck, game.getRangeOfInfluence()); Player player = PlayerFactory.getInstance().createPlayer(playerType, name, deck, options.getRange());
logger.info("Player created " + player.getId()); logger.info("Player created " + player.getId());
return player; return player;
} }
@ -151,26 +189,66 @@ public class TableController {
table.leaveTable(sessionPlayerMap.get(sessionId)); table.leaveTable(sessionPlayerMap.get(sessionId));
} }
public synchronized void startGame(UUID sessionId) { public synchronized void startMatch(UUID sessionId) {
if (sessionId.equals(this.sessionId) && table.getState() == TableState.STARTING) { if (sessionId.equals(this.sessionId) && table.getState() == TableState.STARTING) {
try { try {
table.initGame(game); match.startMatch();
startGame(null);
} catch (GameException ex) { } catch (GameException ex) {
logger.log(Level.SEVERE, null, ex); logger.log(Level.SEVERE, null, ex);
} }
GameManager.getInstance().createGameSession(game, sessionPlayerMap, table.getId()); }
}
private void startGame(UUID choosingPlayerId) throws GameException {
match.startGame();
table.initGame();
GameManager.getInstance().createGameSession(match.getGame(), sessionPlayerMap, table.getId(), choosingPlayerId);
SessionManager sessionManager = SessionManager.getInstance(); SessionManager sessionManager = SessionManager.getInstance();
for (Entry<UUID, UUID> entry: sessionPlayerMap.entrySet()) { for (Entry<UUID, UUID> entry: sessionPlayerMap.entrySet()) {
sessionManager.getSession(entry.getKey()).gameStarted(game.getId(), entry.getValue()); sessionManager.getSession(entry.getKey()).gameStarted(match.getGame().getId(), entry.getValue());
}
}
private void sideboard() {
table.sideboard();
for (MatchPlayer player: match.getPlayers()) {
player.setSideboarding();
player.getPlayer().sideboard(table);
}
while (!match.isDoneSideboarding()){}
}
private void sideboard(UUID playerId) {
SessionManager sessionManager = SessionManager.getInstance();
for (Entry<UUID, UUID> entry: sessionPlayerMap.entrySet()) {
if (entry.getValue().equals(playerId)) {
MatchPlayer player = match.getPlayer(entry.getValue());
sessionManager.getSession(entry.getKey()).sideboard(player.getDeck(), table.getId());
break;
} }
} }
} }
public void endGame() { public void endGame() {
UUID choosingPlayerId = match.getChooser();
match.endGame();
table.endGame(); table.endGame();
saveGame(); saveGame();
GameManager.getInstance().removeGame(game.getId()); GameManager.getInstance().removeGame(match.getGame().getId());
game = null; try {
if (!match.isMatchOver()) {
sideboard();
startGame(choosingPlayerId);
}
} catch (GameException ex) {
logger.log(Level.SEVERE, null, ex);
}
endMatch();
}
public void endMatch() {
match = null;
} }
public void swapSeats(int seatNum1, int seatNum2) { public void swapSeats(int seatNum1, int seatNum2) {
@ -188,17 +266,17 @@ public class TableController {
private void saveGame() { private void saveGame() {
try { try {
OutputStream file = new FileOutputStream("saved/" + game.getId().toString() + ".game"); OutputStream file = new FileOutputStream("saved/" + match.getGame().getId().toString() + ".game");
OutputStream buffer = new BufferedOutputStream(file); OutputStream buffer = new BufferedOutputStream(file);
ObjectOutput output = new ObjectOutputStream(new GZIPOutputStream(buffer)); ObjectOutput output = new ObjectOutputStream(new GZIPOutputStream(buffer));
try { try {
output.writeObject(game); output.writeObject(match.getGame());
output.writeObject(game.getGameStates()); output.writeObject(match.getGame().getGameStates());
} }
finally { finally {
output.close(); output.close();
} }
logger.log(Level.INFO, "Saved game:" + game.getId()); logger.log(Level.INFO, "Saved game:" + match.getGame().getId());
} }
catch(IOException ex) { catch(IOException ex) {
logger.log(Level.SEVERE, "Cannot save game.", ex); logger.log(Level.SEVERE, "Cannot save game.", ex);
@ -207,7 +285,7 @@ public class TableController {
private Game loadGame() { private Game loadGame() {
try{ try{
InputStream file = new FileInputStream("saved/" + gameId.toString() + ".game"); InputStream file = new FileInputStream("saved/" + match.getGame().toString() + ".game");
InputStream buffer = new BufferedInputStream(file); InputStream buffer = new BufferedInputStream(file);
ObjectInput input = new CopierObjectInputStream(Main.classLoader, new GZIPInputStream(buffer)); ObjectInput input = new CopierObjectInputStream(Main.classLoader, new GZIPInputStream(buffer));
try { try {
@ -224,7 +302,7 @@ public class TableController {
logger.log(Level.SEVERE, "Cannot load game. Class not found.", ex); logger.log(Level.SEVERE, "Cannot load game. Class not found.", ex);
} }
catch(IOException ex) { catch(IOException ex) {
logger.log(Level.SEVERE, "Cannot load game:" + game.getId(), ex); logger.log(Level.SEVERE, "Cannot load game:" + match.getGame().getId(), ex);
} }
return null; return null;
} }

View file

@ -30,14 +30,12 @@ package mage.server.game;
import mage.game.Table; import mage.game.Table;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger; import java.util.logging.Logger;
import mage.Constants.MultiplayerAttackOption;
import mage.Constants.RangeOfInfluence;
import mage.cards.decks.DeckCardLists; import mage.cards.decks.DeckCardLists;
import mage.game.GameException; import mage.game.GameException;
import mage.game.match.MatchOptions;
import mage.util.Logging; import mage.util.Logging;
/** /**
@ -56,8 +54,8 @@ public class TableManager {
return INSTANCE; return INSTANCE;
} }
public Table createTable(UUID sessionId, String gameType, String deckType, List<String> playerTypes, MultiplayerAttackOption attackOption, RangeOfInfluence range) { public Table createTable(UUID sessionId, MatchOptions options) {
TableController tableController = new TableController(sessionId, gameType, deckType, playerTypes, attackOption, range); TableController tableController = new TableController(sessionId, options);
controllers.put(tableController.getTable().getId(), tableController); controllers.put(tableController.getTable().getId(), tableController);
tables.put(tableController.getTable().getId(), tableController.getTable()); tables.put(tableController.getTable().getId(), tableController.getTable());
return tableController.getTable(); return tableController.getTable();
@ -75,6 +73,10 @@ public class TableManager {
return controllers.get(tableId).joinTable(sessionId, name, deckList); return controllers.get(tableId).joinTable(sessionId, name, deckList);
} }
public boolean submitDeck(UUID sessionId, UUID tableId, DeckCardLists deckList) throws GameException {
return controllers.get(tableId).submitDeck(sessionId, deckList);
}
public void removeSession(UUID sessionId) { public void removeSession(UUID sessionId) {
// TODO: search through tables and remove session // TODO: search through tables and remove session
} }
@ -100,8 +102,8 @@ public class TableManager {
return controllers.get(tableId).getChatId(); return controllers.get(tableId).getChatId();
} }
public void startGame(UUID sessionId, UUID roomId, UUID tableId) { public void startMatch(UUID sessionId, UUID roomId, UUID tableId) {
controllers.get(tableId).startGame(sessionId); controllers.get(tableId).startMatch(sessionId);
} }
public boolean watchTable(UUID sessionId, UUID tableId) { public boolean watchTable(UUID sessionId, UUID tableId) {

View file

@ -31,11 +31,7 @@ package mage.sets;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.HashMap; import java.util.*;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import mage.cards.Card; import mage.cards.Card;
@ -51,6 +47,7 @@ public class Sets extends HashMap<String, ExpansionSet> {
private static final Sets fINSTANCE = new Sets(); private static final Sets fINSTANCE = new Sets();
private static Set<String> names; private static Set<String> names;
protected static Random rnd = new Random();
public static Sets getInstance() { public static Sets getInstance() {
return fINSTANCE; return fINSTANCE;
@ -94,6 +91,24 @@ public class Sets extends HashMap<String, ExpansionSet> {
return null; return null;
} }
public static String findCard(String name, boolean random) {
if (!random) {
return findCard(name);
} else {
List<String> cards = new ArrayList<String>();
for (ExpansionSet set: fINSTANCE.values()) {
String cardName = set.findCard(name, true);
if (cardName != null) {
cards.add(cardName);
}
}
if (cards.size() > 0) {
return cards.get(rnd.nextInt(cards.size()));
}
}
return null;
}
public static ExpansionSet findSet(String code) { public static ExpansionSet findSet(String code) {
for (ExpansionSet set: fINSTANCE.values()) { for (ExpansionSet set: fINSTANCE.values()) {
if (set.getCode().equals(code)) if (set.getCode().equals(code))

View file

@ -42,11 +42,10 @@ import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.PreventionEffectImpl; import mage.abilities.effects.PreventionEffectImpl;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.AddPlusOneCountersSourceEffect; import mage.abilities.effects.common.AddPlusOneCountersSourceEffect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.counters.PlusOneCounter; import mage.counters.common.PlusOneCounter;
import mage.game.Game; import mage.game.Game;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType; import mage.game.events.GameEvent.EventType;

View file

@ -0,0 +1,80 @@
/*
* 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.scarsofmirrodin;
import java.util.UUID;
import mage.Constants.CardType;
import mage.Constants.Duration;
import mage.Constants.Rarity;
import mage.Constants.Zone;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.keyword.ReachAbility;
import mage.cards.CardImpl;
import mage.filter.Filter;
import mage.filter.FilterPermanent;
import mage.target.TargetPermanent;
/**
*
* @author Loki
*/
public class AcidWebSpider extends CardImpl<AcidWebSpider> {
private static FilterPermanent filter = new FilterPermanent("Equipment");
static {
filter.getSubtype().add("Equipment");
filter.setScopeSubtype(Filter.ComparisonScope.Any);
}
public AcidWebSpider (UUID ownerId) {
super(ownerId, 108, "Acid Web Spider", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{G}{G}");
this.expansionSetCode = "SOM";
this.subtype.add("Spider");
this.color.setGreen(true);
this.power = new MageInt(3);
this.toughness = new MageInt(5);
this.addAbility(ReachAbility.getInstance());
Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), true);
ability.addTarget(new TargetPermanent(filter));
this.addAbility(ability);
}
public AcidWebSpider (final AcidWebSpider card) {
super(card);
}
@Override
public AcidWebSpider copy() {
return new AcidWebSpider(this);
}
}

View file

@ -0,0 +1,103 @@
/*
* 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.scarsofmirrodin;
import java.util.UUID;
import mage.Constants;
import mage.Constants.CardType;
import mage.Constants.Duration;
import mage.Constants.Rarity;
import mage.Constants.Zone;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.BoostEquippedEffect;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.keyword.EquipAbility;
import mage.cards.CardImpl;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;
/**
*
* @author Loki
*/
public class ArgentumArmor extends CardImpl<ArgentumArmor> {
public ArgentumArmor (UUID ownerId) {
super(ownerId, 137, "Argentum Armor", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{6}");
this.expansionSetCode = "SOM";
this.subtype.add("Equipment");
this.addAbility(new EquipAbility(Constants.Outcome.AddAbility, new GenericManaCost(6)));
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(6, 6)));
this.addAbility(new ArgentumArmorAbiltity());
}
public ArgentumArmor (final ArgentumArmor card) {
super(card);
}
@Override
public ArgentumArmor copy() {
return new ArgentumArmor(this);
}
}
class ArgentumArmorAbiltity extends TriggeredAbilityImpl<ArgentumArmorAbiltity> {
public ArgentumArmorAbiltity() {
super(Zone.BATTLEFIELD, new DestroyTargetEffect());
this.addTarget(new TargetPermanent());
}
public ArgentumArmorAbiltity(final ArgentumArmorAbiltity abiltity) {
super(abiltity);
}
@Override
public ArgentumArmorAbiltity copy() {
return new ArgentumArmorAbiltity(this);
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent equipment = game.getPermanent(this.sourceId);
if (equipment != null && equipment.getAttachedTo() != null && event.getType() == GameEvent.EventType.ATTACKER_DECLARED && event.getSourceId().equals(equipment.getAttachedTo())) {
return true;
}
return false;
}
@Override
public String getRule() {
return "Whenever equipped creature attacks, destroy target permanent.";
}
}

View file

@ -0,0 +1,66 @@
/*
* 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.scarsofmirrodin;
import java.util.UUID;
import mage.Constants;
import mage.Constants.CardType;
import mage.Constants.Rarity;
import mage.Constants.Zone;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.BoostEquippedEffect;
import mage.abilities.keyword.EquipAbility;
import mage.cards.CardImpl;
/**
*
* @author Loki
*/
public class BarbedBattlegear extends CardImpl<BarbedBattlegear> {
public BarbedBattlegear (UUID ownerId) {
super(ownerId, 139, "Barbed Battlegear", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{3}");
this.expansionSetCode = "SOM";
this.subtype.add("Equipment");
this.addAbility(new EquipAbility(Constants.Outcome.AddAbility, new GenericManaCost(2)));
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(4, -1)));
}
public BarbedBattlegear (final BarbedBattlegear card) {
super(card);
}
@Override
public BarbedBattlegear copy() {
return new BarbedBattlegear(this);
}
}

View file

@ -0,0 +1,69 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.scarsofmirrodin;
import java.util.UUID;
import mage.Constants;
import mage.Constants.CardType;
import mage.Constants.Rarity;
import mage.Constants.Zone;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.GainAbilityAttachedEffect;
import mage.abilities.keyword.EquipAbility;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
/**
*
* @author Loki
*/
public class BladedPinions extends CardImpl<BladedPinions> {
public BladedPinions (UUID ownerId) {
super(ownerId, 140, "Bladed Pinions", Rarity.COMMON, new CardType[]{CardType.ARTIFACT}, "{2}");
this.expansionSetCode = "SOM";
this.subtype.add("Equipment");
this.addAbility(new EquipAbility(Constants.Outcome.AddAbility, new GenericManaCost(2)));
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(FlyingAbility.getInstance())));
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(FirstStrikeAbility.getInstance())));
}
public BladedPinions (final BladedPinions card) {
super(card);
}
@Override
public BladedPinions copy() {
return new BladedPinions(this);
}
}

View file

@ -0,0 +1,70 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.scarsofmirrodin;
import java.util.UUID;
import mage.Constants.CardType;
import mage.Constants.Duration;
import mage.Constants.Rarity;
import mage.Constants.Zone;
import mage.MageInt;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.RegenerateSourceEffect;
import mage.abilities.keyword.InfectAbility;
import mage.cards.CardImpl;
import mage.sets.magic2011.InfernoTitan;
/**
*
* @author Loki
*/
public class BlightMamba extends CardImpl<BlightMamba> {
public BlightMamba (UUID ownerId) {
super(ownerId, 112, "Blight Mamba", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{G}");
this.expansionSetCode = "SOM";
this.subtype.add("Snake");
this.color.setGreen(true);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
this.addAbility(InfectAbility.getInstance());
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect(), new ManaCostsImpl("{1}{G}")));
}
public BlightMamba (final BlightMamba card) {
super(card);
}
@Override
public BlightMamba copy() {
return new BlightMamba(this);
}
}

View file

@ -0,0 +1,63 @@
/*
* 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.scarsofmirrodin;
import java.util.UUID;
import mage.Constants.CardType;
import mage.Constants.Rarity;
import mage.MageInt;
import mage.abilities.keyword.InfectAbility;
import mage.cards.CardImpl;
/**
*
* @author Loki
*/
public class ContagiousNim extends CardImpl<ContagiousNim> {
public ContagiousNim (UUID ownerId) {
super(ownerId, 58, "Contagious Nim", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{B}");
this.expansionSetCode = "SOM";
this.subtype.add("Zombie");
this.color.setBlack(true);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
this.addAbility(InfectAbility.getInstance());
}
public ContagiousNim (final ContagiousNim card) {
super(card);
}
@Override
public ContagiousNim copy() {
return new ContagiousNim(this);
}
}

View file

@ -0,0 +1,70 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.scarsofmirrodin;
import java.util.UUID;
import mage.Constants.CardType;
import mage.Constants.Duration;
import mage.Constants.Rarity;
import mage.Constants.Zone;
import mage.MageInt;
import mage.abilities.StaticAbility;
import mage.abilities.keyword.InfectAbility;
import mage.cards.CardImpl;
/**
* Cystbearer
*
* @author nantuko
*/
public class Cystbearer extends CardImpl<Cystbearer> {
public Cystbearer(UUID ownerId) {
super(ownerId, 117, "Cystbearer", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{G}");
this.expansionSetCode = "SOM";
this.subtype.add("Beast");
this.color.setGreen(true);
this.power = new MageInt(2);
this.toughness = new MageInt(3);
this.addAbility(InfectAbility.getInstance());
}
public Cystbearer(final Cystbearer card) {
super(card);
}
@Override
public Cystbearer copy() {
return new Cystbearer(this);
}
}

View file

@ -0,0 +1,133 @@
/*
* 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.scarsofmirrodin;
import java.util.UUID;
import mage.Constants;
import mage.Constants.CardType;
import mage.Constants.Rarity;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentToken;
import mage.game.permanent.token.SoldierToken;
import mage.players.Player;
/**
*
* @author Loki
*/
public class ElspethTirel extends CardImpl<ElspethTirel> {
public ElspethTirel (UUID ownerId) {
super(ownerId, 6, "Elspeth Tirel", Rarity.MYTHIC, new CardType[]{CardType.PLANESWALKER}, "{3}{W}{W}");
this.expansionSetCode = "SOM";
this.subtype.add("Elspeth");
this.color.setWhite(true);
this.loyalty = new MageInt(4);
this.addAbility(new LoyaltyAbility(new ElspethTirelFirstEffect(), 2));
this.addAbility(new LoyaltyAbility(new CreateTokenEffect(new SoldierToken(), 3), -2));
this.addAbility(new LoyaltyAbility(new ElspethTirelThirdEffect(), -5));
}
public ElspethTirel (final ElspethTirel card) {
super(card);
}
@Override
public ElspethTirel copy() {
return new ElspethTirel(this);
}
}
class ElspethTirelFirstEffect extends OneShotEffect<ElspethTirelFirstEffect> {
public ElspethTirelFirstEffect() {
super(Constants.Outcome.GainLife);
}
public ElspethTirelFirstEffect(final ElspethTirelFirstEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
int amount = game.getBattlefield().countAll(new FilterCreaturePermanent(), source.getControllerId());
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
player.gainLife(amount, game);
}
return true;
}
@Override
public ElspethTirelFirstEffect copy() {
return new ElspethTirelFirstEffect(this);
}
@Override
public String getText(Ability source) {
return "You gain 1 life for each creature you control";
}
}
class ElspethTirelThirdEffect extends OneShotEffect<ElspethTirelThirdEffect> {
public ElspethTirelThirdEffect() {
super(Constants.Outcome.DestroyPermanent);
}
public ElspethTirelThirdEffect(final ElspethTirelThirdEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
for (Permanent perm: game.getBattlefield().getActivePermanents(source.getControllerId(), game)) {
if (!perm.getId().equals(source.getSourceId()) && !(perm instanceof PermanentToken) && ! (perm.getCardType().contains(CardType.LAND)))
perm.destroy(source.getId(), game, false);
}
return true;
}
@Override
public ElspethTirelThirdEffect copy() {
return new ElspethTirelThirdEffect(this);
}
@Override
public String getText(Ability source) {
return "Destroy all other permanents except for lands and tokens";
}
}

View file

@ -0,0 +1,222 @@
/*
* 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.scarsofmirrodin;
import java.util.UUID;
import mage.Constants;
import mage.Constants.CardType;
import mage.Constants.Duration;
import mage.Constants.Rarity;
import mage.Constants.Zone;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.ManaEffect;
import mage.abilities.effects.common.UntapTargetEffect;
import mage.cards.CardImpl;
import mage.filter.Filter;
import mage.filter.common.FilterLandPermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCreatureOrPlayer;
import mage.target.common.TargetLandPermanent;
/**
*
* @author Loki
*/
public class KothoftheHammer extends CardImpl<KothoftheHammer> {
static FilterLandPermanent filter = new FilterLandPermanent("Mountain");
static {
filter.getSubtype().add("Mountain");
filter.setScopeSubtype(Filter.ComparisonScope.Any);
}
public KothoftheHammer (UUID ownerId) {
super(ownerId, 94, "Koth of the Hammer", Rarity.MYTHIC, new CardType[]{CardType.PLANESWALKER}, "{2}{R}{R}");
this.expansionSetCode = "SOM";
this.subtype.add("Koth");
this.color.setRed(true);
this.loyalty = new MageInt(3);
Ability ability = new LoyaltyAbility(new UntapTargetEffect(), 1);
ability.addEffect(new KothoftheHammerFirstEffect());
ability.addTarget(new TargetLandPermanent(filter));
this.addAbility(ability);
this.addAbility(new LoyaltyAbility(new KothoftheHammerSecondEffect(), -2));
this.addAbility(new LoyaltyAbility(new KothoftheHammerThirdEffect(), -5));
}
public KothoftheHammer (final KothoftheHammer card) {
super(card);
}
@Override
public KothoftheHammer copy() {
return new KothoftheHammer(this);
}
}
class KothoftheHammerFirstEffect extends ContinuousEffectImpl<KothoftheHammerFirstEffect> {
public KothoftheHammerFirstEffect() {
super(Duration.EndOfTurn, Constants.Outcome.BecomeCreature);
}
public KothoftheHammerFirstEffect(final KothoftheHammerFirstEffect effect) {
super(effect);
}
@Override
public boolean apply(Constants.Layer layer, Constants.SubLayer sublayer, Ability source, Game game) {
Permanent permanent = game.getPermanent(source.getFirstTarget());
if (permanent != null) {
switch (layer) {
case TypeChangingEffects_4:
if (sublayer == Constants.SubLayer.NA) {
permanent.getCardType().add(CardType.CREATURE);
permanent.getSubtype().add("Elemental");
}
break;
case ColorChangingEffects_5:
if (sublayer == Constants.SubLayer.NA) {
permanent.getColor().setRed(true);
}
break;
case PTChangingEffects_7:
if (sublayer == Constants.SubLayer.SetPT_7b) {
permanent.getPower().setValue(4);
permanent.getToughness().setValue(4);
}
}
return true;
}
return false;
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public KothoftheHammerFirstEffect copy() {
return new KothoftheHammerFirstEffect(this);
}
@Override
public boolean hasLayer(Constants.Layer layer) {
return layer == Constants.Layer.PTChangingEffects_7 || layer == Constants.Layer.ColorChangingEffects_5 || layer == layer.TypeChangingEffects_4;
}
@Override
public String getText(Ability source) {
return "It becomes a 4/4 red Elemental creature until end of turn. It's still a land";
}
}
class KothoftheHammerSecondEffect extends OneShotEffect<KothoftheHammerSecondEffect> {
public KothoftheHammerSecondEffect() {
super(Constants.Outcome.PutManaInPool);
}
public KothoftheHammerSecondEffect(final KothoftheHammerSecondEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
int count = game.getBattlefield().count(KothoftheHammer.filter, source.getControllerId(), game);
int current = game.getPlayer(source.getControllerId()).getManaPool().getRed();
game.getPlayer(source.getControllerId()).getManaPool().setRed(count + current);
return true;
}
@Override
public KothoftheHammerSecondEffect copy() {
return new KothoftheHammerSecondEffect(this);
}
@Override
public String getText(Ability source) {
return "Add {R} to your mana pool for each Mountain you control";
}
}
class KothoftheHammerThirdEffect extends ContinuousEffectImpl<KothoftheHammerThirdEffect> {
public KothoftheHammerThirdEffect() {
super(Duration.EndOfGame, Constants.Outcome.AddAbility);
}
public KothoftheHammerThirdEffect(final KothoftheHammerThirdEffect effect) {
super(effect);
}
@Override
public boolean apply(Constants.Layer layer, Constants.SubLayer sublayer, Ability source, Game game) {
switch (layer) {
case AbilityAddingRemovingEffects_6:
if (sublayer == Constants.SubLayer.NA) {
for (Permanent p : game.getBattlefield().getActivePermanents(KothoftheHammer.filter, source.getControllerId(), game)) {
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new TapSourceCost());
ability.addTarget(new TargetCreatureOrPlayer());
p.addAbility(ability);
}
}
break;
}
return true;
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public KothoftheHammerThirdEffect copy() {
return new KothoftheHammerThirdEffect(this);
}
@Override
public boolean hasLayer(Constants.Layer layer) {
return layer == Constants.Layer.AbilityAddingRemovingEffects_6;
}
@Override
public String getText(Ability source) {
return "You get an emblem with \"Mountains you control have '{T}: This land deals 1 damage to target creature or player.'\"";
}
}

View file

@ -38,6 +38,7 @@ import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.common.AddCountersSourceEffect; import mage.abilities.effects.common.AddCountersSourceEffect;
import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.counters.CounterType;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import java.util.UUID; import java.util.UUID;
@ -51,9 +52,9 @@ public class LuxCannon extends CardImpl<LuxCannon> {
public LuxCannon (UUID ownerId) { public LuxCannon (UUID ownerId) {
super(ownerId, 173, "Lux Cannon", Rarity.MYTHIC, new CardType[]{CardType.ARTIFACT}, "{4}"); super(ownerId, 173, "Lux Cannon", Rarity.MYTHIC, new CardType[]{CardType.ARTIFACT}, "{4}");
this.expansionSetCode = "SOM"; this.expansionSetCode = "SOM";
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect("charge", 1), new TapSourceCost())); this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.CHARGE.getName(), 1), new TapSourceCost()));
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new TapSourceCost()); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new TapSourceCost());
ability.addCost(new RemoveCountersSourceCost("charge", 3)); ability.addCost(new RemoveCountersSourceCost(CounterType.CHARGE.getName(), 3));
ability.addTarget(new TargetPermanent()); ability.addTarget(new TargetPermanent());
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -0,0 +1,71 @@
/*
* 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.scarsofmirrodin;
import java.util.UUID;
import mage.Constants.CardType;
import mage.Constants.Duration;
import mage.Constants.Rarity;
import mage.Constants.Zone;
import mage.MageInt;
import mage.abilities.common.OnEventTriggeredAbility;
import mage.abilities.effects.common.SacrificeSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.InfectAbility;
import mage.cards.CardImpl;
import mage.game.events.GameEvent;
/**
*
* @author Loki
*/
public class PlagueStinger extends CardImpl<PlagueStinger> {
public PlagueStinger (UUID ownerId) {
super(ownerId, 75, "Plague Stinger", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{B}");
this.expansionSetCode = "SOM";
this.subtype.add("Insect");
this.subtype.add("Horror");
this.color.setBlack(true);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
this.addAbility(FlyingAbility.getInstance());
this.addAbility(InfectAbility.getInstance());
}
public PlagueStinger (final PlagueStinger card) {
super(card);
}
@Override
public PlagueStinger copy() {
return new PlagueStinger(this);
}
}

View file

@ -0,0 +1,69 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.scarsofmirrodin;
import java.util.UUID;
import mage.Constants.CardType;
import mage.Constants.Rarity;
import mage.MageInt;
import mage.abilities.common.OnEventTriggeredAbility;
import mage.abilities.effects.common.SacrificeSourceEffect;
import mage.abilities.keyword.InfectAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.game.events.GameEvent;
/**
*
* @author Loki
*/
public class Putrefax extends CardImpl<Putrefax> {
public Putrefax (UUID ownerId) {
super(ownerId, 126, "Putrefax", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{G}{G}");
this.expansionSetCode = "SOM";
this.subtype.add("Horror");
this.color.setGreen(true);
this.power = new MageInt(5);
this.toughness = new MageInt(3);
this.addAbility(TrampleAbility.getInstance());
this.addAbility(InfectAbility.getInstance());
this.addAbility(new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of the end step", new SacrificeSourceEffect()));
}
public Putrefax (final Putrefax card) {
super(card);
}
@Override
public Putrefax copy() {
return new Putrefax(this);
}
}

View file

@ -0,0 +1,76 @@
/*
* 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.scarsofmirrodin;
import java.util.UUID;
import mage.Constants.CardType;
import mage.Constants.Duration;
import mage.Constants.Rarity;
import mage.Constants.Zone;
import mage.MageInt;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.GainAbilitySourceEffect;
import mage.abilities.effects.common.RegenerateSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.HasteAbility;
import mage.abilities.keyword.InfectAbility;
import mage.cards.CardImpl;
/**
*
* @author Loki
*/
public class SkithiryxtheBlightDragon extends CardImpl<SkithiryxtheBlightDragon> {
public SkithiryxtheBlightDragon (UUID ownerId) {
super(ownerId, 79, "Skithiryx, the Blight Dragon", Rarity.MYTHIC, new CardType[]{CardType.CREATURE}, "{3}{B}{B}");
this.expansionSetCode = "SOM";
this.supertype.add("Legendary");
this.subtype.add("Dragon");
this.subtype.add("Skeleton");
this.color.setBlack(true);
this.power = new MageInt(4);
this.toughness = new MageInt(4);
this.addAbility(FlyingAbility.getInstance());
this.addAbility(InfectAbility.getInstance());
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl("{B}")));
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect(), new ManaCostsImpl("{B}{B}")));
}
public SkithiryxtheBlightDragon (final SkithiryxtheBlightDragon card) {
super(card);
}
@Override
public SkithiryxtheBlightDragon copy() {
return new SkithiryxtheBlightDragon(this);
}
}

View file

@ -0,0 +1,66 @@
/*
* 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.scarsofmirrodin;
import java.util.UUID;
import mage.Constants.CardType;
import mage.Constants.Duration;
import mage.Constants.Rarity;
import mage.Constants.Zone;
import mage.abilities.effects.common.BoostTargetEffect;
import mage.abilities.effects.common.GainAbilityTargetEffect;
import mage.abilities.keyword.InfectAbility;
import mage.cards.CardImpl;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author Loki
*/
public class TaintedStrike extends CardImpl<TaintedStrike> {
public TaintedStrike (UUID ownerId) {
super(ownerId, 80, "Tainted Strike", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{B}");
this.expansionSetCode = "SOM";
this.color.setBlack(true);
this.getSpellAbility().addEffect(new BoostTargetEffect(1, 0, Duration.EndOfTurn));
this.getSpellAbility().addEffect(new GainAbilityTargetEffect(InfectAbility.getInstance(), Duration.EndOfTurn));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
public TaintedStrike (final TaintedStrike card) {
super(card);
}
@Override
public TaintedStrike copy() {
return new TaintedStrike(this);
}
}

View file

@ -0,0 +1,71 @@
/*
* 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.scarsofmirrodin;
import java.util.UUID;
import mage.Constants.CardType;
import mage.Constants.Duration;
import mage.Constants.Rarity;
import mage.Constants.Zone;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.BoostTargetEffect;
import mage.cards.CardImpl;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author Loki
*/
public class VulshokHeartstoker extends CardImpl<VulshokHeartstoker> {
public VulshokHeartstoker (UUID ownerId) {
super(ownerId, 107, "Vulshok Heartstoker", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{R}");
this.expansionSetCode = "SOM";
this.subtype.add("Human");
this.subtype.add("Shaman");
this.color.setRed(true);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
Ability ability = new EntersBattlefieldTriggeredAbility(new BoostTargetEffect(2, 0, Duration.EndOfTurn));
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
public VulshokHeartstoker (final VulshokHeartstoker card) {
super(card);
}
@Override
public VulshokHeartstoker copy() {
return new VulshokHeartstoker(this);
}
}

View file

@ -0,0 +1,96 @@
/*
* 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.scarsofmirrodin;
import java.util.UUID;
import mage.Constants.CardType;
import mage.Constants.Duration;
import mage.Constants.Rarity;
import mage.Constants.Zone;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.PutIntoGraveFromBattlefieldTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.keyword.DeathtouchAbility;
import mage.abilities.keyword.LifelinkAbility;
import mage.cards.CardImpl;
import mage.game.permanent.token.Token;
/**
*
* @author Loki
*/
public class WurmcoilEngine extends CardImpl<WurmcoilEngine> {
public WurmcoilEngine (UUID ownerId) {
super(ownerId, 223, "Wurmcoil Engine", Rarity.MYTHIC, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{6}");
this.expansionSetCode = "SOM";
this.subtype.add("Wurm");
this.power = new MageInt(6);
this.toughness = new MageInt(6);
this.addAbility(DeathtouchAbility.getInstance());
this.addAbility(LifelinkAbility.getInstance());
Ability ability = new PutIntoGraveFromBattlefieldTriggeredAbility(new CreateTokenEffect(new Wurm1Token()), false);
ability.addEffect(new CreateTokenEffect(new Wurm2Token()));
this.addAbility(ability);
}
public WurmcoilEngine (final WurmcoilEngine card) {
super(card);
}
@Override
public WurmcoilEngine copy() {
return new WurmcoilEngine(this);
}
}
class Wurm1Token extends Token {
public Wurm1Token() {
super("Wurm", "a 3/3 colorless Wurm artifact creature token with deathtouch");
cardType.add(CardType.CREATURE);
subtype.add("Wurm");
power = new MageInt(3);
toughness = new MageInt(3);
this.addAbility(DeathtouchAbility.getInstance());
}
}
class Wurm2Token extends Token {
public Wurm2Token() {
super("Wurm", "a 3/3 colorless Wurm artifact creature token with lifelink");
cardType.add(CardType.CREATURE);
subtype.add("Wurm");
power = new MageInt(3);
toughness = new MageInt(3);
this.addAbility(LifelinkAbility.getInstance());
}
}

View file

@ -44,6 +44,7 @@ import mage.abilities.effects.common.ManaEffect;
import mage.abilities.keyword.MultikickerAbility; import mage.abilities.keyword.MultikickerAbility;
import mage.abilities.mana.ManaAbility; import mage.abilities.mana.ManaAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.counters.CounterType;
import mage.game.Game; import mage.game.Game;
/** /**
@ -55,7 +56,7 @@ public class EverflowingChalice extends CardImpl<EverflowingChalice> {
public EverflowingChalice(UUID ownerId) { public EverflowingChalice(UUID ownerId) {
super(ownerId, 123, "Everflowing Chalice", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{0}"); super(ownerId, 123, "Everflowing Chalice", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{0}");
this.expansionSetCode = "WWK"; this.expansionSetCode = "WWK";
Ability ability1 = new EntersBattlefieldTriggeredAbility(new AddCountersSourceEffect("charge", 1)); Ability ability1 = new EntersBattlefieldTriggeredAbility(new AddCountersSourceEffect(CounterType.CHARGE.getName(), 1));
MultikickerAbility ability = new MultikickerAbility(new GainAbilitySourceEffect(ability1, Duration.WhileOnBattlefield), false); MultikickerAbility ability = new MultikickerAbility(new GainAbilitySourceEffect(ability1, Duration.WhileOnBattlefield), false);
ability.addManaCost(new GenericManaCost(2)); ability.addManaCost(new GenericManaCost(2));
this.addAbility(ability); this.addAbility(ability);
@ -120,7 +121,7 @@ class EverflowingChaliceEffect extends ManaEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
this.mana.clear(); this.mana.clear();
this.mana.setColorless(game.getPermanent(source.getSourceId()).getCounters().getCount("charge")); this.mana.setColorless(game.getPermanent(source.getSourceId()).getCounters().getCount(CounterType.CHARGE));
return super.apply(game, source); return super.apply(game, source);
} }

View file

@ -40,7 +40,7 @@ import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.mana.GreenManaAbility; import mage.abilities.mana.GreenManaAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.counters.PlusOneCounter; import mage.counters.common.PlusOneCounter;
import mage.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;

View file

@ -21,6 +21,9 @@ import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import mage.Constants.MultiplayerAttackOption;
import mage.Constants.RangeOfInfluence;
import mage.game.match.MatchOptions;
/** /**
* Base for starting Mage server. * Base for starting Mage server.
@ -64,14 +67,18 @@ public class MageBase {
connect("player", "localhost", 17171); connect("player", "localhost", 17171);
UUID roomId = server.getMainRoomId(); UUID roomId = server.getMainRoomId();
List<String> playerTypes = new ArrayList<String>(); MatchOptions options = new MatchOptions("1", "Two Player Duel");
playerTypes.add("Human"); options.getPlayerTypes().add("Human");
playerTypes.add("Computer - default"); options.getPlayerTypes().add("Computer - default");
TableView table = server.createTable(sessionId, roomId, "Two Player Duel", "Limited", playerTypes, null, null); options.setDeckType("Limited");
options.setAttackOption(MultiplayerAttackOption.LEFT);
options.setRange(RangeOfInfluence.ALL);
options.setWinsNeeded(1);
TableView table = server.createTable(sessionId, roomId, options);
System.out.println("Cards in the deck: " + Sets.loadDeck("UW Control.dck").getCards().size()); System.out.println("Cards in the deck: " + Sets.loadDeck("UW Control.dck").getCards().size());
server.joinTable(sessionId, roomId, table.getTableId(), "Human", Sets.loadDeck("UW Control.dck")); server.joinTable(sessionId, roomId, table.getTableId(), "Human", Sets.loadDeck("UW Control.dck"));
server.joinTable(sessionId, roomId, table.getTableId(), "Computer", Sets.loadDeck("UW Control.dck")); server.joinTable(sessionId, roomId, table.getTableId(), "Computer", Sets.loadDeck("UW Control.dck"));
server.startGame(sessionId, roomId, table.getTableId()); server.startMatch(sessionId, roomId, table.getTableId());
synchronized (syncStart) { synchronized (syncStart) {
int waitTime = 7000; int waitTime = 7000;

View file

@ -39,7 +39,7 @@ import mage.filter.FilterAbility;
public interface Abilities<T extends Ability> extends List<T>, Serializable { public interface Abilities<T extends Ability> extends List<T>, Serializable {
public List<String> getRules(); public List<String> getRules(String source);
public Abilities<ActivatedAbility> getActivatedAbilities(Zone zone); public Abilities<ActivatedAbility> getActivatedAbilities(Zone zone);
public Abilities<ActivatedAbility> getActivatedAbilities(Zone zone, FilterAbility filter); public Abilities<ActivatedAbility> getActivatedAbilities(Zone zone, FilterAbility filter);
public Abilities<ManaAbility> getManaAbilities(Zone zone); public Abilities<ManaAbility> getManaAbilities(Zone zone);

View file

@ -58,7 +58,7 @@ public class AbilitiesImpl<T extends Ability> extends ArrayList<T> implements Ab
} }
@Override @Override
public List<String> getRules() { public List<String> getRules(String source) {
List<String> rules = new ArrayList<String>(); List<String> rules = new ArrayList<String>();
for (T ability:this) { for (T ability:this) {

View file

@ -73,6 +73,7 @@ public interface Ability extends Serializable {
public Zone getZone(); public Zone getZone();
public boolean isUsesStack(); public boolean isUsesStack();
public String getRule(); public String getRule();
public String getRule(String source);
public boolean activate(Game game, boolean noMana); public boolean activate(Game game, boolean noMana);
public boolean resolve(Game game); public boolean resolve(Game game);
public void reset(Game game); public void reset(Game game);

View file

@ -302,6 +302,17 @@ public abstract class AbilityImpl<T extends AbilityImpl<T>> implements Ability {
return sbRule.toString(); return sbRule.toString();
} }
@Override
public String getRule(String source) {
return formatRule(getRule(), source);
}
protected String formatRule(String rule, String source) {
String replace = rule.replace("{this}", source);
replace = replace.replace("{source}", source);
return replace;
}
@Override @Override
public void addCost(Cost cost) { public void addCost(Cost cost) {
if (cost != null) { if (cost != null) {

View file

@ -81,10 +81,13 @@ public abstract class TriggeredAbilityImpl<T extends TriggeredAbilityImpl<T>> ex
Player player = game.getPlayer(this.getControllerId()); Player player = game.getPlayer(this.getControllerId());
MageObject object = game.getObject(sourceId); MageObject object = game.getObject(sourceId);
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("Use ").append(this.getRule()).append("ability");
if (object != null) { if (object != null) {
sb.append("Use ").append(this.getRule(object.getName())).append("ability");
sb.append(" from ").append(object.getName()); sb.append(" from ").append(object.getName());
} }
else {
sb.append("Use ").append(this.getRule()).append("ability");
}
sb.append("?"); sb.append("?");
if (!player.chooseUse(this.effects.get(0).getOutcome(), sb.toString(), game)) { if (!player.chooseUse(this.effects.get(0).getOutcome(), sb.toString(), game)) {
return false; return false;

View file

@ -0,0 +1,19 @@
package mage.abilities.condition.common;
import mage.abilities.Ability;
import mage.abilities.condition.Condition;
import mage.filter.FilterPermanent;
import mage.game.Game;
public class ControlsPermanent implements Condition {
private FilterPermanent filter;
public ControlsPermanent(FilterPermanent filter) {
this.filter = filter;
}
@Override
public boolean apply(Game game, Ability source) {
return game.getBattlefield().countAll(filter, source.getControllerId()) > 0;
}
}

View file

@ -0,0 +1,32 @@
package mage.abilities.effects;
import mage.Constants;
import mage.abilities.Ability;
import mage.abilities.condition.Condition;
import mage.game.Game;
public abstract class WhileConditionContiniousEffect<T extends WhileConditionContiniousEffect<T>> extends ContinuousEffectImpl<T> {
protected Condition condition;
public WhileConditionContiniousEffect(Constants.Duration duration, Constants.Layer layer, Constants.SubLayer sublayer, Condition condition, Constants.Outcome outcome) {
super(duration, outcome);
this.condition = condition;
this.layer = layer;
this.sublayer = sublayer;
}
public WhileConditionContiniousEffect(final WhileConditionContiniousEffect effect) {
super(effect);
this.condition = effect.condition;
}
@Override
public boolean apply(Game game, Ability source) {
if (condition.apply(game, source)) {
return applyEffect(game, source);
}
return false;
}
protected abstract boolean applyEffect(Game game, Ability source);
}

View file

@ -31,7 +31,7 @@ package mage.abilities.effects.common;
import mage.Constants.Outcome; import mage.Constants.Outcome;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.counters.PlusOneCounter; import mage.counters.common.PlusOneCounter;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;

View file

@ -31,7 +31,7 @@ package mage.abilities.effects.common;
import mage.Constants.Outcome; import mage.Constants.Outcome;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.counters.PlusOneCounter; import mage.counters.common.PlusOneCounter;
import mage.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game; import mage.game.Game;

View file

@ -31,7 +31,7 @@ package mage.abilities.effects.common;
import mage.Constants.Outcome; import mage.Constants.Outcome;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.counters.PlusOneCounter; import mage.counters.common.PlusOneCounter;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;

View file

@ -28,7 +28,8 @@
package mage.abilities.effects.common; package mage.abilities.effects.common;
import mage.abilities.effects.WhileControlsContinuousEffect; import mage.abilities.condition.common.ControlsPermanent;
import mage.abilities.effects.WhileConditionContiniousEffect;
import mage.Constants.Duration; import mage.Constants.Duration;
import mage.Constants.Layer; import mage.Constants.Layer;
import mage.Constants.Outcome; import mage.Constants.Outcome;
@ -38,25 +39,32 @@ import mage.filter.FilterPermanent;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import java.util.ArrayList;
import java.util.List;
/** /**
* *
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class BoostSourceWhileControlsEffect extends WhileControlsContinuousEffect<BoostSourceWhileControlsEffect> { public class BoostSourceWhileControlsEffect extends WhileConditionContiniousEffect<BoostSourceWhileControlsEffect> {
private int power; private int power;
private int toughness; private int toughness;
private List<String> filterDescription;
public BoostSourceWhileControlsEffect(FilterPermanent filter, int power, int toughness) { public BoostSourceWhileControlsEffect(FilterPermanent filter, int power, int toughness) {
super(Duration.WhileOnBattlefield, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, filter, Outcome.BoostCreature); super(Duration.WhileOnBattlefield, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, new ControlsPermanent(filter), Outcome.BoostCreature);
this.power = power; this.power = power;
this.toughness = toughness; this.toughness = toughness;
this.filterDescription = filter.getName();
} }
public BoostSourceWhileControlsEffect(final BoostSourceWhileControlsEffect effect) { public BoostSourceWhileControlsEffect(final BoostSourceWhileControlsEffect effect) {
super(effect); super(effect);
this.power = effect.power; this.power = effect.power;
this.toughness = effect.toughness; this.toughness = effect.toughness;
this.filterDescription = new ArrayList<String>();
this.filterDescription.addAll(effect.filterDescription);
} }
@Override @Override
@ -76,6 +84,6 @@ public class BoostSourceWhileControlsEffect extends WhileControlsContinuousEffec
@Override @Override
public String getText(Ability source) { public String getText(Ability source) {
return "{this} gets " + String.format("%1$+d/%2$+d", power, toughness) + " as long as you control a " + filter.getName(); return "{this} gets " + String.format("%1$+d/%2$+d", power, toughness) + " as long as you control a " + filterDescription;
} }
} }

View file

@ -30,16 +30,18 @@ public class SacrificeSourceUnlessPaysEffect extends OneShotEffect<SacrificeSour
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId()); Player player = game.getPlayer(source.getControllerId());
if (player != null && player.chooseUse(Outcome.Benefit, cost.getText() + " or sacrifice {this}?", game)) { Permanent permanent = game.getPermanent(source.getSourceId());
if (player != null && permanent != null) {
if (player.chooseUse(Outcome.Benefit, cost.getText() + " or sacrifice " + permanent.getName() + "?", game)) {
cost.clearPaid(); cost.clearPaid();
if (cost.pay(game, source.getId(), source.getControllerId(), false)) if (cost.pay(game, source.getId(), source.getControllerId(), false))
return true; return true;
} }
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null)
permanent.sacrifice(source.getSourceId(), game); permanent.sacrifice(source.getSourceId(), game);
return true; return true;
} }
return false;
}
@Override @Override
public SacrificeSourceUnlessPaysEffect copy() { public SacrificeSourceUnlessPaysEffect copy() {
@ -48,6 +50,6 @@ public class SacrificeSourceUnlessPaysEffect extends OneShotEffect<SacrificeSour
@Override @Override
public String getText(Ability source) { public String getText(Ability source) {
return "sacrifice it unless you pay " + cost.getText(); return "sacrifice {this} unless you pay " + cost.getText();
} }
} }

View file

@ -57,16 +57,18 @@ public class TapSourceUnlessPaysEffect extends OneShotEffect<TapSourceUnlessPays
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId()); Player player = game.getPlayer(source.getControllerId());
if (player != null && player.chooseUse(Outcome.Benefit, cost.getText() + " or {this} comes into play tapped?", game)) { Permanent permanent = game.getPermanent(source.getSourceId());
if (player != null && permanent != null) {
if (player.chooseUse(Outcome.Benefit, cost.getText() + " or " + permanent.getName() + " comes into play tapped?", game)) {
cost.clearPaid(); cost.clearPaid();
if (cost.pay(game, source.getId(), source.getControllerId(), false)) if (cost.pay(game, source.getId(), source.getControllerId(), false))
return true; return true;
} }
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null)
permanent.setTapped(true); permanent.setTapped(true);
return true; return true;
} }
return false;
}
@Override @Override
public TapSourceUnlessPaysEffect copy() { public TapSourceUnlessPaysEffect copy() {

View file

@ -0,0 +1,84 @@
/*
* 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.io.ObjectStreamException;
import mage.Constants.Zone;
import mage.abilities.StaticAbility;
/**
* 702.87. Infect
*
* 702.87a. Infect is a static ability.
*
* 702.87b. Damage dealt to a player by a source with infect doesn't cause that player to lose life. Rather, it causes the player to get that many poison counters. See rule 119.3.
*
* 702.87c. Damage dealt to a creature by a source with infect isn't marked on that creature. Rather, it causes that many -1/-1 counters to be put on that creature. See rule 119.3.
*
* 702.87d. If a permanent leaves the battlefield before an effect causes it to deal damage, its last known information
* (Last Known Information: Information about an object that's no longer in the zone it's expected to be in, or information about a player that's no longer in the game. This information captures that object's last existence in that zone or that player's last existence in the game....)
* 112.7a. Once activated or triggered, an ability exists on the stack independently of its source. Destruction or removal of the source after that time won't affect the ability. Note that some abilities cause a source to do something (for example, "Prodigal Sorcerer deals 1 damage...
* 608.2b. If the spell or ability specifies targets, it checks whether the targets are still legal. A target that's no longer in the zone it was in when it was targeted is illegal. Other changes to the game state may cause a target to no longer be legal; for example, its...
* 608.2g. If an effect requires information from the game (such as the number of creatures on the battlefield), the answer is determined only once, when the effect is applied. If the effect requires information from a specific object, including the source of the ability itself or a...
* 800.4f. If an effect requires information about a specific player, the effect uses the current information about that player if he or she is still in the game; otherwise, the effect uses the last known information about that player before he or she left the game.
* is used to determine whether it had infect.
*
* 702.87e. The infect rules function no matter what zone an object with infect deals damage from.
*
* 702.87f. Multiple instances of infect on the same object are redundant.
*
* @author nantuko
*/
public class InfectAbility extends StaticAbility<InfectAbility> {
private static final InfectAbility fINSTANCE = new InfectAbility();
private Object readResolve() throws ObjectStreamException {
return fINSTANCE;
}
public static InfectAbility getInstance() {
return fINSTANCE;
}
private InfectAbility() {
super(Zone.ALL, null);
}
@Override
public String getRule() {
return "Infect";
}
@Override
public InfectAbility copy() {
return fINSTANCE;
}
}

View file

@ -93,7 +93,7 @@ public class LevelAbility extends StaticAbility<LevelAbility> {
else else
sb.append("-").append(level2); sb.append("-").append(level2);
sb.append(": ").append(power).append("/").append(toughness).append(" "); sb.append(": ").append(power).append("/").append(toughness).append(" ");
for (String rule: abilities.getRules()) { for (String rule: abilities.getRules("{this}")) {
sb.append(rule).append(" "); sb.append(rule).append(" ");
} }
return sb.toString(); return sb.toString();

View file

@ -0,0 +1,75 @@
/*
* 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 mage.Constants.Zone;
import mage.abilities.StaticAbility;
import java.io.ObjectStreamException;
/**
* 702.77. Wither
*
* 702.77a. Wither is a static ability. Damage dealt to a creature by a source with wither isn't marked on that creature. Rather, it causes that many -1/-1 counters to be put on that creature. See rule 119.3.
*
* 702.77b. If a permanent leaves the battlefield before an effect causes it to deal damage, its last known information is used to determine whether it had wither.
*
* 702.77c. The wither rules function no matter what zone an object with wither deals damage from.
*
* 702.77d. Multiple instances of wither on the same object are redundant.
*
* @author nantuko
*/
public class WitherAbility extends StaticAbility<WitherAbility> {
private static final WitherAbility fINSTANCE = new WitherAbility();
private Object readResolve() throws ObjectStreamException {
return fINSTANCE;
}
public static WitherAbility getInstance() {
return fINSTANCE;
}
private WitherAbility() {
super(Zone.ALL, null);
}
@Override
public String getRule() {
return "Wither";
}
@Override
public WitherAbility copy() {
return fINSTANCE;
}
}

View file

@ -130,9 +130,9 @@ public abstract class CardImpl<T extends CardImpl<T>> extends MageObjectImpl<T>
@Override @Override
public List<String> getRules() { public List<String> getRules() {
List<String> rules = abilities.getRules(); List<String> rules = abilities.getRules(this.name);
if (cardType.contains(CardType.INSTANT) || cardType.contains(CardType.SORCERY)) { if (cardType.contains(CardType.INSTANT) || cardType.contains(CardType.SORCERY)) {
rules.add(0, getSpellAbility().getRule()); rules.add(0, getSpellAbility().getRule(this.name));
} }
return rules; return rules;
} }

View file

@ -143,6 +143,19 @@ public abstract class ExpansionSet implements Serializable {
return null; return null;
} }
public String findCard(String name, boolean random) {
List<String> cards = new ArrayList<String>();
for (Card card: createCards()) {
if (name.equals(card.getName())) {
cards.add(card.getClass().getCanonicalName());
}
}
if (cards.size() > 0) {
return cards.get(rnd.nextInt(cards.size()));
}
return null;
}
public String findCard(int cardNum) { public String findCard(int cardNum) {
for (Card card: createCards()) { for (Card card: createCards()) {
if (card.getCardNumber() == cardNum) if (card.getCardNumber() == cardNum)

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