# VEIN — panel-native dedicated server module.
#
# Native Linux dedicated server. UE4-class survival game. SteamCMD app
# 2131400 (the DEDICATED SERVER app id — distinct from the game app id
# 1857950, which the server reports itself as to Steam via SteamAppId).
# Anonymous Steam login works. Admin console is stdin-only (no network
# RCON), so the panel drives the console via the stdio adapter — same
# model as Enshrouded / Sons of the Forest.
#
# Reference: https://github.com/CubeCoders/AMPTemplates (vein.kvp)

id: vein
name: "VEIN"
version: 0.1.0
authors:
  - panel contributors

supported_modes:
  - docker

runtime:
  docker:
    # Built locally from ./Dockerfile. Rebuild with:
    #   docker build -t panel-vein:latest modules/vein
    image: panel-vein:latest
    # Host networking -- container shares the host net namespace, so
    # any port the game binds is directly on the LAN. AMP-like model.
    # Multi-instance safety comes from env-driven per-instance ports
    # (panel allocator + env: mapping on each ports entry below).
    network_mode: host
    browseable_root: /game-saves
    browseable_roots:
      - name: "Saves & Configs"
        path: /game-saves
        hint: "Vein/Saved/ savegame data + Config/LinuxServer/Game.ini"
      - name: "Game Files"
        path: /game
        hint: "Vein/Binaries/Linux/ server binary + steamclient libs"
    # Pre-declare every env key that any config_value below maps to. The
    # agent's resolve.go ONLY propagates config_values whose key is already
    # present in `docker.env` — keys not listed here get silently filtered
    # out. Empty-string defaults mean "leave Game.ini alone" (the entrypoint
    # stamps only non-empty values, so a recreate with empty env preserves
    # whatever the operator set previously via the Config/Files tab).
    env:
      # Steamworks client runtime init context — the dedicated-server app
      # (2131400) reports itself to Steam as VEIN (1857950). AMP sets this
      # too; without it the server's Steam socket init / master-server
      # listing fails.
      STEAM_APP_ID: "1857950"

      # --- Per-instance ports ---
      # MUST be pre-declared here or resolve.go silently drops the allocator's
      # injected values (it only overrides docker.env keys that already exist),
      # and the entrypoint falls back to these defaults → two VEIN servers on
      # one host both bind 7777 and collide. The `env:` on each ports entry
      # below maps the panel-allocated HOST port into these vars at start.
      GAME_PORT: "7777"
      QUERY_PORT: "27015"
      RCON_PORT: "7878"

      # --- Identity & access (stamped into Game.ini sections) ---
      SERVER_NAME: ""
      SERVER_DESCRIPTION: ""
      SERVER_PASSWORD: ""
      MAX_PLAYERS: ""
      SERVER_PUBLIC: ""        # bPublic — list on the public browser
      HEARTBEAT_INTERVAL: ""
      ENABLE_VAC: ""           # bVACEnabled under [OnlineSubsystemSteam]
      SHOW_SCOREBOARD_BADGES: ""
    volumes:
      - { type: volume, name: "panel-$INSTANCE_ID-saves", container: "/game-saves" }
      - { type: volume, name: "panel-$INSTANCE_ID-game",  container: "/game" }
      - { target: "$DATA_PATH/logs", container: "/game-saves/logs" }

  # Multi-instance safety: `env:` tells the agent which container env var to
  # set with the allocated host port. The entrypoint reads these to build
  # VEIN's `-Port` / `-QueryPort` launch flags so two VEIN servers on the
  # same agent get distinct, non-colliding sockets (avoids the Valheim
  # hardcoded-port collision class of bug).
ports:
  - { name: game,  proto: udp, default: 7777,  required: true, env: GAME_PORT }
  - { name: query, proto: udp, default: 27015, required: true, env: QUERY_PORT }
  # VEIN declares an RCON port but the admin path is STDIO; we expose it for
  # completeness / firewalling but do NOT wire a network rcon adapter to it.
  - { name: rcon,  proto: udp, default: 7878,  internal: true, env: RCON_PORT }

resources:
  min_ram_mb: 4096
  recommended_ram_mb: 8192

rcon:
  # VEIN admin console is stdin-only (no network RCON). The stdio adapter
  # auto-enables container OpenStdin (agent resolve.go) and the Console tab
  # "Send" box writes commands to the server process's stdin. Output comes
  # back via the docker-logs live tail, not a correlated reply.
  adapter: stdio
# Log-derived player events. Regexes converted from CubeCoders'
# AMPTemplates (vein.kvp) — .NET (?<n>) syntax -> Go (?P<n>).
# Sourced-from-template; not yet exercised against a live client.
events:
  join:
    pattern: 'LogNet: Login request: (?:\?Password=[^?]*)?\?Name=(?P<name>.+?)\?\?ID=(?P<id>\d+)\?Ticket='
    kind: join
  leave:
    pattern: 'LogNet: UChannel::CleanUp: ChIndex == \d+\. Closing connection\..*RemoteAddr: (?P<id>\d+):\d+'
    kind: leave


update_providers:
  - id: stable
    kind: steamcmd
    app_id: "2131400"
    install_path: /game

# --- Manifest-driven UI metadata (WI-07) --------------------------
# Consumed by the CONTROLLER/dashboard only (the controller loads its
# own ./modules copy at startup); the agent ignores these at runtime.
# ready_pattern is a JavaScript regex (slash-delimited when it needs
# flags) moved verbatim from the dashboard's READY_PATTERNS map.
ready_pattern: '/LogRamjetNetworking: Steamworks server initialized with SteamID \d+|LogRamjetNetworking: Heartbeating with IP /i'
appearance:
  emoji: "🩸"
  grad: "linear-gradient(135deg,#2a0a0a,#7a1010)"
  art: "/game-art/vein.jpg"
  steam: "1857950"
