405 lines
14 KiB
Bash
405 lines
14 KiB
Bash
#!/usr/bin/env bash
|
|
#
|
|
# shellcheck disable=2043
|
|
#
|
|
# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
|
|
|
|
# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
|
|
# General Settings
|
|
# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
|
|
export DAYZ_FILES=/mnt/dayz
|
|
export STOCK_SERVER_DATA="$DAYZ_FILES/stock/DayZServer"
|
|
export MAIN="/mnt/c/DAYZ"
|
|
export SERVERS="$MAIN/servers"
|
|
export CACHE="$MAIN/cache"
|
|
export MOD_CACHE="$CACHE/mods"
|
|
export RESTART_INTERVAL=$((60 * 60 * 4 + 3))
|
|
|
|
# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
|
|
# Helper functions
|
|
# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
|
|
alias do_sync='rsync -rltDh --delete --partial'
|
|
|
|
msg() {
|
|
>&2 printf '[*] %s ...\n' "$*"
|
|
}
|
|
|
|
warn() {
|
|
>&2 printf '\n\n<<<< WARNING: %s >>>>>\n\n' "$*"
|
|
}
|
|
|
|
die() {
|
|
msg "$*"
|
|
exit 1
|
|
}
|
|
|
|
debug() {
|
|
if [ "$DEBUG" ] ; then
|
|
>&2 printf ' DEBUG: %s\n' "$*"
|
|
fi
|
|
}
|
|
|
|
# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
|
|
# Checks
|
|
# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
|
|
check() {
|
|
mkdir -p "$DAYZ_FILES"
|
|
|
|
if ! mount | grep -i "$DAYZ_FILES" >/dev/null ; then
|
|
msg "$DAYZ_FILES is not mounted!"
|
|
echo "hint: mount -t drvfs //truenas.home.weaver/dayz $DAYZ_FILES"
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -d "$MAIN" ] ; then
|
|
die "$MAIN does not exist"
|
|
fi
|
|
|
|
if [ ! -d "$STOCK_SERVER_DATA" ] ; then
|
|
die "$STOCK_SERVER_DATA does not exist"
|
|
fi
|
|
}
|
|
|
|
# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
|
|
# Environment Setup
|
|
# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
|
|
init() {
|
|
mkdir -p "$SERVER_HOME" "$MOD_CACHE/$MAP_FOLDER_NAME"
|
|
:>"$SERVER_HOME/.modstring"
|
|
}
|
|
|
|
setup_environment() {
|
|
msg "Copying stock server data"
|
|
|
|
# list of all stock folders
|
|
for folder in addons battleye bliss docs dta keys ; do
|
|
do_sync "$STOCK_SERVER_DATA/$folder"/ "$SERVER_HOME/$folder" || die "Failed to copy stock: $folder"
|
|
done
|
|
|
|
# list of all stock files
|
|
for file in ban.txt dayz.gproj dayzsetting.xml whitelist.txt \
|
|
DayZServer_x64.exe steam_api64.dll steamclient64.dll tier0_s64.dll vstdlib_s64.dll ; do
|
|
cp -f "$STOCK_SERVER_DATA/$file" "$SERVER_HOME/$file" || die "Failed to copy stock: $file"
|
|
done
|
|
|
|
msg "Copying mod files"
|
|
do_sync "$DAYZ_FILES/mods/$MAP_FOLDER_NAME"/ "$MOD_CACHE/$MAP_FOLDER_NAME" || die "Failed to copy mod files"
|
|
|
|
msg "Copying DZSA executable"
|
|
cp -f "$DAYZ_FILES/software/DZSALModServer.exe" "$SERVER_HOME/"
|
|
}
|
|
|
|
# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
|
|
# Load Mods
|
|
# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
|
|
load_mods() {
|
|
if [ ! -f "$MOD_CACHE/$MAP_FOLDER_NAME/mods.txt" ] ; then
|
|
die "mods.txt list missing"
|
|
fi
|
|
|
|
mkdir -p "$SERVER_HOME/mods"
|
|
|
|
_modstring=""
|
|
while read -r mod ; do
|
|
case $mod in
|
|
'@'*)
|
|
msg "- Found mod: $mod"
|
|
_modstring="$_modstring;mods/$mod"
|
|
do_sync "$MOD_CACHE/$MAP_FOLDER_NAME/$mod"/ "$SERVER_HOME/mods/$mod"
|
|
|
|
for addon_folder in addons Addons addon Addon ; do
|
|
if [ -d "$SERVER_HOME/mods/$mod/$addon_folder" ] ; then
|
|
for addon in "$SERVER_HOME/mods/$mod/$addon_folder"/* ; do
|
|
if [ ! -f "$SERVER_HOME/addons/${addon##*/}" ] ; then
|
|
cp -f "$addon" "$SERVER_HOME/addons/"
|
|
fi
|
|
done
|
|
fi
|
|
done
|
|
|
|
for key_folder in keys Keys key Key ; do
|
|
if [ -d "$SERVER_HOME/mods/$mod/$key_folder" ] ; then
|
|
for key in "$SERVER_HOME/mods/$mod/$key_folder"/* ; do
|
|
if [ ! -f "$SERVER_HOME/keys/${key##*/}" ] ; then
|
|
cp -f "$key" "$SERVER_HOME/keys/"
|
|
fi
|
|
done
|
|
fi
|
|
done
|
|
esac
|
|
done < "$MOD_CACHE/$MAP_FOLDER_NAME/mods.txt"
|
|
|
|
# trim the initial leading ';'
|
|
_modstring=${_modstring#;}
|
|
printf '%s\n' "$_modstring" > .modstring
|
|
}
|
|
|
|
# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
|
|
# Load Map
|
|
# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
|
|
load_stock_map_data() {
|
|
mkdir -p "$SERVER_HOME/mpmissions/$MAP_FOLDER_NAME"
|
|
do_sync --exclude='*storage_1*' \
|
|
"$DAYZ_FILES/stock/maps/$MAP_FOLDER_NAME"/ \
|
|
"$SERVER_HOME/mpmissions/$MAP_FOLDER_NAME" || \
|
|
die "Failed to copy stock map data"
|
|
}
|
|
|
|
# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
|
|
# Types Patching
|
|
# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
|
|
patch_types() {
|
|
|
|
if [ ! -f "$DAYZ_FILES/server_configs/types/default_types_to_delete.txt" ] ; then
|
|
die "CANNOT REACH FILE: default_types_to_delete.txt"
|
|
fi
|
|
|
|
# deletes
|
|
while read -r line ; do
|
|
case "$line" in
|
|
'#'*|' '*|'')
|
|
;;
|
|
*)
|
|
debug "TYPES -- deleting object: $line"
|
|
xmlstarlet ed -L -P -d "//types/type[@name=\"$line\"]" \
|
|
"$SERVER_HOME/mpmissions/$MAP_FOLDER_NAME/db/types.xml"
|
|
esac
|
|
done < "$DAYZ_FILES/server_configs/types/default_types_to_delete.txt"
|
|
|
|
# copy types edit tool
|
|
if [ -f "$DAYZ_FILES/scripts/adjust_type.sh" ] ; then
|
|
cp -f "$DAYZ_FILES/scripts/adjust_type.sh" "$SERVER_HOME"/
|
|
else
|
|
die "Could not find adjust_type.sh"
|
|
fi
|
|
|
|
if [ -f "$DAYZ_FILES/server_configs/types/$MAP_FOLDER_NAME.sh" ] ; then
|
|
cp -f "$DAYZ_FILES/server_configs/types/$MAP_FOLDER_NAME.sh" \
|
|
"$SERVER_HOME"/
|
|
|
|
cd "$SERVER_HOME" || die "could not cd to $SERVER_HOME"
|
|
|
|
sh "$SERVER_HOME/$MAP_FOLDER_NAME.sh" \
|
|
"$SERVER_HOME/mpmissions/$MAP_FOLDER_NAME/db/types.xml" || \
|
|
die "Failed while running maps types edit script"
|
|
else
|
|
die "Could not find $DAYZ_FILES/server_configs/types/$MAP_FOLDER_NAME.sh"
|
|
fi
|
|
|
|
# if we're on namalsk, we will have a types_dzn.xml as well
|
|
# this file contains the frozen food etc unique namalsk items
|
|
case $MAP_FOLDER_NAME in
|
|
*namalsk*)
|
|
DZN_FILE=namalsk_dzn.sh
|
|
msg "Patching $DZN_FILE"
|
|
if [ -f "$DAYZ_FILES/server_configs/types/$DZN_FILE" ] ; then
|
|
cp -f "$DAYZ_FILES/server_configs/types/$DZN_FILE" \
|
|
"$SERVER_HOME"/
|
|
|
|
cd "$SERVER_HOME" || die "could not cd to $SERVER_HOME"
|
|
|
|
sh "$SERVER_HOME/$DZN_FILE" \
|
|
"$SERVER_HOME/mpmissions/$MAP_FOLDER_NAME/db/types_dzn.xml" || \
|
|
die "Failed while running maps types edit script on types_dzn.xml"
|
|
else
|
|
die "Could not find $DAYZ_FILES/server_configs/types/$DZN_FILE"
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
}
|
|
|
|
load_customtypes() {
|
|
if [ -d "$DAYZ_FILES/server_configs/types/custom.$MAP_FOLDER_NAME" ] ; then
|
|
CUSTOM_TYPES="$SERVER_HOME/mpmissions/$MAP_FOLDER_NAME/customtypes"
|
|
CFG_ECORE="$SERVER_HOME/mpmissions/$MAP_FOLDER_NAME/cfgeconomycore.xml"
|
|
|
|
mkdir -p "$CUSTOM_TYPES"
|
|
do_sync "$DAYZ_FILES/server_configs/types/custom.$MAP_FOLDER_NAME"/ \
|
|
"$CUSTOM_TYPES"
|
|
|
|
for xml in "$CUSTOM_TYPES"/*.xml ; do
|
|
debug " - Found custom type: ${xml##*/}"
|
|
if [ -f "$xml" ] ; then
|
|
sed -E -i '/<\/economycore>/d' "$CFG_ECORE"
|
|
|
|
printf '\n<ce folder="db">\n<file name="customtypes/%s" type="types" />\n</ce>\n\n' "${xml##*/}" \
|
|
>> "$CFG_ECORE"
|
|
|
|
printf '%s\n' '</economycore>' >> "$CFG_ECORE"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# ============== custom SPAWNABLE types ===================
|
|
if [ -d "$DAYZ_FILES/server_configs/types/spawnabletypes.$MAP_FOLDER_NAME" ] ; then
|
|
msg "Copying custom spawnable types"
|
|
|
|
CUSTOM_SPAWNABLE_TYPES="$SERVER_HOME/mpmissions/$MAP_FOLDER_NAME/spawnabletypes"
|
|
CFG_SPAWNABLE_TYPES="$SERVER_HOME/mpmissions/$MAP_FOLDER_NAME/cfgspawnabletypes.xml"
|
|
|
|
mkdir -p "$CUSTOM_SPAWNABLE_TYPES"
|
|
do_sync "$DAYZ_FILES/server_configs/types/spawnabletypes.$MAP_FOLDER_NAME"/ \
|
|
"$CUSTOM_SPAWNABLE_TYPES"
|
|
|
|
for xml in "$CUSTOM_SPAWNABLE_TYPES"/*.xml ; do
|
|
debug " - Found custom spawnabletype: ${xml##*/}"
|
|
if [ -f "$xml" ] ; then
|
|
sed -E -i '/<\/spawnabletypes>/d' "$CFG_SPAWNABLE_TYPES"
|
|
cat "$xml" >> "$CFG_SPAWNABLE_TYPES"
|
|
printf '%s\n' '</spawnabletypes>' >> "$CFG_SPAWNABLE_TYPES"
|
|
fi
|
|
done
|
|
fi
|
|
}
|
|
|
|
# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
|
|
# Configs
|
|
# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
|
|
load_configs() {
|
|
msg "Loading server configs"
|
|
|
|
if [ -d "$DAYZ_FILES/server_configs/mpmissions/$MAP_FOLDER_NAME" ] ; then
|
|
|
|
for xml in "$DAYZ_FILES/server_configs/mpmissions/$MAP_FOLDER_NAME"/*.xml ; do
|
|
if [ -f "$xml" ] ; then
|
|
debug "Found: $xml -- Copying."
|
|
do_sync "$xml" "$SERVER_HOME/mpmissions/$MAP_FOLDER_NAME/${xml##*/}" || \
|
|
die "Failed to copy: ${xml##*/}"
|
|
fi
|
|
done
|
|
|
|
for json in "$DAYZ_FILES/server_configs/mpmissions/$MAP_FOLDER_NAME"/*.json ; do
|
|
if [ -f "$json" ] ; then
|
|
debug "Found: $json -- Copying."
|
|
do_sync "$json" "$SERVER_HOME/mpmissions/$MAP_FOLDER_NAME/${json##*/}" || \
|
|
die "Failed to copy: ${json##*/}"
|
|
fi
|
|
done
|
|
|
|
if [ -f "$DAYZ_FILES/server_configs/mpmissions/$MAP_FOLDER_NAME/init.c" ] ; then
|
|
debug "Found: init.c -- Copying."
|
|
do_sync \
|
|
"$DAYZ_FILES/server_configs/mpmissions/$MAP_FOLDER_NAME/init.c" \
|
|
"$SERVER_HOME/mpmissions/$MAP_FOLDER_NAME/init.c" || \
|
|
die "failed to copy init.c"
|
|
fi
|
|
|
|
if [ -f "$DAYZ_FILES/server_configs/mpmissions/$MAP_FOLDER_NAME/areaflags.map" ] ; then
|
|
debug "Found: areaflags.map -- Copying."
|
|
do_sync \
|
|
"$DAYZ_FILES/server_configs/mpmissions/$MAP_FOLDER_NAME/areaflags.map" \
|
|
"$SERVER_HOME/mpmissions/$MAP_FOLDER_NAME/areaflags.map" || \
|
|
die "failed to copy areaflags.map"
|
|
fi
|
|
|
|
fi
|
|
|
|
if [ -d "$DAYZ_FILES/server_configs/mpmissions/$MAP_FOLDER_NAME/db" ] ; then
|
|
for xml in "$DAYZ_FILES/server_configs/mpmissions/$MAP_FOLDER_NAME/db"/*.xml ; do
|
|
if [ -f "$xml" ] ; then
|
|
debug "Found: $xml -- Copying."
|
|
do_sync "$xml" "$SERVER_HOME/mpmissions/$MAP_FOLDER_NAME/db/${xml##*/}" || \
|
|
die "Failed to copy: ${xml##*/}"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
if [ -d "$DAYZ_FILES/server_configs/mpmissions/$MAP_FOLDER_NAME/env" ] ; then
|
|
for xml in "$DAYZ_FILES/server_configs/mpmissions/$MAP_FOLDER_NAME/env"/*.xml ; do
|
|
if [ -f "$xml" ] ; then
|
|
debug "Found: $xml -- Copying."
|
|
do_sync "$xml" "$SERVER_HOME/mpmissions/$MAP_FOLDER_NAME/env/${xml##*/}" || \
|
|
die "Failed to copy: ${xml##*/}"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
msg "Copying generic Profilesfolder configs"
|
|
if [ -d "$DAYZ_FILES/server_configs/Profilesfolder/sUDE/config" ] ; then
|
|
mkdir -p "$SERVER_HOME/Profilesfolder/sUDE/config"
|
|
cp -f "$DAYZ_FILES/server_configs/Profilesfolder/sUDE/config"/* "$SERVER_HOME/Profilesfolder/sUDE/config"/
|
|
else
|
|
die "missing: $DAYZ_FILES/server_configs/Profilesfolder/sUDE/config"
|
|
fi
|
|
}
|
|
|
|
# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
|
|
# Main
|
|
# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
|
|
main() {
|
|
init
|
|
cd "$SERVER_HOME" || die "Could not cd to '$SERVER_HOME'"
|
|
|
|
check || die "Failed check"
|
|
|
|
msg "Setting up environment"
|
|
setup_environment || die "Could not set up environment."
|
|
|
|
msg "Loading mods"
|
|
load_mods || die "Could not load mods"
|
|
mod_string=$(cat .modstring)
|
|
|
|
msg "Loading stock map data"
|
|
load_stock_map_data || die "Could not load map"
|
|
|
|
msg "Patching types.xml"
|
|
patch_types || die "Failed to patch types"
|
|
|
|
msg "Copying server configs"
|
|
load_configs || die "Failed to load configs"
|
|
|
|
msg "Creating custom types list"
|
|
load_customtypes || die "Failed to load custom types"
|
|
|
|
echo '===================================='
|
|
printf '%s - Server started.\n' "$(date)"
|
|
echo '===================================='
|
|
|
|
# creating temp.bat here to avoid the arg max char limit of windows cmd.exe
|
|
cat > temp.bat <<EOF
|
|
:start
|
|
start "DayZ Server" /min DZSALModServer.exe -config=serverDZ.cfg -port="$SERVER_PORT" -profiles=Profilesfolder -mod="$mod_string" -cpuCount="$SERVER_CPU" -dologs -adminlog -netlog -freezecheck
|
|
EOF
|
|
cmd.exe /C temp.bat
|
|
|
|
printf '\n**** Sleeping for: %s *****\n\n' "$RESTART_INTERVAL"
|
|
count=0
|
|
while [ "$count" -lt "$RESTART_INTERVAL" ] ; do
|
|
sleep 60
|
|
count=$((count + 60))
|
|
msg "TIME LEFT BEFORE RESTART: $(( (RESTART_INTERVAL - count) / 60 )) minutes"
|
|
done
|
|
|
|
echo "==========================="
|
|
|
|
msg "Time up"
|
|
msg "Killing server"
|
|
cmd.exe /C taskkill /im DayZServer_x64.exe /F
|
|
rm -f temp.bat 2>/dev/null ||:
|
|
|
|
msg "Sleeping 10 seconds to settle"
|
|
sleep 10
|
|
msg "SERVER IS RESTARTING"
|
|
}
|
|
|
|
ORIGINAL_DIR="$PWD"
|
|
|
|
while msg 'Starting loop' ; do
|
|
cd "$ORIGINAL_DIR" || die "Can no longer cd to $ORIGINAL_DIR"
|
|
|
|
if [ -e ./SERVER.ENV ] ; then
|
|
. ./SERVER.ENV
|
|
else
|
|
die "Could not source ./SERVER.ENV"
|
|
fi
|
|
|
|
if [ -f ./serverDZ.cfg ] ; then
|
|
cp -f ./serverDZ.cfg "$SERVER_HOME"/
|
|
else
|
|
die "Could not find ./serverDZ.cfg"
|
|
fi
|
|
|
|
main "$@"
|
|
done
|