cb19660fbe
Add version-bound core, world data, geometry, generation and feature implementations with native client/server comparison tools and scoped evidence reports. Apply Horizon project branding. Workspace tests, Clippy and 147 Python tests passed. Full 51-family survival and expanded provider comparisons are still running; complete gameplay parity and a playable Rust client remain unfinished. Private game artifacts and the isolated simple-block placement work are excluded.
79 lines
4.9 KiB
Python
79 lines
4.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Validate registry-backed cached collisions against the pinned vanilla binaries."""
|
|
import argparse
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import platform
|
|
import subprocess
|
|
import tempfile
|
|
|
|
try:
|
|
from . import lab, test_rust_parity
|
|
except ImportError:
|
|
import lab
|
|
import test_rust_parity
|
|
|
|
|
|
def counts(output):
|
|
marker = "HORIZON_COLLISION_RESULT "
|
|
found = [json.loads(line.split(marker, 1)[1]) for line in output.splitlines() if marker in line]
|
|
if len(found) != 1:
|
|
raise AssertionError(f"Missing collision counts: {found}")
|
|
result = found[0]
|
|
if result["registry_states"] != 35723 or result["cached_states"] + result["uncached_states"] != result["registry_states"] or result["queries"] != result["cached_states"] * 6 or result["unique_shapes"] <= 0:
|
|
raise AssertionError(f"Incomplete collision coverage: {result}")
|
|
return result
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("--prepare", action="store_true")
|
|
args = parser.parse_args()
|
|
directory = lab.LOCAL / "rust-collision-parity"
|
|
directory.mkdir(parents=True, exist_ok=True)
|
|
report_path = directory / "report.json"
|
|
report_path.unlink(missing_ok=True)
|
|
if args.prepare:
|
|
lab.prepare()
|
|
lock, jars, libraries = test_rust_parity.verify_artifacts()
|
|
base = Path(tempfile.mkdtemp(prefix="run-", dir=directory))
|
|
oracle = lab.ROOT / "mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCollisionOracle.java"
|
|
sources = [oracle, Path(__file__).resolve(), lab.ROOT / "tools/test_rust_parity.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/collision_fixture.rs"]
|
|
tested_sources = test_rust_parity.source_hashes(sources)
|
|
classes = base / "classes"
|
|
classes.mkdir()
|
|
dependency_path = os.pathsep.join(map(str, libraries))
|
|
test_rust_parity.run(["javac", "--release", "25", "-proc:none", "-cp", os.pathsep.join([str(jars["server"]), dependency_path]), "-d", str(classes), str(oracle)])
|
|
def java(side, mode):
|
|
result = subprocess.run(["java", "-Xmx1G", "-cp", os.pathsep.join([str(classes), str(jars[side]), dependency_path]), "dev.horizonlab.parity.VanillaCollisionOracle", mode, str(base)], cwd=lab.ROOT, capture_output=True, text=True, timeout=300)
|
|
(base / f"{side}-{mode}.log").write_text(result.stdout + result.stderr, encoding="utf-8")
|
|
result.check_returncode()
|
|
return result.stdout
|
|
expected = counts(java("server", "generate"))
|
|
test_rust_parity.run(["cargo", "build", "--release", "-p", "horizon-world", "--example", "collision_fixture"])
|
|
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" / ("collision_fixture.exe" if os.name == "nt" else "collision_fixture")
|
|
actual = counts(subprocess.check_output([str(binary), str(base)], cwd=lab.ROOT, text=True))
|
|
if actual != expected:
|
|
raise AssertionError(f"Collision coverage differs: vanilla={expected}, Rust={actual}")
|
|
references = []
|
|
for side, jar in jars.items():
|
|
java(side, side)
|
|
reference = base / f"vanilla-{side}.txt"
|
|
matched = test_rust_parity.compare(reference, base / "rust.txt")
|
|
references.append({"side": side, "jar_sha256": lab.digest(jar, "sha256"), "output_sha256": lab.digest(reference, "sha256"), "matched_output_lines": matched, **expected})
|
|
print(f"{side}: {matched:,} cached collision output lines match", flush=True)
|
|
test_rust_parity.ensure_sources_unchanged(sources, tested_sources)
|
|
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(),
|
|
"inputs_sha256": lab.digest(base / "inputs.txt", "sha256"), "rust_output_sha256": lab.digest(base / "rust.txt", "sha256"), "sources_sha256": tested_sources, "references": references,
|
|
"scope": "Pinned no-context cached collision branch only. Registry identity validation, resident section lookup, grids, discrete extrema including empty shapes, greedy boxes, bounds, translated collide, ray hits, closest points and moved cell lookup. Uncached states and entity-context behavior remain unsupported."}
|
|
lab.write_json(report_path, report)
|
|
lab.write_json(base / "report.json", report)
|
|
print(f"Cached collision comparison passed: {report_path}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|