diff --git a/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java b/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java index b266d991c8..0243fa0d9a 100644 --- a/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java +++ b/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java @@ -1,42 +1,27 @@ - package mage.client.game; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.event.ActionListener; -import java.awt.event.KeyEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.lang.reflect.Field; -import java.util.UUID; -import javax.swing.BorderFactory; -import javax.swing.GroupLayout; -import javax.swing.GroupLayout.Alignment; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.JPopupMenu; -import javax.swing.LayoutStyle.ComponentPlacement; -import javax.swing.MenuSelectionManager; -import javax.swing.event.ChangeListener; - import mage.cards.decks.importer.DeckImporter; import mage.client.MageFrame; import mage.client.SessionHandler; import mage.client.cards.BigCard; import mage.client.dialog.PreferencesDialog; -import static mage.client.dialog.PreferencesDialog.KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS; -import static mage.client.dialog.PreferencesDialog.KEY_GAME_MANA_AUTOPAYMENT; -import static mage.client.dialog.PreferencesDialog.KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE; -import static mage.client.dialog.PreferencesDialog.KEY_USE_FIRST_MANA_ABILITY; import mage.client.util.GUISizeHelper; import mage.constants.PlayerAction; import mage.view.PlayerView; import mage.view.UserRequestMessage; +import javax.swing.*; +import javax.swing.GroupLayout.Alignment; +import javax.swing.LayoutStyle.ComponentPlacement; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.awt.event.*; +import java.lang.reflect.Field; +import java.util.UUID; + +import static mage.client.dialog.PreferencesDialog.*; + /** - * * @author BetaSteward_at_googlemail.com */ public class PlayAreaPanel extends javax.swing.JPanel { @@ -77,7 +62,7 @@ public class PlayAreaPanel extends javax.swing.JPanel { popupMenu = new JPopupMenu(); if (options.isPlayer) { - addPopupMenuPlayer(player.getUserData().isAllowRequestShowHandCards()); + addPopupMenuPlayer(player.getUserData().isAllowRequestHandToAll()); } else { addPopupMenuWatcher(); } @@ -331,12 +316,12 @@ public class PlayAreaPanel extends javax.swing.JPanel { // Request to see hand cards menuItem.addActionListener(e -> SessionHandler.sendPlayerAction(PlayerAction.REQUEST_PERMISSION_TO_SEE_HAND_CARDS, gameId, playerId)); } else { - allowViewHandCardsMenuItem = new JCheckBoxMenuItem("Allow requests to show from other users", allowRequestToShowHandCards); + allowViewHandCardsMenuItem = new JCheckBoxMenuItem("Allow hand requests from other users", allowRequestToShowHandCards); allowViewHandCardsMenuItem.setMnemonic(KeyEvent.VK_A); - allowViewHandCardsMenuItem.setToolTipText("If activated watchers or other players can request to see your hand cards. If you grant this to a user, it's valid for the complete match."); + allowViewHandCardsMenuItem.setToolTipText("Watchers or other players can request your hand cards once per game. Re-activate it to allow new requests."); handCardsMenu.add(allowViewHandCardsMenuItem); - // Requests allowed + // requests allowed (disable -> enable to reset requested list) allowViewHandCardsMenuItem.addActionListener(e -> { boolean requestsAllowed = ((JCheckBoxMenuItem) e.getSource()).getState(); PreferencesDialog.setPrefValue(KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS, requestsAllowed); @@ -451,13 +436,13 @@ public class PlayAreaPanel extends javax.swing.JPanel { } }); - + popupMenu.addSeparator(); - + menuItem = new JMenuItem("View current deck"); menuItem.setMnemonic(KeyEvent.VK_V); popupMenu.add(menuItem); - + // View limited deck menuItem.addActionListener(e -> { SessionHandler.sendPlayerAction(PlayerAction.VIEW_LIMITED_DECK, gameId, null); @@ -522,7 +507,7 @@ public class PlayAreaPanel extends javax.swing.JPanel { this.playerPanel.update(player); this.battlefieldPanel.update(player.getBattlefield()); if (this.allowViewHandCardsMenuItem != null) { - this.allowViewHandCardsMenuItem.setSelected(player.getUserData().isAllowRequestShowHandCards()); + this.allowViewHandCardsMenuItem.setSelected(player.getUserData().isAllowRequestHandToAll()); } } @@ -547,14 +532,14 @@ public class PlayAreaPanel extends javax.swing.JPanel { javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); layout.setHorizontalGroup( layout.createSequentialGroup() - .addComponent(playerPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(ComponentPlacement.RELATED) - .addComponent(battlefieldPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(playerPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(battlefieldPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(Alignment.LEADING) - .addComponent(playerPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addComponent(battlefieldPanel, GroupLayout.DEFAULT_SIZE, 160, Short.MAX_VALUE) + .addComponent(playerPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addComponent(battlefieldPanel, GroupLayout.DEFAULT_SIZE, 160, Short.MAX_VALUE) ); this.setLayout(layout); } diff --git a/Mage.Common/src/main/java/mage/view/UserDataView.java b/Mage.Common/src/main/java/mage/view/UserDataView.java index 3e8b222d2b..23dd025db9 100644 --- a/Mage.Common/src/main/java/mage/view/UserDataView.java +++ b/Mage.Common/src/main/java/mage/view/UserDataView.java @@ -1,9 +1,10 @@ package mage.view; -import java.io.Serializable; import mage.players.net.UserData; import mage.players.net.UserSkipPrioritySteps; +import java.io.Serializable; + /** * Transfer object for {@link mage.players.net.UserData} * @@ -14,7 +15,6 @@ public class UserDataView implements Serializable { protected int avatarId; protected int userGroup; protected boolean showAbilityPickerForced; - protected boolean allowRequestShowHandCards; protected boolean confirmEmptyManaPool; protected UserSkipPrioritySteps userSkipPrioritySteps; String flagName; @@ -29,10 +29,9 @@ public class UserDataView implements Serializable { } public UserDataView(int avatarId, boolean showAbilityPickerForced, boolean allowRequestShowHandCards, - boolean confirmEmptyManaPool, UserSkipPrioritySteps userSkipPrioritySteps, String flagName, boolean askMoveToGraveOrder) { + boolean confirmEmptyManaPool, UserSkipPrioritySteps userSkipPrioritySteps, String flagName, boolean askMoveToGraveOrder) { this.avatarId = avatarId; this.showAbilityPickerForced = showAbilityPickerForced; - this.allowRequestShowHandCards = allowRequestShowHandCards; this.userSkipPrioritySteps = userSkipPrioritySteps; this.confirmEmptyManaPool = confirmEmptyManaPool; this.flagName = flagName; @@ -43,7 +42,6 @@ public class UserDataView implements Serializable { public UserDataView(UserData userData) { this.avatarId = userData.getAvatarId(); this.userGroup = userData.getGroupId(); - this.allowRequestShowHandCards = userData.isAllowRequestShowHandCards(); this.showAbilityPickerForced = userData.isShowAbilityPickerForced(); this.userSkipPrioritySteps = userData.getUserSkipPrioritySteps(); this.confirmEmptyManaPool = userData.confirmEmptyManaPool(); @@ -59,10 +57,6 @@ public class UserDataView implements Serializable { return showAbilityPickerForced; } - public boolean allowRequestShowHandCards() { - return allowRequestShowHandCards; - } - public UserSkipPrioritySteps getUserSkipPrioritySteps() { return userSkipPrioritySteps; } 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 8ec068a48e..3aaed58143 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameController.java +++ b/Mage.Server/src/main/java/mage/server/game/GameController.java @@ -596,7 +596,9 @@ public class GameController implements GameCallback { if (gameSession != null) { UUID requestingPlayerId = getPlayerId(userIdRequester); if (requestingPlayerId == null || !requestingPlayerId.equals(grantingPlayer.getId())) { // don't allow request for your own cards - if (grantingPlayer.isRequestToShowHandCardsAllowed()) { + if (grantingPlayer.isPlayerAllowedToRequestHand(game.getId(), requestingPlayerId)) { + // one time request per user restrict, enable request will reset users list and allows again + grantingPlayer.addPlayerToRequestedHandList(game.getId(), requestingPlayerId); gameSession.requestPermissionToSeeHandCards(userIdRequester); } else { // player does not allow the request diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java index 2f11fbd530..f01b285655 100644 --- a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java +++ b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java @@ -3077,8 +3077,13 @@ public class TestPlayer implements Player { } @Override - public boolean isRequestToShowHandCardsAllowed() { - return computerPlayer.isRequestToShowHandCardsAllowed(); + public boolean isPlayerAllowedToRequestHand(UUID gameId, UUID requesterPlayerId) { + return computerPlayer.isPlayerAllowedToRequestHand(gameId, requesterPlayerId); + } + + @Override + public void addPlayerToRequestedHandList(UUID gameId, UUID requesterPlayerId) { + computerPlayer.addPlayerToRequestedHandList(gameId, requesterPlayerId); } @Override diff --git a/Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java b/Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java index 6fe462512f..ef25e0469b 100644 --- a/Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java +++ b/Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java @@ -1242,10 +1242,15 @@ public class PlayerStub implements Player { } @Override - public boolean isRequestToShowHandCardsAllowed() { + public boolean isPlayerAllowedToRequestHand(UUID gameId, UUID requesterPlayerId) { return false; } + @Override + public void addPlayerToRequestedHandList(UUID gameId, UUID requesterPlayerId) { + // + } + @Override public Set getUsersAllowedToSeeHandCards() { return null; diff --git a/Mage/src/main/java/mage/players/Player.java b/Mage/src/main/java/mage/players/Player.java index bef24d471e..d6f8bb8bfc 100644 --- a/Mage/src/main/java/mage/players/Player.java +++ b/Mage/src/main/java/mage/players/Player.java @@ -855,7 +855,9 @@ public interface Player extends MageItem, Copyable { void revokePermissionToSeeHandCards(); - boolean isRequestToShowHandCardsAllowed(); + boolean isPlayerAllowedToRequestHand(UUID gameId, UUID requesterPlayerId); + + void addPlayerToRequestedHandList(UUID gameId, UUID requesterPlayerId); Set getUsersAllowedToSeeHandCards(); diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index 569f68e181..6dd3cbbe36 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -2284,6 +2284,7 @@ public abstract class PlayerImpl implements Player, Serializable { break; case PERMISSION_REQUESTS_ALLOWED_ON: userData.setAllowRequestShowHandCards(true); + userData.resetRequestedHandPlayersList(game.getId()); // users can send request again break; } logger.trace("PASS Priority: " + playerAction.toString()); @@ -3969,8 +3970,13 @@ public abstract class PlayerImpl implements Player, Serializable { } @Override - public boolean isRequestToShowHandCardsAllowed() { - return userData.isAllowRequestShowHandCards(); + public boolean isPlayerAllowedToRequestHand(UUID gameId, UUID requesterPlayerId) { + return userData.isAllowRequestHandToPlayer(gameId, requesterPlayerId); + } + + @Override + public void addPlayerToRequestedHandList(UUID gameId, UUID requesterPlayerId) { + userData.addPlayerToRequestedHandList(gameId, requesterPlayerId); } @Override diff --git a/Mage/src/main/java/mage/players/net/UserData.java b/Mage/src/main/java/mage/players/net/UserData.java index fec7fbcba2..06f2aff922 100644 --- a/Mage/src/main/java/mage/players/net/UserData.java +++ b/Mage/src/main/java/mage/players/net/UserData.java @@ -1,6 +1,7 @@ package mage.players.net; import java.io.Serializable; +import java.util.*; /** * User data that is passed during connection to the server. @@ -24,6 +25,7 @@ public class UserData implements Serializable { protected boolean autoOrderTrigger; protected boolean useFirstManaAbility = false; private String userIdStr; + protected Map> requestedHandPlayersList; // game -> players list protected String matchHistory; protected int matchQuitRatio; @@ -35,9 +37,9 @@ public class UserData implements Serializable { private int limitedRating; public UserData(UserGroup userGroup, int avatarId, boolean showAbilityPickerForced, - boolean allowRequestShowHandCards, boolean confirmEmptyManaPool, UserSkipPrioritySteps userSkipPrioritySteps, - String flagName, boolean askMoveToGraveOrder, boolean manaPoolAutomatic, boolean manaPoolAutomaticRestricted, - boolean passPriorityCast, boolean passPriorityActivation, boolean autoOrderTrigger, boolean useFirstManaAbility, String userIdStr) { + boolean allowRequestShowHandCards, boolean confirmEmptyManaPool, UserSkipPrioritySteps userSkipPrioritySteps, + String flagName, boolean askMoveToGraveOrder, boolean manaPoolAutomatic, boolean manaPoolAutomaticRestricted, + boolean passPriorityCast, boolean passPriorityActivation, boolean autoOrderTrigger, boolean useFirstManaAbility, String userIdStr) { this.groupId = userGroup.getGroupId(); this.avatarId = avatarId; this.showAbilityPickerForced = showAbilityPickerForced; @@ -57,6 +59,7 @@ public class UserData implements Serializable { this.tourneyHistory = ""; this.tourneyQuitRatio = 0; this.userIdStr = userIdStr; + this.requestedHandPlayersList = new HashMap<>(); } public void update(UserData userData) { @@ -106,14 +109,35 @@ public class UserData implements Serializable { this.showAbilityPickerForced = showAbilityPickerForced; } - public boolean isAllowRequestShowHandCards() { + public boolean isAllowRequestHandToAll() { return allowRequestShowHandCards; } + public boolean isAllowRequestHandToPlayer(UUID gameId, UUID requesterPlayerId) { + // once per game + boolean allowToPlayer = true; + if (requestedHandPlayersList.containsKey(gameId) && requestedHandPlayersList.get(gameId).contains(requesterPlayerId)) { + allowToPlayer = false; + } + return isAllowRequestHandToAll() && allowToPlayer; + } + + public void addPlayerToRequestedHandList(UUID gameId, UUID requesterPlayerId) { + if (!requestedHandPlayersList.containsKey(gameId)) { + requestedHandPlayersList.put(gameId, new HashSet<>()); + } + Set requestedPlayers = requestedHandPlayersList.get(gameId); + requestedPlayers.add(requesterPlayerId); + } + public void setAllowRequestShowHandCards(boolean allowRequestShowHandCards) { this.allowRequestShowHandCards = allowRequestShowHandCards; } + public void resetRequestedHandPlayersList(UUID gameId) { + this.requestedHandPlayersList.remove(gameId); + } + public UserSkipPrioritySteps getUserSkipPrioritySteps() { return userSkipPrioritySteps; }