diff --git a/.project/designs/app/src/pages/WorldGen/Lab.tsx b/.project/designs/app/src/pages/WorldGen/Lab.tsx index 86c99b6a..e2baeb89 100644 --- a/.project/designs/app/src/pages/WorldGen/Lab.tsx +++ b/.project/designs/app/src/pages/WorldGen/Lab.tsx @@ -275,8 +275,8 @@ function renderCanvas(ctx: CanvasRenderingContext2D, grid: GridCell[][], st: Lab if (st.substrateOn && wasmGrid !== null) { const raw = wasmGrid.tileSubstrateJson(col, row); if (raw) { - const tile = JSON.parse(raw) as { substrate_id: string }; - const [r, g, b] = substrateRgba(tile.substrate_id); + const tile = JSON.parse(raw) as { id: string }; + const [r, g, b] = substrateRgba(tile.id); baseColor = [r, g, b]; } } diff --git a/.project/designs/app/src/pages/WorldGen/Substrate.tsx b/.project/designs/app/src/pages/WorldGen/Substrate.tsx index e5ea521f..b88665a1 100644 --- a/.project/designs/app/src/pages/WorldGen/Substrate.tsx +++ b/.project/designs/app/src/pages/WorldGen/Substrate.tsx @@ -30,6 +30,9 @@ const SUBSTRATE_LEGEND: { id: string; label: string; color: string }[] = [ { id: "lava", label: "lava", color: "rgba(220,80,30,0.95)" }, ]; +interface TileSubstrate { id: string } +interface TileFloraCover { id: string; biome_label: string } + type TileInfo = { substrate_id: string; flora_cover_id: string; biome_label_id: string } | null; function SubstrateCanvas({ grid }: { grid: import("../../../../../../.local/build/wasm/magic_civ_physics").WasmGrid }): React.ReactElement { @@ -54,7 +57,7 @@ function SubstrateCanvas({ grid }: { grid: import("../../../../../../.local/buil for (let col = 0; col < w; col++) { const raw = grid.tileSubstrateJson(col, row); if (!raw) continue; - const tile = JSON.parse(raw) as NonNullable; + const tile = JSON.parse(raw) as TileSubstrate; const { x: cx, y: cy } = hexToPixel(col, row, size); const corners = hexCorners(cx, cy, size); @@ -62,7 +65,7 @@ function SubstrateCanvas({ grid }: { grid: import("../../../../../../.local/buil ctx.moveTo(corners[0][0], corners[0][1]); for (let i = 1; i < 6; i++) ctx.lineTo(corners[i][0], corners[i][1]); ctx.closePath(); - ctx.fillStyle = SUBSTRATE_COLORS[tile.substrate_id] ?? "rgba(180,180,180,0.7)"; + ctx.fillStyle = SUBSTRATE_COLORS[tile.id] ?? "rgba(180,180,180,0.7)"; ctx.fill(); ctx.strokeStyle = "rgba(0,0,0,0.18)"; ctx.lineWidth = 0.5; @@ -86,8 +89,16 @@ function SubstrateCanvas({ grid }: { grid: import("../../../../../../.local/buil const c = Math.max(0, Math.min(grid.width - 1, col)); const row = Math.round((py - (c % 2 === 1 ? h_step / 2 : 0) - h_step / 2) / h_step); const r = Math.max(0, Math.min(grid.height - 1, row)); - const raw = grid.tileSubstrateJson(c, r); - setHoveredTile(raw ? JSON.parse(raw) as NonNullable : null); + const rawSub = grid.tileSubstrateJson(c, r); + const rawFlora = grid.tileFloraCoverJson(c, r); + if (!rawSub) { setHoveredTile(null); return; } + const sub = JSON.parse(rawSub) as TileSubstrate; + const flora = rawFlora ? JSON.parse(rawFlora) as TileFloraCover : null; + setHoveredTile({ + substrate_id: sub.id, + flora_cover_id: flora?.id ?? "", + biome_label_id: flora?.biome_label ?? "", + }); } return ( diff --git a/src/simulator/crates/mc-mapgen/src/lib.rs b/src/simulator/crates/mc-mapgen/src/lib.rs index 2fdb1ccb..f0e8c819 100644 --- a/src/simulator/crates/mc-mapgen/src/lib.rs +++ b/src/simulator/crates/mc-mapgen/src/lib.rs @@ -951,6 +951,7 @@ fn to_grid_state(gen_tiles: &HashMap<(i32, i32), GenTile>, w: i32, h: i32) -> Gr tile.moisture = gt.moisture; tile.elevation = gt.elevation; tile.biome_id = gt.biome_id.clone(); + tile.substrate_id = biome_to_substrate(>.biome_id).to_string(); tile.wind_direction = gt.wind_direction; tile.wind_speed = gt.wind_speed; tile.quality = gt.quality; diff --git a/src/simulator/crates/mc-mapgen/tests/substrate_migration.rs b/src/simulator/crates/mc-mapgen/tests/substrate_migration.rs index a6bee0d0..6209eed0 100644 --- a/src/simulator/crates/mc-mapgen/tests/substrate_migration.rs +++ b/src/simulator/crates/mc-mapgen/tests/substrate_migration.rs @@ -90,3 +90,21 @@ fn substrate_migration_coarse_distribution() { "{unpopulated_sub} tiles have empty substrate_id after generate()" ); } + +#[test] +fn substrate_id_populated_after_generate() { + let gen = MapGenerator::new("{}"); + let grid = gen.generate(42, "tiny"); + let substrate_empty = grid.tiles.iter().filter(|t| t.substrate_id.is_empty()).count(); + assert_eq!(substrate_empty, 0, "{substrate_empty} tiles have empty substrate_id after generate"); +} + +#[test] +fn substrate_id_deterministic() { + let gen = MapGenerator::new("{}"); + let g1 = gen.generate(42, "tiny"); + let g2 = gen.generate(42, "tiny"); + for (i, (t1, t2)) in g1.tiles.iter().zip(g2.tiles.iter()).enumerate() { + assert_eq!(t1.substrate_id, t2.substrate_id, "substrate_id differs at tile {i}"); + } +}