Skip to content

Commit 907645d

Browse files
author
DavidQ
committed
refactor(tools): remove non-source default payloads/replays and enforce strict workspace state application across asset/tile/parallax/vector editors
1 parent 863b11d commit 907645d

10 files changed

Lines changed: 101 additions & 101 deletions

File tree

tools/Asset Pipeline Tool/main.js

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -185,34 +185,6 @@ function runPipeline() {
185185
setStatus(`Pipeline ${result.status || "unknown"}; records=${recordCount}.`);
186186
}
187187

188-
function createDefaultPayload() {
189-
return {
190-
gameId: "asteroids",
191-
domainInputs: {
192-
sprites: [
193-
{
194-
assetId: "ship-main",
195-
runtimeFileName: "ship-main.runtime.json",
196-
toolDataFileName: "ship-main.tool.json",
197-
sourceToolId: "sprite-editor"
198-
}
199-
]
200-
},
201-
toolStates: {
202-
"sprite-editor": {
203-
schema: "html-js-gaming.tool-state",
204-
version: 1,
205-
toolId: "sprite-editor",
206-
projectId: "asteroids",
207-
savedAtIso: "2026-01-01T00:00:00.000Z",
208-
state: {
209-
activeLayerId: "base"
210-
}
211-
}
212-
}
213-
};
214-
}
215-
216188
function extractPipelinePayloadFromPreset(rawPreset) {
217189
if (!rawPreset || typeof rawPreset !== "object") {
218190
return null;
@@ -270,14 +242,11 @@ async function tryLoadPresetFromQuery() {
270242
}
271243

272244
function bootAssetPipelineTool() {
273-
const launchContext = readLaunchContextFromQuery();
274245
if (refs.runButton instanceof HTMLButtonElement) {
275246
refs.runButton.addEventListener("click", runPipeline);
276247
}
277248
if (refs.input instanceof HTMLTextAreaElement && !refs.input.value.trim()) {
278-
const defaultPayload = createDefaultPayload();
279-
const adapted = applyLaunchContextToPayload(defaultPayload, launchContext);
280-
refs.input.value = toPrettyJson(adapted.payload);
249+
setStatus("Awaiting source pipeline JSON. No default payload is applied.");
281250
}
282251
void tryLoadPresetFromQuery();
283252
return { runPipeline };

tools/Parallax Scene Studio/main.js

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2139,6 +2139,30 @@ class ParallaxEditorApp {
21392139

21402140
let parallaxSceneStudioApp = null;
21412141

2142+
function isStrictWorkspaceParallaxSnapshot(snapshot) {
2143+
if (!snapshot || typeof snapshot !== "object") {
2144+
return false;
2145+
}
2146+
const documentModel = snapshot.documentModel;
2147+
const assetRegistry = snapshot.assetRegistry;
2148+
if (!documentModel || typeof documentModel !== "object") {
2149+
return false;
2150+
}
2151+
if (documentModel.schema !== "toolbox.parallax/1") {
2152+
return false;
2153+
}
2154+
if (!documentModel.map || typeof documentModel.map !== "object") {
2155+
return false;
2156+
}
2157+
if (!Array.isArray(documentModel.layers)) {
2158+
return false;
2159+
}
2160+
if (!assetRegistry || typeof assetRegistry !== "object") {
2161+
return false;
2162+
}
2163+
return true;
2164+
}
2165+
21422166
function bootParallaxSceneStudio() {
21432167
if (parallaxSceneStudioApp) {
21442168
window.parallaxSceneStudioApp = parallaxSceneStudioApp;
@@ -2151,13 +2175,15 @@ function bootParallaxSceneStudio() {
21512175
app.applyProjectSystemState = function applyProjectSystemState(snapshot) {
21522176
if (Date.now() <= Number(this.skipExternalProjectStateUntil || 0)) {
21532177
this.skipExternalProjectStateUntil = 0;
2154-
return;
2178+
return true;
2179+
}
2180+
if (!isStrictWorkspaceParallaxSnapshot(snapshot)) {
2181+
this.updateStatus("Project state rejected: workspace snapshot is missing required parallax source data.");
2182+
return false;
21552183
}
21562184
const nextDocument = sanitizeParallaxDocument(snapshot?.documentModel);
21572185
this.documentModel = nextDocument;
2158-
this.assetRegistry = snapshot?.assetRegistry && typeof snapshot.assetRegistry === "object"
2159-
? sanitizeAssetRegistry(snapshot.assetRegistry)
2160-
: createAssetRegistry({ projectId: nextDocument?.map?.name || "parallax-project" });
2186+
this.assetRegistry = sanitizeAssetRegistry(snapshot.assetRegistry);
21612187
this.selectedLayerId = typeof snapshot?.selectedLayerId === "string" && nextDocument.layers.some((layer) => layer.id === snapshot.selectedLayerId)
21622188
? snapshot.selectedLayerId
21632189
: nextDocument.layers[0]?.id || "";
@@ -2169,6 +2195,7 @@ function bootParallaxSceneStudio() {
21692195
this.syncInputsFromDocument();
21702196
this.renderAll();
21712197
this.updateStatus(`Project state loaded for ${this.documentModel.map.name}.`);
2198+
return true;
21722199
};
21732200
parallaxSceneStudioApp = app;
21742201
window.parallaxSceneStudioApp = parallaxSceneStudioApp;

tools/Replay Visualizer/main.js

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import {
2-
createDefaultReplayEvents,
32
getReplayEventAtTime,
43
normalizeReplayEvents,
54
safeParseJson,
@@ -25,7 +24,7 @@ const refs = {
2524
};
2625

2726
const state = {
28-
events: createDefaultReplayEvents(),
27+
events: [],
2928
currentTimeMs: 0,
3029
durationMs: 0,
3130
playing: false,
@@ -252,11 +251,7 @@ function bindEvents() {
252251
}
253252
if (refs.loadSampleButton instanceof HTMLButtonElement) {
254253
refs.loadSampleButton.addEventListener("click", () => {
255-
const sample = createDefaultReplayEvents();
256-
if (refs.input instanceof HTMLTextAreaElement) {
257-
refs.input.value = toPrettyJson({ events: sample });
258-
}
259-
applyEvents(sample, "sample");
254+
setStatus("No built-in replay sample is available. Load replay JSON from source data.");
260255
});
261256
}
262257
if (refs.playButton instanceof HTMLButtonElement) {
@@ -345,10 +340,8 @@ function bootReplayVisualizer() {
345340
refs.input.value = toPrettyJson({ events: normalizeReplayEvents(hostReplay) });
346341
}
347342
} else {
348-
applyEvents(state.events, "default replay");
349-
if (refs.input instanceof HTMLTextAreaElement) {
350-
refs.input.value = toPrettyJson({ events: state.events });
351-
}
343+
applyEvents([], "empty replay");
344+
setStatus("Awaiting replay source JSON. No default replay is applied.");
352345
}
353346
void tryLoadPresetFromQuery();
354347
initialized = true;

tools/Tile Model Converter/main.js

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -137,28 +137,12 @@ async function tryLoadPresetFromQuery() {
137137
}
138138
}
139139

140-
function createDefaultPayload() {
141-
return {
142-
candidate: {
143-
id: "arena-main",
144-
name: "arena-main",
145-
section: "tilemaps",
146-
type: "tilemap",
147-
path: "assets/tilemaps/arena-main.tilemap.json"
148-
},
149-
conversion: {
150-
targetSection: "vectors",
151-
targetType: "vector"
152-
}
153-
};
154-
}
155-
156140
function bootTileModelConverter() {
157141
if (refs.runButton instanceof HTMLButtonElement) {
158142
refs.runButton.addEventListener("click", runConversion);
159143
}
160144
if (refs.input instanceof HTMLTextAreaElement && !refs.input.value.trim()) {
161-
refs.input.value = toPrettyJson(createDefaultPayload());
145+
setStatus("Awaiting source converter JSON. No default payload is applied.");
162146
}
163147
void tryLoadPresetFromQuery();
164148
return { runConversion };

tools/Tilemap Studio/main.js

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2953,6 +2953,36 @@ class TileMapEditorApp {
29532953

29542954
let tileMapStudioApp = null;
29552955

2956+
function isStrictWorkspaceTilemapSnapshot(snapshot) {
2957+
if (!snapshot || typeof snapshot !== "object") {
2958+
return false;
2959+
}
2960+
const documentModel = snapshot.documentModel;
2961+
const assetRegistry = snapshot.assetRegistry;
2962+
if (!documentModel || typeof documentModel !== "object") {
2963+
return false;
2964+
}
2965+
if (documentModel.schema !== "toolbox.tilemap/1") {
2966+
return false;
2967+
}
2968+
if (!documentModel.map || typeof documentModel.map !== "object") {
2969+
return false;
2970+
}
2971+
if (!Array.isArray(documentModel.layers)) {
2972+
return false;
2973+
}
2974+
if (!Array.isArray(documentModel.tileset)) {
2975+
return false;
2976+
}
2977+
if (!documentModel.tilesetAtlas || typeof documentModel.tilesetAtlas !== "object") {
2978+
return false;
2979+
}
2980+
if (!assetRegistry || typeof assetRegistry !== "object") {
2981+
return false;
2982+
}
2983+
return true;
2984+
}
2985+
29562986
function bootTileMapStudio() {
29572987
if (tileMapStudioApp) {
29582988
window.tileMapStudioApp = tileMapStudioApp;
@@ -2965,13 +2995,15 @@ function bootTileMapStudio() {
29652995
app.applyProjectSystemState = function applyProjectSystemState(snapshot) {
29662996
if (Date.now() <= Number(this.skipExternalProjectStateUntil || 0)) {
29672997
this.skipExternalProjectStateUntil = 0;
2968-
return;
2998+
return true;
2999+
}
3000+
if (!isStrictWorkspaceTilemapSnapshot(snapshot)) {
3001+
this.updateStatus("Project state rejected: workspace snapshot is missing required tilemap source data.");
3002+
return false;
29693003
}
29703004
const nextDocument = sanitizeDocument(snapshot?.documentModel);
29713005
this.documentModel = nextDocument;
2972-
this.assetRegistry = snapshot?.assetRegistry && typeof snapshot.assetRegistry === "object"
2973-
? sanitizeAssetRegistry(snapshot.assetRegistry)
2974-
: createAssetRegistry({ projectId: nextDocument?.map?.name || "tilemap-project" });
3006+
this.assetRegistry = sanitizeAssetRegistry(snapshot.assetRegistry);
29753007
this.selectedLayerId = typeof snapshot?.selectedLayerId === "string" && nextDocument.layers.some((layer) => layer.id === snapshot.selectedLayerId)
29763008
? snapshot.selectedLayerId
29773009
: nextDocument.layers[0]?.id || "";
@@ -2983,6 +3015,7 @@ function bootTileMapStudio() {
29833015
this.syncInputsFromDocument();
29843016
this.renderAll();
29853017
this.updateStatus(`Project state loaded for ${this.documentModel.map.name}.`);
3018+
return true;
29863019
};
29873020
tileMapStudioApp = app;
29883021
window.tileMapStudioApp = tileMapStudioApp;

tools/Vector Asset Studio/main.js

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2923,11 +2923,19 @@ const vectorAssetStudioApi = {
29232923
if (Date.now() <= Number(state.skipExternalProjectStateUntil || 0)) {
29242924
return true;
29252925
}
2926-
if (snapshot?.svgText) {
2926+
if (!snapshot || typeof snapshot !== "object") {
2927+
setStatus("Project state rejected: snapshot object is required.");
2928+
return false;
2929+
}
2930+
if (typeof snapshot.svgText !== "string") {
2931+
setStatus("Project state rejected: svgText is required.");
2932+
return false;
2933+
}
2934+
try {
29272935
loadSvgFromText(snapshot.svgText, `${snapshot.documentName || "project"}.svg`);
2928-
} else {
2929-
createNewDocument();
2930-
setCanvasSize(snapshot?.canvasWidth || 1600, snapshot?.canvasHeight || 900);
2936+
} catch (error) {
2937+
setStatus(`Project state rejected: ${error instanceof Error ? error.message : "invalid SVG payload"}`);
2938+
return false;
29312939
}
29322940
state.documentName = snapshot?.documentName || state.documentName;
29332941
state.zoom = Number.isFinite(Number(snapshot?.zoom)) ? Number(snapshot.zoom) : state.zoom;
@@ -2937,17 +2945,6 @@ const vectorAssetStudioApi = {
29372945
updateViewTransform();
29382946
setStatus(`Project state loaded for ${state.documentName}.`);
29392947
return true;
2940-
},
2941-
createDefaultProjectState(projectName) {
2942-
return {
2943-
documentName: projectName || "untitled-background",
2944-
svgText: "",
2945-
canvasWidth: 1600,
2946-
canvasHeight: 900,
2947-
zoom: 1,
2948-
panX: 0,
2949-
panY: 0
2950-
};
29512948
}
29522949
};
29532950

tools/Vector Map Editor/editor/VectorMapDocument.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ function normalizeDegrees(value) {
4444

4545
export class VectorMapDocument {
4646
constructor(data = null) {
47-
this.data = data ? this.normalizeDocument(data) : this.createDefault();
47+
this.data = data ? this.normalizeDocument(data) : this.createEmptyDocument();
4848
}
4949

50-
createDefault() {
50+
createEmptyDocument() {
5151
return clone(DEFAULT_DOCUMENT);
5252
}
5353

tools/Vector Map Editor/editor/VectorMapEditorApp.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,6 +1247,15 @@ export class VectorMapEditorApp {
12471247
}
12481248

12491249
applyHistorySnapshot(snapshot) {
1250+
if (!snapshot || typeof snapshot !== "object") {
1251+
this.setStatus("Project state rejected: snapshot object is required.");
1252+
return false;
1253+
}
1254+
const documentData = snapshot.documentData;
1255+
if (!documentData || typeof documentData !== "object" || !Array.isArray(documentData.objects)) {
1256+
this.setStatus("Project state rejected: documentData with objects array is required.");
1257+
return false;
1258+
}
12501259
this.documentModel.setData(snapshot.documentData);
12511260
const objectId = snapshot.selection?.objectId;
12521261
const pointIndex = snapshot.selection?.pointIndex;
@@ -1264,6 +1273,7 @@ export class VectorMapEditorApp {
12641273
this.interactionController.clearCollisionResult();
12651274
this.syncUIFromDocument();
12661275
this.render();
1276+
return true;
12671277
}
12681278

12691279
commitHistorySnapshot(label, beforeSnapshot) {

tools/shared/debugInspectorData.js

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -74,16 +74,6 @@ export function normalizeReplayEvents(input) {
7474
}));
7575
}
7676

77-
export function createDefaultReplayEvents() {
78-
return normalizeReplayEvents([
79-
{ timeMs: 0, type: "boot", label: "Boot Runtime", payload: { scene: "intro" } },
80-
{ timeMs: 120, type: "input", label: "Press Start", payload: { key: "Enter", down: true } },
81-
{ timeMs: 260, type: "state", label: "Enter Gameplay", payload: { gameState: "playing", wave: 1 } },
82-
{ timeMs: 560, type: "spawn", label: "Spawn Enemy Group", payload: { kind: "asteroid", count: 3 } },
83-
{ timeMs: 900, type: "score", label: "Score +100", payload: { delta: 100, total: 100 } }
84-
]);
85-
}
86-
8777
export function getReplayEventAtTime(events, timeMs = 0) {
8878
const normalized = asArray(events);
8979
const safeTimeMs = Math.max(0, asNumber(timeMs, 0));

tools/shared/projectSystemAdapters.js

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,7 @@ function createVectorMapAdapter() {
6868
if (!state?.snapshot) {
6969
return false;
7070
}
71-
api.applyHistorySnapshot(cloneValue(state.snapshot));
72-
return true;
71+
return api.applyHistorySnapshot(cloneValue(state.snapshot)) === true;
7372
}
7473
};
7574
}
@@ -101,8 +100,7 @@ function createTilemapAdapter() {
101100
return false;
102101
}
103102
if (typeof api.applyProjectSystemState === "function") {
104-
api.applyProjectSystemState(cloneValue(state));
105-
return true;
103+
return api.applyProjectSystemState(cloneValue(state)) === true;
106104
}
107105
return false;
108106
}
@@ -136,8 +134,7 @@ function createParallaxAdapter() {
136134
return false;
137135
}
138136
if (typeof api.applyProjectSystemState === "function") {
139-
api.applyProjectSystemState(cloneValue(state));
140-
return true;
137+
return api.applyProjectSystemState(cloneValue(state)) === true;
141138
}
142139
return false;
143140
}

0 commit comments

Comments
 (0)