Skip to content
1 change: 1 addition & 0 deletions messages/src/main/proto/data_transfer_objects.proto
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
25 changes: 25 additions & 0 deletions src/main/java/net/rptools/maptool/client/AppActions.java
Original file line number Diff line number Diff line change
Expand Up @@ -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") {

Expand Down Expand Up @@ -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());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand Down
4 changes: 4 additions & 0 deletions src/main/java/net/rptools/maptool/client/ui/MapToolFrame.java
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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<GUID> GUIDSet = new HashSet<GUID>();
GUIDSet.add(tokenId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public class StartServerDialog extends AbeillePanel<StartServerDialogPreferences
private JCheckBox playersCanRevealVision;
private JCheckBox hideMapSelectUI;
private JCheckBox lockTokenEditOnStartup;
private JCheckBox lockTokenContextOnStartup;
private JCheckBox lockPlayerMoveOnStartup;
private JCheckBox lockPlayerLibrary;
private JButton generateGMPassword;
Expand Down Expand Up @@ -92,6 +93,7 @@ public String showDialog() {
usePasswordFile = (JCheckBox) getComponent("@usePasswordFile");
hideMapSelectUI = (JCheckBox) getComponent("@hideMapSelectUI");
lockTokenEditOnStartup = (JCheckBox) getComponent("@lockTokenEditOnStartup");
lockTokenContextOnStartup = (JCheckBox) getComponent("@lockTokenContextOnStartup");
lockPlayerMoveOnStartup = (JCheckBox) getComponent("@lockPlayerMovementOnStartup");
lockPlayerLibrary = (JCheckBox) getComponent("@disablePlayerLibrary");

Expand Down Expand Up @@ -143,6 +145,7 @@ public String showDialog() {
});
hideMapSelectUI.setSelected(prefs.getMapSelectUIHidden());
lockTokenEditOnStartup.setSelected(prefs.getLockTokenEditOnStart());
lockTokenContextOnStartup.setSelected(prefs.getLockTokenContextOnStart());
lockPlayerMoveOnStartup.setSelected(prefs.getLockPlayerMovementOnStart());
lockPlayerLibrary.setSelected(prefs.getPlayerLibraryLock());

Expand Down Expand Up @@ -265,6 +268,7 @@ public void initOKButton() {
prefs.setUseEasyConnect(useEasyConnect.isSelected());
prefs.setMapSelectUIHidden(hideMapSelectUI.isSelected());
prefs.setLockTokenEditOnStart(lockTokenEditOnStartup.isSelected());
prefs.setLockTokenContextOnStart(lockTokenContextOnStartup.isSelected());
prefs.setLockPlayerMovementOnStart(lockPlayerMoveOnStartup.isSelected());
prefs.setPlayerLibraryLock(lockPlayerLibrary.isSelected());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public class StartServerDialogPreferences {
private static final String KEY_USE_PASSWORD_FILE = "usePasswordFile";
private static final String KEY_HIDE_MAP_SELECT_UI = "hideMapSelectUI";
private static final String KEY_START_LOCKED_TOKEN_EDIT = "lockTokenEditOnStartup";
private static final String KEY_START_LOCKED_TOKEN_CONTEXT = "lockTokenContextOnStartup";
private static final String KEY_START_LOCKED_PLAYER_MOVEMENT = "lockPlayerMovementOnStartup";
private static final String KEY_LOCK_PLAYER_LIBRARY = "lockPlayerLibrary";

Expand Down Expand Up @@ -242,10 +243,18 @@ public boolean getLockTokenEditOnStart() {
return prefs.getBoolean(KEY_START_LOCKED_TOKEN_EDIT, false);
}

public boolean getLockTokenContextOnStart() {
return prefs.getBoolean(KEY_START_LOCKED_TOKEN_CONTEXT, false);
}

public void setLockTokenEditOnStart(boolean flag) {
prefs.putBoolean(KEY_START_LOCKED_TOKEN_EDIT, flag);
}

public void setLockTokenContextOnStart(boolean flag) {
prefs.putBoolean(KEY_START_LOCKED_TOKEN_CONTEXT, flag);
}

public boolean getLockPlayerMovementOnStart() {
return prefs.getBoolean(KEY_START_LOCKED_PLAYER_MOVEMENT, false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@
<text resource-bundle="net/rptools/maptool/language/i18n" key="ServerDialog.label.gmpassword"/>
</properties>
</component>
<grid id="fc9cf" layout-manager="GridLayoutManager" row-count="15" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="fc9cf" layout-manager="GridLayoutManager" row-count="16" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="6" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
Expand Down Expand Up @@ -196,7 +196,7 @@
</component>
<component id="bdee" class="javax.swing.JLabel">
<constraints>
<grid row="14" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
<grid row="15" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="net/rptools/maptool/language/i18n" key="ServerDialog.label.metric"/>
Expand Down Expand Up @@ -249,7 +249,7 @@
</component>
<component id="cd443" class="javax.swing.JCheckBox">
<constraints>
<grid row="11" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
<grid row="12" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<actionCommand value="Lock Play Movement"/>
Expand All @@ -260,7 +260,7 @@
</component>
<component id="860" class="javax.swing.JCheckBox">
<constraints>
<grid row="12" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
<grid row="13" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<actionCommand value="Lock Player Library"/>
Expand All @@ -282,7 +282,7 @@
</component>
<component id="3eea1" class="javax.swing.JComboBox">
<constraints>
<grid row="14" column="2" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
<grid row="15" column="2" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<actionCommand value="comboBoxChanged"/>
Expand All @@ -292,9 +292,21 @@
</component>
<hspacer id="6c8b3">
<constraints>
<grid row="13" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
<grid row="14" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</hspacer>
<component id="e67f" class="javax.swing.JCheckBox">
<constraints>
<grid row="11" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<actionCommand value="Lock Token Context Menu"/>
<name value="@lockTokenContextOnStartup"/>
<selected value="false"/>
<text resource-bundle="net/rptools/maptool/language/i18n" key="action.toggleTokenContextMenuLock"/>
<toolTipText resource-bundle="net/rptools/maptool/language/i18n" key="action.toggleTokenContextMenuLock.description"/>
</properties>
</component>
</children>
</grid>
<grid id="67b44" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/net/rptools/maptool/server/ServerPolicy.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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();
Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading