mirror of
				https://ceregatti.org/git/daniel/dayzdockerserver.git
				synced 2025-11-03 23:03:35 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			694 lines
		
	
	
	
		
			19 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			694 lines
		
	
	
	
		
			19 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable file
		
	
	
	
	
#!/usr/bin/env bash
 | 
						|
 | 
						|
# If you want/need the server and rcon ports to be different, set them here.
 | 
						|
# The steam query port is set in serverDZ.cfg.
 | 
						|
 | 
						|
# Server port
 | 
						|
port=2302
 | 
						|
rcon_port=2303
 | 
						|
 | 
						|
# Don't change anything else.
 | 
						|
 | 
						|
# Colors
 | 
						|
default="\e[0m"
 | 
						|
red="\e[31m"
 | 
						|
green="\e[32m"
 | 
						|
yellow="\e[93m"
 | 
						|
lightblue="\e[94m"
 | 
						|
blue="\e[34m"
 | 
						|
magenta="\e[35m"
 | 
						|
cyan="\e[36m"
 | 
						|
 | 
						|
# DayZ Experimental server Steam app ID, because there is no release version of the Linux server yet
 | 
						|
#experimental_server_appid=1042420
 | 
						|
 | 
						|
# DayZ release server Steam app ID. Presumably once the Linux server is released, the binaries will come
 | 
						|
# from this ID.
 | 
						|
release_server_appid=223350
 | 
						|
 | 
						|
# DayZ release client SteamID. This is for mods, as only the release client has them.
 | 
						|
release_client_appid=221100
 | 
						|
 | 
						|
# Base directories
 | 
						|
CFG_SRC_FILES="/files"
 | 
						|
SERVER_FILES="${HOME}/serverfiles"
 | 
						|
SERVER_PROFILE="${HOME}/profiles"
 | 
						|
 | 
						|
# Server configuration file
 | 
						|
SERVER_CFG_FILE="serverDZ.cfg"
 | 
						|
SERVER_CFG_DST="${SERVER_FILES}/${SERVER_CFG_FILE}"
 | 
						|
SERVER_CFG_SRC="${CFG_SRC_FILES}/${SERVER_CFG_FILE}"
 | 
						|
 | 
						|
# Command line parameters except mod, as that is handled separately.
 | 
						|
parameters="-config=${SERVER_CFG_FILE} -port=${port} -freezecheck -fps=60 -BEpath=${SERVER_FILES}/battleye -profiles=${SERVER_PROFILE} -nologs"
 | 
						|
 | 
						|
# Used to check if dayZ is installed
 | 
						|
SERVER_INSTALL_FILE="${SERVER_FILES}/DayZServer"
 | 
						|
 | 
						|
# Steam files
 | 
						|
STEAM_LOGIN="${HOME}/steamlogin"
 | 
						|
STEAMCMD=steamcmd
 | 
						|
 | 
						|
# Workshop. This file will store metadata about what mods are installed.
 | 
						|
WORKSHOP_CFG="${HOME}/workshop.cfg"
 | 
						|
if [ ! -f "${WORKSHOP_CFG}" ]
 | 
						|
then
 | 
						|
	touch "${WORKSHOP_CFG}"
 | 
						|
fi
 | 
						|
 | 
						|
# An array to store Workshop items. Each element contains the mod's ID, name, and state (active or not).
 | 
						|
declare -a workshopID
 | 
						|
workshopfolder="${SERVER_FILES}/steamapps/workshop/content/${release_client_appid}"
 | 
						|
 | 
						|
# Backups
 | 
						|
BACKUP_DIR="${HOME}/backup"
 | 
						|
if [ ! -d "${BACKUP_DIR}" ]
 | 
						|
then
 | 
						|
	mkdir -p "${BACKUP_DIR}"
 | 
						|
fi
 | 
						|
 | 
						|
# Other stuff
 | 
						|
YES="${green}yes${default}"
 | 
						|
NO="${red}no${default}"
 | 
						|
 | 
						|
# Functions
 | 
						|
 | 
						|
# Usage
 | 
						|
usage(){
 | 
						|
  echo -e "
 | 
						|
${red}Bad option or arguments! ${yellow}${*}${default}
 | 
						|
 | 
						|
Usage: ${green}$(basename $0)${yellow} option [ arg1 [ arg2 ] ]
 | 
						|
 | 
						|
Options and arguments:
 | 
						|
 | 
						|
  a|activate id [id...] - Activate one or many installed DayZ Workshop items by id
 | 
						|
  add id [id...] - Add one or many DayZ Workshop items by id. Added items become active by default
 | 
						|
  b|backup - Backup the mission storage files in all mission directories
 | 
						|
  c|config - Update the internal serverDZ.cfg file from files/serverDZ.cfg on the host. Presents a unified diff if the internal file doesn't match the host file
 | 
						|
  d|deactivate id [id...] - Deactivate one or many installed DayZ Workshop items by id - Keeps the mod files but excludes from -mod=
 | 
						|
  i|install - Install the DayZ server files
 | 
						|
  l|list - List Workshop items and if they are active or not
 | 
						|
  g|login - Login to Steam
 | 
						|
  m|modupdate - Update the mod files
 | 
						|
  n|rcon - Connect to the server using a python RCON client
 | 
						|
  r|remove id [id...] - Remove all vestiges of one or many Workshop items by id
 | 
						|
  restart - Restart the server without restarting the container
 | 
						|
  t|status - Shows the server's status as well as the state of the server files and mods (Needs install, update, etc.)
 | 
						|
  stop - Stop the server
 | 
						|
  u|update - Update the server files
 | 
						|
${default}"
 | 
						|
  exit 1
 | 
						|
}
 | 
						|
 | 
						|
# Make sure to clean up and report on exit, as these files remain in the container's volume
 | 
						|
report() {
 | 
						|
	rm -f /tmp/mod_command_line /tmp/parameters
 | 
						|
	echo
 | 
						|
	echo -e "${yellow}========================================== error.log =========================================="
 | 
						|
	find "${HOME}" -name error.log -exec head {} \; -exec tail {} \; -exec rm -f {} \;
 | 
						|
	echo
 | 
						|
	echo -e "========================================== script*.log ========================================"
 | 
						|
	find "${HOME}" -name "script*.log" -exec head {} \; -exec tail {} \; -exec rm -f {} \;
 | 
						|
	echo
 | 
						|
	echo -e "========================================== *.RPT =============================================="
 | 
						|
	find "${HOME}" -name "*.RPT" -exec ls -la {} \; -exec tail {} \; -exec rm -f {} \;
 | 
						|
	echo
 | 
						|
	echo -e "========================================== End crash log ======================================${default}"
 | 
						|
}
 | 
						|
 | 
						|
# Convenience function 
 | 
						|
prompt_yn(){
 | 
						|
	echo -n "${1} (y|N) " >&2
 | 
						|
	read -s -n 1 a
 | 
						|
	a=$(echo ${a} | tr A-Z a-z)
 | 
						|
	echo
 | 
						|
	if [[ "${a}" = "y" ]]
 | 
						|
	then
 | 
						|
		return 0
 | 
						|
	else
 | 
						|
		return 1
 | 
						|
	fi
 | 
						|
}
 | 
						|
 | 
						|
check_install(){
 | 
						|
	if [ ! -f "${SERVER_INSTALL_FILE}" ]
 | 
						|
	then
 | 
						|
		echo
 | 
						|
		echo -e "The DayZ server files are not installed. Run '${green}docker-compose run --rm main dayzserver install${default}'"
 | 
						|
		echo
 | 
						|
		exit 1
 | 
						|
	fi
 | 
						|
}
 | 
						|
 | 
						|
# Ensures all is installed and ready before allowing operations that depends on things being ready.
 | 
						|
# Installs the initial server config file from its template.
 | 
						|
# Handles the importing of changes to that template.
 | 
						|
# Installs the initial Battleye RCON config.
 | 
						|
loadconfig(){
 | 
						|
	check_install
 | 
						|
	# Handle the initial server configuration file
 | 
						|
	if [ ! -f ${SERVER_CFG_DST} ]
 | 
						|
	then
 | 
						|
		echo "Creating initial server configuration file"
 | 
						|
		cp "${SERVER_CFG_SRC}" "${SERVER_CFG_DST}"
 | 
						|
	fi
 | 
						|
	# battleye config and rconpassword setup
 | 
						|
	# The server creates a new file from this file, which it then uses.
 | 
						|
	# Let's make sure to delete it first
 | 
						|
	BE_SERVER_FILE="${HOME}/serverfiles/battleye/beserver_x64.cfg"
 | 
						|
	ALT_BE_SERVER_FILE=$(find ${HOME}/serverfiles/battleye -name "beserver_x64_active*")
 | 
						|
	if [ ! -f "${BE_SERVER_FILE}" ] && [ ! -f "${ALT_BE_SERVER_FILE}" ]
 | 
						|
	then
 | 
						|
		passwd=$(openssl rand -base64 8 | tr -dc 'A-Za-z0-9')
 | 
						|
		if [ "${passwd}" == "" ]
 | 
						|
		then
 | 
						|
			passwd=$(< /dev/urandom tr -dc 'A-Za-z0-9' | head -c10)
 | 
						|
		fi
 | 
						|
		if [ "${passwd}" == "" ]
 | 
						|
		then
 | 
						|
			printf "[ ${red}FAIL${default} ] Could not generate a passwort for RCON!\nOpen the Battleye config with 'dayzserver rcon'."
 | 
						|
			exit 1
 | 
						|
		else
 | 
						|
			cat > "${BE_SERVER_FILE}" <<EOF
 | 
						|
RConPassword ${passwd}
 | 
						|
RestrictRCon 0
 | 
						|
RConPort ${rcon_port}
 | 
						|
EOF
 | 
						|
		fi
 | 
						|
		printf "[ ${cyan}INFO${default} ] New RCON password: ${yellow}${passwd}${default}\n"
 | 
						|
	else
 | 
						|
		if [ -f "${BE_SERVER_FILE}" ]
 | 
						|
		then
 | 
						|
			FILE="${BE_SERVER_FILE}"
 | 
						|
		elif [ -f "${ALT_BE_SERVER_FILE}" ]
 | 
						|
		then
 | 
						|
			FILE="${ALT_BE_SERVER_FILE}"
 | 
						|
		fi
 | 
						|
		passwd=$(grep RConPassword ${FILE} | awk '{print $2}')
 | 
						|
#		printf "[ ${cyan}INFO${default} ] Using existing RCON password: ${yellow}${passwd}${default}\n"
 | 
						|
	fi
 | 
						|
	cp /usr/local/py3rcon/configexample.json ~/py3rcon.config.json
 | 
						|
	jq --arg port 2303 --arg rcon_password b0fNIBVfkM \
 | 
						|
		'.logfile="py3rcon.log" | .loglevel=0 | .server.port=$port | .server.rcon_password=$rcon_password | del(.repeatMessage)' \
 | 
						|
		/usr/local/py3rcon/configexample.json \
 | 
						|
		> ~/py3rcon.config.json
 | 
						|
}
 | 
						|
 | 
						|
# Start the server in the foreground
 | 
						|
start(){
 | 
						|
	# Do the report on exit. Set here so that it only happens once we're starting the server, and not for other actions.
 | 
						|
	trap '
 | 
						|
		report
 | 
						|
	' EXIT
 | 
						|
	mod_cmd
 | 
						|
	cd ${SERVER_FILES}
 | 
						|
	# Run the server. Allow docker to restart the container if the script exits with a code other than 0. This is so we can
 | 
						|
	# safely shut the container down without killing the server within.
 | 
						|
	printf "[ ${green}DayZ${default} ] Server starting...\n"
 | 
						|
	# Save the mod command line and parameters that were used to start the server, so status reflects the running server's
 | 
						|
	# actual status with those
 | 
						|
	echo ${mod_command_line} > /tmp/mod_command_line
 | 
						|
	echo ${parameters} > /tmp/parameters
 | 
						|
	./DayZServer ${mod_command_line} ${parameters}
 | 
						|
	EXIT_CODE=$?
 | 
						|
	if [ -f ${SERVER_FILES}/restart ]
 | 
						|
	then
 | 
						|
		rm -f ${SERVER_FILES}/restart
 | 
						|
		EXIT_CODE=42
 | 
						|
	fi
 | 
						|
	printf "\n[ ${yellow}DayZ${default} ] Server exited. Exit code: ${EXIT_CODE}\n"
 | 
						|
	exit ${EXIT_CODE}
 | 
						|
}
 | 
						|
 | 
						|
# Restarts the server by forcing an exit code other than 0, causing docker to restart the container.
 | 
						|
restart(){
 | 
						|
	touch "${SERVER_FILES}/restart"
 | 
						|
	echo "Restarting DayZ server..."
 | 
						|
	kill -TERM $(pidof DayZServer)
 | 
						|
}
 | 
						|
 | 
						|
# Stops the server cleanly and exits 0, which will stop the container.
 | 
						|
stop(){
 | 
						|
	echo "Stopping DayZ server..."
 | 
						|
	kill -TERM $(pidof DayZServer)
 | 
						|
}
 | 
						|
 | 
						|
# Forcibly kill the server, should it be necessary.
 | 
						|
force(){
 | 
						|
	echo "Forcibly stopping DayZ server..."
 | 
						|
	kill -KILL $(pidof DayZServer)
 | 
						|
}
 | 
						|
 | 
						|
# Hanle the Steam login information.
 | 
						|
login(){
 | 
						|
	loadconfig
 | 
						|
	if [ -f "${STEAM_LOGIN}" ]
 | 
						|
	then
 | 
						|
		if prompt_yn "The steam login is already set. Reset it?"
 | 
						|
		then
 | 
						|
			rm -f "${STEAM_LOGIN}"
 | 
						|
		else
 | 
						|
			echo "Not reset."
 | 
						|
			exit 0
 | 
						|
		fi
 | 
						|
	fi
 | 
						|
	if [ ! -f "${STEAM_LOGIN}" ]
 | 
						|
	then
 | 
						|
		echo "Setting up Steam credentials"
 | 
						|
		echo -n "Steam Username (anonymous): "
 | 
						|
		read steamlogin
 | 
						|
		if [[ "${steamlogin}" = "" ]]
 | 
						|
		then
 | 
						|
			echo "Steam login set to 'anonymous'"
 | 
						|
			steamlogin="anonymous"
 | 
						|
		fi
 | 
						|
		echo "steamlogin=${steamlogin}" > "${STEAM_LOGIN}"
 | 
						|
		${STEAMCMD} +force_install_dir ${SERVER_FILES} +login "${steamlogin}" +quit
 | 
						|
	fi
 | 
						|
}
 | 
						|
 | 
						|
# "Perform" the Steam login. This just sources the file with the Steam login name.
 | 
						|
dologin(){
 | 
						|
	loadconfig
 | 
						|
	if [ -f "${STEAM_LOGIN}" ]
 | 
						|
	then
 | 
						|
		source "${STEAM_LOGIN}"
 | 
						|
	else
 | 
						|
		echo "No cached Steam credentials. Please configure this now: "
 | 
						|
		login
 | 
						|
	fi
 | 
						|
}
 | 
						|
 | 
						|
# Perform the installation of the server files.
 | 
						|
install(){
 | 
						|
	loadconfig
 | 
						|
	if [ ! -f "${SERVER_INSTALL_FILE}" ] || [[ ${1} = "force" ]]
 | 
						|
	then
 | 
						|
		mkdir -p "${SERVER_FILES}"
 | 
						|
		mkdir -p "${SERVER_PROFILE}"
 | 
						|
		printf "[ ${yellow}DayZ${default} ] Downloading DayZ Server-Files!\n"
 | 
						|
		dologin
 | 
						|
		${STEAMCMD} +force_install_dir ${SERVER_FILES} +login "${steamlogin}" +app_update "${release_server_appid}" validate +quit
 | 
						|
	else
 | 
						|
		printf "[ ${lightblue}DayZ${default} ] The Server is already installed.\n"
 | 
						|
	fi
 | 
						|
}
 | 
						|
 | 
						|
# Handle any changes in the server config file by allowing them to be merged after viewing a diff.
 | 
						|
config(){
 | 
						|
	if ! diff -q "${SERVER_CFG_SRC}" "${SERVER_CFG_DST}"
 | 
						|
	then
 | 
						|
		echo "========================================================================="
 | 
						|
		diff -Nau --color "${SERVER_CFG_SRC}" "${SERVER_CFG_DST}" || echo ""
 | 
						|
		echo "========================================================================="
 | 
						|
		if prompt_yn "The new server configuration file differs from what's installed. Use it?"
 | 
						|
		then
 | 
						|
			echo "Updating the server configuration file"
 | 
						|
			cp "${SERVER_CFG_SRC}" "${SERVER_CFG_DST}"
 | 
						|
		else
 | 
						|
			echo "NOT updating the server configuration file"
 | 
						|
		fi
 | 
						|
	fi
 | 
						|
}
 | 
						|
 | 
						|
# Update the server files.
 | 
						|
update(){
 | 
						|
	dologin
 | 
						|
	appmanifestfile=${SERVER_FILES}/steamapps/appmanifest_"${release_server_appid}".acf
 | 
						|
	printf "[ ... ] Checking for update:"
 | 
						|
	# gets currentbuild
 | 
						|
	currentbuild=$(grep buildid "${appmanifestfile}" | tr '[:blank:]"' ' ' | tr -s ' ' | cut -d \  -f3)
 | 
						|
	# Removes appinfo.vdf as a fix for not always getting up to date version info from SteamCMD
 | 
						|
	if [ -f "${HOME}/Steam/appcache/appinfo.vdf" ]
 | 
						|
	then
 | 
						|
		rm -f "${HOME}/Steam/appcache/appinfo.vdf"
 | 
						|
	fi
 | 
						|
	# check for new build
 | 
						|
	availablebuild=$(${STEAMCMD} +login "${steamlogin}" +app_info_update 1 +app_info_print "${release_server_appid}" +app_info_print \
 | 
						|
	  "${release_server_appid}" +quit | sed -n '/branch/,$p' | grep -m 1 buildid | tr -cd '[:digit:]')
 | 
						|
	if [ -z "${availablebuild}" ]
 | 
						|
	then
 | 
						|
		printf "\r[ ${red}FAIL${default} ] Checking for update:\n"
 | 
						|
		printf "\r[ ${red}FAIL${default} ] Checking for update:: Not returning version info\n"
 | 
						|
		exit
 | 
						|
	else
 | 
						|
		printf "\r[ ${green}OK${default} ] Checking for update:"
 | 
						|
	fi
 | 
						|
	# compare builds
 | 
						|
	if [ "${currentbuild}" != "${availablebuild}" ] || [[ ${1} = "force" ]]
 | 
						|
	then
 | 
						|
		printf "\r[ ${green}OK${default} ] Checking for update:: Update available\n"
 | 
						|
		printf "Update available:\n"
 | 
						|
		printf "\tCurrent build: ${red}${currentbuild}${default}\n"
 | 
						|
		printf "\tAvailable build: ${green}${availablebuild}${default}\n"
 | 
						|
		printf "\thttps://steamdb.info/app/${release_server_appid}/\n"
 | 
						|
		printf "\nApplying update"
 | 
						|
		# run update
 | 
						|
		dologin
 | 
						|
		${STEAMCMD} +force_install_dir ${SERVER_FILES} +login "${steamlogin}" +app_update "${release_server_appid}" validate +quit
 | 
						|
		modupdate
 | 
						|
	else
 | 
						|
		printf "\r[ ${green}OK${default} ] Checking for update:: No update available\n"
 | 
						|
		printf "\nNo update available:\n"
 | 
						|
		printf "\tCurrent version: ${green}${currentbuild}${default}\n"
 | 
						|
		printf "\tAvailable version: ${green}${availablebuild}${default}\n"
 | 
						|
		printf "\thttps://steamdb.info/app/${release_server_appid}/\n\n"
 | 
						|
	fi
 | 
						|
}
 | 
						|
 | 
						|
# Assemble the workshop list variable
 | 
						|
get_mods(){
 | 
						|
	mapfile -t workshopID < "${WORKSHOP_CFG}"
 | 
						|
	workshoplist=""
 | 
						|
	for i in "${workshopID[@]}"
 | 
						|
	do
 | 
						|
		workshoplist+=" +workshop_download_item "${release_client_appid}" "$i""
 | 
						|
	done
 | 
						|
}
 | 
						|
 | 
						|
# Update mods
 | 
						|
modupdate(){
 | 
						|
	get_mods
 | 
						|
	echo "Updating mods..."
 | 
						|
	dologin
 | 
						|
	${STEAMCMD} +force_install_dir ${SERVER_FILES} +login "${steamlogin}" ${workshoplist} +quit
 | 
						|
	# Updated files come in with mixed cases. Fix that.
 | 
						|
	echo -n "Fixing file names..."
 | 
						|
	find "${workshopfolder}" -depth -exec rename -f 's/(.*)\/([^\/]*)/$1\/\L$2/' {} \;
 | 
						|
	echo "done"
 | 
						|
	echo
 | 
						|
}
 | 
						|
 | 
						|
# Add a mod
 | 
						|
add(){
 | 
						|
	if [ -d "${workshopfolder}/${1}" ]
 | 
						|
	then
 | 
						|
		echo -e "${yellow}Warning: The mod directory ${workshopfolder}/${1} already exists!${default}"
 | 
						|
		MODNAME=$(cut -d '"' -f 2 <<< $(grep name ${workshopfolder}/${1}/meta.cpp))
 | 
						|
	fi
 | 
						|
	if [ -L "${SERVER_FILES}/@${MODNAME}" ]
 | 
						|
	then
 | 
						|
		echo -e "${yellow}Warning: The mod symlink ${SERVER_FILES}/@${MODNAME} already exists!${default}"
 | 
						|
	fi
 | 
						|
	if grep -qP "\b${1}\b" "${WORKSHOP_CFG}"
 | 
						|
	then
 | 
						|
		echo "The mod with id ${1} is already in the workshop configuration."
 | 
						|
		return
 | 
						|
	fi
 | 
						|
	echo "Adding mod id ${1}"
 | 
						|
	echo "${1}:MODNAME:1" >> ${WORKSHOP_CFG}
 | 
						|
	modupdate
 | 
						|
	# Make sure the install succeeded
 | 
						|
	if [ ! -d "${workshopfolder}/${1}" ]
 | 
						|
	then
 | 
						|
		echo -e "${red}Mod installation failed: The mod directory ${workshopfolder}/${1} was not created!${default}"
 | 
						|
		echo "Installation failed! See above (You probably need to use a real Steam login)"
 | 
						|
		# The mod is added temporarily into the workshop config. Since the installation failed, reemove it instead of updating it.
 | 
						|
		head -n-1 "${WORKSHOP_CFG}" > /tmp/workshop.cfg.tmp
 | 
						|
		mv /tmp/workshop.cfg.tmp "${WORKSHOP_CFG}"
 | 
						|
		return
 | 
						|
	fi
 | 
						|
	# Get the name of the newly added mod
 | 
						|
	MODNAME=$(cut -d '"' -f 2 <<< $(grep name ${workshopfolder}/${1}/meta.cpp))
 | 
						|
	symlink ${1} "${MODNAME}"
 | 
						|
	# Lower case all the files in mod directories.
 | 
						|
	find "${workshopfolder}/${1}" -depth -exec rename -f 's/(.*)\/([^\/]*)/$1\/\L$2/' {} \;
 | 
						|
	# Copy the key files
 | 
						|
	copy_keys ${1}
 | 
						|
	# Set the mod name in the workshop config file, as we don't know this at the start.
 | 
						|
	sed -i "${WORKSHOP_CFG}" -e "s/${1}:MODNAME/${1}:${MODNAME}/"
 | 
						|
	echo -e "Mod id ${1} - ${green}${MODNAME}${default} - added"
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
# Remove a mod
 | 
						|
remove(){
 | 
						|
	if [ -d "${workshopfolder}/${1}" ]
 | 
						|
	then
 | 
						|
		MODNAME=$(cut -d '"' -f 2 <<< $(grep name ${workshopfolder}/${1}/meta.cpp))
 | 
						|
		echo "Removing directory ${workshopfolder}/${1}"
 | 
						|
		rm -rf "${workshopfolder}/${1}"
 | 
						|
	fi
 | 
						|
	if [ -L "${SERVER_FILES}/@${MODNAME}" ]
 | 
						|
	then
 | 
						|
		echo "Removing symlink ${SERVER_FILES}/@${MODNAME}"
 | 
						|
		rm -f "${SERVER_FILES}/@${MODNAME}"
 | 
						|
	fi
 | 
						|
	if grep -q ${1} "${WORKSHOP_CFG}"
 | 
						|
	then
 | 
						|
		echo "Removing workshop file entry"
 | 
						|
		sed -i "${WORKSHOP_CFG}" -e "/${1}:/d" 
 | 
						|
	fi
 | 
						|
	echo "Mod id ${1} - ${MODNAME} - removed"
 | 
						|
}
 | 
						|
 | 
						|
# Activate / Deactivate a mod
 | 
						|
activate(){
 | 
						|
	W=${1}
 | 
						|
	shift
 | 
						|
	WW=""
 | 
						|
	if [[ ${W} = 0 ]]
 | 
						|
	then
 | 
						|
		WW="de"
 | 
						|
	fi
 | 
						|
	get_mods
 | 
						|
	X=1
 | 
						|
	# Loop over mod list
 | 
						|
	for i in "${workshopID[@]}"
 | 
						|
	do
 | 
						|
		ID=$(echo ${i} | cut -d: -f1)
 | 
						|
		NAME=$(echo ${i} | cut -d: -f2)
 | 
						|
		ACTIVE=$(echo ${i} | cut -d: -f3)
 | 
						|
		# Find mod by ID or index
 | 
						|
		if [[ ${ID} = ${1} ]] || [[ ${X} = ${1} ]]
 | 
						|
		then
 | 
						|
			# Toggle state or report nothing burger
 | 
						|
			if [[ "${ACTIVE}" != "${W}" ]]
 | 
						|
			then
 | 
						|
				sed -i "${WORKSHOP_CFG}" -e "s/${ID}:${NAME}:[0-1]/${ID}:${NAME}:${W}/"
 | 
						|
				symlink ${W} ${ID} "${NAME}"
 | 
						|
				copy_keys ${W} ${ID}
 | 
						|
				echo "Mod id ${ID} - ${WW}activated"
 | 
						|
			else
 | 
						|
				echo -e "Mod id ${ID} - ${green}${NAME}${default} - is already ${WW}active"
 | 
						|
			fi
 | 
						|
		fi
 | 
						|
		X=$((X+1))
 | 
						|
	done
 | 
						|
	list
 | 
						|
}
 | 
						|
 | 
						|
# List mods
 | 
						|
list(){
 | 
						|
	get_mods
 | 
						|
	X=1
 | 
						|
	spaces="                        "
 | 
						|
	echo -e "     ID          Name                     Active URL"
 | 
						|
	echo "---------------------------------------------------------------------------------------------------------------------"
 | 
						|
	for i in "${workshopID[@]}"
 | 
						|
	do
 | 
						|
		ID=$(echo ${i} | cut -d: -f1)
 | 
						|
		NAME=$(echo ${i} | cut -d: -f2)
 | 
						|
		ACTIVE=$(echo ${i} | cut -d: -f3)
 | 
						|
		if [[ ${ACTIVE} = "1" ]]
 | 
						|
		then
 | 
						|
			C="${green}"
 | 
						|
		else
 | 
						|
			C="${red}"
 | 
						|
		fi
 | 
						|
		printf "${C}%.3d  %s %.23s  %s %s      https://steamcommunity.com/sharedfiles/filedetails/?id=%s${default}\n" ${X} ${ID} "${NAME}" "${spaces:${#NAME}+1}" ${ACTIVE} ${ID}
 | 
						|
		X=$((X+1))
 | 
						|
	done
 | 
						|
}
 | 
						|
 | 
						|
# Copy mod keys
 | 
						|
copy_keys(){
 | 
						|
	if [[ ${1} = 1 ]]
 | 
						|
	then
 | 
						|
		echo "Copying key files..."
 | 
						|
		cp -v ${workshopfolder}/${2}/keys/* "${SERVER_FILES}/keys/"
 | 
						|
	fi
 | 
						|
}
 | 
						|
 | 
						|
# Symlink mods
 | 
						|
symlink(){
 | 
						|
	W=${1}
 | 
						|
	shift
 | 
						|
	ID=${1}
 | 
						|
	NAME=${2}
 | 
						|
	# Symlink it
 | 
						|
	if [ ! -L "${SERVER_FILES}/@${NAME}" ] && [[ ${W} = 1 ]]
 | 
						|
	then
 | 
						|
		ln -sv ${workshopfolder}/${ID} "${SERVER_FILES}/@${NAME}"
 | 
						|
#		echo "Created symlink ${workshopfolder}/${ID} ${SERVER_FILES}/@${NAME}"
 | 
						|
	elif [[ "${W}" = "0" ]]
 | 
						|
	then
 | 
						|
		rm -vf "${SERVER_FILES}/@${NAME}"
 | 
						|
	fi
 | 
						|
#	echo "Symlink ${SERVER_FILES}/@${NAME} managed"
 | 
						|
}
 | 
						|
 | 
						|
# Assemble the mod command line
 | 
						|
mod_cmd(){
 | 
						|
	get_mods
 | 
						|
	mod_command_line=""
 | 
						|
	for i in "${workshopID[@]}"
 | 
						|
	do
 | 
						|
		NAME=$(echo ${i} | cut -d: -f2)
 | 
						|
		ACTIVE=$(echo ${i} | cut -d: -f3)
 | 
						|
		if [[ ${ACTIVE} = "1" ]]
 | 
						|
		then
 | 
						|
			mod_command_line="${mod_command_line}@${NAME};"
 | 
						|
		fi
 | 
						|
	done
 | 
						|
	if [[ ${mod_command_line} != "" ]]
 | 
						|
	then
 | 
						|
		mod_command_line='-mod='${mod_command_line::-1}
 | 
						|
	fi
 | 
						|
}
 | 
						|
 | 
						|
# Our internal RCON
 | 
						|
rcon(){
 | 
						|
	exec /usr/local/py3rcon/py3rcon.py --gui ~/py3rcon.config.json
 | 
						|
}
 | 
						|
 | 
						|
# Display the status of everything
 | 
						|
status(){
 | 
						|
	INSTALLED="${NO}"
 | 
						|
	LOGGED_IN="${NO}"
 | 
						|
	RUNNING="${NO}"
 | 
						|
	get_mods
 | 
						|
 | 
						|
	MODS_INSTALLED=""
 | 
						|
	A=0
 | 
						|
	for i in "${workshopID[@]}"
 | 
						|
	do
 | 
						|
		ID=$(echo ${i} | cut -d: -f1)
 | 
						|
		NAME=$(echo ${i} | cut -d: -f2)
 | 
						|
		ACTIVE=$(echo ${i} | cut -d: -f3)
 | 
						|
		if [[ ${ACTIVE} = "1" ]]
 | 
						|
		then
 | 
						|
			C="${green}"
 | 
						|
			A=$((A+1))
 | 
						|
		else
 | 
						|
			C="${red}"
 | 
						|
		fi
 | 
						|
		MODS_INSTALLED="${MODS_INSTALLED}  ${C}${NAME}${default}\n"
 | 
						|
	done
 | 
						|
	MODS_INSTALLED="Mods installed: ${green}${#workshopID[@]}${default} Active: ${green}${A}${default}\n${MODS_INSTALLED}"
 | 
						|
 | 
						|
	# DayZ Server files installation
 | 
						|
	if [ -f "${SERVER_INSTALL_FILE}" ]
 | 
						|
	then
 | 
						|
		INSTALLED="${YES}"
 | 
						|
	fi
 | 
						|
	# Logged into Steam
 | 
						|
	if [ -f "${STEAM_LOGIN}" ]
 | 
						|
	then
 | 
						|
		LOGGED_IN="${YES}"
 | 
						|
		if grep -q anonymous "${STEAM_LOGIN}"
 | 
						|
		then
 | 
						|
			ANONYMOUS="${yellow}(as anonymous)${default}"
 | 
						|
		else
 | 
						|
			ANONYMOUS="${green}(not anonymous)${default}"
 | 
						|
		fi
 | 
						|
	fi
 | 
						|
	# Running or not
 | 
						|
	if pidof DayZServer > /dev/null
 | 
						|
	then
 | 
						|
		# Uptime
 | 
						|
		UPTIME=$(date -d@$(($(date +%s) - $(date +%s -r ${SERVER_PROFILE}/server_console.log))) -u +%H:%M:%S)
 | 
						|
		RUNNING="${YES}\nUptime: ${green}${UPTIME}${default}"
 | 
						|
		# Current parameters
 | 
						|
		RUNNING="${RUNNING}\nRunning Parameters: $(cat /tmp/parameters)\nRunning mod parameter: $(cat /tmp/mod_command_line)"
 | 
						|
	fi
 | 
						|
	mod_cmd
 | 
						|
	# Map name
 | 
						|
#	MAP=$(grep -E "template=" ${SERVER_CFG_DST} | grep -vE "^//")
 | 
						|
	# Number of mods plus the list denoting on or off
 | 
						|
	echo -e "
 | 
						|
Logged in to Steam: ${LOGGED_IN} ${ANONYMOUS}
 | 
						|
Server files installed: ${INSTALLED}
 | 
						|
${MODS_INSTALLED}Server running: ${RUNNING}
 | 
						|
Working parameters:${parameters}
 | 
						|
Working mod parameter: ${mod_command_line}
 | 
						|
"
 | 
						|
}
 | 
						|
 | 
						|
backup(){
 | 
						|
	cd "${SERVER_FILES}"/mpmissions
 | 
						|
	for i in $(find -type d -name storage_1)
 | 
						|
	do
 | 
						|
		echo "Backing up ${i}..."
 | 
						|
		D=$(date +'%Y-%m-%d-%H-%M-%S')
 | 
						|
		B="${BACKUP_DIR}/${i}-${D}"
 | 
						|
		mkdir -p "${B}"
 | 
						|
		cp -a "${i}" "${B}"
 | 
						|
		echo
 | 
						|
	done
 | 
						|
}
 | 
						|
 | 
						|
# Capture the first argument and shift it off so we can pass $@ to every function
 | 
						|
C=${1}
 | 
						|
shift
 | 
						|
 | 
						|
case "${C}" in
 | 
						|
	a|activate)
 | 
						|
		activate 1 "${@}"
 | 
						|
		;;
 | 
						|
	add)
 | 
						|
		add "${@}"
 | 
						|
		;;
 | 
						|
	b|backup)
 | 
						|
		backup "${@}"
 | 
						|
		;;
 | 
						|
	cmd)
 | 
						|
		mod_cmd "${@}"
 | 
						|
		;;
 | 
						|
	c|config)
 | 
						|
		config "${@}"
 | 
						|
		;;    
 | 
						|
	d|deactivate)
 | 
						|
		activate 0 "${@}"
 | 
						|
		;;
 | 
						|
	f|force)
 | 
						|
		force
 | 
						|
		;;
 | 
						|
	i|install)
 | 
						|
		install "${@}"
 | 
						|
		;;
 | 
						|
	l|list)
 | 
						|
		list "${@}"
 | 
						|
		;;
 | 
						|
	login)
 | 
						|
		login "${@}"
 | 
						|
		;;
 | 
						|
	m|modupdate)
 | 
						|
		modupdate "${@}"
 | 
						|
		;;
 | 
						|
	n|rcon)
 | 
						|
		rcon "${@}"
 | 
						|
		;;
 | 
						|
	r|remove)
 | 
						|
		remove "${@}"
 | 
						|
		;;
 | 
						|
	restart)
 | 
						|
		restart "${@}"
 | 
						|
		;;
 | 
						|
	start)
 | 
						|
		start "${@}"
 | 
						|
		;;
 | 
						|
	s|status)
 | 
						|
		status "${@}"
 | 
						|
		;;
 | 
						|
	stop)
 | 
						|
		stop "${@}"
 | 
						|
		;;
 | 
						|
	u|update)
 | 
						|
		update "${@}"
 | 
						|
		;;
 | 
						|
	**)
 | 
						|
		usage "$*"
 | 
						|
	;;
 | 
						|
esac
 |