mirror of
https://github.com/correl/mage.git
synced 2024-12-25 19:25:41 +00:00
* GUI: added auto-choose for replacement effects (remember answer in dialog + reset answer in popup menu + new option in preferences; #4360, #328, #4219, #6676, #7914);
This commit is contained in:
parent
c081d3fa33
commit
c9ab896d24
11 changed files with 311 additions and 77 deletions
|
@ -324,9 +324,9 @@ public class PickCheckBoxDialog extends MageDialog {
|
|||
|
||||
if (item != null) {
|
||||
if (choice.isKeyChoice()) {
|
||||
choice.setChoiceByKey(item.getKey());
|
||||
choice.setChoiceByKey(item.getKey(), false);
|
||||
} else {
|
||||
choice.setChoice(item.getKey());
|
||||
choice.setChoice(item.getKey(), false);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
|
|
|
@ -161,7 +161,8 @@
|
|||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="cbSpecial" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="btOK" linkSize="3" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
|
@ -177,6 +178,7 @@
|
|||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="btCancel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="btOK" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="cbSpecial" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
|
@ -203,6 +205,11 @@
|
|||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btCancelActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="cbSpecial">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Remember choose"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
|
|
|
@ -18,10 +18,11 @@ import mage.client.util.gui.MageDialogState;
|
|||
public class PickChoiceDialog extends MageDialog {
|
||||
|
||||
Choice choice;
|
||||
|
||||
java.util.List<KeyValueItem> allItems = new ArrayList<>();
|
||||
DefaultListModel<KeyValueItem> dataModel = new DefaultListModel<>();
|
||||
|
||||
final private static String HTML_TEMPLATE = "<html><div style='text-align: center;'>%s</div></html>";
|
||||
final private static String HTML_HEADERS_TEMPLATE = "<html><div style='text-align: center;'>%s</div></html>";
|
||||
|
||||
public void showDialog(Choice choice) {
|
||||
showDialog(choice, null, null, null);
|
||||
|
@ -40,9 +41,13 @@ public class PickChoiceDialog extends MageDialog {
|
|||
|
||||
setLabelText(this.labelMessage, choice.getMessage());
|
||||
setLabelText(this.labelSubMessage, choice.getSubMessage());
|
||||
|
||||
btCancel.setEnabled(!choice.isRequired());
|
||||
|
||||
// special choice (example: auto-choose answer next time)
|
||||
cbSpecial.setVisible(choice.isSpecialEnabled());
|
||||
cbSpecial.setText(choice.getSpecialText());
|
||||
cbSpecial.setToolTipText(choice.getSpecialHint());
|
||||
|
||||
// 2 modes: string or key-values
|
||||
// sore data in allItems for inremental filtering
|
||||
// http://logicbig.com/tutorials/core-java-tutorial/swing/list-filter/
|
||||
|
@ -199,7 +204,7 @@ public class PickChoiceDialog extends MageDialog {
|
|||
|
||||
private void setLabelText(JLabel label, String text) {
|
||||
if ((text != null) && !text.equals("")) {
|
||||
label.setText(String.format(HTML_TEMPLATE, text));
|
||||
label.setText(String.format(HTML_HEADERS_TEMPLATE, text));
|
||||
label.setVisible(true);
|
||||
} else {
|
||||
label.setText("");
|
||||
|
@ -247,6 +252,7 @@ public class PickChoiceDialog extends MageDialog {
|
|||
|
||||
public boolean setChoice() {
|
||||
KeyValueItem item = (KeyValueItem) this.listChoices.getSelectedValue();
|
||||
boolean isSpecial = choice.isSpecialEnabled() && cbSpecial.isSelected();
|
||||
|
||||
// auto select one item (after incemental filtering)
|
||||
if ((item == null) && (this.listChoices.getModel().getSize() == 1)) {
|
||||
|
@ -256,12 +262,23 @@ public class PickChoiceDialog extends MageDialog {
|
|||
|
||||
if (item != null) {
|
||||
if (choice.isKeyChoice()) {
|
||||
choice.setChoiceByKey(item.getKey());
|
||||
choice.setChoiceByKey(item.getKey(), isSpecial);
|
||||
} else {
|
||||
choice.setChoice(item.getKey());
|
||||
choice.setChoice(item.getKey(), isSpecial);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
// special choice can be empty
|
||||
if (choice.isSpecialEnabled() && choice.isSpecialCanBeEmpty()) {
|
||||
if (choice.isKeyChoice()) {
|
||||
choice.setChoiceByKey(null, isSpecial);
|
||||
} else {
|
||||
choice.setChoice(null, isSpecial);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// nothing to choose
|
||||
choice.clearChoice();
|
||||
return false;
|
||||
}
|
||||
|
@ -311,6 +328,7 @@ public class PickChoiceDialog extends MageDialog {
|
|||
panelCommands = new javax.swing.JPanel();
|
||||
btOK = new javax.swing.JButton();
|
||||
btCancel = new javax.swing.JButton();
|
||||
cbSpecial = new javax.swing.JCheckBox();
|
||||
|
||||
setResizable(true);
|
||||
|
||||
|
@ -386,19 +404,22 @@ public class PickChoiceDialog extends MageDialog {
|
|||
}
|
||||
});
|
||||
|
||||
cbSpecial.setText("Remember choose");
|
||||
|
||||
javax.swing.GroupLayout panelCommandsLayout = new javax.swing.GroupLayout(panelCommands);
|
||||
panelCommands.setLayout(panelCommandsLayout);
|
||||
panelCommandsLayout.setHorizontalGroup(
|
||||
panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(panelCommandsLayout.createSequentialGroup()
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(cbSpecial)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(btOK)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
panelCommandsLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, btCancel, btOK);
|
||||
panelCommandsLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {btCancel, btOK});
|
||||
|
||||
panelCommandsLayout.setVerticalGroup(
|
||||
panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
|
@ -406,7 +427,8 @@ public class PickChoiceDialog extends MageDialog {
|
|||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(btCancel)
|
||||
.addComponent(btOK))
|
||||
.addComponent(btOK)
|
||||
.addComponent(cbSpecial))
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
|
@ -460,6 +482,7 @@ public class PickChoiceDialog extends MageDialog {
|
|||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton btCancel;
|
||||
private javax.swing.JButton btOK;
|
||||
private javax.swing.JCheckBox cbSpecial;
|
||||
private javax.swing.JTextField editSearch;
|
||||
private javax.swing.JLabel labelMessage;
|
||||
private javax.swing.JLabel labelSearch;
|
||||
|
|
|
@ -4082,8 +4082,8 @@
|
|||
<Component id="checkBoxEndTurnOthers" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="phases_stopSettings" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="phases_stopSettings" pref="291" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
|
@ -4182,7 +4182,7 @@
|
|||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridLayout">
|
||||
<Property name="columns" type="int" value="1"/>
|
||||
<Property name="rows" type="int" value="9"/>
|
||||
<Property name="rows" type="int" value="10"/>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JCheckBox" name="cbStopAttack">
|
||||
|
@ -4281,8 +4281,8 @@
|
|||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="cbAutoOrderTrigger">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Set order for your triggers automatically if all have the same text"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="<HTML>If activated the order to put on the stack your triggers that trigger at the same time<br/>
is set automatically if all have the same text."/>
|
||||
<Property name="text" type="java.lang.String" value="TRIGGERS: auto-choose triggers order for same rule texts (put same triggers to the stack at default order)"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="<HTML>If you put same triggers with same texts on the stack then auto-choose their order.<br/>
You can change that settings anytime at the game."/>
|
||||
<Property name="actionCommand" type="java.lang.String" value=""/>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[300, 25]"/>
|
||||
|
@ -4292,6 +4292,19 @@
|
|||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbAutoOrderTriggerActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="cbUseSameSettingsForReplacementEffect">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="REPLACEMENT EFFECTS: use same auto-choose settings for same cards (choose replacement effects order dialog)"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="<HTML>If you setup auto-choose for one object/card then it will be applied for all other objects with same name.<br/>
You can change that settings anytime at the game."/>
|
||||
<Property name="actionCommand" type="java.lang.String" value=""/>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[300, 25]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbUseSameSettingsForReplacementEffectActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
|
|
|
@ -134,6 +134,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
public static final String KEY_PASS_PRIORITY_CAST = "passPriorityCast";
|
||||
public static final String KEY_PASS_PRIORITY_ACTIVATION = "passPriorityActivation";
|
||||
public static final String KEY_AUTO_ORDER_TRIGGER = "autoOrderTrigger";
|
||||
public static final String KEY_USE_SAME_SETTINGS_FOR_SAME_REPLACEMENT_EFFECTS = "useSameSettingsForSameReplacementEffects";
|
||||
public static final String KEY_USE_FIRST_MANA_ABILITY = "useFirstManaAbility";
|
||||
|
||||
// mana auto payment
|
||||
|
@ -501,6 +502,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
cbPassPriorityCast = new javax.swing.JCheckBox();
|
||||
cbPassPriorityActivation = new javax.swing.JCheckBox();
|
||||
cbAutoOrderTrigger = new javax.swing.JCheckBox();
|
||||
cbUseSameSettingsForReplacementEffect = new javax.swing.JCheckBox();
|
||||
tabImages = new javax.swing.JPanel();
|
||||
panelCardImages = new javax.swing.JPanel();
|
||||
cbUseDefaultImageFolder = new javax.swing.JCheckBox();
|
||||
|
@ -1405,7 +1407,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
jLabelEndOfTurn.setText("End of turn:");
|
||||
|
||||
phases_stopSettings.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "SKIP settings"));
|
||||
phases_stopSettings.setLayout(new java.awt.GridLayout(9, 1));
|
||||
phases_stopSettings.setLayout(new java.awt.GridLayout(10, 1));
|
||||
|
||||
cbStopAttack.setSelected(true);
|
||||
cbStopAttack.setText("STOP skips on declare attackers if attackers are available");
|
||||
|
@ -1493,8 +1495,8 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
});
|
||||
phases_stopSettings.add(cbPassPriorityActivation);
|
||||
|
||||
cbAutoOrderTrigger.setText("Set order for your triggers automatically if all have the same text");
|
||||
cbAutoOrderTrigger.setToolTipText("<HTML>If activated the order to put on the stack your triggers that trigger at the same time<br/>\nis set automatically if all have the same text.");
|
||||
cbAutoOrderTrigger.setText("TRIGGERS: auto-choose triggers order for same rule texts (put same triggers to the stack at default order)");
|
||||
cbAutoOrderTrigger.setToolTipText("<HTML>If you put same triggers with same texts on the stack then auto-choose their order.<br/>\nYou can change that settings anytime at the game.");
|
||||
cbAutoOrderTrigger.setActionCommand("");
|
||||
cbAutoOrderTrigger.setPreferredSize(new java.awt.Dimension(300, 25));
|
||||
cbAutoOrderTrigger.addActionListener(new java.awt.event.ActionListener() {
|
||||
|
@ -1504,6 +1506,17 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
});
|
||||
phases_stopSettings.add(cbAutoOrderTrigger);
|
||||
|
||||
cbUseSameSettingsForReplacementEffect.setText("REPLACEMENT EFFECTS: use same auto-choose settings for same cards (choose replacement effects order dialog)");
|
||||
cbUseSameSettingsForReplacementEffect.setToolTipText("<HTML>If you setup auto-choose for one object/card then it will be applied for all other objects with same name.<br/>\nYou can change that settings anytime at the game.");
|
||||
cbUseSameSettingsForReplacementEffect.setActionCommand("");
|
||||
cbUseSameSettingsForReplacementEffect.setPreferredSize(new java.awt.Dimension(300, 25));
|
||||
cbUseSameSettingsForReplacementEffect.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cbUseSameSettingsForReplacementEffectActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
phases_stopSettings.add(cbUseSameSettingsForReplacementEffect);
|
||||
|
||||
org.jdesktop.layout.GroupLayout tabPhasesLayout = new org.jdesktop.layout.GroupLayout(tabPhases);
|
||||
tabPhases.setLayout(tabPhasesLayout);
|
||||
tabPhasesLayout.setHorizontalGroup(
|
||||
|
@ -1614,8 +1627,8 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
.add(jLabelEndOfTurn)
|
||||
.add(checkBoxEndTurnOthers))
|
||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
|
||||
.add(phases_stopSettings, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.add(phases_stopSettings, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 291, Short.MAX_VALUE)
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
tabsPanel.addTab("Phases & Priority", tabPhases);
|
||||
|
@ -2925,6 +2938,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
save(prefs, dialog.cbPassPriorityCast, KEY_PASS_PRIORITY_CAST, "true", "false", UPDATE_CACHE_POLICY);
|
||||
save(prefs, dialog.cbPassPriorityActivation, KEY_PASS_PRIORITY_ACTIVATION, "true", "false", UPDATE_CACHE_POLICY);
|
||||
save(prefs, dialog.cbAutoOrderTrigger, KEY_AUTO_ORDER_TRIGGER, "true", "false", UPDATE_CACHE_POLICY);
|
||||
save(prefs, dialog.cbUseSameSettingsForReplacementEffect, KEY_USE_SAME_SETTINGS_FOR_SAME_REPLACEMENT_EFFECTS, "true", "false", UPDATE_CACHE_POLICY);
|
||||
|
||||
// images
|
||||
save(prefs, dialog.cbUseDefaultImageFolder, KEY_CARD_IMAGES_USE_DEFAULT, "true", "false", UPDATE_CACHE_POLICY);
|
||||
|
@ -3309,6 +3323,10 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
}
|
||||
}//GEN-LAST:event_sliderGUISizeStateChanged
|
||||
|
||||
private void cbUseSameSettingsForReplacementEffectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbUseSameSettingsForReplacementEffectActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cbUseSameSettingsForReplacementEffectActionPerformed
|
||||
|
||||
private void showProxySettings() {
|
||||
Connection.ProxyType proxyType = (Connection.ProxyType) cbProxyType.getSelectedItem();
|
||||
switch (proxyType) {
|
||||
|
@ -3465,7 +3483,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
load(prefs, dialog.cbPassPriorityCast, KEY_PASS_PRIORITY_CAST, "true", "false");
|
||||
load(prefs, dialog.cbPassPriorityActivation, KEY_PASS_PRIORITY_ACTIVATION, "true", "false");
|
||||
load(prefs, dialog.cbAutoOrderTrigger, KEY_AUTO_ORDER_TRIGGER, "true", "true");
|
||||
|
||||
load(prefs, dialog.cbUseSameSettingsForReplacementEffect, KEY_USE_SAME_SETTINGS_FOR_SAME_REPLACEMENT_EFFECTS, "true", "true");
|
||||
}
|
||||
|
||||
private static void loadGuiSize(Preferences prefs) {
|
||||
|
@ -3996,6 +4014,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PASS_PRIORITY_CAST, "true").equals("true"),
|
||||
PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PASS_PRIORITY_ACTIVATION, "true").equals("true"),
|
||||
PreferencesDialog.getCachedValue(PreferencesDialog.KEY_AUTO_ORDER_TRIGGER, "true").equals("true"),
|
||||
PreferencesDialog.getCachedValue(PreferencesDialog.KEY_USE_SAME_SETTINGS_FOR_SAME_REPLACEMENT_EFFECTS, "true").equals("true"),
|
||||
PreferencesDialog.getCachedValue(PreferencesDialog.KEY_USE_FIRST_MANA_ABILITY, "false").equals("true"),
|
||||
userStrId
|
||||
);
|
||||
|
@ -4069,6 +4088,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
private javax.swing.JCheckBox cbUseDefaultBattleImage;
|
||||
private javax.swing.JCheckBox cbUseDefaultImageFolder;
|
||||
private javax.swing.JCheckBox cbUseRandomBattleImage;
|
||||
private javax.swing.JCheckBox cbUseSameSettingsForReplacementEffect;
|
||||
private javax.swing.JLabel chatFontSizeLabel;
|
||||
private javax.swing.JCheckBox checkBoxBeforeCOthers;
|
||||
private javax.swing.JCheckBox checkBoxBeforeCYou;
|
||||
|
|
|
@ -108,7 +108,7 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
|
||||
private boolean initComponents;
|
||||
|
||||
private Timer resizeTimer; // can't be final
|
||||
private final Timer resizeTimer; // can't be final
|
||||
|
||||
private enum PopUpMenuType {
|
||||
TRIGGER_ORDER
|
||||
|
@ -128,6 +128,7 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
Map<String, Serializable> options;
|
||||
Set<UUID> targets;
|
||||
}
|
||||
|
||||
private final LastGameData lastGameData = new LastGameData();
|
||||
|
||||
|
||||
|
@ -1746,18 +1747,22 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
// TODO: remember last choices and search incremental for same events?
|
||||
PickChoiceDialog pickChoice = new PickChoiceDialog();
|
||||
pickChoice.showDialog(choice, objectId, choiceWindowState);
|
||||
|
||||
// special mode adds # to the answer (server side code must process that prefix, see replacementEffectChoice)
|
||||
String specialPrefix = choice.isChosenSpecial() ? "#" : "";
|
||||
|
||||
String valueToSend;
|
||||
if (choice.isKeyChoice()) {
|
||||
SessionHandler.sendPlayerString(gameId, choice.getChoiceKey());
|
||||
/* // old code, auto complete was for auto scripting?
|
||||
if (pickChoice.isAutoSelect()) {
|
||||
SessionHandler.sendPlayerString(gameId, '#' + choice.getChoiceKey());
|
||||
} else {
|
||||
SessionHandler.sendPlayerString(gameId, choice.getChoiceKey());
|
||||
}*/
|
||||
valueToSend = choice.getChoiceKey();
|
||||
} else {
|
||||
valueToSend = choice.getChoice();
|
||||
SessionHandler.sendPlayerString(gameId, choice.getChoice());
|
||||
}
|
||||
SessionHandler.sendPlayerString(gameId, valueToSend == null ? null : specialPrefix + valueToSend);
|
||||
|
||||
// keep dialog position
|
||||
choiceWindowState = new MageDialogState(pickChoice);
|
||||
|
||||
pickChoice.removeDialog();
|
||||
}
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
protected final Choice replacementEffectChoice;
|
||||
private static final Logger logger = Logger.getLogger(HumanPlayer.class);
|
||||
|
||||
protected HashSet<String> autoSelectReplacementEffects = new HashSet<>();
|
||||
protected HashSet<String> autoSelectReplacementEffects = new LinkedHashSet<>(); // must be sorted
|
||||
protected ManaCost currentlyUnpaidMana;
|
||||
|
||||
protected Set<UUID> triggerAutoOrderAbilityFirst = new HashSet<>();
|
||||
|
@ -96,9 +96,16 @@ public class HumanPlayer extends PlayerImpl {
|
|||
|
||||
public HumanPlayer(String name, RangeOfInfluence range, int skill) {
|
||||
super(name, range);
|
||||
human = true;
|
||||
|
||||
replacementEffectChoice = new ChoiceImpl(true);
|
||||
replacementEffectChoice.setMessage("Choose replacement effect to resolve first");
|
||||
human = true;
|
||||
replacementEffectChoice.setSpecial(
|
||||
true,
|
||||
false,
|
||||
"Remember answer",
|
||||
"Choose same answer next time (you can reset saved answers by battlefield popup menu)"
|
||||
);
|
||||
}
|
||||
|
||||
public HumanPlayer(final HumanPlayer player) {
|
||||
|
@ -289,6 +296,8 @@ public class HumanPlayer extends PlayerImpl {
|
|||
if (falseText != null) {
|
||||
options.put("UI.right.btn.text", falseText);
|
||||
}
|
||||
|
||||
// auto-answer
|
||||
if (source != null) {
|
||||
Boolean answer = requestAutoAnswerId.get(source.getOriginalId() + "#" + message);
|
||||
if (answer != null) {
|
||||
|
@ -359,11 +368,20 @@ public class HumanPlayer extends PlayerImpl {
|
|||
return 0;
|
||||
}
|
||||
|
||||
// use auto-choice:
|
||||
// - uses "always first" logic (choose in same order as user answer saves)
|
||||
// - search same effects by text (object name [id]: rules)
|
||||
// - autoSelectReplacementEffects is sorted set
|
||||
// - must get "same settings" option between cycle/response (user can change it by preferences)
|
||||
|
||||
boolean useSameSettings = getControllingPlayersUserData(game).isUseSameSettingsForReplacementEffects();
|
||||
if (!autoSelectReplacementEffects.isEmpty()) {
|
||||
for (String autoKey : autoSelectReplacementEffects) {
|
||||
for (String autoText : autoSelectReplacementEffects) {
|
||||
int count = 0;
|
||||
// find effect with same saved text
|
||||
for (String effectKey : rEffects.keySet()) {
|
||||
if (effectKey.equals(autoKey)) {
|
||||
String currentText = prepareReplacementText(rEffects.get(effectKey), useSameSettings);
|
||||
if (currentText.equals(autoText)) {
|
||||
return count;
|
||||
}
|
||||
count++;
|
||||
|
@ -371,10 +389,11 @@ public class HumanPlayer extends PlayerImpl {
|
|||
}
|
||||
}
|
||||
|
||||
replacementEffectChoice.clearChoice();
|
||||
replacementEffectChoice.getChoices().clear();
|
||||
replacementEffectChoice.setKeyChoices(rEffects);
|
||||
|
||||
// Check if there are different ones
|
||||
// if same choices then select first
|
||||
int differentChoices = 0;
|
||||
String lastChoice = "";
|
||||
for (String value : replacementEffectChoice.getKeyChoices().values()) {
|
||||
|
@ -397,11 +416,18 @@ public class HumanPlayer extends PlayerImpl {
|
|||
|
||||
logger.debug("Choose effect: " + response.getString());
|
||||
if (response.getString() != null) {
|
||||
// save auto-choice (effect's text)
|
||||
if (response.getString().startsWith("#")) {
|
||||
autoSelectReplacementEffects.add(response.getString().substring(1));
|
||||
replacementEffectChoice.setChoiceByKey(response.getString().substring(1));
|
||||
replacementEffectChoice.setChoiceByKey(response.getString().substring(1), true);
|
||||
if (replacementEffectChoice.isChosen()) {
|
||||
// put auto-choice to the end
|
||||
useSameSettings = getControllingPlayersUserData(game).isUseSameSettingsForReplacementEffects();
|
||||
String effectText = prepareReplacementText(replacementEffectChoice.getChoiceValue(), useSameSettings);
|
||||
autoSelectReplacementEffects.remove(effectText);
|
||||
autoSelectReplacementEffects.add(effectText);
|
||||
}
|
||||
} else {
|
||||
replacementEffectChoice.setChoiceByKey(response.getString());
|
||||
replacementEffectChoice.setChoiceByKey(response.getString(), false);
|
||||
}
|
||||
|
||||
if (replacementEffectChoice.getChoiceKey() != null) {
|
||||
|
@ -419,6 +445,14 @@ public class HumanPlayer extends PlayerImpl {
|
|||
return 0;
|
||||
}
|
||||
|
||||
private String prepareReplacementText(String fullText, boolean useSameSettingsForDifferentObjects) {
|
||||
// remove object id from the rules text (example: object [abd]: rules -> object : rules)
|
||||
if (useSameSettingsForDifferentObjects) {
|
||||
fullText = fullText.replaceAll("\\[\\w+\\]", "");
|
||||
}
|
||||
return fullText;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean choose(Outcome outcome, Choice choice, Game game) {
|
||||
if (gameInCheckPlayableState(game)) {
|
||||
|
|
|
@ -189,7 +189,7 @@ public class ContinuousEffects implements Serializable {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
logger.error("No abilities for continuous effect: " + effect.toString());
|
||||
logger.error("No abilities for continuous effect: " + effect);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -1282,7 +1282,7 @@ public class ContinuousEffects implements Serializable {
|
|||
logger.error("Effect is null: " + source.toString());
|
||||
return;
|
||||
} else if (source == null) {
|
||||
logger.warn("Adding effect without ability : " + effect.toString());
|
||||
logger.warn("Adding effect without ability : " + effect);
|
||||
}
|
||||
switch (effect.getEffectType()) {
|
||||
case REPLACEMENT:
|
||||
|
@ -1369,6 +1369,8 @@ public class ContinuousEffects implements Serializable {
|
|||
}
|
||||
|
||||
public Map<String, String> getReplacementEffectsTexts(Map<ReplacementEffect, Set<Ability>> rEffects, Game game) {
|
||||
// warning, autoSelectReplacementEffects uses [object id] in texts as different settings,
|
||||
// so if you change keys or texts logic then don't forget to change auto-choose too
|
||||
Map<String, String> texts = new LinkedHashMap<>();
|
||||
for (Map.Entry<ReplacementEffect, Set<Ability>> entry : rEffects.entrySet()) {
|
||||
if (entry.getValue() != null) {
|
||||
|
|
|
@ -1,55 +1,92 @@
|
|||
|
||||
|
||||
package mage.choices;
|
||||
|
||||
import mage.util.Copyable;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com, JayDi85
|
||||
*/
|
||||
public interface Choice {
|
||||
public interface Choice extends Serializable, Copyable<Choice> {
|
||||
|
||||
String getMessage();
|
||||
|
||||
void setMessage(String message);
|
||||
|
||||
String getSubMessage();
|
||||
|
||||
void setSubMessage(String subMessage);
|
||||
|
||||
void clearChoice();
|
||||
|
||||
boolean isChosen();
|
||||
|
||||
boolean isChosenSpecial();
|
||||
|
||||
boolean isRequired();
|
||||
|
||||
Choice copy();
|
||||
// special mode for all choices
|
||||
void setSpecial(boolean enabled, boolean canBeEmpty, String text, String hint);
|
||||
|
||||
boolean isSpecialEnabled();
|
||||
|
||||
boolean isSpecialCanBeEmpty();
|
||||
|
||||
String getSpecialText();
|
||||
|
||||
String getSpecialHint();
|
||||
|
||||
// string choice
|
||||
void setChoices(Set<String> choices);
|
||||
|
||||
Set<String> getChoices();
|
||||
void setChoice(String choice);
|
||||
|
||||
void setChoice(String choice, boolean isSpecial);
|
||||
|
||||
String getChoice();
|
||||
|
||||
default void setChoice(String choice) {
|
||||
setChoice(choice, false);
|
||||
}
|
||||
|
||||
// key-value choice
|
||||
boolean isKeyChoice();
|
||||
|
||||
void setKeyChoices(Map<String, String> choices);
|
||||
|
||||
Map<String, String> getKeyChoices();
|
||||
void setChoiceByKey(String choiceKey);
|
||||
|
||||
void setChoiceByKey(String choiceKey, boolean isSpecial);
|
||||
|
||||
String getChoiceKey();
|
||||
|
||||
String getChoiceValue();
|
||||
|
||||
default void setChoiceByKey(String choiceKey) {
|
||||
setChoiceByKey(choiceKey, false);
|
||||
}
|
||||
|
||||
// search
|
||||
boolean isSearchEnabled();
|
||||
|
||||
void setSearchEnabled(boolean isEnabled);
|
||||
|
||||
void setSearchText(String searchText);
|
||||
|
||||
String getSearchText();
|
||||
|
||||
// sorting
|
||||
boolean isSortEnabled();
|
||||
|
||||
void setSortData(Map<String, Integer> sortData);
|
||||
|
||||
Map<String, Integer> getSortData();
|
||||
|
||||
// random choice
|
||||
// random choice (for AI usage)
|
||||
void setRandomChoice();
|
||||
|
||||
boolean setChoiceByAnswers(List<String> answers, boolean removeSelectAnswerFromList);
|
||||
}
|
||||
|
|
|
@ -2,15 +2,15 @@ package mage.choices;
|
|||
|
||||
import mage.util.RandomUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com, JayDi85
|
||||
*/
|
||||
public class ChoiceImpl implements Choice, Serializable {
|
||||
public class ChoiceImpl implements Choice {
|
||||
|
||||
protected boolean chosen;
|
||||
protected boolean chosenNormal;
|
||||
protected boolean chosenSpecial;
|
||||
protected final boolean required;
|
||||
protected String choice;
|
||||
protected String choiceKey;
|
||||
|
@ -22,6 +22,13 @@ public class ChoiceImpl implements Choice, Serializable {
|
|||
protected boolean searchEnabled = true; // enable for all windows by default
|
||||
protected String searchText;
|
||||
|
||||
// special button with #-answer
|
||||
// warning, only for human's GUI, not AI
|
||||
protected boolean specialEnabled = false;
|
||||
protected boolean specialCanBeEmpty = false; // enable if you want to select "nothing", but not cancel
|
||||
protected String specialText = "";
|
||||
protected String specialHint = "";
|
||||
|
||||
public ChoiceImpl() {
|
||||
this(false);
|
||||
}
|
||||
|
@ -30,9 +37,10 @@ public class ChoiceImpl implements Choice, Serializable {
|
|||
this.required = required;
|
||||
}
|
||||
|
||||
public ChoiceImpl(ChoiceImpl choice) {
|
||||
public ChoiceImpl(final ChoiceImpl choice) {
|
||||
this.choice = choice.choice;
|
||||
this.chosen = choice.chosen;
|
||||
this.chosenNormal = choice.chosenNormal;
|
||||
this.chosenSpecial = choice.chosenSpecial;
|
||||
this.required = choice.required;
|
||||
this.message = choice.message;
|
||||
this.subMessage = choice.subMessage;
|
||||
|
@ -42,18 +50,28 @@ public class ChoiceImpl implements Choice, Serializable {
|
|||
this.choiceKey = choice.choiceKey;
|
||||
this.keyChoices = choice.keyChoices; // list should never change for the same object so copy by reference TODO: check errors with that, it that ok? Color list is static
|
||||
this.sortData = choice.sortData;
|
||||
this.specialEnabled = choice.specialEnabled;
|
||||
this.specialCanBeEmpty = choice.specialCanBeEmpty;
|
||||
this.specialText = choice.specialText;
|
||||
this.specialHint = choice.specialHint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChosen() {
|
||||
return chosen;
|
||||
return chosenNormal || chosenSpecial;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChosenSpecial() {
|
||||
return chosenSpecial;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearChoice() {
|
||||
choice = null;
|
||||
choiceKey = null;
|
||||
chosen = false;
|
||||
this.choice = null;
|
||||
this.choiceKey = null;
|
||||
this.chosenNormal = false;
|
||||
this.chosenSpecial = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -92,10 +110,17 @@ public class ChoiceImpl implements Choice, Serializable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setChoice(String choice) {
|
||||
public void setChoice(String choice, boolean isSpecial) {
|
||||
if (choices.contains(choice)) {
|
||||
this.choice = choice;
|
||||
this.chosen = true;
|
||||
this.chosenNormal = true;
|
||||
this.chosenSpecial = isSpecial;
|
||||
}
|
||||
|
||||
if (isSpecial && this.specialCanBeEmpty && (choice == null || choice.isEmpty())) {
|
||||
clearChoice();
|
||||
this.chosenNormal = false;
|
||||
this.chosenSpecial = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,12 +159,19 @@ public class ChoiceImpl implements Choice, Serializable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setChoiceByKey(String choiceKey) {
|
||||
public void setChoiceByKey(String choiceKey, boolean isSpecial) {
|
||||
String choiceToSet = keyChoices.get(choiceKey);
|
||||
if (choiceToSet != null) {
|
||||
this.choice = choiceToSet;
|
||||
this.choiceKey = choiceKey;
|
||||
this.chosen = true;
|
||||
this.chosenNormal = true;
|
||||
this.chosenSpecial = isSpecial;
|
||||
}
|
||||
|
||||
if (isSpecial && this.specialCanBeEmpty && (choiceKey == null || choiceKey.isEmpty())) {
|
||||
clearChoice();
|
||||
this.chosenNormal = false;
|
||||
this.chosenSpecial = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,14 +223,14 @@ public class ChoiceImpl implements Choice, Serializable {
|
|||
String[] vals = this.getKeyChoices().keySet().toArray(new String[0]);
|
||||
if (vals.length > 0) {
|
||||
int choiceNum = RandomUtil.nextInt(vals.length);
|
||||
this.setChoiceByKey(vals[choiceNum]);
|
||||
this.setChoiceByKey(vals[choiceNum], false);
|
||||
}
|
||||
} else {
|
||||
// string mode
|
||||
String[] vals = this.getChoices().toArray(new String[0]);
|
||||
if (vals.length > 0) {
|
||||
int choiceNum = RandomUtil.nextInt(vals.length);
|
||||
this.setChoice(vals[choiceNum]);
|
||||
this.setChoice(vals[choiceNum], false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -211,18 +243,18 @@ public class ChoiceImpl implements Choice, Serializable {
|
|||
for (String needChoice : answers) {
|
||||
for (Map.Entry<String, String> currentChoice : this.getKeyChoices().entrySet()) {
|
||||
if (currentChoice.getKey().equals(needChoice)) {
|
||||
this.setChoiceByKey(needChoice);
|
||||
this.setChoiceByKey(needChoice, false);
|
||||
answers.remove(needChoice);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
// no key answer found, try to macht by text starting with
|
||||
// no key answer found, try to match by text starting with
|
||||
for (String needChoice : answers) {
|
||||
for (Map.Entry<String, String> currentChoice : this.getKeyChoices().entrySet()) {
|
||||
if (currentChoice.getValue().startsWith(needChoice)) {
|
||||
this.setChoiceByKey(currentChoice.getKey());
|
||||
this.setChoiceByKey(currentChoice.getKey(), false);
|
||||
answers.remove(needChoice);
|
||||
return true;
|
||||
}
|
||||
|
@ -233,7 +265,7 @@ public class ChoiceImpl implements Choice, Serializable {
|
|||
for (String needChoice : answers) {
|
||||
for (String currentChoice : this.getChoices()) {
|
||||
if (currentChoice.equals(needChoice)) {
|
||||
this.setChoice(needChoice);
|
||||
this.setChoice(needChoice, false);
|
||||
answers.remove(needChoice);
|
||||
return true;
|
||||
}
|
||||
|
@ -242,4 +274,32 @@ public class ChoiceImpl implements Choice, Serializable {
|
|||
}
|
||||
return false; // can't find answer
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpecial(boolean enabled, boolean canBeEmpty, String text, String hint) {
|
||||
this.specialEnabled = enabled;
|
||||
this.specialCanBeEmpty = canBeEmpty;
|
||||
this.specialText = text;
|
||||
this.specialHint = hint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSpecialEnabled() {
|
||||
return this.specialEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSpecialCanBeEmpty() {
|
||||
return this.specialCanBeEmpty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSpecialText() {
|
||||
return this.specialText;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSpecialHint() {
|
||||
return this.specialHint;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ public class UserData implements Serializable {
|
|||
protected boolean passPriorityCast;
|
||||
protected boolean passPriorityActivation;
|
||||
protected boolean autoOrderTrigger;
|
||||
protected boolean useSameSettingsForReplacementEffects;
|
||||
protected boolean useFirstManaAbility = false;
|
||||
private String userIdStr;
|
||||
protected Map<UUID, Set<UUID>> requestedHandPlayersList; // game -> players list
|
||||
|
@ -36,10 +37,22 @@ public class UserData implements Serializable {
|
|||
private int constructedRating;
|
||||
private int limitedRating;
|
||||
|
||||
public UserData(UserGroup userGroup, int avatarId, boolean showAbilityPickerForced,
|
||||
boolean allowRequestShowHandCards, boolean confirmEmptyManaPool, UserSkipPrioritySteps userSkipPrioritySteps,
|
||||
String flagName, boolean askMoveToGraveOrder, boolean manaPoolAutomatic, boolean manaPoolAutomaticRestricted,
|
||||
boolean passPriorityCast, boolean passPriorityActivation, boolean autoOrderTrigger, boolean useFirstManaAbility, String userIdStr) {
|
||||
public UserData(UserGroup userGroup,
|
||||
int avatarId,
|
||||
boolean showAbilityPickerForced,
|
||||
boolean allowRequestShowHandCards,
|
||||
boolean confirmEmptyManaPool,
|
||||
UserSkipPrioritySteps userSkipPrioritySteps,
|
||||
String flagName,
|
||||
boolean askMoveToGraveOrder,
|
||||
boolean manaPoolAutomatic,
|
||||
boolean manaPoolAutomaticRestricted,
|
||||
boolean passPriorityCast,
|
||||
boolean passPriorityActivation,
|
||||
boolean autoOrderTrigger,
|
||||
boolean useSameSettingsForReplacementEffects,
|
||||
boolean useFirstManaAbility,
|
||||
String userIdStr) {
|
||||
this.groupId = userGroup.getGroupId();
|
||||
this.avatarId = avatarId;
|
||||
this.showAbilityPickerForced = showAbilityPickerForced;
|
||||
|
@ -53,6 +66,7 @@ public class UserData implements Serializable {
|
|||
this.passPriorityCast = passPriorityCast;
|
||||
this.passPriorityActivation = passPriorityActivation;
|
||||
this.autoOrderTrigger = autoOrderTrigger;
|
||||
this.useSameSettingsForReplacementEffects = useSameSettingsForReplacementEffects;
|
||||
this.useFirstManaAbility = useFirstManaAbility;
|
||||
this.matchHistory = "";
|
||||
this.matchQuitRatio = 0;
|
||||
|
@ -76,13 +90,31 @@ public class UserData implements Serializable {
|
|||
this.passPriorityCast = userData.passPriorityCast;
|
||||
this.passPriorityActivation = userData.passPriorityActivation;
|
||||
this.autoOrderTrigger = userData.autoOrderTrigger;
|
||||
this.useSameSettingsForReplacementEffects = userData.useSameSettingsForReplacementEffects;
|
||||
this.useFirstManaAbility = userData.useFirstManaAbility;
|
||||
this.userIdStr = userData.userIdStr;
|
||||
// todo: why we don't update user stats here? => can't be updated from client side
|
||||
}
|
||||
|
||||
public static UserData getDefaultUserDataView() {
|
||||
return new UserData(UserGroup.DEFAULT, 0, false, false, true, new UserSkipPrioritySteps(), getDefaultFlagName(), false, true, true, false, false, false, false, "");
|
||||
return new UserData(
|
||||
UserGroup.DEFAULT,
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
new UserSkipPrioritySteps(),
|
||||
getDefaultFlagName(),
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
""
|
||||
);
|
||||
}
|
||||
|
||||
public void setGroupId(int groupId) {
|
||||
|
@ -115,10 +147,7 @@ public class UserData implements Serializable {
|
|||
|
||||
public boolean isAllowRequestHandToPlayer(UUID gameId, UUID requesterPlayerId) {
|
||||
// once per game
|
||||
boolean allowToPlayer = true;
|
||||
if (requestedHandPlayersList.containsKey(gameId) && requestedHandPlayersList.get(gameId).contains(requesterPlayerId)) {
|
||||
allowToPlayer = false;
|
||||
}
|
||||
boolean allowToPlayer = !requestedHandPlayersList.containsKey(gameId) || !requestedHandPlayersList.get(gameId).contains(requesterPlayerId);
|
||||
return isAllowRequestHandToAll() && allowToPlayer;
|
||||
}
|
||||
|
||||
|
@ -206,6 +235,10 @@ public class UserData implements Serializable {
|
|||
return autoOrderTrigger;
|
||||
}
|
||||
|
||||
public boolean isUseSameSettingsForReplacementEffects() {
|
||||
return useSameSettingsForReplacementEffects;
|
||||
}
|
||||
|
||||
public void setAutoOrderTrigger(boolean autoOrderTrigger) {
|
||||
this.autoOrderTrigger = autoOrderTrigger;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue