feat(assets): import biome ground art into the pack (#137) #155

Merged
marco merged 10 commits from feat/biomes-art into main 2026-07-24 13:34:16 +02:00
Collaborator

Imports the authored biome ground art into the committed pack, so the biomes already defined in
content/tiledata.txt render real land tiles instead of the placeholder tint. Addresses #137 (ground
portion — see "remaining" below). Design #135.

What this does

  • Adds art/land/<landArt>_0..3.png for the 8 biomes whose tiledata rows currently fall back to a
    tint: dry_grassland, northern_grassland, tundra, desert_sand, salt_plain, harsh_mountain_rock,
    rocky_ground, volcanic_ground
    (32 tiles).
  • Each tile is a 44×44 RGBA iso-diamond produced from the source art in E:\Asset
    (<biome>_1..4.png) by downscaling and applying grass_0's alpha mask — so they tessellate
    identically to the existing grass/marsh ground (no square-edge artefacts).
  • Rebakes them into client/IsoMmo.Client/assets/assets.isoa with the extractor's own-art command
    (no UO client needed — it overlays own-art onto the existing pack). Pack stays ~12.4 MB.

Verification

  • Whole solution builds 0 warnings; all tests green (Shared 93, GameServer 196, Client.Core
    81, Assets 4, Extractor 17, Auth 18, MapEditor.Core 14).
  • Ran the client (DebugHarness): walked the biome bands south of spawn — desert sand, salt plain,
    tundra, rocky/mountain, dry savanna now render textured land art, not flat tint; tiles
    tessellate cleanly (diamond mask). Screenshots taken.

Remaining (not in this PR)

  • Prop/static art (cactus, boulders, mushrooms, pines, shrubs…) is still blocked: the source
    PNGs in E:\Asset are RGB with no alpha, and props need a transparent cut-out (project forbids
    colour-key). They feed the scatter (#140) and statics, not the ground, so ground art ships now and
    props follow once re-exported as RGBA. #137 stays open for that part.

Definition of Done (ground art)

  • Pack contains land/<biome>_0..3 for all 8 biomes; grass/marsh unchanged.
  • Biome grounds render real art in-client (verified), tessellating like the existing ground.
  • Committed pack stays a sane size (~12.4 MB).
  • Game still loads/plays with the pack absent (placeholder tint fallback intact — unchanged path).
Imports the authored **biome ground art** into the committed pack, so the biomes already defined in `content/tiledata.txt` render real land tiles instead of the placeholder tint. Addresses #137 (ground portion — see "remaining" below). Design #135. ## What this does - Adds `art/land/<landArt>_0..3.png` for the 8 biomes whose `tiledata` rows currently fall back to a tint: **dry_grassland, northern_grassland, tundra, desert_sand, salt_plain, harsh_mountain_rock, rocky_ground, volcanic_ground** (32 tiles). - Each tile is a **44×44 RGBA iso-diamond** produced from the source art in `E:\Asset` (`<biome>_1..4.png`) by downscaling and applying **`grass_0`'s alpha mask** — so they tessellate identically to the existing grass/marsh ground (no square-edge artefacts). - Rebakes them into `client/IsoMmo.Client/assets/assets.isoa` with the extractor's `own-art` command (no UO client needed — it overlays own-art onto the existing pack). Pack stays ~12.4 MB. ## Verification - Whole solution builds **0 warnings**; **all tests green** (Shared 93, GameServer 196, Client.Core 81, Assets 4, Extractor 17, Auth 18, MapEditor.Core 14). - **Ran the client** (DebugHarness): walked the biome bands south of spawn — desert sand, salt plain, tundra, rocky/mountain, dry savanna now render **textured land art**, not flat tint; tiles tessellate cleanly (diamond mask). Screenshots taken. ## Remaining (not in this PR) - **Prop/static art** (cactus, boulders, mushrooms, pines, shrubs…) is **still blocked**: the source PNGs in `E:\Asset` are RGB with no alpha, and props need a transparent cut-out (project forbids colour-key). They feed the scatter (#140) and statics, not the ground, so ground art ships now and props follow once re-exported as RGBA. #137 stays open for that part. ## Definition of Done (ground art) - [x] Pack contains `land/<biome>_0..3` for all 8 biomes; grass/marsh unchanged. - [x] Biome grounds render real art in-client (verified), tessellating like the existing ground. - [x] Committed pack stays a sane size (~12.4 MB). - [x] Game still loads/plays with the pack absent (placeholder tint fallback intact — unchanged path).
feat(assets): import biome ground art (8 biomes x 4 tiles) into the pack (#137)
All checks were successful
ci / Lint & Test (pull_request) Successful in 2m3s
221aba300a
panda force-pushed feat/biomes-art from 221aba300a
All checks were successful
ci / Lint & Test (pull_request) Successful in 2m3s
to 3c242d8fa9
All checks were successful
ci / Lint & Test (pull_request) Successful in 1m47s
2026-07-22 21:57:25 +02:00
Compare
Author
Collaborator

Correction after in-client review: the first pass downscaled each 1254² source to 44×44, which averaged away all texture (tile stddev ~4 vs grass ~50) — biomes rendered as flat colour, indistinguishable from the placeholder tint. Fixed by regenerating tiles from a native-resolution 128×128 centre crop (keeps the source grain) with the diamond alpha mask. In-client the biome grounds now show real texture (measured screenshot stddev: desert ~46, salt ~40 vs ~6 before). Naming/loader unchanged (land/<landArt>_0, as grass).

Correction after in-client review: the first pass **downscaled** each 1254² source to 44×44, which averaged away all texture (tile stddev ~4 vs grass ~50) — biomes rendered as flat colour, indistinguishable from the placeholder tint. Fixed by regenerating tiles from a **native-resolution 128×128 centre crop** (keeps the source grain) with the diamond alpha mask. In-client the biome grounds now show real texture (measured screenshot stddev: desert ~46, salt ~40 vs ~6 before). Naming/loader unchanged (`land/<landArt>_0`, as grass).
panda force-pushed feat/biomes-art from 3c242d8fa9
All checks were successful
ci / Lint & Test (pull_request) Successful in 1m47s
to cea082be0c
All checks were successful
ci / Lint & Test (pull_request) Successful in 3m48s
2026-07-22 22:03:23 +02:00
Compare
feat(client): render 4 ground-tile variants per biome, picked per cell (#137)
All checks were successful
ci / Lint & Test (pull_request) Successful in 2m11s
46a86336fb
Author
Collaborator

Added 4-variant-per-cell ground rendering (commit 46a8633), on top of the authored art:
the loader now loads all land/<landArt>_0..3 as a Texture2D[] per biome and the renderer picks
a variant per cell (deterministic hash + horizontal flip, re-added GroundTileSelector in
Client.Core, unit-tested). This reverses the #143 "one tile per biome / no procedural variety"
simplification — per the owner: terrain art is always ≥4 variants, never a single tile (also
recorded in docs/asset-authoring.md). In-client the ground now reads as varied natural terrain,
not a repeating grid. Also folded in the authored grass + marsh grounds (from
grassland_* / wet_marsh_ground_*), so no biome uses UO-derived land art anymore.

Whole solution builds 0 warnings; all tests green (Client.Core +GroundTileSelectorTests).

Added **4-variant-per-cell ground rendering** (commit 46a8633), on top of the authored art: the loader now loads all `land/<landArt>_0..3` as a `Texture2D[]` per biome and the renderer picks a variant **per cell** (deterministic hash + horizontal flip, re-added `GroundTileSelector` in `Client.Core`, unit-tested). This reverses the `#143` "one tile per biome / no procedural variety" simplification — per the owner: **terrain art is always ≥4 variants, never a single tile** (also recorded in `docs/asset-authoring.md`). In-client the ground now reads as varied natural terrain, not a repeating grid. Also folded in the authored **grass** + **marsh** grounds (from `grassland_*` / `wet_marsh_ground_*`), so no biome uses UO-derived land art anymore. Whole solution builds 0 warnings; all tests green (Client.Core +GroundTileSelectorTests).
feat(content): climate-coherent biome world map (128x96) + provisional generator
All checks were successful
ci / Lint & Test (pull_request) Successful in 3m17s
4eb3821328
Author
Collaborator

Also restructured the world map into climate-coherent biome zones (commit 4eb3821): a
128×96 map generated by a provisional climate model (temperature by latitude + noise moisture/
elevation, Whittaker-style) — tundra/mountains in the cold north, a grassland heartland (spawn) with
a marsh valley, desert/savanna in the hot south, a small volcanic caldera at the mountain peak,
salt flats in a corner. Organic region boundaries (hard biome edges remain — transition tiles are
a deliberate follow-up
). The generator (scripts/genmap.py, numpy+scipy, fixed seed) is a
throwaway authoring aid — a pure-binary map format is planned to replace the text map. It carves
the PvP arena (#109) footprint to rocky_ground so those authored statics keep their floor.
Verified in-client (fresh spawn, walked spawn→mountains→south). All tests green.

NB: this PR now bundles #137 art + 4-variant rendering + the world map (biome content as a whole).

Also restructured the **world map** into climate-coherent biome zones (commit 4eb3821): a **128×96** map generated by a provisional climate model (temperature by latitude + noise moisture/ elevation, Whittaker-style) — tundra/mountains in the cold north, a grassland heartland (spawn) with a marsh valley, desert/savanna in the hot south, a small volcanic caldera at the mountain peak, salt flats in a corner. Organic region boundaries (hard biome edges remain — **transition tiles are a deliberate follow-up**). The generator (`scripts/genmap.py`, numpy+scipy, fixed seed) is a **throwaway authoring aid** — a pure-binary map format is planned to replace the text map. It carves the **PvP arena (#109) footprint to rocky_ground** so those authored statics keep their floor. Verified in-client (fresh spawn, walked spawn→mountains→south). All tests green. NB: this PR now bundles #137 art + 4-variant rendering + the world map (biome *content* as a whole).
fix(client): reuse ground-variant resolver in map editor; sync #137 invariants + tests
All checks were successful
ci / Lint & Test (pull_request) Successful in 1m43s
268fee90ce
feat(client): soft biome-border transitions from biome art (noise overlays) (#137)
All checks were successful
ci / Lint & Test (pull_request) Successful in 2m13s
1fe7433b20
feat(client): dual-grid biome borders with 16 corner masks (#162)
Some checks failed
ci / Lint & Test (pull_request) Failing after 4m0s
480b6d92ff
Merge remote-tracking branch 'origin/main' into feat/biomes-art
All checks were successful
ci / Lint & Test (pull_request) Successful in 5m15s
0a7b984454
feat(gameserver): terrain move-cost — marsh slows players and creatures (#138)
All checks were successful
ci / Lint & Test (pull_request) Successful in 4m9s
56e289fd40
Merge remote-tracking branch 'origin/main' into feat/biomes-art
All checks were successful
ci / Lint & Test (pull_request) Successful in 1m51s
cc975bf3db
# Conflicts:
#	client/IsoMmo.Client/assets/assets.isoa
feat(client): marsh-step feedback — ground ripple + one-time slow hint (#138)
All checks were successful
ci / Lint & Test (pull_request) Successful in 1m56s
668337768f
Author
Collaborator

#138 — terrain move-cost + marsh feedback

This branch now also carries #138 (terrain move-cost — marsh slows players & creatures, flying-exempt) and its client feedback (a per-step ground ripple + a one-time hint). Server side is enforced in MovementSystem/CreatureSystem via TileMap.MoveCostTicks; the feedback is pure client presentation (no wire event; ProtocolVersion 11→12 only for the new SystemMessageId.MarshSlowsYou).

Screenshots from the debug harness (fresh DB, driven over the DebugHarness socket: logingoto 64 46 on grass → move north onto marsh at (64,45), capturing the burst as the tile flipped):

Stepping onto marsh — ground ripple + one-time hint. The self player wades from the grass clearing onto marsh (HUD reads tile (64, 45)); a ripple plays at the feet and the journal shows the one-time notice “The marsh drags at your feet, slowing your step.”

marsh ripple + one-time notice

Ripple close-up — the authored splash sits flat on the ground (iso 2:1), scaling up and fading over ~0.55s from a single frame.

ripple close-up

Baseline — on grass, no ripple.

grass baseline

## #138 — terrain move-cost + marsh feedback This branch now also carries **#138** (terrain move-cost — marsh slows players & creatures, flying-exempt) and its **client feedback** (a per-step ground ripple + a one-time hint). Server side is enforced in `MovementSystem`/`CreatureSystem` via `TileMap.MoveCostTicks`; the feedback is pure client presentation (no wire event; `ProtocolVersion` 11→12 only for the new `SystemMessageId.MarshSlowsYou`). Screenshots from the debug harness (fresh DB, driven over the DebugHarness socket: `login` → `goto 64 46` on grass → `move north` onto marsh at `(64,45)`, capturing the burst as the tile flipped): **Stepping onto marsh — ground ripple + one-time hint.** The self player wades from the grass clearing onto marsh (HUD reads `tile (64, 45)`); a ripple plays at the feet and the journal shows the one-time notice *“The marsh drags at your feet, slowing your step.”* ![marsh ripple + one-time notice](https://git.homelab.devncode.it/attachments/4d4b265b-d65e-449b-9f82-c0cbb87db705) **Ripple close-up** — the authored splash sits flat on the ground (iso 2:1), scaling up and fading over ~0.55s from a single frame. ![ripple close-up](https://git.homelab.devncode.it/attachments/96027417-4f8a-4768-950b-45f7df9cab0c) **Baseline — on grass, no ripple.** ![grass baseline](https://git.homelab.devncode.it/attachments/d7f5db9a-91ca-46ab-9deb-61aea2bf9d38)
panda scheduled this pull request to auto merge when all checks succeed 2026-07-24 13:01:12 +02:00
panda canceled auto merging this pull request when all checks succeed 2026-07-24 13:14:55 +02:00
marco merged commit 7c00af9a23 into main 2026-07-24 13:34:16 +02:00
marco deleted branch feat/biomes-art 2026-07-24 13:34:17 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
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!155
No description provided.