| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- import type { AnimationDef, Engine, IntentSystem, MapDef, ParticleDef, ShaderDef, ShopDef, SoundDef, SpriteDef, TimeSystem } from "@nengine/core";
- import type { RenderSnapshot, ViewportHandle } from "../viewport.js";
- import type { SoundPlayer } from "../sound.js";
- import { arrowDirection } from "../keys.js";
- export interface LocalSyncHandle {
- setTimeLabel(fn: (label: string) => void): void;
- refresh(): void;
- intent(action: string, args: Record<string, unknown>): void;
- input(input: string): void;
- destroy(): void;
- }
- export interface LocalSyncOptions {
- sound?: SoundPlayer;
- }
- export function connectLocal(engine: Engine, viewport: ViewportHandle, opts?: LocalSyncOptions): LocalSyncHandle {
- const time = engine.systems.get<TimeSystem>("time");
- const sound = opts?.sound;
- let label: ((label: string) => void) | undefined;
- function refresh(): void {
- const map = engine.registry.list<MapDef>("map")[0];
- if (map) {
- const snapshot: RenderSnapshot = {
- map,
- world: engine.world.snapshot(),
- sprites: engine.registry.list<SpriteDef>("sprite"),
- sounds: engine.registry.list<SoundDef>("sound"),
- particles: engine.registry.list<ParticleDef>("particle"),
- shaders: engine.registry.list<ShaderDef>("shader"),
- shops: engine.registry.list<ShopDef>("shop"),
- animations: engine.registry.list<AnimationDef>("animation"),
- assets: Object.fromEntries(engine.assets),
- };
- sound?.setCatalog(snapshot.sounds ?? []);
- sound?.setAssets(snapshot.assets ?? {});
- viewport.render(snapshot);
- } else {
- viewport.render();
- }
- const state = time?.get();
- if (state && label) {
- label(`Day ${state.day}, ${state.season}`);
- }
- }
- refresh();
- const unsubscribeSound = engine.events.on("sound-play", (payload) => {
- sound?.onEvent({ event: "sound-play", payload });
- });
- const unsubscribeBgmPlay = engine.events.on("bgm-play", (payload) => {
- sound?.onEvent({ event: "bgm-play", payload });
- });
- const unsubscribeBgmStop = engine.events.on("bgm-stop", (payload) => {
- sound?.onEvent({ event: "bgm-stop", payload });
- });
- const unsubscribeParticle = engine.events.on("particle", (payload) => {
- viewport.onEvent({ event: "particle", payload });
- });
- return {
- setTimeLabel(fn: (label: string) => void): void {
- label = fn;
- refresh();
- },
- refresh,
- intent(action: string, args: Record<string, unknown>): void {
- engine.systems.get<IntentSystem>("intent")?.handle(action, args);
- refresh();
- },
- input(input: string): void {
- const direction = arrowDirection(input);
- if (!direction) return;
- const player = engine.world.get("player");
- if (!player) return;
- const x = (typeof player.x === "number" ? player.x : 0) + direction.dx;
- const y = (typeof player.y === "number" ? player.y : 0) + direction.dy;
- engine.systems.get<IntentSystem>("intent")?.handle("move", { tile: { x, y } });
- refresh();
- },
- destroy(): void {
- unsubscribeSound();
- unsubscribeBgmPlay();
- unsubscribeBgmStop();
- unsubscribeParticle();
- label = undefined;
- },
- };
- }
|