diff --git a/Mage.Client/src/main/java/mage/client/dialog/PickChoiceDialog.form b/Mage.Client/src/main/java/mage/client/dialog/PickChoiceDialog.form index 5adaf97cd92..4b4f2fa9812 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PickChoiceDialog.form +++ b/Mage.Client/src/main/java/mage/client/dialog/PickChoiceDialog.form @@ -1,13 +1,6 @@ -
- - - - - - - + @@ -26,19 +19,13 @@ - + - - - - - - - - - - - + + + + + @@ -47,74 +34,173 @@ - - + + - + - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mage.Client/src/main/java/mage/client/dialog/PickChoiceDialog.java b/Mage.Client/src/main/java/mage/client/dialog/PickChoiceDialog.java index 07095dbded2..b0d371c19dc 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PickChoiceDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/PickChoiceDialog.java @@ -1,43 +1,23 @@ /* -* 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. -*/ - -/* - * PickNumberDialog.java - * - * Created on Feb 25, 2010, 12:03:39 PM + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. */ - package mage.client.dialog; import java.awt.Point; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; import java.util.Map; import java.util.UUID; +import javax.swing.DefaultListModel; +import javax.swing.JLabel; import javax.swing.JLayeredPane; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; import mage.choices.Choice; import mage.client.MageFrame; import mage.client.util.SettingsManager; @@ -46,37 +26,103 @@ import mage.client.util.gui.MageDialogState; /** * - * @author BetaSteward_at_googlemail.com + * @author JayDi85 */ + public class PickChoiceDialog extends MageDialog { - /** Creates new form PickNumberDialog */ - public PickChoiceDialog() { - initComponents(); - this.setModal(true); - } Choice choice; - boolean autoSelect; - + ArrayList allItems = new ArrayList<>(); + DefaultListModel dataModel = new DefaultListModel(); + + final private static String HTML_TEMPLATE = "
%s
"; + public void showDialog(Choice choice, UUID objectId, MageDialogState mageDialogState) { - this.lblMessage.setText("" + choice.getMessage()); this.choice = choice; - this.autoSelect = false; - btnAutoSelect.setVisible(choice.isKeyChoice()); - if (choice.isKeyChoice()){ - - ComboItem[] comboItems = new ComboItem[choice.getKeyChoices().size()]; - int count = 0; - for (Map.Entry entry : choice.getKeyChoices().entrySet()) { - comboItems[count] = new ComboItem(entry.getKey(), entry.getValue()); - count++; + setLabelText(this.labelMessage, choice.getMessage()); + setLabelText(this.labelSubMessage, choice.getSubMessage()); + + btCancel.setEnabled(!choice.isRequired()); + + // 2 modes: string or key-values + // sore data in allItems for inremental filtering + // http://logicbig.com/tutorials/core-java-tutorial/swing/list-filter/ + this.allItems.clear(); + if (choice.isKeyChoice()){ + for (Map.Entry entry: choice.getKeyChoices().entrySet()) { + this.allItems.add(new KeyValueItem(entry.getKey(), entry.getValue())); } - this.lstChoices.setListData(comboItems); } else { - this.lstChoices.setListData(choice.getChoices().toArray()); + for (String value: choice.getChoices()){ + this.allItems.add(new KeyValueItem(value, value)); + } } + // search + if(choice.isSearchEnabled()) + { + panelSearch.setVisible(true); + this.editSearch.setText(choice.getSearchText()); + }else{ + panelSearch.setVisible(false); + this.editSearch.setText(""); + } + + // listeners for inremental filtering + editSearch.getDocument().addDocumentListener(new DocumentListener() { + @Override + public void insertUpdate(DocumentEvent e) { + choice.setSearchText(editSearch.getText()); + loadData(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + choice.setSearchText(editSearch.getText()); + loadData(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + choice.setSearchText(editSearch.getText()); + loadData(); + } + }); + + // listeners for select up and down without edit focus lost + editSearch.addKeyListener(new KeyListener() { + @Override + public void keyTyped(KeyEvent e) { + //System.out.println("types"); + } + + @Override + public void keyPressed(KeyEvent e) { + if(e.getKeyCode() == KeyEvent.VK_UP){ + doPrevSelect(); + }else if(e.getKeyCode() == KeyEvent.VK_DOWN){ + doNextSelect(); + } + } + + @Override + public void keyReleased(KeyEvent e) { + //System.out.println("released"); + } + }); + + // listeners double click choose + listChoices.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if(e.getClickCount() == 2){ + doChoose(); + } + } + }); + + // window settings MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER); if (mageDialogState != null) { mageDialogState.setStateToDialog(this); @@ -87,154 +133,308 @@ public class PickChoiceDialog extends MageDialog { GuiDisplayUtil.keepComponentInsideScreen(centered.x, centered.y, this); } + // final load + loadData(); this.setVisible(true); } - - public boolean isAutoSelect() { - return autoSelect; + + private void loadData(){ + // load data to datamodel after filter or on startup + String filter = choice.getSearchText(); + if (filter == null){ filter = ""; } + filter = filter.toLowerCase(); + + this.dataModel.clear(); + for(KeyValueItem item: this.allItems){ + if(!choice.isSearchEnabled() || item.Value.toLowerCase().contains(filter)){ + this.dataModel.addElement(item); + } + } + } + + private void setLabelText(JLabel label, String text){ + if ((text != null) && !text.equals("")){ + label.setText(String.format(HTML_TEMPLATE, text)); + label.setVisible(true); + }else{ + label.setText(""); + label.setVisible(false); + } + } + + private void doNextSelect(){ + int newSel = this.listChoices.getSelectedIndex() + 1; + int maxSel = this.listChoices.getModel().getSize() - 1; + if(newSel <= maxSel){ + this.listChoices.setSelectedIndex(newSel); + this.listChoices.ensureIndexIsVisible(newSel); + } + } + + private void doPrevSelect(){ + int newSel = this.listChoices.getSelectedIndex() - 1; + if(newSel >= 0){ + this.listChoices.setSelectedIndex(newSel); + this.listChoices.ensureIndexIsVisible(newSel); + } } - public void setChoice() { - if (this.lstChoices.getSelectedValue() == null) { - choice.clearChoice(); + private void doChoose(){ + if(setChoice()){ + this.hideDialog(); + } + } + + private void doCancel(){ + this.listChoices.clearSelection(); + this.choice.clearChoice(); + hideDialog(); + } + + /** + * Creates new form PickChoiceDialog + */ + public PickChoiceDialog() { + initComponents(); + this.listChoices.setModel(dataModel); + this.setModal(true); + + // Close the dialog when Esc is pressed + /* + String cancelName = "cancel"; + InputMap inputMap = getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), cancelName); + ActionMap actionMap = getRootPane().getActionMap(); + actionMap.put(cancelName, new AbstractAction() { + public void actionPerformed(ActionEvent e) { + doCancel(); + } + }); + */ + } + + public boolean setChoice() { + KeyValueItem item = (KeyValueItem)this.listChoices.getSelectedValue(); + + // auto select one item (after incemental filtering) + if((item == null) && (this.listChoices.getModel().getSize() == 1)){ + this.listChoices.setSelectedIndex(0); + item = (KeyValueItem)this.listChoices.getSelectedValue(); } - if (choice.isKeyChoice()) { - ComboItem item = (ComboItem)this.lstChoices.getSelectedValue(); - if (item != null) { - choice.setChoiceByKey(item.getValue()); - } else { - choice.clearChoice(); + if(item != null){ + if(choice.isKeyChoice()){ + choice.setChoiceByKey(item.getKey()); + }else{ + choice.setChoice(item.getKey()); } - } else { - choice.setChoice((String)this.lstChoices.getSelectedValue()); + return true; + }else{ + choice.clearChoice(); + return false; } } + + class KeyValueItem + { + private final String Key; + private final String Value; + + public KeyValueItem(String value, String label) { + this.Key = value; + this.Value = label; + } - /** This method is called from within the constructor to - * initialize the form. - * WARNING: Do NOT modify this code. The content of this method is - * always regenerated by the Form Editor. + public String getKey() { + return this.Key; + } + + public String getValue() { + return this.Value; + } + + @Override + public String toString() { + return this.Value; + } + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // //GEN-BEGIN:initComponents private void initComponents() { - btnAutoSelect = new javax.swing.JButton(); - btnCancel = new javax.swing.JButton(); - btnOk = new javax.swing.JButton(); - jScrollPane1 = new javax.swing.JScrollPane(); - lstChoices = new javax.swing.JList(); - lblMessage = new javax.swing.JLabel(); + panelHeader = new javax.swing.JPanel(); + labelMessage = new javax.swing.JLabel(); + labelSubMessage = new javax.swing.JLabel(); + panelSearch = new javax.swing.JPanel(); + labelSearch = new javax.swing.JLabel(); + editSearch = new javax.swing.JTextField(); + scrollList = new javax.swing.JScrollPane(); + listChoices = new javax.swing.JList(); + panelCommands = new javax.swing.JPanel(); + btOK = new javax.swing.JButton(); + btCancel = new javax.swing.JButton(); - setResizable(true); - setMinimumSize(new java.awt.Dimension(280, 200)); - setName(""); // NOI18N + labelMessage.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + labelMessage.setText("
example long message example long message example long message example long message example long message
"); - btnAutoSelect.setText("Auto select"); - btnAutoSelect.setToolTipText("If you select an effect with \"Auto select\", this effect will be selected the next time automatically first."); - btnAutoSelect.addActionListener(evt -> btnAutoSelectActionPerformed(evt)); + labelSubMessage.setFont(labelSubMessage.getFont().deriveFont((labelSubMessage.getFont().getStyle() | java.awt.Font.ITALIC) | java.awt.Font.BOLD)); + labelSubMessage.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + labelSubMessage.setText("
example long message example long
"); - btnCancel.setText("Cancel"); - btnCancel.addActionListener(evt -> btnCancelActionPerformed(evt)); + javax.swing.GroupLayout panelHeaderLayout = new javax.swing.GroupLayout(panelHeader); + panelHeader.setLayout(panelHeaderLayout); + panelHeaderLayout.setHorizontalGroup( + panelHeaderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelHeaderLayout.createSequentialGroup() + .addGroup(panelHeaderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(labelMessage, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 210, Short.MAX_VALUE) + .addComponent(labelSubMessage, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 210, Short.MAX_VALUE)) + .addGap(0, 0, 0)) + ); + panelHeaderLayout.setVerticalGroup( + panelHeaderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelHeaderLayout.createSequentialGroup() + .addGap(0, 0, 0) + .addComponent(labelMessage) + .addGap(0, 0, 0) + .addComponent(labelSubMessage)) + ); - btnOk.setText("OK"); - btnOk.addActionListener(evt -> btnOkActionPerformed(evt)); + labelSearch.setText("Search:"); - lstChoices.setModel(new javax.swing.AbstractListModel() { - final String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" }; + editSearch.setText("sample search text"); + + javax.swing.GroupLayout panelSearchLayout = new javax.swing.GroupLayout(panelSearch); + panelSearch.setLayout(panelSearchLayout); + panelSearchLayout.setHorizontalGroup( + panelSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelSearchLayout.createSequentialGroup() + .addGap(0, 0, 0) + .addComponent(labelSearch) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(editSearch) + .addGap(0, 0, 0)) + ); + panelSearchLayout.setVerticalGroup( + panelSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelSearchLayout.createSequentialGroup() + .addGap(3, 3, 3) + .addGroup(panelSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(labelSearch) + .addComponent(editSearch, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(3, 3, 3)) + ); + + listChoices.setModel(new javax.swing.AbstractListModel() { + String[] strings = { "item1", "item2", "item3" }; public int getSize() { return strings.length; } public Object getElementAt(int i) { return strings[i]; } }); - jScrollPane1.setViewportView(lstChoices); + scrollList.setViewportView(listChoices); - lblMessage.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); - lblMessage.setText("message"); + btOK.setText("Choose"); + btOK.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btOKActionPerformed(evt); + } + }); + + btCancel.setText("Cancel"); + btCancel.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btCancelActionPerformed(evt); + } + }); + + 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(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, new java.awt.Component[] {btCancel, btOK}); + + panelCommandsLayout.setVerticalGroup( + panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelCommandsLayout.createSequentialGroup() + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btCancel) + .addComponent(btOK)) + .addContainerGap()) + ); + + getRootPane().setDefaultButton(btOK); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGroup(layout.createSequentialGroup() .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 335, Short.MAX_VALUE) - .addGroup(layout.createSequentialGroup() - .addGap(0, 0, Short.MAX_VALUE) - .addComponent(btnAutoSelect) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnOk) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnCancel)) - .addComponent(lblMessage, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 335, Short.MAX_VALUE)) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(scrollList, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(panelCommands, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(panelHeader, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(panelSearch, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addGap(6, 6, 6) - .addComponent(lblMessage, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap() + .addComponent(panelHeader, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 158, Short.MAX_VALUE) + .addComponent(panelSearch, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(btnCancel) - .addComponent(btnOk) - .addComponent(btnAutoSelect)) - .addGap(10, 10, 10)) + .addComponent(scrollList, javax.swing.GroupLayout.DEFAULT_SIZE, 246, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(panelCommands, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) ); pack(); }//
//GEN-END:initComponents - private void btnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOkActionPerformed - setChoice(); - this.hideDialog(); - }//GEN-LAST:event_btnOkActionPerformed + private void btOKActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btOKActionPerformed + doChoose(); + }//GEN-LAST:event_btOKActionPerformed - private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed - this.lstChoices.clearSelection(); - this.choice.clearChoice(); - this.hideDialog(); - }//GEN-LAST:event_btnCancelActionPerformed + private void btCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btCancelActionPerformed + doCancel(); + }//GEN-LAST:event_btCancelActionPerformed - private void btnAutoSelectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAutoSelectActionPerformed - this.autoSelect = true; - setChoice(); - this.hideDialog(); - }//GEN-LAST:event_btnAutoSelectActionPerformed + /** + * Closes the dialog + */ + private void closeDialog(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_closeDialog + doCancel(); + }//GEN-LAST:event_closeDialog // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton btnAutoSelect; - private javax.swing.JButton btnCancel; - private javax.swing.JButton btnOk; - private javax.swing.JScrollPane jScrollPane1; - private javax.swing.JLabel lblMessage; - private javax.swing.JList lstChoices; + private javax.swing.JButton btCancel; + private javax.swing.JButton btOK; + private javax.swing.JTextField editSearch; + private javax.swing.JLabel labelMessage; + private javax.swing.JLabel labelSearch; + private javax.swing.JLabel labelSubMessage; + private javax.swing.JList listChoices; + private javax.swing.JPanel panelCommands; + private javax.swing.JPanel panelHeader; + private javax.swing.JPanel panelSearch; + private javax.swing.JScrollPane scrollList; // End of variables declaration//GEN-END:variables - } - class ComboItem { - - private final String value; - private final String label; - - public ComboItem(String value, String label) { - this.value = value; - this.label = label; - } - - public String getValue() { - return this.value; - } - - public String getLabel() { - return this.label; - } - - @Override - public String toString() { - return label; - } - } \ No newline at end of file diff --git a/Mage.Client/src/main/java/mage/client/game/GamePanel.java b/Mage.Client/src/main/java/mage/client/game/GamePanel.java index a014167df0a..ab0daf3e706 100644 --- a/Mage.Client/src/main/java/mage/client/game/GamePanel.java +++ b/Mage.Client/src/main/java/mage/client/game/GamePanel.java @@ -1220,14 +1220,17 @@ public final class GamePanel extends javax.swing.JPanel { public void getChoice(Choice choice, UUID objectId) { hideAll(); + // TODO: remember last choices and search incremental for same events? PickChoiceDialog pickChoice = new PickChoiceDialog(); pickChoice.showDialog(choice, objectId, choiceWindowState); 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()); - } + }*/ } else { SessionHandler.sendPlayerString(gameId, choice.getChoice()); } diff --git a/Mage.Sets/src/mage/cards/a/AphettoDredging.java b/Mage.Sets/src/mage/cards/a/AphettoDredging.java index 3e455021cf0..74df66d9838 100644 --- a/Mage.Sets/src/mage/cards/a/AphettoDredging.java +++ b/Mage.Sets/src/mage/cards/a/AphettoDredging.java @@ -65,7 +65,7 @@ public class AphettoDredging extends CardImpl { if (ability instanceof SpellAbility) { Player controller = game.getPlayer(ability.getControllerId()); if (controller != null) { - Choice typeChoice = new ChoiceCreatureType(); + Choice typeChoice = new ChoiceCreatureType(game.getObject(ability.getSourceId())); while (!controller.choose(Outcome.PutCreatureInPlay, typeChoice, game)) { if (!controller.canRespond()) { return; diff --git a/Mage.Sets/src/mage/cards/b/BloodlineShaman.java b/Mage.Sets/src/mage/cards/b/BloodlineShaman.java index c8e5591919d..4e9867eaa16 100644 --- a/Mage.Sets/src/mage/cards/b/BloodlineShaman.java +++ b/Mage.Sets/src/mage/cards/b/BloodlineShaman.java @@ -98,7 +98,7 @@ class BloodlineShamanEffect extends OneShotEffect { MageObject sourceObject = game.getObject(source.getSourceId()); if (controller != null) { // Choose a creature type. - Choice typeChoice = new ChoiceCreatureType(); + Choice typeChoice = new ChoiceCreatureType(sourceObject); while (!controller.choose(outcome, typeChoice, game)) { if (!controller.canRespond()) { return false; diff --git a/Mage.Sets/src/mage/cards/c/CallerOfTheHunt.java b/Mage.Sets/src/mage/cards/c/CallerOfTheHunt.java index 1249f6b1266..4e440094aa4 100644 --- a/Mage.Sets/src/mage/cards/c/CallerOfTheHunt.java +++ b/Mage.Sets/src/mage/cards/c/CallerOfTheHunt.java @@ -129,7 +129,7 @@ class ChooseCreatureTypeEffect extends OneShotEffect { // code by LevelX2, but t Player controller = game.getPlayer(source.getControllerId()); MageObject mageObject = game.getObject(source.getSourceId()); if (controller != null && mageObject != null) { - Choice typeChoice = new ChoiceCreatureType(); + Choice typeChoice = new ChoiceCreatureType(mageObject); while (!controller.choose(outcome, typeChoice, game)) { if (!controller.canRespond()) { return false; diff --git a/Mage.Sets/src/mage/cards/c/CallousOppressor.java b/Mage.Sets/src/mage/cards/c/CallousOppressor.java index 63acbd3c2e1..f5b9d78b018 100644 --- a/Mage.Sets/src/mage/cards/c/CallousOppressor.java +++ b/Mage.Sets/src/mage/cards/c/CallousOppressor.java @@ -44,7 +44,7 @@ import mage.abilities.effects.common.continuous.GainControlTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.choices.Choice; -import mage.choices.ChoiceImpl; +import mage.choices.ChoiceCreatureType; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Duration; @@ -154,9 +154,8 @@ class CallousOppressorChooseCreatureTypeEffect extends OneShotEffect { } Player opponent = game.getPlayer(target.getFirstTarget()); if (opponent != null && mageObject != null) { - Choice typeChoice = new ChoiceImpl(true); + Choice typeChoice = new ChoiceCreatureType(mageObject); typeChoice.setMessage("Choose creature type"); - typeChoice.setChoices(SubType.getCreatureTypes(false).stream().map(SubType::toString).collect(Collectors.toCollection(LinkedHashSet::new))); while (!opponent.choose(outcome, typeChoice, game)) { if (!opponent.canRespond()) { return false; diff --git a/Mage.Sets/src/mage/cards/c/CoordinatedBarrage.java b/Mage.Sets/src/mage/cards/c/CoordinatedBarrage.java index d9c068c192c..518dfc76ace 100644 --- a/Mage.Sets/src/mage/cards/c/CoordinatedBarrage.java +++ b/Mage.Sets/src/mage/cards/c/CoordinatedBarrage.java @@ -89,7 +89,7 @@ class CoordinatedBarrageEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - Choice choice = new ChoiceCreatureType(); + Choice choice = new ChoiceCreatureType(game.getObject(source.getSourceId())); if (controller.choose(Outcome.Damage, choice, game)) { String chosenType = choice.getChoice(); FilterControlledPermanent filter = new FilterControlledPermanent(); diff --git a/Mage.Sets/src/mage/cards/d/DistantMelody.java b/Mage.Sets/src/mage/cards/d/DistantMelody.java index e773eeeedf9..5502cf22328 100644 --- a/Mage.Sets/src/mage/cards/d/DistantMelody.java +++ b/Mage.Sets/src/mage/cards/d/DistantMelody.java @@ -89,7 +89,7 @@ class DistantMelodyEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); if (player != null) { - Choice typeChoice = new ChoiceCreatureType(); + Choice typeChoice = new ChoiceCreatureType(game.getObject(source.getSourceId())); while (!player.choose(Outcome.BoostCreature, typeChoice, game)) { if (!player.canRespond()) { return false; diff --git a/Mage.Sets/src/mage/cards/e/ElvishSoultiller.java b/Mage.Sets/src/mage/cards/e/ElvishSoultiller.java index 8b20c146bac..51047e50535 100644 --- a/Mage.Sets/src/mage/cards/e/ElvishSoultiller.java +++ b/Mage.Sets/src/mage/cards/e/ElvishSoultiller.java @@ -96,7 +96,7 @@ class ElvishSoultillerEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); MageObject mageObject = game.getObject(source.getSourceId()); if (controller != null && mageObject != null) { - Choice typeChoice = new ChoiceCreatureType(); + Choice typeChoice = new ChoiceCreatureType(mageObject); while (!controller.choose(outcome, typeChoice, game)) { if (!controller.canRespond()) { return false; diff --git a/Mage.Sets/src/mage/cards/e/Extinction.java b/Mage.Sets/src/mage/cards/e/Extinction.java index 5d263271695..0310e869336 100644 --- a/Mage.Sets/src/mage/cards/e/Extinction.java +++ b/Mage.Sets/src/mage/cards/e/Extinction.java @@ -83,7 +83,7 @@ class ExtinctionEffect extends OneShotEffect { Player player = game.getPlayer(source.getControllerId()); MageObject sourceObject = game.getObject(source.getSourceId()); if (player != null) { - Choice typeChoice = new ChoiceCreatureType(); + Choice typeChoice = new ChoiceCreatureType(sourceObject); while (!player.choose(outcome, typeChoice, game)) { if (!player.canRespond()) { return false; diff --git a/Mage.Sets/src/mage/cards/g/GraveSifter.java b/Mage.Sets/src/mage/cards/g/GraveSifter.java index df5c373f73e..c60fe13164d 100644 --- a/Mage.Sets/src/mage/cards/g/GraveSifter.java +++ b/Mage.Sets/src/mage/cards/g/GraveSifter.java @@ -95,7 +95,7 @@ class GraveSifterEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Choice typeChoice = new ChoiceCreatureType(); + Choice typeChoice = new ChoiceCreatureType(game.getObject(source.getSourceId())); typeChoice.setMessage("Choose creature type to return cards from your graveyard"); Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { diff --git a/Mage.Sets/src/mage/cards/h/HarshMercy.java b/Mage.Sets/src/mage/cards/h/HarshMercy.java index 931d63a9386..72f42fb3b70 100644 --- a/Mage.Sets/src/mage/cards/h/HarshMercy.java +++ b/Mage.Sets/src/mage/cards/h/HarshMercy.java @@ -96,7 +96,7 @@ class HarshMercyEffect extends OneShotEffect { PlayerIteration: for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { Player player = game.getPlayer(playerId); - Choice typeChoice = new ChoiceCreatureType(); + Choice typeChoice = new ChoiceCreatureType(sourceObject); while (!player.choose(Outcome.DestroyPermanent, typeChoice, game)) { if (!player.canRespond()) { continue PlayerIteration; diff --git a/Mage.Sets/src/mage/cards/k/KaronaFalseGod.java b/Mage.Sets/src/mage/cards/k/KaronaFalseGod.java index 56a5c395e37..b287a99d533 100644 --- a/Mage.Sets/src/mage/cards/k/KaronaFalseGod.java +++ b/Mage.Sets/src/mage/cards/k/KaronaFalseGod.java @@ -152,7 +152,7 @@ class KaronaFalseGodEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); MageObject sourceObject = game.getObject(source.getSourceId()); if (sourceObject != null && controller != null) { - Choice typeChoice = new ChoiceCreatureType(); + Choice typeChoice = new ChoiceCreatureType(sourceObject); while (!controller.choose(Outcome.BoostCreature, typeChoice, game)) { if (!controller.canRespond()) { return false; diff --git a/Mage.Sets/src/mage/cards/l/LuminescentRain.java b/Mage.Sets/src/mage/cards/l/LuminescentRain.java index 5437d5eec37..cb881e2b5e0 100644 --- a/Mage.Sets/src/mage/cards/l/LuminescentRain.java +++ b/Mage.Sets/src/mage/cards/l/LuminescentRain.java @@ -86,9 +86,9 @@ class LuminescentRainEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); + Player player = game.getPlayer(source.getControllerId()); if (player != null) { - Choice typeChoice = new ChoiceCreatureType(); + Choice typeChoice = new ChoiceCreatureType(game.getObject(source.getSourceId())); while (!player.choose(Outcome.BoostCreature, typeChoice, game)) { if (!player.canRespond()) { return false; diff --git a/Mage.Sets/src/mage/cards/m/MistformSliver.java b/Mage.Sets/src/mage/cards/m/MistformSliver.java index 2ac7c3b16e3..2364d2cd9c4 100644 --- a/Mage.Sets/src/mage/cards/m/MistformSliver.java +++ b/Mage.Sets/src/mage/cards/m/MistformSliver.java @@ -92,7 +92,7 @@ class MistformSliverEffect extends OneShotEffect { Player player = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(source.getSourceId()); if (player != null && permanent != null) { - Choice typeChoice = new ChoiceCreatureType(); + Choice typeChoice = new ChoiceCreatureType(permanent); while (!player.choose(Outcome.Detriment, typeChoice, game)) { if (!player.canRespond()) { return false; diff --git a/Mage.Sets/src/mage/cards/n/NewBlood.java b/Mage.Sets/src/mage/cards/n/NewBlood.java index cd2c534219a..a6f3905c73e 100644 --- a/Mage.Sets/src/mage/cards/n/NewBlood.java +++ b/Mage.Sets/src/mage/cards/n/NewBlood.java @@ -39,7 +39,7 @@ import mage.abilities.text.TextPartSubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.choices.Choice; -import mage.choices.ChoiceImpl; +import mage.choices.ChoiceCreatureType; import mage.constants.*; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.Predicates; @@ -145,9 +145,8 @@ class ChangeCreatureTypeTargetEffect extends ContinuousEffectImpl { return; } if (fromSubType == null) { - Choice typeChoice = new ChoiceImpl(true); + Choice typeChoice = new ChoiceCreatureType(game.getObject(source.getSourceId())); typeChoice.setMessage("Choose creature type to change to Vampire"); - typeChoice.setChoices(SubType.getCreatureTypes(false).stream().map(SubType::toString).collect(Collectors.toCollection(LinkedHashSet::new))); while (!controller.choose(outcome, typeChoice, game)) { if (!controller.canRespond()) { return; diff --git a/Mage.Sets/src/mage/cards/o/Outbreak.java b/Mage.Sets/src/mage/cards/o/Outbreak.java index 1b6e48355a1..4de53cd1150 100644 --- a/Mage.Sets/src/mage/cards/o/Outbreak.java +++ b/Mage.Sets/src/mage/cards/o/Outbreak.java @@ -96,7 +96,7 @@ class OutbreakEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); if (player != null) { - Choice typeChoice = new ChoiceCreatureType(); + Choice typeChoice = new ChoiceCreatureType(game.getObject(source.getSourceId())); while (!player.choose(outcome, typeChoice, game)) { if (!player.canRespond()) { return false; diff --git a/Mage.Sets/src/mage/cards/p/PacksDisdain.java b/Mage.Sets/src/mage/cards/p/PacksDisdain.java index 8b98c53a0eb..88c1951e0b3 100644 --- a/Mage.Sets/src/mage/cards/p/PacksDisdain.java +++ b/Mage.Sets/src/mage/cards/p/PacksDisdain.java @@ -93,7 +93,7 @@ class PacksDisdainEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); if (player != null) { - Choice typeChoice = new ChoiceCreatureType(); + Choice typeChoice = new ChoiceCreatureType(game.getObject(source.getSourceId())); while (!player.choose(Outcome.UnboostCreature, typeChoice, game)) { if (!player.canRespond()) { return false; diff --git a/Mage.Sets/src/mage/cards/p/PatriarchsBidding.java b/Mage.Sets/src/mage/cards/p/PatriarchsBidding.java index a964d7f791c..e4500783854 100644 --- a/Mage.Sets/src/mage/cards/p/PatriarchsBidding.java +++ b/Mage.Sets/src/mage/cards/p/PatriarchsBidding.java @@ -93,7 +93,7 @@ class PatriarchsBiddingEffect extends OneShotEffect { Set chosenTypes = new HashSet<>(); for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { Player player = game.getPlayer(playerId); - Choice typeChoice = new ChoiceCreatureType(); + Choice typeChoice = new ChoiceCreatureType(sourceObject); while (!player.choose(Outcome.PutCreatureInPlay, typeChoice, game)) { if (!player.canRespond()) { break; diff --git a/Mage.Sets/src/mage/cards/p/PeerPressure.java b/Mage.Sets/src/mage/cards/p/PeerPressure.java index 8101dc06be5..4ea1cfe77c3 100644 --- a/Mage.Sets/src/mage/cards/p/PeerPressure.java +++ b/Mage.Sets/src/mage/cards/p/PeerPressure.java @@ -93,7 +93,7 @@ class PeerPressureEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - Choice choice = new ChoiceCreatureType(); + Choice choice = new ChoiceCreatureType(game.getObject(source.getSourceId())); while (!controller.choose(Outcome.GainControl, choice, game)) { if (!controller.canRespond()) { return false; diff --git a/Mage.Sets/src/mage/cards/r/RiptideChronologist.java b/Mage.Sets/src/mage/cards/r/RiptideChronologist.java index b4a838bf6a6..c4d0b45ad60 100644 --- a/Mage.Sets/src/mage/cards/r/RiptideChronologist.java +++ b/Mage.Sets/src/mage/cards/r/RiptideChronologist.java @@ -94,7 +94,7 @@ class RiptideChronologistEffect extends OneShotEffect { Player player = game.getPlayer(source.getControllerId()); MageObject sourceObject = game.getObject(source.getSourceId()); if (player != null) { - Choice typeChoice = new ChoiceCreatureType(); + Choice typeChoice = new ChoiceCreatureType(sourceObject); while (!player.choose(outcome, typeChoice, game)) { if (!player.canRespond()) { return false; diff --git a/Mage.Sets/src/mage/cards/r/RiptideShapeshifter.java b/Mage.Sets/src/mage/cards/r/RiptideShapeshifter.java index 5a5d21a2b94..ec5ee0e3049 100644 --- a/Mage.Sets/src/mage/cards/r/RiptideShapeshifter.java +++ b/Mage.Sets/src/mage/cards/r/RiptideShapeshifter.java @@ -96,7 +96,7 @@ class RiptideShapeshifterEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); MageObject sourceObject = source.getSourceObject(game); if (controller != null && sourceObject != null) { - Choice choice = new ChoiceCreatureType(); + Choice choice = new ChoiceCreatureType(sourceObject); while (!controller.choose(Outcome.BoostCreature, choice, game)) { if (!controller.canRespond()) { return false; diff --git a/Mage.Sets/src/mage/cards/r/RoarOfTheCrowd.java b/Mage.Sets/src/mage/cards/r/RoarOfTheCrowd.java index 181d0fa4d95..213b9198079 100644 --- a/Mage.Sets/src/mage/cards/r/RoarOfTheCrowd.java +++ b/Mage.Sets/src/mage/cards/r/RoarOfTheCrowd.java @@ -89,7 +89,7 @@ class RoarOfTheCrowdEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); if (player != null) { - Choice typeChoice = new ChoiceCreatureType(); + Choice typeChoice = new ChoiceCreatureType(game.getObject(source.getSourceId())); while (!player.choose(Outcome.LoseLife, typeChoice, game)) { if (!player.canRespond()) { return false; diff --git a/Mage.Sets/src/mage/cards/s/Standardize.java b/Mage.Sets/src/mage/cards/s/Standardize.java index b34c7065372..6a1adee518a 100644 --- a/Mage.Sets/src/mage/cards/s/Standardize.java +++ b/Mage.Sets/src/mage/cards/s/Standardize.java @@ -85,7 +85,7 @@ class StandardizeEffect extends OneShotEffect { MageObject sourceObject = game.getObject(source.getSourceId()); String chosenType = ""; if (player != null && sourceObject != null) { - Choice typeChoice = new ChoiceCreatureType(); + Choice typeChoice = new ChoiceCreatureType(sourceObject); typeChoice.setMessage("Choose a creature type other than Wall"); typeChoice.getChoices().remove("Wall"); while (!player.choose(Outcome.BoostCreature, typeChoice, game)) { diff --git a/Mage.Sets/src/mage/cards/t/TribalUnity.java b/Mage.Sets/src/mage/cards/t/TribalUnity.java index e3ac24efd3f..fc9653ce1f1 100644 --- a/Mage.Sets/src/mage/cards/t/TribalUnity.java +++ b/Mage.Sets/src/mage/cards/t/TribalUnity.java @@ -91,7 +91,7 @@ class TribalUnityEffect extends OneShotEffect { MageObject sourceObject = game.getObject(source.getSourceId()); int boost = amount.calculate(game, source, this); if (player != null) { - Choice typeChoice = new ChoiceCreatureType(); + Choice typeChoice = new ChoiceCreatureType(sourceObject); while (!player.choose(outcome, typeChoice, game)) { if (!player.canRespond()) { return false; diff --git a/Mage.Sets/src/mage/cards/t/TsabosDecree.java b/Mage.Sets/src/mage/cards/t/TsabosDecree.java index 36aeb9acc35..b455b455054 100644 --- a/Mage.Sets/src/mage/cards/t/TsabosDecree.java +++ b/Mage.Sets/src/mage/cards/t/TsabosDecree.java @@ -90,7 +90,7 @@ class TsabosDecreeEffect extends OneShotEffect { Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source)); MageObject sourceObject = game.getObject(source.getSourceId()); if (player != null) { - Choice typeChoice = new ChoiceCreatureType(); + Choice typeChoice = new ChoiceCreatureType(sourceObject); while (!player.choose(outcome, typeChoice, game)) { if (!player.canRespond()) { return false; diff --git a/Mage.Sets/src/mage/cards/w/WalkingDesecration.java b/Mage.Sets/src/mage/cards/w/WalkingDesecration.java index 54988c4923a..f23339c4e2a 100644 --- a/Mage.Sets/src/mage/cards/w/WalkingDesecration.java +++ b/Mage.Sets/src/mage/cards/w/WalkingDesecration.java @@ -91,7 +91,7 @@ class WalkingDesecrationEffect extends OneShotEffect { Player player = game.getPlayer(source.getControllerId()); MageObject sourceObject = game.getObject(source.getSourceId()); if (player != null) { - Choice typeChoice = new ChoiceCreatureType(); + Choice typeChoice = new ChoiceCreatureType(sourceObject); while (!player.choose(outcome, typeChoice, game)) { if (!player.canRespond()) { return false; diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/mana/ConditionalManaTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/mana/ConditionalManaTest.java index 104cebecbf1..0a3daff161b 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/mana/ConditionalManaTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/mana/ConditionalManaTest.java @@ -30,6 +30,7 @@ package org.mage.test.cards.mana; import mage.abilities.keyword.FlyingAbility; import mage.constants.PhaseStep; import mage.constants.Zone; +import org.junit.Assert; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; @@ -75,9 +76,10 @@ public class ConditionalManaTest extends CardTestPlayerBase { @Test public void testWorkingWithReflectingPool() { - addCard(Zone.BATTLEFIELD, playerA, "Cavern of Souls", 1); - addCard(Zone.BATTLEFIELD, playerA, "Reflecting Pool", 1); // can create white mana without restriction from the Cavern - addCard(Zone.HAND, playerA, "Silvercoat Lion", 1); + addCard(Zone.BATTLEFIELD, playerA, "Cavern of Souls", 1); // can give {C] or {any} mana ({any} with restrictions) + addCard(Zone.BATTLEFIELD, playerA, "Reflecting Pool", 1); // must give {C} or {any} mana from the Cavern, but without restrictions + addCard(Zone.HAND, playerA, "Silvercoat Lion", 1); // white bear + addCard(Zone.BATTLEFIELD, playerA, "Upwelling", 1); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Silvercoat Lion"); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/mana/HarvesterDruidTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/mana/HarvesterDruidTest.java index f03c021f1ce..c8bcc3b548d 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/mana/HarvesterDruidTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/mana/HarvesterDruidTest.java @@ -33,10 +33,11 @@ import mage.constants.Zone; import org.junit.Assert; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; +import static org.mage.test.utils.ManaOptionsTestUtils.*; /** * - * @author LevelX2 + * @author LevelX2, JayDi85 */ public class HarvesterDruidTest extends CardTestPlayerBase { @@ -52,8 +53,10 @@ public class HarvesterDruidTest extends CardTestPlayerBase { execute(); ManaOptions options = playerA.getAvailableManaTest(currentGame); - Assert.assertEquals("Player should be able to create 2 red and 1 blue mana", "{U}{R}{R}", options.get(0).toString()); - Assert.assertEquals("Player should be able to create 1 red and 3 blue mana", "{U}{U}{R}", options.get(1).toString()); + assertDuplicatedManaOptions(options); + Assert.assertEquals(2, options.size()); + assertManaOptions("{U}{R}{R}", options); + assertManaOptions("{U}{U}{R}", options); } @Test @@ -68,9 +71,10 @@ public class HarvesterDruidTest extends CardTestPlayerBase { execute(); ManaOptions options = playerA.getAvailableManaTest(currentGame); - Assert.assertEquals("Player should be able to create 3 red and 1 blue mana", "{U}{R}{R}{R}", options.get(0).toString()); - Assert.assertEquals("Player should be able to create 2 red and 2 blue mana", "{U}{U}{R}{R}", options.get(1).toString()); - Assert.assertEquals("Player should be able to create 2 red and 2 blue mana", "{U}{U}{R}{R}", options.get(2).toString()); - Assert.assertEquals("Player should be able to create 1 red and 3 blue mana", "{U}{U}{U}{R}", options.get(3).toString()); + assertDuplicatedManaOptions(options); + Assert.assertEquals(3, options.size()); + assertManaOptions("{U}{R}{R}{R}", options); + assertManaOptions("{U}{U}{R}{R}", options); + assertManaOptions("{U}{U}{U}{R}", options); } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/mana/NagaVitalistTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/mana/NagaVitalistTest.java index 9709cb03597..f19d888195a 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/mana/NagaVitalistTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/mana/NagaVitalistTest.java @@ -1,15 +1,21 @@ package org.mage.test.cards.mana; +import mage.constants.Duration; import mage.constants.ManaType; import mage.constants.PhaseStep; import mage.constants.Zone; +import mage.game.permanent.Permanent; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; +import org.mage.test.utils.ManaOptionsTestUtils; + +import static org.mage.test.utils.ManaOptionsTestUtils.manaOptionsContain; /** * - * @author escplan9 + * @author escplan9, JayDi85 */ public class NagaVitalistTest extends CardTestPlayerBase { @@ -21,21 +27,116 @@ public class NagaVitalistTest extends CardTestPlayerBase { private final String nagaVitalist = "Naga Vitalist"; /* - Reported bug (issue #3315) - Naga Vitalist could not produce any color mana with a Gift of Paradise enchanted on a forest. All lands on board were forests. - */ - @Test - public void nagaVitalist_InteractionGiftOfParadise() { - - /* Gift of Paradise 2G Enchantment - Aura Enchant - Land When Gift of Paradise enters the battlefield, you gain 3 life. Enchanted land has "T: Add two mana of any one color to your mana pool." - */ - String giftParadise = "Gift of Paradise"; + */ + private final String giftParadise = "Gift of Paradise"; + @Test + public void nagaVitalist_GiftOfParadiseCanAnyColor() { + addCard(Zone.BATTLEFIELD, playerA, "Upwelling"); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 3); + addCard(Zone.HAND, playerA, giftParadise); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); + + // manual mana cost, cause auto cost can get swamp to pay + activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {G}"); + activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {G}"); + activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {G}"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, giftParadise, "Swamp"); + + setStopAt(1, PhaseStep.PRECOMBAT_MAIN); + execute(); + + Assert.assertTrue("playerA must cast {Any}{Any}", manaOptionsContain(playerA.getManaAvailable(currentGame), "{Any}{Any}")); + } + + public void nagaVitalist_GiftOfParadisesLandCanGiveAnyColorToNaga_Setup(int giftCastTurn, int nagaManaTapTurn, String nagaManaTapColor){ + // test errors on enchanted ability do not apply for "any mana search" on different steps + + addCard(Zone.BATTLEFIELD, playerA, "Upwelling"); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 3); + addCard(Zone.HAND, playerA, giftParadise); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); + addCard(Zone.BATTLEFIELD, playerA, nagaVitalist, 1); + + + // cast and enchant swamp land to any color + activateManaAbility(giftCastTurn, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {G}"); + activateManaAbility(giftCastTurn, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {G}"); + activateManaAbility(giftCastTurn, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {G}"); + castSpell(giftCastTurn, PhaseStep.PRECOMBAT_MAIN, playerA, giftParadise, "Swamp"); + + // activate red mana (by any from enchanted land) + activateManaAbility(nagaManaTapTurn, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add to your mana pool one mana of any"); + setChoice(playerA, nagaManaTapColor); + + setStopAt(nagaManaTapTurn, PhaseStep.PRECOMBAT_MAIN); + execute(); + } + + @Test + @Ignore // TODO: need to fix - on naga mana tap swamp do not have added ability "add 2 any mana" (but it have after step complete) + public void nagaVitalist_GiftOfParadisesLandCanGiveAnyColorToNaga_SameStep1() { + nagaVitalist_GiftOfParadisesLandCanGiveAnyColorToNaga_Setup(1, 1, "Red"); + + + //logger.info(playerA.getManaPool().getMana().toString()); + //logger.info(playerA.getManaAvailable(currentGame).toString()); + //for(Permanent perm: currentGame.getBattlefield().getAllActivePermanents(playerA.getId())){ + // logger.info(perm.getIdName() + ": " + perm.getAbilities().toString()); + //} + + assertTapped("Forest", true); + assertTapped(giftParadise, false); + assertTapped("Swamp", false); + assertTapped(nagaVitalist, true); + Assert.assertEquals(1, playerA.getManaPool().get(ManaType.RED)); + } + + @Test + public void nagaVitalist_GiftOfParadisesLandCanGiveAnyColorToNaga_DiffStep1() { + nagaVitalist_GiftOfParadisesLandCanGiveAnyColorToNaga_Setup(1, 2, "Red"); + + assertTapped("Forest", true); + assertTapped(giftParadise, false); + assertTapped("Swamp", false); + assertTapped(nagaVitalist, true); + Assert.assertEquals(1, playerA.getManaPool().get(ManaType.RED)); + } + + @Test + @Ignore // TODO: need to fix - on naga mana tap swamp do not have added ability "add 2 any mana" (but it have after step complete) + public void nagaVitalist_GiftOfParadisesLandCanGiveAnyColorToNaga_SameStep3() { + nagaVitalist_GiftOfParadisesLandCanGiveAnyColorToNaga_Setup(3, 3, "Red"); + + assertTapped("Forest", true); + assertTapped(giftParadise, false); + assertTapped("Swamp", false); + assertTapped(nagaVitalist, true); + Assert.assertEquals(1, playerA.getManaPool().get(ManaType.RED)); + } + + @Test + public void nagaVitalist_GiftOfParadisesLandCanGiveAnyColorToNaga_DiffStep2() { + nagaVitalist_GiftOfParadisesLandCanGiveAnyColorToNaga_Setup(3, 4, "Red"); + + assertTapped("Forest", true); + assertTapped(giftParadise, false); + assertTapped("Swamp", false); + assertTapped(nagaVitalist, true); + Assert.assertEquals(1, playerA.getManaPool().get(ManaType.RED)); + } + + /* + Reported bug (issue #3315) + Naga Vitalist could not produce any color mana with a Gift of Paradise enchanted on a forest. All lands on board were forests. + */ + @Test + public void nagaVitalist_InteractionGiftOfParadise() { addCard(Zone.BATTLEFIELD, playerA, "Forest", 3); addCard(Zone.BATTLEFIELD, playerA, nagaVitalist); addCard(Zone.BATTLEFIELD, playerA, "Upwelling"); // mana pools do not empty at the end of phases or turns @@ -43,7 +144,7 @@ public class NagaVitalistTest extends CardTestPlayerBase { castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, giftParadise, "Forest"); - activateManaAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add to your mana pool one mana of any type that a land you control could produce"); + activateManaAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add to your mana pool one mana of any"); setChoice(playerA, "Red"); setStopAt(3, PhaseStep.PRECOMBAT_MAIN); @@ -51,6 +152,8 @@ public class NagaVitalistTest extends CardTestPlayerBase { assertLife(playerA, 23); // gift of paradise ETB assertTapped(nagaVitalist, true); + assertTapped(giftParadise, false); + assertTapped("Forest", false); Assert.assertEquals("one red mana has to be in the mana pool", 1, playerA.getManaPool().get(ManaType.RED)); } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/mana/ReflectingPoolTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/mana/ReflectingPoolTest.java index 8479228d8b7..9fb11214c70 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/mana/ReflectingPoolTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/mana/ReflectingPoolTest.java @@ -28,15 +28,18 @@ package org.mage.test.cards.mana; import mage.abilities.mana.ManaOptions; +import mage.constants.ManaType; import mage.constants.PhaseStep; import mage.constants.Zone; import org.junit.Assert; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; +import static org.mage.test.utils.ManaOptionsTestUtils.*; + /** * - * @author LevelX2 + * @author LevelX2, JayDi85 */ public class ReflectingPoolTest extends CardTestPlayerBase { @@ -173,16 +176,122 @@ public class ReflectingPoolTest extends CardTestPlayerBase { execute(); ManaOptions options = playerA.getAvailableManaTest(currentGame); - Assert.assertEquals("Player A should be able to create the ", "{G}{G}{G}", options.get(0).toString()); - Assert.assertEquals("Player A should be able to create the ", "{W}{G}{G}", options.get(1).toString()); - Assert.assertEquals("Player A should be able to create the ", "{W}{G}{G}", options.get(2).toString()); // ManaOption type optimzing seems not optimal yet - Assert.assertEquals("Player A should be able to create the ", "{W}{W}{G}", options.get(3).toString()); - Assert.assertEquals("Player A should be able to create only 3 different mana options", 4, options.size()); + Assert.assertEquals("Player A should be able to create only 3 different mana options", 3, options.size()); + assertManaOptions("{G}{G}{G}", options); + assertManaOptions("{W}{G}{G}", options); + assertManaOptions("{W}{W}{G}", options); options = playerB.getAvailableManaTest(currentGame); - Assert.assertEquals("Player B should be able to create the ", "{W}{G}", options.get(0).toString()); - Assert.assertEquals("Player B should be able to create the ", "{W}{W}", options.get(1).toString()); - Assert.assertEquals("Player B should be able to create only 3 different mana options", 2, options.size()); + Assert.assertEquals("Player B should be able to create only 2 different mana options", 2, options.size()); + assertManaOptions("{W}{G}", options); + assertManaOptions("{W}{W}", options); + } + + @Test + public void testReflectingPoolGiveNonMana() { + addCard(Zone.HAND, playerA, bear1, 1); + addCard(Zone.BATTLEFIELD, playerA, "Reflecting Pool", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bear1); // do not have any mana + setStopAt(1, PhaseStep.PRECOMBAT_MAIN); + execute(); + + Assert.assertEquals(0, playerA.getManaPool().getMana().count()); + assertPermanentCount(playerA, bear1, 0); + } + + @Test + public void testReflectingPoolGiveNonMana2() { + addCard(Zone.HAND, playerA, bear1, 1); + addCard(Zone.BATTLEFIELD, playerA, "Reflecting Pool", 2); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bear1); // do not have any mana + setStopAt(1, PhaseStep.PRECOMBAT_MAIN); + execute(); + + Assert.assertEquals(0, playerA.getManaPool().getMana().count()); + assertPermanentCount(playerA, bear1, 0); + } + + @Test + public void testReflectingPoolGiveBasicManaNeed() { + addCard(Zone.BATTLEFIELD, playerA, "Forest", 1); + addCard(Zone.HAND, playerA, bear1G, 1); + addCard(Zone.BATTLEFIELD, playerA, "Reflecting Pool", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bear1G); // have {G} mana to cast + setStopAt(1, PhaseStep.PRECOMBAT_MAIN); + execute(); + + assertPermanentCount(playerA, bear1G, 1); + } + + @Test + public void testReflectingPoolGiveBasicManaNotNeed() { + addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); + addCard(Zone.HAND, playerA, bear1G, 1); + addCard(Zone.BATTLEFIELD, playerA, "Reflecting Pool", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bear1G); // have only {W} mana, can't cast + setStopAt(1, PhaseStep.PRECOMBAT_MAIN); + execute(); + + assertPermanentCount(playerA, bear1G, 0); + } + + @Test + public void testReflectingPoolAnyManaNeedWithoutCondition() { + // any mana source without conditions (use any mana at any time) + addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); + addCard(Zone.BATTLEFIELD, playerA, "City of Brass", 1); + String bear2GG = "Razorclaw Bear"; + addCard(Zone.HAND, playerA, bear2GG, 1); + addCard(Zone.BATTLEFIELD, playerA, "Reflecting Pool", 1); + addCard(Zone.BATTLEFIELD, playerA, "Upwelling", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bear2GG); // 2 plains + 2 any -- can cast + setStopAt(1, PhaseStep.PRECOMBAT_MAIN); + execute(); + + assertPermanentCount(playerA, bear2GG, 1); + } + + @Test + public void testReflectingPoolAnyManaNeedWithCondition() { + // any mana source have condition to use (Reflecting Pool must ignore that condition) + addCard(Zone.BATTLEFIELD, playerA, "Cavern of Souls", 1); // {C} or {any} + addCard(Zone.HAND, playerA, bear1G, 1); + addCard(Zone.BATTLEFIELD, playerA, "Reflecting Pool", 1); + addCard(Zone.BATTLEFIELD, playerA, "Upwelling", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bear1G); // {C} from cavern and {any} (green) from reflection + setStopAt(1, PhaseStep.PRECOMBAT_MAIN); + execute(); + + assertPermanentCount(playerA, bear1G, 1); + } + + @Test + public void testReflectingPoolAnyManaTapped() { + // any mana source with tapped must allow use any too + addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); + addCard(Zone.BATTLEFIELD, playerA, "City of Brass", 1); + addCard(Zone.BATTLEFIELD, playerA, "Reflecting Pool", 1); + addCard(Zone.BATTLEFIELD, playerA, "Upwelling", 1); + + activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add one mana of any"); + activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {W}"); + setChoice(playerA,"Black"); + + setStopAt(1, PhaseStep.PRECOMBAT_MAIN); + execute(); + + logger.info(playerA.getManaPool().getMana().toString()); + logger.info(playerA.getManaAvailable(currentGame).toString()); + assertTapped("City of Brass", true); + assertTapped("Plains", true); + assertTapped("Reflecting Pool", false); + Assert.assertEquals(1, playerA.getManaPool().get(ManaType.BLACK)); } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/mana/VorinclexVoiceOfHungerTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/mana/VorinclexVoiceOfHungerTest.java index 8b78d5dccd7..f2c034fbc5c 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/mana/VorinclexVoiceOfHungerTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/mana/VorinclexVoiceOfHungerTest.java @@ -27,9 +27,11 @@ */ package org.mage.test.cards.mana; +import mage.constants.ManaType; import mage.constants.PhaseStep; import mage.constants.Zone; import mage.counters.CounterType; +import org.junit.Ignore; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; @@ -60,7 +62,28 @@ public class VorinclexVoiceOfHungerTest extends CardTestPlayerBase { execute(); assertPermanentCount(playerA, "Vedalken Mastermind", 1); + } + /** + * Vorinclex, Voice of Hunger is not mana doubling River of Tears. + */ + @Test + @Ignore // TODO: need to fix Vorinclex, Voice of Hunger -- it's double fireup mana tap event + public void testVorinclexVoiceofHungerRiverOfTearsManaMultiplier() { + addCard(Zone.BATTLEFIELD, playerA, "Upwelling", 1); + // Trample + // Whenever you tap a land for mana, add one mana to your mana pool of any type that land produced. + // Whenever an opponent taps a land for mana, that land doesn't untap during its controller's next untap step. + addCard(Zone.BATTLEFIELD, playerA, "Vorinclex, Voice of Hunger", 1); + // {T}: Add {U} to your mana pool. If you played a land this turn, add {B} to your mana pool instead. + addCard(Zone.BATTLEFIELD, playerA, "River of Tears", 1); + + activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {U} to your mana pool"); + + setStopAt(1, PhaseStep.PRECOMBAT_MAIN); + execute(); + + assertManaPool(playerA, ManaType.BLUE, 2); } /** diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java index fcf5b769b0e..537d8b18422 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java @@ -837,22 +837,22 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement ManaPool manaPool = currentGame.getPlayer(player.getId()).getManaPool(); switch (color){ case COLORLESS: - Assert.assertEquals(manaPool.getColorless() + manaPool.getConditionalMana().stream().mapToInt(Mana::getColorless).sum(), amount); + Assert.assertEquals(amount,manaPool.getColorless() + manaPool.getConditionalMana().stream().mapToInt(Mana::getColorless).sum()); break; case RED: - Assert.assertEquals(manaPool.getRed() + manaPool.getConditionalMana().stream().mapToInt(Mana::getRed).sum(), amount); + Assert.assertEquals(amount,manaPool.getRed() + manaPool.getConditionalMana().stream().mapToInt(Mana::getRed).sum()); break; case BLUE: - Assert.assertEquals(manaPool.getBlue() + manaPool.getConditionalMana().stream().mapToInt(Mana::getBlue).sum(), amount); + Assert.assertEquals(amount,manaPool.getBlue() + manaPool.getConditionalMana().stream().mapToInt(Mana::getBlue).sum()); break; case WHITE: - Assert.assertEquals(manaPool.getWhite() + manaPool.getConditionalMana().stream().mapToInt(Mana::getWhite).sum(), amount); + Assert.assertEquals(amount,manaPool.getWhite() + manaPool.getConditionalMana().stream().mapToInt(Mana::getWhite).sum()); break; case GREEN: - Assert.assertEquals(manaPool.getGreen() + manaPool.getConditionalMana().stream().mapToInt(Mana::getGreen).sum(), amount); + Assert.assertEquals(amount,manaPool.getGreen() + manaPool.getConditionalMana().stream().mapToInt(Mana::getGreen).sum()); break; case BLACK: - Assert.assertEquals(manaPool.getBlack() + manaPool.getConditionalMana().stream().mapToInt(Mana::getBlack).sum(), amount); + Assert.assertEquals(amount,manaPool.getBlack() + manaPool.getConditionalMana().stream().mapToInt(Mana::getBlack).sum()); break; } } diff --git a/Mage.Tests/src/test/java/org/mage/test/utils/ManaOptionsTest.java b/Mage.Tests/src/test/java/org/mage/test/utils/ManaOptionsTest.java index 91ea81bf863..7bb3f892bed 100644 --- a/Mage.Tests/src/test/java/org/mage/test/utils/ManaOptionsTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/utils/ManaOptionsTest.java @@ -35,12 +35,13 @@ import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; +import static org.mage.test.utils.ManaOptionsTestUtils.*; /** * This test checks if the calculated possible mana options are correct related * to the given mana sources available. * - * @author LevelX2 + * @author LevelX2, JayDi85 */ public class ManaOptionsTest extends CardTestPlayerBase { @@ -52,9 +53,10 @@ public class ManaOptionsTest extends CardTestPlayerBase { execute(); ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + assertDuplicatedManaOptions(manaOptions); Assert.assertEquals("mana variations don't fit", 1, manaOptions.size()); - Assert.assertEquals("{G}{G}{G}", getManaOption(0, manaOptions)); + assertManaOptions("{G}{G}{G}", manaOptions); } @@ -69,12 +71,13 @@ public class ManaOptionsTest extends CardTestPlayerBase { execute(); ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + assertDuplicatedManaOptions(manaOptions); Assert.assertEquals("mana variations don't fit", 4, manaOptions.size()); - Assert.assertEquals("{G}{G}{G}", getManaOption(0, manaOptions)); - Assert.assertEquals("{W}{R}{G}{G}", getManaOption(1, manaOptions)); - Assert.assertEquals("{W}{W}{R}{R}{G}", getManaOption(2, manaOptions)); - Assert.assertEquals("{W}{W}{W}{R}{R}{R}", getManaOption(3, manaOptions)); + assertManaOptions("{G}{G}{G}", manaOptions); + assertManaOptions("{W}{R}{G}{G}", manaOptions); + assertManaOptions("{W}{W}{R}{R}{G}", manaOptions); + assertManaOptions("{W}{W}{W}{R}{R}{R}", manaOptions); } @@ -89,18 +92,19 @@ public class ManaOptionsTest extends CardTestPlayerBase { execute(); ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + assertDuplicatedManaOptions(manaOptions); Assert.assertEquals("mana variations don't fit", 10, manaOptions.size()); - Assert.assertEquals("{C}{C}{C}", getManaOption(0, manaOptions)); - Assert.assertEquals("{C}{C}{W}", getManaOption(1, manaOptions)); - Assert.assertEquals("{C}{C}{U}", getManaOption(2, manaOptions)); - Assert.assertEquals("{C}{W}{W}", getManaOption(3, manaOptions)); - Assert.assertEquals("{C}{W}{U}", getManaOption(4, manaOptions)); - Assert.assertEquals("{C}{U}{U}", getManaOption(5, manaOptions)); - Assert.assertEquals("{W}{W}{W}", getManaOption(6, manaOptions)); - Assert.assertEquals("{W}{W}{U}", getManaOption(7, manaOptions)); - Assert.assertEquals("{W}{U}{U}", getManaOption(8, manaOptions)); - Assert.assertEquals("{U}{U}{U}", getManaOption(9, manaOptions)); + assertManaOptions("{C}{C}{C}", manaOptions); + assertManaOptions("{C}{C}{W}", manaOptions); + assertManaOptions("{C}{C}{U}", manaOptions); + assertManaOptions("{C}{W}{W}", manaOptions); + assertManaOptions("{C}{W}{U}", manaOptions); + assertManaOptions("{C}{U}{U}", manaOptions); + assertManaOptions("{W}{W}{W}", manaOptions); + assertManaOptions("{W}{W}{U}", manaOptions); + assertManaOptions("{W}{U}{U}", manaOptions); + assertManaOptions("{U}{U}{U}", manaOptions); } // Chromatic Sphere @@ -114,9 +118,10 @@ public class ManaOptionsTest extends CardTestPlayerBase { execute(); ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + assertDuplicatedManaOptions(manaOptions); Assert.assertEquals("mana variations don't fit", 1, manaOptions.size()); - Assert.assertEquals("{Any}{Any}", getManaOption(0, manaOptions)); + assertManaOptions("{Any}{Any}", manaOptions); } // Orochi Leafcaller @@ -131,9 +136,10 @@ public class ManaOptionsTest extends CardTestPlayerBase { execute(); ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + assertDuplicatedManaOptions(manaOptions); Assert.assertEquals("mana variations don't fit", 1, manaOptions.size()); - Assert.assertEquals("{W}{W}{Any}{Any}", getManaOption(0, manaOptions)); + assertManaOptions("{W}{W}{Any}{Any}", manaOptions); } // Crystal Quarry @@ -149,9 +155,10 @@ public class ManaOptionsTest extends CardTestPlayerBase { execute(); ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + assertDuplicatedManaOptions(manaOptions); Assert.assertEquals("mana variations don't fit", 1, manaOptions.size()); - Assert.assertEquals("{C}{W}{W}{G}{G}", getManaOption(0, manaOptions)); + assertManaOptions("{C}{W}{W}{G}{G}", manaOptions); } // Crystal Quarry @@ -167,10 +174,11 @@ public class ManaOptionsTest extends CardTestPlayerBase { execute(); ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + assertDuplicatedManaOptions(manaOptions); Assert.assertEquals("mana variations don't fit", 2, manaOptions.size()); - Assert.assertEquals("{C}{W}{W}{G}{G}{G}", getManaOption(0, manaOptions)); - Assert.assertEquals("{W}{U}{B}{R}{G}", getManaOption(1, manaOptions)); + assertManaOptions("{C}{W}{W}{G}{G}{G}", manaOptions); + assertManaOptions("{W}{U}{B}{R}{G}", manaOptions); } // Nykthos, Shrine to Nyx @@ -186,28 +194,30 @@ public class ManaOptionsTest extends CardTestPlayerBase { execute(); ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + assertDuplicatedManaOptions(manaOptions); Assert.assertEquals("mana variations don't fit", 2, manaOptions.size()); - Assert.assertEquals("{C}{G}{G}{G}", getManaOption(0, manaOptions)); - Assert.assertEquals("{G}{G}{G}{G}{G}", getManaOption(1, manaOptions)); + assertManaOptions("{C}{G}{G}{G}", manaOptions); + assertManaOptions("{G}{G}{G}{G}{G}", manaOptions); } @Test public void testNykthos2() { addCard(Zone.BATTLEFIELD, playerA, "Sedge Scorpion", 4); addCard(Zone.BATTLEFIELD, playerA, "Akroan Crusader", 3); - addCard(Zone.BATTLEFIELD, playerA, "Forest", 3); - addCard(Zone.BATTLEFIELD, playerA, "Nykthos, Shrine to Nyx", 1); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 3); // {G} + addCard(Zone.BATTLEFIELD, playerA, "Nykthos, Shrine to Nyx", 1); // {C} setStopAt(1, PhaseStep.UPKEEP); execute(); ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + assertDuplicatedManaOptions(manaOptions); Assert.assertEquals("mana variations don't fit", 3, manaOptions.size()); - Assert.assertEquals("{C}{G}{G}{G}", getManaOption(0, manaOptions)); - Assert.assertEquals("{G}{G}{G}{G}{G}", getManaOption(1, manaOptions)); - Assert.assertEquals("{R}{R}{R}{G}", getManaOption(2, manaOptions)); + assertManaOptions("{C}{G}{G}{G}", manaOptions); + assertManaOptions("{G}{G}{G}{G}{G}", manaOptions); + assertManaOptions("{R}{R}{R}{G}", manaOptions); } @Test @@ -220,13 +230,46 @@ public class ManaOptionsTest extends CardTestPlayerBase { execute(); ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + assertDuplicatedManaOptions(manaOptions); Assert.assertEquals("mana variations don't fit", 1, manaOptions.size()); - Assert.assertEquals("{C}{G}{Any}", getManaOption(0, manaOptions)); + assertManaOptions("{C}{G}{Any}", manaOptions); } @Test - public void testMix1() { + public void testDuplicatedDontHave1() { + addCard(Zone.BATTLEFIELD, playerA, "City of Brass", 2); // Any + addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); + + setStopAt(1, PhaseStep.UPKEEP); + execute(); + + ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + assertDuplicatedManaOptions(manaOptions); + } + + @Test + public void testDuplicatedDontHave3() { + addCard(Zone.BATTLEFIELD, playerA, "Grove of the Burnwillows", 2); // R or G + addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); + + setStopAt(1, PhaseStep.UPKEEP); + execute(); + + ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + assertDuplicatedManaOptions(manaOptions); + } + + @Test + public void testDuplicatedHave() { + // getManaAvailable return any combination of mana variants evailable to player + // if mana ability cost another mana then if replaced in mana cost + // example: + // 1x forest + // 1x Chromatic Star ({1}, {T}, Sacrifice Chromatic Star: Add one mana of any color to your mana pool.) + // give {G}{Any}, but after pay it transform to {Any} (1 green will be pay) + // That's why there are can be duplicated records in getManaAvailable + // {1}, {T}, Sacrifice Chromatic Star: Add one mana of any color to your mana pool. // When Chromatic Star is put into a graveyard from the battlefield, draw a card. addCard(Zone.BATTLEFIELD, playerA, "Chromatic Star", 1); @@ -242,10 +285,9 @@ public class ManaOptionsTest extends CardTestPlayerBase { execute(); ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); - - Assert.assertEquals("mana variations don't fit", 2, manaOptions.size()); - Assert.assertEquals("{Any}{Any}", getManaOption(0, manaOptions)); - Assert.assertEquals("{Any}{Any}", getManaOption(1, manaOptions)); + Assert.assertEquals("mana variations don't fit", 1, manaOptions.size()); + assertDuplicatedManaOptions(manaOptions); + assertManaOptions("{Any}{Any}", manaOptions); } @Test @@ -257,12 +299,13 @@ public class ManaOptionsTest extends CardTestPlayerBase { execute(); ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + assertDuplicatedManaOptions(manaOptions); Assert.assertEquals("mana variations don't fit", 4, manaOptions.size()); - Assert.assertEquals("{C}{W}", getManaOption(0, manaOptions)); - Assert.assertEquals("{W}{W}", getManaOption(1, manaOptions)); - Assert.assertEquals("{W}{B}", getManaOption(2, manaOptions)); - Assert.assertEquals("{B}{B}", getManaOption(3, manaOptions)); + assertManaOptions("{C}{W}", manaOptions); + assertManaOptions("{W}{W}", manaOptions); + assertManaOptions("{W}{B}", manaOptions); + assertManaOptions("{B}{B}", manaOptions); } /** @@ -278,9 +321,10 @@ public class ManaOptionsTest extends CardTestPlayerBase { execute(); ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + assertDuplicatedManaOptions(manaOptions); Assert.assertEquals("mana variations don't fit", 1, manaOptions.size()); - Assert.assertEquals("{W}{B}", getManaOption(0, manaOptions)); + assertManaOptions("{W}{B}", manaOptions); } @Test @@ -293,10 +337,11 @@ public class ManaOptionsTest extends CardTestPlayerBase { execute(); ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + assertDuplicatedManaOptions(manaOptions); Assert.assertEquals("mana variations don't fit", 2, manaOptions.size()); - Assert.assertEquals("{W}{B}{B}", getManaOption(0, manaOptions)); - Assert.assertEquals("{B}{B}{B}", getManaOption(1, manaOptions)); + assertManaOptions("{W}{B}{B}", manaOptions); + assertManaOptions("{B}{B}{B}", manaOptions); } @Test @@ -312,9 +357,10 @@ public class ManaOptionsTest extends CardTestPlayerBase { execute(); ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + assertDuplicatedManaOptions(manaOptions); Assert.assertEquals("mana variations don't fit", 1, manaOptions.size()); - Assert.assertEquals("{C}{W}{B}", getManaOption(0, manaOptions)); + assertManaOptions("{C}{W}{B}", manaOptions); } @Test @@ -331,9 +377,10 @@ public class ManaOptionsTest extends CardTestPlayerBase { execute(); ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + assertDuplicatedManaOptions(manaOptions); Assert.assertEquals("mana variations don't fit", 1, manaOptions.size()); - Assert.assertEquals("{C}{C}{C}{C}{W}{B}", getManaOption(0, manaOptions)); + assertManaOptions("{C}{C}{C}{C}{W}{B}", manaOptions); } @Test @@ -349,17 +396,9 @@ public class ManaOptionsTest extends CardTestPlayerBase { execute(); ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + assertDuplicatedManaOptions(manaOptions); Assert.assertEquals("mana variations don't fit", 1, manaOptions.size()); - Assert.assertEquals("{B}{B}", getManaOption(0, manaOptions)); - } - - // TODO - // Test Calciform Pools combination mana lands - private String getManaOption(int index, ManaOptions manaOptions) { - if (manaOptions.size() < index + 1) { - return ""; - } - return manaOptions.get(index).toString(); + assertManaOptions("{B}{B}", manaOptions); } } diff --git a/Mage.Tests/src/test/java/org/mage/test/utils/ManaOptionsTestUtils.java b/Mage.Tests/src/test/java/org/mage/test/utils/ManaOptionsTestUtils.java new file mode 100644 index 00000000000..04d0e8cceac --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/utils/ManaOptionsTestUtils.java @@ -0,0 +1,48 @@ +package org.mage.test.utils; + +import mage.Mana; +import mage.abilities.mana.ManaOptions; +import org.junit.Assert; + +import java.util.HashSet; +import java.util.Set; + +public class ManaOptionsTestUtils { + + public static String bear1W = "Silvercoat Lion"; // {1}{W} + public static String bearG = "Basking Rootwalla"; // {G} + public static String bear1 = "Augmenting Automaton"; // {1} + public static String bear1G = "Balduvian Bears"; // {1}{G} + public static String bear2C = "Matter Reshaper"; // {2}{C} + + //mana info + //logger.info(playerA.getManaPool().getMana().toString()); + //logger.info(playerA.getManaAvailable(currentGame).toString()); + + public static boolean manaOptionsContain(ManaOptions list, String searchMana){ + for(Mana mana: list){ + if (mana.toString().equals(searchMana)){ + return true; + } + } + return false; + } + + public static void assertManaOptions(String searchMana, ManaOptions manaList){ + if(!manaOptionsContain(manaList, searchMana)){ + Assert.fail("Can't find " + searchMana + " in " + manaList.toString()); + } + } + + public static void assertDuplicatedManaOptions(ManaOptions manaList){ + Set list = new HashSet<>(); + for(Mana mana: manaList){ + String s = mana.toString(); + if(list.contains(s)){ + Assert.fail("Founded duplicated mana option " + s + " in " + manaList.toString()); + }else{ + list.add(s); + } + } + } +} diff --git a/Mage/src/main/java/mage/Mana.java b/Mage/src/main/java/mage/Mana.java index 5e4ea50e9a0..b2461d2b367 100644 --- a/Mage/src/main/java/mage/Mana.java +++ b/Mage/src/main/java/mage/Mana.java @@ -221,6 +221,19 @@ public class Mana implements Comparable, Serializable, Copyable { return new Mana(0, 0, 0, 0, 0, 0, 0, notNegative(num, "Colorless")); } + /** + * Creates a {@link Mana} object with the passed in {@code num} of Any + * mana. {@code num} can not be a negative value. Negative values will be + * logged and set to 0. + * + * @param num value of Any mana to create. + * @return a {@link Mana} object with the passed in {@code num} of Any + * mana. + */ + public static Mana AnyMana(int num) { + return new Mana(0, 0, 0, 0, 0, 0, notNegative(num, "Any"), 0); + } + /** * Adds mana from the passed in {@link Mana} object to this object. * diff --git a/Mage/src/main/java/mage/abilities/effects/common/AddManaOfAnyColorEffect.java b/Mage/src/main/java/mage/abilities/effects/common/AddManaOfAnyColorEffect.java index bd9b5aacee5..52e3a0fb3bf 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/AddManaOfAnyColorEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/AddManaOfAnyColorEffect.java @@ -69,11 +69,13 @@ public class AddManaOfAnyColorEffect extends BasicManaEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - ChoiceColor choice = new ChoiceColor(true); + String mes = String.format("Select color of %d mana to add it to your mana pool", this.amount); + ChoiceColor choice = new ChoiceColor(true, mes, game.getObject(source.getSourceId())); if (controller.choose(outcome, choice, game)) { if (choice.getColor() == null) { - return false; // it happens, don't know how + // on user's reconnect choice dialog close and return null even with required settings + return false; } Mana createdMana = choice.getMana(amount); if (createdMana != null) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/ChooseCreatureTypeEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ChooseCreatureTypeEffect.java index 3a9b80b9941..f707e908249 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/ChooseCreatureTypeEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ChooseCreatureTypeEffect.java @@ -33,6 +33,7 @@ import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.choices.Choice; +import mage.choices.ChoiceCreatureType; import mage.choices.ChoiceImpl; import mage.constants.Outcome; import mage.constants.SubType; @@ -63,9 +64,7 @@ public class ChooseCreatureTypeEffect extends OneShotEffect { mageObject = game.getObject(source.getSourceId()); } if (controller != null && mageObject != null) { - Choice typeChoice = new ChoiceImpl(true); - typeChoice.setMessage("Choose creature type"); - typeChoice.setChoices(SubType.getCreatureTypes(false).stream().map(SubType::toString).collect(Collectors.toCollection(LinkedHashSet::new))); + Choice typeChoice = new ChoiceCreatureType(mageObject); while (!controller.choose(outcome, typeChoice, game)) { if (!controller.canRespond()) { return false; diff --git a/Mage/src/main/java/mage/abilities/mana/AnyColorLandsProduceManaAbility.java b/Mage/src/main/java/mage/abilities/mana/AnyColorLandsProduceManaAbility.java index 3a6b662e4cc..2447bd0c501 100644 --- a/Mage/src/main/java/mage/abilities/mana/AnyColorLandsProduceManaAbility.java +++ b/Mage/src/main/java/mage/abilities/mana/AnyColorLandsProduceManaAbility.java @@ -225,6 +225,9 @@ class AnyColorLandsProduceManaEffect extends ManaEffect { if (types.getColorless() > 0) { netManas.add(Mana.ColorlessMana(1)); } + if (types.getAny() > 0) { + netManas.add(Mana.AnyMana(1)); + } return netManas; } diff --git a/Mage/src/main/java/mage/abilities/mana/ManaOptions.java b/Mage/src/main/java/mage/abilities/mana/ManaOptions.java index f5402422dc5..dd90f3a57d0 100644 --- a/Mage/src/main/java/mage/abilities/mana/ManaOptions.java +++ b/Mage/src/main/java/mage/abilities/mana/ManaOptions.java @@ -28,7 +28,10 @@ package mage.abilities.mana; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; + import mage.Mana; import mage.game.Game; @@ -326,4 +329,19 @@ public class ManaOptions extends ArrayList { payCombinations.add(newMana); payCombinationsStrings.add(newMana.toString()); } + + + public void removeDuplicated(){ + Set list = new HashSet<>(); + + for(int i = this.size() - 1; i >= 0; i--){ + String s = this.get(i).toString(); + if (list.contains(s)){ + // remove duplicated + this.remove(i); + }else{ + list.add(s); + } + } + } } diff --git a/Mage/src/main/java/mage/choices/Choice.java b/Mage/src/main/java/mage/choices/Choice.java index 9a20c066bb4..3bfcffa2a83 100644 --- a/Mage/src/main/java/mage/choices/Choice.java +++ b/Mage/src/main/java/mage/choices/Choice.java @@ -37,19 +37,34 @@ import java.util.Set; */ public interface Choice { - boolean isChosen(); - boolean isRequired(); - void clearChoice(); String getMessage(); void setMessage(String message); - void setChoice(String choice); - void setChoiceByKey(String choiceKey); - Set getChoices(); - Map getKeyChoices(); - void setChoices(Set choices); - void setKeyChoices(Map choices); - String getChoice(); - String getChoiceKey(); - boolean isKeyChoice(); + + String getSubMessage(); + void setSubMessage(String subMessage); + + void clearChoice(); + boolean isChosen(); + boolean isRequired(); + Choice copy(); + + // string choice + void setChoices(Set choices); + Set getChoices(); + void setChoice(String choice); + String getChoice(); + + // key-value choice + boolean isKeyChoice(); + void setKeyChoices(Map choices); + Map getKeyChoices(); + void setChoiceByKey(String choiceKey); + String getChoiceKey(); + + // search + boolean isSearchEnabled(); + void setSearchEnabled(boolean isEnabled); + void setSearchText(String searchText); + String getSearchText(); } diff --git a/Mage/src/main/java/mage/choices/ChoiceColor.java b/Mage/src/main/java/mage/choices/ChoiceColor.java index 55531613e8d..6f7255a729a 100644 --- a/Mage/src/main/java/mage/choices/ChoiceColor.java +++ b/Mage/src/main/java/mage/choices/ChoiceColor.java @@ -27,17 +27,22 @@ */ package mage.choices; -import java.util.ArrayList; +import mage.MageObject; import mage.Mana; import mage.ObjectColor; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; + /** * * @author BetaSteward_at_googlemail.com */ public class ChoiceColor extends ChoiceImpl { - public static final ArrayList colorChoices = new ArrayList<>(); + //public static final Set colorChoices = new HashSet<>(); // JayDi85: uncomment 1 of 2 to broke unit tests find wrong tests (?) + public static final ArrayList colorChoices = new ArrayList<>(); static { colorChoices.add("Green"); @@ -52,9 +57,25 @@ public class ChoiceColor extends ChoiceImpl { } public ChoiceColor(boolean required) { + this(required, "Choose color"); + } + + public ChoiceColor(boolean required, String chooseMessage){ + this(required, chooseMessage, ""); + } + + public ChoiceColor(boolean required, String chooseMessage, MageObject source){ + this(required, chooseMessage, source.getIdName()); + } + + public ChoiceColor(boolean required, String chooseMessage, String chooseSubMessage){ super(required); + this.choices.addAll(colorChoices); - this.message = "Choose color"; + //this.setChoices(colorChoices); // JayDi85: uncomment 2 of 2 to broke unit tests find wrong tests (?) + + this.setMessage(chooseMessage); + this.setSubMessage(chooseSubMessage); } public ChoiceColor(final ChoiceColor choice) { diff --git a/Mage/src/main/java/mage/choices/ChoiceCreatureType.java b/Mage/src/main/java/mage/choices/ChoiceCreatureType.java index 558a6ecb5c4..7ffbab88294 100644 --- a/Mage/src/main/java/mage/choices/ChoiceCreatureType.java +++ b/Mage/src/main/java/mage/choices/ChoiceCreatureType.java @@ -1,5 +1,6 @@ package mage.choices; +import mage.MageObject; import mage.constants.SubType; import java.util.LinkedHashSet; @@ -7,10 +8,28 @@ import java.util.stream.Collectors; public class ChoiceCreatureType extends ChoiceImpl { + private static String DEFAULT_MESSAGE = "Choose a creature type"; + public ChoiceCreatureType() { - super(true); + this(true, DEFAULT_MESSAGE, null); + } + + public ChoiceCreatureType(MageObject source) { + this(true, DEFAULT_MESSAGE, source); + } + + public ChoiceCreatureType(String chooseMessage, MageObject source) { + this(true, chooseMessage, source); + } + + public ChoiceCreatureType(boolean required, String chooseMessage, MageObject source){ + super(required); this.setChoices(SubType.getCreatureTypes(false).stream().map(SubType::toString).collect(Collectors.toCollection(LinkedHashSet::new))); - this.message = "Choose a creature type:"; + this.setMessage(chooseMessage); + if(source != null) { + this.setSubMessage(source.getIdName()); + } + this.setSearchEnabled(true); } public ChoiceCreatureType(final ChoiceCreatureType choice) { diff --git a/Mage/src/main/java/mage/choices/ChoiceImpl.java b/Mage/src/main/java/mage/choices/ChoiceImpl.java index bee47239a86..3656c70d2e5 100644 --- a/Mage/src/main/java/mage/choices/ChoiceImpl.java +++ b/Mage/src/main/java/mage/choices/ChoiceImpl.java @@ -40,6 +40,7 @@ import java.util.Set; */ public class ChoiceImpl implements Choice, Serializable { + // TODO: add sorting to items protected boolean chosen; protected final boolean required; protected String choice; @@ -47,6 +48,9 @@ public class ChoiceImpl implements Choice, Serializable { protected Set choices = new LinkedHashSet<>(); protected Map keyChoices = new LinkedHashMap<>(); protected String message; + protected String subMessage; + protected boolean searchEnabled = true; // enable for all windows by default + protected String searchText; public ChoiceImpl() { this(false); @@ -61,6 +65,7 @@ public class ChoiceImpl implements Choice, Serializable { this.chosen = choice.chosen; this.required = choice.required; this.message = choice.message; + this.message = choice.subMessage; this.choices.addAll(choice.choices); this.choiceKey = choice.choiceKey; this.keyChoices = choice.keyChoices; // list should never change for the same object so copy by reference @@ -88,6 +93,12 @@ public class ChoiceImpl implements Choice, Serializable { this.message = message; } + @Override + public String getSubMessage(){ return subMessage; } + + @Override + public void setSubMessage(String subMessage){ this.subMessage = subMessage; } + @Override public Set getChoices() { return choices; @@ -150,4 +161,24 @@ public class ChoiceImpl implements Choice, Serializable { return !keyChoices.isEmpty(); } -} + @Override + public boolean isSearchEnabled(){ + return this.searchEnabled; + }; + + @Override + public void setSearchEnabled(boolean isEnabled){ + this.searchEnabled = isEnabled; + }; + + @Override + public void setSearchText(String searchText){ + this.searchText = searchText; + }; + + @Override + public String getSearchText(){ + return this.searchText; + }; + +} \ No newline at end of file diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index 64c9fde58e0..6233a4ed6f2 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -2439,6 +2439,10 @@ public abstract class PlayerImpl implements Player, Serializable { for (Abilities manaAbilities : sourceWithCosts) { available.addManaWithCost(manaAbilities, game); } + + // remove duplicated variants (see ManaOptionsTest for info - when thats rises) + available.removeDuplicated(); + return available; }