ugly-game 0.7.2 → 0.7.4
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/dist/loop/simCore.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { DeterministicSim } from '../moat';
|
|
2
2
|
import type { ControlView } from './controlBlock';
|
|
3
|
-
import type { CommandQueue } from './commandQueue';
|
|
3
|
+
import type { CommandQueue, Stamped } from './commandQueue';
|
|
4
4
|
export interface SimClock {
|
|
5
5
|
now(): number;
|
|
6
6
|
}
|
|
@@ -21,10 +21,11 @@ export interface CoopStepOpts<S, I> {
|
|
|
21
21
|
tickOf: (s: S) => number;
|
|
22
22
|
maxCatchUpFrames?: number;
|
|
23
23
|
onLate?: (count: number) => void;
|
|
24
|
-
/** Called once per tick, with the commands due THIS tick, immediately before
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
|
|
24
|
+
/** Called once per tick, with the STAMPED commands due THIS tick (carrying `at`/`seq`/`by`), immediately before
|
|
25
|
+
* `sim.tick`. The seam a game drives per-tick co-op diagnostics through — a command journal (whose digest must
|
|
26
|
+
* fold in `at`/`seq`, so a relay reorder reads as a relay bug, not a sim bug) + a checkpoint hash trail. `state`
|
|
27
|
+
* is passed so a checkpoint can hash it at the top of the tick. */
|
|
28
|
+
beforeTick?: (due: Stamped<I>[], state: S) => void;
|
|
28
29
|
}
|
|
29
30
|
export interface SoloStepOpts<S, I> {
|
|
30
31
|
sim: SimHostSim<S, I>;
|
|
@@ -39,7 +40,7 @@ export interface SoloStepOpts<S, I> {
|
|
|
39
40
|
fps?: number;
|
|
40
41
|
maxCatchUpFrames?: number;
|
|
41
42
|
onLate?: (count: number) => void;
|
|
42
|
-
beforeTick?: (due: I[], state: S) => void;
|
|
43
|
+
beforeTick?: (due: Stamped<I>[], state: S) => void;
|
|
43
44
|
}
|
|
44
45
|
/** Single-player stepping: derive a target tick from elapsed wall time (a free-run 60-UPS accumulator, clamped by
|
|
45
46
|
* maxCatchUpFrames), publish it to `ctl.targetTick`, then reuse `coopStepBatch` — so solo and co-op run the identical
|
package/dist/loop/simCore.js
CHANGED
|
@@ -45,12 +45,12 @@ export function coopStepBatch(opts) {
|
|
|
45
45
|
if (late && opts.onLate)
|
|
46
46
|
opts.onLate(late);
|
|
47
47
|
}
|
|
48
|
-
|
|
49
|
-
//
|
|
50
|
-
//
|
|
48
|
+
// Per-tick diagnostics seam: the game records the applied (stamped) stream + a checkpoint hash of the
|
|
49
|
+
// top-of-tick state, BEFORE the tick mutates it. Fires every tick (solo + co-op) so a journal can't silently
|
|
50
|
+
// skip history. The sim itself only needs the bare commands.
|
|
51
51
|
if (opts.beforeTick)
|
|
52
|
-
opts.beforeTick(
|
|
53
|
-
opts.sim.tick(opts.state,
|
|
52
|
+
opts.beforeTick(due, opts.state);
|
|
53
|
+
opts.sim.tick(opts.state, due.map((d) => d.c));
|
|
54
54
|
stepped++;
|
|
55
55
|
};
|
|
56
56
|
// STEP_BUDGET burst first (forced, deterministic — independent of the target).
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Layout } from './layout';
|
|
2
2
|
import { type ControlView } from './controlBlock';
|
|
3
3
|
import { type SimHostSim } from './simCore';
|
|
4
|
+
import { type Stamped } from './commandQueue';
|
|
4
5
|
/** A reply a worker posts back to the main thread. Must be structured-cloneable. Echo the originating request's
|
|
5
6
|
* `rid` so the main thread's `host.request()` Promise resolves on it; any other fields are the game's payload. */
|
|
6
7
|
export interface SimWorkerReply {
|
|
@@ -17,7 +18,8 @@ export interface SimWorkerConfig<S, I> {
|
|
|
17
18
|
layout: Layout<S> | ((init: Record<string, unknown>) => Layout<S>);
|
|
18
19
|
tickOf: (s: S) => number;
|
|
19
20
|
mirror?: (s: S, ctl: ControlView<string>) => void;
|
|
20
|
-
beforeTick?: (due: I[], state: S) => void;
|
|
21
|
+
beforeTick?: (due: Stamped<I>[], state: S) => void;
|
|
21
22
|
onMessage?: (m: Record<string, unknown>, ctx: SimWorkerContext<S>) => void;
|
|
23
|
+
onReinit?: (ctx: SimWorkerContext<S>) => void;
|
|
22
24
|
}
|
|
23
25
|
export declare function runSimWorker<S, I>(cfg: SimWorkerConfig<S, I>): void;
|
|
@@ -3,6 +3,9 @@ import { soloStepBatch, coopStepBatch, } from './simCore';
|
|
|
3
3
|
import { CommandQueue } from './commandQueue';
|
|
4
4
|
export function runSimWorker(cfg) {
|
|
5
5
|
const ctx = globalThis;
|
|
6
|
+
const post = (msg) => {
|
|
7
|
+
ctx.postMessage(msg);
|
|
8
|
+
};
|
|
6
9
|
const queue = new CommandQueue();
|
|
7
10
|
let state = null;
|
|
8
11
|
let ctl = null;
|
|
@@ -98,6 +101,8 @@ export function runSimWorker(cfg) {
|
|
|
98
101
|
queue.clear();
|
|
99
102
|
lastRef.t = clock.now();
|
|
100
103
|
acc = 0;
|
|
104
|
+
if (ctl)
|
|
105
|
+
cfg.onReinit?.({ state, ctl, post });
|
|
101
106
|
}
|
|
102
107
|
else if (m.t === 'cmd') {
|
|
103
108
|
queue.push(m.s);
|
|
@@ -108,13 +113,7 @@ export function runSimWorker(cfg) {
|
|
|
108
113
|
}
|
|
109
114
|
else if (state && ctl) {
|
|
110
115
|
// A message this runner doesn't own — hand it to the game (diagnostics requests, etc.).
|
|
111
|
-
cfg.onMessage?.(m, {
|
|
112
|
-
state,
|
|
113
|
-
ctl,
|
|
114
|
-
post: (msg) => {
|
|
115
|
-
ctx.postMessage(msg);
|
|
116
|
-
},
|
|
117
|
-
});
|
|
116
|
+
cfg.onMessage?.(m, { state, ctl, post });
|
|
118
117
|
}
|
|
119
118
|
};
|
|
120
119
|
}
|