@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,123 @@
|
|
|
1
|
+
/** Snapshot of Clock state for save/load. */
|
|
2
|
+
export interface IClockState {
|
|
3
|
+
/** Total elapsed game-seconds since the simulation started. */
|
|
4
|
+
readonly totalGameSeconds: number;
|
|
5
|
+
/** Time acceleration factor at the moment of save. */
|
|
6
|
+
readonly timeFactor: number;
|
|
7
|
+
/** Whether the clock was paused at the moment of save. */
|
|
8
|
+
readonly paused?: boolean;
|
|
9
|
+
}
|
|
10
|
+
/** Configuration accepted by the Clock constructor. */
|
|
11
|
+
export interface IClockConfig {
|
|
12
|
+
/** Game-seconds per real-second. Default: 10. */
|
|
13
|
+
timeFactor?: number;
|
|
14
|
+
/** Starting hour (0-23). Default: 8 (08:00). */
|
|
15
|
+
startHour?: number;
|
|
16
|
+
/** Starting day number (1-based). Default: 1. */
|
|
17
|
+
startDay?: number;
|
|
18
|
+
/** First hour considered daytime (0-23). Default: 6. */
|
|
19
|
+
dayStartHour?: number;
|
|
20
|
+
/** Last hour considered daytime, exclusive (0-23). Default: 21. */
|
|
21
|
+
dayEndHour?: number;
|
|
22
|
+
/** Called when the in-game hour changes. */
|
|
23
|
+
onHourChanged?: (hour: number, day: number) => void;
|
|
24
|
+
/** Called when the day/night state flips. */
|
|
25
|
+
onDayNightChanged?: (isDay: boolean) => void;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Accelerated in-game clock with day/night cycle detection.
|
|
29
|
+
*
|
|
30
|
+
* Framework-agnostic: no dependency on Phaser, EventBus, or any renderer.
|
|
31
|
+
* Transition notifications are delivered via optional callback functions
|
|
32
|
+
* supplied at construction time.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* const clock = new Clock({
|
|
37
|
+
* timeFactor: 10,
|
|
38
|
+
* startHour: 8,
|
|
39
|
+
* onHourChanged: (h, d) => console.log(`Day ${d}, ${h}:00`),
|
|
40
|
+
* onDayNightChanged: (day) => console.log(day ? 'Dawn' : 'Dusk'),
|
|
41
|
+
* });
|
|
42
|
+
*
|
|
43
|
+
* // Each frame:
|
|
44
|
+
* clock.update(deltaMs);
|
|
45
|
+
*
|
|
46
|
+
* console.log(clock.hour); // 8
|
|
47
|
+
* console.log(clock.isDay); // true
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare class Clock {
|
|
51
|
+
/**
|
|
52
|
+
* Total elapsed game-seconds since the simulation epoch (day 1, 00:00:00).
|
|
53
|
+
* This is the single source of truth — hour, minute, day are all derived.
|
|
54
|
+
*/
|
|
55
|
+
private gameSeconds;
|
|
56
|
+
/** Game-seconds per real-second. */
|
|
57
|
+
private _timeFactor;
|
|
58
|
+
/** Cached hour for boundary detection. */
|
|
59
|
+
private previousHour;
|
|
60
|
+
/** Cached day/night state for transition detection. */
|
|
61
|
+
private wasDaytime;
|
|
62
|
+
/** When true, update() is a no-op — time stands still. */
|
|
63
|
+
private _paused;
|
|
64
|
+
/** First hour of daytime (inclusive). */
|
|
65
|
+
private readonly dayStartHour;
|
|
66
|
+
/** Last hour of daytime (exclusive). */
|
|
67
|
+
private readonly dayEndHour;
|
|
68
|
+
private readonly onHourChanged?;
|
|
69
|
+
private readonly onDayNightChanged?;
|
|
70
|
+
constructor(config?: IClockConfig);
|
|
71
|
+
/** Current in-game hour (0-23). */
|
|
72
|
+
get hour(): number;
|
|
73
|
+
/** Current in-game minute within the current hour (0-59). */
|
|
74
|
+
get minute(): number;
|
|
75
|
+
/** Current in-game day (1-based). */
|
|
76
|
+
get day(): number;
|
|
77
|
+
/** Total elapsed game-seconds since epoch. */
|
|
78
|
+
get totalGameSeconds(): number;
|
|
79
|
+
/** True during daytime hours (configurable, default 06:00 - 20:59). */
|
|
80
|
+
get isDay(): boolean;
|
|
81
|
+
/** True during nighttime hours (21:00 - 05:59). */
|
|
82
|
+
get isNight(): boolean;
|
|
83
|
+
/** Current time acceleration factor. */
|
|
84
|
+
get timeFactor(): number;
|
|
85
|
+
/** `true` when the clock is paused — `update()` becomes a no-op. */
|
|
86
|
+
get isPaused(): boolean;
|
|
87
|
+
/**
|
|
88
|
+
* Advance the in-game clock by `deltaMs` real milliseconds multiplied by
|
|
89
|
+
* the time factor. Call once per frame.
|
|
90
|
+
*
|
|
91
|
+
* Detects hour boundaries and day/night transitions, invoking the
|
|
92
|
+
* corresponding callbacks when they occur.
|
|
93
|
+
*
|
|
94
|
+
* @param deltaMs - Real milliseconds elapsed since the previous frame.
|
|
95
|
+
*/
|
|
96
|
+
update(deltaMs: number): void;
|
|
97
|
+
/** Freeze time — `update()` becomes a no-op until `resume()` is called. */
|
|
98
|
+
pause(): void;
|
|
99
|
+
/** Resume time advancement after a `pause()`. */
|
|
100
|
+
resume(): void;
|
|
101
|
+
/**
|
|
102
|
+
* Set the in-game time to an exact hour (and optionally minute) on the
|
|
103
|
+
* current day. Does not fire transition callbacks — the next `update()`
|
|
104
|
+
* call will detect and emit any resulting transitions naturally.
|
|
105
|
+
*
|
|
106
|
+
* @param hour - Target hour (0-23).
|
|
107
|
+
* @param minute - Target minute (0-59). Default: 0.
|
|
108
|
+
*/
|
|
109
|
+
setTime(hour: number, minute?: number): void;
|
|
110
|
+
/** Capture the current clock state as a plain object for persistence. */
|
|
111
|
+
serialize(): IClockState;
|
|
112
|
+
/**
|
|
113
|
+
* Restore a Clock from a previously serialised state.
|
|
114
|
+
*
|
|
115
|
+
* Callbacks must be re-supplied because functions are not serialisable.
|
|
116
|
+
* If you need the same callbacks, pass them via the optional config parameter.
|
|
117
|
+
*
|
|
118
|
+
* @param state - Snapshot previously returned by {@link serialize}.
|
|
119
|
+
* @param config - Optional callbacks and overrides.
|
|
120
|
+
*/
|
|
121
|
+
static fromState(state: IClockState, config?: Pick<IClockConfig, 'onHourChanged' | 'onDayNightChanged' | 'dayStartHour' | 'dayEndHour'>): Clock;
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=Clock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Clock.d.ts","sourceRoot":"","sources":["../../src/core/Clock.ts"],"names":[],"mappings":"AAqBA,6CAA6C;AAC7C,MAAM,WAAW,WAAW;IAC1B,+DAA+D;IAC/D,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,sDAAsD;IACtD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC3B;AAMD,uDAAuD;AACvD,MAAM,WAAW,YAAY;IAC3B,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4CAA4C;IAC5C,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,6CAA6C;IAC7C,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC9C;AAmBD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,KAAK;IAKhB;;;OAGG;IACH,OAAO,CAAC,WAAW,CAAS;IAE5B,oCAAoC;IACpC,OAAO,CAAC,WAAW,CAAS;IAE5B,0CAA0C;IAC1C,OAAO,CAAC,YAAY,CAAS;IAE7B,uDAAuD;IACvD,OAAO,CAAC,UAAU,CAAU;IAE5B,0DAA0D;IAC1D,OAAO,CAAC,OAAO,CAAS;IAExB,yCAAyC;IACzC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAkC;IAE/D,wCAAwC;IACxC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgC;IAG3D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAsC;IACrE,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAA2B;gBAMlD,MAAM,GAAE,YAAiB;IAuCrC,mCAAmC;IACnC,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,6DAA6D;IAC7D,IAAI,MAAM,IAAI,MAAM,CAInB;IAED,qCAAqC;IACrC,IAAI,GAAG,IAAI,MAAM,CAEhB;IAED,8CAA8C;IAC9C,IAAI,gBAAgB,IAAI,MAAM,CAE7B;IAED,uEAAuE;IACvE,IAAI,KAAK,IAAI,OAAO,CAGnB;IAED,mDAAmD;IACnD,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,wCAAwC;IACxC,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,oEAAoE;IACpE,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAMD;;;;;;;;OAQG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IA0B7B,2EAA2E;IAC3E,KAAK,IAAI,IAAI;IAIb,iDAAiD;IACjD,MAAM,IAAI,IAAI;IAQd;;;;;;;OAOG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAU,GAAG,IAAI;IAsB/C,yEAAyE;IACzE,SAAS,IAAI,WAAW;IAQxB;;;;;;;;OAQG;IACH,MAAM,CAAC,SAAS,CACd,KAAK,EAAE,WAAW,EAClB,MAAM,CAAC,EAAE,IAAI,CAAC,YAAY,EAAE,eAAe,GAAG,mBAAmB,GAAG,cAAc,GAAG,YAAY,CAAC,GACjG,KAAK;CAiBT"}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
// core/Clock.ts
|
|
2
|
+
// Framework-agnostic game time manager — accelerated day/night cycle.
|
|
3
|
+
//
|
|
4
|
+
// Responsibilities:
|
|
5
|
+
// - Advance an in-game clock decoupled from wall-clock time via a
|
|
6
|
+
// configurable timeFactor (e.g. 10 = 10 game-seconds per real-second).
|
|
7
|
+
// - Wrap at 24h and expose human-readable helpers (hour, minute, isDay).
|
|
8
|
+
// - Invoke optional callbacks on hour boundaries and day/night transitions,
|
|
9
|
+
// keeping Clock decoupled from any specific EventBus implementation.
|
|
10
|
+
//
|
|
11
|
+
// Design notes:
|
|
12
|
+
// - All time arithmetic uses seconds (not milliseconds) to avoid large
|
|
13
|
+
// intermediate values and keep the math readable.
|
|
14
|
+
// - Day boundary detection uses a cached previousHour comparison —
|
|
15
|
+
// no string formatting on the hot path.
|
|
16
|
+
// - Zero external dependencies.
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// Constants
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
const SECONDS_PER_MINUTE = 60;
|
|
21
|
+
const SECONDS_PER_HOUR = 3600;
|
|
22
|
+
const SECONDS_PER_DAY = 86400;
|
|
23
|
+
const DEFAULT_DAY_START_HOUR = 6;
|
|
24
|
+
const DEFAULT_DAY_END_HOUR = 21;
|
|
25
|
+
const DEFAULT_TIME_FACTOR = 10;
|
|
26
|
+
const DEFAULT_START_HOUR = 8;
|
|
27
|
+
const DEFAULT_START_DAY = 1;
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// Clock
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
/**
|
|
32
|
+
* Accelerated in-game clock with day/night cycle detection.
|
|
33
|
+
*
|
|
34
|
+
* Framework-agnostic: no dependency on Phaser, EventBus, or any renderer.
|
|
35
|
+
* Transition notifications are delivered via optional callback functions
|
|
36
|
+
* supplied at construction time.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* const clock = new Clock({
|
|
41
|
+
* timeFactor: 10,
|
|
42
|
+
* startHour: 8,
|
|
43
|
+
* onHourChanged: (h, d) => console.log(`Day ${d}, ${h}:00`),
|
|
44
|
+
* onDayNightChanged: (day) => console.log(day ? 'Dawn' : 'Dusk'),
|
|
45
|
+
* });
|
|
46
|
+
*
|
|
47
|
+
* // Each frame:
|
|
48
|
+
* clock.update(deltaMs);
|
|
49
|
+
*
|
|
50
|
+
* console.log(clock.hour); // 8
|
|
51
|
+
* console.log(clock.isDay); // true
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export class Clock {
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
// Construction
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
constructor(config = {}) {
|
|
59
|
+
/** When true, update() is a no-op — time stands still. */
|
|
60
|
+
this._paused = false;
|
|
61
|
+
/** First hour of daytime (inclusive). */
|
|
62
|
+
this.dayStartHour = DEFAULT_DAY_START_HOUR;
|
|
63
|
+
/** Last hour of daytime (exclusive). */
|
|
64
|
+
this.dayEndHour = DEFAULT_DAY_END_HOUR;
|
|
65
|
+
const { timeFactor = DEFAULT_TIME_FACTOR, startHour = DEFAULT_START_HOUR, startDay = DEFAULT_START_DAY, dayStartHour = DEFAULT_DAY_START_HOUR, dayEndHour = DEFAULT_DAY_END_HOUR, onHourChanged, onDayNightChanged, } = config;
|
|
66
|
+
if (timeFactor <= 0) {
|
|
67
|
+
throw new RangeError(`Clock: timeFactor must be > 0, got ${timeFactor}`);
|
|
68
|
+
}
|
|
69
|
+
if (startHour < 0 || startHour > 23) {
|
|
70
|
+
throw new RangeError(`Clock: startHour must be 0-23, got ${startHour}`);
|
|
71
|
+
}
|
|
72
|
+
if (startDay < 1) {
|
|
73
|
+
throw new RangeError(`Clock: startDay must be >= 1, got ${startDay}`);
|
|
74
|
+
}
|
|
75
|
+
this._timeFactor = timeFactor;
|
|
76
|
+
this.dayStartHour = dayStartHour;
|
|
77
|
+
this.dayEndHour = dayEndHour;
|
|
78
|
+
this.onHourChanged = onHourChanged;
|
|
79
|
+
this.onDayNightChanged = onDayNightChanged;
|
|
80
|
+
// Convert start parameters to total game-seconds.
|
|
81
|
+
this.gameSeconds = (startDay - 1) * SECONDS_PER_DAY + startHour * SECONDS_PER_HOUR;
|
|
82
|
+
// Initialize boundary-detection caches.
|
|
83
|
+
this.previousHour = this.hour;
|
|
84
|
+
this.wasDaytime = this.isDay;
|
|
85
|
+
}
|
|
86
|
+
// ---------------------------------------------------------------------------
|
|
87
|
+
// Readonly properties
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
/** Current in-game hour (0-23). */
|
|
90
|
+
get hour() {
|
|
91
|
+
return Math.floor((this.gameSeconds % SECONDS_PER_DAY) / SECONDS_PER_HOUR);
|
|
92
|
+
}
|
|
93
|
+
/** Current in-game minute within the current hour (0-59). */
|
|
94
|
+
get minute() {
|
|
95
|
+
return Math.floor((this.gameSeconds % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE);
|
|
96
|
+
}
|
|
97
|
+
/** Current in-game day (1-based). */
|
|
98
|
+
get day() {
|
|
99
|
+
return Math.floor(this.gameSeconds / SECONDS_PER_DAY) + 1;
|
|
100
|
+
}
|
|
101
|
+
/** Total elapsed game-seconds since epoch. */
|
|
102
|
+
get totalGameSeconds() {
|
|
103
|
+
return this.gameSeconds;
|
|
104
|
+
}
|
|
105
|
+
/** True during daytime hours (configurable, default 06:00 - 20:59). */
|
|
106
|
+
get isDay() {
|
|
107
|
+
const h = this.hour;
|
|
108
|
+
return h >= this.dayStartHour && h < this.dayEndHour;
|
|
109
|
+
}
|
|
110
|
+
/** True during nighttime hours (21:00 - 05:59). */
|
|
111
|
+
get isNight() {
|
|
112
|
+
return !this.isDay;
|
|
113
|
+
}
|
|
114
|
+
/** Current time acceleration factor. */
|
|
115
|
+
get timeFactor() {
|
|
116
|
+
return this._timeFactor;
|
|
117
|
+
}
|
|
118
|
+
/** `true` when the clock is paused — `update()` becomes a no-op. */
|
|
119
|
+
get isPaused() {
|
|
120
|
+
return this._paused;
|
|
121
|
+
}
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
// Frame update
|
|
124
|
+
// ---------------------------------------------------------------------------
|
|
125
|
+
/**
|
|
126
|
+
* Advance the in-game clock by `deltaMs` real milliseconds multiplied by
|
|
127
|
+
* the time factor. Call once per frame.
|
|
128
|
+
*
|
|
129
|
+
* Detects hour boundaries and day/night transitions, invoking the
|
|
130
|
+
* corresponding callbacks when they occur.
|
|
131
|
+
*
|
|
132
|
+
* @param deltaMs - Real milliseconds elapsed since the previous frame.
|
|
133
|
+
*/
|
|
134
|
+
update(deltaMs) {
|
|
135
|
+
if (this._paused)
|
|
136
|
+
return;
|
|
137
|
+
// Convert real ms to game-seconds and advance.
|
|
138
|
+
this.gameSeconds += (deltaMs / 1000) * this._timeFactor;
|
|
139
|
+
const currentHour = this.hour;
|
|
140
|
+
// --- Hour boundary ---
|
|
141
|
+
if (currentHour !== this.previousHour) {
|
|
142
|
+
this.previousHour = currentHour;
|
|
143
|
+
this.onHourChanged?.(currentHour, this.day);
|
|
144
|
+
}
|
|
145
|
+
// --- Day/night transition (inline to avoid recomputing hour via isDay getter) ---
|
|
146
|
+
const nowIsDay = currentHour >= this.dayStartHour && currentHour < this.dayEndHour;
|
|
147
|
+
if (nowIsDay !== this.wasDaytime) {
|
|
148
|
+
this.wasDaytime = nowIsDay;
|
|
149
|
+
this.onDayNightChanged?.(nowIsDay);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// ---------------------------------------------------------------------------
|
|
153
|
+
// Pause / Resume
|
|
154
|
+
// ---------------------------------------------------------------------------
|
|
155
|
+
/** Freeze time — `update()` becomes a no-op until `resume()` is called. */
|
|
156
|
+
pause() {
|
|
157
|
+
this._paused = true;
|
|
158
|
+
}
|
|
159
|
+
/** Resume time advancement after a `pause()`. */
|
|
160
|
+
resume() {
|
|
161
|
+
this._paused = false;
|
|
162
|
+
}
|
|
163
|
+
// ---------------------------------------------------------------------------
|
|
164
|
+
// Manual override
|
|
165
|
+
// ---------------------------------------------------------------------------
|
|
166
|
+
/**
|
|
167
|
+
* Set the in-game time to an exact hour (and optionally minute) on the
|
|
168
|
+
* current day. Does not fire transition callbacks — the next `update()`
|
|
169
|
+
* call will detect and emit any resulting transitions naturally.
|
|
170
|
+
*
|
|
171
|
+
* @param hour - Target hour (0-23).
|
|
172
|
+
* @param minute - Target minute (0-59). Default: 0.
|
|
173
|
+
*/
|
|
174
|
+
setTime(hour, minute = 0) {
|
|
175
|
+
if (hour < 0 || hour > 23) {
|
|
176
|
+
throw new RangeError(`Clock.setTime: hour must be 0-23, got ${hour}`);
|
|
177
|
+
}
|
|
178
|
+
if (minute < 0 || minute > 59) {
|
|
179
|
+
throw new RangeError(`Clock.setTime: minute must be 0-59, got ${minute}`);
|
|
180
|
+
}
|
|
181
|
+
// Preserve the current day, replace only the time-of-day portion.
|
|
182
|
+
const dayOffset = (this.day - 1) * SECONDS_PER_DAY;
|
|
183
|
+
this.gameSeconds = dayOffset + hour * SECONDS_PER_HOUR + minute * SECONDS_PER_MINUTE;
|
|
184
|
+
// Update caches so the next update() doesn't spuriously fire events
|
|
185
|
+
// for the transition we just caused.
|
|
186
|
+
this.previousHour = this.hour;
|
|
187
|
+
this.wasDaytime = this.isDay;
|
|
188
|
+
}
|
|
189
|
+
// ---------------------------------------------------------------------------
|
|
190
|
+
// Serialisation
|
|
191
|
+
// ---------------------------------------------------------------------------
|
|
192
|
+
/** Capture the current clock state as a plain object for persistence. */
|
|
193
|
+
serialize() {
|
|
194
|
+
return {
|
|
195
|
+
totalGameSeconds: this.gameSeconds,
|
|
196
|
+
timeFactor: this._timeFactor,
|
|
197
|
+
paused: this._paused || undefined,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Restore a Clock from a previously serialised state.
|
|
202
|
+
*
|
|
203
|
+
* Callbacks must be re-supplied because functions are not serialisable.
|
|
204
|
+
* If you need the same callbacks, pass them via the optional config parameter.
|
|
205
|
+
*
|
|
206
|
+
* @param state - Snapshot previously returned by {@link serialize}.
|
|
207
|
+
* @param config - Optional callbacks and overrides.
|
|
208
|
+
*/
|
|
209
|
+
static fromState(state, config) {
|
|
210
|
+
const clock = new Clock({
|
|
211
|
+
timeFactor: state.timeFactor,
|
|
212
|
+
startHour: 0,
|
|
213
|
+
startDay: 1,
|
|
214
|
+
...config,
|
|
215
|
+
});
|
|
216
|
+
// Override the computed gameSeconds with the saved value.
|
|
217
|
+
if (!Number.isFinite(state.totalGameSeconds) || state.totalGameSeconds < 0) {
|
|
218
|
+
throw new Error(`Clock.fromState: invalid totalGameSeconds (${state.totalGameSeconds})`);
|
|
219
|
+
}
|
|
220
|
+
clock.gameSeconds = state.totalGameSeconds;
|
|
221
|
+
clock.previousHour = clock.hour;
|
|
222
|
+
clock.wasDaytime = clock.isDay;
|
|
223
|
+
if (state.paused)
|
|
224
|
+
clock._paused = true;
|
|
225
|
+
return clock;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
//# sourceMappingURL=Clock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Clock.js","sourceRoot":"","sources":["../../src/core/Clock.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration for the DevTools inspector snapshot.
|
|
3
|
+
*/
|
|
4
|
+
export interface IDevToolsConfig {
|
|
5
|
+
/** Include per-plugin inspection data. Default: true. */
|
|
6
|
+
readonly includePlugins?: boolean;
|
|
7
|
+
/** Include spatial grid statistics. Default: true. */
|
|
8
|
+
readonly includeSpatialGrid?: boolean;
|
|
9
|
+
/** Include port registry info. Default: true. */
|
|
10
|
+
readonly includePorts?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Runtime snapshot of the kernel state for developer tooling.
|
|
14
|
+
*
|
|
15
|
+
* Returned by `kernel.inspect()`. Designed for overlay UIs, debug panels,
|
|
16
|
+
* or automated monitoring.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* const snapshot = kernel.inspect();
|
|
21
|
+
* console.log(`Tick: ${snapshot.tick}, Clock: ${snapshot.clock.gameHour}`);
|
|
22
|
+
* for (const [name, data] of Object.entries(snapshot.plugins ?? {})) {
|
|
23
|
+
* console.log(` ${name}:`, data);
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export interface IDevToolsSnapshot {
|
|
28
|
+
/** Current simulation tick. */
|
|
29
|
+
readonly tick: number;
|
|
30
|
+
/** Whether the kernel is running. */
|
|
31
|
+
readonly running: boolean;
|
|
32
|
+
/** Whether the kernel is paused. */
|
|
33
|
+
readonly paused: boolean;
|
|
34
|
+
/** Clock state. */
|
|
35
|
+
readonly clock: {
|
|
36
|
+
readonly gameHour: number;
|
|
37
|
+
readonly isDay: boolean;
|
|
38
|
+
readonly elapsedMs: number;
|
|
39
|
+
};
|
|
40
|
+
/** Spatial grid stats (when includeSpatialGrid is true). */
|
|
41
|
+
readonly spatialGrid?: {
|
|
42
|
+
readonly entityCount: number;
|
|
43
|
+
readonly cellSize: number;
|
|
44
|
+
};
|
|
45
|
+
/** Registered port IDs (when includePorts is true). */
|
|
46
|
+
readonly ports?: readonly string[];
|
|
47
|
+
/** Installed plugin names in dependency order. */
|
|
48
|
+
readonly pluginNames: readonly string[];
|
|
49
|
+
/** Per-plugin inspection data (when includePlugins is true). */
|
|
50
|
+
readonly plugins?: Readonly<Record<string, Record<string, unknown>>>;
|
|
51
|
+
}
|
|
52
|
+
export declare const DEFAULT_DEVTOOLS_CONFIG: IDevToolsConfig;
|
|
53
|
+
//# sourceMappingURL=DevToolsInspector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DevToolsInspector.d.ts","sourceRoot":"","sources":["../../src/core/DevToolsInspector.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,yDAAyD;IACzD,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC,sDAAsD;IACtD,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IACtC,iDAAiD;IACjD,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;CACjC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,iBAAiB;IAChC,+BAA+B;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qCAAqC;IACrC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,oCAAoC;IACpC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,mBAAmB;IACnB,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;QACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;KAC5B,CAAC;IACF,4DAA4D;IAC5D,QAAQ,CAAC,WAAW,CAAC,EAAE;QACrB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;QAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;KAC3B,CAAC;IACF,uDAAuD;IACvD,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,kDAAkD;IAClD,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,gEAAgE;IAChE,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;CACtE;AAED,eAAO,MAAM,uBAAuB,EAAE,eAIrC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DevToolsInspector.js","sourceRoot":"","sources":["../../src/core/DevToolsInspector.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAC5B,sDAAsD;AAuDtD,MAAM,CAAC,MAAM,uBAAuB,GAAoB;IACtD,cAAc,EAAE,IAAI;IACpB,kBAAkB,EAAE,IAAI;IACxB,YAAY,EAAE,IAAI;CACnB,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export type DiagnosticSeverity = 'error' | 'warning' | 'info';
|
|
2
|
+
/** A single diagnostic message produced during kernel validation. */
|
|
3
|
+
export interface IDiagnostic {
|
|
4
|
+
/** How severe the problem is. Errors block init; warnings and infos do not. */
|
|
5
|
+
readonly severity: DiagnosticSeverity;
|
|
6
|
+
/** Origin of the diagnostic: `'kernel'`, a plugin name, or `'config'`. */
|
|
7
|
+
readonly source: string;
|
|
8
|
+
/** Dot-separated path to the problematic value (e.g. `'ports.pathfinder'`). */
|
|
9
|
+
readonly path: string;
|
|
10
|
+
/** Human-readable explanation of the problem. */
|
|
11
|
+
readonly message: string;
|
|
12
|
+
/** Optional suggestion for how to fix it (e.g. `'Did you mean "bandits"?'`). */
|
|
13
|
+
readonly hint?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Thrown by {@link DiagnosticsCollector.throwIfErrors} when at least one
|
|
17
|
+
* diagnostic with severity `'error'` has been collected.
|
|
18
|
+
*/
|
|
19
|
+
export declare class ALifeValidationError extends Error {
|
|
20
|
+
readonly diagnostics: readonly IDiagnostic[];
|
|
21
|
+
constructor(diagnostics: readonly IDiagnostic[]);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Accumulates diagnostics during kernel initialization.
|
|
25
|
+
*
|
|
26
|
+
* After all validation passes complete, call {@link throwIfErrors} to
|
|
27
|
+
* either let execution continue (no errors) or throw a single
|
|
28
|
+
* {@link ALifeValidationError} containing every collected problem.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* const diag = new DiagnosticsCollector();
|
|
33
|
+
* diag.error('kernel', 'ports.entityAdapter', 'Required port not provided');
|
|
34
|
+
* diag.warning('surge', 'config.surge.durationMs', 'Duration seems too short');
|
|
35
|
+
* diag.throwIfErrors(); // throws ALifeValidationError
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare class DiagnosticsCollector {
|
|
39
|
+
private readonly items;
|
|
40
|
+
/** Add a raw diagnostic entry. */
|
|
41
|
+
add(diagnostic: IDiagnostic): void;
|
|
42
|
+
/** Shorthand: add an error diagnostic. */
|
|
43
|
+
error(source: string, path: string, message: string, hint?: string): void;
|
|
44
|
+
/** Shorthand: add a warning diagnostic. */
|
|
45
|
+
warning(source: string, path: string, message: string, hint?: string): void;
|
|
46
|
+
/** Shorthand: add an informational diagnostic. */
|
|
47
|
+
info(source: string, path: string, message: string, hint?: string): void;
|
|
48
|
+
/** All error-severity diagnostics. */
|
|
49
|
+
get errors(): IDiagnostic[];
|
|
50
|
+
/** All warning-severity diagnostics. */
|
|
51
|
+
get warnings(): IDiagnostic[];
|
|
52
|
+
/** All collected diagnostics in insertion order. */
|
|
53
|
+
get all(): readonly IDiagnostic[];
|
|
54
|
+
/** `true` when at least one error-severity diagnostic exists. */
|
|
55
|
+
get hasErrors(): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Throw {@link ALifeValidationError} if any errors were collected.
|
|
58
|
+
* Safe to call when only warnings/infos are present — does nothing.
|
|
59
|
+
*/
|
|
60
|
+
throwIfErrors(): void;
|
|
61
|
+
/** Format all diagnostics as a human-readable multi-line string. */
|
|
62
|
+
format(): string;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=Diagnostics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Diagnostics.d.ts","sourceRoot":"","sources":["../../src/core/Diagnostics.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAE9D,qEAAqE;AACrE,MAAM,WAAW,WAAW;IAC1B,+EAA+E;IAC/E,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAC;IACtC,0EAA0E;IAC1E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,+EAA+E;IAC/E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,gFAAgF;IAChF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAMD;;;GAGG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,WAAW,EAAE,SAAS,WAAW,EAAE,CAAC;gBAEjC,WAAW,EAAE,SAAS,WAAW,EAAE;CAKhD;AAMD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqB;IAE3C,kCAAkC;IAClC,GAAG,CAAC,UAAU,EAAE,WAAW,GAAG,IAAI;IAIlC,0CAA0C;IAC1C,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAIzE,2CAA2C;IAC3C,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAI3E,kDAAkD;IAClD,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAIxE,sCAAsC;IACtC,IAAI,MAAM,IAAI,WAAW,EAAE,CAE1B;IAED,wCAAwC;IACxC,IAAI,QAAQ,IAAI,WAAW,EAAE,CAE5B;IAED,oDAAoD;IACpD,IAAI,GAAG,IAAI,SAAS,WAAW,EAAE,CAEhC;IAED,iEAAiE;IACjE,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED;;;OAGG;IACH,aAAa,IAAI,IAAI;IAMrB,oEAAoE;IACpE,MAAM,IAAI,MAAM;CAGjB"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// core/Diagnostics.ts
|
|
2
|
+
// Structured error/warning collector for kernel initialization.
|
|
3
|
+
//
|
|
4
|
+
// Instead of throwing on the first validation failure, the kernel collects
|
|
5
|
+
// all problems into a DiagnosticsCollector and returns it from init().
|
|
6
|
+
// This gives developers a complete picture of what's wrong — missing ports,
|
|
7
|
+
// unresolved plugin dependencies, config issues — in a single pass.
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Validation error
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
/**
|
|
12
|
+
* Thrown by {@link DiagnosticsCollector.throwIfErrors} when at least one
|
|
13
|
+
* diagnostic with severity `'error'` has been collected.
|
|
14
|
+
*/
|
|
15
|
+
export class ALifeValidationError extends Error {
|
|
16
|
+
constructor(diagnostics) {
|
|
17
|
+
super(`A-Life validation failed:\n${formatDiagnostics(diagnostics)}`);
|
|
18
|
+
this.name = 'ALifeValidationError';
|
|
19
|
+
this.diagnostics = diagnostics;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// DiagnosticsCollector
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
/**
|
|
26
|
+
* Accumulates diagnostics during kernel initialization.
|
|
27
|
+
*
|
|
28
|
+
* After all validation passes complete, call {@link throwIfErrors} to
|
|
29
|
+
* either let execution continue (no errors) or throw a single
|
|
30
|
+
* {@link ALifeValidationError} containing every collected problem.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* const diag = new DiagnosticsCollector();
|
|
35
|
+
* diag.error('kernel', 'ports.entityAdapter', 'Required port not provided');
|
|
36
|
+
* diag.warning('surge', 'config.surge.durationMs', 'Duration seems too short');
|
|
37
|
+
* diag.throwIfErrors(); // throws ALifeValidationError
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export class DiagnosticsCollector {
|
|
41
|
+
constructor() {
|
|
42
|
+
this.items = [];
|
|
43
|
+
}
|
|
44
|
+
/** Add a raw diagnostic entry. */
|
|
45
|
+
add(diagnostic) {
|
|
46
|
+
this.items.push(diagnostic);
|
|
47
|
+
}
|
|
48
|
+
/** Shorthand: add an error diagnostic. */
|
|
49
|
+
error(source, path, message, hint) {
|
|
50
|
+
this.items.push({ severity: 'error', source, path, message, hint });
|
|
51
|
+
}
|
|
52
|
+
/** Shorthand: add a warning diagnostic. */
|
|
53
|
+
warning(source, path, message, hint) {
|
|
54
|
+
this.items.push({ severity: 'warning', source, path, message, hint });
|
|
55
|
+
}
|
|
56
|
+
/** Shorthand: add an informational diagnostic. */
|
|
57
|
+
info(source, path, message, hint) {
|
|
58
|
+
this.items.push({ severity: 'info', source, path, message, hint });
|
|
59
|
+
}
|
|
60
|
+
/** All error-severity diagnostics. */
|
|
61
|
+
get errors() {
|
|
62
|
+
return this.items.filter((d) => d.severity === 'error');
|
|
63
|
+
}
|
|
64
|
+
/** All warning-severity diagnostics. */
|
|
65
|
+
get warnings() {
|
|
66
|
+
return this.items.filter((d) => d.severity === 'warning');
|
|
67
|
+
}
|
|
68
|
+
/** All collected diagnostics in insertion order. */
|
|
69
|
+
get all() {
|
|
70
|
+
return this.items;
|
|
71
|
+
}
|
|
72
|
+
/** `true` when at least one error-severity diagnostic exists. */
|
|
73
|
+
get hasErrors() {
|
|
74
|
+
return this.items.some((d) => d.severity === 'error');
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Throw {@link ALifeValidationError} if any errors were collected.
|
|
78
|
+
* Safe to call when only warnings/infos are present — does nothing.
|
|
79
|
+
*/
|
|
80
|
+
throwIfErrors() {
|
|
81
|
+
if (this.hasErrors) {
|
|
82
|
+
throw new ALifeValidationError(this.errors);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/** Format all diagnostics as a human-readable multi-line string. */
|
|
86
|
+
format() {
|
|
87
|
+
return formatDiagnostics(this.items);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
// Formatting
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
const SEVERITY_ICON = {
|
|
94
|
+
error: 'ERROR',
|
|
95
|
+
warning: 'WARN',
|
|
96
|
+
info: 'INFO',
|
|
97
|
+
};
|
|
98
|
+
function formatDiagnostics(diagnostics) {
|
|
99
|
+
return diagnostics
|
|
100
|
+
.map((d) => {
|
|
101
|
+
const prefix = `[${SEVERITY_ICON[d.severity]}] ${d.source} > ${d.path}`;
|
|
102
|
+
const hint = d.hint ? `\n hint: ${d.hint}` : '';
|
|
103
|
+
return ` ${prefix}: ${d.message}${hint}`;
|
|
104
|
+
})
|
|
105
|
+
.join('\n');
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=Diagnostics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Diagnostics.js","sourceRoot":"","sources":["../../src/core/Diagnostics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contract for subsystems that support save/load.
|
|
3
|
+
*
|
|
4
|
+
* TState must be a plain JSON-serialisable object (no functions, Maps, Sets).
|
|
5
|
+
*/
|
|
6
|
+
export interface ISerializable<TState> {
|
|
7
|
+
/** Capture the current state as a plain JSON-serialisable object. */
|
|
8
|
+
serialize(): TState;
|
|
9
|
+
/** Overwrite internal state from a previously serialised snapshot. */
|
|
10
|
+
restore(state: TState): void;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=ISerializable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ISerializable.d.ts","sourceRoot":"","sources":["../../src/core/ISerializable.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,aAAa,CAAC,MAAM;IACnC,qEAAqE;IACrE,SAAS,IAAI,MAAM,CAAC;IACpB,sEAAsE;IACtE,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ISerializable.js","sourceRoot":"","sources":["../../src/core/ISerializable.ts"],"names":[],"mappings":""}
|