cs16-dm-server: CS 1.6 deathmatch server in Docker
One-command setup (SteamCMD + pinned, checksum-verified ReHLDS / ReGameDLL / Metamod-R / AMXX / ReAPI / ReUnion / CSDM-ReAPI / YaPB / GunGame), .env settings, ./cs menu (map, DM/GunGame mode, bots, kill counter, restart, update), own plugins (extras, rtv, mode switch), all-time kill counter, watchdog + nightly backup, docs for admins and players. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
commit
7e9cbee14d
33 files changed
+1890
No files matched your search
Executable
+130
@@ -0,0 +1,130 @@
|
||||
#!/bin/sh
|
||||
# Puts the mod stack on top of the Valve game files in hlds/. setup.sh runs this inside the
|
||||
# image after every game download/update (a Steam "validate" puts Valve's engine back and
|
||||
# silently removes ReHLDS + Metamod, so this always has to run after it).
|
||||
# Safe to run again. Kept as they are on re-runs: maps, stats, bot navigation graphs, and your
|
||||
# edits to users.ini (admins), amxx.cfg, csdm/config.ini, mapcycle.txt and custom.cfg.
|
||||
# Mounts (see setup.sh): repo at /cs/repo (read-only) with dl/ writable, hlds at /cs/hlds.
|
||||
set -e
|
||||
R=/cs/repo; DL=$R/dl; H=/cs/hlds; C=$H/cstrike; A=$C/addons; CF=$C/addons/amxmodx/configs
|
||||
X=$(mktemp -d)
|
||||
trap 'rm -rf "$X"' EXIT
|
||||
step() { printf ' - %s\n' "$*"; }
|
||||
die() { printf '\033[31merror:\033[0m %s\n' "$*" >&2; exit 1; }
|
||||
sha() { sha256sum < "$1" | cut -c1-64; }
|
||||
|
||||
[ -x $H/hlds_linux ] || die "no game files in hlds/ (the Steam download didn't finish)"
|
||||
|
||||
step "downloads (pinned, checked against tools/versions.txt)"
|
||||
mkdir -p $DL/gg $DL/snd $DL/spawns
|
||||
grep -v '^#' $R/tools/versions.txt | while read -r f sum url; do
|
||||
[ -n "$f" ] || continue
|
||||
[ -f "$DL/$f" ] && [ "$(sha "$DL/$f")" = "$sum" ] && continue
|
||||
curl -fsSL --retry 3 -o "$DL/$f.part" "$url" || die "download failed: $url"
|
||||
got=$(sha "$DL/$f.part")
|
||||
[ "$got" = "$sum" ] || { rm -f "$DL/$f.part"; die "checksum mismatch for $f: expected $sum, got $got"; }
|
||||
mv "$DL/$f.part" "$DL/$f"
|
||||
done
|
||||
ls $DL/rehlds-bin-*.zip >/dev/null
|
||||
|
||||
# Game mode in use right now (re-run) or from .env (first install)
|
||||
if [ -f $CF/plugins-gungame.ini ]; then MODE=gg
|
||||
elif [ -f $CF/plugins-CSDM_ReAPI.ini ] || [ -f $CF/plugins-CSDM_ReAPI.ini.off ]; then MODE=dm
|
||||
else MODE=${CS_MODE:-dm}; fi
|
||||
case "$MODE" in dm|gg) ;; *) die "CS_MODE must be dm or gg (is: $MODE)" ;; esac
|
||||
|
||||
# Files people edit: save them now, put them back after the archives are unpacked
|
||||
FIRST=; [ -f $C/.cs16-dm-server ] || FIRST=1
|
||||
KEEP="addons/amxmodx/configs/users.ini addons/amxmodx/configs/amxx.cfg addons/amxmodx/configs/csdm/config.ini"
|
||||
if [ -z "$FIRST" ]; then
|
||||
for f in $KEEP; do [ -f "$C/$f" ] && mkdir -p "$X/keep/$(dirname "$f")" && cp -p "$C/$f" "$X/keep/$f"; done
|
||||
fi
|
||||
|
||||
step "ReHLDS (engine)"
|
||||
unzip -qo $DL/rehlds-bin-3.15.0.896.zip 'bin/linux32/*' -d $X/rehlds
|
||||
cp -a $X/rehlds/bin/linux32/. $H/
|
||||
chmod +x $H/hlds_linux $H/hltv # the zip has no exec bits
|
||||
|
||||
step "ReGameDLL (game logic)"
|
||||
unzip -qo $DL/regamedll-bin-5.30.0.814.zip 'bin/linux32/cstrike/*' -d $X/regame
|
||||
cp -a $X/regame/bin/linux32/cstrike/. $C/
|
||||
# game.cfg runs at every map start and would force alltalk off: server.cfg decides that instead
|
||||
sed -i 's|^sv_alltalk "0"|// sv_alltalk "0" // cs16-dm-server: set in server.cfg instead|' $C/game.cfg
|
||||
|
||||
step "Metamod-R"
|
||||
unzip -qo $DL/metamod-bin-1.3.0.149.zip 'addons/*' -d $X/mm
|
||||
cp -a $X/mm/addons/. $A/
|
||||
[ -f $C/liblist.gam.orig ] || cp $C/liblist.gam $C/liblist.gam.orig
|
||||
sed -i 's|^gamedll_linux .*|gamedll_linux "addons/metamod/metamod_i386.so"|' $C/liblist.gam
|
||||
|
||||
step "AMX Mod X + ReAPI"
|
||||
tar xzf $DL/amxmodx-1.10.0-git5486-base-linux.tar.gz -C $C
|
||||
tar xzf $DL/amxmodx-1.10.0-git5486-cstrike-linux.tar.gz -C $C
|
||||
unzip -qo $DL/reapi-bin-5.29.0.358.zip 'addons/*' -d $X/reapi
|
||||
cp -a $X/reapi/addons/. $A/
|
||||
|
||||
step "ReUnion (non-Steam clients)"
|
||||
unzip -qo $DL/reunion-0.2.0.25.zip bin/Linux/reunion_mm_i386.so reunion.cfg -d $X/reu
|
||||
mkdir -p $A/reunion
|
||||
cp $X/reu/bin/Linux/reunion_mm_i386.so $A/reunion/
|
||||
SALT=$(tr -d '\r\n' < /cs/secrets/reunion-salt.txt)
|
||||
[ -n "$SALT" ] || die "secrets/reunion-salt.txt is empty"
|
||||
# IDClientsLimit 0: several non-Steam players with the same placeholder ID can all join
|
||||
( umask 077; sed -e "s|^SteamIdHashSalt =.*|SteamIdHashSalt = $SALT|" -e 's|^IDClientsLimit = .*|IDClientsLimit = 0|' \
|
||||
$X/reu/reunion.cfg > $C/reunion.cfg )
|
||||
|
||||
step "CSDM-ReAPI (deathmatch) + spawn points"
|
||||
unzip -qo $DL/CSDM-ReAPI-v1.0.8.zip 'cstrike/*' -d $X/csdm
|
||||
cp -a $X/csdm/cstrike/. $C/
|
||||
mkdir -p $CF/csdm/spawns
|
||||
for f in $DL/spawns/*.spawns.cfg; do
|
||||
b=$(basename "$f")
|
||||
# old 6-field lines (de_prodigy, de_train) -> the 10 fields CSDM-ReAPI reads (others are skipped)
|
||||
awk 'NF==6 {print $0" 0 0 0 0"; next} {print}' "$f" > $CF/csdm/spawns/$b
|
||||
ln -sfn spawns/$b $CF/csdm/$b # GunGame looks for them one folder up
|
||||
done
|
||||
|
||||
step "YaPB (bots)"
|
||||
tar xJf $DL/yapb-4.4.957-linux.tar.xz -C $C
|
||||
find $A/yapb -type d -exec chmod 775 {} + # the tarball's dirs have no x bit
|
||||
sed -i -e 's/^yb_csdm_mode ".*"/yb_csdm_mode "2"/' -e 's/^yb_quota_mode ".*"/yb_quota_mode "fill"/' \
|
||||
$A/yapb/conf/yapb.cfg # FFA-aware bots; quota = fill up to CS_BOTS players (start.sh sets it)
|
||||
|
||||
step "GunGame + announcer sounds"
|
||||
cp $DL/gg/gungame.sma $A/amxmodx/scripting/
|
||||
cp $DL/gg/gungame.txt $A/amxmodx/data/lang/
|
||||
mkdir -p $C/sound/gungame $C/sound/misc
|
||||
cp $DL/gg/*.wav $C/sound/gungame/
|
||||
cp $DL/snd/*.wav $C/sound/misc/
|
||||
|
||||
step "configs from the repo"
|
||||
cp -a $R/cstrike/. $C/
|
||||
if [ -n "$FIRST" ]; then
|
||||
cp $R/defaults/mapcycle.txt $C/mapcycle.txt
|
||||
fi
|
||||
[ -f $C/custom.cfg ] || cp $R/defaults/custom.cfg $C/custom.cfg
|
||||
if [ -z "$FIRST" ] && [ -d $X/keep ]; then cp -a $X/keep/. $C/; fi
|
||||
|
||||
step "compiling plugins"
|
||||
cp $R/plugins/*.sma $A/amxmodx/scripting/
|
||||
cd $A/amxmodx/scripting
|
||||
for p in rtv esef_extras esef_mode gungame; do
|
||||
./amxxpc $p.sma -o../plugins/$p.amxx > $X/$p.log 2>&1 || { cat $X/$p.log; die "compiling $p.sma failed"; }
|
||||
done
|
||||
cd - >/dev/null
|
||||
|
||||
step "game mode: $MODE"
|
||||
# exactly one of the two plugin lists is active (.ini), the other one is .ini.off
|
||||
for ini in plugins-gungame.ini plugins-CSDM_ReAPI.ini; do
|
||||
[ -f $CF/$ini ] && rm -f $CF/$ini.off # fresh copy from the archive/repo wins
|
||||
[ -f $CF/$ini ] || mv $CF/$ini.off $CF/$ini
|
||||
done
|
||||
if [ "$MODE" = gg ]; then mv $CF/plugins-CSDM_ReAPI.ini $CF/plugins-CSDM_ReAPI.ini.off
|
||||
else mv $CF/plugins-gungame.ini $CF/plugins-gungame.ini.off; fi
|
||||
|
||||
# hlds looks for steamclient.so here; without it: "Unable to initialize Steam"
|
||||
mkdir -p /cs/steamcmd-home/.steam/sdk32
|
||||
ln -sfn /cs/hlds/steamclient.so /cs/steamcmd-home/.steam/sdk32/steamclient.so
|
||||
|
||||
touch $C/.cs16-dm-server
|
||||
echo " mod stack installed"
|
||||
Reference in new issue
Block a user