Public Access
This commit is contained in:
1 parent
3423dd25bf
commit
644d242bba
20 files changed
+1126
-7
No files matched your search
@@ -0,0 +1,106 @@
|
||||
#!/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()
|
||||
Reference in new issue
Block a user