mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-15 13:04:36 +00:00
120 lines
3.6 KiB
Python
120 lines
3.6 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
"""
|
||
|
|
Generate an MCC BlockPalette C# file from server-generated blocks.json.
|
||
|
|
|
||
|
|
The blocks.json file is generated by running:
|
||
|
|
java -DbundlerMainClass=net.minecraft.data.Main -jar server.jar --reports
|
||
|
|
|
||
|
|
Usage:
|
||
|
|
python3 tools/gen_block_palette.py <blocks.json> <suffix>
|
||
|
|
|
||
|
|
Example:
|
||
|
|
python3 tools/gen_block_palette.py /tmp/mc_reports/reports/blocks.json 1219
|
||
|
|
# Generates Palette1219.cs
|
||
|
|
"""
|
||
|
|
|
||
|
|
import json
|
||
|
|
import re
|
||
|
|
import sys
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
OUTPUT_DIR = (Path(__file__).resolve().parent.parent /
|
||
|
|
"MinecraftClient" / "Mapping" / "BlockPalettes")
|
||
|
|
MATERIAL_CS = OUTPUT_DIR.parent / "Material.cs"
|
||
|
|
|
||
|
|
|
||
|
|
def mc_name_to_csharp(mc_name: str) -> str:
|
||
|
|
"""Convert minecraft:snake_case to PascalCase C# enum name."""
|
||
|
|
name = mc_name.removeprefix("minecraft:")
|
||
|
|
return "".join(word.capitalize() for word in name.split("_"))
|
||
|
|
|
||
|
|
|
||
|
|
def load_known_materials() -> set[str]:
|
||
|
|
known = set()
|
||
|
|
if MATERIAL_CS.exists():
|
||
|
|
with open(MATERIAL_CS) as f:
|
||
|
|
for line in f:
|
||
|
|
m = re.match(r'\s+(\w+),?\s*$', line)
|
||
|
|
if m:
|
||
|
|
known.add(m.group(1))
|
||
|
|
return known
|
||
|
|
|
||
|
|
|
||
|
|
def main():
|
||
|
|
if len(sys.argv) != 3:
|
||
|
|
print(__doc__)
|
||
|
|
sys.exit(1)
|
||
|
|
|
||
|
|
blocks_json = Path(sys.argv[1])
|
||
|
|
class_suffix = sys.argv[2]
|
||
|
|
|
||
|
|
if not blocks_json.exists():
|
||
|
|
print(f"Error: {blocks_json} not found")
|
||
|
|
sys.exit(1)
|
||
|
|
|
||
|
|
with open(blocks_json) as f:
|
||
|
|
data = json.load(f)
|
||
|
|
|
||
|
|
# Build (min_state, max_state, cs_name) for each block, sorted by min_state
|
||
|
|
block_ranges = []
|
||
|
|
for block_key, block_info in data.items():
|
||
|
|
cs_name = mc_name_to_csharp(block_key)
|
||
|
|
states = block_info.get("states", [])
|
||
|
|
state_ids = [s["id"] for s in states]
|
||
|
|
if state_ids:
|
||
|
|
block_ranges.append((min(state_ids), max(state_ids), cs_name))
|
||
|
|
|
||
|
|
block_ranges.sort(key=lambda x: x[0])
|
||
|
|
print(f"Loaded {len(block_ranges)} blocks from {blocks_json}")
|
||
|
|
|
||
|
|
max_state = max(r[1] for r in block_ranges)
|
||
|
|
print(f"State ID range: 0 - {max_state}")
|
||
|
|
|
||
|
|
known_materials = load_known_materials()
|
||
|
|
missing = [cs for _, _, cs in block_ranges if known_materials and cs not in known_materials]
|
||
|
|
if missing:
|
||
|
|
print(f"\nWARNING: {len(missing)} blocks not found in Material.cs enum:")
|
||
|
|
for cs_name in missing:
|
||
|
|
print(f" {cs_name}")
|
||
|
|
print("\nYou need to add these to Material.cs before the palette will compile.")
|
||
|
|
print("Insert them in alphabetical order within the enum.")
|
||
|
|
|
||
|
|
class_name = f"Palette{class_suffix}"
|
||
|
|
output_path = OUTPUT_DIR / f"{class_name}.cs"
|
||
|
|
|
||
|
|
lines = [
|
||
|
|
"using System.Collections.Generic;",
|
||
|
|
"",
|
||
|
|
"namespace MinecraftClient.Mapping.BlockPalettes",
|
||
|
|
"{",
|
||
|
|
f" public class {class_name} : BlockPalette",
|
||
|
|
" {",
|
||
|
|
" private static readonly Dictionary<int, Material> materials = new();",
|
||
|
|
"",
|
||
|
|
f" static {class_name}()",
|
||
|
|
" {",
|
||
|
|
]
|
||
|
|
|
||
|
|
for min_s, max_s, cs_name in block_ranges:
|
||
|
|
lines.append(f" for (int i = {min_s}; i <= {max_s}; i++)")
|
||
|
|
lines.append(f" materials[i] = Material.{cs_name};")
|
||
|
|
|
||
|
|
lines += [
|
||
|
|
" }",
|
||
|
|
"",
|
||
|
|
" protected override Dictionary<int, Material> GetDict()",
|
||
|
|
" {",
|
||
|
|
" return materials;",
|
||
|
|
" }",
|
||
|
|
" }",
|
||
|
|
"}",
|
||
|
|
"",
|
||
|
|
]
|
||
|
|
|
||
|
|
output_path.write_text("\n".join(lines))
|
||
|
|
print(f"Generated {output_path} with {len(block_ranges)} blocks ({max_state + 1} total states)")
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
main()
|