import { Engine, type Effect } from "../core.ts"; import type { PetCommand, PetState } from "../types.ts"; import { save } from "./storage.ts"; import { emit, store, toast } from "./store.ts"; import { errorMessage } from "./utils.ts"; // The browser's copy of the pet lives in the shared Rust engine (core/), the // same one the host runs. `store.state` is a read-only snapshot for rendering. // In remote mode the engine only holds the server's latest checkpoint. let engine: Engine | null = null; export function petEngine(): Engine { if (!engine) throw new Error("The pet has not loaded yet."); return engine; } /** `seed` is the deployment's weather seed, shared with its host. */ export function startEngine(state: PetState, seed: string) { engine?.raw.free(); engine = new Engine(state, Date.now(), seed); store.state = engine.state(); } let onChange: ((effects: Effect[]) => void) | null = null; /** Runs after every change with its new effects (lifecycle.ts plays them). */ export function afterChanges(hook: (effects: Effect[]) => void) { onChange = hook; } /** Refreshes the snapshot (only the body fields when `full` is false), hands on new effects and saves. */ export function changed(full = true) { const e = petEngine(); store.state = full ? e.state() : { ...store.state, ...e.body() }; const effects = e.takeEffects(); onChange?.(effects); save(); emit(); } /** Replaces the save: an import, a transfer or a server snapshot. */ export function setState(state: PetState, keepTurns = false) { const e = petEngine(); if (keepTurns) e.edit(state); else e.replace(state, Date.now()); changed(); } /** Debug and test edits of the save, keeping the turn queue. */ export function editState(edit: (state: PetState) => void) { const state = petEngine().state(); edit(state); setState(state, true); } /** Runs an owner command locally. Refusals become a toast. */ export function localCommand(command: PetCommand) { try { petEngine().command(command, Date.now()); return true; } catch (error) { toast(errorMessage(error)); return false; } finally { changed(); } }