Better world generation

This commit is contained in:
2026-09-25 17:14:26 -03:00
parent c750321ced
commit d07528bd0e
14 changed files with 1315 additions and 334 deletions
+18 -13
View File
@@ -714,10 +714,19 @@ produce identical terrain. So worldgen scripts must be **deterministic**.
Each chunk is generated in three passes:
1. **Terrain.** One terrain generator fills in the ground, water and trees.
1. **Terrain.** One terrain generator fills in the ground and water.
2. **Ores.** Every mod's `worldgen/ores.json`, in load order.
3. **Features.** Every mod's registered features, in load order.
The world is 256 blocks tall and the sea is at y 64 (`CHUNK_HEIGHT` and `SEA_LEVEL` in `common/constants.ts`). The
base overworld lives in `common/worldgen/` until phase 3 moves it into `mods/bworld`. It works like Minecraft 1.18+ and
the Terralith datapack: continentalness, erosion and weirdness noises feed nested splines that give every column a
height, jaggedness and roughness, a 3D density around that height is sampled on a coarse grid and interpolated, and
caves are cut out of it. On top of that come Terralith-style shapes: terraced plateaus, shattered hills, river valleys
and gorges, jagged peaks and rare sky islands. Its biome ids (`biome_at`) are the keys of `BIOMES` in
`common/worldgen/overworld.ts`, like `bworld:yosemite_cliffs` or `bworld:skylands`. It places no trees or other
features yet. `deno run -A tools/worldgen_preview.ts [seed]` renders it to PNG files.
### Terrain generators
A world uses exactly one terrain generator, registered by a worldgen script. The base game's is `bworld:overworld`.
@@ -757,7 +766,7 @@ Seeding is exact, so a generator ported from the current code produces the same
### Ores
`worldgen/ores.json` uses the same fields as the `ORES` table in `common/generation.ts`, plus the block they replace:
`worldgen/ores.json` uses the same fields as the `BASE_ORES` table in `common/generation.ts`:
```json
{
@@ -1030,8 +1039,8 @@ anything the base game does.
| Chest | `server/game/blocks.ts` | component `bworld:storage`, params `{ rows }` |
| Furnace (smelting, fuel, its screen) | `server/game/blocks.ts` | component `bworld:furnace` |
| Watering can's starting water | `common/items/watering_can.ts` | item component `bworld:watering_can`, params `{ max_water }` |
| Terrain, biomes and trees | `common/generation.ts` | terrain generator `bworld:overworld` in `scripts/worldgen.ts` |
| Ore table | `common/generation.ts` | `worldgen/ores.json`, if it generates identically (see phase 3) |
| Terrain and biomes | `common/worldgen/` | terrain generator `bworld:overworld` in `scripts/worldgen.ts` |
| Ore table (`BASE_ORES`) | `common/generation.ts` | `worldgen/ores.json`, unchanged |
| Texture credits (the Kenney packs) | `assets/ASSETS.md` | `CREDITS.md`, listed in the manifest's `credits` |
Not moved:
@@ -1101,15 +1110,11 @@ loading mods (the base game and the template), their scripts and worldgen, saves
**Phase 3: world generation** (after step 9).
- Port `generate_chunk` to `mods/bworld/scripts/worldgen.ts` as the `bworld:overworld` terrain generator. It's a
straight port: the seeding rules in [Terrain generators](#terrain-generators) were chosen so the same noise names give
the same values.
- Keep trees inside the terrain generator rather than making them a feature. Right now a tree's leaves can be
overwritten by later columns of the same chunk; as a feature running after all terrain, they would win instead, and
the terrain would change.
- Try moving the ores to `ores.json` with `"replaces": "bworld:stone"`. The current code only places ores in stone, so
this should be identical, but only the golden test can say so. If it isn't, the ores stay inside the terrain
generator.
- Port `common/worldgen/` to `mods/bworld/scripts/worldgen.ts` as the `bworld:overworld` terrain generator. It's a
straight port: it only uses named noises, which are exactly `noise_2d` / `noise_3d` in
[Terrain generators](#terrain-generators).
- Move `BASE_ORES` to `mods/bworld/worldgen/ores.json`. They already run through the same ore pass as mods' ores, in
the same order, so the result is identical.
- Remove the content from `common/generation.ts`, leaving the passes and noise helpers.
- Check: `terrain.json` matches exactly, client and server terrain still agree, and `world_v2.json` loads unchanged.