Skip to main content
Glama
engine.ts6.47 kB
import { GeneratedWorld } from '../worldgen/index.js'; import { PatchCommand, CommandType } from './schema.js'; import { validateStructurePlacement, getSuggestedBiomesForStructure } from '../worldgen/validation.js'; import { StructureType } from '../../schema/structure.js'; export interface PatchResult { success: boolean; commandsExecuted: number; errors: PatchError[]; warnings: PatchWarning[]; } export interface PatchError { command: string; message: string; location?: { x: number; y: number }; } export interface PatchWarning { command: string; message: string; } /** * Options for patch application */ export interface PatchOptions { /** If true, skip invalid commands instead of failing. Default: false */ skipInvalid?: boolean; /** If true, validate but don't apply. Default: false */ dryRun?: boolean; } /** * Applies a list of patch commands to a generated world. * Mutates the world object in place for performance. * * @returns PatchResult with success status and any errors/warnings */ export function applyPatch( world: GeneratedWorld, commands: PatchCommand[], options: PatchOptions = {} ): PatchResult { const { skipInvalid = false, dryRun = false } = options; const result: PatchResult = { success: true, commandsExecuted: 0, errors: [], warnings: [] }; for (const command of commands) { const cmdResult = validateAndApplyCommand(world, command, dryRun); if (cmdResult.error) { result.errors.push(cmdResult.error); if (!skipInvalid) { result.success = false; break; // Stop on first error unless skipInvalid } } else { result.commandsExecuted++; } if (cmdResult.warning) { result.warnings.push(cmdResult.warning); } } return result; } interface CommandResult { error?: PatchError; warning?: PatchWarning; } function validateAndApplyCommand( world: GeneratedWorld, command: PatchCommand, dryRun: boolean ): CommandResult { switch (command.command) { case CommandType.ADD_STRUCTURE: { const { type, x, y, name } = command.args; // Validate structure placement const validation = validateStructurePlacement( type as StructureType, x, y, world ); if (!validation.valid) { const suggestedBiomes = getSuggestedBiomesForStructure(type as StructureType); return { error: { command: `ADD_STRUCTURE ${type} ${x} ${y}`, message: `${validation.reason}. Suggested biomes for ${type}: ${suggestedBiomes.join(', ')}`, location: { x, y } } }; } if (!dryRun) { world.structures.push({ type, location: { x, y }, name, score: 100 // Manual placement gets max score }); } return {}; } case CommandType.SET_BIOME: { const { x, y, type } = command.args; if (!isValidCoordinate(world, x, y)) { return { error: { command: `SET_BIOME ${type} ${x} ${y}`, message: `Coordinates (${x}, ${y}) are out of bounds`, location: { x, y } } }; } if (!dryRun) { world.biomes[y][x] = type; } return {}; } case CommandType.EDIT_TILE: { const { x, y, elevation, moisture, temperature } = command.args; if (!isValidCoordinate(world, x, y)) { return { error: { command: `EDIT_TILE ${x} ${y}`, message: `Coordinates (${x}, ${y}) are out of bounds`, location: { x, y } } }; } if (!dryRun) { const idx = y * world.width + x; if (elevation !== undefined) world.elevation[idx] = elevation; if (moisture !== undefined) world.moisture[idx] = moisture; if (temperature !== undefined) world.temperature[idx] = temperature; } return {}; } case CommandType.MOVE_STRUCTURE: { const { id, x, y } = command.args; const structure = world.structures.find(s => s.name === id); if (!structure) { return { error: { command: `MOVE_STRUCTURE ${id} ${x} ${y}`, message: `Structure not found: ${id}`, location: { x, y } } }; } // Validate new location const validation = validateStructurePlacement( structure.type as StructureType, x, y, world ); if (!validation.valid) { return { error: { command: `MOVE_STRUCTURE ${id} ${x} ${y}`, message: validation.reason!, location: { x, y } } }; } if (!dryRun) { structure.location = { x, y }; } return {}; } case CommandType.ADD_ROAD: case CommandType.ADD_ANNOTATION: return { warning: { command: command.command, message: `Command ${command.command} is not yet implemented` } }; } // This should never be reached due to exhaustive switch // but satisfies TypeScript's control flow analysis return {}; } function isValidCoordinate(world: GeneratedWorld, x: number, y: number): boolean { return x >= 0 && x < world.width && y >= 0 && y < world.height; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Mnehmos/rpg-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server