refactor: remove legacy types.ts file and update frontend to use new contracts feat: add applyActions function to manage action application and world state mutation chore: remove empty .gitkeep file from sqlite data directory refactor: update frontend App component to align with new API contracts and improve UX docs: revise project.md to reflect updated architecture and system requirements docs: update thoughts.md with current status, architecture decisions, and remaining checks
74 lines
1.7 KiB
TypeScript
74 lines
1.7 KiB
TypeScript
import { randomUUID } from "node:crypto";
|
|
|
|
import type { Action } from "../contracts/action";
|
|
import type { ValidationResult } from "../contracts/validation";
|
|
import type { Entity } from "../contracts/entity";
|
|
import type { WorldState } from "../contracts/world";
|
|
|
|
function cloneWorldState(worldState: WorldState): WorldState {
|
|
const entities: Record<string, Entity> = {};
|
|
for (const [id, entity] of Object.entries(worldState.entities)) {
|
|
entities[id] = {
|
|
...entity,
|
|
attributes: { ...entity.attributes },
|
|
};
|
|
}
|
|
|
|
return {
|
|
...worldState,
|
|
entities,
|
|
metadata: { ...worldState.metadata },
|
|
};
|
|
}
|
|
|
|
export function applyActions(
|
|
actions: Action[],
|
|
results: ValidationResult[],
|
|
worldState: WorldState
|
|
): WorldState {
|
|
const nextState = cloneWorldState(worldState);
|
|
|
|
for (const result of results) {
|
|
if (!result.success) {
|
|
continue;
|
|
}
|
|
|
|
const action = actions[result.actionIndex];
|
|
if (!action) {
|
|
continue;
|
|
}
|
|
|
|
const actor = nextState.entities[action.actorId];
|
|
const target = action.targetId ? nextState.entities[action.targetId] : undefined;
|
|
|
|
switch (action.type) {
|
|
case "move":
|
|
if (actor && action.targetId) {
|
|
actor.attributes.location = action.targetId;
|
|
}
|
|
break;
|
|
case "take":
|
|
if (actor && target) {
|
|
target.attributes.location = `inventory:${actor.id}`;
|
|
if (target.id === "key_1") {
|
|
actor.attributes.has_key_1 = true;
|
|
}
|
|
}
|
|
break;
|
|
case "open":
|
|
if (target) {
|
|
target.attributes.open = true;
|
|
}
|
|
break;
|
|
case "inspect":
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
nextState.id = randomUUID();
|
|
nextState.createdAt = Date.now();
|
|
|
|
return nextState;
|
|
}
|