From 35f00a20f93321358f96c9b8e9ab107de9a8cd75 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 31 Jul 2026 11:45:47 -0400 Subject: [PATCH] Allow two instances side by side on different ports PORT_WS, PORT_MM and INSTANCE are now overridable. INSTANCE namespaces everything that would otherwise be a shared file - the generated Webswing config, the jetty properties, the Webswing log and the host log - so two people can run their own instance without clobbering each other's state. The MegaMek port also has to reach the client's launch args, so it is now a @PORT_MM@ placeholder in the Webswing config template rather than hardcoded 8850. The jetty properties are likewise generated with the chosen HTTP port. Verified with two concurrent instances: default on 8080/8850 and "claude" on 8090/8860, both serving HTTP 200, each client pointed at its own game server. Still shared and documented: MegaMek's mmconf/ (both seed the same clientsettings.xml, so the content is identical) and logs/. Co-Authored-By: Claude Opus 5 --- README.md | 10 +++++++- spike-webswing/start.sh | 31 +++++++++++++++++-------- spike-webswing/webswing.config.template | 2 +- 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 40e8c41..fecccea 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,15 @@ TraineeB; press "Done" in the lobby. Exits on victory. `AUTO_READY=` forces the human ready server-side, for automated runs that need the deploy phase without a UI click. -**One browser at a time; restart the instance between runs, not just the +Two people can run side by side by picking different ports and an instance name, +which namespaces the generated configs and logs: + + INSTANCE=claude PORT_WS=8090 PORT_MM=8860 ./spike-webswing/start.sh + +Still shared between instances: MegaMek's `mmconf/` (both seed the same +`clientsettings.xml`, so identical content) and `logs/`. + +**One browser per instance; restart the instance between runs, not just the browser.** Webswing keeps the client JVM alive after the page closes. If a second client connects while the first holds `TraineeA`, the server renames it `TraineeA.2` — that player owns no units and has no team, so controls are greyed diff --git a/spike-webswing/start.sh b/spike-webswing/start.sh index 8e6e9f6..f232508 100755 --- a/spike-webswing/start.sh +++ b/spike-webswing/start.sh @@ -19,9 +19,17 @@ SCENARIO="${1:-data/scenarios/TrainingScenarios/1-FirstRun.mms}" # Diagnostic: seconds after connect to force the human ready server-side, # so an automated run reaches DEPLOYMENT without a UI click. 0 = normal play. AUTO_READY="${AUTO_READY:-0}" -PORT_WS=8080 -PORT_MM=8850 -RAW_LOG="$ROOT/results/host-raw.log" +# Ports and instance name are overridable so two people can run their own +# instance side by side without colliding. Everything that would otherwise be a +# shared file - the generated Webswing config, the jetty properties and both logs +# - is namespaced by INSTANCE. +PORT_WS="${PORT_WS:-8080}" +PORT_MM="${PORT_MM:-8850}" +INSTANCE="${INSTANCE:-default}" +WS_CONFIG="$WS/webswing-$INSTANCE.config" +WS_JETTY="$WS/jetty-$INSTANCE.properties" +WS_LOG="logs/ws-$INSTANCE.log" +RAW_LOG="$ROOT/results/host-$INSTANCE-raw.log" [ -x "$JAVA" ] || { echo "ERROR: JDK missing; run scripts/fetch-deps.sh" >&2; exit 1; } [ -d "$WS" ] || { echo "ERROR: $WS missing; see README" >&2; exit 1; } @@ -51,7 +59,10 @@ if [ ! -f "$ROOT/spike-webswing/fontconfig.properties" ]; then fi # Materialise the Webswing config with absolute paths for this checkout. -sed "s|@ROOT@|$ROOT|g" "$ROOT/spike-webswing/webswing.config.template" > "$WS/webswing.config" +sed -e "s|@ROOT@|$ROOT|g" -e "s|@PORT_MM@|$PORT_MM|g" \ + "$ROOT/spike-webswing/webswing.config.template" > "$WS_CONFIG" +sed "s|^org.webswing.server.http.port=.*|org.webswing.server.http.port=$PORT_WS|" \ + "$WS/jetty.properties" > "$WS_JETTY" # Seed MegaMek's GUI preferences: fullscreen frame, docked unit display and # report pane. MegaMek rewrites this file on exit, so re-seed every launch. @@ -86,7 +97,7 @@ cleanup() { } trap cleanup INT TERM EXIT -echo "starting Webswing on :$PORT_WS ..." +echo "starting Webswing on :$PORT_WS (instance: $INSTANCE, MegaMek :$PORT_MM) ..." cd "$WS" env -u DISPLAY -u XAUTHORITY setsid "$JAVA" -server -Xmx2G -Xms256m \ --add-modules=java.desktop \ @@ -105,17 +116,17 @@ env -u DISPLAY -u XAUTHORITY setsid "$JAVA" -server -Xmx2G -Xms256m \ --add-opens=java.desktop/sun.awt.image=ALL-UNNAMED \ -Dwebswing.websocketMessageSizeLimit=1024000 \ -jar webswing-server-26.4.5.war \ - -h 0.0.0.0 -j jetty.properties -c webswing.config -pf webswing.properties \ - > logs/ws.log 2>&1 & + -h 0.0.0.0 -j "$WS_JETTY" -c "$WS_CONFIG" -pf webswing.properties \ + > "$WS_LOG" 2>&1 & WS_PID=$! for _ in $(seq 60); do ss -ltn 2>/dev/null | grep -q ":$PORT_WS " && break - kill -0 "$WS_PID" 2>/dev/null || { echo "ERROR: Webswing exited; see $WS/logs/ws.log" >&2; exit 1; } + kill -0 "$WS_PID" 2>/dev/null || { echo "ERROR: Webswing exited; see $WS/$WS_LOG" >&2; exit 1; } sleep 0.5 done ss -ltn 2>/dev/null | grep -q ":$PORT_WS " \ - || { echo "ERROR: Webswing did not open :$PORT_WS; see $WS/logs/ws.log" >&2; exit 1; } + || { echo "ERROR: Webswing did not open :$PORT_WS; see $WS/$WS_LOG" >&2; exit 1; } cat <