107 lines
4.3 KiB
TypeScript
107 lines
4.3 KiB
TypeScript
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<T extends abstract new (...args: any[]) => ScriptAction> =
|
|
// (...args: ConstructorParameters<T>) => InstanceType<T>;
|
|
|
|
// // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
// const scriptActionHelperFunction = <T extends new (...args: any[]) => ScriptAction>(Cls: T): ScriptActionHelperFunction<T> =>
|
|
// (...args) => new Cls(...args) as InstanceType<T>;
|
|
|
|
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<string, (...args: any[]) => 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;
|
|
}
|
|
}
|