# DayZ dedicated server module.
#
# Native-Linux binary via SteamCMD app 223350 ("DayZ Server"). App is
# paid content — SteamCMD refuses `+login anonymous` with
# "No subscription". We set `requires_steam_login: true` which makes the
# controller gate updates behind the Steam-login modal; operators sign in
# once with a Steam account that owns DayZ (base game app 221100 — NOT
# the dedicated-server app itself — grants download entitlement).
#
# RCON is BattlEye's proprietary UDP protocol, not Source or WebSocket.
# The panel's new `be_rcon` adapter speaks it natively (MD5-challenge
# login, sequenced commands with ack packets, keep-alive pings).
#
# References:
#   https://community.bistudio.com/wiki/DayZ:Hosting_a_Linux_Server
#   https://www.battleye.com/downloads/BERConProtocol.txt

id: dayz
name: "DayZ"
version: 0.1.0
authors:
  - panel contributors

supported_modes:
  - docker

runtime:
  docker:
    # Built locally from ./Dockerfile. Rebuild with:
    #   docker build -t panel-dayz:latest modules/dayz
    image: panel-dayz:latest
    # Host networking -- container shares the host net namespace, so
    # any port the game/mod 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).
    network_mode: host
    browseable_root: /game-saves
    browseable_roots:
      - name: "Saves & Configs"
        path: /game-saves
        hint: "serverDZ.cfg + profiles/ (logs, bans, RPTs) + mpmissions/ world state"
      - name: "Game Files"
        path: /game
        hint: "DayZServer binary + core keys/, shipped mpmissions, BattlEye/"
    env:
      SERVER_NAME: "panel DayZ"
      SERVER_PORT: "2302"
      BE_PASSWORD: "panel_be"        # BattlEye RCON admin password
      SERVER_PASSWORD: ""            # optional client join password
      CPU_COUNT: "2"                 # -cpuCount= for the server binary
    volumes:
      - { type: volume, name: "panel-$INSTANCE_ID-saves", container: "/game-saves" }
      - { type: volume, name: "panel-$INSTANCE_ID-game",  container: "/game" }
      # Shared DayZ Workshop cache — multiple DayZ instances download and use
      # the same workshop content. Each instance creates @ModName symlinks in
      # its own /game/ pointing at this shared tree, so disk space is saved
      # and one download serves N instances.
      - { type: volume, name: "panel-dayz-workshop",      container: "/game/steamapps/workshop" }
      - { target: "$DATA_PATH/logs", container: "/game-saves/logs" }

# DayZ ports:
#   2302/udp — primary game + query (Bohemia's convention: game port and
#              Steam query are the SAME port, unlike Source-engine games)
#   2303/udp — additional-instance offset (+1)
#   2304/udp — additional-instance offset (+2)
#   2305/udp — additional-instance offset (+3)
#   27016/udp — alternate Steam-query port (some community servers expose)
#   2310/udp  — BattlEye RCON (BE_PORT + 1 by convention; configurable)
ports:
  - { name: game,     proto: udp, default: 2302, required: true, env: SERVER_PORT }  # entrypoint reads SERVER_PORT (declared in docker env); query shares this port
  - { name: reserved, proto: udp, default: 2303, required: false }
  - { name: battleye, proto: udp, default: 2304, required: false }   # client BE anti-cheat traffic
  - { name: rcon,     proto: udp, default: 2305, internal: true }    # BE RCON (AMP convention)

resources:
  min_ram_mb: 4096
  recommended_ram_mb: 8192

# Per-instance generated RCON secret. The agent generates a random
# 24-byte token at create time (pkg/module GenerateSecrets), which
# overrides the env default for BE_PASSWORD below — so every instance
# gets a unique password. The weak env default only applies to
# containers launched outside the panel.
secrets:
  - name: BE_PASSWORD
    description: "DayZ BattlEye RCON password — generated per instance"
    generated: true

rcon:
  adapter: be_rcon
  host_port: rcon
  auth: password
  password_secret: BE_PASSWORD
  # Legacy fallback only (pre-generated-secret instances). New instances
  # always get the generated BE_PASSWORD secret above.
  password_literal: "panel_be"
  commands:
    list: "players"
    broadcast: "say -1 {msg}"
    kick: "kick {player}"
    ban: "ban {player}"
    save: "#shutdown"   # DayZ has no "save" command; use shutdown as a placeholder
    shutdown: "#shutdown"

state_sources:
  - type: rcon
    command: "players"
    every: 60s

# Log-line event patterns (RE2). Patterns observed from a real DayZ
# 1.24 server log; tighten after smoke test if needed.
events:
  join:
    pattern: 'Player "(?P<name>[^"]+)" is connected'
    kind: join
  leave:
    pattern: 'Player "(?P<name>[^"]+)" disconnected'
    kind: leave
  chat:
    pattern: 'Chat\("(?P<name>[^"]+)"\): (?P<msg>.+)'
    kind: chat

update_providers:
  - id: stable
    kind: steamcmd
    app_id: "223350"
    install_path: /game
    # DayZ is paid content. Anonymous SteamCMD returns "No subscription".
    # Operator logs in once via the panel's Steam-login modal; the cached
    # SSFN blob (via the shared panel-steamcmd-auth volume) makes
    # subsequent updates skip the 2FA prompt.
    requires_steam_login: true

# --- 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: '/Mission read from bank|BattlEye Server: Initialized|Server World: Initialized|NetServer: (:\d+)?started|Creating a new world/i'
appearance:
  emoji: "🧟"
  grad: "linear-gradient(135deg,#2d3e2e,#6b7f56)"
  art: "/game-art/dayz.jpg"
  steam: "221100"
