From 93d1587f619b71ffd88fa427a03cb3d7e18de9e3 Mon Sep 17 00:00:00 2001 From: Matheus Clemente Date: Sun, 7 Jul 2024 15:56:41 -0300 Subject: [PATCH] Update for V12 (#22) --- module.json | 5 ++-- src/libwrapper_shim.js | 61 ------------------------------------------ src/socketlib.js | 40 ++++++++------------------- 3 files changed, 13 insertions(+), 93 deletions(-) delete mode 100644 src/libwrapper_shim.js diff --git a/module.json b/module.json index 34ed93a..180344f 100644 --- a/module.json +++ b/module.json @@ -4,8 +4,8 @@ "description": "A library for easier handling of foundry sockets", "version": "1.0.13", "compatibility": { - "minimum": "10", - "verified": "11" + "minimum": "11", + "verified": "12" }, "library": true, "authors": [ @@ -17,7 +17,6 @@ } ], "esmodules": [ - "src/libwrapper_shim.js", "src/socketlib.js" ], "url": "https://github.com/manuelVo/foundryvtt-socketlib", diff --git a/src/libwrapper_shim.js b/src/libwrapper_shim.js deleted file mode 100644 index dc76133..0000000 --- a/src/libwrapper_shim.js +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: MIT -// Copyright © 2021 fvtt-lib-wrapper Rui Pinheiro - -'use strict'; - -// A shim for the libWrapper library -export let libWrapper = undefined; - -Hooks.once('init', () => { - // Check if the real module is already loaded - if so, use it - if(globalThis.libWrapper && !(globalThis.libWrapper.is_fallback ?? true)) { - libWrapper = globalThis.libWrapper; - return; - } - - // Fallback implementation - libWrapper = class { - static get is_fallback() { return true }; - - static register(module, target, fn, type="MIXED", {chain=undefined}={}) { - const is_setter = target.endsWith('#set'); - target = !is_setter ? target : target.slice(0, -4); - const split = target.split('.'); - const fn_name = split.pop(); - const root_nm = split.splice(0,1)[0]; - const _eval = eval; // The browser doesn't expose all global variables (e.g. 'Game') inside globalThis, but it does to an eval. We copy it to a variable to have it run in global scope. - const obj = split.reduce((x,y)=>x[y], globalThis[root_nm] ?? _eval(root_nm)); - - let iObj = obj; - let descriptor = null; - while(iObj) { - descriptor = Object.getOwnPropertyDescriptor(iObj, fn_name); - if(descriptor) break; - iObj = Object.getPrototypeOf(iObj); - } - if(!descriptor || descriptor?.configurable === false) throw `libWrapper Shim: '${target}' does not exist, could not be found, or has a non-configurable descriptor.`; - - let original = null; - const wrapper = (chain ?? type != 'OVERRIDE') ? function() { return fn.call(this, original.bind(this), ...arguments); } : function() { return fn.apply(this, arguments); }; - - if(!is_setter) { - if(descriptor.value) { - original = descriptor.value; - descriptor.value = wrapper; - } - else { - original = descriptor.get; - descriptor.get = wrapper; - } - } - else { - if(!descriptor.set) throw `libWrapper Shim: '${target}' does not have a setter`; - original = descriptor.set; - descriptor.set = wrapper; - } - - descriptor.configurable = true; - Object.defineProperty(obj, fn_name, descriptor); - } - } -}); diff --git a/src/socketlib.js b/src/socketlib.js index 2f85645..73fbcdb 100644 --- a/src/socketlib.js +++ b/src/socketlib.js @@ -1,4 +1,3 @@ -import {libWrapper} from "./libwrapper_shim.js"; import * as errors from "./errors.js"; const RECIPIENT_TYPES = { @@ -18,9 +17,10 @@ const MESSAGE_TYPES = { Hooks.once("init", () => { window.socketlib = new Socketlib(); - libWrapper.register("socketlib", "Users.prototype.constructor._handleUserActivity", handleUserActivity); Hooks.callAll("socketlib.ready"); -}, "WRAPPER"); +}); + +Hooks.on("userConnected", handleUserActivity); class Socketlib { constructor() { @@ -90,7 +90,7 @@ class SocketlibSocket { return this._executeLocal(func, ...args); } else { - if (!game.users.find(isActiveGM)) { + if (!game.users.activeGM) { throw new errors.SocketlibNoGMConnectedError(`Could not execute handler '${name}' (${func.name}) as GM, because no GM is connected.`); } return this._sendRequest(name, args, RECIPIENT_TYPES.ONE_GM); @@ -162,7 +162,7 @@ class SocketlibSocket { _sendRequest(handlerName, args, recipient) { const message = {handlerName, args, recipient}; - message.id = randomID(); + message.id = foundry.utils.randomID(); message.type = MESSAGE_TYPES.REQUEST; const promise = new Promise((resolve, reject) => this.pendingRequests.set(message.id, {handlerName, resolve, reject, recipient})); game.socket.emit(this.socketName, message); @@ -224,7 +224,7 @@ class SocketlibSocket { else { switch (recipient) { case RECIPIENT_TYPES.ONE_GM: - if (!isResponsibleGM()) + if (!game.users.activeGM?.isSelf) return; break; case RECIPIENT_TYPES.ALL_GMS: @@ -303,42 +303,25 @@ class SocketlibSocket { } } -function isResponsibleGM() { - if (!game.user.isGM) - return false; - const connectedGMs = game.users.filter(isActiveGM); - return !connectedGMs.some(other => other.id < game.user.id); -} - -function isActiveGM(user) { - return user.active && user.isGM; -} - -function handleUserActivity(wrapper, userId, activityData={}) { - const user = game.users.get(userId); - const wasActive = user.active; - const result = wrapper(userId, activityData); - - // If user disconnected - if (!user.active && wasActive) { +function handleUserActivity(user, active) { + if (!active) { const modules = Array.from(socketlib.modules.values()); if (socketlib.system) modules.concat(socketlib.system); - const GMConnected = Boolean(game.users.find(isActiveGM)); // Reject all promises that are still waiting for a response from this player for (const socket of modules) { const failedRequests = Array.from(socket.pendingRequests.entries()).filter(([id, request]) => { const recipient = request.recipient; const handlerName = request.handlerName; if (recipient === RECIPIENT_TYPES.ONE_GM) { - if (!GMConnected) { + if (!game.users.activeGM) { request.reject(new errors.SocketlibNoGMConnectedError(`Could not execute handler '${handlerName}' as GM, because all GMs disconnected while the execution was being dispatched.`)); return true; } } else if (recipient instanceof Array) { - if (recipient.includes(userId)) { - request.reject(new errors.SocketlibInvalidUserError(`User '${game.users.get(userId).name}' (${userId}) disconnected while handler '${handlerName}' was being dispatched.`)); + if (recipient.includes(user.id)) { + request.reject(new errors.SocketlibInvalidUserError(`User '${user.name}' (${user.id}) disconnected while handler '${handlerName}' was being dispatched.`)); return true; } } @@ -349,5 +332,4 @@ function handleUserActivity(wrapper, userId, activityData={}) { } } } - return result; }