Przeglądaj źródła

Merge branch 'feature/factorio'

Conflicts:
	lgsm/functions/command_details.sh
Daniel Gibbs 9 lat temu
rodzic
commit
28ba1ea9dd

+ 3 - 0
lgsm/functions/check_deps.sh

@@ -202,6 +202,9 @@ if [ -n "$(command -v dpkg-query)" ]; then
 	# GoldenEye: Source
 	elif [ "${gamename}" ==  "GoldenEye: Source" ]; then
 		array_deps_required+=( zlib1g:i386 libldap-2.4-2:i386 )
+	# Serious Sam 3: BFE
+	elif [ "${gamename}" ==  "Serious Sam 3: BFE" ]; then
+		array_deps_required+=( libxrandr2:i386 libglu1-mesa:i386 libxtst6:i386 libusb-1.0-0-dev:i386 libxxf86vm1:i386 libopenal1:i386 libssl1.0.0:i386 libgtk2.0-0:i386 libdbus-glib-1-2:i386 libnm-glib-dev:i386 )		
 	# Unreal Engine
 	elif [ "${executable}" ==  "./ucc-bin" ]; then
 		#UT2K4

+ 819 - 0
lgsm/functions/command_details.sh

@@ -0,0 +1,819 @@
+#!/bin/bash
+# LGSM command_details.sh function
+# Author: Daniel Gibbs
+# Contributor: UltimateByte
+# Website: https://gameservermanagers.com
+# Description: Displays server information.
+
+local commandname="DETAILS"
+local commandaction="Details"
+local function_selfname="$(basename $(readlink -f "${BASH_SOURCE[0]}"))"
+
+# Standard Details
+# This applies to all engines
+
+fn_details_os(){
+	#
+	# Distro Details
+	# =====================================
+	# Distro:    Ubuntu 14.04.4 LTS
+	# Arch:      x86_64
+	# Kernel:    3.13.0-79-generic
+	# Hostname:  hostname
+	# tmux:      tmux 1.8
+	# GLIBC:     2.19
+
+	echo -e ""
+	echo -e "${lightyellow}Distro Details${default}"
+	printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' =
+	{
+		echo -e "${blue}Distro:\t${default}${distroname}"
+		echo -e "${blue}Arch:\t${default}${arch}"
+		echo -e "${blue}Kernel:\t${default}${kernel}"
+		echo -e "${blue}Hostname:\t${default}$HOSTNAME"
+		echo -e "${blue}tmux:\t${default}${tmuxv}"
+		echo -e "${blue}GLIBC:\t${default}${glibcversion}"
+	} | column -s $'\t' -t
+}
+
+fn_details_performance(){
+	#
+	# Performance
+	# =====================================
+	# Uptime:    55d, 3h, 38m
+	# Avg Load:  1.00, 1.01, 0.78
+	#
+	# Mem:       total   used   free  cached
+	# Physical:  741M    656M   85M   256M
+	# Swap:      0B      0B     0B
+
+	echo -e ""
+	echo -e "${lightyellow}Performance${default}"
+	printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' =
+	{
+		echo -e "${blue}Uptime:\t${default}${days}d, ${hours}h, ${minutes}m"
+		echo -e "${blue}Avg Load:\t${default}${load}"
+	} | column -s $'\t' -t
+	echo -e ""
+	{
+		echo -e "${blue}Mem:\t${blue}total\t used\t free\t cached${default}"
+		echo -e "${blue}Physical:\t${default}${physmemtotal}\t${physmemused}\t${physmemfree}\t${physmemcached}${default}"
+		echo -e "${blue}Swap:\t${default}${swaptotal}\t${swapused}\t${swapfree}${default}"
+	} | column -s $'\t' -t
+}
+
+fn_details_disk(){
+	#
+	# Storage
+	# =====================================
+	# Filesystem:   /dev/disk/by-uuid/320c8edd-a2ce-4a23-8c9d-e00a7af2d6ff
+	# Total:        15G
+	# Used:         8.4G
+	# Available:    5.7G
+	# LGSM Total:	1G
+	# Serverfiles:  961M
+	# Backups:  	2G
+
+	echo -e ""
+	echo -e "${lightyellow}Storage${default}"
+	printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' =
+	{
+		echo -e "${blue}Filesystem:\t${default}${filesystem}"
+		echo -e "${blue}Total:\t${default}${totalspace}"
+		echo -e "${blue}Used:\t${default}${usedspace}"
+		echo -e "${blue}Available:\t${default}${availspace}"
+		echo -e "${blue}LGSM Total:\t${default}${rootdirdu}"
+		echo -e "${blue}Serverfiles:\t${default}${filesdirdu}"
+		if [ -d "${backupdir}" ]; then
+			echo -e "${blue}Backups:\t${default}${backupdirdu}"
+		fi
+	} | column -s $'\t' -t
+}
+
+fn_details_gameserver(){
+	#
+	# Quake Live Server Details
+	# =====================================
+	# Server name:      ql-server
+	# Server IP:        1.2.3.4:27960
+	# RCON password:    CHANGE_ME
+	# Server password:  NOT SET
+	# Maxplayers:		16
+	# Status:           OFFLINE
+
+	echo -e ""
+	echo -e "${lightgreen}${gamename} Server Details${default}"
+	printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' =
+	{
+		# Server name
+		if [ -n "${servername}" ]; then
+			echo -e "${blue}Server name:\t${default}${servername}"
+		fi
+
+		# Server ip
+		echo -e "${blue}Server IP:\t${default}${ip}:${port}"
+
+		# Server password
+		if [ -n "${serverpassword}" ]; then
+			echo -e "${blue}Server password:\t${default}${serverpassword}"
+		fi
+
+		# RCON password
+		if [ -n "${rconpassword}" ]; then
+			echo -e "${blue}RCON password:\t${default}${rconpassword}"
+		fi
+
+		# Admin password
+		if [ -n "${adminpassword}" ]; then
+			echo -e "${blue}Admin password:\t${default}${adminpassword}"
+		fi
+
+		# Stats password (Quake Live)
+		if [ -n "${statspassword}" ]; then
+			echo -e "${blue}Stats password:\t${default}${statspassword}"
+		fi
+
+		# Maxplayers
+		if [ -n "${maxplayers}" ]; then
+			echo -e "${blue}Maxplayers:\t${default}${maxplayers}"
+		fi
+
+		# Game mode
+		if [ -n "${gamemode}" ]; then
+			echo -e "${blue}Game mode:\t${default}${gamemode}"
+		fi
+
+		# Game world
+		if [ -n "${gameworld}" ]; then
+			echo -e "${blue}Game world:\t${default}${gameworld}"
+		fi
+
+		# Tick rate
+		if [ -n "${tickrate}" ]; then
+			echo -e "${blue}Tick rate:\t${default}${tickrate}"
+		fi
+
+		# Cluster (Don't Starve Together)
+		if [ -n "${cluster}" ]; then
+			echo -e "${blue}Cluster:\t${default}${cluster}"
+		fi
+
+		# Shard (Don't Starve Together)
+		if [ -n "${shard}" ]; then
+			echo -e "${blue}Shard:\t${default}${shard}"
+		fi
+
+		# TeamSpeak dbplugin
+		if [ -n "${dbplugin}" ]; then
+			echo -e "${blue}dbplugin:\t${default}${dbplugin}"
+		fi
+
+		# Online status
+		if [ "${status}" == "0" ]; then
+			echo -e "${blue}Status:\t${red}OFFLINE${default}"
+		else
+			echo -e "${blue}Status:\t${green}ONLINE${default}"
+		fi
+	} | column -s $'\t' -t
+	echo -e ""
+}
+
+fn_details_script(){
+	#
+	# qlserver Script Details
+	# =====================================
+	# Service name:        ql-server
+	# qlserver version:    150316
+	# User:                lgsm
+	# Email alert:  off
+	# Update on start:     off
+	# Location:            /home/lgsm/qlserver
+	# Config file:         /home/lgsm/qlserver/serverfiles/baseq3/ql-server.cfg
+
+	echo -e "${lightgreen}${selfname} Script Details${default}"
+	printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' =
+	{
+		# Service name
+		echo -e "${blue}Service name:\t${default}${servicename}"
+
+		# Script version
+		if [ -n "${version}" ]; then
+			echo -e "${blue}${selfname} version:\t${default}${version}"
+		fi
+
+		# User
+		echo -e "${blue}User:\t${default}$(whoami)"
+
+		# GLIBC required
+		if [ -n "${glibcrequired}" ]; then
+			if [ "${glibcrequired}" == "NOT REQUIRED" ]; then
+					:
+			elif [ "${glibcrequired}" == "UNKNOWN" ]; then
+				echo -e "${blue}GLIBC required:\t${red}${glibcrequired}"
+			elif [ "$(printf '%s\n'${glibcrequired}'\n' ${glibcversion} | sort -V | head -n 1)" != "${glibcrequired}" ]; then
+				if [ "${glibcfix}" == "yes" ]; then
+					echo -e "${blue}GLIBC required:\t${red}${glibcrequired} ${default}(${green}Using GLIBC fix${default})"
+				else
+					echo -e "${blue}GLIBC required:\t${red}${glibcrequired} ${default}(${red}GLIBC version too old${default})"
+				fi
+			else
+				echo -e "${blue}GLIBC required:\t${green}${glibcrequired}${default}"
+			fi
+		fi
+
+		# Email alert
+		echo -e "${blue}Email alert:\t${default}${emailalert}"
+
+		# Pushbullet alert
+		echo -e "${blue}Pushbullet alert:\t${default}${pushbulletalert}"
+
+		# Update on start
+		if [ -n "${updateonstart}" ]; then
+			echo -e "${blue}Update on start:\t${default}${updateonstart}"
+		fi
+
+		# Script location
+		echo -e "${blue}Location:\t${default}${rootdir}"
+
+		# Config file location
+		if [ -n "${servercfgfullpath}" ]; then
+			if [ -f "${servercfgfullpath}" ]; then
+				echo -e "${blue}Config file:\t${default}${servercfgfullpath}"
+			elif [ -d "${servercfgfullpath}" ]; then
+				echo -e "${blue}Config dir:\t${default}${servercfgfullpath}"
+			else
+				echo -e "${blue}Config file:\t${default}${red}${servercfgfullpath}${default} (${red}FILE MISSING${default})"
+			fi
+		fi
+
+		# Network config file location (ARMA 3)
+		if [ -n "${networkcfgfullpath}" ]; then
+			echo -e "${blue}Network config file:\t${default}${networkcfgfullpath}"
+		fi
+	} | column -s $'\t' -t
+}
+
+fn_details_backup(){
+	#
+	# Backups
+	# =====================================
+	# No. of backups:    1
+	# Latest backup:
+	#     date:          Fri May  6 18:34:19 UTC 2016
+	#     file:          /home/lgsm/qlserver/backups/ql-server-2016-05-06-183239.tar.gz
+	#     size:          945M
+
+	echo -e ""
+	echo -e "${lightgreen}Backups${default}"
+	printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' =
+	if [ ! -d "${backupdir}" ]||[ "${backupcount}" == "0" ]; then
+		echo -e "No Backups created"
+	else
+		{
+			echo -e "${blue}No. of backups:\t${default}${backupcount}"
+			echo -e "${blue}Latest backup:${default}"
+			if [ "${lastbackupdaysago}" == "0" ]; then
+				echo -e "${blue}    date:\t${default}${lastbackupdate} (less than 1 day ago)"
+			elif [ "${lastbackupdaysago}" == "1" ]; then
+				echo -e "${blue}    date:\t${default}${lastbackupdate} (1 day ago)"
+			else
+				echo -e "${blue}    date:\t${default}${lastbackupdate} (${lastbackupdaysago} days ago)"
+			fi
+			echo -e "${blue}    file:\t${default}${lastbackup}"
+			echo -e "${blue}    size:\t${default}${lastbackupsize}"
+		} | column -s $'\t' -t
+	fi
+}
+
+fn_details_commandlineparms(){
+	#
+	# Command-line Parameters
+	# =====================================
+	# ./run_server_x86.sh +set net_strict 1
+
+	echo -e ""
+	echo -e "${lightgreen}Command-line Parameters${default}"
+	printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' =
+	echo -e "${executable} ${parms}"
+}
+
+fn_details_ports(){
+	# Ports
+	# =====================================
+	# Change ports by editing the parameters in:
+	# /home/lgsm/qlserver/serverfiles/baseq3/ql-server.cfg
+
+	echo -e ""
+	echo -e "${lightgreen}Ports${default}"
+	printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' =
+	echo -e "Change ports by editing the parameters in:"
+
+	parmslocation="${red}UNKNOWN${default}"
+	# engines/games that require editing in the config file
+	local ports_edit_array=( "avalanche" "dontstarve" "idtech2" "idtech3" "idtech3_ql" "lwjgl2" "projectzomboid" "quake" "refractor" "realvirtuality" "seriousengine35" "teeworlds" "terraria" "unreal" "unreal2" "unreal3" "TeamSpeak 3" "Mumble" "7 Days To Die" )
+	for port_edit in "${ports_edit_array[@]}"
+	do
+		if [ "${engine}" == "${port_edit}" ]||[ "${gamename}" == "${port_edit}" ]; then
+			parmslocation="${servercfgfullpath}"
+		fi
+	done
+	# engines/games that require editing in the script file
+	local ports_edit_array=( "goldsource" "Factorio" "Hurtworld" "iw3.0"  "Rust" "spark" "source" "starbound" "unreal4" )
+	for port_edit in "${ports_edit_array[@]}"
+	do
+		if [ "${engine}" == "${port_edit}" ]||[ "${gamename}" == "${port_edit}" ]; then
+			parmslocation="${selfname}"
+		fi
+	done
+	echo -e "${parmslocation}"
+	echo -e ""
+	echo -e "Useful port diagnostic command:"
+}
+
+fn_details_statusbottom(){
+	echo -e ""
+	if [ "${status}" == "0" ]; then
+		echo -e "${blue}Status:\t${red}OFFLINE${default}"
+	else
+		echo -e "${blue}Status:\t${green}ONLINE${default}"
+	fi
+	echo -e ""
+}
+
+
+# Engine Specific details
+
+fn_details_ark(){
+	echo -e "netstat -atunp | grep ShooterGame"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL\tINI VARIABLE"
+		echo -e "> Game\tINBOUND\t${port}\tudp\tPort=${port}"
+		echo -e "> Query\tINBOUND\t${queryport}\tudp"
+	} | column -s $'\t' -t
+}
+
+fn_details_avalanche(){
+	echo -e "netstat -atunp | grep Jcmp-Server"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game\tINBOUND\t${port}\tudp"
+	} | column -s $'\t' -t
+}
+
+fn_details_cod(){
+	echo -e "netstat -atunp | grep cod_lnxded"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game\tINBOUND\t${port}\tudp"
+	} | column -s $'\t' -t
+}
+
+fn_details_coduo(){
+	echo -e "netstat -atunp | grep coduo_lnxded"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game\tINBOUND\t${port}\tudp"
+	} | column -s $'\t' -t
+}
+
+fn_details_cod2(){
+	echo -e "netstat -atunp | grep cod2_lnxded"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game\tINBOUND\t${port}\tudp"
+	} | column -s $'\t' -t
+}
+
+fn_details_cod4(){
+	echo -e "netstat -atunp"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game\tINBOUND\t${port}\tudp"
+	} | column -s $'\t' -t
+}
+
+fn_details_codwaw(){
+	echo -e "netstat -atunp | grep codwaw_lnxded"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game\tINBOUND\t${port}\tudp"
+	} | column -s $'\t' -t
+}
+
+fn_details_dontstarve(){
+	echo -e "netstat -atunp | grep dontstarve"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game: Server\tINBOUND\t${port}\tudp"
+		echo -e "> Game: Master\tINBOUND\t${masterport}\tudp"
+		echo -e "> Steam: Auth\tINBOUND\t${steamauthenticationport}\tudp"
+		echo -e "> Steam: Master\tINBOUND\t${steammasterserverport}\tudp"
+	} | column -s $'\t' -t
+}
+
+fn_details_factorio(){
+	echo -e "netstat -atunp | grep factorio"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game\tINBOUND\t${port}\ttcp"
+	} | column -s $'\t' -t
+}
+
+fn_details_goldsource(){
+	echo -e "netstat -atunp | grep hlds_linux"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game/RCON\tINBOUND\t${port}\ttcp/udp"
+		echo -e "< Client\tOUTBOUND\t${clientport}\tudp"
+	} | column -s $'\t' -t
+}
+
+fn_details_hurtworld(){
+	echo -e "netstat -atunp | grep Hurtworld"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game/RCON\tINBOUND\t${port}\tudp"
+		echo -e "> Query\tINBOUND\t${queryport}\tudp"
+	} | column -s $'\t' -t
+}
+
+fn_details_minecraft(){
+	echo -e "netstat -atunp | grep java"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game\tINBOUND\t${port}\tudp"
+	} | column -s $'\t' -t
+}
+
+fn_details_mumble(){
+	echo -e "netstat -atunp | grep murmur"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Voice\tINBOUND\t${port}\tudp"
+		echo -e "> ServerQuery\tINBOUND\t${port}\ttcp"
+	} | column -s $'\t' -t
+}
+
+fn_details_projectzomboid(){
+	echo -e "netstat -atunp | grep java"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game\tINBOUND\t${port}\tudp"
+	} | column -s $'\t' -t
+}
+
+fn_details_quake(){
+	echo -e "netstat -atunp | grep mvdsv"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game\tINBOUND\t${port}\tudp"
+	} | column -s $'\t' -t
+}
+
+fn_details_quake2(){
+	echo -e "netstat -atunp | grep quake2"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game\tINBOUND\t${port}\tudp"
+	} | column -s $'\t' -t
+}
+
+fn_details_quake3(){
+	echo -e "netstat -atunp | grep q3ded"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game\tINBOUND\t${port}\tudp"
+	} | column -s $'\t' -t
+}
+
+fn_details_quakelive(){
+	echo -e "netstat -atunp | grep qzeroded"
+	echo -e ""
+	if [ -z "${port}" ]||[ -z "${rconport}" ]||[ -z "${statsport}" ]; then
+		echo -e "${red}ERROR!${default} Missing/commented ports in ${servercfg}."
+		echo -e ""
+	fi
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game\tINBOUND\t${port}\tudp"
+		echo -e "> Rcon\tINBOUND\t${rconport}\tudp"
+		echo -e "> Stats\tINBOUND\t${statsport}\tudp"
+	} | column -s $'\t' -t
+}
+
+fn_details_realvirtuality(){
+	echo -e "netstat -atunp | grep arma3server"
+	echo -e ""
+	if [ -z "${port}" ]||[ -z "${queryport}" ]||[ -z "${masterport}" ]; then
+		echo -e "${red}ERROR!${default} Missing/commented ports in ${servercfg}."
+		echo -e ""
+	fi
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game\tINBOUND\t${port}\tudp"
+		echo -e "> Steam: Query\tINBOUND\t${queryport}\tudp"
+		echo -e "> Steam: Master traffic\tINBOUND\t${masterport}\tudp"
+	} | column -s $'\t' -t
+}
+
+fn_details_refractor(){
+	echo -e "netstat -atunp | grep bf1942_lnxd"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game/Query\tINBOUND\t${port}\tudp"
+		echo -e "> Steam: Query\tINBOUND\t${queryport}\tudp"
+	} | column -s $'\t' -t
+}
+
+fn_details_rust(){
+	echo -e "netstat -atunp | grep Rust"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game/Query\tINBOUND\t${port}\ttcp/udp"
+		echo -e "> RCON\tINBOUND\t${rconport}\ttcp"
+	} | column -s $'\t' -t
+}
+
+fn_details_seriousengine35(){
+	echo -e "netstat -atunp | grep Sam3_Dedicate"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game/RCON\tINBOUND\t${port}\ttcp"
+		echo -e "> Query\tINBOUND\t${queryport}\tudp"
+	} | column -s $'\t' -t
+}
+
+fn_details_sdtd(){
+	echo -e "netstat -atunp | grep 7DaysToDie"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game/RCON\tINBOUND\t${port}\tudp"
+		echo -e "> Query\tINBOUND\t${queryport}\tudp"
+		echo -e "> WebAdmin\tINBOUND\t${webadminport}\ttcp"
+		echo -e "> Telnet\tINBOUND\t${telnetport}\ttcp"
+	} | column -s $'\t' -t
+	echo -e ""
+	echo -e "${lightgreen}${servername} WebAdmin${default}"
+	printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' =
+	{
+		echo -e "${blue}WebAdmin enabled:\t${default}${webadminenabled}"
+		echo -e "${blue}WebAdmin url:\t${default}http://${ip}:${webadminport}"
+		echo -e "${blue}WebAdmin password:\t${default}${webadminpass}"
+	} | column -s $'\t' -t
+	echo -e ""
+	echo -e "${lightgreen}${servername} Telnet${default}"
+	printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' =
+	{
+		echo -e "${blue}Telnet enabled:\t${default}${telnetenabled}"
+		echo -e "${blue}Telnet address:\t${default}${ip} ${telnetport}"
+		echo -e "${blue}Telnet password:\t${default}${telnetpass}"
+	} | column -s $'\t' -t
+}
+
+fn_details_source(){
+	echo -e "netstat -atunp | grep srcds_linux"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game/RCON\tINBOUND\t${port}\ttcp/udp"
+		echo -e "> SourceTV\tINBOUND\t${sourcetvport}\tudp"
+		echo -e "< Client\tOUTBOUND\t${clientport}\tudp"
+	} | column -s $'\t' -t
+}
+
+fn_details_spark(){
+	echo -e "netstat -atunp | grep server_linux3"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game/RCON\tINBOUND\t${port}\tudp"
+		echo -e "> Query\tINBOUND\t${queryport}\tudp"
+		echo -e "> WebAdmin\tINBOUND\t${webadminport}\ttcp"
+	} | column -s $'\t' -t
+	echo -e ""
+	echo -e "${lightgreen}${servername} WebAdmin${default}"
+	printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' =
+	{
+		echo -e "${blue}WebAdmin url:\t${default}http://${ip}:${webadminport}/index.html"
+		echo -e "${blue}WebAdmin username:\t${default}${webadminuser}"
+		echo -e "${blue}WebAdmin password:\t${default}${webadminpass}"
+	} | column -s $'\t' -t
+}
+
+fn_details_starbound(){
+	echo -e "netstat -atunp | grep starbound"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game\tINBOUND\t${port}\ttcp"
+		echo -e "> Query\tINBOUND\t${queryport}\ttcp"
+		echo -e "> Rcon\tINBOUND\t${rconport}\ttcp"
+	} | column -s $'\t' -t
+}
+
+fn_details_teamspeak3(){
+	echo -e "netstat -atunp | grep ts3server"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Voice\tINBOUND\t${port}\tudp"
+		echo -e "> ServerQuery\tINBOUND\t${queryport}\ttcp"
+		echo -e "> File transfer\tINBOUND\t${fileport}\ttcp"
+	} | column -s $'\t' -t
+}
+
+fn_details_teeworlds(){
+	echo -e "netstat -atunp | grep teeworlds_srv"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game\tINBOUND\t${port}\ttcp"
+	} | column -s $'\t' -t
+}
+
+fn_details_terraria(){
+	echo -e "netstat -atunp | grep TerrariaServer"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game\tINBOUND\t${port}\ttcp"
+	} | column -s $'\t' -t
+}
+
+fn_details_unreal(){
+	echo -e "netstat -atunp | grep ucc-bin"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL\tINI VARIABLE"
+		echo -e "> Game\tINBOUND\t${port}\tudp\tPort=${port}"
+		echo -e "> Query\tINBOUND\t${queryport}\tudp"
+		if [ "${engine}" == "unreal" ]; then
+			echo -e "< UdpLink Port (random)\tOUTBOUND\t${udplinkport}+\tudp"
+		fi
+		if [ "${engine}" != "unreal" ] && [ "${appid}" != "223250" ]; then
+			echo -e "> GameSpy query\tINBOUND\t${gsqueryport}\tudp\tOldQueryPortNumber=${gsqueryport}"
+		fi
+		if [ "${appid}" == "215360" ]; then
+			echo -e "< Master server\tOUTBOUND\t28852\ttcp/udp"
+		else
+			echo -e "< Master server\tOUTBOUND\t28900/28902\ttcp/udp"
+		fi
+		if [ "${appid}" ]; then
+			if [ "${appid}" == "223250" ]; then
+				echo -e "< Steam\tOUTBOUND\t20610\tudp"
+			else
+				echo -e "< Steam\tOUTBOUND\t20660\tudp"
+			fi
+		fi
+		echo -e "> WebAdmin\tINBOUND\t${webadminport}\ttcp\tListenPort=${webadminport}"
+	} | column -s $'\t' -t
+	echo -e ""
+	echo -e "${lightgreen}${servername} WebAdmin${default}"
+	printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' =
+	{
+		echo -e "${blue}WebAdmin enabled:\t${default}${webadminenabled}"
+		echo -e "${blue}WebAdmin url:\t${default}http://${ip}:${webadminport}"
+		echo -e "${blue}WebAdmin username:\t${default}${webadminuser}"
+		echo -e "${blue}WebAdmin password:\t${default}${webadminpass}"
+	} | column -s $'\t' -t
+}
+
+fn_details_ut3(){
+	echo -e "netstat -atunp | grep ut3-bin"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game/Query\tINBOUND\t${port}\ttcp/udp"
+	} | column -s $'\t' -t
+}
+
+fn_details_wolfensteinenemyterritory(){
+	echo -e "netstat -atunp | grep etded"
+	echo -e ""
+	{
+		echo -e "DESCRIPTION\tDIRECTION\tPORT\tPROTOCOL"
+		echo -e "> Game/Query\tINBOUND\t${port}\tudp"
+	} | column -s $'\t' -t
+}
+
+
+# Run checks and gathers details to display.
+
+fn_display_details() {
+	check.sh
+	info_config.sh
+	info_distro.sh
+	info_glibc.sh
+	info_parms.sh
+	fn_details_os
+	fn_details_performance
+	fn_details_disk
+	fn_details_gameserver
+	fn_details_script
+	fn_details_backup
+	# Some game servers do not have parms.
+	if [ "${gamename}" != "TeamSpeak 3" ]&&[ "${engine}" != "avalanche" ]&&[ "${engine}" != "dontstarve" ]&&[ "${engine}" != "projectzomboid" ]; then
+		fn_parms
+		fn_details_commandlineparms
+	fi
+	fn_details_ports
+
+	# Display details depending on game or engine.
+	if [ "${engine}" == "avalanche" ]; then
+		fn_details_avalanche
+	elif [ "${engine}" == "refractor" ]; then
+		fn_details_refractor
+	elif [ "${engine}" == "dontstarve" ]; then
+		fn_details_dontstarve
+	elif [ "${engine}" == "goldsource" ]; then
+		fn_details_goldsource
+	elif [ "${engine}" == "lwjgl2" ]; then
+		fn_details_minecraft
+	elif [ "${engine}" == "projectzomboid" ]; then
+		fn_details_projectzomboid
+	elif [ "${engine}" == "realvirtuality" ]; then
+		fn_details_realvirtuality
+	elif [ "${engine}" == "seriousengine35" ]; then
+		fn_details_seriousengine35
+	elif [ "${engine}" == "source" ]; then
+		fn_details_source
+	elif [ "${engine}" == "spark" ]; then
+		fn_details_spark
+	elif [ "${engine}" == "starbound" ]; then
+		fn_details_starbound
+	elif [ "${engine}" == "teeworlds" ]; then
+		fn_details_teeworlds
+	elif [ "${engine}" == "terraria" ]; then
+		fn_details_terraria
+	elif [ "${engine}" == "unreal" ]||[ "${engine}" == "unreal2" ]; then
+		fn_details_unreal
+	elif [ "${engine}" == "unreal3" ]; then
+		fn_details_ut3
+	elif [ "${gamename}" == "7 Days To Die" ]; then
+		fn_details_sdtd
+	elif [ "${gamename}" == "ARK: Survivial Evolved" ]; then
+		fn_details_ark
+	elif [ "${gamename}" == "Call of Duty" ]; then
+		fn_details_cod
+	elif [ "${gamename}" == "Call of Duty: United Offensive" ]; then
+		fn_details_coduo
+	elif [ "${gamename}" == "Call of Duty 2" ]; then
+		fn_details_cod2
+	elif [ "${gamename}" == "Call of Duty 4" ]; then
+		fn_details_cod4
+	elif [ "${gamename}" == "Call of Duty: World at War" ]; then
+		fn_details_codwaw
+	elif [ "${gamename}" == "Hurtworld" ]; then
+		fn_details_hurtworld
+	elif [ "${gamename}" == "QuakeWorld" ]; then
+		fn_details_quake
+	elif [ "${gamename}" == "Quake 2" ]; then
+		fn_details_quake2
+	elif [ "${gamename}" == "Quake 3: Arena" ]; then
+		fn_details_quake3
+	elif [ "${gamename}" == "Quake Live" ]; then
+		fn_details_quakelive
+	elif [ "${gamename}" == "TeamSpeak 3" ]; then
+		fn_details_teamspeak3
+	elif [ "${gamename}" == "Mumble" ]; then
+		fn_details_mumble
+	elif [ "${gamename}" == "Rust" ]; then
+		fn_details_rust
+	elif [ "${gamename}" == "Wolfenstein: Enemy Territory" ]; then
+		fn_details_wolfensteinenemyterritory
+	elif [ "${gamename}" == "Factorio" ]; then
+		fn_details_factorio
+	else
+		fn_print_error_nl "Unable to detect server engine."
+	fi
+
+	fn_details_statusbottom
+}
+
+if [ -z "${postdetails}" ] ;
+then
+  fn_display_details
+  core_exit.sh
+fi
+

+ 1 - 1
lgsm/functions/command_install.sh

@@ -18,7 +18,7 @@ check_deps.sh
 if [ "${gamename}" == "Unreal Tournament 2004" ]; then
 	install_server_files.sh
 	install_ut2k4_key.sh
-elif [ "${gamename}" == "Battlefield: 1942" ]||[ "${gamename}" == "Call of Duty" ]||[ "${gamename}" == "Call of Duty: United Offensive" ]||[ "${gamename}" == "Call of Duty 2" ]||[ "${gamename}" == "Call of Duty 4" ]||[ "${gamename}" == "Call of Duty: World at War" ]||[ "${gamename}" == "Minecraft" ]||[ "${gamename}" == "Quake 2" ]||[ "${gamename}" == "Quake 3: Arena" ]||[ "${gamename}" == "QuakeWorld" ]||[ "${gamename}" == "Unreal Tournament 99" ]||[ "${gamename}" == "Unreal Tournament" ]||[ "${gamename}" == "Unreal Tournament 3" ]||[ "${gamename}" == "TeamSpeak 3" ]||[ "${gamename}" == "Mumble" ]||[ "${gamename}" == "Wolfenstein: Enemy Territory" ]; then
+elif [ "${gamename}" == "Battlefield: 1942" ]||[ "${gamename}" == "Call of Duty" ]||[ "${gamename}" == "Call of Duty: United Offensive" ]||[ "${gamename}" == "Call of Duty 2" ]||[ "${gamename}" == "Call of Duty 4" ]||[ "${gamename}" == "Call of Duty: World at War" ]||[ "${gamename}" == "Factorio" ]||[ "${gamename}" == "Minecraft" ]||[ "${gamename}" == "Quake 2" ]||[ "${gamename}" == "Quake 3: Arena" ]||[ "${gamename}" == "QuakeWorld" ]||[ "${gamename}" == "Unreal Tournament 99" ]||[ "${gamename}" == "Unreal Tournament" ]||[ "${gamename}" == "Unreal Tournament 3" ]||[ "${gamename}" == "TeamSpeak 3" ]||[ "${gamename}" == "Mumble" ]||[ "${gamename}" == "Wolfenstein: Enemy Territory" ]; then
 	installer=1
 	install_server_files.sh
 elif [ -n "${appid}" ]; then

+ 2 - 2
lgsm/functions/command_postdetails.sh

@@ -36,7 +36,7 @@ posttarget=${posttarget="https://hastebin.com"}
 # For pastebin, you can set the expiration period.
 # use 1 week as the default, other options are '24h' for a day, etc.
 # This, too, may be overridden from the command line at the top-level
-postexpire="${postexpire="1W"}"
+postexpire="${postexpire="30D"}"
 
 # This file sources the command_details.sh file to leverage all
 # of the already-defined functions.  To keep the command_details.sh
@@ -128,7 +128,7 @@ if [ "${posttarget}" == "http://pastebin.com" ] ; then
 	fn_print_ok_nl "Posting details to pastbin.com for ${postexpire}"
 	echo "  Please share the following url for support: ${posttarget}${link}"
 elif [ "${posttarget}" == "https://hastebin.com" ] ; then
-	fn_print_dots "Posting details to hastebin.com (expires 30 days after last view)"
+	fn_print_dots "Posting details to hastebin.com"
 	sleep 1
 	# hastebin is a bit simpler.  If successful, the returned result
 	# should look like: {"something":"key"}, putting the reference that

+ 20 - 0
lgsm/functions/command_stop.sh

@@ -58,6 +58,24 @@ fn_stop_graceful_goldsource(){
 	fn_stop_tmux
 }
 
+fn_stop_graceful_factorio(){
+	fn_print_dots "Graceful: console CTRL+c"
+	fn_script_log_info "Graceful: console CTRL+c"
+	# sends quit
+	tmux send-keys C-c -t "${servicename}" > /dev/null 2>&1
+	# waits 3 seconds as goldsource servers restart with the quit command
+	for seconds in {1..3}; do
+		sleep 1
+		fn_print_dots "Graceful: console CTRL+c: ${seconds}"
+	done
+	fn_print_ok "Graceful: console CTRL+c: ${seconds}: "
+	fn_print_ok_eol_nl
+	fn_script_log_pass "Graceful: console CTRL+c: OK: ${seconds} seconds"
+	sleep 1
+	fn_stop_tmux
+}
+
+
 # Attempts graceful of 7 Days To Die using telnet.
 fn_stop_telnet_sdtd(){
 	sdtd_telnet_shutdown=$( expect -c '
@@ -175,6 +193,8 @@ fn_stop_graceful_minecraft(){
 fn_stop_graceful_select(){
 	if [ "${gamename}" == "7 Days To Die" ]; then
 		fn_stop_graceful_sdtd
+	elif [ "${gamename}" == "Factorio" ]; then
+		fn_stop_graceful_factorio
 	elif [ "${engine}" == "source" ]; then
 		fn_stop_graceful_source
 	elif [ "${engine}" == "goldsource" ]; then

+ 2 - 0
lgsm/functions/command_update.sh

@@ -19,6 +19,8 @@ elif [ "${engine}" == "lwjgl2" ]; then
 	update_minecraft.sh
 elif [ "${gamename}" == "Mumble" ]; then
 	update_mumble.sh
+elif [ "${gamename}" == "Factorio" ]; then
+        update_factorio.sh
 else
 	update_steamcmd.sh
 fi

+ 1 - 1
lgsm/functions/core_dl.sh

@@ -117,7 +117,7 @@ fn_fetch_file(){
 			# trap to remove part downloaded files
 			trap fn_fetch_trap INT
 			# if larger file shows progress bar
-			if [ ${filename##*.} == "bz2" ]||[ ${filename##*.} == "jar" ]; then
+			if [ ${filename##*.} == "bz2" ]||[ ${filename##*.} == "gz" ]||[ ${filename##*.} == "zip" ]||[ ${filename##*.} == "jar" ]; then
 				echo -ne "downloading ${filename}..."
 				sleep 1
 				curlcmd=$(${curlcmd} --progress-bar --fail -L -o "${filedir}/${filename}" "${fileurl}")

+ 10 - 0
lgsm/functions/core_functions.sh

@@ -450,6 +450,11 @@ functionfile="${FUNCNAME}"
 fn_fetch_function
 }
 
+update_factorio.sh(){
+functionfile="${FUNCNAME}"
+fn_fetch_function
+}
+
 update_steamcmd.sh(){
 functionfile="${FUNCNAME}"
 fn_fetch_function
@@ -480,6 +485,11 @@ functionfile="${FUNCNAME}"
 fn_fetch_function
 }
 
+install_factorio_save.sh(){
+functionfile="${FUNCNAME}"
+fn_fetch_function
+}
+
 install_dst_token.sh(){
 functionfile="${FUNCNAME}"
 fn_fetch_function

+ 85 - 9
lgsm/functions/core_getopt.sh

@@ -80,6 +80,73 @@ case "${getopt}" in
 	esac
 }
 
+fn_getopt_generic_update_no_steam(){
+case "${getopt}" in
+	st|start)
+		command_start.sh;;
+	sp|stop)
+		command_stop.sh;;
+	r|restart)
+		command_restart.sh;;
+	u|update)
+		command_update.sh;;
+	uf|update-functions)
+		command_update_functions.sh;;
+	m|monitor)
+		command_monitor.sh;;
+	ta|test-alert)
+		command_test_alert.sh;;
+	dt|details)
+		command_details.sh;;
+	pd|postdetails)
+		command_postdetails.sh;;
+	b|backup)
+		command_backup.sh;;
+	c|console)
+		command_console.sh;;
+	d|debug)
+		command_debug.sh;;
+	dev|dev-debug)
+		command_dev_debug.sh;;
+	i|install)
+		command_install.sh;;
+	ai|auto-install)
+		fn_autoinstall;;
+	dd|detect-deps)
+		command_dev_detect_deps.sh;;
+	dg|detect-glibc)
+		command_dev_detect_glibc.sh;;
+	dl|detect-ldd)
+		command_dev_detect_ldd.sh;;
+	*)
+	if [ -n "${getopt}" ]; then
+		echo -e "${red}Unknown command${default}: $0 ${getopt}"
+		exitcode=2
+	fi
+	echo "Usage: $0 [option]"
+	echo "${gamename} - Linux Game Server Manager - Version ${version}"
+	echo "https://gameservermanagers.com/${selfname}"
+	echo -e ""
+	echo -e "${lightyellow}Commands${default}"
+	{
+		echo -e "${blue}start\t${default}st |Start the server."
+		echo -e "${blue}stop\t${default}sp |Stop the server."
+		echo -e "${blue}restart\t${default}r  |Restart the server."
+		echo -e "${blue}update\t${default}u  |Checks and applies updates."
+		echo -e "${blue}update-functions\t${default}uf |Removes all functions so latest can be downloaded."
+		echo -e "${blue}monitor\t${default}m  |Checks that the server is running."
+		echo -e "${blue}test-alert\t${default}ta |Sends test alert."
+		echo -e "${blue}details\t${default}dt |Displays useful information about the server."
+		echo -e "${blue}postdetails\t${default}pd |Post stripped details to pastebin (for support)"
+		echo -e "${blue}backup\t${default}b  |Create archive of the server."
+		echo -e "${blue}console\t${default}c  |Console allows you to access the live view of a server."
+		echo -e "${blue}debug\t${default}d  |See the output of the server directly to your terminal."
+		echo -e "${blue}install\t${default}i  |Install the server."
+		echo -e "${blue}auto-install\t${default}ai |Install the server, without prompts."
+	} | column -s $'\t' -t
+	esac
+}
+
 fn_getopt_generic_no_update(){
 case "${getopt}" in
 	st|start)
@@ -144,7 +211,6 @@ case "${getopt}" in
 	esac
 }
 
-
 fn_getopt_teamspeak3(){
 case "${getopt}" in
 	st|start)
@@ -697,26 +763,36 @@ case "${getopt}" in
 	esac
 }
 
-if [ "${gamename}" == "Mumble" ]; then
-	fn_getopt_mumble
-elif [ "${gamename}" == "Battlefield: 1942" ]||[ "${gamename}" == "Call of Duty" ]||[ "${gamename}" == "Call of Duty: United Offensive" ]||[ "${gamename}" == "Call of Duty 2" ]||[ "${gamename}" == "Call of Duty 4" ]||[ "${gamename}" == "Call of Duty: World at War" ]||[ "${gamename}" == "QuakeWorld" ]||[ "${gamename}" == "Quake 2" ]||[ "${gamename}" == "Quake 3: Arena" ]||[ "${gamename}" == "Wolfenstein: Enemy Territory" ]; then
-	fn_getopt_generic_no_update
+# Don't Starve Together
+if [ "${gamename}" == "Don't Starve Together" ]; then
+	fn_getopt_dstserver
+# Garry's Mod
+elif [ "${gamename}" == "Garry's Mod" ]; then
+	fn_getopt_gmodserver
+# Minecraft
 elif [ "${engine}" == "lwjgl2" ]; then
 	fn_getopt_minecraft
+# Mumble
+elif [ "${gamename}" == "Mumble" ]; then
+	fn_getopt_mumble
+# Teamspeak 3	
 elif [ "${gamename}" == "TeamSpeak 3" ]; then
 	fn_getopt_teamspeak3
-elif [ "${gamename}" == "Don't Starve Together" ]; then
-	fn_getopt_dstserver
-elif [ "${gamename}" == "Garry's Mod" ]; then
-	fn_getopt_gmodserver
+# Unreal 2 Engine
 elif [ "${engine}" == "unreal2" ]; then
 	if [ "${gamename}" == "Unreal Tournament 2004" ]; then
 		fn_getopt_ut2k4
 	else
 		fn_getopt_unreal2
 	fi
+# Unreal Engine	
 elif [ "${engine}" == "unreal" ]; then
 	fn_getopt_unreal
+# Generic
+elif [ "${gamename}" == "Battlefield: 1942" ]||[ "${gamename}" == "Call of Duty" ]||[ "${gamename}" == "Call of Duty: United Offensive" ]||[ "${gamename}" == "Call of Duty 2" ]||[ "${gamename}" == "Call of Duty 4" ]||[ "${gamename}" == "Call of Duty: World at War" ]||[ "${gamename}" == "QuakeWorld" ]||[ "${gamename}" == "Quake 2" ]||[ "${gamename}" == "Quake 3: Arena" ]||[ "${gamename}" == "Wolfenstein: Enemy Territory" ]; then
+	fn_getopt_generic_no_update
+elif  [ "${gamename}" == "Factorio" ]; then
+	fn_getopt_generic_update_no_steam	
 else
 	fn_getopt_generic
 fi

+ 25 - 7
lgsm/functions/fix_glibc.sh

@@ -8,6 +8,9 @@ local commandname="FIX"
 local commandaction="Fix"
 local function_selfname="$(basename $(readlink -f "${BASH_SOURCE[0]}"))"
 
+## i386
+
+# libstdc++.so.6
 local libstdc_servers_array=( "ARMA 3" "Blade Symphony" "Garry's Mod" "GoldenEye: Source" "Just Cause 2" )
 for libstdc_server in "${libstdc_servers_array[@]}"
 do
@@ -16,6 +19,7 @@ do
 	fi
 done
 
+# libm.so.6
 local libm_servers_array=( "Black Mesa: Deathmatch" "Codename CURE" "Day of Infamy" "Double Action: Boogaloo" "Empires Mod" "Fistful of Frags" "Garry's Mod" "GoldenEye: Source" "Insurgency" "Natural Selection 2" "NS2: Combat" "No More Room in Hell" )
 for libm_server in "${libm_servers_array[@]}"
 do
@@ -24,6 +28,7 @@ do
 	fi
 done
 
+# libc.so.6
 local libc_servers_array=( "Black Mesa: Deathmatch" "Blade Symphony" "Garry's Mod" "GoldenEye: Source" )
 for libc_server in "${libc_servers_array[@]}"
 do
@@ -32,6 +37,7 @@ do
 	fi
 done
 
+# libpthread.so.0
 local libpthread_servers_array=( "Black Mesa: Deathmatch" "Blade Symphony" "Garry's Mod" )
 for libpthread_server in "${libpthread_servers_array[@]}"
 do
@@ -40,12 +46,24 @@ do
 	fi
 done
 
-if [ "${gamename}" == "Call of Duty: United Offensive" ]; then
-	fn_fetch_file_github "lgsm/lib/gcc3" "libgcc_s.so.1" "${lgsmdir}/lib" "noexecutecmd" "norun" "noforce" "nomd5"
-	fn_fetch_file_github "lgsm/lib/gcc3" "libstdc++.so.5.0.3" "${lgsmdir}/lib" "noexecutecmd" "norun" "noforce" "nomd5"
-	if [ ! -f "${lgsmdir}/lib/libstdc++.so.5" ]; then	
-		ln -s "${lgsmdir}/lib/libstdc++.so.5.0.3" "${lgsmdir}/lib/libstdc++.so.5"
+export LD_LIBRARY_PATH=:"${libdir}"
+
+## amd64
+
+# libm.so.6
+local libm_servers_array=( "Factorio" )
+for libm_server in "${libm_servers_array[@]}"
+do
+	if [ "${gamename}" == "${libm_server}" ]; then
+		fn_fetch_file_github "lgsm/lib/ubuntu12.04/amd64" "libm.so.6" "${lgsmdir}/lib" "noexecutecmd" "norun" "noforce" "nomd5"
 	fi
-fi
+done
 
-export LD_LIBRARY_PATH=:"${libdir}"
+# libc.so.6
+local libc_servers_array=( "Factorio" )
+for libc_server in "${libc_servers_array[@]}"
+do
+	if [ "${gamename}" == "${libc_server}" ]; then
+		fn_fetch_file_github "lgsm/lib/ubuntu12.04/amd64" "libc.so.6" "${lgsmdir}/lib" "noexecutecmd" "norun" "noforce" "nomd5"
+	fi
+done

+ 1 - 1
lgsm/functions/gsquery.py

@@ -29,7 +29,7 @@ class GameServer:
         elif self.option.engine == 'iw2.0':
             self.query_prompt_string = b'\xff\xff\xff\xffgetstatus'
         elif self.option.engine == 'iw3.0':
-            self.query_prompt_string = b'\xff\xff\xff\xffgetstatus'            
+            self.query_prompt_string = b'\xff\xff\xff\xffgetstatus'
         elif self.option.engine == 'quake':
             self.query_prompt_string = b'\xff\xff\xff\xffstatus\x00'
         elif self.option.engine == 'quakelive':

+ 20 - 0
lgsm/functions/info_config.sh

@@ -166,6 +166,23 @@ fn_info_config_dontstarve(){
 	fi
 }
 
+fn_info_config_factorio(){
+	if [ ! -f "${servercfgfullpath}" ]; then
+		servername="Factorio Server"
+		serverpassword="${unavailable}"
+		maxplayers="${zero}"
+	else
+		servername="Factorio Server"
+		serverpassword=$(grep "game_password" "${servercfgfullpath}" | sed -e 's/^[ \t]*//g' -e '/^#/d' -e 's/game_password//g' | tr -d '=\";,:' | sed -e 's/^[ \t]*//' -e 's/[ \t]*$//')
+		maxplayers=$(grep "\"max_players\"" "${servercfgfullpath}" | tr -cd '[:digit:]')
+
+		# Not Set
+		servername=${servername:-"NOT SET"}
+		maxplayers=${maxplayers=:-"0"}
+		rconpassword=${rconpassword=:-"NOT SET"}
+	fi
+}
+
 fn_info_config_minecraft(){
 	if [ ! -f "${servercfgfullpath}" ]; then
 		servername="${unavailable}"
@@ -597,6 +614,9 @@ elif [ "${gamename}" == "Call of Duty: World at War" ]; then
 # Dont Starve Together
 elif [ "${engine}" == "dontstarve" ]; then
 	fn_info_config_dontstarve
+# Factorio	
+elif [ "${gamename}" == "Factorio" ]; then
+	fn_info_config_factorio
 # Quake 2
 elif [ "${gamename}" == "Quake 2" ]; then
 	fn_info_config_quake2

+ 3 - 0
lgsm/functions/info_glibc.sh

@@ -38,6 +38,9 @@ elif [ "${gamename}" == "Double Action: Boogaloo" ]; then
 elif [ "${gamename}" == "Empires Mod" ]; then
 	glibcrequired="2.15"
 	glibcfix="yes"
+elif [ "${gamename}" == "Factorio" ]; then
+	glibcrequired="2.15"
+	glibcfix="yes"
 elif [ "${gamename}" == "Fistful of Frags" ]; then
 	glibcrequired="2.15"
 	glibcfix="yes"

+ 6 - 0
lgsm/functions/install_config.sh

@@ -261,6 +261,12 @@ elif [ "${gamename}" == "Double Action: Boogaloo" ]; then
 	fn_fetch_default_config
 	fn_default_config_remote
 	fn_set_config_vars
+elif [ "${gamename}" == "Factorio" ]; then
+	gamedirname="Factorio"
+	array_configs+=( server-settings.json )
+	fn_fetch_default_config
+	fn_default_config_remote
+	fn_set_config_vars
 elif [ "${gamename}" == "Fistful of Frags" ]; then
 	gamedirname="FistfulofFrags"
 	array_configs+=( server.cfg )

+ 15 - 0
lgsm/functions/install_factorio_save.sh

@@ -0,0 +1,15 @@
+#!/bin/bash
+# LGSM install_factorio_save.sh function
+# Author: Kristian Polso
+# Website: https://gameservermanagers.com
+# Description: Creates the initial save file for Factorio
+
+local commandname="INSTALL"
+local commandaction="Install"
+
+echo ""
+echo "Creating initial Factorio savefile"
+echo "================================="
+sleep 1
+check_glibc.sh
+"${executabledir}"/factorio --create ${filesdir}/save1

+ 3 - 0
lgsm/functions/install_server_files.sh

@@ -129,6 +129,9 @@ elif [ "${gamename}" == "Minecraft" ]; then
 	update_minecraft.sh
 elif [ "${gamename}" == "Mumble" ]; then
 	update_mumble.sh
+elif [ "${gamename}" == "Factorio" ]; then
+  update_factorio.sh
+  install_factorio_save.sh
 elif [ -z "${appid}" ]||[ "${gamename}" == "GoldenEye: Source" ]; then
 	if [ "${gamename}" == "Unreal Tournament" ]; then
 		install_unreal_tournament_eula.sh

+ 167 - 0
lgsm/functions/update_factorio.sh

@@ -0,0 +1,167 @@
+#!/bin/bash
+# LGSM update_factorio.sh function
+# Author: Daniel Gibbs
+# Contributor: Kristian Polso
+# Website: https://gameservermanagers.com
+# Description: Handles updating of Factorio servers.
+
+local commandname="UPDATE"
+local commandaction="Update"
+local function_selfname="$(basename $(readlink -f "${BASH_SOURCE[0]}"))"
+
+fn_update_factorio_dl(){
+	fn_fetch_file "https://www.factorio.com/get-download/${availablebuild}/headless/${factorioarch}" "${tmpdir}" "factorio_headless_${factorioarch}-${availablebuild}.tar.gz"
+	fn_dl_extract "${tmpdir}" "factorio_headless_${factorioarch}-${availablebuild}.tar.gz" "${tmpdir}"
+	echo -e "copying to ${filesdir}...\c"
+	fn_script_log "Copying to ${filesdir}"
+	cp -R "${tmpdir}/factorio/"* "${filesdir}"
+	local exitcode=$?
+	if [ "${exitcode}" == "0" ]; then
+		fn_print_ok_eol_nl
+	else
+		fn_print_fail_eol_nl
+	fi
+}
+
+fn_update_factorio_currentbuild(){
+	# Gets current build info
+	# Checks if current build info is available. If it fails, then a server restart will be forced to generate logs.
+	if [ ! -f "${consolelogdir}/${servicename}-console.log" ]; then
+		fn_print_error "Checking for update: factorio.com"
+		sleep 1
+		fn_print_error_nl "Checking for update: factorio.com: No logs with server version found"
+		fn_script_log_error "Checking for update: factorio.com: No logs with server version found"
+		sleep 1
+		fn_print_info_nl "Checking for update: factorio.com: Forcing server restart"
+		fn_script_log_info "Checking for update: factorio.com: Forcing server restart"
+		sleep 1
+		exitbypass=1
+		command_stop.sh
+		exitbypass=1
+		command_start.sh
+		sleep 1
+		# Check again and exit on failure.
+		if [ ! -f "${consolelogdir}/${servicename}-console.log" ]; then
+			fn_print_fail_nl "Checking for update: factorio.com: Still No logs with server version found"
+			fn_script_log_fatal "Checking for update: factorio.com: Still No logs with server version found"
+			core_exit.sh
+		fi
+	fi
+
+	# Get current build from logs
+	currentbuild=$(grep "Loading mod base" "${consolelogdir}"/"${servicename}"-console.log 2> /dev/null|awk '{print $5}')
+	if [ -z "${currentbuild}" ]; then
+		fn_print_error_nl "Checking for update: factorio.com: Current build version not found"
+		fn_script_log_error "Checking for update: factorio.com: Current build version not found"
+		sleep 1
+		fn_print_info_nl "Checking for update: factorio.com: Forcing server restart"
+		fn_script_log_info "Checking for update: factorio.com: Forcing server restart"
+		exitbypass=1
+		command_stop.sh
+		exitbypass=1
+		command_start.sh
+		currentbuild=$(grep "Loading mod base" "${consolelogdir}"/"${servicename}"-console.log 2> /dev/null|awk '{print $5}')
+		if [ -z "${currentbuild}" ]; then
+			fn_print_fail_nl "Checking for update: factorio.com: Current build version still not found"
+			fn_script_log_fatal "Checking for update: factorio.com: Current build version still not found"
+			core_exit.sh
+		fi
+	fi
+}
+
+fn_update_factorio_arch(){
+	# Factorio is linux64 only for now
+	factorioarch="linux64"
+}
+
+fn_update_factorio_availablebuild(){
+	# Gets latest build info.
+	availablebuild=$(curl -s https://www.factorio.com/download-headless/stable | grep 'headless/linux64' | head -n 1 | grep -oP '(?<=get-download/).*?(?=/)')
+	sleep 1
+
+	# Checks if availablebuild variable has been set
+	if [ -z "${availablebuild}" ]; then
+		fn_print_fail "Checking for update: factorio.com"
+		sleep 1
+		fn_print_fail "Checking for update: factorio.com: Not returning version info"
+		fn_script_log_fatal "Failure! Checking for update: factorio.com: Not returning version info"
+		core_exit.sh
+	elif [ "${installer}" == "1" ]; then
+		:
+	else
+		fn_print_ok "Checking for update: factorio.com"
+		fn_script_log_pass "Checking for update: factorio.com"
+		sleep 1
+	fi
+}
+
+fn_update_factorio_compare(){
+	# Removes dots so if can compare version numbers
+	currentbuilddigit=$(echo "${currentbuild}"|tr -cd '[:digit:]')
+	availablebuilddigit=$(echo "${availablebuild}"|tr -cd '[:digit:]')
+
+	if [ "${currentbuilddigit}" -ne "${availablebuilddigit}" ]; then
+		echo -e "\n"
+		echo -e "Update available:"
+		sleep 1
+		echo -e "	Current build: ${red}${currentbuild} ${factorioarch}${default}"
+		echo -e "	Available build: ${green}${availablebuild} ${factorioarch}${default}"
+		echo -e ""
+		sleep 1
+		echo ""
+		echo -en "Applying update.\r"
+		sleep 1
+		echo -en "Applying update..\r"
+		sleep 1
+		echo -en "Applying update...\r"
+		sleep 1
+		echo -en "\n"
+		fn_script_log "Update available"
+		fn_script_log "Current build: ${currentbuild}"
+		fn_script_log "Available build: ${availablebuild}"
+		fn_script_log "${currentbuild} > ${availablebuild}"
+
+		unset updateonstart
+
+		check_status.sh
+		if [ "${status}" == "0" ]; then
+			fn_update_factorio_dl
+			exitbypass=1
+			command_start.sh
+			exitbypass=1
+			command_stop.sh
+		else
+			exitbypass=1
+			command_stop.sh
+			fn_update_factorio_dl
+			exitbypass=1
+			command_start.sh
+		fi
+		alert="update"
+		alert.sh
+	else
+		echo -e "\n"
+		echo -e "No update available:"
+		echo -e "	Current version: ${green}${currentbuild}${default}"
+		echo -e "	Available version: ${green}${availablebuild}${default}"
+		echo -e ""
+		fn_print_ok_nl "No update available"
+		fn_script_log_info "Current build: ${currentbuild}"
+		fn_script_log_info "Available build: ${availablebuild}"
+	fi
+}
+
+
+fn_update_factorio_arch
+if [ "${installer}" == "1" ]; then
+	fn_update_factorio_availablebuild
+	fn_update_factorio_dl
+else
+	# Checks for server update from factorio.com
+	fn_print_dots "Checking for update: factorio.com"
+	fn_script_log_info "Checking for update: factorio.com"
+	sleep 1
+	fn_update_factorio_currentbuild
+	fn_update_factorio_availablebuild
+	fn_update_factorio_compare
+fi

+ 2 - 0
lgsm/functions/update_minecraft.sh

@@ -79,6 +79,8 @@ fn_update_availablebuild(){
 		fn_print_fail "Checking for update: mojang.com: Not returning version info"
 		fn_script_log_fatal "Failure! Checking for update: mojang.com: Not returning version info"
 		core_exit.sh
+	elif [ "${installer}" == "1" ]; then
+		:
 	else
 		fn_print_ok_nl "Checking for update: mojang.com"
 		fn_script_log_pass "Checking for update: mojang.com"

+ 2 - 0
lgsm/functions/update_mumble.sh

@@ -86,6 +86,8 @@ fn_update_mumble_availablebuild(){
 		fn_print_fail "Checking for update: GitHub: Not returning version info"
 		fn_script_log_fatal "Failure! Checking for update: GitHub: Not returning version info"
 		core_exit.sh
+	elif [ "${installer}" == "1" ]; then
+		:
 	else
 		fn_print_ok "Checking for update: GitHub"
 		fn_script_log_pass "Checking for update: GitHub"

+ 5 - 3
lgsm/functions/update_ts3.sh

@@ -15,7 +15,7 @@ fn_update_ts3_dl(){
 	fn_script_log "Copying to ${filesdir}"
 	cp -R "${tmpdir}/teamspeak3-server_linux_${ts3arch}/"* "${filesdir}"
 	local exitcode=$?
-	if [ ${exitcode} -eq 0 ]; then
+	if [ "${exitcode}" == "0" ]; then
 		fn_print_ok_eol_nl
 	else
 		fn_print_fail_eol_nl
@@ -23,8 +23,8 @@ fn_update_ts3_dl(){
 }
 
 fn_update_ts3_currentbuild(){
-	# Gets currentbuild info
-	# Checks currentbuild info is available, if fails a server restart will be forced to generate logs.
+	# Gets current build info
+	# Checks if current build info is available. If it fails, then a server restart will be forced to generate logs.
 	if [ -z "$(find ./* -name 'ts3server*_0.log')" ]; then
 		fn_print_error "Checking for update: teamspeak.com"
 		sleep 1
@@ -113,6 +113,8 @@ fn_update_ts3_availablebuild(){
 		fn_print_fail "Checking for update: teamspeak.com: Not returning version info"
 		fn_script_log_fatal "Failure! Checking for update: teamspeak.com: Not returning version info"
 		core_exit.sh
+	elif [ "${installer}" == "1" ]; then
+		:
 	else
 		fn_print_ok "Checking for update: teamspeak.com"
 		fn_script_log_pass "Checking for update: teamspeak.com"

BIN
lgsm/lib/gcc3/libgcc_s.so.1


BIN
lgsm/lib/gcc3/libstdc++.so.5.0.3


BIN
lgsm/lib/ubuntu12.04/amd64/libc.so.6


BIN
lgsm/lib/ubuntu12.04/amd64/libm.so.6