/** * Spawner Module - Core Implementation * * Implements phases 1-5 of the improvement plan: * - Phase 1: Standard { type, params } structure, Module base class alignment * - Phase 2: Extension system with registerType, registerPlacement, etc. * - Phase 3: Cluster spawner, path spawner, Poisson distribution, post-spawn hooks * - Phase 4: Syntax polish (spawnerDefaults, 2D paths, heightOffset, excludeSpawner) * - Phase 5: Wave spawner with runtime control and serialization */ import { ECSContext } from "../../core/ecs"; import { Module } from "../Module"; export * from './types'; import { Position, Bounds, SpawnerResult, BaseSpawnerParams, WaveState, SpawnerDefinition, SpawnerExecutor, PostSpawnHookExecutor, SpawnerDefaults } from './types'; import { PlacementModule } from './placement'; import { SelectionModule } from './selection'; import { TerrainSettings, ConstraintsModule } from './constraints'; export { PlacementModule, SelectionModule, ConstraintsModule }; /** Register a composite spawner executor */ export declare function registerSpawnerType(type: string, executor: SpawnerExecutor): void; /** Get a spawner executor by type */ export declare function getSpawnerExecutor(type: string): SpawnerExecutor | undefined; /** Get all registered spawner types */ export declare function getSpawnerTypes(): string[]; /** Register a custom post-spawn hook */ export declare function registerPostSpawnHook(type: string, executor: PostSpawnHookExecutor): void; /** Get a post-spawn hook executor by type */ export declare function getPostSpawnHook(type: string): PostSpawnHookExecutor | undefined; interface SpawnerState { definition: SpawnerDefinition; result?: SpawnerResult; isExecuted: boolean; waveState?: WaveState; loopTriggerName?: string; } export interface SpawnerModuleDefinition { type: string; params: any; } /** * Saved state for spawner restoration during save/load * Includes isExecuted for all spawners and waveState for wave spawners */ export interface SavedSpawnerState { /** Whether the spawner has been executed (prevents re-execution on load) */ isExecuted?: boolean; /** Wave-specific state (for composite schedule spawners) */ waveState?: WaveState; } /** * SpawnerModule - Manages declarative entity spawning * * Extends Module base class for compatibility with the module system, * but uses its own internal state management for spawner-specific behavior. * * Phases 4-5 additions: * - spawnerDefaults support for default heightField, heightOffset, transform * - Wave spawner runtime control (pause/resume/reset/trigger) * - excludeSpawner constraint support via result reference getter * - Dimension-level terrain settings for proper height field coordinate normalization * * Phase 6.1 additions: * - Integration with trigger module for wave spawner timing * - Trigger support in composite spawners for advanced composition */ /** * SpawnerModule - Manages declarative entity spawning * * FOLLOWS MODULE PATTERN WITH JUSTIFIED DIVERGENCES: * * Core Principles Followed: * 1. ✅ Extends Module * 2. ✅ Uses {type, params} structure via SpawnerDefinition * 3. ✅ Uses registerType() for spawner type factories * 4. ✅ Calls addDefinition() for all registrations * 5. ✅ Marks built-in spawner types as built-in * * Justified Divergences: * 1. Custom state management (spawnerStates Map): * - Tracks execution state (isExecuted, waveState, SpawnerResult) * - Spawners are executable entities, not just resolvable definitions * 2. Runtime control API (execute, getResult, pauseWave, etc.): * - Spawners need runtime operations beyond resolution * 3. Defaults system integration: * - setDefaults() applies to all spawners * - Integrates with dimension terrain configuration * 4. Override register() for spawner-specific initialization: * - Applies defaults, sets up triggers, handles immediate execution */ export declare class SpawnerModule extends Module { private spawnerStates; private _defaults; private _terrainSettings; private _triggerModule; private _placementModule; private _selectionModule; private _constraintsModule; constructor(ctx: ECSContext); /** * Execute a spawner by type using the global executor registry * This bridges between Module pattern (factories) and spawner pattern (executors) */ private executeSpawnerType; /** * Get or create the trigger module * Lazy initialization to avoid circular dependencies */ private getTriggerModule; /** * Get placement module */ private getPlacementModule; /** * Get selection module */ private getSelectionModule; /** * Get constraints module */ private getConstraintsModule; /** * Check if position passes all constraints (helper method) */ private passesConstraints; /** * Set defaults that apply to all spawners (Phase 4) * These can be overridden per-spawner */ setDefaults(defaults: SpawnerDefaults): void; /** * Get current spawner defaults */ getDefaults(): SpawnerDefaults; /** * Get terrain settings from dimension configuration */ getTerrainSettings(): TerrainSettings | undefined; /** * Refresh terrain settings from dimension configuration * Call this after dimension metadata is updated */ refreshTerrainSettings(): void; /** * Apply defaults to spawner params * Priority: spawner-specific > spawnerDefaults > dimension terrain */ private applyDefaults; /** * Get the terrain size for height field coordinate normalization * Returns dimension terrain size, or derives from bounds as fallback */ getTerrainSize(bounds?: Bounds): number; /** * Register a canonical composite spawner definition */ registerSpawner(def: SpawnerDefinition, savedState?: SavedSpawnerState): void; /** * Override register to support spawner-specific types * Enforces canonical { type, params } schema for spawner definitions */ register(name: string, defOrBase: SpawnerModuleDefinition | string, overrides?: Partial): SpawnerState; /** * Execute a spawner by name */ execute(name: string): SpawnerResult; /** * Execute all registered spawners that haven't been executed yet */ executeAll(): void; /** * Get the result of a spawner execution */ getResult(name: string): SpawnerResult | undefined; /** * Check if a spawner has been executed */ isExecuted(name: string): boolean; /** * Get all registered spawner names */ getSpawnerNames(): string[]; /** * Get a spawner definition by name */ getSpawnerDefinition(name: string): SpawnerDefinition | undefined; /** * Override getRuntimeDefinitions to include spawner state for serialization * This enables proper save/load of spawner progress including: * - isExecuted: Prevents one-shot spawners from re-executing on load * - waveState: Preserves wave spawner timing and progress */ getRuntimeDefinitions(): Array<{ name: string; definition: SpawnerModuleDefinition; isExecuted?: boolean; waveState?: WaveState; }>; /** * Serialize spawner state for save/load * Includes wave state for wave spawners */ serializeState(): Record; /** * Clear all spawner state */ clear(): void; /** * Check all spawners with triggers and execute those whose triggers have fired * Should be called each frame after trigger.update() but before trigger.resetFiredFlags() * * This implements the ECS pattern: spawners poll trigger state instead of using callbacks */ checkTriggersAndExecute(): void; /** * Pause a wave spawner */ pauseWave(name: string): void; /** * Resume a wave spawner */ resumeWave(name: string): void; /** * Reset a wave spawner to initial state */ resetWave(name: string): void; /** * Manually trigger the next wave */ triggerNextWave(name: string): SpawnerResult | undefined; /** * Setup trigger for a composite spawner (Phase 6.1) * Creates a trigger that executes the composite spawner when fired * * @param spawnerName Name of the composite spawner * @param params Composite spawner parameters */ /** * Setup trigger for a composite spawner * The trigger's hasFired state will be checked by checkTriggersAndExecute() */ private setupCompositeSpawnerTrigger; /** * Setup triggers for a wave spawner (Phase 6.1) * Creates time-based triggers for each wave * * Note: delay=0 waves are handled by the wave spawner executor (executeWave) * which runs during initial spawner execution. This method only sets up triggers * for delayed waves (delay > 0). * * @param spawnerName Name of the wave spawner * @param params Wave spawner parameters * @param alreadyElapsedTime Time already elapsed (for save/load restoration) */ /** * Setup triggers for a wave spawner (Phase 6.1) * Creates time-based triggers for each wave * checkTriggersAndExecute() will poll hasFired and call triggerNextWave() * * Note: delay=0 waves are handled by the wave spawner executor (executeWave) * which runs during initial spawner execution. This method only sets up triggers * for delayed waves (delay > 0). * * @param spawnerName Name of the wave spawner * @param params Wave spawner parameters * @param alreadyElapsedTime Time already elapsed (for save/load restoration) */ private setupWaveTriggersForSpawner; /** * Execute a specific wave at an index * Used by trigger callbacks * * @param spawnerName Name of the wave spawner * @param waveIndex Index of the wave to execute */ private executeWaveAtIndex; /** * Update trigger timing and execute triggered spawners * Call this every frame with deltaTime in seconds * * This method follows the ECS pattern: * 1. Reset hasFired flags from previous frame * 2. Update trigger timing (sets hasFired for triggers that should fire) * 3. Check and execute spawners whose triggers fired */ update(deltaTime: number): void; /** * Get the wave state for a spawner */ getWaveState(name: string): WaveState | undefined; /** * Get the current population count for a spawner (number of spawned entities) */ getPopulation(name: string): number; /** * Register a composite spawner type executor * Note: Named registerSpawnerExecutor instead of registerType to avoid * conflict with Module base class. The spawner module's extension API * is intentionally different since it registers executors (functions) * rather than factories (constructors). */ registerSpawnerExecutor(type: string, executor: SpawnerExecutor): void; /** * Register a custom placement primitive */ registerPlacementPrimitive(type: string, generator: (params: T, ctx?: ECSContext) => Position[]): void; /** * Register a custom selection strategy */ registerSelectionStrategy(type: string, selector: (params: T, index: number, position: Position, ctx?: ECSContext) => string): void; /** * Register a custom constraint checker */ registerConstraintChecker(type: string, checker: (params: T, position: Position, ctx: ECSContext, heightField?: string) => boolean): void; /** * Register a custom post-spawn hook */ registerHook(type: string, executor: (params: T, entityId: number, position: Position, ctx: ECSContext) => void): void; /** * Get available extension types */ getAvailableTypes(): { spawners: string[]; placements: string[]; selections: string[]; constraints: string[]; }; } export declare const spawnerModule: (ctx: ECSContext) => SpawnerModule; //# sourceMappingURL=index.d.ts.map