@alife-sdk/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +283 -0
- package/dist/ai/DangerManager.d.ts +71 -0
- package/dist/ai/DangerManager.d.ts.map +1 -0
- package/dist/ai/DangerManager.js +176 -0
- package/dist/ai/DangerManager.js.map +1 -0
- package/dist/ai/GOAPAction.d.ts +45 -0
- package/dist/ai/GOAPAction.d.ts.map +1 -0
- package/dist/ai/GOAPAction.js +32 -0
- package/dist/ai/GOAPAction.js.map +1 -0
- package/dist/ai/GOAPPlanner.d.ts +80 -0
- package/dist/ai/GOAPPlanner.d.ts.map +1 -0
- package/dist/ai/GOAPPlanner.js +259 -0
- package/dist/ai/GOAPPlanner.js.map +1 -0
- package/dist/ai/IStateHandler.d.ts +8 -0
- package/dist/ai/IStateHandler.d.ts.map +1 -0
- package/dist/ai/IStateHandler.js +8 -0
- package/dist/ai/IStateHandler.js.map +1 -0
- package/dist/ai/MemorySystem.d.ts +94 -0
- package/dist/ai/MemorySystem.d.ts.map +1 -0
- package/dist/ai/MemorySystem.js +207 -0
- package/dist/ai/MemorySystem.js.map +1 -0
- package/dist/ai/StateMachine.d.ts +49 -0
- package/dist/ai/StateMachine.d.ts.map +1 -0
- package/dist/ai/StateMachine.js +83 -0
- package/dist/ai/StateMachine.js.map +1 -0
- package/dist/ai/WorldState.d.ts +48 -0
- package/dist/ai/WorldState.d.ts.map +1 -0
- package/dist/ai/WorldState.js +93 -0
- package/dist/ai/WorldState.js.map +1 -0
- package/dist/ai/index.d.ts +10 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +8 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/combat/DamageInstance.d.ts +26 -0
- package/dist/combat/DamageInstance.d.ts.map +1 -0
- package/dist/combat/DamageInstance.js +25 -0
- package/dist/combat/DamageInstance.js.map +1 -0
- package/dist/combat/MoraleStateMachine.d.ts +53 -0
- package/dist/combat/MoraleStateMachine.d.ts.map +1 -0
- package/dist/combat/MoraleStateMachine.js +84 -0
- package/dist/combat/MoraleStateMachine.js.map +1 -0
- package/dist/combat/index.d.ts +5 -0
- package/dist/combat/index.d.ts.map +1 -0
- package/dist/combat/index.js +3 -0
- package/dist/combat/index.js.map +1 -0
- package/dist/config/ALifeConfig.d.ts +131 -0
- package/dist/config/ALifeConfig.d.ts.map +1 -0
- package/dist/config/ALifeConfig.js +82 -0
- package/dist/config/ALifeConfig.js.map +1 -0
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +2 -0
- package/dist/config/index.js.map +1 -0
- package/dist/core/ALifeKernel.d.ts +163 -0
- package/dist/core/ALifeKernel.d.ts.map +1 -0
- package/dist/core/ALifeKernel.js +542 -0
- package/dist/core/ALifeKernel.js.map +1 -0
- package/dist/core/Clock.d.ts +123 -0
- package/dist/core/Clock.d.ts.map +1 -0
- package/dist/core/Clock.js +228 -0
- package/dist/core/Clock.js.map +1 -0
- package/dist/core/DevToolsInspector.d.ts +53 -0
- package/dist/core/DevToolsInspector.d.ts.map +1 -0
- package/dist/core/DevToolsInspector.js +8 -0
- package/dist/core/DevToolsInspector.js.map +1 -0
- package/dist/core/Diagnostics.d.ts +64 -0
- package/dist/core/Diagnostics.d.ts.map +1 -0
- package/dist/core/Diagnostics.js +107 -0
- package/dist/core/Diagnostics.js.map +1 -0
- package/dist/core/ISerializable.d.ts +12 -0
- package/dist/core/ISerializable.d.ts.map +1 -0
- package/dist/core/ISerializable.js +2 -0
- package/dist/core/ISerializable.js.map +1 -0
- package/dist/core/PortRegistry.d.ts +57 -0
- package/dist/core/PortRegistry.d.ts.map +1 -0
- package/dist/core/PortRegistry.js +72 -0
- package/dist/core/PortRegistry.js.map +1 -0
- package/dist/core/PortTokens.d.ts +39 -0
- package/dist/core/PortTokens.d.ts.map +1 -0
- package/dist/core/PortTokens.js +39 -0
- package/dist/core/PortTokens.js.map +1 -0
- package/dist/core/SpatialGrid.d.ts +114 -0
- package/dist/core/SpatialGrid.d.ts.map +1 -0
- package/dist/core/SpatialGrid.js +258 -0
- package/dist/core/SpatialGrid.js.map +1 -0
- package/dist/core/Vec2.d.ts +34 -0
- package/dist/core/Vec2.d.ts.map +1 -0
- package/dist/core/Vec2.js +52 -0
- package/dist/core/Vec2.js.map +1 -0
- package/dist/core/math/CatmullRom.d.ts +20 -0
- package/dist/core/math/CatmullRom.d.ts.map +1 -0
- package/dist/core/math/CatmullRom.js +37 -0
- package/dist/core/math/CatmullRom.js.map +1 -0
- package/dist/core/math/index.d.ts +6 -0
- package/dist/core/math/index.d.ts.map +1 -0
- package/dist/core/math/index.js +5 -0
- package/dist/core/math/index.js.map +1 -0
- package/dist/core/math/intersects.d.ts +32 -0
- package/dist/core/math/intersects.d.ts.map +1 -0
- package/dist/core/math/intersects.js +92 -0
- package/dist/core/math/intersects.js.map +1 -0
- package/dist/core/math/utils.d.ts +5 -0
- package/dist/core/math/utils.d.ts.map +1 -0
- package/dist/core/math/utils.js +13 -0
- package/dist/core/math/utils.js.map +1 -0
- package/dist/entity/IComponent.d.ts +17 -0
- package/dist/entity/IComponent.d.ts.map +1 -0
- package/dist/entity/IComponent.js +2 -0
- package/dist/entity/IComponent.js.map +1 -0
- package/dist/entity/IEntity.d.ts +33 -0
- package/dist/entity/IEntity.d.ts.map +1 -0
- package/dist/entity/IEntity.js +2 -0
- package/dist/entity/IEntity.js.map +1 -0
- package/dist/entity/index.d.ts +3 -0
- package/dist/entity/index.d.ts.map +1 -0
- package/dist/entity/index.js +2 -0
- package/dist/entity/index.js.map +1 -0
- package/dist/events/ALifeEvents.d.ts +241 -0
- package/dist/events/ALifeEvents.d.ts.map +1 -0
- package/dist/events/ALifeEvents.js +53 -0
- package/dist/events/ALifeEvents.js.map +1 -0
- package/dist/events/EventBus.d.ts +52 -0
- package/dist/events/EventBus.d.ts.map +1 -0
- package/dist/events/EventBus.js +129 -0
- package/dist/events/EventBus.js.map +1 -0
- package/dist/events/index.d.ts +4 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/index.js +4 -0
- package/dist/events/index.js.map +1 -0
- package/dist/faction/Faction.d.ts +53 -0
- package/dist/faction/Faction.d.ts.map +1 -0
- package/dist/faction/Faction.js +101 -0
- package/dist/faction/Faction.js.map +1 -0
- package/dist/faction/FactionBuilder.d.ts +32 -0
- package/dist/faction/FactionBuilder.d.ts.map +1 -0
- package/dist/faction/FactionBuilder.js +80 -0
- package/dist/faction/FactionBuilder.js.map +1 -0
- package/dist/faction/ImmunityProfile.d.ts +24 -0
- package/dist/faction/ImmunityProfile.d.ts.map +1 -0
- package/dist/faction/ImmunityProfile.js +43 -0
- package/dist/faction/ImmunityProfile.js.map +1 -0
- package/dist/faction/index.d.ts +6 -0
- package/dist/faction/index.d.ts.map +1 -0
- package/dist/faction/index.js +5 -0
- package/dist/faction/index.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/logger/ILogEntry.d.ts +16 -0
- package/dist/logger/ILogEntry.d.ts.map +1 -0
- package/dist/logger/ILogEntry.js +2 -0
- package/dist/logger/ILogEntry.js.map +1 -0
- package/dist/logger/LogChannel.d.ts +27 -0
- package/dist/logger/LogChannel.d.ts.map +1 -0
- package/dist/logger/LogChannel.js +26 -0
- package/dist/logger/LogChannel.js.map +1 -0
- package/dist/logger/LogLevel.d.ts +10 -0
- package/dist/logger/LogLevel.d.ts.map +1 -0
- package/dist/logger/LogLevel.js +9 -0
- package/dist/logger/LogLevel.js.map +1 -0
- package/dist/logger/Logger.d.ts +56 -0
- package/dist/logger/Logger.d.ts.map +1 -0
- package/dist/logger/Logger.js +106 -0
- package/dist/logger/Logger.js.map +1 -0
- package/dist/logger/index.d.ts +8 -0
- package/dist/logger/index.d.ts.map +1 -0
- package/dist/logger/index.js +5 -0
- package/dist/logger/index.js.map +1 -0
- package/dist/movement/MonsterHome.d.ts +49 -0
- package/dist/movement/MonsterHome.d.ts.map +1 -0
- package/dist/movement/MonsterHome.js +75 -0
- package/dist/movement/MonsterHome.js.map +1 -0
- package/dist/movement/PatrolRoute.d.ts +99 -0
- package/dist/movement/PatrolRoute.d.ts.map +1 -0
- package/dist/movement/PatrolRoute.js +141 -0
- package/dist/movement/PatrolRoute.js.map +1 -0
- package/dist/movement/index.d.ts +5 -0
- package/dist/movement/index.d.ts.map +1 -0
- package/dist/movement/index.js +4 -0
- package/dist/movement/index.js.map +1 -0
- package/dist/navigation/LevelGraph.d.ts +78 -0
- package/dist/navigation/LevelGraph.d.ts.map +1 -0
- package/dist/navigation/LevelGraph.js +268 -0
- package/dist/navigation/LevelGraph.js.map +1 -0
- package/dist/navigation/NPCGraphMover.d.ts +87 -0
- package/dist/navigation/NPCGraphMover.d.ts.map +1 -0
- package/dist/navigation/NPCGraphMover.js +193 -0
- package/dist/navigation/NPCGraphMover.js.map +1 -0
- package/dist/navigation/index.d.ts +5 -0
- package/dist/navigation/index.d.ts.map +1 -0
- package/dist/navigation/index.js +4 -0
- package/dist/navigation/index.js.map +1 -0
- package/dist/plugins/AnomaliesPlugin.d.ts +26 -0
- package/dist/plugins/AnomaliesPlugin.d.ts.map +1 -0
- package/dist/plugins/AnomaliesPlugin.js +30 -0
- package/dist/plugins/AnomaliesPlugin.js.map +1 -0
- package/dist/plugins/CombatSchemaPlugin.d.ts +35 -0
- package/dist/plugins/CombatSchemaPlugin.d.ts.map +1 -0
- package/dist/plugins/CombatSchemaPlugin.js +44 -0
- package/dist/plugins/CombatSchemaPlugin.js.map +1 -0
- package/dist/plugins/FactionsPlugin.d.ts +26 -0
- package/dist/plugins/FactionsPlugin.d.ts.map +1 -0
- package/dist/plugins/FactionsPlugin.js +30 -0
- package/dist/plugins/FactionsPlugin.js.map +1 -0
- package/dist/plugins/IALifePlugin.d.ts +91 -0
- package/dist/plugins/IALifePlugin.d.ts.map +1 -0
- package/dist/plugins/IALifePlugin.js +2 -0
- package/dist/plugins/IALifePlugin.js.map +1 -0
- package/dist/plugins/MonstersPlugin.d.ts +26 -0
- package/dist/plugins/MonstersPlugin.d.ts.map +1 -0
- package/dist/plugins/MonstersPlugin.js +30 -0
- package/dist/plugins/MonstersPlugin.js.map +1 -0
- package/dist/plugins/NPCTypesPlugin.d.ts +26 -0
- package/dist/plugins/NPCTypesPlugin.d.ts.map +1 -0
- package/dist/plugins/NPCTypesPlugin.js +30 -0
- package/dist/plugins/NPCTypesPlugin.js.map +1 -0
- package/dist/plugins/PluginToken.d.ts +26 -0
- package/dist/plugins/PluginToken.d.ts.map +1 -0
- package/dist/plugins/PluginToken.js +22 -0
- package/dist/plugins/PluginToken.js.map +1 -0
- package/dist/plugins/SocialPlugin.d.ts +14 -0
- package/dist/plugins/SocialPlugin.d.ts.map +1 -0
- package/dist/plugins/SocialPlugin.js +16 -0
- package/dist/plugins/SocialPlugin.js.map +1 -0
- package/dist/plugins/SpawnPlugin.d.ts +15 -0
- package/dist/plugins/SpawnPlugin.d.ts.map +1 -0
- package/dist/plugins/SpawnPlugin.js +26 -0
- package/dist/plugins/SpawnPlugin.js.map +1 -0
- package/dist/plugins/SquadPlugin.d.ts +14 -0
- package/dist/plugins/SquadPlugin.d.ts.map +1 -0
- package/dist/plugins/SquadPlugin.js +16 -0
- package/dist/plugins/SquadPlugin.js.map +1 -0
- package/dist/plugins/SurgePlugin.d.ts +20 -0
- package/dist/plugins/SurgePlugin.d.ts.map +1 -0
- package/dist/plugins/SurgePlugin.js +22 -0
- package/dist/plugins/SurgePlugin.js.map +1 -0
- package/dist/plugins/TradePlugin.d.ts +16 -0
- package/dist/plugins/TradePlugin.d.ts.map +1 -0
- package/dist/plugins/TradePlugin.js +18 -0
- package/dist/plugins/TradePlugin.js.map +1 -0
- package/dist/plugins/index.d.ts +11 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +10 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/pluginNames.d.ts +37 -0
- package/dist/plugins/pluginNames.d.ts.map +1 -0
- package/dist/plugins/pluginNames.js +28 -0
- package/dist/plugins/pluginNames.js.map +1 -0
- package/dist/plugins/presets.d.ts +31 -0
- package/dist/plugins/presets.d.ts.map +1 -0
- package/dist/plugins/presets.js +50 -0
- package/dist/plugins/presets.js.map +1 -0
- package/dist/ports/IDataLoader.d.ts +38 -0
- package/dist/ports/IDataLoader.d.ts.map +1 -0
- package/dist/ports/IDataLoader.js +12 -0
- package/dist/ports/IDataLoader.js.map +1 -0
- package/dist/ports/IEntityAdapter.d.ts +73 -0
- package/dist/ports/IEntityAdapter.d.ts.map +1 -0
- package/dist/ports/IEntityAdapter.js +36 -0
- package/dist/ports/IEntityAdapter.js.map +1 -0
- package/dist/ports/IEntityFactory.d.ts +66 -0
- package/dist/ports/IEntityFactory.d.ts.map +1 -0
- package/dist/ports/IEntityFactory.js +21 -0
- package/dist/ports/IEntityFactory.js.map +1 -0
- package/dist/ports/ILogger.d.ts +29 -0
- package/dist/ports/ILogger.d.ts.map +1 -0
- package/dist/ports/ILogger.js +2 -0
- package/dist/ports/ILogger.js.map +1 -0
- package/dist/ports/IPlayerPositionProvider.d.ts +20 -0
- package/dist/ports/IPlayerPositionProvider.d.ts.map +1 -0
- package/dist/ports/IPlayerPositionProvider.js +11 -0
- package/dist/ports/IPlayerPositionProvider.js.map +1 -0
- package/dist/ports/IRandom.d.ts +25 -0
- package/dist/ports/IRandom.d.ts.map +1 -0
- package/dist/ports/IRandom.js +39 -0
- package/dist/ports/IRandom.js.map +1 -0
- package/dist/ports/IRuntimeClock.d.ts +18 -0
- package/dist/ports/IRuntimeClock.d.ts.map +1 -0
- package/dist/ports/IRuntimeClock.js +2 -0
- package/dist/ports/IRuntimeClock.js.map +1 -0
- package/dist/ports/index.d.ts +12 -0
- package/dist/ports/index.d.ts.map +1 -0
- package/dist/ports/index.js +5 -0
- package/dist/ports/index.js.map +1 -0
- package/dist/registry/AIStateRegistry.d.ts +42 -0
- package/dist/registry/AIStateRegistry.d.ts.map +1 -0
- package/dist/registry/AIStateRegistry.js +27 -0
- package/dist/registry/AIStateRegistry.js.map +1 -0
- package/dist/registry/AnomalyTypeRegistry.d.ts +21 -0
- package/dist/registry/AnomalyTypeRegistry.d.ts.map +1 -0
- package/dist/registry/AnomalyTypeRegistry.js +20 -0
- package/dist/registry/AnomalyTypeRegistry.js.map +1 -0
- package/dist/registry/BehaviorSchemeRegistry.d.ts +21 -0
- package/dist/registry/BehaviorSchemeRegistry.d.ts.map +1 -0
- package/dist/registry/BehaviorSchemeRegistry.js +24 -0
- package/dist/registry/BehaviorSchemeRegistry.js.map +1 -0
- package/dist/registry/DamageTypeRegistry.d.ts +17 -0
- package/dist/registry/DamageTypeRegistry.d.ts.map +1 -0
- package/dist/registry/DamageTypeRegistry.js +24 -0
- package/dist/registry/DamageTypeRegistry.js.map +1 -0
- package/dist/registry/FactionRegistry.d.ts +41 -0
- package/dist/registry/FactionRegistry.d.ts.map +1 -0
- package/dist/registry/FactionRegistry.js +29 -0
- package/dist/registry/FactionRegistry.js.map +1 -0
- package/dist/registry/MonsterRegistry.d.ts +44 -0
- package/dist/registry/MonsterRegistry.d.ts.map +1 -0
- package/dist/registry/MonsterRegistry.js +43 -0
- package/dist/registry/MonsterRegistry.js.map +1 -0
- package/dist/registry/NPCTypeRegistry.d.ts +34 -0
- package/dist/registry/NPCTypeRegistry.d.ts.map +1 -0
- package/dist/registry/NPCTypeRegistry.js +20 -0
- package/dist/registry/NPCTypeRegistry.js.map +1 -0
- package/dist/registry/Registry.d.ts +44 -0
- package/dist/registry/Registry.d.ts.map +1 -0
- package/dist/registry/Registry.js +80 -0
- package/dist/registry/Registry.js.map +1 -0
- package/dist/registry/TaskTypeRegistry.d.ts +17 -0
- package/dist/registry/TaskTypeRegistry.d.ts.map +1 -0
- package/dist/registry/TaskTypeRegistry.js +16 -0
- package/dist/registry/TaskTypeRegistry.js.map +1 -0
- package/dist/registry/index.d.ts +19 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +11 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/schema/index.d.ts +3 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +3 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/validators.d.ts +32 -0
- package/dist/schema/validators.d.ts.map +1 -0
- package/dist/schema/validators.js +249 -0
- package/dist/schema/validators.js.map +1 -0
- package/dist/spawn/SpawnRegistry.d.ts +48 -0
- package/dist/spawn/SpawnRegistry.d.ts.map +1 -0
- package/dist/spawn/SpawnRegistry.js +141 -0
- package/dist/spawn/SpawnRegistry.js.map +1 -0
- package/dist/spawn/index.d.ts +3 -0
- package/dist/spawn/index.d.ts.map +1 -0
- package/dist/spawn/index.js +3 -0
- package/dist/spawn/index.js.map +1 -0
- package/dist/terrain/SmartTerrain.d.ts +119 -0
- package/dist/terrain/SmartTerrain.d.ts.map +1 -0
- package/dist/terrain/SmartTerrain.js +124 -0
- package/dist/terrain/SmartTerrain.js.map +1 -0
- package/dist/terrain/TerrainBuilder.d.ts +44 -0
- package/dist/terrain/TerrainBuilder.d.ts.map +1 -0
- package/dist/terrain/TerrainBuilder.js +112 -0
- package/dist/terrain/TerrainBuilder.js.map +1 -0
- package/dist/terrain/Zone.d.ts +25 -0
- package/dist/terrain/Zone.d.ts.map +1 -0
- package/dist/terrain/Zone.js +29 -0
- package/dist/terrain/Zone.js.map +1 -0
- package/dist/terrain/index.d.ts +6 -0
- package/dist/terrain/index.d.ts.map +1 -0
- package/dist/terrain/index.js +5 -0
- package/dist/terrain/index.js.map +1 -0
- package/dist/time/TimeManager.d.ts +21 -0
- package/dist/time/TimeManager.d.ts.map +1 -0
- package/dist/time/TimeManager.js +41 -0
- package/dist/time/TimeManager.js.map +1 -0
- package/dist/time/index.d.ts +3 -0
- package/dist/time/index.d.ts.map +1 -0
- package/dist/time/index.js +2 -0
- package/dist/time/index.js.map +1 -0
- package/package.json +119 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opaque token identifying a port type.
|
|
3
|
+
*
|
|
4
|
+
* The phantom `_brand` field carries the port's TypeScript type without
|
|
5
|
+
* contributing to the runtime shape, enabling type-safe `require<T>()`.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* const MyPort = createPortToken<IMyAdapter>('myAdapter', 'Bridge to XYZ');
|
|
10
|
+
* kernel.provide(MyPort, new MyAdapterImpl());
|
|
11
|
+
* const adapter = kernel.portRegistry.require(MyPort); // typed as IMyAdapter
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export interface PortToken<T> {
|
|
15
|
+
readonly id: string;
|
|
16
|
+
readonly description: string;
|
|
17
|
+
/** @internal Phantom field for type inference — never set at runtime. */
|
|
18
|
+
readonly _brand?: T;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Create a new port token with a unique id and human-readable description.
|
|
22
|
+
*
|
|
23
|
+
* @param id - Unique identifier (e.g. `'entityAdapter'`).
|
|
24
|
+
* @param description - Short explanation shown in diagnostics.
|
|
25
|
+
*/
|
|
26
|
+
export declare function createPortToken<T>(id: string, description: string): PortToken<T>;
|
|
27
|
+
/**
|
|
28
|
+
* Runtime container for port implementations, keyed by {@link PortToken}.
|
|
29
|
+
*
|
|
30
|
+
* Designed for a single-phase lifecycle:
|
|
31
|
+
* 1. `provide()` during setup (before `kernel.init()`).
|
|
32
|
+
* 2. `require()` / `tryGet()` during init and at runtime.
|
|
33
|
+
*
|
|
34
|
+
* Duplicate registrations throw immediately to surface wiring bugs early.
|
|
35
|
+
*/
|
|
36
|
+
export declare class PortRegistry {
|
|
37
|
+
private readonly ports;
|
|
38
|
+
/**
|
|
39
|
+
* Register a port implementation.
|
|
40
|
+
*
|
|
41
|
+
* @throws {Error} If a port with the same token id is already registered.
|
|
42
|
+
*/
|
|
43
|
+
provide<T>(token: PortToken<T>, impl: T): void;
|
|
44
|
+
/**
|
|
45
|
+
* Retrieve a required port.
|
|
46
|
+
*
|
|
47
|
+
* @throws {Error} If the port has not been provided.
|
|
48
|
+
*/
|
|
49
|
+
require<T>(token: PortToken<T>): T;
|
|
50
|
+
/** Retrieve an optional port, returning `undefined` when absent. */
|
|
51
|
+
tryGet<T>(token: PortToken<T>): T | undefined;
|
|
52
|
+
/** Check whether a port has been provided. */
|
|
53
|
+
has(token: PortToken<unknown>): boolean;
|
|
54
|
+
/** Return all registered port ids (useful for diagnostics). */
|
|
55
|
+
registeredIds(): string[];
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=PortRegistry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PortRegistry.d.ts","sourceRoot":"","sources":["../../src/core/PortRegistry.ts"],"names":[],"mappings":"AAaA;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,SAAS,CAAC,CAAC;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,yEAAyE;IACzE,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,CAEhF;AAMD;;;;;;;;GAQG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA8B;IAEpD;;;;OAIG;IACH,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI;IAU9C;;;;OAIG;IACH,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC;IAWlC,oEAAoE;IACpE,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS;IAI7C,8CAA8C;IAC9C,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,GAAG,OAAO;IAIvC,+DAA+D;IAC/D,aAAa,IAAI,MAAM,EAAE;CAG1B"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// core/PortRegistry.ts
|
|
2
|
+
// Type-safe service registry with token-based port resolution.
|
|
3
|
+
//
|
|
4
|
+
// Ports are external adapters (entity adapter, player position, pathfinder)
|
|
5
|
+
// that the host game engine supplies to the A-Life kernel. PortRegistry
|
|
6
|
+
// replaces the hard-coded IALifeKernelPorts interface with an extensible
|
|
7
|
+
// token-based lookup, allowing third-party plugins to declare and consume
|
|
8
|
+
// custom ports without modifying the kernel's constructor signature.
|
|
9
|
+
/**
|
|
10
|
+
* Create a new port token with a unique id and human-readable description.
|
|
11
|
+
*
|
|
12
|
+
* @param id - Unique identifier (e.g. `'entityAdapter'`).
|
|
13
|
+
* @param description - Short explanation shown in diagnostics.
|
|
14
|
+
*/
|
|
15
|
+
export function createPortToken(id, description) {
|
|
16
|
+
return { id, description };
|
|
17
|
+
}
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// PortRegistry
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
/**
|
|
22
|
+
* Runtime container for port implementations, keyed by {@link PortToken}.
|
|
23
|
+
*
|
|
24
|
+
* Designed for a single-phase lifecycle:
|
|
25
|
+
* 1. `provide()` during setup (before `kernel.init()`).
|
|
26
|
+
* 2. `require()` / `tryGet()` during init and at runtime.
|
|
27
|
+
*
|
|
28
|
+
* Duplicate registrations throw immediately to surface wiring bugs early.
|
|
29
|
+
*/
|
|
30
|
+
export class PortRegistry {
|
|
31
|
+
constructor() {
|
|
32
|
+
this.ports = new Map();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Register a port implementation.
|
|
36
|
+
*
|
|
37
|
+
* @throws {Error} If a port with the same token id is already registered.
|
|
38
|
+
*/
|
|
39
|
+
provide(token, impl) {
|
|
40
|
+
if (this.ports.has(token.id)) {
|
|
41
|
+
throw new Error(`[PortRegistry] Port "${token.id}" already registered. ` +
|
|
42
|
+
`Each port token must be provided exactly once.`);
|
|
43
|
+
}
|
|
44
|
+
this.ports.set(token.id, impl);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Retrieve a required port.
|
|
48
|
+
*
|
|
49
|
+
* @throws {Error} If the port has not been provided.
|
|
50
|
+
*/
|
|
51
|
+
require(token) {
|
|
52
|
+
const impl = this.ports.get(token.id);
|
|
53
|
+
if (impl === undefined) {
|
|
54
|
+
throw new Error(`[PortRegistry] Required port "${token.id}" (${token.description}) ` +
|
|
55
|
+
`not provided. Call kernel.provide(token, impl) before init().`);
|
|
56
|
+
}
|
|
57
|
+
return impl;
|
|
58
|
+
}
|
|
59
|
+
/** Retrieve an optional port, returning `undefined` when absent. */
|
|
60
|
+
tryGet(token) {
|
|
61
|
+
return this.ports.get(token.id);
|
|
62
|
+
}
|
|
63
|
+
/** Check whether a port has been provided. */
|
|
64
|
+
has(token) {
|
|
65
|
+
return this.ports.has(token.id);
|
|
66
|
+
}
|
|
67
|
+
/** Return all registered port ids (useful for diagnostics). */
|
|
68
|
+
registeredIds() {
|
|
69
|
+
return [...this.ports.keys()];
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=PortRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PortRegistry.js","sourceRoot":"","sources":["../../src/core/PortRegistry.ts"],"names":[],"mappings":"AAAA,uBAAuB;AACvB,+DAA+D;AAC/D,EAAE;AACF,4EAA4E;AAC5E,wEAAwE;AACxE,yEAAyE;AACzE,0EAA0E;AAC1E,qEAAqE;AA0BrE;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAI,EAAU,EAAE,WAAmB;IAChE,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC;AAC7B,CAAC;AAED,8EAA8E;AAC9E,eAAe;AACf,8EAA8E;AAE9E;;;;;;;;GAQG;AACH,MAAM,OAAO,YAAY;IAAzB;QACmB,UAAK,GAAG,IAAI,GAAG,EAAmB,CAAC;IA+CtD,CAAC;IA7CC;;;;OAIG;IACH,OAAO,CAAI,KAAmB,EAAE,IAAO;QACrC,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CACb,wBAAwB,KAAK,CAAC,EAAE,wBAAwB;gBACxD,gDAAgD,CACjD,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IACjC,CAAC;IAED;;;;OAIG;IACH,OAAO,CAAI,KAAmB;QAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CACb,iCAAiC,KAAK,CAAC,EAAE,MAAM,KAAK,CAAC,WAAW,IAAI;gBACpE,+DAA+D,CAChE,CAAC;QACJ,CAAC;QACD,OAAO,IAAS,CAAC;IACnB,CAAC;IAED,oEAAoE;IACpE,MAAM,CAAI,KAAmB;QAC3B,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAkB,CAAC;IACnD,CAAC;IAED,8CAA8C;IAC9C,GAAG,CAAC,KAAyB;QAC3B,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAClC,CAAC;IAED,+DAA+D;IAC/D,aAAa;QACX,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IAChC,CAAC;CACF"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { IEntityAdapter } from '../ports/IEntityAdapter';
|
|
2
|
+
import type { IPlayerPositionProvider } from '../ports/IPlayerPositionProvider';
|
|
3
|
+
import type { IEntityFactory } from '../ports/IEntityFactory';
|
|
4
|
+
import type { IRandom } from '../ports/IRandom';
|
|
5
|
+
import type { IRuntimeClock } from '../ports/IRuntimeClock';
|
|
6
|
+
/**
|
|
7
|
+
* Well-known port tokens shipped with the SDK.
|
|
8
|
+
*
|
|
9
|
+
* The first three (`EntityAdapter`, `PlayerPosition`, `EntityFactory`) are
|
|
10
|
+
* required by the kernel — `init()` will report a diagnostic error if any
|
|
11
|
+
* is missing. The rest are optional capability ports consumed by plugins.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* import { Ports } from '@alife-sdk/core';
|
|
16
|
+
*
|
|
17
|
+
* kernel.provide(Ports.EntityAdapter, myAdapter);
|
|
18
|
+
* kernel.provide(Ports.PlayerPosition, myPositionProvider);
|
|
19
|
+
* kernel.provide(Ports.EntityFactory, myFactory);
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare const Ports: {
|
|
23
|
+
readonly EntityAdapter: import("./PortRegistry").PortToken<IEntityAdapter>;
|
|
24
|
+
readonly PlayerPosition: import("./PortRegistry").PortToken<IPlayerPositionProvider>;
|
|
25
|
+
readonly EntityFactory: import("./PortRegistry").PortToken<IEntityFactory>;
|
|
26
|
+
readonly Random: import("./PortRegistry").PortToken<IRandom>;
|
|
27
|
+
readonly RuntimeClock: import("./PortRegistry").PortToken<IRuntimeClock>;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Port tokens that the kernel unconditionally requires.
|
|
31
|
+
*
|
|
32
|
+
* `EntityAdapter`, `PlayerPosition`, and `EntityFactory` are no longer listed
|
|
33
|
+
* here — the kernel auto-provides no-op defaults for them in `init()` when the
|
|
34
|
+
* host does not supply real implementations (same pattern as `Random`).
|
|
35
|
+
* Plugins that genuinely need real implementations declare them via
|
|
36
|
+
* `plugin.requiredPorts`.
|
|
37
|
+
*/
|
|
38
|
+
export declare const REQUIRED_PORTS: readonly import('./PortRegistry').PortToken<unknown>[];
|
|
39
|
+
//# sourceMappingURL=PortTokens.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PortTokens.d.ts","sourceRoot":"","sources":["../../src/core/PortTokens.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAChF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE5D;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,KAAK;;;;;;CAqBR,CAAC;AAEX;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,EAAE,SAAS,OAAO,gBAAgB,EAAE,SAAS,CAAC,OAAO,CAAC,EAAO,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// core/PortTokens.ts
|
|
2
|
+
// Built-in port tokens for the standard A-Life kernel adapters.
|
|
3
|
+
//
|
|
4
|
+
// Third-party plugins can create their own tokens via createPortToken<T>().
|
|
5
|
+
import { createPortToken } from './PortRegistry';
|
|
6
|
+
/**
|
|
7
|
+
* Well-known port tokens shipped with the SDK.
|
|
8
|
+
*
|
|
9
|
+
* The first three (`EntityAdapter`, `PlayerPosition`, `EntityFactory`) are
|
|
10
|
+
* required by the kernel — `init()` will report a diagnostic error if any
|
|
11
|
+
* is missing. The rest are optional capability ports consumed by plugins.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* import { Ports } from '@alife-sdk/core';
|
|
16
|
+
*
|
|
17
|
+
* kernel.provide(Ports.EntityAdapter, myAdapter);
|
|
18
|
+
* kernel.provide(Ports.PlayerPosition, myPositionProvider);
|
|
19
|
+
* kernel.provide(Ports.EntityFactory, myFactory);
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export const Ports = {
|
|
23
|
+
EntityAdapter: createPortToken('entityAdapter', 'Bridge between kernel and host entity system'),
|
|
24
|
+
PlayerPosition: createPortToken('playerPosition', 'Provides player world position for online/offline checks'),
|
|
25
|
+
EntityFactory: createPortToken('entityFactory', 'Creates and destroys game entities on spawn/despawn'),
|
|
26
|
+
Random: createPortToken('random', 'PRNG for simulation randomness'),
|
|
27
|
+
RuntimeClock: createPortToken('runtimeClock', 'Monotonic real-time ms for cooldowns and memory aging'),
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Port tokens that the kernel unconditionally requires.
|
|
31
|
+
*
|
|
32
|
+
* `EntityAdapter`, `PlayerPosition`, and `EntityFactory` are no longer listed
|
|
33
|
+
* here — the kernel auto-provides no-op defaults for them in `init()` when the
|
|
34
|
+
* host does not supply real implementations (same pattern as `Random`).
|
|
35
|
+
* Plugins that genuinely need real implementations declare them via
|
|
36
|
+
* `plugin.requiredPorts`.
|
|
37
|
+
*/
|
|
38
|
+
export const REQUIRED_PORTS = [];
|
|
39
|
+
//# sourceMappingURL=PortTokens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PortTokens.js","sourceRoot":"","sources":["../../src/core/PortTokens.ts"],"names":[],"mappings":"AAAA,qBAAqB;AACrB,gEAAgE;AAChE,EAAE;AACF,4EAA4E;AAE5E,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAOjD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,aAAa,EAAE,eAAe,CAC5B,eAAe,EACf,8CAA8C,CAC/C;IACD,cAAc,EAAE,eAAe,CAC7B,gBAAgB,EAChB,0DAA0D,CAC3D;IACD,aAAa,EAAE,eAAe,CAC5B,eAAe,EACf,qDAAqD,CACtD;IACD,MAAM,EAAE,eAAe,CACrB,QAAQ,EACR,gCAAgC,CACjC;IACD,YAAY,EAAE,eAAe,CAC3B,cAAc,EACd,uDAAuD,CACxD;CACO,CAAC;AAEX;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,cAAc,GAA2D,EAAE,CAAC"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import type { Vec2 } from './Vec2';
|
|
2
|
+
export interface IRect {
|
|
3
|
+
readonly x: number;
|
|
4
|
+
readonly y: number;
|
|
5
|
+
readonly width: number;
|
|
6
|
+
readonly height: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Spatial hash grid that supports fast radius and rectangle queries
|
|
10
|
+
* over an arbitrary item type.
|
|
11
|
+
*
|
|
12
|
+
* @typeParam T - Any object stored in the grid. Position is extracted
|
|
13
|
+
* via the `positionFn` supplied at construction time.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* interface NPC { name: string; pos: Vec2 }
|
|
18
|
+
*
|
|
19
|
+
* const grid = new SpatialGrid<NPC>(200, (npc) => npc.pos);
|
|
20
|
+
* grid.insert(myNpc);
|
|
21
|
+
*
|
|
22
|
+
* const nearby = grid.queryRadius({ x: 400, y: 300 }, 250);
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare class SpatialGrid<T> {
|
|
26
|
+
/** Offset to shift cell indices into non-negative range. Supports +/-512 cells. */
|
|
27
|
+
private static readonly CELL_OFFSET;
|
|
28
|
+
/** Stride for packing (cx, cy) into a single integer. */
|
|
29
|
+
private static readonly CELL_STRIDE;
|
|
30
|
+
/** Pixel size of each square cell. */
|
|
31
|
+
private readonly cellSize;
|
|
32
|
+
/** Extracts a world-space position from an item. */
|
|
33
|
+
private readonly positionFn;
|
|
34
|
+
/**
|
|
35
|
+
* Packed integer key -> Set of items whose position hashes to that cell.
|
|
36
|
+
* Cells are created lazily and deleted when they become empty.
|
|
37
|
+
*/
|
|
38
|
+
private readonly cells;
|
|
39
|
+
/**
|
|
40
|
+
* item -> packed integer cell key where that item currently lives.
|
|
41
|
+
* Enables O(1) lookup of the old cell in update() and remove().
|
|
42
|
+
*/
|
|
43
|
+
private readonly itemToCell;
|
|
44
|
+
/**
|
|
45
|
+
* Scratch array reused by queryRadius() and queryRect() to avoid
|
|
46
|
+
* allocating a new array on every call. Callers that need to hold
|
|
47
|
+
* results beyond the next query should copy the returned array.
|
|
48
|
+
*/
|
|
49
|
+
private readonly _scratchResults;
|
|
50
|
+
/**
|
|
51
|
+
* @param cellSize - Width and height of each grid cell in world units.
|
|
52
|
+
* A good default is 2x your most common query radius so that a centred
|
|
53
|
+
* radius query never reads more than ~9 cells.
|
|
54
|
+
* @param positionFn - Pure function that extracts a Vec2 from an item.
|
|
55
|
+
*/
|
|
56
|
+
constructor(cellSize: number, positionFn: (item: T) => Vec2);
|
|
57
|
+
/**
|
|
58
|
+
* Add an item to the grid.
|
|
59
|
+
*
|
|
60
|
+
* If the item is already tracked, this behaves like {@link update} to keep
|
|
61
|
+
* internal state consistent.
|
|
62
|
+
*/
|
|
63
|
+
insert(item: T): void;
|
|
64
|
+
/**
|
|
65
|
+
* Remove an item from the grid.
|
|
66
|
+
*
|
|
67
|
+
* @returns `true` if the item was found and removed, `false` if it was not tracked.
|
|
68
|
+
*/
|
|
69
|
+
remove(item: T): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Re-hash an item after its position has changed.
|
|
72
|
+
*
|
|
73
|
+
* If the item has not crossed a cell boundary this is a no-op.
|
|
74
|
+
* If the item is not yet tracked, it is inserted automatically.
|
|
75
|
+
*/
|
|
76
|
+
update(item: T): void;
|
|
77
|
+
/** Remove all items and all cells. */
|
|
78
|
+
clear(): void;
|
|
79
|
+
/**
|
|
80
|
+
* Return all items within `radius` world-units of `center`.
|
|
81
|
+
*
|
|
82
|
+
* **Note:** The returned array is reused between calls. Callers that need
|
|
83
|
+
* to hold the result beyond the next query should copy it (e.g. `[...result]`).
|
|
84
|
+
*
|
|
85
|
+
* Algorithm:
|
|
86
|
+
* 1. Compute the cell-space AABB that covers the bounding box of the circle.
|
|
87
|
+
* 2. Iterate that rectangular band of cells.
|
|
88
|
+
* 3. Filter each candidate by exact squared distance (no sqrt).
|
|
89
|
+
*/
|
|
90
|
+
queryRadius(center: Vec2, radius: number): T[];
|
|
91
|
+
/**
|
|
92
|
+
* Return all items whose position lies within the axis-aligned rectangle
|
|
93
|
+
* defined by its top-left corner (x, y) and dimensions (width x height).
|
|
94
|
+
*
|
|
95
|
+
* **Note:** The returned array is reused between calls. Callers that need
|
|
96
|
+
* to hold the result beyond the next query should copy it (e.g. `[...result]`).
|
|
97
|
+
*/
|
|
98
|
+
queryRect(bounds: IRect): T[];
|
|
99
|
+
/** Total number of items currently tracked by the grid. */
|
|
100
|
+
get size(): number;
|
|
101
|
+
/**
|
|
102
|
+
* Pack cell coordinates (cx, cy) into a single non-negative integer.
|
|
103
|
+
* Supports cell indices in the range [-512, +511].
|
|
104
|
+
*/
|
|
105
|
+
private cellKeyInt;
|
|
106
|
+
/** Add an item to the cell identified by `key`, creating the cell lazily. */
|
|
107
|
+
private addToCell;
|
|
108
|
+
/**
|
|
109
|
+
* Remove an item from the cell at `key`.
|
|
110
|
+
* Prunes the cell if it becomes empty to prevent unbounded growth.
|
|
111
|
+
*/
|
|
112
|
+
private removeFromCell;
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=SpatialGrid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SpatialGrid.d.ts","sourceRoot":"","sources":["../../src/core/SpatialGrid.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEnC,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAMD;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,WAAW,CAAC,CAAC;IAKxB,mFAAmF;IACnF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAO;IAE1C,yDAAyD;IACzD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAQ;IAM3C,sCAAsC;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAElC,oDAAoD;IACpD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;IAE/C;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkC;IAExD;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA6B;IAExD;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAW;IAM3C;;;;;OAKG;gBACS,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI;IAY3D;;;;;OAKG;IACH,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI;IAYrB;;;;OAIG;IACH,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO;IASxB;;;;;OAKG;IACH,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI;IAuBrB,sCAAsC;IACtC,KAAK,IAAI,IAAI;IASb;;;;;;;;;;OAUG;IACH,WAAW,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC,EAAE;IAgC9C;;;;;;OAMG;IACH,SAAS,CAAC,MAAM,EAAE,KAAK,GAAG,CAAC,EAAE;IAoC7B,2DAA2D;IAC3D,IAAI,IAAI,IAAI,MAAM,CAEjB;IAMD;;;OAGG;IACH,OAAO,CAAC,UAAU;IAMlB,6EAA6E;IAC7E,OAAO,CAAC,SAAS;IASjB;;;OAGG;IACH,OAAO,CAAC,cAAc;CAUvB"}
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
// core/SpatialGrid.ts
|
|
2
|
+
// Generic spatial hash grid for efficient radius and rectangle queries.
|
|
3
|
+
//
|
|
4
|
+
// Algorithm:
|
|
5
|
+
// The world is divided into axis-aligned cells of cellSize x cellSize pixels.
|
|
6
|
+
// Each item hashes to exactly one cell based on its position (extracted via
|
|
7
|
+
// a caller-supplied positionFn). Cells are lazily created as Maps keyed by
|
|
8
|
+
// integer and pruned when empty to bound memory.
|
|
9
|
+
//
|
|
10
|
+
// Performance:
|
|
11
|
+
// insert / remove / update O(1)
|
|
12
|
+
// queryRadius / queryRect O(k), k = items in intersected cells
|
|
13
|
+
// No Math.sqrt on the hot path — radius checks use squared distance.
|
|
14
|
+
// Cell keys are packed integers (no string allocation).
|
|
15
|
+
// Query methods reuse a scratch array to avoid per-call allocation.
|
|
16
|
+
//
|
|
17
|
+
// Generic design:
|
|
18
|
+
// SpatialGrid<T> works with any item type. The caller provides a positionFn
|
|
19
|
+
// that extracts a Vec2 from T, so there is no interface constraint on T.
|
|
20
|
+
// Internally, items are tracked via a WeakRef-free identity Map (item -> cell key).
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// SpatialGrid<T>
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
/**
|
|
25
|
+
* Spatial hash grid that supports fast radius and rectangle queries
|
|
26
|
+
* over an arbitrary item type.
|
|
27
|
+
*
|
|
28
|
+
* @typeParam T - Any object stored in the grid. Position is extracted
|
|
29
|
+
* via the `positionFn` supplied at construction time.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* interface NPC { name: string; pos: Vec2 }
|
|
34
|
+
*
|
|
35
|
+
* const grid = new SpatialGrid<NPC>(200, (npc) => npc.pos);
|
|
36
|
+
* grid.insert(myNpc);
|
|
37
|
+
*
|
|
38
|
+
* const nearby = grid.queryRadius({ x: 400, y: 300 }, 250);
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export class SpatialGrid {
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
// Constructor
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
/**
|
|
46
|
+
* @param cellSize - Width and height of each grid cell in world units.
|
|
47
|
+
* A good default is 2x your most common query radius so that a centred
|
|
48
|
+
* radius query never reads more than ~9 cells.
|
|
49
|
+
* @param positionFn - Pure function that extracts a Vec2 from an item.
|
|
50
|
+
*/
|
|
51
|
+
constructor(cellSize, positionFn) {
|
|
52
|
+
/**
|
|
53
|
+
* Packed integer key -> Set of items whose position hashes to that cell.
|
|
54
|
+
* Cells are created lazily and deleted when they become empty.
|
|
55
|
+
*/
|
|
56
|
+
this.cells = new Map();
|
|
57
|
+
/**
|
|
58
|
+
* item -> packed integer cell key where that item currently lives.
|
|
59
|
+
* Enables O(1) lookup of the old cell in update() and remove().
|
|
60
|
+
*/
|
|
61
|
+
this.itemToCell = new Map();
|
|
62
|
+
/**
|
|
63
|
+
* Scratch array reused by queryRadius() and queryRect() to avoid
|
|
64
|
+
* allocating a new array on every call. Callers that need to hold
|
|
65
|
+
* results beyond the next query should copy the returned array.
|
|
66
|
+
*/
|
|
67
|
+
this._scratchResults = [];
|
|
68
|
+
if (cellSize <= 0) {
|
|
69
|
+
throw new RangeError(`SpatialGrid: cellSize must be > 0, got ${cellSize}`);
|
|
70
|
+
}
|
|
71
|
+
this.cellSize = cellSize;
|
|
72
|
+
this.positionFn = positionFn;
|
|
73
|
+
}
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
// Mutation API
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
/**
|
|
78
|
+
* Add an item to the grid.
|
|
79
|
+
*
|
|
80
|
+
* If the item is already tracked, this behaves like {@link update} to keep
|
|
81
|
+
* internal state consistent.
|
|
82
|
+
*/
|
|
83
|
+
insert(item) {
|
|
84
|
+
if (this.itemToCell.has(item)) {
|
|
85
|
+
this.update(item);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const pos = this.positionFn(item);
|
|
89
|
+
const key = this.cellKeyInt(pos.x, pos.y);
|
|
90
|
+
this.addToCell(key, item);
|
|
91
|
+
this.itemToCell.set(item, key);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Remove an item from the grid.
|
|
95
|
+
*
|
|
96
|
+
* @returns `true` if the item was found and removed, `false` if it was not tracked.
|
|
97
|
+
*/
|
|
98
|
+
remove(item) {
|
|
99
|
+
const key = this.itemToCell.get(item);
|
|
100
|
+
if (key === undefined)
|
|
101
|
+
return false;
|
|
102
|
+
this.removeFromCell(key, item);
|
|
103
|
+
this.itemToCell.delete(item);
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Re-hash an item after its position has changed.
|
|
108
|
+
*
|
|
109
|
+
* If the item has not crossed a cell boundary this is a no-op.
|
|
110
|
+
* If the item is not yet tracked, it is inserted automatically.
|
|
111
|
+
*/
|
|
112
|
+
update(item) {
|
|
113
|
+
const pos = this.positionFn(item);
|
|
114
|
+
const newKey = this.cellKeyInt(pos.x, pos.y);
|
|
115
|
+
const oldKey = this.itemToCell.get(item);
|
|
116
|
+
if (oldKey === undefined) {
|
|
117
|
+
// Not yet tracked — insert.
|
|
118
|
+
this.addToCell(newKey, item);
|
|
119
|
+
this.itemToCell.set(item, newKey);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
if (oldKey === newKey) {
|
|
123
|
+
// Still in the same cell — nothing to do.
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
// Moved to a different cell — re-bucket.
|
|
127
|
+
this.removeFromCell(oldKey, item);
|
|
128
|
+
this.addToCell(newKey, item);
|
|
129
|
+
this.itemToCell.set(item, newKey);
|
|
130
|
+
}
|
|
131
|
+
/** Remove all items and all cells. */
|
|
132
|
+
clear() {
|
|
133
|
+
this.cells.clear();
|
|
134
|
+
this.itemToCell.clear();
|
|
135
|
+
}
|
|
136
|
+
// ---------------------------------------------------------------------------
|
|
137
|
+
// Query API
|
|
138
|
+
// ---------------------------------------------------------------------------
|
|
139
|
+
/**
|
|
140
|
+
* Return all items within `radius` world-units of `center`.
|
|
141
|
+
*
|
|
142
|
+
* **Note:** The returned array is reused between calls. Callers that need
|
|
143
|
+
* to hold the result beyond the next query should copy it (e.g. `[...result]`).
|
|
144
|
+
*
|
|
145
|
+
* Algorithm:
|
|
146
|
+
* 1. Compute the cell-space AABB that covers the bounding box of the circle.
|
|
147
|
+
* 2. Iterate that rectangular band of cells.
|
|
148
|
+
* 3. Filter each candidate by exact squared distance (no sqrt).
|
|
149
|
+
*/
|
|
150
|
+
queryRadius(center, radius) {
|
|
151
|
+
const radiusSq = radius * radius;
|
|
152
|
+
const results = this._scratchResults;
|
|
153
|
+
results.length = 0;
|
|
154
|
+
const minCX = Math.floor((center.x - radius) / this.cellSize);
|
|
155
|
+
const minCY = Math.floor((center.y - radius) / this.cellSize);
|
|
156
|
+
const maxCX = Math.floor((center.x + radius) / this.cellSize);
|
|
157
|
+
const maxCY = Math.floor((center.y + radius) / this.cellSize);
|
|
158
|
+
for (let cy = minCY; cy <= maxCY; cy++) {
|
|
159
|
+
for (let cx = minCX; cx <= maxCX; cx++) {
|
|
160
|
+
const cell = this.cells.get((cx + SpatialGrid.CELL_OFFSET) * SpatialGrid.CELL_STRIDE +
|
|
161
|
+
(cy + SpatialGrid.CELL_OFFSET));
|
|
162
|
+
if (!cell)
|
|
163
|
+
continue;
|
|
164
|
+
for (const item of cell) {
|
|
165
|
+
const pos = this.positionFn(item);
|
|
166
|
+
const dx = pos.x - center.x;
|
|
167
|
+
const dy = pos.y - center.y;
|
|
168
|
+
if (dx * dx + dy * dy <= radiusSq) {
|
|
169
|
+
results.push(item);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return results;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Return all items whose position lies within the axis-aligned rectangle
|
|
178
|
+
* defined by its top-left corner (x, y) and dimensions (width x height).
|
|
179
|
+
*
|
|
180
|
+
* **Note:** The returned array is reused between calls. Callers that need
|
|
181
|
+
* to hold the result beyond the next query should copy it (e.g. `[...result]`).
|
|
182
|
+
*/
|
|
183
|
+
queryRect(bounds) {
|
|
184
|
+
const { x, y, width, height } = bounds;
|
|
185
|
+
const right = x + width;
|
|
186
|
+
const bottom = y + height;
|
|
187
|
+
const results = this._scratchResults;
|
|
188
|
+
results.length = 0;
|
|
189
|
+
const minCX = Math.floor(x / this.cellSize);
|
|
190
|
+
const minCY = Math.floor(y / this.cellSize);
|
|
191
|
+
const maxCX = Math.floor(right / this.cellSize);
|
|
192
|
+
const maxCY = Math.floor(bottom / this.cellSize);
|
|
193
|
+
for (let cy = minCY; cy <= maxCY; cy++) {
|
|
194
|
+
for (let cx = minCX; cx <= maxCX; cx++) {
|
|
195
|
+
const cell = this.cells.get((cx + SpatialGrid.CELL_OFFSET) * SpatialGrid.CELL_STRIDE +
|
|
196
|
+
(cy + SpatialGrid.CELL_OFFSET));
|
|
197
|
+
if (!cell)
|
|
198
|
+
continue;
|
|
199
|
+
for (const item of cell) {
|
|
200
|
+
const pos = this.positionFn(item);
|
|
201
|
+
if (pos.x >= x && pos.x <= right && pos.y >= y && pos.y <= bottom) {
|
|
202
|
+
results.push(item);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return results;
|
|
208
|
+
}
|
|
209
|
+
// ---------------------------------------------------------------------------
|
|
210
|
+
// Diagnostics
|
|
211
|
+
// ---------------------------------------------------------------------------
|
|
212
|
+
/** Total number of items currently tracked by the grid. */
|
|
213
|
+
get size() {
|
|
214
|
+
return this.itemToCell.size;
|
|
215
|
+
}
|
|
216
|
+
// ---------------------------------------------------------------------------
|
|
217
|
+
// Private helpers
|
|
218
|
+
// ---------------------------------------------------------------------------
|
|
219
|
+
/**
|
|
220
|
+
* Pack cell coordinates (cx, cy) into a single non-negative integer.
|
|
221
|
+
* Supports cell indices in the range [-512, +511].
|
|
222
|
+
*/
|
|
223
|
+
cellKeyInt(x, y) {
|
|
224
|
+
const cx = Math.floor(x / this.cellSize);
|
|
225
|
+
const cy = Math.floor(y / this.cellSize);
|
|
226
|
+
return (cx + SpatialGrid.CELL_OFFSET) * SpatialGrid.CELL_STRIDE + (cy + SpatialGrid.CELL_OFFSET);
|
|
227
|
+
}
|
|
228
|
+
/** Add an item to the cell identified by `key`, creating the cell lazily. */
|
|
229
|
+
addToCell(key, item) {
|
|
230
|
+
let cell = this.cells.get(key);
|
|
231
|
+
if (!cell) {
|
|
232
|
+
cell = new Set();
|
|
233
|
+
this.cells.set(key, cell);
|
|
234
|
+
}
|
|
235
|
+
cell.add(item);
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Remove an item from the cell at `key`.
|
|
239
|
+
* Prunes the cell if it becomes empty to prevent unbounded growth.
|
|
240
|
+
*/
|
|
241
|
+
removeFromCell(key, item) {
|
|
242
|
+
const cell = this.cells.get(key);
|
|
243
|
+
if (!cell)
|
|
244
|
+
return;
|
|
245
|
+
cell.delete(item);
|
|
246
|
+
if (cell.size === 0) {
|
|
247
|
+
this.cells.delete(key);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
// ---------------------------------------------------------------------------
|
|
252
|
+
// Integer key packing constants
|
|
253
|
+
// ---------------------------------------------------------------------------
|
|
254
|
+
/** Offset to shift cell indices into non-negative range. Supports +/-512 cells. */
|
|
255
|
+
SpatialGrid.CELL_OFFSET = 512;
|
|
256
|
+
/** Stride for packing (cx, cy) into a single integer. */
|
|
257
|
+
SpatialGrid.CELL_STRIDE = 1024;
|
|
258
|
+
//# sourceMappingURL=SpatialGrid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SpatialGrid.js","sourceRoot":"","sources":["../../src/core/SpatialGrid.ts"],"names":[],"mappings":"AAAA,sBAAsB;AACtB,wEAAwE;AACxE,EAAE;AACF,aAAa;AACb,gFAAgF;AAChF,8EAA8E;AAC9E,6EAA6E;AAC7E,mDAAmD;AACnD,EAAE;AACF,eAAe;AACf,oCAAoC;AACpC,oEAAoE;AACpE,uEAAuE;AACvE,0DAA0D;AAC1D,sEAAsE;AACtE,EAAE;AACF,kBAAkB;AAClB,8EAA8E;AAC9E,2EAA2E;AAC3E,sFAAsF;AAWtF,8EAA8E;AAC9E,iBAAiB;AACjB,8EAA8E;AAE9E;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,OAAO,WAAW;IAwCtB,8EAA8E;IAC9E,cAAc;IACd,8EAA8E;IAE9E;;;;;OAKG;IACH,YAAY,QAAgB,EAAE,UAA6B;QA7B3D;;;WAGG;QACc,UAAK,GAAwB,IAAI,GAAG,EAAE,CAAC;QAExD;;;WAGG;QACc,eAAU,GAAmB,IAAI,GAAG,EAAE,CAAC;QAExD;;;;WAIG;QACc,oBAAe,GAAQ,EAAE,CAAC;QAazC,IAAI,QAAQ,IAAI,CAAC,EAAE,CAAC;YAClB,MAAM,IAAI,UAAU,CAAC,0CAA0C,QAAQ,EAAE,CAAC,CAAC;QAC7E,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED,8EAA8E;IAC9E,eAAe;IACf,8EAA8E;IAE9E;;;;;OAKG;IACH,MAAM,CAAC,IAAO;QACZ,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAClB,OAAO;QACT,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;QAC1C,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC1B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACjC,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,IAAO;QACZ,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,GAAG,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QAEpC,IAAI,CAAC,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,IAAO;QACZ,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;QAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAEzC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,4BAA4B;YAC5B,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAC7B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAClC,OAAO;QACT,CAAC;QAED,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YACtB,0CAA0C;YAC1C,OAAO;QACT,CAAC;QAED,yCAAyC;QACzC,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC;IAED,sCAAsC;IACtC,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IAC1B,CAAC;IAED,8EAA8E;IAC9E,YAAY;IACZ,8EAA8E;IAE9E;;;;;;;;;;OAUG;IACH,WAAW,CAAC,MAAY,EAAE,MAAc;QACtC,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;QACjC,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC;QACrC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;QAEnB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC9D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC9D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC9D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QAE9D,KAAK,IAAI,EAAE,GAAG,KAAK,EAAE,EAAE,IAAI,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC;YACvC,KAAK,IAAI,EAAE,GAAG,KAAK,EAAE,EAAE,IAAI,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC;gBACvC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CACzB,CAAC,EAAE,GAAG,WAAW,CAAC,WAAW,CAAC,GAAG,WAAW,CAAC,WAAW;oBACtD,CAAC,EAAE,GAAG,WAAW,CAAC,WAAW,CAAC,CACjC,CAAC;gBACF,IAAI,CAAC,IAAI;oBAAE,SAAS;gBAEpB,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;oBACxB,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;oBAClC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;oBAC5B,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;oBAC5B,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,QAAQ,EAAE,CAAC;wBAClC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACrB,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;;;;OAMG;IACH,SAAS,CAAC,MAAa;QACrB,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;QACvC,MAAM,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC;QACxB,MAAM,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC;QAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC;QACrC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;QAEnB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEjD,KAAK,IAAI,EAAE,GAAG,KAAK,EAAE,EAAE,IAAI,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC;YACvC,KAAK,IAAI,EAAE,GAAG,KAAK,EAAE,EAAE,IAAI,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC;gBACvC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CACzB,CAAC,EAAE,GAAG,WAAW,CAAC,WAAW,CAAC,GAAG,WAAW,CAAC,WAAW;oBACtD,CAAC,EAAE,GAAG,WAAW,CAAC,WAAW,CAAC,CACjC,CAAC;gBACF,IAAI,CAAC,IAAI;oBAAE,SAAS;gBAEpB,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;oBACxB,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;oBAClC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,KAAK,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,MAAM,EAAE,CAAC;wBAClE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACrB,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,8EAA8E;IAC9E,cAAc;IACd,8EAA8E;IAE9E,2DAA2D;IAC3D,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;IAC9B,CAAC;IAED,8EAA8E;IAC9E,kBAAkB;IAClB,8EAA8E;IAE9E;;;OAGG;IACK,UAAU,CAAC,CAAS,EAAE,CAAS;QACrC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzC,OAAO,CAAC,EAAE,GAAG,WAAW,CAAC,WAAW,CAAC,GAAG,WAAW,CAAC,WAAW,GAAG,CAAC,EAAE,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC;IACnG,CAAC;IAED,6EAA6E;IACrE,SAAS,CAAC,GAAW,EAAE,IAAO;QACpC,IAAI,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,IAAI,GAAG,IAAI,GAAG,EAAK,CAAC;YACpB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC5B,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IAED;;;OAGG;IACK,cAAc,CAAC,GAAW,EAAE,IAAO;QACzC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAElB,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACpB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;;AApQD,8EAA8E;AAC9E,gCAAgC;AAChC,8EAA8E;AAE9E,mFAAmF;AAC3D,uBAAW,GAAG,GAAG,AAAN,CAAO;AAE1C,yDAAyD;AACjC,uBAAW,GAAG,IAAI,AAAP,CAAQ"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** Immutable 2D point / vector. All positions and directions in the SDK use this type. */
|
|
2
|
+
export interface Vec2 {
|
|
3
|
+
/** Horizontal coordinate (px, rightward positive). */
|
|
4
|
+
readonly x: number;
|
|
5
|
+
/** Vertical coordinate (px, downward positive). */
|
|
6
|
+
readonly y: number;
|
|
7
|
+
}
|
|
8
|
+
/** Frozen origin vector `{ x: 0, y: 0 }`. Safe to use as a default or sentinel. */
|
|
9
|
+
export declare const ZERO: Vec2;
|
|
10
|
+
/** Squared Euclidean distance. Prefer over distance() in hot loops to avoid sqrt. */
|
|
11
|
+
export declare function distanceSq(a: Vec2, b: Vec2): number;
|
|
12
|
+
/** Euclidean distance between two points. */
|
|
13
|
+
export declare function distance(a: Vec2, b: Vec2): number;
|
|
14
|
+
/** Linear interpolation. t = 0 returns `a`, t = 1 returns `b`. */
|
|
15
|
+
export declare function lerp(a: Vec2, b: Vec2, t: number): Vec2;
|
|
16
|
+
/** Component-wise subtraction (a − b). */
|
|
17
|
+
export declare function subtract(a: Vec2, b: Vec2): Vec2;
|
|
18
|
+
/** Length of the vector (distance from origin). */
|
|
19
|
+
export declare function magnitude(v: Vec2): number;
|
|
20
|
+
/** Unit vector in the same direction. Returns ZERO for zero-length input. */
|
|
21
|
+
export declare function normalize(v: Vec2): Vec2;
|
|
22
|
+
/** Component-wise addition. Returns a new Vec2. */
|
|
23
|
+
export declare function add(a: Vec2, b: Vec2): Vec2;
|
|
24
|
+
/** Scalar multiplication. Returns a new Vec2. */
|
|
25
|
+
export declare function scale(v: Vec2, s: number): Vec2;
|
|
26
|
+
/** Dot product of two vectors. */
|
|
27
|
+
export declare function dot(a: Vec2, b: Vec2): number;
|
|
28
|
+
/**
|
|
29
|
+
* Angle of vector from +X axis in radians (-π, +π].
|
|
30
|
+
* Returns 0 for the zero vector.
|
|
31
|
+
* Replaces `Math.atan2(dy, dx)` pattern in state handlers.
|
|
32
|
+
*/
|
|
33
|
+
export declare function angle(v: Vec2): number;
|
|
34
|
+
//# sourceMappingURL=Vec2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Vec2.d.ts","sourceRoot":"","sources":["../../src/core/Vec2.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,MAAM,WAAW,IAAI;IACnB,sDAAsD;IACtD,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,mFAAmF;AACnF,eAAO,MAAM,IAAI,EAAE,IAAoC,CAAC;AAExD,qFAAqF;AACrF,wBAAgB,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,GAAG,MAAM,CAInD;AAED,6CAA6C;AAC7C,wBAAgB,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,GAAG,MAAM,CAEjD;AAED,kEAAkE;AAClE,wBAAgB,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAEtD;AAED,0CAA0C;AAC1C,wBAAgB,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,GAAG,IAAI,CAE/C;AAED,mDAAmD;AACnD,wBAAgB,SAAS,CAAC,CAAC,EAAE,IAAI,GAAG,MAAM,CAEzC;AAED,6EAA6E;AAC7E,wBAAgB,SAAS,CAAC,CAAC,EAAE,IAAI,GAAG,IAAI,CAIvC;AAED,mDAAmD;AACnD,wBAAgB,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,GAAG,IAAI,CAE1C;AAED,iDAAiD;AACjD,wBAAgB,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAE9C;AAED,kCAAkC;AAClC,wBAAgB,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,GAAG,MAAM,CAE5C;AAED;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,IAAI,GAAG,MAAM,CAErC"}
|