#!/usr/bin/env python3 """Check on the test server that a balance change goes live with tools/server_update.py alone (Adrian, 2026-11-09): the server loads the update's data instead of the copy in its jar, `/reload` picks up a changed file while it runs, and without the update the jar's copy is used again. Usage: tools/check_server_update.py (needs eula.txt from tools/selftest.py --accept-eula) """ import json import subprocess import sys import time import zipfile from io import BytesIO from pathlib import Path from mcserver import ROOT, SERVER, Server, eula_accepted, prepare ZIP = SERVER / "config/cobblesurvival/datapack.zip" TUNING = "data/cobblesurvival/tuning/server.json" LEVEL = "world-update-check" FLAT = {"level-name": LEVEL, "level-type": "minecraft:flat", "generator-settings": '{"layers":[{"block":"minecraft:stone","height":4}],"biome":"minecraft:plains"}'} def expect(line, *parts): missing = [p for p in parts if p not in line] if missing: sys.exit(f"expected {missing} in: {line}") print(f"ok: {line.strip()}") def set_boss_evs(value): with zipfile.ZipFile(ZIP) as z: items = [(i, z.read(i.filename)) for i in z.infolist()] out = BytesIO() with zipfile.ZipFile(out, "w", zipfile.ZIP_DEFLATED) as z: for info, content in items: if info.filename == TUNING: content = json.dumps(json.loads(content) | {"boss_evs": value}).encode() z.writestr(info, content) part = ZIP.with_name(ZIP.name + ".part") part.write_bytes(out.getvalue()) part.replace(ZIP) # as an update does, with the server running def main(): if not eula_accepted(): sys.exit("build/server/eula.txt does not accept the Minecraft EULA yet (see tools/selftest.py --accept-eula).") args_file = prepare() subprocess.run([sys.executable, str(ROOT / "tools/server_update.py"), "--install", str(SERVER), "--level", LEVEL, "--force"], check=True) try: with Server(args_file, FLAT, stdout_name="update-check-stdout.log") as server: server.wait_ready() first = server.command("cobblesurvival data") expect(first, "data server;", "boss_evs 170;") set_boss_evs(150) server.command("reload") for _ in range(60): time.sleep(2) line = server.command("cobblesurvival data") if "boss_evs 150" in line: break expect(line, "data server;", "boss_evs 150;") server.stop() ZIP.unlink() with Server(args_file, FLAT, stdout_name="update-check-stdout.log") as server: server.wait_ready() expect(server.command("cobblesurvival data"), "data jar;", "boss_evs 170;") server.stop() finally: ZIP.unlink(missing_ok=True) print("SERVER UPDATE CHECK PASSED") if __name__ == "__main__": main()