"""The world map is a contract with the rest of the runtime. Voyager's placement, navigation and prompts are all pinned to a walkable surface at Y=64, and generator settings are only read when a world is first created, so a careless layer edit silently moves the ground under the bot or leaves the old map in place. These tests lock both properties down. """ from __future__ import annotations import json import tempfile from pathlib import Path import minecraft_stack as mc # Every ore a farming bot is expected to be able to reach on foot. FARMABLE_ORES = ( "coal_ore", "copper_ore", "iron_ore", "gold_ore", "redstone_ore", "diamond_ore", "lapis_ore", "emerald_ore", ) def _column() -> list[tuple[str, int, int]]: """Return (block, lowest_y, highest_y) from the bottom of the world up.""" y = mc.WORLD_FLOOR_Y column = [] for block, height in mc.WORLD_FLAT_LAYERS: column.append((block, y, y + height - 1)) y += height return column def test_layer_stack_reaches_the_declared_surface(): column = _column() assert sum(height for _, height in mc.WORLD_FLAT_LAYERS) == ( mc.WORLD_SURFACE_Y - mc.WORLD_FLOOR_Y ) # The top layer is the walkable surface and its first air block is Y=64. assert column[-1][0] == "minecraft:grass_block" assert column[-1][2] == mc.WORLD_SURFACE_Y - 1 assert column[-1][1] == column[-1][2] def test_surface_has_farmable_soil_over_the_ores(): column = _column() by_block = {} for block, low, high in column: by_block.setdefault(block, []).append((low, high)) # Soil and grass on top so crops and building have something to work with. assert "minecraft:dirt" in by_block assert by_block["minecraft:dirt"][-1][1] == mc.WORLD_SURFACE_Y - 2 # A resource band close enough to the surface to mine without a long shaft. for ore in FARMABLE_ORES: assert f"minecraft:{ore}" in by_block, f"{ore} missing from the map" shallow = [span for span in by_block[f"minecraft:{ore}"] if span[0] > 0] assert shallow, f"{ore} is only in the deepslate band" assert min(low for low, _ in shallow) >= mc.WORLD_SURFACE_Y - 32, ( f"{ore} sits too deep to mine from the surface" ) # The deepslate band duplicates the table at the bottom of the column. for ore in FARMABLE_ORES: assert f"minecraft:deepslate_{ore}" in by_block, f"deepslate {ore} missing" assert "minecraft:bedrock" in by_block def test_every_layer_block_exists_in_minecraft_1_19(): # An unknown block name makes the server refuse to generate the world, which # would take the whole Space down on boot. The registry shipped in the repo # is the same minecraft-data dataset the runtime ships to Mineflayer. registry = json.loads( (Path(__file__).resolve().parents[1] / "minecraft_ids_1_19.json").read_text( encoding="utf-8" ) ) known = { entry if isinstance(entry, str) else entry.get("name") for entry in registry["diggable_blocks"] } # bedrock is the one layer that is never diggable, so it is absent by design. known.add("bedrock") unknown = [ block for block, _ in mc.WORLD_FLAT_LAYERS if block.split(":", 1)[1] not in known ] assert unknown == [], f"blocks absent from Minecraft 1.19: {unknown}" def test_generator_settings_match_the_declared_layers(): settings = json.loads(mc.FLAT_GENERATOR_SETTINGS) assert settings["layers"] == [ {"block": block, "height": height} for block, height in mc.WORLD_FLAT_LAYERS ] # Lava lakes stay off: they are the only thing `lakes` controls, and they # would put lava on the surface the bot builds and pathfinds on. # (minecraft.wiki/w/Superflat/Settings) assert settings["lakes"] is False # `features` was previously asserted False on the theory that vegetation # would sit on the walkable surface. It does not: biome features such as # trees and grass occupy blocks *above* WORLD_SURFACE_Y, which is unchanged. # Leaving it off left a plains superflat with no wood at all, so the official # curriculum kept proposing crafting tasks the bot could not satisfy. assert settings["features"] is True # Omitted on purpose: the documented default is "all the structure sets", # while an empty list disables every structure. This used to pass []. assert "structure_overrides" not in settings def test_map_change_uses_a_new_world_directory(): # Generator settings are only applied when level.dat is created, so the map # can only be replaced by pointing at a directory that has no world yet. assert mc.WORLD_DIR != mc.PREVIOUS_WORLD_DIR assert mc.WORLD_DIR.parent == mc.PERSIST_ROOT def test_carrying_player_saves_keeps_the_human_session_and_resets_the_bot(): with tempfile.TemporaryDirectory() as tmp: previous = Path(tmp) / "old-world" current = Path(tmp) / "new-world" human = f"{mc._offline_player_uuid(mc.ADMIN_USERNAME)}.dat" bot = f"{mc._offline_player_uuid(mc.BOT_USERNAME)}.dat" (previous / "playerdata").mkdir(parents=True) (previous / "playerdata" / human).write_bytes(b"human-save") (previous / "playerdata" / bot).write_bytes(b"bot-save") (previous / "playerdata" / "README.txt").write_text("not a save", encoding="utf-8") current.mkdir(parents=True) mc._carry_player_saves(previous, current) carried = sorted(p.name for p in (current / "playerdata").iterdir()) assert carried == [human] assert (current / "playerdata" / human).read_bytes() == b"human-save" # A full bot inventory is what pins the official CurriculumAgent to its # hardcoded full-inventory branch, so the bot must start clean. assert not (current / "playerdata" / bot).exists() # Running again on an already-populated world must not resurrect the bot # save, and must be safe when there is no previous world at all. mc._carry_player_saves(previous, current) mc._carry_player_saves(Path(tmp) / "missing", current) assert sorted(p.name for p in (current / "playerdata").iterdir()) == [human] if __name__ == "__main__": test_layer_stack_reaches_the_declared_surface() test_surface_has_farmable_soil_over_the_ores() test_every_layer_block_exists_in_minecraft_1_19() test_generator_settings_match_the_declared_layers() test_map_change_uses_a_new_world_directory() test_carrying_player_saves_keeps_the_human_session_and_resets_the_bot() print("PASS resource map, surface Y=64 and player save carry-over")