Phase 9: reproducible builds, balance from the server, spark check, play feedback
Build: every tool pinned (JDK, packwiz, Gradle plugins, Python packages), exports normalised, tools/check_reproducible.py proves two clean builds are byte-identical. Server-side balance: a server can load config/cobblesurvival/datapack.zip in place of the jar's data, /reload applies it, tools/server_update.py packages it and refuses when a client change is needed. JEI drop pages are sent by the server. Code-held balance numbers moved to tuning/server.json. Performance: spark in the pack (server only), tools/perf_test.py with fake players whose chunks really are active, docs/performance.md. Adrian's feedback: default keys R, U, J, §; drop pages link to Cobblemon Info and show real chances; bosses only hurt in battles; battle XP halved; channels between the islands low level; temperature ×3 with insulation doubled; hazards start at once; no item dots on the map; a wild attack starts a battle; the starter only faints; quest book on join with a basics page and an HMs page; regional forms obtainable. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0741c84077
commit
4083791944
133 files changed
+8350
-3273
No files matched your search
Executable
+76
@@ -0,0 +1,76 @@
|
||||
#!/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()
|
||||
Reference in new issue
Block a user