104 lines
3.7 KiB
Shell
Executable file
104 lines
3.7 KiB
Shell
Executable file
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
repo_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
|
output_dir="$repo_dir/Builds/linux"
|
|
player="$output_dir/Simulation.x86_64"
|
|
mode="${1:---demo}"
|
|
case "$mode" in
|
|
--demo|--server|--vnc) ;;
|
|
*) echo "Usage: $0 [--demo | --server | --vnc]"; exit 2 ;;
|
|
esac
|
|
if [[ ! -x "$player" ]]; then
|
|
echo "Build the Linux player first: ./build-linux.sh" >&2
|
|
exit 1
|
|
fi
|
|
if [[ "$mode" == --vnc && -z "${DISPLAY:-}" ]]; then
|
|
exec xvfb-run -a -s '-screen 0 1280x800x24 -nolisten tcp' "$0" --vnc
|
|
fi
|
|
if [[ "$mode" == --demo && -z "${DISPLAY:-}" ]]; then
|
|
echo "No display. Use --vnc to view over SSH, or --server for a headless server." >&2
|
|
exit 1
|
|
fi
|
|
if [[ "$mode" == --vnc ]]; then
|
|
command -v x11vnc >/dev/null || { echo "Install x11vnc, xvfb, and xauth." >&2; exit 1; }
|
|
fi
|
|
|
|
cd "$repo_dir"
|
|
mkdir -p "$output_dir"
|
|
children=()
|
|
cleanup() {
|
|
trap - EXIT INT TERM
|
|
if (( ${#children[@]} )); then
|
|
kill "${children[@]}" 2>/dev/null || true
|
|
wait "${children[@]}" 2>/dev/null || true
|
|
fi
|
|
}
|
|
trap cleanup EXIT
|
|
trap 'exit 130' INT
|
|
trap 'exit 143' TERM
|
|
|
|
# These services control the local simulation. Refuse to reuse unknown servers.
|
|
python3 - <<'PY'
|
|
import socket
|
|
for port in (8080, 8081):
|
|
with socket.socket() as sock:
|
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
try:
|
|
sock.bind(('127.0.0.1', port))
|
|
except OSError:
|
|
raise SystemExit('Port %s is already in use; stop the previous simulation first.' % port)
|
|
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
|
|
try:
|
|
sock.bind(('0.0.0.0', 7777))
|
|
except OSError:
|
|
raise SystemExit('UDP port 7777 is already in use.')
|
|
PY
|
|
SIMULATION_BIND_ADDRESS=127.0.0.1 python3 -u traffic_light_server.py >"$output_dir/traffic.log" 2>&1 &
|
|
children+=("$!")
|
|
SIMULATION_BIND_ADDRESS=127.0.0.1 python3 -u event_server.py >"$output_dir/events.log" 2>&1 &
|
|
children+=("$!")
|
|
python3 - <<'PY'
|
|
import time, urllib.request
|
|
for port, path in ((8080, '/trafficLights/'), (8081, '/tweetCount')):
|
|
for attempt in range(50):
|
|
try:
|
|
with urllib.request.urlopen('http://127.0.0.1:%s%s' % (port, path), timeout=1) as response:
|
|
response.read()
|
|
break
|
|
except OSError:
|
|
time.sleep(.1)
|
|
else:
|
|
raise SystemExit('Backend failed to start; inspect Builds/linux/*.log')
|
|
PY
|
|
: > "$output_dir/server.log"
|
|
"$player" -batchmode -nographics --server \
|
|
--traffic-url http://127.0.0.1:8080 --event-url http://127.0.0.1:8081 \
|
|
-logFile "$output_dir/server.log" >"$output_dir/server-console.log" 2>&1 &
|
|
children+=("$!")
|
|
echo "Simulation server running on port 7777. Logs: $output_dir"
|
|
|
|
if [[ "$mode" != --server ]]; then
|
|
# Wait for UNet to finish loading the scene before connecting the client.
|
|
for ((attempt=0; attempt<100; attempt++)); do
|
|
if grep -q 'Simulation server started' "$output_dir/server.log"; then break; fi
|
|
kill -0 "${children[2]}" 2>/dev/null || exit 1
|
|
sleep .1
|
|
done
|
|
if ! grep -q 'Simulation server started' "$output_dir/server.log"; then
|
|
echo "Server startup timed out; inspect $output_dir/server.log" >&2
|
|
exit 1
|
|
fi
|
|
"$player" --connect 127.0.0.1 -screen-width 1280 -screen-height 800 \
|
|
-screen-fullscreen 0 -force-glcore -logFile "$output_dir/client.log" \
|
|
>"$output_dir/client-console.log" 2>&1 &
|
|
children+=("$!")
|
|
fi
|
|
if [[ "$mode" == --vnc ]]; then
|
|
x11vnc -display "$DISPLAY" -localhost -rfbport 5901 -forever -shared -nopw \
|
|
>"$output_dir/vnc.log" 2>&1 &
|
|
children+=("$!")
|
|
echo "Forward SSH port 5901, then connect your VNC viewer to localhost:5901."
|
|
fi
|
|
echo "Press Ctrl-C to stop the simulation and its services."
|
|
wait -n "${children[@]}"
|