fix: persist debug modes and skip missing map models

This commit is contained in:
Tom Boullay
2026-04-28 16:35:33 +02:00
parent 3b8c59db87
commit 9ff75e0516
2 changed files with 66 additions and 7 deletions
+61 -6
View File
@@ -2,6 +2,41 @@ import GUI from "lil-gui";
import type { CameraMode, SceneMode } from "@/types/debug";
import { isDebugEnabled } from "@/utils/debug/isDebugEnabled";
const DEBUG_CONTROLS_STORAGE_KEY = "la-fabrik-debug-controls";
interface StoredDebugControls {
cameraMode: CameraMode;
sceneMode: SceneMode;
}
function isCameraMode(value: unknown): value is CameraMode {
return value === "player" || value === "debug";
}
function isSceneMode(value: unknown): value is SceneMode {
return value === "game" || value === "physics";
}
function getStoredDebugControls(): Partial<StoredDebugControls> {
try {
const rawValue = window.localStorage.getItem(DEBUG_CONTROLS_STORAGE_KEY);
if (!rawValue) return {};
const parsedValue = JSON.parse(rawValue) as Partial<StoredDebugControls>;
return {
...(isCameraMode(parsedValue.cameraMode)
? { cameraMode: parsedValue.cameraMode }
: {}),
...(isSceneMode(parsedValue.sceneMode)
? { sceneMode: parsedValue.sceneMode }
: {}),
};
} catch {
return {};
}
}
export class Debug {
private static instance: Debug | null = null;
@@ -14,10 +49,6 @@ export class Debug {
cameraMode: CameraMode;
showInteractionSpheres: boolean;
sceneMode: SceneMode;
} = {
cameraMode: "player",
showInteractionSpheres: false,
sceneMode: "game",
};
static getInstance(): Debug {
@@ -30,6 +61,14 @@ export class Debug {
private constructor() {
this.active = isDebugEnabled();
const storedControls = getStoredDebugControls();
this.controls = {
cameraMode: storedControls.cameraMode ?? "player",
showInteractionSpheres: false,
sceneMode: storedControls.sceneMode ?? "game",
};
this.gui = this.active ? new GUI({ title: "La-Fabrik Debug" }) : null;
if (this.gui) {
@@ -42,7 +81,7 @@ export class Debug {
.name("Camera Mode")
.onChange((value: CameraMode) => {
this.controls.cameraMode = value;
this.emit();
this.saveAndEmit();
});
folder
@@ -50,7 +89,7 @@ export class Debug {
.name("Scene")
.onChange((value: SceneMode) => {
this.controls.sceneMode = value;
this.emit();
this.saveAndEmit();
});
folder
@@ -122,4 +161,20 @@ export class Debug {
private emit(): void {
this.listeners.forEach((listener) => listener());
}
private saveAndEmit(): void {
try {
window.localStorage.setItem(
DEBUG_CONTROLS_STORAGE_KEY,
JSON.stringify({
cameraMode: this.controls.cameraMode,
sceneMode: this.controls.sceneMode,
}),
);
} catch {
// Debug persistence is optional; controls still work if storage is blocked.
}
this.emit();
}
}
+5 -1
View File
@@ -3,6 +3,7 @@ import { parseMapNodes } from "@/utils/mapNodeValidation";
const MAP_JSON_PATH = "/map.json";
const MODEL_FILE_NAME = "model.gltf";
const HTML_CONTENT_TYPE = "text/html";
type ModelEntry = [modelName: string, modelUrl: string];
export async function loadMapSceneData(): Promise<SceneData | null> {
@@ -31,8 +32,11 @@ async function loadMapModelUrls(
try {
const response = await fetch(modelUrl, { method: "HEAD" });
const contentType = response.headers.get("content-type") ?? "";
const modelEntry: ModelEntry = [modelName, modelUrl];
return response.ok ? modelEntry : null;
return response.ok && !contentType.includes(HTML_CONTENT_TYPE)
? modelEntry
: null;
} catch {
return null;
}