#!/usr/bin/env python3 """Rebuild the bundled 1.21.1 structure template from Mystcraft Legacy's layout. Run manually; world generation never downloads anything. The pinned Legacy source is LGPL-3.0 and its original block placement order is preserved here. """ import gzip import hashlib import re import struct import urllib.request from pathlib import Path SOURCE = ("https://raw.githubusercontent.com/Mystcraft/Mystcraft-Legacy/" "9bc8ddc061845df0cd5ea47f4fdef773cff786ae/src/main/java/" "com/xcompwiz/mystcraft/world/gen/structure/ComponentScatteredFeatureSmallLibrary.java") SHA256 = "487b3bef48dacfbea35ac2020dbb5543dab0c2a9d99bae4a11acb5cc6fc8bfac" OUTPUT = Path(__file__).resolve().parents[1] / "src/main/resources/data/rivencraft/structure/mystcraft_library.nbt" LECTERNS = {(6, 2), (8, 4), (8, 5), (8, 6), (6, 8)} BLOCKS = { "AIR": "air", "BOOKSHELF": "bookshelf", "COBBLESTONE": "cobblestone", "COBBLESTONE_WALL": "cobblestone_wall", "PLANKS": "oak_planks", "STONE_STAIRS": "stone_stairs", "STONE_SLAB": "cobblestone_slab", "WEB": "cobweb", } PATTERN = re.compile(r"setBlockState\(worldObj, Blocks\.(\w+)\.(.+?), " r"(\d+), (\d+), (\d+), boundingbox\);") def nbt_string(value): encoded = value.encode("utf-8") return struct.pack(">H", len(encoded)) + encoded def tag(kind, name, payload): return bytes([kind]) + nbt_string(name) + payload def compound(entries): return b"".join(entries) + b"\0" def list_tag(name, element_kind, elements): return tag(9, name, bytes([element_kind]) + struct.pack(">i", len(elements)) + b"".join(elements)) def int_list(name, values): return list_tag(name, 3, [struct.pack(">i", value) for value in values]) def main(): source = urllib.request.urlopen(SOURCE, timeout=15).read() if hashlib.sha256(source).hexdigest() != SHA256: raise ValueError("Pinned Legacy source changed") placements = {} matches = PATTERN.findall(source.decode("utf-8")) if len(matches) != 694: raise ValueError(f"Expected 694 Legacy block placements, got {len(matches)}") for legacy_block, state, x, y, z in matches: x, y, z = int(x), int(y), int(z) if legacy_block not in BLOCKS or not (0 <= x <= 10 and 0 <= y <= 10 and 0 <= z <= 10): raise ValueError(f"Unsupported Legacy block/position: {legacy_block} {(x, y, z)}") properties = {} facing = re.search(r"BlockStairs.FACING, EnumFacing.(\w+)", state) if facing: properties["facing"] = facing.group(1).lower() if "BlockStairs.EnumHalf.TOP" in state: properties["half"] = "top" if legacy_block == "STONE_SLAB": meta = re.search(r"getStateFromMeta\((\d+)\)", state) if not meta or int(meta.group(1)) not in (3, 11): raise ValueError(f"Unknown Legacy slab metadata: {state}") properties["type"] = "top" if int(meta.group(1)) == 11 else "bottom" placements[x, y, z] = ("minecraft:" + BLOCKS[legacy_block], tuple(sorted(properties.items()))) # Legacy's lower lectern is a bookshelf at y=1. Remove that and its # two-block upper half; runtime places a one-block Rivencraft stand at y=1. for x, z in LECTERNS: placements.pop((x, 1, z), None) placements.pop((x, 2, z), None) # Chest and its inventory are assigned at runtime, never frozen in NBT. placements.pop((4, 1, 2), None) placements = {pos: state for pos, state in placements.items() if state[0] != "minecraft:air"} palette = sorted(set(placements.values())) indexes = {state: index for index, state in enumerate(palette)} palette_tags = [] for name, properties in palette: entries = [tag(8, "Name", nbt_string(name))] if properties: entries.append(tag(10, "Properties", compound( [tag(8, key, nbt_string(value)) for key, value in properties]))) palette_tags.append(compound(entries)) block_tags = [compound([int_list("pos", (x, y, z)), tag(3, "state", struct.pack(">i", indexes[state]))]) for (x, y, z), state in sorted(placements.items())] root = compound([int_list("size", (11, 11, 11)), list_tag("palette", 10, palette_tags), list_tag("blocks", 10, block_tags), list_tag("entities", 10, []), tag(3, "DataVersion", struct.pack(">i", 3955))]) OUTPUT.parent.mkdir(parents=True, exist_ok=True) OUTPUT.write_bytes(gzip.compress(tag(10, "", root), mtime=0)) print(f"Wrote {OUTPUT}: {len(placements)} blocks, {len(palette)} palette states") if __name__ == "__main__": main()