#!/usr/bin/env python3 """Compare registered cached block support with pinned vanilla.""" import argparse import json import os from pathlib import Path import platform import subprocess import random import struct import math try: from . import lab, test_rust_parity as base except ImportError: import lab import test_rust_parity as base def main(): parser=argparse.ArgumentParser(description=__doc__);parser.add_argument('--prepare',action='store_true');args=parser.parse_args() build=lab.LOCAL/'rust-block-support-parity';build.mkdir(parents=True,exist_ok=True) report_path=build/'report.json';report_path.unlink(missing_ok=True) if args.prepare:lab.prepare() lock,jars,libraries=base.verify_artifacts() oracle=lab.ROOT/'mods/horizon/src/test/java/dev/horizonlab/parity/VanillaBlockSupportOracle.java' helper=lab.ROOT/'mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCollisionOracle.java' sources=[oracle,helper,Path(__file__),lab.ROOT/'tools/test_rust_parity.py',lab.ROOT/'tools/lab.py',lab.ROOT/'Cargo.toml',lab.ROOT/'Cargo.lock',lab.ROOT/'crates/horizon-core/Cargo.toml',lab.ROOT/'crates/horizon-world/Cargo.toml',*sorted((lab.ROOT/'crates/horizon-core/src').rglob('*.rs')),*sorted((lab.ROOT/'crates/horizon-world/src').rglob('*.rs')),lab.ROOT/'crates/horizon-world/examples/probe/block_support_fixture.rs'] tested_sources=base.source_hashes(sources) classes=build/'classes';classes.mkdir(exist_ok=True) def run(command,name): with (build/(name+'.log')).open('w',encoding='utf-8') as log:base.run(list(map(str,command)),stdout=log,stderr=subprocess.STDOUT) dependency_path=os.pathsep.join(map(str,libraries)) run(['javac','--release',lock['minecraft']['java_major'],'-proc:none','-sourcepath',str(lab.ROOT/'mods/horizon/src/test/java'),'-cp',str(jars['server'])+os.pathsep+dependency_path,'-d',classes,oracle,helper],'compile-java') def java(side,mode,path): run(['java','-Xmx512M','-cp',os.pathsep.join([str(classes),str(jars[side]),dependency_path]),'dev.horizonlab.parity.VanillaBlockSupportOracle',mode,path],side+'-'+mode) java('server','export',build) fixture_paths=[build/'block-registry.nbt',build/'cached-support.nbt'];tested_fixtures=base.source_hashes(fixture_paths) run(['cargo','build','--release','-p','horizon-world','--example','world_probe'],'compile-rust') metadata=json.loads(subprocess.check_output(['cargo','metadata','--no-deps','--format-version','1'],cwd=lab.ROOT,text=True)) binary=Path(metadata['target_directory'])/'release/examples'/('world_probe.exe' if os.name=='nt' else 'world_probe') run([binary,'block_support_fixture',build],'rust');references=[] for side,jar in jars.items(): java(side,side,build);reference=build/f'{side}.txt';matched=base.compare(reference,build/'rust.txt') references.append({'side':side,'jar_sha256':lab.digest(jar,'sha256'),'output_sha256':lab.digest(reference,'sha256'),'matched_output_lines':matched}) print(f'{side}: {matched:,} block-support output lines match Rust',flush=True) base.ensure_sources_unchanged(sources,tested_sources);base.ensure_sources_unchanged(fixture_paths,tested_fixtures) report={'schema':1,'minecraft':lock['minecraft']['version'],'manifest_sha1':lock['minecraft']['manifest_sha1'],'platform':platform.platform(),'java':subprocess.check_output(['java','--version'],text=True).splitlines()[0],'rustc':subprocess.check_output(['rustc','--version'],text=True).strip(),'registry_states':35723,'cached_states':35524,'uncached_states':199,'support_queries':35524*18,'sources_sha256':tested_sources,'fixtures_sha256':tested_fixtures,'rust_output_sha256':lab.digest(build/'rust.txt','sha256'),'references':references,'scope':'All 35,524 cached block-state support shapes are imported privately and Rust derives FULL/CENTER/RIGID face-support masks. These are compared with actual BlockState.isFaceSturdy cache results across all six directions; all 199 uncached states remain explicitly unsupported. Registry/DataVersion/kind validation, shared shape identities, exact face geometry and full-state queries are covered. Dynamic support selection, block survival and full gameplay remain pending.'} lab.write_json(report_path,report);print(f'Scoped block-support parity passed: {report_path}') if __name__=='__main__':main()