@vworlds/vecs 1.0.11 → 1.0.12
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/.husky/pre-commit +1 -0
- package/README.md +85 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/package.json +1 -1
- package/dist/phase.d.ts +7 -2
- package/dist/phase.js.map +1 -1
- package/dist/system.d.ts +114 -2
- package/dist/system.js +142 -3
- package/dist/system.js.map +1 -1
- package/dist/timer.d.ts +50 -0
- package/dist/timer.js +154 -0
- package/dist/timer.js.map +1 -0
- package/dist/world.d.ts +26 -2
- package/dist/world.js +63 -6
- package/dist/world.js.map +1 -1
- package/package.json +1 -1
package/.husky/pre-commit
CHANGED
package/README.md
CHANGED
|
@@ -217,9 +217,14 @@ const send = world.addPhase("send");
|
|
|
217
217
|
world.progress(now, delta);
|
|
218
218
|
|
|
219
219
|
// ...or run individual phases manually:
|
|
220
|
-
world.
|
|
221
|
-
|
|
222
|
-
world.runPhase(
|
|
220
|
+
world.beginFrame(now, delta);
|
|
221
|
+
try {
|
|
222
|
+
world.runPhase(preUpdate, now, delta);
|
|
223
|
+
world.runPhase(update, now, delta);
|
|
224
|
+
world.runPhase(send, now, delta);
|
|
225
|
+
} finally {
|
|
226
|
+
world.endFrame();
|
|
227
|
+
}
|
|
223
228
|
```
|
|
224
229
|
|
|
225
230
|
Systems with no explicit phase are placed in the built-in `"update"` phase.
|
|
@@ -237,6 +242,67 @@ world
|
|
|
237
242
|
.exit(...);
|
|
238
243
|
```
|
|
239
244
|
|
|
245
|
+
#### Timers and rate filters
|
|
246
|
+
|
|
247
|
+
Systems can opt into a slower cadence instead of running on every phase tick. `interval()` takes seconds; throttled `run()` callbacks receive the accumulated milliseconds since the previous fire as `delta`.
|
|
248
|
+
|
|
249
|
+
```ts
|
|
250
|
+
import { IntervalTickSource, RateTickSource } from "@vworlds/vecs";
|
|
251
|
+
|
|
252
|
+
world
|
|
253
|
+
.system("Move")
|
|
254
|
+
.interval(1.0)
|
|
255
|
+
.each([Position], (e, [pos]) => {
|
|
256
|
+
// 1 Hz
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
world
|
|
260
|
+
.system("Move")
|
|
261
|
+
.rate(2)
|
|
262
|
+
.each([Position], (e, [pos]) => {
|
|
263
|
+
// every 2nd frame
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
const second = new IntervalTickSource(1.0);
|
|
267
|
+
|
|
268
|
+
world
|
|
269
|
+
.system("Move")
|
|
270
|
+
.tickSource(second)
|
|
271
|
+
.each([Position], (e, [pos]) => {
|
|
272
|
+
// driven by a shared timer
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
second.stop();
|
|
276
|
+
second.start();
|
|
277
|
+
|
|
278
|
+
const minute = new RateTickSource(60, second);
|
|
279
|
+
const hour = world
|
|
280
|
+
.system("Hour")
|
|
281
|
+
.tickSource(minute)
|
|
282
|
+
.rate(60)
|
|
283
|
+
.run((now, delta) => {
|
|
284
|
+
console.log("hour tick", now, delta);
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
// Systems can also be tick sources for each other.
|
|
288
|
+
const eachSecond = world
|
|
289
|
+
.system("EachSecond")
|
|
290
|
+
.interval(1)
|
|
291
|
+
.run(() => {
|
|
292
|
+
// ...
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
const eachMinute = world
|
|
296
|
+
.system("EachMinute")
|
|
297
|
+
.tickSource(eachSecond)
|
|
298
|
+
.rate(60)
|
|
299
|
+
.run(() => {
|
|
300
|
+
// ...
|
|
301
|
+
});
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Tick source objects and systems can both be used as sources. Disabling a source system suppresses its callbacks, but its clock still drives downstream consumers.
|
|
305
|
+
|
|
240
306
|
#### Queries
|
|
241
307
|
|
|
242
308
|
```ts
|
|
@@ -489,6 +555,22 @@ Fires every tick when the system's phase runs, regardless of entity state. Use f
|
|
|
489
555
|
});
|
|
490
556
|
```
|
|
491
557
|
|
|
558
|
+
#### `.disable()` / `.enable()`
|
|
559
|
+
|
|
560
|
+
Pause and resume a system at runtime. While disabled the system is effectively invisible: the inbox is cleared immediately, any new `enter`, `exit`, or `update` events are silently dropped, `run` and `each` callbacks do not fire, and the system skips its `_run` entirely. Entity membership in the underlying query is still maintained, so the tracked set remains correct and the system resumes cleanly when re-enabled. Events that occurred while the system was disabled are **not** replayed.
|
|
561
|
+
|
|
562
|
+
```ts
|
|
563
|
+
const ai = world.system("AI").requires(Enemy).run(tickAI);
|
|
564
|
+
|
|
565
|
+
// Pause AI processing during a cutscene:
|
|
566
|
+
ai.disable();
|
|
567
|
+
|
|
568
|
+
// Resume normal processing:
|
|
569
|
+
ai.enable();
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
Both methods return `this` for chaining and are idempotent (calling `disable()` on an already-disabled system, or `enable()` on an already-enabled system, is a no-op).
|
|
573
|
+
|
|
492
574
|
#### `.destroy()`
|
|
493
575
|
|
|
494
576
|
**Not supported on `System`** — calling it throws. Systems live for the duration of the world. Use a standalone `Query` for temporary reactive sets.
|
package/dist/index.d.ts
CHANGED
|
@@ -5,4 +5,5 @@ export { Filter } from "./filter.js";
|
|
|
5
5
|
export { Component, type ComponentMeta } from "./component.js";
|
|
6
6
|
export { type Entity } from "./entity.js";
|
|
7
7
|
export { type IPhase } from "./phase.js";
|
|
8
|
+
export { IntervalTickSource, RateTickSource, type ITickSource } from "./timer.js";
|
|
8
9
|
export { Bitset } from "./util/bitset.js";
|
package/dist/index.js
CHANGED
|
@@ -2,5 +2,6 @@ export { Query } from "./query.js";
|
|
|
2
2
|
export { World } from "./world.js";
|
|
3
3
|
export { Filter } from "./filter.js";
|
|
4
4
|
export { Component } from "./component.js";
|
|
5
|
+
export { IntervalTickSource, RateTickSource } from "./timer.js";
|
|
5
6
|
export { Bitset } from "./util/bitset.js";
|
|
6
7
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,SAAS,EAAsB,MAAM,gBAAgB,CAAC;AAG/D,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,SAAS,EAAsB,MAAM,gBAAgB,CAAC;AAG/D,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAoB,MAAM,YAAY,CAAC;AAClF,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/package.json
CHANGED
package/dist/phase.d.ts
CHANGED
|
@@ -12,8 +12,13 @@ import { type World } from "./world.js";
|
|
|
12
12
|
* world.system("NetworkUpdate").phase(preUpdate).run(tick);
|
|
13
13
|
*
|
|
14
14
|
* // each frame:
|
|
15
|
-
* world.
|
|
16
|
-
*
|
|
15
|
+
* world.beginFrame(now, delta);
|
|
16
|
+
* try {
|
|
17
|
+
* world.runPhase(preUpdate, now, delta);
|
|
18
|
+
* world.runPhase(send, now, delta);
|
|
19
|
+
* } finally {
|
|
20
|
+
* world.endFrame();
|
|
21
|
+
* }
|
|
17
22
|
* ```
|
|
18
23
|
*/
|
|
19
24
|
export interface IPhase {
|
package/dist/phase.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"phase.js","sourceRoot":"","sources":["../src/phase.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"phase.js","sourceRoot":"","sources":["../src/phase.ts"],"names":[],"mappings":"AAgCA;;;;;;;;;;GAUG;AACH,MAAM,OAAO,KAAK;IAIhB;IACE,sDAAsD;IACtC,IAAY;IAC5B,kCAAkC;IAClB,KAAY;QAFZ,SAAI,GAAJ,IAAI,CAAQ;QAEZ,UAAK,GAAL,KAAK,CAAO;QAP9B,4DAA4D;QACrD,YAAO,GAAa,EAAE,CAAC;IAO3B,CAAC;CACL"}
|
package/dist/system.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { type QueryDSL, type MaybeRequired } from "./dsl.js";
|
|
|
4
4
|
import type { Entity } from "./entity.js";
|
|
5
5
|
import { type IPhase } from "./phase.js";
|
|
6
6
|
import { type World } from "./world.js";
|
|
7
|
+
import { type ITickSource } from "./timer.js";
|
|
7
8
|
export type { QueryDSL as SystemQuery, EntityTestFunc } from "./dsl.js";
|
|
8
9
|
type RunCallback = (now: number, delta: number) => void;
|
|
9
10
|
/**
|
|
@@ -43,8 +44,75 @@ type RunCallback = (now: number, delta: number) => void;
|
|
|
43
44
|
*
|
|
44
45
|
* @typeParam R - Component classes guaranteed present on every matched entity.
|
|
45
46
|
*/
|
|
46
|
-
export declare class System<R extends (typeof Component)[] = []> extends Query<R> {
|
|
47
|
+
export declare class System<R extends (typeof Component)[] = []> extends Query<R> implements ITickSource {
|
|
47
48
|
constructor(name: string, world: World);
|
|
49
|
+
/** True when this system's cadence source fired during the current frame. */
|
|
50
|
+
get didTick(): boolean;
|
|
51
|
+
/** Milliseconds accumulated into this system's most recent fire. */
|
|
52
|
+
get lastFireDelta(): number;
|
|
53
|
+
/**
|
|
54
|
+
* Run this system at a fixed interval, expressed in seconds.
|
|
55
|
+
*
|
|
56
|
+
* This is seconds, unlike `World.beginFrame`, `World.progress`, and
|
|
57
|
+
* `runPhase`, which receive millisecond deltas. Calling `interval` replaces
|
|
58
|
+
* the current cadence source with an {@link IntervalTickSource}. When this
|
|
59
|
+
* system has a cadence source, the `delta` passed to {@link run} is the
|
|
60
|
+
* accumulated milliseconds since the previous fire, not the per-frame delta.
|
|
61
|
+
*
|
|
62
|
+
* @param seconds - Positive interval duration in seconds.
|
|
63
|
+
* @returns This system, for chaining.
|
|
64
|
+
* @throws When `seconds` is less than or equal to zero.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```ts
|
|
68
|
+
* world.system("AI")
|
|
69
|
+
* .interval(0.5)
|
|
70
|
+
* .run((now, delta) => tickAI(delta));
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
interval(seconds: number): this;
|
|
74
|
+
/**
|
|
75
|
+
* Run this system every `n` ticks from the world or an upstream source.
|
|
76
|
+
*
|
|
77
|
+
* Without a `source`, this composes with the current cadence source. For an
|
|
78
|
+
* unconfigured system, that means every `n` frames. With a `source`, it
|
|
79
|
+
* replaces the current cadence with a {@link RateTickSource} over that source.
|
|
80
|
+
* The `delta` passed to {@link run} is the accumulated milliseconds since
|
|
81
|
+
* this system last fired.
|
|
82
|
+
*
|
|
83
|
+
* @param n - Positive integer tick divisor.
|
|
84
|
+
* @param source - Optional upstream source to divide.
|
|
85
|
+
* @returns This system, for chaining.
|
|
86
|
+
* @throws When `n` is not a positive integer.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```ts
|
|
90
|
+
* world.system("SendSnapshots")
|
|
91
|
+
* .rate(2)
|
|
92
|
+
* .run(flushNetwork);
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
rate(n: number): this;
|
|
96
|
+
rate(n: number, source: ITickSource): this;
|
|
97
|
+
/**
|
|
98
|
+
* Run this system only when another timer or system ticks.
|
|
99
|
+
*
|
|
100
|
+
* Calling `tickSource` mirrors `source` directly; no wrapper source is
|
|
101
|
+
* created. Use `.tickSource(source).rate(n)` or `.rate(n, source)` when this
|
|
102
|
+
* system should divide an upstream source. The `delta` passed to {@link run}
|
|
103
|
+
* is the accumulated milliseconds since this system last fired.
|
|
104
|
+
*
|
|
105
|
+
* @param source - Tick source or system source to mirror.
|
|
106
|
+
* @returns This system, for chaining.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```ts
|
|
110
|
+
* const second = new IntervalTickSource(1);
|
|
111
|
+
* world.system("Logger").tickSource(second).run(logStats);
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
tickSource(source: ITickSource): this;
|
|
115
|
+
private _setTickSource;
|
|
48
116
|
/**
|
|
49
117
|
* Assign this system to a pipeline phase.
|
|
50
118
|
*
|
|
@@ -66,7 +134,9 @@ export declare class System<R extends (typeof Component)[] = []> extends Query<R
|
|
|
66
134
|
* network flushing, global timers, etc.
|
|
67
135
|
*
|
|
68
136
|
* @param callback - Receives `now` (absolute timestamp in ms) and `delta`
|
|
69
|
-
* (ms since the previous tick).
|
|
137
|
+
* (ms since the previous tick). If the system has an active interval,
|
|
138
|
+
* rate, or tick source, `delta` is the accumulated milliseconds since this
|
|
139
|
+
* system last fired.
|
|
70
140
|
* @returns This system, for chaining.
|
|
71
141
|
*/
|
|
72
142
|
run(callback: RunCallback): this;
|
|
@@ -133,6 +203,48 @@ export declare class System<R extends (typeof Component)[] = []> extends Query<R
|
|
|
133
203
|
* @returns This system, retyped with the required tuple as its `R`.
|
|
134
204
|
*/
|
|
135
205
|
requires<T extends (typeof Component)[]>(...components: [...T]): System<T>;
|
|
206
|
+
/**
|
|
207
|
+
* Disable this system.
|
|
208
|
+
*
|
|
209
|
+
* While disabled the system is effectively invisible: the inbox is cleared
|
|
210
|
+
* immediately, any new `enter`, `exit`, or `update` events are silently
|
|
211
|
+
* dropped, and {@link _run} returns without executing any callbacks. Entity
|
|
212
|
+
* membership in the underlying query is still maintained so the tracked set
|
|
213
|
+
* remains consistent and the system resumes correctly when
|
|
214
|
+
* {@link enable} is called.
|
|
215
|
+
*
|
|
216
|
+
* Disabling is independent from tick-source cadence: `disable` suppresses
|
|
217
|
+
* callbacks, but a disabled system used as a tick source still drives
|
|
218
|
+
* downstream consumers. Use `stop()` on an external `IntervalTickSource` or
|
|
219
|
+
* `RateTickSource` reference to halt that clock itself.
|
|
220
|
+
*
|
|
221
|
+
* Calling `disable` on an already-disabled system is a no-op.
|
|
222
|
+
*
|
|
223
|
+
* @returns This system, for chaining.
|
|
224
|
+
*
|
|
225
|
+
* @example
|
|
226
|
+
* ```ts
|
|
227
|
+
* const sys = world.system("AI").requires(Enemy).run(runAI);
|
|
228
|
+
* // Pause AI processing during a cutscene:
|
|
229
|
+
* sys.disable();
|
|
230
|
+
* // Resume:
|
|
231
|
+
* sys.enable();
|
|
232
|
+
* ```
|
|
233
|
+
*/
|
|
234
|
+
disable(): this;
|
|
235
|
+
/**
|
|
236
|
+
* Enable this system after a previous {@link disable} call.
|
|
237
|
+
*
|
|
238
|
+
* Once re-enabled the system resumes its normal tick behaviour: enter, exit,
|
|
239
|
+
* and update events are queued, and {@link _run} processes the inbox and fires
|
|
240
|
+
* all registered callbacks. Events that occurred while the system was disabled
|
|
241
|
+
* are not replayed.
|
|
242
|
+
*
|
|
243
|
+
* Calling `enable` on an already-enabled system is a no-op.
|
|
244
|
+
*
|
|
245
|
+
* @returns This system, for chaining.
|
|
246
|
+
*/
|
|
247
|
+
enable(): this;
|
|
136
248
|
/**
|
|
137
249
|
* Not supported on `System`. Throws unconditionally.
|
|
138
250
|
*
|
package/dist/system.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Query } from "./query.js";
|
|
2
2
|
import { Phase } from "./phase.js";
|
|
3
|
+
import { ALWAYS_TICK_SOURCE, IntervalTickSource, RateTickSource, } from "./timer.js";
|
|
3
4
|
/**
|
|
4
5
|
* A reactive processor running over a filtered subset of world entities.
|
|
5
6
|
*
|
|
@@ -42,6 +43,10 @@ export class System extends Query {
|
|
|
42
43
|
super(name, world, false);
|
|
43
44
|
/** @internal Single inbox replayed in arrival order on every `_run`. */
|
|
44
45
|
this._inbox = [];
|
|
46
|
+
/** @internal Whether this system processes events and runs callbacks. */
|
|
47
|
+
this._enabled = true;
|
|
48
|
+
/** @internal Cadence source for this system. Defaults to every frame. */
|
|
49
|
+
this._tickSource = ALWAYS_TICK_SOURCE;
|
|
45
50
|
}
|
|
46
51
|
/**
|
|
47
52
|
* @internal Routing entry: register query membership for `e`, push an
|
|
@@ -52,6 +57,9 @@ export class System extends Query {
|
|
|
52
57
|
_enter(e) {
|
|
53
58
|
this._entities?.add(e);
|
|
54
59
|
e._addQueryMembership(this);
|
|
60
|
+
if (!this._enabled) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
55
63
|
if (this._enterCallback !== undefined) {
|
|
56
64
|
this._inbox.push({ kind: 0 /* InboxCommand.Enter */, entity: e });
|
|
57
65
|
}
|
|
@@ -70,6 +78,9 @@ export class System extends Query {
|
|
|
70
78
|
_exit(e) {
|
|
71
79
|
this._entities?.delete(e);
|
|
72
80
|
e._removeQueryMembership(this);
|
|
81
|
+
if (!this._enabled) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
73
84
|
if (this._exitCallback !== undefined) {
|
|
74
85
|
let snapshot;
|
|
75
86
|
if (this._exitSnapshotTypes && this._exitSnapshotTypes.length > 0) {
|
|
@@ -89,7 +100,7 @@ export class System extends Query {
|
|
|
89
100
|
* component matches the watchlist.
|
|
90
101
|
*/
|
|
91
102
|
_notifyModified(c) {
|
|
92
|
-
if (!this._watchlistBitmask.hasBit(c.bitPtr)) {
|
|
103
|
+
if (!this._enabled || !this._watchlistBitmask.hasBit(c.bitPtr)) {
|
|
93
104
|
return;
|
|
94
105
|
}
|
|
95
106
|
this._inbox.push({ kind: 2 /* InboxCommand.Update */, component: c });
|
|
@@ -102,6 +113,13 @@ export class System extends Query {
|
|
|
102
113
|
* callbacks land in the world queue and are processed when `_run` returns.
|
|
103
114
|
*/
|
|
104
115
|
_run(now, delta) {
|
|
116
|
+
if (!this._enabled) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (!this._tickSource.didTick) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const tickDelta = this._tickSource.lastFireDelta;
|
|
105
123
|
this.world.defer(() => {
|
|
106
124
|
for (let i = 0; i < this._inbox.length; i++) {
|
|
107
125
|
const event = this._inbox[i];
|
|
@@ -122,7 +140,7 @@ export class System extends Query {
|
|
|
122
140
|
}
|
|
123
141
|
this._inbox.length = 0;
|
|
124
142
|
if (this._runCallback) {
|
|
125
|
-
this._runCallback(now,
|
|
143
|
+
this._runCallback(now, tickDelta);
|
|
126
144
|
}
|
|
127
145
|
if (this._eachCallback) {
|
|
128
146
|
const cb = this._eachCallback;
|
|
@@ -130,6 +148,76 @@ export class System extends Query {
|
|
|
130
148
|
}
|
|
131
149
|
});
|
|
132
150
|
}
|
|
151
|
+
/** True when this system's cadence source fired during the current frame. */
|
|
152
|
+
get didTick() {
|
|
153
|
+
return this._tickSource.didTick;
|
|
154
|
+
}
|
|
155
|
+
/** Milliseconds accumulated into this system's most recent fire. */
|
|
156
|
+
get lastFireDelta() {
|
|
157
|
+
return this._tickSource.lastFireDelta;
|
|
158
|
+
}
|
|
159
|
+
/** @internal Evaluate this system's cadence source for a frame. */
|
|
160
|
+
_evalTick(delta, frameId) {
|
|
161
|
+
return this._tickSource._evalTick(delta, frameId);
|
|
162
|
+
}
|
|
163
|
+
/** @internal Register this system source and its current cadence source. */
|
|
164
|
+
_register(world) {
|
|
165
|
+
world._registerTickSource(this);
|
|
166
|
+
this._tickSource._register(world);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Run this system at a fixed interval, expressed in seconds.
|
|
170
|
+
*
|
|
171
|
+
* This is seconds, unlike `World.beginFrame`, `World.progress`, and
|
|
172
|
+
* `runPhase`, which receive millisecond deltas. Calling `interval` replaces
|
|
173
|
+
* the current cadence source with an {@link IntervalTickSource}. When this
|
|
174
|
+
* system has a cadence source, the `delta` passed to {@link run} is the
|
|
175
|
+
* accumulated milliseconds since the previous fire, not the per-frame delta.
|
|
176
|
+
*
|
|
177
|
+
* @param seconds - Positive interval duration in seconds.
|
|
178
|
+
* @returns This system, for chaining.
|
|
179
|
+
* @throws When `seconds` is less than or equal to zero.
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* ```ts
|
|
183
|
+
* world.system("AI")
|
|
184
|
+
* .interval(0.5)
|
|
185
|
+
* .run((now, delta) => tickAI(delta));
|
|
186
|
+
* ```
|
|
187
|
+
*/
|
|
188
|
+
interval(seconds) {
|
|
189
|
+
this._setTickSource(new IntervalTickSource(seconds));
|
|
190
|
+
return this;
|
|
191
|
+
}
|
|
192
|
+
rate(n, source) {
|
|
193
|
+
this._setTickSource(new RateTickSource(n, source ?? this._tickSource));
|
|
194
|
+
return this;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Run this system only when another timer or system ticks.
|
|
198
|
+
*
|
|
199
|
+
* Calling `tickSource` mirrors `source` directly; no wrapper source is
|
|
200
|
+
* created. Use `.tickSource(source).rate(n)` or `.rate(n, source)` when this
|
|
201
|
+
* system should divide an upstream source. The `delta` passed to {@link run}
|
|
202
|
+
* is the accumulated milliseconds since this system last fired.
|
|
203
|
+
*
|
|
204
|
+
* @param source - Tick source or system source to mirror.
|
|
205
|
+
* @returns This system, for chaining.
|
|
206
|
+
*
|
|
207
|
+
* @example
|
|
208
|
+
* ```ts
|
|
209
|
+
* const second = new IntervalTickSource(1);
|
|
210
|
+
* world.system("Logger").tickSource(second).run(logStats);
|
|
211
|
+
* ```
|
|
212
|
+
*/
|
|
213
|
+
tickSource(source) {
|
|
214
|
+
this._setTickSource(source);
|
|
215
|
+
return this;
|
|
216
|
+
}
|
|
217
|
+
_setTickSource(source) {
|
|
218
|
+
this._tickSource = source;
|
|
219
|
+
source._register(this.world);
|
|
220
|
+
}
|
|
133
221
|
/**
|
|
134
222
|
* Assign this system to a pipeline phase.
|
|
135
223
|
*
|
|
@@ -162,7 +250,9 @@ export class System extends Query {
|
|
|
162
250
|
* network flushing, global timers, etc.
|
|
163
251
|
*
|
|
164
252
|
* @param callback - Receives `now` (absolute timestamp in ms) and `delta`
|
|
165
|
-
* (ms since the previous tick).
|
|
253
|
+
* (ms since the previous tick). If the system has an active interval,
|
|
254
|
+
* rate, or tick source, `delta` is the accumulated milliseconds since this
|
|
255
|
+
* system last fired.
|
|
166
256
|
* @returns This system, for chaining.
|
|
167
257
|
*/
|
|
168
258
|
run(callback) {
|
|
@@ -247,6 +337,55 @@ export class System extends Query {
|
|
|
247
337
|
super.requires(...components);
|
|
248
338
|
return this;
|
|
249
339
|
}
|
|
340
|
+
/**
|
|
341
|
+
* Disable this system.
|
|
342
|
+
*
|
|
343
|
+
* While disabled the system is effectively invisible: the inbox is cleared
|
|
344
|
+
* immediately, any new `enter`, `exit`, or `update` events are silently
|
|
345
|
+
* dropped, and {@link _run} returns without executing any callbacks. Entity
|
|
346
|
+
* membership in the underlying query is still maintained so the tracked set
|
|
347
|
+
* remains consistent and the system resumes correctly when
|
|
348
|
+
* {@link enable} is called.
|
|
349
|
+
*
|
|
350
|
+
* Disabling is independent from tick-source cadence: `disable` suppresses
|
|
351
|
+
* callbacks, but a disabled system used as a tick source still drives
|
|
352
|
+
* downstream consumers. Use `stop()` on an external `IntervalTickSource` or
|
|
353
|
+
* `RateTickSource` reference to halt that clock itself.
|
|
354
|
+
*
|
|
355
|
+
* Calling `disable` on an already-disabled system is a no-op.
|
|
356
|
+
*
|
|
357
|
+
* @returns This system, for chaining.
|
|
358
|
+
*
|
|
359
|
+
* @example
|
|
360
|
+
* ```ts
|
|
361
|
+
* const sys = world.system("AI").requires(Enemy).run(runAI);
|
|
362
|
+
* // Pause AI processing during a cutscene:
|
|
363
|
+
* sys.disable();
|
|
364
|
+
* // Resume:
|
|
365
|
+
* sys.enable();
|
|
366
|
+
* ```
|
|
367
|
+
*/
|
|
368
|
+
disable() {
|
|
369
|
+
this._enabled = false;
|
|
370
|
+
this._inbox.length = 0;
|
|
371
|
+
return this;
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Enable this system after a previous {@link disable} call.
|
|
375
|
+
*
|
|
376
|
+
* Once re-enabled the system resumes its normal tick behaviour: enter, exit,
|
|
377
|
+
* and update events are queued, and {@link _run} processes the inbox and fires
|
|
378
|
+
* all registered callbacks. Events that occurred while the system was disabled
|
|
379
|
+
* are not replayed.
|
|
380
|
+
*
|
|
381
|
+
* Calling `enable` on an already-enabled system is a no-op.
|
|
382
|
+
*
|
|
383
|
+
* @returns This system, for chaining.
|
|
384
|
+
*/
|
|
385
|
+
enable() {
|
|
386
|
+
this._enabled = true;
|
|
387
|
+
return this;
|
|
388
|
+
}
|
|
250
389
|
/**
|
|
251
390
|
* Not supported on `System`. Throws unconditionally.
|
|
252
391
|
*
|
package/dist/system.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system.js","sourceRoot":"","sources":["../src/system.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGnC,OAAO,EAAE,KAAK,EAAe,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"system.js","sourceRoot":"","sources":["../src/system.ts"],"names":[],"mappings":"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"}
|
package/dist/timer.d.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/** A clock that the world evaluates once per frame. */
|
|
2
|
+
export interface ITickSource {
|
|
3
|
+
/** True when this source fired during the current frame. */
|
|
4
|
+
readonly didTick: boolean;
|
|
5
|
+
/** Milliseconds accumulated into the most recent fire. */
|
|
6
|
+
readonly lastFireDelta: number;
|
|
7
|
+
}
|
|
8
|
+
/** Shared state and start/stop control for concrete tick sources. */
|
|
9
|
+
declare abstract class BaseTickSource implements ITickSource {
|
|
10
|
+
get didTick(): boolean;
|
|
11
|
+
get lastFireDelta(): number;
|
|
12
|
+
/** Resume this source without replaying time elapsed while stopped. */
|
|
13
|
+
start(): this;
|
|
14
|
+
/** Pause this source, freezing accumulators and counters until `start()`. */
|
|
15
|
+
stop(): this;
|
|
16
|
+
}
|
|
17
|
+
/** Fires every `intervalSeconds` of accumulated wall-clock time. */
|
|
18
|
+
export declare class IntervalTickSource extends BaseTickSource {
|
|
19
|
+
private readonly _intervalMs;
|
|
20
|
+
private _accumulator;
|
|
21
|
+
/**
|
|
22
|
+
* Create an interval source.
|
|
23
|
+
*
|
|
24
|
+
* Intervals are expressed in seconds, unlike `World.progress` and
|
|
25
|
+
* `World.beginFrame`, which receive millisecond deltas. Large deltas produce
|
|
26
|
+
* at most one tick; residual time is preserved by subtracting the interval.
|
|
27
|
+
*
|
|
28
|
+
* @param intervalSeconds - Positive interval duration in seconds.
|
|
29
|
+
* @throws When `intervalSeconds` is less than or equal to zero.
|
|
30
|
+
*/
|
|
31
|
+
constructor(intervalSeconds: number);
|
|
32
|
+
}
|
|
33
|
+
/** Fires every `rate` ticks of `source`, or every `rate` frames without one. */
|
|
34
|
+
export declare class RateTickSource extends BaseTickSource {
|
|
35
|
+
private readonly _rate;
|
|
36
|
+
private _counter;
|
|
37
|
+
/**
|
|
38
|
+
* Create a rate filter.
|
|
39
|
+
*
|
|
40
|
+
* Without `source`, this counts world frames. With `source`, it counts ticks
|
|
41
|
+
* from that upstream clock. The source is immutable, so cyclic source graphs
|
|
42
|
+
* cannot be constructed through the public API.
|
|
43
|
+
*
|
|
44
|
+
* @param rate - Positive integer tick divisor.
|
|
45
|
+
* @param source - Optional upstream source to divide.
|
|
46
|
+
* @throws When `rate` is not a positive integer.
|
|
47
|
+
*/
|
|
48
|
+
constructor(rate: number, source?: ITickSource);
|
|
49
|
+
}
|
|
50
|
+
export {};
|
package/dist/timer.js
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/** Shared state and start/stop control for concrete tick sources. */
|
|
2
|
+
class BaseTickSource {
|
|
3
|
+
constructor() {
|
|
4
|
+
/** @internal */
|
|
5
|
+
this._didTick = false;
|
|
6
|
+
/** @internal */
|
|
7
|
+
this._running = true;
|
|
8
|
+
/** @internal */
|
|
9
|
+
this._lastEvaluatedFrame = -1;
|
|
10
|
+
/** @internal */
|
|
11
|
+
this._timeSinceLastTick = 0;
|
|
12
|
+
/** @internal Delta accumulated into the most recent tick, in milliseconds. */
|
|
13
|
+
this._lastFireDelta = 0;
|
|
14
|
+
}
|
|
15
|
+
get didTick() {
|
|
16
|
+
return this._didTick;
|
|
17
|
+
}
|
|
18
|
+
get lastFireDelta() {
|
|
19
|
+
return this._lastFireDelta;
|
|
20
|
+
}
|
|
21
|
+
/** Resume this source without replaying time elapsed while stopped. */
|
|
22
|
+
start() {
|
|
23
|
+
this._running = true;
|
|
24
|
+
return this;
|
|
25
|
+
}
|
|
26
|
+
/** Pause this source, freezing accumulators and counters until `start()`. */
|
|
27
|
+
stop() {
|
|
28
|
+
this._running = false;
|
|
29
|
+
return this;
|
|
30
|
+
}
|
|
31
|
+
/** @internal Register this source with `world`. */
|
|
32
|
+
_register(world) {
|
|
33
|
+
world._registerTickSource(this);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/** Fires every `intervalSeconds` of accumulated wall-clock time. */
|
|
37
|
+
export class IntervalTickSource extends BaseTickSource {
|
|
38
|
+
/**
|
|
39
|
+
* Create an interval source.
|
|
40
|
+
*
|
|
41
|
+
* Intervals are expressed in seconds, unlike `World.progress` and
|
|
42
|
+
* `World.beginFrame`, which receive millisecond deltas. Large deltas produce
|
|
43
|
+
* at most one tick; residual time is preserved by subtracting the interval.
|
|
44
|
+
*
|
|
45
|
+
* @param intervalSeconds - Positive interval duration in seconds.
|
|
46
|
+
* @throws When `intervalSeconds` is less than or equal to zero.
|
|
47
|
+
*/
|
|
48
|
+
constructor(intervalSeconds) {
|
|
49
|
+
super();
|
|
50
|
+
this._accumulator = 0;
|
|
51
|
+
if (intervalSeconds <= 0) {
|
|
52
|
+
throw "interval seconds must be greater than 0";
|
|
53
|
+
}
|
|
54
|
+
this._intervalMs = intervalSeconds * 1000;
|
|
55
|
+
}
|
|
56
|
+
/** @internal */
|
|
57
|
+
_evalTick(deltaMs, frameId) {
|
|
58
|
+
if (this._lastEvaluatedFrame === frameId) {
|
|
59
|
+
return this._didTick;
|
|
60
|
+
}
|
|
61
|
+
this._lastEvaluatedFrame = frameId;
|
|
62
|
+
if (!this._running) {
|
|
63
|
+
this._didTick = false;
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
this._timeSinceLastTick += deltaMs;
|
|
67
|
+
this._accumulator += deltaMs;
|
|
68
|
+
let fired = false;
|
|
69
|
+
if (this._accumulator >= this._intervalMs) {
|
|
70
|
+
this._accumulator -= this._intervalMs;
|
|
71
|
+
fired = true;
|
|
72
|
+
this._lastFireDelta = this._timeSinceLastTick;
|
|
73
|
+
this._timeSinceLastTick = 0;
|
|
74
|
+
}
|
|
75
|
+
this._didTick = fired;
|
|
76
|
+
return fired;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/** Fires every `rate` ticks of `source`, or every `rate` frames without one. */
|
|
80
|
+
export class RateTickSource extends BaseTickSource {
|
|
81
|
+
/**
|
|
82
|
+
* Create a rate filter.
|
|
83
|
+
*
|
|
84
|
+
* Without `source`, this counts world frames. With `source`, it counts ticks
|
|
85
|
+
* from that upstream clock. The source is immutable, so cyclic source graphs
|
|
86
|
+
* cannot be constructed through the public API.
|
|
87
|
+
*
|
|
88
|
+
* @param rate - Positive integer tick divisor.
|
|
89
|
+
* @param source - Optional upstream source to divide.
|
|
90
|
+
* @throws When `rate` is not a positive integer.
|
|
91
|
+
*/
|
|
92
|
+
constructor(rate, source) {
|
|
93
|
+
super();
|
|
94
|
+
this._counter = 0;
|
|
95
|
+
if (!Number.isInteger(rate) || rate <= 0) {
|
|
96
|
+
throw "rate must be a positive integer";
|
|
97
|
+
}
|
|
98
|
+
this._rate = rate;
|
|
99
|
+
this._source = source;
|
|
100
|
+
}
|
|
101
|
+
/** @internal */
|
|
102
|
+
_evalTick(deltaMs, frameId) {
|
|
103
|
+
if (this._lastEvaluatedFrame === frameId) {
|
|
104
|
+
return this._didTick;
|
|
105
|
+
}
|
|
106
|
+
this._lastEvaluatedFrame = frameId;
|
|
107
|
+
if (!this._running) {
|
|
108
|
+
this._didTick = false;
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
const upstreamFired = this._source ? this._source._evalTick(deltaMs, frameId) : true;
|
|
112
|
+
const upstreamDelta = this._source ? this._source.lastFireDelta : deltaMs;
|
|
113
|
+
let fired = false;
|
|
114
|
+
if (upstreamFired) {
|
|
115
|
+
this._timeSinceLastTick += upstreamDelta;
|
|
116
|
+
this._counter++;
|
|
117
|
+
if (this._counter >= this._rate) {
|
|
118
|
+
this._counter = 0;
|
|
119
|
+
fired = true;
|
|
120
|
+
this._lastFireDelta = this._timeSinceLastTick;
|
|
121
|
+
this._timeSinceLastTick = 0;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
this._didTick = fired;
|
|
125
|
+
return fired;
|
|
126
|
+
}
|
|
127
|
+
/** @internal */
|
|
128
|
+
_register(world) {
|
|
129
|
+
super._register(world);
|
|
130
|
+
this._source?._register(world);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/** @internal Singleton source used by systems with no explicit cadence. */
|
|
134
|
+
class _AlwaysTickSource {
|
|
135
|
+
constructor() {
|
|
136
|
+
this._lastDelta = 0;
|
|
137
|
+
}
|
|
138
|
+
get didTick() {
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
get lastFireDelta() {
|
|
142
|
+
return this._lastDelta;
|
|
143
|
+
}
|
|
144
|
+
/** @internal */
|
|
145
|
+
_evalTick(deltaMs, _frameId) {
|
|
146
|
+
this._lastDelta = deltaMs;
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
/** @internal */
|
|
150
|
+
_register(_world) { }
|
|
151
|
+
}
|
|
152
|
+
/** @internal Shared default clock for unconfigured systems. */
|
|
153
|
+
export const ALWAYS_TICK_SOURCE = new _AlwaysTickSource();
|
|
154
|
+
//# sourceMappingURL=timer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timer.js","sourceRoot":"","sources":["../src/timer.ts"],"names":[],"mappings":"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"}
|
package/dist/world.d.ts
CHANGED
|
@@ -334,22 +334,46 @@ export declare class World {
|
|
|
334
334
|
*/
|
|
335
335
|
start(): void;
|
|
336
336
|
/**
|
|
337
|
-
*
|
|
337
|
+
* Open a new frame and evaluate every registered tick source once.
|
|
338
|
+
*
|
|
339
|
+
* Call this before one or more {@link runPhase} calls when manually driving
|
|
340
|
+
* phases. {@link progress} wraps this automatically for the full pipeline.
|
|
341
|
+
*
|
|
342
|
+
* @param delta - Milliseconds elapsed since the previous frame.
|
|
343
|
+
* @throws When a frame is already open.
|
|
344
|
+
*/
|
|
345
|
+
beginFrame(delta: number): void;
|
|
346
|
+
/**
|
|
347
|
+
* Close the current frame.
|
|
348
|
+
*
|
|
349
|
+
* @throws When no frame is currently open.
|
|
350
|
+
*/
|
|
351
|
+
endFrame(): void;
|
|
352
|
+
/**
|
|
353
|
+
* Execute every system in `phase` within the current frame.
|
|
338
354
|
*
|
|
339
355
|
* Pending top-level mutations are drained before the first system runs so
|
|
340
356
|
* each system observes a consistent world. Each system body executes in a
|
|
341
357
|
* deferred scope; mutations made by callbacks land in the world queue and
|
|
342
358
|
* are processed before the next system runs.
|
|
343
359
|
*
|
|
360
|
+
* `runPhase` is safe to call re-entrantly from a system body: it reuses the
|
|
361
|
+
* frame opened by {@link beginFrame} and does not advance `_frameCounter` or
|
|
362
|
+
* re-evaluate tick sources.
|
|
363
|
+
*
|
|
344
364
|
* @param phase - Phase reference returned from {@link addPhase}.
|
|
345
365
|
* @param now - Absolute timestamp in milliseconds (e.g. `Date.now()`).
|
|
346
366
|
* @param delta - Milliseconds elapsed since the previous tick.
|
|
367
|
+
* @throws When called outside an open frame.
|
|
347
368
|
*/
|
|
348
369
|
runPhase(phase: IPhase, now: number, delta: number): void;
|
|
349
370
|
/**
|
|
350
371
|
* Run every phase in the pipeline in registration order.
|
|
351
372
|
*
|
|
352
|
-
* Equivalent to calling {@link runPhase} for each
|
|
373
|
+
* Equivalent to `beginFrame(delta)`, calling {@link runPhase} for each
|
|
374
|
+
* phase, then {@link endFrame}. All registered tick sources are evaluated
|
|
375
|
+
* once up front for the whole frame, and the frame is closed in a `finally`
|
|
376
|
+
* block if a system throws.
|
|
353
377
|
*
|
|
354
378
|
* @param now - Absolute timestamp in milliseconds (e.g. `Date.now()`).
|
|
355
379
|
* @param delta - Milliseconds elapsed since the previous tick.
|
package/dist/world.js
CHANGED
|
@@ -5,6 +5,7 @@ import { System } from "./system.js";
|
|
|
5
5
|
import { Filter } from "./filter.js";
|
|
6
6
|
import { ArrayMap } from "./util/array_map.js";
|
|
7
7
|
import { Phase } from "./phase.js";
|
|
8
|
+
import { ALWAYS_TICK_SOURCE } from "./timer.js";
|
|
8
9
|
/**
|
|
9
10
|
* Numeric type ids below this value are reserved for components whose id was
|
|
10
11
|
* pre-registered via {@link World.registerComponentType} (typically server
|
|
@@ -79,6 +80,13 @@ export class World {
|
|
|
79
80
|
this._draining = false;
|
|
80
81
|
/** @internal Phase name → phase. Insertion-ordered, matches pipeline execution order. */
|
|
81
82
|
this._pipeline = new Map();
|
|
83
|
+
/** @internal World-owned tick sources evaluated once per frame. */
|
|
84
|
+
this._tickSources = new Set();
|
|
85
|
+
/** @internal Monotonic frame id used to memoize tick-source evaluation. */
|
|
86
|
+
this._frameCounter = 0;
|
|
87
|
+
/** @internal True while the world is driving one logical frame. */
|
|
88
|
+
this._frameInProgress = false;
|
|
89
|
+
this._tickSources.add(ALWAYS_TICK_SOURCE);
|
|
82
90
|
}
|
|
83
91
|
/**
|
|
84
92
|
* @internal Drain the top-level command queue: walk it in arrival order,
|
|
@@ -164,6 +172,10 @@ export class World {
|
|
|
164
172
|
_addQuery(q) {
|
|
165
173
|
this._queries.push(q);
|
|
166
174
|
}
|
|
175
|
+
/** @internal Register a tick source with this world. */
|
|
176
|
+
_registerTickSource(t) {
|
|
177
|
+
this._tickSources.add(t);
|
|
178
|
+
}
|
|
167
179
|
/**
|
|
168
180
|
* @internal Unregister a query and purge its membership from every entity.
|
|
169
181
|
* Called by {@link Query.destroy}.
|
|
@@ -527,18 +539,55 @@ export class World {
|
|
|
527
539
|
this._reindexSystems();
|
|
528
540
|
}
|
|
529
541
|
/**
|
|
530
|
-
*
|
|
542
|
+
* Open a new frame and evaluate every registered tick source once.
|
|
543
|
+
*
|
|
544
|
+
* Call this before one or more {@link runPhase} calls when manually driving
|
|
545
|
+
* phases. {@link progress} wraps this automatically for the full pipeline.
|
|
546
|
+
*
|
|
547
|
+
* @param delta - Milliseconds elapsed since the previous frame.
|
|
548
|
+
* @throws When a frame is already open.
|
|
549
|
+
*/
|
|
550
|
+
beginFrame(delta) {
|
|
551
|
+
if (this._frameInProgress) {
|
|
552
|
+
throw "endFrame() not called before beginFrame()";
|
|
553
|
+
}
|
|
554
|
+
this._frameInProgress = true;
|
|
555
|
+
this._frameCounter++;
|
|
556
|
+
this.flush();
|
|
557
|
+
this._tickSources.forEach((t) => t._evalTick(delta, this._frameCounter));
|
|
558
|
+
}
|
|
559
|
+
/**
|
|
560
|
+
* Close the current frame.
|
|
561
|
+
*
|
|
562
|
+
* @throws When no frame is currently open.
|
|
563
|
+
*/
|
|
564
|
+
endFrame() {
|
|
565
|
+
if (!this._frameInProgress) {
|
|
566
|
+
throw "beginFrame() not called before endFrame()";
|
|
567
|
+
}
|
|
568
|
+
this._frameInProgress = false;
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Execute every system in `phase` within the current frame.
|
|
531
572
|
*
|
|
532
573
|
* Pending top-level mutations are drained before the first system runs so
|
|
533
574
|
* each system observes a consistent world. Each system body executes in a
|
|
534
575
|
* deferred scope; mutations made by callbacks land in the world queue and
|
|
535
576
|
* are processed before the next system runs.
|
|
536
577
|
*
|
|
578
|
+
* `runPhase` is safe to call re-entrantly from a system body: it reuses the
|
|
579
|
+
* frame opened by {@link beginFrame} and does not advance `_frameCounter` or
|
|
580
|
+
* re-evaluate tick sources.
|
|
581
|
+
*
|
|
537
582
|
* @param phase - Phase reference returned from {@link addPhase}.
|
|
538
583
|
* @param now - Absolute timestamp in milliseconds (e.g. `Date.now()`).
|
|
539
584
|
* @param delta - Milliseconds elapsed since the previous tick.
|
|
585
|
+
* @throws When called outside an open frame.
|
|
540
586
|
*/
|
|
541
587
|
runPhase(phase, now, delta) {
|
|
588
|
+
if (!this._frameInProgress) {
|
|
589
|
+
throw "runPhase() called outside a frame — call beginFrame() first";
|
|
590
|
+
}
|
|
542
591
|
this.flush();
|
|
543
592
|
phase.systems.forEach((s) => {
|
|
544
593
|
s._run(now, delta);
|
|
@@ -547,16 +596,24 @@ export class World {
|
|
|
547
596
|
/**
|
|
548
597
|
* Run every phase in the pipeline in registration order.
|
|
549
598
|
*
|
|
550
|
-
* Equivalent to calling {@link runPhase} for each
|
|
599
|
+
* Equivalent to `beginFrame(delta)`, calling {@link runPhase} for each
|
|
600
|
+
* phase, then {@link endFrame}. All registered tick sources are evaluated
|
|
601
|
+
* once up front for the whole frame, and the frame is closed in a `finally`
|
|
602
|
+
* block if a system throws.
|
|
551
603
|
*
|
|
552
604
|
* @param now - Absolute timestamp in milliseconds (e.g. `Date.now()`).
|
|
553
605
|
* @param delta - Milliseconds elapsed since the previous tick.
|
|
554
606
|
*/
|
|
555
607
|
progress(now, delta) {
|
|
556
|
-
this.
|
|
557
|
-
|
|
558
|
-
this.
|
|
559
|
-
|
|
608
|
+
this.beginFrame(delta);
|
|
609
|
+
try {
|
|
610
|
+
this._pipeline.forEach((phase) => {
|
|
611
|
+
this.runPhase(phase, now, delta);
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
finally {
|
|
615
|
+
this.endFrame();
|
|
616
|
+
}
|
|
560
617
|
}
|
|
561
618
|
}
|
|
562
619
|
//# sourceMappingURL=world.js.map
|
package/dist/world.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"world.js","sourceRoot":"","sources":["../src/world.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmC,aAAa,EAAQ,MAAM,gBAAgB,CAAC;AACtF,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAU,KAAK,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"world.js","sourceRoot":"","sources":["../src/world.ts"],"names":[],"mappings":"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"}
|