@aura3d/core 1.0.6

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 (77) hide show
  1. package/README.md +51 -0
  2. package/dist/Diagnostics.d.ts +25 -0
  3. package/dist/Diagnostics.d.ts.map +1 -0
  4. package/dist/Diagnostics.js +60 -0
  5. package/dist/Diagnostics.js.map +1 -0
  6. package/dist/Disposable.d.ts +12 -0
  7. package/dist/Disposable.d.ts.map +1 -0
  8. package/dist/Disposable.js +37 -0
  9. package/dist/Disposable.js.map +1 -0
  10. package/dist/Engine.d.ts +46 -0
  11. package/dist/Engine.d.ts.map +1 -0
  12. package/dist/Engine.js +130 -0
  13. package/dist/Engine.js.map +1 -0
  14. package/dist/EngineConfig.d.ts +18 -0
  15. package/dist/EngineConfig.d.ts.map +1 -0
  16. package/dist/EngineConfig.js +23 -0
  17. package/dist/EngineConfig.js.map +1 -0
  18. package/dist/EngineLoop.d.ts +33 -0
  19. package/dist/EngineLoop.d.ts.map +1 -0
  20. package/dist/EngineLoop.js +63 -0
  21. package/dist/EngineLoop.js.map +1 -0
  22. package/dist/Errors.d.ts +14 -0
  23. package/dist/Errors.d.ts.map +1 -0
  24. package/dist/Errors.js +24 -0
  25. package/dist/Errors.js.map +1 -0
  26. package/dist/EventBus.d.ts +18 -0
  27. package/dist/EventBus.d.ts.map +1 -0
  28. package/dist/EventBus.js +45 -0
  29. package/dist/EventBus.js.map +1 -0
  30. package/dist/FixedStepAccumulator.d.ts +15 -0
  31. package/dist/FixedStepAccumulator.d.ts.map +1 -0
  32. package/dist/FixedStepAccumulator.js +34 -0
  33. package/dist/FixedStepAccumulator.js.map +1 -0
  34. package/dist/Logger.d.ts +23 -0
  35. package/dist/Logger.d.ts.map +1 -0
  36. package/dist/Logger.js +53 -0
  37. package/dist/Logger.js.map +1 -0
  38. package/dist/ResourceScope.d.ts +18 -0
  39. package/dist/ResourceScope.d.ts.map +1 -0
  40. package/dist/ResourceScope.js +53 -0
  41. package/dist/ResourceScope.js.map +1 -0
  42. package/dist/Scheduler.d.ts +31 -0
  43. package/dist/Scheduler.d.ts.map +1 -0
  44. package/dist/Scheduler.js +77 -0
  45. package/dist/Scheduler.js.map +1 -0
  46. package/dist/TaskQueue.d.ts +13 -0
  47. package/dist/TaskQueue.d.ts.map +1 -0
  48. package/dist/TaskQueue.js +42 -0
  49. package/dist/TaskQueue.js.map +1 -0
  50. package/dist/Time.d.ts +24 -0
  51. package/dist/Time.d.ts.map +1 -0
  52. package/dist/Time.js +45 -0
  53. package/dist/Time.js.map +1 -0
  54. package/dist/VersionedSerialization.d.ts +96 -0
  55. package/dist/VersionedSerialization.d.ts.map +1 -0
  56. package/dist/VersionedSerialization.js +278 -0
  57. package/dist/VersionedSerialization.js.map +1 -0
  58. package/dist/index.d.ts +15 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +15 -0
  61. package/dist/index.js.map +1 -0
  62. package/package.json +16 -0
  63. package/src/Diagnostics.ts +80 -0
  64. package/src/Disposable.ts +41 -0
  65. package/src/Engine.ts +140 -0
  66. package/src/EngineConfig.ts +38 -0
  67. package/src/EngineLoop.ts +83 -0
  68. package/src/Errors.ts +28 -0
  69. package/src/EventBus.ts +52 -0
  70. package/src/FixedStepAccumulator.ts +39 -0
  71. package/src/Logger.ts +67 -0
  72. package/src/ResourceScope.ts +55 -0
  73. package/src/Scheduler.ts +94 -0
  74. package/src/TaskQueue.ts +50 -0
  75. package/src/Time.ts +54 -0
  76. package/src/VersionedSerialization.ts +351 -0
  77. package/src/index.ts +14 -0
@@ -0,0 +1,45 @@
1
+ export class EventBus {
2
+ onListenerError;
3
+ listeners = new Map();
4
+ onceListeners = new WeakSet();
5
+ constructor(onListenerError) {
6
+ this.onListenerError = onListenerError;
7
+ }
8
+ on(eventName, listener) {
9
+ const set = this.listeners.get(eventName) ?? new Set();
10
+ set.add(listener);
11
+ this.listeners.set(eventName, set);
12
+ return { unsubscribe: () => this.off(eventName, listener) };
13
+ }
14
+ once(eventName, listener) {
15
+ const subscription = this.on(eventName, listener);
16
+ this.onceListeners.add(listener);
17
+ return subscription;
18
+ }
19
+ off(eventName, listener) {
20
+ const set = this.listeners.get(eventName);
21
+ set?.delete(listener);
22
+ if (set?.size === 0)
23
+ this.listeners.delete(eventName);
24
+ }
25
+ emit(eventName, event) {
26
+ const snapshot = [...(this.listeners.get(eventName) ?? [])];
27
+ for (const listener of snapshot) {
28
+ if (!this.listeners.get(eventName)?.has(listener))
29
+ continue;
30
+ try {
31
+ listener(event);
32
+ }
33
+ catch (error) {
34
+ this.onListenerError?.(error, String(eventName));
35
+ }
36
+ if (this.onceListeners.has(listener)) {
37
+ this.listeners.get(eventName)?.delete(listener);
38
+ }
39
+ }
40
+ }
41
+ clear() {
42
+ this.listeners.clear();
43
+ }
44
+ }
45
+ //# sourceMappingURL=EventBus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EventBus.js","sourceRoot":"","sources":["../../../../packages/core/src/EventBus.ts"],"names":[],"mappings":"AAQA,MAAM,OAAO,QAAQ;IAIU;IAHZ,SAAS,GAAG,IAAI,GAAG,EAA6D,CAAC;IACjF,aAAa,GAAG,IAAI,OAAO,EAAyC,CAAC;IAEtF,YAA6B,eAAmC;QAAnC,oBAAe,GAAf,eAAe,CAAoB;IAAG,CAAC;IAEpE,EAAE,CAA0B,SAAY,EAAE,QAAmC;QAC3E,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,GAAG,EAAyC,CAAC;QAC9F,GAAG,CAAC,GAAG,CAAC,QAAiD,CAAC,CAAC;QAC3D,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QACnC,OAAO,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,CAAC;IAC9D,CAAC;IAED,IAAI,CAA0B,SAAY,EAAE,QAAmC;QAC7E,MAAM,YAAY,GAAG,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAClD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAiD,CAAC,CAAC;QAC1E,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,GAAG,CAA0B,SAAY,EAAE,QAAmC;QAC5E,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC1C,GAAG,EAAE,MAAM,CAAC,QAAiD,CAAC,CAAC;QAC/D,IAAI,GAAG,EAAE,IAAI,KAAK,CAAC;YAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACxD,CAAC;IAED,IAAI,CAA0B,SAAY,EAAE,KAAiB;QAC3D,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAC5D,KAAK,MAAM,QAAQ,IAAI,QAAQ,EAAE,CAAC;YAChC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC;gBAAE,SAAS;YAC5D,IAAI,CAAC;gBACF,QAAsC,CAAC,KAAK,CAAC,CAAC;YACjD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;YACnD,CAAC;YACD,IAAI,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACrC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK;QACH,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;IACzB,CAAC;CACF"}
@@ -0,0 +1,15 @@
1
+ export interface FixedStepResult {
2
+ readonly steps: number;
3
+ readonly alpha: number;
4
+ readonly droppedTime: number;
5
+ }
6
+ export declare class FixedStepAccumulator {
7
+ readonly fixedDelta: number;
8
+ readonly maxSteps: number;
9
+ private accumulator;
10
+ constructor(fixedDelta: number, maxSteps: number);
11
+ add(delta: number): FixedStepResult;
12
+ get alpha(): number;
13
+ reset(): void;
14
+ }
15
+ //# sourceMappingURL=FixedStepAccumulator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FixedStepAccumulator.d.ts","sourceRoot":"","sources":["../../../../packages/core/src/FixedStepAccumulator.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,qBAAa,oBAAoB;IAI7B,QAAQ,CAAC,UAAU,EAAE,MAAM;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM;IAJ3B,OAAO,CAAC,WAAW,CAAK;gBAGb,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM;IAM3B,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe;IAcnC,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,KAAK,IAAI,IAAI;CAGd"}
@@ -0,0 +1,34 @@
1
+ export class FixedStepAccumulator {
2
+ fixedDelta;
3
+ maxSteps;
4
+ accumulator = 0;
5
+ constructor(fixedDelta, maxSteps) {
6
+ this.fixedDelta = fixedDelta;
7
+ this.maxSteps = maxSteps;
8
+ if (!Number.isFinite(fixedDelta) || fixedDelta <= 0)
9
+ throw new RangeError("fixedDelta must be finite and positive.");
10
+ if (!Number.isInteger(maxSteps) || maxSteps <= 0)
11
+ throw new RangeError("maxSteps must be a positive integer.");
12
+ }
13
+ add(delta) {
14
+ if (!Number.isFinite(delta) || delta < 0)
15
+ throw new RangeError("delta must be finite and non-negative.");
16
+ this.accumulator += delta;
17
+ const possibleSteps = Math.floor(this.accumulator / this.fixedDelta);
18
+ const steps = Math.min(possibleSteps, this.maxSteps);
19
+ this.accumulator -= steps * this.fixedDelta;
20
+ let droppedTime = 0;
21
+ if (possibleSteps > this.maxSteps) {
22
+ droppedTime = this.accumulator;
23
+ this.accumulator = 0;
24
+ }
25
+ return Object.freeze({ steps, alpha: this.alpha, droppedTime });
26
+ }
27
+ get alpha() {
28
+ return this.accumulator / this.fixedDelta;
29
+ }
30
+ reset() {
31
+ this.accumulator = 0;
32
+ }
33
+ }
34
+ //# sourceMappingURL=FixedStepAccumulator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FixedStepAccumulator.js","sourceRoot":"","sources":["../../../../packages/core/src/FixedStepAccumulator.ts"],"names":[],"mappings":"AAMA,MAAM,OAAO,oBAAoB;IAIpB;IACA;IAJH,WAAW,GAAG,CAAC,CAAC;IAExB,YACW,UAAkB,EAClB,QAAgB;QADhB,eAAU,GAAV,UAAU,CAAQ;QAClB,aAAQ,GAAR,QAAQ,CAAQ;QAEzB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,UAAU,IAAI,CAAC;YAAE,MAAM,IAAI,UAAU,CAAC,yCAAyC,CAAC,CAAC;QACrH,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,QAAQ,IAAI,CAAC;YAAE,MAAM,IAAI,UAAU,CAAC,sCAAsC,CAAC,CAAC;IACjH,CAAC;IAED,GAAG,CAAC,KAAa;QACf,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC;YAAE,MAAM,IAAI,UAAU,CAAC,wCAAwC,CAAC,CAAC;QACzG,IAAI,CAAC,WAAW,IAAI,KAAK,CAAC;QAC1B,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;QACrE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrD,IAAI,CAAC,WAAW,IAAI,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC;QAC5C,IAAI,WAAW,GAAG,CAAC,CAAC;QACpB,IAAI,aAAa,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;YAC/B,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;QACvB,CAAC;QACD,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC;IAC5C,CAAC;IAED,KAAK;QACH,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;IACvB,CAAC;CACF"}
@@ -0,0 +1,23 @@
1
+ export type LogLevel = "debug" | "info" | "warn" | "error" | "silent";
2
+ export interface LogEntry {
3
+ readonly level: Exclude<LogLevel, "silent">;
4
+ readonly category: string;
5
+ readonly message: string;
6
+ readonly timestamp: number;
7
+ readonly data?: unknown;
8
+ }
9
+ export type LogSink = (entry: LogEntry) => void;
10
+ export declare class Logger {
11
+ private level;
12
+ private readonly sinks;
13
+ private readonly lastEmitted;
14
+ constructor(level?: LogLevel);
15
+ setLevel(level: LogLevel): void;
16
+ addSink(sink: LogSink): () => void;
17
+ debug(category: string, message: string, data?: unknown): void;
18
+ info(category: string, message: string, data?: unknown): void;
19
+ warn(category: string, message: string, data?: unknown): void;
20
+ error(category: string, message: string, data?: unknown): void;
21
+ log(level: Exclude<LogLevel, "silent">, category: string, message: string, data?: unknown, rateLimitMs?: number): void;
22
+ }
23
+ //# sourceMappingURL=Logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Logger.d.ts","sourceRoot":"","sources":["../../../../packages/core/src/Logger.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEtE,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC5C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,MAAM,OAAO,GAAG,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC;AAUhD,qBAAa,MAAM;IAIL,OAAO,CAAC,KAAK;IAHzB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAsB;IAC5C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA6B;gBAErC,KAAK,GAAE,QAAiB;IAE5C,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAI/B,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,IAAI;IAKlC,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAI9D,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAI7D,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAI7D,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAI9D,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,WAAW,SAAI,GAAG,IAAI;CAelH"}
package/dist/Logger.js ADDED
@@ -0,0 +1,53 @@
1
+ const levelRank = {
2
+ debug: 10,
3
+ info: 20,
4
+ warn: 30,
5
+ error: 40,
6
+ silent: 50
7
+ };
8
+ export class Logger {
9
+ level;
10
+ sinks = new Set();
11
+ lastEmitted = new Map();
12
+ constructor(level = "info") {
13
+ this.level = level;
14
+ }
15
+ setLevel(level) {
16
+ this.level = level;
17
+ }
18
+ addSink(sink) {
19
+ this.sinks.add(sink);
20
+ return () => this.sinks.delete(sink);
21
+ }
22
+ debug(category, message, data) {
23
+ this.log("debug", category, message, data);
24
+ }
25
+ info(category, message, data) {
26
+ this.log("info", category, message, data);
27
+ }
28
+ warn(category, message, data) {
29
+ this.log("warn", category, message, data);
30
+ }
31
+ error(category, message, data) {
32
+ this.log("error", category, message, data);
33
+ }
34
+ log(level, category, message, data, rateLimitMs = 0) {
35
+ if (levelRank[level] < levelRank[this.level])
36
+ return;
37
+ const key = `${level}:${category}:${message}`;
38
+ const now = Date.now();
39
+ if (rateLimitMs > 0 && now - (this.lastEmitted.get(key) ?? -Infinity) < rateLimitMs)
40
+ return;
41
+ this.lastEmitted.set(key, now);
42
+ const entry = Object.freeze({ level, category, message, timestamp: now, data });
43
+ for (const sink of [...this.sinks]) {
44
+ try {
45
+ sink(entry);
46
+ }
47
+ catch {
48
+ this.sinks.delete(sink);
49
+ }
50
+ }
51
+ }
52
+ }
53
+ //# sourceMappingURL=Logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Logger.js","sourceRoot":"","sources":["../../../../packages/core/src/Logger.ts"],"names":[],"mappings":"AAYA,MAAM,SAAS,GAA6B;IAC1C,KAAK,EAAE,EAAE;IACT,IAAI,EAAE,EAAE;IACR,IAAI,EAAE,EAAE;IACR,KAAK,EAAE,EAAE;IACT,MAAM,EAAE,EAAE;CACX,CAAC;AAEF,MAAM,OAAO,MAAM;IAIG;IAHH,KAAK,GAAG,IAAI,GAAG,EAAW,CAAC;IAC3B,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEzD,YAAoB,QAAkB,MAAM;QAAxB,UAAK,GAAL,KAAK,CAAmB;IAAG,CAAC;IAEhD,QAAQ,CAAC,KAAe;QACtB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,OAAO,CAAC,IAAa;QACnB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACrB,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,QAAgB,EAAE,OAAe,EAAE,IAAc;QACrD,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAC7C,CAAC;IAED,IAAI,CAAC,QAAgB,EAAE,OAAe,EAAE,IAAc;QACpD,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAC5C,CAAC;IAED,IAAI,CAAC,QAAgB,EAAE,OAAe,EAAE,IAAc;QACpD,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,QAAgB,EAAE,OAAe,EAAE,IAAc;QACrD,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAC7C,CAAC;IAED,GAAG,CAAC,KAAkC,EAAE,QAAgB,EAAE,OAAe,EAAE,IAAc,EAAE,WAAW,GAAG,CAAC;QACxG,IAAI,SAAS,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO;QACrD,MAAM,GAAG,GAAG,GAAG,KAAK,IAAI,QAAQ,IAAI,OAAO,EAAE,CAAC;QAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,WAAW,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,WAAW;YAAE,OAAO;QAC5F,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAC/B,MAAM,KAAK,GAAa,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1F,KAAK,MAAM,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACnC,IAAI,CAAC;gBACH,IAAI,CAAC,KAAK,CAAC,CAAC;YACd,CAAC;YAAC,MAAM,CAAC;gBACP,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,18 @@
1
+ import { type Disposable } from "./Disposable.js";
2
+ export interface ResourceLeak {
3
+ name: string;
4
+ resourceCount: number;
5
+ childScopes: ResourceLeak[];
6
+ }
7
+ export declare class ResourceScope implements Disposable {
8
+ readonly name: string;
9
+ private readonly stack;
10
+ private readonly children;
11
+ private disposed;
12
+ constructor(name: string);
13
+ use<T extends Disposable>(resource: T): T;
14
+ createChild(name: string): ResourceScope;
15
+ leakSnapshot(): ResourceLeak;
16
+ dispose(): Promise<void>;
17
+ }
18
+ //# sourceMappingURL=ResourceScope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResourceScope.d.ts","sourceRoot":"","sources":["../../../../packages/core/src/ResourceScope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEnE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,YAAY,EAAE,CAAC;CAC7B;AAED,qBAAa,aAAc,YAAW,UAAU;IAKlC,QAAQ,CAAC,IAAI,EAAE,MAAM;IAJjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAyB;IAC/C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA4B;IACrD,OAAO,CAAC,QAAQ,CAAS;gBAEJ,IAAI,EAAE,MAAM;IAEjC,GAAG,CAAC,CAAC,SAAS,UAAU,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC;IAKzC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa;IAOxC,YAAY,IAAI,YAAY;IAQtB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAmB/B"}
@@ -0,0 +1,53 @@
1
+ import { DisposableStack } from "./Disposable.js";
2
+ export class ResourceScope {
3
+ name;
4
+ stack = new DisposableStack();
5
+ children = new Set();
6
+ disposed = false;
7
+ constructor(name) {
8
+ this.name = name;
9
+ }
10
+ use(resource) {
11
+ if (this.disposed)
12
+ throw new Error(`Resource scope ${this.name} is disposed.`);
13
+ return this.stack.use(resource);
14
+ }
15
+ createChild(name) {
16
+ if (this.disposed)
17
+ throw new Error(`Resource scope ${this.name} is disposed.`);
18
+ const child = new ResourceScope(name);
19
+ this.children.add(child);
20
+ return child;
21
+ }
22
+ leakSnapshot() {
23
+ return {
24
+ name: this.name,
25
+ resourceCount: this.stack.size,
26
+ childScopes: [...this.children].map((child) => child.leakSnapshot())
27
+ };
28
+ }
29
+ async dispose() {
30
+ if (this.disposed)
31
+ return;
32
+ this.disposed = true;
33
+ const errors = [];
34
+ for (const child of [...this.children].reverse()) {
35
+ try {
36
+ await child.dispose();
37
+ }
38
+ catch (error) {
39
+ errors.push(error);
40
+ }
41
+ }
42
+ this.children.clear();
43
+ try {
44
+ await this.stack.dispose();
45
+ }
46
+ catch (error) {
47
+ errors.push(error);
48
+ }
49
+ if (errors.length > 0)
50
+ throw new AggregateError(errors, `Resource scope ${this.name} failed to dispose.`);
51
+ }
52
+ }
53
+ //# sourceMappingURL=ResourceScope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResourceScope.js","sourceRoot":"","sources":["../../../../packages/core/src/ResourceScope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAmB,MAAM,iBAAiB,CAAC;AAQnE,MAAM,OAAO,aAAa;IAKH;IAJJ,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;IAC9B,QAAQ,GAAG,IAAI,GAAG,EAAiB,CAAC;IAC7C,QAAQ,GAAG,KAAK,CAAC;IAEzB,YAAqB,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;IAAG,CAAC;IAErC,GAAG,CAAuB,QAAW;QACnC,IAAI,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,IAAI,CAAC,IAAI,eAAe,CAAC,CAAC;QAC/E,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC;IAED,WAAW,CAAC,IAAY;QACtB,IAAI,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,IAAI,CAAC,IAAI,eAAe,CAAC,CAAC;QAC/E,MAAM,KAAK,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACzB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,YAAY;QACV,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,aAAa,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI;YAC9B,WAAW,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;SACrE,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,OAAO;QACX,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO;QAC1B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,MAAM,MAAM,GAAc,EAAE,CAAC;QAC7B,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;YACjD,IAAI,CAAC;gBACH,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC;YACxB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QAC7B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM,IAAI,cAAc,CAAC,MAAM,EAAE,kBAAkB,IAAI,CAAC,IAAI,qBAAqB,CAAC,CAAC;IAC5G,CAAC;CACF"}
@@ -0,0 +1,31 @@
1
+ export declare const SystemPhase: Readonly<{
2
+ Platform: "platform";
3
+ Tasks: "tasks";
4
+ Fixed: "fixed";
5
+ Update: "update";
6
+ Scene: "scene";
7
+ Render: "render";
8
+ Present: "present";
9
+ Cleanup: "cleanup";
10
+ }>;
11
+ export type SystemPhase = (typeof SystemPhase)[keyof typeof SystemPhase];
12
+ export interface SchedulerContext {
13
+ readonly phase: SystemPhase;
14
+ readonly fixedStepIndex?: number;
15
+ }
16
+ export interface ScheduledTask {
17
+ readonly id: string;
18
+ readonly phase: SystemPhase;
19
+ readonly dependsOn?: readonly string[];
20
+ readonly enabled?: boolean;
21
+ run(context: SchedulerContext): void | Promise<void>;
22
+ }
23
+ export declare class Scheduler {
24
+ private readonly tasks;
25
+ add(task: ScheduledTask): void;
26
+ remove(id: string): void;
27
+ getExecutionPlan(): readonly ScheduledTask[];
28
+ runPhase(phase: SystemPhase, fixedStepIndex?: number): Promise<void>;
29
+ private sortPhase;
30
+ }
31
+ //# sourceMappingURL=Scheduler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Scheduler.d.ts","sourceRoot":"","sources":["../../../../packages/core/src/Scheduler.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW;;;;;;;;;EAStB,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC;AAEzE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,GAAG,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtD;AAID,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoC;IAE1D,GAAG,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI;IAK9B,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAIxB,gBAAgB,IAAI,SAAS,aAAa,EAAE;IAgBtC,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS1E,OAAO,CAAC,SAAS;CA0BlB"}
@@ -0,0 +1,77 @@
1
+ import { ValidationError } from "./Errors.js";
2
+ export const SystemPhase = Object.freeze({
3
+ Platform: "platform",
4
+ Tasks: "tasks",
5
+ Fixed: "fixed",
6
+ Update: "update",
7
+ Scene: "scene",
8
+ Render: "render",
9
+ Present: "present",
10
+ Cleanup: "cleanup"
11
+ });
12
+ const phaseOrder = Object.values(SystemPhase);
13
+ export class Scheduler {
14
+ tasks = new Map();
15
+ add(task) {
16
+ if (this.tasks.has(task.id))
17
+ throw new ValidationError("DUPLICATE_TASK", `Task ${task.id} already exists.`);
18
+ this.tasks.set(task.id, task);
19
+ }
20
+ remove(id) {
21
+ this.tasks.delete(id);
22
+ }
23
+ getExecutionPlan() {
24
+ const ordered = [];
25
+ const byPhase = new Map();
26
+ for (const task of this.tasks.values()) {
27
+ if (task.enabled === false)
28
+ continue;
29
+ const list = byPhase.get(task.phase) ?? [];
30
+ list.push(task);
31
+ byPhase.set(task.phase, list);
32
+ }
33
+ for (const phase of phaseOrder) {
34
+ ordered.push(...this.sortPhase(byPhase.get(phase) ?? []));
35
+ }
36
+ return Object.freeze(ordered);
37
+ }
38
+ async runPhase(phase, fixedStepIndex) {
39
+ for (const task of this.getExecutionPlan()) {
40
+ if (task.phase === phase) {
41
+ const context = fixedStepIndex === undefined ? { phase } : { phase, fixedStepIndex };
42
+ await task.run(context);
43
+ }
44
+ }
45
+ }
46
+ sortPhase(tasks) {
47
+ const taskIds = new Set(tasks.map((task) => task.id));
48
+ const visiting = new Set();
49
+ const visited = new Set();
50
+ const output = [];
51
+ const taskById = new Map(tasks.map((task) => [task.id, task]));
52
+ const visit = (task) => {
53
+ if (visited.has(task.id))
54
+ return;
55
+ if (visiting.has(task.id))
56
+ throw new ValidationError("TASK_CYCLE", `Scheduler cycle includes ${task.id}.`);
57
+ visiting.add(task.id);
58
+ for (const dependency of task.dependsOn ?? []) {
59
+ const dep = this.tasks.get(dependency);
60
+ if (!dep || dep.enabled === false)
61
+ throw new ValidationError("MISSING_DEPENDENCY", `Task ${task.id} depends on missing task ${dependency}.`);
62
+ if (dep.phase !== task.phase)
63
+ throw new ValidationError("CROSS_PHASE_DEPENDENCY", `Task ${task.id} depends on ${dependency} in a different phase.`);
64
+ if (!taskIds.has(dependency))
65
+ throw new ValidationError("MISSING_DEPENDENCY", `Task ${task.id} depends on missing phase peer ${dependency}.`);
66
+ visit(taskById.get(dependency));
67
+ }
68
+ visiting.delete(task.id);
69
+ visited.add(task.id);
70
+ output.push(task);
71
+ };
72
+ for (const task of tasks)
73
+ visit(task);
74
+ return output;
75
+ }
76
+ }
77
+ //# sourceMappingURL=Scheduler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Scheduler.js","sourceRoot":"","sources":["../../../../packages/core/src/Scheduler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export interface TaskHandle {
2
+ readonly id: number;
3
+ cancel(): void;
4
+ readonly cancelled: boolean;
5
+ }
6
+ export declare class TaskQueue {
7
+ private queue;
8
+ private nextId;
9
+ enqueue(task: () => void | Promise<void>): TaskHandle;
10
+ get size(): number;
11
+ flush(): Promise<void>;
12
+ }
13
+ //# sourceMappingURL=TaskQueue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TaskQueue.d.ts","sourceRoot":"","sources":["../../../../packages/core/src/TaskQueue.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,MAAM,IAAI,IAAI,CAAC;IACf,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAeD,qBAAa,SAAS;IACpB,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,MAAM,CAAK;IAEnB,OAAO,CAAC,IAAI,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,UAAU;IAMrD,IAAI,IAAI,IAAI,MAAM,CAEjB;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAgB7B"}
@@ -0,0 +1,42 @@
1
+ class MutableTaskHandle {
2
+ id;
3
+ cancelled = false;
4
+ constructor(id) {
5
+ this.id = id;
6
+ }
7
+ cancel() {
8
+ this.cancelled = true;
9
+ }
10
+ }
11
+ export class TaskQueue {
12
+ queue = [];
13
+ nextId = 1;
14
+ enqueue(task) {
15
+ const handle = new MutableTaskHandle(this.nextId++);
16
+ this.queue.push({ handle, task });
17
+ return handle;
18
+ }
19
+ get size() {
20
+ return this.queue.length;
21
+ }
22
+ async flush() {
23
+ const errors = [];
24
+ while (this.queue.length > 0) {
25
+ const batch = this.queue;
26
+ this.queue = [];
27
+ for (const item of batch) {
28
+ if (item.handle.cancelled)
29
+ continue;
30
+ try {
31
+ await item.task();
32
+ }
33
+ catch (error) {
34
+ errors.push(error);
35
+ }
36
+ }
37
+ }
38
+ if (errors.length > 0)
39
+ throw new AggregateError(errors, "One or more queued tasks failed.");
40
+ }
41
+ }
42
+ //# sourceMappingURL=TaskQueue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TaskQueue.js","sourceRoot":"","sources":["../../../../packages/core/src/TaskQueue.ts"],"names":[],"mappings":"AAWA,MAAM,iBAAiB;IAEA;IADrB,SAAS,GAAG,KAAK,CAAC;IAClB,YAAqB,EAAU;QAAV,OAAE,GAAF,EAAE,CAAQ;IAAG,CAAC;IACnC,MAAM;QACJ,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;IACxB,CAAC;CACF;AAED,MAAM,OAAO,SAAS;IACZ,KAAK,GAAiB,EAAE,CAAC;IACzB,MAAM,GAAG,CAAC,CAAC;IAEnB,OAAO,CAAC,IAAgC;QACtC,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACpD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAClC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,MAAM,GAAc,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;YACzB,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YAChB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS;oBAAE,SAAS;gBACpC,IAAI,CAAC;oBACH,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;gBACpB,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACrB,CAAC;YACH,CAAC;QACH,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM,IAAI,cAAc,CAAC,MAAM,EAAE,kCAAkC,CAAC,CAAC;IAC9F,CAAC;CACF"}
package/dist/Time.d.ts ADDED
@@ -0,0 +1,24 @@
1
+ export interface TimeSnapshot {
2
+ readonly frame: number;
3
+ readonly elapsed: number;
4
+ readonly unscaledElapsed: number;
5
+ readonly delta: number;
6
+ readonly unscaledDelta: number;
7
+ readonly smoothedDelta: number;
8
+ readonly timeScale: number;
9
+ }
10
+ export declare class Time {
11
+ private readonly maxDelta;
12
+ private timeScaleValue;
13
+ private frameValue;
14
+ private elapsedValue;
15
+ private unscaledElapsedValue;
16
+ private deltaValue;
17
+ private unscaledDeltaValue;
18
+ private smoothedDeltaValue;
19
+ constructor(maxDelta: number, timeScaleValue?: number);
20
+ setTimeScale(timeScale: number): void;
21
+ update(unscaledDelta: number): TimeSnapshot;
22
+ snapshot(): TimeSnapshot;
23
+ }
24
+ //# sourceMappingURL=Time.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Time.d.ts","sourceRoot":"","sources":["../../../../packages/core/src/Time.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,qBAAa,IAAI;IASb,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,cAAc;IATxB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,oBAAoB,CAAK;IACjC,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,kBAAkB,CAAK;IAC/B,OAAO,CAAC,kBAAkB,CAAK;gBAGZ,QAAQ,EAAE,MAAM,EACzB,cAAc,SAAI;IAM5B,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAKrC,MAAM,CAAC,aAAa,EAAE,MAAM,GAAG,YAAY;IAW3C,QAAQ,IAAI,YAAY;CAWzB"}
package/dist/Time.js ADDED
@@ -0,0 +1,45 @@
1
+ export class Time {
2
+ maxDelta;
3
+ timeScaleValue;
4
+ frameValue = 0;
5
+ elapsedValue = 0;
6
+ unscaledElapsedValue = 0;
7
+ deltaValue = 0;
8
+ unscaledDeltaValue = 0;
9
+ smoothedDeltaValue = 0;
10
+ constructor(maxDelta, timeScaleValue = 1) {
11
+ this.maxDelta = maxDelta;
12
+ this.timeScaleValue = timeScaleValue;
13
+ if (!Number.isFinite(maxDelta) || maxDelta <= 0)
14
+ throw new RangeError("maxDelta must be finite and positive.");
15
+ this.setTimeScale(timeScaleValue);
16
+ }
17
+ setTimeScale(timeScale) {
18
+ if (!Number.isFinite(timeScale) || timeScale < 0)
19
+ throw new RangeError("timeScale must be finite and non-negative.");
20
+ this.timeScaleValue = timeScale;
21
+ }
22
+ update(unscaledDelta) {
23
+ if (!Number.isFinite(unscaledDelta) || unscaledDelta < 0)
24
+ throw new RangeError("delta must be finite and non-negative.");
25
+ this.unscaledDeltaValue = Math.min(unscaledDelta, this.maxDelta);
26
+ this.deltaValue = this.unscaledDeltaValue * this.timeScaleValue;
27
+ this.unscaledElapsedValue += this.unscaledDeltaValue;
28
+ this.elapsedValue += this.deltaValue;
29
+ this.frameValue++;
30
+ this.smoothedDeltaValue = this.frameValue === 1 ? this.deltaValue : this.smoothedDeltaValue * 0.9 + this.deltaValue * 0.1;
31
+ return this.snapshot();
32
+ }
33
+ snapshot() {
34
+ return Object.freeze({
35
+ frame: this.frameValue,
36
+ elapsed: this.elapsedValue,
37
+ unscaledElapsed: this.unscaledElapsedValue,
38
+ delta: this.deltaValue,
39
+ unscaledDelta: this.unscaledDeltaValue,
40
+ smoothedDelta: this.smoothedDeltaValue,
41
+ timeScale: this.timeScaleValue
42
+ });
43
+ }
44
+ }
45
+ //# sourceMappingURL=Time.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Time.js","sourceRoot":"","sources":["../../../../packages/core/src/Time.ts"],"names":[],"mappings":"AAUA,MAAM,OAAO,IAAI;IASI;IACT;IATF,UAAU,GAAG,CAAC,CAAC;IACf,YAAY,GAAG,CAAC,CAAC;IACjB,oBAAoB,GAAG,CAAC,CAAC;IACzB,UAAU,GAAG,CAAC,CAAC;IACf,kBAAkB,GAAG,CAAC,CAAC;IACvB,kBAAkB,GAAG,CAAC,CAAC;IAE/B,YACmB,QAAgB,EACzB,iBAAiB,CAAC;QADT,aAAQ,GAAR,QAAQ,CAAQ;QACzB,mBAAc,GAAd,cAAc,CAAI;QAE1B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,IAAI,CAAC;YAAE,MAAM,IAAI,UAAU,CAAC,uCAAuC,CAAC,CAAC;QAC/G,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC;IACpC,CAAC;IAED,YAAY,CAAC,SAAiB;QAC5B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,GAAG,CAAC;YAAE,MAAM,IAAI,UAAU,CAAC,4CAA4C,CAAC,CAAC;QACrH,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;IAClC,CAAC;IAED,MAAM,CAAC,aAAqB;QAC1B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,aAAa,GAAG,CAAC;YAAE,MAAM,IAAI,UAAU,CAAC,wCAAwC,CAAC,CAAC;QACzH,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACjE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,cAAc,CAAC;QAChE,IAAI,CAAC,oBAAoB,IAAI,IAAI,CAAC,kBAAkB,CAAC;QACrD,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,UAAU,CAAC;QACrC,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,GAAG,GAAG,GAAG,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC;QAC1H,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;IACzB,CAAC;IAED,QAAQ;QACN,OAAO,MAAM,CAAC,MAAM,CAAC;YACnB,KAAK,EAAE,IAAI,CAAC,UAAU;YACtB,OAAO,EAAE,IAAI,CAAC,YAAY;YAC1B,eAAe,EAAE,IAAI,CAAC,oBAAoB;YAC1C,KAAK,EAAE,IAAI,CAAC,UAAU;YACtB,aAAa,EAAE,IAAI,CAAC,kBAAkB;YACtC,aAAa,EAAE,IAAI,CAAC,kBAAkB;YACtC,SAAS,EAAE,IAAI,CAAC,cAAc;SAC/B,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -0,0 +1,96 @@
1
+ export type VersionedFieldKind = "boolean" | "int32" | "uint32" | "float32" | "float64" | "string" | "array" | "object";
2
+ export interface VersionedSchemaField {
3
+ readonly name: string;
4
+ readonly kind: VersionedFieldKind;
5
+ readonly required?: boolean;
6
+ readonly defaultValue?: unknown;
7
+ readonly elementKind?: VersionedFieldKind;
8
+ readonly schema?: VersionedSchema;
9
+ }
10
+ export interface VersionedSchemaValidation {
11
+ readonly ok: boolean;
12
+ readonly issues: readonly string[];
13
+ }
14
+ export declare class VersionedSchema {
15
+ readonly name: string;
16
+ readonly version: number;
17
+ private readonly fields;
18
+ constructor(name: string, version: number);
19
+ addField(field: VersionedSchemaField): this;
20
+ getField(name: string): VersionedSchemaField | undefined;
21
+ getFields(): readonly VersionedSchemaField[];
22
+ validate(data: unknown): VersionedSchemaValidation;
23
+ serialize(data: unknown): Record<string, unknown>;
24
+ deserialize(data: unknown): Record<string, unknown>;
25
+ static builder(name: string, version: number): VersionedSchemaBuilder;
26
+ }
27
+ export declare class VersionedSchemaBuilder {
28
+ private readonly schema;
29
+ constructor(name: string, version: number);
30
+ boolean(name: string, options?: FieldOptions<boolean>): this;
31
+ int32(name: string, options?: FieldOptions<number>): this;
32
+ uint32(name: string, options?: FieldOptions<number>): this;
33
+ float32(name: string, options?: FieldOptions<number>): this;
34
+ string(name: string, options?: FieldOptions<string>): this;
35
+ array(name: string, elementKind: VersionedFieldKind, options?: FieldOptions<readonly unknown[]>): this;
36
+ object(name: string, schema?: VersionedSchema, options?: FieldOptions<Record<string, unknown>>): this;
37
+ field(field: VersionedSchemaField): this;
38
+ build(): VersionedSchema;
39
+ }
40
+ export interface FieldOptions<T> {
41
+ readonly required?: boolean;
42
+ readonly defaultValue?: T;
43
+ }
44
+ export interface MigrationDefinition<T = unknown> {
45
+ readonly from: number;
46
+ readonly to: number;
47
+ readonly description?: string;
48
+ migrate(data: T): T;
49
+ }
50
+ export declare class MigrationRegistry<T = unknown> {
51
+ private readonly migrations;
52
+ register(migration: MigrationDefinition<T>): this;
53
+ canMigrate(from: number, to: number): boolean;
54
+ migrate(data: T, from: number, to: number): T;
55
+ list(): readonly MigrationDefinition<T>[];
56
+ private plan;
57
+ }
58
+ export type SaveSlotFormat = "json" | "binary";
59
+ export interface SaveSlotMetadata {
60
+ readonly name?: string;
61
+ readonly description?: string;
62
+ readonly playTime?: number;
63
+ readonly version?: string;
64
+ readonly autoSave?: boolean;
65
+ readonly [key: string]: unknown;
66
+ }
67
+ export interface SerializedSaveSlot {
68
+ readonly id: string;
69
+ readonly format: SaveSlotFormat;
70
+ readonly timestamp: number;
71
+ readonly metadata: SaveSlotMetadata;
72
+ readonly compressed: boolean;
73
+ readonly data: string;
74
+ }
75
+ export declare class SaveSlot {
76
+ readonly id: string;
77
+ private data;
78
+ private format;
79
+ private timestamp;
80
+ private metadata;
81
+ private compressed;
82
+ constructor(id: string, timestamp?: number);
83
+ setData(data: string | Uint8Array, format: SaveSlotFormat, options?: {
84
+ readonly compressed?: boolean;
85
+ }): void;
86
+ getData(): string | Uint8Array | null;
87
+ getFormat(): SaveSlotFormat;
88
+ getTimestamp(): number;
89
+ getMetadata(): SaveSlotMetadata;
90
+ setMetadata(metadata: SaveSlotMetadata): void;
91
+ isCompressed(): boolean;
92
+ getSize(): number;
93
+ toJSON(): SerializedSaveSlot;
94
+ static fromJSON(serialized: SerializedSaveSlot): SaveSlot;
95
+ }
96
+ //# sourceMappingURL=VersionedSerialization.d.ts.map