From 46081d9185c489eddea1ca78ef4851585e76ae9c Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Mon, 20 Sep 2021 02:17:22 +0400 Subject: [PATCH] GUI related improves: * GUI: fixed that choose triggers/piles dialog doesn't close correctly before cast mode choose (#8225); * GUI: fixed that some choose dialogs doesn't update battlefield state (example: choose amount, choose mana); * Game: fixed duplicated json logs at the game's end; --- .../components/ability/AbilityPicker.java | 2 +- .../java/mage/client/game/FeedbackPanel.java | 54 +++++--- .../main/java/mage/client/game/GamePanel.java | 131 ++++++++++++------ .../client/remote/CallbackClientImpl.java | 50 +++---- .../java/mage/view/AbilityPickerView.java | 21 ++- .../java/mage/view/GameClientMessage.java | 81 ++++------- .../java/mage/server/game/GameController.java | 4 +- .../mage/server/game/GameSessionPlayer.java | 18 +-- .../mage/server/game/GameSessionWatcher.java | 7 +- .../test/serverside/AbilityPickerTest.java | 13 +- Mage/src/main/java/mage/util/CardUtil.java | 2 +- 11 files changed, 212 insertions(+), 171 deletions(-) diff --git a/Mage.Client/src/main/java/mage/client/components/ability/AbilityPicker.java b/Mage.Client/src/main/java/mage/client/components/ability/AbilityPicker.java index 648c17bd62..855f8f13b4 100644 --- a/Mage.Client/src/main/java/mage/client/components/ability/AbilityPicker.java +++ b/Mage.Client/src/main/java/mage/client/components/ability/AbilityPicker.java @@ -22,7 +22,7 @@ import java.util.List; import java.util.*; /** - * Dialog for choosing abilities. + * GUI: Dialog for choosing abilities (list) * * @author nantuko, JayDi85 */ diff --git a/Mage.Client/src/main/java/mage/client/game/FeedbackPanel.java b/Mage.Client/src/main/java/mage/client/game/FeedbackPanel.java index 5a2274d636..13ff20959a 100644 --- a/Mage.Client/src/main/java/mage/client/game/FeedbackPanel.java +++ b/Mage.Client/src/main/java/mage/client/game/FeedbackPanel.java @@ -14,6 +14,7 @@ import org.apache.log4j.Logger; import java.awt.*; import java.awt.event.ActionEvent; import java.io.Serializable; +import java.util.HashMap; import java.util.Map; import java.util.UUID; import java.util.concurrent.Executors; @@ -38,6 +39,7 @@ public class FeedbackPanel extends javax.swing.JPanel { private MageDialog connectedDialog; private ChatPanelBasic connectedChatPanel; private int lastMessageId; + private Map lastOptions = new HashMap<>(); private static final ScheduledExecutorService WORKER = Executors.newSingleThreadScheduledExecutor(); @@ -63,8 +65,8 @@ public class FeedbackPanel extends javax.swing.JPanel { private void setGUISize() { } - public void getFeedback(FeedbackMode mode, String message, boolean special, Map options, - int messageId, boolean gameNeedUserFeedback, TurnPhase gameTurnPhase) { + public void prepareFeedback(FeedbackMode mode, String message, boolean special, Map options, + int messageId, boolean gameNeedUserFeedback, TurnPhase gameTurnPhase) { synchronized (this) { if (messageId < this.lastMessageId) { // if too many warning messages here then look at GAME_REDRAW_GUI event logic @@ -72,13 +74,16 @@ public class FeedbackPanel extends javax.swing.JPanel { return; } this.lastMessageId = messageId; + this.lastOptions = options; + this.mode = mode; } + this.helper.setBasicMessage(message); this.helper.setOriginalId(null); // reference to the feedback causing ability String lblText = addAdditionalText(message, options); this.helper.setTextArea(lblText); - this.mode = mode; + switch (this.mode) { case INFORM: setButtonState("", "", mode); @@ -113,7 +118,7 @@ public class FeedbackPanel extends javax.swing.JPanel { } requestFocusIfPossible(); - handleOptions(options); + updateOptions(options); this.revalidate(); this.repaint(); @@ -167,29 +172,35 @@ public class FeedbackPanel extends javax.swing.JPanel { WORKER.schedule(task, 8, TimeUnit.SECONDS); } - private void handleOptions(Map options) { - // clear already opened dialog (second request) - if (connectedDialog != null) { - connectedDialog.removeDialog(); - connectedDialog = null; - } + public void updateOptions(Map options) { + this.lastOptions = options; - if (options != null) { - if (options.containsKey("UI.left.btn.text")) { - String text = (String) options.get("UI.left.btn.text"); + if (this.lastOptions != null) { + if (this.lastOptions.containsKey("UI.left.btn.text")) { + String text = (String) this.lastOptions.get("UI.left.btn.text"); this.btnLeft.setText(text); this.helper.setLeft(text, !text.isEmpty()); } - if (options.containsKey("UI.right.btn.text")) { - String text = (String) options.get("UI.right.btn.text"); + if (this.lastOptions.containsKey("UI.right.btn.text")) { + String text = (String) this.lastOptions.get("UI.right.btn.text"); this.btnRight.setText(text); this.helper.setRight(text, !text.isEmpty()); } - if (options.containsKey("dialog")) { - connectedDialog = (MageDialog) options.get("dialog"); - } - + updateConnectedDialog((MageDialog) this.lastOptions.getOrDefault("dialog", null)); this.helper.autoSizeButtonsAndFeedbackState(); + } else { + updateConnectedDialog(null); + } + } + + private void updateConnectedDialog(MageDialog newDialog) { + if (this.connectedDialog != null && this.connectedDialog != newDialog) { + // remove old + this.connectedDialog.removeDialog(); + } + this.connectedDialog = newDialog; + if (this.connectedDialog != null) { + this.connectedDialog.setVisible(true); } } @@ -244,10 +255,7 @@ public class FeedbackPanel extends javax.swing.JPanel { } private void btnRightActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRightActionPerformed - if (connectedDialog != null) { - connectedDialog.removeDialog(); - connectedDialog = null; - } + updateConnectedDialog(null); if (mode == FeedbackMode.SELECT && (evt.getModifiers() & ActionEvent.CTRL_MASK) == ActionEvent.CTRL_MASK) { SessionHandler.sendPlayerInteger(gameId, 0); } else if (mode == FeedbackMode.END) { 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 503fe93af9..83f3862b05 100644 --- a/Mage.Client/src/main/java/mage/client/game/GamePanel.java +++ b/Mage.Client/src/main/java/mage/client/game/GamePanel.java @@ -274,8 +274,7 @@ public final class GamePanel extends javax.swing.JPanel { windowDialog.removeDialog(); } - clearPickTargetDialogs(); - clearPickPileDialogs(); + clearPickDialogs(); Plugins.instance.getActionCallback().hideOpenComponents(); try { @@ -288,18 +287,41 @@ public final class GamePanel extends javax.swing.JPanel { this.bigCard = null; } + private void hidePickDialogs() { + // temporary hide opened dialog on redraw/update + + //try { + // pick target + for (ShowCardsDialog dialog : this.pickTarget) { + dialog.setVisible(false); + } + // pick pile + for (PickPileDialog dialog : this.pickPile) { + dialog.setVisible(false); + } + //} catch (PropertyVetoException e) { + // logger.error("Couldn't close pick dialog", e); + //} + } + + private void clearPickDialogs() { + // remove dialogs forever on clean or full update + clearPickTargetDialogs(); + clearPickPileDialogs(); + } + private void clearPickTargetDialogs() { - for (ShowCardsDialog pickTargetDialog : this.pickTarget) { - pickTargetDialog.cleanUp(); - pickTargetDialog.removeDialog(); + for (ShowCardsDialog dialog : this.pickTarget) { + dialog.cleanUp(); + dialog.removeDialog(); } this.pickTarget.clear(); } private void clearPickPileDialogs() { - for (PickPileDialog pickPileDialog : this.pickPile) { - pickPileDialog.cleanUp(); - pickPileDialog.removeDialog(); + for (PickPileDialog dialog : this.pickPile) { + dialog.cleanUp(); + dialog.removeDialog(); } this.pickPile.clear(); } @@ -929,6 +951,7 @@ public final class GamePanel extends javax.swing.JPanel { } feedbackPanel.disableUndo(); + feedbackPanel.updateOptions(lastGameData.options); this.revalidate(); this.repaint(); @@ -1344,7 +1367,7 @@ public final class GamePanel extends javax.swing.JPanel { public void ask(String question, GameView gameView, int messageId, Map options) { updateGame(gameView, false, options, null); - this.feedbackPanel.getFeedback(FeedbackMode.QUESTION, question, false, options, messageId, true, gameView.getPhase()); + this.feedbackPanel.prepareFeedback(FeedbackMode.QUESTION, question, false, options, messageId, true, gameView.getPhase()); } private void keepLastGameData(GameView game, boolean showPlayable, Map options, Set targets) { @@ -1604,11 +1627,16 @@ public final class GamePanel extends javax.swing.JPanel { * @param options * @param messageId */ - public void pickTarget(String message, CardsView cardsView, GameView gameView, Set targets, boolean required, Map options, int messageId) { + public void pickTarget(GameView gameView, Map options, String message, CardsView cardsView, Set targets, boolean required, int messageId) { + updateGame(gameView, false, options, targets); + hideAll(); + DialogManager.getManager(gameId).fadeOut(); + clearPickTargetDialogs(); + PopUpMenuType popupMenuType = null; - if (options != null) { + if (lastGameData.options != null) { if (options.containsKey("queryType")) { - PlayerQueryEvent.QueryType needType = (PlayerQueryEvent.QueryType) options.get("queryType"); + PlayerQueryEvent.QueryType needType = (PlayerQueryEvent.QueryType) lastGameData.options.get("queryType"); switch (needType) { case PICK_ABILITY: popupMenuType = PopUpMenuType.TRIGGER_ORDER; @@ -1622,17 +1650,13 @@ public final class GamePanel extends javax.swing.JPanel { } } - updateGame(gameView, false, options, targets); - - Map options0 = options == null ? new HashMap<>() : options; + Map options0 = lastGameData.options == null ? new HashMap<>() : lastGameData.options; ShowCardsDialog dialog = null; if (cardsView != null && !cardsView.isEmpty()) { - // clear old dialogs before the new - clearPickTargetDialogs(); - dialog = showCards(message, cardsView, required, options0, popupMenuType); + dialog = prepareCardsDialog(message, cardsView, required, options0, popupMenuType); options0.put("dialog", dialog); } - this.feedbackPanel.getFeedback(required ? FeedbackMode.INFORM : FeedbackMode.CANCEL, message, gameView.getSpecial(), options0, messageId, true, gameView.getPhase()); + this.feedbackPanel.prepareFeedback(required ? FeedbackMode.INFORM : FeedbackMode.CANCEL, message, gameView.getSpecial(), options0, messageId, true, gameView.getPhase()); if (dialog != null) { this.pickTarget.add(dialog); } @@ -1640,15 +1664,23 @@ public final class GamePanel extends javax.swing.JPanel { public void inform(String information, GameView gameView, int messageId) { updateGame(gameView); - this.feedbackPanel.getFeedback(FeedbackMode.INFORM, information, gameView.getSpecial(), null, messageId, false, gameView.getPhase()); + this.feedbackPanel.prepareFeedback(FeedbackMode.INFORM, information, gameView.getSpecial(), null, messageId, false, gameView.getPhase()); } - public void endMessage(String message, int messageId) { - this.feedbackPanel.getFeedback(FeedbackMode.END, message, false, null, messageId, true, null); + public void endMessage(GameView gameView, Map options, String message, int messageId) { + updateGame(gameView, false, options, null); + hideAll(); + DialogManager.getManager(gameId).fadeOut(); + + this.feedbackPanel.prepareFeedback(FeedbackMode.END, message, false, null, messageId, true, null); ArrowBuilder.getBuilder().removeAllArrows(gameId); } - public void select(String message, GameView gameView, int messageId, Map options) { + public void select(GameView gameView, Map options, String message, int messageId) { + updateGame(gameView, true, options, null); + hideAll(); + DialogManager.getManager(gameId).fadeOut(); + this.abilityPicker.setVisible(false); holdingPriority = false; @@ -1659,8 +1691,6 @@ public final class GamePanel extends javax.swing.JPanel { PreferencesDialog.getCachedValue(KEY_USE_FIRST_MANA_ABILITY, "false").equals("true"), false); - updateGame(gameView, true, options, null); - boolean controllingPlayer = false; for (PlayerView playerView : gameView.getPlayers()) { if (playerView.getPlayerId().equals(playerId)) { @@ -1675,8 +1705,8 @@ public final class GamePanel extends javax.swing.JPanel { } Map panelOptions = new HashMap<>(); - if (options != null) { - panelOptions.putAll(options); + if (lastGameData.options != null) { + panelOptions.putAll(lastGameData.options); } panelOptions.put("your_turn", true); String activePlayerText; @@ -1690,39 +1720,45 @@ public final class GamePanel extends javax.swing.JPanel { priorityPlayerText = " / priority " + gameView.getPriorityPlayerName(); } String messageToDisplay = message + FeedbackPanel.getSmallText(activePlayerText + " / " + gameView.getStep().toString() + priorityPlayerText); - this.feedbackPanel.getFeedback(FeedbackMode.SELECT, messageToDisplay, gameView.getSpecial(), panelOptions, messageId, true, gameView.getPhase()); + this.feedbackPanel.prepareFeedback(FeedbackMode.SELECT, messageToDisplay, gameView.getSpecial(), panelOptions, messageId, true, gameView.getPhase()); } - public void playMana(String message, GameView gameView, Map options, int messageId) { + public void playMana(GameView gameView, Map options, String message, int messageId) { updateGame(gameView, true, options, null); + hideAll(); DialogManager.getManager(gameId).fadeOut(); - this.feedbackPanel.getFeedback(FeedbackMode.CANCEL, message, gameView.getSpecial(), options, messageId, true, gameView.getPhase()); + + this.feedbackPanel.prepareFeedback(FeedbackMode.CANCEL, message, gameView.getSpecial(), options, messageId, true, gameView.getPhase()); } - public void playXMana(String message, GameView gameView, int messageId) { - updateGame(gameView, true, null, null); + public void playXMana(GameView gameView, Map options, String message, int messageId) { + updateGame(gameView, true, options, null); + hideAll(); DialogManager.getManager(gameId).fadeOut(); - this.feedbackPanel.getFeedback(FeedbackMode.CONFIRM, message, gameView.getSpecial(), null, messageId, true, gameView.getPhase()); + + this.feedbackPanel.prepareFeedback(FeedbackMode.CONFIRM, message, gameView.getSpecial(), null, messageId, true, gameView.getPhase()); } public void replayMessage(String message) { //TODO: implement this } - public void pickAbility(AbilityPickerView choices) { + public void pickAbility(GameView gameView, Map options, AbilityPickerView choices) { + updateGame(gameView, false, options, null); hideAll(); DialogManager.getManager(gameId).fadeOut(); + this.abilityPicker.show(choices, MageFrame.getDesktop().getMousePosition()); } private void hideAll() { + hidePickDialogs(); this.abilityPicker.setVisible(false); ActionCallback callback = Plugins.instance.getActionCallback(); ((MageActionCallback) callback).hideGameUpdate(gameId); } - private ShowCardsDialog showCards(String title, CardsView cards, boolean required, Map options, PopUpMenuType popupMenuType) { - hideAll(); + private ShowCardsDialog prepareCardsDialog(String title, CardsView cards, boolean required, Map options, PopUpMenuType popupMenuType) { ShowCardsDialog showCards = new ShowCardsDialog(); JPopupMenu popupMenu = null; if (PopUpMenuType.TRIGGER_ORDER == popupMenuType) { @@ -1732,7 +1768,11 @@ public final class GamePanel extends javax.swing.JPanel { return showCards; } - public void getAmount(int min, int max, String message) { + public void getAmount(GameView gameView, Map options, int min, int max, String message) { + updateGame(gameView, false, options, null); + hideAll(); + DialogManager.getManager(gameId).fadeOut(); + pickNumber.showDialog(min, max, message); if (pickNumber.isCancel()) { SessionHandler.sendPlayerBoolean(gameId, false); @@ -1741,13 +1781,20 @@ public final class GamePanel extends javax.swing.JPanel { } } - public void getMultiAmount(List messages, int min, int max, Map options) { - pickMultiNumber.showDialog(messages, min, max, options); + public void getMultiAmount(List messages, GameView gameView, Map options, int min, int max) { + updateGame(gameView, false, options, null); + hideAll(); + DialogManager.getManager(gameId).fadeOut(); + + pickMultiNumber.showDialog(messages, min, max, lastGameData.options); SessionHandler.sendPlayerString(gameId, pickMultiNumber.getMultiAmount()); } - public void getChoice(Choice choice, UUID objectId) { + public void getChoice(GameView gameView, Map options, Choice choice, UUID objectId) { + updateGame(gameView, false, options, null); hideAll(); + DialogManager.getManager(gameId).fadeOut(); + // TODO: remember last choices and search incremental for same events? PickChoiceDialog pickChoice = new PickChoiceDialog(); pickChoice.showDialog(choice, null, objectId, choiceWindowState, bigCard); @@ -1769,8 +1816,10 @@ public final class GamePanel extends javax.swing.JPanel { pickChoice.removeDialog(); } - public void pickPile(String message, CardsView pile1, CardsView pile2) { + public void pickPile(GameView gameView, Map options, String message, CardsView pile1, CardsView pile2) { + updateGame(gameView, false, options, null); hideAll(); + DialogManager.getManager(gameId).fadeOut(); // remove old dialogs before the new clearPickPileDialogs(); diff --git a/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java b/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java index e256f7307c..1e062a2396 100644 --- a/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java +++ b/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java @@ -157,7 +157,7 @@ public class CallbackClientImpl implements CallbackClient { case REPLAY_DONE: { GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { - panel.endMessage((String) callback.getData(), callback.getMessageId()); + panel.endMessage(null, null, (String) callback.getData(), callback.getMessageId()); } break; } @@ -180,16 +180,17 @@ public class CallbackClientImpl implements CallbackClient { } case GAME_OVER: { + GameClientMessage message = (GameClientMessage) callback.getData(); GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { Session session = SessionHandler.getSession(); if (session.isJsonLogActive()) { - appendJsonEvent("GAME_OVER", callback.getObjectId(), callback.getData()); - ActionData actionData = appendJsonEvent("GAME_OVER", callback.getObjectId(), callback.getData()); - String logFileName = "game-" + actionData.gameId + ".json"; - S3Uploader.upload(logFileName, actionData.gameId.toString()); + UUID gameId = callback.getObjectId(); + appendJsonEvent("GAME_OVER", callback.getObjectId(), message); + String logFileName = "game-" + gameId + ".json"; + S3Uploader.upload(logFileName, gameId.toString()); } - panel.endMessage((String) callback.getData(), callback.getMessageId()); + panel.endMessage(message.getGameView(), message.getOptions(), message.getMessage(), callback.getMessageId()); } break; } @@ -209,35 +210,34 @@ public class CallbackClientImpl implements CallbackClient { break; } - case GAME_TARGET: // e.g. Pick triggered ability - { + case GAME_TARGET: { + // e.g. Pick triggered ability GameClientMessage message = (GameClientMessage) callback.getData(); - GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { appendJsonEvent("GAME_TARGET", callback.getObjectId(), message); - panel.pickTarget(message.getMessage(), message.getCardsView(), message.getGameView(), - message.getTargets(), message.isFlag(), message.getOptions(), callback.getMessageId()); + panel.pickTarget(message.getGameView(), message.getOptions(), message.getMessage(), + message.getCardsView1(), message.getTargets(), message.isFlag(), callback.getMessageId()); } break; } case GAME_SELECT: { GameClientMessage message = (GameClientMessage) callback.getData(); - GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { appendJsonEvent("GAME_SELECT", callback.getObjectId(), message); - panel.select(message.getMessage(), message.getGameView(), callback.getMessageId(), message.getOptions()); + panel.select(message.getGameView(), message.getOptions(), message.getMessage(), callback.getMessageId()); } break; } case GAME_CHOOSE_ABILITY: { + AbilityPickerView abilityPickerView = (AbilityPickerView) callback.getData(); GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { appendJsonEvent("GAME_CHOOSE_ABILITY", callback.getObjectId(), callback.getData()); - panel.pickAbility((AbilityPickerView) callback.getData()); + panel.pickAbility(abilityPickerView.getGameView(), null, abilityPickerView); } break; } @@ -247,19 +247,17 @@ public class CallbackClientImpl implements CallbackClient { GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { appendJsonEvent("GAME_CHOOSE_PILE", callback.getObjectId(), message); - panel.pickPile(message.getMessage(), message.getPile1(), message.getPile2()); + panel.pickPile(message.getGameView(), message.getOptions(), message.getMessage(), message.getCardsView1(), message.getCardsView2()); } break; } case GAME_CHOOSE_CHOICE: { GameClientMessage message = (GameClientMessage) callback.getData(); - GamePanel panel = MageFrame.getGame(callback.getObjectId()); - if (panel != null) { appendJsonEvent("GAME_CHOOSE_CHOICE", callback.getObjectId(), message); - panel.getChoice(message.getChoice(), callback.getObjectId()); + panel.getChoice(message.getGameView(), message.getOptions(), message.getChoice(), callback.getObjectId()); } break; } @@ -269,53 +267,48 @@ public class CallbackClientImpl implements CallbackClient { GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { appendJsonEvent("GAME_PLAY_MANA", callback.getObjectId(), message); - panel.playMana(message.getMessage(), message.getGameView(), message.getOptions(), callback.getMessageId()); + panel.playMana(message.getGameView(), message.getOptions(), message.getMessage(), callback.getMessageId()); } break; } case GAME_PLAY_XMANA: { GameClientMessage message = (GameClientMessage) callback.getData(); - GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { appendJsonEvent("GAME_PLAY_XMANA", callback.getObjectId(), message); - panel.playXMana(message.getMessage(), message.getGameView(), callback.getMessageId()); + panel.playXMana(message.getGameView(), message.getOptions(), message.getMessage(), callback.getMessageId()); } break; } case GAME_GET_AMOUNT: { GameClientMessage message = (GameClientMessage) callback.getData(); - GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { appendJsonEvent("GAME_GET_AMOUNT", callback.getObjectId(), message); - panel.getAmount(message.getMin(), message.getMax(), message.getMessage()); + panel.getAmount(message.getGameView(), message.getOptions(), message.getMin(), message.getMax(), message.getMessage()); } break; } case GAME_GET_MULTI_AMOUNT: { GameClientMessage message = (GameClientMessage) callback.getData(); - GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { appendJsonEvent("GAME_GET_MULTI_AMOUNT", callback.getObjectId(), message); - panel.getMultiAmount(message.getMessages(), message.getMin(), message.getMax(), message.getOptions()); + panel.getMultiAmount(message.getMessages(), message.getGameView(), message.getOptions(), message.getMin(), message.getMax()); } break; } case GAME_UPDATE: { GamePanel panel = MageFrame.getGame(callback.getObjectId()); - if (panel != null) { appendJsonEvent("GAME_UPDATE", callback.getObjectId(), callback.getData()); - - panel.updateGame((GameView) callback.getData(), true, null, null); // update after undo + panel.updateGame((GameView) callback.getData(), true, null, null); // update after undo wtf?! } break; } @@ -325,6 +318,7 @@ public class CallbackClientImpl implements CallbackClient { // uses for client side only (example: update after scrollbars support) GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { + logger.info("redraw"); panel.updateGame(); } break; diff --git a/Mage.Common/src/main/java/mage/view/AbilityPickerView.java b/Mage.Common/src/main/java/mage/view/AbilityPickerView.java index d4ae6a0c23..7b4141294c 100644 --- a/Mage.Common/src/main/java/mage/view/AbilityPickerView.java +++ b/Mage.Common/src/main/java/mage/view/AbilityPickerView.java @@ -17,9 +17,11 @@ public class AbilityPickerView implements Serializable { private static final long serialVersionUID = 1L; private Map choices = new LinkedHashMap<>(); - private String message = null; + private String message; + private GameView gameView; - public AbilityPickerView(String objectName, List abilities, String message) { + public AbilityPickerView(GameView gameView, String objectName, List abilities, String message) { + this.gameView = gameView; this.message = message; int num = 0; @@ -44,6 +46,12 @@ public class AbilityPickerView implements Serializable { } } + public AbilityPickerView(GameView gameView, Map modes, String message) { + this.gameView = gameView; + this.choices = modes; + this.message = message; + } + private String getAbilityRules(Ability ability, String objectName) { String rule = ability.getRule(objectName); if (rule.isEmpty()) { @@ -55,11 +63,6 @@ public class AbilityPickerView implements Serializable { return rule; } - public AbilityPickerView(Map modes, String message) { - this.choices = modes; - this.message = message; - } - public Map getChoices() { return choices; } @@ -67,4 +70,8 @@ public class AbilityPickerView implements Serializable { public String getMessage() { return message; } + + public GameView getGameView() { + return gameView; + } } diff --git a/Mage.Common/src/main/java/mage/view/GameClientMessage.java b/Mage.Common/src/main/java/mage/view/GameClientMessage.java index 092079bf7c..64a4c43e37 100644 --- a/Mage.Common/src/main/java/mage/view/GameClientMessage.java +++ b/Mage.Common/src/main/java/mage/view/GameClientMessage.java @@ -24,7 +24,7 @@ public class GameClientMessage implements Serializable { @Expose private GameView gameView; @Expose - private CardsView cardsView; + private CardsView cardsView1; @Expose private CardsView cardsView2; @Expose @@ -32,8 +32,6 @@ public class GameClientMessage implements Serializable { @Expose private boolean flag; @Expose - private String[] strings; - @Expose private Set targets; @Expose private int min; @@ -46,64 +44,53 @@ public class GameClientMessage implements Serializable { @Expose private List messages; - public GameClientMessage(GameView gameView) { + public GameClientMessage(GameView gameView, Map options) { this.gameView = gameView; - } - - public GameClientMessage(GameView gameView, String message) { - this.gameView = gameView; - this.message = message; - } - - public GameClientMessage(GameView gameView, String message, Map options) { - this.gameView = gameView; - this.message = message; this.options = options; } - private GameClientMessage(GameView gameView, String question, CardsView cardView, Set targets, boolean required) { + public GameClientMessage(GameView gameView, Map options, String message) { this.gameView = gameView; - this.message = question; - this.cardsView = cardView; + this.options = options; + this.message = message; + } + + public GameClientMessage(GameView gameView, Map options, String message, CardsView cardsView1, Set targets, boolean required) { + this.gameView = gameView; + this.options = options; + this.message = message; + this.cardsView1 = cardsView1; this.targets = targets; this.flag = required; } - public GameClientMessage(GameView gameView, String question, CardsView cardView, Set targets, boolean required, Map options) { - this(gameView, question, cardView, targets, required); + public GameClientMessage(GameView gameView, Map options, String message, int min, int max) { + this.gameView = gameView; this.options = options; - } - - public GameClientMessage(String[] choices, String message) { - this.strings = choices; - this.message = message; - } - - public GameClientMessage(String message, int min, int max) { this.message = message; this.min = min; this.max = max; } - public GameClientMessage(String message, CardsView pile1, CardsView pile2) { + public GameClientMessage(GameView gameView, Map options, String message, CardsView pile1, CardsView pile2) { + this.gameView = gameView; + this.options = options; this.message = message; - this.cardsView = pile1; + this.cardsView1 = pile1; this.cardsView2 = pile2; } - public GameClientMessage(CardsView cardView, String name) { - this.cardsView = cardView; - this.message = name; - } - - public GameClientMessage(List messages, int min, int max, Map options) { + public GameClientMessage(GameView gameView, Map options, List messages, int min, int max) { + this.gameView = gameView; + this.options = options; this.messages = messages; this.min = min; this.max = max; - this.options = options; } - public GameClientMessage(Choice choice) { + public GameClientMessage(GameView gameView, Map options, Choice choice) { + this.gameView = gameView; + this.options = options; this.choice = choice; } @@ -111,8 +98,12 @@ public class GameClientMessage implements Serializable { return gameView; } - public CardsView getCardsView() { - return cardsView; + public CardsView getCardsView1() { + return cardsView1; + } + + public CardsView getCardsView2() { + return cardsView2; } public String getMessage() { @@ -123,22 +114,10 @@ public class GameClientMessage implements Serializable { return flag; } - public String[] getStrings() { - return strings; - } - public Set getTargets() { return targets; } - public CardsView getPile1() { - return cardsView; - } - - public CardsView getPile2() { - return cardsView2; - } - public int getMin() { return min; } diff --git a/Mage.Server/src/main/java/mage/server/game/GameController.java b/Mage.Server/src/main/java/mage/server/game/GameController.java index d2b0cbac49..e839e15186 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameController.java +++ b/Mage.Server/src/main/java/mage/server/game/GameController.java @@ -810,7 +810,7 @@ public class GameController implements GameCallback { } private synchronized void chooseAbility(UUID playerId, final String objectName, final List choices, String message) throws MageException { - perform(playerId, playerId1 -> getGameSession(playerId1).chooseAbility(new AbilityPickerView(objectName, choices, message))); + perform(playerId, playerId1 -> getGameSession(playerId1).chooseAbility(new AbilityPickerView(getGameView(playerId), objectName, choices, message))); } private synchronized void choosePile(UUID playerId, final String message, final List pile1, final List pile2) throws MageException { @@ -818,7 +818,7 @@ public class GameController implements GameCallback { } private synchronized void chooseMode(UUID playerId, final Map modes, final String message) throws MageException { - perform(playerId, playerId1 -> getGameSession(playerId1).chooseAbility(new AbilityPickerView(modes, message))); + perform(playerId, playerId1 -> getGameSession(playerId1).chooseAbility(new AbilityPickerView(getGameView(playerId), modes, message))); } private synchronized void chooseChoice(UUID playerId, final Choice choice) throws MageException { diff --git a/Mage.Server/src/main/java/mage/server/game/GameSessionPlayer.java b/Mage.Server/src/main/java/mage/server/game/GameSessionPlayer.java index dfa6bf947f..714572fdc4 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameSessionPlayer.java +++ b/Mage.Server/src/main/java/mage/server/game/GameSessionPlayer.java @@ -47,7 +47,7 @@ public class GameSessionPlayer extends GameSessionWatcher { public void ask(final String question, final Map options) { if (!killed) { - userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_ASK, game.getId(), new GameClientMessage(getGameView(), question, options))) + userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_ASK, game.getId(), new GameClientMessage(getGameView(), options, question))) ); } } @@ -55,7 +55,7 @@ public class GameSessionPlayer extends GameSessionWatcher { public void target(final String question, final CardsView cardView, final Set targets, final boolean required, final Map options) { if (!killed) { userManager.getUser(userId).ifPresent(user -> { - user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_TARGET, game.getId(), new GameClientMessage(getGameView(), question, cardView, targets, required, options))); + user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_TARGET, game.getId(), new GameClientMessage(getGameView(), options, question, cardView, targets, required))); }); } @@ -63,7 +63,7 @@ public class GameSessionPlayer extends GameSessionWatcher { public void select(final String message, final Map options) { if (!killed) { - userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_SELECT, game.getId(), new GameClientMessage(getGameView(), message, options)))); + userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_SELECT, game.getId(), new GameClientMessage(getGameView(), options, message)))); } } @@ -78,7 +78,7 @@ public class GameSessionPlayer extends GameSessionWatcher { public void choosePile(final String message, final CardsView pile1, final CardsView pile2) { if (!killed) { userManager.getUser(userId).ifPresent(user - -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_CHOOSE_PILE, game.getId(), new GameClientMessage(message, pile1, pile2)))); + -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_CHOOSE_PILE, game.getId(), new GameClientMessage(getGameView(), null, message, pile1, pile2)))); } } @@ -86,7 +86,7 @@ public class GameSessionPlayer extends GameSessionWatcher { public void chooseChoice(final Choice choice) { if (!killed) { userManager.getUser(userId).ifPresent(user - -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_CHOOSE_CHOICE, game.getId(), new GameClientMessage(choice)))); + -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_CHOOSE_CHOICE, game.getId(), new GameClientMessage(getGameView(), null, choice)))); } } @@ -94,14 +94,14 @@ public class GameSessionPlayer extends GameSessionWatcher { public void playMana(final String message, final Map options) { if (!killed) { userManager.getUser(userId).ifPresent(user - -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_PLAY_MANA, game.getId(), new GameClientMessage(getGameView(), message, options)))); + -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_PLAY_MANA, game.getId(), new GameClientMessage(getGameView(), options, message)))); } } public void playXMana(final String message) { if (!killed) { userManager.getUser(userId).ifPresent(user - -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_PLAY_XMANA, game.getId(), new GameClientMessage(getGameView(), message)))); + -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_PLAY_XMANA, game.getId(), new GameClientMessage(getGameView(), null, message)))); } } @@ -109,7 +109,7 @@ public class GameSessionPlayer extends GameSessionWatcher { public void getAmount(final String message, final int min, final int max) { if (!killed) { userManager.getUser(userId).ifPresent(user -> { - user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_GET_AMOUNT, game.getId(), new GameClientMessage(message, min, max))); + user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_GET_AMOUNT, game.getId(), new GameClientMessage(getGameView(), null, message, min, max))); }); } } @@ -117,7 +117,7 @@ public class GameSessionPlayer extends GameSessionWatcher { public void getMultiAmount(final List messages, final int min, final int max, final Map options) { if (!killed) { userManager.getUser(userId).ifPresent(user - -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_GET_MULTI_AMOUNT, game.getId(), new GameClientMessage(messages, min, max, options)))); + -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_GET_MULTI_AMOUNT, game.getId(), new GameClientMessage(getGameView(), options, messages, min, max)))); } } diff --git a/Mage.Server/src/main/java/mage/server/game/GameSessionWatcher.java b/Mage.Server/src/main/java/mage/server/game/GameSessionWatcher.java index 4bcd69d57c..452e948abe 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameSessionWatcher.java +++ b/Mage.Server/src/main/java/mage/server/game/GameSessionWatcher.java @@ -58,14 +58,14 @@ public class GameSessionWatcher { public void inform(final String message) { if (!killed) { - userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_INFORM, game.getId(), new GameClientMessage(getGameView(), message)))); + userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_INFORM, game.getId(), new GameClientMessage(getGameView(), null, message)))); } } public void informPersonal(final String message) { if (!killed) { - userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_INFORM_PERSONAL, game.getId(), new GameClientMessage(getGameView(), message)))); + userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_INFORM_PERSONAL, game.getId(), new GameClientMessage(getGameView(), null, message)))); } } @@ -74,7 +74,7 @@ public class GameSessionWatcher { if (!killed) { userManager.getUser(userId).ifPresent(user -> { user.removeGameWatchInfo(game.getId()); - user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_OVER, game.getId(), message)); + user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_OVER, game.getId(), new GameClientMessage(getGameView(), null, message))); }); } } @@ -89,7 +89,6 @@ public class GameSessionWatcher { public void gameError(final String message) { if (!killed) { userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_ERROR, game.getId(), message))); - } } diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/AbilityPickerTest.java b/Mage.Tests/src/test/java/org/mage/test/serverside/AbilityPickerTest.java index a064f280e4..100e71737d 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/AbilityPickerTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/AbilityPickerTest.java @@ -7,6 +7,7 @@ import mage.cards.repository.CardRepository; import mage.game.permanent.PermanentCard; import mage.game.permanent.PermanentImpl; import mage.view.AbilityPickerView; +import mage.view.GameView; import org.junit.Assert; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; @@ -16,13 +17,17 @@ import org.mage.test.serverside.base.CardTestPlayerBase; */ public class AbilityPickerTest extends CardTestPlayerBase { + private GameView prepareGameView() { + return new GameView(currentGame.getState(), currentGame, playerA.getId(), null); + } + @Test public void test_PickerChoices_FusedSpells() { // must be 3 spells for choices Abilities abilities = getAbilitiesFromCard("Armed // Dangerous"); Assert.assertEquals(3, abilities.size()); - AbilityPickerView view = new AbilityPickerView("test name", abilities, "test message"); + AbilityPickerView view = new AbilityPickerView(prepareGameView(), "test name", abilities, "test message"); Assert.assertEquals(3, view.getChoices().size()); view.getChoices().values().forEach(c -> { Assert.assertTrue("Must start with Cast text, but found: " + c, c.contains("Cast ")); @@ -35,7 +40,7 @@ public class AbilityPickerTest extends CardTestPlayerBase { Abilities abilities = getAbilitiesFromCard("Foulmire Knight"); Assert.assertEquals(3, abilities.size()); - AbilityPickerView view = new AbilityPickerView("test name", abilities, "test message"); + AbilityPickerView view = new AbilityPickerView(prepareGameView(), "test name", abilities, "test message"); Assert.assertEquals(3, view.getChoices().size()); view.getChoices().values().forEach(c -> { if (c.contains("Deathtouch")) { @@ -51,7 +56,7 @@ public class AbilityPickerTest extends CardTestPlayerBase { Abilities abilities = getAbilitiesFromCard("Dimir Cluestone"); Assert.assertEquals(4, abilities.size()); - AbilityPickerView view = new AbilityPickerView("test name", abilities, "test message"); + AbilityPickerView view = new AbilityPickerView(prepareGameView(), "test name", abilities, "test message"); Assert.assertEquals(4, view.getChoices().size()); int castCount = 0; int abilsCount = 0; @@ -72,7 +77,7 @@ public class AbilityPickerTest extends CardTestPlayerBase { Abilities abilities = getAbilitiesFromCard("Cling to Dust"); Assert.assertEquals(2, abilities.size()); - AbilityPickerView view = new AbilityPickerView("test name", abilities, "test message"); + AbilityPickerView view = new AbilityPickerView(prepareGameView(), "test name", abilities, "test message"); Assert.assertEquals(2, view.getChoices().size()); view.getChoices().values().forEach(c -> { Assert.assertTrue("Must start with Cast text, but found: " + c, c.contains("Cast ")); diff --git a/Mage/src/main/java/mage/util/CardUtil.java b/Mage/src/main/java/mage/util/CardUtil.java index fdbae85486..a5a294dc30 100644 --- a/Mage/src/main/java/mage/util/CardUtil.java +++ b/Mage/src/main/java/mage/util/CardUtil.java @@ -1394,7 +1394,7 @@ public final class CardUtil { if (!controller.moveCards(card, toZone, source, game)) { return false; } - + // add counter // after move it's a new object (not a permanent), so must work with main card Effect effect = new AddCountersTargetEffect(counter);