95 lines
5.2 KiB
Python
95 lines
5.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Prepare private pinned resources for Horizon's native development client."""
|
|
import argparse
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import subprocess
|
|
import zipfile
|
|
try:
|
|
from . import lab, test_rust_parity as base, test_worldgen_parity as worldgen, test_model_baking_parity as baking
|
|
except ImportError:
|
|
import lab
|
|
import test_rust_parity as base
|
|
import test_worldgen_parity as worldgen
|
|
import test_model_baking_parity as baking
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument('--prepare', action='store_true', help='Fetch pinned reference artifacts first')
|
|
args = parser.parse_args()
|
|
if args.prepare:
|
|
lab.prepare()
|
|
lock, jars, libraries = base.verify_artifacts()
|
|
root = lab.LOCAL / 'horizon-client' / lock['minecraft']['version']
|
|
root.mkdir(parents=True, exist_ok=True)
|
|
facts = root / 'facts.json'
|
|
manifest = root / 'horizon-resources.json'
|
|
oracle = lab.ROOT / 'mods/horizon/src/test/java/dev/horizonlab/parity/VanillaHeightmapOracle.java'
|
|
origin = {'minecraft': lock['minecraft']['version'],
|
|
'client_sha256': lab.digest(jars['client'], 'sha256'),
|
|
'server_sha256': lab.digest(jars['server'], 'sha256'),
|
|
'exporter_sha256': lab.digest(oracle, 'sha256')}
|
|
previous = json.loads(manifest.read_text()) if manifest.exists() else {}
|
|
if not (all(previous.get(k) == v for k, v in origin.items()) and facts.exists()
|
|
and previous.get('facts_sha256') == lab.digest(facts, 'sha256')):
|
|
classes = root / 'classes'
|
|
classes.mkdir(exist_ok=True)
|
|
dependencies = os.pathsep.join(map(str, [jars['server'], *libraries]))
|
|
with (root / 'export.log').open('w') as log:
|
|
subprocess.run(['javac', '--release', str(lock['minecraft']['java_major']), '-proc:none',
|
|
'-cp', dependencies, '-d', str(classes), str(oracle)], check=True,
|
|
stdout=log, stderr=subprocess.STDOUT, timeout=3600)
|
|
subprocess.run(['java', '-Xmx512M', '-cp', str(classes) + os.pathsep + dependencies,
|
|
'dev.horizonlab.parity.VanillaHeightmapOracle', 'export', str(facts)],
|
|
check=True, stdout=log, stderr=subprocess.STDOUT, timeout=3600)
|
|
binding = oracle.with_name('VanillaBlockStateBindingOracle.java')
|
|
helper = oracle.with_name('VanillaCuboidModelOracle.java')
|
|
binding_sources = base.source_hashes([binding, helper])
|
|
model_states = root / 'model-states.json'
|
|
if not (previous.get('model_state_exporters_sha256') == binding_sources
|
|
and previous.get('client_sha256') == origin['client_sha256']
|
|
and model_states.exists()
|
|
and previous.get('model_states_sha256') == lab.digest(model_states, 'sha256')):
|
|
classes = root / 'client-classes'; classes.mkdir(exist_ok=True)
|
|
dependencies = os.pathsep.join(map(str, [jars['client'], *baking.client_libraries()]))
|
|
with (root / 'model-state-export.log').open('w') as log:
|
|
subprocess.run(['javac', '--release', str(lock['minecraft']['java_major']), '-proc:none',
|
|
'-cp', dependencies, '-d', str(classes), str(binding), str(helper)],
|
|
check=True, stdout=log, stderr=subprocess.STDOUT, timeout=3600)
|
|
subprocess.run(['java', '-Xmx512M', '-cp', str(classes) + os.pathsep + dependencies,
|
|
'dev.horizonlab.parity.VanillaBlockStateBindingOracle', 'export', str(model_states)],
|
|
check=True, stdout=log, stderr=subprocess.STDOUT, timeout=3600)
|
|
tags = worldgen.tag_resources(jars['server'])
|
|
if tags != worldgen.tag_resources(jars['client']):
|
|
raise ValueError('Reference block tags disagree')
|
|
lab.write_json(root / 'block-tags.json', tags)
|
|
count = 0
|
|
prefixes = ('assets/minecraft/blockstates/', 'assets/minecraft/models/block/',
|
|
'assets/minecraft/textures/block/')
|
|
with zipfile.ZipFile(jars['client']) as archive:
|
|
version = json.loads(archive.read('version.json'))
|
|
for name in archive.namelist():
|
|
if not name.startswith(prefixes) or name.endswith('/'):
|
|
continue
|
|
relative = Path(name)
|
|
if relative.is_absolute() or '..' in relative.parts:
|
|
raise ValueError('Invalid resource path')
|
|
target = root / relative
|
|
data = archive.read(name)
|
|
if not target.exists() or target.read_bytes() != data:
|
|
target.parent.mkdir(parents=True, exist_ok=True)
|
|
target.write_bytes(data)
|
|
count += 1
|
|
lab.write_json(manifest, {'schema': 2, **origin,
|
|
'model_state_exporters_sha256': binding_sources,
|
|
'model_states_sha256': lab.digest(model_states, 'sha256'), 'data_version': version['world_version'],
|
|
'facts_sha256': lab.digest(facts, 'sha256'),
|
|
'block_tags_sha256': lab.digest(root / 'block-tags.json', 'sha256'), 'resource_files': count})
|
|
print(f'Prepared Horizon native-client resources: {root}')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|