@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,25 @@
1
+ import type { IComponent } from './Component';
2
+ export declare function resetEntityIdCounter(): void;
3
+ export declare function nextEntityId(): number;
4
+ export declare class Entity {
5
+ private _id;
6
+ protected components: Map<symbol, IComponent>;
7
+ private _isDestroyed;
8
+ _poolTypeKey?: string;
9
+ _inPool: boolean;
10
+ constructor();
11
+ get id(): number;
12
+ _setId(id: number): void;
13
+ _revive(): void;
14
+ addComponent<T extends IComponent>(component: T): T;
15
+ getComponent<T extends IComponent>(type: symbol): T | undefined;
16
+ hasComponent(type: symbol): boolean;
17
+ hasComponents(...types: symbol[]): boolean;
18
+ removeComponent(type: symbol): boolean;
19
+ getComponentTypes(): symbol[];
20
+ getComponents(): ReadonlyMap<symbol, IComponent>;
21
+ get isDestroyed(): boolean;
22
+ destroy(): void;
23
+ dispose(): void;
24
+ }
25
+ //# sourceMappingURL=Entity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Entity.d.ts","sourceRoot":"","sources":["../src/Entity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAQ9C,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C;AAOD,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAUD,qBAAa,MAAM;IACjB,OAAO,CAAC,GAAG,CAAS;IACpB,SAAS,CAAC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAa;IAC1D,OAAO,CAAC,YAAY,CAAkB;IAG/B,YAAY,CAAC,EAAE,MAAM,CAAC;IAGtB,OAAO,EAAE,OAAO,CAAS;;IAShC,IAAW,EAAE,IAAI,MAAM,CAEtB;IAMM,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAOxB,OAAO,IAAI,IAAI;IAOf,YAAY,CAAC,CAAC,SAAS,UAAU,EAAE,SAAS,EAAE,CAAC,GAAG,CAAC;IASnD,YAAY,CAAC,CAAC,SAAS,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAO/D,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAOnC,aAAa,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO;IAO1C,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAQtC,iBAAiB,IAAI,MAAM,EAAE;IAQ7B,aAAa,IAAI,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC;IAOvD,IAAW,WAAW,IAAI,OAAO,CAEhC;IAKM,OAAO,IAAI,IAAI;IAOf,OAAO,IAAI,IAAI;CAIvB"}
package/dist/Entity.js ADDED
@@ -0,0 +1,58 @@
1
+ let entityIdCounter = 0;
2
+ export function resetEntityIdCounter() {
3
+ entityIdCounter = 0;
4
+ }
5
+ export function nextEntityId() {
6
+ return ++entityIdCounter;
7
+ }
8
+ export class Entity {
9
+ _id;
10
+ components = new Map();
11
+ _isDestroyed = false;
12
+ _poolTypeKey;
13
+ _inPool = false;
14
+ constructor() {
15
+ this._id = ++entityIdCounter;
16
+ }
17
+ get id() {
18
+ return this._id;
19
+ }
20
+ _setId(id) {
21
+ this._id = id;
22
+ }
23
+ _revive() {
24
+ this._isDestroyed = false;
25
+ }
26
+ addComponent(component) {
27
+ this.components.set(component.type, component);
28
+ return component;
29
+ }
30
+ getComponent(type) {
31
+ return this.components.get(type);
32
+ }
33
+ hasComponent(type) {
34
+ return this.components.has(type);
35
+ }
36
+ hasComponents(...types) {
37
+ return types.every((type) => this.components.has(type));
38
+ }
39
+ removeComponent(type) {
40
+ return this.components.delete(type);
41
+ }
42
+ getComponentTypes() {
43
+ return Array.from(this.components.keys());
44
+ }
45
+ getComponents() {
46
+ return this.components;
47
+ }
48
+ get isDestroyed() {
49
+ return this._isDestroyed;
50
+ }
51
+ destroy() {
52
+ this._isDestroyed = true;
53
+ }
54
+ dispose() {
55
+ this._isDestroyed = true;
56
+ this.components.clear();
57
+ }
58
+ }
@@ -0,0 +1,36 @@
1
+ import type { Entity } from './Entity';
2
+ import { SoAComponentStore } from './SoAComponentStore';
3
+ import type { SoAComponentStoreOptions } from './SoAComponentStore';
4
+ import type { SoASchema, SoASchemaDefinition } from './SoASchema';
5
+ export declare class EntityManager {
6
+ private entities;
7
+ private sortedEntityIds;
8
+ private soaStores;
9
+ private componentIndices;
10
+ private binarySearchInsertIndex;
11
+ private sortedInsert;
12
+ private sortedRemove;
13
+ registerComponentTypes(componentTypes: readonly symbol[]): void;
14
+ addEntity(entity: Entity): void;
15
+ removeEntity(entity: Entity): void;
16
+ getEntity(id: number): Entity | undefined;
17
+ getAllEntities(): Entity[];
18
+ queryEntities(...componentTypes: symbol[]): Entity[];
19
+ queryEntitiesAny(...componentTypes: symbol[]): Entity[];
20
+ private mergeSortedArrays;
21
+ onComponentAdded(entity: Entity, componentType: symbol): void;
22
+ onComponentRemoved(entity: Entity, componentType: symbol): void;
23
+ cleanupDestroyed(): Entity[];
24
+ countWithComponent(componentType: symbol): number;
25
+ get count(): number;
26
+ registerSoAStore<S extends SoASchemaDefinition>(store: SoAComponentStore<S>): void;
27
+ getSoAStore<S extends SoASchemaDefinition>(schema: SoASchema<S>): SoAComponentStore<S> | undefined;
28
+ getSoAStoreByType<S extends SoASchemaDefinition>(schemaType: symbol): SoAComponentStore<S> | undefined;
29
+ getOrCreateSoAStore<S extends SoASchemaDefinition>(schema: SoASchema<S>, initialCapacityOrOptions?: number | SoAComponentStoreOptions): SoAComponentStore<S>;
30
+ hasSoAStore(schema: SoASchema): boolean;
31
+ private cleanupSoAStores;
32
+ getAllSoAStores(): ReadonlyMap<symbol, SoAComponentStore<any>>;
33
+ getComponentTypeStats(): Map<symbol, number>;
34
+ clear(): void;
35
+ }
36
+ //# sourceMappingURL=EntityManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EntityManager.d.ts","sourceRoot":"","sources":["../src/EntityManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,KAAK,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAclE,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAkC;IAGlD,OAAO,CAAC,eAAe,CAAgB;IAIvC,OAAO,CAAC,SAAS,CAAkD;IAInE,OAAO,CAAC,gBAAgB,CAAoC;IAM5D,OAAO,CAAC,uBAAuB;IAkB/B,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,YAAY;IAYb,sBAAsB,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI;IAW/D,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAe/B,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAgBlC,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAYzC,cAAc,IAAI,MAAM,EAAE;IAqB1B,aAAa,CAAC,GAAG,cAAc,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE;IA0CpD,gBAAgB,CAAC,GAAG,cAAc,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE;IA0B9D,OAAO,CAAC,iBAAiB;IAwClB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI;IAU7D,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI;IAU/D,gBAAgB,IAAI,MAAM,EAAE;IAmB5B,kBAAkB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM;IAOxD,IAAW,KAAK,IAAI,MAAM,CAEzB;IAUM,gBAAgB,CAAC,CAAC,SAAS,mBAAmB,EACnD,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAC1B,IAAI;IAUA,WAAW,CAAC,CAAC,SAAS,mBAAmB,EAC9C,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,GACnB,iBAAiB,CAAC,CAAC,CAAC,GAAG,SAAS;IAU5B,iBAAiB,CAAC,CAAC,SAAS,mBAAmB,EACpD,UAAU,EAAE,MAAM,GACjB,iBAAiB,CAAC,CAAC,CAAC,GAAG,SAAS;IAa5B,mBAAmB,CAAC,CAAC,SAAS,mBAAmB,EACtD,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EACpB,wBAAwB,GAAE,MAAM,GAAG,wBAA+B,GACjE,iBAAiB,CAAC,CAAC,CAAC;IAahB,WAAW,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO;IAQ9C,OAAO,CAAC,gBAAgB;IAajB,eAAe,IAAI,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAAG,CAAC,CAAC;IAS9D,qBAAqB,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAW5C,KAAK,IAAI,IAAI;CAgBrB"}
@@ -0,0 +1,218 @@
1
+ import { SoAComponentStore } from './SoAComponentStore';
2
+ export class EntityManager {
3
+ entities = new Map();
4
+ sortedEntityIds = [];
5
+ soaStores = new Map();
6
+ componentIndices = new Map();
7
+ binarySearchInsertIndex(arr, value) {
8
+ let low = 0;
9
+ let high = arr.length;
10
+ while (low < high) {
11
+ const mid = (low + high) >>> 1;
12
+ if (arr[mid] < value) {
13
+ low = mid + 1;
14
+ }
15
+ else {
16
+ high = mid;
17
+ }
18
+ }
19
+ return low;
20
+ }
21
+ sortedInsert(arr, value) {
22
+ const index = this.binarySearchInsertIndex(arr, value);
23
+ if (arr[index] !== value) {
24
+ arr.splice(index, 0, value);
25
+ }
26
+ }
27
+ sortedRemove(arr, value) {
28
+ const index = this.binarySearchInsertIndex(arr, value);
29
+ if (arr[index] === value) {
30
+ arr.splice(index, 1);
31
+ }
32
+ }
33
+ registerComponentTypes(componentTypes) {
34
+ for (const type of componentTypes) {
35
+ if (!this.componentIndices.has(type)) {
36
+ this.componentIndices.set(type, []);
37
+ }
38
+ }
39
+ }
40
+ addEntity(entity) {
41
+ this.entities.set(entity.id, entity);
42
+ this.sortedInsert(this.sortedEntityIds, entity.id);
43
+ for (const [type, index] of this.componentIndices) {
44
+ if (entity.hasComponent(type)) {
45
+ this.sortedInsert(index, entity.id);
46
+ }
47
+ }
48
+ }
49
+ removeEntity(entity) {
50
+ for (const index of this.componentIndices.values()) {
51
+ this.sortedRemove(index, entity.id);
52
+ }
53
+ this.cleanupSoAStores(entity.id);
54
+ this.sortedRemove(this.sortedEntityIds, entity.id);
55
+ this.entities.delete(entity.id);
56
+ }
57
+ getEntity(id) {
58
+ return this.entities.get(id);
59
+ }
60
+ getAllEntities() {
61
+ const result = [];
62
+ for (const id of this.sortedEntityIds) {
63
+ const entity = this.entities.get(id);
64
+ if (entity) {
65
+ result.push(entity);
66
+ }
67
+ }
68
+ return result;
69
+ }
70
+ queryEntities(...componentTypes) {
71
+ if (componentTypes.length === 0) {
72
+ return this.getAllEntities();
73
+ }
74
+ const sortedTypes = [...componentTypes].sort((a, b) => {
75
+ const sizeA = this.componentIndices.get(a)?.length ?? 0;
76
+ const sizeB = this.componentIndices.get(b)?.length ?? 0;
77
+ return sizeA - sizeB;
78
+ });
79
+ const firstIndex = this.componentIndices.get(sortedTypes[0]);
80
+ if (!firstIndex || firstIndex.length === 0) {
81
+ return [];
82
+ }
83
+ const result = [];
84
+ for (const entityId of firstIndex) {
85
+ const entity = this.entities.get(entityId);
86
+ if (entity &&
87
+ !entity.isDestroyed &&
88
+ entity.hasComponents(...componentTypes)) {
89
+ result.push(entity);
90
+ }
91
+ }
92
+ return result;
93
+ }
94
+ queryEntitiesAny(...componentTypes) {
95
+ if (componentTypes.length === 0) {
96
+ return [];
97
+ }
98
+ const mergedIds = this.mergeSortedArrays(componentTypes
99
+ .map((type) => this.componentIndices.get(type))
100
+ .filter((arr) => arr !== undefined));
101
+ const result = [];
102
+ for (const id of mergedIds) {
103
+ const entity = this.entities.get(id);
104
+ if (entity && !entity.isDestroyed) {
105
+ result.push(entity);
106
+ }
107
+ }
108
+ return result;
109
+ }
110
+ mergeSortedArrays(arrays) {
111
+ if (arrays.length === 0)
112
+ return [];
113
+ if (arrays.length === 1)
114
+ return arrays[0];
115
+ const result = [];
116
+ const pointers = arrays.map(() => 0);
117
+ while (true) {
118
+ let minValue = Infinity;
119
+ let minIndex = -1;
120
+ for (let i = 0; i < arrays.length; i++) {
121
+ if (pointers[i] < arrays[i].length && arrays[i][pointers[i]] < minValue) {
122
+ minValue = arrays[i][pointers[i]];
123
+ minIndex = i;
124
+ }
125
+ }
126
+ if (minIndex === -1)
127
+ break;
128
+ if (result.length === 0 || result[result.length - 1] !== minValue) {
129
+ result.push(minValue);
130
+ }
131
+ for (let i = 0; i < arrays.length; i++) {
132
+ if (pointers[i] < arrays[i].length && arrays[i][pointers[i]] === minValue) {
133
+ pointers[i]++;
134
+ }
135
+ }
136
+ }
137
+ return result;
138
+ }
139
+ onComponentAdded(entity, componentType) {
140
+ const index = this.componentIndices.get(componentType);
141
+ if (index) {
142
+ this.sortedInsert(index, entity.id);
143
+ }
144
+ }
145
+ onComponentRemoved(entity, componentType) {
146
+ const index = this.componentIndices.get(componentType);
147
+ if (index) {
148
+ this.sortedRemove(index, entity.id);
149
+ }
150
+ }
151
+ cleanupDestroyed() {
152
+ const destroyed = [];
153
+ for (const entity of this.entities.values()) {
154
+ if (entity.isDestroyed) {
155
+ destroyed.push(entity);
156
+ }
157
+ }
158
+ for (const entity of destroyed) {
159
+ this.removeEntity(entity);
160
+ }
161
+ return destroyed;
162
+ }
163
+ countWithComponent(componentType) {
164
+ return this.componentIndices.get(componentType)?.length ?? 0;
165
+ }
166
+ get count() {
167
+ return this.entities.size;
168
+ }
169
+ registerSoAStore(store) {
170
+ this.soaStores.set(store.schema.type, store);
171
+ }
172
+ getSoAStore(schema) {
173
+ return this.soaStores.get(schema.type);
174
+ }
175
+ getSoAStoreByType(schemaType) {
176
+ return this.soaStores.get(schemaType);
177
+ }
178
+ getOrCreateSoAStore(schema, initialCapacityOrOptions = 1024) {
179
+ const existing = this.soaStores.get(schema.type);
180
+ if (existing) {
181
+ return existing;
182
+ }
183
+ const store = new SoAComponentStore(schema, initialCapacityOrOptions);
184
+ this.soaStores.set(schema.type, store);
185
+ return store;
186
+ }
187
+ hasSoAStore(schema) {
188
+ return this.soaStores.has(schema.type);
189
+ }
190
+ cleanupSoAStores(entityId) {
191
+ for (const store of this.soaStores.values()) {
192
+ store.remove(entityId);
193
+ }
194
+ }
195
+ getAllSoAStores() {
196
+ return this.soaStores;
197
+ }
198
+ getComponentTypeStats() {
199
+ const stats = new Map();
200
+ for (const [type, index] of this.componentIndices) {
201
+ stats.set(type, index.length);
202
+ }
203
+ return stats;
204
+ }
205
+ clear() {
206
+ for (const entity of this.entities.values()) {
207
+ entity.dispose();
208
+ }
209
+ this.entities.clear();
210
+ this.sortedEntityIds.length = 0;
211
+ for (const index of this.componentIndices.values()) {
212
+ index.length = 0;
213
+ }
214
+ for (const store of this.soaStores.values()) {
215
+ store.clear();
216
+ }
217
+ }
218
+ }
@@ -0,0 +1,15 @@
1
+ type EventCallback<T = unknown> = (data: T) => void;
2
+ type UnsubscribeFunction = () => void;
3
+ export declare class EventBus {
4
+ private listeners;
5
+ on<T>(eventType: string, callback: EventCallback<T>): UnsubscribeFunction;
6
+ once<T>(eventType: string, callback: EventCallback<T>): UnsubscribeFunction;
7
+ off<T>(eventType: string, callback: EventCallback<T>): void;
8
+ emit<T>(eventType: string, data: T): void;
9
+ clear(eventType: string): void;
10
+ clearAll(): void;
11
+ listenerCount(eventType: string): number;
12
+ }
13
+ export declare const globalEventBus: EventBus;
14
+ export {};
15
+ //# sourceMappingURL=EventBus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EventBus.d.ts","sourceRoot":"","sources":["../src/EventBus.ts"],"names":[],"mappings":"AAKA,KAAK,aAAa,CAAC,CAAC,GAAG,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;AACpD,KAAK,mBAAmB,GAAG,MAAM,IAAI,CAAC;AAOtC,qBAAa,QAAQ;IACnB,OAAO,CAAC,SAAS,CAA0C;IAQpD,EAAE,CAAC,CAAC,EACT,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,GACzB,mBAAmB;IAqBf,IAAI,CAAC,CAAC,EACX,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,GACzB,mBAAmB;IAoBf,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI;IAoB3D,IAAI,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI;IAkCzC,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAO9B,QAAQ,IAAI,IAAI;IAQhB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;CAGhD;AAGD,eAAO,MAAM,cAAc,UAAiB,CAAC"}
@@ -0,0 +1,69 @@
1
+ export class EventBus {
2
+ listeners = new Map();
3
+ on(eventType, callback) {
4
+ if (!this.listeners.has(eventType)) {
5
+ this.listeners.set(eventType, []);
6
+ }
7
+ const subscription = {
8
+ callback: callback,
9
+ once: false,
10
+ };
11
+ this.listeners.get(eventType).push(subscription);
12
+ return () => this.off(eventType, callback);
13
+ }
14
+ once(eventType, callback) {
15
+ if (!this.listeners.has(eventType)) {
16
+ this.listeners.set(eventType, []);
17
+ }
18
+ const subscription = {
19
+ callback: callback,
20
+ once: true,
21
+ };
22
+ this.listeners.get(eventType).push(subscription);
23
+ return () => this.off(eventType, callback);
24
+ }
25
+ off(eventType, callback) {
26
+ const subscriptions = this.listeners.get(eventType);
27
+ if (!subscriptions)
28
+ return;
29
+ const index = subscriptions.findIndex((sub) => sub.callback === callback);
30
+ if (index !== -1) {
31
+ subscriptions.splice(index, 1);
32
+ }
33
+ if (subscriptions.length === 0) {
34
+ this.listeners.delete(eventType);
35
+ }
36
+ }
37
+ emit(eventType, data) {
38
+ const subscriptions = this.listeners.get(eventType);
39
+ if (!subscriptions)
40
+ return;
41
+ const subscriptionsCopy = [...subscriptions];
42
+ const toRemove = [];
43
+ for (const subscription of subscriptionsCopy) {
44
+ subscription.callback(data);
45
+ if (subscription.once) {
46
+ toRemove.push(subscription);
47
+ }
48
+ }
49
+ for (const subscription of toRemove) {
50
+ const index = subscriptions.indexOf(subscription);
51
+ if (index !== -1) {
52
+ subscriptions.splice(index, 1);
53
+ }
54
+ }
55
+ if (subscriptions.length === 0) {
56
+ this.listeners.delete(eventType);
57
+ }
58
+ }
59
+ clear(eventType) {
60
+ this.listeners.delete(eventType);
61
+ }
62
+ clearAll() {
63
+ this.listeners.clear();
64
+ }
65
+ listenerCount(eventType) {
66
+ return this.listeners.get(eventType)?.length ?? 0;
67
+ }
68
+ }
69
+ export const globalEventBus = new EventBus();
@@ -0,0 +1,23 @@
1
+ import type { SystemContext } from './SystemContext';
2
+ import type { EventBus } from './EventBus';
3
+ import type { EntityManager } from './EntityManager';
4
+ import type { IAbilitySystem } from './IAbilitySystem';
5
+ import type { IPhysicsWorld } from './IPhysicsWorld';
6
+ import type { PoolManager } from './pool/PoolManager';
7
+ export declare abstract class GameSystem {
8
+ protected context: SystemContext;
9
+ protected get eventBus(): EventBus;
10
+ protected get entityManager(): EntityManager;
11
+ protected get abilities(): IAbilitySystem | undefined;
12
+ protected get physics(): IPhysicsWorld | undefined;
13
+ protected get pools(): PoolManager | null;
14
+ enabled: boolean;
15
+ private unsubscribers;
16
+ init(context: SystemContext): void;
17
+ processTick(_tick: number): void;
18
+ update(_deltaTime: number): void;
19
+ protected subscribe<T>(eventType: string, handler: (event: T) => void): () => void;
20
+ protected subscribeOnce<T>(eventType: string, handler: (event: T) => void): () => void;
21
+ dispose(): void;
22
+ }
23
+ //# sourceMappingURL=GameSystem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GameSystem.d.ts","sourceRoot":"","sources":["../src/GameSystem.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAkBtD,8BAAsB,UAAU;IAE9B,SAAS,CAAC,OAAO,EAAG,aAAa,CAAC;IAGlC,SAAS,KAAK,QAAQ,IAAI,QAAQ,CAEjC;IAGD,SAAS,KAAK,aAAa,IAAI,aAAa,CAE3C;IAQD,SAAS,KAAK,SAAS,IAAI,cAAc,GAAG,SAAS,CAEpD;IAMD,SAAS,KAAK,OAAO,IAAI,aAAa,GAAG,SAAS,CAEjD;IAMD,SAAS,KAAK,KAAK,IAAI,WAAW,GAAG,IAAI,CAExC;IAGM,OAAO,EAAE,OAAO,CAAQ;IAG/B,OAAO,CAAC,aAAa,CAAsB;IASpC,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAYlC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAWhC,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAYvC,SAAS,CAAC,SAAS,CAAC,CAAC,EACnB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,GAC1B,MAAM,IAAI;IAab,SAAS,CAAC,aAAa,CAAC,CAAC,EACvB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,GAC1B,MAAM,IAAI;IAWN,OAAO,IAAI,IAAI;CAOvB"}
@@ -0,0 +1,43 @@
1
+ export class GameSystem {
2
+ context;
3
+ get eventBus() {
4
+ return this.context.eventBus;
5
+ }
6
+ get entityManager() {
7
+ return this.context.entityManager;
8
+ }
9
+ get abilities() {
10
+ return this.context.abilities;
11
+ }
12
+ get physics() {
13
+ return this.context.physics;
14
+ }
15
+ get pools() {
16
+ return this.context.pools;
17
+ }
18
+ enabled = true;
19
+ unsubscribers = [];
20
+ init(context) {
21
+ this.context = context;
22
+ }
23
+ processTick(_tick) {
24
+ }
25
+ update(_deltaTime) {
26
+ }
27
+ subscribe(eventType, handler) {
28
+ const unsubscribe = this.eventBus.on(eventType, handler);
29
+ this.unsubscribers.push(unsubscribe);
30
+ return unsubscribe;
31
+ }
32
+ subscribeOnce(eventType, handler) {
33
+ const unsubscribe = this.eventBus.once(eventType, handler);
34
+ this.unsubscribers.push(unsubscribe);
35
+ return unsubscribe;
36
+ }
37
+ dispose() {
38
+ for (const unsubscribe of this.unsubscribers) {
39
+ unsubscribe();
40
+ }
41
+ this.unsubscribers = [];
42
+ }
43
+ }
@@ -0,0 +1,69 @@
1
+ import { PoolManager } from './pool/PoolManager';
2
+ import { DebugDataProvider } from './debug/DebugDataProvider';
3
+ import { DebugPanel } from './debug/DebugPanel';
4
+ import type { DebugDataProviderConfig, DebugPanelConfig } from './debug/types';
5
+ import type { PoolingConfig } from './pool/types';
6
+ import type { ITickFrameProvider } from './ITickFrameProvider';
7
+ import type { EventBus } from './EventBus';
8
+ import type { EntityManager } from './EntityManager';
9
+ import type { SystemContext } from './SystemContext';
10
+ import type { GameSystem } from './GameSystem';
11
+ export declare const GameWorldEvents: {
12
+ readonly PAUSED: "gameWorld:paused";
13
+ readonly RESUMED: "gameWorld:resumed";
14
+ };
15
+ export interface GameWorldConfig {
16
+ componentTypes?: symbol[];
17
+ tickRate?: number;
18
+ maxFrameTime?: number;
19
+ tickFrameProvider?: ITickFrameProvider;
20
+ pooling?: PoolingConfig;
21
+ debug?: boolean;
22
+ debugConfig?: DebugDataProviderConfig;
23
+ debugPanelConfig?: DebugPanelConfig;
24
+ }
25
+ export interface GameWorldHooks {
26
+ beforeTick?: (tick: number, commands: import('./ITickFrameProvider').CommandsBatch) => void;
27
+ afterTick?: (tick: number) => void;
28
+ beforeFrame?: (alpha: number, dt: number) => void;
29
+ afterFrame?: (alpha: number, dt: number) => void;
30
+ }
31
+ export declare class GameWorld {
32
+ private readonly systemRegistry;
33
+ private readonly provider;
34
+ private readonly ownsProvider;
35
+ private readonly _pools;
36
+ private readonly _poolingConfig;
37
+ private readonly _debugProvider;
38
+ private readonly _debugPanelConfig;
39
+ private _debugPanel;
40
+ private beforeTickSystems;
41
+ private afterTickSystems;
42
+ private beforeFrameSystems;
43
+ private afterFrameSystems;
44
+ private unsubscribeTick;
45
+ private unsubscribeFrame;
46
+ private unsubscribePause;
47
+ private unsubscribeResume;
48
+ private _paused;
49
+ constructor(config: GameWorldConfig);
50
+ get paused(): boolean;
51
+ pause(): void;
52
+ resume(): void;
53
+ get eventBus(): EventBus;
54
+ get entityManager(): EntityManager;
55
+ get pools(): PoolManager | null;
56
+ get debugProvider(): DebugDataProvider | null;
57
+ get debugPanel(): DebugPanel | null;
58
+ get context(): SystemContext;
59
+ getSystem<T extends GameSystem>(systemClass: new (...args: any[]) => T): T | undefined;
60
+ registerSystems(tickSystems: GameSystem[], frameSystems: GameSystem[]): void;
61
+ private buildLifecycleCaches;
62
+ addFrameSystem(system: GameSystem): void;
63
+ processAllTicks(tick: number): void;
64
+ updateAll(dt: number): void;
65
+ start(hooks?: GameWorldHooks): void;
66
+ stop(): void;
67
+ dispose(): void;
68
+ }
69
+ //# sourceMappingURL=GameWorld.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GameWorld.d.ts","sourceRoot":"","sources":["../src/GameWorld.ts"],"names":[],"mappings":"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"}