Phase 4: veins in every chunk, drops for the mobs the island lacks

Ore veins: make_world.py loads the island again row by row until
Regenerating Ore Veins has filled every chunk (/cobblesurvival veins
unfilled), cave tiers sit at their biome's depths, small zones get denser
veins, showcase veins are full size. The world report checks surface
tiers against the zone grid, cave tiers within two biome cells of their
cave, and fails on unfilled chunks; the template passes (37,689 chunks).

Drops: tools/drop_audit.py checks every creature drop a recipe or brewing
needs (docs/pokemon-drops.md). Blaze rods, ghast tears, breeze rods,
shulker shells and nether stars now drop from Pokemon through species
additions (self-test drop_additions_apply). The field guide counts vanilla
mobs as absent, applies species additions and reads the veins as sources.

Cobblebase tried (loads, self-tests pass) and left out until Adrian
decides its scope. Phase 4 checklist with the open questions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
claudeandClaude Opus 5.5 committed 2026-10-30 03:36:50 +01:00
1 parent 5d275e4e14
commit 1a1fb93da8
33 files changed
+1279 -126

No files matched your search

+34 -2
View File
@@ -7,7 +7,9 @@
type and gamerules, and pregenerate a circle of `pregen_radius` around
0,0 (the island plus a strip of sea; the sea corners inside the square
border generate when someone gets there).
3. In the same session: place the showcase ore veins (world/zones.json →
3. In the same session: load the circle again row by row until Regenerating
Ore Veins has put veins into every chunk (it only fills a new chunk while
it is loaded, 8 a tick, and Chunky is faster), place the showcase ore veins (world/zones.json →
"ores", tiers with "showcase": one vein sticking out of the ground near
its zone's sample point, so players see what a regenerating vein looks
like), save, measure where the land ends (tools/world_report.py) and set
@@ -23,9 +25,12 @@ Usage: tools/make_world.py
"""
import argparse
import json
import math
import re
import shutil
import subprocess
import sys
import time
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent))
@@ -41,6 +46,32 @@ SKIP = shutil.ignore_patterns("playerdata", "advancements", "stats", "session.lo
SHOWCASE_OFFSETS = [(16, 0), (0, 16), (-16, 0), (0, -16), (24, 24), (-24, -24)]
def fill_veins(server, radius):
"""Keep each chunk row of the pregenerated circle loaded until the vein mod has filled it; returns chunks left."""
# A forced row also fully loads the two chunks around it (some of them new, past the circle's edge), so the wait
# counts the loaded, unfilled chunks in the row and two chunks around it.
started, left, rows = time.time(), 0, radius // 16 + 1
for cz in range(-rows, rows + 1):
half = math.isqrt(max(0, rows * rows - cz * cz))
area = f"{-half * 16} {cz * 16} {half * 16 + 15} {cz * 16 + 15}"
around = f"{-half * 16 - 32} {cz * 16 - 32} {half * 16 + 47} {cz * 16 + 47}"
server.command(f"forceload add {area}")
deadline = time.time() + 60
while True:
reply = server.command(f"cobblesurvival veins unfilled {around}")
match = re.search(r"unfilled chunks: (\d+)", reply)
if not match:
raise RuntimeError(f"veins unfilled: unexpected reply {reply!r}")
unfilled = int(match[1])
if unfilled == 0 or time.time() > deadline:
break
time.sleep(0.5)
server.command(f"forceload remove {area}")
left += unfilled
print(f"veins filled in {time.time() - started:.0f}s" + (f"; {left} chunks left unfilled" if left else ""))
return left
def place_showcases(server):
"""One hand-placed vein per showcase tier, half sunk into the ground near the zone's sample point."""
plan = json.loads((ROOT / "world/zones.json").read_text())
@@ -56,7 +87,7 @@ def place_showcases(server):
x, z = spot
server.command(f"forceload add {x} {z}")
reply = server.command(f"execute in minecraft:overworld positioned {x} 0 {z} positioned over world_surface "
f"positioned ~ ~-1 ~ run regenerating_ore_veins place {tier}").strip()
f"positioned ~ ~-1 ~ run regenerating_ore_veins place {tier}_showcase").strip()
server.command(f"forceload remove {x} {z}")
print(f" showcase {tier} at {x},{z}: {reply[:100]}")
@@ -101,6 +132,7 @@ def main():
print(f" {server.command(f'gamerule {rule} {str(value).lower()}').strip()}")
seconds = server.pregenerate(0, 0, recipe["pregen_radius"], shape="circle")
print(f"pregeneration finished in {seconds:.0f}s")
fill_veins(server, recipe["pregen_radius"])
place_showcases(server)
server.command("save-all flush")
cx, cz, size = border_for(world, recipe)