import { Agent, type Connection, type WSMessage } from "agents";
import type { GeneratedEnv } from "@ayjnt/env";
const WORLD = { w: 800, h: 600 };
const TICK_HZ = 30;
type Ship = { id: string; name: string; x: number; y: number; vx: number; vy: number; a: number; thrust: boolean; left: boolean; right: boolean; kills: number; deaths: number; nextShotAt: number; respawnedAt: number; };
type State = { ships: Ship[]; bullets: unknown[]; asteroids: unknown[]; lastTick: number };
export default class SectorAgent extends Agent<GeneratedEnv, State> {
override initialState: State = { ships: [], bullets: [], asteroids: [], lastTick: 0 };
private loopHandle: ReturnType<typeof setInterval> | null = null;
override async onConnect(conn: Connection) {
this.seedAsteroids();
this.setState({ ...this.state, ships: [...this.state.ships, this.spawn(conn.id, "guest")] });
this.ensureLoop();
}
override async onMessage(conn: Connection, message: WSMessage) {
if (typeof message !== "string") return;
const frame = JSON.parse(message);
// handle hello / input / fire — see examples/space-game for full code
}
override async onClose(conn: Connection) {
this.setState({ ...this.state, ships: this.state.ships.filter((s) => s.id !== conn.id) });
if (this.state.ships.length === 0) this.stopLoop();
}
private ensureLoop() {
if (this.loopHandle) return;
this.loopHandle = setInterval(() => this.tick(), 1000 / TICK_HZ);
}
private stopLoop() { if (this.loopHandle) clearInterval(this.loopHandle); this.loopHandle = null; }
private tick() {
// integrate ships, advance bullets, collide, setState(world)
}
private spawn(id: string, name: string): Ship { /* random edge, random heading */ return {} as Ship; }
private seedAsteroids() { /* 12 drifting asteroids if state empty */ }
override async onRequest() { return Response.json({ instance: this.name, ...this.state }); }
}