create-gametau 0.3.0 → 0.3.1
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/package.json +1 -1
- package/templates/base/package.json +2 -2
- package/templates/base/src/game/snapshot-queue.ts +62 -0
- package/templates/base/src/index.ts +13 -4
- package/templates/base/src-tauri/commands/Cargo.toml +1 -1
- package/templates/base/src-tauri/wasm/Cargo.toml +1 -1
- package/templates/pixi/package.json +2 -2
- package/templates/three/package.json +2 -2
package/package.json
CHANGED
|
@@ -11,12 +11,12 @@
|
|
|
11
11
|
"preview": "vite preview"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"webtau": "^0.3.
|
|
14
|
+
"webtau": "^0.3.1"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
17
17
|
"typescript": "^5.8.0",
|
|
18
18
|
"vite": "^6.0.0",
|
|
19
|
-
"webtau-vite": "^0.3.
|
|
19
|
+
"webtau-vite": "^0.3.1",
|
|
20
20
|
"@tauri-apps/cli": "^2.0.0",
|
|
21
21
|
"@tauri-apps/api": "^2.0.0"
|
|
22
22
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export interface SnapshotQueueOptions {
|
|
2
|
+
maxRetries?: number;
|
|
3
|
+
backoffMs?: number;
|
|
4
|
+
onError?: (error: unknown, retriesLeft: number) => void;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function createSnapshotQueue<T>(
|
|
8
|
+
save: (snapshot: T) => Promise<void>,
|
|
9
|
+
options?: SnapshotQueueOptions,
|
|
10
|
+
): { enqueue(snapshot: T): void } {
|
|
11
|
+
const maxRetries = options?.maxRetries ?? 3;
|
|
12
|
+
const baseBackoffMs = options?.backoffMs ?? 500;
|
|
13
|
+
const onError = options?.onError;
|
|
14
|
+
|
|
15
|
+
let snapshotInFlight = false;
|
|
16
|
+
let pendingSnapshot: T | null = null;
|
|
17
|
+
|
|
18
|
+
async function flush(): Promise<void> {
|
|
19
|
+
if (snapshotInFlight) return;
|
|
20
|
+
snapshotInFlight = true;
|
|
21
|
+
try {
|
|
22
|
+
while (pendingSnapshot !== null) {
|
|
23
|
+
const snapshot = pendingSnapshot;
|
|
24
|
+
pendingSnapshot = null;
|
|
25
|
+
|
|
26
|
+
let lastError: unknown;
|
|
27
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
28
|
+
try {
|
|
29
|
+
await save(snapshot);
|
|
30
|
+
lastError = null;
|
|
31
|
+
break;
|
|
32
|
+
} catch (error) {
|
|
33
|
+
lastError = error;
|
|
34
|
+
const retriesLeft = maxRetries - attempt;
|
|
35
|
+
onError?.(error, retriesLeft);
|
|
36
|
+
if (retriesLeft > 0) {
|
|
37
|
+
const delayMs = baseBackoffMs * 2 ** attempt;
|
|
38
|
+
await new Promise((r) => setTimeout(r, delayMs));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (lastError !== null && lastError !== undefined) {
|
|
44
|
+
// All retries exhausted for this snapshot; continue draining
|
|
45
|
+
// pending queue so newer snapshots are not blocked.
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
} finally {
|
|
49
|
+
snapshotInFlight = false;
|
|
50
|
+
if (pendingSnapshot !== null) {
|
|
51
|
+
void flush();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
enqueue(snapshot: T): void {
|
|
58
|
+
pendingSnapshot = snapshot;
|
|
59
|
+
void flush();
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { configure, isTauri } from "webtau";
|
|
2
2
|
import { startGameLoop } from "./game/loop";
|
|
3
|
+
import { createSnapshotQueue } from "./game/snapshot-queue";
|
|
3
4
|
import { initScene, updateScene } from "./game/scene";
|
|
4
5
|
import {
|
|
5
6
|
createServiceLayer,
|
|
@@ -69,6 +70,13 @@ async function main() {
|
|
|
69
70
|
let tickInFlight = false;
|
|
70
71
|
const tickRate = 1 / settings.tickRateHz;
|
|
71
72
|
|
|
73
|
+
const snapshotQueue = createSnapshotQueue<WorldView>(
|
|
74
|
+
async (snapshot) => {
|
|
75
|
+
await services.session.saveSnapshot(snapshot);
|
|
76
|
+
document.getElementById("session")!.textContent = `saved at tick ${snapshot.tick_count}`;
|
|
77
|
+
},
|
|
78
|
+
);
|
|
79
|
+
|
|
72
80
|
startGameLoop(
|
|
73
81
|
(dt) => {
|
|
74
82
|
tickAccumulator += dt;
|
|
@@ -81,15 +89,16 @@ async function main() {
|
|
|
81
89
|
updateHud(nextView, settings);
|
|
82
90
|
|
|
83
91
|
if (nextView.tick_count % settings.autoSaveEveryTicks === 0) {
|
|
84
|
-
|
|
85
|
-
document.getElementById("session")!.textContent = `saved at tick ${nextView.tick_count}`;
|
|
92
|
+
snapshotQueue.enqueue(nextView);
|
|
86
93
|
}
|
|
87
94
|
|
|
88
|
-
|
|
95
|
+
// Intentional fire-and-forget: comms events are non-critical side effects
|
|
96
|
+
// and must not block the tick cadence. void suppresses the floating-promise lint.
|
|
97
|
+
void services.comms.publish({
|
|
89
98
|
level: resolveAlertLevel(tickResult.score_delta),
|
|
90
99
|
source: "engine",
|
|
91
100
|
message: `score delta ${tickResult.score_delta}`,
|
|
92
|
-
});
|
|
101
|
+
}).catch(console.error);
|
|
93
102
|
})
|
|
94
103
|
.catch(console.error)
|
|
95
104
|
.finally(() => { tickInFlight = false; });
|
|
@@ -11,7 +11,7 @@ wasm-bindgen = "0.2"
|
|
|
11
11
|
serde = { version = "1", features = ["derive"] }
|
|
12
12
|
serde-wasm-bindgen = "0.6"
|
|
13
13
|
getrandom = { version = "0.2", features = ["js"] }
|
|
14
|
-
webtau = "0.3.
|
|
14
|
+
webtau = "0.3.1"
|
|
15
15
|
{{PROJECT_NAME}}-core = { path = "../core" }
|
|
16
16
|
{{PROJECT_NAME}}-commands = { path = "../commands" }
|
|
17
17
|
|
|
@@ -12,12 +12,12 @@
|
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"pixi.js": "^8.0.0",
|
|
15
|
-
"webtau": "^0.3.
|
|
15
|
+
"webtau": "^0.3.1"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"typescript": "^5.8.0",
|
|
19
19
|
"vite": "^6.0.0",
|
|
20
|
-
"webtau-vite": "^0.3.
|
|
20
|
+
"webtau-vite": "^0.3.1",
|
|
21
21
|
"@tauri-apps/cli": "^2.0.0",
|
|
22
22
|
"@tauri-apps/api": "^2.0.0"
|
|
23
23
|
}
|
|
@@ -12,13 +12,13 @@
|
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"three": "^0.172.0",
|
|
15
|
-
"webtau": "^0.3.
|
|
15
|
+
"webtau": "^0.3.1"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"@types/three": "^0.172.0",
|
|
19
19
|
"typescript": "^5.8.0",
|
|
20
20
|
"vite": "^6.0.0",
|
|
21
|
-
"webtau-vite": "^0.3.
|
|
21
|
+
"webtau-vite": "^0.3.1",
|
|
22
22
|
"@tauri-apps/cli": "^2.0.0",
|
|
23
23
|
"@tauri-apps/api": "^2.0.0"
|
|
24
24
|
}
|