mirror of
https://github.com/correl/mage.git
synced 2024-11-15 03:00:16 +00:00
* Added optional rollback current turn and up to 3 previous turns to the battlefield menu. All other players have to agree to the rollback to let it happen.
This commit is contained in:
parent
5736efa103
commit
8acf28eed1
38 changed files with 661 additions and 252 deletions
|
@ -32,20 +32,22 @@
|
|||
<Component id="lblGameType" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="cbGameType" min="-2" pref="398" max="-2" attributes="1"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="cbGameType" min="-2" pref="270" max="-2" attributes="1"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="chkRollbackTurnsAllowed" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="13" max="32767" attributes="0"/>
|
||||
<Component id="lblFreeMulligans" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="spnFreeMulligans" min="-2" pref="50" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="1" max="-2" attributes="0">
|
||||
<Component id="txtName" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="cbDeckType" alignment="0" pref="338" max="32767" attributes="1"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="txtName" max="32767" attributes="0"/>
|
||||
<Component id="cbDeckType" pref="332" max="32767" attributes="1"/>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="lbTimeLimit" alignment="1" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblPassword" alignment="1" min="-2" max="-2" attributes="0"/>
|
||||
|
@ -89,10 +91,10 @@
|
|||
<Component id="cbSkillLevel" min="-2" pref="148" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="spnNumWins" min="-2" pref="50" max="-2" attributes="0"/>
|
||||
<Component id="lblNumWins" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblNumWins" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="spnNumWins" alignment="0" min="-2" pref="50" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Component id="jSeparator2" alignment="1" max="32767" attributes="0"/>
|
||||
|
@ -105,7 +107,7 @@
|
|||
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jSeparator3" pref="606" max="32767" attributes="0"/>
|
||||
<Component id="jSeparator3" pref="586" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
|
@ -133,6 +135,7 @@
|
|||
<Group type="103" alignment="0" groupAlignment="3" attributes="0">
|
||||
<Component id="spnFreeMulligans" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblFreeMulligans" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="chkRollbackTurnsAllowed" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="cbGameType" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
|
@ -147,11 +150,13 @@
|
|||
<Component id="spnNumPlayers" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="lblRange" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblAttack" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="lblSkillLevel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblNumWins" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="lblRange" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblAttack" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
|
@ -171,8 +176,8 @@
|
|||
<EmptySpace min="-2" pref="16" max="-2" attributes="0"/>
|
||||
<Component id="jLabel2" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="pnlOtherPlayers" pref="113" max="32767" attributes="0"/>
|
||||
<EmptySpace pref="13" max="32767" attributes="0"/>
|
||||
<Component id="pnlOtherPlayers" pref="105" max="32767" attributes="0"/>
|
||||
<EmptySpace pref="7" max="32767" attributes="0"/>
|
||||
<Component id="jSeparator1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
|
@ -185,7 +190,7 @@
|
|||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="201" max="-2" attributes="0"/>
|
||||
<Component id="jSeparator3" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="178" max="32767" attributes="0"/>
|
||||
<EmptySpace pref="167" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
|
@ -237,6 +242,12 @@
|
|||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbGameTypeActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="chkRollbackTurnsAllowed">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Allow rollbacks"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="<HTML>Allow to rollback to the start of previous turns<br>
if all players agree.
"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblFreeMulligans">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Free Mulligans:"/>
|
||||
|
|
|
@ -101,6 +101,7 @@ public class NewTableDialog extends MageDialog {
|
|||
cbTimeLimit = new javax.swing.JComboBox();
|
||||
lblGameType = new javax.swing.JLabel();
|
||||
cbGameType = new javax.swing.JComboBox();
|
||||
chkRollbackTurnsAllowed = new javax.swing.JCheckBox();
|
||||
lblFreeMulligans = new javax.swing.JLabel();
|
||||
spnFreeMulligans = new javax.swing.JSpinner();
|
||||
lblNumPlayers = new javax.swing.JLabel();
|
||||
|
@ -144,6 +145,9 @@ public class NewTableDialog extends MageDialog {
|
|||
}
|
||||
});
|
||||
|
||||
chkRollbackTurnsAllowed.setText("Allow rollbacks");
|
||||
chkRollbackTurnsAllowed.setToolTipText("<HTML>Allow to rollback to the start of previous turns<br>\nif all players agree.\n");
|
||||
|
||||
lblFreeMulligans.setText("Free Mulligans:");
|
||||
lblFreeMulligans.setToolTipText("The number of mulligans a player can use without decreasing the number of drawn cards.");
|
||||
|
||||
|
@ -216,18 +220,20 @@ public class NewTableDialog extends MageDialog {
|
|||
.addComponent(lbDeckType)
|
||||
.addComponent(lblGameType))
|
||||
.addGap(6, 6, 6)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(cbGameType, javax.swing.GroupLayout.PREFERRED_SIZE, 398, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(cbGameType, javax.swing.GroupLayout.PREFERRED_SIZE, 270, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(chkRollbackTurnsAllowed)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 13, Short.MAX_VALUE)
|
||||
.addComponent(lblFreeMulligans)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(spnFreeMulligans, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
|
||||
.addComponent(txtName, javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(cbDeckType, javax.swing.GroupLayout.Alignment.LEADING, 0, 338, Short.MAX_VALUE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(txtName)
|
||||
.addComponent(cbDeckType, 0, 332, Short.MAX_VALUE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(lbTimeLimit, javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(lblPassword, javax.swing.GroupLayout.Alignment.TRAILING))
|
||||
|
@ -260,10 +266,10 @@ public class NewTableDialog extends MageDialog {
|
|||
.addComponent(cbAttackOption, javax.swing.GroupLayout.PREFERRED_SIZE, 177, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(cbSkillLevel, javax.swing.GroupLayout.PREFERRED_SIZE, 148, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGap(18, 18, 18)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(lblNumWins)))
|
||||
.addComponent(lblNumWins)
|
||||
.addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addComponent(jSeparator2)
|
||||
.addComponent(player1Panel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(pnlOtherPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
|
@ -272,7 +278,7 @@ public class NewTableDialog extends MageDialog {
|
|||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(jSeparator3, javax.swing.GroupLayout.DEFAULT_SIZE, 606, Short.MAX_VALUE)
|
||||
.addComponent(jSeparator3, javax.swing.GroupLayout.DEFAULT_SIZE, 586, Short.MAX_VALUE)
|
||||
.addContainerGap()))
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
|
@ -294,7 +300,8 @@ public class NewTableDialog extends MageDialog {
|
|||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(spnFreeMulligans, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(lblFreeMulligans))
|
||||
.addComponent(lblFreeMulligans)
|
||||
.addComponent(chkRollbackTurnsAllowed))
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(cbGameType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(lblGameType)))
|
||||
|
@ -305,11 +312,12 @@ public class NewTableDialog extends MageDialog {
|
|||
.addGap(0, 0, 0)
|
||||
.addComponent(spnNumPlayers, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(lblRange)
|
||||
.addComponent(lblAttack)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(lblSkillLevel)
|
||||
.addComponent(lblNumWins))
|
||||
.addComponent(lblNumWins)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(lblRange)
|
||||
.addComponent(lblAttack)))
|
||||
.addGap(0, 0, 0)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(cbRange, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
|
@ -325,8 +333,8 @@ public class NewTableDialog extends MageDialog {
|
|||
.addGap(16, 16, 16)
|
||||
.addComponent(jLabel2)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(pnlOtherPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, 113, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 13, Short.MAX_VALUE)
|
||||
.addComponent(pnlOtherPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, 105, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 7, Short.MAX_VALUE)
|
||||
.addComponent(jSeparator1, 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)
|
||||
|
@ -337,7 +345,7 @@ public class NewTableDialog extends MageDialog {
|
|||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(201, 201, 201)
|
||||
.addComponent(jSeparator3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap(178, Short.MAX_VALUE)))
|
||||
.addContainerGap(167, Short.MAX_VALUE)))
|
||||
);
|
||||
|
||||
pack();
|
||||
|
@ -363,6 +371,7 @@ public class NewTableDialog extends MageDialog {
|
|||
options.setSkillLevel((SkillLevel) this.cbSkillLevel.getSelectedItem());
|
||||
options.setRange((RangeOfInfluence) this.cbRange.getSelectedItem());
|
||||
options.setWinsNeeded((Integer)this.spnNumWins.getValue());
|
||||
options.setRollbackTurnsAllowed(chkRollbackTurnsAllowed.isSelected());
|
||||
options.setFreeMulligans((Integer)this.spnFreeMulligans.getValue());
|
||||
options.setPassword(this.txtPassword.getText());
|
||||
if (!checkMatchOptions(options)) {
|
||||
|
@ -597,6 +606,9 @@ public class NewTableDialog extends MageDialog {
|
|||
this.player1Panel.setDeckFile(deckFile);
|
||||
}
|
||||
this.spnNumWins.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_NUMBER_OF_WINS, "2")));
|
||||
this.chkRollbackTurnsAllowed.setSelected(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_ROLLBACK_TURNS_ALLOWED, "Yes").equals("Yes"));
|
||||
|
||||
|
||||
int range = Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_RANGE, "1"));
|
||||
for (RangeOfInfluence roi :RangeOfInfluence.values()) {
|
||||
if (roi.getRange() == range) {
|
||||
|
@ -633,6 +645,8 @@ public class NewTableDialog extends MageDialog {
|
|||
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_TIME_LIMIT, Integer.toString(options.getPriorityTime()));
|
||||
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_GAME_TYPE, options.getGameType());
|
||||
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_NUMBER_OF_WINS, Integer.toString(options.getWinsNeeded()));
|
||||
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_ROLLBACK_TURNS_ALLOWED, options.isRollbackTurnsAllowed() ? "Yes": "No");
|
||||
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_NUMBER_OF_FREE_MULLIGANS, Integer.toString(options.getFreeMulligans()));
|
||||
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_DECK_FILE, deckFile);
|
||||
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_NUMBER_PLAYERS, spnNumPlayers.getValue().toString());
|
||||
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_RANGE, Integer.toString(options.getRange().getRange()));
|
||||
|
@ -659,6 +673,7 @@ public class NewTableDialog extends MageDialog {
|
|||
private javax.swing.JComboBox cbRange;
|
||||
private javax.swing.JComboBox cbSkillLevel;
|
||||
private javax.swing.JComboBox cbTimeLimit;
|
||||
private javax.swing.JCheckBox chkRollbackTurnsAllowed;
|
||||
private javax.swing.JLabel jLabel1;
|
||||
private javax.swing.JLabel jLabel2;
|
||||
private javax.swing.JSeparator jSeparator1;
|
||||
|
|
|
@ -51,7 +51,11 @@
|
|||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="spnConstructTime" min="-2" pref="50" max="-2" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="spnConstructTime" min="-2" pref="50" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="chkRollbackTurnsAllowed" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="spnNumRounds" min="-2" pref="50" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
|
@ -67,52 +71,49 @@
|
|||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="btnCancel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Component id="lblDraftCube" max="-2" attributes="0"/>
|
||||
<Component id="lblTournamentType" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lbDeckType" max="-2" attributes="0"/>
|
||||
<Component id="lblGameType" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="cbDraftCube" min="-2" pref="290" max="-2" attributes="0"/>
|
||||
<Component id="cbDeckType" alignment="0" min="-2" pref="290" max="-2" attributes="1"/>
|
||||
<Component id="cbGameType" min="-2" pref="290" max="-2" attributes="1"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="cbTournamentType" min="-2" pref="290" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lblFreeMulligans" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="spnFreeMulligans" min="-2" pref="41" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lblNumWins" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="spnNumWins" min="-2" pref="50" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Group type="103" alignment="1" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Component id="lblDraftCube" max="-2" attributes="0"/>
|
||||
<Component id="lblTournamentType" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lbDeckType" max="-2" attributes="0"/>
|
||||
<Component id="lblGameType" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="lblName" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="txtName" min="-2" pref="124" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lbTimeLimit" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cbTimeLimit" min="-2" pref="89" max="-2" attributes="1"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lbSkillLevel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cbSkillLevel" min="-2" pref="112" max="-2" attributes="1"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lblPassword" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="txtPassword" min="-2" pref="56" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="cbDraftCube" min="-2" pref="290" max="-2" attributes="0"/>
|
||||
<Component id="cbDeckType" alignment="0" min="-2" pref="290" max="-2" attributes="1"/>
|
||||
<Component id="cbGameType" min="-2" pref="290" max="-2" attributes="1"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="cbTournamentType" min="-2" pref="290" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lblFreeMulligans" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="spnFreeMulligans" min="-2" pref="41" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lblNumWins" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="spnNumWins" min="-2" pref="50" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="lblName" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="txtName" min="-2" pref="124" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lbTimeLimit" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cbTimeLimit" min="-2" pref="101" max="-2" attributes="1"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="lbSkillLevel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="cbSkillLevel" min="-2" pref="88" max="-2" attributes="1"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lblPassword" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="txtPassword" min="-2" pref="56" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
|
@ -183,10 +184,11 @@
|
|||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="spnConstructTime" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblConstructionTime" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="chkRollbackTurnsAllowed" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="player1Panel" pref="62" max="32767" attributes="0"/>
|
||||
<Component id="player1Panel" pref="64" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="pnlPlayers" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
|
@ -440,6 +442,12 @@
|
|||
<Property name="text" type="java.lang.String" value="Construction Time (Minutes):"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="chkRollbackTurnsAllowed">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Allow rollbacks"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="<HTML>Allow to rollback to the start of previous turns<br> if all players agree. "/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JSpinner" name="spnConstructTime">
|
||||
<Properties>
|
||||
<Property name="toolTipText" type="java.lang.String" value="The time players have to build their deck."/>
|
||||
|
@ -462,7 +470,7 @@
|
|||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="pnlOtherPlayers" alignment="0" pref="5" max="32767" attributes="0"/>
|
||||
<Component id="pnlOtherPlayers" alignment="0" pref="7" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
|
|
|
@ -164,6 +164,7 @@ public class NewTournamentDialog extends MageDialog {
|
|||
cbAllowSpectators = new javax.swing.JCheckBox();
|
||||
lblPlayer1 = new javax.swing.JLabel();
|
||||
lblConstructionTime = new javax.swing.JLabel();
|
||||
chkRollbackTurnsAllowed = new javax.swing.JCheckBox();
|
||||
spnConstructTime = new javax.swing.JSpinner();
|
||||
player1Panel = new mage.client.table.NewPlayerPanel();
|
||||
pnlPlayers = new javax.swing.JPanel();
|
||||
|
@ -297,6 +298,9 @@ public class NewTournamentDialog extends MageDialog {
|
|||
|
||||
lblConstructionTime.setText("Construction Time (Minutes):");
|
||||
|
||||
chkRollbackTurnsAllowed.setText("Allow rollbacks");
|
||||
chkRollbackTurnsAllowed.setToolTipText("<HTML>Allow to rollback to the start of previous turns<br> if all players agree. ");
|
||||
|
||||
spnConstructTime.setToolTipText("The time players have to build their deck.");
|
||||
|
||||
player1Panel.setPreferredSize(new java.awt.Dimension(400, 44));
|
||||
|
@ -312,7 +316,7 @@ public class NewTournamentDialog extends MageDialog {
|
|||
);
|
||||
pnlPlayersLayout.setVerticalGroup(
|
||||
pnlPlayersLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(pnlOtherPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, 5, Short.MAX_VALUE)
|
||||
.addComponent(pnlOtherPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, 7, Short.MAX_VALUE)
|
||||
);
|
||||
|
||||
btnOk.setText("OK");
|
||||
|
@ -357,7 +361,10 @@ public class NewTournamentDialog extends MageDialog {
|
|||
.addComponent(lblConstructionTime)))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(spnConstructTime, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(spnConstructTime, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(chkRollbackTurnsAllowed))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(spnNumRounds, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
|
@ -369,46 +376,44 @@ public class NewTournamentDialog extends MageDialog {
|
|||
.addComponent(btnOk)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnCancel))
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(lblDraftCube)
|
||||
.addComponent(lblTournamentType)
|
||||
.addComponent(lbDeckType)
|
||||
.addComponent(lblGameType))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(cbDraftCube, javax.swing.GroupLayout.PREFERRED_SIZE, 290, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(cbDeckType, javax.swing.GroupLayout.PREFERRED_SIZE, 290, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(cbGameType, javax.swing.GroupLayout.PREFERRED_SIZE, 290, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(cbTournamentType, javax.swing.GroupLayout.PREFERRED_SIZE, 290, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lblFreeMulligans)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(spnFreeMulligans, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lblNumWins)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE))))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(lblName)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(txtName, javax.swing.GroupLayout.PREFERRED_SIZE, 124, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lbTimeLimit)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(cbTimeLimit, javax.swing.GroupLayout.PREFERRED_SIZE, 89, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lbSkillLevel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(cbSkillLevel, javax.swing.GroupLayout.PREFERRED_SIZE, 112, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lblPassword)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(txtPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 56, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addGap(0, 0, 0))))
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(lblDraftCube)
|
||||
.addComponent(lblTournamentType)
|
||||
.addComponent(lbDeckType)
|
||||
.addComponent(lblGameType))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(cbDraftCube, javax.swing.GroupLayout.PREFERRED_SIZE, 290, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(cbDeckType, javax.swing.GroupLayout.PREFERRED_SIZE, 290, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(cbGameType, javax.swing.GroupLayout.PREFERRED_SIZE, 290, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(cbTournamentType, javax.swing.GroupLayout.PREFERRED_SIZE, 290, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lblFreeMulligans)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(spnFreeMulligans, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lblNumWins)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE))))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(lblName)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(txtName, javax.swing.GroupLayout.PREFERRED_SIZE, 124, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lbTimeLimit)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(cbTimeLimit, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(lbSkillLevel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(cbSkillLevel, javax.swing.GroupLayout.PREFERRED_SIZE, 88, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lblPassword)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(txtPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 56, javax.swing.GroupLayout.PREFERRED_SIZE)))))
|
||||
.addComponent(player1Panel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
);
|
||||
|
@ -464,9 +469,10 @@ public class NewTournamentDialog extends MageDialog {
|
|||
.addComponent(lblPlayer1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(spnConstructTime, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(lblConstructionTime)))
|
||||
.addComponent(lblConstructionTime)
|
||||
.addComponent(chkRollbackTurnsAllowed)))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(player1Panel, javax.swing.GroupLayout.DEFAULT_SIZE, 62, Short.MAX_VALUE)
|
||||
.addComponent(player1Panel, javax.swing.GroupLayout.DEFAULT_SIZE, 64, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(pnlPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
|
@ -535,6 +541,7 @@ public class NewTournamentDialog extends MageDialog {
|
|||
tOptions.getMatchOptions().setFreeMulligans((Integer)this.spnFreeMulligans.getValue());
|
||||
tOptions.getMatchOptions().setAttackOption(MultiplayerAttackOption.LEFT);
|
||||
tOptions.getMatchOptions().setRange(RangeOfInfluence.ALL);
|
||||
tOptions.getMatchOptions().setRollbackTurnsAllowed(this.chkRollbackTurnsAllowed.isSelected());
|
||||
saveTournamentSettingsToPrefs(tOptions);
|
||||
|
||||
table = session.createTournamentTable(roomId, tOptions);
|
||||
|
@ -834,6 +841,7 @@ public class NewTournamentDialog extends MageDialog {
|
|||
}
|
||||
}
|
||||
this.cbAllowSpectators.setSelected(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_ALLOW_SPECTATORS, "Yes").equals("Yes"));
|
||||
this.chkRollbackTurnsAllowed.setSelected(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_ALLOW_ROLLBACKS, "Yes").equals("Yes"));
|
||||
}
|
||||
|
||||
private void loadBoosterPacks(String packString) {
|
||||
|
@ -896,6 +904,7 @@ public class NewTournamentDialog extends MageDialog {
|
|||
}
|
||||
}
|
||||
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TOURNAMENT_ALLOW_SPECTATORS, (tOptions.isWatchingAllowed()?"Yes":"No"));
|
||||
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TOURNAMENT_ALLOW_ROLLBACKS, (tOptions.getMatchOptions().isRollbackTurnsAllowed()?"Yes":"No"));
|
||||
}
|
||||
|
||||
|
||||
|
@ -915,6 +924,7 @@ public class NewTournamentDialog extends MageDialog {
|
|||
private javax.swing.JComboBox cbSkillLevel;
|
||||
private javax.swing.JComboBox cbTimeLimit;
|
||||
private javax.swing.JComboBox cbTournamentType;
|
||||
private javax.swing.JCheckBox chkRollbackTurnsAllowed;
|
||||
private javax.swing.JLabel jLabel6;
|
||||
private javax.swing.JLabel lbDeckType;
|
||||
private javax.swing.JLabel lbSkillLevel;
|
||||
|
|
|
@ -162,6 +162,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
public static final String KEY_NEW_TABLE_TIME_LIMIT = "newTableTimeLimit";
|
||||
public static final String KEY_NEW_TABLE_GAME_TYPE = "newTableGameType";
|
||||
public static final String KEY_NEW_TABLE_NUMBER_OF_WINS = "newTableNumberOfWins";
|
||||
public static final String KEY_NEW_TABLE_ROLLBACK_TURNS_ALLOWED = "newTableRollbackTurnsAllowed";
|
||||
public static final String KEY_NEW_TABLE_NUMBER_OF_FREE_MULLIGANS = "newTableNumberOfFreeMulligans";
|
||||
public static final String KEY_NEW_TABLE_DECK_FILE = "newTableDeckFile";
|
||||
public static final String KEY_NEW_TABLE_RANGE = "newTableRange";
|
||||
|
@ -184,6 +185,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
public static final String KEY_NEW_TOURNAMENT_PLAYERS_DRAFT = "newTournamentPlayersDraft";
|
||||
public static final String KEY_NEW_TOURNAMENT_DRAFT_TIMING = "newTournamentDraftTiming";
|
||||
public static final String KEY_NEW_TOURNAMENT_ALLOW_SPECTATORS = "newTournamentAllowSpectators";
|
||||
public static final String KEY_NEW_TOURNAMENT_ALLOW_ROLLBACKS = "newTournamentAllowRollbacks";
|
||||
public static final String KEY_NEW_TOURNAMENT_DECK_FILE = "newTournamentDeckFile";
|
||||
|
||||
// pref setting for deck generator
|
||||
|
|
|
@ -177,12 +177,8 @@ public class UserRequestDialog extends MageDialog {
|
|||
|
||||
private void sendUserReplay(PlayerAction playerAction) {
|
||||
Session session = MageFrame.getSession();
|
||||
switch(playerAction) {
|
||||
case ADD_PERMISSION_TO_SEE_HAND_CARDS:
|
||||
session.sendPlayerAction(playerAction, userRequestMessage.getGameId(), userRequestMessage.getRelatedUserId());
|
||||
break;
|
||||
default:
|
||||
// not supported action
|
||||
if (session != null && playerAction != null) {
|
||||
session.sendPlayerAction(playerAction, userRequestMessage.getGameId(), userRequestMessage.getRelatedUserId());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -483,7 +483,8 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
}
|
||||
}
|
||||
PlayerView player = game.getPlayers().get(playerSeat);
|
||||
PlayAreaPanel sessionPlayer = new PlayAreaPanel(player, bigCard, gameId, true, game.getPriorityTime(), game.isPlayer(), this);
|
||||
PlayAreaPanel sessionPlayer = new PlayAreaPanel(player, bigCard, gameId, game.getPriorityTime(), this,
|
||||
new PlayAreaPanelOptions(game.isPlayer(), true, game.isRollbackTurnsAllowed()));
|
||||
players.put(player.getPlayerId(), sessionPlayer);
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
c.fill = GridBagConstraints.BOTH;
|
||||
|
@ -515,7 +516,8 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
col = numColumns - 1;
|
||||
}
|
||||
player = game.getPlayers().get(playerNum);
|
||||
PlayAreaPanel playerPanel = new PlayAreaPanel(player, bigCard, gameId, false, game.getPriorityTime(), game.isPlayer(), this);
|
||||
PlayAreaPanel playerPanel = new PlayAreaPanel(player, bigCard, gameId, game.getPriorityTime(), this,
|
||||
new PlayAreaPanelOptions(game.isPlayer(), false, game.isRollbackTurnsAllowed()));
|
||||
players.put(player.getPlayerId(), playerPanel);
|
||||
c = new GridBagConstraints();
|
||||
c.fill = GridBagConstraints.BOTH;
|
||||
|
|
|
@ -42,6 +42,7 @@ import javax.swing.BorderFactory;
|
|||
import javax.swing.GroupLayout;
|
||||
import javax.swing.GroupLayout.Alignment;
|
||||
import javax.swing.JCheckBoxMenuItem;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPopupMenu;
|
||||
|
@ -69,8 +70,8 @@ public class PlayAreaPanel extends javax.swing.JPanel {
|
|||
private boolean smallMode = false;
|
||||
private boolean playingMode = true;
|
||||
private final GamePanel gamePanel;
|
||||
private final boolean playerItself;
|
||||
|
||||
private final PlayAreaPanelOptions options;
|
||||
|
||||
private JCheckBoxMenuItem manaPoolMenuItem;
|
||||
private JCheckBoxMenuItem allowViewHandCardsMenuItem;
|
||||
|
||||
|
@ -81,19 +82,18 @@ public class PlayAreaPanel extends javax.swing.JPanel {
|
|||
* @param player
|
||||
* @param bigCard
|
||||
* @param gameId
|
||||
* @param isPlayer true if the client is a player / false if the client is a watcher
|
||||
* @param playerItself true if it's the area of the player itself
|
||||
* @param priorityTime
|
||||
* @param gamePanel */
|
||||
public PlayAreaPanel(PlayerView player, BigCard bigCard, UUID gameId, boolean playerItself, int priorityTime, boolean isPlayer, GamePanel gamePanel) {
|
||||
//this(isPlayer);
|
||||
this.playerItself = playerItself;
|
||||
* @param gamePanel
|
||||
* @param options
|
||||
*/
|
||||
public PlayAreaPanel(PlayerView player, BigCard bigCard, UUID gameId, int priorityTime, GamePanel gamePanel, PlayAreaPanelOptions options) {
|
||||
this.options = options;
|
||||
initComponents();
|
||||
setOpaque(false);
|
||||
battlefieldPanel.setOpaque(false);
|
||||
|
||||
popupMenu = new JPopupMenu();
|
||||
if (isPlayer) {
|
||||
if (options.isPlayer) {
|
||||
addPopupMenuPlayer(player.getUserData().allowRequestShowHandCards());
|
||||
} else {
|
||||
addPopupMenuWatcher();
|
||||
|
@ -242,7 +242,7 @@ public class PlayAreaPanel extends javax.swing.JPanel {
|
|||
|
||||
popupMenu.addSeparator();
|
||||
|
||||
if (!playerItself) {
|
||||
if (!options.playerItself) {
|
||||
menuItem = new JMenuItem("Request permission to see hand cards");
|
||||
popupMenu.add(menuItem);
|
||||
|
||||
|
@ -283,6 +283,63 @@ public class PlayAreaPanel extends javax.swing.JPanel {
|
|||
});
|
||||
}
|
||||
popupMenu.addSeparator();
|
||||
|
||||
if (options.rollbackTurnsAllowed) {
|
||||
ActionListener rollBackActionListener = new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int turnsToRollBack = Integer.parseInt(e.getActionCommand());
|
||||
gamePanel.getSession().sendPlayerAction(PlayerAction.ROLLBACK_TURNS, gameId, turnsToRollBack);
|
||||
}
|
||||
};
|
||||
|
||||
JMenu rollbackMainItem = new JMenu("Roll back");
|
||||
rollbackMainItem.setMnemonic(KeyEvent.VK_R);
|
||||
rollbackMainItem.setToolTipText("The game will be rolled back to the start of the requested turn if all players agree.");
|
||||
popupMenu.add(rollbackMainItem);
|
||||
|
||||
menuItem = new JMenuItem("to the start of the current turn");
|
||||
menuItem.setMnemonic(KeyEvent.VK_C);
|
||||
menuItem.setActionCommand("0");
|
||||
menuItem.addActionListener(rollBackActionListener);
|
||||
rollbackMainItem.add(menuItem);
|
||||
|
||||
menuItem = new JMenuItem("to the start of the previous turn");
|
||||
menuItem.setMnemonic(KeyEvent.VK_P);
|
||||
menuItem.setActionCommand("1");
|
||||
menuItem.addActionListener(rollBackActionListener);
|
||||
rollbackMainItem.add(menuItem);
|
||||
|
||||
menuItem = new JMenuItem("the current turn and the 2 turns before");
|
||||
menuItem.setMnemonic(KeyEvent.VK_2);
|
||||
menuItem.setActionCommand("2");
|
||||
menuItem.addActionListener(rollBackActionListener);
|
||||
rollbackMainItem.add(menuItem);
|
||||
|
||||
menuItem = new JMenuItem("the current turn and the 3 turns before");
|
||||
menuItem.setMnemonic(KeyEvent.VK_3);
|
||||
menuItem.setActionCommand("3");
|
||||
menuItem.addActionListener(rollBackActionListener);
|
||||
rollbackMainItem.add(menuItem);
|
||||
|
||||
popupMenu.addSeparator();
|
||||
|
||||
}
|
||||
|
||||
menuItem = new JMenuItem("Revoke all permission(s) to see your hand cards");
|
||||
menuItem.setMnemonic(KeyEvent.VK_P);
|
||||
menuItem.setToolTipText("Revoke already granted permission for all spectators to see your hand cards.");
|
||||
popupMenu.add(menuItem);
|
||||
|
||||
// revoke permissions to see hand cards
|
||||
menuItem.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
gamePanel.getSession().sendPlayerAction(PlayerAction.REVOKE_PERMISSIONS_TO_SEE_HAND_CARDS, gameId, null);
|
||||
}
|
||||
});
|
||||
|
||||
popupMenu.addSeparator();
|
||||
|
||||
menuItem = new JMenuItem("Concede game");
|
||||
popupMenu.add(menuItem);
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.client.game;
|
||||
|
||||
/**
|
||||
* Defines some options for the PlayAreaPanel
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class PlayAreaPanelOptions {
|
||||
|
||||
public PlayAreaPanelOptions(boolean isPlayer, boolean playerItself, boolean rollbackTurnsAllowed) {
|
||||
this.isPlayer = isPlayer;
|
||||
this.playerItself = playerItself;
|
||||
this.rollbackTurnsAllowed = rollbackTurnsAllowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* true if the client is a player / false if the client is a watcher
|
||||
*/
|
||||
public boolean isPlayer = false;
|
||||
|
||||
/**
|
||||
* true if the player is the client player itself, false if the player is another player playing with the clinet player
|
||||
*/
|
||||
public boolean playerItself = false;
|
||||
|
||||
/**
|
||||
* true if the player can roll back turns if all players agree
|
||||
*/
|
||||
public boolean rollbackTurnsAllowed = false;
|
||||
|
||||
}
|
|
@ -81,6 +81,7 @@ public class GameView implements Serializable {
|
|||
private boolean special = false;
|
||||
private final boolean isPlayer;
|
||||
private final int spellsCastCurrentTurn;
|
||||
private final boolean rollbackTurnsAllowed;
|
||||
|
||||
|
||||
public GameView(GameState state, Game game, UUID createdForPlayerId, UUID watcherUserId) {
|
||||
|
@ -179,7 +180,8 @@ public class GameView implements Serializable {
|
|||
spellsCastCurrentTurn = watcher.getAmountOfSpellsAllPlayersCastOnCurrentTurn();
|
||||
} else {
|
||||
spellsCastCurrentTurn = 0;
|
||||
}
|
||||
}
|
||||
rollbackTurnsAllowed = game.getOptions().rollbackTurnsAllowed;
|
||||
}
|
||||
|
||||
private void checkPaid(UUID uuid, StackAbility stackAbility) {
|
||||
|
@ -322,5 +324,9 @@ public class GameView implements Serializable {
|
|||
public int getSpellsCastCurrentTurn() {
|
||||
return spellsCastCurrentTurn;
|
||||
}
|
||||
|
||||
public boolean isRollbackTurnsAllowed() {
|
||||
return rollbackTurnsAllowed;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -51,9 +51,9 @@ public class CommanderFreeForAll extends GameCommanderImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void init(UUID choosingPlayerId, GameOptions gameOptions) {
|
||||
protected void init(UUID choosingPlayerId) {
|
||||
startingPlayerSkipsDraw = false;
|
||||
super.init(choosingPlayerId, gameOptions);
|
||||
super.init(choosingPlayerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -59,8 +59,8 @@ public class TwoPlayerDuel extends GameImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void init(UUID choosingPlayerId, GameOptions gameOptions) {
|
||||
super.init(choosingPlayerId, gameOptions);
|
||||
protected void init(UUID choosingPlayerId) {
|
||||
super.init(choosingPlayerId);
|
||||
state.getTurnMods().add(new TurnMod(startingPlayerId, PhaseStep.DRAW));
|
||||
}
|
||||
|
||||
|
|
|
@ -554,6 +554,9 @@ public class HumanPlayer extends PlayerImpl {
|
|||
updateGameStatePriority("priority", game);
|
||||
game.firePriorityEvent(playerId);
|
||||
waitForResponse(game);
|
||||
if(game.executingRollback()) {
|
||||
return true;
|
||||
}
|
||||
if (response.getBoolean() != null) {
|
||||
pass(game);
|
||||
return false;
|
||||
|
|
|
@ -43,6 +43,7 @@ import mage.constants.RangeOfInfluence;
|
|||
import mage.constants.TableState;
|
||||
import mage.game.Game;
|
||||
import mage.game.GameException;
|
||||
import mage.game.GameOptions;
|
||||
import mage.game.Seat;
|
||||
import mage.game.Table;
|
||||
import mage.game.draft.Draft;
|
||||
|
@ -551,7 +552,10 @@ public class TableController {
|
|||
try {
|
||||
match.startGame();
|
||||
table.initGame();
|
||||
GameManager.getInstance().createGameSession(match.getGame(), userPlayerMap, table.getId(), choosingPlayerId);
|
||||
GameOptions gameOptions = new GameOptions();
|
||||
gameOptions.rollbackTurnsAllowed = match.getOptions().isRollbackTurnsAllowed();
|
||||
match.getGame().setGameOptions(gameOptions);
|
||||
GameManager.getInstance().createGameSession(match.getGame(), userPlayerMap, table.getId(), choosingPlayerId, gameOptions);
|
||||
String creator = null;
|
||||
StringBuilder opponent = new StringBuilder();
|
||||
for (Entry<UUID, UUID> entry: userPlayerMap.entrySet()) { // no AI players
|
||||
|
|
|
@ -64,6 +64,7 @@ import mage.constants.PlayerAction;
|
|||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.GameException;
|
||||
import mage.game.GameOptions;
|
||||
import mage.game.Table;
|
||||
import mage.game.events.Listener;
|
||||
import mage.game.events.PlayerQueryEvent;
|
||||
|
@ -116,15 +117,23 @@ public class GameController implements GameCallback {
|
|||
private UUID choosingPlayerId;
|
||||
private Future<?> gameFuture;
|
||||
private boolean useTimeout = true;
|
||||
private GameOptions gameOptions;
|
||||
|
||||
private UUID userReqestingRollback;
|
||||
private int turnsToRollback;
|
||||
private int requestsOpen;
|
||||
|
||||
|
||||
public GameController(Game game, ConcurrentHashMap<UUID, UUID> userPlayerMap, UUID tableId, UUID choosingPlayerId) {
|
||||
public GameController(Game game, ConcurrentHashMap<UUID, UUID> userPlayerMap, UUID tableId, UUID choosingPlayerId, GameOptions gameOptions) {
|
||||
gameSessionId = UUID.randomUUID();
|
||||
this.userPlayerMap = userPlayerMap;
|
||||
chatId = ChatManager.getInstance().createChatSession("Game " + game.getId());
|
||||
this.userReqestingRollback = null;
|
||||
this.game = game;
|
||||
this.game.setSaveGame(ConfigSettings.getInstance().isSaveGameActivated());
|
||||
this.tableId = tableId;
|
||||
this.choosingPlayerId = choosingPlayerId;
|
||||
this.gameOptions = gameOptions;
|
||||
for (Player player: game.getPlayers().values()) {
|
||||
if (!player.isHuman()) {
|
||||
useTimeout = false; // no timeout for AI players because of beeing idle
|
||||
|
@ -474,6 +483,56 @@ public class GameController implements GameCallback {
|
|||
case UNDO:
|
||||
game.undo(getPlayerId(userId));
|
||||
break;
|
||||
case ROLLBACK_TURNS: // basic request of a player to rollback
|
||||
if (data instanceof Integer) {
|
||||
turnsToRollback = (Integer) data;
|
||||
if (game.canRollbackTurns(turnsToRollback)) {
|
||||
requestsOpen = requestPermissionToRollback(userId, turnsToRollback);
|
||||
if (requestsOpen == 0) {
|
||||
game.rollbackTurns(turnsToRollback);
|
||||
turnsToRollback = -1;
|
||||
requestsOpen = -1;
|
||||
} else {
|
||||
userReqestingRollback = userId;
|
||||
}
|
||||
} else {
|
||||
UUID playerId = getPlayerId(userId);
|
||||
if (playerId != null) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
game.informPlayer(player, "That turn is not available for rollback.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ADD_PERMISSION_TO_ROLLBACK_TURN:
|
||||
if (userReqestingRollback != null && requestsOpen > 0 && !userId.equals(userReqestingRollback)) {
|
||||
requestsOpen--;
|
||||
if (requestsOpen == 0) {
|
||||
game.rollbackTurns(turnsToRollback);
|
||||
turnsToRollback = -1;
|
||||
userReqestingRollback = null;
|
||||
requestsOpen = -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DENY_PERMISSON_TO_ROLLBACK_TURN: // one player has denied - so cancel the request
|
||||
{
|
||||
UUID playerId = getPlayerId(userId);
|
||||
if (playerId != null) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
if (userReqestingRollback != null && requestsOpen > 0 && !userId.equals(userReqestingRollback)) {
|
||||
turnsToRollback = -1;
|
||||
userReqestingRollback = null;
|
||||
requestsOpen = -1;
|
||||
game.informPlayers("Rollback request denied by " + player.getLogName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CONCEDE:
|
||||
game.concede(getPlayerId(userId));
|
||||
break;
|
||||
|
@ -513,6 +572,23 @@ public class GameController implements GameCallback {
|
|||
}
|
||||
}
|
||||
|
||||
private int requestPermissionToRollback(UUID userIdRequester, int numberTurns) {
|
||||
int requests = 0;
|
||||
for (Player player: game.getState().getPlayers().values()) {
|
||||
User requestedUser = getUserByPlayerId(player.getId());
|
||||
if (player.isInGame() && player.isHuman() &&
|
||||
requestedUser != null &&
|
||||
!requestedUser.getId().equals(userIdRequester)) {
|
||||
requests++;
|
||||
GameSessionPlayer gameSession = gameSessions.get(player.getId());
|
||||
if (gameSession != null) {
|
||||
gameSession.requestPermissionToRollbackTurn(userIdRequester, numberTurns);
|
||||
}
|
||||
}
|
||||
}
|
||||
return requests;
|
||||
}
|
||||
|
||||
private void requestPermissionToSeeHandCards(UUID userIdRequester, UUID userIdGranter) {
|
||||
Player grantingPlayer = game.getPlayer(userIdGranter);
|
||||
if (grantingPlayer != null) {
|
||||
|
|
|
@ -34,6 +34,7 @@ import mage.cards.decks.DeckCardLists;
|
|||
import mage.constants.ManaType;
|
||||
import mage.constants.PlayerAction;
|
||||
import mage.game.Game;
|
||||
import mage.game.GameOptions;
|
||||
import mage.view.GameView;
|
||||
|
||||
/**
|
||||
|
@ -51,8 +52,8 @@ public class GameManager {
|
|||
|
||||
private final ConcurrentHashMap<UUID, GameController> gameControllers = new ConcurrentHashMap<>();
|
||||
|
||||
public UUID createGameSession(Game game, ConcurrentHashMap<UUID, UUID> userPlayerMap, UUID tableId, UUID choosingPlayerId) {
|
||||
GameController gameController = new GameController(game, userPlayerMap, tableId, choosingPlayerId);
|
||||
public UUID createGameSession(Game game, ConcurrentHashMap<UUID, UUID> userPlayerMap, UUID tableId, UUID choosingPlayerId, GameOptions gameOptions) {
|
||||
GameController gameController = new GameController(game, userPlayerMap, tableId, choosingPlayerId, gameOptions);
|
||||
gameControllers.put(game.getId(), gameController);
|
||||
return gameController.getSessionId();
|
||||
}
|
||||
|
|
|
@ -170,6 +170,34 @@ public class GameSessionPlayer extends GameSessionWatcher {
|
|||
}
|
||||
}
|
||||
|
||||
public void requestPermissionToRollbackTurn(UUID requestingUserId, int numberTurns) {
|
||||
if (!killed) {
|
||||
User requestingUser = UserManager.getInstance().getUser(requestingUserId);
|
||||
User requestedUser = UserManager.getInstance().getUser(userId);
|
||||
if (requestedUser != null && requestingUser != null) {
|
||||
String message;
|
||||
switch(numberTurns) {
|
||||
case 0:
|
||||
message = "Allow rollback to the start of the current turn?";
|
||||
break;
|
||||
case 1:
|
||||
message = "Allow rollback to the start of the previous turn?";
|
||||
break;
|
||||
default:
|
||||
message = "Allow to rollback "+numberTurns+ " turns?";
|
||||
}
|
||||
UserRequestMessage userRequestMessage = new UserRequestMessage(
|
||||
"Request by " + requestedUser.getName(), message
|
||||
, PlayerAction.REQUEST_PERMISSION_TO_ROLLBACK_TURN);
|
||||
userRequestMessage.setRelatedUser(requestingUserId, requestingUser.getName());
|
||||
userRequestMessage.setGameId(game.getId());
|
||||
userRequestMessage.setButton1("Accept", PlayerAction.ADD_PERMISSION_TO_ROLLBACK_TURN);
|
||||
userRequestMessage.setButton2("Deny", PlayerAction.DENY_PERMISSON_TO_ROLLBACK_TURN);
|
||||
requestedUser.fireCallback(new ClientCallback("userRequestDialog", game.getId(), userRequestMessage));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void requestPermissionToSeeHandCards(UUID watcherId) {
|
||||
if (!killed) {
|
||||
User watcher = UserManager.getInstance().getUser(watcherId);
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.apache.log4j.Logger;
|
|||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
* @param <T>
|
||||
*/
|
||||
public class GameWorker<T> implements Callable {
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ import java.util.UUID;
|
|||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.common.EquippedCondition;
|
||||
import mage.abilities.decorator.ConditionalContinuousEffect;
|
||||
|
@ -47,23 +48,23 @@ import mage.constants.Zone;
|
|||
*/
|
||||
public class SunspearShikari extends CardImpl {
|
||||
|
||||
private static final String rule1 = "As long as {this} is equipped, it has first strike";
|
||||
private static final String rule2 = "As long as {this} is equipped, it has lifelink";
|
||||
|
||||
public SunspearShikari(UUID ownerId) {
|
||||
super(ownerId, 23, "Sunspear Shikari", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{W}");
|
||||
this.expansionSetCode = "SOM";
|
||||
this.subtype.add("Cat");
|
||||
this.subtype.add("Soldier");
|
||||
|
||||
this.color.setWhite(true);
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(2);
|
||||
|
||||
ConditionalContinuousEffect effect1 = new ConditionalContinuousEffect(new GainAbilitySourceEffect(FirstStrikeAbility.getInstance()), EquippedCondition.getInstance(), rule1);
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect1));
|
||||
ConditionalContinuousEffect effect2 = new ConditionalContinuousEffect(new GainAbilitySourceEffect(LifelinkAbility.getInstance()), EquippedCondition.getInstance(), rule2);
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect2));
|
||||
// As long as Sunspear Shikari is equipped, it has first strike and lifelink.
|
||||
ConditionalContinuousEffect effect1 = new ConditionalContinuousEffect(new GainAbilitySourceEffect(FirstStrikeAbility.getInstance()),
|
||||
EquippedCondition.getInstance(), "As long as {this} is equipped, it has first strike");
|
||||
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect1);
|
||||
ConditionalContinuousEffect effect2 = new ConditionalContinuousEffect(new GainAbilitySourceEffect(LifelinkAbility.getInstance()),
|
||||
EquippedCondition.getInstance(), "and lifelink");
|
||||
ability.addEffect(effect2);
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
public SunspearShikari(final SunspearShikari card) {
|
||||
|
|
|
@ -27,7 +27,7 @@ import java.util.Random;
|
|||
*/
|
||||
public class PlayGameTest extends MageTestBase {
|
||||
|
||||
private static List<String> colorChoices = Arrays.asList("bu", "bg", "br", "bw", "ug", "ur", "uw", "gr", "gw", "rw", "bur", "buw", "bug", "brg", "brw", "bgw", "wur", "wug", "wrg", "rgu");
|
||||
private final static List<String> colorChoices = Arrays.asList("bu", "bg", "br", "bw", "ug", "ur", "uw", "gr", "gw", "rw", "bur", "buw", "bug", "brg", "brw", "bgw", "wur", "wug", "wrg", "rgu");
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
|
@ -67,7 +67,8 @@ public class PlayGameTest extends MageTestBase {
|
|||
long t1 = System.nanoTime();
|
||||
GameOptions options = new GameOptions();
|
||||
options.testMode = true;
|
||||
game.start(computerA.getId(), options);
|
||||
game.setGameOptions(options);
|
||||
game.start(computerA.getId());
|
||||
long t2 = System.nanoTime();
|
||||
|
||||
logger.info("Winner: " + game.getWinner());
|
||||
|
|
|
@ -27,7 +27,7 @@ import java.util.Random;
|
|||
*/
|
||||
public class TestPlayRandomGame extends MageTestBase {
|
||||
|
||||
private static List<String> colorChoices = Arrays.asList("bu", "bg", "br", "bw", "ug", "ur", "uw", "gr", "gw", "rw", "bur", "buw", "bug", "brg", "brw", "bgw", "wur", "wug", "wrg", "rgu");
|
||||
private final static List<String> colorChoices = Arrays.asList("bu", "bg", "br", "bw", "ug", "ur", "uw", "gr", "gw", "rw", "bur", "buw", "bug", "brg", "brw", "bgw", "wur", "wug", "wrg", "rgu");
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
|
@ -58,12 +58,11 @@ public class TestPlayRandomGame extends MageTestBase {
|
|||
game.addPlayer(computerB, deck2);
|
||||
game.loadCards(deck2.getCards(), computerB.getId());
|
||||
|
||||
boolean testMode = true;
|
||||
|
||||
long t1 = System.nanoTime();
|
||||
GameOptions options = new GameOptions();
|
||||
options.testMode = true;
|
||||
game.start(computerA.getId(), options);
|
||||
game.setGameOptions(options);
|
||||
game.start(computerA.getId());
|
||||
long t2 = System.nanoTime();
|
||||
|
||||
logger.info("Winner: " + game.getWinner());
|
||||
|
|
|
@ -172,7 +172,8 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
|
|||
gameOptions.testMode = true;
|
||||
gameOptions.stopOnTurn = stopOnTurn;
|
||||
gameOptions.stopAtStep = stopAtStep;
|
||||
currentGame.start(activePlayer.getId(), gameOptions);
|
||||
currentGame.setGameOptions(gameOptions);
|
||||
currentGame.start(activePlayer.getId());
|
||||
long t2 = System.nanoTime();
|
||||
logger.debug("Winner: " + currentGame.getWinner());
|
||||
logger.info("Test has been executed. Execution time: " + (t2 - t1) / 1000000 + " ms");
|
||||
|
|
|
@ -39,6 +39,7 @@ public enum PlayerAction {
|
|||
PASS_PRIORITY_UNTIL_NEXT_TURN,
|
||||
PASS_PRIORITY_UNTIL_STACK_RESOLVED,
|
||||
PASS_PRIORITY_CANCEL_ALL_ACTIONS,
|
||||
ROLLBACK_TURNS,
|
||||
UNDO,
|
||||
CONCEDE,
|
||||
MANA_AUTO_PAYMENT_ON,
|
||||
|
@ -46,7 +47,10 @@ public enum PlayerAction {
|
|||
RESET_AUTO_SELECT_REPLACEMENT_EFFECTS,
|
||||
REVOKE_PERMISSIONS_TO_SEE_HAND_CARDS,
|
||||
REQUEST_PERMISSION_TO_SEE_HAND_CARDS,
|
||||
REQUEST_PERMISSION_TO_ROLLBACK_TURN,
|
||||
ADD_PERMISSION_TO_SEE_HAND_CARDS,
|
||||
ADD_PERMISSION_TO_ROLLBACK_TURN,
|
||||
DENY_PERMISSON_TO_ROLLBACK_TURN,
|
||||
PERMISSION_REQUESTS_ALLOWED_ON,
|
||||
PERMISSION_REQUESTS_ALLOWED_OFF
|
||||
}
|
|
@ -208,9 +208,7 @@ public interface Game extends MageItem, Serializable {
|
|||
*/
|
||||
PreventionEffectData preventDamage(GameEvent event, Ability source, Game game, boolean preventAllDamage);
|
||||
|
||||
//game play methods
|
||||
void start(UUID choosingPlayerId);
|
||||
void start(UUID choosingPlayerId, GameOptions options);
|
||||
void resume();
|
||||
void pause();
|
||||
boolean isPaused();
|
||||
|
@ -293,5 +291,10 @@ public interface Game extends MageItem, Serializable {
|
|||
int getPriorityTime();
|
||||
void setPriorityTime(int priorityTime);
|
||||
UUID getStartingPlayerId();
|
||||
|
||||
void saveRollBackGameState();
|
||||
boolean canRollbackTurns(int turnsToRollback);
|
||||
void rollbackTurns(int turnsToRollback);
|
||||
boolean executingRollback();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ public abstract class GameCommanderImpl extends GameImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void init(UUID choosingPlayerId, GameOptions gameOptions) {
|
||||
protected void init(UUID choosingPlayerId) {
|
||||
Ability ability = new SimpleStaticAbility(Zone.COMMAND, new InfoEffect("Commander effects"));
|
||||
//Move commander to command zone
|
||||
for (UUID playerId: state.getPlayerList(startingPlayerId)) {
|
||||
|
@ -101,7 +101,7 @@ public abstract class GameCommanderImpl extends GameImpl {
|
|||
|
||||
}
|
||||
this.getState().addAbility(ability, null);
|
||||
super.init(choosingPlayerId, gameOptions);
|
||||
super.init(choosingPlayerId);
|
||||
if (startingPlayerSkipsDraw) {
|
||||
state.getTurnMods().add(new TurnMod(startingPlayerId, PhaseStep.DRAW));
|
||||
}
|
||||
|
|
|
@ -116,6 +116,7 @@ import mage.players.Players;
|
|||
import mage.target.Target;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.TargetPlayer;
|
||||
import mage.util.GameLog;
|
||||
import mage.util.functions.ApplyToPermanent;
|
||||
import mage.watchers.Watchers;
|
||||
import mage.watchers.common.BlockedAttackerWatcher;
|
||||
|
@ -129,6 +130,8 @@ import org.apache.log4j.Logger;
|
|||
|
||||
public abstract class GameImpl implements Game, Serializable {
|
||||
|
||||
private static final int ROLLBACK_TURNS_MAX = 4;
|
||||
|
||||
private static final transient Logger logger = Logger.getLogger(GameImpl.class);
|
||||
|
||||
private static final FilterPermanent filterAura = new FilterPermanent();
|
||||
|
@ -155,7 +158,8 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
private transient Object customData;
|
||||
protected boolean simulation = false;
|
||||
|
||||
protected final UUID id;
|
||||
protected final UUID id;
|
||||
|
||||
protected boolean ready;
|
||||
protected transient TableEventSource tableEventSource = new TableEventSource();
|
||||
protected transient PlayerQueryEventSource playerQueryEventSource = new PlayerQueryEventSource();
|
||||
|
@ -170,6 +174,9 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
protected GameState state;
|
||||
private transient Stack<Integer> savedStates = new Stack<>();
|
||||
protected transient GameStates gameStates = new GameStates();
|
||||
// game states to allow player roll back
|
||||
protected transient Map<Integer, GameState> gameStatesRollBack = new HashMap<>();
|
||||
protected boolean executingRollback;
|
||||
|
||||
protected Date startTime;
|
||||
protected Date endTime;
|
||||
|
@ -206,7 +213,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
this.attackOption = attackOption;
|
||||
this.state = new GameState();
|
||||
this.startLife = startLife;
|
||||
// this.actions = new LinkedList<MageAction>();
|
||||
this.executingRollback = false;
|
||||
}
|
||||
|
||||
public GameImpl(final GameImpl game) {
|
||||
|
@ -232,7 +239,6 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
copyCount++;
|
||||
copyTime += (System.currentTimeMillis() - t1);
|
||||
}
|
||||
// this.actions = new LinkedList<MageAction>();
|
||||
this.stateCheckRequired = game.stateCheckRequired;
|
||||
this.scorePlayer = game.scorePlayer;
|
||||
this.scopeRelevant = game.scopeRelevant;
|
||||
|
@ -268,7 +274,10 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
|
||||
@Override
|
||||
public GameOptions getOptions() {
|
||||
return gameOptions;
|
||||
if (gameOptions != null) {
|
||||
return gameOptions;
|
||||
}
|
||||
return new GameOptions(); // happens during the first game updates
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -610,23 +619,17 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(UUID choosingPlayerId) {
|
||||
start(choosingPlayerId, this.gameOptions != null ? gameOptions : GameOptions.getDefault());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanUp() {
|
||||
gameCards.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(UUID choosingPlayerId, GameOptions options) {
|
||||
public void start(UUID choosingPlayerId) {
|
||||
startTime = new Date();
|
||||
this.gameOptions = options;
|
||||
if (state.getPlayers().values().iterator().hasNext()) {
|
||||
scorePlayer = state.getPlayers().values().iterator().next();
|
||||
init(choosingPlayerId, options);
|
||||
init(choosingPlayerId);
|
||||
play(startingPlayerId);
|
||||
}
|
||||
}
|
||||
|
@ -731,13 +734,26 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
|
||||
private boolean playTurn(Player player) {
|
||||
this.logStartOfTurn(player);
|
||||
if (checkStopOnTurnOption()) {
|
||||
return false;
|
||||
}
|
||||
state.setActivePlayerId(player.getId());
|
||||
player.becomesActivePlayer();
|
||||
state.getTurn().play(this, player.getId());
|
||||
do {
|
||||
if (executingRollback) {
|
||||
executingRollback = false;
|
||||
player = getPlayer(state.getActivePlayerId());
|
||||
for (Player playerObject: getPlayers().values()) {
|
||||
if (playerObject.isInGame()) {
|
||||
playerObject.abortReset();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
state.setActivePlayerId(player.getId());
|
||||
saveRollBackGameState();
|
||||
}
|
||||
this.logStartOfTurn(player);
|
||||
if (checkStopOnTurnOption()) {
|
||||
return false;
|
||||
}
|
||||
state.getTurn().play(this, player);
|
||||
} while (executingRollback);
|
||||
|
||||
if (isPaused() || gameOver(null)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -778,7 +794,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
return false;
|
||||
}
|
||||
|
||||
protected void init(UUID choosingPlayerId, GameOptions gameOptions) {
|
||||
protected void init(UUID choosingPlayerId) {
|
||||
for (Player player: state.getPlayers().values()) {
|
||||
player.beginTurn(this);
|
||||
// init only if match is with timer (>0) and time left was not set yet (== MAX_VALUE).
|
||||
|
@ -1151,6 +1167,9 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
// resetPassed should be called if player performs any action
|
||||
if (player.priority(this)) {
|
||||
if(executingRollback()) {
|
||||
return;
|
||||
}
|
||||
applyEffects();
|
||||
}
|
||||
if (isPaused()) {
|
||||
|
@ -2566,6 +2585,51 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveRollBackGameState() {
|
||||
if (gameOptions.rollbackTurnsAllowed) {
|
||||
int toDelete = getTurnNum()- ROLLBACK_TURNS_MAX;
|
||||
if (toDelete > 0 && gameStatesRollBack.containsKey(toDelete)) {
|
||||
gameStatesRollBack.remove(toDelete);
|
||||
}
|
||||
gameStatesRollBack.put(getTurnNum(), state.copy());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canRollbackTurns(int turnsToRollback) {
|
||||
int turnToGoTo = getTurnNum() - turnsToRollback;
|
||||
return turnToGoTo > 0 && gameStatesRollBack.containsKey(turnToGoTo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void rollbackTurns(int turnsToRollback) {
|
||||
if (gameOptions.rollbackTurnsAllowed) {
|
||||
int turnToGoTo = getTurnNum() - turnsToRollback;
|
||||
if (turnToGoTo < 1 || !gameStatesRollBack.containsKey(turnToGoTo)) {
|
||||
informPlayers(GameLog.getPlayerRequestColoredText("Player request: It's not possible to rollback " + turnsToRollback +" turn(s)"));
|
||||
} else {
|
||||
GameState restore = gameStatesRollBack.get(turnToGoTo);
|
||||
if (restore != null) {
|
||||
informPlayers(GameLog.getPlayerRequestColoredText("Player request: Rolling back to start of turn " + restore.getTurnNum()));
|
||||
for (Player playerObject: getPlayers().values()) {
|
||||
if (playerObject.isHuman() && playerObject.isInGame()) {
|
||||
playerObject.abort();
|
||||
}
|
||||
}
|
||||
state.restore(restore);
|
||||
// because restore uses the objects without copy each copy the state again
|
||||
gameStatesRollBack.put(getTurnNum(), state.copy());
|
||||
executingRollback = true;
|
||||
fireUpdatePlayersEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean executingRollback() {
|
||||
return executingRollback;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -37,4 +37,9 @@ public class GameOptions implements Serializable {
|
|||
* If true, library won't be shuffled at the beginning of the game
|
||||
*/
|
||||
public boolean skipInitShuffling = false;
|
||||
|
||||
/**
|
||||
* If true, players can roll back turn if all players agree
|
||||
*/
|
||||
public boolean rollbackTurnsAllowed = true;
|
||||
}
|
||||
|
|
|
@ -77,19 +77,19 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
|
||||
private final Players players;
|
||||
private final PlayerList playerList;
|
||||
private final Turn turn;
|
||||
private UUID choosingPlayerId; // player that makes a choice at game start
|
||||
|
||||
// revealed cards <Name, <Cards>>, will be reset if all players pass priority
|
||||
private final Revealed revealed;
|
||||
private final Map<UUID, LookedAt> lookedAt = new HashMap<>();
|
||||
private final DelayedTriggeredAbilities delayed;
|
||||
private final SpecialActions specialActions;
|
||||
private final TurnMods turnMods;
|
||||
private final Watchers watchers;
|
||||
|
||||
|
||||
private DelayedTriggeredAbilities delayed;
|
||||
private SpecialActions specialActions;
|
||||
private Watchers watchers;
|
||||
private Turn turn;
|
||||
private TurnMods turnMods;
|
||||
private UUID activePlayerId; // playerId which turn it is
|
||||
private UUID priorityPlayerId; // player that has currently priority
|
||||
private UUID choosingPlayerId; // player that makes a choice at game start
|
||||
private SpellStack stack;
|
||||
private Command command;
|
||||
private Exile exile;
|
||||
|
@ -134,21 +134,24 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
public GameState(final GameState state) {
|
||||
this.players = state.players.copy();
|
||||
this.playerList = state.playerList.copy();
|
||||
this.choosingPlayerId = state.choosingPlayerId;
|
||||
this.revealed = state.revealed.copy();
|
||||
this.lookedAt.putAll(state.lookedAt);
|
||||
this.gameOver = state.gameOver;
|
||||
this.paused = state.paused;
|
||||
|
||||
this.activePlayerId = state.activePlayerId;
|
||||
this.priorityPlayerId = state.priorityPlayerId;
|
||||
this.choosingPlayerId = state.choosingPlayerId;
|
||||
this.turn = state.turn.copy();
|
||||
|
||||
this.stack = state.stack.copy();
|
||||
this.command = state.command.copy();
|
||||
this.exile = state.exile.copy();
|
||||
this.revealed = state.revealed.copy();
|
||||
this.lookedAt.putAll(state.lookedAt);
|
||||
this.battlefield = state.battlefield.copy();
|
||||
this.turnNum = state.turnNum;
|
||||
this.stepNum = state.stepNum;
|
||||
this.extraTurn = state.extraTurn;
|
||||
this.legendaryRuleActive = state.legendaryRuleActive;
|
||||
this.gameOver = state.gameOver;
|
||||
this.effects = state.effects.copy();
|
||||
for (TriggeredAbility trigger: state.triggered) {
|
||||
this.triggered.add(trigger.copy());
|
||||
|
@ -163,7 +166,6 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
this.values.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
this.zones.putAll(state.zones);
|
||||
this.paused = state.paused;
|
||||
this.simultaneousEvents.addAll(state.simultaneousEvents);
|
||||
for (Map.Entry<UUID, CardState> entry: state.cardState.entrySet()) {
|
||||
cardState.put(entry.getKey(), entry.getValue().copy());
|
||||
|
@ -172,6 +174,40 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
this.copiedCards.putAll(state.copiedCards);
|
||||
this.permanentOrderNumber = state.permanentOrderNumber;
|
||||
}
|
||||
|
||||
public void restore(GameState state) {
|
||||
this.activePlayerId = state.activePlayerId;
|
||||
this.priorityPlayerId = state.priorityPlayerId;
|
||||
this.turn = state.turn;
|
||||
|
||||
this.stack = state.stack;
|
||||
this.command = state.command;
|
||||
this.exile = state.exile;
|
||||
this.battlefield = state.battlefield;
|
||||
this.turnNum = state.turnNum;
|
||||
this.stepNum = state.stepNum;
|
||||
this.extraTurn = state.extraTurn;
|
||||
this.legendaryRuleActive = state.legendaryRuleActive;
|
||||
this.effects = state.effects;
|
||||
this.triggered = state.triggered;
|
||||
this.triggers = state.triggers;
|
||||
this.delayed = state.delayed;
|
||||
this.specialActions = state.specialActions;
|
||||
this.combat = state.combat;
|
||||
this.turnMods = state.turnMods;
|
||||
this.watchers = state.watchers;
|
||||
this.values = state.values;
|
||||
for (Player copyPlayer: state.players.values()) {
|
||||
Player origPlayer = players.get(copyPlayer.getId());
|
||||
origPlayer.restore(copyPlayer);
|
||||
}
|
||||
this.zones = state.zones;
|
||||
this.simultaneousEvents = state.simultaneousEvents;
|
||||
this.cardState = state.cardState;
|
||||
this.zoneChangeCounter = state.zoneChangeCounter;
|
||||
this.copiedCards = state.copiedCards;
|
||||
this.permanentOrderNumber = state.permanentOrderNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GameState copy() {
|
||||
|
@ -558,28 +594,6 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
zones.put(id, zone);
|
||||
}
|
||||
|
||||
public void restore(GameState state) {
|
||||
this.stack = state.stack;
|
||||
this.command = state.command;
|
||||
this.effects = state.effects;
|
||||
this.triggers = state.triggers;
|
||||
this.triggered = state.triggered;
|
||||
this.combat = state.combat;
|
||||
this.exile = state.exile;
|
||||
this.battlefield = state.battlefield;
|
||||
this.zones = state.zones;
|
||||
this.values = state.values;
|
||||
for (Player copyPlayer: state.players.values()) {
|
||||
Player origPlayer = players.get(copyPlayer.getId());
|
||||
origPlayer.restore(copyPlayer);
|
||||
}
|
||||
this.simultaneousEvents = state.simultaneousEvents;
|
||||
this.cardState = state.cardState;
|
||||
this.zoneChangeCounter = state.zoneChangeCounter;
|
||||
this.copiedCards = state.copiedCards;
|
||||
this.permanentOrderNumber = state.permanentOrderNumber;
|
||||
}
|
||||
|
||||
public void addSimultaneousEvent(GameEvent event, Game game) {
|
||||
simultaneousEvents.add(event);
|
||||
}
|
||||
|
|
|
@ -42,8 +42,12 @@ public class GameStates implements Serializable {
|
|||
|
||||
private static final transient Logger logger = Logger.getLogger(GameStates.class);
|
||||
|
||||
// private List<byte[]> states = new LinkedList<byte[]>();
|
||||
private final List<GameState> states = new LinkedList<>();
|
||||
// private final List<byte[]> states;
|
||||
private final List<GameState> states;
|
||||
|
||||
public GameStates() {
|
||||
this.states = new LinkedList<>();
|
||||
}
|
||||
|
||||
public void save(GameState gameState) {
|
||||
// states.add(new Copier<GameState>().copyCompressed(gameState));
|
||||
|
@ -60,8 +64,8 @@ public class GameStates implements Serializable {
|
|||
while (states.size() > index + 1) {
|
||||
states.remove(states.size() - 1);
|
||||
}
|
||||
// return new Copier<GameState>().uncompressCopy(states.get(index));
|
||||
logger.trace("Rolling back state: " + index);
|
||||
// return new Copier<GameState>().uncompressCopy(states.get(index));
|
||||
return states.get(index);
|
||||
}
|
||||
return null;
|
||||
|
@ -78,7 +82,7 @@ public class GameStates implements Serializable {
|
|||
|
||||
public GameState get(int index) {
|
||||
if (index < states.size()) {
|
||||
// return new Copier<GameState>().uncompressCopy(states.get(index));
|
||||
// return new Copier<GameState>().uncompressCopy(states.get(index));
|
||||
return states.get(index);
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -74,7 +74,7 @@ public abstract class GameTinyLeadersImpl extends GameImpl{
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void init(UUID choosingPlayerId, GameOptions gameOptions) {
|
||||
protected void init(UUID choosingPlayerId) {
|
||||
Ability ability = new SimpleStaticAbility(Zone.COMMAND, new InfoEffect("Commander effects"));
|
||||
//Move tiny leader to command zone
|
||||
for (UUID playerId: state.getPlayerList(startingPlayerId)) {
|
||||
|
@ -101,7 +101,7 @@ public abstract class GameTinyLeadersImpl extends GameImpl{
|
|||
|
||||
}
|
||||
this.getState().addAbility(ability, null);
|
||||
super.init(choosingPlayerId, gameOptions);
|
||||
super.init(choosingPlayerId);
|
||||
if (startingPlayerSkipsDraw) {
|
||||
state.getTurnMods().add(new TurnMod(startingPlayerId, PhaseStep.DRAW));
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ public class MatchOptions implements Serializable {
|
|||
protected List<String> playerTypes = new ArrayList<>();
|
||||
protected String password;
|
||||
protected SkillLevel skillLevel;
|
||||
protected boolean rollbackTurnsAllowed;
|
||||
|
||||
/**
|
||||
* Time each player has during the game to play using his\her priority.
|
||||
|
@ -159,4 +160,12 @@ public class MatchOptions implements Serializable {
|
|||
public void setSkillLevel(SkillLevel skillLevel) {
|
||||
this.skillLevel = skillLevel;
|
||||
}
|
||||
|
||||
public boolean isRollbackTurnsAllowed() {
|
||||
return rollbackTurnsAllowed;
|
||||
}
|
||||
|
||||
public void setRollbackTurnsAllowed(boolean rollbackTurnsAllowed) {
|
||||
this.rollbackTurnsAllowed = rollbackTurnsAllowed;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
package mage.game.match;
|
||||
|
||||
import java.io.Serializable;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.players.Player;
|
||||
|
@ -36,7 +37,10 @@ import mage.players.Player;
|
|||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class MatchPlayer {
|
||||
public class MatchPlayer implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 42L;
|
||||
|
||||
private int wins;
|
||||
private boolean matchWinner;
|
||||
|
||||
|
@ -45,7 +49,7 @@ public class MatchPlayer {
|
|||
private final String name;
|
||||
|
||||
private boolean quit;
|
||||
private final boolean timerTimeout;
|
||||
//private final boolean timerTimeout;
|
||||
private boolean doneSideboarding;
|
||||
private int priorityTimeLeft;
|
||||
|
||||
|
@ -56,7 +60,7 @@ public class MatchPlayer {
|
|||
this.wins = 0;
|
||||
this.doneSideboarding = true;
|
||||
this.quit = false;
|
||||
this.timerTimeout = false;
|
||||
//this.timerTimeout = false;
|
||||
this.name = player.getName();
|
||||
this.matchWinner = false;
|
||||
}
|
||||
|
|
|
@ -113,6 +113,9 @@ public abstract class Phase implements Serializable {
|
|||
currentStep = step;
|
||||
if (!game.getState().getTurnMods().skipStep(activePlayerId, getStep().getType())) {
|
||||
playStep(game);
|
||||
if (game.executingRollback()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!game.isSimulation() && checkStopOnStepOption(game)) {
|
||||
return false;
|
||||
|
@ -201,6 +204,9 @@ public abstract class Phase implements Serializable {
|
|||
prePriority(game, activePlayerId);
|
||||
if (!game.isPaused() && !game.gameOver(null)) {
|
||||
currentStep.priority(game, activePlayerId, false);
|
||||
if(game.executingRollback()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!game.isPaused() && !game.gameOver(null)) {
|
||||
postPriority(game, activePlayerId);
|
||||
|
|
|
@ -117,30 +117,34 @@ public class Turn implements Serializable {
|
|||
return null;
|
||||
}
|
||||
|
||||
public void play(Game game, UUID activePlayerId) {
|
||||
public void play(Game game, Player activePlayer) {
|
||||
activePlayer.becomesActivePlayer();
|
||||
this.setDeclareAttackersStepStarted(false);
|
||||
if (game.isPaused() || game.gameOver(null)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (game.getState().getTurnMods().skipTurn(activePlayerId)) {
|
||||
if (game.getState().getTurnMods().skipTurn(activePlayer.getId())) {
|
||||
return;
|
||||
}
|
||||
|
||||
checkTurnIsControlledByOtherPlayer(game, activePlayerId);
|
||||
checkTurnIsControlledByOtherPlayer(game, activePlayer.getId());
|
||||
|
||||
this.activePlayerId = activePlayerId;
|
||||
this.activePlayerId = activePlayer.getId();
|
||||
resetCounts();
|
||||
game.getPlayer(activePlayerId).beginTurn(game);
|
||||
game.getPlayer(activePlayer.getId()).beginTurn(game);
|
||||
for (Phase phase: phases) {
|
||||
if (game.isPaused() || game.gameOver(null)) {
|
||||
return;
|
||||
}
|
||||
if (!isEndTurnRequested() || phase.getType().equals(TurnPhase.END)) {
|
||||
currentPhase = phase;
|
||||
game.fireEvent(new GameEvent(GameEvent.EventType.PHASE_CHANGED, activePlayerId, null, activePlayerId));
|
||||
if (!game.getState().getTurnMods().skipPhase(activePlayerId, currentPhase.getType())) {
|
||||
if (phase.play(game, activePlayerId)) {
|
||||
game.fireEvent(new GameEvent(GameEvent.EventType.PHASE_CHANGED, activePlayer.getId(), null, activePlayer.getId()));
|
||||
if (!game.getState().getTurnMods().skipPhase(activePlayer.getId(), currentPhase.getType())) {
|
||||
if (phase.play(game, activePlayer.getId())) {
|
||||
if(game.executingRollback()) {
|
||||
return;
|
||||
}
|
||||
//20091005 - 500.4/703.4n
|
||||
game.emptyManaPools();
|
||||
game.saveState(false);
|
||||
|
|
|
@ -280,6 +280,7 @@ public interface Player extends MageItem, Copyable<Player> {
|
|||
void leave();
|
||||
void concede(Game game);
|
||||
void abort();
|
||||
void abortReset();
|
||||
void skip();
|
||||
|
||||
// priority, undo, ...
|
||||
|
|
|
@ -369,8 +369,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
this.canPaySacrificeCost = player.canPaySacrificeCost();
|
||||
this.loseByZeroOrLessLife = player.canLoseByZeroOrLessLife();
|
||||
this.canPlayCardsFromGraveyard = player.canPlayCardsFromGraveyard();
|
||||
this.alternativeSourceCosts.addAll(player.getAlternativeSourceCosts());
|
||||
this.storedBookmark = player.getStoredBookmark();
|
||||
this.alternativeSourceCosts.addAll(player.getAlternativeSourceCosts());
|
||||
|
||||
this.topCardRevealed = player.isTopCardRevealed();
|
||||
this.playersUnderYourControl.clear();
|
||||
|
@ -385,7 +384,9 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
this.castSourceIdWithAlternateMana = player.getCastSourceIdWithAlternateMana();
|
||||
this.castSourceIdManaCosts = player.getCastSourceIdManaCosts();
|
||||
|
||||
this.usersAllowedToSeeHandCards.addAll(player.getUsersAllowedToSeeHandCards());
|
||||
// Don't restore!
|
||||
// this.storedBookmark
|
||||
// this.usersAllowedToSeeHandCards
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1855,7 +1856,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
passedAllTurns = false;
|
||||
passedUntilEndOfTurn = true;
|
||||
passedUntilStackResolved = false;
|
||||
skippedAtLeastOnce = !game.getTurn().getStepType().equals(PhaseStep.END_TURN);
|
||||
skippedAtLeastOnce = !PhaseStep.END_TURN.equals(game.getTurn().getStepType());
|
||||
this.skip();
|
||||
break;
|
||||
case PASS_PRIORITY_UNTIL_NEXT_TURN: // F4
|
||||
|
@ -3126,4 +3127,9 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
return matchPlayer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void abortReset() {
|
||||
abort = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ import java.util.zip.GZIPOutputStream;
|
|||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
* @param <T>
|
||||
*/
|
||||
public class Copier<T> {
|
||||
|
||||
|
@ -95,8 +96,7 @@ public class Copier<T> {
|
|||
|
||||
public T uncompressCopy(byte[] buffer) {
|
||||
T copy = null;
|
||||
try {
|
||||
ObjectInputStream in = new CopierObjectInputStream(loader, new GZIPInputStream(new ByteArrayInputStream(buffer)));
|
||||
try (ObjectInputStream in = new CopierObjectInputStream(loader, new GZIPInputStream(new ByteArrayInputStream(buffer)))) {
|
||||
copy = (T) in.readObject();
|
||||
}
|
||||
catch(IOException e) {
|
||||
|
|
|
@ -38,6 +38,7 @@ import mage.ObjectColor;
|
|||
public class GameLog {
|
||||
|
||||
static final String LOG_COLOR_PLAYER = "#20B2AA"; // LightSeaGreen
|
||||
static final String LOG_COLOR_PLAYER_REQUEST = "#D2691E"; // Chocolate
|
||||
static final String LOG_COLOR_GREEN = "#90EE90"; // LightGreen
|
||||
static final String LOG_COLOR_RED = "#FF6347"; // Tomato
|
||||
static final String LOG_COLOR_BLUE = "#87CEFA"; // LightSkyBlue
|
||||
|
@ -64,6 +65,10 @@ public class GameLog {
|
|||
public static String getColoredPlayerName(String name) {
|
||||
return "<font color=\'" + LOG_COLOR_PLAYER + "\'>" + name + "</font>";
|
||||
}
|
||||
|
||||
public static String getPlayerRequestColoredText(String name) {
|
||||
return "<font color=\'" + LOG_COLOR_PLAYER_REQUEST + "\'>" + name + "</font>";
|
||||
}
|
||||
|
||||
private static String getColorName(ObjectColor objectColor) {
|
||||
if (objectColor.isMulticolored()) {
|
||||
|
|
Loading…
Reference in a new issue