From 03e3be90d694ab2f93d09db2d0a90d09e412538e Mon Sep 17 00:00:00 2001 From: BetaSteward Date: Sat, 8 Jan 2011 23:54:32 -0500 Subject: [PATCH] draft stuff --- .../src/main/java/mage/client/MageFrame.java | 1371 +++++++++-------- .../java/mage/client/cards/DraftGrid.form | 29 + .../java/mage/client/cards/DraftGrid.java | 126 ++ .../java/mage/client/draft/DraftPane.java | 5 + .../java/mage/client/draft/DraftPanel.form | 50 +- .../java/mage/client/draft/DraftPanel.java | 68 +- .../main/java/mage/client/remote/Client.java | 24 +- .../main/java/mage/client/remote/Session.java | 24 +- .../java/mage/client/table/TablesPanel.java | 1 + .../src/mage/view/DraftClientMessage.java | 7 + Mage.Common/src/mage/view/DraftPickView.java | 10 +- Mage.Common/src/mage/view/DraftView.java | 3 +- Mage.Common/src/mage/view/RoundView.java | 3 +- .../src/mage/view/TournamentPlayerView.java | 4 +- Mage.Common/src/mage/view/TournamentView.java | 3 +- .../Mage.Draft.8PlayerBooster/pom.xml | 49 + .../src/mage/draft/BoosterDraft.java | 59 + Mage.Server.Plugins/pom.xml | 8 +- Mage.Server/config/config.xml | 3 + .../plugins/mage-draft-8playerbooster.jar | Bin 0 -> 2637 bytes Mage.Server/plugins/mage-player-ai.jar | Bin 28977 -> 29132 bytes Mage.Server/plugins/mage-player-human.jar | Bin 11295 -> 11430 bytes .../src/main/java/mage/server/Main.java | 4 + .../src/main/java/mage/server/Session.java | 4 + .../mage/server/game/DraftController.java | 9 +- .../java/mage/server/game/DraftSession.java | 4 +- .../mage/server/game/TableController.java | 20 +- .../src/main/java/mage/server/util/Config.xsd | 39 +- .../java/mage/server/util/ConfigSettings.java | 4 + .../main/xml-resources/jaxb/Config/Config.xsd | 9 + Mage/src/mage/game/draft/DraftImpl.java | 28 +- Mage/src/mage/game/draft/DraftOptions.java | 2 +- .../mage/game/events/PlayerQueryEvent.java | 7 +- .../game/events/PlayerQueryEventSource.java | 4 +- 34 files changed, 1238 insertions(+), 743 deletions(-) create mode 100644 Mage.Client/src/main/java/mage/client/cards/DraftGrid.form create mode 100644 Mage.Client/src/main/java/mage/client/cards/DraftGrid.java create mode 100644 Mage.Server.Plugins/Mage.Draft.8PlayerBooster/pom.xml create mode 100644 Mage.Server.Plugins/Mage.Draft.8PlayerBooster/src/mage/draft/BoosterDraft.java create mode 100644 Mage.Server/plugins/mage-draft-8playerbooster.jar diff --git a/Mage.Client/src/main/java/mage/client/MageFrame.java b/Mage.Client/src/main/java/mage/client/MageFrame.java index f141f9908d..100fcf6572 100644 --- a/Mage.Client/src/main/java/mage/client/MageFrame.java +++ b/Mage.Client/src/main/java/mage/client/MageFrame.java @@ -1,674 +1,697 @@ -/* -* 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. -*/ - -/* - * MageFrame.java - * - * Created on 15-Dec-2009, 9:11:37 PM - */ - -package mage.client; - -import mage.cards.Card; -import mage.cards.decks.Deck; -import mage.client.cards.CardsStorage; -import mage.client.components.MageComponents; -import mage.client.components.MageJDesktop; -import mage.client.components.MageRoundPane; -import mage.client.components.arcane.ManaSymbols; -import mage.client.constants.Constants.DeckEditorMode; -import mage.client.deckeditor.collection.viewer.CollectionViewerPane; -import mage.client.dialog.*; -import mage.client.plugins.impl.Plugins; -import mage.client.remote.Session; -import mage.client.util.EDTExceptionHandler; -import mage.client.util.gui.ArrowBuilder; -import mage.components.ImagePanel; -import mage.util.Logging; - -import javax.imageio.ImageIO; -import javax.swing.*; -import javax.swing.JToolBar.Separator; -import java.awt.*; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.UUID; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.prefs.Preferences; - -/** - * @author BetaSteward_at_googlemail.com - */ -public class MageFrame extends javax.swing.JFrame { - - private final static Logger logger = Logging.getLogger(MageFrame.class.getName()); - - private static Session session; - private ConnectDialog connectDialog; - private static CombatDialog combat; - private static PickNumberDialog pickNumber; - private static Preferences prefs = Preferences.userNodeForPackage(MageFrame.class); - private JLabel title; - private Rectangle titleRectangle; - - /** - * @return the session - */ - public static Session getSession() { - return session; - } - - public static JDesktopPane getDesktop() { - return desktopPane; - } - - public static Preferences getPreferences() { - return prefs; - } - - /** - * Creates new form MageFrame - */ - public MageFrame() { - - setTitle("Mage, version 0.5.1"); - - EDTExceptionHandler.registerExceptionHandler(); - addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - exitApp(); - } - }); - - try { - UIManager.put("desktop", new Color(0, 0, 0, 0)); - UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"); - //MageSynthStyleFactory f = new MageSynthStyleFactory(SynthLookAndFeel.getStyleFactory()); - //SynthLookAndFeel.setStyleFactory(f); - } catch (Exception ex) { - logger.log(Level.SEVERE, null, ex); - } - - Plugins.getInstance().loadPlugins(); - ManaSymbols.loadImages(); - - initComponents(); - setSize(1024, 768); - this.setExtendedState(JFrame.MAXIMIZED_BOTH); - - session = new Session(this); - connectDialog = new ConnectDialog(); - combat = new CombatDialog(); - pickNumber = new PickNumberDialog(); - desktopPane.add(connectDialog, JLayeredPane.POPUP_LAYER); - desktopPane.add(combat, JLayeredPane.POPUP_LAYER); - combat.hideDialog(); - desktopPane.add(pickNumber, JLayeredPane.POPUP_LAYER); - session.getUI().addComponent(MageComponents.DESKTOP_PANE, desktopPane); - - addTooltipContainer(); - setBackground(); - addMageLabel(); - setAppIcon(); - - desktopPane.add(ArrowBuilder.getArrowsPanel(), 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(); - backgroundPane.setSize(width, height); - JPanel arrowsPanel = ArrowBuilder.getArrowsPanelRef(); - if (arrowsPanel != null) arrowsPanel.setSize(width, height); - if (title != null) { - //title.setBorder(BorderFactory.createLineBorder(Color.red)); - title.setBounds((int) (width - titleRectangle.getWidth()) / 2, (int) (height - titleRectangle.getHeight()) / 2, titleRectangle.width, titleRectangle.height); - } - } - }); - - //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.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); - btnDownloadSymbols.setFocusable(false); - btnDownloadSymbols.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); - btnDownloadSymbols.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); - btnDownloadSymbols.addActionListener(new java.awt.event.ActionListener() { - 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.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); - btnDownload.setFocusable(false); - btnDownload.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); - btnDownload.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); - btnDownload.addActionListener(new java.awt.event.ActionListener() { - 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); - } - - session.getUI().addButton(MageComponents.TABLES_MENU_BUTTON, btnGames); - - SwingUtilities.invokeLater(new Runnable() { - public void run() { - if (autoConnect()) - enableButtons(); - else - disableButtons(); - } - }); - } - - private void addTooltipContainer() { - final JEditorPane cardInfoPane = (JEditorPane) Plugins.getInstance().getCardInfoPane(); - cardInfoPane.setSize(320, 201); - cardInfoPane.setLocation(40, 40); - cardInfoPane.setBackground(new Color(0, 0, 0, 0)); - - MageRoundPane popupContainer = new MageRoundPane(); - popupContainer.setLayout(null); - - popupContainer.add(cardInfoPane); - popupContainer.setVisible(false); - popupContainer.setBounds(0, 0, 320 + 80, 201 + 80); - - desktopPane.add(popupContainer, JLayeredPane.POPUP_LAYER); - - session.getUI().addComponent(MageComponents.CARD_INFO_PANE, cardInfoPane); - session.getUI().addComponent(MageComponents.POPUP_CONTAINER, popupContainer); - } - - private void setBackground() { - String filename = "/background.jpg"; - try { - if (Plugins.getInstance().isThemePluginLoaded()) { - Map ui = new HashMap(); - backgroundPane = (ImagePanel) Plugins.getInstance().updateTablePanel(ui); - } else { - InputStream is = this.getClass().getResourceAsStream(filename); - BufferedImage background = ImageIO.read(is); - backgroundPane = new ImagePanel(background, ImagePanel.SCALED); - } - backgroundPane.setSize(1024, 768); - desktopPane.add(backgroundPane, JLayeredPane.DEFAULT_LAYER); - } catch (IOException e) { - e.printStackTrace(); - } - } - - private void addMageLabel() { - String filename = "/label-mage.png"; - try { - InputStream is = this.getClass().getResourceAsStream(filename); - - float ratio = 1179.0f / 678.0f; - titleRectangle = new Rectangle(640, (int) (640 / ratio)); - if (is != null) { - BufferedImage image = ImageIO.read(is); - //ImageIcon resized = new ImageIcon(image.getScaledInstance(titleRectangle.width, titleRectangle.height, java.awt.Image.SCALE_SMOOTH)); - title = new JLabel(); - title.setIcon(new ImageIcon(image)); - backgroundPane.setLayout(null); - backgroundPane.add(title); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - private void setAppIcon() { - String filename = "/icon-mage.png"; - try { - InputStream is = this.getClass().getResourceAsStream(filename); - - if (is != null) { - BufferedImage image = ImageIO.read(is); - setIconImage(image); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - private void btnImagesActionPerformed(java.awt.event.ActionEvent evt) { - Plugins.getInstance().downloadImage(new HashSet(CardsStorage.getAllCards())); - } - - private void btnSymbolsActionPerformed(java.awt.event.ActionEvent evt) { - if (JOptionPane.showConfirmDialog(null, "Do you want to download mana symbols?") == JOptionPane.OK_OPTION) { - Plugins.getInstance().downloadSymbols(); - } - } - - public void showGame(UUID gameId, UUID playerId) { - this.tablesPane.hideTables(); - this.tablesPane.setVisible(false); - this.gamePane.setVisible(true); - this.gamePane.showGame(gameId, playerId); - } - - public void watchGame(UUID gameId) { - this.tablesPane.hideTables(); - this.tablesPane.setVisible(false); - this.gamePane.setVisible(true); - this.gamePane.watchGame(gameId); - } - - public void replayGame() { - this.tablesPane.hideTables(); - this.tablesPane.setVisible(false); - this.gamePane.setVisible(true); - this.gamePane.replayGame(); - } - - public static boolean connect(String userName, String serverName, int port) { - return session.connect(userName, serverName, port); - } - - public boolean autoConnect() { - boolean autoConnect = Boolean.parseBoolean(prefs.get("autoConnect", "false")); - if (autoConnect) { - String userName = prefs.get("userName", ""); - String server = prefs.get("serverAddress", ""); - int port = Integer.parseInt(prefs.get("serverPort", "")); - try { - setCursor(new Cursor(Cursor.WAIT_CURSOR)); - if (MageFrame.connect(userName, server, port)) { - return true; - } else { - JOptionPane.showMessageDialog(rootPane, "Unable to connect to server"); - } - } finally { - setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - } - } - return false; - } - - /** - * 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(); - tablesPane = new mage.client.table.TablesPane(); - gamePane = new mage.client.game.GamePane(); - deckEditorPane = new mage.client.deckeditor.DeckEditorPane(); - collectionViewerPane = new CollectionViewerPane(); - mageToolbar = new javax.swing.JToolBar(); - btnConnect = new javax.swing.JButton(); - jSeparator5 = new javax.swing.JToolBar.Separator(); - btnGames = new javax.swing.JButton(); - jSeparator4 = new javax.swing.JToolBar.Separator(); - btnDeckEditor = new javax.swing.JButton(); - jSeparator3 = new javax.swing.JToolBar.Separator(); - btnPreferences = new javax.swing.JButton(); - jSeparator2 = new javax.swing.JToolBar.Separator(); - btnAbout = new javax.swing.JButton(); - jSeparator1 = new javax.swing.JToolBar.Separator(); - btnExit = new javax.swing.JButton(); - lblStatus = new javax.swing.JLabel(); - jSeparator6 = new javax.swing.JToolBar.Separator(); - btnCollectionViewer = new JButton(); - - setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); - //setMinimumSize(new java.awt.Dimension(1024, 768)); - - tablesPane.setBounds(20, 10, 560, 440); - desktopPane.add(tablesPane, javax.swing.JLayeredPane.DEFAULT_LAYER); - try { - tablesPane.setMaximum(true); - } catch (java.beans.PropertyVetoException e1) { - e1.printStackTrace(); - } - gamePane.setBounds(20, 30, -1, -1); - desktopPane.add(gamePane, javax.swing.JLayeredPane.DEFAULT_LAYER); - try { - gamePane.setMaximum(true); - } catch (java.beans.PropertyVetoException e1) { - e1.printStackTrace(); - } - deckEditorPane.setBounds(140, 50, -1, -1); - desktopPane.add(deckEditorPane, javax.swing.JLayeredPane.DEFAULT_LAYER); - try { - deckEditorPane.setMaximum(true); - } catch (java.beans.PropertyVetoException e1) { - e1.printStackTrace(); - } - collectionViewerPane.setBounds(140, 50, -1, -1); - desktopPane.add(collectionViewerPane, javax.swing.JLayeredPane.DEFAULT_LAYER); - try { - collectionViewerPane.setMaximum(true); - } catch (java.beans.PropertyVetoException e1) { - e1.printStackTrace(); - } - - mageToolbar.setFloatable(false); - mageToolbar.setRollover(true); - - btnConnect.setText("Connect"); - btnConnect.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); - 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(jSeparator4); - - btnGames.setText("Tables"); - btnGames.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); - 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(jSeparator3); - - btnDeckEditor.setText("Deck Editor"); - btnDeckEditor.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); - 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.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); - 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(jSeparator6); - - btnPreferences.setText("Preferences"); - btnPreferences.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); - 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(jSeparator5); - - btnAbout.setText("About"); - btnAbout.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); - 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(jSeparator1); - - btnExit.setText("Exit"); - btnExit.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); - 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); - - lblStatus.setText("Not connected "); - mageToolbar.add(Box.createHorizontalGlue()); - 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, javax.swing.GroupLayout.DEFAULT_SIZE, 1144, Short.MAX_VALUE) - .addComponent(mageToolbar, javax.swing.GroupLayout.DEFAULT_SIZE, 1144, 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, javax.swing.GroupLayout.DEFAULT_SIZE, 880, Short.MAX_VALUE)) - ); - - pack(); - }// //GEN-END:initComponents - - private void btnDeckEditorActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDeckEditorActionPerformed - this.gamePane.setVisible(false); - this.tablesPane.setVisible(false); - this.collectionViewerPane.setVisible(false); - showDeckEditor(DeckEditorMode.Constructed, null, null); - }//GEN-LAST:event_btnDeckEditorActionPerformed - - private void btnCollectionViewerActionPerformed(java.awt.event.ActionEvent evt) { - this.gamePane.setVisible(false); - this.tablesPane.setVisible(false); - this.deckEditorPane.setVisible(false); - showCollectionViewer(); - } - - private void btnPreferencesActionPerformed(java.awt.event.ActionEvent evt) { - PhasesDialog.main(new String[]{}); - } - - private void btnGamesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnGamesActionPerformed - this.gamePane.setVisible(false); - this.deckEditorPane.setVisible(false); - this.collectionViewerPane.setVisible(false); - this.tablesPane.setVisible(true); - this.tablesPane.showTables(); - }//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 (session.isConnected()) { - if (JOptionPane.showConfirmDialog(this, "Are you sure you want to disconnect?", "Confirm disconnect", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { - session.disconnect(); - } - } else { - connectDialog.showDialog(); - } - }//GEN-LAST:event_btnConnectActionPerformed - - private void btnAboutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAboutActionPerformed - AboutDialog aboutDialog = new AboutDialog(); - desktopPane.add(aboutDialog); - aboutDialog.showDialog(); - }//GEN-LAST:event_btnAboutActionPerformed - - public void exitApp() { - session.disconnect(); - 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); - this.tablesPane.setVisible(false); - this.gamePane.setVisible(false); - this.deckEditorPane.setVisible(false); - this.collectionViewerPane.setVisible(false); - } - - public void showDeckEditor(DeckEditorMode mode, Deck deck, UUID tableId) { - this.deckEditorPane.setVisible(true); - this.deckEditorPane.show(mode, deck, tableId); - } - - public void showCollectionViewer() { - this.collectionViewerPane.setVisible(true); - } - - public static CombatDialog getCombatDialog() { - return combat; - } - - public static PickNumberDialog getPickNumberDialog() { - return pickNumber; - } - - 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.5.1", 560, 460); - } - - /** - * @param args the command line arguments - */ - public static void main(String args[]) { - final SplashScreen splash = SplashScreen.getSplashScreen(); - if (splash != null) { - Graphics2D g = splash.createGraphics(); - if (g != null) { - renderSplashFrame(g); - } - splash.update(); - } - - Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { - public void uncaughtException(Thread t, Throwable e) { - logger.log(Level.SEVERE, null, e); - } - }); - SwingUtilities.invokeLater(new Runnable() { - public void run() { - new MageFrame().setVisible(true); - } - }); - } - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton btnAbout; - private javax.swing.JButton btnConnect; - private javax.swing.JButton btnDeckEditor; - private javax.swing.JButton btnCollectionViewer; - private javax.swing.JButton btnPreferences; - private javax.swing.JButton btnExit; - private javax.swing.JButton btnGames; - private mage.client.deckeditor.DeckEditorPane deckEditorPane; - private CollectionViewerPane collectionViewerPane; - private static MageJDesktop desktopPane; - private mage.client.game.GamePane gamePane; - 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.JLabel lblStatus; - private javax.swing.JToolBar mageToolbar; - private mage.client.table.TablesPane tablesPane; - // End of variables declaration//GEN-END:variables - - private static final long serialVersionUID = -9104885239063142218L; - private ImagePanel backgroundPane; - - public void setStatusText(String status) { - this.lblStatus.setText(status); - } -} +/* +* 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. +*/ + +/* + * MageFrame.java + * + * Created on 15-Dec-2009, 9:11:37 PM + */ + +package mage.client; + +import mage.cards.Card; +import mage.cards.decks.Deck; +import mage.client.cards.CardsStorage; +import mage.client.components.MageComponents; +import mage.client.components.MageJDesktop; +import mage.client.components.MageRoundPane; +import mage.client.components.arcane.ManaSymbols; +import mage.client.constants.Constants.DeckEditorMode; +import mage.client.deckeditor.collection.viewer.CollectionViewerPane; +import mage.client.dialog.*; +import mage.client.plugins.impl.Plugins; +import mage.client.remote.Session; +import mage.client.util.EDTExceptionHandler; +import mage.client.util.gui.ArrowBuilder; +import mage.components.ImagePanel; +import mage.util.Logging; + +import javax.imageio.ImageIO; +import javax.swing.*; +import javax.swing.JToolBar.Separator; +import java.awt.*; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.prefs.Preferences; +import mage.client.draft.DraftPane; + +/** + * @author BetaSteward_at_googlemail.com + */ +public class MageFrame extends javax.swing.JFrame { + + private final static Logger logger = Logging.getLogger(MageFrame.class.getName()); + + private static Session session; + private ConnectDialog connectDialog; + private static CombatDialog combat; + private static PickNumberDialog pickNumber; + private static Preferences prefs = Preferences.userNodeForPackage(MageFrame.class); + private JLabel title; + private Rectangle titleRectangle; + + /** + * @return the session + */ + public static Session getSession() { + return session; + } + + public static JDesktopPane getDesktop() { + return desktopPane; + } + + public static Preferences getPreferences() { + return prefs; + } + + /** + * Creates new form MageFrame + */ + public MageFrame() { + + setTitle("Mage, version 0.5.1"); + + EDTExceptionHandler.registerExceptionHandler(); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + exitApp(); + } + }); + + try { + UIManager.put("desktop", new Color(0, 0, 0, 0)); + UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"); + //MageSynthStyleFactory f = new MageSynthStyleFactory(SynthLookAndFeel.getStyleFactory()); + //SynthLookAndFeel.setStyleFactory(f); + } catch (Exception ex) { + logger.log(Level.SEVERE, null, ex); + } + + Plugins.getInstance().loadPlugins(); + ManaSymbols.loadImages(); + + initComponents(); + setSize(1024, 768); + this.setExtendedState(JFrame.MAXIMIZED_BOTH); + + session = new Session(this); + connectDialog = new ConnectDialog(); + combat = new CombatDialog(); + pickNumber = new PickNumberDialog(); + desktopPane.add(connectDialog, JLayeredPane.POPUP_LAYER); + desktopPane.add(combat, JLayeredPane.POPUP_LAYER); + combat.hideDialog(); + desktopPane.add(pickNumber, JLayeredPane.POPUP_LAYER); + session.getUI().addComponent(MageComponents.DESKTOP_PANE, desktopPane); + + draftPane = new DraftPane(); + desktopPane.add(draftPane, javax.swing.JLayeredPane.DEFAULT_LAYER); + try { + draftPane.setMaximum(true); + } catch (java.beans.PropertyVetoException e1) { + e1.printStackTrace(); + } + + addTooltipContainer(); + setBackground(); + addMageLabel(); + setAppIcon(); + + desktopPane.add(ArrowBuilder.getArrowsPanel(), 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(); + backgroundPane.setSize(width, height); + JPanel arrowsPanel = ArrowBuilder.getArrowsPanelRef(); + if (arrowsPanel != null) arrowsPanel.setSize(width, height); + if (title != null) { + //title.setBorder(BorderFactory.createLineBorder(Color.red)); + title.setBounds((int) (width - titleRectangle.getWidth()) / 2, (int) (height - titleRectangle.getHeight()) / 2, titleRectangle.width, titleRectangle.height); + } + } + }); + + //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.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); + btnDownloadSymbols.setFocusable(false); + btnDownloadSymbols.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + btnDownloadSymbols.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + btnDownloadSymbols.addActionListener(new java.awt.event.ActionListener() { + 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.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); + btnDownload.setFocusable(false); + btnDownload.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + btnDownload.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + btnDownload.addActionListener(new java.awt.event.ActionListener() { + 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); + } + + session.getUI().addButton(MageComponents.TABLES_MENU_BUTTON, btnGames); + + SwingUtilities.invokeLater(new Runnable() { + public void run() { + if (autoConnect()) + enableButtons(); + else + disableButtons(); + } + }); + } + + private void addTooltipContainer() { + final JEditorPane cardInfoPane = (JEditorPane) Plugins.getInstance().getCardInfoPane(); + cardInfoPane.setSize(320, 201); + cardInfoPane.setLocation(40, 40); + cardInfoPane.setBackground(new Color(0, 0, 0, 0)); + + MageRoundPane popupContainer = new MageRoundPane(); + popupContainer.setLayout(null); + + popupContainer.add(cardInfoPane); + popupContainer.setVisible(false); + popupContainer.setBounds(0, 0, 320 + 80, 201 + 80); + + desktopPane.add(popupContainer, JLayeredPane.POPUP_LAYER); + + session.getUI().addComponent(MageComponents.CARD_INFO_PANE, cardInfoPane); + session.getUI().addComponent(MageComponents.POPUP_CONTAINER, popupContainer); + } + + private void setBackground() { + String filename = "/background.jpg"; + try { + if (Plugins.getInstance().isThemePluginLoaded()) { + Map ui = new HashMap(); + backgroundPane = (ImagePanel) Plugins.getInstance().updateTablePanel(ui); + } else { + InputStream is = this.getClass().getResourceAsStream(filename); + BufferedImage background = ImageIO.read(is); + backgroundPane = new ImagePanel(background, ImagePanel.SCALED); + } + backgroundPane.setSize(1024, 768); + desktopPane.add(backgroundPane, JLayeredPane.DEFAULT_LAYER); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void addMageLabel() { + String filename = "/label-mage.png"; + try { + InputStream is = this.getClass().getResourceAsStream(filename); + + float ratio = 1179.0f / 678.0f; + titleRectangle = new Rectangle(640, (int) (640 / ratio)); + if (is != null) { + BufferedImage image = ImageIO.read(is); + //ImageIcon resized = new ImageIcon(image.getScaledInstance(titleRectangle.width, titleRectangle.height, java.awt.Image.SCALE_SMOOTH)); + title = new JLabel(); + title.setIcon(new ImageIcon(image)); + backgroundPane.setLayout(null); + backgroundPane.add(title); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void setAppIcon() { + String filename = "/icon-mage.png"; + try { + InputStream is = this.getClass().getResourceAsStream(filename); + + if (is != null) { + BufferedImage image = ImageIO.read(is); + setIconImage(image); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void btnImagesActionPerformed(java.awt.event.ActionEvent evt) { + Plugins.getInstance().downloadImage(new HashSet(CardsStorage.getAllCards())); + } + + private void btnSymbolsActionPerformed(java.awt.event.ActionEvent evt) { + if (JOptionPane.showConfirmDialog(null, "Do you want to download mana symbols?") == JOptionPane.OK_OPTION) { + Plugins.getInstance().downloadSymbols(); + } + } + + public void showGame(UUID gameId, UUID playerId) { + this.tablesPane.hideTables(); + this.tablesPane.setVisible(false); + this.draftPane.setVisible(false); + this.gamePane.setVisible(true); + this.gamePane.showGame(gameId, playerId); + } + + public void watchGame(UUID gameId) { + this.tablesPane.hideTables(); + this.tablesPane.setVisible(false); + this.draftPane.setVisible(false); + this.gamePane.setVisible(true); + this.gamePane.watchGame(gameId); + } + + public void replayGame() { + this.tablesPane.hideTables(); + this.tablesPane.setVisible(false); + this.draftPane.setVisible(false); + this.gamePane.setVisible(true); + this.gamePane.replayGame(); + } + + public void showDraft(UUID draftId) { + this.tablesPane.hideTables(); + this.tablesPane.setVisible(false); + this.gamePane.setVisible(false); + this.draftPane.setVisible(true); + this.draftPane.showDraft(draftId); + } + + public static boolean connect(String userName, String serverName, int port) { + return session.connect(userName, serverName, port); + } + + public boolean autoConnect() { + boolean autoConnect = Boolean.parseBoolean(prefs.get("autoConnect", "false")); + if (autoConnect) { + String userName = prefs.get("userName", ""); + String server = prefs.get("serverAddress", ""); + int port = Integer.parseInt(prefs.get("serverPort", "")); + try { + setCursor(new Cursor(Cursor.WAIT_CURSOR)); + if (MageFrame.connect(userName, server, port)) { + return true; + } else { + JOptionPane.showMessageDialog(rootPane, "Unable to connect to server"); + } + } finally { + setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + } + return false; + } + + /** + * 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(); + tablesPane = new mage.client.table.TablesPane(); + gamePane = new mage.client.game.GamePane(); + deckEditorPane = new mage.client.deckeditor.DeckEditorPane(); + collectionViewerPane = new CollectionViewerPane(); + mageToolbar = new javax.swing.JToolBar(); + btnConnect = new javax.swing.JButton(); + jSeparator5 = new javax.swing.JToolBar.Separator(); + btnGames = new javax.swing.JButton(); + jSeparator4 = new javax.swing.JToolBar.Separator(); + btnDeckEditor = new javax.swing.JButton(); + jSeparator3 = new javax.swing.JToolBar.Separator(); + btnPreferences = new javax.swing.JButton(); + jSeparator2 = new javax.swing.JToolBar.Separator(); + btnAbout = new javax.swing.JButton(); + jSeparator1 = new javax.swing.JToolBar.Separator(); + btnExit = new javax.swing.JButton(); + lblStatus = new javax.swing.JLabel(); + jSeparator6 = new javax.swing.JToolBar.Separator(); + btnCollectionViewer = new JButton(); + + setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); + //setMinimumSize(new java.awt.Dimension(1024, 768)); + + tablesPane.setBounds(20, 10, 560, 440); + desktopPane.add(tablesPane, javax.swing.JLayeredPane.DEFAULT_LAYER); + try { + tablesPane.setMaximum(true); + } catch (java.beans.PropertyVetoException e1) { + e1.printStackTrace(); + } + gamePane.setBounds(20, 30, -1, -1); + desktopPane.add(gamePane, javax.swing.JLayeredPane.DEFAULT_LAYER); + try { + gamePane.setMaximum(true); + } catch (java.beans.PropertyVetoException e1) { + e1.printStackTrace(); + } + deckEditorPane.setBounds(140, 50, -1, -1); + desktopPane.add(deckEditorPane, javax.swing.JLayeredPane.DEFAULT_LAYER); + try { + deckEditorPane.setMaximum(true); + } catch (java.beans.PropertyVetoException e1) { + e1.printStackTrace(); + } + collectionViewerPane.setBounds(140, 50, -1, -1); + desktopPane.add(collectionViewerPane, javax.swing.JLayeredPane.DEFAULT_LAYER); + try { + collectionViewerPane.setMaximum(true); + } catch (java.beans.PropertyVetoException e1) { + e1.printStackTrace(); + } + + mageToolbar.setFloatable(false); + mageToolbar.setRollover(true); + + btnConnect.setText("Connect"); + btnConnect.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); + 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(jSeparator4); + + btnGames.setText("Tables"); + btnGames.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); + 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(jSeparator3); + + btnDeckEditor.setText("Deck Editor"); + btnDeckEditor.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); + 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.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); + 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(jSeparator6); + + btnPreferences.setText("Preferences"); + btnPreferences.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); + 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(jSeparator5); + + btnAbout.setText("About"); + btnAbout.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); + 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(jSeparator1); + + btnExit.setText("Exit"); + btnExit.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); + 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); + + lblStatus.setText("Not connected "); + mageToolbar.add(Box.createHorizontalGlue()); + 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, javax.swing.GroupLayout.DEFAULT_SIZE, 1144, Short.MAX_VALUE) + .addComponent(mageToolbar, javax.swing.GroupLayout.DEFAULT_SIZE, 1144, 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, javax.swing.GroupLayout.DEFAULT_SIZE, 880, Short.MAX_VALUE)) + ); + + pack(); + }// //GEN-END:initComponents + + private void btnDeckEditorActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDeckEditorActionPerformed + this.gamePane.setVisible(false); + this.tablesPane.setVisible(false); + this.draftPane.setVisible(false); + this.collectionViewerPane.setVisible(false); + showDeckEditor(DeckEditorMode.Constructed, null, null); + }//GEN-LAST:event_btnDeckEditorActionPerformed + + private void btnCollectionViewerActionPerformed(java.awt.event.ActionEvent evt) { + this.gamePane.setVisible(false); + this.tablesPane.setVisible(false); + this.deckEditorPane.setVisible(false); + showCollectionViewer(); + } + + private void btnPreferencesActionPerformed(java.awt.event.ActionEvent evt) { + PhasesDialog.main(new String[]{}); + } + + private void btnGamesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnGamesActionPerformed + this.gamePane.setVisible(false); + this.deckEditorPane.setVisible(false); + this.collectionViewerPane.setVisible(false); + this.tablesPane.setVisible(true); + this.tablesPane.showTables(); + }//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 (session.isConnected()) { + if (JOptionPane.showConfirmDialog(this, "Are you sure you want to disconnect?", "Confirm disconnect", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { + session.disconnect(); + } + } else { + connectDialog.showDialog(); + } + }//GEN-LAST:event_btnConnectActionPerformed + + private void btnAboutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAboutActionPerformed + AboutDialog aboutDialog = new AboutDialog(); + desktopPane.add(aboutDialog); + aboutDialog.showDialog(); + }//GEN-LAST:event_btnAboutActionPerformed + + public void exitApp() { + session.disconnect(); + 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); + this.tablesPane.setVisible(false); + this.gamePane.setVisible(false); + this.deckEditorPane.setVisible(false); + this.draftPane.setVisible(false); + this.collectionViewerPane.setVisible(false); + } + + public void showDeckEditor(DeckEditorMode mode, Deck deck, UUID tableId) { + this.deckEditorPane.setVisible(true); + this.deckEditorPane.show(mode, deck, tableId); + } + + public void showCollectionViewer() { + this.collectionViewerPane.setVisible(true); + } + + public static CombatDialog getCombatDialog() { + return combat; + } + + public static PickNumberDialog getPickNumberDialog() { + return pickNumber; + } + + 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.5.1", 560, 460); + } + + /** + * @param args the command line arguments + */ + public static void main(String args[]) { + final SplashScreen splash = SplashScreen.getSplashScreen(); + if (splash != null) { + Graphics2D g = splash.createGraphics(); + if (g != null) { + renderSplashFrame(g); + } + splash.update(); + } + + Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { + public void uncaughtException(Thread t, Throwable e) { + logger.log(Level.SEVERE, null, e); + } + }); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + new MageFrame().setVisible(true); + } + }); + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnAbout; + private javax.swing.JButton btnConnect; + private javax.swing.JButton btnDeckEditor; + private javax.swing.JButton btnCollectionViewer; + private javax.swing.JButton btnPreferences; + private javax.swing.JButton btnExit; + private javax.swing.JButton btnGames; + private mage.client.deckeditor.DeckEditorPane deckEditorPane; + private CollectionViewerPane collectionViewerPane; + private static MageJDesktop desktopPane; + private mage.client.game.GamePane gamePane; + 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.JLabel lblStatus; + private javax.swing.JToolBar mageToolbar; + private mage.client.table.TablesPane tablesPane; + // End of variables declaration//GEN-END:variables + + private static final long serialVersionUID = -9104885239063142218L; + private ImagePanel backgroundPane; + private DraftPane draftPane; + + public void setStatusText(String status) { + this.lblStatus.setText(status); + } +} diff --git a/Mage.Client/src/main/java/mage/client/cards/DraftGrid.form b/Mage.Client/src/main/java/mage/client/cards/DraftGrid.form new file mode 100644 index 0000000000..797927e8af --- /dev/null +++ b/Mage.Client/src/main/java/mage/client/cards/DraftGrid.form @@ -0,0 +1,29 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/main/java/mage/client/cards/DraftGrid.java b/Mage.Client/src/main/java/mage/client/cards/DraftGrid.java new file mode 100644 index 0000000000..41022d9d3a --- /dev/null +++ b/Mage.Client/src/main/java/mage/client/cards/DraftGrid.java @@ -0,0 +1,126 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * DraftGrid.java + * + * Created on 7-Jan-2011, 6:23:39 PM + */ + +package mage.client.cards; + +import java.awt.Rectangle; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.UUID; +import mage.cards.MageCard; +import mage.client.MageFrame; +import mage.client.plugins.impl.Plugins; +import mage.client.util.Config; +import mage.view.CardView; +import mage.view.CardsView; +import mage.client.util.Event; +import mage.client.util.Listener; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class DraftGrid extends javax.swing.JPanel implements MouseListener { + + protected CardEventSource cardEventSource = new CardEventSource(); + protected BigCard bigCard; + + /** Creates new form DraftGrid */ + public DraftGrid() { + initComponents(); + } + + public void loadBooster(CardsView booster, BigCard bigCard) { + this.bigCard = bigCard; + this.removeAll(); + int numColumns = 5; + int curColumn = 0; + int curRow = 0; + Rectangle rectangle = new Rectangle(Config.dimensions.frameWidth, Config.dimensions.frameHeight); + for (CardView card: booster.values()) { + MageCard cardImg = Plugins.getInstance().getMageCard(card, bigCard, Config.dimensions, null); + cardImg.addMouseListener(this); + add(cardImg); + cardImg.update(card); + rectangle.setLocation(curColumn * Config.dimensions.frameWidth, curRow * Config.dimensions.frameHeight); + cardImg.setBounds(rectangle); + cardImg.setCardBounds(rectangle.x, rectangle.y, Config.dimensions.frameWidth, Config.dimensions.frameHeight); + curColumn++; + if (curColumn == numColumns) { + curColumn = 0; + curRow++; + } + } + + } + + public void addCardEventListener(Listener listener) { + cardEventSource.addListener(listener); + } + + public void clearCardEventListeners() { + cardEventSource.clearListeners(); + } + + + /** 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() { + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 400, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 300, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2 && !e.isConsumed()) { + e.consume(); + Object obj = e.getSource(); + if (obj instanceof MageCard) { + this.cardEventSource.doubleClick(((MageCard)obj).getOriginal().getId(), "double-click"); + } + } + } + + @Override + public void mousePressed(MouseEvent e) { + } + + @Override + public void mouseReleased(MouseEvent e) { + } + + @Override + public void mouseEntered(MouseEvent e) { + } + + @Override + public void mouseExited(MouseEvent e) { + } + + + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/main/java/mage/client/draft/DraftPane.java b/Mage.Client/src/main/java/mage/client/draft/DraftPane.java index 6e99b46672..528d413f7e 100644 --- a/Mage.Client/src/main/java/mage/client/draft/DraftPane.java +++ b/Mage.Client/src/main/java/mage/client/draft/DraftPane.java @@ -34,6 +34,7 @@ package mage.client.draft; +import java.util.UUID; import mage.client.MagePane; /** @@ -47,6 +48,10 @@ public class DraftPane extends MagePane { initComponents(); } + public void showDraft(UUID draftId) { + this.draftPanel1.showDraft(draftId); + } + /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is diff --git a/Mage.Client/src/main/java/mage/client/draft/DraftPanel.form b/Mage.Client/src/main/java/mage/client/draft/DraftPanel.form index 2df044075c..f61cee7816 100644 --- a/Mage.Client/src/main/java/mage/client/draft/DraftPanel.form +++ b/Mage.Client/src/main/java/mage/client/draft/DraftPanel.form @@ -1,6 +1,10 @@
+ + + + @@ -18,13 +22,22 @@ - + + + + + + + + + + @@ -47,7 +60,7 @@ - + @@ -58,5 +71,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mage.Client/src/main/java/mage/client/draft/DraftPanel.java b/Mage.Client/src/main/java/mage/client/draft/DraftPanel.java index 1d5e92ebce..189b3ba36f 100644 --- a/Mage.Client/src/main/java/mage/client/draft/DraftPanel.java +++ b/Mage.Client/src/main/java/mage/client/draft/DraftPanel.java @@ -35,8 +35,11 @@ package mage.client.draft; import java.util.UUID; -import mage.client.cards.BigCard; -import mage.view.CardsView; +import mage.client.MageFrame; +import mage.client.remote.Session; +import mage.client.util.Event; +import mage.client.util.Listener; +import mage.view.DraftPickView; /** * @@ -44,14 +47,41 @@ import mage.view.CardsView; */ public class DraftPanel extends javax.swing.JPanel { + private UUID draftId; + private Session session; + /** Creates new form DraftPanel */ public DraftPanel() { initComponents(); } - public void loadBooster(CardsView cards, UUID draftId) { + public synchronized void showDraft(UUID draftId) { + this.draftId = draftId; + session = MageFrame.getSession(); + session.setDraft(this); + if (!session.joinDraft(draftId)) + hideDraft(); + } + + public void loadBooster(DraftPickView draftPickView) { + draftBooster.loadBooster(draftPickView.getBooster(), bigCard); + draftPicks.loadCards(draftPickView.getPicks(), bigCard, null); + this.draftBooster.clearCardEventListeners(); + this.draftBooster.addCardEventListener( + new Listener () { + @Override + public void event(Event event) { + if (event.getEventName().equals("double-click")) { + session.sendCardPick(draftId, (UUID)event.getSource()); + } + } + } + ); + } + public void hideDraft() { + this.setVisible(false); } /** This method is called from within the constructor to @@ -63,8 +93,11 @@ public class DraftPanel extends javax.swing.JPanel { // //GEN-BEGIN:initComponents private void initComponents() { + jSeparator1 = new javax.swing.JSeparator(); jPanel1 = new javax.swing.JPanel(); bigCard = new mage.client.cards.BigCard(); + draftBooster = new mage.client.cards.DraftGrid(); + draftPicks = new mage.client.cards.CardGrid(); jPanel1.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED)); @@ -77,28 +110,53 @@ public class DraftPanel extends javax.swing.JPanel { jPanel1Layout.setVerticalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() - .addContainerGap(85, Short.MAX_VALUE) + .addContainerGap(186, Short.MAX_VALUE) .addComponent(bigCard, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) ); + draftBooster.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0))); + + javax.swing.GroupLayout draftBoosterLayout = new javax.swing.GroupLayout(draftBooster); + draftBooster.setLayout(draftBoosterLayout); + draftBoosterLayout.setHorizontalGroup( + draftBoosterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 568, Short.MAX_VALUE) + ); + draftBoosterLayout.setVerticalGroup( + draftBoosterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 432, Short.MAX_VALUE) + ); + + draftPicks.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0))); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(465, Short.MAX_VALUE)) + .addGap(0, 0, 0) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(draftBooster, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(draftPicks, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 570, Short.MAX_VALUE))) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(draftPicks, javax.swing.GroupLayout.DEFAULT_SIZE, 123, Short.MAX_VALUE) + .addGap(0, 0, 0) + .addComponent(draftBooster, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) ); }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables private mage.client.cards.BigCard bigCard; + private mage.client.cards.DraftGrid draftBooster; + private mage.client.cards.CardGrid draftPicks; private javax.swing.JPanel jPanel1; + private javax.swing.JSeparator jSeparator1; // End of variables declaration//GEN-END:variables } diff --git a/Mage.Client/src/main/java/mage/client/remote/Client.java b/Mage.Client/src/main/java/mage/client/remote/Client.java index 3633b4de0c..88ffa2bf7f 100644 --- a/Mage.Client/src/main/java/mage/client/remote/Client.java +++ b/Mage.Client/src/main/java/mage/client/remote/Client.java @@ -83,7 +83,7 @@ public class Client implements CallbackClient { } else if(callback.getMethod().equals("startDraft")) { TableClientMessage message = (TableClientMessage) callback.getData(); - //TODO: add code to start draft + draftStarted(message.getGameId(), message.getPlayerId()); } else if (callback.getMethod().equals("replayGame")) { replayGame(); @@ -166,9 +166,13 @@ public class Client implements CallbackClient { TableClientMessage message = (TableClientMessage) callback.getData(); sideboard(message.getDeck(), message.getTableId()); } + else if (callback.getMethod().equals("construct")) { + TableClientMessage message = (TableClientMessage) callback.getData(); + construct(message.getDeck(), message.getTableId()); + } else if (callback.getMethod().equals("draftPick")) { DraftClientMessage message = (DraftClientMessage) callback.getData(); - + session.getDraft().loadBooster(message.getDraftPickView()); } else if (callback.getMethod().equals("draftInform")) { if (callback.getMessageId() > messageId) { @@ -179,7 +183,7 @@ public class Client implements CallbackClient { } } else if (callback.getMethod().equals("draftInit")) { - + session.ack("draftInit"); } messageId = callback.getMessageId(); } @@ -206,6 +210,16 @@ public class Client implements CallbackClient { } } + protected void draftStarted(UUID draftId, UUID playerId) { + try { + frame.showDraft(draftId); + logger.info("Draft " + draftId + " started for player " + playerId); + } + catch (Exception ex) { + handleException(ex); + } + } + protected void watchGame(UUID gameId) { try { frame.watchGame(gameId); @@ -230,6 +244,10 @@ public class Client implements CallbackClient { frame.showDeckEditor(DeckEditorMode.Sideboard, deck, tableId); } + protected void construct(Deck deck, UUID tableId) { + frame.showDeckEditor(DeckEditorMode.Limited, deck, tableId); + } + private void handleException(Exception ex) { logger.log(Level.SEVERE, "Client error\n", ex); JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Unrecoverable client error. Disconnecting", "Error", JOptionPane.ERROR_MESSAGE); diff --git a/Mage.Client/src/main/java/mage/client/remote/Session.java b/Mage.Client/src/main/java/mage/client/remote/Session.java index 3c1e3a207f..641a16dbfb 100644 --- a/Mage.Client/src/main/java/mage/client/remote/Session.java +++ b/Mage.Client/src/main/java/mage/client/remote/Session.java @@ -44,6 +44,7 @@ import mage.cards.decks.DeckCardLists; import mage.client.MageFrame; import mage.client.chat.ChatPanel; import mage.client.components.MageUI; +import mage.client.draft.DraftPanel; import mage.client.game.GamePanel; import mage.client.util.Config; import mage.game.GameException; @@ -73,6 +74,7 @@ public class Session { private ServerState serverState; private Map chats = new HashMap(); private GamePanel game; + private DraftPanel draft; private CallbackClientDaemon callbackDaemon; private MageUI ui = new MageUI(); @@ -170,6 +172,14 @@ public class Session { game = gamePanel; } + public DraftPanel getDraft() { + return draft; + } + + public void setDraft(DraftPanel draftPanel) { + draft = draftPanel; + } + public UUID getMainRoomId() { try { return server.getMainRoomId(); @@ -337,7 +347,7 @@ public class Session { public boolean sendCardPick(UUID draftId, UUID cardId) { try { - server.sendPlayerUUID(draftId, sessionId, cardId); + server.sendCardPick(draftId, sessionId, cardId); return true; } catch (RemoteException ex) { handleRemoteException(ex); @@ -397,6 +407,18 @@ public class Session { return false; } + public boolean joinDraft(UUID draftId) { + try { + server.joinDraft(draftId, sessionId); + return true; + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return false; + } + public boolean watchGame(UUID gameId) { try { server.watchGame(gameId, sessionId); diff --git a/Mage.Client/src/main/java/mage/client/table/TablesPanel.java b/Mage.Client/src/main/java/mage/client/table/TablesPanel.java index 79315c6c7f..9516d6089a 100644 --- a/Mage.Client/src/main/java/mage/client/table/TablesPanel.java +++ b/Mage.Client/src/main/java/mage/client/table/TablesPanel.java @@ -321,6 +321,7 @@ public class TablesPanel extends javax.swing.JPanel implements Observer { private void btnNewDraftActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnNewDraftActionPerformed DraftOptions options = new DraftOptions("testDraft"); + options.setDraftType("8 Player Booster"); options.getPlayerTypes().add("Human"); options.getPlayerTypes().add("Computer - default"); options.getPlayerTypes().add("Computer - default"); diff --git a/Mage.Common/src/mage/view/DraftClientMessage.java b/Mage.Common/src/mage/view/DraftClientMessage.java index f868c3fd41..5e4c6feb32 100644 --- a/Mage.Common/src/mage/view/DraftClientMessage.java +++ b/Mage.Common/src/mage/view/DraftClientMessage.java @@ -53,4 +53,11 @@ public class DraftClientMessage implements Serializable { this.draftView = draftView; } + public DraftPickView getDraftPickView() { + return draftPickView; + } + + public DraftView getDraftView() { + return draftView; + } } diff --git a/Mage.Common/src/mage/view/DraftPickView.java b/Mage.Common/src/mage/view/DraftPickView.java index f1c98330b0..5020154ddd 100644 --- a/Mage.Common/src/mage/view/DraftPickView.java +++ b/Mage.Common/src/mage/view/DraftPickView.java @@ -28,17 +28,21 @@ package mage.view; +import java.io.Serializable; +import mage.game.draft.DraftPlayer; + /** * * @author BetaSteward_at_googlemail.com */ -public class DraftPickView { +public class DraftPickView implements Serializable { protected CardsView booster; protected CardsView picks; - public DraftPickView() { - + public DraftPickView(DraftPlayer player) { + this.booster = new CardsView(player.getBooster()); + this.picks = new CardsView(player.getDeck().getSideboard()); } public CardsView getBooster() { diff --git a/Mage.Common/src/mage/view/DraftView.java b/Mage.Common/src/mage/view/DraftView.java index ebb0dc13fa..4d5ee79ea5 100644 --- a/Mage.Common/src/mage/view/DraftView.java +++ b/Mage.Common/src/mage/view/DraftView.java @@ -28,6 +28,7 @@ package mage.view; +import java.io.Serializable; import java.util.ArrayList; import java.util.List; import mage.game.draft.Draft; @@ -36,7 +37,7 @@ import mage.game.draft.Draft; * * @author BetaSteward_at_googlemail.com */ -public class DraftView { +public class DraftView implements Serializable { private List players = new ArrayList(); diff --git a/Mage.Common/src/mage/view/RoundView.java b/Mage.Common/src/mage/view/RoundView.java index 1c60ee211b..20d35e3eb1 100644 --- a/Mage.Common/src/mage/view/RoundView.java +++ b/Mage.Common/src/mage/view/RoundView.java @@ -28,13 +28,14 @@ package mage.view; +import java.io.Serializable; import mage.game.tournament.Round; /** * * @author BetaSteward_at_googlemail.com */ -public class RoundView { +public class RoundView implements Serializable { public RoundView(Round round) { diff --git a/Mage.Common/src/mage/view/TournamentPlayerView.java b/Mage.Common/src/mage/view/TournamentPlayerView.java index 084dff7b9a..2e8fdb0915 100644 --- a/Mage.Common/src/mage/view/TournamentPlayerView.java +++ b/Mage.Common/src/mage/view/TournamentPlayerView.java @@ -28,10 +28,12 @@ package mage.view; +import java.io.Serializable; + /** * * @author BetaSteward_at_googlemail.com */ -public class TournamentPlayerView { +public class TournamentPlayerView implements Serializable { } diff --git a/Mage.Common/src/mage/view/TournamentView.java b/Mage.Common/src/mage/view/TournamentView.java index 2a44b1f42d..a783896593 100644 --- a/Mage.Common/src/mage/view/TournamentView.java +++ b/Mage.Common/src/mage/view/TournamentView.java @@ -28,6 +28,7 @@ package mage.view; +import java.io.Serializable; import java.util.ArrayList; import java.util.List; import mage.game.tournament.Tournament; @@ -36,7 +37,7 @@ import mage.game.tournament.Tournament; * * @author BetaSteward_at_googlemail.com */ -public class TournamentView { +public class TournamentView implements Serializable { List rounds = new ArrayList(); diff --git a/Mage.Server.Plugins/Mage.Draft.8PlayerBooster/pom.xml b/Mage.Server.Plugins/Mage.Draft.8PlayerBooster/pom.xml new file mode 100644 index 0000000000..14d00806cc --- /dev/null +++ b/Mage.Server.Plugins/Mage.Draft.8PlayerBooster/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + + + org.mage + mage-root + 0.5.1 + + + Mage-Draft-8PlayerBooster + jar + Mage Draft 8 Player Booster + + + + ${project.groupId} + Mage + ${project.version} + + + + + src + + + org.apache.maven.plugins + maven-compiler-plugin + 2.0.2 + + 1.6 + 1.6 + + + + maven-resources-plugin + + UTF-8 + + + + + + mage-draft-8playerbooster + + + + diff --git a/Mage.Server.Plugins/Mage.Draft.8PlayerBooster/src/mage/draft/BoosterDraft.java b/Mage.Server.Plugins/Mage.Draft.8PlayerBooster/src/mage/draft/BoosterDraft.java new file mode 100644 index 0000000000..f88ca485db --- /dev/null +++ b/Mage.Server.Plugins/Mage.Draft.8PlayerBooster/src/mage/draft/BoosterDraft.java @@ -0,0 +1,59 @@ +/* + * Copyright 2011 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.draft; + +import mage.game.draft.DraftImpl; +import mage.game.draft.DraftOptions; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class BoosterDraft extends DraftImpl { + + public BoosterDraft(DraftOptions options) { + super(options); + } + + @Override + public void start() { + while (boosterNum < sets.size()) { + openBooster(); + while (pickCards()) { + if (boosterNum % 2 == 1) + passLeft(); + else + passRight(); + fireUpdatePlayersEvent(); + } + } + startTournament(); + } + +} diff --git a/Mage.Server.Plugins/pom.xml b/Mage.Server.Plugins/pom.xml index cdf3442c05..7b390eaef2 100644 --- a/Mage.Server.Plugins/pom.xml +++ b/Mage.Server.Plugins/pom.xml @@ -1,6 +1,5 @@ - + 4.0.0 @@ -23,6 +22,7 @@ Mage.Player.AI Mage.Player.AIMinimax Mage.Player.Human - + Mage.Draft.8PlayerBooster + - + \ No newline at end of file diff --git a/Mage.Server/config/config.xml b/Mage.Server/config/config.xml index df6998b9b9..6afc3b6d8a 100644 --- a/Mage.Server/config/config.xml +++ b/Mage.Server/config/config.xml @@ -12,6 +12,9 @@ + + + diff --git a/Mage.Server/plugins/mage-draft-8playerbooster.jar b/Mage.Server/plugins/mage-draft-8playerbooster.jar new file mode 100644 index 0000000000000000000000000000000000000000..861bd06e7793c3e9546c55ab2d433077d608594a GIT binary patch literal 2637 zcmWIWW@h1H0D&!=)a}3wD8UJ&eO*Hwbv^yu^aG&EI2bkqm8oC<#gqz^t_ETeWM#gN zex7cw!6ACSZl8V6oc8h7)w{^+t*dqJ%=yhh23L$9JT21kI(I_HTi1z${mGKBDPr0O zR4R7P=?)V14hk-rtF=}{hFfT|agb<@@adq>Kp8LNVy^>_{AOBO3eZRQDAJ_ zT%qh7rx&Nk0CN_m>sf)$%1um9g}WS62{%khN>O5330xruI3zC2-yyBb#K16tnSntT zRiRUUesM`^kqbzdUUE)iadBAcGhBDRyKOCQhu)zJ1ygC)cBl2Chi^b`$lE{~~a zoR^dw%$wwMd0}7f&BcVM6wvv>u&+rq-f?GgI-}6ROLKM>zyERPaq-{3 z*RSU@3Gi|LD13$$QtcujHK5ZolVlTcm9JvBKm{SHbl1*i&b$>-u+B+f4ao z(7l#V^WM9AwHOvpKKMbntnKOl^7IpKUF}_pu@}9TS$BQslmD1-NBjOn z=Kj@z9v_eGUs=}Hczf20rM|jn`s}%?A1%DnQ(Qmowf;}R?FPM)+@@i@Wk>+ckhkvUc0s_ zE9X8sb6>JHbf4J9;4g6p`CH82dE2pWD&KMTaGl8Ycmp3+n=YA!U!Roz@Zsarh`Td= zVTIh6okISx|GZi*HY-02Tqtoqar&H39y^u?EW3ZQsV*qtmeL`mxwlIEF3wxMwwCR; z!1Z*_vlh{=)8@=soME`LwNmGZj^&&~nU55BHF|g6J95Wi^*2GysF(UD4EDIM{l*y? zwR5|=eW|8&%Dsb2S_*lZw`oTGd^}lx%giW8tFR4SHi>hSW>=XO^r`J|Vvbq<(=?-I z_6;ZD^5oL6OXX|c@#r>B(Vue3a?%!&`YVx27k>Y|k2}rsBWI=D#In>pc%sBiy%Ly; z^NZ5;2&8!_auO?3i=ZhT?g|cuha1%GnoG48{%2%h_zKKpmSmY% zke{npk()C&#JBslfr!oZ{fAoObS+(Sf9l`& zQ-wp__DosXo%Olz_swor?UV?gRlwD)z;m{G-8$Z5ek?wnArG|D`L(iRu zm9O>QM9*Z5@U^%mxblJZwCk7po>crlv$UksZp*VX0;Ur!Gu*%2Pj>yo?rB^mrd`^=IC5Ab7i~y{KchByTAV5CdQ*Eze4W5prO4Mf4R>vRavF+1TXXvwC;!-^> zcz2 JB!6}g4*=1son-(3 literal 0 HcmV?d00001 diff --git a/Mage.Server/plugins/mage-player-ai.jar b/Mage.Server/plugins/mage-player-ai.jar index f3f37a9fbca17989687bf2c3f74a15264ebd59c6..679b14deebeb98ff85c09831e7efa354a8deb5c3 100644 GIT binary patch delta 16836 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 delta 16652 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 G=>Gx4DxKK? diff --git a/Mage.Server/plugins/mage-player-human.jar b/Mage.Server/plugins/mage-player-human.jar index 6050acc5de2c5d09cc9fcd13c2cb771521a1e0d1..53e260222e9ba195dbb1b3ce435426865774adf3 100644 GIT binary patch delta 9042 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 entry: sessionPlayerMap.entrySet()) { + if (entry.getValue().equals(playerId)) { + sessionManager.getSession(entry.getKey()).construct(deck, table.getId()); + break; + } + } + } + public void endGame() { UUID choosingPlayerId = match.getChooser(); match.endGame(); diff --git a/Mage.Server/src/main/java/mage/server/util/Config.xsd b/Mage.Server/src/main/java/mage/server/util/Config.xsd index 20c7319dea..ac06d7978d 100644 --- a/Mage.Server/src/main/java/mage/server/util/Config.xsd +++ b/Mage.Server/src/main/java/mage/server/util/Config.xsd @@ -8,11 +8,12 @@ + - + @@ -23,26 +24,40 @@ - - - - - - - + + + + + + + + + + + + + - + - + - + + + + + + + + + @@ -50,7 +65,7 @@ - + diff --git a/Mage.Server/src/main/java/mage/server/util/ConfigSettings.java b/Mage.Server/src/main/java/mage/server/util/ConfigSettings.java index d0aba9c981..06a0cf19f7 100644 --- a/Mage.Server/src/main/java/mage/server/util/ConfigSettings.java +++ b/Mage.Server/src/main/java/mage/server/util/ConfigSettings.java @@ -92,6 +92,10 @@ public class ConfigSettings { return config.getGameTypes().getGameType(); } + public List getDraftTypes() { + return config.getDraftTypes().getDraftType(); + } + public List getDeckTypes() { return config.getDeckTypes().getDeckType(); } diff --git a/Mage.Server/src/main/xml-resources/jaxb/Config/Config.xsd b/Mage.Server/src/main/xml-resources/jaxb/Config/Config.xsd index 142e7f1a74..c9a949dd56 100644 --- a/Mage.Server/src/main/xml-resources/jaxb/Config/Config.xsd +++ b/Mage.Server/src/main/xml-resources/jaxb/Config/Config.xsd @@ -8,6 +8,7 @@ + @@ -53,6 +54,14 @@ + + + + + + + + diff --git a/Mage/src/mage/game/draft/DraftImpl.java b/Mage/src/mage/game/draft/DraftImpl.java index b51584e256..b92a6def9c 100644 --- a/Mage/src/mage/game/draft/DraftImpl.java +++ b/Mage/src/mage/game/draft/DraftImpl.java @@ -50,7 +50,7 @@ import mage.players.PlayerList; * * @author BetaSteward_at_googlemail.com */ -public class DraftImpl> implements Draft { +public abstract class DraftImpl> implements Draft { protected final UUID id; protected Map players = new HashMap(); @@ -74,8 +74,8 @@ public class DraftImpl> implements Draft { @Override public void addPlayer(Player player) { DraftPlayer draftPlayer = new DraftPlayer(player); - players.put(draftPlayer.getId(), draftPlayer); - table.add(draftPlayer.getId()); + players.put(player.getId(), draftPlayer); + table.add(player.getId()); } @Override @@ -139,7 +139,7 @@ public class DraftImpl> implements Draft { } protected void openBooster() { - if (sets.size() < boosterNum) { + if (boosterNum < sets.size()) { for (DraftPlayer player: players.values()) { player.setBooster(sets.get(boosterNum).createBooster()); } @@ -151,8 +151,8 @@ public class DraftImpl> implements Draft { for (DraftPlayer player: players.values()) { if (player.getBooster().size() == 0) return false; - player.getPlayer().pickCard(player.getBooster(), player.getDeck(), this); player.setPicking(); + player.getPlayer().pickCard(player.getBooster(), player.getDeck(), this); } while (!donePicking()) { try { @@ -173,21 +173,6 @@ public class DraftImpl> implements Draft { return true; } - @Override - public void start() { - while (boosterNum < sets.size()) { - openBooster(); - while (pickCards()) { - if (boosterNum % 2 == 1) - passLeft(); - else - passRight(); - fireUpdatePlayersEvent(); - } - } - startTournament(); - } - @Override public void addTableEventListener(Listener listener) { tableEventSource.addListener(listener); @@ -205,7 +190,7 @@ public class DraftImpl> implements Draft { @Override public void firePickCardEvent(UUID playerId) { - playerQueryEventSource.pickCard(playerId, "Pick card", players.get(playerId).booster); + playerQueryEventSource.pickCard(playerId, "Pick card", players.get(playerId).booster, 20); } @Override @@ -214,6 +199,7 @@ public class DraftImpl> implements Draft { for (Card card: player.booster) { if (card.getId().equals(cardId)) { player.addPick(card); + player.booster.remove(card); break; } } diff --git a/Mage/src/mage/game/draft/DraftOptions.java b/Mage/src/mage/game/draft/DraftOptions.java index d973c32c0d..9f62a4043c 100644 --- a/Mage/src/mage/game/draft/DraftOptions.java +++ b/Mage/src/mage/game/draft/DraftOptions.java @@ -41,7 +41,7 @@ public class DraftOptions implements Serializable { protected String name; protected String draftType; - protected List sets; + protected List sets = new ArrayList(); protected List playerTypes = new ArrayList(); protected TimingOption timing; diff --git a/Mage/src/mage/game/events/PlayerQueryEvent.java b/Mage/src/mage/game/events/PlayerQueryEvent.java index 4a7dfa295e..87365361be 100644 --- a/Mage/src/mage/game/events/PlayerQueryEvent.java +++ b/Mage/src/mage/game/events/PlayerQueryEvent.java @@ -76,12 +76,13 @@ public class PlayerQueryEvent extends EventObject implements ExternalEvent, Seri this.max = max; } - private PlayerQueryEvent(UUID playerId, String message, List booster, QueryType queryType) { + private PlayerQueryEvent(UUID playerId, String message, List booster, QueryType queryType, int time) { super(playerId); this.queryType = queryType; this.message = message; this.playerId = playerId; this.booster = booster; + this.max = time; } public static PlayerQueryEvent askEvent(UUID playerId, String message) { @@ -127,8 +128,8 @@ public class PlayerQueryEvent extends EventObject implements ExternalEvent, Seri return new PlayerQueryEvent(playerId, message, null, null, null, cards, QueryType.LOOK, 0, 0, false); } - public static PlayerQueryEvent pickCard(UUID playerId, String message, List booster) { - return new PlayerQueryEvent(playerId, message, booster, QueryType.PICK_CARD); + public static PlayerQueryEvent pickCard(UUID playerId, String message, List booster, int time) { + return new PlayerQueryEvent(playerId, message, booster, QueryType.PICK_CARD, time); } public String getMessage() { diff --git a/Mage/src/mage/game/events/PlayerQueryEventSource.java b/Mage/src/mage/game/events/PlayerQueryEventSource.java index 0052211c0b..23f429be67 100644 --- a/Mage/src/mage/game/events/PlayerQueryEventSource.java +++ b/Mage/src/mage/game/events/PlayerQueryEventSource.java @@ -95,8 +95,8 @@ public class PlayerQueryEventSource implements EventSource, Se dispatcher.fireEvent(PlayerQueryEvent.playXManaEvent(playerId, message)); } - public void pickCard(UUID playerId, String message, List booster) { - dispatcher.fireEvent(PlayerQueryEvent.pickCard(playerId, message, booster)); + public void pickCard(UUID playerId, String message, List booster, int time) { + dispatcher.fireEvent(PlayerQueryEvent.pickCard(playerId, message, booster, time)); } }