From dba7aec6fa6b40dbe1b010077606b078a0a1aea1 Mon Sep 17 00:00:00 2001 From: Tom Boullay Date: Thu, 14 May 2026 16:13:32 +0200 Subject: [PATCH] fix: dupplicate buisson and ecole --- src/utils/map/loadMapSceneData.ts | 38 ++++++++++++++++++++++- src/world/GameMap.tsx | 2 +- src/world/vegetation/useVegetationData.ts | 4 ++- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/utils/map/loadMapSceneData.ts b/src/utils/map/loadMapSceneData.ts index b1a0cb4..2efef22 100644 --- a/src/utils/map/loadMapSceneData.ts +++ b/src/utils/map/loadMapSceneData.ts @@ -5,6 +5,7 @@ const MAP_JSON_PATH = "/map.json"; const MODEL_FILE_NAMES = ["model.glb", "model.gltf"]; const HTML_CONTENT_TYPE = "text/html"; const MAP_STRUCTURE_NODE_NAMES = new Set(["Scene", "blocking"]); +const POSITION_PRECISION = 3; type ModelEntry = [modelName: string, modelUrl: string]; let cachedSceneData: SceneData | null = null; @@ -45,7 +46,42 @@ async function loadMapSceneDataInternal(): Promise { const mapPayload: unknown = await response.json(); const mapNodes = parseMapNodes(mapPayload); - return createSceneData(mapNodes); + const deduplicatedNodes = deduplicateMapNodes(mapNodes); + return createSceneData(deduplicatedNodes); +} + +function createPositionKey(node: MapNode): string { + const [x, y, z] = node.position; + const px = x.toFixed(POSITION_PRECISION); + const py = y.toFixed(POSITION_PRECISION); + const pz = z.toFixed(POSITION_PRECISION); + return `${node.name}:${px},${py},${pz}`; +} + +function deduplicateMapNodes(nodes: MapNode[]): MapNode[] { + const seen = new Set(); + const result: MapNode[] = []; + + const sortedNodes = [...nodes].sort((a, b) => { + if (a.type === "Object3D" && b.type !== "Object3D") return -1; + if (a.type !== "Object3D" && b.type === "Object3D") return 1; + return 0; + }); + + for (const node of sortedNodes) { + if (MAP_STRUCTURE_NODE_NAMES.has(node.name)) { + result.push(node); + continue; + } + + const key = createPositionKey(node); + if (!seen.has(key)) { + seen.add(key); + result.push(node); + } + } + + return result; } async function createSceneData(mapNodes: MapNode[]): Promise { diff --git a/src/world/GameMap.tsx b/src/world/GameMap.tsx index 66b9327..d74d2dc 100644 --- a/src/world/GameMap.tsx +++ b/src/world/GameMap.tsx @@ -28,7 +28,7 @@ interface LoadedMapNode { const MAP_STRUCTURE_NODE_NAMES = new Set(["Scene", "blocking"]); const LITE_MAP_SKIPPED_NODE_NAMES = new Set([ "arbre", - "buissons", + "buisson", "champdeble", "champdesoja", "champsdetournesol", diff --git a/src/world/vegetation/useVegetationData.ts b/src/world/vegetation/useVegetationData.ts index 89350ac..2695de2 100644 --- a/src/world/vegetation/useVegetationData.ts +++ b/src/world/vegetation/useVegetationData.ts @@ -30,7 +30,9 @@ function extractVegetationData(mapNodes: MapNode[]): VegetationData { if (!config.enabled) continue; const instances = mapNodes - .filter((node) => node.name === config.mapName) + .filter( + (node) => node.name === config.mapName && node.type === "Object3D", + ) .map(mapNodeToInstance); if (instances.length > 0) {