workspaces folders
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
import type { Game, RuntimeGameScene, RuntimeScene, World } from "../types";
|
||||
import type { GameEventContext, GameEventHandler, GeneratorEventHandler, InternalGameEventBus } from "../types/runtime/gameBus";
|
||||
import { clone } from "../utils";
|
||||
import { populateRuntimeScene } from "../utils/runtime";
|
||||
import { ObjectApi } from "../utils/runtime/objectApi";
|
||||
import type { GameScheduler, YieldCommand } from "./gameScheduler";
|
||||
|
||||
export class GameEventBus {
|
||||
private handlers = new Map<string, GameEventHandler[]>();
|
||||
|
||||
on(event: string, handler: GameEventHandler): void {
|
||||
console.log('subscribing to ' + event, handler);
|
||||
let set = this.handlers.get(event);
|
||||
if (!set) {
|
||||
set = [];
|
||||
this.handlers.set(event, set);
|
||||
}
|
||||
if (!set.includes(handler))
|
||||
set.push(handler);
|
||||
}
|
||||
|
||||
off(event: string, handler: GameEventHandler): void {
|
||||
console.log('unubscribing from ' + event, handler);
|
||||
const handlers = this.handlers.get(event);
|
||||
if (!handlers)
|
||||
return;
|
||||
|
||||
this.handlers.set(event, handlers.filter((h) => h !== handler));
|
||||
}
|
||||
|
||||
emit(event: string, context: GameEventContext): void {
|
||||
console.log('emitting ' + event);
|
||||
this.handlers.get(event)
|
||||
?.forEach((handler) => handler(context));
|
||||
}
|
||||
}
|
||||
|
||||
export class GameFactory {
|
||||
|
||||
public static create(world: World): Game {
|
||||
const scene = populateRuntimeScene(clone(world.initialScene), world);
|
||||
|
||||
const game = {
|
||||
paused: false,
|
||||
time: 0,
|
||||
scene: GameFactory.initGameScene(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));
|
||||
}
|
||||
|
||||
private static initGameScene(scene: RuntimeScene): RuntimeGameScene {
|
||||
return scene as RuntimeGameScene;
|
||||
}
|
||||
|
||||
public static evalGameScripts(
|
||||
world: World,
|
||||
scene: RuntimeGameScene,
|
||||
eventBus: GameEventBus,
|
||||
scheduler: GameScheduler,
|
||||
): void {
|
||||
|
||||
const handlerWrappers = new WeakMap<GeneratorEventHandler, GameEventHandler>();
|
||||
|
||||
const wait = (seconds: number): YieldCommand => ({ type: 'waitSeconds', seconds });
|
||||
const waitFrames = (frames: number): YieldCommand => ({ type: 'waitFrames', frames });
|
||||
const waitUntil = (condition: () => boolean): YieldCommand => ({ type: 'waitUntil', condition });
|
||||
|
||||
const internalBus: InternalGameEventBus = {
|
||||
onGameEvent(event, genFn) {
|
||||
const wrapper: GameEventHandler = (ctx) => scheduler.startCoroutine(genFn(ctx) as Generator<YieldCommand, void, void>);
|
||||
handlerWrappers.set(genFn, wrapper);
|
||||
eventBus.on(event, wrapper);
|
||||
},
|
||||
offGameEvent(event, genFn) {
|
||||
const wrapper = handlerWrappers.get(genFn);
|
||||
if (wrapper) {
|
||||
eventBus.off(event, wrapper);
|
||||
handlerWrappers.delete(genFn);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
try {
|
||||
Object.values(world.objectTypes)
|
||||
.filter((ot) => ot.javascript)
|
||||
.forEach((ot) => {
|
||||
const gameScript = eval(`(function gameScript({onGameEvent, offGameEvent, wait, waitFrames, waitUntil}, {api, object, objectType}) {${ot.javascript}})`);
|
||||
|
||||
Object.values(scene.objects)
|
||||
.filter((o) => o.typeId == ot.id)
|
||||
.forEach((o) => {
|
||||
const api = new ObjectApi(o, ot, world, scene);
|
||||
gameScript({ ...internalBus, wait, waitFrames, waitUntil }, { api, object: o, objectType: ot });
|
||||
});
|
||||
});
|
||||
}
|
||||
catch (err) {
|
||||
console.log('Error running game script:\n' + err);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user