#!/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())