# Minecraft Bedrock Edition module.
#
# itzg/minecraft-bedrock-server is the de-facto community image for the
# Mojang-shipped Linux Bedrock binary. It auto-downloads the binary on
# first container start (license-accepted via EULA=TRUE) and re-pulls on
# version bumps via the VERSION env var.
#
# Bedrock is the iOS / Android / Console / Win10-Edition flavor of
# Minecraft. It speaks RakNet over UDP — TOTALLY DIFFERENT wire protocol
# from Java Edition. Bedrock clients cannot connect to Java servers and
# vice-versa. Run BOTH if your players are mixed-platform; or use the
# GeyserMC translation proxy (out of scope for this module).
#
# No RCON — Bedrock servers don't ship a remote-admin protocol. Admin
# commands go through the in-process console only. Players tab will be
# empty; state tracker has nothing to poll.
#
# Verified scaffolding pattern:
#   - same `auto_update_on_create: false` + placeholder update_providers
#     combination as minecraft-java (see panel/memory/gotchas.md
#     "image-managed module" entry).
#   - `env: SERVER_PORT` / `env: SERVER_PORT_V6` on each port wires the
#     panel-allocated host ports through to the container env, then
#     itzg's entrypoint passes them to the binary. Combined with
#     `network_mode: host`, two Bedrock instances on the same agent
#     allocate unique ports and bind them directly.

id: minecraft-bedrock
name: "Minecraft Bedrock Edition"
version: 0.1.0
authors:
  - panel contributors

supported_modes:
  - docker

runtime:
  docker:
    image: itzg/minecraft-bedrock-server:latest
    # Host networking — Bedrock's UDP RakNet protocol relies on the
    # client speaking directly to the server's published port. Port
    # publishing through Docker's bridge would NAT every Bedrock packet,
    # which RakNet doesn't tolerate well. AMP-like host-net model keeps
    # the packets clean. Multi-instance safety is the panel allocator
    # picking distinct SERVER_PORT values per instance.
    network_mode: host
    browseable_root: /data
    browseable_roots:
      - name: "Server data"
        path: /data
        hint: "worlds/, allowlist.json, permissions.json, server.properties"
    env:
      EULA: "TRUE"
      SERVER_NAME: "Refuge Bedrock"
      GAMEMODE: "survival"          # survival | creative | adventure
      DIFFICULTY: "easy"            # peaceful | easy | normal | hard
      LEVEL_NAME: "level"
      LEVEL_TYPE: "DEFAULT"         # DEFAULT | FLAT | LEGACY
      MAX_PLAYERS: "10"
      ONLINE_MODE: "true"
      ALLOW_CHEATS: "false"
      VIEW_DISTANCE: "10"
      TICK_DISTANCE: "4"
      DEFAULT_PLAYER_PERMISSION_LEVEL: "member"
      TEXTUREPACK_REQUIRED: "false"
      VERSION: "LATEST"
      # Pre-declared so the agent's resolve.go filter lets allocator-derived
      # ports flow through to the container env. itzg honors both SERVER_PORT
      # (IPv4) and SERVER_PORT_V6 (IPv6) — defaults match the manifest port
      # defaults below; agent overrides at create time.
      SERVER_PORT: "19132"
      SERVER_PORT_V6: "19133"
    volumes:
      - { type: volume, name: "panel-$INSTANCE_ID-bedrock", container: "/data" }
      - { target: "$DATA_PATH/logs", container: "/data/logs" }

# Bedrock binds two UDP ports — IPv4 and IPv6. Both are required for
# proper dual-stack listing in Bedrock's server browser. itzg defaults
# 19132 / 19133. The panel allocator picks unique ports from the agent's
# window (e.g. 7000-7999 on princess); the agent injects them as
# SERVER_PORT / SERVER_PORT_V6 env at container-create time.
ports:
  - { name: game,    proto: udp, default: 19132, required: true,  env: SERVER_PORT }
  - { name: game-v6, proto: udp, default: 19133, required: true,  env: SERVER_PORT_V6 }

resources:
  min_ram_mb: 1024
  recommended_ram_mb: 2048

# itzg/minecraft-bedrock-server handles install + version pinning via the
# VERSION env var on first container start — no SteamCMD / GitHub / direct
# flow the panel needs to drive. Same shape as minecraft-java: keep a
# placeholder update_providers entry to satisfy the manifest validator,
# pair with auto_update_on_create:false so the agent doesn't actually run
# it (which would crash on the missing target_path — see
# panel/memory/gotchas.md "image-managed module" pattern).
auto_update_on_create: false
update_providers:
  - id: image-managed
    kind: direct
    url: "https://hub.docker.com/r/itzg/minecraft-bedrock-server"
    target_path: ".panel-image-managed-marker"  # never written; auto-update is suppressed above

# itzg's bedrock image streams the server log to stdout. The format depends
# on the bundled binary's version — in 1.21+ the ready signal is
# "Server started." and join/leave use "Player connected/disconnected".
# Older builds use slightly different phrasing. We grep the broad shape;
# tighten once we observe the live format.
state_sources:
  - type: log_tail
    files:
      - "$DATA_PATH/logs/*.log"
      - "/data/logs/*.log"

events:
  join:
    pattern: 'Player connected: (?P<name>[^,]+), xuid: (?P<xuid>\S+)'
    kind: join
  leave:
    pattern: 'Player disconnected: (?P<name>[^,]+), xuid: (?P<xuid>\S+)'
    kind: leave

# Backup what's recoverable; everything else (binary, libs) is fetched
# fresh on next start.
backup:
  include:
    - "worlds"               # world saves (one dir per LEVEL_NAME)
    - "*.properties"         # server.properties
    - "*.json"               # permissions.json, allowlist.json, etc.
  exclude:
    - "logs"                 # rotates infinitely
    - "premium_cache"        # auto-restored
    - "behavior_packs"       # auto-fetched (mods landing here are operator-managed via Files tab)
    - "resource_packs"       # same
  notes: "World saves + permissions + server.properties (~10-100 MB typical). Bedrock binary fetched fresh by itzg on next start."

# --- 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.
appearance:
  emoji: "🧱"
  grad: "linear-gradient(135deg,#2d6929,#5a9d56)"
