874b6f20c2
Основа — Horizon (MIT). История апстрима не переносится: этот репозиторий ведёт свою.
82 lines
4.2 KiB
Python
82 lines
4.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Compare cauldron item interactions with vanilla's CauldronInteractions.
|
|
|
|
The Java oracle (VanillaCauldronOracle) calls the cauldron block's useItemOn
|
|
with a recording level and player; the Rust example (cauldron_fixture) runs
|
|
horizon_client::cauldron. Every item is used on every cauldron state (empty,
|
|
water, lava and powder snow at each level), with water potions, dyed armour,
|
|
patterned banners and shulker boxes, in survival and creative, under water or
|
|
not, and with a crowded inventory. The result, block writes, sounds, drops and
|
|
the final inventory are compared.
|
|
"""
|
|
import argparse
|
|
import json
|
|
import random
|
|
try:
|
|
from . import interaction_lab as lib, lab
|
|
except ImportError:
|
|
import interaction_lab as lib
|
|
import lab
|
|
|
|
STATES = ['minecraft:cauldron|', 'minecraft:water_cauldron|level=1', 'minecraft:water_cauldron|level=2',
|
|
'minecraft:water_cauldron|level=3', 'minecraft:lava_cauldron|', 'minecraft:powder_snow_cauldron|level=1',
|
|
'minecraft:powder_snow_cauldron|level=3']
|
|
DYES = ['white', 'orange', 'magenta', 'light_blue', 'yellow', 'lime', 'pink', 'gray', 'light_gray', 'cyan', 'purple',
|
|
'blue', 'brown', 'green', 'red', 'black']
|
|
|
|
|
|
def snbt(item, count=1, **components):
|
|
body = ','.join('"minecraft:%s":%s' % (k, v) for k, v in sorted(components.items()))
|
|
return '{id:"%s",count:%d%s}' % (item, count, ',components:{%s}' % body if body else '')
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument('--seed', type=int, default=7)
|
|
parser.add_argument('--limit', type=int, default=4)
|
|
args = parser.parse_args()
|
|
work = lib.work_dir('cauldron-parity')
|
|
vanilla = lib.Vanilla(work)
|
|
vanilla.compile('ParityData', 'VanillaCauldronOracle')
|
|
items = json.loads((lib.RESOURCES / 'items.json').read_text())
|
|
patterns = sorted('minecraft:' + p.stem for p in (lib.RESOURCES / 'data/minecraft/banner_pattern').glob('*.json'))
|
|
rng = random.Random(args.seed)
|
|
held = []
|
|
for name, info in items.items():
|
|
if name == 'minecraft:air':
|
|
continue
|
|
top = info.get('minecraft:max_stack_size', 64)
|
|
held.append(snbt(name, 1))
|
|
held.append(snbt(name, rng.randrange(1, top + 1)))
|
|
for color in DYES:
|
|
for layers in range(0, 4):
|
|
body = '[%s]' % ','.join('{pattern:"%s",color:"%s"}' % (rng.choice(patterns), rng.choice(DYES)) for _ in range(layers))
|
|
held.append(snbt('minecraft:%s_banner' % color, rng.choice([1, 3]), banner_patterns=body))
|
|
held.append(snbt('minecraft:%s_shulker_box' % color, rng.choice([1, 2])))
|
|
for item in ['leather_helmet', 'leather_chestplate', 'leather_leggings', 'leather_boots', 'leather_horse_armor', 'wolf_armor']:
|
|
held.append(snbt('minecraft:' + item, 1, dyed_color=rng.randrange(1 << 24)))
|
|
for potion in ['minecraft:water', 'minecraft:healing', 'minecraft:awkward']:
|
|
for item in ['potion', 'splash_potion', 'lingering_potion']:
|
|
held.append(snbt('minecraft:' + item, rng.choice([1, 2]), potion_contents='{potion:"%s"}' % potion))
|
|
cases = []
|
|
filler = [snbt(i, 64) for i in ['minecraft:stone', 'minecraft:dirt', 'minecraft:cobblestone']]
|
|
for state in STATES:
|
|
for stack in held:
|
|
crowded = rng.random() < 0.25
|
|
inventory = [[i, rng.choice(filler)] for i in range(1, 36)] if crowded else []
|
|
if not crowded and rng.random() < 0.3:
|
|
inventory = [[rng.randrange(1, 36), snbt('minecraft:bucket', rng.randrange(1, 16))]]
|
|
cases.append({'state': state, 'held': stack, 'creative': rng.random() < 0.3, 'under_water': rng.random() < 0.3,
|
|
'inventory': inventory})
|
|
(work / 'cases.jsonl').write_text(''.join(json.dumps(c) + '\n' for c in cases))
|
|
vanilla.run('VanillaCauldronOracle', work / 'cases.jsonl', work / 'native.txt')
|
|
lib.cargo_example('horizon-client', 'cauldron_fixture', lib.RESOURCES, work / 'cases.jsonl', work / 'rust.txt')
|
|
total = lib.compare(cases, work / 'native.txt', work / 'rust.txt',
|
|
lambda case, line: case['state'].split('|')[0] + ' ' + line.split('\t')[0],
|
|
lambda case: json.dumps(case)[:700], args.limit)
|
|
raise SystemExit(1 if total else 0)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|