diff --git a/Mage.Client/src/main/java/mage/client/MageFrame.java b/Mage.Client/src/main/java/mage/client/MageFrame.java index ff39fef25fc..21bcca05f1e 100644 --- a/Mage.Client/src/main/java/mage/client/MageFrame.java +++ b/Mage.Client/src/main/java/mage/client/MageFrame.java @@ -1,1790 +1,1792 @@ -/* -* 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.client; - -import java.awt.AlphaComposite; -import java.awt.Color; -import java.awt.Component; -import java.awt.Cursor; -import java.awt.Graphics2D; -import java.awt.Image; -import java.awt.Rectangle; -import java.awt.SplashScreen; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.awt.image.BufferedImage; -import java.beans.PropertyVetoException; -import java.io.IOException; -import java.io.InputStream; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.prefs.Preferences; -import javax.imageio.ImageIO; -import javax.swing.AbstractButton; -import javax.swing.Box; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JComponent; -import javax.swing.JDesktopPane; -import javax.swing.JEditorPane; -import javax.swing.JFrame; -import javax.swing.JInternalFrame; -import javax.swing.JLabel; -import javax.swing.JLayeredPane; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JToggleButton; -import javax.swing.JToolBar.Separator; -import javax.swing.SwingConstants; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; -import javax.swing.event.PopupMenuEvent; -import javax.swing.event.PopupMenuListener; -import mage.cards.decks.Deck; -import mage.cards.repository.CardCriteria; -import mage.cards.repository.CardInfo; -import mage.cards.repository.CardRepository; -import mage.cards.repository.ExpansionInfo; -import mage.cards.repository.ExpansionRepository; -import mage.choices.Choice; -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; -import mage.client.components.ext.dlg.DialogManager; -import mage.client.components.tray.MageTray; -import mage.client.constants.Constants.DeckEditorMode; -import mage.client.deckeditor.DeckEditorPane; -import mage.client.deckeditor.collection.viewer.CollectionViewerPane; -import mage.client.dialog.AboutDialog; -import mage.client.dialog.ConnectDialog; -import mage.client.dialog.ErrorDialog; -import mage.client.dialog.FeedbackDialog; -import mage.client.dialog.GameEndDialog; -import mage.client.dialog.PreferencesDialog; -import mage.client.dialog.TableWaitingDialog; -import mage.client.dialog.UserRequestDialog; -import mage.client.draft.DraftPane; -import mage.client.draft.DraftPanel; -import mage.client.game.GamePane; -import mage.client.game.GamePanel; -import mage.client.plugins.impl.Plugins; -import mage.client.table.TablesPane; -import mage.client.tournament.TournamentPane; -import mage.client.util.DeckUtil; -import mage.client.util.EDTExceptionHandler; -import mage.client.util.GameManager; -import mage.client.util.SettingsManager; -import mage.client.util.SystemUtil; -import mage.client.util.audio.AudioManager; -import mage.client.util.audio.MusicPlayer; -import mage.client.util.gui.ArrowBuilder; -import mage.client.util.stats.UpdateMemUsageTask; -import mage.components.ImagePanel; -import mage.interfaces.ServerState; -import mage.remote.Connection; -import mage.remote.Connection.ProxyType; -import mage.utils.MageVersion; -import mage.view.AbilityPickerView; -import mage.view.CardsView; -import mage.view.ChatMessage; -import mage.view.DeckView; -import mage.view.DraftPickView; -import mage.view.DraftView; -import mage.view.GameClientMessage; -import mage.view.GameEndView; -import mage.view.GameView; -import mage.view.UserRequestMessage; -import net.java.truevfs.access.TArchiveDetector; -import net.java.truevfs.access.TConfig; -import net.java.truevfs.kernel.spec.FsAccessOption; -import org.apache.log4j.Logger; -import org.mage.card.arcane.ManaSymbols; -import org.mage.network.Client; -import org.mage.network.interfaces.MageClient; -import org.mage.network.messages.MessageType; -import org.mage.plugins.card.constants.Constants; -import org.mage.plugins.card.images.DownloadPictures; -import org.mage.plugins.card.utils.impl.ImageManagerImpl; - -/** - * @author BetaSteward_at_googlemail.com - */ -public class MageFrame extends javax.swing.JFrame implements MageClient { - - private static final String TITLE_NAME = "XMage"; - - private static final Logger logger = Logger.getLogger(MageFrame.class); - private static final String liteModeArg = "-lite"; - private static final String grayModeArg = "-gray"; - private static final String fullscreenArg = "-fullscreen"; - - private static MageFrame instance; - - private static Client client; - private ServerState serverState; - private ConnectDialog connectDialog; - private final ErrorDialog errorDialog; - private static final Preferences prefs = Preferences.userNodeForPackage(MageFrame.class); - private JLabel title; - private Rectangle titleRectangle; - private static final MageVersion version = MageVersion.getCurrent(); - private UUID clientId; - private static MagePane activeFrame; - private static boolean liteMode = false; - //TODO: make gray theme, implement theme selector in preferences dialog - private static boolean grayMode = false; - private static boolean fullscreenMode = false; - - private static final Map chats = new HashMap<>(); - private static final Map games = new HashMap<>(); - private static final Map drafts = new HashMap<>(); - private static final MageUI ui = new MageUI(); - - private static UpdateMemUsageTask updateMemUsageTask; - - private static long startTime; - - public static Client getClient() { - return client; - } - - public static JDesktopPane getDesktop() { - return desktopPane; - } - - public static Preferences getPreferences() { - return prefs; - } - - public static boolean isLite() { - return liteMode; - } - - public static boolean isGray() { - return grayMode; - } - - public MageVersion getVersion() { - return version; - } - - public static MageFrame getInstance() { - return instance; - } - - /** - * Creates new form MageFrame - */ - public MageFrame() { - setWindowTitle(); - - clientId = UUID.randomUUID(); - EDTExceptionHandler.registerExceptionHandler(); - addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - exitApp(); - } - }); - - TConfig config = TConfig.current(); - config.setArchiveDetector(new TArchiveDetector("zip")); - config.setAccessPreference(FsAccessOption.STORE, true); - - try { - UIManager.put("desktop", new Color(0, 0, 0, 0)); - UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"); - } catch (Exception ex) { - logger.fatal(null, ex); - } - - ManaSymbols.loadImages(); - Plugins.getInstance().loadPlugins(); - - initComponents(); - - desktopPane.setDesktopManager(new MageDesktopManager()); - - setSize(1024, 768); - SettingsManager.getInstance().setScreenWidthAndHeight(1024, 768); - DialogManager.updateParams(768, 1024, false); - this.setExtendedState(JFrame.MAXIMIZED_BOTH); - - connectDialog = new ConnectDialog(); - desktopPane.add(connectDialog, JLayeredPane.POPUP_LAYER); - errorDialog = new ErrorDialog(); - errorDialog.setLocation(100, 100); - desktopPane.add(errorDialog, JLayeredPane.POPUP_LAYER); - ui.addComponent(MageComponents.DESKTOP_PANE, desktopPane); - - updateMemUsageTask = new UpdateMemUsageTask(jMemUsageLabel); - - try { - tablesPane = new TablesPane(); - desktopPane.add(tablesPane, javax.swing.JLayeredPane.DEFAULT_LAYER); - tablesPane.setMaximum(true); - } catch (PropertyVetoException ex) { - logger.fatal(null, ex); - } - - addTooltipContainer(); - setBackground(); - addMageLabel(); - setAppIcon(); - MageTray.getInstance().install(); - - desktopPane.add(ArrowBuilder.getBuilder().getArrowsManagerPanel(), JLayeredPane.DRAG_LAYER); - - desktopPane.addComponentListener(new ComponentAdapter() { - @Override - public void componentResized(ComponentEvent e) { - int width = ((JComponent) e.getSource()).getWidth(); - int height = ((JComponent) e.getSource()).getHeight(); - SettingsManager.getInstance().setScreenWidthAndHeight(width, height); - if (!liteMode && !grayMode) { - backgroundPane.setSize(width, height); - } - - ArrowBuilder.getBuilder().setSize(width, height); - - if (title != null) { - title.setBounds((int) (width - titleRectangle.getWidth()) / 2, (int) (height - titleRectangle.getHeight()) / 2, titleRectangle.width, titleRectangle.height); - } - } - }); - - mageToolbar.add(new javax.swing.JToolBar.Separator()); - mageToolbar.add(createWindowsButton()); - - //TODO: move to plugin impl - if (Plugins.getInstance().isCardPluginLoaded()) { - Separator separator = new javax.swing.JToolBar.Separator(); - mageToolbar.add(separator); - - JButton btnDownloadSymbols = new JButton("Symbols"); - btnDownloadSymbols.setFocusable(false); - btnDownloadSymbols.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); - btnDownloadSymbols.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); - btnDownloadSymbols.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnSymbolsActionPerformed(evt); - } - }); - mageToolbar.add(btnDownloadSymbols); - - separator = new javax.swing.JToolBar.Separator(); - mageToolbar.add(separator); - - JButton btnDownload = new JButton("Images"); - btnDownload.setFocusable(false); - btnDownload.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); - btnDownload.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); - btnDownload.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnImagesActionPerformed(evt); - } - }); - mageToolbar.add(btnDownload); - } - - if (Plugins.getInstance().isCounterPluginLoaded()) { - int i = Plugins.getInstance().getGamesPlayed(); - JLabel label = new JLabel(" Games played: " + String.valueOf(i)); - desktopPane.add(label, JLayeredPane.DEFAULT_LAYER + 1); - label.setVisible(true); - label.setForeground(Color.white); - label.setBounds(0, 0, 180, 30); - } - - ui.addButton(MageComponents.TABLES_MENU_BUTTON, btnGames); - - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - disableButtons(); - if (PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_CHECK, "false").equals("true")) { - checkForNewImages(); - } - updateMemUsageTask.execute(); - logger.info("Client start up time: " + ((System.currentTimeMillis() - startTime) / 1000 + " seconds")); - if (autoConnect()) { - enableButtons(); - } else { - connectDialog.showDialog(); - if (client != null && client.isConnected()) { - showGames(false); - } - } - } - }); - - if (SystemUtil.isMacOSX()) { - SystemUtil.enableMacOSFullScreenMode(this); - if (fullscreenMode) { - SystemUtil.toggleMacOSFullScreenMode(this); - } - } - } - - public void setWindowTitle() { - setTitle(TITLE_NAME + " Client: " - + version == null ? "" : version.toString() + " Server: " - + ((client != null && client.isConnected()) ? serverState.getVersion().toString():"")); - } - - private void addTooltipContainer() { - final JEditorPane cardInfoPane = (JEditorPane) Plugins.getInstance().getCardInfoPane(); - if (cardInfoPane == null) { - return; - } - cardInfoPane.setSize(Constants.TOOLTIP_WIDTH_MIN, Constants.TOOLTIP_HEIGHT_MIN); - 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, - Constants.TOOLTIP_WIDTH_MIN + Constants.TOOLTIP_BORDER_WIDTH, - Constants.TOOLTIP_HEIGHT_MIN + Constants.TOOLTIP_BORDER_WIDTH); - - desktopPane.add(popupContainer, JLayeredPane.POPUP_LAYER); - - ui.addComponent(MageComponents.CARD_INFO_PANE, cardInfoPane); - ui.addComponent(MageComponents.POPUP_CONTAINER, popupContainer); - - // preview panel normal - JPanel cardPreviewContainer = new JPanel(); - cardPreviewContainer.setOpaque(false); - cardPreviewContainer.setLayout(null); - BigCard bigCard = new BigCard(); - bigCard.setSize(320, 500); - bigCard.setLocation(40, 40); - bigCard.setBackground(new Color(0, 0, 0, 0)); - - cardPreviewContainer.add(bigCard); - cardPreviewContainer.setVisible(false); - cardPreviewContainer.setBounds(0, 0, 320 + 80, 500 + 30); - - ui.addComponent(MageComponents.CARD_PREVIEW_PANE, bigCard); - ui.addComponent(MageComponents.CARD_PREVIEW_CONTAINER, cardPreviewContainer); - - desktopPane.add(cardPreviewContainer, JLayeredPane.POPUP_LAYER); - - // preview panel rotated - JPanel cardPreviewContainerRotated = new JPanel(); - cardPreviewContainerRotated.setOpaque(false); - cardPreviewContainerRotated.setLayout(null); - bigCard = new BigCard(true); - bigCard.setSize(500, 350); - bigCard.setLocation(40, 40); - bigCard.setBackground(new Color(0, 0, 0, 0)); - cardPreviewContainerRotated.add(bigCard); - cardPreviewContainerRotated.setVisible(false); - cardPreviewContainerRotated.setBounds(0, 0, 500 + 80, 420 + 30); - - ui.addComponent(MageComponents.CARD_PREVIEW_PANE_ROTATED, bigCard); - ui.addComponent(MageComponents.CARD_PREVIEW_CONTAINER_ROTATED, cardPreviewContainerRotated); - - desktopPane.add(cardPreviewContainerRotated, JLayeredPane.POPUP_LAYER); - - } - - private void setBackground() { - if (liteMode || grayMode) { - return; - } - String filename = "/background.jpg"; - try { - if (Plugins.getInstance().isThemePluginLoaded()) { - backgroundPane = (ImagePanel) Plugins.getInstance().updateTablePanel(new HashMap()); - } 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) { - logger.fatal("Error while setting background.", e); - } - } - - private void addMageLabel() { - if (liteMode || grayMode) { - return; - } - String filename = "/label-xmage.png"; - try { - InputStream is = this.getClass().getResourceAsStream(filename); - - float ratio = 1179.0f / 678.0f; - titleRectangle = new Rectangle(540, (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) { - logger.fatal("Error while adding mage label.", e); - } - } - - private void setAppIcon() { - Image image = ImageManagerImpl.getInstance().getAppImage(); - setIconImage(image); - } - - private AbstractButton createWindowsButton() { - final JToggleButton windowButton = new JToggleButton("Windows"); - windowButton.addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - if (e.getStateChange() == ItemEvent.SELECTED) { - createAndShowMenu((JComponent) e.getSource(), windowButton); - } - } - }); - windowButton.setFocusable(false); - windowButton.setHorizontalTextPosition(SwingConstants.LEADING); - return windowButton; - } - - private void createAndShowMenu(final JComponent component, final AbstractButton windowButton) { - JPopupMenu menu = new JPopupMenu(); - JInternalFrame[] windows = desktopPane.getAllFramesInLayer(javax.swing.JLayeredPane.DEFAULT_LAYER); - MagePaneMenuItem menuItem; - - for (int i = 0; i < windows.length; i++) { - if (windows[i] instanceof MagePane) { - MagePane window = (MagePane) windows[i]; - if (window.isVisible()) { - menuItem = new MagePaneMenuItem(window); - menuItem.setState(i == 0); - menuItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent ae) { - MagePane frame = ((MagePaneMenuItem) ae.getSource()).getFrame(); - setActive(frame); - } - }); - menuItem.setIcon(window.getFrameIcon()); - menu.add(menuItem); - } - } - } - - menu.addPopupMenuListener(new PopupMenuListener() { - @Override - public void popupMenuWillBecomeVisible(PopupMenuEvent e) { - } - - @Override - public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { - windowButton.setSelected(false); - } - - @Override - public void popupMenuCanceled(PopupMenuEvent e) { - windowButton.setSelected(false); - } - }); - - menu.show(component, 0, component.getHeight()); - } - - private void checkForNewImages() { - long beforeCall = System.currentTimeMillis(); - List cards = CardRepository.instance.findCards(new CardCriteria()); - logger.info("Card pool load time: " + ((System.currentTimeMillis() - beforeCall) / 1000 + " seconds")); - - beforeCall = System.currentTimeMillis(); - if (DownloadPictures.checkForNewCards(cards)) { - logger.info("Card images checking time: " + ((System.currentTimeMillis() - beforeCall) / 1000 + " seconds")); - if (JOptionPane.showConfirmDialog(this, "New cards are available. Do you want to download the images?", "New images available", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { - DownloadPictures.startDownload(null, cards); - } - } - } - - public void btnImagesActionPerformed(java.awt.event.ActionEvent evt) { - List cards = CardRepository.instance.findCards(new CardCriteria()); - - DownloadPictures.startDownload(null, cards); - } - - public void btnSymbolsActionPerformed(java.awt.event.ActionEvent evt) { - if (JOptionPane.showConfirmDialog(this, "Do you want to download game symbols and additional image files?", "Download additional resources", JOptionPane.YES_NO_OPTION) == JOptionPane.OK_OPTION) { - Plugins.getInstance().downloadSymbols(); - } - } - - public static void setActive(MagePane frame) { - if (frame == null) { - activeFrame = null; - return; - } - logger.debug("Setting " + frame.getTitle() + " active"); - if (activeFrame != null) { - activeFrame.deactivated(); - } - activeFrame = frame; - activeFrame.setVisible(true); - activeFrame.toFront(); - try { - activeFrame.setSelected(true); - } catch (PropertyVetoException ex) { - logger.error("Error setting " + frame.getTitle() + " active"); - } - activeFrame.activated(); - ArrowBuilder.getBuilder().hideAllPanels(); - if (frame instanceof GamePane) { - ArrowBuilder.getBuilder().showPanel(((GamePane) frame).getGameId()); - MusicPlayer.playBGM(); - } else { - MusicPlayer.stopBGM(); - } - } - - public static void deactivate(MagePane frame) { - frame.setVisible(false); - setActive(getTopMost(frame)); - if (activeFrame != frame) { - frame.deactivated(); - } - - } - - private static MagePane getTopMost(MagePane exclude) { - MagePane topmost = null; - int best = Integer.MAX_VALUE; - for (JInternalFrame frame : desktopPane.getAllFramesInLayer(JLayeredPane.DEFAULT_LAYER)) { - if (frame.isVisible()) { - int z = desktopPane.getComponentZOrder(frame); - if (z < best) { - if (frame instanceof MagePane) { - best = z; - if (!frame.equals(exclude)) { - topmost = (MagePane) frame; - } - } - } - } - } - return topmost; - } - - /** - * Shows a game for a player of the game - * - * @param gameId - * @param playerId - */ - public void showGame(final UUID gameId, final UUID playerId) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - try { - GamePane gamePane = new GamePane(); - desktopPane.add(gamePane, JLayeredPane.DEFAULT_LAYER); - gamePane.setMaximum(true); - gamePane.setVisible(true); - gamePane.showGame(gameId, playerId); - setActive(gamePane); - } catch (PropertyVetoException ex) { - } - } - }); - } - - @Override - public void watchGame(final UUID gameId, final UUID chatId, final GameView game) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - try { - for(Component component :desktopPane.getComponents()) { - if (component instanceof GamePane - && ((GamePane) component).getGameId().equals(gameId)) { - setActive((GamePane) component); - return; - } - } - GamePane gamePane = new GamePane(); - desktopPane.add(gamePane, JLayeredPane.DEFAULT_LAYER); - gamePane.setMaximum(true); - gamePane.setVisible(true); - gamePane.watchGame(gameId, chatId, game); - setActive(gamePane); - } catch (PropertyVetoException ex) { - } - } - }); - } - - public void replayGame(final UUID gameId) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - try { - GamePane gamePane = new GamePane(); - desktopPane.add(gamePane, JLayeredPane.DEFAULT_LAYER); - gamePane.setMaximum(true); - gamePane.setVisible(true); - gamePane.replayGame(gameId); - setActive(gamePane); - } catch (PropertyVetoException ex) { - } - } - }); - } - - public void showDraft(final UUID draftId) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - try { - DraftPane draftPane = new DraftPane(); - desktopPane.add(draftPane, JLayeredPane.DEFAULT_LAYER); - draftPane.setMaximum(true); - draftPane.setVisible(true); - draftPane.showDraft(draftId); - setActive(draftPane); - } catch (PropertyVetoException ex) { - } - } - }); - } - - public void endDraft(UUID draftId) { - // inform all open draft panes about - for (JInternalFrame window : desktopPane.getAllFramesInLayer(JLayeredPane.DEFAULT_LAYER)) { - if (window instanceof DraftPane) { - DraftPane draftPane = (DraftPane) window; - draftPane.removeDraft(); - } - } - } - - @Override - public void showTournament(final UUID tournamentId) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - try { - for(Component component :desktopPane.getComponents()) { - if (component instanceof TournamentPane && - ((TournamentPane) component).getTournamentId().equals(tournamentId)) { - setActive((TournamentPane) component); - return; - } - } - TournamentPane tournamentPane = new TournamentPane(); - desktopPane.add(tournamentPane, JLayeredPane.DEFAULT_LAYER); - tournamentPane.setMaximum(true); - tournamentPane.setVisible(true); - tournamentPane.showTournament(tournamentId); - setActive(tournamentPane); - } catch (PropertyVetoException ex) { - } - } - }); - } - - public void showGameEndDialog(final GameEndView gameEndView) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - GameEndDialog gameEndDialog = new GameEndDialog(gameEndView); - desktopPane.add(gameEndDialog, JLayeredPane.MODAL_LAYER); - gameEndDialog.showDialog(); - } - }); - } - - public void showTableWaitingDialog(final UUID roomId, final UUID tableId, final UUID chatId, final boolean owner, final boolean tournament) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - TableWaitingDialog tableWaitingDialog = new TableWaitingDialog(); - desktopPane.add(tableWaitingDialog, JLayeredPane.MODAL_LAYER); - tableWaitingDialog.showDialog(roomId, tableId, chatId, owner, tournament); - } - }); - } - - public boolean connect(Connection connection) { - client = new Client(instance); - boolean result = client.connect(connection, version); - setWindowTitle(); - if (result) { - updateDatabase(connection.isForceDBComparison(), serverState); - } - return result; - } - - private void updateDatabase(boolean forceDBComparison, ServerState serverState) { - long cardDBVersion = CardRepository.instance.getContentVersionFromDB(); - if (forceDBComparison || serverState.getCardsContentVersion() > cardDBVersion) { - List classNames = CardRepository.instance.getClassNames(); - List cards = CardRepository.instance.getMissingCards(classNames); - CardRepository.instance.addCards(cards); - CardRepository.instance.setContentVersion(serverState.getCardsContentVersion()); - logger.info("Updating client cards DB - existing cards: " + classNames.size() + " new cards: " + cards.size() + - " content versions - server: " + serverState.getCardsContentVersion() + " client: " + cardDBVersion); - } - - long expansionDBVersion = ExpansionRepository.instance.getContentVersionFromDB(); - if (forceDBComparison || serverState.getExpansionsContentVersion() > expansionDBVersion) { - List setCodes = ExpansionRepository.instance.getSetCodes(); - List expansions = getMissingExpansionData(setCodes); - for (ExpansionInfo expansion : expansions) { - ExpansionRepository.instance.add(expansion); - } - ExpansionRepository.instance.setContentVersion(serverState.getExpansionsContentVersion()); - logger.info("Updating client expansions DB - existing sets: " + setCodes.size() + " new sets: " + expansions.size()+ - " content versions - server: " + serverState.getExpansionsContentVersion() + " client: " + expansionDBVersion); - } - } - - private List getMissingExpansionData(List codes) { - List result = new ArrayList<>(); - for (ExpansionInfo expansionInfo : ExpansionRepository.instance.getAll()) { - if (!codes.contains(expansionInfo.getCode())) { - result.add(expansionInfo); - } - } - return result; - } - - public boolean autoConnect() { - boolean autoConnectParamValue = Boolean.parseBoolean(prefs.get("autoConnect", "false")); - boolean status = false; - if (autoConnectParamValue) { - status = performConnect(); - } - return status; - } - - private boolean performConnect() { - String userName = prefs.get("userName", ""); - String server = prefs.get("serverAddress", ""); - int port = Integer.parseInt(prefs.get("serverPort", "")); - String proxyServer = prefs.get("proxyAddress", ""); - int proxyPort = Integer.parseInt(prefs.get("proxyPort", "0")); - ProxyType proxyType = ProxyType.valueByText(prefs.get("proxyType", "None")); - String proxyUsername = prefs.get("proxyUsername", ""); - String proxyPassword = prefs.get("proxyPassword", ""); - try { - setCursor(new Cursor(Cursor.WAIT_CURSOR)); - Connection connection = new Connection(); - connection.setUsername(userName); - connection.setHost(server); - connection.setPort(port); - connection.setSSL(true); - connection.setProxyType(proxyType); - connection.setProxyHost(proxyServer); - connection.setProxyPort(proxyPort); - connection.setProxyUsername(proxyUsername); - connection.setProxyPassword(proxyPassword); - - setUserPrefsToConnection(connection); - - logger.debug("connecting (auto): " + proxyType + " " + proxyServer + " " + proxyPort + " " + proxyUsername); - if (connect(connection)) { - return true; - } else { - showMessage("Error Connecting", "Unable to connect to server"); - } - } finally { - setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - } - return false; - } - - public void setUserPrefsToConnection(Connection connection) { - connection.setUserData(PreferencesDialog.getUserData()); - } - - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - @SuppressWarnings("unchecked") - // //GEN-BEGIN:initComponents - private void initComponents() { - - desktopPane = new MageJDesktop(); - mageToolbar = new javax.swing.JToolBar(); - btnSendFeedback = new javax.swing.JButton(); - jSeparator4 = new javax.swing.JToolBar.Separator(); - btnConnect = new javax.swing.JButton(); - jSeparator3 = new javax.swing.JToolBar.Separator(); - btnGames = new javax.swing.JButton(); - jSeparator1 = new javax.swing.JToolBar.Separator(); - btnDeckEditor = new javax.swing.JButton(); - jSeparator2 = new javax.swing.JToolBar.Separator(); - btnCollectionViewer = new javax.swing.JButton(); - jSeparator5 = new javax.swing.JToolBar.Separator(); - btnPreferences = new javax.swing.JButton(); - jSeparator6 = new javax.swing.JToolBar.Separator(); - btnAbout = new javax.swing.JButton(); - jSeparator7 = new javax.swing.JToolBar.Separator(); - btnExit = new javax.swing.JButton(); - jMemUsageLabel = new javax.swing.JLabel(); - jSeparator8 = new javax.swing.JToolBar.Separator(); - lblStatus = new javax.swing.JLabel(); - - setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE); - setMinimumSize(new java.awt.Dimension(1024, 768)); - - desktopPane.setBackground(new java.awt.Color(204, 204, 204)); - - mageToolbar.setFloatable(false); - mageToolbar.setRollover(true); - - btnSendFeedback.setText("Feedback"); - btnSendFeedback.setFocusable(false); - btnSendFeedback.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); - btnSendFeedback.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); - btnSendFeedback.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnSendFeedbackActionPerformed(evt); - } - }); - mageToolbar.add(btnSendFeedback); - mageToolbar.add(jSeparator4); - - btnConnect.setText("Connect"); - btnConnect.setFocusable(false); - btnConnect.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); - btnConnect.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); - btnConnect.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnConnectActionPerformed(evt); - } - }); - mageToolbar.add(btnConnect); - mageToolbar.add(jSeparator3); - - btnGames.setText("Games"); - btnGames.setFocusable(false); - btnGames.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); - btnGames.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); - btnGames.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnGamesActionPerformed(evt); - } - }); - mageToolbar.add(btnGames); - mageToolbar.add(jSeparator1); - - btnDeckEditor.setText("Deck Editor"); - btnDeckEditor.setFocusable(false); - btnDeckEditor.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); - btnDeckEditor.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); - btnDeckEditor.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnDeckEditorActionPerformed(evt); - } - }); - mageToolbar.add(btnDeckEditor); - mageToolbar.add(jSeparator2); - - btnCollectionViewer.setText("Collection Viewer"); - btnCollectionViewer.setFocusable(false); - btnCollectionViewer.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); - btnCollectionViewer.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); - btnCollectionViewer.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnCollectionViewerActionPerformed(evt); - } - }); - mageToolbar.add(btnCollectionViewer); - mageToolbar.add(jSeparator5); - - btnPreferences.setText("Preferences"); - btnPreferences.setFocusable(false); - btnPreferences.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); - btnPreferences.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); - btnPreferences.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnPreferencesActionPerformed(evt); - } - }); - mageToolbar.add(btnPreferences); - mageToolbar.add(jSeparator6); - - btnAbout.setText("About"); - btnAbout.setFocusable(false); - btnAbout.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); - btnAbout.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); - btnAbout.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnAboutActionPerformed(evt); - } - }); - mageToolbar.add(btnAbout); - mageToolbar.add(jSeparator7); - - btnExit.setText("Exit"); - btnExit.setFocusable(false); - btnExit.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); - btnExit.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); - btnExit.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnExitActionPerformed(evt); - } - }); - mageToolbar.add(btnExit); - - jMemUsageLabel.setText("100% Free mem"); - mageToolbar.add(Box.createHorizontalGlue()); - mageToolbar.add(jMemUsageLabel); - mageToolbar.add(jSeparator8); - - lblStatus.setText("Not connected "); - mageToolbar.add(lblStatus); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); - getContentPane().setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(desktopPane) - .addComponent(mageToolbar, javax.swing.GroupLayout.DEFAULT_SIZE, 697, Short.MAX_VALUE) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(mageToolbar, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(0, 0, 0) - .addComponent(desktopPane)) - ); - - pack(); - }// //GEN-END:initComponents - - private void btnDeckEditorActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDeckEditorActionPerformed - showDeckEditor(DeckEditorMode.FREE_BUILDING, null, null, 0); - }//GEN-LAST:event_btnDeckEditorActionPerformed - - private void btnGamesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnGamesActionPerformed - this.showGames(true); - }//GEN-LAST:event_btnGamesActionPerformed - - private void btnExitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnExitActionPerformed - exitApp(); - }//GEN-LAST:event_btnExitActionPerformed - - private void btnConnectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnConnectActionPerformed - if (client != null && client.isConnected()) { - if (JOptionPane.showConfirmDialog(this, "Are you sure you want to disconnect?", "Confirm disconnect", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { - client.disconnect(false); - tablesPane.clearChat(); - setWindowTitle(); - showMessage("Disconnected", "You have disconnected"); - } - } else { - connectDialog.showDialog(); - if (client != null && client.isConnected()) { - showGames(false); - } - } - }//GEN-LAST:event_btnConnectActionPerformed - - public void btnAboutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAboutActionPerformed - JInternalFrame[] windows = desktopPane.getAllFramesInLayer(JLayeredPane.POPUP_LAYER); - for (JInternalFrame window : windows) { - if (window instanceof AboutDialog) { - // don't open the window twice. - return; - } - } - AboutDialog aboutDialog = new AboutDialog(); - desktopPane.add(aboutDialog, JLayeredPane.POPUP_LAYER); - aboutDialog.showDialog(version); - }//GEN-LAST:event_btnAboutActionPerformed - - private void btnCollectionViewerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCollectionViewerActionPerformed - showCollectionViewer(); - }//GEN-LAST:event_btnCollectionViewerActionPerformed - - public void btnPreferencesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnPreferencesActionPerformed - PreferencesDialog.main(new String[]{}); - }//GEN-LAST:event_btnPreferencesActionPerformed - - public void btnSendFeedbackActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSendFeedbackActionPerformed - if (client == null || !client.isConnected()) { - JOptionPane.showMessageDialog(null, "You may send us feedback only when connected to server.", "Information", JOptionPane.INFORMATION_MESSAGE); - return; - } - FeedbackDialog.main(new String[]{}); - }//GEN-LAST:event_btnSendFeedbackActionPerformed - - public void exitApp() { - if (client != null && client.isConnected()) { - if (JOptionPane.showConfirmDialog(this, "You are currently connected. Are you sure you want to disconnect?", "Confirm disconnect", JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) { - return; - } - client.disconnect(false); - } else { - if (JOptionPane.showConfirmDialog(this, "Are you sure you want to exit?", "Confirm exit", JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) { - return; - } - } - CardRepository.instance.closeDB(); - tablesPane.cleanUp(); - Plugins.getInstance().shutdown(); - dispose(); - System.exit(0); - } - - public void enableButtons() { - btnConnect.setEnabled(true); - btnConnect.setText("Disconnect"); - btnGames.setEnabled(true); - btnDeckEditor.setEnabled(true); - } - - public void disableButtons() { - btnConnect.setEnabled(true); - btnConnect.setText("Connect"); - btnGames.setEnabled(false); - btnDeckEditor.setEnabled(true); - } - - public void hideTables() { - this.tablesPane.hideTables(); - } - - public void showGames(final boolean setActive) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - MagePane topPanebefore = getTopMost(tablesPane); - if (!tablesPane.isVisible()) { - tablesPane.setVisible(true); - tablesPane.showTables(); - } - if (setActive) { - setActive(tablesPane); - } else { - // if other panel was already shown, mamke sure it's topmost again - if (topPanebefore != null) { - setActive(topPanebefore); - } - } - } - }); - } - - public void hideGames() { - JInternalFrame[] windows = desktopPane.getAllFramesInLayer(JLayeredPane.DEFAULT_LAYER); - for (JInternalFrame window : windows) { - if (window instanceof GamePane) { - GamePane gamePane = (GamePane) window; - gamePane.removeGame(); - } - if (window instanceof DraftPane) { - DraftPane draftPane = (DraftPane) window; - draftPane.removeDraft(); - } - if (window instanceof TournamentPane) { - TournamentPane tournamentPane = (TournamentPane) window; - tournamentPane.removeTournament(); - } - // close & remove sideboarding or construction pane if open - if (window instanceof DeckEditorPane) { - DeckEditorPane deckEditorPane = (DeckEditorPane) window; - if (deckEditorPane.getDeckEditorMode().equals(DeckEditorMode.LIMITED_BUILDING) - || deckEditorPane.getDeckEditorMode().equals(DeckEditorMode.SIDEBOARDING)) { - deckEditorPane.removeFrame(); - } - } - - } - } - - public void showDeckEditor(final DeckEditorMode mode, final Deck deck, final UUID tableId, final int time) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - String name; - if (mode == DeckEditorMode.SIDEBOARDING || mode == DeckEditorMode.LIMITED_BUILDING) { - name = "Deck Editor - " + tableId.toString(); - } else { - if (deck != null) { - name = "Deck Editor - " + deck.getName(); - } else { - name = "Deck Editor"; - } - // use already open editor - JInternalFrame[] windows = desktopPane.getAllFramesInLayer(JLayeredPane.DEFAULT_LAYER); - for (JInternalFrame window : windows) { - if (window instanceof DeckEditorPane && window.getTitle().equals(name)) { - setActive((MagePane) window); - return; - } - } - } - - try { - DeckEditorPane deckEditorPane = new DeckEditorPane(); - desktopPane.add(deckEditorPane, JLayeredPane.DEFAULT_LAYER); - deckEditorPane.setMaximum(true); - deckEditorPane.setVisible(true); - deckEditorPane.show(mode, deck, name, tableId, time); - setActive(deckEditorPane); - } catch (PropertyVetoException ex) { - logger.fatal(null, ex); - } - } - }); - } - - public void showUserRequestDialog(final UserRequestMessage userRequestMessage) { - final UserRequestDialog userRequestDialog = new UserRequestDialog(); - userRequestDialog.setLocation(100, 100); - desktopPane.add(userRequestDialog, JLayeredPane.MODAL_LAYER); -// ui.addComponent(MageComponents.DESKTOP_PANE, userRequestDialog); - if (SwingUtilities.isEventDispatchThread()) { - userRequestDialog.showDialog(userRequestMessage); - } else { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - userRequestDialog.showDialog(userRequestMessage); - } - }); - } - - } - - public void showErrorDialog(final String title, final String message) { - if (SwingUtilities.isEventDispatchThread()) { - errorDialog.showDialog(title, message); - } else { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - errorDialog.showDialog(title, message); - } - }); - } - - } - - public void showCollectionViewer() { - JInternalFrame[] windows = desktopPane.getAllFramesInLayer(JLayeredPane.DEFAULT_LAYER); - for (JInternalFrame window : windows) { - if (window instanceof CollectionViewerPane) { - setActive((MagePane) window); - return; - } - } - try { - CollectionViewerPane collectionViewerPane = new CollectionViewerPane(); - desktopPane.add(collectionViewerPane, javax.swing.JLayeredPane.DEFAULT_LAYER); - collectionViewerPane.setMaximum(true); - collectionViewerPane.setVisible(true); - setActive(collectionViewerPane); - } catch (PropertyVetoException ex) { - logger.fatal(null, ex); - } - } - - static void renderSplashFrame(Graphics2D g) { - g.setComposite(AlphaComposite.Clear); - g.fillRect(120, 140, 200, 40); - g.setPaintMode(); - g.setColor(Color.white); - g.drawString("Version 0.6.1", 560, 460); - } - - /** - * @param args the command line arguments - */ - public static void main(final String args[]) { - // Workaround for #451 - System.setProperty("java.util.Arrays.useLegacyMergeSort", "true"); - logger.info("Starting MAGE client version " + version); - logger.info("Logging level: " + logger.getEffectiveLevel()); - - startTime = System.currentTimeMillis(); - Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { - @Override - public void uncaughtException(Thread t, Throwable e) { - logger.fatal(null, e); - } - }); - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - for (String arg : args) { - if (arg.startsWith(liteModeArg)) { - liteMode = true; - } - if (arg.startsWith(grayModeArg)) { - grayMode = true; - } - if (arg.startsWith(fullscreenArg)) { - fullscreenMode = true; - } - } - if (!liteMode) { - final SplashScreen splash = SplashScreen.getSplashScreen(); - if (splash != null) { - Graphics2D g = splash.createGraphics(); - if (g != null) { - renderSplashFrame(g); - } - splash.update(); - } - } - instance = new MageFrame(); - instance.setVisible(true); - - } - }); - } - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton btnAbout; - private javax.swing.JButton btnCollectionViewer; - private javax.swing.JButton btnConnect; - private javax.swing.JButton btnDeckEditor; - private javax.swing.JButton btnExit; - private javax.swing.JButton btnGames; - private javax.swing.JButton btnPreferences; - private javax.swing.JButton btnSendFeedback; - private static javax.swing.JDesktopPane desktopPane; - private javax.swing.JLabel jMemUsageLabel; - private javax.swing.JToolBar.Separator jSeparator1; - private javax.swing.JToolBar.Separator jSeparator2; - private javax.swing.JToolBar.Separator jSeparator3; - private javax.swing.JToolBar.Separator jSeparator4; - private javax.swing.JToolBar.Separator jSeparator5; - private javax.swing.JToolBar.Separator jSeparator6; - private javax.swing.JToolBar.Separator jSeparator7; - private javax.swing.JToolBar.Separator jSeparator8; - private javax.swing.JLabel lblStatus; - private javax.swing.JToolBar mageToolbar; - // End of variables declaration//GEN-END:variables - - private static final long serialVersionUID = -9104885239063142218L; - private ImagePanel backgroundPane; - private TablesPane tablesPane; -// private CollectionViewerPane collectionViewerPane; - - public void setStatusText(String status) { - this.lblStatus.setText(status); - } - - public static MageUI getUI() { - return ui; - } - - public static ChatPanel getChat(UUID chatId) { - return chats.get(chatId); - } - - public static void addChat(UUID chatId, ChatPanel chatPanel) { - chats.put(chatId, chatPanel); - } - - public static void removeChat(UUID chatId) { - chats.remove(chatId); - } - - public static void addGame(UUID gameId, GamePanel gamePanel) { - games.put(gameId, gamePanel); - } - - public static GamePanel getGame(UUID gameId) { - return games.get(gameId); - } - - public static void removeGame(UUID gameId) { - games.remove(gameId); - } - - public static DraftPanel getDraft(UUID draftId) { - return drafts.get(draftId); - } - - public static void removeDraft(final UUID draftId) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - DraftPanel draftPanel = drafts.get(draftId); - if (draftPanel != null) { - drafts.remove(draftId); - draftPanel.hideDraft(); - } - } - }); - } - - public static void addDraft(UUID draftId, DraftPanel draftPanel) { - drafts.put(draftId, draftPanel); - } - - @Override - public void connected(final String message) { - if (SwingUtilities.isEventDispatchThread()) { - setStatusText(message); - enableButtons(); - } else { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - setStatusText(message); - enableButtons(); - } - }); - } - } - - @Override - public void disconnected(final boolean errorCall) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - setStatusText("Not connected"); - disableButtons(); - hideGames(); - hideTables(); - if (errorCall && JOptionPane.showConfirmDialog(MageFrame.this, "The connection to server was lost. Reconnect?", "Warning", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { - if (performConnect()) { - enableButtons(); - } - } - } - }); - } - - public void showMessage(final String title, final String message) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - JOptionPane.showMessageDialog(desktopPane, message, title, JOptionPane.INFORMATION_MESSAGE); - } - }); - } - - public void showError(final String title, final String message) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - JOptionPane.showMessageDialog(desktopPane, message, title, JOptionPane.ERROR_MESSAGE); - } - }); - } - - @Override - public void inform(String title, String message, MessageType type) { - if (type == MessageType.ERROR) { - showError(title, message); - } - else { - showMessage(title, message); - } - } - - @Override - public void receiveChatMessage(final UUID chatId, final ChatMessage message) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - ChatPanel panel = MageFrame.getChat(chatId); - if (panel != null) { - // send the message to subchat if exists and it's not a game message - if (!message.getMessageType().equals(ChatMessage.MessageType.GAME) && panel.getConnectedChat() != null) { - panel.getConnectedChat().receiveMessage(message); - } else { - panel.receiveMessage(message); - } - } - } - }); - } - - @Override - public void receiveBroadcastMessage(String message) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. - } - - @Override - public void clientRegistered(ServerState state) { - this.serverState = state; - } - - @Override - public ServerState getServerState() { - return serverState; - } - - @Override - public void joinedTable(UUID roomId, UUID tableId, UUID chatId, boolean owner, boolean tournament) { - showTableWaitingDialog(roomId, tableId, chatId, owner, tournament); - } - - @Override - public void gameStarted(UUID gameId, UUID playerId) { - GameManager.getInstance().setCurrentPlayerUUID(playerId); - showGame(gameId, playerId); - logger.info("Game " + gameId + " started for player " + playerId); - - if (Plugins.getInstance().isCounterPluginLoaded()) { - Plugins.getInstance().addGamesPlayed(); - } - } - - @Override - public void initGame(final UUID gameId, final GameView gameView) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - GamePanel panel = MageFrame.getGame(gameId); - if (panel != null) { - panel.init(gameView); - } - } - }); - } - - @Override - public void gameAsk(final UUID gameId, final GameView gameView, final String question, final Map options) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - GamePanel panel = MageFrame.getGame(gameId); - if (panel != null) { - panel.ask(question, gameView, options); - } - } - }); - } - - @Override - public void gameTarget(final UUID gameId, final GameView gameView, final String question, final CardsView cardView, final Set targets, final boolean required, final Map options) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - GamePanel panel = MageFrame.getGame(gameId); - if (panel != null) { - panel.pickTarget(question, cardView, gameView, targets, required, options); - } - } - }); - } - - @Override - public void gameChooseAbility(final UUID gameId, final AbilityPickerView abilities) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - GamePanel panel = MageFrame.getGame(gameId); - if (panel != null) { - panel.pickAbility(abilities); - } - } - }); - } - - @Override - public void gameChoosePile(final UUID gameId, final String message, final CardsView pile1, final CardsView pile2) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - GamePanel panel = MageFrame.getGame(gameId); - if (panel != null) { - panel.pickPile(message, pile1, pile2); - } - } - }); - } - - @Override - public void gameChooseChoice(final UUID gameId, final Choice choice) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - GamePanel panel = MageFrame.getGame(gameId); - if (panel != null) { - panel.getChoice(choice); - } - } - }); - } - - @Override - public void gamePlayMana(final UUID gameId, final GameView gameView, final String message, final Map options) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - GamePanel panel = MageFrame.getGame(gameId); - if (panel != null) { - panel.playMana(message, gameView, options); - } - } - }); - } - - @Override - public void gamePlayXMana(final UUID gameId, final GameView gameView, final String message) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - GamePanel panel = MageFrame.getGame(gameId); - if (panel != null) { - panel.playXMana(message, gameView); - } - } - }); - } - - @Override - public void gameSelectAmount(final UUID gameId, final String message, final int min, final int max) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - GamePanel panel = MageFrame.getGame(gameId); - if (panel != null) { - panel.getAmount(min, max, message); - } - } - }); - } - - @Override - public void gameSelect(final UUID gameId, final GameView gameView, final String message, final Map options) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - GamePanel panel = MageFrame.getGame(gameId); - if (panel != null) { - panel.select(message, gameView, options); - } - } - }); - } - - @Override - public void gameEndInfo(UUID gameId, GameEndView view) { - showGameEndDialog(view); - } - - @Override - public void userRequestDialog(UUID gameId, UserRequestMessage userRequestMessage) { - showUserRequestDialog(userRequestMessage); - } - - @Override - public void gameUpdate(final UUID gameId, final GameView gameView) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - GamePanel panel = MageFrame.getGame(gameId); - if (panel != null) { - panel.updateGame(gameView); - } - } - }); - } - - @Override - public void gameInform(final UUID gameId, final GameClientMessage message) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - GamePanel panel = MageFrame.getGame(gameId); - if (panel != null) { - panel.inform(message.getMessage(), message.getGameView()); - } - } - }); - } - - @Override - public void gameInformPersonal(final UUID gameId, final GameClientMessage message) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - GamePanel panel = MageFrame.getGame(gameId); - if (panel != null) { - JOptionPane.showMessageDialog(panel, message.getMessage(), "Game message", JOptionPane.INFORMATION_MESSAGE); - } - } - }); - } - - @Override - public void gameOver(final UUID gameId, final String message) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - GamePanel panel = MageFrame.getGame(gameId); - if (panel != null) { - panel.endMessage(message); - } - } - }); - } - - @Override - public void gameError(UUID gameId, String message) { - this.showErrorDialog("Game Error", message); - } - - @Override - public void sideboard(UUID tableId, DeckView deckView, int time, boolean limited) { - Deck deck = DeckUtil.construct(deckView); - if (limited) { - construct(deck, tableId, time); - } else { - sideboard(deck, tableId, time); - } - } - - @Override - public void construct(UUID tableId, DeckView deckView, int time) { - Deck deck = DeckUtil.construct(deckView); - construct(deck, tableId, time); - } - - - protected void sideboard(Deck deck, UUID tableId, int time) { - showDeckEditor(DeckEditorMode.SIDEBOARDING, deck, tableId, time); - } - - protected void construct(Deck deck, UUID tableId, int time) { - showDeckEditor(DeckEditorMode.LIMITED_BUILDING, deck, tableId, time); - } - - @Override - public void startDraft(UUID draftId, UUID playerId) { - showDraft(draftId); - logger.info("Draft " + draftId + " started for player " + playerId); - } - - @Override - public void draftInit(final UUID draftId, final DraftPickView draftPickView) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - DraftPanel panel = MageFrame.getDraft(draftId); - if (panel != null) { - panel.loadBooster(draftPickView); - } - } - }); - } - - @Override - public void draftUpdate(final UUID draftId, final DraftView draftView) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - DraftPanel panel = MageFrame.getDraft(draftId); - if (panel != null) { - panel.updateDraft(draftView); - } - } - }); - } - - @Override - public void draftPick(final UUID draftId, final DraftPickView draftPickView) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - DraftPanel panel = MageFrame.getDraft(draftId); - if (panel != null) { - try { - panel.loadBooster(draftPickView); - } catch (Exception ex) { - logger.error("arrrgh", ex); - } - } - } - }); - } - - @Override - public void draftOver(UUID draftId) { - removeDraft(draftId); - } - - @Override - public void tournamentStarted(UUID tournamentId) { - showTournament(tournamentId); - AudioManager.playTournamentStarted(); - logger.info("Tournament " + tournamentId + " started"); - } - -} - -class MagePaneMenuItem extends JCheckBoxMenuItem { - - private final MagePane frame; - - public MagePaneMenuItem(MagePane frame) { - super(frame.getTitle()); - this.frame = frame; - } - - public MagePane getFrame() { - return frame; - } -} +/* +* 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.client; + +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Rectangle; +import java.awt.SplashScreen; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.image.BufferedImage; +import java.beans.PropertyVetoException; +import java.io.IOException; +import java.io.InputStream; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.prefs.Preferences; +import javax.imageio.ImageIO; +import javax.swing.AbstractButton; +import javax.swing.Box; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JComponent; +import javax.swing.JDesktopPane; +import javax.swing.JEditorPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.JLabel; +import javax.swing.JLayeredPane; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JToggleButton; +import javax.swing.JToolBar.Separator; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import mage.cards.decks.Deck; +import mage.cards.repository.CardCriteria; +import mage.cards.repository.CardInfo; +import mage.cards.repository.CardRepository; +import mage.cards.repository.ExpansionInfo; +import mage.cards.repository.ExpansionRepository; +import mage.choices.Choice; +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; +import mage.client.components.ext.dlg.DialogManager; +import mage.client.components.tray.MageTray; +import mage.client.constants.Constants.DeckEditorMode; +import mage.client.deckeditor.DeckEditorPane; +import mage.client.deckeditor.collection.viewer.CollectionViewerPane; +import mage.client.dialog.AboutDialog; +import mage.client.dialog.ConnectDialog; +import mage.client.dialog.ErrorDialog; +import mage.client.dialog.FeedbackDialog; +import mage.client.dialog.GameEndDialog; +import mage.client.dialog.PreferencesDialog; +import mage.client.dialog.TableWaitingDialog; +import mage.client.dialog.UserRequestDialog; +import mage.client.draft.DraftPane; +import mage.client.draft.DraftPanel; +import mage.client.game.GamePane; +import mage.client.game.GamePanel; +import mage.client.plugins.impl.Plugins; +import mage.client.table.TablesPane; +import mage.client.tournament.TournamentPane; +import mage.client.util.DeckUtil; +import mage.client.util.EDTExceptionHandler; +import mage.client.util.GameManager; +import mage.client.util.SettingsManager; +import mage.client.util.SystemUtil; +import mage.client.util.audio.AudioManager; +import mage.client.util.audio.MusicPlayer; +import mage.client.util.gui.ArrowBuilder; +import mage.client.util.stats.UpdateMemUsageTask; +import mage.components.ImagePanel; +import mage.interfaces.ServerState; +import mage.remote.Connection; +import mage.remote.Connection.ProxyType; +import mage.utils.MageVersion; +import mage.view.AbilityPickerView; +import mage.view.CardsView; +import mage.view.ChatMessage; +import mage.view.DeckView; +import mage.view.DraftPickView; +import mage.view.DraftView; +import mage.view.GameClientMessage; +import mage.view.GameEndView; +import mage.view.GameView; +import mage.view.UserRequestMessage; +import net.java.truevfs.access.TArchiveDetector; +import net.java.truevfs.access.TConfig; +import net.java.truevfs.kernel.spec.FsAccessOption; +import org.apache.log4j.Logger; +import org.mage.card.arcane.ManaSymbols; +import org.mage.network.Client; +import org.mage.network.interfaces.MageClient; +import org.mage.network.messages.MessageType; +import org.mage.plugins.card.constants.Constants; +import org.mage.plugins.card.images.DownloadPictures; +import org.mage.plugins.card.utils.impl.ImageManagerImpl; + +/** + * @author BetaSteward_at_googlemail.com + */ +public class MageFrame extends javax.swing.JFrame implements MageClient { + + private static final String TITLE_NAME = "XMage"; + + private static final Logger logger = Logger.getLogger(MageFrame.class); + private static final String liteModeArg = "-lite"; + private static final String grayModeArg = "-gray"; + private static final String fullscreenArg = "-fullscreen"; + + private static MageFrame instance; + + private static Client client; + private ServerState serverState; + private ConnectDialog connectDialog; + private final ErrorDialog errorDialog; + private static final Preferences prefs = Preferences.userNodeForPackage(MageFrame.class); + private JLabel title; + private Rectangle titleRectangle; + private static final MageVersion version = MageVersion.getCurrent(); + private UUID clientId; + private static MagePane activeFrame; + private static boolean liteMode = false; + //TODO: make gray theme, implement theme selector in preferences dialog + private static boolean grayMode = false; + private static boolean fullscreenMode = false; + + private static final Map chats = new HashMap<>(); + private static final Map games = new HashMap<>(); + private static final Map drafts = new HashMap<>(); + private static final MageUI ui = new MageUI(); + + private static UpdateMemUsageTask updateMemUsageTask; + + private static long startTime; + + public static Client getClient() { + return client; + } + + public static JDesktopPane getDesktop() { + return desktopPane; + } + + public static Preferences getPreferences() { + return prefs; + } + + public static boolean isLite() { + return liteMode; + } + + public static boolean isGray() { + return grayMode; + } + + public MageVersion getVersion() { + return version; + } + + public static MageFrame getInstance() { + return instance; + } + + /** + * Creates new form MageFrame + */ + public MageFrame() { + setWindowTitle(); + + clientId = UUID.randomUUID(); + EDTExceptionHandler.registerExceptionHandler(); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + exitApp(); + } + }); + + TConfig config = TConfig.current(); + config.setArchiveDetector(new TArchiveDetector("zip")); + config.setAccessPreference(FsAccessOption.STORE, true); + + try { + UIManager.put("desktop", new Color(0, 0, 0, 0)); + UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"); + } catch (Exception ex) { + logger.fatal(null, ex); + } + + ManaSymbols.loadImages(); + Plugins.getInstance().loadPlugins(); + + initComponents(); + + desktopPane.setDesktopManager(new MageDesktopManager()); + + setSize(1024, 768); + SettingsManager.getInstance().setScreenWidthAndHeight(1024, 768); + DialogManager.updateParams(768, 1024, false); + this.setExtendedState(JFrame.MAXIMIZED_BOTH); + + connectDialog = new ConnectDialog(); + desktopPane.add(connectDialog, JLayeredPane.POPUP_LAYER); + errorDialog = new ErrorDialog(); + errorDialog.setLocation(100, 100); + desktopPane.add(errorDialog, JLayeredPane.POPUP_LAYER); + ui.addComponent(MageComponents.DESKTOP_PANE, desktopPane); + + updateMemUsageTask = new UpdateMemUsageTask(jMemUsageLabel); + + try { + tablesPane = new TablesPane(); + desktopPane.add(tablesPane, javax.swing.JLayeredPane.DEFAULT_LAYER); + tablesPane.setMaximum(true); + } catch (PropertyVetoException ex) { + logger.fatal(null, ex); + } + + addTooltipContainer(); + setBackground(); + addMageLabel(); + setAppIcon(); + MageTray.getInstance().install(); + + desktopPane.add(ArrowBuilder.getBuilder().getArrowsManagerPanel(), JLayeredPane.DRAG_LAYER); + + desktopPane.addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(ComponentEvent e) { + int width = ((JComponent) e.getSource()).getWidth(); + int height = ((JComponent) e.getSource()).getHeight(); + SettingsManager.getInstance().setScreenWidthAndHeight(width, height); + if (!liteMode && !grayMode) { + backgroundPane.setSize(width, height); + } + + ArrowBuilder.getBuilder().setSize(width, height); + + if (title != null) { + title.setBounds((int) (width - titleRectangle.getWidth()) / 2, (int) (height - titleRectangle.getHeight()) / 2, titleRectangle.width, titleRectangle.height); + } + } + }); + + mageToolbar.add(new javax.swing.JToolBar.Separator()); + mageToolbar.add(createWindowsButton()); + + //TODO: move to plugin impl + if (Plugins.getInstance().isCardPluginLoaded()) { + Separator separator = new javax.swing.JToolBar.Separator(); + mageToolbar.add(separator); + + JButton btnDownloadSymbols = new JButton("Symbols"); + btnDownloadSymbols.setFocusable(false); + btnDownloadSymbols.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + btnDownloadSymbols.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + btnDownloadSymbols.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnSymbolsActionPerformed(evt); + } + }); + mageToolbar.add(btnDownloadSymbols); + + separator = new javax.swing.JToolBar.Separator(); + mageToolbar.add(separator); + + JButton btnDownload = new JButton("Images"); + btnDownload.setFocusable(false); + btnDownload.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + btnDownload.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + btnDownload.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnImagesActionPerformed(evt); + } + }); + mageToolbar.add(btnDownload); + } + + if (Plugins.getInstance().isCounterPluginLoaded()) { + int i = Plugins.getInstance().getGamesPlayed(); + JLabel label = new JLabel(" Games played: " + String.valueOf(i)); + desktopPane.add(label, JLayeredPane.DEFAULT_LAYER + 1); + label.setVisible(true); + label.setForeground(Color.white); + label.setBounds(0, 0, 180, 30); + } + + ui.addButton(MageComponents.TABLES_MENU_BUTTON, btnGames); + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + disableButtons(); + if (PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_CHECK, "false").equals("true")) { + checkForNewImages(); + } + updateMemUsageTask.execute(); + logger.info("Client start up time: " + ((System.currentTimeMillis() - startTime) / 1000 + " seconds")); + if (autoConnect()) { + enableButtons(); + } else { + connectDialog.showDialog(); + if (client != null && client.isConnected()) { + showGames(false); + } + } + setWindowTitle(); + } + }); + + if (SystemUtil.isMacOSX()) { + SystemUtil.enableMacOSFullScreenMode(this); + if (fullscreenMode) { + SystemUtil.toggleMacOSFullScreenMode(this); + } + } + } + + private void setWindowTitle() { + setTitle(TITLE_NAME + " Client: " + + version == null ? "" : version.toString() + " Server: " + + ((client != null && client.isConnected()) ? serverState.getVersion().toString():"")); + } + + private void addTooltipContainer() { + final JEditorPane cardInfoPane = (JEditorPane) Plugins.getInstance().getCardInfoPane(); + if (cardInfoPane == null) { + return; + } + cardInfoPane.setSize(Constants.TOOLTIP_WIDTH_MIN, Constants.TOOLTIP_HEIGHT_MIN); + 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, + Constants.TOOLTIP_WIDTH_MIN + Constants.TOOLTIP_BORDER_WIDTH, + Constants.TOOLTIP_HEIGHT_MIN + Constants.TOOLTIP_BORDER_WIDTH); + + desktopPane.add(popupContainer, JLayeredPane.POPUP_LAYER); + + ui.addComponent(MageComponents.CARD_INFO_PANE, cardInfoPane); + ui.addComponent(MageComponents.POPUP_CONTAINER, popupContainer); + + // preview panel normal + JPanel cardPreviewContainer = new JPanel(); + cardPreviewContainer.setOpaque(false); + cardPreviewContainer.setLayout(null); + BigCard bigCard = new BigCard(); + bigCard.setSize(320, 500); + bigCard.setLocation(40, 40); + bigCard.setBackground(new Color(0, 0, 0, 0)); + + cardPreviewContainer.add(bigCard); + cardPreviewContainer.setVisible(false); + cardPreviewContainer.setBounds(0, 0, 320 + 80, 500 + 30); + + ui.addComponent(MageComponents.CARD_PREVIEW_PANE, bigCard); + ui.addComponent(MageComponents.CARD_PREVIEW_CONTAINER, cardPreviewContainer); + + desktopPane.add(cardPreviewContainer, JLayeredPane.POPUP_LAYER); + + // preview panel rotated + JPanel cardPreviewContainerRotated = new JPanel(); + cardPreviewContainerRotated.setOpaque(false); + cardPreviewContainerRotated.setLayout(null); + bigCard = new BigCard(true); + bigCard.setSize(500, 350); + bigCard.setLocation(40, 40); + bigCard.setBackground(new Color(0, 0, 0, 0)); + cardPreviewContainerRotated.add(bigCard); + cardPreviewContainerRotated.setVisible(false); + cardPreviewContainerRotated.setBounds(0, 0, 500 + 80, 420 + 30); + + ui.addComponent(MageComponents.CARD_PREVIEW_PANE_ROTATED, bigCard); + ui.addComponent(MageComponents.CARD_PREVIEW_CONTAINER_ROTATED, cardPreviewContainerRotated); + + desktopPane.add(cardPreviewContainerRotated, JLayeredPane.POPUP_LAYER); + + } + + private void setBackground() { + if (liteMode || grayMode) { + return; + } + String filename = "/background.jpg"; + try { + if (Plugins.getInstance().isThemePluginLoaded()) { + backgroundPane = (ImagePanel) Plugins.getInstance().updateTablePanel(new HashMap()); + } 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) { + logger.fatal("Error while setting background.", e); + } + } + + private void addMageLabel() { + if (liteMode || grayMode) { + return; + } + String filename = "/label-xmage.png"; + try { + InputStream is = this.getClass().getResourceAsStream(filename); + + float ratio = 1179.0f / 678.0f; + titleRectangle = new Rectangle(540, (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) { + logger.fatal("Error while adding mage label.", e); + } + } + + private void setAppIcon() { + Image image = ImageManagerImpl.getInstance().getAppImage(); + setIconImage(image); + } + + private AbstractButton createWindowsButton() { + final JToggleButton windowButton = new JToggleButton("Windows"); + windowButton.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + if (e.getStateChange() == ItemEvent.SELECTED) { + createAndShowMenu((JComponent) e.getSource(), windowButton); + } + } + }); + windowButton.setFocusable(false); + windowButton.setHorizontalTextPosition(SwingConstants.LEADING); + return windowButton; + } + + private void createAndShowMenu(final JComponent component, final AbstractButton windowButton) { + JPopupMenu menu = new JPopupMenu(); + JInternalFrame[] windows = desktopPane.getAllFramesInLayer(javax.swing.JLayeredPane.DEFAULT_LAYER); + MagePaneMenuItem menuItem; + + for (int i = 0; i < windows.length; i++) { + if (windows[i] instanceof MagePane) { + MagePane window = (MagePane) windows[i]; + if (window.isVisible()) { + menuItem = new MagePaneMenuItem(window); + menuItem.setState(i == 0); + menuItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent ae) { + MagePane frame = ((MagePaneMenuItem) ae.getSource()).getFrame(); + setActive(frame); + } + }); + menuItem.setIcon(window.getFrameIcon()); + menu.add(menuItem); + } + } + } + + menu.addPopupMenuListener(new PopupMenuListener() { + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + } + + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + windowButton.setSelected(false); + } + + @Override + public void popupMenuCanceled(PopupMenuEvent e) { + windowButton.setSelected(false); + } + }); + + menu.show(component, 0, component.getHeight()); + } + + private void checkForNewImages() { + long beforeCall = System.currentTimeMillis(); + List cards = CardRepository.instance.findCards(new CardCriteria()); + logger.info("Card pool load time: " + ((System.currentTimeMillis() - beforeCall) / 1000 + " seconds")); + + beforeCall = System.currentTimeMillis(); + if (DownloadPictures.checkForNewCards(cards)) { + logger.info("Card images checking time: " + ((System.currentTimeMillis() - beforeCall) / 1000 + " seconds")); + if (JOptionPane.showConfirmDialog(this, "New cards are available. Do you want to download the images?", "New images available", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { + DownloadPictures.startDownload(null, cards); + } + } + } + + public void btnImagesActionPerformed(java.awt.event.ActionEvent evt) { + List cards = CardRepository.instance.findCards(new CardCriteria()); + + DownloadPictures.startDownload(null, cards); + } + + public void btnSymbolsActionPerformed(java.awt.event.ActionEvent evt) { + if (JOptionPane.showConfirmDialog(this, "Do you want to download game symbols and additional image files?", "Download additional resources", JOptionPane.YES_NO_OPTION) == JOptionPane.OK_OPTION) { + Plugins.getInstance().downloadSymbols(); + } + } + + public static void setActive(MagePane frame) { + if (frame == null) { + activeFrame = null; + return; + } + logger.debug("Setting " + frame.getTitle() + " active"); + if (activeFrame != null) { + activeFrame.deactivated(); + } + activeFrame = frame; + activeFrame.setVisible(true); + activeFrame.toFront(); + try { + activeFrame.setSelected(true); + } catch (PropertyVetoException ex) { + logger.error("Error setting " + frame.getTitle() + " active"); + } + activeFrame.activated(); + ArrowBuilder.getBuilder().hideAllPanels(); + if (frame instanceof GamePane) { + ArrowBuilder.getBuilder().showPanel(((GamePane) frame).getGameId()); + MusicPlayer.playBGM(); + } else { + MusicPlayer.stopBGM(); + } + } + + public static void deactivate(MagePane frame) { + frame.setVisible(false); + setActive(getTopMost(frame)); + if (activeFrame != frame) { + frame.deactivated(); + } + + } + + private static MagePane getTopMost(MagePane exclude) { + MagePane topmost = null; + int best = Integer.MAX_VALUE; + for (JInternalFrame frame : desktopPane.getAllFramesInLayer(JLayeredPane.DEFAULT_LAYER)) { + if (frame.isVisible()) { + int z = desktopPane.getComponentZOrder(frame); + if (z < best) { + if (frame instanceof MagePane) { + best = z; + if (!frame.equals(exclude)) { + topmost = (MagePane) frame; + } + } + } + } + } + return topmost; + } + + /** + * Shows a game for a player of the game + * + * @param gameId + * @param playerId + */ + public void showGame(final UUID gameId, final UUID playerId) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + try { + GamePane gamePane = new GamePane(); + desktopPane.add(gamePane, JLayeredPane.DEFAULT_LAYER); + gamePane.setMaximum(true); + gamePane.setVisible(true); + gamePane.showGame(gameId, playerId); + setActive(gamePane); + } catch (PropertyVetoException ex) { + } + } + }); + } + + @Override + public void watchGame(final UUID gameId, final UUID chatId, final GameView game) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + try { + for(Component component :desktopPane.getComponents()) { + if (component instanceof GamePane + && ((GamePane) component).getGameId().equals(gameId)) { + setActive((GamePane) component); + return; + } + } + GamePane gamePane = new GamePane(); + desktopPane.add(gamePane, JLayeredPane.DEFAULT_LAYER); + gamePane.setMaximum(true); + gamePane.setVisible(true); + gamePane.watchGame(gameId, chatId, game); + setActive(gamePane); + } catch (PropertyVetoException ex) { + } + } + }); + } + + public void replayGame(final UUID gameId) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + try { + GamePane gamePane = new GamePane(); + desktopPane.add(gamePane, JLayeredPane.DEFAULT_LAYER); + gamePane.setMaximum(true); + gamePane.setVisible(true); + gamePane.replayGame(gameId); + setActive(gamePane); + } catch (PropertyVetoException ex) { + } + } + }); + } + + public void showDraft(final UUID draftId) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + try { + DraftPane draftPane = new DraftPane(); + desktopPane.add(draftPane, JLayeredPane.DEFAULT_LAYER); + draftPane.setMaximum(true); + draftPane.setVisible(true); + draftPane.showDraft(draftId); + setActive(draftPane); + } catch (PropertyVetoException ex) { + } + } + }); + } + + public void endDraft(UUID draftId) { + // inform all open draft panes about + for (JInternalFrame window : desktopPane.getAllFramesInLayer(JLayeredPane.DEFAULT_LAYER)) { + if (window instanceof DraftPane) { + DraftPane draftPane = (DraftPane) window; + draftPane.removeDraft(); + } + } + } + + @Override + public void showTournament(final UUID tournamentId) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + try { + for(Component component :desktopPane.getComponents()) { + if (component instanceof TournamentPane && + ((TournamentPane) component).getTournamentId().equals(tournamentId)) { + setActive((TournamentPane) component); + return; + } + } + TournamentPane tournamentPane = new TournamentPane(); + desktopPane.add(tournamentPane, JLayeredPane.DEFAULT_LAYER); + tournamentPane.setMaximum(true); + tournamentPane.setVisible(true); + tournamentPane.showTournament(tournamentId); + setActive(tournamentPane); + } catch (PropertyVetoException ex) { + } + } + }); + } + + public void showGameEndDialog(final GameEndView gameEndView) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + GameEndDialog gameEndDialog = new GameEndDialog(gameEndView); + desktopPane.add(gameEndDialog, JLayeredPane.MODAL_LAYER); + gameEndDialog.showDialog(); + } + }); + } + + public void showTableWaitingDialog(final UUID roomId, final UUID tableId, final UUID chatId, final boolean owner, final boolean tournament) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + TableWaitingDialog tableWaitingDialog = new TableWaitingDialog(); + desktopPane.add(tableWaitingDialog, JLayeredPane.MODAL_LAYER); + tableWaitingDialog.showDialog(roomId, tableId, chatId, owner, tournament); + } + }); + } + + public boolean connect(Connection connection) { + client = new Client(instance); + boolean result = client.connect(connection, version); + setWindowTitle(); + if (result) { + updateDatabase(connection.isForceDBComparison(), serverState); + } + return result; + } + + private void updateDatabase(boolean forceDBComparison, ServerState serverState) { + long cardDBVersion = CardRepository.instance.getContentVersionFromDB(); + if (forceDBComparison || serverState.getCardsContentVersion() > cardDBVersion) { + List classNames = CardRepository.instance.getClassNames(); + List cards = CardRepository.instance.getMissingCards(classNames); + CardRepository.instance.addCards(cards); + CardRepository.instance.setContentVersion(serverState.getCardsContentVersion()); + logger.info("Updating client cards DB - existing cards: " + classNames.size() + " new cards: " + cards.size() + + " content versions - server: " + serverState.getCardsContentVersion() + " client: " + cardDBVersion); + } + + long expansionDBVersion = ExpansionRepository.instance.getContentVersionFromDB(); + if (forceDBComparison || serverState.getExpansionsContentVersion() > expansionDBVersion) { + List setCodes = ExpansionRepository.instance.getSetCodes(); + List expansions = getMissingExpansionData(setCodes); + for (ExpansionInfo expansion : expansions) { + ExpansionRepository.instance.add(expansion); + } + ExpansionRepository.instance.setContentVersion(serverState.getExpansionsContentVersion()); + logger.info("Updating client expansions DB - existing sets: " + setCodes.size() + " new sets: " + expansions.size()+ + " content versions - server: " + serverState.getExpansionsContentVersion() + " client: " + expansionDBVersion); + } + } + + private List getMissingExpansionData(List codes) { + List result = new ArrayList<>(); + for (ExpansionInfo expansionInfo : ExpansionRepository.instance.getAll()) { + if (!codes.contains(expansionInfo.getCode())) { + result.add(expansionInfo); + } + } + return result; + } + + public boolean autoConnect() { + boolean autoConnectParamValue = Boolean.parseBoolean(prefs.get("autoConnect", "false")); + boolean status = false; + if (autoConnectParamValue) { + status = performConnect(); + } + return status; + } + + private boolean performConnect() { + String userName = prefs.get("userName", ""); + String server = prefs.get("serverAddress", ""); + int port = Integer.parseInt(prefs.get("serverPort", "")); + String proxyServer = prefs.get("proxyAddress", ""); + int proxyPort = Integer.parseInt(prefs.get("proxyPort", "0")); + ProxyType proxyType = ProxyType.valueByText(prefs.get("proxyType", "None")); + String proxyUsername = prefs.get("proxyUsername", ""); + String proxyPassword = prefs.get("proxyPassword", ""); + try { + setCursor(new Cursor(Cursor.WAIT_CURSOR)); + Connection connection = new Connection(); + connection.setUsername(userName); + connection.setHost(server); + connection.setPort(port); + connection.setSSL(true); + connection.setProxyType(proxyType); + connection.setProxyHost(proxyServer); + connection.setProxyPort(proxyPort); + connection.setProxyUsername(proxyUsername); + connection.setProxyPassword(proxyPassword); + + setUserPrefsToConnection(connection); + + logger.debug("connecting (auto): " + proxyType + " " + proxyServer + " " + proxyPort + " " + proxyUsername); + if (connect(connection)) { + return true; + } else { + showMessage("Error Connecting", "Unable to connect to server"); + } + } finally { + setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + return false; + } + + public void setUserPrefsToConnection(Connection connection) { + connection.setUserData(PreferencesDialog.getUserData()); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + desktopPane = new MageJDesktop(); + mageToolbar = new javax.swing.JToolBar(); + btnSendFeedback = new javax.swing.JButton(); + jSeparator4 = new javax.swing.JToolBar.Separator(); + btnConnect = new javax.swing.JButton(); + jSeparator3 = new javax.swing.JToolBar.Separator(); + btnGames = new javax.swing.JButton(); + jSeparator1 = new javax.swing.JToolBar.Separator(); + btnDeckEditor = new javax.swing.JButton(); + jSeparator2 = new javax.swing.JToolBar.Separator(); + btnCollectionViewer = new javax.swing.JButton(); + jSeparator5 = new javax.swing.JToolBar.Separator(); + btnPreferences = new javax.swing.JButton(); + jSeparator6 = new javax.swing.JToolBar.Separator(); + btnAbout = new javax.swing.JButton(); + jSeparator7 = new javax.swing.JToolBar.Separator(); + btnExit = new javax.swing.JButton(); + jMemUsageLabel = new javax.swing.JLabel(); + jSeparator8 = new javax.swing.JToolBar.Separator(); + lblStatus = new javax.swing.JLabel(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE); + setMinimumSize(new java.awt.Dimension(1024, 768)); + + desktopPane.setBackground(new java.awt.Color(204, 204, 204)); + + mageToolbar.setFloatable(false); + mageToolbar.setRollover(true); + + btnSendFeedback.setText("Feedback"); + btnSendFeedback.setFocusable(false); + btnSendFeedback.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + btnSendFeedback.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + btnSendFeedback.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnSendFeedbackActionPerformed(evt); + } + }); + mageToolbar.add(btnSendFeedback); + mageToolbar.add(jSeparator4); + + btnConnect.setText("Connect"); + btnConnect.setFocusable(false); + btnConnect.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + btnConnect.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + btnConnect.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnConnectActionPerformed(evt); + } + }); + mageToolbar.add(btnConnect); + mageToolbar.add(jSeparator3); + + btnGames.setText("Games"); + btnGames.setFocusable(false); + btnGames.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + btnGames.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + btnGames.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnGamesActionPerformed(evt); + } + }); + mageToolbar.add(btnGames); + mageToolbar.add(jSeparator1); + + btnDeckEditor.setText("Deck Editor"); + btnDeckEditor.setFocusable(false); + btnDeckEditor.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + btnDeckEditor.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + btnDeckEditor.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnDeckEditorActionPerformed(evt); + } + }); + mageToolbar.add(btnDeckEditor); + mageToolbar.add(jSeparator2); + + btnCollectionViewer.setText("Collection Viewer"); + btnCollectionViewer.setFocusable(false); + btnCollectionViewer.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + btnCollectionViewer.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + btnCollectionViewer.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnCollectionViewerActionPerformed(evt); + } + }); + mageToolbar.add(btnCollectionViewer); + mageToolbar.add(jSeparator5); + + btnPreferences.setText("Preferences"); + btnPreferences.setFocusable(false); + btnPreferences.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + btnPreferences.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + btnPreferences.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnPreferencesActionPerformed(evt); + } + }); + mageToolbar.add(btnPreferences); + mageToolbar.add(jSeparator6); + + btnAbout.setText("About"); + btnAbout.setFocusable(false); + btnAbout.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + btnAbout.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + btnAbout.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnAboutActionPerformed(evt); + } + }); + mageToolbar.add(btnAbout); + mageToolbar.add(jSeparator7); + + btnExit.setText("Exit"); + btnExit.setFocusable(false); + btnExit.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + btnExit.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + btnExit.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnExitActionPerformed(evt); + } + }); + mageToolbar.add(btnExit); + + jMemUsageLabel.setText("100% Free mem"); + mageToolbar.add(Box.createHorizontalGlue()); + mageToolbar.add(jMemUsageLabel); + mageToolbar.add(jSeparator8); + + lblStatus.setText("Not connected "); + mageToolbar.add(lblStatus); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(desktopPane) + .addComponent(mageToolbar, javax.swing.GroupLayout.DEFAULT_SIZE, 697, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(mageToolbar, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(desktopPane)) + ); + + pack(); + }// //GEN-END:initComponents + + private void btnDeckEditorActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDeckEditorActionPerformed + showDeckEditor(DeckEditorMode.FREE_BUILDING, null, null, 0); + }//GEN-LAST:event_btnDeckEditorActionPerformed + + private void btnGamesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnGamesActionPerformed + this.showGames(true); + }//GEN-LAST:event_btnGamesActionPerformed + + private void btnExitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnExitActionPerformed + exitApp(); + }//GEN-LAST:event_btnExitActionPerformed + + private void btnConnectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnConnectActionPerformed + if (client != null && client.isConnected()) { + if (JOptionPane.showConfirmDialog(this, "Are you sure you want to disconnect?", "Confirm disconnect", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { + client.disconnect(false); + tablesPane.clearChat(); + setWindowTitle(); + showMessage("Disconnected", "You have disconnected"); + } + } else { + connectDialog.showDialog(); + if (client != null && client.isConnected()) { + showGames(false); + } + } + setWindowTitle(); + }//GEN-LAST:event_btnConnectActionPerformed + + public void btnAboutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAboutActionPerformed + JInternalFrame[] windows = desktopPane.getAllFramesInLayer(JLayeredPane.POPUP_LAYER); + for (JInternalFrame window : windows) { + if (window instanceof AboutDialog) { + // don't open the window twice. + return; + } + } + AboutDialog aboutDialog = new AboutDialog(); + desktopPane.add(aboutDialog, JLayeredPane.POPUP_LAYER); + aboutDialog.showDialog(version); + }//GEN-LAST:event_btnAboutActionPerformed + + private void btnCollectionViewerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCollectionViewerActionPerformed + showCollectionViewer(); + }//GEN-LAST:event_btnCollectionViewerActionPerformed + + public void btnPreferencesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnPreferencesActionPerformed + PreferencesDialog.main(new String[]{}); + }//GEN-LAST:event_btnPreferencesActionPerformed + + public void btnSendFeedbackActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSendFeedbackActionPerformed + if (client == null || !client.isConnected()) { + JOptionPane.showMessageDialog(null, "You may send us feedback only when connected to server.", "Information", JOptionPane.INFORMATION_MESSAGE); + return; + } + FeedbackDialog.main(new String[]{}); + }//GEN-LAST:event_btnSendFeedbackActionPerformed + + public void exitApp() { + if (client != null && client.isConnected()) { + if (JOptionPane.showConfirmDialog(this, "You are currently connected. Are you sure you want to disconnect?", "Confirm disconnect", JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) { + return; + } + client.disconnect(false); + } else { + if (JOptionPane.showConfirmDialog(this, "Are you sure you want to exit?", "Confirm exit", JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) { + return; + } + } + CardRepository.instance.closeDB(); + tablesPane.cleanUp(); + Plugins.getInstance().shutdown(); + dispose(); + System.exit(0); + } + + public void enableButtons() { + btnConnect.setEnabled(true); + btnConnect.setText("Disconnect"); + btnGames.setEnabled(true); + btnDeckEditor.setEnabled(true); + } + + public void disableButtons() { + btnConnect.setEnabled(true); + btnConnect.setText("Connect"); + btnGames.setEnabled(false); + btnDeckEditor.setEnabled(true); + } + + public void hideTables() { + this.tablesPane.hideTables(); + } + + public void showGames(final boolean setActive) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + MagePane topPanebefore = getTopMost(tablesPane); + if (!tablesPane.isVisible()) { + tablesPane.setVisible(true); + tablesPane.showTables(); + } + if (setActive) { + setActive(tablesPane); + } else { + // if other panel was already shown, mamke sure it's topmost again + if (topPanebefore != null) { + setActive(topPanebefore); + } + } + } + }); + } + + public void hideGames() { + JInternalFrame[] windows = desktopPane.getAllFramesInLayer(JLayeredPane.DEFAULT_LAYER); + for (JInternalFrame window : windows) { + if (window instanceof GamePane) { + GamePane gamePane = (GamePane) window; + gamePane.removeGame(); + } + if (window instanceof DraftPane) { + DraftPane draftPane = (DraftPane) window; + draftPane.removeDraft(); + } + if (window instanceof TournamentPane) { + TournamentPane tournamentPane = (TournamentPane) window; + tournamentPane.removeTournament(); + } + // close & remove sideboarding or construction pane if open + if (window instanceof DeckEditorPane) { + DeckEditorPane deckEditorPane = (DeckEditorPane) window; + if (deckEditorPane.getDeckEditorMode().equals(DeckEditorMode.LIMITED_BUILDING) + || deckEditorPane.getDeckEditorMode().equals(DeckEditorMode.SIDEBOARDING)) { + deckEditorPane.removeFrame(); + } + } + + } + } + + public void showDeckEditor(final DeckEditorMode mode, final Deck deck, final UUID tableId, final int time) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + String name; + if (mode == DeckEditorMode.SIDEBOARDING || mode == DeckEditorMode.LIMITED_BUILDING) { + name = "Deck Editor - " + tableId.toString(); + } else { + if (deck != null) { + name = "Deck Editor - " + deck.getName(); + } else { + name = "Deck Editor"; + } + // use already open editor + JInternalFrame[] windows = desktopPane.getAllFramesInLayer(JLayeredPane.DEFAULT_LAYER); + for (JInternalFrame window : windows) { + if (window instanceof DeckEditorPane && window.getTitle().equals(name)) { + setActive((MagePane) window); + return; + } + } + } + + try { + DeckEditorPane deckEditorPane = new DeckEditorPane(); + desktopPane.add(deckEditorPane, JLayeredPane.DEFAULT_LAYER); + deckEditorPane.setMaximum(true); + deckEditorPane.setVisible(true); + deckEditorPane.show(mode, deck, name, tableId, time); + setActive(deckEditorPane); + } catch (PropertyVetoException ex) { + logger.fatal(null, ex); + } + } + }); + } + + public void showUserRequestDialog(final UserRequestMessage userRequestMessage) { + final UserRequestDialog userRequestDialog = new UserRequestDialog(); + userRequestDialog.setLocation(100, 100); + desktopPane.add(userRequestDialog, JLayeredPane.MODAL_LAYER); +// ui.addComponent(MageComponents.DESKTOP_PANE, userRequestDialog); + if (SwingUtilities.isEventDispatchThread()) { + userRequestDialog.showDialog(userRequestMessage); + } else { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + userRequestDialog.showDialog(userRequestMessage); + } + }); + } + + } + + public void showErrorDialog(final String title, final String message) { + if (SwingUtilities.isEventDispatchThread()) { + errorDialog.showDialog(title, message); + } else { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + errorDialog.showDialog(title, message); + } + }); + } + + } + + public void showCollectionViewer() { + JInternalFrame[] windows = desktopPane.getAllFramesInLayer(JLayeredPane.DEFAULT_LAYER); + for (JInternalFrame window : windows) { + if (window instanceof CollectionViewerPane) { + setActive((MagePane) window); + return; + } + } + try { + CollectionViewerPane collectionViewerPane = new CollectionViewerPane(); + desktopPane.add(collectionViewerPane, javax.swing.JLayeredPane.DEFAULT_LAYER); + collectionViewerPane.setMaximum(true); + collectionViewerPane.setVisible(true); + setActive(collectionViewerPane); + } catch (PropertyVetoException ex) { + logger.fatal(null, ex); + } + } + + static void renderSplashFrame(Graphics2D g) { + g.setComposite(AlphaComposite.Clear); + g.fillRect(120, 140, 200, 40); + g.setPaintMode(); + g.setColor(Color.white); + g.drawString("Version 0.6.1", 560, 460); + } + + /** + * @param args the command line arguments + */ + public static void main(final String args[]) { + // Workaround for #451 + System.setProperty("java.util.Arrays.useLegacyMergeSort", "true"); + logger.info("Starting MAGE client version " + version); + logger.info("Logging level: " + logger.getEffectiveLevel()); + + startTime = System.currentTimeMillis(); + Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { + @Override + public void uncaughtException(Thread t, Throwable e) { + logger.fatal(null, e); + } + }); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + for (String arg : args) { + if (arg.startsWith(liteModeArg)) { + liteMode = true; + } + if (arg.startsWith(grayModeArg)) { + grayMode = true; + } + if (arg.startsWith(fullscreenArg)) { + fullscreenMode = true; + } + } + if (!liteMode) { + final SplashScreen splash = SplashScreen.getSplashScreen(); + if (splash != null) { + Graphics2D g = splash.createGraphics(); + if (g != null) { + renderSplashFrame(g); + } + splash.update(); + } + } + instance = new MageFrame(); + instance.setVisible(true); + + } + }); + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnAbout; + private javax.swing.JButton btnCollectionViewer; + private javax.swing.JButton btnConnect; + private javax.swing.JButton btnDeckEditor; + private javax.swing.JButton btnExit; + private javax.swing.JButton btnGames; + private javax.swing.JButton btnPreferences; + private javax.swing.JButton btnSendFeedback; + private static javax.swing.JDesktopPane desktopPane; + private javax.swing.JLabel jMemUsageLabel; + private javax.swing.JToolBar.Separator jSeparator1; + private javax.swing.JToolBar.Separator jSeparator2; + private javax.swing.JToolBar.Separator jSeparator3; + private javax.swing.JToolBar.Separator jSeparator4; + private javax.swing.JToolBar.Separator jSeparator5; + private javax.swing.JToolBar.Separator jSeparator6; + private javax.swing.JToolBar.Separator jSeparator7; + private javax.swing.JToolBar.Separator jSeparator8; + private javax.swing.JLabel lblStatus; + private javax.swing.JToolBar mageToolbar; + // End of variables declaration//GEN-END:variables + + private static final long serialVersionUID = -9104885239063142218L; + private ImagePanel backgroundPane; + private TablesPane tablesPane; +// private CollectionViewerPane collectionViewerPane; + + public void setStatusText(String status) { + this.lblStatus.setText(status); + } + + public static MageUI getUI() { + return ui; + } + + public static ChatPanel getChat(UUID chatId) { + return chats.get(chatId); + } + + public static void addChat(UUID chatId, ChatPanel chatPanel) { + chats.put(chatId, chatPanel); + } + + public static void removeChat(UUID chatId) { + chats.remove(chatId); + } + + public static void addGame(UUID gameId, GamePanel gamePanel) { + games.put(gameId, gamePanel); + } + + public static GamePanel getGame(UUID gameId) { + return games.get(gameId); + } + + public static void removeGame(UUID gameId) { + games.remove(gameId); + } + + public static DraftPanel getDraft(UUID draftId) { + return drafts.get(draftId); + } + + public static void removeDraft(final UUID draftId) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + DraftPanel draftPanel = drafts.get(draftId); + if (draftPanel != null) { + drafts.remove(draftId); + draftPanel.hideDraft(); + } + } + }); + } + + public static void addDraft(UUID draftId, DraftPanel draftPanel) { + drafts.put(draftId, draftPanel); + } + + @Override + public void connected(final String message) { + if (SwingUtilities.isEventDispatchThread()) { + setStatusText(message); + enableButtons(); + } else { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + setStatusText(message); + enableButtons(); + } + }); + } + } + + @Override + public void disconnected(final boolean errorCall) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + setStatusText("Not connected"); + disableButtons(); + hideGames(); + hideTables(); + if (errorCall && JOptionPane.showConfirmDialog(MageFrame.this, "The connection to server was lost. Reconnect?", "Warning", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { + if (performConnect()) { + enableButtons(); + } + } + } + }); + } + + public void showMessage(final String title, final String message) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + JOptionPane.showMessageDialog(desktopPane, message, title, JOptionPane.INFORMATION_MESSAGE); + } + }); + } + + public void showError(final String title, final String message) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + JOptionPane.showMessageDialog(desktopPane, message, title, JOptionPane.ERROR_MESSAGE); + } + }); + } + + @Override + public void inform(String title, String message, MessageType type) { + if (type == MessageType.ERROR) { + showError(title, message); + } + else { + showMessage(title, message); + } + } + + @Override + public void receiveChatMessage(final UUID chatId, final ChatMessage message) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + ChatPanel panel = MageFrame.getChat(chatId); + if (panel != null) { + // send the message to subchat if exists and it's not a game message + if (!message.getMessageType().equals(ChatMessage.MessageType.GAME) && panel.getConnectedChat() != null) { + panel.getConnectedChat().receiveMessage(message); + } else { + panel.receiveMessage(message); + } + } + } + }); + } + + @Override + public void receiveBroadcastMessage(String message) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public void clientRegistered(ServerState state) { + this.serverState = state; + } + + @Override + public ServerState getServerState() { + return serverState; + } + + @Override + public void joinedTable(UUID roomId, UUID tableId, UUID chatId, boolean owner, boolean tournament) { + showTableWaitingDialog(roomId, tableId, chatId, owner, tournament); + } + + @Override + public void gameStarted(UUID gameId, UUID playerId) { + GameManager.getInstance().setCurrentPlayerUUID(playerId); + showGame(gameId, playerId); + logger.info("Game " + gameId + " started for player " + playerId); + + if (Plugins.getInstance().isCounterPluginLoaded()) { + Plugins.getInstance().addGamesPlayed(); + } + } + + @Override + public void initGame(final UUID gameId, final GameView gameView) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + GamePanel panel = MageFrame.getGame(gameId); + if (panel != null) { + panel.init(gameView); + } + } + }); + } + + @Override + public void gameAsk(final UUID gameId, final GameView gameView, final String question, final Map options) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + GamePanel panel = MageFrame.getGame(gameId); + if (panel != null) { + panel.ask(question, gameView, options); + } + } + }); + } + + @Override + public void gameTarget(final UUID gameId, final GameView gameView, final String question, final CardsView cardView, final Set targets, final boolean required, final Map options) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + GamePanel panel = MageFrame.getGame(gameId); + if (panel != null) { + panel.pickTarget(question, cardView, gameView, targets, required, options); + } + } + }); + } + + @Override + public void gameChooseAbility(final UUID gameId, final AbilityPickerView abilities) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + GamePanel panel = MageFrame.getGame(gameId); + if (panel != null) { + panel.pickAbility(abilities); + } + } + }); + } + + @Override + public void gameChoosePile(final UUID gameId, final String message, final CardsView pile1, final CardsView pile2) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + GamePanel panel = MageFrame.getGame(gameId); + if (panel != null) { + panel.pickPile(message, pile1, pile2); + } + } + }); + } + + @Override + public void gameChooseChoice(final UUID gameId, final Choice choice) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + GamePanel panel = MageFrame.getGame(gameId); + if (panel != null) { + panel.getChoice(choice); + } + } + }); + } + + @Override + public void gamePlayMana(final UUID gameId, final GameView gameView, final String message, final Map options) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + GamePanel panel = MageFrame.getGame(gameId); + if (panel != null) { + panel.playMana(message, gameView, options); + } + } + }); + } + + @Override + public void gamePlayXMana(final UUID gameId, final GameView gameView, final String message) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + GamePanel panel = MageFrame.getGame(gameId); + if (panel != null) { + panel.playXMana(message, gameView); + } + } + }); + } + + @Override + public void gameSelectAmount(final UUID gameId, final String message, final int min, final int max) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + GamePanel panel = MageFrame.getGame(gameId); + if (panel != null) { + panel.getAmount(min, max, message); + } + } + }); + } + + @Override + public void gameSelect(final UUID gameId, final GameView gameView, final String message, final Map options) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + GamePanel panel = MageFrame.getGame(gameId); + if (panel != null) { + panel.select(message, gameView, options); + } + } + }); + } + + @Override + public void gameEndInfo(UUID gameId, GameEndView view) { + showGameEndDialog(view); + } + + @Override + public void userRequestDialog(UUID gameId, UserRequestMessage userRequestMessage) { + showUserRequestDialog(userRequestMessage); + } + + @Override + public void gameUpdate(final UUID gameId, final GameView gameView) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + GamePanel panel = MageFrame.getGame(gameId); + if (panel != null) { + panel.updateGame(gameView); + } + } + }); + } + + @Override + public void gameInform(final UUID gameId, final GameClientMessage message) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + GamePanel panel = MageFrame.getGame(gameId); + if (panel != null) { + panel.inform(message.getMessage(), message.getGameView()); + } + } + }); + } + + @Override + public void gameInformPersonal(final UUID gameId, final GameClientMessage message) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + GamePanel panel = MageFrame.getGame(gameId); + if (panel != null) { + JOptionPane.showMessageDialog(panel, message.getMessage(), "Game message", JOptionPane.INFORMATION_MESSAGE); + } + } + }); + } + + @Override + public void gameOver(final UUID gameId, final String message) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + GamePanel panel = MageFrame.getGame(gameId); + if (panel != null) { + panel.endMessage(message); + } + } + }); + } + + @Override + public void gameError(UUID gameId, String message) { + this.showErrorDialog("Game Error", message); + } + + @Override + public void sideboard(UUID tableId, DeckView deckView, int time, boolean limited) { + Deck deck = DeckUtil.construct(deckView); + if (limited) { + construct(deck, tableId, time); + } else { + sideboard(deck, tableId, time); + } + } + + @Override + public void construct(UUID tableId, DeckView deckView, int time) { + Deck deck = DeckUtil.construct(deckView); + construct(deck, tableId, time); + } + + + protected void sideboard(Deck deck, UUID tableId, int time) { + showDeckEditor(DeckEditorMode.SIDEBOARDING, deck, tableId, time); + } + + protected void construct(Deck deck, UUID tableId, int time) { + showDeckEditor(DeckEditorMode.LIMITED_BUILDING, deck, tableId, time); + } + + @Override + public void startDraft(UUID draftId, UUID playerId) { + showDraft(draftId); + logger.info("Draft " + draftId + " started for player " + playerId); + } + + @Override + public void draftInit(final UUID draftId, final DraftPickView draftPickView) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + DraftPanel panel = MageFrame.getDraft(draftId); + if (panel != null) { + panel.loadBooster(draftPickView); + } + } + }); + } + + @Override + public void draftUpdate(final UUID draftId, final DraftView draftView) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + DraftPanel panel = MageFrame.getDraft(draftId); + if (panel != null) { + panel.updateDraft(draftView); + } + } + }); + } + + @Override + public void draftPick(final UUID draftId, final DraftPickView draftPickView) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + DraftPanel panel = MageFrame.getDraft(draftId); + if (panel != null) { + try { + panel.loadBooster(draftPickView); + } catch (Exception ex) { + logger.error("arrrgh", ex); + } + } + } + }); + } + + @Override + public void draftOver(UUID draftId) { + removeDraft(draftId); + } + + @Override + public void tournamentStarted(UUID tournamentId) { + showTournament(tournamentId); + AudioManager.playTournamentStarted(); + logger.info("Tournament " + tournamentId + " started"); + } + +} + +class MagePaneMenuItem extends JCheckBoxMenuItem { + + private final MagePane frame; + + public MagePaneMenuItem(MagePane frame) { + super(frame.getTitle()); + this.frame = frame; + } + + public MagePane getFrame() { + return frame; + } +} diff --git a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java index af4e96ed42e..625866f9ce2 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java @@ -2446,17 +2446,17 @@ public class PreferencesDialog extends javax.swing.JDialog { } } - public static UserDataView getUserData(){ + public static UserDataView getUserData() { return new UserDataView(UserGroup.PLAYER, - PreferencesDialog.selectedAvatarId, - PreferencesDialog.getCachedValue(PreferencesDialog.KEY_SHOW_TOOLTIPS_ANY_ZONE, "true").equals("true"), - PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS, "true").equals("true"), - PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_CONFIRM_EMPTY_MANA_POOL, "true").equals("true"), - getUserSkipPrioritySteps(), - MageFrame.getPreferences().get(KEY_CONNECT_FLAG, "world"), - PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_ASK_MOVE_TO_GRAVE_ORDER, "true").equals("true"), - PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_MANA_AUTOPAYMENT, "true").equals("true"), - PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE, "true").equals("true") + PreferencesDialog.selectedAvatarId, + PreferencesDialog.getCachedValue(PreferencesDialog.KEY_SHOW_ABILITY_PICKER_FORCED, "true").equals("true"), + PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS, "true").equals("true"), + PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_CONFIRM_EMPTY_MANA_POOL, "true").equals("true"), + getUserSkipPrioritySteps(), + MageFrame.getPreferences().get(KEY_CONNECT_FLAG, "world"), + PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_ASK_MOVE_TO_GRAVE_ORDER, "true").equals("true"), + PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_MANA_AUTOPAYMENT, "true").equals("true"), + PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE, "true").equals("true") ); } diff --git a/Mage.Common/src/mage/view/UserDataView.java b/Mage.Common/src/mage/view/UserDataView.java index 00f7ae730f8..1142044993a 100644 --- a/Mage.Common/src/mage/view/UserDataView.java +++ b/Mage.Common/src/mage/view/UserDataView.java @@ -1,138 +1,138 @@ -package mage.view; - -import java.io.Serializable; -import mage.players.net.UserData; -import mage.players.net.UserGroup; -import mage.players.net.UserSkipPrioritySteps; - -/** - * Transfer object for {@link mage.players.net.UserData} - * - * @author ayrat - */ -public class UserDataView implements Serializable { - - protected int groupId; - protected int avatarId; - protected boolean showAbilityPickerForced; - protected boolean allowRequestShowHandCards; - protected boolean confirmEmptyManaPool; - protected UserSkipPrioritySteps userSkipPrioritySteps; - protected String flagName; - protected boolean askMoveToGraveOrder; - protected boolean manaPoolAutomatic; - protected boolean manaPoolAutomaticRestricted; - - static UserData getDefaultUserDataView() { - return UserData.getDefaultUserDataView(); - } - - public UserDataView(UserGroup userGroup, int avatarId, boolean showAbilityPickerForced, - boolean allowRequestShowHandCards, boolean confirmEmptyManaPool, UserSkipPrioritySteps userSkipPrioritySteps, - String flagName, boolean askMoveToGraveOrder, boolean manaPoolAutomatic, boolean manaPoolAutomaticRestricted) { - this.groupId = userGroup.getGroupId(); - this.avatarId = avatarId; - this.showAbilityPickerForced = showAbilityPickerForced; - this.allowRequestShowHandCards = allowRequestShowHandCards; - this.userSkipPrioritySteps = userSkipPrioritySteps; - this.confirmEmptyManaPool = confirmEmptyManaPool; - this.flagName = flagName; - this.askMoveToGraveOrder = askMoveToGraveOrder; - this.manaPoolAutomatic = manaPoolAutomatic; - this.manaPoolAutomaticRestricted = manaPoolAutomaticRestricted; - } - - public void update(UserData userData) { - this.groupId = userData.getGroupId(); - this.avatarId = userData.getAvatarId(); - this.showAbilityPickerForced = userData.isShowAbilityPickerForced(); - this.allowRequestShowHandCards = userData.isAllowRequestShowHandCards(); - this.userSkipPrioritySteps = userData.getUserSkipPrioritySteps(); - this.confirmEmptyManaPool = userData.confirmEmptyManaPool(); - this.flagName = userData.getFlagName(); - this.askMoveToGraveOrder = userData.askMoveToGraveOrder(); - this.manaPoolAutomatic = userData.isManaPoolAutomatic(); - this.manaPoolAutomaticRestricted = userData.isManaPoolAutomaticRestricted(); - } - - public void setGroupId(int groupId) { - this.groupId = groupId; - } - - public int getGroupId() { - return groupId; - } - - public int getAvatarId() { - return avatarId; - } - - public void setAvatarId(int avatarId) { - this.avatarId = avatarId; - } - - public boolean isShowAbilityPickerForced() { - return showAbilityPickerForced; - } - - public void setShowAbilityPickerForced(boolean showAbilityPickerForced) { - this.showAbilityPickerForced = showAbilityPickerForced; - } - - public boolean isAllowRequestShowHandCards() { - return allowRequestShowHandCards; - } - - public void setAllowRequestShowHandCards(boolean allowRequestShowHandCards) { - this.allowRequestShowHandCards = allowRequestShowHandCards; - } - - public UserSkipPrioritySteps getUserSkipPrioritySteps() { - return userSkipPrioritySteps; - } - - public void setUserSkipPrioritySteps(UserSkipPrioritySteps userSkipPrioritySteps) { - this.userSkipPrioritySteps = userSkipPrioritySteps; - } - - public boolean confirmEmptyManaPool() { - return confirmEmptyManaPool; - } - - public void setConfirmEmptyManaPool(boolean confirmEmptyManaPool) { - this.confirmEmptyManaPool = confirmEmptyManaPool; - } - - public String getFlagName() { - return flagName; - } - - public void setFlagName(String flagName) { - this.flagName = flagName; - } - - public boolean askMoveToGraveOrder() { - return askMoveToGraveOrder; - } - - public void setAskMoveToGraveOrder(boolean askMoveToGraveOrder) { - this.askMoveToGraveOrder = askMoveToGraveOrder; - } - - public boolean isManaPoolAutomatic() { - return manaPoolAutomatic; - } - - public void setManaPoolAutomatic(boolean manaPoolAutomatic) { - this.manaPoolAutomatic = manaPoolAutomatic; - } - - public boolean isManaPoolAutomaticRestricted() { - return manaPoolAutomaticRestricted; - } - - public void setManaPoolAutomaticRestricted(boolean manaPoolAutomaticRestricted) { - this.manaPoolAutomaticRestricted = manaPoolAutomaticRestricted; - } - -} +package mage.view; + +import java.io.Serializable; +import mage.players.net.UserData; +import mage.players.net.UserGroup; +import mage.players.net.UserSkipPrioritySteps; + +/** + * Transfer object for {@link mage.players.net.UserData} + * + * @author ayrat + */ +public class UserDataView implements Serializable { + + protected int groupId; + protected int avatarId; + protected boolean showAbilityPickerForced; + protected boolean allowRequestShowHandCards; + protected boolean confirmEmptyManaPool; + protected UserSkipPrioritySteps userSkipPrioritySteps; + protected String flagName; + protected boolean askMoveToGraveOrder; + protected boolean manaPoolAutomatic; + protected boolean manaPoolAutomaticRestricted; + + static UserData getDefaultUserData() { + return UserData.getDefaultUserDataView(); + } + + public UserDataView(UserGroup userGroup, int avatarId, boolean showAbilityPickerForced, + boolean allowRequestShowHandCards, boolean confirmEmptyManaPool, UserSkipPrioritySteps userSkipPrioritySteps, + String flagName, boolean askMoveToGraveOrder, boolean manaPoolAutomatic, boolean manaPoolAutomaticRestricted) { + this.groupId = userGroup.getGroupId(); + this.avatarId = avatarId; + this.showAbilityPickerForced = showAbilityPickerForced; + this.allowRequestShowHandCards = allowRequestShowHandCards; + this.userSkipPrioritySteps = userSkipPrioritySteps; + this.confirmEmptyManaPool = confirmEmptyManaPool; + this.flagName = flagName; + this.askMoveToGraveOrder = askMoveToGraveOrder; + this.manaPoolAutomatic = manaPoolAutomatic; + this.manaPoolAutomaticRestricted = manaPoolAutomaticRestricted; + } + + public void update(UserData userData) { + this.groupId = userData.getGroupId(); + this.avatarId = userData.getAvatarId(); + this.showAbilityPickerForced = userData.isShowAbilityPickerForced(); + this.allowRequestShowHandCards = userData.isAllowRequestShowHandCards(); + this.userSkipPrioritySteps = userData.getUserSkipPrioritySteps(); + this.confirmEmptyManaPool = userData.confirmEmptyManaPool(); + this.flagName = userData.getFlagName(); + this.askMoveToGraveOrder = userData.askMoveToGraveOrder(); + this.manaPoolAutomatic = userData.isManaPoolAutomatic(); + this.manaPoolAutomaticRestricted = userData.isManaPoolAutomaticRestricted(); + } + + public void setGroupId(int groupId) { + this.groupId = groupId; + } + + public int getGroupId() { + return groupId; + } + + public int getAvatarId() { + return avatarId; + } + + public void setAvatarId(int avatarId) { + this.avatarId = avatarId; + } + + public boolean isShowAbilityPickerForced() { + return showAbilityPickerForced; + } + + public void setShowAbilityPickerForced(boolean showAbilityPickerForced) { + this.showAbilityPickerForced = showAbilityPickerForced; + } + + public boolean isAllowRequestShowHandCards() { + return allowRequestShowHandCards; + } + + public void setAllowRequestShowHandCards(boolean allowRequestShowHandCards) { + this.allowRequestShowHandCards = allowRequestShowHandCards; + } + + public UserSkipPrioritySteps getUserSkipPrioritySteps() { + return userSkipPrioritySteps; + } + + public void setUserSkipPrioritySteps(UserSkipPrioritySteps userSkipPrioritySteps) { + this.userSkipPrioritySteps = userSkipPrioritySteps; + } + + public boolean confirmEmptyManaPool() { + return confirmEmptyManaPool; + } + + public void setConfirmEmptyManaPool(boolean confirmEmptyManaPool) { + this.confirmEmptyManaPool = confirmEmptyManaPool; + } + + public String getFlagName() { + return flagName; + } + + public void setFlagName(String flagName) { + this.flagName = flagName; + } + + public boolean askMoveToGraveOrder() { + return askMoveToGraveOrder; + } + + public void setAskMoveToGraveOrder(boolean askMoveToGraveOrder) { + this.askMoveToGraveOrder = askMoveToGraveOrder; + } + + public boolean isManaPoolAutomatic() { + return manaPoolAutomatic; + } + + public void setManaPoolAutomatic(boolean manaPoolAutomatic) { + this.manaPoolAutomatic = manaPoolAutomatic; + } + + public boolean isManaPoolAutomaticRestricted() { + return manaPoolAutomaticRestricted; + } + + public void setManaPoolAutomaticRestricted(boolean manaPoolAutomaticRestricted) { + this.manaPoolAutomaticRestricted = manaPoolAutomaticRestricted; + } + +} diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/Reciprocate.java b/Mage.Sets/src/mage/sets/championsofkamigawa/Reciprocate.java index 65eac2b615a..5098fa1427c 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/Reciprocate.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/Reciprocate.java @@ -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.sets.championsofkamigawa; import java.util.HashSet; @@ -48,8 +47,8 @@ import mage.watchers.common.PlayerDamagedBySourceWatcher; */ public class Reciprocate extends CardImpl { - public Reciprocate(UUID ownerId) { - super(ownerId, 40, "Reciprocate", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{1}{W}"); + public Reciprocate(UUID ownerId) { + super(ownerId, 40, "Reciprocate", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{W}"); this.expansionSetCode = "CHK"; // Exile target creature that dealt damage to you this turn. @@ -81,7 +80,7 @@ class ReciprocateTarget extends TargetPermanent { @Override public boolean canTarget(UUID id, Ability source, Game game) { - PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource",source.getControllerId()); + PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource", source.getControllerId()); if (watcher != null && watcher.hasSourceDoneDamage(id, game)) { return super.canTarget(id, source, game); } @@ -95,7 +94,7 @@ class ReciprocateTarget extends TargetPermanent { PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource", sourceControllerId); for (UUID targetId : availablePossibleTargets) { Permanent permanent = game.getPermanent(targetId); - if(permanent != null && watcher != null && watcher.hasSourceDoneDamage(targetId, game)){ + if (permanent != null && watcher != null && watcher.hasSourceDoneDamage(targetId, game)) { possibleTargets.add(targetId); } } @@ -111,14 +110,14 @@ class ReciprocateTarget extends TargetPermanent { int count = 0; MageObject targetSource = game.getObject(sourceId); PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get("PlayerDamagedBySource", sourceControllerId); - for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) { - if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, game) + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) { + if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, game) && watcher != null && watcher.hasSourceDoneDamage(permanent.getId(), game)) { - count++; - if (count >= remainingTargets) { - return true; - } + count++; + if (count >= remainingTargets) { + return true; } + } } return false; } diff --git a/Mage.Sets/src/mage/sets/fifthdawn/RainOfRust.java b/Mage.Sets/src/mage/sets/fifthdawn/RainOfRust.java index ad28ada69ed..83f34843cb7 100644 --- a/Mage.Sets/src/mage/sets/fifthdawn/RainOfRust.java +++ b/Mage.Sets/src/mage/sets/fifthdawn/RainOfRust.java @@ -47,11 +47,8 @@ public class RainOfRust extends CardImpl { super(ownerId, 76, "Rain of Rust", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{3}{R}{R}"); this.expansionSetCode = "5DN"; - - // Choose one - - this.getSpellAbility().getModes().setMinModes(1); - this.getSpellAbility().getModes().setMaxModes(1); - //Destroy target artifact; + // Choose one - + //Destroy target artifact; this.getSpellAbility().addEffect(new DestroyTargetEffect()); this.getSpellAbility().addTarget(new TargetArtifactPermanent()); //or destroy target land. diff --git a/Mage.Sets/src/mage/sets/masterseditioniii/CorruptEunuchs.java b/Mage.Sets/src/mage/sets/masterseditioniii/CorruptEunuchs.java new file mode 100644 index 00000000000..266fba9eeba --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditioniii/CorruptEunuchs.java @@ -0,0 +1,68 @@ +/* + * 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.masterseditioniii; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + */ +public class CorruptEunuchs extends CardImpl { + + public CorruptEunuchs(UUID ownerId) { + super(ownerId, 92, "Corrupt Eunuchs", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{R}"); + this.expansionSetCode = "ME3"; + this.subtype.add("Human"); + this.subtype.add("Advisor"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // When Corrupt Eunuchs enters the battlefield, it deals 2 damage to target creature. + Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(2), false); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public CorruptEunuchs(final CorruptEunuchs card) { + super(card); + } + + @Override + public CorruptEunuchs copy() { + return new CorruptEunuchs(this); + } +} diff --git a/Mage.Sets/src/mage/sets/masterseditioniii/DesperateCharge.java b/Mage.Sets/src/mage/sets/masterseditioniii/DesperateCharge.java new file mode 100644 index 00000000000..d33a2052ff8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditioniii/DesperateCharge.java @@ -0,0 +1,54 @@ +/* + * 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.masterseditioniii; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LoneFox + */ +public class DesperateCharge extends mage.sets.portalthreekingdoms.DesperateCharge { + + public DesperateCharge(UUID ownerId) { + super(ownerId); + this.cardNumber = 63; + this.expansionSetCode = "ME3"; + this.rarity = Rarity.COMMON; + } + + public DesperateCharge(final DesperateCharge card) { + super(card); + } + + @Override + public DesperateCharge copy() { + return new DesperateCharge(this); + } +} diff --git a/Mage.Sets/src/mage/sets/masterseditioniii/GhostlyVisit.java b/Mage.Sets/src/mage/sets/masterseditioniii/GhostlyVisit.java new file mode 100644 index 00000000000..a9f1ec18d0e --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditioniii/GhostlyVisit.java @@ -0,0 +1,52 @@ +/* + * 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.masterseditioniii; + +import java.util.UUID; + +/** + * + * @author LoneFox + */ +public class GhostlyVisit extends mage.sets.portalthreekingdoms.GhostlyVisit { + + public GhostlyVisit(UUID ownerId) { + super(ownerId); + this.cardNumber = 67; + this.expansionSetCode = "ME3"; + } + + public GhostlyVisit(final GhostlyVisit card) { + super(card); + } + + @Override + public GhostlyVisit copy() { + return new GhostlyVisit(this); + } +} diff --git a/Mage.Sets/src/mage/sets/masterseditioniii/GuanYus1000LiMarch.java b/Mage.Sets/src/mage/sets/masterseditioniii/GuanYus1000LiMarch.java new file mode 100644 index 00000000000..a391fb5ad5f --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditioniii/GuanYus1000LiMarch.java @@ -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.masterseditioniii; + +import java.util.UUID; +import mage.abilities.effects.common.DestroyAllEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.TappedPredicate; + +/** + * + * @author LoneFox + */ +public class GuanYus1000LiMarch extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creatures"); + + static { + filter.add(new TappedPredicate()); + } + + public GuanYus1000LiMarch(UUID ownerId) { + super(ownerId, 13, "Guan Yu's 1,000-Li March", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{4}{W}{W}"); + this.expansionSetCode = "ME3"; + + // Destroy all tapped creatures. + this.getSpellAbility().addEffect(new DestroyAllEffect(filter, false)); + } + + public GuanYus1000LiMarch(final GuanYus1000LiMarch card) { + super(card); + } + + @Override + public GuanYus1000LiMarch copy() { + return new GuanYus1000LiMarch(this); + } +} diff --git a/Mage.Sets/src/mage/sets/masterseditioniii/HuntingCheetah.java b/Mage.Sets/src/mage/sets/masterseditioniii/HuntingCheetah.java new file mode 100644 index 00000000000..3ae56e6bfd3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditioniii/HuntingCheetah.java @@ -0,0 +1,54 @@ +/* + * 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.masterseditioniii; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LoneFox + */ +public class HuntingCheetah extends mage.sets.portalthreekingdoms.HuntingCheetah { + + public HuntingCheetah(UUID ownerId) { + super(ownerId); + this.cardNumber = 124; + this.expansionSetCode = "ME3"; + this.rarity = Rarity.COMMON; + } + + public HuntingCheetah(final HuntingCheetah card) { + super(card); + } + + @Override + public HuntingCheetah copy() { + return new HuntingCheetah(this); + } +} diff --git a/Mage.Sets/src/mage/sets/masterseditioniii/LiuBeiLordOfShu.java b/Mage.Sets/src/mage/sets/masterseditioniii/LiuBeiLordOfShu.java new file mode 100644 index 00000000000..e98e81460f4 --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditioniii/LiuBeiLordOfShu.java @@ -0,0 +1,52 @@ +/* + * 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.masterseditioniii; + +import java.util.UUID; + +/** + * + * @author LoneFox + */ +public class LiuBeiLordOfShu extends mage.sets.portalthreekingdoms.LiuBeiLordOfShu { + + public LiuBeiLordOfShu(UUID ownerId) { + super(ownerId); + this.cardNumber = 19; + this.expansionSetCode = "ME3"; + } + + public LiuBeiLordOfShu(final LiuBeiLordOfShu card) { + super(card); + } + + @Override + public LiuBeiLordOfShu copy() { + return new LiuBeiLordOfShu(this); + } +} diff --git a/Mage.Sets/src/mage/sets/masterseditioniii/RidingTheDiluHorse.java b/Mage.Sets/src/mage/sets/masterseditioniii/RidingTheDiluHorse.java new file mode 100644 index 00000000000..20069b53790 --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditioniii/RidingTheDiluHorse.java @@ -0,0 +1,67 @@ +/* + * 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.masterseditioniii; + +import java.util.UUID; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.HorsemanshipAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + */ +public class RidingTheDiluHorse extends CardImpl { + + public RidingTheDiluHorse(UUID ownerId) { + super(ownerId, 131, "Riding the Dilu Horse", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{2}{G}"); + this.expansionSetCode = "ME3"; + + // Target creature gets +2/+2 and gains horsemanship. + this.getSpellAbility().addEffect(new BoostTargetEffect(2, 2, Duration.WhileOnBattlefield)); + Effect effect = new GainAbilityTargetEffect(HorsemanshipAbility.getInstance(), Duration.WhileOnBattlefield); + effect.setText("and gains horsemanship"); + this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + public RidingTheDiluHorse(final RidingTheDiluHorse card) { + super(card); + } + + @Override + public RidingTheDiluHorse copy() { + return new RidingTheDiluHorse(this); + } +} diff --git a/Mage.Sets/src/mage/sets/masterseditioniii/ShuSoldierFarmers.java b/Mage.Sets/src/mage/sets/masterseditioniii/ShuSoldierFarmers.java new file mode 100644 index 00000000000..c045ae172cc --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditioniii/ShuSoldierFarmers.java @@ -0,0 +1,54 @@ +/* + * 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.masterseditioniii; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LoneFox + */ +public class ShuSoldierFarmers extends mage.sets.portalthreekingdoms.ShuSoldierFarmers { + + public ShuSoldierFarmers(UUID ownerId) { + super(ownerId); + this.cardNumber = 26; + this.expansionSetCode = "ME3"; + this.rarity = Rarity.COMMON; + } + + public ShuSoldierFarmers(final ShuSoldierFarmers card) { + super(card); + } + + @Override + public ShuSoldierFarmers copy() { + return new ShuSoldierFarmers(this); + } +} diff --git a/Mage.Sets/src/mage/sets/masterseditioniii/StolenGrain.java b/Mage.Sets/src/mage/sets/masterseditioniii/StolenGrain.java new file mode 100644 index 00000000000..b8a7ad87418 --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditioniii/StolenGrain.java @@ -0,0 +1,62 @@ +/* + * 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.masterseditioniii; + +import java.util.UUID; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.target.common.TargetOpponent; + +/** + * + * @author LoneFox + */ +public class StolenGrain extends CardImpl { + + public StolenGrain(UUID ownerId) { + super(ownerId, 75, "Stolen Grain", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{4}{B}{B}"); + this.expansionSetCode = "ME3"; + + // Stolen Grain deals 5 damage to target opponent. You gain 5 life. + this.getSpellAbility().addEffect(new DamageTargetEffect(5)); + this.getSpellAbility().addEffect(new GainLifeEffect(5)); + this.getSpellAbility().addTarget(new TargetOpponent()); + } + + public StolenGrain(final StolenGrain card) { + super(card); + } + + @Override + public StolenGrain copy() { + return new StolenGrain(this); + } +} diff --git a/Mage.Sets/src/mage/sets/masterseditioniii/SunCeYoungConquerer.java b/Mage.Sets/src/mage/sets/masterseditioniii/SunCeYoungConquerer.java new file mode 100644 index 00000000000..be6957bee40 --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditioniii/SunCeYoungConquerer.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.masterseditioniii; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.abilities.keyword.HorsemanshipAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + */ +public class SunCeYoungConquerer extends CardImpl { + + public SunCeYoungConquerer(UUID ownerId) { + super(ownerId, 52, "Sun Ce, Young Conquerer", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{U}{U}"); + this.expansionSetCode = "ME3"; + this.supertype.add("Legendary"); + this.subtype.add("Human"); + this.subtype.add("Soldier"); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Horsemanship + this.addAbility(HorsemanshipAbility.getInstance()); + // When Sun Ce, Young Conquerer enters the battlefield, you may return target creature to its owner's hand. + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), true); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public SunCeYoungConquerer(final SunCeYoungConquerer card) { + super(card); + } + + @Override + public SunCeYoungConquerer copy() { + return new SunCeYoungConquerer(this); + } +} diff --git a/Mage.Sets/src/mage/sets/masterseditioniii/TripWire.java b/Mage.Sets/src/mage/sets/masterseditioniii/TripWire.java new file mode 100644 index 00000000000..f95dca4b43e --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditioniii/TripWire.java @@ -0,0 +1,68 @@ +/* + * 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.masterseditioniii; + +import java.util.UUID; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.keyword.HorsemanshipAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + */ +public class TripWire extends CardImpl { + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with horsemanship"); + + static { + filter.add(new AbilityPredicate(HorsemanshipAbility.class)); + } + + public TripWire(UUID ownerId) { + super(ownerId, 137, "Trip Wire", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{2}{G}"); + this.expansionSetCode = "ME3"; + + // Destroy target creature with horsemanship. + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addEffect(new DestroyTargetEffect()); + } + + public TripWire(final TripWire card) { + super(card); + } + + @Override + public TripWire copy() { + return new TripWire(this); + } +} diff --git a/Mage.Sets/src/mage/sets/masterseditioniii/YoungWeiRecruits.java b/Mage.Sets/src/mage/sets/masterseditioniii/YoungWeiRecruits.java new file mode 100644 index 00000000000..843d6ddacfa --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditioniii/YoungWeiRecruits.java @@ -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.masterseditioniii; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.CantBlockAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author LoneFox + */ +public class YoungWeiRecruits extends CardImpl { + + public YoungWeiRecruits(UUID ownerId) { + super(ownerId, 84, "Young Wei Recruits", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{B}"); + this.expansionSetCode = "ME3"; + this.subtype.add("Human"); + this.subtype.add("Soldier"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Young Wei Recruits can't block. + this.addAbility(new CantBlockAbility()); + } + + public YoungWeiRecruits(final YoungWeiRecruits card) { + super(card); + } + + @Override + public YoungWeiRecruits copy() { + return new YoungWeiRecruits(this); + } +} diff --git a/Mage.Sets/src/mage/sets/masterseditioniv/RockslideAmbush.java b/Mage.Sets/src/mage/sets/masterseditioniv/RockslideAmbush.java new file mode 100644 index 00000000000..b899b3818fa --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditioniv/RockslideAmbush.java @@ -0,0 +1,54 @@ +/* + * 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.masterseditioniv; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LoneFox + */ +public class RockslideAmbush extends mage.sets.portalthreekingdoms.RockslideAmbush { + + public RockslideAmbush(UUID ownerId) { + super(ownerId); + this.cardNumber = 134; + this.expansionSetCode = "ME4"; + this.rarity = Rarity.COMMON; + } + + public RockslideAmbush(final RockslideAmbush card) { + super(card); + } + + @Override + public RockslideAmbush copy() { + return new RockslideAmbush(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/ToothAndNail.java b/Mage.Sets/src/mage/sets/modernmasters/ToothAndNail.java index 3902ef10adc..86f2e6936b8 100644 --- a/Mage.Sets/src/mage/sets/modernmasters/ToothAndNail.java +++ b/Mage.Sets/src/mage/sets/modernmasters/ToothAndNail.java @@ -55,7 +55,7 @@ public class ToothAndNail extends CardImpl { super(ownerId, 170, "Tooth and Nail", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{5}{G}{G}"); this.expansionSetCode = "MMA"; - // Choose one - + // Choose one - // Search your library for up to two creature cards, reveal them, put them into your hand, then shuffle your library; this.getSpellAbility().addEffect(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(0, 2, new FilterCreatureCard()), true)); // or put up to two creature cards from your hand onto the battlefield. @@ -95,17 +95,17 @@ class ToothAndNailPutCreatureOnBattlefieldEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player == null) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { return false; } TargetCardInHand target = new TargetCardInHand(0, 2, new FilterCreatureCard("creature cards")); - if (player.choose(Outcome.PutCreatureInPlay, target, source.getSourceId(), game)) { - for (UUID targetId: target.getTargets()) { + if (controller.choose(Outcome.PutCreatureInPlay, target, source.getSourceId(), game)) { + for (UUID targetId : target.getTargets()) { Card card = game.getCard(targetId); if (card != null) { - card.putOntoBattlefield(game, Zone.HAND, source.getSourceId(), source.getControllerId()); + controller.putOntoBattlefieldWithInfo(card, game, Zone.HAND, source.getSourceId(), false); } } return true; diff --git a/Mage.Sets/src/mage/sets/portal/MysticDenial.java b/Mage.Sets/src/mage/sets/portal/MysticDenial.java new file mode 100644 index 00000000000..94dc18ea422 --- /dev/null +++ b/Mage.Sets/src/mage/sets/portal/MysticDenial.java @@ -0,0 +1,69 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.portal; + +import java.util.UUID; +import mage.abilities.effects.common.CounterTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterSpell; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.target.TargetSpell; + +/** + * + * @author LoneFox + */ +public class MysticDenial extends CardImpl { + + private static final FilterSpell filter = new FilterSpell("creature or sorcery spell"); + + static { + filter.add(Predicates.or(new CardTypePredicate(CardType.CREATURE), new CardTypePredicate(CardType.SORCERY))); + } + + public MysticDenial(UUID ownerId) { + super(ownerId, 62, "Mystic Denial", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{1}{U}{U}"); + this.expansionSetCode = "POR"; + + // Counter target creature or sorcery spell. + this.getSpellAbility().addTarget(new TargetSpell(filter)); + this.getSpellAbility().addEffect(new CounterTargetEffect()); + } + + public MysticDenial(final MysticDenial card) { + super(card); + } + + @Override + public MysticDenial copy() { + return new MysticDenial(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalsecondage/Extinguish.java b/Mage.Sets/src/mage/sets/portalsecondage/Extinguish.java new file mode 100644 index 00000000000..4ce95004029 --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalsecondage/Extinguish.java @@ -0,0 +1,68 @@ +/* + * 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.portalsecondage; + +import java.util.UUID; +import mage.abilities.effects.common.CounterTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterSpell; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.target.TargetSpell; + +/** + * + * @author LoneFox + */ +public class Extinguish extends CardImpl { + + private static final FilterSpell filter = new FilterSpell("sorcery spell"); + + static { + filter.add(new CardTypePredicate(CardType.SORCERY)); + } + + public Extinguish(UUID ownerId) { + super(ownerId, 38, "Extinguish", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{U}"); + this.expansionSetCode = "PO2"; + + // Counter target sorcery spell. + this.getSpellAbility().addTarget(new TargetSpell(filter)); + this.getSpellAbility().addEffect(new CounterTargetEffect()); + } + + public Extinguish(final Extinguish card) { + super(card); + } + + @Override + public Extinguish copy() { + return new Extinguish(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalsecondage/MysticDenial.java b/Mage.Sets/src/mage/sets/portalsecondage/MysticDenial.java new file mode 100644 index 00000000000..c814123cb55 --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalsecondage/MysticDenial.java @@ -0,0 +1,52 @@ +/* + * 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.portalsecondage; + +import java.util.UUID; + +/** + * + * @author LoneFox + */ +public class MysticDenial extends mage.sets.portal.MysticDenial { + + public MysticDenial(UUID ownerId) { + super(ownerId); + this.cardNumber = 41; + this.expansionSetCode = "PO2"; + } + + public MysticDenial(final MysticDenial card) { + super(card); + } + + @Override + public MysticDenial copy() { + return new MysticDenial(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/BorrowingTheEastWind.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/BorrowingTheEastWind.java new file mode 100644 index 00000000000..31ccf10a387 --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/BorrowingTheEastWind.java @@ -0,0 +1,67 @@ +/* + * 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.portalthreekingdoms; + +import java.util.UUID; +import mage.abilities.dynamicvalue.common.ManacostVariableValue; +import mage.abilities.effects.common.DamageEverythingEffect; +import mage.abilities.keyword.HorsemanshipAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.AbilityPredicate; + +/** + * + * @author LoneFox + */ +public class BorrowingTheEastWind extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with horsemanship"); + + static { + filter.add(new AbilityPredicate(HorsemanshipAbility.class)); + } + + public BorrowingTheEastWind(UUID ownerId) { + super(ownerId, 133, "Borrowing the East Wind", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{X}{G}{G}"); + this.expansionSetCode = "PTK"; + + // Borrowing the East Wind deals X damage to each creature with horsemanship and each player. + this.getSpellAbility().addEffect(new DamageEverythingEffect(new ManacostVariableValue(), filter)); } + + public BorrowingTheEastWind(final BorrowingTheEastWind card) { + super(card); + } + + @Override + public BorrowingTheEastWind copy() { + return new BorrowingTheEastWind(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/BrokenDam.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/BrokenDam.java new file mode 100644 index 00000000000..698ebcd5b1d --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/BrokenDam.java @@ -0,0 +1,70 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.portalthreekingdoms; + +import java.util.UUID; +import mage.abilities.effects.common.TapTargetEffect; +import mage.abilities.keyword.HorsemanshipAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + */ +public class BrokenDam extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + + static { + filter.add(Predicates.not(new AbilityPredicate(HorsemanshipAbility.class))); + } + + public BrokenDam(UUID ownerId) { + super(ownerId, 37, "Broken Dam", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{U}"); + this.expansionSetCode = "PTK"; + + // Tap one or two target creatures without horsemanship. + this.getSpellAbility().addEffect(new TapTargetEffect("one or two target creatures without horsemanship")); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(1, 2, filter, false)); + } + + public BrokenDam(final BrokenDam card) { + super(card); + } + + @Override + public BrokenDam copy() { + return new BrokenDam(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/BurningFields.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/BurningFields.java new file mode 100644 index 00000000000..402d09f0305 --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/BurningFields.java @@ -0,0 +1,60 @@ +/* + * 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.portalthreekingdoms; + +import java.util.UUID; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.target.common.TargetOpponent; + +/** + * + * @author LoneFox + */ +public class BurningFields extends CardImpl { + + public BurningFields(UUID ownerId) { + super(ownerId, 103, "Burning Fields", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{4}{R}"); + this.expansionSetCode = "PTK"; + + // Burning Fields deals 5 damage to target opponent. + this.getSpellAbility().addTarget(new TargetOpponent()); + this.getSpellAbility().addEffect(new DamageTargetEffect(5)); + } + + public BurningFields(final BurningFields card) { + super(card); + } + + @Override + public BurningFields copy() { + return new BurningFields(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/CaoRenWeiCommander.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/CaoRenWeiCommander.java new file mode 100644 index 00000000000..8bf4749d878 --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/CaoRenWeiCommander.java @@ -0,0 +1,69 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.portalthreekingdoms; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.LoseLifeSourceControllerEffect; +import mage.abilities.keyword.HorsemanshipAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author LoneFox + */ +public class CaoRenWeiCommander extends CardImpl { + + public CaoRenWeiCommander(UUID ownerId) { + super(ownerId, 69, "Cao Ren, Wei Commander", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{B}{B}"); + this.expansionSetCode = "PTK"; + this.supertype.add("Legendary"); + this.subtype.add("Human"); + this.subtype.add("Soldier"); + this.subtype.add("Warrior"); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Horsemanship + this.addAbility(HorsemanshipAbility.getInstance()); + // When Cao Ren, Wei Commander enters the battlefield, you lose 3 life. + this.addAbility(new EntersBattlefieldTriggeredAbility(new LoseLifeSourceControllerEffect(3))); + } + + public CaoRenWeiCommander(final CaoRenWeiCommander card) { + super(card); + } + + @Override + public CaoRenWeiCommander copy() { + return new CaoRenWeiCommander(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/CorruptCourtOfficial.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/CorruptCourtOfficial.java new file mode 100644 index 00000000000..9f2a8abf50d --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/CorruptCourtOfficial.java @@ -0,0 +1,68 @@ +/* + * 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.portalthreekingdoms; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.discard.DiscardTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.target.common.TargetOpponent; + +/** + * + * @author LoneFox + */ +public class CorruptCourtOfficial extends CardImpl { + + public CorruptCourtOfficial(UUID ownerId) { + super(ownerId, 71, "Corrupt Court Official", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{B}"); + this.expansionSetCode = "PTK"; + this.subtype.add("Human"); + this.subtype.add("Advisor"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // When Corrupt Court Official enters the battlefield, target opponent discards a card. + Ability ability = new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(1)); + ability.addTarget(new TargetOpponent()); + this.addAbility(ability); + } + + public CorruptCourtOfficial(final CorruptCourtOfficial card) { + super(card); + } + + @Override + public CorruptCourtOfficial copy() { + return new CorruptCourtOfficial(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/CorruptEunuchs.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/CorruptEunuchs.java new file mode 100644 index 00000000000..f3177279c15 --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/CorruptEunuchs.java @@ -0,0 +1,52 @@ +/* + * 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.portalthreekingdoms; + +import java.util.UUID; + +/** + * + * @author LoneFox + */ +public class CorruptEunuchs extends mage.sets.masterseditioniii.CorruptEunuchs { + + public CorruptEunuchs(UUID ownerId) { + super(ownerId); + this.cardNumber = 106; + this.expansionSetCode = "PTK"; + } + + public CorruptEunuchs(final CorruptEunuchs card) { + super(card); + } + + @Override + public CorruptEunuchs copy() { + return new CorruptEunuchs(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/CouncilOfAdvisors.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/CouncilOfAdvisors.java new file mode 100644 index 00000000000..3d2eeda876b --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/CouncilOfAdvisors.java @@ -0,0 +1,64 @@ +/* + * 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.portalthreekingdoms; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author LoneFox + */ +public class CouncilOfAdvisors extends CardImpl { + + public CouncilOfAdvisors(UUID ownerId) { + super(ownerId, 40, "Council of Advisors", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{U}"); + this.expansionSetCode = "PTK"; + this.subtype.add("Human"); + this.subtype.add("Advisor"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // When Council of Advisors enters the battlefield, draw a card. + this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1))); + } + + public CouncilOfAdvisors(final CouncilOfAdvisors card) { + super(card); + } + + @Override + public CouncilOfAdvisors copy() { + return new CouncilOfAdvisors(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/DesertSandstorm.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/DesertSandstorm.java new file mode 100644 index 00000000000..88e0093051f --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/DesertSandstorm.java @@ -0,0 +1,59 @@ +/* + * 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.portalthreekingdoms; + +import java.util.UUID; +import mage.abilities.effects.common.DamageAllEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; + +/** + * + * @author LoneFox + */ +public class DesertSandstorm extends CardImpl { + + public DesertSandstorm(UUID ownerId) { + super(ownerId, 107, "Desert Sandstorm", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{2}{R}"); + this.expansionSetCode = "PTK"; + + // Desert Sandstorm deals 1 damage to each creature. + this.getSpellAbility().addEffect(new DamageAllEffect(1, new FilterCreaturePermanent())); + } + + public DesertSandstorm(final DesertSandstorm card) { + super(card); + } + + @Override + public DesertSandstorm copy() { + return new DesertSandstorm(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/DesperateCharge.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/DesperateCharge.java new file mode 100644 index 00000000000..d5fcab16d6d --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/DesperateCharge.java @@ -0,0 +1,59 @@ +/* + * 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.portalthreekingdoms; + +import java.util.UUID; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; + +/** + * + * @author LoneFox + */ +public class DesperateCharge extends CardImpl { + + public DesperateCharge(UUID ownerId) { + super(ownerId, 74, "Desperate Charge", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{2}{B}"); + this.expansionSetCode = "PTK"; + + // Creatures you control get +2/+0 until end of turn. + this.getSpellAbility().addEffect(new BoostControlledEffect(2, 0, Duration.EndOfTurn)); + } + + public DesperateCharge(final DesperateCharge card) { + super(card); + } + + @Override + public DesperateCharge copy() { + return new DesperateCharge(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/Extinguish.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/Extinguish.java new file mode 100644 index 00000000000..796af8ca00f --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/Extinguish.java @@ -0,0 +1,52 @@ +/* + * 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.portalthreekingdoms; + +import java.util.UUID; + +/** + * + * @author LoneFox + */ +public class Extinguish extends mage.sets.portalsecondage.Extinguish { + + public Extinguish(UUID ownerId) { + super(ownerId); + this.cardNumber = 43; + this.expansionSetCode = "PTK"; + } + + public Extinguish(final Extinguish card) { + super(card); + } + + @Override + public Extinguish copy() { + return new Extinguish(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/GhostlyVisit.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/GhostlyVisit.java new file mode 100644 index 00000000000..7f481d21d42 --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/GhostlyVisit.java @@ -0,0 +1,70 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.portalthreekingdoms; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + */ +public class GhostlyVisit extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nonblack creature"); + + static { + filter.add(Predicates.not(new ColorPredicate(ObjectColor.BLACK))); + } + + public GhostlyVisit(UUID ownerId) { + super(ownerId, 76, "Ghostly Visit", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{2}{B}"); + this.expansionSetCode = "PTK"; + + // Destroy target nonblack creature. + this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + } + + public GhostlyVisit(final GhostlyVisit card) { + super(card); + } + + @Override + public GhostlyVisit copy() { + return new GhostlyVisit(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/GuanYus1000LiMarch.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/GuanYus1000LiMarch.java new file mode 100644 index 00000000000..8f6b260b422 --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/GuanYus1000LiMarch.java @@ -0,0 +1,52 @@ +/* + * 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.portalthreekingdoms; + +import java.util.UUID; + +/** + * + * @author LoneFox + */ +public class GuanYus1000LiMarch extends mage.sets.masterseditioniii.GuanYus1000LiMarch { + + public GuanYus1000LiMarch(UUID ownerId) { + super(ownerId); + this.cardNumber = 7; + this.expansionSetCode = "PTK"; + } + + public GuanYus1000LiMarch(final GuanYus1000LiMarch card) { + super(card); + } + + @Override + public GuanYus1000LiMarch copy() { + return new GuanYus1000LiMarch(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/HuntingCheetah.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/HuntingCheetah.java new file mode 100644 index 00000000000..b7df3c83fbf --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/HuntingCheetah.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.portalthreekingdoms; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.DealsDamageToOpponentTriggeredAbility; +import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author LoneFox + */ +public class HuntingCheetah extends CardImpl { + + private static final FilterCard filter = new FilterCard("Forest card"); + + static { + filter.add(new SubtypePredicate("Forest")); + } + + public HuntingCheetah(UUID ownerId) { + super(ownerId, 138, "Hunting Cheetah", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{G}"); + this.expansionSetCode = "PTK"; + this.subtype.add("Cat"); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Whenever Hunting Cheetah deals damage to an opponent, you may search your library for a Forest card, reveal that card, put it into your hand, then shuffle your library. + this.addAbility(new DealsDamageToOpponentTriggeredAbility(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filter), true), true)); + } + + public HuntingCheetah(final HuntingCheetah card) { + super(card); + } + + @Override + public HuntingCheetah copy() { + return new HuntingCheetah(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/LiuBeiLordOfShu.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/LiuBeiLordOfShu.java new file mode 100644 index 00000000000..104fa35252f --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/LiuBeiLordOfShu.java @@ -0,0 +1,85 @@ +/* + * 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.portalthreekingdoms; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.keyword.HorsemanshipAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.NamePredicate; + +/** + * + * @author LoneFox + */ +public class LiuBeiLordOfShu extends CardImpl { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent(); + + static { + filter.add(Predicates.or(new NamePredicate("Guan Yu, Sainted Warrior"), + new NamePredicate("Zhang Fei, Fierce Warrior"))); + } + + public LiuBeiLordOfShu(UUID ownerId) { + super(ownerId, 11, "Liu Bei, Lord of Shu", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{W}{W}"); + this.expansionSetCode = "PTK"; + this.supertype.add("Legendary"); + this.subtype.add("Human"); + this.subtype.add("Soldier"); + this.power = new MageInt(2); + this.toughness = new MageInt(4); + + // Horsemanship + this.addAbility(HorsemanshipAbility.getInstance()); + // Liu Bei, Lord of Shu gets +2/+2 as long as you control a permanent named Guan Yu, Sainted Warrior or a permanent named Zhang Fei, Fierce Warrior. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect( + new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield), + new PermanentsOnTheBattlefieldCondition(filter), + "{this} gets +2/+2 as long as you control a permanent named Guan Yu, Sainted Warrior or a permanent named Zhang Fei, Fierce Warrior"))); + } + + public LiuBeiLordOfShu(final LiuBeiLordOfShu card) { + super(card); + } + + @Override + public LiuBeiLordOfShu copy() { + return new LiuBeiLordOfShu(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/MysticDenial.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/MysticDenial.java new file mode 100644 index 00000000000..242b23636e8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/MysticDenial.java @@ -0,0 +1,52 @@ +/* + * 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.portalthreekingdoms; + +import java.util.UUID; + +/** + * + * @author LoneFox + */ +public class MysticDenial extends mage.sets.portal.MysticDenial { + + public MysticDenial(UUID ownerId) { + super(ownerId); + this.cardNumber = 49; + this.expansionSetCode = "PTK"; + } + + public MysticDenial(final MysticDenial card) { + super(card); + } + + @Override + public MysticDenial copy() { + return new MysticDenial(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/PoisonArrow.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/PoisonArrow.java new file mode 100644 index 00000000000..a2c2617a16f --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/PoisonArrow.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.portalthreekingdoms; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + */ +public class PoisonArrow extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nonblack creature"); + + static { + filter.add(Predicates.not(new ColorPredicate(ObjectColor.BLACK))); + } + + public PoisonArrow(UUID ownerId) { + super(ownerId, 80, "Poison Arrow", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{4}{B}{B}"); + this.expansionSetCode = "PTK"; + + // Destroy target nonblack creature. You gain 3 life. + this.getSpellAbility().addEffect(new DestroyTargetEffect()); + this.getSpellAbility().addEffect(new GainLifeEffect(3)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + } + + public PoisonArrow(final PoisonArrow card) { + super(card); + } + + @Override + public PoisonArrow copy() { + return new PoisonArrow(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/ReturnToBattle.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/ReturnToBattle.java new file mode 100644 index 00000000000..b383044698b --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/ReturnToBattle.java @@ -0,0 +1,61 @@ +/* + * 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.portalthreekingdoms; + +import java.util.UUID; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterCreatureCard; +import mage.target.common.TargetCardInYourGraveyard; + +/** + * + * @author LoneFox + */ +public class ReturnToBattle extends CardImpl { + + public ReturnToBattle(UUID ownerId) { + super(ownerId, 81, "Return to Battle", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{B}"); + this.expansionSetCode = "PTK"; + + // Return target creature card from your graveyard to your hand. + this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()); + this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(new FilterCreatureCard("creature card from your graveyard"))); + } + + public ReturnToBattle(final ReturnToBattle card) { + super(card); + } + + @Override + public ReturnToBattle copy() { + return new ReturnToBattle(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/RidingRedHare.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/RidingRedHare.java new file mode 100644 index 00000000000..3a946867abc --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/RidingRedHare.java @@ -0,0 +1,69 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.portalthreekingdoms; + +import java.util.UUID; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.HorsemanshipAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + */ +public class RidingRedHare extends CardImpl { + + public RidingRedHare(UUID ownerId) { + super(ownerId, 18, "Riding Red Hare", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{2}{W}"); + this.expansionSetCode = "PTK"; + + // Target creature gets +3/+3 and gains horsemanship until end of turn. + Effect effect = new BoostTargetEffect(3, 3, Duration.EndOfTurn); + effect.setText("Target creature gets +3/+3"); + this.getSpellAbility().addEffect(effect); + effect = new GainAbilityTargetEffect(HorsemanshipAbility.getInstance(), Duration.EndOfTurn); + effect.setText("and gains horsemanship until end of turn"); + this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + public RidingRedHare(final RidingRedHare card) { + super(card); + } + + @Override + public RidingRedHare copy() { + return new RidingRedHare(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/RidingTheDiluHorse.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/RidingTheDiluHorse.java new file mode 100644 index 00000000000..12887868cab --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/RidingTheDiluHorse.java @@ -0,0 +1,54 @@ +/* + * 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.portalthreekingdoms; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LoneFox + */ +public class RidingTheDiluHorse extends mage.sets.masterseditioniii.RidingTheDiluHorse { + + public RidingTheDiluHorse(UUID ownerId) { + super(ownerId); + this.cardNumber = 144; + this.expansionSetCode = "PTK"; + this.rarity = Rarity.RARE; + } + + public RidingTheDiluHorse(final RidingTheDiluHorse card) { + super(card); + } + + @Override + public RidingTheDiluHorse copy() { + return new RidingTheDiluHorse(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/RockslideAmbush.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/RockslideAmbush.java new file mode 100644 index 00000000000..528a5f5016e --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/RockslideAmbush.java @@ -0,0 +1,68 @@ +/* + * 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.portalthreekingdoms; + +import java.util.UUID; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + */ +public class RockslideAmbush extends CardImpl { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent("Mountain you control"); + + static { + filter.add(new SubtypePredicate("Mountain")); + } + + public RockslideAmbush(UUID ownerId) { + super(ownerId, 121, "Rockslide Ambush", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{1}{R}"); + this.expansionSetCode = "PTK"; + + // Rockslide Ambush deals damage to target creature equal to the number of Mountains you control. + this.getSpellAbility().addEffect(new DamageTargetEffect(new PermanentsOnBattlefieldCount(filter))); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + public RockslideAmbush(final RockslideAmbush card) { + super(card); + } + + @Override + public RockslideAmbush copy() { + return new RockslideAmbush(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/ShuGrainCaravan.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/ShuGrainCaravan.java new file mode 100644 index 00000000000..965843b0092 --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/ShuGrainCaravan.java @@ -0,0 +1,64 @@ +/* + * 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.portalthreekingdoms; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author LoneFox + */ +public class ShuGrainCaravan extends CardImpl { + + public ShuGrainCaravan(UUID ownerId) { + super(ownerId, 26, "Shu Grain Caravan", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{W}"); + this.expansionSetCode = "PTK"; + this.subtype.add("Human"); + this.subtype.add("Soldier"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // When Shu Grain Caravan enters the battlefield, you gain 2 life. + this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(2))); + } + + public ShuGrainCaravan(final ShuGrainCaravan card) { + super(card); + } + + @Override + public ShuGrainCaravan copy() { + return new ShuGrainCaravan(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/ShuSoldierFarmers.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/ShuSoldierFarmers.java new file mode 100644 index 00000000000..d039e4d206a --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/ShuSoldierFarmers.java @@ -0,0 +1,64 @@ +/* + * 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.portalthreekingdoms; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author LoneFox + */ +public class ShuSoldierFarmers extends CardImpl { + + public ShuSoldierFarmers(UUID ownerId) { + super(ownerId, 27, "Shu Soldier-Farmers", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{4}{W}"); + this.expansionSetCode = "PTK"; + this.subtype.add("Human"); + this.subtype.add("Soldier"); + this.power = new MageInt(2); + this.toughness = new MageInt(4); + + // When Shu Soldier-Farmers enters the battlefield, you gain 4 life. + this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(4))); + } + + public ShuSoldierFarmers(final ShuSoldierFarmers card) { + super(card); + } + + @Override + public ShuSoldierFarmers copy() { + return new ShuSoldierFarmers(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/SimaYiWeiFieldMarshal.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/SimaYiWeiFieldMarshal.java new file mode 100644 index 00000000000..1080daa8204 --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/SimaYiWeiFieldMarshal.java @@ -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.sets.portalthreekingdoms; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.common.continuous.SetPowerSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; + +/** + * + * @author LoneFox + */ +public class SimaYiWeiFieldMarshal extends CardImpl { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent("Swamps you control"); + + static{ + filter.add(new SubtypePredicate("Swamp")); + } + + public SimaYiWeiFieldMarshal(UUID ownerId) { + super(ownerId, 82, "Sima Yi, Wei Field Marshal", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{5}{B}"); + this.expansionSetCode = "PTK"; + this.supertype.add("Legendary"); + this.subtype.add("Human"); + this.subtype.add("Soldier"); + this.power = new MageInt(0); + this.toughness = new MageInt(4); + + // Sima Yi, Wei Field Marshal's power is equal to the number of Swamps you control. + this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerSourceEffect(new PermanentsOnBattlefieldCount(filter), Duration.EndOfGame))); } + + public SimaYiWeiFieldMarshal(final SimaYiWeiFieldMarshal card) { + super(card); + } + + @Override + public SimaYiWeiFieldMarshal copy() { + return new SimaYiWeiFieldMarshal(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/SpringOfEternalPeace.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/SpringOfEternalPeace.java new file mode 100644 index 00000000000..c088936511b --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/SpringOfEternalPeace.java @@ -0,0 +1,58 @@ +/* + * 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.portalthreekingdoms; + +import java.util.UUID; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author LoneFox + */ +public class SpringOfEternalPeace extends CardImpl { + + public SpringOfEternalPeace(UUID ownerId) { + super(ownerId, 148, "Spring of Eternal Peace", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{3}{G}{G}"); + this.expansionSetCode = "PTK"; + + // You gain 8 life. + this.getSpellAbility().addEffect(new GainLifeEffect(8)); + } + + public SpringOfEternalPeace(final SpringOfEternalPeace card) { + super(card); + } + + @Override + public SpringOfEternalPeace copy() { + return new SpringOfEternalPeace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/StolenGrain.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/StolenGrain.java new file mode 100644 index 00000000000..794a7c58930 --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/StolenGrain.java @@ -0,0 +1,52 @@ +/* + * 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.portalthreekingdoms; + +import java.util.UUID; + +/** + * + * @author LoneFox + */ +public class StolenGrain extends mage.sets.masterseditioniii.StolenGrain { + + public StolenGrain(UUID ownerId) { + super(ownerId); + this.cardNumber = 83; + this.expansionSetCode = "PTK"; + } + + public StolenGrain(final StolenGrain card) { + super(card); + } + + @Override + public StolenGrain copy() { + return new StolenGrain(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/SunCeYoungConquerer.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/SunCeYoungConquerer.java new file mode 100644 index 00000000000..da5fcfdebcf --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/SunCeYoungConquerer.java @@ -0,0 +1,54 @@ +/* + * 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.portalthreekingdoms; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LoneFox + */ +public class SunCeYoungConquerer extends mage.sets.masterseditioniii.SunCeYoungConquerer { + + public SunCeYoungConquerer(UUID ownerId) { + super(ownerId); + this.cardNumber = 55; + this.expansionSetCode = "PTK"; + this.rarity = Rarity.RARE; + } + + public SunCeYoungConquerer(final SunCeYoungConquerer card) { + super(card); + } + + @Override + public SunCeYoungConquerer copy() { + return new SunCeYoungConquerer(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/TripWire.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/TripWire.java new file mode 100644 index 00000000000..ee30216aae1 --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/TripWire.java @@ -0,0 +1,54 @@ +/* + * 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.portalthreekingdoms; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LoneFox + */ +public class TripWire extends mage.sets.masterseditioniii.TripWire { + + public TripWire(UUID ownerId) { + super(ownerId); + this.cardNumber = 156; + this.expansionSetCode = "PTK"; + this.rarity = Rarity.UNCOMMON; + } + + public TripWire(final TripWire card) { + super(card); + } + + @Override + public TripWire copy() { + return new TripWire(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/VirtuousCharge.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/VirtuousCharge.java new file mode 100644 index 00000000000..ba2a99e8a7d --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/VirtuousCharge.java @@ -0,0 +1,59 @@ +/* + * 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.portalthreekingdoms; + +import java.util.UUID; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; + +/** + * + * @author LoneFox + */ +public class VirtuousCharge extends CardImpl { + + public VirtuousCharge(UUID ownerId) { + super(ownerId, 29, "Virtuous Charge", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{2}{W}"); + this.expansionSetCode = "PTK"; + + // Creatures you control get +1/+1 until end of turn. + this.getSpellAbility().addEffect(new BoostControlledEffect(1, 1, Duration.EndOfTurn)); + } + + public VirtuousCharge(final VirtuousCharge card) { + super(card); + } + + @Override + public VirtuousCharge copy() { + return new VirtuousCharge(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/WieldingTheGreenDragon.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/WieldingTheGreenDragon.java new file mode 100644 index 00000000000..9e6f56d4b96 --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/WieldingTheGreenDragon.java @@ -0,0 +1,61 @@ +/* + * 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.portalthreekingdoms; + +import java.util.UUID; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + */ +public class WieldingTheGreenDragon extends CardImpl { + + public WieldingTheGreenDragon(UUID ownerId) { + super(ownerId, 157, "Wielding the Green Dragon", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{1}{G}"); + this.expansionSetCode = "PTK"; + + // Target creature gets +4/+4 until end of turn. + this.getSpellAbility().addEffect(new BoostTargetEffect(4, 4, Duration.EndOfTurn)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + public WieldingTheGreenDragon(final WieldingTheGreenDragon card) { + super(card); + } + + @Override + public WieldingTheGreenDragon copy() { + return new WieldingTheGreenDragon(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/WuAdmiral.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/WuAdmiral.java new file mode 100644 index 00000000000..9d732edec3a --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/WuAdmiral.java @@ -0,0 +1,83 @@ +/* + * 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.portalthreekingdoms; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition.CountType; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.permanent.ControllerPredicate; + +/** + * + * @author LoneFox + */ +public class WuAdmiral extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent(); + + static { + filter.add(new SubtypePredicate("Island")); + filter.add(new ControllerPredicate(TargetController.OPPONENT)); + } + + public WuAdmiral(UUID ownerId) { + super(ownerId, 57, "Wu Admiral", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{4}{U}"); + this.expansionSetCode = "PTK"; + this.subtype.add("Human"); + this.subtype.add("Soldier"); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Wu Admiral gets +1/+1 as long as an opponent controls an Island. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect( + new BoostSourceEffect(1, 1, Duration.WhileOnBattlefield), + new PermanentsOnTheBattlefieldCondition(filter, CountType.MORE_THAN, 0, false), + "{this} gets +1/+1 as long as an opponent controls an Island"))); + } + + public WuAdmiral(final WuAdmiral card) { + super(card); + } + + @Override + public WuAdmiral copy() { + return new WuAdmiral(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/YellowScarvesTroops.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/YellowScarvesTroops.java new file mode 100644 index 00000000000..123664560a7 --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/YellowScarvesTroops.java @@ -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.portalthreekingdoms; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.CantBlockAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author LoneFox + */ +public class YellowScarvesTroops extends CardImpl { + + public YellowScarvesTroops(UUID ownerId) { + super(ownerId, 127, "Yellow Scarves Troops", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{R}"); + this.expansionSetCode = "PTK"; + this.subtype.add("Human"); + this.subtype.add("Soldier"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Yellow Scarves Troops can't block. + this.addAbility(new CantBlockAbility()); + } + + public YellowScarvesTroops(final YellowScarvesTroops card) { + super(card); + } + + @Override + public YellowScarvesTroops copy() { + return new YellowScarvesTroops(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/YoungWeiRecruits.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/YoungWeiRecruits.java new file mode 100644 index 00000000000..83bf0b49464 --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/YoungWeiRecruits.java @@ -0,0 +1,52 @@ +/* + * 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.portalthreekingdoms; + +import java.util.UUID; + +/** + * + * @author LoneFox + */ +public class YoungWeiRecruits extends mage.sets.masterseditioniii.YoungWeiRecruits { + + public YoungWeiRecruits(UUID ownerId) { + super(ownerId); + this.cardNumber = 94; + this.expansionSetCode = "PTK"; + } + + public YoungWeiRecruits(final YoungWeiRecruits card) { + super(card); + } + + @Override + public YoungWeiRecruits copy() { + return new YoungWeiRecruits(this); + } +} diff --git a/Mage.Sets/src/mage/sets/starter1999/Extinguish.java b/Mage.Sets/src/mage/sets/starter1999/Extinguish.java new file mode 100644 index 00000000000..50f758d1e78 --- /dev/null +++ b/Mage.Sets/src/mage/sets/starter1999/Extinguish.java @@ -0,0 +1,52 @@ +/* + * 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.starter1999; + +import java.util.UUID; + +/** + * + * @author LoneFox + */ +public class Extinguish extends mage.sets.portalsecondage.Extinguish { + + public Extinguish(UUID ownerId) { + super(ownerId); + this.cardNumber = 37; + this.expansionSetCode = "S99"; + } + + public Extinguish(final Extinguish card) { + super(card); + } + + @Override + public Extinguish copy() { + return new Extinguish(this); + } +} diff --git a/Mage/src/mage/abilities/keyword/EntwineAbility.java b/Mage/src/mage/abilities/keyword/EntwineAbility.java index 141fd25162b..8448463486c 100644 --- a/Mage/src/mage/abilities/keyword/EntwineAbility.java +++ b/Mage/src/mage/abilities/keyword/EntwineAbility.java @@ -90,6 +90,7 @@ public class EntwineAbility extends StaticAbility implements OptionalAdditionalM } } + @Override public boolean isActivated() { if (additionalCost != null) { return additionalCost.isActivated(); diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index 4ee90b73ca1..631b5614a3c 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -1033,8 +1033,10 @@ public abstract class PlayerImpl implements Player, Serializable { int bookmark = game.bookmarkState(); if (ability.activate(game, false)) { if (ability.resolve(game)) { - if (ability.isUndoPossible() && storedBookmark == -1 || storedBookmark > bookmark) { // e.g. usefull for undo Nykthos, Shrine to Nyx + if (ability.isUndoPossible() && (storedBookmark == -1 || storedBookmark > bookmark)) { // e.g. usefull for undo Nykthos, Shrine to Nyx setStoredBookmark(bookmark); + } else { + resetStoredBookmark(game); } return true; } @@ -1366,6 +1368,17 @@ public abstract class PlayerImpl implements Player, Serializable { //20091005 - 502.1 List phasedOut = game.getBattlefield().getPhasedOut(playerId); for (Permanent permanent : game.getBattlefield().getPhasedIn(playerId)) { + // 502.15i When a permanent phases out, any local enchantments or Equipment + // attached to that permanent phase out at the same time. This alternate way of + // phasing out is known as phasing out "indirectly." An enchantment or Equipment + // that phased out indirectly won't phase in by itself, but instead phases in + // along with the card it's attached to. + for (UUID attachmentId : permanent.getAttachments()) { + Permanent attachment = game.getPermanent(attachmentId); + if (attachment != null) { + attachment.phaseOut(game); + } + } permanent.phaseOut(game); } for (Permanent permanent : phasedOut) {