import { TransformNode } from '@babylonjs/core'; import { GameEntityBehaviorConstructor } from "../interfaces/entity.d.ts"; import { Destroyable } from "../interfaces/lifecycle.d.ts"; import { ColliderDebugConfig } from "../managers/colliderDebug.d.ts"; import { GameEvent, GameEventBus } from "./eventBus.d.ts"; import { GameEngine } from "./gameEngine.d.ts"; /** * Result of a request sent to an entity's behaviors. * `success: true` means a behavior handled the request and returned a value. * `success: false` means no behavior handled it, or a behavior threw an error. */ export type RequestResult = { success: true; value: T; } | { success: false; error: string; }; /** * Narrow interface for entity-to-manager messaging delegation. * Avoids a circular import between entity.ts and managers/entity.ts. */ interface EntityMessenger { send(target: string, type: string, payload?: unknown, senderID?: string): Promise; request(target: string, type: string, payload?: unknown, senderID?: string): Promise>; } /** * Options for attaching a behavior at a specific position. * Only one positioning option should be specified. */ export interface AttachBehaviorOptions { /** Insert before behavior of this class */ before?: GameEntityBehaviorConstructor; /** Insert after behavior of this class */ after?: GameEntityBehaviorConstructor; /** Insert at specific index (0-based, clamped to valid range) */ at?: number; } /** * Minimal entity surface exposed to behaviors, preventing them from accessing internals like * subscription management or behavior ordering. */ interface SimpleGameEntity { id: string; type: string; name?: string; node?: TransformNode; state: EntityState; eventBus: GameEventBus; tags: ReadonlySet; send(target: string, type: string, payload?: unknown): Promise; request(target: string, type: string, payload?: unknown): Promise>; } /** * Base class for game entity behaviors. Subclass this to define how an entity reacts to events * and updates each frame. Multiple behaviors can be attached to a single entity; event processing * order matches the attachment order. */ export declare abstract class GameEntityBehavior { abstract name: string; abstract eventSubscriptions: string[]; protected entity: SimpleGameEntity | null; $emit(event: GameEvent): void; /** * Emits an entity:state-changed event to notify UI or other observers of state changes. * Call this after making significant state changes that external systems should know about. * * @param state - Optional state to include in the event. If omitted, uses current entity state. * @param changes - Optional record of specific changes made (alternative to full state). */ $emitStateChanged(state?: object, changes?: Record): void; /** * Sets the entity for this behavior. * @param entity */ $setEntity(entity: SimpleGameEntity | null): void; abstract processEvent(event: GameEvent, state: RequiredState): Promise | boolean; /** * Handles a direct request sent to this entity. Return a value to respond, * or `undefined` to pass the request to the next behavior. * * @param event - The request event (type, payload, senderID, targetID) * @param state - Current entity state */ processRequest?(event: GameEvent, state: RequiredState): Promise | unknown | undefined; update?(dt: number, state: RequiredState): void; destroy?(): Promise; /** * Called when the entity is attached to a scene node. * Override to perform initialization that requires the node (physics, spatial audio, etc.) * * The scene is accessible via `node.getScene()`. * * @param node - The TransformNode (typically a Mesh) the entity is attached to. * @param gameEngine - The game engine instance for accessing managers and engines. */ onNodeAttached?(node: TransformNode, gameEngine: GameEngine): void; /** * Called when the entity is detached from its scene node. * Override to clean up node-dependent resources. */ onNodeDetached?(): void; /** * Called when the entity is recycled from an object pool. * Override to reset behavior-specific state that isn't covered by entity state reset. * Distinct from onNodeDetached — this signals a full lifecycle reset. * * @param state - The freshly reset entity state. */ onReset?(state: RequiredState): void; } /** * Base class for game entities. Owns a set of behaviors, manages event subscriptions * (reference-counted per event type), and delegates lifecycle calls to its behaviors. */ export declare class GameEntity implements SimpleGameEntity, Destroyable { /** The unique identifier of the entity (16-char hex string). */ readonly id: string; readonly type: string; /** Optional human-readable name for the entity. */ readonly name?: string; /** * The scene node this entity is attached to (if any). * When attached, the entity controls this node's behavior. * Use EntityManager.attachToNode() / detachFromNode() to modify. */ readonly node?: TransformNode; /** Child entities in the hierarchy. */ readonly children: GameEntity[]; /** Parent entity in the hierarchy, or null if this is a root entity. */ readonly parent: GameEntity | null; state: EntityState; /** Array of behaviors attached to the entity. Order determines event processing priority. */ behaviors: GameEntityBehavior[]; eventBus: GameEventBus; private _gameEngine; private _entityManager; private _tags; private subscriptions; /** * Creates an instance of GameEntity. * @param type * @param eventBus * @param initialState * @param behaviors - Attached in order; order determines event processing priority. * @param name */ constructor(type: string, eventBus: GameEventBus, initialState: EntityState, behaviors: GameEntityBehaviorConstructor[], name?: string); /** * Read-only access to the entity's tags. */ get tags(): ReadonlySet; /** * Checks if the entity has a specific tag. * @param tag */ hasTag(tag: string): boolean; /** * Internal method for EntityManager to add a tag. * @param tag */ $addTag(tag: string): void; /** * Internal method for EntityManager to remove a tag. * @param tag */ $removeTag(tag: string): boolean; /** * Find a direct child node by name. * @param name */ getChildNode(name: string): TransformNode | undefined; /** * Find a descendant node by path (e.g., "armature/hand/finger"). * @param path - Slash-separated path of node names. */ findNode(path: string): TransformNode | undefined; /** * Internal method for EntityManager to attach entity to a node. * Do not call directly - use EntityManager.attachToNode() instead. * @param node * @param gameEngine * @internal */ $attachToNode(node: TransformNode, gameEngine: GameEngine): void; /** * Internal method for EntityManager to detach entity from its node. * Do not call directly - use EntityManager.detachFromNode() instead. * @internal */ $detachFromNode(): void; /** * Add this entity to a named outline layer for visual highlighting. * Requires the entity to be attached to a node in a level with outlines configured. * * @param layerName - The name of the outline layer (must exist on the current level) */ highlight(layerName: string): void; /** * Remove this entity from an outline layer, or from all layers if no name given. * * @param layerName - Specific layer to remove from, or omit to remove from all */ unhighlight(layerName?: string): void; /** * Shows collider debug visualization for this entity's physics nodes. * * Overloads: * - `showCollider()` — show all colliders, default color * - `showCollider(true)` — show all colliders, default color (config-driven) * - `showCollider('#ff0000')` — show all colliders with a specific color * - `showCollider('head')` — show a specific collider by node name * - `showCollider('head', '#ff0000')` — show a specific collider by name with color * - `showCollider({ head: '#ff0000', body: false })` — per-collider control */ showCollider(configOrNameOrColor?: ColliderDebugConfig, color?: string): void; /** * Hides collider debug visualization for this entity's physics nodes. * * - `hideCollider()` — hide all colliders * - `hideCollider('head')` — hide a specific collider by node name */ hideCollider(name?: string): void; private _getPhysicsNodes; /** * Adds a child entity to this entity's hierarchy. * Sets the child's parent to this entity. If both entities have nodes, parents the child's node. * @param child */ $addChild(child: GameEntity): void; /** * Removes a child entity from this entity's hierarchy. * Clears the child's parent reference. If the child has a node, detaches it. * @param child */ $removeChild(child: GameEntity): void; /** * Sets the entity manager reference for cross-entity messaging. * Called by the EntityManager after entity creation. * @param manager * @internal */ $setEntityManager(manager: EntityMessenger): void; /** * Sends a fire-and-forget event directly to a specific entity's behaviors, bypassing the event bus. * If the target matches this entity's own ID, dispatches locally. * * @param target - Entity ID or name * @param type - Event type string * @param payload - Optional event payload */ send(target: string, type: string, payload?: unknown): Promise; /** * Sends a request to a specific entity's behaviors and returns the first response. * If the target matches this entity's own ID, dispatches locally. * * @param target - Entity ID or name * @param type - Request type string * @param payload - Optional request payload */ request(target: string, type: string, payload?: unknown): Promise>; /** * Sends a fire-and-forget event directly to this entity's own behaviors. * * @param type - Event type string * @param payload - Optional event payload * @internal */ $send(type: string, payload?: unknown, senderID?: string): Promise; /** * Sends a request to this entity's own behaviors and returns the first response. * * @param type - Request type string * @param payload - Optional request payload * @internal */ $request(type: string, payload?: unknown, senderID?: string): Promise>; /** * Resets the entity for object pool recycling. * Restores state and tags to defaults, detaches from node, notifies behaviors, and resets children. * @param defaultState - Default state from the entity definition * @param defaultTags - Default tags from the entity definition */ $reset(defaultState: object, defaultTags: string[]): void; /** * Processes a game event by passing it to the entity's behaviors. * @param event */ $processEvent(event: GameEvent): Promise; /** * Updates the entity by calling the update method of its behaviors. * @param dt - Seconds elapsed since the last update. */ $update(dt: number): void; /** * Destroys the entity by calling the destroy method of its behaviors and unsubscribing from all events. */ $destroy(): Promise; /** * Finds the index of a behavior by its constructor. * @param behaviorClass */ private findBehaviorIndex; /** * Checks if a behavior of the given class is attached. * @param behaviorClass */ hasBehavior(behaviorClass: GameEntityBehaviorConstructor): boolean; /** * Gets a behavior by its constructor. * @param behaviorClass */ getBehavior(behaviorClass: new () => T): T | undefined; /** * Attaches a behavior to the entity. * Without options, appends to the end (most common case). * With options, inserts at the specified position. * * @param behavior * @param options * @throws If the behavior is already attached. * @throws If 'before' or 'after' target is not found. * @throws If more than one positioning option is specified. */ attachBehavior(behavior: GameEntityBehavior, options?: AttachBehaviorOptions): void; /** * Detaches a behavior from the entity by its constructor. * @param behaviorClass */ detachBehavior(behaviorClass: GameEntityBehaviorConstructor): boolean; } export {};