From f7ffbb477304f4e518c67b9bf796625946ea93cd Mon Sep 17 00:00:00 2001 From: BetaSteward Date: Thu, 10 Feb 2011 22:00:47 -0500 Subject: [PATCH] added Sealed tournaments --- .../src/main/java/mage/client/MageFrame.java | 6 +- .../client/deckeditor/DeckEditorPane.java | 4 +- .../client/deckeditor/DeckEditorPanel.java | 54 ++++++++++-- .../mage/client/dialog/AddLandDialog.form | 29 ++++++- .../mage/client/dialog/AddLandDialog.java | 12 ++- .../client/dialog/NewTournamentDialog.java | 75 +++++++++++++---- .../main/java/mage/client/remote/Client.java | 12 +-- .../src/mage/view/TableClientMessage.java | 8 +- .../src/mage/view/TournamentTypeView.java | 6 ++ .../Mage.Deck.Constructed/pom.xml | 2 +- Mage.Server.Plugins/Mage.Deck.Limited/pom.xml | 2 +- .../Mage.Game.FreeForAll/pom.xml | 2 +- .../Mage.Game.TwoPlayerDuel/pom.xml | 2 +- Mage.Server.Plugins/Mage.Player.AI.MA/pom.xml | 2 +- Mage.Server.Plugins/Mage.Player.AI/pom.xml | 2 +- .../java/mage/player/ai/ComputerPlayer.java | 5 +- .../Mage.Player.AIMinimax/pom.xml | 2 +- Mage.Server.Plugins/Mage.Player.Human/pom.xml | 2 +- .../src/mage/player/human/HumanPlayer.java | 5 +- .../BoosterDraftEliminationTournament.java | 3 +- ...BoosterDraftEliminationTournamentType.java | 1 + .../Mage.Tournament.Sealed/pom.xml | 51 ++++++++++++ .../SealedEliminationTournament.java | 77 ++++++++++++++++++ .../SealedEliminationTournamentType.java | 48 +++++++++++ Mage.Server.Plugins/pom.xml | 5 +- Mage.Server/config/config.xml | 1 + Mage.Server/plugins/mage-player-ai.jar | Bin 39769 -> 39830 bytes Mage.Server/plugins/mage-player-aiminimax.jar | Bin 36412 -> 36416 bytes Mage.Server/plugins/mage-player-human.jar | Bin 11573 -> 11637 bytes .../plugins/mage-tournament-booster-draft.jar | Bin 5679 -> 5721 bytes Mage.Server/pom.xml | 2 +- Mage.Server/release/config/config.xml | 22 ++--- .../src/main/java/mage/server/Session.java | 8 +- .../java/mage/server/TableController.java | 65 +++++++-------- .../main/java/mage/server/TableManager.java | 6 +- .../mage/server/draft/DraftController.java | 1 - .../java/mage/server/draft/DraftManager.java | 4 +- .../tournament/TournamentController.java | 41 ++++++++-- .../server/tournament/TournamentManager.java | 9 ++ .../server/tournament/TournamentSession.java | 47 ++++++++++- Mage/src/mage/game/Table.java | 8 +- Mage/src/mage/game/draft/DraftOptions.java | 11 +-- .../mage/game/events/PlayerQueryEvent.java | 22 ++++- .../game/events/PlayerQueryEventSource.java | 5 ++ .../mage/game/tournament/LimitedOptions.java | 48 +++++++++++ Mage/src/mage/game/tournament/Tournament.java | 7 +- .../mage/game/tournament/TournamentImpl.java | 46 ++++++++++- .../game/tournament/TournamentOptions.java | 11 ++- .../mage/game/tournament/TournamentType.java | 4 + Mage/src/mage/players/Player.java | 3 +- pom.xml | 7 +- 51 files changed, 652 insertions(+), 143 deletions(-) create mode 100644 Mage.Server.Plugins/Mage.Tournament.Sealed/pom.xml create mode 100644 Mage.Server.Plugins/Mage.Tournament.Sealed/src/mage/tournament/SealedEliminationTournament.java create mode 100644 Mage.Server.Plugins/Mage.Tournament.Sealed/src/mage/tournament/SealedEliminationTournamentType.java create mode 100644 Mage/src/mage/game/tournament/LimitedOptions.java diff --git a/Mage.Client/src/main/java/mage/client/MageFrame.java b/Mage.Client/src/main/java/mage/client/MageFrame.java index b093d29e3d..1e35f66af2 100644 --- a/Mage.Client/src/main/java/mage/client/MageFrame.java +++ b/Mage.Client/src/main/java/mage/client/MageFrame.java @@ -627,7 +627,7 @@ public class MageFrame extends javax.swing.JFrame { }// //GEN-END:initComponents private void btnDeckEditorActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDeckEditorActionPerformed - showDeckEditor(DeckEditorMode.Constructed, null, null); + showDeckEditor(DeckEditorMode.Constructed, null, null, 0); }//GEN-LAST:event_btnDeckEditorActionPerformed private void btnCollectionViewerActionPerformed(java.awt.event.ActionEvent evt) { @@ -685,10 +685,10 @@ public class MageFrame extends javax.swing.JFrame { btnDeckEditor.setEnabled(true); } - public void showDeckEditor(DeckEditorMode mode, Deck deck, UUID tableId) { + public void showDeckEditor(DeckEditorMode mode, Deck deck, UUID tableId, int time) { this.deckEditorPane.setVisible(true); this.deckEditorPane.toFront(); - this.deckEditorPane.show(mode, deck, tableId); + this.deckEditorPane.show(mode, deck, tableId, time); } public void showCollectionViewer() { diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPane.java b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPane.java index 33fbe59613..842be6614f 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPane.java +++ b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPane.java @@ -73,12 +73,12 @@ public class DeckEditorPane extends MagePane { } } - public void show(DeckEditorMode mode, Deck deck, UUID tableId) { + public void show(DeckEditorMode mode, Deck deck, UUID tableId, int time) { if (deck != null) this.setTitle("Deck Editor - " + deck.getName()); else this.setTitle("Deck Editor"); - this.deckEditorPanel1.showDeckEditor(mode, deck, tableId); + this.deckEditorPanel1.showDeckEditor(mode, deck, tableId, time); this.repaint(); } diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java index c71b096efa..48267da7cb 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java +++ b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java @@ -47,14 +47,14 @@ import mage.view.CardView; import javax.swing.*; import javax.swing.filechooser.FileFilter; import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.io.File; import java.io.IOException; -import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; -import mage.client.MagePane; import mage.client.cards.BigCard; import mage.client.constants.Constants.DeckEditorMode; import mage.client.dialog.AddLandDialog; @@ -72,6 +72,8 @@ public class DeckEditorPanel extends javax.swing.JPanel { private boolean isShowCardInfo = false; private UUID tableId; private DeckEditorMode mode; + private int timeout; + private Timer countdown; /** Creates new form DeckEditorPanel */ @@ -87,9 +89,23 @@ public class DeckEditorPanel extends javax.swing.JPanel { deckArea.setOpaque(false); jPanel1.setOpaque(false); jSplitPane1.setOpaque(false); - } + countdown = new Timer(1000, + new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (--timeout > 0) { + setTimeout(Integer.toString(timeout)); + } + else { + setTimeout("0"); + countdown.stop(); + } + } + } + ); + } - public void showDeckEditor(DeckEditorMode mode, Deck deck, UUID tableId) { + public void showDeckEditor(DeckEditorMode mode, Deck deck, UUID tableId, int time) { if (deck != null) this.deck = deck; this.tableId = tableId; @@ -98,6 +114,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { switch (mode) { case Limited: this.btnAddLand.setVisible(true); + this.txtTimeRemaining.setVisible(true); case Sideboard: this.btnSubmit.setVisible(true); this.cardSelector.loadCards(new ArrayList(deck.getSideboard()), this.bigCard, mode == DeckEditorMode.Limited); @@ -105,6 +122,12 @@ public class DeckEditorPanel extends javax.swing.JPanel { this.btnImport.setVisible(false); this.btnLoad.setVisible(false); this.deckArea.showSideboard(false); + countdown.stop(); + this.timeout = time; + setTimeout(Integer.toString(timeout)); + if (timeout != 0) { + countdown.start(); + } break; case Constructed: this.btnSubmit.setVisible(false); @@ -113,6 +136,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { this.btnImport.setVisible(true); this.btnLoad.setVisible(true); this.deckArea.showSideboard(true); + this.txtTimeRemaining.setVisible(false); break; } init(); @@ -184,7 +208,11 @@ public class DeckEditorPanel extends javax.swing.JPanel { } } - private void initComponents() { + private void setTimeout(String text) { + this.txtTimeRemaining.setText(text); + } + + private void initComponents() { jSplitPane1 = new javax.swing.JSplitPane(); cardSelector = new mage.client.deckeditor.CardSelector(); @@ -200,6 +228,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { btnImport = new javax.swing.JButton(); btnSubmit = new javax.swing.JButton(); btnAddLand = new javax.swing.JButton(); + txtTimeRemaining = new javax.swing.JTextField(); jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); jSplitPane1.setResizeWeight(0.5); @@ -273,6 +302,11 @@ public class DeckEditorPanel extends javax.swing.JPanel { } }); + txtTimeRemaining.setEditable(false); + txtTimeRemaining.setForeground(java.awt.Color.red); + txtTimeRemaining.setHorizontalAlignment(javax.swing.JTextField.CENTER); + txtTimeRemaining.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED)); + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( @@ -301,7 +335,11 @@ public class DeckEditorPanel extends javax.swing.JPanel { .addContainerGap() .addComponent(btnAddLand) .addContainerGap() - .addComponent(btnSubmit))) + .addComponent(btnSubmit)) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addComponent(txtTimeRemaining)) + ) .addContainerGap()) ); jPanel1Layout.setVerticalGroup( @@ -322,6 +360,9 @@ public class DeckEditorPanel extends javax.swing.JPanel { .addComponent(btnImport) .addComponent(btnAddLand) .addComponent(btnSubmit)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(txtTimeRemaining)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, isShowCardInfo ? 30 : 159, Short.MAX_VALUE) .addComponent(cardInfoPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(bigCard, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) @@ -488,6 +529,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { private JComponent cardInfoPane; private javax.swing.JButton btnSubmit; private javax.swing.JButton btnAddLand; + private javax.swing.JTextField txtTimeRemaining; } class DeckFilter extends FileFilter { diff --git a/Mage.Client/src/main/java/mage/client/dialog/AddLandDialog.form b/Mage.Client/src/main/java/mage/client/dialog/AddLandDialog.form index b0409c68aa..9b10b2b17b 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/AddLandDialog.form +++ b/Mage.Client/src/main/java/mage/client/dialog/AddLandDialog.form @@ -1,6 +1,6 @@ -
+ @@ -97,7 +97,7 @@ - + @@ -114,8 +114,18 @@ + + + + + + + + + + @@ -128,8 +138,18 @@ + + + + + + + + + + @@ -137,6 +157,11 @@ + + + + + diff --git a/Mage.Client/src/main/java/mage/client/dialog/AddLandDialog.java b/Mage.Client/src/main/java/mage/client/dialog/AddLandDialog.java index 05dded511b..0adeaa7b18 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/AddLandDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/AddLandDialog.java @@ -88,12 +88,22 @@ public class AddLandDialog extends MageDialog { lblForest.setText("Forest"); + spnForest.setModel(new javax.swing.SpinnerNumberModel(Integer.valueOf(0), Integer.valueOf(0), null, Integer.valueOf(1))); + + spnIsland.setModel(new javax.swing.SpinnerNumberModel(Integer.valueOf(0), Integer.valueOf(0), null, Integer.valueOf(1))); + lblIsland.setText("Island"); lblPains.setText("Plains"); + spnPlains.setModel(new javax.swing.SpinnerNumberModel(Integer.valueOf(0), Integer.valueOf(0), null, Integer.valueOf(1))); + + spnMountain.setModel(new javax.swing.SpinnerNumberModel(Integer.valueOf(0), Integer.valueOf(0), null, Integer.valueOf(1))); + lblMountain.setText("Mountain"); + spnSwamp.setModel(new javax.swing.SpinnerNumberModel(Integer.valueOf(0), Integer.valueOf(0), null, Integer.valueOf(1))); + lblSwamp.setText("Swamp"); btnAdd.setText("Add"); @@ -168,7 +178,7 @@ public class AddLandDialog extends MageDialog { .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(lblSwamp) .addComponent(spnSwamp, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 16, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 20, Short.MAX_VALUE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(btnAdd) .addComponent(btnCancel)) diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java index f80cbf3c44..ae7e3f079b 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java @@ -49,6 +49,8 @@ import mage.client.MageFrame; import mage.client.remote.Session; import mage.client.table.TournamentPlayerPanel; import mage.game.draft.DraftOptions; +import mage.game.draft.DraftOptions.TimingOption; +import mage.game.tournament.LimitedOptions; import mage.game.tournament.TournamentOptions; import mage.sets.Sets; import mage.util.Logging; @@ -80,6 +82,7 @@ public class NewTournamentDialog extends MageDialog { session = MageFrame.getSession(); this.txtPlayer1Name.setText(session.getUserName()); cbTournamentType.setModel(new DefaultComboBoxModel(session.getTournamentTypes().toArray())); + cbDraftTiming.setModel(new DefaultComboBoxModel(DraftOptions.TimingOption.values())); this.setModal(true); setTournamentOptions(); this.setLocation(150, 100); @@ -108,6 +111,9 @@ public class NewTournamentDialog extends MageDialog { txtPlayer1Name = new javax.swing.JTextField(); pnlOtherPlayers = new javax.swing.JPanel(); jLabel5 = new javax.swing.JLabel(); + pnlDraftOptions = new javax.swing.JPanel(); + cbDraftTiming = new javax.swing.JComboBox(); + jLabel6 = new javax.swing.JLabel(); setTitle("New Tournament"); @@ -178,12 +184,33 @@ public class NewTournamentDialog extends MageDialog { .addComponent(jLabel4) .addComponent(txtPlayer1Name, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(pnlOtherPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, 58, Short.MAX_VALUE)) + .addComponent(pnlOtherPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, 80, Short.MAX_VALUE)) ); jLabel5.setFont(new java.awt.Font("Tahoma", 1, 11)); jLabel5.setText("Packs"); + cbDraftTiming.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" })); + + jLabel6.setText("Timing:"); + + javax.swing.GroupLayout pnlDraftOptionsLayout = new javax.swing.GroupLayout(pnlDraftOptions); + pnlDraftOptions.setLayout(pnlDraftOptionsLayout); + pnlDraftOptionsLayout.setHorizontalGroup( + pnlDraftOptionsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnlDraftOptionsLayout.createSequentialGroup() + .addComponent(jLabel6) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cbDraftTiming, javax.swing.GroupLayout.PREFERRED_SIZE, 161, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(232, Short.MAX_VALUE)) + ); + pnlDraftOptionsLayout.setVerticalGroup( + pnlDraftOptionsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnlDraftOptionsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(cbDraftTiming, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel6)) + ); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( @@ -191,8 +218,8 @@ public class NewTournamentDialog extends MageDialog { .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(pnlPacks, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 525, Short.MAX_VALUE) - .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addComponent(btnOk) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -201,11 +228,13 @@ public class NewTournamentDialog extends MageDialog { .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 113, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(cbTournamentType, 0, 408, Short.MAX_VALUE)) + .addComponent(jLabel5) .addGroup(layout.createSequentialGroup() .addComponent(jLabel2) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(spnNumPlayers, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addComponent(jLabel5)) + .addComponent(spnNumPlayers, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pnlDraftOptions, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) .addContainerGap()) ); layout.setVerticalGroup( @@ -218,13 +247,15 @@ public class NewTournamentDialog extends MageDialog { .addGap(3, 3, 3) .addComponent(jLabel5) .addGap(1, 1, 1) - .addComponent(pnlPacks, javax.swing.GroupLayout.DEFAULT_SIZE, 47, Short.MAX_VALUE) + .addComponent(pnlPacks, javax.swing.GroupLayout.DEFAULT_SIZE, 46, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(spnNumPlayers, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(jLabel2)) - .addGap(19, 19, 19) - .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(pnlDraftOptions, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(spnNumPlayers) + .addComponent(jLabel2))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(btnCancel) @@ -248,10 +279,16 @@ public class NewTournamentDialog extends MageDialog { tOptions.getPlayerTypes().add(player.getPlayerType()); } if (tournamentType.isDraft()) { - tOptions.getDraftOptions().setDraftType(""); - tOptions.getDraftOptions().setTiming(DraftOptions.TimingOption.REGULAR); + DraftOptions options = new DraftOptions(); + options.setDraftType(""); + options.setTiming((TimingOption) this.cbDraftTiming.getSelectedItem()); + tOptions.setLimitedOptions(options); + } + if (tournamentType.isLimited()) { + if (tOptions.getLimitedOptions() == null) + tOptions.setLimitedOptions(new LimitedOptions()); for (JComboBox pack: packs) { - tOptions.getDraftOptions().getSets().add((ExpansionSet) pack.getSelectedItem()); + tOptions.getLimitedOptions().getSets().add((ExpansionSet) pack.getSelectedItem()); } } tOptions.getMatchOptions().setDeckType("Limited"); @@ -294,7 +331,14 @@ public class NewTournamentDialog extends MageDialog { this.spnNumPlayers.setModel(new SpinnerNumberModel(tournamentType.getMinPlayers(), tournamentType.getMinPlayers(), tournamentType.getMaxPlayers(), 1)); this.spnNumPlayers.setEnabled(tournamentType.getMinPlayers() != tournamentType.getMaxPlayers()); createPlayers(tournamentType.getMinPlayers() - 1); - createPacks(tournamentType.getNumBoosters()); + if (tournamentType.isLimited()) { + this.pnlPacks.setVisible(true); + createPacks(tournamentType.getNumBoosters()); + } + else { + this.pnlPacks.setVisible(false); + } + this.pnlDraftOptions.setVisible(tournamentType.isDraft()); } private void createPacks(int numPacks) { @@ -343,13 +387,16 @@ public class NewTournamentDialog extends MageDialog { // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton btnCancel; private javax.swing.JButton btnOk; + private javax.swing.JComboBox cbDraftTiming; private javax.swing.JComboBox cbTournamentType; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JLabel jLabel3; private javax.swing.JLabel jLabel4; private javax.swing.JLabel jLabel5; + private javax.swing.JLabel jLabel6; private javax.swing.JPanel jPanel1; + private javax.swing.JPanel pnlDraftOptions; private javax.swing.JPanel pnlOtherPlayers; private javax.swing.JPanel pnlPacks; private javax.swing.JSpinner spnNumPlayers; 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 e6f01c3b05..17848e48ff 100644 --- a/Mage.Client/src/main/java/mage/client/remote/Client.java +++ b/Mage.Client/src/main/java/mage/client/remote/Client.java @@ -169,11 +169,11 @@ public class Client implements CallbackClient { } else if (callback.getMethod().equals("sideboard")) { TableClientMessage message = (TableClientMessage) callback.getData(); - sideboard(message.getDeck(), message.getTableId()); + sideboard(message.getDeck(), message.getTableId(), message.getTime()); } else if (callback.getMethod().equals("construct")) { TableClientMessage message = (TableClientMessage) callback.getData(); - construct(message.getDeck(), message.getTableId()); + construct(message.getDeck(), message.getTableId(), message.getTime()); } else if (callback.getMethod().equals("draftOver")) { session.getDraft().hideDraft(); @@ -266,12 +266,12 @@ public class Client implements CallbackClient { } } - protected void sideboard(Deck deck, UUID tableId) { - frame.showDeckEditor(DeckEditorMode.Sideboard, deck, tableId); + protected void sideboard(Deck deck, UUID tableId, int time) { + frame.showDeckEditor(DeckEditorMode.Sideboard, deck, tableId, time); } - protected void construct(Deck deck, UUID tableId) { - frame.showDeckEditor(DeckEditorMode.Limited, deck, tableId); + protected void construct(Deck deck, UUID tableId, int time) { + frame.showDeckEditor(DeckEditorMode.Limited, deck, tableId, time); } private void handleException(Exception ex) { diff --git a/Mage.Common/src/mage/view/TableClientMessage.java b/Mage.Common/src/mage/view/TableClientMessage.java index 8b27bfb987..4e4b269a83 100644 --- a/Mage.Common/src/mage/view/TableClientMessage.java +++ b/Mage.Common/src/mage/view/TableClientMessage.java @@ -43,10 +43,12 @@ public class TableClientMessage implements Serializable { private UUID tableId; private UUID gameId; private UUID playerId; + private int time; - public TableClientMessage(Deck deck, UUID tableId) { + public TableClientMessage(Deck deck, UUID tableId, int time) { this.deck = deck; this.tableId = tableId; + this.time = time; } public TableClientMessage(UUID gameId, UUID playerId) { @@ -69,4 +71,8 @@ public class TableClientMessage implements Serializable { public UUID getPlayerId() { return playerId; } + + public int getTime() { + return time; + } } diff --git a/Mage.Common/src/mage/view/TournamentTypeView.java b/Mage.Common/src/mage/view/TournamentTypeView.java index 79b8c98b5c..98d21e865c 100644 --- a/Mage.Common/src/mage/view/TournamentTypeView.java +++ b/Mage.Common/src/mage/view/TournamentTypeView.java @@ -43,6 +43,7 @@ public class TournamentTypeView implements Serializable { private int maxPlayers; private int numBoosters; private boolean draft; + private boolean limited; public TournamentTypeView(TournamentType tournamentType) { this.name = tournamentType.getName(); @@ -50,6 +51,7 @@ public class TournamentTypeView implements Serializable { this.maxPlayers = tournamentType.getMaxPlayers(); this.numBoosters = tournamentType.getNumBoosters(); this.draft = tournamentType.isDraft(); + this.limited = tournamentType.isLimited(); } @Override @@ -76,4 +78,8 @@ public class TournamentTypeView implements Serializable { public boolean isDraft() { return draft; } + + public boolean isLimited() { + return limited; + } } diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/pom.xml b/Mage.Server.Plugins/Mage.Deck.Constructed/pom.xml index 9f24091a7a..e40141d178 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/pom.xml +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/pom.xml @@ -6,7 +6,7 @@ org.mage - mage-root + Mage-Server-Plugins 0.6 diff --git a/Mage.Server.Plugins/Mage.Deck.Limited/pom.xml b/Mage.Server.Plugins/Mage.Deck.Limited/pom.xml index 5b51853cb4..58f46a4469 100644 --- a/Mage.Server.Plugins/Mage.Deck.Limited/pom.xml +++ b/Mage.Server.Plugins/Mage.Deck.Limited/pom.xml @@ -6,7 +6,7 @@ org.mage - mage-root + Mage-Server-Plugins 0.6 diff --git a/Mage.Server.Plugins/Mage.Game.FreeForAll/pom.xml b/Mage.Server.Plugins/Mage.Game.FreeForAll/pom.xml index c5cfa73857..d9e15c941c 100644 --- a/Mage.Server.Plugins/Mage.Game.FreeForAll/pom.xml +++ b/Mage.Server.Plugins/Mage.Game.FreeForAll/pom.xml @@ -6,7 +6,7 @@ org.mage - mage-root + Mage-Server-Plugins 0.6 diff --git a/Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/pom.xml index 5121b4abf7..4d4fb25746 100644 --- a/Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/pom.xml +++ b/Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/pom.xml @@ -6,7 +6,7 @@ org.mage - mage-root + Mage-Server-Plugins 0.6 diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/pom.xml b/Mage.Server.Plugins/Mage.Player.AI.MA/pom.xml index a4671e0e52..f814619e6e 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/pom.xml +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/pom.xml @@ -6,7 +6,7 @@ org.mage - mage-root + Mage-Server-Plugins 0.6 diff --git a/Mage.Server.Plugins/Mage.Player.AI/pom.xml b/Mage.Server.Plugins/Mage.Player.AI/pom.xml index cfbea7e711..c7b14f1288 100644 --- a/Mage.Server.Plugins/Mage.Player.AI/pom.xml +++ b/Mage.Server.Plugins/Mage.Player.AI/pom.xml @@ -6,7 +6,7 @@ org.mage - mage-root + Mage-Server-Plugins 0.6 diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java index eec2a7224e..4f1a120d7f 100644 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java @@ -81,6 +81,7 @@ import mage.game.Game; import mage.game.Table; import mage.game.combat.CombatGroup; import mage.game.permanent.Permanent; +import mage.game.tournament.Tournament; import mage.player.ai.utils.RateCard; import mage.players.Player; import mage.players.PlayerImpl; @@ -774,7 +775,7 @@ public class ComputerPlayer> extends PlayerImpl i } @Override - public void construct(Table table, Deck deck) { + public void construct(Tournament tournament, Deck deck) { //TODO: improve this if (deck.getCards().size() < 40) { while (deck.getCards().size() < 40) { @@ -783,7 +784,7 @@ public class ComputerPlayer> extends PlayerImpl i deck.getSideboard().remove(card); } } - table.fireSubmitDeckEvent(playerId, deck); + tournament.submitDeck(playerId, deck); } @Override diff --git a/Mage.Server.Plugins/Mage.Player.AIMinimax/pom.xml b/Mage.Server.Plugins/Mage.Player.AIMinimax/pom.xml index 12c2767e2d..321eec47b4 100644 --- a/Mage.Server.Plugins/Mage.Player.AIMinimax/pom.xml +++ b/Mage.Server.Plugins/Mage.Player.AIMinimax/pom.xml @@ -6,7 +6,7 @@ org.mage - mage-root + Mage-Server-Plugins 0.6 diff --git a/Mage.Server.Plugins/Mage.Player.Human/pom.xml b/Mage.Server.Plugins/Mage.Player.Human/pom.xml index 51c871d92b..482f08d161 100644 --- a/Mage.Server.Plugins/Mage.Player.Human/pom.xml +++ b/Mage.Server.Plugins/Mage.Player.Human/pom.xml @@ -6,7 +6,7 @@ org.mage - mage-root + Mage-Server-Plugins 0.6 diff --git a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java index 28bfd4aef4..3c1d67d5bc 100644 --- a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java @@ -58,6 +58,7 @@ import mage.filter.common.FilterCreatureForCombat; import mage.game.Game; import mage.game.Table; import mage.game.permanent.Permanent; +import mage.game.tournament.Tournament; import mage.target.Target; import mage.target.TargetAmount; import mage.target.TargetCard; @@ -486,8 +487,8 @@ public class HumanPlayer extends PlayerImpl { } @Override - public void construct(Table table, Deck deck) { - table.fireConstructEvent(playerId, deck); + public void construct(Tournament tournament, Deck deck) { + tournament.fireConstructEvent(playerId, deck); } @Override diff --git a/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/src/mage/tournament/BoosterDraftEliminationTournament.java b/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/src/mage/tournament/BoosterDraftEliminationTournament.java index b9df7a19b7..9160fcccbd 100644 --- a/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/src/mage/tournament/BoosterDraftEliminationTournament.java +++ b/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/src/mage/tournament/BoosterDraftEliminationTournament.java @@ -30,6 +30,7 @@ package mage.tournament; import mage.game.draft.BoosterDraft; import mage.game.draft.Draft; +import mage.game.draft.DraftOptions; import mage.game.events.TableEvent.EventType; import mage.game.tournament.TournamentOptions; import mage.game.tournament.TournamentPlayer; @@ -53,7 +54,7 @@ public class BoosterDraftEliminationTournament extends TournamentSingleEliminati } protected void draft() { - Draft draft = new BoosterDraft(options.getDraftOptions()); + Draft draft = new BoosterDraft((DraftOptions) options.getLimitedOptions()); for (TournamentPlayer player: players.values()) { draft.addPlayer(player.getPlayer()); } diff --git a/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/src/mage/tournament/BoosterDraftEliminationTournamentType.java b/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/src/mage/tournament/BoosterDraftEliminationTournamentType.java index aa67a6c261..a1e2448ba0 100644 --- a/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/src/mage/tournament/BoosterDraftEliminationTournamentType.java +++ b/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/src/mage/tournament/BoosterDraftEliminationTournamentType.java @@ -42,6 +42,7 @@ public class BoosterDraftEliminationTournamentType extends TournamentType + + 4.0.0 + + + org.mage + Mage-Server-Plugins + 0.6 + + + Mage-Tournament-Sealed + jar + Mage Tournament Sealed + + + + ${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-tournament-sealed + + + + + diff --git a/Mage.Server.Plugins/Mage.Tournament.Sealed/src/mage/tournament/SealedEliminationTournament.java b/Mage.Server.Plugins/Mage.Tournament.Sealed/src/mage/tournament/SealedEliminationTournament.java new file mode 100644 index 0000000000..311e34f048 --- /dev/null +++ b/Mage.Server.Plugins/Mage.Tournament.Sealed/src/mage/tournament/SealedEliminationTournament.java @@ -0,0 +1,77 @@ +/* + * 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.tournament; + +import mage.game.tournament.TournamentOptions; +import mage.game.tournament.TournamentSingleElimination; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class SealedEliminationTournament extends TournamentSingleElimination { + + protected enum TournamentStep { + START, OPEN_BOOSTERS, CONSTRUCT, COMPETE, WINNERS + } + + protected TournamentStep currentStep; + + public SealedEliminationTournament(TournamentOptions options) { + super(options); + currentStep = TournamentStep.START; + } + + protected void winners() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void nextStep() { + switch (currentStep) { + case START: + currentStep = TournamentStep.OPEN_BOOSTERS; + openBoosters(); + break; + case OPEN_BOOSTERS: + currentStep = TournamentStep.CONSTRUCT; + construct(); + break; + case CONSTRUCT: + currentStep = TournamentStep.COMPETE; + runTournament(); + break; + case COMPETE: + currentStep = TournamentStep.WINNERS; + winners(); + break; + } + } + +} diff --git a/Mage.Server.Plugins/Mage.Tournament.Sealed/src/mage/tournament/SealedEliminationTournamentType.java b/Mage.Server.Plugins/Mage.Tournament.Sealed/src/mage/tournament/SealedEliminationTournamentType.java new file mode 100644 index 0000000000..c8be382e3e --- /dev/null +++ b/Mage.Server.Plugins/Mage.Tournament.Sealed/src/mage/tournament/SealedEliminationTournamentType.java @@ -0,0 +1,48 @@ +/* + * 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.tournament; + +import mage.game.tournament.TournamentType; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class SealedEliminationTournamentType extends TournamentType { + + public SealedEliminationTournamentType() { + this.name = "Sealed Elimination"; + this.maxPlayers = 16; + this.minPlayers = 4; + this.numBoosters = 6; + this.draft = false; + this.limited = true; + } + +} diff --git a/Mage.Server.Plugins/pom.xml b/Mage.Server.Plugins/pom.xml index 7d79087696..7eba6f0bc3 100644 --- a/Mage.Server.Plugins/pom.xml +++ b/Mage.Server.Plugins/pom.xml @@ -11,7 +11,7 @@ Mage-Server-Plugins pom - Mage Server Plugins + Mage Server Plugins Mage Server Plugins POM @@ -24,6 +24,7 @@ Mage.Player.AI.MA Mage.Player.Human Mage.Tournament.BoosterDraft - + Mage.Tournament.Sealed + \ No newline at end of file diff --git a/Mage.Server/config/config.xml b/Mage.Server/config/config.xml index 4e9c75581f..e66b98593c 100644 --- a/Mage.Server/config/config.xml +++ b/Mage.Server/config/config.xml @@ -15,6 +15,7 @@ + diff --git a/Mage.Server/plugins/mage-player-ai.jar b/Mage.Server/plugins/mage-player-ai.jar index a7989fd3231ba558e96c6f91e1d6b4e10ee544a1..0d84511d774eedc33a5a2c94f94eaf59e9a29aec 100644 GIT binary patch delta 20209 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 Ku&{x@qW%X3LoeL` diff --git a/Mage.Server/plugins/mage-player-aiminimax.jar b/Mage.Server/plugins/mage-player-aiminimax.jar index 9ddd1b6941452680005da8bf40952187cebd13ec..6f0d28c6edcd6e3b15427358fda49a2b28a09e16 100644 GIT binary patch delta 1171 zcmdlphv~o^Cf)#VW)?065D4gSpUA7i><^?&rZ9terxn1|J9Q8>S%OguL~nLwe8dE1 zXt5jx>hEy3v;P$(%fQUQ&_BsoWwQdiFf&-%jBBq3nDNa>lbH{sE;@22=PMZohR2SR z9l4Y@2bleq0W0teHe>}enj$`Mff=RA5fD2rr0#++dNTrr!BP*aAG3fN#~WsYr6#8~ zgB><`QnN8gV)BV*PhR%b&UPEJPk8Y#F)-|yEZ1UJf3WMefq?Dx_(Z4m+xEN+@+#ov zUMg^7OJlBgez%r(TyE}3k4=*UzTLN;CUUxLju02OU4*}Xm9f9E@RF?}=cl~*5HK~S zHpV71cD=x=0`JP6Y@c}}-}`8`TWoVmI=$+mj`{o}vO+qU~mlKxU${GWkc zTgGsm$+H%{rh0=GVeQlh)s7p|n&K73f^lq3Jne4gq+?hiRts=gA&lv}FXvbU-nJaMqV9;h+HK_x<0gKqRqO}(1-V~XT z*TwexU%=}nlYi89Mai@0D9XDUXm8N{D9G~en)I>AR{rNg6FBOB_B!r6F>m9WJR9A& zX2(TM%Ui##`;aI5ZTif!4|-FdZCPfse2&2?wuj$8Tx?c8eD7ajtBCcJ)MLALzIpan zs`Ao&if^=4s< z%RS$g_xJ7G<%6!Q|8KrEfoo^eryqTVF?BDOd7FDFieA>A5xV^3W6pKAejh3e_U+P~ z<@6|I;ks{*C(HuH{;B;kZr6$Ytan+DL&nkhRjoS$VM;LXS+!VJli;Ph97LRi5;F` zdTmD_m}cyR(4n3FVE%F_|2LHH+vNrppVk!wreAjjgK5WZi2BJ;`f0ZxSlp~908DrG sKwhiT6oCf)#VW)?065O7#&Gm%$?*%nBdOkoD`PAh<^cj_Q&vIL_Rh~DhV_=pM2 z&|*2t#0wO$v;P$(%fQUQ&_BsoWwQdiFf&-%jBBq3nDNa>lbH{sE;@22=PMZohR2SR z9l4Y@2bleq0W0teHe>}enj$`Mff=RA5fD2rr0#++dNTrr!BP*aAG3fN#~WsYr6#8~ zYYBpk2m1m_NK9^Qlb*c08Eo9-6V0ByMq8%Z?r1oYz|O?Luwk-Xi(P$e_Zo0B<){38Z~E$p%H$~vH%w@+u(|ix_Fna3 zACG@78~XZ7k6vj%y7*cWZ({Ga7Dg3;I+cdgLig%#9+IBWRPu1f>&1&?e-~IZ9F{&E zz4WEfzdQG8P1&=j1S~U2nxV7EqTWpX+Nne3GRnS|yPfprB}XXSyl=CFU(;e$(nM*_ z&qoWxJ~xHfcZ9epZ4WfEIAFERVUoez+pVl#C#5%P7A~U_;kKfy>M_j17A+$_Cq#YCOXGME4LD>?ovW=a(tI#b!MA2aDlY(Q-K zWz(Cpg&w(D3+}7`J!Q}Ngzf+CUs+`Mgj?%@^{IfbJLl?^*>PRh@3{8-q%g<6Te}Z^ z3-&E?^m*iRP+{A*-U-=@Y<_XW@&E@Y57@Qy)LWDQlTrEP+BVmEN3KH#0t^SL73w2i z>{R3w$y&(HuO-UVRF|+do8w0BnvFN^&wlJvtfY3($@q>r#}1+Ft1_wwB_(V4@9~zI zm)OdzGyibSa&6co|5G+mmuH^R`1yO@Ged6^ZnsNZOP8qId7TYdymwE5a_0A7k2zw0 zGQYA1cr!AIFhlbs6ENdBwVQx)<>bnCdr-okyt~~1OuuV42h+Vhl9L@f6v6D&4o@(> zu_F*nvvxx0$WDJSe>IfIwqW@4JG*v}-p+{d6e(vfB?VZq*Y2rh9v= y!1SpeXD}_$8;O>~%6h{TP=XT}q&7%dbV*}k+vJ7KQj=|4q$Vr$NwMj-gJc2SBjbYr diff --git a/Mage.Server/plugins/mage-player-human.jar b/Mage.Server/plugins/mage-player-human.jar index ea5222287e43b1a544db40ccc675899a305421d1..049c58a1d7c71ac008a58154712ca58a4669e88b 100644 GIT binary patch delta 9211 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%0DDWk_WgE1dyz{O4mk^JDKCMDq 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 Jt??YL{2#f@R*3)r delta 3553 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 GIr<;0fJ0RP diff --git a/Mage.Server/pom.xml b/Mage.Server/pom.xml index f4f5980556..8f76f2ecac 100644 --- a/Mage.Server/pom.xml +++ b/Mage.Server/pom.xml @@ -90,7 +90,7 @@ ${project.groupId} - Mage-Draft-8PlayerBooster + Mage-Tournament-BoosterDraft ${project.version} runtime diff --git a/Mage.Server/release/config/config.xml b/Mage.Server/release/config/config.xml index 8c56e0515d..62c7d6854f 100644 --- a/Mage.Server/release/config/config.xml +++ b/Mage.Server/release/config/config.xml @@ -3,20 +3,20 @@ - - - - + + + + - - + + - - - + + + - - + + diff --git a/Mage.Server/src/main/java/mage/server/Session.java b/Mage.Server/src/main/java/mage/server/Session.java index 6e0cc2480c..d15017b863 100644 --- a/Mage.Server/src/main/java/mage/server/Session.java +++ b/Mage.Server/src/main/java/mage/server/Session.java @@ -102,12 +102,12 @@ public class Session { fireCallback(new ClientCallback("startTournament", new TableClientMessage(tournamentId, playerId))); } - public void sideboard(final Deck deck, final UUID tableId) { - fireCallback(new ClientCallback("sideboard", new TableClientMessage(deck, tableId))); + public void sideboard(final Deck deck, final UUID tableId, final int time) { + fireCallback(new ClientCallback("sideboard", new TableClientMessage(deck, tableId, time))); } - public void construct(final Deck deck, final UUID tableId) { - fireCallback(new ClientCallback("construct", new TableClientMessage(deck, tableId))); + public void construct(final Deck deck, final UUID tableId, final int time) { + fireCallback(new ClientCallback("construct", new TableClientMessage(deck, tableId, time))); } public void watchGame(final UUID gameId) { diff --git a/Mage.Server/src/main/java/mage/server/TableController.java b/Mage.Server/src/main/java/mage/server/TableController.java index d1540b965d..7f707e2ea6 100644 --- a/Mage.Server/src/main/java/mage/server/TableController.java +++ b/Mage.Server/src/main/java/mage/server/TableController.java @@ -68,9 +68,6 @@ import mage.game.tournament.Tournament; import mage.game.tournament.TournamentOptions; import mage.game.tournament.TournamentPlayer; import mage.players.Player; -import mage.server.ChatManager; -import mage.server.Main; -import mage.server.SessionManager; import mage.server.game.DeckValidatorFactory; import mage.server.game.GameFactory; import mage.server.game.GameManager; @@ -88,6 +85,8 @@ public class TableController { private final static Logger logger = Logging.getLogger(TableController.class.getName()); + private static final int SIDEBOARD_TIME = 180; + private UUID sessionId; private UUID chatId; private Table table; @@ -124,9 +123,9 @@ public class TableController { case SIDEBOARD: sideboard(event.getPlayerId(), event.getDeck()); break; - case CONSTRUCT: - construct(event.getPlayerId(), event.getDeck()); - break; +// case CONSTRUCT: +// construct(event.getPlayerId(), event.getDeck()); +// break; case SUBMIT_DECK: submitDeck(event.getPlayerId(), event.getDeck()); break; @@ -200,30 +199,21 @@ public class TableController { if (table.getState() != TableState.SIDEBOARDING && table.getState() != TableState.CONSTRUCTING) { return false; } - String playerName; - if (table.getState() == TableState.SIDEBOARDING) { - MatchPlayer player = match.getPlayer(sessionPlayerMap.get(sessionId)); - playerName = player.getPlayer().getName(); - } - else { - TournamentPlayer player = tournament.getPlayer(sessionPlayerMap.get(sessionId)); - playerName = player.getPlayer().getName(); - } Deck deck = Deck.load(deckList); if (!Main.server.isTestMode() && !validDeck(deck)) { - throw new GameException(playerName + " has an invalid deck for this format"); + throw new GameException("Invalid deck for this format"); } - submitDeck(sessionPlayerMap.get(sessionId), deck); + submitDeck(sessionId, deck); return true; } - private void submitDeck(UUID playerId, Deck deck) { + private void submitDeck(UUID sessionId, Deck deck) { if (table.getState() == TableState.SIDEBOARDING) { - MatchPlayer player = match.getPlayer(playerId); + MatchPlayer player = match.getPlayer(sessionPlayerMap.get(sessionId)); player.submitDeck(deck); } else { - tournament.submitDeck(playerId, deck); + TournamentManager.getInstance().submitDeck(tournament.getId(), sessionId, deck); } } @@ -294,6 +284,7 @@ public class TableController { public synchronized void startTournament(UUID sessionId) { if (sessionId.equals(this.sessionId) && table.getState() == TableState.STARTING) { + table.initTournament(); TournamentManager.getInstance().createTournamentSession(tournament, sessionPlayerMap, table.getId()); SessionManager sessionManager = SessionManager.getInstance(); for (Entry entry: sessionPlayerMap.entrySet()) { @@ -324,29 +315,29 @@ public class TableController { SessionManager sessionManager = SessionManager.getInstance(); for (Entry entry: sessionPlayerMap.entrySet()) { if (entry.getValue().equals(playerId)) { - sessionManager.getSession(entry.getKey()).sideboard(deck, table.getId()); + sessionManager.getSession(entry.getKey()).sideboard(deck, table.getId(), SIDEBOARD_TIME); break; } } } - public void construct() { - table.construct(); - for (TournamentPlayer player: tournament.getPlayers()) { - player.setConstructing(); - player.getPlayer().construct(table, player.getDeck()); - } - } +// public void construct() { +// table.construct(); +// for (TournamentPlayer player: tournament.getPlayers()) { +// player.setConstructing(); +// player.getPlayer().construct(table, player.getDeck()); +// } +// } - private void construct(UUID playerId, Deck deck) { - SessionManager sessionManager = SessionManager.getInstance(); - for (Entry entry: sessionPlayerMap.entrySet()) { - if (entry.getValue().equals(playerId)) { - sessionManager.getSession(entry.getKey()).construct(deck, table.getId()); - break; - } - } - } +// private void construct(UUID playerId, Deck deck) { +// SessionManager sessionManager = SessionManager.getInstance(); +// for (Entry entry: sessionPlayerMap.entrySet()) { +// if (entry.getValue().equals(playerId)) { +// sessionManager.getSession(entry.getKey()).construct(deck, table.getId(), CONSTRUCT_TIME); +// break; +// } +// } +// } public void endGame() { UUID choosingPlayerId = match.getChooser(); diff --git a/Mage.Server/src/main/java/mage/server/TableManager.java b/Mage.Server/src/main/java/mage/server/TableManager.java index 168f535ea5..2a120a9a9e 100644 --- a/Mage.Server/src/main/java/mage/server/TableManager.java +++ b/Mage.Server/src/main/java/mage/server/TableManager.java @@ -161,9 +161,9 @@ public class TableManager { } } - public void construct(UUID tableId) { - controllers.get(tableId).construct(); - } +// public void construct(UUID tableId) { +// controllers.get(tableId).construct(); +// } public void addPlayer(UUID sessionId, UUID tableId, Player player, String playerType, Deck deck) throws GameException { controllers.get(tableId).addPlayer(sessionId, player, playerType, deck); diff --git a/Mage.Server/src/main/java/mage/server/draft/DraftController.java b/Mage.Server/src/main/java/mage/server/draft/DraftController.java index 04fa685b65..dc1854bdf9 100644 --- a/Mage.Server/src/main/java/mage/server/draft/DraftController.java +++ b/Mage.Server/src/main/java/mage/server/draft/DraftController.java @@ -175,7 +175,6 @@ public class DraftController { public void timeout(UUID sessionId) { if (sessionPlayerMap.containsKey(sessionId)) { -// ChatManager.getInstance().broadcast(chatId, "", draft.getPlayer(sessionPlayerMap.get(sessionId)).getPlayer().getName() + " has timed out. Auto picking.", MessageColor.BLACK); draft.autoPick(sessionPlayerMap.get(sessionId)); } } diff --git a/Mage.Server/src/main/java/mage/server/draft/DraftManager.java b/Mage.Server/src/main/java/mage/server/draft/DraftManager.java index ecae582d51..e4fbdff9e8 100644 --- a/Mage.Server/src/main/java/mage/server/draft/DraftManager.java +++ b/Mage.Server/src/main/java/mage/server/draft/DraftManager.java @@ -76,11 +76,11 @@ public class DraftManager { draftControllers.get(draftId).kill(sessionId); } - void timeout(UUID gameId, UUID sessionId) { + public void timeout(UUID gameId, UUID sessionId) { draftControllers.get(gameId).timeout(sessionId); } - void removeDraft(UUID draftId) { + public void removeDraft(UUID draftId) { draftControllers.remove(draftId); } diff --git a/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java b/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java index cbb622cd34..36ce1e3230 100644 --- a/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java +++ b/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java @@ -33,10 +33,12 @@ import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; +import mage.cards.decks.Deck; import mage.game.GameException; import mage.game.Table; import mage.game.draft.Draft; import mage.game.events.Listener; +import mage.game.events.PlayerQueryEvent; import mage.game.events.TableEvent; import mage.game.match.MatchOptions; import mage.game.tournament.Tournament; @@ -64,6 +66,8 @@ public class TournamentController { private ConcurrentHashMap sessionPlayerMap = new ConcurrentHashMap(); private ConcurrentHashMap tournamentSessions = new ConcurrentHashMap(); + private static final int CONSTRUCT_TIME = 600; + public TournamentController(Tournament tournament, ConcurrentHashMap sessionPlayerMap, UUID tableId) { sessionId = UUID.randomUUID(); this.sessionPlayerMap = sessionPlayerMap; @@ -83,15 +87,27 @@ public class TournamentController { ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.BLACK); logger.finest(tournament.getId() + " " + event.getMessage()); break; - case CONSTRUCT: - construct(); - break; case START_DRAFT: startDraft(event.getDraft()); break; case START_MATCH: startMatch(event.getPair(), event.getMatchOptions()); break; + case SUBMIT_DECK: + submitDeck(event.getPlayerId(), event.getDeck()); + break; + } + } + } + ); + tournament.addPlayerQueryEventListener( + new Listener () { + @Override + public void event(PlayerQueryEvent event) { + switch (event.getQueryType()) { + case CONSTRUCT: + construct(event.getPlayerId(), event.getDeck(), event.getMax()); + break; } } } @@ -108,7 +124,7 @@ public class TournamentController { public synchronized void join(UUID sessionId) { UUID playerId = sessionPlayerMap.get(sessionId); - TournamentSession tournamentSession = new TournamentSession(tournament, sessionId, playerId); + TournamentSession tournamentSession = new TournamentSession(tournament, sessionId, tableId, playerId); tournamentSessions.put(playerId, tournamentSession); TournamentPlayer player = tournament.getPlayer(playerId); player.setJoined(); @@ -170,8 +186,21 @@ public class TournamentController { TableManager.getInstance().startDraft(tableId, draft); } - private void construct() { - TableManager.getInstance().construct(tableId); + private synchronized void construct(UUID sessionId, Deck deck, int timeout) { + if (tournamentSessions.containsKey(sessionId)) + tournamentSessions.get(sessionId).construct(deck, timeout); + } + + + public void submitDeck(UUID sessionId, Deck deck) { + tournamentSessions.get(sessionPlayerMap.get(sessionId)).submitDeck(deck); + } + + public void timeout(UUID sessionId) { + if (sessionPlayerMap.containsKey(sessionId)) { + TournamentPlayer player = tournament.getPlayer(sessionPlayerMap.get(sessionId)); + tournament.autoSubmit(sessionPlayerMap.get(sessionId), player.getDeck()); + } } public UUID getSessionId() { diff --git a/Mage.Server/src/main/java/mage/server/tournament/TournamentManager.java b/Mage.Server/src/main/java/mage/server/tournament/TournamentManager.java index 60bd35c705..87b673be42 100644 --- a/Mage.Server/src/main/java/mage/server/tournament/TournamentManager.java +++ b/Mage.Server/src/main/java/mage/server/tournament/TournamentManager.java @@ -30,6 +30,7 @@ package mage.server.tournament; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; +import mage.cards.decks.Deck; import mage.game.tournament.Tournament; import mage.view.TournamentView; @@ -61,6 +62,14 @@ public class TournamentManager { controllers.get(tournamentId).kill(sessionId); } + public void timeout(UUID tournamentId, UUID sessionId) { + controllers.get(tournamentId).timeout(sessionId); + } + + public void submitDeck(UUID tournamentId, UUID sessionId, Deck deck) { + controllers.get(tournamentId).submitDeck(sessionId, deck); + } + public TournamentView getTournamentView(UUID tournamentId) { return controllers.get(tournamentId).getTournamentView(); } diff --git a/Mage.Server/src/main/java/mage/server/tournament/TournamentSession.java b/Mage.Server/src/main/java/mage/server/tournament/TournamentSession.java index bfd4f7ac22..34abc7d3f1 100644 --- a/Mage.Server/src/main/java/mage/server/tournament/TournamentSession.java +++ b/Mage.Server/src/main/java/mage/server/tournament/TournamentSession.java @@ -30,12 +30,17 @@ package mage.server.tournament; import java.rmi.RemoteException; import java.util.UUID; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; +import mage.cards.decks.Deck; import mage.game.tournament.Tournament; import mage.interfaces.callback.ClientCallback; import mage.server.Session; import mage.server.SessionManager; +import mage.server.util.ThreadExecutor; import mage.util.Logging; import mage.view.TournamentView; @@ -48,13 +53,18 @@ public class TournamentSession { protected UUID sessionId; protected UUID playerId; + protected UUID tableId; protected Tournament tournament; protected boolean killed = false; - public TournamentSession(Tournament tournament, UUID sessionId, UUID playerId) { + private ScheduledFuture futureTimeout; + protected static ScheduledExecutorService timeoutExecutor = ThreadExecutor.getInstance().getTimeoutExecutor(); + + public TournamentSession(Tournament tournament, UUID sessionId, UUID tableId, UUID playerId) { this.sessionId = sessionId; this.tournament = tournament; this.playerId = playerId; + this.tableId = tableId; } public boolean init(final TournamentView tournamentView) { @@ -94,6 +104,20 @@ public class TournamentSession { } } + public void construct(Deck deck, int timeout) { + if (!killed) { + setupTimeout(timeout); + Session session = SessionManager.getInstance().getSession(sessionId); + if (session != null) + session.construct(deck, tableId, timeout); + } + } + + public void submitDeck(Deck deck) { + cancelTimeout(); + tournament.submitDeck(playerId, deck); + } + protected void handleRemoteException(RemoteException ex) { logger.log(Level.SEVERE, null, ex); TournamentManager.getInstance().kill(tournament.getId(), sessionId); @@ -103,4 +127,25 @@ public class TournamentSession { killed = true; } + private synchronized void setupTimeout(int seconds) { + cancelTimeout(); + if (seconds > 0) { + futureTimeout = timeoutExecutor.schedule( + new Runnable() { + @Override + public void run() { + TournamentManager.getInstance().timeout(tournament.getId(), sessionId); + } + }, + seconds, TimeUnit.SECONDS + ); + } + } + + private synchronized void cancelTimeout() { + if (futureTimeout != null) { + futureTimeout.cancel(false); + } + } + } diff --git a/Mage/src/mage/game/Table.java b/Mage/src/mage/game/Table.java index 196ccc78c5..93bf40f2a4 100644 --- a/Mage/src/mage/game/Table.java +++ b/Mage/src/mage/game/Table.java @@ -153,10 +153,6 @@ public class Table implements Serializable { state = TableState.SIDEBOARDING; } - public void construct() { - state = TableState.CONSTRUCTING; - } - public String getName() { return this.name; } @@ -177,4 +173,8 @@ public class Table implements Serializable { tableEventSource.addListener(listener); } + public void initTournament() { + state = TableState.CONSTRUCTING; + } + } diff --git a/Mage/src/mage/game/draft/DraftOptions.java b/Mage/src/mage/game/draft/DraftOptions.java index da82bcea58..58b192b4d8 100644 --- a/Mage/src/mage/game/draft/DraftOptions.java +++ b/Mage/src/mage/game/draft/DraftOptions.java @@ -29,18 +29,15 @@ package mage.game.draft; import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import mage.cards.ExpansionSet; +import mage.game.tournament.LimitedOptions; /** * * @author BetaSteward_at_googlemail.com */ -public class DraftOptions implements Serializable { +public class DraftOptions extends LimitedOptions implements Serializable { protected String draftType; - protected List sets = new ArrayList(); protected TimingOption timing; public enum TimingOption { @@ -59,10 +56,6 @@ public class DraftOptions implements Serializable { } } - public List getSets() { - return sets; - } - public String getDraftType() { return draftType; } diff --git a/Mage/src/mage/game/events/PlayerQueryEvent.java b/Mage/src/mage/game/events/PlayerQueryEvent.java index 58ff9e96d2..406d005a73 100644 --- a/Mage/src/mage/game/events/PlayerQueryEvent.java +++ b/Mage/src/mage/game/events/PlayerQueryEvent.java @@ -36,6 +36,7 @@ import mage.abilities.ActivatedAbility; import mage.abilities.TriggeredAbilities; import mage.cards.Card; import mage.cards.Cards; +import mage.cards.decks.Deck; /** * @@ -44,7 +45,7 @@ import mage.cards.Cards; public class PlayerQueryEvent extends EventObject implements ExternalEvent, Serializable { public enum QueryType { - ASK, CHOOSE, CHOOSE_ABILITY, PICK_TARGET, PICK_ABILITY, SELECT, PLAY_MANA, PLAY_X_MANA, AMOUNT, LOOK, PICK_CARD + ASK, CHOOSE, CHOOSE_ABILITY, PICK_TARGET, PICK_ABILITY, SELECT, PLAY_MANA, PLAY_X_MANA, AMOUNT, LOOK, PICK_CARD, CONSTRUCT } private String message; @@ -58,6 +59,7 @@ public class PlayerQueryEvent extends EventObject implements ExternalEvent, Seri private boolean required; private int min; private int max; + private Deck deck; private Map options; private PlayerQueryEvent(UUID playerId, String message, Collection abilities, Set choices, Set targets, Cards cards, QueryType queryType, int min, int max, boolean required, Map options) { @@ -88,6 +90,15 @@ public class PlayerQueryEvent extends EventObject implements ExternalEvent, Seri this.max = time; } + private PlayerQueryEvent(UUID playerId, String message, QueryType queryType, Deck deck, int time) { + super(playerId); + this.queryType = queryType; + this.message = message; + this.playerId = playerId; + this.deck = deck; + this.max = time; + } + public static PlayerQueryEvent askEvent(UUID playerId, String message) { return new PlayerQueryEvent(playerId, message, null, null, null, null, QueryType.ASK, 0, 0, false); } @@ -139,6 +150,11 @@ public class PlayerQueryEvent extends EventObject implements ExternalEvent, Seri return new PlayerQueryEvent(playerId, message, booster, QueryType.PICK_CARD, time); } + public static PlayerQueryEvent construct(UUID playerId, String message, Deck deck, int time) { + return new PlayerQueryEvent(playerId, message, QueryType.CONSTRUCT, deck, time); + } + + public String getMessage() { return message; } @@ -183,6 +199,10 @@ public class PlayerQueryEvent extends EventObject implements ExternalEvent, Seri return max; } + public Deck getDeck() { + return deck; + } + public Map getOptions() { return options; } diff --git a/Mage/src/mage/game/events/PlayerQueryEventSource.java b/Mage/src/mage/game/events/PlayerQueryEventSource.java index 541a1c5f13..61e0e0f0b6 100644 --- a/Mage/src/mage/game/events/PlayerQueryEventSource.java +++ b/Mage/src/mage/game/events/PlayerQueryEventSource.java @@ -35,6 +35,7 @@ import mage.abilities.ActivatedAbility; import mage.abilities.TriggeredAbilities; import mage.cards.Card; import mage.cards.Cards; +import mage.cards.decks.Deck; /** * @@ -101,4 +102,8 @@ public class PlayerQueryEventSource implements EventSource, Se dispatcher.fireEvent(PlayerQueryEvent.pickCard(playerId, message, booster, time)); } + public void construct(UUID playerId, String message, Deck deck, int time) { + dispatcher.fireEvent(PlayerQueryEvent.construct(playerId, message, deck, time)); + } + } diff --git a/Mage/src/mage/game/tournament/LimitedOptions.java b/Mage/src/mage/game/tournament/LimitedOptions.java new file mode 100644 index 0000000000..07cca76151 --- /dev/null +++ b/Mage/src/mage/game/tournament/LimitedOptions.java @@ -0,0 +1,48 @@ +/* + * 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.game.tournament; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import mage.cards.ExpansionSet; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class LimitedOptions implements Serializable { + + protected List sets = new ArrayList(); + + public List getSets() { + return sets; + } + +} diff --git a/Mage/src/mage/game/tournament/Tournament.java b/Mage/src/mage/game/tournament/Tournament.java index 48d267d64d..583301e3f7 100644 --- a/Mage/src/mage/game/tournament/Tournament.java +++ b/Mage/src/mage/game/tournament/Tournament.java @@ -32,6 +32,7 @@ import java.util.Collection; import java.util.UUID; import mage.cards.decks.Deck; import mage.game.events.Listener; +import mage.game.events.PlayerQueryEvent; import mage.game.events.TableEvent; import mage.players.Player; @@ -47,11 +48,15 @@ public interface Tournament { public Collection getPlayers(); public Collection getRounds(); public void submitDeck(UUID playerId, Deck deck); + public void autoSubmit(UUID playerId, Deck deck); public boolean allJoined(); public boolean isDoneConstructing(); public void leave(UUID playerId); public void nextStep(); public void addTableEventListener(Listener listener); - + public void addPlayerQueryEventListener(Listener listener); + public void fireConstructEvent(UUID playerId, Deck deck); + public void fireSubmitDeckEvent(UUID playerId, Deck deck); + } diff --git a/Mage/src/mage/game/tournament/TournamentImpl.java b/Mage/src/mage/game/tournament/TournamentImpl.java index b5ab65afed..979d247627 100644 --- a/Mage/src/mage/game/tournament/TournamentImpl.java +++ b/Mage/src/mage/game/tournament/TournamentImpl.java @@ -38,8 +38,12 @@ import java.util.UUID; import java.util.concurrent.CopyOnWriteArrayList; import java.util.logging.Level; import java.util.logging.Logger; +import mage.cards.Card; +import mage.cards.ExpansionSet; import mage.cards.decks.Deck; import mage.game.events.Listener; +import mage.game.events.PlayerQueryEvent; +import mage.game.events.PlayerQueryEventSource; import mage.game.events.TableEvent; import mage.game.events.TableEvent.EventType; import mage.game.events.TableEventSource; @@ -60,6 +64,7 @@ public abstract class TournamentImpl implements Tournament { protected TournamentOptions options; protected transient TableEventSource tableEventSource = new TableEventSource(); + protected transient PlayerQueryEventSource playerQueryEventSource = new PlayerQueryEventSource(); public TournamentImpl(TournamentOptions options) { this.options = options; @@ -80,6 +85,13 @@ public abstract class TournamentImpl implements Tournament { return players.get(playerId); } + @Override + public void autoSubmit(UUID playerId, Deck deck) { + if (players.containsKey(playerId)) { + players.get(playerId).submitDeck(deck); + } + } + @Override public Collection getPlayers() { return players.values(); @@ -195,8 +207,27 @@ public abstract class TournamentImpl implements Tournament { tableEventSource.addListener(listener); } + @Override + public void fireSubmitDeckEvent(UUID playerId, Deck deck) { + tableEventSource.fireTableEvent(EventType.SUBMIT_DECK, playerId, deck); + } + + @Override + public void addPlayerQueryEventListener(Listener listener) { + playerQueryEventSource.addListener(listener); + } + + @Override + public void fireConstructEvent(UUID playerId, Deck deck) { + TournamentPlayer player = players.get(playerId); + playerQueryEventSource.construct(playerId, "Construct", deck, 600); + } + public void construct() { - tableEventSource.fireTableEvent(EventType.CONSTRUCT); + for (TournamentPlayer player: players.values()) { + player.setConstructing(); + player.getPlayer().construct(this, player.getDeck()); + } synchronized(this) { while (!isDoneConstructing()) { try { @@ -207,6 +238,19 @@ public abstract class TournamentImpl implements Tournament { nextStep(); } + protected void openBoosters() { + for (TournamentPlayer player: this.players.values()) { + player.setDeck(new Deck()); + for (ExpansionSet set: options.limitedOptions.getSets()) { + List booster = set.createBooster(); + for (Card card: booster) { + player.getDeck().getSideboard().add(card); + } + } + } + nextStep(); + } + public void playMatch(TournamentPairing pair) { options.getMatchOptions().getPlayerTypes().clear(); options.getMatchOptions().getPlayerTypes().add(pair.getPlayer1().getPlayerType()); diff --git a/Mage/src/mage/game/tournament/TournamentOptions.java b/Mage/src/mage/game/tournament/TournamentOptions.java index d4ab631b12..141fc6e290 100644 --- a/Mage/src/mage/game/tournament/TournamentOptions.java +++ b/Mage/src/mage/game/tournament/TournamentOptions.java @@ -31,7 +31,6 @@ package mage.game.tournament; import java.io.Serializable; import java.util.ArrayList; import java.util.List; -import mage.game.draft.DraftOptions; import mage.game.match.MatchOptions; /** @@ -44,7 +43,7 @@ public class TournamentOptions implements Serializable { protected String tournamentType; protected List playerTypes = new ArrayList(); protected MatchOptions matchOptions = new MatchOptions("", "Two Player Duel"); - protected DraftOptions draftOptions = new DraftOptions(); + protected LimitedOptions limitedOptions; public TournamentOptions(String name) { this.name = name; @@ -70,8 +69,12 @@ public class TournamentOptions implements Serializable { return matchOptions; } - public DraftOptions getDraftOptions() { - return draftOptions; + public void setLimitedOptions(LimitedOptions limitedOptions) { + this.limitedOptions = limitedOptions; + } + + public LimitedOptions getLimitedOptions() { + return limitedOptions; } } diff --git a/Mage/src/mage/game/tournament/TournamentType.java b/Mage/src/mage/game/tournament/TournamentType.java index 5a6b4172a1..11a40c015e 100644 --- a/Mage/src/mage/game/tournament/TournamentType.java +++ b/Mage/src/mage/game/tournament/TournamentType.java @@ -41,6 +41,7 @@ public class TournamentType > implements Serializabl protected int maxPlayers; protected int numBoosters; protected boolean draft; + protected boolean limited; protected TournamentType() {} @@ -69,4 +70,7 @@ public class TournamentType > implements Serializabl return draft; } + public boolean isLimited() { + return limited; + } } diff --git a/Mage/src/mage/players/Player.java b/Mage/src/mage/players/Player.java index ecba103813..850752feac 100644 --- a/Mage/src/mage/players/Player.java +++ b/Mage/src/mage/players/Player.java @@ -57,6 +57,7 @@ import mage.game.Game; import mage.game.Table; import mage.game.draft.Draft; import mage.game.permanent.Permanent; +import mage.game.tournament.Tournament; import mage.target.Target; import mage.target.TargetAmount; import mage.target.TargetCard; @@ -154,7 +155,7 @@ public interface Player extends MageItem, Copyable { public abstract void assignDamage(int damage, List targets, UUID sourceId, Game game); public abstract int getAmount(int min, int max, String message, Game game); public abstract void sideboard(Table table, Deck deck); - public abstract void construct(Table table, Deck deck); + public abstract void construct(Tournament tournament, Deck deck); public abstract void pickCard(List cards, Deck deck, Draft draft); public void declareAttacker(UUID attackerId, UUID defenderId, Game game); diff --git a/pom.xml b/pom.xml index 6354f84bd3..b259abec65 100644 --- a/pom.xml +++ b/pom.xml @@ -25,12 +25,7 @@ mage.googlecode.com - http://magic--another-game-engine.googlecode.com/svn/trunk/repository - - - java-image-scaling - Java Image Scaling Repository Released - svn:https://java-image-scaling.googlecode.com/svn/repo/released + http://mage.googlecode.com/svn/trunk/repository jetlang.googlecode.com