mani-game-engine 1.0.0-pre.5 → 1.0.0-pre.50

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/lib/gameEngine.js CHANGED
@@ -1,317 +1,369 @@
1
- import { EngineSignals } from './types';
2
- import { putIfAbsent } from 'mani-injector';
3
- import { EcsInjector, signalHandlers, staticSignalHandlers } from './ecsInjector';
4
- import { Clock } from './clock';
5
- const defaultOptions = {
6
- fixedDeltaTime: 1 / 60,
7
- plugins: [],
8
- };
9
- export class GameEngine {
10
- constructor(injector, clock) {
11
- this.injector = injector;
12
- this.clock = clock;
13
- this.onEarlyUpdateSet = new Set();
14
- this.onUpdateSet = new Set();
15
- this.onFixedUpdateSet = new Set();
16
- this.onPreFixedUpdateSet = new Set();
17
- this.onPhysicsUpdateSet = new Set();
18
- this.onPostPhysicsUpdateSet = new Set();
19
- this.onLateUpdateSet = new Set();
20
- this.onRenderUpdateSet = new Set();
21
- this.entitySystemMap = new Map();
22
- this.serviceClasses = new Set();
23
- this.services = [];
24
- this.resolveFrame = () => undefined;
25
- this.addQueue = [];
26
- this.removeQueue = [];
27
- this._started = false;
28
- this._frameCount = 0;
29
- this._fixedFrameCount = 0;
30
- this.signalMappings = new Map();
31
- this.staticSignalMappings = new Map();
32
- this.signalMapBindings = new Map();
33
- this.injector.map(GameEngine).toValue(this);
34
- this.onPrepare = this.injector.getSignal(EngineSignals.OnPrepare);
35
- this.onStart = this.injector.getSignal(EngineSignals.OnStart);
36
- this.onRender = this.injector.getSignal(EngineSignals.OnRender);
37
- this.onFixedUpdate = this.injector.getSignal(EngineSignals.OnFixedUpdate);
38
- this.onUpdate = this.injector.getSignal(EngineSignals.OnUpdate);
39
- this.onLateUpdate = this.injector.getSignal(EngineSignals.OnLateUpdate);
40
- this.onPostPhysics = this.injector.getSignal(EngineSignals.OnPostPhysics);
41
- this.setupClock();
42
- this.prepareFrame();
43
- }
44
- get started() { return this._started; }
45
- get frameCount() { return this._frameCount; }
46
- get fixedFrameCount() { return this._fixedFrameCount; }
47
- get numEntities() { return this.entitySystemMap.size; }
48
- static createDefault(options) {
49
- const opts = Object.assign(Object.assign({}, defaultOptions), options);
50
- const clock = new Clock({
51
- fixedDeltaTime: opts.fixedDeltaTime,
52
- autoStart: false,
53
- });
54
- const injector = new EcsInjector();
55
- const engine = new GameEngine(injector, clock);
56
- engine.installPlugins(opts.plugins);
57
- return engine;
58
- }
59
- static createDefaultWithInjector(injector, options) {
60
- const opts = Object.assign(Object.assign({}, defaultOptions), options);
61
- const clock = new Clock({
62
- fixedDeltaTime: opts.fixedDeltaTime,
63
- autoStart: false,
64
- });
65
- const engine = new GameEngine(injector, clock);
66
- engine.installPlugins(opts.plugins);
67
- return engine;
68
- }
69
- setupClock() {
70
- this.clock.onPrepare.add(this.prepareFrame, this);
71
- this.clock.onEarlyUpdate.add(({ time, deltaTime }) => {
72
- for (const system of this.onEarlyUpdateSet) {
73
- system.onEarlyUpdate(time, deltaTime);
74
- }
75
- });
76
- this.clock.onFixedUpdate.add((params) => {
77
- const { time, deltaTime } = params;
78
- for (const system of this.onPreFixedUpdateSet) {
79
- system.onPreFixedUpdate();
80
- }
81
- for (const system of this.onFixedUpdateSet) {
82
- system.onFixedUpdate(time, deltaTime);
83
- }
84
- this.onFixedUpdate.dispatch(params);
85
- for (const system of this.onPhysicsUpdateSet) {
86
- system.onPhysicsUpdate(time, deltaTime);
87
- }
88
- this.onPostPhysics.dispatch(params);
89
- for (const system of this.onPostPhysicsUpdateSet) {
90
- system.onPostPhysicsUpdate(time, deltaTime);
91
- }
92
- this._fixedFrameCount++;
93
- });
94
- this.clock.onUpdate.add(onUpdateParams => {
95
- const { time, deltaTime, alpha } = onUpdateParams;
96
- for (const system of this.onUpdateSet) {
97
- system.onUpdate(time, deltaTime, alpha);
98
- }
99
- this.onUpdate.dispatch(onUpdateParams);
100
- for (const system of this.onLateUpdateSet) {
101
- system.onLateUpdate(time, deltaTime, alpha);
102
- }
103
- this.onLateUpdate.dispatch(onUpdateParams);
104
- for (const system of this.onRenderUpdateSet) {
105
- system.onRender(time, deltaTime, alpha);
106
- }
107
- this.onRender.dispatch(onUpdateParams);
108
- this._frameCount++;
109
- });
110
- }
111
- installPlugins(plugins) {
112
- plugins.forEach(plugin => {
113
- plugin.onPrepare && plugin.onPrepare(this);
114
- });
115
- plugins.forEach(plugin => {
116
- plugin.onStart && plugin.onStart(this);
117
- });
118
- }
119
- registerSystem(systemClass) {
120
- this.mapStaticAnnotatedSignals(systemClass);
121
- if (this._started)
122
- throw new Error('Register Systems before engine is started');
123
- this.injector.registerSystem(systemClass);
124
- }
125
- registerService(serviceClass) {
126
- this.mapStaticAnnotatedSignals(serviceClass);
127
- if (this._started)
128
- throw new Error('Register Services before engine is started');
129
- this.injector.map(serviceClass).toSingleton();
130
- this.serviceClasses.add(serviceClass);
131
- }
132
- getService(serviceClass) {
133
- return this.injector.get(serviceClass);
134
- }
135
- start() {
136
- this._started = true;
137
- for (const serviceClass of this.serviceClasses) {
138
- const service = this.injector.get(serviceClass);
139
- this.addService(service);
140
- }
141
- this.clock.start();
142
- this.onStart.dispatch();
143
- }
144
- addService(service) {
145
- this.mapAnnotatedSignals(service);
146
- service.onStart && service.onStart();
147
- service.onPreFixedUpdate && this.onPreFixedUpdateSet.add(service);
148
- service.onFixedUpdate && this.onFixedUpdateSet.add(service);
149
- service.onUpdate && this.onUpdateSet.add(service);
150
- service.onLateUpdate && this.onLateUpdateSet.add(service);
151
- service.onPhysicsUpdate && this.onPhysicsUpdateSet.add(service);
152
- service.onPostPhysicsUpdate && this.onPostPhysicsUpdateSet.add(service);
153
- service.onRender && this.onRenderUpdateSet.add(service);
154
- this.services.push(service);
155
- }
156
- add(entity) {
157
- return new Promise(resolve => this.addQueue.push([entity, resolve]));
158
- }
159
- waitFrame() {
160
- return this.framePromise;
161
- }
162
- async remove(entity) {
163
- if (entity.markRemoval)
164
- return;
165
- entity.markRemoval = true;
166
- return new Promise(resolve => this.removeQueue.push([entity, resolve]));
167
- }
168
- stop() {
169
- this.clock.stop();
170
- }
171
- runAction(action) {
172
- return action(this);
173
- }
174
- getSignal(signalId) {
175
- return this.injector.getSignal(signalId);
176
- }
177
- mapStaticAnnotatedSignals(target) {
178
- let staticSignalMap = this.getStaticSignalMap(target);
179
- if (staticSignalMap.length === 0)
180
- return;
181
- const bindings = [];
182
- for (const [key, signal] of staticSignalMap) {
183
- bindings.push(signal.add(target[key], target));
184
- }
185
- }
186
- mapAnnotatedSignals(target) {
187
- const signalMap = this.getSignalMap(target.constructor);
188
- if (signalMap.length === 0)
189
- return;
190
- const bindings = [];
191
- for (const [key, signal] of signalMap) {
192
- bindings.push(signal.add(target[key], target));
193
- }
194
- this.signalMapBindings.set(target, bindings);
195
- }
196
- unmapAnnotatedSignals(target) {
197
- const signalBindings = this.signalMapBindings.get(target);
198
- if (!signalBindings)
199
- return;
200
- for (const binding of signalBindings) {
201
- binding.detach();
202
- }
203
- }
204
- getSignalMap(target) {
205
- return putIfAbsent(this.signalMappings, target, () => {
206
- const handlers = signalHandlers.get(target);
207
- if (!handlers)
208
- return [];
209
- const result = [];
210
- for (const [key, signalId] of handlers) {
211
- result.push([key, this.getSignal(signalId)]);
212
- }
213
- return result;
214
- });
215
- }
216
- getStaticSignalMap(target) {
217
- return putIfAbsent(this.staticSignalMappings, target, () => {
218
- const handlers = staticSignalHandlers.get(target);
219
- if (!handlers)
220
- return [];
221
- const result = [];
222
- for (const [key, signalId] of handlers) {
223
- result.push([key, this.getSignal(signalId)]);
224
- }
225
- return result;
226
- });
227
- }
228
- dispose() {
229
- this.clock.stop();
230
- for (const systems of this.entitySystemMap.values()) {
231
- for (const system of systems) {
232
- system.system.onEnd && system.system.onEnd();
233
- }
234
- }
235
- for (const service of this.services) {
236
- service.onEnd && service.onEnd();
237
- }
238
- }
239
- prepareFrame() {
240
- for (const [entity, resolve] of this.removeQueue) {
241
- const entities = entity.getAllEntities();
242
- for (const entity of entities) {
243
- entity.markRemoval = false;
244
- if (!entity.gameEngine) {
245
- console.log(entity);
246
- }
247
- entity.gameEngine = undefined;
248
- const systemContexts = this.entitySystemMap.get(entity);
249
- this.entitySystemMap.delete(entity);
250
- if (systemContexts) {
251
- for (const context of systemContexts) {
252
- context.dispose();
253
- const system = context.system;
254
- this.unmapAnnotatedSignals(system);
255
- system.onEnd && system.onEnd();
256
- system.onPreFixedUpdate && this.onPreFixedUpdateSet.delete(system);
257
- system.onFixedUpdate && this.onFixedUpdateSet.delete(system);
258
- system.onEarlyUpdate && this.onEarlyUpdateSet.delete(system);
259
- system.onUpdate && this.onUpdateSet.delete(system);
260
- system.onLateUpdate && this.onLateUpdateSet.delete(system);
261
- system.onPhysicsUpdate && this.onPhysicsUpdateSet.delete(system);
262
- system.onPostPhysicsUpdate && this.onPostPhysicsUpdateSet.delete(system);
263
- system.onRender && this.onRenderUpdateSet.delete(system);
264
- }
265
- }
266
- entity.onRemove.dispatch();
267
- }
268
- resolve();
269
- }
270
- this.removeQueue = [];
271
- for (const [entity, resolve] of this.addQueue) {
272
- const preparePromises = [];
273
- const nexSystemContexts = [];
274
- const entities = entity.getAllEntities();
275
- for (const entity of entities) {
276
- if (entity.gameEngine)
277
- throw new Error('Entity already added to a gameEngine');
278
- entity.gameEngine = this;
279
- const systemContexts = this.injector.createSystems(entity);
280
- for (const context of systemContexts) {
281
- context.system.onPrepare && preparePromises.push(context.system.onPrepare());
282
- nexSystemContexts.push(context);
283
- }
284
- this.entitySystemMap.set(entity, systemContexts);
285
- }
286
- const startSystems = () => {
287
- for (const context of nexSystemContexts) {
288
- const system = context.system;
289
- this.mapAnnotatedSignals(system);
290
- system.onStart && system.onStart();
291
- system.onPreFixedUpdate && this.onPreFixedUpdateSet.add(system);
292
- system.onFixedUpdate && this.onFixedUpdateSet.add(system);
293
- system.onEarlyUpdate && this.onEarlyUpdateSet.add(system);
294
- system.onUpdate && this.onUpdateSet.add(system);
295
- system.onLateUpdate && this.onLateUpdateSet.add(system);
296
- system.onPhysicsUpdate && this.onPhysicsUpdateSet.add(system);
297
- system.onPostPhysicsUpdate && this.onPostPhysicsUpdateSet.add(system);
298
- system.onRender && this.onRenderUpdateSet.add(system);
299
- }
300
- resolve();
301
- };
302
- if (preparePromises.length === 0) {
303
- startSystems();
304
- }
305
- else {
306
- Promise.all(preparePromises).then(startSystems);
307
- }
308
- }
309
- this.addQueue = [];
310
- this.resolveFrame();
311
- this.framePromise = new Promise(resolve => {
312
- this.resolveFrame = resolve;
313
- });
314
- this.onPrepare.dispatch();
315
- }
316
- }
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GameEngine = void 0;
4
+ const types_1 = require("./types");
5
+ const ecsInjector_1 = require("./ecsInjector");
6
+ const clock_1 = require("./clock");
7
+ const injector_1 = require("./injector");
8
+ const defaultOptions = {
9
+ fixedDeltaTime: 1 / 60,
10
+ plugins: [],
11
+ };
12
+ let id = 0;
13
+ class GameEngine {
14
+ get started() { return this._started; }
15
+ get frameCount() { return this._frameCount; }
16
+ get fixedFrameCount() { return this._fixedFrameCount; }
17
+ get numEntities() { return this.entitySystemMap.size; }
18
+ constructor(injector, clock) {
19
+ this.injector = injector;
20
+ this.clock = clock;
21
+ this.id = id++;
22
+ this.onEarlyUpdateSet = new Set();
23
+ this.onUpdateSet = new Set();
24
+ this.onFixedUpdateSet = new Set();
25
+ this.onPreFixedUpdateSet = new Set();
26
+ this.onPhysicsUpdateSet = new Set();
27
+ this.onPrePhysicsUpdateSet = new Set();
28
+ this.onPostPhysicsUpdateSet = new Set();
29
+ this.onLateFixedUpdateSet = new Set();
30
+ this.onLateUpdateSet = new Set();
31
+ this.onRenderUpdateSet = new Set();
32
+ this.onAddEntitySet = new Set();
33
+ this.onRemoveEntitySet = new Set();
34
+ this.entitySystemMap = new Map();
35
+ this.serviceClasses = new Set();
36
+ this.services = [];
37
+ this.resolveFrame = () => undefined;
38
+ this.addQueue = [];
39
+ this.removeQueue = [];
40
+ this._started = false;
41
+ this._frameCount = 0;
42
+ this._fixedFrameCount = 0;
43
+ this.signalMappings = new Map();
44
+ this.staticSignalMappings = new Map();
45
+ this.signalMapBindings = new Map();
46
+ this.injector.map(GameEngine).toValue(this);
47
+ this.onPrepare = this.injector.getSignal(types_1.EngineSignals.OnPrepare);
48
+ this.onStart = this.injector.getSignal(types_1.EngineSignals.OnStart);
49
+ this.onEnd = this.injector.getSignal(types_1.EngineSignals.OnEnd);
50
+ this.onRender = this.injector.getSignal(types_1.EngineSignals.OnRender);
51
+ this.onFixedUpdate = this.injector.getSignal(types_1.EngineSignals.OnFixedUpdate);
52
+ this.onUpdate = this.injector.getSignal(types_1.EngineSignals.OnUpdate);
53
+ this.onLateUpdate = this.injector.getSignal(types_1.EngineSignals.OnLateUpdate);
54
+ this.onPrePhysicsUpdate = this.injector.getSignal(types_1.EngineSignals.OnPrePhysicsUpdate);
55
+ this.onPhysicsUpdate = this.injector.getSignal(types_1.EngineSignals.OnPhysicsUpdate);
56
+ this.onPostPhysicsUpdate = this.injector.getSignal(types_1.EngineSignals.OnPostPhysicsUpdate);
57
+ this.onLateFixedUpdate = this.injector.getSignal(types_1.EngineSignals.onLateFixedUpdate);
58
+ this.onAddEntity = this.injector.getSignal(types_1.EngineSignals.OnAddEntity);
59
+ this.onRemoveEntity = this.injector.getSignal(types_1.EngineSignals.OnRemoveEntity);
60
+ this.setupClock();
61
+ this.prepareFrame();
62
+ }
63
+ static createDefault(options) {
64
+ const opts = Object.assign(Object.assign({}, defaultOptions), options);
65
+ const clock = new clock_1.GameClock({
66
+ fixedDeltaTime: opts.fixedDeltaTime,
67
+ autoStart: false,
68
+ });
69
+ const injector = new ecsInjector_1.EcsInjector();
70
+ const engine = new GameEngine(injector, clock);
71
+ engine.installPlugins(opts.plugins);
72
+ return engine;
73
+ }
74
+ static createDefaultWithInjector(injector, options) {
75
+ const opts = Object.assign(Object.assign({}, defaultOptions), options);
76
+ const clock = new clock_1.GameClock({
77
+ fixedDeltaTime: opts.fixedDeltaTime,
78
+ autoStart: false,
79
+ });
80
+ const engine = new GameEngine(injector, clock);
81
+ engine.installPlugins(opts.plugins);
82
+ return engine;
83
+ }
84
+ addService(service) {
85
+ this.mapAnnotatedSignals(service);
86
+ service.onStart && service.onStart();
87
+ service.onPreFixedUpdate && this.onPreFixedUpdateSet.add(service);
88
+ service.onFixedUpdate && this.onFixedUpdateSet.add(service);
89
+ service.onUpdate && this.onUpdateSet.add(service);
90
+ service.onLateUpdate && this.onLateUpdateSet.add(service);
91
+ service.onPrePhysicsUpdate && this.onPrePhysicsUpdateSet.add(service);
92
+ service.onPhysicsUpdate && this.onPhysicsUpdateSet.add(service);
93
+ service.onPostPhysicsUpdate && this.onPostPhysicsUpdateSet.add(service);
94
+ service.onLateFixedUpdate && this.onLateFixedUpdateSet.add(service);
95
+ service.onRender && this.onRenderUpdateSet.add(service);
96
+ service.onAddEntity && this.onAddEntitySet.add(service);
97
+ service.onRemoveEntity && this.onRemoveEntitySet.add(service);
98
+ this.services.push(service);
99
+ }
100
+ installPlugins(plugins) {
101
+ plugins.forEach(plugin => {
102
+ plugin.onPrepare && plugin.onPrepare(this);
103
+ });
104
+ plugins.forEach(plugin => {
105
+ plugin.onStart && plugin.onStart(this);
106
+ });
107
+ }
108
+ registerSystem(systemClass) {
109
+ this.mapStaticAnnotatedSignals(systemClass);
110
+ if (this._started)
111
+ throw new Error('Register Systems before engine is started');
112
+ this.injector.registerSystem(systemClass);
113
+ }
114
+ registerService(serviceClass) {
115
+ this.mapStaticAnnotatedSignals(serviceClass);
116
+ if (this._started)
117
+ throw new Error('Register Services before engine is started');
118
+ this.injector.map(serviceClass).toSingleton();
119
+ this.serviceClasses.add(serviceClass);
120
+ }
121
+ getService(serviceClass) {
122
+ return this.injector.get(serviceClass);
123
+ }
124
+ start() {
125
+ this._started = true;
126
+ for (const serviceClass of this.serviceClasses) {
127
+ const service = this.injector.get(serviceClass);
128
+ this.addService(service);
129
+ }
130
+ this.clock.start();
131
+ this.onStart.dispatch();
132
+ }
133
+ setupClock() {
134
+ this.clock.onPrepare.add(this.prepareFrame, this);
135
+ this.clock.onEarlyUpdate.add(({ time, deltaTime }) => {
136
+ for (const system of this.onEarlyUpdateSet) {
137
+ system.onEarlyUpdate(time, deltaTime);
138
+ }
139
+ });
140
+ this.clock.onFixedUpdate.add((params) => {
141
+ const { time, deltaTime } = params;
142
+ for (const system of this.onPreFixedUpdateSet) {
143
+ system.onPreFixedUpdate(time, deltaTime);
144
+ }
145
+ for (const system of this.onFixedUpdateSet) {
146
+ system.onFixedUpdate(time, deltaTime);
147
+ }
148
+ this.onFixedUpdate.dispatch(params);
149
+ for (const system of this.onPhysicsUpdateSet) {
150
+ system.onPhysicsUpdate(time, deltaTime);
151
+ }
152
+ this.onPhysicsUpdate.dispatch(params);
153
+ this.onPostPhysicsUpdate.dispatch(params);
154
+ for (const system of this.onPostPhysicsUpdateSet) {
155
+ system.onPostPhysicsUpdate(time, deltaTime);
156
+ }
157
+ this.onLateFixedUpdate.dispatch(params);
158
+ for (const system of this.onLateFixedUpdateSet) {
159
+ system.onLateFixedUpdate(time, deltaTime);
160
+ }
161
+ this._fixedFrameCount++;
162
+ });
163
+ this.clock.onUpdate.add(onUpdateParams => {
164
+ const { time, deltaTime, alpha } = onUpdateParams;
165
+ for (const system of this.onUpdateSet) {
166
+ system.onUpdate(time, deltaTime, alpha);
167
+ }
168
+ this.onUpdate.dispatch(onUpdateParams);
169
+ for (const system of this.onLateUpdateSet) {
170
+ system.onLateUpdate(time, deltaTime, alpha);
171
+ }
172
+ this.onLateUpdate.dispatch(onUpdateParams);
173
+ for (const system of this.onRenderUpdateSet) {
174
+ system.onRender(time, deltaTime, alpha);
175
+ }
176
+ this.onRender.dispatch(onUpdateParams);
177
+ this._frameCount++;
178
+ });
179
+ }
180
+ add(entity) {
181
+ return new Promise(resolve => this.addQueue.push([entity, resolve]));
182
+ }
183
+ waitFrame() {
184
+ return this.framePromise;
185
+ }
186
+ async remove(entity) {
187
+ if (entity.markRemoval)
188
+ return;
189
+ entity.markRemoval = true;
190
+ return new Promise(resolve => this.removeQueue.push([entity, resolve]));
191
+ }
192
+ stop() {
193
+ this.clock.stop();
194
+ }
195
+ runAction(action) {
196
+ return action(this);
197
+ }
198
+ getSignal(signalId) {
199
+ return this.injector.getSignal(signalId);
200
+ }
201
+ mapStaticAnnotatedSignals(target) {
202
+ let staticSignalMap = this.getStaticSignalMap(target);
203
+ if (staticSignalMap.length === 0)
204
+ return;
205
+ const bindings = [];
206
+ for (const [key, signal] of staticSignalMap) {
207
+ bindings.push(signal.add(target[key], target));
208
+ }
209
+ }
210
+ mapAnnotatedSignals(target) {
211
+ const signalMap = this.getSignalMap(target.constructor);
212
+ if (signalMap.length === 0)
213
+ return;
214
+ const bindings = [];
215
+ for (const [key, signal] of signalMap) {
216
+ bindings.push(signal.add(target[key], target));
217
+ }
218
+ this.signalMapBindings.set(target, bindings);
219
+ }
220
+ unmapAnnotatedSignals(target) {
221
+ const signalBindings = this.signalMapBindings.get(target);
222
+ if (!signalBindings)
223
+ return;
224
+ for (const binding of signalBindings) {
225
+ binding.detach();
226
+ }
227
+ }
228
+ getSignalMap(target) {
229
+ return (0, injector_1.putIfAbsent)(this.signalMappings, target, () => {
230
+ const handlers = ecsInjector_1.signalHandlers.get(target);
231
+ if (!handlers)
232
+ return [];
233
+ const result = [];
234
+ for (const [key, signalId] of handlers) {
235
+ result.push([key, this.getSignal(signalId)]);
236
+ }
237
+ return result;
238
+ });
239
+ }
240
+ getStaticSignalMap(target) {
241
+ return (0, injector_1.putIfAbsent)(this.staticSignalMappings, target, () => {
242
+ const handlers = ecsInjector_1.staticSignalHandlers.get(target);
243
+ if (!handlers)
244
+ return [];
245
+ const result = [];
246
+ for (const [key, signalId] of handlers) {
247
+ result.push([key, this.getSignal(signalId)]);
248
+ }
249
+ return result;
250
+ });
251
+ }
252
+ dispose() {
253
+ this.clock.stop();
254
+ this.clock.dispose();
255
+ for (const systems of this.entitySystemMap.values()) {
256
+ for (const system of systems) {
257
+ system.system.onEnd && system.system.onEnd();
258
+ }
259
+ }
260
+ for (const service of this.services) {
261
+ service.onEnd && service.onEnd();
262
+ }
263
+ this.onEnd.dispatch();
264
+ }
265
+ prepareFrame() {
266
+ for (const [entity, resolve] of this.removeQueue) {
267
+ const entities = entity.getAllEntities();
268
+ for (const entity of entities) {
269
+ entity.markRemoval = false;
270
+ if (!entity.gameEngine) {
271
+ console.log(entity);
272
+ }
273
+ entity.gameEngine = undefined;
274
+ const systemContexts = this.entitySystemMap.get(entity);
275
+ this.entitySystemMap.delete(entity);
276
+ if (systemContexts) {
277
+ for (const context of systemContexts) {
278
+ this.disposeContext(context);
279
+ }
280
+ }
281
+ entity.onRemove.dispatch();
282
+ entity.onRemove.detachAll();
283
+ for (const system of this.onRemoveEntitySet) {
284
+ system.onRemoveEntity(entity);
285
+ }
286
+ }
287
+ resolve();
288
+ }
289
+ this.removeQueue = [];
290
+ for (const [entity, resolve] of this.addQueue) {
291
+ const preparePromises = [];
292
+ const nextSystemContexts = [];
293
+ const entities = entity.getAllEntities();
294
+ for (const entity of entities) {
295
+ if (entity.gameEngine)
296
+ throw new Error('Entity already added to a gameEngine');
297
+ entity.gameEngine = this;
298
+ const systemContexts = this.injector.createSystemsForEntity(entity);
299
+ for (const context of systemContexts) {
300
+ context.system.onPrepare && preparePromises.push(context.system.onPrepare());
301
+ nextSystemContexts.push(context);
302
+ }
303
+ this.entitySystemMap.set(entity, systemContexts);
304
+ }
305
+ const entityWasAdded = () => {
306
+ for (const system of this.onAddEntitySet) {
307
+ system.onAddEntity(entity);
308
+ }
309
+ resolve();
310
+ };
311
+ if (preparePromises.length === 0) {
312
+ this.startSystems(nextSystemContexts, entityWasAdded);
313
+ }
314
+ else {
315
+ Promise.all(preparePromises).then(() => this.startSystems(nextSystemContexts, entityWasAdded));
316
+ }
317
+ }
318
+ this.addQueue = [];
319
+ this.resolveFrame();
320
+ this.framePromise = new Promise(resolve => {
321
+ this.resolveFrame = resolve;
322
+ });
323
+ this.onPrepare.dispatch();
324
+ }
325
+ startSystems(contexts, then) {
326
+ for (const context of contexts) {
327
+ const system = context.system;
328
+ this.mapAnnotatedSignals(system);
329
+ system.onStart && system.onStart();
330
+ system.onPreFixedUpdate && this.onPreFixedUpdateSet.add(system);
331
+ system.onFixedUpdate && this.onFixedUpdateSet.add(system);
332
+ system.onUpdate && this.onUpdateSet.add(system);
333
+ system.onLateUpdate && this.onLateUpdateSet.add(system);
334
+ system.onPhysicsUpdate && this.onPhysicsUpdateSet.add(system);
335
+ system.onPrePhysicsUpdate && this.onPrePhysicsUpdateSet.add(system);
336
+ system.onPostPhysicsUpdate && this.onPostPhysicsUpdateSet.add(system);
337
+ system.onLateFixedUpdate && this.onLateFixedUpdateSet.add(system);
338
+ system.onRender && this.onRenderUpdateSet.add(system);
339
+ system.onAddEntity && this.onAddEntitySet.add(system);
340
+ system.onRemoveEntity && this.onRemoveEntitySet.add(system);
341
+ }
342
+ then === null || then === void 0 ? void 0 : then();
343
+ }
344
+ ;
345
+ disposeContext(context) {
346
+ const system = context.system;
347
+ const onEndPromise = system.onEnd && system.onEnd();
348
+ if (onEndPromise instanceof Promise) {
349
+ onEndPromise.then(() => {
350
+ context.dispose();
351
+ });
352
+ }
353
+ else {
354
+ context.dispose();
355
+ }
356
+ this.unmapAnnotatedSignals(system);
357
+ system.onPreFixedUpdate && this.onPreFixedUpdateSet.delete(system);
358
+ system.onFixedUpdate && this.onFixedUpdateSet.delete(system);
359
+ system.onUpdate && this.onUpdateSet.delete(system);
360
+ system.onLateUpdate && this.onLateUpdateSet.delete(system);
361
+ system.onPhysicsUpdate && this.onPhysicsUpdateSet.delete(system);
362
+ system.onPrePhysicsUpdate && this.onPrePhysicsUpdateSet.delete(system);
363
+ system.onPostPhysicsUpdate && this.onPostPhysicsUpdateSet.delete(system);
364
+ system.onLateFixedUpdate && this.onLateFixedUpdateSet.delete(system);
365
+ system.onRender && this.onRenderUpdateSet.delete(system);
366
+ }
367
+ }
368
+ exports.GameEngine = GameEngine;
317
369
  //# sourceMappingURL=gameEngine.js.map