#!/bin/bash # panel-native RuneScape: Dragonwilds entrypoint. # # Contract: # /game — SteamCMD-installed Linux build of Dragonwilds Dedicated # Server (app 4019830). Populated by the panel's SteamCMD # updater sidecar. # /game-saves — RSDragonwilds/Saved/ config + save tree + logs. set -euo pipefail log() { printf '[panel-dragonwilds] %s\n' "$*"; } # ----- stage 1: root-only bootstrap ----- if [[ "$(id -u)" = "0" ]]; then chown -R panel:panel /game /game-saves /home/panel 2>/dev/null || true log "dropping privileges to panel (UID 1000)" exec setpriv --reuid=panel --regid=panel --clear-groups \ --inh-caps=-all --bounding-set=-all \ env \ HOME=/home/panel \ SERVER_NAME="${SERVER_NAME:-panel Dragonwilds}" \ SERVER_PORT="${SERVER_PORT:-7777}" \ OWNER_ID="${OWNER_ID:-}" \ ADMIN_PASSWORD="${ADMIN_PASSWORD:-}" \ DEFAULT_WORLD_NAME="${DEFAULT_WORLD_NAME:-Gielinor}" \ PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \ /entrypoint.sh "$@" fi GAME_DIR=/game SAVE_DIR=/game-saves # --- locate the launcher wrapper --- # Jagex ships RSDragonwildsServer.sh at the install root; it execs the # UE5 shipping binary under RSDragonwilds/Binaries/Linux/. LAUNCHER="${GAME_DIR}/RSDragonwildsServer.sh" FALLBACK="${GAME_DIR}/RSDragonwilds/Binaries/Linux/RSDragonwildsServer-Linux-Shipping" if [[ ! -x "${LAUNCHER}" && ! -x "${FALLBACK}" ]]; then log "ERROR: ${LAUNCHER} not found or not executable." log " Run 'Update' on this server in the panel — that launches a" log " SteamCMD sidecar which installs Dragonwilds (app 4019830)" log " for Linux into this volume via +@sSteamCmdForcePlatformType linux." exit 78 # EX_CONFIG fi # --- persist RSDragonwilds/Saved into /game-saves --- # UE5 writes config + save data under /RSDragonwilds/Saved/. Move # it into the save volume on first discovery and symlink back so SteamCMD # validate can't wipe world data. Idempotent on re-boot. mkdir -p "${SAVE_DIR}/RSDragonwilds" "${GAME_DIR}/RSDragonwilds" if [[ -d "${GAME_DIR}/RSDragonwilds/Saved" && ! -L "${GAME_DIR}/RSDragonwilds/Saved" ]]; then if [[ ! -d "${SAVE_DIR}/RSDragonwilds/Saved" ]]; then mv "${GAME_DIR}/RSDragonwilds/Saved" "${SAVE_DIR}/RSDragonwilds/Saved" else rm -rf "${GAME_DIR}/RSDragonwilds/Saved" fi fi mkdir -p "${SAVE_DIR}/RSDragonwilds/Saved/Config/LinuxServer" ln -sfn "${SAVE_DIR}/RSDragonwilds/Saved" "${GAME_DIR}/RSDragonwilds/Saved" # --- seed DedicatedServer.ini from env on first boot --- # Jagex requires OwnerId + Server Name + Default World Name + Admin Password # to be set. Observed behavior on 0.11: Dragonwilds overwrites an absent # DedicatedServer.ini on first boot with its OWN random-generated values # under the `[/Script/Dominion.DedicatedServerSettings]` section ("Dominion" # is the internal UE5 project name). So the best we can do for first-boot # seeding is to pre-write the file — if it exists the server reads it and # leaves it. We only touch the file when it doesn't already exist. INI="${SAVE_DIR}/RSDragonwilds/Saved/Config/LinuxServer/DedicatedServer.ini" if [[ ! -s "${INI}" ]]; then log "seeding DedicatedServer.ini (first boot)" cat > "${INI}" <}" log " port: ${SERVER_PORT}/udp" trap 'log "SIGTERM received; stopping server"; kill -TERM "${SRV_PID:-0}" 2>/dev/null || true; wait "${SRV_PID:-0}" 2>/dev/null || true; exit 0' TERM INT # Use the Jagex-shipped launcher when present; otherwise exec the shipping # binary directly. `-log` routes UE5 output to stdout. Drop `-NewConsole` # (Windows-only; harmless but noisy on Linux). if [[ -x "${LAUNCHER}" ]]; then exec stdbuf -oL -eL "${LAUNCHER}" -log "-Port=${SERVER_PORT}" & else exec stdbuf -oL -eL "${FALLBACK}" -log "-Port=${SERVER_PORT}" & fi SRV_PID=$! wait "${SRV_PID}"