Skip to content

Commit

Permalink
a
Browse files Browse the repository at this point in the history
  • Loading branch information
theripper93 committed Jun 27, 2024
1 parent 3c8de70 commit 6d7220c
Show file tree
Hide file tree
Showing 11 changed files with 353 additions and 193 deletions.
11 changes: 2 additions & 9 deletions module.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,8 @@
"path": "languages/ja.json"
}
],
"scripts": [
"scripts/main.js",
"scripts/BossBar.js",
"scripts/cameraPan.js"
"esmodules": [
"scripts/main.js"
],
"styles": [
"styles/module.css"
Expand All @@ -70,11 +68,6 @@
"id": "bossbar",
"relationships": {
"requires": [
{
"id": "socketlib",
"type": "module",
"compatibility": {}
}
]
},
"compatibility": {
Expand Down
6 changes: 0 additions & 6 deletions packs/macros.db

This file was deleted.

File renamed without changes.
2 changes: 1 addition & 1 deletion packs/macros/CURRENT
Original file line number Diff line number Diff line change
@@ -1 +1 @@
MANIFEST-000333
MANIFEST-000353
6 changes: 3 additions & 3 deletions packs/macros/LOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
2024/06/08-19:50:40.390 3f58 Recovering log #331
2024/06/08-19:50:40.394 3f58 Delete type=0 #331
2024/06/08-19:50:40.395 3f58 Delete type=3 #329
2024/06/27-22:45:40.343 4928 Recovering log #352
2024/06/27-22:45:40.346 4928 Delete type=0 #352
2024/06/27-22:45:40.346 4928 Delete type=3 #351
11 changes: 3 additions & 8 deletions packs/macros/LOG.old
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
2024/05/30-14:14:05.946 4760 Recovering log #328
2024/05/30-14:14:05.949 4760 Delete type=0 #328
2024/05/30-14:14:05.949 4760 Delete type=3 #327
2024/05/30-14:24:29.343 6724 Level-0 table #332: started
2024/05/30-14:24:29.343 6724 Level-0 table #332: 0 bytes OK
2024/05/30-14:24:29.345 6724 Delete type=0 #330
2024/05/30-14:24:29.345 6724 Manual compaction at level-0 from '!macros!LD5Wc6K0vLQw0att' @ 72057594037927935 : 1 .. '!macros!iWwnlmoMWqNGJ54U' @ 0 : 0; will stop at (end)
2024/05/30-14:24:29.345 6724 Manual compaction at level-1 from '!macros!LD5Wc6K0vLQw0att' @ 72057594037927935 : 1 .. '!macros!iWwnlmoMWqNGJ54U' @ 0 : 0; will stop at (end)
2024/06/27-22:41:50.291 68d4 Recovering log #349
2024/06/27-22:41:50.295 68d4 Delete type=0 #349
2024/06/27-22:41:50.295 68d4 Delete type=3 #347
Binary file not shown.
14 changes: 8 additions & 6 deletions scripts/BossBar.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
class BossBar {
import {Socket} from "./lib/socket.js";

export class BossBar {
constructor() {
this.actor;
this.token;
Expand Down Expand Up @@ -29,7 +31,7 @@ class BossBar {
await canvas.scene.setFlag("bossbar", "bossBarActive", oldBars);
}
instance.hookId = Hooks.on("updateActor", (actor, updates) => {
if (actor.id == instance.actor.id && Object.byString(updates.system, game.settings.get("bossbar", "currentHpPath")) !== undefined) {
if (actor.id == instance.actor.id && foundry.utils.getProperty(updates.system, game.settings.get("bossbar", "currentHpPath")) !== undefined) {
instance.update();
}
});
Expand Down Expand Up @@ -166,7 +168,7 @@ class BossBar {
canvas.scene._bossBars[bossBar.id] = bossBar;
}

static cameraPan(tokenId, scale, duration) {
static cameraPan({tokenId, scale, duration}) {
const token = canvas.tokens.get(tokenId);
canvas.animatePan({
x: token.center.x,
Expand All @@ -177,7 +179,7 @@ class BossBar {
}

static panCamera(token, scale = 1.8, duration = 1000) {
_BossBarSocket.executeForEveryone("cameraPan", token.id, scale, duration);
Socket.cameraPan({tokenId: token.id, scale: scale, duration: duration});
}

static async renderBossBar() {
Expand All @@ -196,11 +198,11 @@ class BossBar {
}

get currentHp() {
return Object.byString(this.actor.system, game.settings.get("bossbar", "currentHpPath"));
return foundry.utils.getProperty(this.actor.system, game.settings.get("bossbar", "currentHpPath"));
}

get maxHp() {
return Object.byString(this.actor.system, game.settings.get("bossbar", "maxHpPath"));
return foundry.utils.getProperty(this.actor.system, game.settings.get("bossbar", "maxHpPath"));
}

get hpPercent() {
Expand Down
6 changes: 0 additions & 6 deletions scripts/cameraPan.js

This file was deleted.

198 changes: 198 additions & 0 deletions scripts/lib/socket.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
import { MODULE_ID } from "../main.js";

export class Socket {
static __$callbacks = {};

static __$stores = {};

static __$promises = {};

static USERS = {
GMS: "gms",
PLAYERS: "players",
ALL: "all",
OTHERS: "others",
FIRSTGM: "firstGM",
SELF: "self",
};

static __$reserved = ["__$eventName", "__$response", "__$onMessage", "__$parseUsers", "register", "USERS"];

static async __$onMessage(data) {
const options = data.__$socketOptions;

if (options.__$storeName) {
if (options.__$request) {
const store = this.__$stores[options.__$storeName];
const _isLive = store._isLive;
if (!_isLive) return;
game.socket.emit(`module.${MODULE_ID}`, { __$socketOptions: { __$storeName: options.__$storeName, user: game.user.id }, data: store.getData() });
} else {
this.__$stores[options.__$storeName].synchronize(data.data, game.users.get(options.user));
}
return;
}

if (options.__$eventName === "__$response") {
const key = options.__$responseKey;
if (this.__$promises[key]) {
this.__$promises[key].resolve({ user: game.users.get(options.__$userId), response: data.result });
delete this.__$promises[key];
}
return;
}
if (!options.users.includes(game.user.id)) return;
const callback = this.__$callbacks[options.__$eventName];
delete data.__$socketOptions;
const result = await callback(data);
if (options.response) {
const key = `${options.__$eventId}.${game.user.id}`;
const data = { __$socketOptions: { __$eventName: "__$response", __$responseKey: key, __$userId: game.user.id }, result };
this.__$socket.emit(`module.${MODULE_ID}`, data);
}
}

static __$parseUsers(options) {
if (Array.isArray(options?.users)) return options;
if (typeof options === "string") options = { users: options };
if (Array.isArray(options)) options = { users: options };
options.users = options.users || this.USERS.ALL;
const active = game.users.filter((u) => u.active);
const users = options.users;
if (users === this.USERS.ALL) {
options.users = active.map((u) => u.id);
} else if (users === this.USERS.GMS) {
options.users = active.filter((u) => u.isGM).map((u) => u.id);
} else if (users === this.USERS.PLAYERS) {
options.users = active.filter((u) => !u.isGM).map((u) => u.id);
} else if (users === this.USERS.OTHERS) {
options.users = active.filter((u) => u.id !== game.user.id).map((u) => u.id);
} else if (users === this.USERS.FIRSTGM) {
options.users = game.users.activeGM.id;
} else if (users === this.USERS.SELF) {
options.users = [game.user.id];
}
return options;
}

static register(eventName, callback, defaultOptions = {}) {
if (!this.__$socket) {
this.__$socket = game.socket;
game.socket.on(`module.${MODULE_ID}`, this.__$onMessage.bind(this));
}

if (this.__$reserved.includes(eventName)) {
throw new Error(`Socket event name ${eventName} is reserved`);
}

this.__$callbacks[eventName] = callback;

const wrappedCallback = async (data = {}, options = {}) => {
options = this.__$parseUsers(options);
options = { ...defaultOptions, ...options };
const eventId = foundry.utils.randomID();
options.__$eventId = eventId;
options.__$eventName = eventName;
const promises = [];
const local = options.users.includes(game.user.id);
options.users = options.users.filter((u) => u !== game.user.id);
if (options.response) {
for (const user of options.users) {
promises.push(
new Promise((resolve, reject) => {
const key = `${eventId}.${user}`;
this.__$promises[key] = { resolve, reject };
}),
);
}

setTimeout(() => {
for (const user of options.users) {
const key = `${eventId}.${user}`;
if (this.__$promises[key]) {
this.__$promises[key].reject({ user: game.users.get(user), response: "timeout" });
delete this.__$promises[key];
}
}
}, options.timeout || 30000);
}

data.__$socketOptions = options;
this.__$socket.emit(`module.${MODULE_ID}`, data);

const results = [];

if (local) {
const localWrapper = async () => {
return { user: game.user, response: await callback(data) };
};
promises.push(localWrapper());
}

const allPromises = await Promise.all(promises);
for (const promise of allPromises) {
results.push(promise);
}

return results;
};

this[eventName] = wrappedCallback.bind(this);
}

static registerStore(storeName, initialValue = {}, callback = null) {
if (this.__$reserved.includes(storeName)) {
throw new Error(`Store name ${storeName} is reserved`);
}

if (typeof initialValue !== "object") {
throw new Error("Initial value for store must be an object");
}

this.__$stores[storeName] = new SynchronizedStore(storeName, initialValue, callback);

Object.defineProperty(this, storeName, {
get: () => {
return this.__$stores[storeName].getData();
},
set: (value) => {
this.__$stores[storeName].setData(value);
},
});

return this.__$stores[storeName];
}
}

class SynchronizedStore {
constructor(storeName, initialValue, callback) {
this._storeName = storeName;

this._onChange = callback;

this._data = initialValue;

this._timestamp = Date.now();

this._isLive = false;

//request value from other users
game.socket.emit(`module.${MODULE_ID}`, { __$socketOptions: { __$storeName: this._storeName, __$request: true, user: game.user.id } });
}

synchronize(data) {
this._data = data;
this._timestamp = Date.now();
this._isLive = true;
this._onChange?.(this.data);
}

getData() {
return this._data;
}

setData(value) {
this.synchronize(value);
game.socket.emit(`module.${MODULE_ID}`, { __$socketOptions: { __$storeName: this._storeName, user: game.user.id }, data: value });
}
}
Loading

0 comments on commit 6d7220c

Please sign in to comment.