8a94ffd58f
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
400 lines
18 KiB
Bash
400 lines
18 KiB
Bash
#!/bin/bash
|
|
# panel-native Conan Exiles entrypoint.
|
|
#
|
|
# Contract:
|
|
# /game — SteamCMD-installed Windows build of Conan Exiles Dedicated
|
|
# Server (populated by the panel's SteamCMD updater sidecar).
|
|
# If missing, exit with EX_CONFIG and a helpful message.
|
|
# /game-saves — ConanSandbox/Saved/ tree (world data) + Config/ INIs.
|
|
#
|
|
# Stage 1 runs as root: chown volumes (SteamCMD wrote as root), nuke stale
|
|
# X lock, symlink /Logs + ConanSandbox/Saved into the save volume, then drop
|
|
# to the `panel` user via setpriv. Wine refuses to run as root.
|
|
#
|
|
# Stage 2 (panel user): stamp config_values env vars into [ServerSettings]
|
|
# of ServerSettings.ini, then exec the dedicated server under Wine + Xvfb.
|
|
|
|
set -euo pipefail
|
|
|
|
log() { printf '[panel-conan] %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
|
|
|
|
# UE4/UE5 under Wine writes to Z:\Logs (= /Logs). Pre-create as symlink
|
|
# into save volume so logs survive container recreate + show up in Files
|
|
# tab.
|
|
mkdir -p /game-saves/ConanLogs
|
|
chown -R panel:panel /game-saves/ConanLogs
|
|
if [[ ! -e /Logs || -L /Logs ]]; then
|
|
ln -sfn /game-saves/ConanLogs /Logs
|
|
fi
|
|
|
|
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 \
|
|
WINEPREFIX=/home/panel/.wine \
|
|
WINEDEBUG=-all \
|
|
STEAM_APP_ID="${STEAM_APP_ID:-440900}" \
|
|
SteamAppId="${STEAM_APP_ID:-440900}" \
|
|
SERVER_NAME="${SERVER_NAME:-panel Conan Exiles}" \
|
|
SERVER_PASSWORD="${SERVER_PASSWORD:-}" \
|
|
ADMIN_PASSWORD="${ADMIN_PASSWORD:-}" \
|
|
RCON_PASSWORD="${RCON_PASSWORD:-panel_rcon}" \
|
|
MAX_PLAYERS="${MAX_PLAYERS:-40}" \
|
|
SERVER_REGION="${SERVER_REGION:-1}" \
|
|
SERVER_COMMUNITY="${SERVER_COMMUNITY:-0}" \
|
|
MAX_NUDITY="${MAX_NUDITY:-0}" \
|
|
SERVER_MAP="${SERVER_MAP:-/Game/Maps/ConanSandbox/ConanSandbox}" \
|
|
CUSTOM_MAP="${CUSTOM_MAP:-}" \
|
|
ENABLE_BATTLEYE="${ENABLE_BATTLEYE:-False}" \
|
|
ENABLE_VAC="${ENABLE_VAC:-True}" \
|
|
PVP_ENABLED="${PVP_ENABLED:-}" \
|
|
AVATARS_ENABLED="${AVATARS_ENABLED:-}" \
|
|
CONTAINERS_IGNORE_OWNERSHIP="${CONTAINERS_IGNORE_OWNERSHIP:-}" \
|
|
CAN_DAMAGE_PLAYER_OWNED_STRUCTURES="${CAN_DAMAGE_PLAYER_OWNED_STRUCTURES:-}" \
|
|
DYNAMIC_BUILDING_DAMAGE="${DYNAMIC_BUILDING_DAMAGE:-}" \
|
|
FRIENDLY_FIRE_DAMAGE="${FRIENDLY_FIRE_DAMAGE:-}" \
|
|
PLAYER_XP_RATE="${PLAYER_XP_RATE:-}" \
|
|
PLAYER_XP_KILL="${PLAYER_XP_KILL:-}" \
|
|
PLAYER_XP_HARVEST="${PLAYER_XP_HARVEST:-}" \
|
|
PLAYER_XP_CRAFT="${PLAYER_XP_CRAFT:-}" \
|
|
PLAYER_XP_TIME="${PLAYER_XP_TIME:-}" \
|
|
PLAYER_DAMAGE_MULTIPLIER="${PLAYER_DAMAGE_MULTIPLIER:-}" \
|
|
PLAYER_DAMAGE_TAKEN="${PLAYER_DAMAGE_TAKEN:-}" \
|
|
PLAYER_HEALTH_REGEN="${PLAYER_HEALTH_REGEN:-}" \
|
|
PLAYER_STAMINA_COST="${PLAYER_STAMINA_COST:-}" \
|
|
PLAYER_SPRINT_SPEED="${PLAYER_SPRINT_SPEED:-}" \
|
|
PLAYER_MOVEMENT_SPEED="${PLAYER_MOVEMENT_SPEED:-}" \
|
|
PLAYER_ENCUMBRANCE="${PLAYER_ENCUMBRANCE:-}" \
|
|
NPC_DAMAGE_MULTIPLIER="${NPC_DAMAGE_MULTIPLIER:-}" \
|
|
NPC_DAMAGE_TAKEN="${NPC_DAMAGE_TAKEN:-}" \
|
|
NPC_HEALTH_MULTIPLIER="${NPC_HEALTH_MULTIPLIER:-}" \
|
|
NPC_RESPAWN_MULTIPLIER="${NPC_RESPAWN_MULTIPLIER:-}" \
|
|
NPC_MAX_SPAWN_CAP="${NPC_MAX_SPAWN_CAP:-}" \
|
|
STRUCTURE_DAMAGE_MULTIPLIER="${STRUCTURE_DAMAGE_MULTIPLIER:-}" \
|
|
STRUCTURE_HEALTH_MULTIPLIER="${STRUCTURE_HEALTH_MULTIPLIER:-}" \
|
|
LANDCLAIM_RADIUS_MULTIPLIER="${LANDCLAIM_RADIUS_MULTIPLIER:-}" \
|
|
AVATAR_DOME_DURATION="${AVATAR_DOME_DURATION:-}" \
|
|
AVATAR_DOME_DAMAGE="${AVATAR_DOME_DAMAGE:-}" \
|
|
GAME_PORT="${GAME_PORT:-7777}" \
|
|
PINGER_PORT="${PINGER_PORT:-7778}" \
|
|
QUERY_PORT="${QUERY_PORT:-27015}" \
|
|
RCON_PORT="${RCON_PORT:-25575}" \
|
|
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
|
|
/entrypoint.sh "$@"
|
|
fi
|
|
|
|
GAME_DIR=/game
|
|
SAVE_DIR=/game-saves
|
|
|
|
# --- edition-aware launch mode ---
|
|
# Enhanced (UE5) is the native-Linux depot — direct exec, no Wine.
|
|
# Legacy (UE4) is Windows-only — Wine + Xvfb.
|
|
# Drives binary path, fallback find pattern, config subdir, prefix bootstrap,
|
|
# SIGTERM trap, and the launch line further below.
|
|
case "${EDITION:-enhanced}" in
|
|
legacy)
|
|
LAUNCH_MODE=wine
|
|
CANDIDATES=("${GAME_DIR}/ConanSandbox/Binaries/Win64/ConanSandboxServer-Win64-Shipping.exe")
|
|
CONFIG_SUBDIR=WindowsServer
|
|
;;
|
|
*)
|
|
LAUNCH_MODE=native
|
|
CANDIDATES=("${GAME_DIR}/ConanSandbox/Binaries/Linux/ConanSandboxServer-Linux-Shipping")
|
|
CONFIG_SUBDIR=LinuxServer
|
|
;;
|
|
esac
|
|
BIN_BASENAME=$(basename "${CANDIDATES[0]}")
|
|
log "edition: ${EDITION:-enhanced} launch mode: ${LAUNCH_MODE} config subdir: ${CONFIG_SUBDIR}"
|
|
|
|
# --- locate the server binary ---
|
|
# Enhanced UE5 Linux depot ships the binary at
|
|
# /game/ConanSandbox/Binaries/Linux/ConanSandboxServer-Linux-Shipping (ELF).
|
|
# Legacy UE4 Windows depot ships
|
|
# /game/ConanSandbox/Binaries/Win64/ConanSandboxServer-Win64-Shipping.exe (PE).
|
|
# Mod loading happens via ServerSettings.ini's ServerModList= key (populated
|
|
# by the panel's Mods tab) AND ConanSandbox/Mods/modlist.txt — Conan reads both.
|
|
DEDI_EXE=""
|
|
for c in "${CANDIDATES[@]}"; do
|
|
if [[ -f "$c" ]]; then
|
|
DEDI_EXE="$c"
|
|
break
|
|
fi
|
|
done
|
|
if [[ -z "${DEDI_EXE}" ]]; then
|
|
found=$(find "${GAME_DIR}" -maxdepth 6 -iname "${BIN_BASENAME}" -type f 2>/dev/null | head -1 || true)
|
|
if [[ -n "${found}" ]]; then
|
|
DEDI_EXE="${found}"
|
|
fi
|
|
fi
|
|
if [[ -z "${DEDI_EXE}" ]]; then
|
|
log "ERROR: ${BIN_BASENAME} not found under ${GAME_DIR}."
|
|
log " Run 'Update' on this server in the panel — that launches a"
|
|
log " SteamCMD sidecar which installs Conan Exiles into this volume"
|
|
log " for the selected edition (${EDITION:-enhanced})."
|
|
exit 78 # EX_CONFIG
|
|
fi
|
|
log "found server binary: ${DEDI_EXE}"
|
|
|
|
# --- persist ConanSandbox/Saved into /game-saves ---
|
|
# UE4/UE5 writes world saves + config INIs under <GameRoot>/ConanSandbox/Saved/.
|
|
# Move to save volume on first boot + symlink back, so SteamCMD validate
|
|
# can't wipe world data. Idempotent on subsequent boots.
|
|
mkdir -p "${SAVE_DIR}/ConanSandbox"
|
|
if [[ -d "${GAME_DIR}/ConanSandbox/Saved" && ! -L "${GAME_DIR}/ConanSandbox/Saved" ]]; then
|
|
if [[ ! -d "${SAVE_DIR}/ConanSandbox/Saved" ]]; then
|
|
mv "${GAME_DIR}/ConanSandbox/Saved" "${SAVE_DIR}/ConanSandbox/Saved"
|
|
else
|
|
rm -rf "${GAME_DIR}/ConanSandbox/Saved"
|
|
fi
|
|
fi
|
|
mkdir -p "${SAVE_DIR}/ConanSandbox/Saved/Config/${CONFIG_SUBDIR}"
|
|
ln -sfn "${SAVE_DIR}/ConanSandbox/Saved" "${GAME_DIR}/ConanSandbox/Saved"
|
|
|
|
# First-time native boot after Wine: if WindowsServer/ has config and
|
|
# LinuxServer/ does not yet, copy ServerSettings.ini + Engine.ini + Game.ini
|
|
# across so operator-tuned values survive the Wine -> native cut-over. Wine
|
|
# path is untouched; both dirs coexist.
|
|
if [[ "${LAUNCH_MODE}" = native ]]; then
|
|
WIN_CFG_DIR="${SAVE_DIR}/ConanSandbox/Saved/Config/WindowsServer"
|
|
LINUX_CFG_DIR="${SAVE_DIR}/ConanSandbox/Saved/Config/LinuxServer"
|
|
mkdir -p "${LINUX_CFG_DIR}"
|
|
for f in ServerSettings.ini Engine.ini Game.ini; do
|
|
if [[ -f "${WIN_CFG_DIR}/${f}" && ! -f "${LINUX_CFG_DIR}/${f}" ]]; then
|
|
log "migrating ${f} from WindowsServer/ to LinuxServer/ (first native boot)"
|
|
cp -a "${WIN_CFG_DIR}/${f}" "${LINUX_CFG_DIR}/${f}"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# OSS / Engine.ini: intentionally left alone.
|
|
#
|
|
# Empirically (see reference_conan_oss_steam_impossible.md): Conan Exiles
|
|
# Enhanced (UE5) native Linux dedi cannot be coerced into OSS=Steam without
|
|
# breaking the socket bind. AMP's Conan01 instance on figaro runs the same
|
|
# build with OSS=Null, no Engine.ini, no steam_appid.txt, and no
|
|
# ~/.steam/sdk64/steamclient.so symlink — and we now do the same. Engine
|
|
# default is Null, which binds IpNetDriver cleanly. Direct-IP join works;
|
|
# Steam server-browser listing is not achievable on this build.
|
|
#
|
|
# SteamAppId env var is already exported in stage 1 — that's enough for the
|
|
# Steamworks Game Server API to identify itself without a steam_appid.txt
|
|
# file on disk.
|
|
|
|
# --- stamp config_values env into ServerSettings.ini ---
|
|
# Each non-empty env value is written under [ServerSettings] (replace if the
|
|
# key already exists, append if not). Empty values are SKIPPED so operator
|
|
# manual edits to ServerSettings.ini via the Files tab survive boot. The
|
|
# panel UI's Config tab → Save → recreate-with-env path is the canonical
|
|
# way to mutate INI values; direct file edits are for fields the panel
|
|
# doesn't expose.
|
|
INI="${SAVE_DIR}/ConanSandbox/Saved/Config/${CONFIG_SUBDIR}/ServerSettings.ini"
|
|
if [[ ! -f "${INI}" ]]; then
|
|
log "ServerSettings.ini missing — initializing with [ServerSettings] header"
|
|
printf '[ServerSettings]\n' > "${INI}"
|
|
fi
|
|
if ! grep -qE '^\[ServerSettings\]' "${INI}"; then
|
|
log "ServerSettings.ini lacked [ServerSettings] header — prepending"
|
|
printf '[ServerSettings]\n' > "${INI}.new"
|
|
cat "${INI}" >> "${INI}.new"
|
|
mv "${INI}.new" "${INI}"
|
|
fi
|
|
|
|
# set_ini_kv KEY VALUE: write/replace KEY=VALUE under [ServerSettings].
|
|
# Skip on empty value. Idempotent. Tolerates `&` and `\` in values via the
|
|
# safe_value escape (sed RHS replacement metachars).
|
|
set_ini_kv() {
|
|
local key="$1" value="$2"
|
|
if [[ -z "${value}" ]]; then return 0; fi
|
|
local safe_value
|
|
safe_value=$(printf '%s' "${value}" | sed -e 's/[\\&|]/\\&/g')
|
|
if grep -qE "^${key}=" "${INI}"; then
|
|
sed -i "s|^${key}=.*|${key}=${safe_value}|" "${INI}"
|
|
else
|
|
sed -i "/^\[ServerSettings\]/a ${key}=${safe_value}" "${INI}"
|
|
fi
|
|
}
|
|
|
|
# Resolve the {{CUSTOM_MAP}} sentinel: if Map is set to "Custom" via the UI
|
|
# the panel passes SERVER_MAP="{{CUSTOM_MAP}}" or "{{CustomMap}}" — swap in
|
|
# the operator's CUSTOM_MAP value (or fall back to Exiled Lands if blank).
|
|
case "${SERVER_MAP}" in
|
|
"{{CUSTOM_MAP}}"|"{{CustomMap}}")
|
|
if [[ -n "${CUSTOM_MAP}" ]]; then
|
|
log "Map set to Custom; resolving to ${CUSTOM_MAP}"
|
|
SERVER_MAP="${CUSTOM_MAP}"
|
|
else
|
|
log "WARNING: Map set to Custom but CUSTOM_MAP is empty; falling back to Exiled Lands"
|
|
SERVER_MAP="/Game/Maps/ConanSandbox/ConanSandbox"
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
log "stamping operator config_values into ${INI}"
|
|
|
|
# Identity
|
|
set_ini_kv "ServerName" "${SERVER_NAME}"
|
|
set_ini_kv "ServerPassword" "${SERVER_PASSWORD}"
|
|
set_ini_kv "AdminPassword" "${ADMIN_PASSWORD}"
|
|
set_ini_kv "MaxPlayers" "${MAX_PLAYERS}"
|
|
set_ini_kv "serverRegion" "${SERVER_REGION}"
|
|
set_ini_kv "ServerCommunity" "${SERVER_COMMUNITY}"
|
|
set_ini_kv "MaxNudity" "${MAX_NUDITY}"
|
|
|
|
# Anti-cheat
|
|
set_ini_kv "IsBattlEyeEnabled" "${ENABLE_BATTLEYE}"
|
|
set_ini_kv "IsVACEnabled" "${ENABLE_VAC}"
|
|
|
|
# PvP / world
|
|
set_ini_kv "PVPEnabled" "${PVP_ENABLED}"
|
|
set_ini_kv "AvatarsEnabled" "${AVATARS_ENABLED}"
|
|
set_ini_kv "ContainersIgnoreOwnership" "${CONTAINERS_IGNORE_OWNERSHIP}"
|
|
set_ini_kv "CanDamagePlayerOwnedStructures" "${CAN_DAMAGE_PLAYER_OWNED_STRUCTURES}"
|
|
set_ini_kv "DynamicBuildingDamage" "${DYNAMIC_BUILDING_DAMAGE}"
|
|
set_ini_kv "FriendlyFireDamageMultiplier" "${FRIENDLY_FIRE_DAMAGE}"
|
|
|
|
# XP rates
|
|
set_ini_kv "PlayerXPRateMultiplier" "${PLAYER_XP_RATE}"
|
|
set_ini_kv "PlayerXPKillMultiplier" "${PLAYER_XP_KILL}"
|
|
set_ini_kv "PlayerXPHarvestMultiplier" "${PLAYER_XP_HARVEST}"
|
|
set_ini_kv "PlayerXPCraftMultiplier" "${PLAYER_XP_CRAFT}"
|
|
set_ini_kv "PlayerXPTimeMultiplier" "${PLAYER_XP_TIME}"
|
|
|
|
# Player tuning
|
|
set_ini_kv "PlayerDamageMultiplier" "${PLAYER_DAMAGE_MULTIPLIER}"
|
|
set_ini_kv "PlayerDamageTakenMultiplier" "${PLAYER_DAMAGE_TAKEN}"
|
|
set_ini_kv "PlayerHealthRegenSpeedScale" "${PLAYER_HEALTH_REGEN}"
|
|
set_ini_kv "PlayerStaminaCostMultiplier" "${PLAYER_STAMINA_COST}"
|
|
set_ini_kv "PlayerSprintSpeedScale" "${PLAYER_SPRINT_SPEED}"
|
|
set_ini_kv "PlayerMovementSpeedScale" "${PLAYER_MOVEMENT_SPEED}"
|
|
set_ini_kv "PlayerEncumbranceMultiplier" "${PLAYER_ENCUMBRANCE}"
|
|
|
|
# NPC tuning
|
|
set_ini_kv "NPCDamageMultiplier" "${NPC_DAMAGE_MULTIPLIER}"
|
|
set_ini_kv "NPCDamageTakenMultiplier" "${NPC_DAMAGE_TAKEN}"
|
|
set_ini_kv "NPCHealthMultiplier" "${NPC_HEALTH_MULTIPLIER}"
|
|
set_ini_kv "NPCRespawnMultiplier" "${NPC_RESPAWN_MULTIPLIER}"
|
|
set_ini_kv "NPCMaxSpawnCapMultiplier" "${NPC_MAX_SPAWN_CAP}"
|
|
|
|
# Structures / land claim
|
|
set_ini_kv "StructureDamageMultiplier" "${STRUCTURE_DAMAGE_MULTIPLIER}"
|
|
set_ini_kv "StructureHealthMultiplier" "${STRUCTURE_HEALTH_MULTIPLIER}"
|
|
set_ini_kv "LandClaimRadiusMultiplier" "${LANDCLAIM_RADIUS_MULTIPLIER}"
|
|
set_ini_kv "AvatarDomeDurationMultiplier" "${AVATAR_DOME_DURATION}"
|
|
set_ini_kv "AvatarDomeDamageMultiplier" "${AVATAR_DOME_DAMAGE}"
|
|
|
|
# --- Steam OSS fix — INCOMPLETE, currently disabled ---
|
|
# Live experiment on conan-1 (2026-05-10) showed:
|
|
# 1. Adding DefaultPlatformService=Steam to Engine.ini alone is a no-op:
|
|
# Steam SDK reports "[STEAM] disabled" because the Windows binary can't
|
|
# locate steamclient64.dll (Funcom's dedi-server depot ships these at
|
|
# /game root, not under ConanSandbox/Binaries/Win64/).
|
|
# 2. Copying steamclient*.dll + tier0_s*.dll + vstdlib_s*.dll +
|
|
# steamwebrtc*.dll + a steam_appid.txt (440900) into the binary dir
|
|
# makes the SDK initialize successfully:
|
|
# LogOnline: STEAM: [AppId: 440900] Game Server API initialized 1
|
|
# LogOnline: OSS: Created online subsystem instance for: STEAM
|
|
# 3. BUT once Steam OSS comes up under Wine, the engine hangs the
|
|
# GameThread within ~80s, never binds the game port (8010 UDP),
|
|
# and LogServerStats reports "NetDriver is null". Pre-fix logs had
|
|
# none of these symptoms (server bound + responded to A2S fine, just
|
|
# couldn't accept real-client joins past encryption handshake).
|
|
# Net effect: enabling Steam OSS via Engine.ini + DLL drops trades one
|
|
# failure mode (handshake reject) for a worse one (no NetDriver at all).
|
|
# Leaving the original Engine.ini untouched until we find the correct
|
|
# NetDriverDefinitions / SteamSockets-disable knob that lets Steam OSS
|
|
# coexist with a working IpNetDriver under Wine.
|
|
#
|
|
# See session log 2026-05-10 for full investigation.
|
|
|
|
# --- Wine prefix bootstrap (first boot only, legacy/Wine path only). xvfb-run
|
|
# gives Wine a guaranteed-fresh DISPLAY without colliding with host Xvfb
|
|
# on :99. Native (enhanced) path skips this entirely. ---
|
|
if [[ "${LAUNCH_MODE}" = wine ]]; then
|
|
if [[ ! -d "${WINEPREFIX}" || ! -f "${WINEPREFIX}/system.reg" ]]; then
|
|
log "initializing Wine prefix at ${WINEPREFIX}"
|
|
xvfb-run -a wineboot --init 2>&1 | sed 's/^/ /' || true
|
|
wineserver -w || true
|
|
fi
|
|
fi
|
|
|
|
# --- go ---
|
|
# CLI-arg fallbacks: env values default to empty strings in module.yaml so
|
|
# the entrypoint's INI-stamper leaves operator INI edits alone. But Conan's
|
|
# launch CLI requires real values for ServerName, MaxPlayers, ports, and
|
|
# RconPassword. Resolve those here so empty config_values still produce a
|
|
# launchable server. These fallbacks should match the previous module.yaml
|
|
# defaults so behaviour is unchanged for fresh installs.
|
|
SERVER_NAME_LAUNCH="${SERVER_NAME:-panel Conan Exiles}"
|
|
MAX_PLAYERS_LAUNCH="${MAX_PLAYERS:-40}"
|
|
RCON_PASSWORD_LAUNCH="${RCON_PASSWORD:-panel_rcon}"
|
|
|
|
BIN_DIR="$(dirname "${DEDI_EXE}")"
|
|
cd "${BIN_DIR}"
|
|
log "starting Conan Exiles dedicated server"
|
|
log " game dir: ${GAME_DIR}"
|
|
log " save dir: ${SAVE_DIR}"
|
|
log " binary: ${DEDI_EXE}"
|
|
log " bin dir: ${BIN_DIR}"
|
|
log " map: ${SERVER_MAP}"
|
|
log " max: ${MAX_PLAYERS_LAUNCH}"
|
|
log " game port: ${GAME_PORT}/tcp+udp"
|
|
log " query: ${QUERY_PORT}/udp"
|
|
log " rcon: ${RCON_PORT}/tcp"
|
|
|
|
if [[ "${LAUNCH_MODE}" = wine ]]; then
|
|
trap 'log "SIGTERM received; stopping server"; wineserver -k || true; exit 0' TERM INT
|
|
else
|
|
trap 'log "SIGTERM received; stopping server"; kill -TERM "${SERVER_PID:-0}" 2>/dev/null || true; wait "${SERVER_PID:-0}" 2>/dev/null || true; exit 0' TERM INT
|
|
fi
|
|
|
|
# Launch flags. Conan reads most settings from ServerSettings.ini (which we
|
|
# just stamped) — CLI args set the boot-time essentials. Pinger port is
|
|
# `Port + 1` per AMP convention; setting only -Port is enough — Conan
|
|
# derives pinger from it automatically.
|
|
#
|
|
# Native (enhanced) — match Funcom's launcher convention: `ConanSandbox`
|
|
# first positional, then the map URL. No -log/-nosound/-SteamServerName
|
|
# (those are Wine-era flags). ServerName lives in [ServerSettings]
|
|
# ServerName= which our INI stamper already handles.
|
|
if [[ "${LAUNCH_MODE}" = native ]]; then
|
|
chmod +x "${DEDI_EXE}" || true
|
|
exec stdbuf -oL -eL "${DEDI_EXE}" \
|
|
ConanSandbox \
|
|
"${SERVER_MAP}" \
|
|
-stdout \
|
|
-FullStdOutLogOutput \
|
|
"-ServerName=${SERVER_NAME_LAUNCH}" \
|
|
"-MaxPlayers=${MAX_PLAYERS_LAUNCH}" \
|
|
"-Port=${GAME_PORT}" \
|
|
"-QueryPort=${QUERY_PORT}" \
|
|
-RconEnabled=1 \
|
|
"-RconPort=${RCON_PORT}" \
|
|
"-RconPassword=${RCON_PASSWORD_LAUNCH}"
|
|
fi
|
|
|
|
# Wine (legacy) — xvfb-run -a auto-allocates a free X display (host has its
|
|
# own Xvfb on :99 / :100 / :101 — see panel/memory/gotchas.md "network_mode:
|
|
# host Xvfb collision"). `ConanSandbox` first positional matches Funcom's
|
|
# launcher convention; was missing on the old Wine launch line.
|
|
exec stdbuf -oL -eL xvfb-run -a --server-args="-screen 0 1024x768x24" \
|
|
wine "${DEDI_EXE}" \
|
|
ConanSandbox \
|
|
"${SERVER_MAP}" \
|
|
-log \
|
|
"-SteamServerName=${SERVER_NAME_LAUNCH}" \
|
|
"-ServerName=${SERVER_NAME_LAUNCH}" \
|
|
"-MaxPlayers=${MAX_PLAYERS_LAUNCH}" \
|
|
"-Port=${GAME_PORT}" \
|
|
"-QueryPort=${QUERY_PORT}" \
|
|
-RconEnabled=1 \
|
|
"-RconPort=${RCON_PORT}" \
|
|
"-RconPassword=${RCON_PASSWORD_LAUNCH}" \
|
|
-nosound \
|
|
-stdout \
|
|
-FullStdOutLogOutput
|