Initial
This commit is contained in:
1
resources/app/dist/components/activity.mjs
vendored
Normal file
1
resources/app/dist/components/activity.mjs
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export default class Activity{constructor(t){this.#t=t,this.#e=setInterval((()=>this.heartbeat(this)),15e3),this.#i()}#t;#e;users={};worldTime;#s;#i(){this.#s=Date.now(),db.Setting.getValue("core.time").then((t=>{if(this.worldTime=Number.isNumeric(t)?Number(t):0,void 0===t)return db.Setting.set("core.time",0)}))}get serverTime(){return Date.now()-this.#s}heartbeat(){if(game.world===this.#t){if(game.users)for(let t of game.users)t.id in this.users&&0===t.sockets.length&&this.deactivateUser(t)}else clearInterval(this.#e)}activateUser(t){const{express:e,game:i,db:s}=global;return"string"==typeof t&&(t=i.users.find((e=>e.id===t))),t instanceof s.User&&(!(t.id in this.users)&&(this.users[t.id]={},e.io.emit("userActivity",t.id,{active:!0}),!0))}deactivateUser(t){const{express:e,db:i}=global;if(!(t instanceof i.User))throw new Error("You must provide a User document instance to the deactivateUser method");return!t.sockets.length&&(t.id in this.users&&(delete this.users[t.id],e.io.emit("userActivity",t.id,{active:!1})),!0)}static socketListeners(t){this._onActivate(t,!0),t.on("disconnect",(()=>this._onActivate(t,!1))),t.on("userActivity",((e,i)=>Activity.#a(t,e,i))),t.on("getUserActivity",(()=>Activity.#r(t))),t.on("pause",(e=>this.pause(t,e))),t.on("time",this._onGameTime),t.on("reload",(()=>{t.user.can("SETTINGS_MODIFY")&&t.broadcast.emit("reload")}))}static _onActivate(t,e){const{game:i}=global;i.ready&&i.activity&&t.user&&(e?i.activity.activateUser(t.user):i.activity.deactivateUser(t.user))}static async _onGameTime(t){const{game:e}=global;return e.ready&&e.activity?t({serverTime:e.activity.serverTime,worldTime:e.activity.worldTime}):t({})}static pause(t,e){game.ready&&(global.logger.info(`Toggling game pause status to ${e}`),game.paused=e,t.broadcast.emit("pause",e))}static#a(t,e,i={}){if(!game.ready||!game.activity)return;const s=game.activity.users;e in s||(s[e]={});const a=s[e];for(const t of["sceneId","cursor","ruler","targets","av"])t in i&&(a[t]=i[t]);t.broadcast.emit("userActivity",e,i)}static#r(t){if(game.ready&&game.activity)for(const[e,i]of Object.entries(game.activity.users))t.emit("userActivity",e,i)}}
|
||||
1
resources/app/dist/components/demo.mjs
vendored
Normal file
1
resources/app/dist/components/demo.mjs
vendored
Normal file
@@ -0,0 +1 @@
|
||||
import fs from"node:fs";import path from"node:path";import Files from"../files/files.mjs";import{World}from"../packages/_module.mjs";export async function resetDemo(){const{game:e,options:o}=globalThis;if(!o.demoMode)return null;const r=o.demo;e.world&&await e.world.deactivate(null,{asAdmin:!0});const t=path.join(World.baseDir,r.worldName);await fs.promises.rm(t,{force:!0,recursive:!0}),await Files.extractArchive(r.sourceZip,t,{removeRoot:r.worldName}),World.resetPackages();const s=World.get(r.worldName);return s?(await s.setup(),setTimeout(resetDemo,1e3*r.resetSeconds),s):(global.logger.warn(`Could not load ${r.worldName}`),null)}
|
||||
1
resources/app/dist/components/document-cache.mjs
vendored
Normal file
1
resources/app/dist/components/document-cache.mjs
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export default class DocumentCache{static#e={Scene:5};#t={Scene:new Map};#c(e){const t=this.#s(e),c=DocumentCache.#e[e];if(t.size<=c)return;const s=Array.from(t.values());for(s.sort(((e,t)=>t.lastAccessed-e.lastAccessed));t.size>c;){const e=s.pop();t.delete(e.value.id)}}#s(e){const t=this.#t[e];if(!t)throw new Error(`The document cache does not support ${e} documents.`);return t}addAll(e){const t=e[0]?.documentName,c=this.#s(t),s=performance.now();e.forEach((e=>c.set(e.id,{lastAccessed:s,value:e}))),this.#c(t)}delete(e){this.#s(e.documentName).delete(e.id)}get(e,t){return this.#t[e]?.get(t)?.value}set(e){this.#s(e.documentName).set(e.id,{lastAccessed:performance.now(),value:e}),this.#c(e.documentName)}}
|
||||
1
resources/app/dist/components/progress-emitter.mjs
vendored
Normal file
1
resources/app/dist/components/progress-emitter.mjs
vendored
Normal file
@@ -0,0 +1 @@
|
||||
import{mergeObject}from"../../common/utils/helpers.mjs";export default class ProgressEmitter{constructor(t,o,e,s={},i={}){this.#t=t,this.#o=o,this.#e=e,this.#s=s,this.#i=mergeObject({log:!0,decimalPlaces:0},i)}#t;#o=null;#e;#s;#i;#n;get operationString(){return this.#i.operationName?`${this.#i.operationName} | `:""}complete({event:t="progress",context:o={},log:e,step:s}={}){const{express:i,logger:n}=global,{log:r,onProgress:c}=this.#i,{STEPS:a}=CONST.SETUP_PACKAGE_PROGRESS;s??=a.COMPLETE;const g={...this.#s,...o,step:s,pct:100,action:this.#t};c instanceof Function&&c(g),r&&n.info(`${this.operationString}${e??`${s} - 100%`}`),i.io.emit(t,g)}emit(t,{event:o="progress",force:e=!1,log:s,context:i={}}={}){const{express:n,logger:r}=global,{log:c,decimalPlaces:a,onProgress:g}=this.#i,p=Math.min(Number((t/this.#e*100).toFixed(a)),100),l=p!==this.#n,h={...this.#s,...i,pct:p,hasChanged:l,action:this.#t,step:this.#o};if(g instanceof Function&&g(h),e||l){if(c){const t=s??`${this.#t} ${this.#o} progress`;r.info(`${this.operationString}${t} - ${p}%`)}n.io.emit(o,h),this.#n=p}}error(t,{event:o="progress",log:e,context:s={}}={}){const{express:i,logger:n}=global,{log:r,onProgress:c}=this.#i,{STEPS:a}=CONST.SETUP_PACKAGE_PROGRESS,g={...this.#s,...s,pct:100,action:this.#t,step:a.ERROR,error:t.message,stack:t.stack};c instanceof Function&&c(g),r&&n.error(e??t),i.io.emit(o,g)}nextStep(t,o,e={}){this.#o=t,this.#e=o,mergeObject(this.#s,e)}log(t){logger.info(`${this.operationString}${t}`)}}
|
||||
1
resources/app/dist/components/prosemirror.mjs
vendored
Normal file
1
resources/app/dist/components/prosemirror.mjs
vendored
Normal file
@@ -0,0 +1 @@
|
||||
import{EditorState}from"prosemirror-state";import{Step}from"prosemirror-transform";import{defaultSchema}from"../../common/prosemirror/_module.mjs";import{serializeHTMLString}from"../../common/prosemirror/util.mjs";import{fromUuid}from"../core/utils.mjs";import{getProperty,isEmpty,setProperty}from"../../common/utils/helpers.mjs";export default class ProseMirrorAuthority{constructor(t,r){this.#t=t,this.#r=r,this.#e()}#r;get doc(){return this.#r}#s=0;get version(){return this.#s}#o=0;get offset(){return this.#o}#t;#i;history=[];users=new Set;applySteps(t,r){r.forEach((r=>{r=Step.fromJSON(defaultSchema,r);try{this.#r=r.apply(this.#r).doc}catch(r){return void logger.warn(`Failed to apply collaborative editing step for user ${t}. Editors may be in an inconsistent state.`)}this.#s++,this.history.push({userId:t,step:r})})),this.#a()}broadcast(t,...r){const{game:e}=global;for(const s of this.users){const o=e.users.find((t=>t.id===s));o&&o.sockets.forEach((e=>e.emit(t,...r)))}}#a(){const t=this.history.length-ProseMirrorAuthority.#n;t<1||(this.history.splice(0,t),this.#o+=t)}async#e(){let t=await db.Setting.getValue("core.editorAutosaveSecs")||60;t=Math.clamp(t,30,300),this.#i=setInterval(this.#u.bind(this),1e3*t)}async#u(){const{logger:t}=global,r=serializeHTMLString(this.doc),[e,s]=this.#t.split("#"),o=await fromUuid(e);if(o||t.warn(`Tried to autosave contents of ProseMirror instance '${this.#t}' but could not retrieve the document.`),!game?.ready)return;if(!o.isEmbedded&&!o.constructor.ready)return;const i={};setProperty(i,s,r),o.constructor.sanitizeUserInput(i,{document:o});const a=o.updateSource(i);if(!isEmpty(getProperty(a,s))){t.debug(`Broadcasting autosave update for instance '${this.#t}'.`);for(const t of game.users)t.sockets.forEach((t=>t.emit("pm.autosave",this.#t,r)));return o.isEmbedded?o.parent.save():o.save()}}static#n=256;static#c=new Map;static async create(t,r){const e=EditorState.fromJSON({schema:defaultSchema},r).doc;return new ProseMirrorAuthority(t,e)}static async getOrCreate(t,r){const e=ProseMirrorAuthority.#c,s=e.get(t)??await this.create(t,r);return s?(e.has(t)||e.set(t,s),s):null}static socketListeners(t){t.on("pm.editDocument",ProseMirrorAuthority.#d.bind(this,t.userId)),t.on("pm.receiveSteps",ProseMirrorAuthority.#h.bind(this,t)),t.on("pm.endSession",ProseMirrorAuthority.#m.bind(this,t.userId)),t.on("disconnect",ProseMirrorAuthority.#p.bind(this,t.userId))}static async#d(t,r,e,s){const o=await this.getOrCreate(r,e);if(!o)return s({});logger.debug(`Starting edit session for user '${t}' and instance '${r}'.`),o.users.add(t);s({state:EditorState.create({doc:o.doc}),version:o.version,users:Array.from(o.users)}),o.broadcast("pm.usersEditing",r,Array.from(o.users))}static#m(t,r){const{game:e}=global,s=ProseMirrorAuthority.#c.get(r);if(!s)return;s.users.delete(t)&&logger.debug(`Retiring user '${t}' from editing session for instance '${r}'.`),e.ready&&s.users.size?s.broadcast("pm.usersEditing",r,Array.from(s.users)):(logger.debug(`Instance '${r}' has no more active editors, cleaning up.`),clearInterval(s.#i),ProseMirrorAuthority.#c.delete(r))}static#p(t){for(const r of ProseMirrorAuthority.#c.keys())ProseMirrorAuthority.#m(t,r)}static#h(t,r,e,s){const{logger:o}=global,i=ProseMirrorAuthority.#c.get(r);if(!i)return void o.error("Editing steps were received for an JournalEntryPage that is not in an editing state.");const a=i.version-e;a>ProseMirrorAuthority.#n?t.emit("pm.resync",r):0===a&&(i.applySteps(t.userId,s),i.broadcast("pm.newSteps",r,i.offset,i.history))}}
|
||||
Reference in New Issue
Block a user