#!/bin/bash
# Derive one seat's full environment and exec the live stack.
# Seat N: display :1N, signaling 8144+N, ICE 40000+200(N-1)..+199, private
# prefix, capture/control files, pulse sink, and logs.
set -euo pipefail

SEAT=${1:?usage: w3cs-seat-launch.sh <seat-number 1..9>}
case "$SEAT" in
  [1-9]) ;;
  *) echo "seat must be 1..9" >&2; exit 2 ;;
esac
IDX=$((SEAT - 1))

export W3_D3D9_DISPLAY=":1$SEAT"
export W3CS_RELAY_PORT=$((8144 + SEAT))
export W3CS_ICE_MIN=$((40000 + 200 * IDX))
export W3CS_ICE_MAX=$((40199 + 200 * IDX))
export W3_D3D9_CAPTURE_FILE="/tmp/w3cs-command-stream-seat$SEAT.bin"
export W3_D3D9_STREAM_FILE="Z:\\tmp\\w3cs-command-stream-seat$SEAT.bin"
export W3CS_GAME_CONTROL="/tmp/w3cs-game-control-seat$SEAT"
export W3_D3D9_CONTROL_FILE="Z:\\tmp\\w3cs-game-control-seat$SEAT"
export W3CS_SEAT_STATE="/tmp/w3cs-seat-state-seat$SEAT.json"
export WINEPREFIX="/opt/war3-runtime/classic/prefix-seat$SEAT"
export W3CS_PREFIX64="/opt/war3-runtime/classic-131/prefix64-seat$SEAT"
export W3CS_PULSE_SINK="w3cs$SEAT"
# The shared pulse daemon is its own systemd unit (w3cs-pulse), outside
# every seat's cgroup, so seat restarts can never silence other seats.
export PULSE_SERVER="unix:/run/w3cs-pulse/native"
export W3CS_LOG_SUFFIX="-seat$SEAT"
# One raster thread per seat: with rasterization disabled llvmpipe is nearly
# idle, and seat count matters more than per-seat headroom on this box.
export LP_NUM_THREADS=${LP_NUM_THREADS:-1}

# Old engines (1.14/1.24) ignore every resolution stamp and size their outer
# window to exactly 0.75 x desktop, with the D3D backbuffer as its client
# area (frame 8px wide, 34px tall; measured 1920x1440 -> 1432x1046 and
# 1024x768 -> 760x542). Sizing the seat's Xvfb root so that this law lands
# on 1024x768 keeps every lane at the session resolution without touching
# the engines: 0.75 x 1376 = 1032 outer -> 1024 client. 1.28.5 reads the
# registry stamp and fits fine on the smaller root.
export W3_D3D9_DISPLAY_WIDTH=${W3_D3D9_DISPLAY_WIDTH:-1376}
export W3_D3D9_DISPLAY_HEIGHT=${W3_D3D9_DISPLAY_HEIGHT:-1070}

# Seat 3 is the encoder lab seat: quantized world geometry behind a
# per-slice coordinate-magnitude gate (peak |xyz| >= 16). WC3's UI plane
# (0..0.8 coords — menus, minimap square, cursor quad) always fails the
# gate and ships byte-identical classic records; the two earlier failures
# and the root cause are documented in RELEASE-PLAN.md. Verified sessions
# target this seat with ?labSeat=3; seats 1-2 stay classic until the
# user's feel-test passes.
# Promoted to ALL seats after lab verification and the user's feel-tests
# (2026-08-20):
# - W3CS_QUANT: world-geometry position deltas quantized to int16 steps of
#   1/64 behind a per-slice coordinate-magnitude gate; the UI plane and
#   cursor stay byte-exact. Frames ~ -35-47% encoded.
# - W3CS_TEXDELTA: repeat texture uploads ship as CRC-gated sparse XOR
#   deltas (fog-style content is ~99.9% identical between uploads).
#   Recurring texture wire ~ -85%; lossless; CRC mismatch = skip + repair.
export W3CS_QUANT=1
export W3CS_TEXDELTA=1
# - W3CS_OCTA: changed near-unit normals ship as one int8 octahedral
#   (u, v) point instead of three float16 deltas (quant mode bit 8).
#   Measured on full same-replay games: total encoded wire -13.4%/frame,
#   zero hash mismatches, lighting visually identical. Promoted to all
#   seats after the user's feel test (2026-08-20 late).
export W3CS_OCTA=1
# - W3CS_BLOBREF: geometry blobs re-defined with identical content within
#   8 captured frames ship as 24-byte references (opcode 37) instead of
#   full quant records; the client provably retains draw-touched blobs for
#   16 applied frames, so a reference can never miss (applied is a subset
#   of captured). A/B on same-replay 8X slices: total encoded wire
#   -11.4%/frame (32.4 -> 28.7 KiB), refs cost 0.4% of wire. Promoted to
#   all seats 2026-08-20.
export W3CS_BLOBREF=1
# - Geometry GOP 8 (anchor + 7 chained dependents, default was 4): frames
#   ship on reliable in-order planes and recovery keyframes force an
#   anchor, so a longer GOP costs nothing in resync latency — it only
#   halves the anchor overhead. A/B on same-replay 8X slices: total
#   encoded wire -12.6%/frame (28.7 -> 25.1 KiB). Promoted 2026-08-20.
export W3_D3D9_GEOMETRY_GOP=8
# Shared-memory capture ring on tmpfs: the proxy->relay byte stream skips
# the disk entirely (the append file remains the fallback and the CRIU
# compatibility path; unset both to revert). Same file, two views: the
# relay maps the Linux path, the game maps it through wine's Z: drive.
# W3CS_RING_DISABLE=1 (a systemd drop-in on one seat) reverts that seat to
# the append file so a session's raw command stream can be captured for
# offline analysis - compression sweeps, record-redundancy studies.
if [ "${W3CS_RING_DISABLE:-0}" != 1 ]; then
  export W3CS_RING_FILE="/dev/shm/w3cs-ring-seat$SEAT"
  export W3_D3D9_RING_FILE="Z:\\dev\\shm\\w3cs-ring-seat$SEAT"
else
  # A stale ring from a previous ring-enabled boot still carries a valid
  # magic; any process that finds ring env baked into an older image
  # would happily write into it while nothing reads. Remove it so every
  # capture-tee byte provably flows through the append file.
  rm -f "/dev/shm/w3cs-ring-seat$SEAT"
fi

exec /home/ubuntu/w3cs-lab/lab-live.sh
