mirror of
				https://ceregatti.org/git/daniel/dayzdockerserver.git
				synced 2025-11-04 07:13:34 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			376 lines
		
	
	
	
		
			9.7 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			376 lines
		
	
	
	
		
			9.7 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable file
		
	
	
	
	
#!/usr/bin/env bash
 | 
						|
 | 
						|
source dz-common
 | 
						|
 | 
						|
# An array to store Workshop items. Each element contains the mod's ID, name, and state (active or not).
 | 
						|
WORKSHOP_DIR="/mods/${release_client_appid}"
 | 
						|
if [ ! -d ${WORKSHOP_DIR} ]
 | 
						|
then
 | 
						|
	mkdir -p ${WORKSHOP_DIR}
 | 
						|
fi
 | 
						|
 | 
						|
workshoplist=""
 | 
						|
 | 
						|
# Functions
 | 
						|
 | 
						|
# Usage
 | 
						|
usage(){
 | 
						|
	echo -e "
 | 
						|
${red}Bad option or arguments! ${yellow}${*}${default}
 | 
						|
 | 
						|
Usage: ${green}$(basename $0)${yellow} option [ arg1 [ arg2 ] ]
 | 
						|
 | 
						|
Options and arguments:
 | 
						|
 | 
						|
  a|add id - Add a DayZ Workshop item by id. Added items become active by default
 | 
						|
  i|install - Install the DayZ server files
 | 
						|
  g|login - Login to Steam.
 | 
						|
  m|modupdate - Update the mod files
 | 
						|
  p|map id - Install a mod's mpmissions files by id. (Presumes template exists)
 | 
						|
  r|remove id - Remove all files and directories of a Workshop item by id
 | 
						|
  l|s|status - Shows Steam login status, if base files are installed, installed mods
 | 
						|
  u|update - Update the server files
 | 
						|
  x|xml id - Get and normalize XML files from a mod's template by id (Presumes template exists)
 | 
						|
${default}"
 | 
						|
  exit 1
 | 
						|
}
 | 
						|
 | 
						|
# Manage the mod symlink
 | 
						|
symlink(){
 | 
						|
	W=${1}
 | 
						|
	ID=${2}
 | 
						|
	NAME=${3}
 | 
						|
	if [ ! -L "${SERVER_FILES}/@${NAME}" ] && [[ ${W} = 1 ]]
 | 
						|
	then
 | 
						|
		ln -sv ${WORKSHOP_DIR}/${ID} "${SERVER_FILES}/@${NAME}"
 | 
						|
	elif [[ "${W}" = "0" ]]
 | 
						|
	then
 | 
						|
		rm -vf "${SERVER_FILES}/@${NAME}"
 | 
						|
	fi
 | 
						|
}
 | 
						|
 | 
						|
installxml(){
 | 
						|
	ID=${1}
 | 
						|
	# Going to have to maintain a matrix of file names -> root node -> child node permutations
 | 
						|
	for i in "CFGEVENTGROUPS:eventgroupdef:group" "CFGEVENTSPAWNS:eventposdef:event" "CFGSPAWNABLETYPES:spawnabletypes:type" "EVENTS:events:event" "TYPES:types:type"
 | 
						|
	do
 | 
						|
		var=$(echo ${i} | cut -d: -f1)
 | 
						|
		CHECK=$(echo ${i} | cut -d: -f2)
 | 
						|
		if [ -f "${WORKSHOP_DIR}/${ID}/${var,,}.xml" ]
 | 
						|
		then
 | 
						|
			echo "Normalizing ${WORKSHOP_DIR}/${ID}/${var,,}.xml..."
 | 
						|
			cp ${WORKSHOP_DIR}/${ID}/${var,,}.xml /tmp/x
 | 
						|
			# Quirks
 | 
						|
			# Some cfgeventspanws.xml files have <events> instead of <eventposdef>. Let's just try to fix that first.
 | 
						|
			if [[ ${var} = "CFGEVENTSPAWNS" ]]
 | 
						|
			then
 | 
						|
				if grep -q '<events>' /tmp/x
 | 
						|
				then
 | 
						|
					echo "  - (Quirk) has <events> instead of <eventposdef>. fixing..."
 | 
						|
					xmlstarlet ed -L -r "events" -v "eventposdef" /tmp/x
 | 
						|
				fi
 | 
						|
			fi
 | 
						|
			if ! grep -q '<'${CHECK}'>' /tmp/x
 | 
						|
			then
 | 
						|
				echo "  - has no root node <${CHECK}>. fixing..."
 | 
						|
				echo '<'${CHECK}'>' > /tmp/y
 | 
						|
				cat /tmp/x >> /tmp/y
 | 
						|
				echo '</'${CHECK}'>' >> /tmp/y
 | 
						|
				xmlstarlet fo /tmp/y > /tmp/x
 | 
						|
			fi
 | 
						|
			if ! grep -q '<?xml' /tmp/x
 | 
						|
			then
 | 
						|
				echo "  - has no XML node, fixing..."
 | 
						|
				xmlstarlet fo /tmp/x > /tmp/y
 | 
						|
				mv /tmp/y /tmp/x
 | 
						|
			fi
 | 
						|
			lint /tmp/x ${ID} ${var}
 | 
						|
		fi
 | 
						|
	done
 | 
						|
}
 | 
						|
 | 
						|
# Add a mod
 | 
						|
add(){
 | 
						|
	if [ -d "${WORKSHOP_DIR}/${1}" ]
 | 
						|
	then
 | 
						|
		echo -e "${yellow}Warning: The mod directory ${WORKSHOP_DIR}/${1} already exists!${default}"
 | 
						|
		MODNAME=$(get_mod_name ${1})
 | 
						|
	fi
 | 
						|
	if [ -L "${SERVER_FILES}/@${MODNAME}" ]
 | 
						|
	then
 | 
						|
		echo -e "${yellow}Warning: The mod symlink ${SERVER_FILES}/@${MODNAME} already exists!${default}"
 | 
						|
	fi
 | 
						|
	echo "Adding mod id ${1}"
 | 
						|
	dologin
 | 
						|
	${STEAMCMD} +force_install_dir ${SERVER_FILES} +login "${steamlogin}" +workshop_download_item "${release_client_appid}" "${1}" +quit
 | 
						|
	# Make sure the install succeeded
 | 
						|
	if [ ! -d "${WORKSHOP_DIR}/${1}" ]
 | 
						|
	then
 | 
						|
		echo -e "${red}Mod installation failed: The mod directory ${WORKSHOP_DIR}/${1} was not created!${default}"
 | 
						|
		echo "Installation failed! See above (You probably need to use a real Steam login)"
 | 
						|
		return
 | 
						|
	fi
 | 
						|
	# Get the name of the newly added mod
 | 
						|
	MODNAME=$(get_mod_name ${1})
 | 
						|
	symlink 1 ${1} "${MODNAME}"
 | 
						|
	echo -e "Mod id ${1} - ${green}${MODNAME}${default} - added"
 | 
						|
	xml ${ID}
 | 
						|
	installMod ${ID}
 | 
						|
	map ${ID}
 | 
						|
}
 | 
						|
 | 
						|
# Remove a mod
 | 
						|
remove(){
 | 
						|
	DIR="${WORKSHOP_DIR}/${1:?}"
 | 
						|
	if [ -d "${DIR}" ]
 | 
						|
	then
 | 
						|
		MODNAME=$(get_mod_name ${1})
 | 
						|
		echo "Removing directory ${DIR}"
 | 
						|
		rm -rf "${DIR}"
 | 
						|
	else
 | 
						|
		echo "Directory ${DIR} doesn't exist?"
 | 
						|
	fi
 | 
						|
	if [ -L "${SERVER_FILES}/@${MODNAME}" ]
 | 
						|
	then
 | 
						|
		echo "Removing symlink ${SERVER_FILES}/@${MODNAME}"
 | 
						|
		rm -f "${SERVER_FILES}/@${MODNAME}"
 | 
						|
	else
 | 
						|
		echo "Symlink ${SERVER_FILES}/@${MODNAME} doesn't exist?"
 | 
						|
	fi
 | 
						|
	echo -e "Mod id ${1} - ${red}${MODNAME}${default} - removed"
 | 
						|
}
 | 
						|
 | 
						|
# Handle custom scripts after installing a mod
 | 
						|
installMod(){
 | 
						|
	FILE="${FILES}/mods/${1}/install.sh"
 | 
						|
	if [ -f "${FILE}" ]
 | 
						|
	then
 | 
						|
		MODNAME=$(get_mod_name ${1})
 | 
						|
		echo
 | 
						|
		echo "Running custom install script for ${MODNAME}"
 | 
						|
		${FILE}
 | 
						|
	fi
 | 
						|
}
 | 
						|
 | 
						|
# Handle the Steam login information.
 | 
						|
login(){
 | 
						|
	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(){
 | 
						|
	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(){
 | 
						|
	if [ ! -f "${SERVER_INSTALL_FILE}" ] || [[ ${1} = "force" ]]
 | 
						|
	then
 | 
						|
		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
 | 
						|
		# This installs the mpmissions for charnarusplus and enoch (AKA Livonia) from github. The game once allowed the full server
 | 
						|
		# to be downloaded, but now you get the server without any mpmissions. This is a workaround.
 | 
						|
		echo "Installing mpmissions for ChernarusPlus and Livonia from github..."
 | 
						|
		map default
 | 
						|
	else
 | 
						|
		printf "[ ${lightblue}DayZ${default} ] The server is already installed.\n"
 | 
						|
	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}" +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
 | 
						|
}
 | 
						|
 | 
						|
# Update mods
 | 
						|
modupdate(){
 | 
						|
	echo "Updating mods..."
 | 
						|
	dologin
 | 
						|
	get_mods
 | 
						|
	${STEAMCMD} +force_install_dir ${SERVER_FILES} +login "${steamlogin}" ${workshoplist} +quit
 | 
						|
	# Updated files come in with mixed cases. Fix that.
 | 
						|
	echo "done"
 | 
						|
	echo
 | 
						|
}
 | 
						|
 | 
						|
# Display the status of everything
 | 
						|
status(){
 | 
						|
	INSTALLED="${NO}"
 | 
						|
	LOGGED_IN="${NO}"
 | 
						|
 | 
						|
	# 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
 | 
						|
	echo -ne "
 | 
						|
Logged in to Steam: ${LOGGED_IN} ${ANONYMOUS}
 | 
						|
Server files installed: ${INSTALLED}"
 | 
						|
	if [[ "${INSTALLED}" = "${NO}" ]]
 | 
						|
	then
 | 
						|
		echo
 | 
						|
		echo
 | 
						|
		exit 0
 | 
						|
	fi
 | 
						|
	# Version of DayZ Server files
 | 
						|
	echo -ne "
 | 
						|
Version: ${VERSION}"
 | 
						|
 | 
						|
	# Mods
 | 
						|
	echo
 | 
						|
	MODS=$(list)
 | 
						|
	if [[ ${MODS} == "" ]]
 | 
						|
	then
 | 
						|
		echo -ne "${red}none${default}"
 | 
						|
	fi
 | 
						|
	echo -e "${MODS}"
 | 
						|
}
 | 
						|
 | 
						|
map(){
 | 
						|
	# Install map mpmissions for mods that have them. Presumes a map.env was created for the mod, with the required metadata (git URL, etc.)
 | 
						|
	WHICH="map"
 | 
						|
	if [[ "${1}" =~ ^[0-9]+$ ]]
 | 
						|
	then
 | 
						|
		WHICH="mod id"
 | 
						|
	fi
 | 
						|
	if [ -f "${FILES}/mods/${1}/map.env" ]
 | 
						|
	then
 | 
						|
		echo "Installing mpmissions files for ${WHICH} ${1}..."
 | 
						|
		source ${FILES}/mods/${1}/map.env
 | 
						|
		${FILES}/bin/map.sh ${1} install
 | 
						|
	fi
 | 
						|
}
 | 
						|
 | 
						|
mod_install(){
 | 
						|
	if [ -f ${FILES}/mods/${1}/${2}.sh ]
 | 
						|
	then
 | 
						|
		echo "An ${2}.sh was found for mod id ${1}. Running..."
 | 
						|
		${FILES}/mods/${1}/${2}.sh
 | 
						|
	fi
 | 
						|
	# A generic map install script. Presumes a git repo as the source
 | 
						|
}
 | 
						|
 | 
						|
# "Manage" XML files.
 | 
						|
xml(){
 | 
						|
	/files/bin/xml.sh ${1}
 | 
						|
	installxml ${1}
 | 
						|
}
 | 
						|
 | 
						|
# Capture the first argument and shift it off so we can pass $@ to every function
 | 
						|
C=${1}
 | 
						|
shift || {
 | 
						|
	usage
 | 
						|
}
 | 
						|
 | 
						|
case "${C}" in
 | 
						|
	a|add)
 | 
						|
		add "${@}"
 | 
						|
		;;
 | 
						|
	i|install)
 | 
						|
		install "${@}"
 | 
						|
		;;
 | 
						|
	g|login)
 | 
						|
		login "${@}"
 | 
						|
		;;
 | 
						|
	m|modupdate)
 | 
						|
		modupdate "${@}"
 | 
						|
		;;
 | 
						|
	r|remove)
 | 
						|
		remove "${@}"
 | 
						|
		;;
 | 
						|
	l|s|status)
 | 
						|
		status "${@}"
 | 
						|
		;;
 | 
						|
	p|map)
 | 
						|
		map "${@}"
 | 
						|
		;;
 | 
						|
	u|update)
 | 
						|
		update "${@}"
 | 
						|
		;;
 | 
						|
	x|xml)
 | 
						|
		xml "${@}"
 | 
						|
		;;
 | 
						|
	*)
 | 
						|
		usage "$*"
 | 
						|
	;;
 | 
						|
esac
 |