67 lines
2.3 KiB
TypeScript
67 lines
2.3 KiB
TypeScript
import type { RPGAction, RPGActions, RPGVariables } from "../types";
|
|
import type { EvalContext, Entity } from "../core/world";
|
|
|
|
export function resolveVariables(entity: Entity): RPGVariables {
|
|
const result: RPGVariables = {};
|
|
for (const [key, component] of entity) {
|
|
for (const [varKey, value] of Object.entries(component.getVariables())) {
|
|
if (value != null) {
|
|
if (varKey && varKey !== '.') {
|
|
result[`${key}.${varKey}`] = value;
|
|
} else {
|
|
result[key] = value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
export function resolveVariable(name: string, ctx: EvalContext): RPGVariables[string] {
|
|
// $. prefix → world globals
|
|
if (name.startsWith('$.')) {
|
|
return ctx.world.globals[name.slice(2)];
|
|
}
|
|
// @entityId.component.variable → another entity
|
|
if (name.startsWith('@')) {
|
|
const dotIdx = name.indexOf('.', 1);
|
|
if (dotIdx === -1) return undefined;
|
|
const entityId = name.slice(1, dotIdx);
|
|
const varName = name.slice(dotIdx + 1);
|
|
const entity = ctx.world.getEntity(entityId);
|
|
if (!entity) return undefined;
|
|
return resolveVariables(entity)[varName];
|
|
}
|
|
// bare name → self entity
|
|
return resolveVariables(ctx.self)[name];
|
|
}
|
|
|
|
export function resolveActions(entity: Entity): RPGActions {
|
|
const result: RPGActions = {};
|
|
for (const [key, component] of entity) {
|
|
for (const [actionKey, fn] of Object.entries(component.getActions())) {
|
|
result[`${key}.${actionKey}`] = fn;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
export async function executeAction(action: RPGAction, ctx: EvalContext): Promise<unknown> {
|
|
let entity = ctx.self;
|
|
let actionType = action.type;
|
|
|
|
// @entityId.component.action → dispatch to another entity
|
|
if (action.type.startsWith('@')) {
|
|
const dotIdx = action.type.indexOf('.', 1);
|
|
if (dotIdx === -1) return;
|
|
const entityId = action.type.slice(1, dotIdx);
|
|
const found = ctx.world.getEntity(entityId);
|
|
if (!found) return;
|
|
entity = found;
|
|
actionType = action.type.slice(dotIdx + 1);
|
|
}
|
|
|
|
const actions = resolveActions(entity);
|
|
return actions[actionType]?.(action.arg);
|
|
}
|