@phalanx-engine/ecs 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.
Files changed (89) hide show
  1. package/README.md +666 -0
  2. package/dist/Component.d.ts +7 -0
  3. package/dist/Component.d.ts.map +1 -0
  4. package/dist/Component.js +7 -0
  5. package/dist/Entity.d.ts +25 -0
  6. package/dist/Entity.d.ts.map +1 -0
  7. package/dist/Entity.js +58 -0
  8. package/dist/EntityManager.d.ts +36 -0
  9. package/dist/EntityManager.d.ts.map +1 -0
  10. package/dist/EntityManager.js +218 -0
  11. package/dist/EventBus.d.ts +15 -0
  12. package/dist/EventBus.d.ts.map +1 -0
  13. package/dist/EventBus.js +69 -0
  14. package/dist/GameSystem.d.ts +23 -0
  15. package/dist/GameSystem.d.ts.map +1 -0
  16. package/dist/GameSystem.js +43 -0
  17. package/dist/GameWorld.d.ts +69 -0
  18. package/dist/GameWorld.d.ts.map +1 -0
  19. package/dist/GameWorld.js +237 -0
  20. package/dist/IAbilitySystem.d.ts +18 -0
  21. package/dist/IAbilitySystem.d.ts.map +1 -0
  22. package/dist/IAbilitySystem.js +1 -0
  23. package/dist/IPhysicsWorld.d.ts +21 -0
  24. package/dist/IPhysicsWorld.d.ts.map +1 -0
  25. package/dist/IPhysicsWorld.js +1 -0
  26. package/dist/ISystemLifecycleHooks.d.ts +18 -0
  27. package/dist/ISystemLifecycleHooks.d.ts.map +1 -0
  28. package/dist/ISystemLifecycleHooks.js +12 -0
  29. package/dist/ITickFrameProvider.d.ts +24 -0
  30. package/dist/ITickFrameProvider.d.ts.map +1 -0
  31. package/dist/ITickFrameProvider.js +1 -0
  32. package/dist/SoAComponent.d.ts +22 -0
  33. package/dist/SoAComponent.d.ts.map +1 -0
  34. package/dist/SoAComponent.js +59 -0
  35. package/dist/SoAComponentStore.d.ts +41 -0
  36. package/dist/SoAComponentStore.d.ts.map +1 -0
  37. package/dist/SoAComponentStore.js +253 -0
  38. package/dist/SoASchema.d.ts +22 -0
  39. package/dist/SoASchema.d.ts.map +1 -0
  40. package/dist/SoASchema.js +33 -0
  41. package/dist/SystemContext.d.ts +18 -0
  42. package/dist/SystemContext.d.ts.map +1 -0
  43. package/dist/SystemContext.js +18 -0
  44. package/dist/SystemRegistry.d.ts +20 -0
  45. package/dist/SystemRegistry.d.ts.map +1 -0
  46. package/dist/SystemRegistry.js +73 -0
  47. package/dist/TickFrameManager.d.ts +35 -0
  48. package/dist/TickFrameManager.d.ts.map +1 -0
  49. package/dist/TickFrameManager.js +130 -0
  50. package/dist/debug/DebugDataProvider.d.ts +26 -0
  51. package/dist/debug/DebugDataProvider.d.ts.map +1 -0
  52. package/dist/debug/DebugDataProvider.js +128 -0
  53. package/dist/debug/DebugPanel.d.ts +57 -0
  54. package/dist/debug/DebugPanel.d.ts.map +1 -0
  55. package/dist/debug/DebugPanel.js +482 -0
  56. package/dist/debug/index.d.ts +4 -0
  57. package/dist/debug/index.d.ts.map +1 -0
  58. package/dist/debug/index.js +2 -0
  59. package/dist/debug/types.d.ts +47 -0
  60. package/dist/debug/types.d.ts.map +1 -0
  61. package/dist/debug/types.js +1 -0
  62. package/dist/index.d.ts +27 -0
  63. package/dist/index.d.ts.map +1 -0
  64. package/dist/index.js +15 -0
  65. package/dist/pool/EntityPool.d.ts +21 -0
  66. package/dist/pool/EntityPool.d.ts.map +1 -0
  67. package/dist/pool/EntityPool.js +86 -0
  68. package/dist/pool/IPoolable.d.ts +4 -0
  69. package/dist/pool/IPoolable.d.ts.map +1 -0
  70. package/dist/pool/IPoolable.js +1 -0
  71. package/dist/pool/IPoolableComponent.d.ts +7 -0
  72. package/dist/pool/IPoolableComponent.d.ts.map +1 -0
  73. package/dist/pool/IPoolableComponent.js +4 -0
  74. package/dist/pool/IPoolableEntity.d.ts +6 -0
  75. package/dist/pool/IPoolableEntity.d.ts.map +1 -0
  76. package/dist/pool/IPoolableEntity.js +1 -0
  77. package/dist/pool/ObjectPool.d.ts +20 -0
  78. package/dist/pool/ObjectPool.d.ts.map +1 -0
  79. package/dist/pool/ObjectPool.js +76 -0
  80. package/dist/pool/PoolManager.d.ts +20 -0
  81. package/dist/pool/PoolManager.d.ts.map +1 -0
  82. package/dist/pool/PoolManager.js +92 -0
  83. package/dist/pool/index.d.ts +10 -0
  84. package/dist/pool/index.d.ts.map +1 -0
  85. package/dist/pool/index.js +5 -0
  86. package/dist/pool/types.d.ts +31 -0
  87. package/dist/pool/types.d.ts.map +1 -0
  88. package/dist/pool/types.js +8 -0
  89. package/package.json +46 -0
@@ -0,0 +1,237 @@
1
+ import { SystemRegistry } from './SystemRegistry';
2
+ import { TickFrameManager } from './TickFrameManager';
3
+ import { SoAComponent } from './SoAComponent';
4
+ import { PoolManager } from './pool/PoolManager';
5
+ import { DebugDataProvider } from './debug/DebugDataProvider';
6
+ import { DebugPanel } from './debug/DebugPanel';
7
+ import { resetEntityIdCounter } from "./Entity";
8
+ import { isBeforeTick, isAfterTick, isBeforeFrame, isAfterFrame, } from './ISystemLifecycleHooks';
9
+ export const GameWorldEvents = {
10
+ PAUSED: 'gameWorld:paused',
11
+ RESUMED: 'gameWorld:resumed',
12
+ };
13
+ export class GameWorld {
14
+ systemRegistry;
15
+ provider;
16
+ ownsProvider;
17
+ _pools;
18
+ _poolingConfig;
19
+ _debugProvider;
20
+ _debugPanelConfig;
21
+ _debugPanel = null;
22
+ beforeTickSystems = [];
23
+ afterTickSystems = [];
24
+ beforeFrameSystems = [];
25
+ afterFrameSystems = [];
26
+ unsubscribeTick = null;
27
+ unsubscribeFrame = null;
28
+ unsubscribePause = null;
29
+ unsubscribeResume = null;
30
+ _paused = false;
31
+ constructor(config) {
32
+ resetEntityIdCounter();
33
+ this.systemRegistry = new SystemRegistry(config.componentTypes);
34
+ SoAComponent.useEntityManager(this.systemRegistry.entityManager);
35
+ if (config.pooling) {
36
+ this._poolingConfig = config.pooling;
37
+ this._pools = new PoolManager(this.systemRegistry.entityManager);
38
+ for (const [typeKey, typeConfig] of Object.entries(config.pooling.entityTypes)) {
39
+ this._pools.registerEntityType(typeKey, typeConfig);
40
+ }
41
+ }
42
+ else {
43
+ this._poolingConfig = undefined;
44
+ this._pools = null;
45
+ }
46
+ this.systemRegistry.getContext().pools = this._pools;
47
+ if (config.tickFrameProvider) {
48
+ this.provider = config.tickFrameProvider;
49
+ this.ownsProvider = false;
50
+ }
51
+ else {
52
+ this.provider = new TickFrameManager({
53
+ tickRate: config.tickRate,
54
+ maxFrameTime: config.maxFrameTime,
55
+ });
56
+ this.ownsProvider = true;
57
+ }
58
+ if (config.debug) {
59
+ this._debugProvider = new DebugDataProvider(this.systemRegistry.entityManager, this._pools, config.debugConfig);
60
+ this._debugPanelConfig = config.debugPanelConfig;
61
+ }
62
+ else {
63
+ this._debugProvider = null;
64
+ this._debugPanelConfig = undefined;
65
+ }
66
+ }
67
+ get paused() {
68
+ return this._paused;
69
+ }
70
+ pause() {
71
+ if (this._paused)
72
+ return;
73
+ if (this.provider.requestPause) {
74
+ this.provider.requestPause();
75
+ }
76
+ else {
77
+ this._paused = true;
78
+ if (this._debugProvider)
79
+ this._debugProvider.paused = true;
80
+ this.systemRegistry.eventBus.emit(GameWorldEvents.PAUSED, {});
81
+ }
82
+ }
83
+ resume() {
84
+ if (!this._paused)
85
+ return;
86
+ if (this.provider.requestResume) {
87
+ this.provider.requestResume();
88
+ }
89
+ else {
90
+ this._paused = false;
91
+ if (this._debugProvider)
92
+ this._debugProvider.paused = false;
93
+ this.systemRegistry.eventBus.emit(GameWorldEvents.RESUMED, {});
94
+ }
95
+ }
96
+ get eventBus() {
97
+ return this.systemRegistry.eventBus;
98
+ }
99
+ get entityManager() {
100
+ return this.systemRegistry.entityManager;
101
+ }
102
+ get pools() {
103
+ return this._pools;
104
+ }
105
+ get debugProvider() {
106
+ return this._debugProvider;
107
+ }
108
+ get debugPanel() {
109
+ return this._debugPanel;
110
+ }
111
+ get context() {
112
+ return this.systemRegistry.getContext();
113
+ }
114
+ getSystem(systemClass) {
115
+ return this.systemRegistry.getContext().getSystem(systemClass);
116
+ }
117
+ registerSystems(tickSystems, frameSystems) {
118
+ this.systemRegistry.registerSystems(tickSystems, frameSystems);
119
+ this.buildLifecycleCaches();
120
+ }
121
+ buildLifecycleCaches() {
122
+ this.beforeTickSystems = [];
123
+ this.afterTickSystems = [];
124
+ this.beforeFrameSystems = [];
125
+ this.afterFrameSystems = [];
126
+ for (const system of this.systemRegistry.getAllSystems()) {
127
+ if (isBeforeTick(system))
128
+ this.beforeTickSystems.push(system);
129
+ if (isAfterTick(system))
130
+ this.afterTickSystems.push(system);
131
+ if (isBeforeFrame(system))
132
+ this.beforeFrameSystems.push(system);
133
+ if (isAfterFrame(system))
134
+ this.afterFrameSystems.push(system);
135
+ }
136
+ }
137
+ addFrameSystem(system) {
138
+ this.systemRegistry.addFrameSystem(system);
139
+ }
140
+ processAllTicks(tick) {
141
+ this.systemRegistry.processAllTicks(tick);
142
+ }
143
+ updateAll(dt) {
144
+ this.systemRegistry.updateAll(dt);
145
+ }
146
+ start(hooks) {
147
+ if (this._pools && this._poolingConfig?.autoPrewarm !== false) {
148
+ this._pools.prewarmAll();
149
+ }
150
+ if (this.provider.onPause) {
151
+ this.unsubscribePause = this.provider.onPause(() => {
152
+ this._paused = true;
153
+ if (this._debugProvider)
154
+ this._debugProvider.paused = true;
155
+ this.systemRegistry.eventBus.emit(GameWorldEvents.PAUSED, {});
156
+ });
157
+ }
158
+ if (this.provider.onResume) {
159
+ this.unsubscribeResume = this.provider.onResume(() => {
160
+ this._paused = false;
161
+ if (this._debugProvider)
162
+ this._debugProvider.paused = false;
163
+ this.systemRegistry.eventBus.emit(GameWorldEvents.RESUMED, {});
164
+ });
165
+ }
166
+ this.unsubscribeTick = this.provider.onTick((tick, commands) => {
167
+ if (this._paused)
168
+ return;
169
+ for (const s of this.beforeTickSystems)
170
+ s.beforeTick(tick, commands);
171
+ hooks?.beforeTick?.(tick, commands);
172
+ this.processAllTicks(tick);
173
+ for (const s of this.afterTickSystems)
174
+ s.afterTick(tick);
175
+ hooks?.afterTick?.(tick);
176
+ });
177
+ this.unsubscribeFrame = this.provider.onFrame((alpha, dt) => {
178
+ if (this._paused)
179
+ return;
180
+ for (const s of this.beforeFrameSystems)
181
+ s.beforeFrame(alpha, dt);
182
+ hooks?.beforeFrame?.(alpha, dt);
183
+ this.updateAll(dt);
184
+ for (const s of this.afterFrameSystems)
185
+ s.afterFrame(alpha, dt);
186
+ hooks?.afterFrame?.(alpha, dt);
187
+ });
188
+ if (this.ownsProvider && this.provider instanceof TickFrameManager) {
189
+ this.provider.start();
190
+ }
191
+ if (this._debugProvider) {
192
+ this._debugProvider.start();
193
+ if (this._debugPanelConfig !== undefined && typeof document !== 'undefined') {
194
+ this._debugPanel = new DebugPanel(this._debugProvider, this._debugPanelConfig);
195
+ }
196
+ }
197
+ }
198
+ stop() {
199
+ if (this.unsubscribeTick) {
200
+ this.unsubscribeTick();
201
+ this.unsubscribeTick = null;
202
+ }
203
+ if (this.unsubscribeFrame) {
204
+ this.unsubscribeFrame();
205
+ this.unsubscribeFrame = null;
206
+ }
207
+ if (this.unsubscribePause) {
208
+ this.unsubscribePause();
209
+ this.unsubscribePause = null;
210
+ }
211
+ if (this.unsubscribeResume) {
212
+ this.unsubscribeResume();
213
+ this.unsubscribeResume = null;
214
+ }
215
+ if (this.ownsProvider && this.provider instanceof TickFrameManager) {
216
+ this.provider.stop();
217
+ }
218
+ if (this._debugPanel) {
219
+ this._debugPanel.destroy();
220
+ this._debugPanel = null;
221
+ }
222
+ if (this._debugProvider) {
223
+ this._debugProvider.stop();
224
+ }
225
+ }
226
+ dispose() {
227
+ this.stop();
228
+ if (this._debugProvider) {
229
+ this._debugProvider.dispose();
230
+ }
231
+ if (this._pools) {
232
+ this._pools.drainAll();
233
+ }
234
+ this.systemRegistry.dispose();
235
+ SoAComponent.resetContext();
236
+ }
237
+ }
@@ -0,0 +1,18 @@
1
+ import type { GameSystem } from "./GameSystem";
2
+ export interface IAbilitySystem {
3
+ activateAbility(casterEntityId: number, abilityId: string, providedTarget?: unknown): boolean;
4
+ applyEffect(targetEntityId: number, effectId: string, sourceEntityId?: number): void;
5
+ tryGetAttribute(entityId: number, attrId: string): {
6
+ base: unknown;
7
+ current: unknown;
8
+ } | undefined;
9
+ getAttribute(entityId: number, attrId: string): {
10
+ base: unknown;
11
+ current: unknown;
12
+ };
13
+ hasTag(entityId: number, tag: string): boolean;
14
+ addTag(entityId: number, tag: string): void;
15
+ removeTag(entityId: number, tag: string): boolean;
16
+ readonly tickSystems: readonly GameSystem[];
17
+ }
18
+ //# sourceMappingURL=IAbilitySystem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IAbilitySystem.d.ts","sourceRoot":"","sources":["../src/IAbilitySystem.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,cAAc,CAAC;AAc7C,MAAM,WAAW,cAAc;IAC7B,eAAe,CACb,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,EACjB,cAAc,CAAC,EAAE,OAAO,GACvB,OAAO,CAAC;IAEX,WAAW,CACT,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,MAAM,EAChB,cAAc,CAAC,EAAE,MAAM,GACtB,IAAI,CAAC;IAER,eAAe,CACb,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG,SAAS,CAAC;IAEnD,YAAY,CACV,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAEvC,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAE/C,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAE5C,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAElD,QAAQ,CAAC,WAAW,EAAE,SAAS,UAAU,EAAE,CAAC;CAC7C"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,21 @@
1
+ export interface InterpolatedTransformSample {
2
+ position: {
3
+ x: number;
4
+ y: number;
5
+ z: number;
6
+ };
7
+ rotation: {
8
+ x: number;
9
+ y: number;
10
+ z: number;
11
+ };
12
+ }
13
+ export interface IPhysicsWorld {
14
+ getInterpolatedTransform(entityId: number): InterpolatedTransformSample | undefined;
15
+ getEntityPosition(entityId: number): {
16
+ x: unknown;
17
+ z: unknown;
18
+ } | undefined;
19
+ applyImpulse(entityId: number, vx: unknown, vz: unknown): void;
20
+ }
21
+ //# sourceMappingURL=IPhysicsWorld.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IPhysicsWorld.d.ts","sourceRoot":"","sources":["../src/IPhysicsWorld.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,QAAQ,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/C;AAeD,MAAM,WAAW,aAAa;IAI5B,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,2BAA2B,GAAG,SAAS,CAAC;IAKpF,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG;QAAE,CAAC,EAAE,OAAO,CAAC;QAAC,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,SAAS,CAAC;IAG5E,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,GAAG,IAAI,CAAC;CAChE"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,18 @@
1
+ import type { CommandsBatch } from './ITickFrameProvider';
2
+ export interface IBeforeTick {
3
+ beforeTick(tick: number, commands: CommandsBatch): void;
4
+ }
5
+ export interface IAfterTick {
6
+ afterTick(tick: number): void;
7
+ }
8
+ export interface IBeforeFrame {
9
+ beforeFrame(alpha: number, dt: number): void;
10
+ }
11
+ export interface IAfterFrame {
12
+ afterFrame(alpha: number, dt: number): void;
13
+ }
14
+ export declare function isBeforeTick(system: object): system is IBeforeTick;
15
+ export declare function isAfterTick(system: object): system is IAfterTick;
16
+ export declare function isBeforeFrame(system: object): system is IBeforeFrame;
17
+ export declare function isAfterFrame(system: object): system is IAfterFrame;
18
+ //# sourceMappingURL=ISystemLifecycleHooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ISystemLifecycleHooks.d.ts","sourceRoot":"","sources":["../src/ISystemLifecycleHooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAoB1D,MAAM,WAAW,WAAW;IAC1B,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;CACzD;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9C;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7C;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,IAAI,WAAW,CAElE;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,IAAI,UAAU,CAEhE;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,IAAI,YAAY,CAEpE;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,IAAI,WAAW,CAElE"}
@@ -0,0 +1,12 @@
1
+ export function isBeforeTick(system) {
2
+ return typeof system.beforeTick === 'function';
3
+ }
4
+ export function isAfterTick(system) {
5
+ return typeof system.afterTick === 'function';
6
+ }
7
+ export function isBeforeFrame(system) {
8
+ return typeof system.beforeFrame === 'function';
9
+ }
10
+ export function isAfterFrame(system) {
11
+ return typeof system.afterFrame === 'function';
12
+ }
@@ -0,0 +1,24 @@
1
+ export interface CommandsBatch {
2
+ tick: number;
3
+ commands: {
4
+ [playerId: string]: PlayerCommand[];
5
+ };
6
+ }
7
+ export interface PlayerCommand {
8
+ type: string;
9
+ data?: any;
10
+ playerId?: string;
11
+ }
12
+ export type TickHandler = (tick: number, commands: CommandsBatch) => void;
13
+ export type FrameHandler = (alpha: number, dt: number) => void;
14
+ export type Unsubscribe = () => void;
15
+ export type PauseHandler = () => void;
16
+ export interface ITickFrameProvider {
17
+ onTick(handler: TickHandler): Unsubscribe;
18
+ onFrame(handler: FrameHandler): Unsubscribe;
19
+ requestPause?(): void;
20
+ requestResume?(): void;
21
+ onPause?(handler: PauseHandler): Unsubscribe;
22
+ onResume?(handler: PauseHandler): Unsubscribe;
23
+ }
24
+ //# sourceMappingURL=ITickFrameProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ITickFrameProvider.d.ts","sourceRoot":"","sources":["../src/ITickFrameProvider.ts"],"names":[],"mappings":"AAiCA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE;QACR,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,EAAE,CAAC;KACrC,CAAC;CACH;AAKD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAOD,MAAM,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAC;AAO1E,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;AAK/D,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC;AAKrC,MAAM,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC;AAkBtC,MAAM,WAAW,kBAAkB;IAMjC,MAAM,CAAC,OAAO,EAAE,WAAW,GAAG,WAAW,CAAC;IAO1C,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,WAAW,CAAC;IAS5C,YAAY,CAAC,IAAI,IAAI,CAAC;IAMtB,aAAa,CAAC,IAAI,IAAI,CAAC;IAQvB,OAAO,CAAC,CAAC,OAAO,EAAE,YAAY,GAAG,WAAW,CAAC;IAM7C,QAAQ,CAAC,CAAC,OAAO,EAAE,YAAY,GAAG,WAAW,CAAC;CAC/C"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,22 @@
1
+ import type { IComponent } from './Component';
2
+ import type { IPoolableComponent } from './pool/IPoolableComponent';
3
+ import type { SoASchemaDefinition, SoASchema, SoAFieldsOf } from './SoASchema';
4
+ import type { SoAComponentStore } from './SoAComponentStore';
5
+ import type { EntityManager } from './EntityManager';
6
+ export declare abstract class SoAComponent<S extends SoASchemaDefinition> implements IComponent, IPoolableComponent {
7
+ abstract readonly type: symbol;
8
+ protected readonly store: SoAComponentStore<S>;
9
+ protected readonly entityId: number;
10
+ private _cachedIndex;
11
+ private readonly _spawnDefaults;
12
+ private static _entityManager;
13
+ static useEntityManager(em: EntityManager): void;
14
+ static resetContext(): void;
15
+ constructor(schema: SoASchema<S>, entityId: number, initialValues: SoAFieldsOf<S>);
16
+ onSpawn(): void;
17
+ onDespawn(): void;
18
+ protected getIndex(): number;
19
+ protected getField<K extends keyof S & string>(fieldName: K): SoAFieldsOf<S>[K];
20
+ protected setField<K extends keyof S & string>(fieldName: K, value: SoAFieldsOf<S>[K]): void;
21
+ }
22
+ //# sourceMappingURL=SoAComponent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SoAComponent.d.ts","sourceRoot":"","sources":["../src/SoAComponent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AA6BrD,8BAAsB,YAAY,CAAC,CAAC,SAAS,mBAAmB,CAAE,YAAW,UAAU,EAAE,kBAAkB;IACzG,kBAAyB,IAAI,EAAE,MAAM,CAAC;IAGtC,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAG/C,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAGpC,OAAO,CAAC,YAAY,CAAc;IAGlC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;IAIhD,OAAO,CAAC,MAAM,CAAC,cAAc,CAA8B;WAM7C,gBAAgB,CAAC,EAAE,EAAE,aAAa,GAAG,IAAI;WAOzC,YAAY,IAAI,IAAI;gBAMtB,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC,CAAC;IAyB1E,OAAO,IAAI,IAAI;IAgBf,SAAS,IAAI,IAAI;IAWxB,SAAS,CAAC,QAAQ,IAAI,MAAM;IAY5B,SAAS,CAAC,QAAQ,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAQ/E,SAAS,CAAC,QAAQ,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI;CAS7F"}
@@ -0,0 +1,59 @@
1
+ const DEFAULT_STORE_CAPACITY = 1024;
2
+ export class SoAComponent {
3
+ store;
4
+ entityId;
5
+ _cachedIndex = -1;
6
+ _spawnDefaults;
7
+ static _entityManager = null;
8
+ static useEntityManager(em) {
9
+ SoAComponent._entityManager = em;
10
+ }
11
+ static resetContext() {
12
+ SoAComponent._entityManager = null;
13
+ }
14
+ constructor(schema, entityId, initialValues) {
15
+ if (!SoAComponent._entityManager) {
16
+ throw new Error('SoAComponent: No EntityManager context. Ensure GameWorld is created before instantiating SoA components.');
17
+ }
18
+ this.entityId = entityId;
19
+ this.store = SoAComponent._entityManager.getOrCreateSoAStore(schema, DEFAULT_STORE_CAPACITY);
20
+ this._spawnDefaults = initialValues;
21
+ this.store.add(entityId, initialValues);
22
+ this._cachedIndex = this.store.indexOf(entityId);
23
+ }
24
+ onSpawn() {
25
+ if (this.store.indexOf(this.entityId) === -1) {
26
+ this.store.add(this.entityId, this._spawnDefaults);
27
+ }
28
+ else {
29
+ for (const key of Object.keys(this._spawnDefaults)) {
30
+ this.setField(key, this._spawnDefaults[key]);
31
+ }
32
+ }
33
+ this._cachedIndex = this.store.indexOf(this.entityId);
34
+ }
35
+ onDespawn() {
36
+ this.store.remove(this.entityId);
37
+ this._cachedIndex = -1;
38
+ }
39
+ getIndex() {
40
+ if (this._cachedIndex === -1 || this.store.entityAt(this._cachedIndex) !== this.entityId) {
41
+ this._cachedIndex = this.store.indexOf(this.entityId);
42
+ }
43
+ return this._cachedIndex;
44
+ }
45
+ getField(fieldName) {
46
+ const idx = this.getIndex();
47
+ return this.store.arrays[fieldName][idx];
48
+ }
49
+ setField(fieldName, value) {
50
+ const idx = this.getIndex();
51
+ const arr = this.store.arrays[fieldName];
52
+ if (arr instanceof BigInt64Array) {
53
+ arr[idx] = value;
54
+ }
55
+ else {
56
+ arr[idx] = value;
57
+ }
58
+ }
59
+ }
@@ -0,0 +1,41 @@
1
+ import { type SoASchema, type SoASchemaDefinition, type SoAFieldsOf, type SoAArraysOf } from './SoASchema';
2
+ export interface SoAComponentStoreOptions {
3
+ initialCapacity?: number;
4
+ autoShrink?: boolean;
5
+ }
6
+ export declare class SoAComponentStore<S extends SoASchemaDefinition> {
7
+ readonly schema: SoASchema<S>;
8
+ readonly arrays: SoAArraysOf<S>;
9
+ private _count;
10
+ private _capacity;
11
+ private readonly _minCapacity;
12
+ private readonly _autoShrink;
13
+ private _fieldArrays;
14
+ private _fieldIsBigInt;
15
+ private entityToIndex;
16
+ private indexToEntity;
17
+ private _sortedEntityIds;
18
+ private binarySearchInsertIndex;
19
+ constructor(schema: SoASchema<S>, initialCapacityOrOptions?: number | SoAComponentStoreOptions);
20
+ private rebuildFieldCache;
21
+ get count(): number;
22
+ get capacity(): number;
23
+ has(entityId: number): boolean;
24
+ indexOf(entityId: number): number;
25
+ entityAt(index: number): number;
26
+ entityIds(): readonly number[];
27
+ add(entityId: number, values: SoAFieldsOf<S>): number;
28
+ remove(entityId: number): boolean;
29
+ get(entityId: number): SoAFieldsOf<S> | undefined;
30
+ set(entityId: number, values: Partial<SoAFieldsOf<S>>): boolean;
31
+ getField<K extends keyof S & string>(entityId: number, fieldName: K): SoAFieldsOf<S>[K] | undefined;
32
+ setField<K extends keyof S & string>(entityId: number, fieldName: K, value: SoAFieldsOf<S>[K]): boolean;
33
+ clear(): void;
34
+ private grow;
35
+ private resize;
36
+ private maybeAutoShrink;
37
+ shrinkToFit(minCapacity?: number): number;
38
+ forEachDense(callback: (entityId: number, index: number) => void): void;
39
+ forEach(callback: (entityId: number, index: number) => void): void;
40
+ }
41
+ //# sourceMappingURL=SoAComponentStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SoAComponentStore.d.ts","sourceRoot":"","sources":["../src/SoAComponentStore.ts"],"names":[],"mappings":"AAqCA,OAAO,EACL,KAAK,SAAS,EACd,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAChB,KAAK,WAAW,EAGjB,MAAM,aAAa,CAAC;AAmBrB,MAAM,WAAW,wBAAwB;IAEvC,eAAe,CAAC,EAAE,MAAM,CAAC;IAQzB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AA2BD,qBAAa,iBAAiB,CAAC,CAAC,SAAS,mBAAmB;IAE1D,SAAgB,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IAGrC,SAAgB,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IAGvC,OAAO,CAAC,MAAM,CAAa;IAG3B,OAAO,CAAC,SAAS,CAAS;IAM1B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IAGtC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAU;IAOtC,OAAO,CAAC,YAAY,CAAwB;IAO5C,OAAO,CAAC,cAAc,CAAiB;IAMvC,OAAO,CAAC,aAAa,CAAkC;IAMvD,OAAO,CAAC,aAAa,CAAgB;IAMrC,OAAO,CAAC,gBAAgB,CAAgB;IAKxC,OAAO,CAAC,uBAAuB;gBAgB7B,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EACpB,wBAAwB,GAAE,MAAM,GAAG,wBAAmD;IA6BxF,OAAO,CAAC,iBAAiB;IAczB,IAAW,KAAK,IAAI,MAAM,CAEzB;IAKD,IAAW,QAAQ,IAAI,MAAM,CAE5B;IAKM,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAQ9B,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAQjC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAmB/B,SAAS,IAAI,SAAS,MAAM,EAAE;IAU9B,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,MAAM;IAyCrD,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAiDjC,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,SAAS;IAiBjD,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO;IAmB/D,QAAQ,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EACxC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,CAAC,GACX,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS;IAYzB,QAAQ,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EACxC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,CAAC,EACZ,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GACvB,OAAO;IAcH,KAAK,IAAI,IAAI;IAoBpB,OAAO,CAAC,IAAI;IAUZ,OAAO,CAAC,MAAM;IA6Bd,OAAO,CAAC,eAAe;IAwBhB,WAAW,CAAC,WAAW,GAAE,MAA0B,GAAG,MAAM;IAa5D,YAAY,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IASvE,OAAO,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;CAM1E"}