Files

1 line
18 KiB
JavaScript
Raw Permalink Normal View History

2025-01-04 00:34:03 +01:00
import fs from"node:fs";import path from"node:path";import{USER_ROLES,PACKAGE_AVAILABILITY_CODES}from"../../common/constants.mjs";import{getRoute,isNewerVersion,isEmpty,randomID,deepClone,mergeObject}from"../../common/utils/helpers.mjs";import{BaseWorld}from"../../common/packages/module.mjs";import{PackageAssetField,ServerPackageMixin}from"./package.mjs";import Activity from"../components/activity.mjs";import migrations from"../migrations.mjs";import Files from"../files/files.mjs";import{HotReload}from"./_module.mjs";import DocumentCache from"../components/document-cache.mjs";import ProgressEmitter from"../components/progress-emitter.mjs";export default class World extends(ServerPackageMixin(BaseWorld)){static defineSchema(){const e=super.defineSchema();return e.background=new PackageAssetField({relativeToPackage:!1,mustExist:!1,...e.background.options}),e}#e=null;updatingPacks=Promise.resolve();_initialize(e){super._initialize(e),this.system=packages.System.get(this._source.system),this.modules=packages.Module.getPackages({system:this.system,enforceCompatibility:!0}),this.compatibility.maximum=this.compatibility.maximum||this.system?.compatibility.maximum,this.background=this.background||this.system?.background}vend(){const e=super.vend();return e.system=this._source.system,e}static loadLocalManifest(e){const{manifestData:t}=super.loadLocalManifest(e);return this.schema.get("id").validate(t.id)&&(e=World.#t(t)),{manifestPath:e,manifestData:t}}static#t(e){const t=e.id.slugify({strict:!0});let s=t,a=path.join(this.baseDir,s),i=0;for(;fs.existsSync(a);)s=`${t}-${++i}`,a=path.join(this.baseDir,s);const o=path.join(this.baseDir,e.id);fs.renameSync(o,a),e.id=s,delete e.name;const r=path.join(a,this.manifestFile);return Files.writeFileSyncSafe(r,JSON.stringify(e,null,2)),r}prepareDataModel(){const e={};for(const t of Object.values(foundry.documents)){if(!("coreTypes"in t.metadata))continue;const s=t.documentName,a=e[s]={};for(const e of t.metadata.coreTypes)a[e]={};if(!t.hasTypeData)continue;if(s in this.system.documentTypes)for(const e of Object.keys(this.system.documentTypes[s]))a[e]={};const i=this.system.template;if(i&&s in i){const e=foundry.utils.deepClone(i[s]),t=e.templates||{};for(const s of e.types||[]){const i=e[s]||{},o={};for(const e of i.templates||[])e in t&&mergeObject(o,t[e],{enforceTypes:!1});delete i.templates,mergeObject(o,i,{enforceTypes:!1}),a[s]=o}}}return e}get active(){const{game:e}=global;return e.world&&this.id===e.world.id}get canAutoLaunch(){const e=this.availability,t=globalThis.release;if(e===PACKAGE_AVAILABILITY_CODES.MISSING_SYSTEM)return!1;if(this.incompatibleWithCoreVersion)return!1;const s=this.compatibility.verified;return!!s&&(Number.isInteger(Number(s))?s>=t.generation:!isNewerVersion(t.version,s))}static create(e){if(e.id||(e.id=e.name),!e.id)throw new Error("You must provide a unique id that names this World.");if(e.id=e.id.slugify(),e.id.startsWith(".."))throw new Error("You are not allowed to install packages outside of the designated directory path");const t=path.join(this.baseDir,e.id);if(fs.existsSync(t))throw new Error(`A World already exists in the requested directory ${e.id}.`);const s=packages.System.get(e.system);if(!s)throw new Error(`The requested system ${config.system} does not seem to exist!`);e.coreVersion=global.release.version,e.compatibility={minimum:global.release.generation,verified:global.release.generation,maximum:void 0},e.systemVersion=s.version,e.lastPlayed=(new Date).toString();const a=new this(e,{strict:!0});return fs.mkdirSync(t),fs.mkdirSync(path.join(t,"data")),fs.mkdirSync(path.join(t,"scenes")),a.save(),globalThis.logger.info(`Created World "${a.id}"`),this.packages&&this.packages.set(a.id,a),a.vend()}static update(e){delete e.action;const t=this.get(e.id,{strict:!0});return t.updateSource(e),game.world&&(game.world=t),t.save(),t.vend()}static async install(e,t,s,a,i){const o=path.join(this.baseDir,e);if(fs.existsSync(o))throw new Error("You may not install a World on top of a directory that already exists.");return super.install(e,t,s,a,i)}static launc