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 a7989fd323..0d84511d77 100644 Binary files a/Mage.Server/plugins/mage-player-ai.jar and b/Mage.Server/plugins/mage-player-ai.jar differ diff --git a/Mage.Server/plugins/mage-player-aiminimax.jar b/Mage.Server/plugins/mage-player-aiminimax.jar index 9ddd1b6941..6f0d28c6ed 100644 Binary files a/Mage.Server/plugins/mage-player-aiminimax.jar and b/Mage.Server/plugins/mage-player-aiminimax.jar differ diff --git a/Mage.Server/plugins/mage-player-human.jar b/Mage.Server/plugins/mage-player-human.jar index ea5222287e..049c58a1d7 100644 Binary files a/Mage.Server/plugins/mage-player-human.jar and b/Mage.Server/plugins/mage-player-human.jar differ diff --git a/Mage.Server/plugins/mage-tournament-booster-draft.jar b/Mage.Server/plugins/mage-tournament-booster-draft.jar index e48a8b75ad..9b81b4c1bf 100644 Binary files a/Mage.Server/plugins/mage-tournament-booster-draft.jar and b/Mage.Server/plugins/mage-tournament-booster-draft.jar differ 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