cirrahn / foundry-polmap

A political map overlay module for Foundry VTT.
MIT License
2 stars 1 forks source link

Make the needed permission level configurable #4

Closed barrucadu closed 1 year ago

barrucadu commented 2 years ago

This is a great little module, and looks like it'll be very handy for a West Marches-style hexcrawl, where the players are mapping out the terrain as they go. I can give them a blank map, and give them GM permissions, and they can colour hexes as they explore them.

But it would be even better if I didn't need to make them GMs, if I could let players or trusted players access the map controls directly.

~I'll probably just fork this module and comment out the GM check, rather than implement the config myself, but I think it would be handy to have the configuration in the module.~

barrucadu commented 2 years ago

Alright, so I see this might not actually be possible, since I don't see a way to make a scene flag editable by a normal user without also giving them access to everything else.

cirrahn commented 2 years ago

One technique I have seen in other modules is to send messages, via socket, from player clients to a connected GM client. This allows the player clients to proxy actions through the GM.

barrucadu commented 2 years ago

I had a go at this using socketlib, and came up with something incomplete but functional enough for my needs (probably):

diff --git a/classes/OverlayLayer.js b/classes/OverlayLayer.js
index f4025ac..5cbff22 100644
--- a/classes/OverlayLayer.js
+++ b/classes/OverlayLayer.js
@@ -156,28 +156,13 @@ export default class OverlayLayer extends CanvasLayer {
    * Add buffered history stack to scene flag and clear buffer
    */
    async commitHistory () {
-       // Do nothing if no history to be committed, otherwise get history
        if (this.historyBuffer.length === 0) return;
        if (this.lock) return;
        this.lock = true;
-       let history = canvas.scene.getFlag(this.layername, "history");
-       // If history storage doesn't exist, create it
-       if (!history) {
-           history = {
-               events: [],
-               pointer: 0,
-           };
+       if (await canvas.polmapSocket.executeAsGM("commit", this.historyBuffer)) {
+           polmapLog(`Pushed ${this.historyBuffer.length} updates (via GM socket).`);
+           this.historyBuffer = [];
        }
-       // If pointer is less than history length (f.x. user undo), truncate history
-       history.events = history.events.slice(0, history.pointer);
-       // Push the new history buffer to the scene
-       history.events.push(this.historyBuffer);
-       history.pointer = history.events.length;
-       await canvas.scene.unsetFlag(this.layername, "history");
-       await this.setSetting("history", history);
-       polmapLog(`Pushed ${this.historyBuffer.length} updates.`);
-       // Clear the history buffer
-       this.historyBuffer = [];
        this.lock = false;
    }

diff --git a/classes/PaletteControls.js b/classes/PaletteControls.js
index e30e03b..9f4bba2 100644
--- a/classes/PaletteControls.js
+++ b/classes/PaletteControls.js
@@ -15,7 +15,7 @@ export default class PaletteControls extends FormApplication {
            submitOnChange: true,
            submitOnClose: true,
            popOut: false,
-           editable: game.user.isGM,
+           editable: true,
            template: "modules/polmap/templates/palette-controls.hbs",
            id: "filter-config",
            title: game.i18n.localize("POLMAP.Political Map Options"),
diff --git a/js/controls.js b/js/controls.js
index eb074d9..1399363 100644
--- a/js/controls.js
+++ b/js/controls.js
@@ -11,14 +11,16 @@ const _doCacheControls = () => {
  * Add control buttons
  */
 Hooks.on("getSceneControlButtons", (controls) => {
-   if (!game.user.isGM) return;
-   controls.push({
-       name: "polmap",
-       title: game.i18n.localize("POLMAP.Political Map Overlay"),
-       icon: "fas fa-handshake",
-       layer: "polmap",
-       activeTool: "grid",
-       tools: [
+   let tools = [
+       {
+           name: "grid",
+           title: game.i18n.localize("POLMAP.Marker Tool"),
+           icon: "fas fa-border-none",
+       }
+   ];
+
+   if (game.user.isGM) {
+       tools = [
            {
                name: "polmaptoggle",
                title: game.i18n.localize("POLMAP.Enable/Disable Political Map Overlay"),
@@ -68,7 +70,16 @@ Hooks.on("getSceneControlButtons", (controls) => {
                },
                button: true,
            },
-       ],
+       ];
+   }
+
+   controls.push({
+       name: "polmap",
+       title: game.i18n.localize("POLMAP.Political Map Overlay"),
+       icon: "fas fa-handshake",
+       layer: "polmap",
+       activeTool: "grid",
+       tools: tools,
    });
 });

diff --git a/js/polmap.js b/js/polmap.js
index ad0f333..b65d678 100644
--- a/js/polmap.js
+++ b/js/polmap.js
@@ -24,6 +24,33 @@ Hooks.once("canvasInit", () => {
    }});
 });

+Hooks.once("socketlib.ready", () => {
+   canvas.polmapSocket = socketlib.registerModule("polmap");
+   canvas.polmapSocket.register("commit", async (historyBuffer) => {
+       if (historyBuffer.length === 0) return true;
+       if (canvas.scene.getFlag("polmap", "history_lock") === true) return false;
+       await canvas.scene.setFlag("polmap", "history_lock", true);
+       let history = canvas.scene.getFlag("polmap", "history");
+       // If history storage doesn't exist, create it
+       if (!history) {
+           history = {
+               events: [],
+               pointer: 0,
+           };
+       }
+       // If pointer is less than history length (f.x. user undo), truncate history
+       history.events = history.events.slice(0, history.pointer);
+       // Push the new history buffer to the scene
+       history.events.push(historyBuffer);
+       history.pointer = history.events.length;
+       await canvas.scene.setFlag("polmap", "history", history);
+       await canvas.scene.setFlag("polmap", "history_lock", false);
+       polmapLog(`Pushed ${historyBuffer.length} updates.`);
+
+       return true;
+   });
+});
+
 Hooks.once("ready", () => {
    PoliticalMapMigrations.check().then(() => polmapLog("Migrations complete!"));
 });
diff --git a/module.json b/module.json
index cdbf334..fc38481 100644
--- a/module.json
+++ b/module.json
@@ -27,5 +27,11 @@
    ],
    "styles": [
        "css/main.css"
-   ]
+   ],
+   "dependencies": [
+       {
+           "name": "socketlib"
+       }
+   ],
+   "socket": true
 }