mirror of
https://github.com/correl/mage.git
synced 2024-12-26 03:00:11 +00:00
Merge origin/master
This commit is contained in:
commit
9741d34e1e
18 changed files with 1414 additions and 1210 deletions
|
@ -85,6 +85,7 @@ import mage.cards.repository.CardRepository;
|
|||
import mage.client.cards.BigCard;
|
||||
import mage.client.chat.ChatPanel;
|
||||
import mage.client.components.MageComponents;
|
||||
import mage.client.components.MageDesktopManager;
|
||||
import mage.client.components.MageJDesktop;
|
||||
import mage.client.components.MageRoundPane;
|
||||
import mage.client.components.MageUI;
|
||||
|
@ -236,6 +237,9 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
|||
Plugins.getInstance().loadPlugins();
|
||||
|
||||
initComponents();
|
||||
|
||||
desktopPane.setDesktopManager(new MageDesktopManager());
|
||||
|
||||
setSize(1024, 768);
|
||||
SettingsManager.getInstance().setScreenWidthAndHeight(1024, 768);
|
||||
DialogManager.updateParams(768, 1024, false);
|
||||
|
@ -692,8 +696,8 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
|||
public void showTournament(UUID tournamentId) {
|
||||
try {
|
||||
for (Component component : desktopPane.getComponents()) {
|
||||
if (component instanceof TournamentPane &&
|
||||
((TournamentPane) component).getTournamentId().equals(tournamentId)) {
|
||||
if (component instanceof TournamentPane
|
||||
&& ((TournamentPane) component).getTournamentId().equals(tournamentId)) {
|
||||
setActive((TournamentPane) component);
|
||||
return;
|
||||
}
|
||||
|
@ -780,10 +784,9 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
|||
}
|
||||
|
||||
/**
|
||||
* This method is called from within the constructor to
|
||||
* initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is
|
||||
* always regenerated by the Form Editor.
|
||||
* This method is called from within the constructor to initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is always
|
||||
* regenerated by the Form Editor.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
|
@ -1270,7 +1273,6 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
|||
games.remove(gameId);
|
||||
}
|
||||
|
||||
|
||||
public static DraftPanel getDraft(UUID draftId) {
|
||||
return drafts.get(draftId);
|
||||
}
|
||||
|
@ -1368,6 +1370,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
|||
}
|
||||
|
||||
class MagePaneMenuItem extends JCheckBoxMenuItem {
|
||||
|
||||
private final MagePane frame;
|
||||
|
||||
public MagePaneMenuItem(MagePane frame) {
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
*
|
||||
* Created on Dec 18, 2009, 10:40:12 AM
|
||||
*/
|
||||
|
||||
package mage.client.cards;
|
||||
|
||||
import java.awt.Color;
|
||||
|
@ -77,14 +76,16 @@ public class Cards extends javax.swing.JPanel {
|
|||
private int minOffsetY = 0;
|
||||
|
||||
/**
|
||||
* Defines whether component should be visible whenever there is no objects within.
|
||||
* True by default.
|
||||
* Defines whether component should be visible whenever there is no objects
|
||||
* within. True by default.
|
||||
*/
|
||||
private boolean isVisibleIfEmpty = true;
|
||||
|
||||
private Dimension cardDimension;
|
||||
|
||||
/** Creates new form Cards */
|
||||
/**
|
||||
* Creates new form Cards
|
||||
*/
|
||||
public Cards() {
|
||||
this(false);
|
||||
}
|
||||
|
@ -105,10 +106,12 @@ public class Cards extends javax.swing.JPanel {
|
|||
cardArea.setBorder(emptyBorder);
|
||||
}
|
||||
|
||||
public void cleanUp() {}
|
||||
public void cleanUp() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets components background color
|
||||
*
|
||||
* @param color
|
||||
*/
|
||||
public void setBackgroundColor(Color color) {
|
||||
|
@ -217,6 +220,10 @@ public class Cards extends javax.swing.JPanel {
|
|||
cardArea.repaint();
|
||||
}
|
||||
|
||||
public int getNumberOfCards() {
|
||||
return cards.size();
|
||||
}
|
||||
|
||||
private Dimension getCardDimension() {
|
||||
if (cardDimension == null) {
|
||||
cardDimension = new Dimension(Config.dimensions.frameWidth, Config.dimensions.frameHeight);
|
||||
|
@ -264,10 +271,10 @@ public class Cards extends javax.swing.JPanel {
|
|||
return cardArea.getComponentCount();
|
||||
}
|
||||
|
||||
/** This method is called from within the constructor to
|
||||
* initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is
|
||||
* always regenerated by the Form Editor.
|
||||
/**
|
||||
* This method is called from within the constructor to initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is always
|
||||
* regenerated by the Form Editor.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
|
@ -288,7 +295,6 @@ public class Cards extends javax.swing.JPanel {
|
|||
}
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JPanel cardArea;
|
||||
private javax.swing.JScrollPane jScrollPane1;
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package mage.client.components;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import javax.swing.DefaultDesktopManager;
|
||||
import javax.swing.DesktopManager;
|
||||
import javax.swing.JDesktopPane;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JInternalFrame;
|
||||
import javax.swing.SwingUtilities;
|
||||
import mage.client.dialog.CardInfoWindowDialog;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class MageDesktopManager extends DefaultDesktopManager {
|
||||
|
||||
static final int DESKTOP_ICON_WIDTH = 250;
|
||||
|
||||
@Override
|
||||
public void iconifyFrame(JInternalFrame f) {
|
||||
super.iconifyFrame(f);
|
||||
if (f instanceof CardInfoWindowDialog) {
|
||||
JInternalFrame.JDesktopIcon icon = f.getDesktopIcon();
|
||||
icon.setBounds(f.getX() + (f.getWidth() - DESKTOP_ICON_WIDTH), f.getY(), DESKTOP_ICON_WIDTH, icon.getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deiconifyFrame(JInternalFrame f) {
|
||||
super.deiconifyFrame(f);
|
||||
if (f instanceof CardInfoWindowDialog) {
|
||||
JInternalFrame.JDesktopIcon icon = f.getDesktopIcon();
|
||||
f.setBounds(icon.getX() + (DESKTOP_ICON_WIDTH - f.getWidth()), icon.getY(), f.getWidth(), f.getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
JFrame frame = new JFrame();
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
|
||||
JDesktopPane desktopPane = new JDesktopPane();
|
||||
DesktopManager dm = new MageDesktopManager();
|
||||
desktopPane.setDesktopManager(dm);
|
||||
JInternalFrame internalFrame = new JInternalFrame("Test Internal Frame", true, false, true, true);
|
||||
internalFrame.setSize(200, 150);
|
||||
internalFrame.setVisible(true);
|
||||
desktopPane.add(internalFrame);
|
||||
|
||||
frame.add(desktopPane, BorderLayout.CENTER);
|
||||
frame.setSize(800, 600);
|
||||
frame.setVisible(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -31,12 +31,9 @@
|
|||
*
|
||||
* Created on Feb 1, 2010, 3:00:35 PM
|
||||
*/
|
||||
|
||||
package mage.client.dialog;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.beans.PropertyVetoException;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
|
@ -61,7 +58,10 @@ import org.mage.plugins.card.utils.impl.ImageManagerImpl;
|
|||
*/
|
||||
public class CardInfoWindowDialog extends MageDialog {
|
||||
|
||||
public static enum ShowType { REVEAL, LOOKED_AT, EXILE, GRAVEYARD, OTHER };
|
||||
public static enum ShowType {
|
||||
|
||||
REVEAL, REVEAL_TOP_LIBRARY, LOOKED_AT, EXILE, GRAVEYARD, OTHER
|
||||
};
|
||||
|
||||
private ShowType showType;
|
||||
private boolean positioned;
|
||||
|
@ -84,9 +84,12 @@ public class CardInfoWindowDialog extends MageDialog {
|
|||
this.setFrameIcon(new ImageIcon(ImageManagerImpl.getInstance().getRevealedImage()));
|
||||
this.setClosable(true);
|
||||
break;
|
||||
case REVEAL_TOP_LIBRARY:
|
||||
this.setFrameIcon(new ImageIcon(ImageHelper.getImageFromResources("/info/library.png")));
|
||||
this.setClosable(true);
|
||||
break;
|
||||
case GRAVEYARD:
|
||||
this.setFrameIcon(new ImageIcon(ImageHelper.getImageFromResources("/info/grave.png")));
|
||||
this.setIconifiable(false);
|
||||
this.setClosable(true);
|
||||
this.setDefaultCloseOperation(HIDE_ON_CLOSE);
|
||||
addInternalFrameListener(new InternalFrameAdapter() {
|
||||
|
@ -123,6 +126,19 @@ public class CardInfoWindowDialog extends MageDialog {
|
|||
showAndPositionWindow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
if (showType.equals(ShowType.EXILE)) {
|
||||
if (cards == null || cards.getNumberOfCards() == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.show();
|
||||
if (positioned) { // check if in frame rectangle
|
||||
showAndPositionWindow();
|
||||
}
|
||||
}
|
||||
|
||||
private void showAndPositionWindow() {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
|
@ -132,13 +148,13 @@ public class CardInfoWindowDialog extends MageDialog {
|
|||
if (width > 0 && height > 0) {
|
||||
Point centered = SettingsManager.getInstance().getComponentPosition(width, height);
|
||||
if (!positioned) {
|
||||
positioned = true;
|
||||
int xPos = centered.x / 2;
|
||||
int yPos = centered.y / 2;
|
||||
CardInfoWindowDialog.this.setLocation(xPos, yPos);
|
||||
show();
|
||||
positioned = true;
|
||||
}
|
||||
GuiDisplayUtil.keepComponentInsideScreen(centered.x, centered.y, CardInfoWindowDialog.this);
|
||||
GuiDisplayUtil.keepComponentInsideFrame(centered.x, centered.y, CardInfoWindowDialog.this);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -155,16 +171,15 @@ public class CardInfoWindowDialog extends MageDialog {
|
|||
Logger.getLogger(CardInfoWindowDialog.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.hideDialog();
|
||||
}
|
||||
}
|
||||
|
||||
/** This method is called from within the constructor to
|
||||
* initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is
|
||||
* always regenerated by the Form Editor.
|
||||
/**
|
||||
* This method is called from within the constructor to initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is always
|
||||
* regenerated by the Form Editor.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
|
@ -191,7 +206,6 @@ public class CardInfoWindowDialog extends MageDialog {
|
|||
pack();
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private mage.client.cards.Cards cards;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
|
|
@ -133,7 +133,6 @@ import mage.view.SimpleCardsView;
|
|||
import org.apache.log4j.Logger;
|
||||
import org.mage.plugins.card.utils.impl.ImageManagerImpl;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com, nantuko8
|
||||
|
@ -344,8 +343,7 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
p.sizePlayer(smallMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (smallMode) {
|
||||
smallMode = false;
|
||||
Dimension bbDimension = new Dimension(256, 367);
|
||||
|
@ -410,7 +408,6 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
this.feedbackPanel.init(gameId);
|
||||
this.feedbackPanel.clear();
|
||||
|
||||
|
||||
this.btnConcede.setVisible(false);
|
||||
this.btnStopWatching.setVisible(true);
|
||||
this.btnSwitchHands.setVisible(false);
|
||||
|
@ -521,8 +518,7 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
while (true) {
|
||||
if (row == 1) {
|
||||
col++;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
col--;
|
||||
}
|
||||
if (col >= numColumns) {
|
||||
|
@ -597,7 +593,6 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
|
||||
hideAll();
|
||||
|
||||
|
||||
if (playerId != null) {
|
||||
// set visible only if we have any other hand visible than ours
|
||||
btnSwitchHands.setVisible(handCards.size() > 1);
|
||||
|
@ -660,7 +655,6 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
updateSkipButtons(player.isPassedTurn(), player.isPassedUntilEndOfTurn(), player.isPassedUntilNextMain(), player.isPassedAllTurns(), player.isPassedUntilStackResolved());
|
||||
}
|
||||
// update open or remove closed graveyard windows
|
||||
|
||||
graveyards.put(player.getName(), player.getGraveyard());
|
||||
if (graveyardWindows.containsKey(player.getName())) {
|
||||
CardInfoWindowDialog cardInfoWindowDialog = graveyardWindows.get(player.getName());
|
||||
|
@ -670,6 +664,12 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
cardInfoWindowDialog.loadCards(player.getGraveyard(), bigCard, gameId);
|
||||
}
|
||||
}
|
||||
// show top card window
|
||||
if (player.getTopCard() != null) {
|
||||
CardsView cardsView = new CardsView();
|
||||
cardsView.put(player.getTopCard().getId(), player.getTopCard());
|
||||
handleGameInfoWindow(revealed, ShowType.REVEAL_TOP_LIBRARY, player.getName() + "'s top library card", cardsView);
|
||||
}
|
||||
} else {
|
||||
logger.warn("Couldn't find player.");
|
||||
logger.warn(" uuid:" + player.getPlayerId());
|
||||
|
@ -759,6 +759,7 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
|
||||
/**
|
||||
* Set the same state for menu selections to all player areas.
|
||||
*
|
||||
* @param manaPoolAutomatic
|
||||
* @param manaPoolAutomaticRestricted
|
||||
*/
|
||||
|
@ -879,6 +880,18 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
newGraveyard.loadCards(graveyards.get(playerName), bigCard, gameId);
|
||||
}
|
||||
|
||||
public void openTopLibraryWindow(String playerName) {
|
||||
String title = playerName + "'s top library card";
|
||||
if (revealed.containsKey(title)) {
|
||||
CardInfoWindowDialog cardInfoWindowDialog = revealed.get(title);
|
||||
if (cardInfoWindowDialog.isVisible()) {
|
||||
cardInfoWindowDialog.hideDialog();
|
||||
} else {
|
||||
cardInfoWindowDialog.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void showRevealed(GameView game) {
|
||||
for (RevealedView revealView : game.getRevealed()) {
|
||||
handleGameInfoWindow(revealed, ShowType.REVEAL, revealView.getName(), revealView.getCards());
|
||||
|
@ -906,6 +919,7 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
if (cardInfoWindowDialog != null && !cardInfoWindowDialog.isClosed()) {
|
||||
switch (showType) {
|
||||
case REVEAL:
|
||||
case REVEAL_TOP_LIBRARY:
|
||||
cardInfoWindowDialog.loadCards((CardsView) cardsView, bigCard, gameId);
|
||||
break;
|
||||
case LOOKED_AT:
|
||||
|
@ -929,8 +943,10 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
updateGame(gameView);
|
||||
this.feedbackPanel.getFeedback(FeedbackMode.QUESTION, question, false, null, messageId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a pick target dialog and allows the player to pick a target (e.g. the pick triggered ability)
|
||||
* Shows a pick target dialog and allows the player to pick a target (e.g.
|
||||
* the pick triggered ability)
|
||||
*
|
||||
* @param message
|
||||
* @param cardView
|
||||
|
@ -1058,8 +1074,7 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
pickNumber.showDialog(min, max, message);
|
||||
if (pickNumber.isCancel()) {
|
||||
session.sendPlayerBoolean(gameId, false);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
session.sendPlayerInteger(gameId, pickNumber.getAmount());
|
||||
}
|
||||
}
|
||||
|
@ -1369,7 +1384,6 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
KeyStroke ks2 = KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0);
|
||||
this.getInputMap(c).put(ks2, "F2_PRESS");
|
||||
this.getActionMap().put("F2_PRESS", new AbstractAction() {
|
||||
|
@ -1578,7 +1592,6 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 164, Short.MAX_VALUE)
|
||||
.addComponent(pnlReplay, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
|
||||
.addGroup(gl_pnlShortCuts.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(btnSkipToNextTurn)
|
||||
.addComponent(btnSkipToEndTurn)
|
||||
|
@ -1616,7 +1629,6 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
createPhaseButton(name, phasesMouseAdapter);
|
||||
}
|
||||
|
||||
|
||||
int i = 0;
|
||||
for (String name : hoverButtons.keySet()) {
|
||||
HoverButton hoverButton = hoverButtons.get(name);
|
||||
|
@ -1701,9 +1713,12 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
|
||||
GridBagConstraints gbc = new GridBagConstraints();
|
||||
gbc.fill = GridBagConstraints.BOTH;
|
||||
gbc.gridx = 0; gbc.gridy = 0;
|
||||
gbc.gridwidth = 1; gbc.gridheight = 4; // size 4/5
|
||||
gbc.weightx = 1.0; gbc.weighty = 1.0;
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy = 0;
|
||||
gbc.gridwidth = 1;
|
||||
gbc.gridheight = 4; // size 4/5
|
||||
gbc.weightx = 1.0;
|
||||
gbc.weighty = 1.0;
|
||||
gbl.setConstraints(bigCard, gbc);
|
||||
jPanel2.add(bigCard);
|
||||
|
||||
|
@ -1877,8 +1892,7 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
private void btnStopReplayActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnStopReplayActionPerformed
|
||||
if (replayTask != null && !replayTask.isDone()) {
|
||||
replayTask.cancel(true);
|
||||
}
|
||||
else if (modalQuestion("Are you sure you want to stop replay?", "Stop replay") == JOptionPane.YES_OPTION) {
|
||||
} else if (modalQuestion("Are you sure you want to stop replay?", "Stop replay") == JOptionPane.YES_OPTION) {
|
||||
session.stopReplay(gameId);
|
||||
}
|
||||
}//GEN-LAST:event_btnStopReplayActionPerformed
|
||||
|
@ -2003,6 +2017,7 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
private boolean imagePanelState;
|
||||
|
||||
}
|
||||
|
||||
class ReplayTask extends SwingWorker<Void, Collection<MatchView>> {
|
||||
|
||||
private final Session session;
|
||||
|
@ -2032,8 +2047,8 @@ class ReplayTask extends SwingWorker<Void, Collection<MatchView>> {
|
|||
logger.fatal("Replay Match Task error", ex);
|
||||
} catch (ExecutionException ex) {
|
||||
logger.fatal("Replay Match Task error", ex);
|
||||
} catch (CancellationException ex) {}
|
||||
} catch (CancellationException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
*
|
||||
* Created on Nov 18, 2009, 3:01:31 PM
|
||||
*/
|
||||
|
||||
package mage.client.game;
|
||||
|
||||
import java.awt.Color;
|
||||
|
@ -57,18 +56,13 @@ import javax.swing.SwingConstants;
|
|||
import javax.swing.border.Border;
|
||||
import javax.swing.border.LineBorder;
|
||||
import mage.MageException;
|
||||
import mage.cards.MageCard;
|
||||
import mage.cards.action.ActionCallback;
|
||||
import mage.cards.decks.importer.DckDeckImporter;
|
||||
import mage.cards.repository.CardRepository;
|
||||
import mage.client.MageFrame;
|
||||
import mage.client.cards.BigCard;
|
||||
import mage.client.components.HoverButton;
|
||||
import mage.client.components.MageRoundPane;
|
||||
import mage.client.components.ext.dlg.DialogManager;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.client.plugins.adapters.MageActionCallback;
|
||||
import mage.client.plugins.impl.Plugins;
|
||||
import mage.client.util.CardsViewUtil;
|
||||
import mage.client.util.Command;
|
||||
import mage.client.util.ImageHelper;
|
||||
|
@ -77,7 +71,6 @@ import mage.components.ImagePanel;
|
|||
import mage.constants.ManaType;
|
||||
import mage.remote.Session;
|
||||
import mage.utils.timer.PriorityTimer;
|
||||
import mage.view.CardView;
|
||||
import mage.view.ManaPoolView;
|
||||
import mage.view.PlayerView;
|
||||
import org.mage.card.arcane.ManaSymbols;
|
||||
|
@ -105,18 +98,17 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
|||
private static final int PANEL_HEIGHT_SMALL = 212;
|
||||
private static final int MANA_LABEL_SIZE_HORIZONTAL = 20;
|
||||
|
||||
|
||||
private static final Border greenBorder = new LineBorder(Color.green, 3);
|
||||
private static final Border redBorder = new LineBorder(Color.red, 2);
|
||||
private static final Border emptyBorder = BorderFactory.createEmptyBorder(0, 0, 0, 0);
|
||||
|
||||
private static final Dimension topCardDimension = new Dimension(40, 56);
|
||||
|
||||
private int avatarId = -1;
|
||||
|
||||
private PriorityTimer timer;
|
||||
|
||||
/** Creates new form PlayerPanel */
|
||||
/**
|
||||
* Creates new form PlayerPanel
|
||||
*/
|
||||
public PlayerPanelExt() {
|
||||
setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
|
||||
initComponents();
|
||||
|
@ -158,7 +150,6 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
|||
if (timer != null) {
|
||||
this.timer.cancel();
|
||||
}
|
||||
topCardPanel.updateCallback(null, gameId);
|
||||
}
|
||||
|
||||
public void update(PlayerView player) {
|
||||
|
@ -272,26 +263,6 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
|||
this.btnPlayer.setBorder(emptyBorder);
|
||||
}
|
||||
|
||||
|
||||
synchronized (this) {
|
||||
if (player.getTopCard() != null) {
|
||||
if (topCard == null || !topCard.getId().equals(player.getTopCard().getId())) {
|
||||
if (topCard == null) {
|
||||
topCardPanel.setVisible(true);
|
||||
}
|
||||
topCard = player.getTopCard();
|
||||
topCardPanel.update(topCard);
|
||||
topCardPanel.updateImage();
|
||||
ActionCallback callback = Plugins.getInstance().getActionCallback();
|
||||
((MageActionCallback)callback).refreshSession();
|
||||
topCardPanel.updateCallback(callback, gameId);
|
||||
}
|
||||
} else if (topCard != null) {
|
||||
topCard = null;
|
||||
topCardPanel.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
update(player.getManaPool());
|
||||
}
|
||||
|
||||
|
@ -316,10 +287,10 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
|||
manaLabels.get("X").setText(Integer.toString(pool.getColorless()));
|
||||
}
|
||||
|
||||
/** This method is called from within the constructor to
|
||||
* initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is
|
||||
* always regenerated by the Form Editor.
|
||||
/**
|
||||
* This method is called from within the constructor to initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is always
|
||||
* regenerated by the Form Editor.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void initComponents() {
|
||||
|
@ -331,6 +302,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
|||
lifeLabel = new JLabel();
|
||||
handLabel = new JLabel();
|
||||
poisonLabel = new JLabel();
|
||||
graveLabel = new JLabel();
|
||||
libraryLabel = new JLabel();
|
||||
setOpaque(false);
|
||||
|
||||
|
@ -341,10 +313,6 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
|||
// Avatar
|
||||
Image image = ImageHelper.getImageFromResources(DEFAULT_AVATAR_PATH);
|
||||
|
||||
topCardPanel = Plugins.getInstance().getMageCard(new CardView(CardRepository.instance.findCard("Forest").getMockCard()), bigCard, topCardDimension, gameId, true);
|
||||
topCardPanel.setVisible(false);
|
||||
panelBackground.add(topCardPanel);
|
||||
|
||||
BufferedImage resized = ImageHelper.getResizedImage(BufferedImageBuilder.bufferImage(image, BufferedImage.TYPE_INT_ARGB), r);
|
||||
avatar = new HoverButton("player", resized, resized, resized, r);
|
||||
String showPlayerNamePermanently = MageFrame.getPreferences().get(PreferencesDialog.KEY_SHOW_PLAYER_NAMES_PERMANENTLY, "true");
|
||||
|
@ -395,16 +363,23 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
|||
libraryLabel.setToolTipText("Library");
|
||||
Image imageLibrary = ImageHelper.getImageFromResources("/info/library.png");
|
||||
BufferedImage resizedLibrary = ImageHelper.getResizedImage(BufferedImageBuilder.bufferImage(imageLibrary, BufferedImage.TYPE_INT_ARGB), r);
|
||||
library = new ImagePanel(resizedLibrary, ImagePanel.ACTUAL);
|
||||
|
||||
library = new HoverButton(null, resizedLibrary, resizedLibrary, resizedLibrary, r);
|
||||
library.setToolTipText("Library");
|
||||
library.setOpaque(false);
|
||||
library.setObserver(new Command() {
|
||||
@Override
|
||||
public void execute() {
|
||||
btnLibraryActionPerformed(null);
|
||||
}
|
||||
});
|
||||
|
||||
// Grave count and open graveyard button
|
||||
graveLabel = new JLabel();
|
||||
r = new Rectangle(21, 21);
|
||||
graveLabel.setToolTipText("Graveyard");
|
||||
Image imageGrave = ImageHelper.getImageFromResources("/info/grave.png");
|
||||
BufferedImage resizedGrave = ImageHelper.getResizedImage(BufferedImageBuilder.bufferImage(imageGrave, BufferedImage.TYPE_INT_ARGB), r);
|
||||
|
||||
grave = new HoverButton(null, resizedGrave, resizedGrave, resizedGrave, r);
|
||||
grave.setToolTipText("Graveyard");
|
||||
grave.setOpaque(false);
|
||||
|
@ -663,7 +638,6 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
|||
.addComponent(timerLabel, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(avatar, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 80, Short.MAX_VALUE))
|
||||
.addGap(14))
|
||||
|
||||
.addGroup(gl_panelBackground.createSequentialGroup()
|
||||
.addGap(6)
|
||||
.addComponent(zonesPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
|
@ -672,7 +646,6 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
|||
gl_panelBackground.setVerticalGroup(
|
||||
gl_panelBackground.createParallelGroup(Alignment.LEADING)
|
||||
.addGroup(gl_panelBackground.createSequentialGroup()
|
||||
|
||||
.addGap(6)
|
||||
.addComponent(avatar, GroupLayout.PREFERRED_SIZE, 80, GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(ComponentPlacement.RELATED)
|
||||
|
@ -704,7 +677,6 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
|||
.addGap(5)
|
||||
.addComponent(grave, GroupLayout.PREFERRED_SIZE, 21, GroupLayout.PREFERRED_SIZE)
|
||||
)
|
||||
|
||||
.addGroup(gl_panelBackground.createSequentialGroup()
|
||||
.addGroup(gl_panelBackground.createParallelGroup(Alignment.LEADING)
|
||||
.addGroup(gl_panelBackground.createSequentialGroup()
|
||||
|
@ -780,8 +752,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
|||
timerLabel.setVisible(true);
|
||||
panelBackground.setPreferredSize(new Dimension(PANEL_WIDTH - 2, PANEL_HEIGHT_SMALL));
|
||||
panelBackground.setBounds(0, 0, PANEL_WIDTH - 2, PANEL_HEIGHT_SMALL);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
avatar.setVisible(true);
|
||||
btnPlayer.setVisible(false);
|
||||
timerLabel.setVisible(false);
|
||||
|
@ -794,13 +765,12 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
|||
session.sendPlayerManaType(gameId, player.getPlayerId(), manaType);
|
||||
}
|
||||
|
||||
private void btnGraveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnGraveActionPerformed
|
||||
private void btnGraveActionPerformed(java.awt.event.ActionEvent evt) {
|
||||
MageFrame.getGame(gameId).openGraveyardWindow(player.getName());
|
||||
/*if (graveyard == null) {
|
||||
graveyard = new ShowCardsDialog();
|
||||
}*/
|
||||
//graveyard.loadCards(player.getName() + " graveyard", player.getGraveyard(), bigCard, Config.dimensions, gameId, false);
|
||||
// DialogManager.getManager(gameId).showGraveyardDialog(player.getGraveyard(), bigCard, gameId);
|
||||
}
|
||||
|
||||
private void btnLibraryActionPerformed(java.awt.event.ActionEvent evt) {
|
||||
MageFrame.getGame(gameId).openTopLibraryWindow(player.getName());
|
||||
}
|
||||
|
||||
private void btnCommandZoneActionPerformed(java.awt.event.ActionEvent evt) {
|
||||
|
@ -826,9 +796,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
|||
private ImagePanel poison;
|
||||
private ImagePanel hand;
|
||||
private HoverButton grave;
|
||||
private ImagePanel library;
|
||||
private CardView topCard;
|
||||
private MageCard topCardPanel;
|
||||
private HoverButton library;
|
||||
private JButton cheat;
|
||||
private MageRoundPane panelBackground;
|
||||
|
||||
|
|
|
@ -1,7 +1,21 @@
|
|||
package mage.client.util.gui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.util.ArrayList;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.SwingConstants;
|
||||
import mage.client.MageFrame;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.MageObjectType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.utils.CardUtil;
|
||||
import mage.view.CardView;
|
||||
import mage.view.CounterView;
|
||||
|
@ -10,12 +24,8 @@ import org.jdesktop.swingx.JXPanel;
|
|||
import org.mage.card.arcane.ManaSymbols;
|
||||
import org.mage.card.arcane.UI;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import mage.constants.Rarity;
|
||||
|
||||
public class GuiDisplayUtil {
|
||||
|
||||
private static final Font cardNameFont = new Font("Calibri", Font.BOLD, 15);
|
||||
private static final Insets DEFAULT_INSETS = new Insets(0, 0, 70, 25);
|
||||
private static final Insets COMPONENT_INSETS = new Insets(0, 0, 40, 40);
|
||||
|
@ -35,7 +45,6 @@ public class GuiDisplayUtil {
|
|||
descriptionPanel.setLayout(null);
|
||||
|
||||
//descriptionPanel.setBorder(BorderFactory.createLineBorder(Color.green));
|
||||
|
||||
JButton j = new JButton("");
|
||||
j.setBounds(0, 0, width, height);
|
||||
j.setBackground(Color.black);
|
||||
|
@ -70,36 +79,52 @@ public class GuiDisplayUtil {
|
|||
return out.toString().toLowerCase();
|
||||
}
|
||||
|
||||
public static void keepComponentInsideScreen(int centerX, int centerY, Component component) {
|
||||
Dimension screenDim = component.getToolkit().getScreenSize();
|
||||
GraphicsConfiguration g = component.getGraphicsConfiguration();
|
||||
|
||||
public static void keepComponentInsideScreen(int x, int y, Component c) {
|
||||
Dimension screenDim = c.getToolkit().getScreenSize();
|
||||
GraphicsConfiguration g = c.getGraphicsConfiguration();
|
||||
if (g != null) {
|
||||
Insets insets = c.getToolkit().getScreenInsets(g);
|
||||
Insets insets = component.getToolkit().getScreenInsets(g); // no usable space like toolbar
|
||||
boolean setLocation = false;
|
||||
if (x + c.getWidth() > screenDim.width - insets.right) {
|
||||
x = (screenDim.width - insets.right) - c.getWidth();
|
||||
if (centerX + component.getWidth() > screenDim.width - insets.right) {
|
||||
centerX = (screenDim.width - insets.right) - component.getWidth();
|
||||
setLocation = true;
|
||||
} else if (x < insets.left) {
|
||||
x = insets.left;
|
||||
} else if (centerX < insets.left) {
|
||||
centerX = insets.left;
|
||||
setLocation = true;
|
||||
}
|
||||
|
||||
if (y + c.getHeight() > screenDim.height - insets.bottom) {
|
||||
y = (screenDim.height - insets.bottom) - c.getHeight();
|
||||
if (centerY + component.getHeight() > screenDim.height - insets.bottom) {
|
||||
centerY = (screenDim.height - insets.bottom) - component.getHeight();
|
||||
setLocation = true;
|
||||
} else if (y < insets.top) {
|
||||
y = insets.top;
|
||||
} else if (centerY < insets.top) {
|
||||
centerY = insets.top;
|
||||
setLocation = true;
|
||||
}
|
||||
if (setLocation) {
|
||||
c.setLocation(x, y);
|
||||
component.setLocation(centerX, centerY);
|
||||
}
|
||||
} else {
|
||||
System.out.println("GuiDisplayUtil::keepComponentInsideScreen -> no GraphicsConfiguration");
|
||||
}
|
||||
}
|
||||
|
||||
static final int OVERLAP_LIMIT = 10;
|
||||
|
||||
public static void keepComponentInsideFrame(int centerX, int centerY, Component component) {
|
||||
Rectangle frameRec = MageFrame.getInstance().getBounds();
|
||||
boolean setLocation = false;
|
||||
if (component.getX() > (frameRec.width - OVERLAP_LIMIT)) {
|
||||
setLocation = true;
|
||||
}
|
||||
if (component.getY() > (frameRec.height - OVERLAP_LIMIT)) {
|
||||
setLocation = true;
|
||||
}
|
||||
if (setLocation) {
|
||||
component.setLocation(centerX, centerY);
|
||||
}
|
||||
}
|
||||
|
||||
public static Point keepComponentInsideParent(Point l, Point parentPoint, Component c, Component parent) {
|
||||
int dx = parentPoint.x + parent.getWidth() - DEFAULT_INSETS.right - COMPONENT_INSETS.right;
|
||||
if (l.x + c.getWidth() > dx) {
|
||||
|
|
|
@ -61,6 +61,7 @@ import mage.util.CardUtil;
|
|||
public class DaxosOfMeletis extends CardImpl {
|
||||
|
||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures with power 3 or greater");
|
||||
|
||||
static {
|
||||
filter.add(new PowerPredicate(Filter.ComparisonType.GreaterThan, 2));
|
||||
}
|
||||
|
@ -172,7 +173,7 @@ class DaxosOfMeletisCastFromExileEffect extends AsThoughEffectImpl {
|
|||
|
||||
@Override
|
||||
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
|
||||
if (sourceId.equals(cardId)) {
|
||||
if (sourceId.equals(cardId) && source.getControllerId().equals(affectedControllerId)) {
|
||||
ExileZone exileZone = game.getState().getExile().getExileZone(exileId);
|
||||
return exileZone != null && exileZone.contains(cardId);
|
||||
}
|
||||
|
@ -202,7 +203,10 @@ class DaxosOfMeletisSpendAnyManaEffect extends AsThoughEffectImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
|
||||
return sourceId.equals(getTargetPointer().getFirst(game, source));
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
return source.getControllerId().equals(affectedControllerId)
|
||||
&& objectId == ((FixedTarget) getTargetPointer()).getTarget()
|
||||
&& ((FixedTarget) getTargetPointer()).getZoneChangeCounter() + 1 == game.getState().getZoneChangeCounter(objectId)
|
||||
&& game.getState().getZone(objectId).equals(Zone.STACK);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,6 @@ import mage.filter.predicate.permanent.ControllerIdPredicate;
|
|||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.players.PlayerList;
|
||||
import mage.target.Target;
|
||||
import mage.target.common.TargetNonlandPermanent;
|
||||
|
||||
|
@ -58,7 +57,6 @@ public class CouncilsJudgment extends CardImpl {
|
|||
super(ownerId, 20, "Council's Judgment", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{1}{W}{W}");
|
||||
this.expansionSetCode = "VMA";
|
||||
|
||||
|
||||
// Will of the council - Starting with you, each player votes for a nonland permanent you don't control. Exile each permanent with the most votes or tied for most votes.
|
||||
this.getSpellAbility().addEffect(new CouncilsJudgmentEffect());
|
||||
}
|
||||
|
@ -98,13 +96,9 @@ class CouncilsJudgmentEffect extends OneShotEffect {
|
|||
FilterNonlandPermanent filter = new FilterNonlandPermanent("a nonland permanent " + controller.getLogName() + " doesn't control");
|
||||
filter.add(Predicates.not(new ControllerIdPredicate(controller.getId())));
|
||||
//Players each choose a legal permanent
|
||||
PlayerList playerList = game.getState().getPlayerList().copy();
|
||||
while (!playerList.get().equals(controller.getId()) && controller.isInGame()) {
|
||||
playerList.getNext();
|
||||
}
|
||||
do {
|
||||
Player player = game.getPlayer(playerList.get());
|
||||
if (player != null && player.isInGame()) {
|
||||
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
Target target = new TargetNonlandPermanent(filter);
|
||||
target.setNotTarget(true);
|
||||
if (player.choose(Outcome.Exile, target, source.getSourceId(), game)) {
|
||||
|
@ -116,8 +110,7 @@ class CouncilsJudgmentEffect extends OneShotEffect {
|
|||
maxCount = count;
|
||||
}
|
||||
chosenCards.put(permanent, count);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (maxCount == 0) {
|
||||
maxCount = 1;
|
||||
}
|
||||
|
@ -127,7 +120,8 @@ class CouncilsJudgmentEffect extends OneShotEffect {
|
|||
}
|
||||
}
|
||||
}
|
||||
} while (playerList.getNextInRange(controller, game) != controller && controller.isInGame());
|
||||
}
|
||||
|
||||
//Exile the card(s) with the most votes.
|
||||
for (Entry<Permanent, Integer> entry : chosenCards.entrySet()) {
|
||||
if (entry.getValue() == maxCount) {
|
||||
|
|
|
@ -84,21 +84,21 @@ class PleaForPowerEffect extends OneShotEffect {
|
|||
if (controller != null) {
|
||||
int timeCount = 0;
|
||||
int knowledgeCount = 0;
|
||||
for (UUID playerId : controller.getInRange()) {
|
||||
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
if (player.chooseUse(Outcome.ExtraTurn, "Choose time?", game)) {
|
||||
timeCount++;
|
||||
game.informPlayers(player.getLogName() + " has chosen: time");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
knowledgeCount++;
|
||||
game.informPlayers(player.getLogName() + " has chosen: knowledge");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (timeCount > knowledgeCount) {
|
||||
new AddExtraTurnControllerEffect().apply(game, source);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
controller.drawCards(3, game);
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package org.mage.test.cards.mana;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class SpendManaAsThoughItWereManaOfAnyColorTest extends CardTestPlayerBase {
|
||||
|
||||
@Test
|
||||
public void testDaxosOfMeletis() {
|
||||
// Put two 2/2 black Zombie creature tokens onto the battlefield.
|
||||
// Flashback (You may cast this card from your graveyard for its flashback cost. Then exile it.)
|
||||
addCard(Zone.LIBRARY, playerA, "Moan of the Unhallowed", 1);
|
||||
|
||||
skipInitShuffling();
|
||||
|
||||
// Daxos of Meletis can't be blocked by creatures with power 3 or greater.
|
||||
// Whenever Daxos of Meletis deals combat damage to a player, exile the top card of that player's library.
|
||||
// You gain life equal to that card's converted mana cost. Until end of turn, you may cast that card and
|
||||
// you may spend mana as though it were mana of any color to cast it.
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Daxos of Meletis", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Island", 4);
|
||||
|
||||
attack(2, playerB, "Daxos of Meletis");
|
||||
|
||||
castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerB, "Moan of the Unhallowed");
|
||||
|
||||
setStopAt(2, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertLife(playerA, 18);
|
||||
assertLife(playerB, 24);
|
||||
|
||||
assertExileCount(playerA, 0);
|
||||
assertGraveyardCount(playerA, "Moan of the Unhallowed", 1);
|
||||
assertPermanentCount(playerB, "Zombie", 2);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -5,9 +5,10 @@
|
|||
*/
|
||||
package org.mage.test.cards.triggers;
|
||||
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
|
@ -133,7 +134,6 @@ public class WorldgorgerDragonTest extends CardTestPlayerBase {
|
|||
*
|
||||
*/
|
||||
@Test
|
||||
@Ignore
|
||||
public void testWithAnimateDeadDifferentTargets() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
|
||||
|
||||
|
@ -153,35 +153,40 @@ public class WorldgorgerDragonTest extends CardTestPlayerBase {
|
|||
// When Staunch Defenders enters the battlefield, you gain 4 life.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Staunch Defenders", 1);
|
||||
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {B}");
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {B}");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Animate Dead", "Worldgorger Dragon");
|
||||
addTarget(playerA, "Worldgorger Dragon");
|
||||
addTarget(playerA, "Worldgorger Dragon");
|
||||
addTarget(playerA, "Silvercoat Lion");
|
||||
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||
setChoice(playerA, "Worldgorger Dragon");
|
||||
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||
|
||||
setChoice(playerA, "Silvercoat Lion");
|
||||
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Volcanic Geyser", playerB, 9);
|
||||
setChoice(playerA, "X=7");
|
||||
setChoice(playerA, "X=9");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Volcanic Geyser", 1);
|
||||
assertGraveyardCount(playerA, "Worldgorger Dragon", 1);
|
||||
assertPermanentCount(playerA, "Silvercoat Lion", 1);
|
||||
|
||||
assertLife(playerA, 24);
|
||||
assertLife(playerA, 28);
|
||||
assertLife(playerB, 11);
|
||||
|
||||
assertGraveyardCount(playerA, "Volcanic Geyser", 1);
|
||||
Assert.assertEquals("Mana pool", "[]", playerA.getManaAvailable(currentGame).toString());
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -628,8 +628,10 @@ public class TestPlayer implements Player {
|
|||
if (targetCardInGraveyard.canTarget(targetObject.getId(), game)) {
|
||||
if (alreadyTargetted != null && !alreadyTargetted.contains(targetObject.getId())) {
|
||||
targetCardInGraveyard.add(targetObject.getId(), game);
|
||||
choices.remove(choose2);
|
||||
targetFound = true;
|
||||
if (target.getTargets().size() >= target.getMaxNumberOfTargets()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -810,12 +812,14 @@ public class TestPlayer implements Player {
|
|||
@Override
|
||||
public int announceXMana(int min, int max, String message, Game game, Ability ability) {
|
||||
if (!choices.isEmpty()) {
|
||||
if (choices.get(0).startsWith("X=")) {
|
||||
int xValue = Integer.parseInt(choices.get(0).substring(2));
|
||||
choices.remove(0);
|
||||
for(String choice: choices) {
|
||||
if (choice.startsWith("X=")) {
|
||||
int xValue = Integer.parseInt(choice.substring(2));
|
||||
choices.remove(choice);
|
||||
return xValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return computerPlayer.announceXMana(min, max, message, game, ability);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.abilities;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -214,23 +213,26 @@ public abstract class AbilityImpl implements Ability {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
game.addEffect((ContinuousEffect) effect, this);
|
||||
}
|
||||
/**
|
||||
* All restrained trigger events are fired now.
|
||||
* To restrain the events is mainly neccessary because of the movement of multiple object at once.
|
||||
* If the event is fired directly as one object moved, other objects are not already in the correct zone
|
||||
* to check for their effects. (e.g. Valakut, the Molten Pinnacle)
|
||||
* All restrained trigger events are fired now. To restrain the
|
||||
* events is mainly neccessary because of the movement of
|
||||
* multiple object at once. If the event is fired directly as
|
||||
* one object moved, other objects are not already in the
|
||||
* correct zone to check for their effects. (e.g. Valakut, the
|
||||
* Molten Pinnacle)
|
||||
*/
|
||||
game.getState().handleSimultaneousEvent(game);
|
||||
game.resetShortLivingLKI();
|
||||
/**
|
||||
* game.applyEffects() has to be done at least for every effect that moves cards/permanent between zones,
|
||||
* so Static effects work as intened if dependant from the moved objects zone it is in
|
||||
* Otherwise for example were static abilities with replacement effects deactivated to late
|
||||
* Example: {@link org.mage.test.cards.replacement.DryadMilitantTest#testDiesByDestroy testDiesByDestroy}
|
||||
* game.applyEffects() has to be done at least for every effect
|
||||
* that moves cards/permanent between zones, so Static effects
|
||||
* work as intened if dependant from the moved objects zone it
|
||||
* is in Otherwise for example were static abilities with
|
||||
* replacement effects deactivated to late Example:
|
||||
* {@link org.mage.test.cards.replacement.DryadMilitantTest#testDiesByDestroy testDiesByDestroy}
|
||||
*/
|
||||
if (effect.applyEffectsAfter()) {
|
||||
game.applyEffects();
|
||||
|
@ -265,7 +267,6 @@ public abstract class AbilityImpl implements Ability {
|
|||
game.getContinuousEffects().applySpliceEffects(this, game);
|
||||
}
|
||||
|
||||
|
||||
if (sourceObject != null) {
|
||||
sourceObject.adjustChoices(this, game);
|
||||
}
|
||||
|
@ -394,7 +395,6 @@ public abstract class AbilityImpl implements Ability {
|
|||
}
|
||||
|
||||
//20100716 - 601.2g
|
||||
|
||||
if (!costs.pay(this, game, sourceId, activatorId, noMana)) {
|
||||
logger.debug("activate failed - non mana costs");
|
||||
return false;
|
||||
|
@ -479,7 +479,9 @@ public abstract class AbilityImpl implements Ability {
|
|||
|
||||
/**
|
||||
* Handles the setting of non mana X costs
|
||||
* @param controller *
|
||||
*
|
||||
* @param controller
|
||||
*
|
||||
* @param game
|
||||
* @return announce message
|
||||
*
|
||||
|
@ -566,7 +568,8 @@ public abstract class AbilityImpl implements Ability {
|
|||
|
||||
// called at end of turn for each Permanent
|
||||
@Override
|
||||
public void reset(Game game) {}
|
||||
public void reset(Game game) {
|
||||
}
|
||||
|
||||
// Is this still needed?
|
||||
protected boolean useAlternativeCost(Game game) {
|
||||
|
@ -605,7 +608,6 @@ public abstract class AbilityImpl implements Ability {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public UUID getSourceId() {
|
||||
return sourceId;
|
||||
|
@ -643,7 +645,8 @@ public abstract class AbilityImpl implements Ability {
|
|||
}
|
||||
|
||||
/**
|
||||
* Should be used by {@link mage.abilities.effects.CostModificationEffect cost modification effects}
|
||||
* Should be used by
|
||||
* {@link mage.abilities.effects.CostModificationEffect cost modification effects}
|
||||
* to manipulate what is actually paid before resolution.
|
||||
*
|
||||
* @return
|
||||
|
@ -792,8 +795,7 @@ public abstract class AbilityImpl implements Ability {
|
|||
if (cost != null) {
|
||||
if (cost instanceof ManaCost) {
|
||||
this.addManaCost((ManaCost) cost);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.costs.add(cost);
|
||||
}
|
||||
}
|
||||
|
@ -1170,12 +1172,12 @@ public abstract class AbilityImpl implements Ability {
|
|||
public void setSourceObject(MageObject sourceObject, Game game) {
|
||||
if (sourceObject == null) {
|
||||
this.sourceObject = game.getObject(sourceId);
|
||||
// if permanent get card /permanent instead of spell
|
||||
|
||||
} else {
|
||||
this.sourceObject = sourceObject;
|
||||
}
|
||||
this.sourceObjectZoneChangeCounter = game.getState().getZoneChangeCounter(sourceId);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -27,26 +27,25 @@
|
|||
*/
|
||||
package mage.abilities.effects;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.effects.common.AttachEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.cards.Card;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.PermanentCard;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.game.stack.StackAbility;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.effects.common.AttachEffect;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.target.common.TargetCardInGraveyard;
|
||||
|
||||
/**
|
||||
|
@ -118,6 +117,9 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
|
|||
if (targetId == null) {
|
||||
Target target = card.getSpellAbility().getTargets().get(0);
|
||||
enchantCardInGraveyard = target instanceof TargetCardInGraveyard;
|
||||
if (enchantCardInGraveyard && target != null) {
|
||||
target.clearChosen();
|
||||
}
|
||||
Player player = game.getPlayer(card.getOwnerId());
|
||||
Outcome auraOutcome = Outcome.BoostCreature;
|
||||
Ability: for (Ability ability:card.getAbilities()) {
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.abilities.effects;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
@ -147,6 +146,9 @@ public class ContinuousEffects implements Serializable {
|
|||
allEffectsLists.add(restrictionUntapNotMoreThanEffects);
|
||||
allEffectsLists.add(costModificationEffects);
|
||||
allEffectsLists.add(spliceCardEffects);
|
||||
for (ContinuousEffectsList continuousEffectsList : asThoughEffectsMap.values()) {
|
||||
allEffectsLists.add(continuousEffectsList);
|
||||
}
|
||||
}
|
||||
|
||||
public ContinuousEffects copy() {
|
||||
|
@ -232,9 +234,12 @@ public class ContinuousEffects implements Serializable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Initially effect timestamp is set when game starts in game.loadCard method.
|
||||
* After that timestamp should be updated whenever effect becomes "actual" meaning it becomes turned on
|
||||
* that is defined by Ability.#isInUseableZone(Game, boolean) method in #getLayeredEffects(Game).
|
||||
* Initially effect timestamp is set when game starts in game.loadCard
|
||||
* method. After that timestamp should be updated whenever effect becomes
|
||||
* "actual" meaning it becomes turned on that is defined by
|
||||
* Ability.#isInUseableZone(Game, boolean) method in
|
||||
* #getLayeredEffects(Game).
|
||||
*
|
||||
* @param layerEffects
|
||||
*/
|
||||
private void updateTimestamps(List<ContinuousEffect> layerEffects) {
|
||||
|
@ -323,7 +328,8 @@ public class ContinuousEffects implements Serializable {
|
|||
*
|
||||
* @param event
|
||||
* @param game
|
||||
* @return a list of all {@link ReplacementEffect} that apply to the current event
|
||||
* @return a list of all {@link ReplacementEffect} that apply to the current
|
||||
* event
|
||||
*/
|
||||
private HashMap<ReplacementEffect, HashSet<Ability>> getApplicableReplacementEffects(GameEvent event, Game game) {
|
||||
HashMap<ReplacementEffect, HashSet<Ability>> replaceEffects = new HashMap<>();
|
||||
|
@ -403,9 +409,9 @@ public class ContinuousEffects implements Serializable {
|
|||
return true;
|
||||
}
|
||||
MageObject object;
|
||||
if (event.getType().equals(EventType.ZONE_CHANGE) &&
|
||||
((ZoneChangeEvent)event).getFromZone().equals(Zone.BATTLEFIELD)&&
|
||||
event.getTargetId().equals(ability.getSourceId())) {
|
||||
if (event.getType().equals(EventType.ZONE_CHANGE)
|
||||
&& ((ZoneChangeEvent) event).getFromZone().equals(Zone.BATTLEFIELD)
|
||||
&& event.getTargetId().equals(ability.getSourceId())) {
|
||||
object = ((ZoneChangeEvent) event).getTarget();
|
||||
} else {
|
||||
object = game.getObject(ability.getSourceId());
|
||||
|
@ -461,6 +467,7 @@ public class ContinuousEffects implements Serializable {
|
|||
|
||||
return costEffects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters out splice effects that are not active.
|
||||
*
|
||||
|
@ -509,7 +516,6 @@ public class ContinuousEffects implements Serializable {
|
|||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Filters out asThough effects that are not active.
|
||||
*
|
||||
|
@ -537,21 +543,24 @@ public class ContinuousEffects implements Serializable {
|
|||
|
||||
/**
|
||||
* 601.2e The player determines the total cost of the spell. Usually this is
|
||||
* just the mana cost. Some spells have additional or alternative costs. Some
|
||||
* effects may increase or reduce the cost to pay, or may provide other alternative costs.
|
||||
* Costs may include paying mana, tapping permanents, sacrificing permanents,
|
||||
* discarding cards, and so on. The total cost is the mana cost or alternative
|
||||
* cost (as determined in rule 601.2b), plus all additional costs and cost increases,
|
||||
* and minus all cost reductions. If the mana component of the total cost is reduced
|
||||
* to nothing by cost reduction effects, it is considered to be {0}.
|
||||
* It can’t be reduced to less than {0}. Once the total cost is determined,
|
||||
* any effects that directly affect the total cost are applied.
|
||||
* Then the resulting total cost becomes “locked in.”
|
||||
* If effects would change the total cost after this time, they have no effect.
|
||||
* just the mana cost. Some spells have additional or alternative costs.
|
||||
* Some effects may increase or reduce the cost to pay, or may provide other
|
||||
* alternative costs. Costs may include paying mana, tapping permanents,
|
||||
* sacrificing permanents, discarding cards, and so on. The total cost is
|
||||
* the mana cost or alternative cost (as determined in rule 601.2b), plus
|
||||
* all additional costs and cost increases, and minus all cost reductions.
|
||||
* If the mana component of the total cost is reduced to nothing by cost
|
||||
* reduction effects, it is considered to be {0}. It can’t be reduced to
|
||||
* less than {0}. Once the total cost is determined, any effects that
|
||||
* directly affect the total cost are applied. Then the resulting total cost
|
||||
* becomes “locked in.” If effects would change the total cost after this
|
||||
* time, they have no effect.
|
||||
*/
|
||||
/**
|
||||
* Inspects all {@link Permanent permanent's} {@link Ability abilities} on the battlefield
|
||||
* for {@link CostModificationEffect cost modification effects} and applies them if necessary.
|
||||
* Inspects all {@link Permanent permanent's} {@link Ability abilities} on
|
||||
* the battlefield for
|
||||
* {@link CostModificationEffect cost modification effects} and applies them
|
||||
* if necessary.
|
||||
*
|
||||
* @param abilityToModify
|
||||
* @param game
|
||||
|
@ -658,7 +667,8 @@ public class ContinuousEffects implements Serializable {
|
|||
* @param event
|
||||
* @param targetAbility ability the event is attached to. can be null.
|
||||
* @param game
|
||||
* @param checkPlayableMode true if the event does not really happen but it's checked if the event would be replaced
|
||||
* @param checkPlayableMode true if the event does not really happen but
|
||||
* it's checked if the event would be replaced
|
||||
* @return
|
||||
*/
|
||||
public boolean preventedByRuleModification(GameEvent event, Ability targetAbility, Game game, boolean checkPlayableMode) {
|
||||
|
@ -930,9 +940,10 @@ public class ContinuousEffects implements Serializable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Adds a continuous ability with a reference to a sourceId.
|
||||
* It's used for effects that cease to exist again
|
||||
* So this effects were removed again before each applyEffecs
|
||||
* Adds a continuous ability with a reference to a sourceId. It's used for
|
||||
* effects that cease to exist again So this effects were removed again
|
||||
* before each applyEffecs
|
||||
*
|
||||
* @param effect
|
||||
* @param sourceId
|
||||
* @param source
|
||||
|
@ -1143,6 +1154,7 @@ public class ContinuousEffects implements Serializable {
|
|||
}
|
||||
|
||||
class ContinuousEffectSorter implements Comparator<ContinuousEffect>, Serializable {
|
||||
|
||||
@Override
|
||||
public int compare(ContinuousEffect one, ContinuousEffect two) {
|
||||
return Long.compare(one.getOrder(), two.getOrder());
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.abilities.effects.common.search;
|
||||
|
||||
import java.util.UUID;
|
||||
|
@ -106,7 +105,7 @@ public class SearchLibraryPutInHandEffect extends SearchEffect {
|
|||
String name = "Reveal";
|
||||
Card sourceCard = game.getCard(source.getSourceId());
|
||||
if (sourceCard != null) {
|
||||
name = sourceCard.getName();
|
||||
name = sourceCard.getIdName();
|
||||
}
|
||||
controller.revealCards(name, cards, game);
|
||||
}
|
||||
|
@ -126,14 +125,12 @@ public class SearchLibraryPutInHandEffect extends SearchEffect {
|
|||
if (target.getNumberOfTargets() == 0 && target.getMaxNumberOfTargets() > 0) {
|
||||
sb.append("up to ").append(CardUtil.numberToText(target.getMaxNumberOfTargets())).append(" ");
|
||||
sb.append(target.getTargetName()).append(revealCards ? ", reveal them, " : "").append(" and put them into your hand");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
sb.append("a ").append(target.getTargetName()).append(revealCards ? ", reveal it, " : "").append(" and put that card into your hand");
|
||||
}
|
||||
if (forceShuffle) {
|
||||
sb.append(". Then shuffle your library");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
sb.append(". If you do, shuffle your library");
|
||||
}
|
||||
staticText = sb.toString();
|
||||
|
|
|
@ -25,11 +25,27 @@
|
|||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.game;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.*;
|
||||
import mage.abilities.Abilities;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.ActivatedAbility;
|
||||
import mage.abilities.DelayedTriggeredAbilities;
|
||||
import mage.abilities.DelayedTriggeredAbility;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.SpecialActions;
|
||||
import mage.abilities.StaticAbility;
|
||||
import mage.abilities.TriggeredAbilities;
|
||||
import mage.abilities.TriggeredAbility;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.ContinuousEffects;
|
||||
import mage.abilities.effects.Effect;
|
||||
|
@ -53,26 +69,22 @@ import mage.players.PlayerList;
|
|||
import mage.players.Players;
|
||||
import mage.target.Target;
|
||||
import mage.util.Copyable;
|
||||
import mage.util.ThreadLocalStringBuilder;
|
||||
import mage.watchers.Watcher;
|
||||
import mage.watchers.Watchers;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import mage.util.ThreadLocalStringBuilder;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*
|
||||
* since at any time the game state may be copied and restored you cannot
|
||||
* rely on any object maintaining it's instance
|
||||
* it then becomes necessary to only refer to objects by their ids since
|
||||
* these will always remain constant throughout its lifetime
|
||||
* since at any time the game state may be copied and restored you cannot rely
|
||||
* on any object maintaining it's instance it then becomes necessary to only
|
||||
* refer to objects by their ids since these will always remain constant
|
||||
* throughout its lifetime
|
||||
*
|
||||
*/
|
||||
public class GameState implements Serializable, Copyable<GameState> {
|
||||
|
||||
|
||||
private static final transient ThreadLocalStringBuilder threadLocalBuilder = new ThreadLocalStringBuilder(1024);
|
||||
|
||||
private final Players players;
|
||||
|
@ -237,8 +249,7 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
sb.append("player").append(player.getLife()).append("hand");
|
||||
if (useHidden) {
|
||||
sb.append(player.getHand());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
sb.append(player.getHand().size());
|
||||
}
|
||||
sb.append("library").append(player.getLibrary().size()).append("graveyard").append(player.getGraveyard());
|
||||
|
@ -276,8 +287,7 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
sb.append("player").append(player.isPassed()).append(player.getLife()).append("hand");
|
||||
if (useHidden) {
|
||||
sb.append(player.getHand().getValue(game));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
sb.append(player.getHand().size());
|
||||
}
|
||||
sb.append("library").append(player.getLibrary().size());
|
||||
|
@ -335,8 +345,7 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
sb.append("player").append(player.isPassed()).append(player.getLife()).append("hand");
|
||||
if (playerId == player.getId()) {
|
||||
sb.append(player.getHand().getValue(game));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
sb.append(player.getHand().size());
|
||||
}
|
||||
sb.append("library").append(player.getLibrary().size());
|
||||
|
@ -462,8 +471,9 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the game step counter. This counter isgoing one up for
|
||||
* every played step during the game.
|
||||
* Gets the game step counter. This counter isgoing one up for every played
|
||||
* step during the game.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getStepNum() {
|
||||
|
@ -557,10 +567,9 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
// public void addMessage(String message) {
|
||||
// this.messages.add(message);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Returns a list of all players of the game ignoring range or
|
||||
* if a player has lost or left the game.
|
||||
* Returns a list of all players of the game ignoring range or if a player
|
||||
* has lost or left the game.
|
||||
*
|
||||
* @return playerList
|
||||
*/
|
||||
|
@ -569,8 +578,8 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all active players of the game, setting the
|
||||
* playerId to the current player of the list.
|
||||
* Returns a list of all active players of the game, setting the playerId to
|
||||
* the current player of the list.
|
||||
*
|
||||
* @param playerId
|
||||
* @return playerList
|
||||
|
@ -585,9 +594,11 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
newPlayerList.setCurrent(playerId);
|
||||
return newPlayerList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all active players of the game in range of playerId,
|
||||
* also setting the playerId to the current player of the list.
|
||||
* also setting the playerId to the first/current player of the list. Also
|
||||
* returning the other players in turn order.
|
||||
*
|
||||
* @param playerId
|
||||
* @param game
|
||||
|
@ -642,6 +653,7 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasSimultaneousEvents() {
|
||||
return !simultaneousEvents.isEmpty();
|
||||
}
|
||||
|
@ -682,8 +694,9 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Used for adding abilities that exist permanent on cards/permanents and are not
|
||||
* only gained for a certain time (e.g. until end of turn).
|
||||
* Used for adding abilities that exist permanent on cards/permanents and
|
||||
* are not only gained for a certain time (e.g. until end of turn).
|
||||
*
|
||||
* @param ability
|
||||
* @param attachedTo
|
||||
*/
|
||||
|
@ -700,14 +713,15 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ability instanceof TriggeredAbility) {
|
||||
} else if (ability instanceof TriggeredAbility) {
|
||||
this.triggers.add((TriggeredAbility) ability, attachedTo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Abilities that are applied to other objects or applie for a certain time span
|
||||
* Abilities that are applied to other objects or applie for a certain time
|
||||
* span
|
||||
*
|
||||
* @param ability
|
||||
* @param sourceId
|
||||
* @param attachedTo
|
||||
|
@ -721,8 +735,7 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ability instanceof TriggeredAbility) {
|
||||
} else if (ability instanceof TriggeredAbility) {
|
||||
// TODO: add sources for triggers - the same way as in addEffect: sources
|
||||
this.triggers.add((TriggeredAbility) ability, sourceId, attachedTo);
|
||||
}
|
||||
|
@ -788,9 +801,9 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Best only use immutable objects, otherwise the states/values of the object may be
|
||||
* changed by AI simulation, because the Value objects are not copied as the state
|
||||
* class is copied.
|
||||
* Best only use immutable objects, otherwise the states/values of the
|
||||
* object may be changed by AI simulation, because the Value objects are not
|
||||
* copied as the state class is copied.
|
||||
*
|
||||
* @param valueId
|
||||
* @param value
|
||||
|
@ -800,11 +813,14 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Other abilities are used to implement some special kind of continuous effects that give abilities to non permanents.
|
||||
* Other abilities are used to implement some special kind of continuous
|
||||
* effects that give abilities to non permanents.
|
||||
*
|
||||
* Crucible of Worlds - You may play land cards from your graveyard.
|
||||
* Past in Flames - Each instant and sorcery card in your graveyard gains flashback until end of turn. The flashback cost is equal to its mana cost.
|
||||
* Varolz, the Scar-Striped - Each creature card in your graveyard has scavenge. The scavenge cost is equal to its mana cost.
|
||||
* Crucible of Worlds - You may play land cards from your graveyard. Past in
|
||||
* Flames - Each instant and sorcery card in your graveyard gains flashback
|
||||
* until end of turn. The flashback cost is equal to its mana cost. Varolz,
|
||||
* the Scar-Striped - Each creature card in your graveyard has scavenge. The
|
||||
* scavenge cost is equal to its mana cost.
|
||||
*
|
||||
* @param objectId
|
||||
* @param zone
|
||||
|
@ -826,6 +842,7 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
|
||||
/**
|
||||
* Adds the ability to continuous or triggered abilities
|
||||
*
|
||||
* @param attachedTo
|
||||
* @param ability
|
||||
*/
|
||||
|
@ -840,8 +857,8 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Removes Triggered abilities that belong to sourceId
|
||||
* This is used if a token leaves the battlefield
|
||||
* Removes Triggered abilities that belong to sourceId This is used if a
|
||||
* token leaves the battlefield
|
||||
*
|
||||
* @param sourceId
|
||||
*/
|
||||
|
@ -849,7 +866,6 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
triggers.removeAbilitiesOfSource(sourceId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called before applyEffects
|
||||
*/
|
||||
|
@ -914,6 +930,7 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
|
||||
/**
|
||||
* Only used for diagnostic purposes of tests
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public TriggeredAbilities getTriggers() {
|
||||
|
|
Loading…
Reference in a new issue