Files
claudeandClaude Opus 5.5 4083791944 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>
2026-11-09 16:26:30 +01:00

61 lines
2.0 KiB
Python

#!/usr/bin/env python3
"""Install or update a packwiz pack into a folder with packwiz-installer.
packwiz-installer wants a URL, so the pack folder is served on 127.0.0.1 for
the duration of the sync. It downloads Modrinth and CurseForge files from
their own CDNs and removes files that left the pack since the last sync.
Usage: tools/packwiz_sync.py <client|server> <target_dir> [pack_dir]
(pack_dir defaults to build/stage/full)
"""
import functools
import http.server
import shutil
import subprocess
import sys
import threading
from pathlib import Path
import lock
ROOT = Path(__file__).resolve().parent.parent
def java():
for candidate in (Path.home() / ".var/app/org.prismlauncher.PrismLauncher/data/PrismLauncher/java/java-runtime-delta/bin/java",):
if candidate.exists():
return str(candidate)
return shutil.which("java")
class QuietHandler(http.server.SimpleHTTPRequestHandler):
def log_message(self, *args):
pass
def sync(side, target, pack_dir):
target.mkdir(parents=True, exist_ok=True)
handler = functools.partial(QuietHandler, directory=str(pack_dir))
server = http.server.ThreadingHTTPServer(("127.0.0.1", 0), handler)
threading.Thread(target=server.serve_forever, daemon=True).start()
try:
url = f"http://127.0.0.1:{server.server_port}/pack.toml"
subprocess.run([java(), "-jar", str(lock.download("packwiz-installer-bootstrap-0.0.3.jar")),
"--bootstrap-no-update",
"--bootstrap-main-jar", str(lock.download("packwiz-installer-0.5.14.jar")),
"-g", "-s", side, url],
cwd=target, check=True)
finally:
server.shutdown()
def main():
if len(sys.argv) < 3 or sys.argv[1] not in ("client", "server"):
sys.exit(__doc__)
pack_dir = Path(sys.argv[3]) if len(sys.argv) > 3 else ROOT / "build" / "stage" / "full"
sync(sys.argv[1], Path(sys.argv[2]).resolve(), pack_dir.resolve())
if __name__ == "__main__":
main()