Files
horizon/tools/generate_lan_command_order.py
Ludovic MarieandClaude Opus 5.5 e70c38e578 Send the command tree in vanilla's registration order
The LAN and dedicated servers built the tree from the data generator's
commands report, which sorts each node's children. lan/command_order.rs,
generated from vanilla's Commands(CommandSelection.ALL) by
tools/generate_lan_command_order.py, gives the registration order, and the
dedicated-server harness now compares the tree in order (the game rules,
registered in an identity-hashed order, aside).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 04:59:34 +02:00

65 lines
2.5 KiB
Python

#!/usr/bin/env python3
"""Generate crates/horizon-client/src/lan/command_order.rs: the order of the
children of every node of vanilla's command tree (Commands constructed with
CommandSelection.ALL), which the tree sent to players keeps. Brigadier keeps
children in registration order; the data generator's commands report, which
the sent tree is built from, sorts them.
python3 tools/generate_lan_command_order.py
"""
import json
import os
import subprocess
import sys
try:
from . import lab, test_rust_parity as base
except ImportError:
import lab
import test_rust_parity as base
OUT = lab.ROOT / 'crates/horizon-client/src/lan/command_order.rs'
def main():
lock, jars, libraries = base.verify_artifacts()
build = lab.LOCAL / 'lan-command-order'
classes = build / 'classes'
classes.mkdir(parents=True, exist_ok=True)
oracle = lab.ROOT / 'mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCommandParseOracle.java'
path = os.pathsep.join(map(str, [jars['server'], *libraries]))
subprocess.run(['javac', '--release', str(lock['minecraft']['java_major']), '-proc:none', '-cp', path,
'-d', str(classes), str(oracle)], check=True)
subprocess.run(['java', '-Xmx1G', '-cp', str(classes) + os.pathsep + path,
'dev.horizonlab.parity.VanillaCommandParseOracle', 'tree', str(build), 'ALL'],
check=True, cwd=build, stdout=subprocess.DEVNULL)
tree = json.loads((build / 'tree.json').read_text())
rows = []
def walk(node, path):
names = list(node.get('children', {}))
# GameRuleCommand registers the rules in an identity-hashed map's
# order, which changes from run to run.
if len(names) > 1 and path != ['gamerule']:
rows.append((' '.join(path), ' '.join(names)))
for name in names:
walk(node['children'][name], path + [name])
walk(tree, [])
lines = [
'//! The order of the children of each node of vanilla\'s command tree',
'//! (path of node names from the root, children in registration order),',
'//! for nodes with several children. Generated by',
'//! tools/generate_lan_command_order.py; do not edit by hand.',
'',
'pub const ORDER: &[(&str, &str)] = &[',
]
lines += [f' ("{p}", "{n}"),' for p, n in rows]
lines += ['];', '']
OUT.write_text('\n'.join(lines))
print(f'wrote {len(rows)} nodes to {OUT}')
if __name__ == '__main__':
sys.exit(main())