Minecraft-Console-Client/tools/gen_entity_palette.py
BruceChen 34671fdab2 feat: enhance palette generation and validation for MC 1.21.9
Updated the SKILL.md documentation to include critical steps for generating server reports and validating decompiled source against server data, emphasizing the importance of using server data since MC 1.21.9. Enhanced the diff_registries.py script to support cross-validation with server registries.json, allowing for accurate palette generation. Added new scripts for generating block and entity palettes from server data, ensuring completeness and correctness of entries.

This update improves the workflow for adapting to new Minecraft versions and ensures that palette generation reflects the latest changes in item and block registration.

Made-with: Cursor
2026-03-21 15:04:20 +08:00

111 lines
3.3 KiB
Python

#!/usr/bin/env python3
"""
Generate an MCC EntityPalette C# file from server-generated registries.json.
The registries.json file is generated by running:
java -DbundlerMainClass=net.minecraft.data.Main -jar server.jar --reports
Usage:
python3 tools/gen_entity_palette.py <registries.json> <suffix>
Example:
python3 tools/gen_entity_palette.py /tmp/mc_reports/reports/registries.json 1219
# Generates EntityPalette1219.cs
"""
import json
import re
import sys
from pathlib import Path
OUTPUT_DIR = (Path(__file__).resolve().parent.parent /
"MinecraftClient" / "Mapping" / "EntityPalettes")
ENTITY_TYPE_CS = OUTPUT_DIR.parent / "EntityType.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_entity_types() -> set[str]:
known = set()
if ENTITY_TYPE_CS.exists():
with open(ENTITY_TYPE_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)
registry_path = Path(sys.argv[1])
class_suffix = sys.argv[2]
if not registry_path.exists():
print(f"Error: {registry_path} not found")
sys.exit(1)
with open(registry_path) as f:
data = json.load(f)
entities_reg = data.get("minecraft:entity_type", {}).get("entries", {})
mappings = []
for entity_key, info in entities_reg.items():
pid = info["protocol_id"]
cs_name = mc_name_to_csharp(entity_key)
mappings.append((pid, cs_name))
mappings.sort(key=lambda x: x[0])
print(f"Loaded {len(mappings)} entity types from {registry_path}")
known = load_known_entity_types()
missing = [cs for _, cs in mappings if known and cs not in known]
if missing:
print(f"\nWARNING: {len(missing)} entity types not found in EntityType.cs enum:")
for cs_name in missing:
print(f" {cs_name}")
print("\nYou need to add these to EntityType.cs before the palette will compile.")
print("Insert them in alphabetical order within the enum.")
class_name = f"EntityPalette{class_suffix}"
output_path = OUTPUT_DIR / f"{class_name}.cs"
lines = [
"using System.Collections.Generic;",
"",
"namespace MinecraftClient.Mapping.EntityPalettes",
"{",
f" public class {class_name} : EntityPalette",
" {",
" private static readonly Dictionary<int, EntityType> mappings = new();",
"",
f" static {class_name}()",
" {",
]
for pid, cs_name in mappings:
lines.append(f" mappings[{pid}] = EntityType.{cs_name};")
lines += [
" }",
"",
" protected override Dictionary<int, EntityType> GetDict()",
" {",
" return mappings;",
" }",
" }",
"}",
"",
]
output_path.write_text("\n".join(lines))
print(f"Generated {output_path} with {len(mappings)} entity types")
if __name__ == "__main__":
main()