import { toJS } from "mobx"; import type { Game, Scene, ScriptAction, ScriptCoroutineContext, World } from "../types"; import { clone } from "../utils"; import { ScriptGameEventBus } from "../scripts/eventBus"; import * as ScriptActions from "../scripts/actions"; import { positionOfObject } from "../scripts/positionOfObject"; import { debugLabelsStore } from "../state/debugLabelsState"; import type { ScriptCoroutines } from "../scripts/coroutines"; // // eslint-disable-next-line @typescript-eslint/no-explicit-any // type ScriptActionHelperFunction ScriptAction> = // (...args: ConstructorParameters) => InstanceType; // // eslint-disable-next-line @typescript-eslint/no-explicit-any // const scriptActionHelperFunction = ScriptAction>(Cls: T): ScriptActionHelperFunction => // (...args) => new Cls(...args) as InstanceType; export class GameFactory { public static create(world: World): Game { const scene = clone(world.initialScene); const game = { paused: false, time: 0, scene, }; return game; } public static load(): Game | undefined { const json = localStorage.getItem("game"); if (json) { return JSON.parse(json) as Game; } } public static save(game: Game): void { localStorage.setItem("game", JSON.stringify(game)); } public static evalGameScripts( world: World, scene: Scene, coroutines: ScriptCoroutines, ): ScriptGameEventBus { const eventBus = new ScriptGameEventBus(coroutines); const scriptHelpers = { positionOfObject, // convert all ScriptActions imported to a structure factory(coroutine): // { // WaitSeconds: (seconds) => new WaitSecondsScriptAction(coroutine, seconds), // ... // } actions: (context: ScriptCoroutineContext) => Object.fromEntries( Object.entries(ScriptActions) .map(([name, Cls]) => [ name.replace(/ScriptAction$/, ''), // eslint-disable-next-line @typescript-eslint/no-explicit-any (...args: any[]) => new (Cls as any)(context, ...args), ]) // eslint-disable-next-line @typescript-eslint/no-explicit-any ) as Record ScriptAction>, }; Object.values(world.objectTypes) .filter((ot) => ot.javascript) .forEach((ot) => { try { const javascript = `(function gameScript(eventBus, helpers, thisObject, thisObjectType) {${ot.javascript}})\n//# sourceURL=GameScript:${ot.name}.js`; const gameScript = eval(javascript); Object.values(scene.objects) .filter((o) => o.typeId == ot.id) .map((liveObj) => { const snapshot = toJS(liveObj); snapshot.rb = () => liveObj.rb(); return snapshot; }) .forEach((o) => { try { const localScriptHelpers = { ...scriptHelpers, actions: scriptHelpers.actions({ thisObject: o, thisObjectType: ot }), debug: { show: (key: string, text: string) => debugLabelsStore.setOne(o.id, key, text), clear: (key: string) => debugLabelsStore.deleteOne(o.id, key), }, }; gameScript(eventBus, localScriptHelpers, o, ot); } catch (err) { console.error(`[GameScript:${ot.name}] Error running script for object ${o.id}:`, err); } }); } catch (err) { console.error(`[GameScript:${ot.name}] Error evaluating script:`, err); } }); return eventBus; } }