feat(world): terrain base-Z — land baseline sits above the sea (#238) #241

Merged
panda merged 1 commit from feat/terrain-base-z into main 2026-08-01 13:27:55 +02:00
Collaborator

Summary

Base-Z per tipo di terreno (implementa il design #238, modello additivo): GroundZAt = terrain.BaseZ + relief. La terra ha base 5, spiagge/oceano 0 — così la terra sta sopra il livello del mare e le coste hanno un dislivello, senza salvare un Z per cella (la base è derivata dal terreno; solo il relief autorato è memorizzato).

  • TerrainDef.BaseZ (colonna opzionale in tiledata.txt, default 0), parse/write in TextMapFormat.
  • GroundZAt = BaseZ + relief in TileMap e CompactWorldMap.
  • LegacyMapImporter memorizza il relief (GroundZAt − BaseZ), così un mondo piatto con terra rialzata importa zero elevazione (la base si riaggiunge in lettura).
  • asterra si aggiorna da sola: la terra sale a Z5, l'oceano resta 0, e le 64 zone di rilievo autorato sono preservate (raggiunta la vetta a Z49 = 48+1). Nessun re-bake, nessun cambio storage.
  • Nessun cambio wire → nessun bump ProtocolVersion (Z derivato da mappa+tiledata su entrambi i lati).

Screenshots / recording

La costa di asterra con la terra a Z5 sopra il mare (spawn 5183,4378). Il gradino esiste geometricamente ma il blend SDF non lo ombreggia → si vede solo come un gradiente verde→blu più largo, non come uno scalino. Reso visibile dall'hillshade (issue collegata).

shot

Vetta vulcanica raggiunta via /tp: Z49 = relief 48 + base 1 — la base-Z è viva sul mondo caricato e il rilievo autorato è preservato (nessun re-bake).

shot

Nota onesta: il gradino di costa non si vede ancora — il renderer sposta il terreno in altezza (ZScale=4) ma non lo ombreggia, e il blend SDF spalma il dislivello. Alzare il baseline (provato fino a Z5) non basta: è un limite di rendering. Reso visibile dall'hillshade → issue #239. (Lag nelle zone di rilievo → issue #240, pre-esistente e separato.)

How it was tested

  • Unit (TerrainBaseZTests): GroundZAt = BaseZ + relief; parità CompactWorldMap cella-per-cella; passo costa spiaggia→terra ΔZ ok; round-trip tiledata.
  • Guard asterra: lo spawn è terra sopra il mare (GroundZAt ≥ 1).
  • In-game (harness, DB fresco): spawn a Z5 sulla costa; /tp alla vetta Z49 (=48+1) → base-Z viva sul mondo caricato; passi nell'oceano rifiutati dal server (walkability ok).
  • Gate: build intera 0 warning, 737 test verdi, CSharpier pulito.

Checklist

  • just lint passes (CSharpier + analyzers, zero warnings)
  • just test is green
  • The whole solution builds (client and tools included)
  • Multi-platform preserved (server on Win/macOS/Linux, client on Win/macOS)
  • Tests added/updated for this change
  • Linked the related issue (if any) and its Definition of Done is met

Design: #238 · Follow-up: #239 (hillshade), #240 (perf).

## Summary Base-Z per tipo di terreno (implementa il design #238, modello **additivo**): `GroundZAt = terrain.BaseZ + relief`. La **terra** ha base **5**, **spiagge/oceano** **0** — così la terra sta sopra il livello del mare e le coste hanno un dislivello, **senza salvare un Z per cella** (la base è derivata dal terreno; solo il relief autorato è memorizzato). - `TerrainDef.BaseZ` (colonna opzionale in `tiledata.txt`, default 0), parse/write in `TextMapFormat`. - `GroundZAt = BaseZ + relief` in `TileMap` **e** `CompactWorldMap`. - `LegacyMapImporter` memorizza il **relief** (`GroundZAt − BaseZ`), così un mondo piatto con terra rialzata importa zero elevazione (la base si riaggiunge in lettura). - **asterra si aggiorna da sola**: la terra sale a Z5, l'oceano resta 0, e le **64 zone di rilievo autorato sono preservate** (raggiunta la vetta a Z49 = 48+1). Nessun re-bake, nessun cambio storage. - **Nessun cambio wire → nessun bump `ProtocolVersion`** (Z derivato da mappa+tiledata su entrambi i lati). ## Screenshots / recording La costa di asterra con la terra a **Z5** sopra il mare (spawn 5183,4378). Il gradino esiste geometricamente ma **il blend SDF non lo ombreggia** → si vede solo come un gradiente verde→blu più largo, non come uno scalino. Reso visibile dall'hillshade (issue collegata). ![shot](https://git.homelab.devncode.it/attachments/36472edf-7383-4861-8cee-a151fad2ef9a) Vetta vulcanica raggiunta via /tp: **Z49 = relief 48 + base 1** — la base-Z è viva sul mondo caricato e il rilievo autorato è preservato (nessun re-bake). ![shot](https://git.homelab.devncode.it/attachments/d03cc941-92ac-48ec-aaa9-f32bf1c640ca) **Nota onesta:** il *gradino* di costa **non si vede ancora** — il renderer sposta il terreno in altezza (`ZScale=4`) ma **non lo ombreggia**, e il blend SDF spalma il dislivello. Alzare il baseline (provato fino a Z5) non basta: è un limite di rendering. Reso visibile dall'**hillshade** → issue #239. (Lag nelle zone di rilievo → issue #240, pre-esistente e separato.) ## How it was tested - **Unit** (`TerrainBaseZTests`): `GroundZAt = BaseZ + relief`; parità `CompactWorldMap` cella-per-cella; passo costa spiaggia→terra ΔZ ok; round-trip `tiledata`. - **Guard asterra**: lo spawn è terra sopra il mare (`GroundZAt ≥ 1`). - **In-game** (harness, DB fresco): spawn a Z5 sulla costa; `/tp` alla vetta **Z49 (=48+1)** → base-Z viva sul mondo caricato; passi nell'oceano **rifiutati** dal server (walkability ok). - **Gate**: build intera **0 warning**, **737 test verdi**, CSharpier pulito. ## Checklist - [x] `just lint` passes (CSharpier + analyzers, zero warnings) - [x] `just test` is green - [x] The whole solution builds (client and tools included) - [x] Multi-platform preserved (server on Win/macOS/Linux, client on Win/macOS) - [x] Tests added/updated for this change - [x] Linked the related issue (if any) and its Definition of Done is met Design: #238 · Follow-up: #239 (hillshade), #240 (perf).
feat(world): terrain base-Z — land baseline sits above the sea (#238)
All checks were successful
ci / Lua content lint (pull_request) Successful in 12s
ci / Lint & Test (pull_request) Successful in 4m52s
9a7d833cc3
panda merged commit 2cf4ad9e78 into main 2026-08-01 13:27:55 +02:00
panda deleted branch feat/terrain-base-z 2026-08-01 13:27:55 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
marco/IsoMmo!241
No description provided.