import { type World, type EntityId, type Actor, type Vec2 } from "../core/types"; import { idx } from "./world/world-logic"; export class EntityManager { private grid: Map = new Map(); private actors: Map; private world: World; private lastId: number = 0; constructor(world: World) { this.world = world; this.actors = world.actors; this.lastId = Math.max(0, ...this.actors.keys()); this.rebuildGrid(); } rebuildGrid() { this.grid.clear(); for (const actor of this.actors.values()) { this.addToGrid(actor); } } private addToGrid(actor: Actor) { const i = idx(this.world, actor.pos.x, actor.pos.y); if (!this.grid.has(i)) { this.grid.set(i, []); } this.grid.get(i)!.push(actor.id); } private removeFromGrid(actor: Actor) { const i = idx(this.world, actor.pos.x, actor.pos.y); const ids = this.grid.get(i); if (ids) { const index = ids.indexOf(actor.id); if (index !== -1) { ids.splice(index, 1); } if (ids.length === 0) { this.grid.delete(i); } } } moveActor(actorId: EntityId, from: Vec2, to: Vec2) { const actor = this.actors.get(actorId); if (!actor) return; // Remove from old position const oldIdx = idx(this.world, from.x, from.y); const ids = this.grid.get(oldIdx); if (ids) { const index = ids.indexOf(actorId); if (index !== -1) ids.splice(index, 1); if (ids.length === 0) this.grid.delete(oldIdx); } // Update position actor.pos.x = to.x; actor.pos.y = to.y; // Add to new position const newIdx = idx(this.world, to.x, to.y); if (!this.grid.has(newIdx)) this.grid.set(newIdx, []); this.grid.get(newIdx)!.push(actorId); } addActor(actor: Actor) { this.actors.set(actor.id, actor); this.addToGrid(actor); } removeActor(actorId: EntityId) { const actor = this.actors.get(actorId); if (actor) { this.removeFromGrid(actor); this.actors.delete(actorId); } } getActorsAt(x: number, y: number): Actor[] { const i = idx(this.world, x, y); const ids = this.grid.get(i); if (!ids) return []; return ids.map(id => this.actors.get(id)!).filter(Boolean); } isOccupied(x: number, y: number, ignoreType?: string): boolean { const actors = this.getActorsAt(x, y); if (ignoreType) { return actors.some(a => a.type !== ignoreType); } return actors.length > 0; } getNextId(): EntityId { this.lastId++; return this.lastId; } }