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>
61 lines
2.0 KiB
Python
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()
|