hore(review): tighten pre-merge audit cleanup
🔍 Lint / 🪄 Check lint (pull_request) Has been cancelled
🔍 Lint / 🎨 Check format (pull_request) Has been cancelled
🔍 Lint / 🔎 Typecheck (pull_request) Has been cancelled
📊 Quality / 🔒 Security Audit (pull_request) Has been cancelled
📊 Quality / 📋 Dependency Freshness (pull_request) Has been cancelled
📊 Quality / 📦 Bundle Size (pull_request) Has been cancelled
🔍 Lint / 🏗 Build (pull_request) Has been cancelled
🔍 Lint / 🪄 Check lint (pull_request) Has been cancelled
🔍 Lint / 🎨 Check format (pull_request) Has been cancelled
🔍 Lint / 🔎 Typecheck (pull_request) Has been cancelled
📊 Quality / 🔒 Security Audit (pull_request) Has been cancelled
📊 Quality / 📋 Dependency Freshness (pull_request) Has been cancelled
📊 Quality / 📦 Bundle Size (pull_request) Has been cancelled
🔍 Lint / 🏗 Build (pull_request) Has been cancelled
This commit is contained in:
@@ -6,8 +6,12 @@ import * as THREE from "three";
|
||||
import type { OrbitControls as OrbitControlsImpl } from "three-stdlib";
|
||||
import { EditorMap } from "@/components/editor/scene/EditorMap";
|
||||
import { FlyController } from "@/controls/editor/FlyController";
|
||||
import type { CinematicDefinition } from "@/types/cinematics/cinematics";
|
||||
import type { MapNode, TransformMode, SceneData } from "@/types/editor/editor";
|
||||
import type {
|
||||
EditorCinematicPreviewRequest,
|
||||
MapNode,
|
||||
TransformMode,
|
||||
SceneData,
|
||||
} from "@/types/editor/editor";
|
||||
|
||||
const EDITOR_CAMERA_HOME_POSITION = new THREE.Vector3(0, 50, 100);
|
||||
const EDITOR_CAMERA_HOME_TARGET = new THREE.Vector3(0, 0, 0);
|
||||
@@ -23,11 +27,6 @@ function isEditableShortcutTarget(target: EventTarget | null): boolean {
|
||||
);
|
||||
}
|
||||
|
||||
export interface EditorCinematicPreviewRequest {
|
||||
id: string;
|
||||
cinematic: CinematicDefinition;
|
||||
}
|
||||
|
||||
interface EditorSceneProps {
|
||||
sceneData: SceneData;
|
||||
selectedNodeIndex: number | null;
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useGLTF } from "@react-three/drei";
|
||||
import { Component, useEffect, useMemo, useRef, type ReactNode } from "react";
|
||||
import * as THREE from "three";
|
||||
import { useLoggedGLTF } from "@/hooks/three/useLoggedGLTF";
|
||||
import { logger } from "@/utils/core/Logger";
|
||||
|
||||
interface SkyModelProps {
|
||||
fallbackModelScale?: number | undefined;
|
||||
@@ -20,6 +21,8 @@ interface SkyModelContentProps {
|
||||
interface SkyModelErrorBoundaryProps {
|
||||
children: ReactNode;
|
||||
fallback: ReactNode;
|
||||
label: string;
|
||||
modelPath: string;
|
||||
}
|
||||
|
||||
interface SkyModelErrorBoundaryState {
|
||||
@@ -43,6 +46,17 @@ class SkyModelErrorBoundary extends Component<
|
||||
return { hasError: true };
|
||||
}
|
||||
|
||||
componentDidCatch(error: Error): void {
|
||||
logger.warn(
|
||||
"SkyModel",
|
||||
`${this.props.label} model failed; using fallback`,
|
||||
{
|
||||
error,
|
||||
modelPath: this.props.modelPath,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
render(): ReactNode {
|
||||
if (this.state.hasError) {
|
||||
return this.props.fallback;
|
||||
@@ -63,7 +77,12 @@ export function SkyModel({
|
||||
<color attach="background" args={[fallbackColor]} />
|
||||
) : null;
|
||||
const fallback = fallbackModelPath ? (
|
||||
<SkyModelErrorBoundary key={fallbackModelPath} fallback={colorFallback}>
|
||||
<SkyModelErrorBoundary
|
||||
key={fallbackModelPath}
|
||||
fallback={colorFallback}
|
||||
label="Fallback sky"
|
||||
modelPath={fallbackModelPath}
|
||||
>
|
||||
<SkyModelContent
|
||||
modelPath={fallbackModelPath}
|
||||
scale={fallbackModelScale}
|
||||
@@ -74,7 +93,12 @@ export function SkyModel({
|
||||
);
|
||||
|
||||
return (
|
||||
<SkyModelErrorBoundary key={modelPath} fallback={fallback}>
|
||||
<SkyModelErrorBoundary
|
||||
key={modelPath}
|
||||
fallback={fallback}
|
||||
label="Primary sky"
|
||||
modelPath={modelPath}
|
||||
>
|
||||
<SkyModelContent modelPath={modelPath} scale={scale} />
|
||||
</SkyModelErrorBoundary>
|
||||
);
|
||||
|
||||
@@ -2,8 +2,8 @@ import type {
|
||||
MissionStep,
|
||||
RepairMissionId,
|
||||
} from "@/types/gameplay/repairMission";
|
||||
import { REPAIR_MISSION_IDS } from "@/types/gameplay/repairMission";
|
||||
|
||||
const REPAIR_MISSION_IDS = ["ebike", "pylon", "farm"] as const;
|
||||
const REPAIR_MISSION_ID_VALUES: ReadonlySet<string> = new Set(
|
||||
REPAIR_MISSION_IDS,
|
||||
);
|
||||
|
||||
@@ -83,6 +83,12 @@ export const VEGETATION_TYPE_KEYS = [
|
||||
|
||||
export type VegetationType = (typeof VEGETATION_TYPE_KEYS)[number];
|
||||
|
||||
export const VEGETATION_MAP_NODE_NAMES: ReadonlySet<string> = new Set(
|
||||
Object.values(VEGETATION_TYPES)
|
||||
.filter((config) => config.enabled)
|
||||
.map((config) => config.mapName),
|
||||
);
|
||||
|
||||
export function getVegetationModelScaleMultiplier(name: string): number {
|
||||
return (
|
||||
Object.values(VEGETATION_TYPES).find((config) => config.mapName === name)
|
||||
|
||||
@@ -2,13 +2,16 @@ import { useCallback, useEffect, useState } from "react";
|
||||
import { Canvas, useThree } from "@react-three/fiber";
|
||||
import { EditorControls } from "@/components/editor/EditorControls";
|
||||
import { EditorScene } from "@/components/editor/scene/EditorScene";
|
||||
import type { EditorCinematicPreviewRequest } from "@/components/editor/scene/EditorScene";
|
||||
import { SceneLoadingOverlay } from "@/components/ui/SceneLoadingOverlay";
|
||||
import { Subtitles } from "@/components/ui/Subtitles";
|
||||
import { useEditorHistory } from "@/hooks/editor/useEditorHistory";
|
||||
import type { CinematicDefinition } from "@/types/cinematics/cinematics";
|
||||
import { useEditorSceneData } from "@/hooks/editor/useEditorSceneData";
|
||||
import type { MapNode, TransformMode } from "@/types/editor/editor";
|
||||
import type {
|
||||
EditorCinematicPreviewRequest,
|
||||
MapNode,
|
||||
TransformMode,
|
||||
} from "@/types/editor/editor";
|
||||
import type { SceneLoadingState } from "@/types/world/sceneLoading";
|
||||
import { logger } from "@/utils/core/Logger";
|
||||
import {
|
||||
@@ -82,7 +85,7 @@ export function EditorPage(): React.JSX.Element {
|
||||
);
|
||||
const editorLoadingState: SceneLoadingState = isMapLoading
|
||||
? {
|
||||
currentStep: "Récupération blocking",
|
||||
currentStep: "Chargement de la carte",
|
||||
progress: 0.08,
|
||||
status: "loading" as const,
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import type { CinematicDefinition } from "@/types/cinematics/cinematics";
|
||||
|
||||
export type {
|
||||
HierarchicalMapNode,
|
||||
MapNode,
|
||||
@@ -5,3 +7,8 @@ export type {
|
||||
} from "@/types/map/mapScene";
|
||||
|
||||
export type TransformMode = "translate" | "rotate" | "scale";
|
||||
|
||||
export interface EditorCinematicPreviewRequest {
|
||||
id: string;
|
||||
cinematic: CinematicDefinition;
|
||||
}
|
||||
|
||||
+2
-1
@@ -1,4 +1,5 @@
|
||||
import type { Vector3Tuple } from "@/types/three/three";
|
||||
import type { RepairMissionId } from "@/types/gameplay/repairMission";
|
||||
|
||||
export type GameStep =
|
||||
| "intro"
|
||||
@@ -12,7 +13,7 @@ export type GameStep =
|
||||
| "manipulation"
|
||||
| "outOfFabrik";
|
||||
|
||||
export type MainGameState = "intro" | "ebike" | "pylon" | "farm" | "outro";
|
||||
export type MainGameState = "intro" | RepairMissionId | "outro";
|
||||
|
||||
export interface Zone {
|
||||
id: string;
|
||||
|
||||
@@ -4,7 +4,9 @@ import type {
|
||||
Vector3Tuple,
|
||||
} from "@/types/three/three";
|
||||
|
||||
export type RepairMissionId = "ebike" | "pylon" | "farm";
|
||||
export const REPAIR_MISSION_IDS = ["ebike", "pylon", "farm"] as const;
|
||||
|
||||
export type RepairMissionId = (typeof REPAIR_MISSION_IDS)[number];
|
||||
|
||||
export interface RepairMissionTriggerConfig {
|
||||
mission: RepairMissionId;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { logger } from "@/utils/core/Logger";
|
||||
|
||||
const DEBUG_GAME_STATE_COOKIE_NAME = "la-fabrik-debug-game-state";
|
||||
const DEBUG_GAME_STATE_COOKIE_MAX_AGE = 60 * 60 * 24 * 30;
|
||||
|
||||
@@ -18,7 +20,11 @@ export function readDebugGameStateCookie(): unknown {
|
||||
|
||||
try {
|
||||
return JSON.parse(decodeURIComponent(value));
|
||||
} catch {
|
||||
} catch (error) {
|
||||
logger.warn("DebugGameState", "Invalid debug game state cookie cleared", {
|
||||
error: error instanceof Error ? error : String(error),
|
||||
});
|
||||
clearDebugGameStateCookie();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
import type { MapNode } from "@/types/map/mapScene";
|
||||
import { VEGETATION_MAP_NODE_NAMES } from "@/data/world/vegetationConfig";
|
||||
import { isInstancedMapNodeName } from "@/utils/map/isInstancedMapNodeName";
|
||||
|
||||
const MAP_STRUCTURE_NODE_NAMES = new Set(["Scene", "blocking", "terrain"]);
|
||||
const RUNTIME_VEGETATION_NODE_NAMES = new Set([
|
||||
"arbre",
|
||||
"buisson",
|
||||
"champdeble",
|
||||
"champdesoja",
|
||||
"champsdetournesol",
|
||||
"potager",
|
||||
"sapin",
|
||||
]);
|
||||
|
||||
function isRuntimeStructureMapNode(name: string): boolean {
|
||||
return MAP_STRUCTURE_NODE_NAMES.has(name);
|
||||
@@ -26,7 +18,7 @@ export function isRuntimeSingleMapNode(node: MapNode): boolean {
|
||||
}
|
||||
|
||||
return (
|
||||
!RUNTIME_VEGETATION_NODE_NAMES.has(node.name) &&
|
||||
!VEGETATION_MAP_NODE_NAMES.has(node.name) &&
|
||||
!isInstancedMapNodeName(node.name)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ export function GameMap({
|
||||
|
||||
useEffect(() => {
|
||||
onLoadingStateChange?.({
|
||||
currentStep: "Récupération blocking",
|
||||
currentStep: "Chargement de la carte",
|
||||
progress: 0.05,
|
||||
status: "loading",
|
||||
});
|
||||
@@ -163,7 +163,7 @@ export function GameMap({
|
||||
}
|
||||
|
||||
onLoadingStateChange?.({
|
||||
currentStep: "Importation des models",
|
||||
currentStep: "Importation des modèles",
|
||||
progress: 0.18,
|
||||
status: "loading",
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user