Adds a keybind into the module that allows GMs to temporarily hide their cursor from everyone else (including other GMs)

This commit is contained in:
Oliver 2025-12-14 15:27:45 -07:00
parent c2601ba69c
commit f58c8411aa
3 changed files with 144 additions and 0 deletions

View file

@ -65,6 +65,12 @@
"label": "Configure Hotbar" "label": "Configure Hotbar"
} }
}, },
"keybindings": {
"toggleMouseBroadcast": {
"name": "Toggle Mouse Position",
"hint": "(v13+) Temporarily turns off or on the mouse cursor position that players see."
}
},
"apps": { "apps": {
"no-settings-to-display": "No settings to display", "no-settings-to-display": "No settings to display",
"make-global-reference": "Make Global Reference" "make-global-reference": "Make Global Reference"
@ -77,6 +83,12 @@
"ignoreAndDontShowAgain": "", "ignoreAndDontShowAgain": "",
"disableEntirely": "" "disableEntirely": ""
} }
},
"notifs": {
"toggleMouseBroadcast": {
"hidingCursor": "Hiding your cursor from others!",
"showingCursor": "Showing your cursor to others!"
}
} }
} }
} }

View file

@ -1,5 +1,6 @@
// Settings // Settings
import { preventMovementHistory } from "../settings/preventMovementHistory.mjs"; import { preventMovementHistory } from "../settings/preventMovementHistory.mjs";
import { toggleMouseBroadcast } from "../settings/toggleMouseBroadcast.mjs";
// Utils // Utils
import { Logger } from "../utils/Logger.mjs"; import { Logger } from "../utils/Logger.mjs";
@ -14,4 +15,5 @@ Hooks.on(`init`, () => {
Logger.log(`Initializing`); Logger.log(`Initializing`);
preventMovementHistory(); preventMovementHistory();
toggleMouseBroadcast();
}); });

View file

@ -0,0 +1,130 @@
import { SettingStatusEnum, status } from "../utils/SettingStatus.mjs";
import { __ID__ } from "../consts.mjs";
import { Logger } from "../utils/Logger.mjs";
const key = `toggleMouseBroadcast`;
/** @type {number | null} */
let notifID = null;
export function toggleMouseBroadcast() {
status[key] = SettingStatusEnum.Unknown;
// #region Registration
const prevented = Hooks.call(`${__ID__}.preventSetting`, key);
if (!prevented) {
Logger.log(`Preventing setting "${key}" from being registered`);
status[key] = SettingStatusEnum.Blocked;
return;
};
Logger.log(`Registering setting: ${key}`);
// MARK: setting
game.settings.register(__ID__, key, {
scope: `client`,
config: false,
default: true,
});
// MARK: keybind
game.keybindings.register(__ID__, key, {
name: `OFT.keybindings.${key}.name`,
hint: `OFT.keybindings.${key}.hint`,
precedence: CONST.KEYBINDING_PRECEDENCE.NORMAL,
restricted: true,
editable: [
{ key: `KeyH` },
],
onDown: (event) => {
if (!game.user.hasPermission(`SHOW_CURSOR`)) { return };
event.preventDefault?.();
const current = game.settings.get(__ID__, key);
if (current) {
notifID = ui.notifications.warn(
`OFT.notifs.${key}.hidingCursor`,
{ console: false, localize: true, permanent: true },
).id;
} else {
if (notifID != null) {
ui.notifications.remove(notifID);
};
ui.notifications.success(
`OFT.notifs.${key}.showingCursor`,
{ console: false, localize: true },
);
};
game.settings.set(__ID__, key, !current);
// Hide the existing cursor
game.user.broadcastActivity({ cursor: null });
return true;
},
});
// #endregion Registration
// #region Implementation
Hooks.on(`renderControlsConfig`, renderControlsConfigHandler);
Hooks.once(`ready`, readyHandler);
class OFTControlsLayer extends CONFIG.Canvas.layers.controls.layerClass {
_onMouseMove(currentPos) {
if (!game.settings.get(__ID__, key)) {
game.user.broadcastActivity({});
};
super._onMouseMove(currentPos);
};
};
CONFIG.Canvas.layers.controls.layerClass = OFTControlsLayer;
// #endregion Implementation
status[key] = SettingStatusEnum.Registered;
};
// #region Helpers
const tabGroup = `categories`;
/**
* Handle showing the "hiding your cursor" notification when the user
* connects to the server initially, allowing the current state to be
* correctly described to the user.
*/
function readyHandler() {
const hideCursor = !game.settings.get(__ID__, key);
const canShowCursor = game.user.hasPermission(`SHOW_CURSOR`);
if (hideCursor && canShowCursor) {
notifID = ui.notifications.warn(
`OFT.notifs.${key}.hidingCursor`,
{ console: false, localize: true, permanent: true },
).id;
};
};
/**
* Handles hiding the keybinding from the configuration if and when the user
* does not have the SHOW_CURSOR permission since this keybinding is really
* useless if they can't even broadcast their cursor in the first place.
*/
function renderControlsConfigHandler(_app, element) {
if (game.user.hasPermission(`SHOW_CURSOR`)) { return };
const keybindingList = element.querySelector(`section[data-group="${tabGroup}"][data-tab="${__ID__}"]`);
const tabButton = element.querySelector(`button[data-group="${tabGroup}"][data-tab="${__ID__}"]`);
if (keybindingList.childElementCount === 0) {
tabButton?.remove();
return;
};
const keybind = keybindingList.querySelector(`.form-group[data-action-id="${__ID__}.${key}"]`);
keybind?.remove();
if (keybindingList.childElementCount === 0) {
keybindingList.remove();
tabButton.remove();
};
};
// #endregion Helpers