diff --git a/messages/src/main/proto/data_transfer_objects.proto b/messages/src/main/proto/data_transfer_objects.proto index 27bedf1b16..b2d8bcc0d1 100644 --- a/messages/src/main/proto/data_transfer_objects.proto +++ b/messages/src/main/proto/data_transfer_objects.proto @@ -31,6 +31,7 @@ message ServerPolicyDto { bool vbl_blocks_move = 15; bool hide_map_select_ui = 16; bool lock_player_library = 17; + bool is_token_context_locked = 18; } message CampaignDto { diff --git a/src/main/java/net/rptools/maptool/client/AppActions.java b/src/main/java/net/rptools/maptool/client/AppActions.java index 9a500f2f2a..12c660730e 100644 --- a/src/main/java/net/rptools/maptool/client/AppActions.java +++ b/src/main/java/net/rptools/maptool/client/AppActions.java @@ -1945,6 +1945,30 @@ protected void executeAction() { } }; + public static final Action TOGGLE_TOKEN_CONTEXT_LOCK = + new TranslatedClientAction("action.toggleTokenContextMenuLock") { + + @Override + public boolean isAvailable() { + return MapTool.getPlayer().isGM(); + } + + @Override + public boolean isSelected() { + return MapTool.getServerPolicy().isTokenContextLocked(); + } + + @Override + protected void executeAction() { + var client = MapTool.getClient(); + + ServerPolicy policy = client.getServerPolicy(); + policy.setIsTokenContextLocked(!policy.isTokenContextLocked()); + + client.setServerPolicy(policy); + client.getServerCommand().setServerPolicy(policy); + } + }; public static final Action START_SERVER = new TranslatedClientAction("action.serverStart") { @@ -1985,6 +2009,7 @@ protected void executeAction() { policy.setPlayersReceiveCampaignMacros(serverProps.getPlayersReceiveCampaignMacros()); policy.setHiddenMapSelectUI(serverProps.getMapSelectUIHidden()); policy.setIsTokenEditorLocked(serverProps.getLockTokenEditOnStart()); + policy.setIsTokenContextLocked(serverProps.getLockTokenContextOnStart()); policy.setIsMovementLocked(serverProps.getLockPlayerMovementOnStart()); policy.setDisablePlayerAssetPanel(serverProps.getPlayerLibraryLock()); diff --git a/src/main/java/net/rptools/maptool/client/tool/PointerTool.java b/src/main/java/net/rptools/maptool/client/tool/PointerTool.java index 774a4e1f65..9e4e1e0896 100644 --- a/src/main/java/net/rptools/maptool/client/tool/PointerTool.java +++ b/src/main/java/net/rptools/maptool/client/tool/PointerTool.java @@ -281,7 +281,9 @@ public void handleMousePressed(MouseEvent event) { } if (SwingUtilities.isRightMouseButton(event)) { Token token = getTokenAt(event.getX(), event.getY()); - if (token == null || !AppUtil.playerOwns(token)) { + if (token == null + || !AppUtil.playerOwns(token) + || (!MapTool.getPlayer().isGM() && MapTool.getServerPolicy().isTokenContextLocked())) { return; } tokenUnderMouse = token; @@ -568,6 +570,9 @@ public void mouseReleased(MouseEvent e) { // POPUP MENU if (SwingUtilities.isRightMouseButton(e) && tokenDragOp == null && !isDraggingMap) { + if (!MapTool.getPlayer().isGM() && MapTool.getServerPolicy().isTokenContextLocked()) { + return; + } final var selectionModel = renderer.getSelectionModel(); if (tokenUnderMouse != null && !selectionModel.isSelected(tokenUnderMouse.getId())) { if (!SwingUtil.isShiftDown(e)) { diff --git a/src/main/java/net/rptools/maptool/client/ui/AppMenuBar.java b/src/main/java/net/rptools/maptool/client/ui/AppMenuBar.java index 7b850a78bb..0fda468132 100644 --- a/src/main/java/net/rptools/maptool/client/ui/AppMenuBar.java +++ b/src/main/java/net/rptools/maptool/client/ui/AppMenuBar.java @@ -191,6 +191,7 @@ protected JMenu createToolsMenu() { menu.add(new RPCheckBoxMenuItem(AppActions.TOGGLE_LINK_PLAYER_VIEW, menu)); menu.add(new RPCheckBoxMenuItem(AppActions.TOGGLE_MOVEMENT_LOCK, menu)); menu.add(new RPCheckBoxMenuItem(AppActions.TOGGLE_TOKEN_EDITOR_LOCK, menu)); + menu.add(new RPCheckBoxMenuItem(AppActions.TOGGLE_TOKEN_CONTEXT_LOCK, menu)); menu.add(new RPCheckBoxMenuItem(AppActions.TOGGLE_ZOOM_LOCK, menu)); menu.add(new RPCheckBoxMenuItem(AppActions.TOGGLE_ENFORCE_NOTIFICATION, menu)); diff --git a/src/main/java/net/rptools/maptool/client/ui/MapToolFrame.java b/src/main/java/net/rptools/maptool/client/ui/MapToolFrame.java index bef898650f..0e9edc1d15 100644 --- a/src/main/java/net/rptools/maptool/client/ui/MapToolFrame.java +++ b/src/main/java/net/rptools/maptool/client/ui/MapToolFrame.java @@ -1399,6 +1399,10 @@ public void mousePressed(MouseEvent e) { } } if (!selectedTokenSet.isEmpty()) { + if (!MapTool.getPlayer().isGM() + && MapTool.getServerPolicy().isTokenContextLocked()) { + return; + } try { if (firstToken.getLayer().isStampLayer()) { new StampPopupMenu( diff --git a/src/main/java/net/rptools/maptool/client/ui/macrobuttons/buttongroups/AbstractButtonGroup.java b/src/main/java/net/rptools/maptool/client/ui/macrobuttons/buttongroups/AbstractButtonGroup.java index 4addb4d104..3e45336c7d 100644 --- a/src/main/java/net/rptools/maptool/client/ui/macrobuttons/buttongroups/AbstractButtonGroup.java +++ b/src/main/java/net/rptools/maptool/client/ui/macrobuttons/buttongroups/AbstractButtonGroup.java @@ -185,7 +185,9 @@ public void mousePressed(MouseEvent event) {} public void mouseReleased(MouseEvent event) { Token token = getToken(); if (SwingUtilities.isRightMouseButton(event)) { - if (getPanelClass().equals("CampaignPanel") && !MapTool.getPlayer().isGM()) { + if (!MapTool.getPlayer().isGM() + && ("CampaignPanel".equals(getPanelClass()) + || MapTool.getServerPolicy().isTokenContextLocked())) { return; } // open button group menu @@ -280,6 +282,9 @@ public void mouseReleased(MouseEvent event) { MapTool.getFrame() .showTokenPropertiesDialog(token, MapTool.getFrame().getCurrentZoneRenderer()); } else if (SwingUtilities.isRightMouseButton(event)) { + if (!MapTool.getPlayer().isGM() && MapTool.getServerPolicy().isTokenContextLocked()) { + return; + } // open token popup menu Set GUIDSet = new HashSet(); GUIDSet.add(tokenId); diff --git a/src/main/java/net/rptools/maptool/client/ui/macrobuttons/buttongroups/AreaGroup.java b/src/main/java/net/rptools/maptool/client/ui/macrobuttons/buttongroups/AreaGroup.java index ef2d0f594f..76bd89d7d4 100644 --- a/src/main/java/net/rptools/maptool/client/ui/macrobuttons/buttongroups/AreaGroup.java +++ b/src/main/java/net/rptools/maptool/client/ui/macrobuttons/buttongroups/AreaGroup.java @@ -145,7 +145,9 @@ public Dimension getPreferredSize() { public void mouseReleased(MouseEvent event) { Token token = getToken(); if (SwingUtilities.isRightMouseButton(event)) { - if ("CampaignPanel".equals(getPanelClass()) && !MapTool.getPlayer().isGM()) { + if (!MapTool.getPlayer().isGM() + && ("CampaignPanel".equals(getPanelClass()) + || MapTool.getServerPolicy().isTokenContextLocked())) { return; } // open button group menu diff --git a/src/main/java/net/rptools/maptool/client/ui/macrobuttons/buttons/MacroButton.java b/src/main/java/net/rptools/maptool/client/ui/macrobuttons/buttons/MacroButton.java index 27973d492a..efdc729143 100644 --- a/src/main/java/net/rptools/maptool/client/ui/macrobuttons/buttons/MacroButton.java +++ b/src/main/java/net/rptools/maptool/client/ui/macrobuttons/buttons/MacroButton.java @@ -204,6 +204,9 @@ public void mouseReleased(MouseEvent event) { properties.executeMacro(); } } else if (SwingUtilities.isRightMouseButton(event)) { + if (!MapTool.getPlayer().isGM() && MapTool.getServerPolicy().isTokenContextLocked()) { + return; + } if (getPanelClass().equals("GlobalPanel")) { new MacroButtonPopupMenu(this, panelClass, false).show(this, event.getX(), event.getY()); } else if (getPanelClass().equals("CampaignPanel")) { diff --git a/src/main/java/net/rptools/maptool/client/ui/macrobuttons/panels/AbstractMacroPanel.java b/src/main/java/net/rptools/maptool/client/ui/macrobuttons/panels/AbstractMacroPanel.java index d8dfa9bf3a..705a8130b5 100644 --- a/src/main/java/net/rptools/maptool/client/ui/macrobuttons/panels/AbstractMacroPanel.java +++ b/src/main/java/net/rptools/maptool/client/ui/macrobuttons/panels/AbstractMacroPanel.java @@ -173,7 +173,9 @@ public void mousePressed(MouseEvent event) {} public void mouseReleased(MouseEvent event) { if (SwingUtilities.isRightMouseButton(event)) { - if ("CampaignPanel".equals(getPanelClass()) && !MapTool.getPlayer().isGM()) { + if (!MapTool.getPlayer().isGM() + && ("CampaignPanel".equals(getPanelClass()) + || MapTool.getServerPolicy().isTokenContextLocked())) { return; } // open button group menu diff --git a/src/main/java/net/rptools/maptool/client/ui/startserverdialog/StartServerDialog.java b/src/main/java/net/rptools/maptool/client/ui/startserverdialog/StartServerDialog.java index 7adb56b6a5..de8dddd635 100644 --- a/src/main/java/net/rptools/maptool/client/ui/startserverdialog/StartServerDialog.java +++ b/src/main/java/net/rptools/maptool/client/ui/startserverdialog/StartServerDialog.java @@ -49,6 +49,7 @@ public class StartServerDialog extends AbeillePanel - + @@ -196,7 +196,7 @@ - + @@ -249,7 +249,7 @@ - + @@ -260,7 +260,7 @@ - + @@ -282,7 +282,7 @@ - + @@ -292,9 +292,21 @@ - + + + + + + + + + + + + + diff --git a/src/main/java/net/rptools/maptool/server/ServerPolicy.java b/src/main/java/net/rptools/maptool/server/ServerPolicy.java index 11300be34b..286c0f5974 100644 --- a/src/main/java/net/rptools/maptool/server/ServerPolicy.java +++ b/src/main/java/net/rptools/maptool/server/ServerPolicy.java @@ -30,6 +30,7 @@ public class ServerPolicy { private boolean strictTokenMovement; private boolean isMovementLocked; private boolean isTokenEditorLocked; + private boolean isTokenContextLocked; private boolean playersCanRevealVision; private boolean gmRevealsVisionForUnownedTokens; private boolean useIndividualViews; @@ -57,6 +58,7 @@ public ServerPolicy(ServerPolicy other) { this.strictTokenMovement = other.strictTokenMovement; this.isMovementLocked = other.isMovementLocked; this.isTokenEditorLocked = other.isTokenEditorLocked; + this.isTokenContextLocked = other.isTokenContextLocked; this.playersCanRevealVision = other.playersCanRevealVision; this.gmRevealsVisionForUnownedTokens = other.gmRevealsVisionForUnownedTokens; this.useIndividualViews = other.useIndividualViews; @@ -98,10 +100,18 @@ public boolean isTokenEditorLocked() { return isTokenEditorLocked; } + public boolean isTokenContextLocked() { + return isTokenContextLocked; + } + public void setIsTokenEditorLocked(boolean locked) { isTokenEditorLocked = locked; } + public void setIsTokenContextLocked(boolean locked) { + isTokenContextLocked = locked; + } + public void setPlayersCanRevealVision(boolean flag) { playersCanRevealVision = flag; } @@ -273,6 +283,8 @@ public JsonObject toJSON() { sinfo.addProperty("movement locked", isMovementLocked() ? BigDecimal.ONE : BigDecimal.ZERO); sinfo.addProperty( "token editor locked", isTokenEditorLocked() ? BigDecimal.ONE : BigDecimal.ZERO); + sinfo.addProperty( + "token context locked", isTokenContextLocked() ? BigDecimal.ONE : BigDecimal.ZERO); sinfo.addProperty( "restricted impersonation", isRestrictedImpersonation() ? BigDecimal.ONE : BigDecimal.ZERO); sinfo.addProperty( @@ -325,6 +337,7 @@ public static ServerPolicy fromDto(ServerPolicyDto dto) { policy.strictTokenMovement = dto.getUseStrictTokenManagement(); policy.isMovementLocked = dto.getIsMovementLocked(); policy.isTokenEditorLocked = dto.getIsTokenEditorLocked(); + policy.isTokenContextLocked = dto.getIsTokenContextLocked(); policy.playersCanRevealVision = dto.getPlayersCanRevealVision(); policy.gmRevealsVisionForUnownedTokens = dto.getGmRevealsVisionForUnownedTokens(); policy.useIndividualViews = dto.getUseIndividualViews(); @@ -347,6 +360,7 @@ public ServerPolicyDto toDto() { dto.setUseStrictTokenManagement(strictTokenMovement); dto.setIsMovementLocked(isMovementLocked); dto.setIsTokenEditorLocked(isTokenEditorLocked); + dto.setIsTokenContextLocked(isTokenContextLocked); dto.setPlayersCanRevealVision(playersCanRevealVision); dto.setGmRevealsVisionForUnownedTokens(gmRevealsVisionForUnownedTokens); dto.setUseIndividualViews(useIndividualViews); diff --git a/src/main/resources/net/rptools/maptool/language/i18n.properties b/src/main/resources/net/rptools/maptool/language/i18n.properties index d983aaf40f..cec16a834d 100644 --- a/src/main/resources/net/rptools/maptool/language/i18n.properties +++ b/src/main/resources/net/rptools/maptool/language/i18n.properties @@ -1645,6 +1645,8 @@ action.toggleMovementLock = &Lock Player Movement action.toggleMovementLock.description = Locks movement for player-owned tokens. action.toggleTokenEditorLock = Lock Player Token Editor action.toggleTokenEditorLock.description = Locks access to the Token Editor. +action.toggleTokenContextMenuLock = Lock Player Token Context Menu +action.toggleTokenContextMenuLock.description = Locks access to the Context Menu. action.toggleNewZonesHaveFOW = New Maps have Fog of War action.toggleTokensStartSnapToGrid = Tokens Start Snap to Grid # Edit Menu