#!/bin/bash

### WARNING -- READ NOW -- THAT MEANS YOU!
# This is a TEMPLATE service script and will NOT WORK as is.
#
# You MUST create a copy of this script for EACH of your SvenDS profiles you
# intend to run, and  replace the following strings (with `sed` or your
# favourite text editor) as follows:
#
# $$GAME_PATH$$         Path to your base SvenDS installation as delivered by
#                       SteamCMD, e.g. "/home/svc.svends/SvenDS-public".
#
# $$SERVER_LOGIN$$      User on the system of which will be running the SvenDS
#                       instance. (NEVER use "root" for this!)
#
# $$MOD_NAME$$          The name of the SvenDS mod, almost always "svencoop".
#
# $$PROFILE_NAME$$      The folder name of your SvenDS profile, e.g. "public1".
#                       This will form part of the system service name prefixed
#                       with "svends-", e.g. "svends-public1".
#
# $$PROFILE_PATH$$      The relative path of your SvenDS profile relative to the
#                       mod folder, e.g. "servers/public1". Ensure that a "logs"
#                       folder exists within this.
#
# $$PROFILE_ADDRESS$$   The IP address SvenDS will listen on. (This must be
#                       assigned to a NIC on this system. Do not specify an
#                       external or public IP address assigned to a NAT gateway.
#
# $$PROFILE_PORT$$      The UDP port SvenDS will listen on.
#
# $$MAX_PLAYERS$$       The number of player slots SvenDS will create. (2-32)
#
# $$DEFAULT_MAP$$       The map SvenDS should start running. This is best set as
#                       "_server_start", as this will give your SvenDS plug-ins
#                       an opportunity to initialise, along with the map cycle.
#
# N.B. The IP address and port when combined must be unique for each SvenDS
# profile running concurrently.
#
# If you seriously know what you're doing you're welcome to edit this script to
# trim out variables you'll never need (potentially "$$PROFILE_ADDRESS$$".)
#
# After you have completed this place this script in EACH of your SvenDS profile
# folders, then call it as root with the "install" action. (You cannot install
# the service as the non-root user of which will be running SvenDS.)
#
# Ensure you have GNU Screen installed too. The SvenDS instances will get their
# own Screen instance running as the user specified, so you can attach to it at
# any point to see and interact with the SvenDS console at runtime.
### WARNING -- READ NOW -- THAT MEANS YOU!

### BEGIN INIT INFO
# Provides:             svends-$$PROFILE_NAME$$
# Default-Start:        2 3 4 5
# Default-Stop:         1
# Short-Description:    Sven Co-op dedicated server: Profile $$PROFILE_NAME$$
### END INIT INFO

set -e

DAEMON="$$GAME_PATH$$/svends_run"
NAME="svends-$$PROFILE_NAME$$"
PATH="/sbin:/bin:/usr/sbin:/usr/bin:$$GAME_PATH$$"
LOGFILE="/var/log/svends-$$PROFILE_NAME$$.log"
CHROOT="$$GAME_PATH$$"
USER=$(whoami)

test -x "${DAEMON}" || exit 1

if [ ! -e "${LOGFILE}" ]; then
	touch "${LOGFILE}"
	chmod 640 "${LOGFILE}"
	chown root:adm "${LOGFILE}"
fi

if [ ! -d "${CHROOT}" ]; then
	mkdir -p -m 0755 "${CHROOT}"
fi



BIN_INTERFACE="/usr/bin/screen -AdmS ${NAME}"

DIR_GAME="$$GAME_PATH$$"
BIN_GAME="$$GAME_PATH$$/svends_run"
SERVICE_USER="$$SERVER_LOGIN$$"
SERVICE_SCRIPT="$$PROFILE_PATH$$/service.sh"
SERVICE_SCRIPT_FILE="/etc/init.d/${NAME}"
FILE_PID="$$PROFILE_PATH$$/$$PROFILE_NAME$$.pid"
FILE_SCREEN_PID="$$PROFILE_PATH$$/$$PROFILE_NAME$$-screen.pid"

MOD_NAME="$$MOD_NAME$$"
PROFILE_NAME="$$PROFILE_NAME$$"
LISTEN_ADDRESS="$$PROFILE_ADDRESS$$"
LISTEN_PORT=$$PROFILE_PORT$$
MAX_PLAYERS=$$SERVER_PLAYERS$$
MAP_NAME="$$DEFAULT_MAP$$"

LAUNCH_PARAMS="-console -game ${MOD_NAME} +ip \"${LISTEN_ADDRESS}\" -port ${LISTEN_PORT} +maxplayers ${MAX_PLAYERS} \
	+servercfgfile \"$$PROFILE_PATH$$/server.cfg\" +logsdir \"$$PROFILE_PATH$$/logs\" -pidfile \"${FILE_PID}\" \"
	+log on +map \"${MAP_NAME}\""

case "$1" in
	start)
		printf "Starting \"${NAME}\"...\n\n"

		if [ $EUID -ne 0 -a "${USER}" != "${SERVICE_USER}" ]; then
			printf "[Error] Cannot start: Must be root or user ${SERVICE_USER}.\n"
			exit 100
		fi

		if [ -f "${FILE_SCREEN_PID}" ]; then
			printf "[Error] Cannot start: Already running.\n"
			exit 1
		fi

		if [ ! -f "${BIN_GAME}" ] || [ ! -x "${BIN_GAME}" ]; then
			printf "[Error] Cannot start: Server binary missing or not executable.\n"
			exit 1
		fi

		cd "${DIR_GAME}"
		if [ $EUID -ne 0 ]; then
			$BIN_INTERFACE "${BIN_GAME}" $LAUNCH_PARAMS
		else
			sudo -H -u "${SERVICE_USER}" $BIN_INTERFACE "${BIN_GAME}" $LAUNCH_PARAMS
		fi

		sleep 1
		ps -ef | grep SCREEN | grep "${NAME}" | grep -v grep | awk '{ print $2 }' > "${FILE_SCREEN_PID}"
		printf "Screen process ID file: ${FILE_SCREEN_PID}\n"
	;;

	stop)
		printf "Stopping \"${NAME}\"...\n\n"

		if [ $EUID -ne 0 -a "${USER}" != "${SERVICE_USER}" ]; then
			printf "[Error] Cannot stop: Must be root or user ${SERVICE_USER}.\n"
			exit 100
		fi

		if [ ! -f "${FILE_SCREEN_PID}" ]; then
			printf "[Error] Cannot stop: Not running.\n"
			exit 1
		fi

		for PID in $(cat "${FILE_SCREEN_PID}"); do
			printf "Killing process ID ${PID}...\n"
			kill -TERM "${PID}"
			break
		done

		printf "Removing Screen process ID file...\n"
		rm -f "${FILE_SCREEN_PID}"

		screen -wipe 1> /dev/null 2> /dev/null
	;;

	restart)
		$0 stop
		$0 start
	;;

	status)
		if [ -f "${FILE_SCREEN_PID}" ]; then
			printf "Service is running.\n"
		else
			printf "Service is not running.\n"
		fi
	;;

	install)
		if [ $EUID -ne 0 ]; then
			printf "[Error] Service installation/uninstallation can only be done as root.\n"
			exit 100
		fi

		if [ -f "${SERVICE_SCRIPT_FILE}" ]; then
			printf "[Warning] Service already installed, reinstalling.\n"

			if [ -f "${FILE_SCREEN_PID}" ]; then
				$0 stop
			fi
		fi

		cp "${SERVICE_SCRIPT}" "${SERVICE_SCRIPT_FILE}"
		printf "Service \"${NAME}\" installed.\n"
		$0 start
	;;

	uninstall)
		if [ $EUID -ne 0 ]; then
			printf "[Error] Service installation/uninstallation can only be done as root.\n"
			exit 100
		fi

		if [ ! -f "${SERVICE_SCRIPT_FILE}" ]; then
			printf "[Error] Cannot uninstall: Service not installed.\n"
		fi

		if [ -f "${FILE_SCREEN_PID}" ]; then
			$0 stop
		fi

		rm "${SERVICE_SCRIPT_FILE}"
		printf "Service \"${NAME}\" uninstalled.\n"
	;;

	*)
		if [ $EUID -ne 0 -a "${USER}" != "${SERVICE_USER}" ]; then
			printf "[Error] Cannot use: Must be root or user ${SERVICE_USER}.\n"
			exit 100
		fi

		if [ $EUID -ne 0 ]; then
			printf "Usage: ${0} start|stop|restart|status\n"
		else
			printf "Usage: ${0} start|stop|restart|status|install|uninstall\n"
		fi
	;;
esac
