Переглянути джерело

feat: convert functions dir to modules dir (#4169)

* functions dir will be deleted after 14 days
Daniel Gibbs 3 роки тому
батько
коміт
0bec0ca218
100 змінених файлів з 4829 додано та 200 видалено
  1. 1 1
      .github/workflows/version-check.sh
  2. 51 49
      lgsm/functions/core_dl.sh
  3. 9 9
      lgsm/functions/core_exit.sh
  4. 1 1
      lgsm/functions/core_functions.sh
  5. 5 5
      lgsm/functions/core_getopt.sh
  6. 3 3
      lgsm/functions/core_github.sh
  7. 10 1
      lgsm/functions/core_legacy.sh
  8. 1 1
      lgsm/functions/core_logs.sh
  9. 1 1
      lgsm/functions/core_messages.sh
  10. 816 0
      lgsm/functions/core_modules.sh
  11. 2 2
      lgsm/functions/core_steamcmd.sh
  12. 1 1
      lgsm/functions/core_trap.sh
  13. 0 0
      lgsm/modules/README.md
  14. 2 2
      lgsm/modules/alert.sh
  15. 1 1
      lgsm/modules/alert_discord.sh
  16. 1 1
      lgsm/modules/alert_email.sh
  17. 1 1
      lgsm/modules/alert_gotify.sh
  18. 1 1
      lgsm/modules/alert_ifttt.sh
  19. 1 1
      lgsm/modules/alert_mailgun.sh
  20. 1 1
      lgsm/modules/alert_pushbullet.sh
  21. 1 1
      lgsm/modules/alert_pushover.sh
  22. 1 1
      lgsm/modules/alert_rocketchat.sh
  23. 1 1
      lgsm/modules/alert_slack.sh
  24. 1 1
      lgsm/modules/alert_telegram.sh
  25. 2 2
      lgsm/modules/check.sh
  26. 1 1
      lgsm/modules/check_config.sh
  27. 1 1
      lgsm/modules/check_deps.sh
  28. 1 1
      lgsm/modules/check_executable.sh
  29. 1 1
      lgsm/modules/check_glibc.sh
  30. 1 1
      lgsm/modules/check_ip.sh
  31. 1 1
      lgsm/modules/check_last_update.sh
  32. 1 1
      lgsm/modules/check_logs.sh
  33. 8 8
      lgsm/modules/check_permissions.sh
  34. 1 1
      lgsm/modules/check_root.sh
  35. 1 1
      lgsm/modules/check_status.sh
  36. 2 2
      lgsm/modules/check_steamcmd.sh
  37. 1 1
      lgsm/modules/check_system_dir.sh
  38. 1 1
      lgsm/modules/check_system_requirements.sh
  39. 1 1
      lgsm/modules/check_tmuxception.sh
  40. 1 1
      lgsm/modules/check_version.sh
  41. 1 1
      lgsm/modules/command_backup.sh
  42. 1 1
      lgsm/modules/command_check_update.sh
  43. 1 1
      lgsm/modules/command_console.sh
  44. 1 1
      lgsm/modules/command_debug.sh
  45. 1 1
      lgsm/modules/command_details.sh
  46. 6 6
      lgsm/modules/command_dev_clear_modules.sh
  47. 1 1
      lgsm/modules/command_dev_debug.sh
  48. 1 1
      lgsm/modules/command_dev_detect_deps.sh
  49. 1 1
      lgsm/modules/command_dev_detect_glibc.sh
  50. 1 1
      lgsm/modules/command_dev_detect_ldd.sh
  51. 4 4
      lgsm/modules/command_dev_query_raw.sh
  52. 1 1
      lgsm/modules/command_fastdl.sh
  53. 2 2
      lgsm/modules/command_install.sh
  54. 1 1
      lgsm/modules/command_install_resources_mta.sh
  55. 1 1
      lgsm/modules/command_mods_install.sh
  56. 1 1
      lgsm/modules/command_mods_remove.sh
  57. 1 1
      lgsm/modules/command_mods_update.sh
  58. 4 4
      lgsm/modules/command_monitor.sh
  59. 2 2
      lgsm/modules/command_postdetails.sh
  60. 1 1
      lgsm/modules/command_restart.sh
  61. 1 1
      lgsm/modules/command_send.sh
  62. 1 1
      lgsm/modules/command_skeleton.sh
  63. 1 1
      lgsm/modules/command_sponsor.sh
  64. 1 1
      lgsm/modules/command_start.sh
  65. 1 1
      lgsm/modules/command_stop.sh
  66. 1 1
      lgsm/modules/command_test_alert.sh
  67. 1 1
      lgsm/modules/command_ts3_server_pass.sh
  68. 1 1
      lgsm/modules/command_update.sh
  69. 24 24
      lgsm/modules/command_update_linuxgsm.sh
  70. 1 1
      lgsm/modules/command_validate.sh
  71. 1 1
      lgsm/modules/command_wipe.sh
  72. 1 1
      lgsm/modules/compress_unreal2_maps.sh
  73. 1 1
      lgsm/modules/compress_ut99_maps.sh
  74. 627 0
      lgsm/modules/core_dl.sh
  75. 61 0
      lgsm/modules/core_exit.sh
  76. 816 0
      lgsm/modules/core_functions.sh
  77. 215 0
      lgsm/modules/core_getopt.sh
  78. 114 0
      lgsm/modules/core_github.sh
  79. 93 0
      lgsm/modules/core_legacy.sh
  80. 110 0
      lgsm/modules/core_logs.sh
  81. 598 0
      lgsm/modules/core_messages.sh
  82. 816 0
      lgsm/modules/core_modules.sh
  83. 330 0
      lgsm/modules/core_steamcmd.sh
  84. 22 0
      lgsm/modules/core_trap.sh
  85. 4 4
      lgsm/modules/fix.sh
  86. 1 1
      lgsm/modules/fix_ark.sh
  87. 1 1
      lgsm/modules/fix_arma3.sh
  88. 1 1
      lgsm/modules/fix_armar.sh
  89. 1 1
      lgsm/modules/fix_av.sh
  90. 1 1
      lgsm/modules/fix_bo.sh
  91. 1 1
      lgsm/modules/fix_bt.sh
  92. 1 1
      lgsm/modules/fix_cmw.sh
  93. 1 1
      lgsm/modules/fix_csgo.sh
  94. 1 1
      lgsm/modules/fix_dst.sh
  95. 1 1
      lgsm/modules/fix_hw.sh
  96. 1 1
      lgsm/modules/fix_ins.sh
  97. 1 1
      lgsm/modules/fix_kf.sh
  98. 1 1
      lgsm/modules/fix_kf2.sh
  99. 2 2
      lgsm/modules/fix_lo.sh
  100. 1 1
      lgsm/modules/fix_mcb.sh

+ 1 - 1
.github/workflows/version-check.sh

@@ -1,6 +1,6 @@
 #!/bin/bash
 version=$(grep "version=" linuxgsm.sh | sed -e 's/version//g' | tr -d '="')
-modulesversion=$(grep "modulesversion=" lgsm/functions/core_functions.sh | sed -e 's/modulesversion//g' | tr -d '="')
+modulesversion=$(grep "modulesversion=" lgsm/modules/core_modules.sh | sed -e 's/modulesversion//g' | tr -d '="')
 
 if [ "${version}" != "${modulesversion}" ]; then
 	echo "Error! LinuxGSM version mismatch"

+ 51 - 49
lgsm/functions/core_dl.sh

@@ -17,7 +17,7 @@
 # fn_fetch_file "${remote_fileurl}" "${remote_fileurl_backup}" "${remote_fileurl_name}" "${remote_fileurl_backup_name}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${hash}"
 # fn_fetch_file "http://example.com/file.tar.bz2" "http://example.com/file2.tar.bz2" "file.tar.bz2" "file2.tar.bz2" "/some/dir" "file.tar.bz2" "chmodx" "run" "forcedl" "10cd7353aa9d758a075c600a6dd193fd"
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 fn_dl_steamcmd() {
 	fn_print_start_nl "${remotelocation}"
@@ -453,11 +453,13 @@ fn_fetch_file() {
 	fi
 }
 
-# GitHub file download functions.
+# GitHub file download modules.
 # Used to simplify downloading specific files from GitHub.
 
-# github_fileurl_dir: the directory of the file in the GitHub: lgsm/functions
-# github_fileurl_name: the filename of the file to download from GitHub: core_messages.sh
+# github_file_url_dir: the directory of the file in the GitHub: lgsm/modules
+# github_file_url_name: the filename of the file to download from GitHub: core_messages.sh
+# github_file_url_dir: the directory of the file in the GitHub: lgsm/modules
+# github_file_url_name: the filename of the file to download from GitHub: core_messages.sh
 # githuburl: the full GitHub url
 
 # remote_fileurl: The URL of the file: http://example.com/dl/File.tar.bz2
@@ -470,58 +472,58 @@ fn_fetch_file() {
 
 # Fetches files from the Git repo.
 fn_fetch_file_github() {
-	github_fileurl_dir="${1}"
-	github_fileurl_name="${2}"
+	github_file_url_dir="${1}"
+	github_file_url_name="${2}"
 	# For legacy versions - code can be removed at a future date
 	if [ "${legacymode}" == "1" ]; then
-		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_fileurl_dir}/${github_fileurl_name}"
-		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_fileurl_dir}/${github_fileurl_name}"
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
 	# If master branch will currently running LinuxGSM version to prevent "version mixing". This is ignored if a fork.
 	elif [ "${githubbranch}" == "master" ] && [ "${githubuser}" == "GameServerManagers" ] && [ "${commandname}" != "UPDATE-LGSM" ]; then
-		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${version}/${github_fileurl_dir}/${github_fileurl_name}"
-		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${version}/${github_fileurl_dir}/${github_fileurl_name}"
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${version}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${version}/${github_file_url_dir}/${github_file_url_name}"
 	else
-		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_fileurl_dir}/${github_fileurl_name}"
-		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_fileurl_dir}/${github_fileurl_name}"
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
 	fi
 	remote_fileurl_name="GitHub"
 	remote_fileurl_backup_name="Bitbucket"
 	local_filedir="${3}"
-	local_filename="${github_fileurl_name}"
+	local_filename="${github_file_url_name}"
 	chmodx="${4:-0}"
 	run="${5:-0}"
 	forcedl="${6:-0}"
 	hash="${7:-0}"
-	# Passes vars to the file download function.
+	# Passes vars to the file download module.
 	fn_fetch_file "${remote_fileurl}" "${remote_fileurl_backup}" "${remote_fileurl_name}" "${remote_fileurl_backup_name}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${hash}"
 }
 
 fn_check_file_github() {
-	github_fileurl_dir="${1}"
-	github_fileurl_name="${2}"
+	github_file_url_dir="${1}"
+	github_file_url_name="${2}"
 	if [ "${githubbranch}" == "master" ] && [ "${githubuser}" == "GameServerManagers" ] && [ "${commandname}" != "UPDATE-LGSM" ]; then
-		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${version}/${github_fileurl_dir}/${github_fileurl_name}"
-		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${version}/${github_fileurl_dir}/${github_fileurl_name}"
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${version}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${version}/${github_file_url_dir}/${github_file_url_name}"
 	else
-		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_fileurl_dir}/${github_fileurl_name}"
-		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_fileurl_dir}/${github_fileurl_name}"
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
 	fi
 	remote_fileurl_name="GitHub"
 	remote_fileurl_backup_name="Bitbucket"
-	fn_check_file "${remote_fileurl}" "${remote_fileurl_backup}" "${remote_fileurl_name}" "${remote_fileurl_backup_name}" "${github_fileurl_name}"
+	fn_check_file "${remote_fileurl}" "${remote_fileurl_backup}" "${remote_fileurl_name}" "${remote_fileurl_backup_name}" "${github_file_url_name}"
 }
 
 # Fetches config files from the Git repo.
 fn_fetch_config() {
-	github_fileurl_dir="${1}"
-	github_fileurl_name="${2}"
+	github_file_url_dir="${1}"
+	github_file_url_name="${2}"
 	# If master branch will currently running LinuxGSM version to prevent "version mixing". This is ignored if a fork.
 	if [ "${githubbranch}" == "master" ] && [ "${githubuser}" == "GameServerManagers" ] && [ "${commandname}" != "UPDATE-LGSM" ]; then
-		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${version}/${github_fileurl_dir}/${github_fileurl_name}"
-		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${version}/${github_fileurl_dir}/${github_fileurl_name}"
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${version}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${version}/${github_file_url_dir}/${github_file_url_name}"
 	else
-		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_fileurl_dir}/${github_fileurl_name}"
-		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_fileurl_dir}/${github_fileurl_name}"
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
 	fi
 	remote_fileurl_name="GitHub"
 	remote_fileurl_backup_name="Bitbucket"
@@ -531,55 +533,55 @@ fn_fetch_config() {
 	run="norun"
 	forcedl="noforce"
 	hash="nohash"
-	# Passes vars to the file download function.
+	# Passes vars to the file download module.
 	fn_fetch_file "${remote_fileurl}" "${remote_fileurl_backup}" "${remote_fileurl_name}" "${remote_fileurl_backup_name}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${hash}"
 }
 
 # Fetches modules from the Git repo during first download.
-fn_fetch_function() {
-	github_fileurl_dir="lgsm/functions"
-	github_fileurl_name="${functionfile}"
+fn_fetch_module() {
+	github_file_url_dir="lgsm/modules"
+	github_file_url_name="${modulefile}"
 	# If master branch will currently running LinuxGSM version to prevent "version mixing". This is ignored if a fork.
 	if [ "${githubbranch}" == "master" ] && [ "${githubuser}" == "GameServerManagers" ] && [ "${commandname}" != "UPDATE-LGSM" ]; then
-		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${version}/${github_fileurl_dir}/${github_fileurl_name}"
-		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${version}/${github_fileurl_dir}/${github_fileurl_name}"
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${version}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${version}/${github_file_url_dir}/${github_file_url_name}"
 	else
-		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_fileurl_dir}/${github_fileurl_name}"
-		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_fileurl_dir}/${github_fileurl_name}"
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
 	fi
 	remote_fileurl_name="GitHub"
 	remote_fileurl_backup_name="Bitbucket"
-	local_filedir="${functionsdir}"
-	local_filename="${github_fileurl_name}"
+	local_filedir="${modulesdir}"
+	local_filename="${github_file_url_name}"
 	chmodx="chmodx"
 	run="run"
 	forcedl="noforce"
 	hash="nohash"
-	# Passes vars to the file download function.
+	# Passes vars to the file download module.
 	fn_fetch_file "${remote_fileurl}" "${remote_fileurl_backup}" "${remote_fileurl_name}" "${remote_fileurl_backup_name}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${hash}"
 }
 
 # Fetches modules from the Git repo during update-lgsm.
-fn_update_function() {
-	github_fileurl_dir="lgsm/functions"
-	github_fileurl_name="${functionfile}"
+fn_update_module() {
+	github_file_url_dir="lgsm/modules"
+	github_file_url_name="${modulefile}"
 	# If master branch will currently running LinuxGSM version to prevent "version mixing". This is ignored if a fork.
 	if [ "${githubbranch}" == "master" ] && [ "${githubuser}" == "GameServerManagers" ] && [ "${commandname}" != "UPDATE-LGSM" ]; then
-		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${version}/${github_fileurl_dir}/${github_fileurl_name}"
-		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${version}/${github_fileurl_dir}/${github_fileurl_name}"
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${version}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${version}/${github_file_url_dir}/${github_file_url_name}"
 	else
-		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_fileurl_dir}/${github_fileurl_name}"
-		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_fileurl_dir}/${github_fileurl_name}"
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
 	fi
 	remote_fileurl_name="GitHub"
 	remote_fileurl_backup_name="Bitbucket"
-	local_filedir="${functionsdir}"
-	local_filename="${github_fileurl_name}"
+	local_filedir="${modulesdir}"
+	local_filename="${github_file_url_name}"
 	chmodx="chmodx"
 	run="norun"
 	forcedl="noforce"
 	hash="nohash"
-	# Passes vars to the file download function.
+	# Passes vars to the file download module.
 	fn_fetch_file "${remote_fileurl}" "${remote_fileurl_backup}" "${remote_fileurl_name}" "${remote_fileurl_backup_name}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${hash}"
 
 }
@@ -618,7 +620,7 @@ fn_dl_latest_release_github() {
 			fn_print_fail_nl "Cannot get version from GitHub API for ${githubreleaseuser}/${githubreleaserepo}"
 			fn_script_log_fatal "Cannot get version from GitHub API for ${githubreleaseuser}/${githubreleaserepo}"
 		else
-			# Fetch file from the remote location from the existing function to the ${tmpdir} for now.
+			# Fetch file from the remote location from the existing module to the ${tmpdir} for now.
 			fn_fetch_file "${githubreleasedownloadlink}" "" "${githubreleasefilename}" "" "${githubreleasedownloadpath}" "${githubreleasefilename}"
 		fi
 	fi

+ 9 - 9
lgsm/functions/core_exit.sh

@@ -5,14 +5,14 @@
 # Website: https://linuxgsm.com
 # Description: Handles exiting of LinuxGSM by running and reporting an exit code.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 fn_exit_dev_debug() {
 	if [ -f "${rootdir}/.dev-debug" ]; then
 		echo -e ""
-		echo -e "${functionselfname} exiting with code: ${exitcode}"
+		echo -e "${moduleselfname} exiting with code: ${exitcode}"
 		if [ -f "${rootdir}/dev-debug.log" ]; then
-			grep "functionfile=" "${rootdir}/dev-debug.log" | sed 's/functionfile=//g' > "${rootdir}/dev-debug-function-order.log"
+			grep "modulefile=" "${rootdir}/dev-debug.log" | sed 's/modulefile=//g' > "${rootdir}/dev-debug-module-order.log"
 		fi
 	fi
 }
@@ -29,13 +29,13 @@ elif [ "${exitcode}" != "0" ]; then
 	# List LinuxGSM version in logs
 	fn_script_log_info "LinuxGSM version: ${version}"
 	if [ "${exitcode}" == "1" ]; then
-		fn_script_log_fatal "${functionselfname} exiting with code: ${exitcode}"
+		fn_script_log_fatal "${moduleselfname} exiting with code: ${exitcode}"
 	elif [ "${exitcode}" == "2" ]; then
-		fn_script_log_error "${functionselfname} exiting with code: ${exitcode}"
+		fn_script_log_error "${moduleselfname} exiting with code: ${exitcode}"
 	elif [ "${exitcode}" == "3" ]; then
-		fn_script_log_warn "${functionselfname} exiting with code: ${exitcode}"
+		fn_script_log_warn "${moduleselfname} exiting with code: ${exitcode}"
 	else
-		fn_script_log_warn "${functionselfname} exiting with code: ${exitcode}"
+		fn_script_log_warn "${moduleselfname} exiting with code: ${exitcode}"
 	fi
 	fn_exit_dev_debug
 	# remove trap.
@@ -44,7 +44,7 @@ elif [ "${exitcode}" != "0" ]; then
 elif [ "${exitcode}" ] && [ "${exitcode}" == "0" ]; then
 	# List LinuxGSM version in logs
 	fn_script_log_info "LinuxGSM version: ${version}"
-	fn_script_log_pass "${functionselfname} exiting with code: ${exitcode}"
+	fn_script_log_pass "${moduleselfname} exiting with code: ${exitcode}"
 	fn_exit_dev_debug
 	# remove trap.
 	trap - INT
@@ -53,7 +53,7 @@ else
 	# List LinuxGSM version in logs
 	fn_script_log_info "LinuxGSM version: ${version}"
 	fn_print_error "No exit code set"
-	fn_script_log_pass "${functionselfname} exiting with code: NOT SET"
+	fn_script_log_pass "${moduleselfname} exiting with code: NOT SET"
 	fn_exit_dev_debug
 	# remove trap.
 	trap - INT

+ 1 - 1
lgsm/functions/core_functions.sh

@@ -6,7 +6,7 @@
 # Description: Defines all functions to allow download and execution of functions using fn_fetch_function.
 # This function is called first before any other function. Without this file other functions will not load.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+module_selfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 modulesversion="v23.2.0"
 

+ 5 - 5
lgsm/functions/core_getopt.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: getopt arguments.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 ### Define all commands here.
 ## User commands | Trigger commands | Description
@@ -18,11 +18,11 @@ cmd_restart=("r;restart" "command_restart.sh" "Restart the server.")
 cmd_details=("dt;details" "command_details.sh" "Display server information.")
 cmd_postdetails=("pd;postdetails" "command_postdetails.sh" "Post details to termbin.com (removing passwords).")
 cmd_backup=("b;backup" "command_backup.sh" "Create backup archives of the server.")
-cmd_update_linuxgsm=("ul;update-lgsm;uf;update-functions" "command_update_linuxgsm.sh" "Check and apply any LinuxGSM updates.")
+cmd_update_linuxgsm=("ul;update-lgsm;uf;update-modules" "command_update_linuxgsm.sh" "Check and apply any LinuxGSM updates.")
 cmd_test_alert=("ta;test-alert" "command_test_alert.sh" "Send a test alert.")
 cmd_monitor=("m;monitor" "command_monitor.sh" "Check server status and restart if crashed.")
 cmd_skeleton=("sk;skeleton" "command_skeleton.sh" "Create a skeleton directory.")
-cmd_sponsor=("s;sponsor" "command_sponsor.sh" "Donation options.")
+cmd_sponso=("s;sponsor" "command_sponsor.sh" "Donation options.")
 cmd_send=("sd;send" "command_send.sh" "Send command to game server console.")
 # Console servers only.
 cmd_console=("c;console" "command_console.sh" "Access server console.")
@@ -54,7 +54,7 @@ cmd_dev_detect_deps=("dd;detect-deps" "command_dev_detect_deps.sh" "Detect requi
 cmd_dev_detect_glibc=("dg;detect-glibc" "command_dev_detect_glibc.sh" "Detect required glibc.")
 cmd_dev_detect_ldd=("dl;detect-ldd" "command_dev_detect_ldd.sh" "Detect required dynamic dependencies.")
 cmd_dev_query_raw=("qr;query-raw" "command_dev_query_raw.sh" "The raw output of gamedig and gsquery.")
-cmd_dev_clear_functions=("cf;clear-functions" "command_dev_clear_functions.sh" "Delete the contents of the functions dir.")
+cmd_dev_clear_modules=("cf;clear-modules" "command_dev_clear_modules.sh" "Delete the contents of the modules dir.")
 
 ### Set specific opt here.
 
@@ -145,7 +145,7 @@ currentopt+=("${cmd_install[@]}" "${cmd_auto_install[@]}")
 ## Developer commands.
 currentopt+=("${cmd_dev_debug[@]}")
 if [ -f ".dev-debug" ]; then
-	currentopt+=("${cmd_dev_detect_deps[@]}" "${cmd_dev_detect_glibc[@]}" "${cmd_dev_detect_ldd[@]}" "${cmd_dev_query_raw[@]}" "${cmd_dev_clear_functions[@]}")
+	currentopt+=("${cmd_dev_detect_deps[@]}" "${cmd_dev_detect_glibc[@]}" "${cmd_dev_detect_ldd[@]}" "${cmd_dev_query_raw[@]}" "${cmd_dev_clear_modules[@]}")
 fi
 
 ## Sponsor.

+ 3 - 3
lgsm/functions/core_github.sh

@@ -1,11 +1,11 @@
 #!/bin/bash
-# LinuxGSM core_github.sh function
+# LinuxGSM core_github.sh module
 # Author: Daniel Gibbs
 # Contributors: http://linuxgsm.com/contrib
 # Website: https://linuxgsm.com
-# Description: core function file for updates via github
+# Description: core module file for updates via github
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 github_api="https://api.github.com"
 

+ 10 - 1
lgsm/functions/core_legacy.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Code for backwards compatability with older versions of LinuxGSM.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 # This is to help the transition to v20.3.0 and above
 legacy_versions_array=(v20.2.1 v20.2.0 v20.1.5 v20.1.4 v20.1.3 v20.1.2 v20.1.1 v20.1.0 v19.12.5 v19.12.4 v19.12.3 v19.12.2 v19.12.1 v19.12.0)
@@ -78,6 +78,15 @@ if [ -z "${wsstartmap}" ]; then
 	fi
 fi
 
+# Added as part of migrating functions dir to modules dir.
+# Will remove functions dir if files in modules dir older than 14 days
+functionsdir="${lgsmdir}/modules"
+if [ -d "${lgsmdir}/functions" ]; then
+	if [ "$(find "${lgsmdir}/modules"/ -type f -mtime +"14" | wc -l)" -ne "0" ]; then
+		rm -rf "${lgsmdir:?}/functions"
+	fi
+fi
+
 fn_parms() {
 	fn_reload_startparameters
 	parms="${startparameters}"

+ 1 - 1
lgsm/functions/core_logs.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Acts as a log rotator, removing old logs.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 # Check if logfile variable and file exist, create logfile if it doesn't exist.
 if [ "${consolelog}" ]; then

+ 1 - 1
lgsm/functions/core_messages.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Defines on-screen messages such as [  OK  ] and how script logs look.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 # nl: new line: message is following by a new line.
 # eol: end of line: message is placed at the end of the current line.

+ 816 - 0
lgsm/functions/core_modules.sh

@@ -0,0 +1,816 @@
+#!/bin/bash
+# LinuxGSM core_modules.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Defines all modules to allow download and execution of modules using fn_fetch_module.
+# This module is called first before any other module. Without this file other modules will not load.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+modulesversion="v23.2.0"
+
+# Core
+
+core_dl.sh() {
+	modulefile="${FUNCNAME[0]}"
+	if [ "$(type fn_fetch_core_dl 2> /dev/null)" ]; then
+		fn_fetch_core_dl "lgsm/modules" "core_dl.sh" "${modulesdir}" "chmodx" "run" "noforcedl" "nohash"
+	else
+		fn_bootstrap_fetch_file_github "lgsm/modules" "core_dl.sh" "${modulesdir}" "chmodx" "run" "noforcedl" "nohash"
+	fi
+}
+
+core_messages.sh() {
+	modulefile="${FUNCNAME[0]}"
+	if [ "$(type fn_fetch_core_dl 2> /dev/null)" ]; then
+		fn_fetch_core_dl "lgsm/modules" "core_messages.sh" "${modulesdir}" "chmodx" "run" "noforcedl" "nohash"
+	else
+		fn_bootstrap_fetch_file_github "lgsm/modules" "core_messages.sh" "${modulesdir}" "chmodx" "run" "noforcedl" "nohash"
+	fi
+}
+
+core_legacy.sh() {
+	modulefile="${FUNCNAME[0]}"
+	if [ "$(type fn_fetch_core_dl 2> /dev/null)" ]; then
+		fn_fetch_core_dl "lgsm/modules" "core_legacy.sh" "${modulesdir}" "chmodx" "run" "noforcedl" "nohash"
+	else
+		fn_bootstrap_fetch_file_github "lgsm/modules" "core_legacy.sh" "${modulesdir}" "chmodx" "run" "noforcedl" "nohash"
+	fi
+}
+
+core_exit.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+core_getopt.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+core_trap.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+core_steamcmd.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+core_github.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+# Commands
+
+command_backup.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_console.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_debug.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_details.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_sponsor.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_postdetails.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_test_alert.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_monitor.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_start.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_stop.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_validate.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_install.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_install_resources_mta.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_squad_license.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_mods_install.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_mods_update.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_mods_remove.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_fastdl.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_ts3_server_pass.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_restart.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_skeleton.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_wipe.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_send.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+# Checks
+
+check.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_config.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_deps.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_executable.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_glibc.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_ip.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_last_update.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_logs.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_permissions.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_root.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_status.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_steamcmd.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_system_dir.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_system_requirements.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_tmuxception.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_version.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+# Compress
+
+compress_unreal2_maps.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+compress_ut99_maps.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+# Mods
+
+mods_list.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+mods_core.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+# Dev
+
+command_dev_clear_modules.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_dev_debug.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_dev_detect_deps.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_dev_detect_glibc.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_dev_detect_ldd.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_dev_query_raw.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+# Fix
+
+fix.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_ark.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_av.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_arma3.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_armar.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_bt.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_bo.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_cmw.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_csgo.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_dst.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_hw.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_ins.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_kf.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_kf2.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_lo.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_mcb.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_mta.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_nmrih.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_onset.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_ro.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_rust.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_rw.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_sfc.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_st.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_steamcmd.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_terraria.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_tf2.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_ut3.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_rust.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_samp.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_sdtd.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_sof2.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_squad.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_ts3.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_ut2k4.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_ut.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_unt.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_vh.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_wurm.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_zmr.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+# Info
+
+info_distro.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+info_game.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+info_messages.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+info_stats.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+# Alert
+
+alert.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+alert_discord.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+alert_email.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+alert_ifttt.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+alert_mailgun.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+alert_pushbullet.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+alert_pushover.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+alert_gotify.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+alert_telegram.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+alert_rocketchat.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+alert_slack.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+# Logs
+
+core_logs.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+# Query
+
+query_gamedig.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+# Update
+
+command_update_modules.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_update_linuxgsm.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_update.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_check_update.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+update_ts3.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+update_minecraft.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+update_minecraft_bedrock.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+update_papermc.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+update_mta.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+update_factorio.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+update_jediknight2.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+update_steamcmd.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+update_vintagestory.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+update_ut99.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fn_update_modules.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+#
+## Installer modules
+#
+
+fn_autoinstall() {
+	autoinstall=1
+	command_install.sh
+}
+
+install_complete.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_config.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_factorio_save.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_dst_token.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_eula.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_gsquery.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_gslt.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_header.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_logs.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_retry.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_server_dir.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+install_server_files.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_stats.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_steamcmd.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_ts3.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_ts3db.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_ut2k4.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_dl_ut2k4.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_ut2k4_key.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+# Calls code required for legacy servers
+core_legacy.sh
+
+# Creates tmp dir if missing
+if [ ! -d "${tmpdir}" ]; then
+	mkdir -p "${tmpdir}"
+fi
+
+# Creates lock dir if missing
+if [ ! -d "${lockdir}" ]; then
+	mkdir -p "${lockdir}"
+fi
+
+# Calls on-screen messages (bootstrap)
+core_messages.sh
+
+#Calls file downloader (bootstrap)
+core_dl.sh
+
+# Calls the global Ctrl-C trap
+core_trap.sh

+ 2 - 2
lgsm/functions/core_steamcmd.sh

@@ -3,9 +3,9 @@
 # Author: Daniel Gibbs
 # Contributors: http://linuxgsm.com/contrib
 # Website: https://linuxgsm.com
-# Description: Core functions for SteamCMD
+# Description: Core modules for SteamCMD
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 fn_install_steamcmd() {
 	if [ "${shortname}" == "ark" ] && [ "${installsteamcmd}" == "1" ]; then

+ 1 - 1
lgsm/functions/core_trap.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Handles CTRL-C trap to give an exit code.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 fn_exit_trap() {
 	if [ -z "${exitcode}" ]; then

+ 0 - 0
lgsm/functions/README.md → lgsm/modules/README.md


+ 2 - 2
lgsm/functions/alert.sh → lgsm/modules/alert.sh

@@ -3,9 +3,9 @@
 # Author: Daniel Gibbs
 # Contributors: http://linuxgsm.com/contrib
 # Website: https://linuxgsm.com
-# Description: Overall function for managing alerts.
+# Description: Overall module for managing alerts.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 # Generates alert log of the details at the time of the alert.
 # Used with email alerts.

+ 1 - 1
lgsm/functions/alert_discord.sh → lgsm/modules/alert_discord.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Sends Discord alert.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 json=$(
 	cat << EOF

+ 1 - 1
lgsm/functions/alert_email.sh → lgsm/modules/alert_email.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Sends email alert.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 fn_print_dots "Sending Email alert: ${email}"
 fn_sleep_time

+ 1 - 1
lgsm/functions/alert_gotify.sh → lgsm/modules/alert_gotify.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Sends Gotify alert.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+module_selfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 json=$(
 	cat << EOF

+ 1 - 1
lgsm/functions/alert_ifttt.sh → lgsm/modules/alert_ifttt.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Sends IFTTT alert.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 json=$(
 	cat << EOF

+ 1 - 1
lgsm/functions/alert_mailgun.sh → lgsm/modules/alert_mailgun.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Sends Mailgun Email alert.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 if [ "${mailgunapiregion}" == "eu" ]; then
 	mailgunapiurl="https://api.eu.mailgun.net"

+ 1 - 1
lgsm/functions/alert_pushbullet.sh → lgsm/modules/alert_pushbullet.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Sends Pushbullet Messenger alert.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 json=$(
 	cat << EOF

+ 1 - 1
lgsm/functions/alert_pushover.sh → lgsm/modules/alert_pushover.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Sends Pushover alert.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 fn_print_dots "Sending Pushover alert"
 

+ 1 - 1
lgsm/functions/alert_rocketchat.sh → lgsm/modules/alert_rocketchat.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Sends Rocketchat alert.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 json=$(
 	cat << EOF

+ 1 - 1
lgsm/functions/alert_slack.sh → lgsm/modules/alert_slack.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Sends Slack alert.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 json=$(
 	cat << EOF

+ 1 - 1
lgsm/functions/alert_telegram.sh → lgsm/modules/alert_telegram.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Sends Telegram Messenger alert.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 json=$(
 	cat << EOF

+ 2 - 2
lgsm/functions/check.sh → lgsm/modules/check.sh

@@ -3,10 +3,10 @@
 # Author: Daniel Gibbs
 # Contributors: http://linuxgsm.com/contrib
 # Website: https://linuxgsm.com
-# Description: Overall function for managing checks.
+# Description: Overall module for managing checks.
 # Runs checks that will either halt on or fix an issue.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 # Every command that requires checks just references check.sh.
 # check.sh selects which checks to run by using arrays.

+ 1 - 1
lgsm/functions/check_config.sh → lgsm/modules/check_config.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Checks if the server config is missing and warns the user if needed.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 if [ -n "${servercfgfullpath}" ] && [ ! -f "${servercfgfullpath}" ]; then
 	fn_print_dots ""

+ 1 - 1
lgsm/functions/check_deps.sh → lgsm/modules/check_deps.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Checks and installs missing dependencies.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 fn_install_mono_repo() {
 	if [ "${autodepinstall}" == "0" ]; then

+ 1 - 1
lgsm/functions/check_executable.sh → lgsm/modules/check_executable.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Checks if server executable exists.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 # Check if executable exists
 execname=$(basename "${executable}")

+ 1 - 1
lgsm/functions/check_glibc.sh → lgsm/modules/check_glibc.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Checks if the server has the correct Glibc version.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 info_distro.sh
 

+ 1 - 1
lgsm/functions/check_ip.sh → lgsm/modules/check_ip.sh

@@ -6,7 +6,7 @@
 # Description: Automatically identifies the server interface IP.
 # If multiple interfaces are detected the user will need to manually set using ip="0.0.0.0".
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 info_game.sh
 

+ 1 - 1
lgsm/functions/check_last_update.sh → lgsm/modules/check_last_update.sh

@@ -6,7 +6,7 @@
 # Description: Checks lock file to see when last update happened.
 # Will reboot server if instance not rebooted since update.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 if [ -f "${lockdir}/${selfname}-laststart.lock" ]; then
 	laststart=$(cat "${lockdir}/${selfname}-laststart.lock")

+ 1 - 1
lgsm/functions/check_logs.sh → lgsm/modules/check_logs.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Checks if log files exist.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 fn_check_logs() {
 	fn_print_dots "Checking for log files"

+ 8 - 8
lgsm/functions/check_permissions.sh → lgsm/modules/check_permissions.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Checks ownership & permissions of scripts, files and directories.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 fn_check_ownership() {
 	if [ -f "${rootdir}/${selfname}" ]; then
@@ -13,8 +13,8 @@ fn_check_ownership() {
 			selfownissue=1
 		fi
 	fi
-	if [ -d "${functionsdir}" ]; then
-		if [ "$(find "${functionsdir}" -not -user "$(whoami)" | wc -l)" -ne "0" ]; then
+	if [ -d "${modulesdir}" ]; then
+		if [ "$(find "${modulesdir}" -not -user "$(whoami)" | wc -l)" -ne "0" ]; then
 			funcownissue=1
 		fi
 	fi
@@ -34,7 +34,7 @@ fn_check_ownership() {
 				find "${rootdir}/${selfname}" -not -user "$(whoami)" -printf "%u\t%g\t%p\n"
 			fi
 			if [ "${funcownissue}" == "1" ]; then
-				find "${functionsdir}" -not -user "$(whoami)" -printf "%u\t%g\t%p\n"
+				find "${modulesdir}" -not -user "$(whoami)" -printf "%u\t%g\t%p\n"
 			fi
 			if [ "${filesownissue}" == "1" ]; then
 				find "${serverfiles}" -not -user "$(whoami)" -printf "%u\t%g\t%p\n"
@@ -53,15 +53,15 @@ fn_check_ownership() {
 }
 
 fn_check_permissions() {
-	if [ -d "${functionsdir}" ]; then
-		if [ "$(find "${functionsdir}" -type f -not -executable | wc -l)" -ne "0" ]; then
+	if [ -d "${modulesdir}" ]; then
+		if [ "$(find "${modulesdir}" -type f -not -executable | wc -l)" -ne "0" ]; then
 			fn_print_fail_nl "Permissions issues found"
 			fn_script_log_fatal "Permissions issues found"
 			fn_print_information_nl "The following files are not executable:"
 			fn_script_log_info "The following files are not executable:"
 			{
 				echo -e "File\n"
-				find "${functionsdir}" -type f -not -executable -printf "%p\n"
+				find "${modulesdir}" -type f -not -executable -printf "%p\n"
 			} | column -s $'\t' -t | tee -a "${lgsmlog}"
 			if [ "${monitorflag}" == 1 ]; then
 				alert="permissions"
@@ -141,7 +141,7 @@ fn_check_permissions() {
 	fi
 }
 
-## The following fn_sys_perm_* functions checks for permission errors in /sys directory.
+## The following fn_sys_perm_* modules checks for permission errors in /sys directory.
 
 # Checks for permission errors in /sys directory.
 fn_sys_perm_errors_detect() {

+ 1 - 1
lgsm/functions/check_root.sh → lgsm/modules/check_root.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Checks if the user tried to run the script as root.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 if [ "$(whoami)" == "root" ] && [ ! -f /.dockerenv ]; then
 	if [ "${commandname}" != "INSTALL" ]; then

+ 1 - 1
lgsm/functions/check_status.sh → lgsm/modules/check_status.sh

@@ -5,6 +5,6 @@
 # Website: https://linuxgsm.com
 # Description: Checks the process status of the server. Either online or offline.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 status=$(tmux list-sessions -F "#{session_name}" 2> /dev/null | grep -Ecx "^${sessionname}")

+ 2 - 2
lgsm/functions/check_steamcmd.sh → lgsm/modules/check_steamcmd.sh

@@ -5,9 +5,9 @@
 # Website: https://linuxgsm.com
 # Description: Checks if SteamCMD is installed correctly.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
-# init steamcmd functions
+# init steamcmd functions.
 core_steamcmd.sh
 
 fn_check_steamcmd_clear

+ 1 - 1
lgsm/functions/check_system_dir.sh → lgsm/modules/check_system_dir.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Checks if systemdir/serverfiles is accessible.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 if [ "${commandname}" != "VALIDATE" ]; then
 	checkdir="${serverfiles}"

+ 1 - 1
lgsm/functions/check_system_requirements.sh → lgsm/modules/check_system_requirements.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Checks RAM requirements.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 info_distro.sh
 

+ 1 - 1
lgsm/functions/check_tmuxception.sh → lgsm/modules/check_tmuxception.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Checks if run from tmux or screen.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 fn_check_is_in_tmux() {
 	if [ "${TMUX}" ]; then

+ 1 - 1
lgsm/functions/check_version.sh → lgsm/modules/check_version.sh

@@ -6,7 +6,7 @@
 # Description: Will run update-lgsm if gameserver.sh and modules version does not match
 # this will allow gameserver.sh to update - useful for multi instance servers.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 if [ -n "${modulesversion}" ] && [ -n "${version}" ] && [ "${version}" != "${modulesversion}" ]; then
 	exitbypass=1

+ 1 - 1
lgsm/functions/command_backup.sh → lgsm/modules/command_backup.sh

@@ -7,7 +7,7 @@
 
 commandname="BACKUP"
 commandaction="Backing up"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 check.sh

+ 1 - 1
lgsm/functions/command_check_update.sh → lgsm/modules/command_check_update.sh

@@ -7,7 +7,7 @@
 
 commandname="CHECK-UPDATE"
 commandaction="check for Update"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 fn_print_dots ""

+ 1 - 1
lgsm/functions/command_console.sh → lgsm/modules/command_console.sh

@@ -7,7 +7,7 @@
 
 commandname="CONSOLE"
 commandaction="Access console"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 check.sh

+ 1 - 1
lgsm/functions/command_debug.sh → lgsm/modules/command_debug.sh

@@ -7,7 +7,7 @@
 
 commandname="DEBUG"
 commandaction="Debuging"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 # Trap to remove lockfile on quit.

+ 1 - 1
lgsm/functions/command_details.sh → lgsm/modules/command_details.sh

@@ -7,7 +7,7 @@
 
 commandname="DETAILS"
 commandaction="Viewing details"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 # Run checks and gathers details to display.

+ 6 - 6
lgsm/functions/command_dev_clear_functions.sh → lgsm/modules/command_dev_clear_modules.sh

@@ -1,21 +1,21 @@
 #!/bin/bash
-# LinuxGSM command_dev_clear_functions.sh module
+# LinuxGSM command_dev_clear_modules.sh module
 # Author: Daniel Gibbs
 # Contributors: http://linuxgsm.com/contrib
 # Website: https://linuxgsm.com
-# Description: Deletes the contents of the functions dir.
+# Description: Deletes the contents of the modules dir.
 
 commandname="DEV-CLEAR-MODULES"
 commandaction="Clearing modules"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 echo -e "================================="
-echo -e "Clear Functions"
+echo -e "Clear Modules"
 echo -e "================================="
 echo -e ""
-if fn_prompt_yn "Do you want to delete all functions?" Y; then
-	rm -rfv "${functionsdir:?}/"*
+if fn_prompt_yn "Do you want to delete all modules?" Y; then
+	rm -rfv "${modulesdir:?}/"*
 	rm -rfv "${configdirdefault:?}/"*
 	fn_script_log_info "Cleared modules directory"
 	fn_script_log_info "Cleared default config directory"

+ 1 - 1
lgsm/functions/command_dev_debug.sh → lgsm/modules/command_dev_debug.sh

@@ -7,7 +7,7 @@
 
 commandname="DEV-DEBUG"
 commandaction="Developer debug"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_reset
 
 if [ -f "${rootdir}/.dev-debug" ]; then

+ 1 - 1
lgsm/functions/command_dev_detect_deps.sh → lgsm/modules/command_dev_detect_deps.sh

@@ -7,7 +7,7 @@
 
 commandname="DEV-DETECT-DEPS"
 commandaction="Developer detect deps"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 echo -e "================================="

+ 1 - 1
lgsm/functions/command_dev_detect_glibc.sh → lgsm/modules/command_dev_detect_glibc.sh

@@ -8,7 +8,7 @@
 
 commandname="DEV-DETECT-GLIBC"
 commandaction="Developer detect glibc"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 echo -e "================================="

+ 1 - 1
lgsm/functions/command_dev_detect_ldd.sh → lgsm/modules/command_dev_detect_ldd.sh

@@ -8,7 +8,7 @@
 
 commandname="DEV-DETECT-LDD"
 commandaction="Developer detect ldd"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 echo -e "================================="

+ 4 - 4
lgsm/functions/command_dev_query_raw.sh → lgsm/modules/command_dev_query_raw.sh

@@ -7,7 +7,7 @@
 
 commandname="DEV-QUERY-RAW"
 commandaction="Developer query raw"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 check.sh
@@ -229,10 +229,10 @@ echo -e ""
 for queryip in "${queryips[@]}"; do
 	echo -e "./query_gsquery.py -a \"${queryip}\" -p \"${queryport}\" -e \"${querytype}\""
 	echo -e ""
-	if [ ! -f "${functionsdir}/query_gsquery.py" ]; then
-		fn_fetch_file_github "lgsm/functions" "query_gsquery.py" "${functionsdir}" "chmodx" "norun" "noforce" "nohash"
+	if [ ! -f "${modulesdir}/query_gsquery.py" ]; then
+		fn_fetch_file_github "lgsm/modules" "query_gsquery.py" "${modulesdir}" "chmodx" "norun" "noforce" "nohash"
 	fi
-	"${functionsdir}"/query_gsquery.py -a "${queryip}" -p "${queryport}" -e "${querytype}"
+	"${modulesdir}"/query_gsquery.py -a "${queryip}" -p "${queryport}" -e "${querytype}"
 done
 echo -e ""
 echo -e "${lightgreen}TCP Raw Output${default}"

+ 1 - 1
lgsm/functions/command_fastdl.sh → lgsm/modules/command_fastdl.sh

@@ -7,7 +7,7 @@
 
 commandname="FASTDL"
 commandaction="Fastdl"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 check.sh

+ 2 - 2
lgsm/functions/command_install.sh → lgsm/modules/command_install.sh

@@ -3,11 +3,11 @@
 # Author: Daniel Gibbs
 # Contributors: http://linuxgsm.com/contrib
 # Website: https://linuxgsm.com
-# Description: Overall function for the installer.
+# Description: Overall module for the installer.
 
 commandname="INSTALL"
 commandaction="Installing"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 check.sh

+ 1 - 1
lgsm/functions/command_install_resources_mta.sh → lgsm/modules/command_install_resources_mta.sh

@@ -7,7 +7,7 @@
 
 commandname="DEFAULT-RESOURCES"
 commandaction="Default Resources"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 fn_install_resources() {

+ 1 - 1
lgsm/functions/command_mods_install.sh → lgsm/modules/command_mods_install.sh

@@ -7,7 +7,7 @@
 
 commandname="MODS-INSTALL"
 commandaction="Installing mods"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 check.sh

+ 1 - 1
lgsm/functions/command_mods_remove.sh → lgsm/modules/command_mods_remove.sh

@@ -7,7 +7,7 @@
 
 commandname="MODS-REMOVE"
 commandaction="Removing mods"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 check.sh

+ 1 - 1
lgsm/functions/command_mods_update.sh → lgsm/modules/command_mods_update.sh

@@ -7,7 +7,7 @@
 
 commandname="MODS-UPDATE"
 commandaction="Updating mods"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 check.sh

+ 4 - 4
lgsm/functions/command_monitor.sh → lgsm/modules/command_monitor.sh

@@ -8,7 +8,7 @@
 
 commandname="MONITOR"
 commandaction="Monitoring"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 fn_monitor_check_lockfile() {
@@ -84,10 +84,10 @@ fn_monitor_check_queryport() {
 }
 
 fn_query_gsquery() {
-	if [ ! -f "${functionsdir}/query_gsquery.py" ]; then
-		fn_fetch_file_github "lgsm/functions" "query_gsquery.py" "${functionsdir}" "chmodx" "norun" "noforce" "nohash"
+	if [ ! -f "${modulesdir}/query_gsquery.py" ]; then
+		fn_fetch_file_github "lgsm/modules" "query_gsquery.py" "${modulesdir}" "chmodx" "norun" "noforce" "nohash"
 	fi
-	"${functionsdir}"/query_gsquery.py -a "${queryip}" -p "${queryport}" -e "${querytype}" > /dev/null 2>&1
+	"${modulesdir}"/query_gsquery.py -a "${queryip}" -p "${queryport}" -e "${querytype}" > /dev/null 2>&1
 	querystatus="$?"
 }
 

+ 2 - 2
lgsm/functions/command_postdetails.sh → lgsm/modules/command_postdetails.sh

@@ -7,12 +7,12 @@
 
 commandname="POST-DETAILS"
 commandaction="Posting details"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 posttarget="https://termbin.com"
 
-# source all of the functions defined in the details command.
+# source all of the modules defined in the details command.
 info_messages.sh
 
 fn_bad_postdetailslog() {

+ 1 - 1
lgsm/functions/command_restart.sh → lgsm/modules/command_restart.sh

@@ -7,7 +7,7 @@
 
 commandname="MODS-INSTALL"
 commandaction="Restarting"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 info_game.sh

+ 1 - 1
lgsm/functions/command_send.sh → lgsm/modules/command_send.sh

@@ -7,7 +7,7 @@
 
 commandname="SEND"
 commandaction="Send"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 check.sh

+ 1 - 1
lgsm/functions/command_skeleton.sh → lgsm/modules/command_skeleton.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Creates an copy of a game servers directorys.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 fn_print_dots "Creating skeleton directory"
 check.sh

+ 1 - 1
lgsm/functions/command_sponsor.sh → lgsm/modules/command_sponsor.sh

@@ -7,7 +7,7 @@
 
 commandname="SPONSOR"
 commandaction="Sponsor"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 fn_print_ascii_logo

+ 1 - 1
lgsm/functions/command_start.sh → lgsm/modules/command_start.sh

@@ -7,7 +7,7 @@
 
 commandname="START"
 commandaction="Starting"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 addtimestamp="gawk '{ print strftime(\\\"[$logtimestampformat]\\\"), \\\$0 }'"
 fn_firstcommand_set
 

+ 1 - 1
lgsm/functions/command_stop.sh → lgsm/modules/command_stop.sh

@@ -7,7 +7,7 @@
 
 commandname="STOP"
 commandaction="Stopping"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 # Attempts graceful shutdown by sending 'CTRL+c'.

+ 1 - 1
lgsm/functions/command_test_alert.sh → lgsm/modules/command_test_alert.sh

@@ -7,7 +7,7 @@
 
 commandname="TEST-ALERT"
 commandaction="Sending Alert"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 fn_print_dots "${servername}"

+ 1 - 1
lgsm/functions/command_ts3_server_pass.sh → lgsm/modules/command_ts3_server_pass.sh

@@ -7,7 +7,7 @@
 
 commandname="CHANGE-PASSWORD"
 commandaction="Changing password"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 fn_serveradmin_password_prompt() {

+ 1 - 1
lgsm/functions/command_update.sh → lgsm/modules/command_update.sh

@@ -7,7 +7,7 @@
 
 commandname="UPDATE"
 commandaction="Updating"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 fn_print_dots ""

+ 24 - 24
lgsm/functions/command_update_linuxgsm.sh → lgsm/modules/command_update_linuxgsm.sh

@@ -3,11 +3,11 @@
 # Author: Daniel Gibbs
 # Contributors: http://linuxgsm.com/contrib
 # Website: https://linuxgsm.com
-# Description: Deletes the functions dir to allow re-downloading of functions from GitHub.
+# Description: Deletes the modules dir to allow re-downloading of modules from GitHub.
 
 commandname="UPDATE-LGSM"
 commandaction="Updating LinuxGSM"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 check.sh
@@ -180,49 +180,49 @@ if [ -f "${datadir}/${distroid}-${distroversioncsv}.csv" ]; then
 	fi
 fi
 # Check and update modules.
-if [ -n "${functionsdir}" ]; then
-	if [ -d "${functionsdir}" ]; then
+if [ -n "${modulesdir}" ]; then
+	if [ -d "${modulesdir}" ]; then
 		(
-			cd "${functionsdir}" || exit
-			for functionfile in *; do
+			cd "${modulesdir}" || exit
+			for modulefile in *; do
 				# check if module exists in the repo and remove if missing.
 				# commonly used if module names change.
-				echo -en "checking ${remotereponame} module ${functionfile}...\c"
-				github_file_url_dir="lgsm/functions"
+				echo -en "checking ${remotereponame} module ${modulefile}...\c"
+				github_file_url_dir="lgsm/modules"
 				if [ "${remotereponame}" == "GitHub" ]; then
-					curl --connect-timeout 10 -IsfL "https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${functionfile}" 1> /dev/null
+					curl --connect-timeout 10 -IsfL "https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${modulefile}" 1> /dev/null
 				else
-					curl --connect-timeout 10 -IsfL "https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_file_url_dir}/${functionfile}" 1> /dev/null
+					curl --connect-timeout 10 -IsfL "https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_file_url_dir}/${modulefile}" 1> /dev/null
 				fi
 				if [ $? != 0 ]; then
 					fn_print_error_eol_nl
-					fn_script_log_error "Checking ${remotereponame} module ${functionfile}"
-					echo -en "removing module ${functionfile}...\c"
-					if ! rm -f "${functionfile:?}"; then
+					fn_script_log_error "Checking ${remotereponame} module ${modulefile}"
+					echo -en "removing module ${modulefile}...\c"
+					if ! rm -f "${modulefile:?}"; then
 						fn_print_fail_eol_nl
-						fn_script_log_fatal "Removing module ${functionfile}"
+						fn_script_log_fatal "Removing module ${modulefile}"
 						core_exit.sh
 					else
 						fn_print_ok_eol_nl
-						fn_script_log_pass "Removing module ${functionfile}"
+						fn_script_log_pass "Removing module ${modulefile}"
 					fi
 				else
 					# compare file
 					if [ "${remotereponame}" == "GitHub" ]; then
-						function_file_diff=$(diff "${functionsdir}/${functionfile}" <(curl --connect-timeout 10 -s "https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${functionfile}"))
+						module_file_diff=$(diff "${modulesdir}/${modulefile}" <(curl --connect-timeout 10 -s "https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${modulefile}"))
 					else
-						function_file_diff=$(diff "${functionsdir}/${functionfile}" <(curl --connect-timeout 10 -s "https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_file_url_dir}/${functionfile}"))
+						module_file_diff=$(diff "${modulesdir}/${modulefile}" <(curl --connect-timeout 10 -s "https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_file_url_dir}/${modulefile}"))
 					fi
 
 					# results
-					if [ "${function_file_diff}" != "" ]; then
+					if [ "${module_file_diff}" != "" ]; then
 						fn_print_update_eol_nl
-						fn_script_log_update "Checking ${remotereponame} module ${functionfile}"
-						rm -rf "${functionsdir:?}/${functionfile}"
-						fn_update_function
+						fn_script_log_update "Checking ${remotereponame} module ${modulefile}"
+						rm -rf "${modulesdir:?}/${modulefile}"
+						fn_update_module
 					else
 						fn_print_ok_eol_nl
-						fn_script_log_pass "Checking ${remotereponame} module ${functionfile}"
+						fn_script_log_pass "Checking ${remotereponame} module ${modulefile}"
 					fi
 				fi
 			done
@@ -230,7 +230,7 @@ if [ -n "${functionsdir}" ]; then
 	fi
 fi
 
-fn_print_ok_nl "Updating functions"
-fn_script_log_pass "Updating functions"
+fn_print_ok_nl "Updating modules"
+fn_script_log_pass "Updating modules"
 
 core_exit.sh

+ 1 - 1
lgsm/functions/command_validate.sh → lgsm/modules/command_validate.sh

@@ -7,7 +7,7 @@
 
 commandname="VALIDATE"
 commandaction="Validating"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 fn_validate() {

+ 1 - 1
lgsm/functions/command_wipe.sh → lgsm/modules/command_wipe.sh

@@ -7,7 +7,7 @@
 
 commandname="WIPE"
 commandaction="Wiping"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 # Provides an exit code upon error.

+ 1 - 1
lgsm/functions/compress_unreal2_maps.sh → lgsm/modules/compress_unreal2_maps.sh

@@ -7,7 +7,7 @@
 
 commandname="MAP-COMPRESSOR"
 commandaction="Compressing maps"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 check.sh

+ 1 - 1
lgsm/functions/compress_ut99_maps.sh → lgsm/modules/compress_ut99_maps.sh

@@ -7,7 +7,7 @@
 
 commandname="MAP-COMPRESSOR"
 commandaction="Compressing maps"
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 fn_firstcommand_set
 
 check.sh

+ 627 - 0
lgsm/modules/core_dl.sh

@@ -0,0 +1,627 @@
+#!/bin/bash
+# LinuxGSM core_dl.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Deals with all downloads for LinuxGSM.
+
+# remote_fileurl: The URL of the file: http://example.com/dl/File.tar.bz2
+# local_filedir: location the file is to be saved: /home/server/lgsm/tmp
+# local_filename: name of file (this can be different from the url name): file.tar.bz2
+# chmodx: Optional, set to "chmodx" to make file executable using chmod +x
+# run: Optional, set run to execute the file after download
+# forcedl: Optional, force re-download of file even if exists
+# hash: Optional, set an hash sum and will compare it against the file.
+#
+# Downloads can be defined in code like so:
+# fn_fetch_file "${remote_fileurl}" "${remote_fileurl_backup}" "${remote_fileurl_name}" "${remote_fileurl_backup_name}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${hash}"
+# fn_fetch_file "http://example.com/file.tar.bz2" "http://example.com/file2.tar.bz2" "file.tar.bz2" "file2.tar.bz2" "/some/dir" "file.tar.bz2" "chmodx" "run" "forcedl" "10cd7353aa9d758a075c600a6dd193fd"
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+fn_dl_steamcmd() {
+	fn_print_start_nl "${remotelocation}"
+	fn_script_log_info "${commandaction} ${selfname}: ${remotelocation}"
+	if [ -n "${branch}" ]; then
+		echo -e "Branch: ${branch}"
+		fn_script_log_info "Branch: ${branch}"
+	fi
+	if [ -n "${betapassword}" ]; then
+		echo -e "Branch password: ${betapassword}"
+		fn_script_log_info "Branch password: ${betapassword}"
+	fi
+	if [ -d "${steamcmddir}" ]; then
+		cd "${steamcmddir}" || exit
+	fi
+
+	# Unbuffer will allow the output of steamcmd not buffer allowing a smooth output.
+	# unbuffer us part of the expect package.
+	if [ "$(command -v unbuffer)" ]; then
+		unbuffer="unbuffer"
+	fi
+
+	# Validate will be added as a parameter if required.
+	if [ "${commandname}" == "VALIDATE" ] || [ "${commandname}" == "INSTALL" ]; then
+		validate="validate"
+	fi
+
+	# To do error checking for SteamCMD the output of steamcmd will be saved to a log.
+	steamcmdlog="${lgsmlogdir}/${selfname}-steamcmd.log"
+
+	# clear previous steamcmd log
+	if [ -f "${steamcmdlog}" ]; then
+		rm -f "${steamcmdlog:?}"
+	fi
+	counter=0
+	while [ "${counter}" == "0" ] || [ "${exitcode}" != "0" ]; do
+		counter=$((counter + 1))
+		# Select SteamCMD parameters
+		# If GoldSrc (appid 90) servers. GoldSrc (appid 90) require extra commands.
+		if [ "${appid}" == "90" ]; then
+			# If using a specific branch.
+			if [ -n "${branch}" ] && [ -n "${betapassword}" ]; then
+				${unbuffer} ${steamcmdcommand} +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_set_config 90 mod "${appidmod}" +app_update "${appid}" -beta "${branch}" -betapassword "${betapassword}" ${validate} +quit | uniq | tee -a "${lgsmlog}" "${steamcmdlog}"
+			elif [ -n "${branch}" ]; then
+				${unbuffer} ${steamcmdcommand} +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_set_config 90 mod "${appidmod}" +app_update "${appid}" -beta "${branch}" ${validate} +quit | uniq | tee -a "${lgsmlog}" "${steamcmdlog}"
+			else
+				${unbuffer} ${steamcmdcommand} +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_set_config 90 mod "${appidmod}" +app_update "${appid}" ${validate} +quit | uniq | tee -a "${lgsmlog}" "${steamcmdlog}"
+			fi
+		# Force Windows Platform type.
+		elif [ "${steamcmdforcewindows}" == "yes" ]; then
+			if [ -n "${branch}" ] && [ -n "${betapassword}" ]; then
+				${unbuffer} ${steamcmdcommand} +@sSteamCmdForcePlatformType windows +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_update "${appid}" -beta "${branch}" -betapassword "${betapassword}" ${validate} +quit | uniq | tee -a "${lgsmlog}" "${steamcmdlog}"
+			elif [ -n "${branch}" ]; then
+				${unbuffer} ${steamcmdcommand} +@sSteamCmdForcePlatformType windows +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_update "${appid}" -beta "${branch}" ${validate} +quit | uniq | tee -a "${lgsmlog}" "${steamcmdlog}"
+			else
+				${unbuffer} ${steamcmdcommand} +@sSteamCmdForcePlatformType windows +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_update "${appid}" ${validate} +quit | uniq | tee -a "${lgsmlog}" "${steamcmdlog}"
+			fi
+		# All other servers.
+		else
+			if [ -n "${branch}" ] && [ -n "${betapassword}" ]; then
+				${unbuffer} ${steamcmdcommand} +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_update "${appid}" -beta "${branch}" -betapassword "${betapassword}" ${validate} +quit | uniq | tee -a "${lgsmlog}" "${steamcmdlog}"
+			elif [ -n "${branch}" ]; then
+				${unbuffer} ${steamcmdcommand} +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_update "${appid}" -beta "${branch}" ${validate} +quit | uniq | tee -a "${lgsmlog}" "${steamcmdlog}"
+			else
+				${unbuffer} ${steamcmdcommand} +force_install_dir "${serverfiles}" +login "${steamuser}" "${steampass}" +app_update "${appid}" ${validate} +quit | uniq | tee -a "${lgsmlog}" "${steamcmdlog}"
+			fi
+		fi
+
+		# Error checking for SteamCMD. Some errors will loop to try again and some will just exit.
+		# Check also if we have more errors than retries to be sure that we do not loop to many times and error out.
+		exitcode=$?
+		if [ -n "$(grep -i "Error!" "${steamcmdlog}" | tail -1)" ] && [ "$(grep -ic "Error!" "${steamcmdlog}")" -ge "${counter}" ]; then
+			# Not enough space.
+			if [ -n "$(grep "0x202" "${steamcmdlog}" | tail -1)" ]; then
+				fn_print_failure_nl "${commandaction} ${selfname}: ${remotelocation}: Not enough disk space to download server files"
+				fn_script_log_fatal "${commandaction} ${selfname}: ${remotelocation}: Not enough disk space to download server files"
+				core_exit.sh
+				# Not enough space.
+			elif [ -n "$(grep "0x212" "${steamcmdlog}" | tail -1)" ]; then
+				fn_print_failure_nl "${commandaction} ${selfname}: ${remotelocation}: Not enough disk space to download server files"
+				fn_script_log_fatal "${commandaction} ${selfname}: ${remotelocation}: Not enough disk space to download server files"
+				core_exit.sh
+			# Need tp purchase game.
+			elif [ -n "$(grep "No subscription" "${steamcmdlog}" | tail -1)" ]; then
+				fn_print_failure_nl "${commandaction} ${selfname}: ${remotelocation}: Steam account does not have a license for the required game"
+				fn_script_log_fatal "${commandaction} ${selfname}: ${remotelocation}: Steam account does not have a license for the required game"
+				core_exit.sh
+			# Two-factor authentication failure
+			elif [ -n "$(grep "Two-factor code mismatch" "${steamcmdlog}" | tail -1)" ]; then
+				fn_print_failure_nl "${commandaction} ${selfname}: ${remotelocation}: Two-factor authentication failure"
+				fn_script_log_fatal "${commandaction} ${selfname}: ${remotelocation}: Two-factor authentication failure"
+				core_exit.sh
+			# Incorrect Branch password
+			elif [ -n "$(grep "Password check for AppId" "${steamcmdlog}" | tail -1)" ]; then
+				fn_print_failure_nl "${commandaction} ${selfname}: ${remotelocation}: betapassword is incorrect"
+				fn_script_log_fatal "${commandaction} ${selfname}: ${remotelocation}: betapassword is incorrect"
+				core_exit.sh
+			# Update did not finish.
+			elif [ -n "$(grep "0x402" "${steamcmdlog}" | tail -1)" ] || [ -n "$(grep "0x602" "${steamcmdlog}" | tail -1)" ]; then
+				fn_print_error2_nl "${commandaction} ${selfname}: ${remotelocation}: Update required but not completed - check network"
+				fn_script_log_error "${commandaction} ${selfname}: ${remotelocation}: Update required but not completed - check network"
+			else
+				fn_print_error2_nl "${commandaction} ${selfname}: ${remotelocation}: Unknown error occured"
+				echo -en "Please provide content log to LinuxGSM developers https://linuxgsm.com/steamcmd-error"
+				fn_script_log_error "${commandaction} ${selfname}: ${remotelocation}: Unknown error occured"
+			fi
+		elif [ "${exitcode}" != 0 ]; then
+			fn_print_error2_nl "${commandaction} ${selfname}: ${remotelocation}: Exit code: ${exitcode}"
+			fn_script_log_error "${commandaction} ${selfname}: ${remotelocation}: Exit code: ${exitcode}"
+		else
+			fn_print_complete_nl "${commandaction} ${selfname}: ${remotelocation}"
+			fn_script_log_pass "${commandaction} ${selfname}: ${remotelocation}"
+		fi
+
+		if [ "${counter}" -gt "10" ]; then
+			fn_print_failure_nl "${commandaction} ${selfname}: ${remotelocation}: Did not complete the download, too many retrys"
+			fn_script_log_fatal "${commandaction} ${selfname}: ${remotelocation}: Did not complete the download, too many retrys"
+			core_exit.sh
+		fi
+	done
+}
+
+# Emptys contents of the LinuxGSM tmpdir.
+fn_clear_tmp() {
+	echo -en "clearing LinuxGSM tmp directory..."
+	if [ -d "${tmpdir}" ]; then
+		rm -rf "${tmpdir:?}/"*
+		local exitcode=$?
+		if [ "${exitcode}" != 0 ]; then
+			fn_print_error_eol_nl
+			fn_script_log_error "clearing LinuxGSM tmp directory"
+		else
+			fn_print_ok_eol_nl
+			fn_script_log_pass "clearing LinuxGSM tmp directory"
+		fi
+	fi
+}
+
+fn_dl_hash() {
+	# Runs Hash Check if available.
+	if [ "${hash}" != "0" ] && [ "${hash}" != "nohash" ] && [ "${hash}" != "nomd5" ]; then
+		# MD5
+		if [ "${#hash}" == "32" ]; then
+			hashbin="md5sum"
+			hashtype="MD5"
+		# SHA1
+		elif [ "${#hash}" == "40" ]; then
+			hashbin="sha1sum"
+			hashtype="SHA1"
+		# SHA256
+		elif [ "${#hash}" == "64" ]; then
+			hashbin="sha256sum"
+			hashtype="SHA256"
+		# SHA512
+		elif [ "${#hash}" == "128" ]; then
+			hashbin="sha512sum"
+			hashtype="SHA512"
+		else
+			fn_script_log_error "hash lengh not known for hash type"
+			fn_print_error_nl "hash lengh not known for hash type"
+			core_exit.sh
+		fi
+		echo -en "verifying ${local_filename} with ${hashtype}..."
+		fn_sleep_time
+		hashsumcmd=$(${hashbin} "${local_filedir}/${local_filename}" | awk '{print $1}')
+		if [ "${hashsumcmd}" != "${hash}" ]; then
+			fn_print_fail_eol_nl
+			echo -e "${local_filename} returned ${hashtype} checksum: ${hashsumcmd}"
+			echo -e "expected ${hashtype} checksum: ${hash}"
+			fn_script_log_fatal "Verifying ${local_filename} with ${hashtype}"
+			fn_script_log_info "${local_filename} returned ${hashtype} checksum: ${hashsumcmd}"
+			fn_script_log_info "Expected ${hashtype} checksum: ${hash}"
+			core_exit.sh
+		else
+			fn_print_ok_eol_nl
+			fn_script_log_pass "Verifying ${local_filename} with ${hashtype}"
+			fn_script_log_info "${local_filename} returned ${hashtype} checksum: ${hashsumcmd}"
+			fn_script_log_info "Expected ${hashtype} checksum: ${hash}"
+		fi
+	fi
+}
+
+# Extracts bzip2, gzip or zip files.
+# Extracts can be defined in code like so:
+# fn_dl_extract "${local_filedir}" "${local_filename}" "${extractdest}" "${extractsrc}"
+# fn_dl_extract "/home/gameserver/lgsm/tmp" "file.tar.bz2" "/home/gamserver/serverfiles"
+fn_dl_extract() {
+	local_filedir="${1}"
+	local_filename="${2}"
+	extractdest="${3}"
+	extractsrc="${4}"
+	# Extracts archives.
+	echo -en "extracting ${local_filename}..."
+
+	if [ ! -d "${extractdest}" ]; then
+		mkdir "${extractdest}"
+	fi
+	if [ ! -f "${local_filedir}/${local_filename}" ]; then
+		fn_print_fail_eol_nl
+		echo -en "file ${local_filedir}/${local_filename} not found"
+		fn_script_log_fatal "Extracting ${local_filename}"
+		fn_script_log_fatal "File ${local_filedir}/${local_filename} not found"
+		core_exit.sh
+	fi
+	mime=$(file -b --mime-type "${local_filedir}/${local_filename}")
+	if [ "${mime}" == "application/gzip" ] || [ "${mime}" == "application/x-gzip" ]; then
+		if [ -n "${extractsrc}" ]; then
+			extractcmd=$(tar -zxf "${local_filedir}/${local_filename}" -C "${extractdest}" --strip-components=1 "${extractsrc}")
+		else
+			extractcmd=$(tar -zxf "${local_filedir}/${local_filename}" -C "${extractdest}")
+		fi
+	elif [ "${mime}" == "application/x-bzip2" ]; then
+		if [ -n "${extractsrc}" ]; then
+			extractcmd=$(tar -jxf "${local_filedir}/${local_filename}" -C "${extractdest}" --strip-components=1 "${extractsrc}")
+		else
+			extractcmd=$(tar -jxf "${local_filedir}/${local_filename}" -C "${extractdest}")
+		fi
+	elif [ "${mime}" == "application/x-xz" ]; then
+		if [ -n "${extractsrc}" ]; then
+			extractcmd=$(tar -Jxf "${local_filedir}/${local_filename}" -C "${extractdest}" --strip-components=1 "${extractsrc}")
+		else
+			extractcmd=$(tar -Jxf "${local_filedir}/${local_filename}" -C "${extractdest}")
+		fi
+	elif [ "${mime}" == "application/zip" ]; then
+		if [ -n "${extractsrc}" ]; then
+			extractcmd=$(unzip -qoj -d "${extractdest}" "${local_filedir}/${local_filename}" "${extractsrc}"/*)
+		else
+			extractcmd=$(unzip -qo -d "${extractdest}" "${local_filedir}/${local_filename}")
+		fi
+	fi
+	local exitcode=$?
+	if [ "${exitcode}" != 0 ]; then
+		fn_print_fail_eol_nl
+		fn_script_log_fatal "Extracting ${local_filename}"
+		if [ -f "${lgsmlog}" ]; then
+			echo -e "${extractcmd}" >> "${lgsmlog}"
+		fi
+		echo -e "${extractcmd}"
+		core_exit.sh
+	else
+		fn_print_ok_eol_nl
+		fn_script_log_pass "Extracting ${local_filename}"
+	fi
+}
+
+# Trap to remove file download if canceled before completed.
+fn_fetch_trap() {
+	echo -e ""
+	echo -en "downloading ${local_filename}..."
+	fn_print_canceled_eol_nl
+	fn_script_log_info "Downloading ${local_filename}...CANCELED"
+	fn_sleep_time
+	rm -f "${local_filedir:?}/${local_filename}"
+	echo -en "downloading ${local_filename}..."
+	fn_print_removed_eol_nl
+	fn_script_log_info "Downloading ${local_filename}...REMOVED"
+	core_exit.sh
+}
+
+# Will check a file exists and download it. Will not exit if fails to download.
+fn_check_file() {
+	remote_fileurl="${1}"
+	remote_fileurl_backup="${2}"
+	remote_fileurl_name="${3}"
+	remote_fileurl_backup_name="${4}"
+	remote_filename="${5}"
+	# If backup fileurl exists include it.
+	if [ -n "${remote_fileurl_backup}" ]; then
+		# counter set to 0 to allow second try
+		counter=0
+		remote_fileurls_array=(remote_fileurl remote_fileurl_backup)
+	else
+		# counter set to 1 to not allow second try
+		counter=1
+		remote_fileurls_array=(remote_fileurl)
+	fi
+	for remote_fileurl_array in "${remote_fileurls_array[@]}"; do
+		if [ "${remote_fileurl_array}" == "remote_fileurl" ]; then
+			fileurl="${remote_fileurl}"
+			fileurl_name="${remote_fileurl_name}"
+		elif [ "${remote_fileurl_array}" == "remote_fileurl_backup" ]; then
+			fileurl="${remote_fileurl_backup}"
+			fileurl_name="${remote_fileurl_backup_name}"
+		fi
+		counter=$((counter + 1))
+		echo -en "checking ${fileurl_name} ${remote_filename}...\c"
+		curlcmd=$(curl --output /dev/null --silent --head --fail "${fileurl}" 2>&1)
+		local exitcode=$?
+
+		# On first try will error. On second try will fail.
+		if [ "${exitcode}" != 0 ]; then
+			if [ ${counter} -ge 2 ]; then
+				fn_print_fail_eol_nl
+				if [ -f "${lgsmlog}" ]; then
+					fn_script_log_fatal "Checking ${remote_filename}"
+					fn_script_log_fatal "${fileurl}"
+					checkflag=1
+				fi
+			else
+				fn_print_error_eol_nl
+				if [ -f "${lgsmlog}" ]; then
+					fn_script_log_error "Checking ${remote_filename}"
+					fn_script_log_error "${fileurl}"
+					checkflag=2
+				fi
+			fi
+		else
+			fn_print_ok_eol
+			echo -en "\033[2K\\r"
+			if [ -f "${lgsmlog}" ]; then
+				fn_script_log_pass "Checking ${remote_filename}"
+				checkflag=0
+			fi
+			break
+		fi
+	done
+
+	if [ -f "${local_filedir}/${local_filename}" ]; then
+		fn_dl_hash
+		# Execute file if run is set.
+		if [ "${run}" == "run" ]; then
+			# shellcheck source=/dev/null
+			source "${local_filedir}/${local_filename}"
+		fi
+	fi
+}
+
+fn_fetch_file() {
+	remote_fileurl="${1}"
+	remote_fileurl_backup="${2}"
+	remote_fileurl_name="${3}"
+	remote_fileurl_backup_name="${4}"
+	local_filedir="${5}"
+	local_filename="${6}"
+	chmodx="${7:-0}"
+	run="${8:-0}"
+	forcedl="${9:-0}"
+	hash="${10:-0}"
+
+	# Download file if missing or download forced.
+	if [ ! -f "${local_filedir}/${local_filename}" ] || [ "${forcedl}" == "forcedl" ]; then
+		# If backup fileurl exists include it.
+		if [ -n "${remote_fileurl_backup}" ]; then
+			# counter set to 0 to allow second try
+			counter=0
+			remote_fileurls_array=(remote_fileurl remote_fileurl_backup)
+		else
+			# counter set to 1 to not allow second try
+			counter=1
+			remote_fileurls_array=(remote_fileurl)
+		fi
+		for remote_fileurl_array in "${remote_fileurls_array[@]}"; do
+			if [ "${remote_fileurl_array}" == "remote_fileurl" ]; then
+				fileurl="${remote_fileurl}"
+				fileurl_name="${remote_fileurl_name}"
+			elif [ "${remote_fileurl_array}" == "remote_fileurl_backup" ]; then
+				fileurl="${remote_fileurl_backup}"
+				fileurl_name="${remote_fileurl_backup_name}"
+			fi
+			counter=$((counter + 1))
+			if [ ! -d "${local_filedir}" ]; then
+				mkdir -p "${local_filedir}"
+			fi
+			# Trap will remove part downloaded files if canceled.
+			trap fn_fetch_trap INT
+			curlcmd=(curl --connect-timeout 10 --fail -L -o "${local_filedir}/${local_filename}" --retry 2)
+
+			# if is large file show progress, else be silent
+			local exitcode=""
+			large_files=("bz2" "gz" "zip" "jar" "xz")
+			if grep -qE "(^|\s)${local_filename##*.}(\s|$)" <<< "${large_files[@]}"; then
+				echo -en "downloading ${local_filename}..."
+				fn_sleep_time
+				echo -en "\033[1K"
+				"${curlcmd[@]}" --progress-bar "${fileurl}" 2>&1
+				exitcode="$?"
+			else
+				echo -en "fetching ${fileurl_name} ${local_filename}...\c"
+				"${curlcmd[@]}" --silent --show-error "${fileurl}" 2>&1
+				exitcode="$?"
+			fi
+
+			# Download will fail if downloads a html file.
+			if [ -f "${local_filedir}/${local_filename}" ]; then
+				if head -n 1 "${local_filedir}/${local_filename}" | grep -q "DOCTYPE"; then
+					rm "${local_filedir:?}/${local_filename:?}"
+					local exitcode=2
+				fi
+			fi
+
+			# On first try will error. On second try will fail.
+			if [ "${exitcode}" != 0 ]; then
+				if [ ${counter} -ge 2 ]; then
+					fn_print_fail_eol_nl
+					if [ -f "${lgsmlog}" ]; then
+						fn_script_log_fatal "Downloading ${local_filename}..."
+						fn_script_log_fatal "${fileurl}"
+					fi
+					core_exit.sh
+				else
+					fn_print_error_eol_nl
+					if [ -f "${lgsmlog}" ]; then
+						fn_script_log_error "Downloading ${local_filename}..."
+						fn_script_log_error "${fileurl}"
+					fi
+				fi
+			else
+				fn_print_ok_eol_nl
+				if [ -f "${lgsmlog}" ]; then
+					fn_script_log_pass "Downloading ${local_filename}..."
+				fi
+
+				# Make file executable if chmodx is set.
+				if [ "${chmodx}" == "chmodx" ]; then
+					chmod +x "${local_filedir}/${local_filename}"
+				fi
+
+				# Remove trap.
+				trap - INT
+
+				break
+			fi
+		done
+	fi
+
+	if [ -f "${local_filedir}/${local_filename}" ]; then
+		fn_dl_hash
+		# Execute file if run is set.
+		if [ "${run}" == "run" ]; then
+			# shellcheck source=/dev/null
+			source "${local_filedir}/${local_filename}"
+		fi
+	fi
+}
+
+# GitHub file download modules.
+# Used to simplify downloading specific files from GitHub.
+
+# github_file_url_dir: the directory of the file in the GitHub: lgsm/modules
+# github_file_url_name: the filename of the file to download from GitHub: core_messages.sh
+# github_file_url_dir: the directory of the file in the GitHub: lgsm/modules
+# github_file_url_name: the filename of the file to download from GitHub: core_messages.sh
+# githuburl: the full GitHub url
+
+# remote_fileurl: The URL of the file: http://example.com/dl/File.tar.bz2
+# local_filedir: location the file is to be saved: /home/server/lgsm/tmp
+# local_filename: name of file (this can be different from the url name): file.tar.bz2
+# chmodx: Optional, set to "chmodx" to make file executable using chmod +x
+# run: Optional, set run to execute the file after download
+# forcedl: Optional, force re-download of file even if exists
+# hash: Optional, set an hash sum and will compare it against the file.
+
+# Fetches files from the Git repo.
+fn_fetch_file_github() {
+	github_file_url_dir="${1}"
+	github_file_url_name="${2}"
+	# For legacy versions - code can be removed at a future date
+	if [ "${legacymode}" == "1" ]; then
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+	# If master branch will currently running LinuxGSM version to prevent "version mixing". This is ignored if a fork.
+	elif [ "${githubbranch}" == "master" ] && [ "${githubuser}" == "GameServerManagers" ] && [ "${commandname}" != "UPDATE-LGSM" ]; then
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${version}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${version}/${github_file_url_dir}/${github_file_url_name}"
+	else
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+	fi
+	remote_fileurl_name="GitHub"
+	remote_fileurl_backup_name="Bitbucket"
+	local_filedir="${3}"
+	local_filename="${github_file_url_name}"
+	chmodx="${4:-0}"
+	run="${5:-0}"
+	forcedl="${6:-0}"
+	hash="${7:-0}"
+	# Passes vars to the file download module.
+	fn_fetch_file "${remote_fileurl}" "${remote_fileurl_backup}" "${remote_fileurl_name}" "${remote_fileurl_backup_name}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${hash}"
+}
+
+fn_check_file_github() {
+	github_file_url_dir="${1}"
+	github_file_url_name="${2}"
+	if [ "${githubbranch}" == "master" ] && [ "${githubuser}" == "GameServerManagers" ] && [ "${commandname}" != "UPDATE-LGSM" ]; then
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${version}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${version}/${github_file_url_dir}/${github_file_url_name}"
+	else
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+	fi
+	remote_fileurl_name="GitHub"
+	remote_fileurl_backup_name="Bitbucket"
+	fn_check_file "${remote_fileurl}" "${remote_fileurl_backup}" "${remote_fileurl_name}" "${remote_fileurl_backup_name}" "${github_file_url_name}"
+}
+
+# Fetches config files from the Git repo.
+fn_fetch_config() {
+	github_file_url_dir="${1}"
+	github_file_url_name="${2}"
+	# If master branch will currently running LinuxGSM version to prevent "version mixing". This is ignored if a fork.
+	if [ "${githubbranch}" == "master" ] && [ "${githubuser}" == "GameServerManagers" ] && [ "${commandname}" != "UPDATE-LGSM" ]; then
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${version}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${version}/${github_file_url_dir}/${github_file_url_name}"
+	else
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+	fi
+	remote_fileurl_name="GitHub"
+	remote_fileurl_backup_name="Bitbucket"
+	local_filedir="${3}"
+	local_filename="${4}"
+	chmodx="nochmodx"
+	run="norun"
+	forcedl="noforce"
+	hash="nohash"
+	# Passes vars to the file download module.
+	fn_fetch_file "${remote_fileurl}" "${remote_fileurl_backup}" "${remote_fileurl_name}" "${remote_fileurl_backup_name}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${hash}"
+}
+
+# Fetches modules from the Git repo during first download.
+fn_fetch_module() {
+	github_file_url_dir="lgsm/modules"
+	github_file_url_name="${modulefile}"
+	# If master branch will currently running LinuxGSM version to prevent "version mixing". This is ignored if a fork.
+	if [ "${githubbranch}" == "master" ] && [ "${githubuser}" == "GameServerManagers" ] && [ "${commandname}" != "UPDATE-LGSM" ]; then
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${version}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${version}/${github_file_url_dir}/${github_file_url_name}"
+	else
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+	fi
+	remote_fileurl_name="GitHub"
+	remote_fileurl_backup_name="Bitbucket"
+	local_filedir="${modulesdir}"
+	local_filename="${github_file_url_name}"
+	chmodx="chmodx"
+	run="run"
+	forcedl="noforce"
+	hash="nohash"
+	# Passes vars to the file download module.
+	fn_fetch_file "${remote_fileurl}" "${remote_fileurl_backup}" "${remote_fileurl_name}" "${remote_fileurl_backup_name}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${hash}"
+}
+
+# Fetches modules from the Git repo during update-lgsm.
+fn_update_module() {
+	github_file_url_dir="lgsm/modules"
+	github_file_url_name="${modulefile}"
+	# If master branch will currently running LinuxGSM version to prevent "version mixing". This is ignored if a fork.
+	if [ "${githubbranch}" == "master" ] && [ "${githubuser}" == "GameServerManagers" ] && [ "${commandname}" != "UPDATE-LGSM" ]; then
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${version}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${version}/${github_file_url_dir}/${github_file_url_name}"
+	else
+		remote_fileurl="https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+		remote_fileurl_backup="https://bitbucket.org/${githubuser}/${githubrepo}/raw/${githubbranch}/${github_file_url_dir}/${github_file_url_name}"
+	fi
+	remote_fileurl_name="GitHub"
+	remote_fileurl_backup_name="Bitbucket"
+	local_filedir="${modulesdir}"
+	local_filename="${github_file_url_name}"
+	chmodx="chmodx"
+	run="norun"
+	forcedl="noforce"
+	hash="nohash"
+	# Passes vars to the file download module.
+	fn_fetch_file "${remote_fileurl}" "${remote_fileurl_backup}" "${remote_fileurl_name}" "${remote_fileurl_backup_name}" "${local_filedir}" "${local_filename}" "${chmodx}" "${run}" "${forcedl}" "${hash}"
+
+}
+
+# Function to download latest github release.
+# $1 GitHub user / organisation.
+# $2 Repo name.
+# $3 Destination for download.
+# $4 Search string in releases (needed if there are more files that can be downloaded from the release pages).
+fn_dl_latest_release_github() {
+	local githubreleaseuser="${1}"
+	local githubreleaserepo="${2}"
+	local githubreleasedownloadpath="${3}"
+	local githubreleasesearch="${4}"
+	local githublatestreleaseurl="https://api.github.com/repos/${githubreleaseuser}/${githubreleaserepo}/releases/latest"
+
+	# Get last github release.
+	# If no search for the release filename is set, just get the first file from the latest release.
+	if [ -z "${githubreleasesearch}" ]; then
+		githubreleaseassets=$(curl -s "${githublatestreleaseurl}" | jq '[ .assets[] ]')
+	else
+		githubreleaseassets=$(curl -s "${githublatestreleaseurl}" | jq "[ .assets[]|select(.browser_download_url | contains(\"${githubreleasesearch}\")) ]")
+	fi
+
+	# Check how many releases we got from the api and exit if we have more then one.
+	if [ "$(echo -e "${githubreleaseassets}" | jq '. | length')" -gt 1 ]; then
+		fn_print_fatal_nl "Found more than one release to download - Please report this to the LinuxGSM issue tracker"
+		fn_script_log_fatal "Found more than one release to download - Please report this to the LinuxGSM issue tracker"
+	else
+		# Set variables for download via fn_fetch_file.
+		githubreleasefilename=$(echo -e "${githubreleaseassets}" | jq -r '.[]name')
+		githubreleasedownloadlink=$(echo -e "${githubreleaseassets}" | jq -r '.[]browser_download_url')
+
+		# Error if no version is there.
+		if [ -z "${githubreleasefilename}" ]; then
+			fn_print_fail_nl "Cannot get version from GitHub API for ${githubreleaseuser}/${githubreleaserepo}"
+			fn_script_log_fatal "Cannot get version from GitHub API for ${githubreleaseuser}/${githubreleaserepo}"
+		else
+			# Fetch file from the remote location from the existing module to the ${tmpdir} for now.
+			fn_fetch_file "${githubreleasedownloadlink}" "" "${githubreleasefilename}" "" "${githubreleasedownloadpath}" "${githubreleasefilename}"
+		fi
+	fi
+}

+ 61 - 0
lgsm/modules/core_exit.sh

@@ -0,0 +1,61 @@
+#!/bin/bash
+# LinuxGSM core_exit.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Handles exiting of LinuxGSM by running and reporting an exit code.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+fn_exit_dev_debug() {
+	if [ -f "${rootdir}/.dev-debug" ]; then
+		echo -e ""
+		echo -e "${moduleselfname} exiting with code: ${exitcode}"
+		if [ -f "${rootdir}/dev-debug.log" ]; then
+			grep "modulefile=" "${rootdir}/dev-debug.log" | sed 's/modulefile=//g' > "${rootdir}/dev-debug-module-order.log"
+		fi
+	fi
+}
+
+# If running dependency check as root will remove any files that belong to root user.
+if [ "$(whoami)" == "root" ] && [ ! -f /.dockerenv ]; then
+	find "${lgsmdir}"/ -group root -prune -exec rm -rf {} + > /dev/null 2>&1
+	find "${logdir}"/ -group root -prune -exec rm -rf {} + > /dev/null 2>&1
+fi
+
+if [ "${exitbypass}" ]; then
+	unset exitbypass
+elif [ "${exitcode}" != "0" ]; then
+	# List LinuxGSM version in logs
+	fn_script_log_info "LinuxGSM version: ${version}"
+	if [ "${exitcode}" == "1" ]; then
+		fn_script_log_fatal "${moduleselfname} exiting with code: ${exitcode}"
+	elif [ "${exitcode}" == "2" ]; then
+		fn_script_log_error "${moduleselfname} exiting with code: ${exitcode}"
+	elif [ "${exitcode}" == "3" ]; then
+		fn_script_log_warn "${moduleselfname} exiting with code: ${exitcode}"
+	else
+		fn_script_log_warn "${moduleselfname} exiting with code: ${exitcode}"
+	fi
+	fn_exit_dev_debug
+	# remove trap.
+	trap - INT
+	exit "${exitcode}"
+elif [ "${exitcode}" ] && [ "${exitcode}" == "0" ]; then
+	# List LinuxGSM version in logs
+	fn_script_log_info "LinuxGSM version: ${version}"
+	fn_script_log_pass "${moduleselfname} exiting with code: ${exitcode}"
+	fn_exit_dev_debug
+	# remove trap.
+	trap - INT
+	exit "${exitcode}"
+else
+	# List LinuxGSM version in logs
+	fn_script_log_info "LinuxGSM version: ${version}"
+	fn_print_error "No exit code set"
+	fn_script_log_pass "${moduleselfname} exiting with code: NOT SET"
+	fn_exit_dev_debug
+	# remove trap.
+	trap - INT
+	exit "${exitcode}"
+fi

+ 816 - 0
lgsm/modules/core_functions.sh

@@ -0,0 +1,816 @@
+#!/bin/bash
+# LinuxGSM core_functions.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Defines all functions to allow download and execution of functions using fn_fetch_function.
+# This function is called first before any other function. Without this file other functions will not load.
+
+module_selfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+modulesversion="v23.2.0"
+
+# Core
+
+core_dl.sh() {
+	functionfile="${FUNCNAME[0]}"
+	if [ "$(type fn_fetch_core_dl 2> /dev/null)" ]; then
+		fn_fetch_core_dl "lgsm/functions" "core_dl.sh" "${functionsdir}" "chmodx" "run" "noforcedl" "nohash"
+	else
+		fn_bootstrap_fetch_file_github "lgsm/functions" "core_dl.sh" "${functionsdir}" "chmodx" "run" "noforcedl" "nohash"
+	fi
+}
+
+core_messages.sh() {
+	functionfile="${FUNCNAME[0]}"
+	if [ "$(type fn_fetch_core_dl 2> /dev/null)" ]; then
+		fn_fetch_core_dl "lgsm/functions" "core_messages.sh" "${functionsdir}" "chmodx" "run" "noforcedl" "nohash"
+	else
+		fn_bootstrap_fetch_file_github "lgsm/functions" "core_messages.sh" "${functionsdir}" "chmodx" "run" "noforcedl" "nohash"
+	fi
+}
+
+core_legacy.sh() {
+	functionfile="${FUNCNAME[0]}"
+	if [ "$(type fn_fetch_core_dl 2> /dev/null)" ]; then
+		fn_fetch_core_dl "lgsm/functions" "core_legacy.sh" "${functionsdir}" "chmodx" "run" "noforcedl" "nohash"
+	else
+		fn_bootstrap_fetch_file_github "lgsm/functions" "core_legacy.sh" "${functionsdir}" "chmodx" "run" "noforcedl" "nohash"
+	fi
+}
+
+core_exit.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+core_getopt.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+core_trap.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+core_steamcmd.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+core_github.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+# Commands
+
+command_backup.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_console.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_debug.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_details.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_sponsor.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_postdetails.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_test_alert.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_monitor.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_start.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_stop.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_validate.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_install.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_install_resources_mta.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+install_squad_license.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_mods_install.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_mods_update.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_mods_remove.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_fastdl.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_ts3_server_pass.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_restart.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_skeleton.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_wipe.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_send.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+# Checks
+
+check.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+check_config.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+check_deps.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+check_executable.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+check_glibc.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+check_ip.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+check_last_update.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+check_logs.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+check_permissions.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+check_root.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+check_status.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+check_steamcmd.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+check_system_dir.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+check_system_requirements.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+check_tmuxception.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+check_version.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+# Compress
+
+compress_unreal2_maps.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+compress_ut99_maps.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+# Mods
+
+mods_list.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+mods_core.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+# Dev
+
+command_dev_clear_functions.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_dev_debug.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_dev_detect_deps.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_dev_detect_glibc.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_dev_detect_ldd.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_dev_query_raw.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+# Fix
+
+fix.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_ark.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_av.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_arma3.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_armar.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_bt.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_bo.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_cmw.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_csgo.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_dst.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_hw.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_ins.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_kf.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_kf2.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_lo.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_mcb.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_mta.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_nmrih.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_onset.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_ro.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_rust.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_rw.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_sfc.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_st.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_steamcmd.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_terraria.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_tf2.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_ut3.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_rust.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_samp.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_sdtd.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_sof2.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_squad.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_ts3.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_ut2k4.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_ut.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_unt.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_vh.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_wurm.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fix_zmr.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+# Info
+
+info_distro.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+info_game.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+info_messages.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+info_stats.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+# Alert
+
+alert.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+alert_discord.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+alert_email.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+alert_ifttt.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+alert_mailgun.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+alert_pushbullet.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+alert_pushover.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+alert_gotify.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+alert_telegram.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+alert_rocketchat.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+alert_slack.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+# Logs
+
+core_logs.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+# Query
+
+query_gamedig.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+# Update
+
+command_update_functions.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_update_linuxgsm.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_update.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+command_check_update.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+update_ts3.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+update_minecraft.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+update_minecraft_bedrock.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+update_papermc.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+update_mta.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+update_factorio.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+update_jediknight2.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+update_steamcmd.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+update_vintagestory.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+update_ut99.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+fn_update_functions.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+#
+## Installer functions
+#
+
+fn_autoinstall() {
+	autoinstall=1
+	command_install.sh
+}
+
+install_complete.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+install_config.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+install_factorio_save.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+install_dst_token.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+install_eula.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+install_gsquery.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+install_gslt.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+install_header.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+install_logs.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+install_retry.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+install_server_dir.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+install_server_files.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+install_stats.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+install_steamcmd.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+install_ts3.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+install_ts3db.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+install_ut2k4.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+install_dl_ut2k4.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+install_ut2k4_key.sh() {
+	functionfile="${FUNCNAME[0]}"
+	fn_fetch_function
+}
+
+# Calls code required for legacy servers
+core_legacy.sh
+
+# Creates tmp dir if missing
+if [ ! -d "${tmpdir}" ]; then
+	mkdir -p "${tmpdir}"
+fi
+
+# Creates lock dir if missing
+if [ ! -d "${lockdir}" ]; then
+	mkdir -p "${lockdir}"
+fi
+
+# Calls on-screen messages (bootstrap)
+core_messages.sh
+
+#Calls file downloader (bootstrap)
+core_dl.sh
+
+# Calls the global Ctrl-C trap
+core_trap.sh

+ 215 - 0
lgsm/modules/core_getopt.sh

@@ -0,0 +1,215 @@
+#!/bin/bash
+# LinuxGSM core_getopt.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: getopt arguments.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+### Define all commands here.
+## User commands | Trigger commands | Description
+# Standard commands.
+cmd_install=("i;install" "command_install.sh" "Install the server.")
+cmd_auto_install=("ai;auto-install" "fn_autoinstall" "Install the server without prompts.")
+cmd_start=("st;start" "command_start.sh" "Start the server.")
+cmd_stop=("sp;stop" "command_stop.sh" "Stop the server.")
+cmd_restart=("r;restart" "command_restart.sh" "Restart the server.")
+cmd_details=("dt;details" "command_details.sh" "Display server information.")
+cmd_postdetails=("pd;postdetails" "command_postdetails.sh" "Post details to termbin.com (removing passwords).")
+cmd_backup=("b;backup" "command_backup.sh" "Create backup archives of the server.")
+cmd_update_linuxgsm=("ul;update-lgsm;uf;update-modules" "command_update_linuxgsm.sh" "Check and apply any LinuxGSM updates.")
+cmd_test_alert=("ta;test-alert" "command_test_alert.sh" "Send a test alert.")
+cmd_monitor=("m;monitor" "command_monitor.sh" "Check server status and restart if crashed.")
+cmd_skeleton=("sk;skeleton" "command_skeleton.sh" "Create a skeleton directory.")
+cmd_sponso=("s;sponsor" "command_sponsor.sh" "Donation options.")
+cmd_send=("sd;send" "command_send.sh" "Send command to game server console.")
+# Console servers only.
+cmd_console=("c;console" "command_console.sh" "Access server console.")
+cmd_debug=("d;debug" "command_debug.sh" "Start server directly in your terminal.")
+# Update servers only.
+cmd_update=("u;update" "command_update.sh" "Check and apply any server updates.")
+cmd_check_update=("cu;check-update" "command_check_update.sh" "Check if a gameserver update is available")
+cmd_force_update=("fu;force-update;update-restart;ur" "forceupdate=1; command_update.sh" "Apply server updates bypassing check.")
+# SteamCMD servers only.
+cmd_validate=("v;validate" "command_validate.sh" "Validate server files with SteamCMD.")
+# Server with mods-install.
+cmd_mods_install=("mi;mods-install" "command_mods_install.sh" "View and install available mods/addons.")
+cmd_mods_remove=("mr;mods-remove" "command_mods_remove.sh" "View and remove an installed mod/addon.")
+cmd_mods_update=("mu;mods-update" "command_mods_update.sh" "Update installed mods/addons.")
+# Server specific.
+cmd_change_password=("pw;change-password" "command_ts3_server_pass.sh" "Change TS3 serveradmin password.")
+cmd_install_default_resources=("ir;install-default-resources" "command_install_resources_mta.sh" "Install the MTA default resources.")
+cmd_fullwipe=("fw;full-wipe;wa;wipeall" "serverwipe=1; command_wipe.sh" "Reset the map and remove blueprint data.")
+cmd_mapwipe=("mw;map-wipe;w;wipe;wi" "mapwipe=1; command_wipe.sh" "Reset the map and keep blueprint data.")
+cmd_map_compressor_u99=("mc;map-compressor" "compress_ut99_maps.sh" "Compresses all ${gamename} server maps.")
+cmd_map_compressor_u2=("mc;map-compressor" "compress_unreal2_maps.sh" "Compresses all ${gamename} server maps.")
+cmd_install_cdkey=("cd;server-cd-key" "install_ut2k4_key.sh" "Add your server cd key.")
+cmd_install_dst_token=("ct;cluster-token" "install_dst_token.sh" "Configure cluster token.")
+cmd_install_squad_license=("li;license" "install_squad_license.sh" "Add your Squad server license.")
+cmd_fastdl=("fd;fastdl" "command_fastdl.sh" "Build a FastDL directory.")
+# Dev commands.
+cmd_dev_debug=("dev;developer" "command_dev_debug.sh" "Enable developer Mode.")
+cmd_dev_detect_deps=("dd;detect-deps" "command_dev_detect_deps.sh" "Detect required dependencies.")
+cmd_dev_detect_glibc=("dg;detect-glibc" "command_dev_detect_glibc.sh" "Detect required glibc.")
+cmd_dev_detect_ldd=("dl;detect-ldd" "command_dev_detect_ldd.sh" "Detect required dynamic dependencies.")
+cmd_dev_query_raw=("qr;query-raw" "command_dev_query_raw.sh" "The raw output of gamedig and gsquery.")
+cmd_dev_clear_modules=("cf;clear-modules" "command_dev_clear_modules.sh" "Delete the contents of the modules dir.")
+
+### Set specific opt here.
+
+currentopt=("${cmd_start[@]}" "${cmd_stop[@]}" "${cmd_restart[@]}" "${cmd_monitor[@]}" "${cmd_test_alert[@]}" "${cmd_details[@]}" "${cmd_postdetails[@]}" "${cmd_skeleton[@]}")
+
+# Update LinuxGSM.
+currentopt+=("${cmd_update_linuxgsm[@]}")
+
+# Exclude noupdate games here.
+if [ "${shortname}" == "jk2" ] || [ "${engine}" != "idtech3" ]; then
+	if [ "${shortname}" != "bf1942" ] && [ "${shortname}" != "bfv" ] && [ "${engine}" != "idtech2" ] && [ "${engine}" != "iw2.0" ] && [ "${engine}" != "iw3.0" ] && [ "${engine}" != "quake" ] && [ "${shortname}" != "samp" ] && [ "${shortname}" != "ut2k4" ]; then
+		currentopt+=("${cmd_update[@]}" "${cmd_check_update[@]}")
+		# force update for SteamCMD or Multi Theft Auto only.
+		if [ "${appid}" ] || [ "${shortname}" == "mta" ]; then
+			currentopt+=("${cmd_force_update[@]}")
+		fi
+	fi
+fi
+
+# Validate and check-update command.
+if [ "${appid}" ]; then
+	currentopt+=("${cmd_validate[@]}")
+fi
+
+# Backup.
+currentopt+=("${cmd_backup[@]}")
+
+# Console & Debug.
+currentopt+=("${cmd_console[@]}" "${cmd_debug[@]}")
+
+# Console send.
+if [ "${consoleinteract}" == "yes" ]; then
+	currentopt+=("${cmd_send[@]}")
+fi
+
+## Game server exclusive commands.
+
+# FastDL command.
+if [ "${engine}" == "source" ]; then
+	currentopt+=("${cmd_fastdl[@]}")
+fi
+
+# TeamSpeak exclusive.
+if [ "${shortname}" == "ts3" ]; then
+	currentopt+=("${cmd_change_password[@]}")
+fi
+
+# Rust exclusive.
+if [ "${shortname}" == "rust" ]; then
+	currentopt+=("${cmd_fullwipe[@]}" "${cmd_mapwipe[@]}")
+fi
+
+# Unreal exclusive.
+if [ "${engine}" == "unreal2" ]; then
+	if [ "${shortname}" == "ut2k4" ]; then
+		currentopt+=("${cmd_install_cdkey[@]}" "${cmd_map_compressor_u2[@]}")
+	else
+		currentopt+=("${cmd_map_compressor_u2[@]}")
+	fi
+fi
+if [ "${engine}" == "unreal" ]; then
+	currentopt+=("${cmd_map_compressor_u99[@]}")
+fi
+
+# DST exclusive.
+if [ "${shortname}" == "dst" ]; then
+	currentopt+=("${cmd_install_dst_token[@]}")
+fi
+
+# MTA exclusive.
+if [ "${shortname}" == "mta" ]; then
+	currentopt+=("${cmd_install_default_resources[@]}")
+fi
+
+# Squad license exclusive.
+if [ "${shortname}" == "squad" ]; then
+	currentopt+=("${cmd_install_squad_license[@]}")
+fi
+
+## Mods commands.
+if [ "${engine}" == "source" ] || [ "${shortname}" == "rust" ] || [ "${shortname}" == "hq" ] || [ "${shortname}" == "sdtd" ] || [ "${shortname}" == "cs" ] || [ "${shortname}" == "dod" ] || [ "${shortname}" == "tfc" ] || [ "${shortname}" == "ns" ] || [ "${shortname}" == "ts" ] || [ "${shortname}" == "hldm" ] || [ "${shortname}" == "vh" ]; then
+	currentopt+=("${cmd_mods_install[@]}" "${cmd_mods_remove[@]}" "${cmd_mods_update[@]}")
+fi
+
+## Installer.
+currentopt+=("${cmd_install[@]}" "${cmd_auto_install[@]}")
+
+## Developer commands.
+currentopt+=("${cmd_dev_debug[@]}")
+if [ -f ".dev-debug" ]; then
+	currentopt+=("${cmd_dev_detect_deps[@]}" "${cmd_dev_detect_glibc[@]}" "${cmd_dev_detect_ldd[@]}" "${cmd_dev_query_raw[@]}" "${cmd_dev_clear_modules[@]}")
+fi
+
+## Sponsor.
+currentopt+=("${cmd_sponsor[@]}")
+
+### Build list of available commands.
+optcommands=()
+index="0"
+for ((index = "0"; index < ${#currentopt[@]}; index += 3)); do
+	cmdamount=$(echo -e "${currentopt[index]}" | awk -F ';' '{ print NF }')
+	for ((cmdindex = 1; cmdindex <= cmdamount; cmdindex++)); do
+		optcommands+=("$(echo -e "${currentopt[index]}" | awk -F ';' -v x=${cmdindex} '{ print $x }')")
+	done
+done
+
+# Shows LinuxGSM usage.
+fn_opt_usage() {
+	echo -e "Usage: $0 [option]"
+	echo -e ""
+	echo -e "LinuxGSM - ${gamename} - Version ${version}"
+	echo -e "https://linuxgsm.com/${gameservername}"
+	echo -e ""
+	echo -e "${lightyellow}Commands${default}"
+	# Display available commands.
+	index="0"
+	{
+		for ((index = "0"; index < ${#currentopt[@]}; index += 3)); do
+			# Hide developer commands.
+			if [ "${currentopt[index + 2]}" != "DEVCOMMAND" ]; then
+				echo -e "${cyan}$(echo -e "${currentopt[index]}" | awk -F ';' '{ print $2 }')\t${default}$(echo -e "${currentopt[index]}" | awk -F ';' '{ print $1 }')\t| ${currentopt[index + 2]}"
+			fi
+		done
+	} | column -s $'\t' -t
+	fn_script_log_pass "Display commands"
+	core_exit.sh
+}
+
+# Check if command existw and run corresponding scripts, or display script usage.
+if [ -z "${getopt}" ]; then
+	fn_opt_usage
+fi
+# If command exists.
+for i in "${optcommands[@]}"; do
+	if [ "${i}" == "${getopt}" ]; then
+		# Seek and run command.
+		index="0"
+		for ((index = "0"; index < ${#currentopt[@]}; index += 3)); do
+			currcmdamount=$(echo -e "${currentopt[index]}" | awk -F ';' '{ print NF }')
+			for ((currcmdindex = 1; currcmdindex <= currcmdamount; currcmdindex++)); do
+				if [ "$(echo -e "${currentopt[index]}" | awk -F ';' -v x=${currcmdindex} '{ print $x }')" == "${getopt}" ]; then
+					# Run command.
+					eval "${currentopt[index + 1]}"
+					# Exit should occur in modules. Should this not happen print an error
+					fn_print_error2_nl "Command did not exit correctly: ${getopt}"
+					fn_script_log_error "Command did not exit correctly: ${getopt}"
+					core_exit.sh
+				fi
+			done
+		done
+	fi
+done
+
+# If we're executing this, it means command was not found.
+fn_print_error2_nl "Unknown command: $0 ${getopt}"
+fn_script_log_error "Unknown command: $0 ${getopt}"
+fn_opt_usage
+core_exit.sh

+ 114 - 0
lgsm/modules/core_github.sh

@@ -0,0 +1,114 @@
+#!/bin/bash
+# LinuxGSM core_github.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: core module file for updates via github
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+github_api="https://api.github.com"
+
+fn_githublocalversionfile() {
+	local githubreleaseuser="${1}"
+	local githubreleaserepo="${2}"
+
+	githublocalversionfile="${datadir}/github-${githubreleaseuser}-${githubreleaserepo}-version"
+}
+
+# $1 githubuser/group
+# $2 github repo name
+fn_github_get_latest_release_version() {
+	local githubreleaseuser="${1}"
+	local githubreleaserepo="${2}"
+	local githublatestreleaseurl="${github_api}/repos/${githubreleaseuser}/${githubreleaserepo}/releases/latest"
+
+	githubreleaseversion=$(curl -s --connect-timeout 10 "${githublatestreleaseurl}" | jq '.tag_name')
+
+	# error if no version is there
+	if [ -z "${githubreleaseversion}" ]; then
+		fn_print_fail_nl "Cannot get version from GitHub API for ${githubreleaseuser}/${githubreleaserepo}"
+		fn_script_log_fatal "Cannot get version from GitHub API for ${githubreleaseuser}/${githubreleaserepo}"
+	fi
+}
+
+# $1 githubuser/group
+# $2 github repo name
+fn_github_set_latest_release_version() {
+	local githubreleaseuser="${1}"
+	local githubreleaserepo="${2}"
+
+	fn_githublocalversionfile "${githubreleaseuser}" "${githubreleaserepo}"
+
+	local githublatestreleaseurl="${github_api}/repos/${githubreleaseuser}/${githubreleaserepo}/releases/latest"
+	githubreleaseversion=$(curl -s "${githublatestreleaseurl}" | jq -r '.tag_name')
+
+	# error if no version is there
+	if [ -z "${githubreleaseversion}" ]; then
+		fn_print_fail_nl "Cannot get version from GitHub API for ${githubreleaseuser}/${githubreleaserepo}"
+		fn_script_log_fatal "Cannot get version from GitHub API for ${githubreleaseuser}/${githubreleaserepo}"
+	else
+		echo "${githubreleaseversion}" > "${githublocalversionfile}"
+	fi
+}
+
+# $1 githubuser/group
+# $2 github repo name
+fn_github_get_installed_version() {
+	local githubreleaseuser="${1}"
+	local githubreleaserepo="${2}"
+
+	fn_githublocalversionfile "${githubreleaseuser}" "${githubreleaserepo}"
+
+	githublocalversion=$(cat "${githublocalversionfile}")
+}
+
+# $1 githubuser/group
+# $2 github repo name
+# if a update needs to be downloaded - updateneeded is set to 1
+fn_github_compare_version() {
+	local githubreleaseuser="${1}"
+	local githubreleaserepo="${2}"
+	exitcode=0
+	updateneeded=0
+
+	fn_githublocalversionfile "${githubreleaseuser}" "${githubreleaserepo}"
+	local githublatestreleaseurl="${github_api}/repos/${githubreleaseuser}/${githubreleaserepo}/releases/latest"
+
+	githublocalversion=$(cat "${githublocalversionfile}")
+	githubreleaseversion=$(curl -s "${githublatestreleaseurl}" | jq '.tag_name')
+
+	# error if no version is there
+	if [ -z "${githubreleaseversion}" ]; then
+		fn_print_fail_nl "Can not get version from Github Api for ${githubreleaseuser}/${githubreleaserepo}"
+		fn_script_log_fatal "Can not get version from Github Api for ${githubreleaseuser}/${githubreleaserepo}"
+	else
+		if [ "${githublocalversion}" == "${githubreleaseversion}" ]; then
+			echo -en "\n"
+			echo -e "No update from github.com/${githubreleaseuser}/${githubreleaserepo}/ available:"
+			echo -e "* Local build: ${red}${githublocalversion}${default}"
+			echo -e "* Remote build: ${green}${githubreleaseversion}${default}"
+			echo -en "\n"
+		else
+			# check if version that is installed is higher than the remote version to not override it
+			last_version=$(echo -e "${githublocalversion}\n${githubreleaseversion}" | sort -V | head -n1)
+			if [ "${githubreleaseversion}" == "${last_version}" ]; then
+				echo -en "\n"
+				echo -e "Update from github.com/${githubreleaseuser}/${githubreleaserepo}/ available:"
+				echo -e "* Local build: ${red}${githublocalversion}${default}"
+				echo -e "* Remote build: ${green}${githubreleaseversion}${default}"
+				echo -en "\n"
+				updateneeded=1
+			else
+				# local version is higher than the remote version output this to the user
+				# strange case but could be possible, as a release could be removed from github
+				echo -en "\n"
+				echo -e "Local version is newer than the remote version"
+				echo -e "* Local version: ${green}${githublocalversion}${default}"
+				echo -e "* Remote version: ${green}${githubreleaseversion}${default}"
+				echo -en "\n"
+				exitcode=1
+			fi
+		fi
+	fi
+}

+ 93 - 0
lgsm/modules/core_legacy.sh

@@ -0,0 +1,93 @@
+#!/bin/bash
+# LinuxGSM core_legacy.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Code for backwards compatability with older versions of LinuxGSM.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+# This is to help the transition to v20.3.0 and above
+legacy_versions_array=(v20.2.1 v20.2.0 v20.1.5 v20.1.4 v20.1.3 v20.1.2 v20.1.1 v20.1.0 v19.12.5 v19.12.4 v19.12.3 v19.12.2 v19.12.1 v19.12.0)
+for legacy_version in "${legacy_versions_array[@]}"; do
+	if [ "${version}" == "${legacy_version}" ]; then
+		legacymode=1
+	fi
+done
+
+if [ -z "${serverfiles}" ]; then
+	serverfiles="${filesdir}"
+fi
+
+if [ -z "${logdir}" ]; then
+	logdir="${rootdir}/log"
+fi
+
+if [ -z "${lgsmlogdir}" ]; then
+	lgsmlogdir="${scriptlogdir}"
+fi
+
+if [ -z "${lgsmlog}" ]; then
+	lgsmlog="${scriptlog}"
+fi
+
+if [ -z "${lgsmlogdate}" ]; then
+	lgsmlogdate="${scriptlogdate}"
+fi
+
+if [ -z "${steamcmddir}" ]; then
+	steamcmddir="${HOME}/.steam/steamcmd"
+fi
+
+if [ -z "${lgsmdir}" ]; then
+	lgsmdir="${rootdir}/lgsm"
+fi
+
+if [ -z "${tmpdir}" ]; then
+	tmpdir="${lgsmdir}/tmp"
+fi
+
+if [ -z "${alertlog}" ]; then
+	alertlog="${emaillog}"
+fi
+
+if [ -z "${servicename}" ]; then
+	servicename="${selfname}"
+fi
+
+# Alternations to workshop variables.
+if [ -z "${wsapikey}" ]; then
+	if [ "${workshopauth}" ]; then
+		wsapikey="${workshopauth}"
+	elif [ "${authkey}" ]; then
+		wsapikey="${authkey}"
+	fi
+fi
+
+if [ -z "${wscollectionid}" ]; then
+	if [ "${workshopauth}" ]; then
+		wscollectionid="${ws_collection_id}"
+	elif [ "${authkey}" ]; then
+		wscollectionid="${workshopcollectionid}"
+	fi
+fi
+
+if [ -z "${wsstartmap}" ]; then
+	if [ "${ws_start_map}" ]; then
+		wscollectionid="${ws_start_map}"
+	fi
+fi
+
+# Added as part of migrating functions dir to modules dir.
+# Will remove functions dir if files in modules dir older than 14 days
+functionsdir="${lgsmdir}/modules"
+if [ -d "${lgsmdir}/functions" ]; then
+	if [ "$(find "${lgsmdir}/modules"/ -type f -mtime +"14" | wc -l)" -ne "0" ]; then
+		rm -rf "${lgsmdir:?}/functions"
+	fi
+fi
+
+fn_parms() {
+	fn_reload_startparameters
+	parms="${startparameters}"
+}

+ 110 - 0
lgsm/modules/core_logs.sh

@@ -0,0 +1,110 @@
+#!/bin/bash
+# LinuxGSM core_logs.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Acts as a log rotator, removing old logs.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+# Check if logfile variable and file exist, create logfile if it doesn't exist.
+if [ "${consolelog}" ]; then
+	if [ ! -f "${consolelog}" ]; then
+		touch "${consolelog}"
+	fi
+fi
+
+# For games not displaying a console, and having logs into their game directory.
+check_status.sh
+if [ "${status}" != "0" ] && [ "${commandname}" == "START" ] && [ -n "${gamelogfile}" ]; then
+	if [ "$(find "${systemdir}" -name "gamelog*.log")" ]; then
+		fn_print_info "Moving game logs to ${gamelogdir}"
+		fn_script_log_info "Moving game logs to ${gamelogdir}"
+		echo -en "\n"
+		fn_sleep_time
+		mv "${systemdir}"/gamelog*.log "${gamelogdir}"
+	fi
+fi
+
+# Log manager will start the cleanup if it finds logs older than "${logdays}".
+if [ "$(find "${lgsmlogdir}"/ -type f -mtime +"${logdays}" | wc -l)" -ne "0" ]; then
+	fn_print_dots "Starting"
+	# Set common logs directories
+	commonlogs="${systemdir}/logs"
+	commonsourcelogs="${systemdir}/*/logs"
+	# Set addon logs directories
+	sourcemodlogdir="${systemdir}/addons/sourcemod/logs"
+	ulxlogdir="${systemdir}/data/ulx_logs"
+	darkrplogdir="${systemdir}/data/darkrp_logs"
+	legacyserverlogdir="${logdir}/server"
+	# Setting up counting variables
+	scriptcount="0"
+	consolecount="0"
+	gamecount="0"
+	srcdscount="0"
+	smcount="0"
+	ulxcount="0"
+	darkrpcount="0"
+	legacycount="0"
+	fn_sleep_time
+	fn_print_info "Removing logs older than ${logdays} days"
+	fn_script_log_info "Removing logs older than ${logdays} days"
+	# Logging logfiles to be removed according to "${logdays}", counting and removing them.
+	# Script logfiles.
+	find "${lgsmlogdir}"/ -type f -mtime +"${logdays}" | tee >> "${lgsmlog}"
+	scriptcount=$(find "${lgsmlogdir}"/ -type f -mtime +"${logdays}" | wc -l)
+	find "${lgsmlogdir}"/ -mtime +"${logdays}" -type f -exec rm -f {} \;
+	# SRCDS and unreal logfiles.
+	if [ "${engine}" == "unreal2" ] || [ "${engine}" == "source" ]; then
+		find "${gamelogdir}"/ -type f -mtime +"${logdays}" | tee >> "${lgsmlog}"
+		gamecount=$(find "${gamelogdir}"/ -type f -mtime +"${logdays}" | wc -l)
+		find "${gamelogdir}"/ -mtime +"${logdays}" -type f -exec rm -f {} \;
+	fi
+	# Console logfiles.
+	if [ "${consolelog}" ]; then
+		find "${consolelogdir}"/ -type f -mtime +"${logdays}" | tee >> "${lgsmlog}"
+		consolecount=$(find "${consolelogdir}"/ -type f -mtime +"${logdays}" | wc -l)
+		find "${consolelogdir}"/ -mtime +"${logdays}" -type f -exec rm -f {} \;
+	fi
+	# Common logfiles.
+	if [ -d "${commonlogs}" ]; then
+		find "${commonlogs}"/ -type f -mtime +"${logdays}" | tee >> "${lgsmlog}"
+		smcount=$(find "${commonlogs}"/ -type f -mtime +"${logdays}" | wc -l)
+		find "${commonlogs}"/ -mtime +"${logdays}" -type f -exec rm -f {} \;
+	fi
+	if [ -d "${commonsourcelogs}" ]; then
+		find "${commonsourcelogs}"/* -type f -mtime +"${logdays}" | tee >> "${lgsmlog}"
+		smcount=$(find "${commonsourcelogs}"/* -type f -mtime +"${logdays}" | wc -l)
+		find "${commonsourcelogs}"/* -mtime +"${logdays}" -type f -exec rm -f {} \;
+	fi
+	# Source addons logfiles.
+	if [ "${engine}" == "source" ]; then
+		# SourceMod logfiles.
+		if [ -d "${sourcemodlogdir}" ]; then
+			find "${sourcemodlogdir}"/ -type f -mtime +"${logdays}" | tee >> "${lgsmlog}"
+			smcount=$(find "${sourcemodlogdir}"/ -type f -mtime +"${logdays}" | wc -l)
+			find "${sourcemodlogdir}"/ -mtime +"${logdays}" -type f -exec rm -f {} \;
+		fi
+		# Garry's Mod logfiles.
+		if [ "${shortname}" == "gmod" ]; then
+			# ULX logfiles.
+			if [ -d "${ulxlogdir}" ]; then
+				find "${ulxlogdir}"/ -type f -mtime +"${logdays}" | tee >> "${lgsmlog}"
+				ulxcount=$(find "${ulxlogdir}"/ -type f -mtime +"${logdays}" | wc -l)
+				find "${ulxlogdir}"/ -mtime +"${logdays}" -type f -exec rm -f {} \;
+			fi
+			# DarkRP logfiles.
+			if [ -d "${darkrplogdir}" ]; then
+				find "${darkrplogdir}"/ -type f -mtime +"${logdays}" | tee >> "${lgsmlog}"
+				darkrpcount=$(find "${darkrplogdir}"/ -type f -mtime +"${logdays}" | wc -l)
+				find "${darkrplogdir}"/ -mtime +"${logdays}" -type f -exec rm -f {} \;
+			fi
+		fi
+	fi
+
+	# Count total amount of files removed.
+	countlogs=$((scriptcount + consolecount + gamecount + srcdscount + smcount + ulxcount + darkrpcount))
+	# Job done.
+	fn_print_ok "Removed ${countlogs} log files"
+	fn_script_log "Removed ${countlogs} log files"
+fi

+ 598 - 0
lgsm/modules/core_messages.sh

@@ -0,0 +1,598 @@
+#!/bin/bash
+# LinuxGSM core_messages.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Defines on-screen messages such as [  OK  ] and how script logs look.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+# nl: new line: message is following by a new line.
+# eol: end of line: message is placed at the end of the current line.
+fn_ansi_loader() {
+	if [ "${ansi}" != "off" ]; then
+		# echo colors
+		default="\e[0m"
+		black="\e[30m"
+		red="\e[31m"
+		lightred="\e[91m"
+		green="\e[32m"
+		lightgreen="\e[92m"
+		yellow="\e[33m"
+		lightyellow="\e[93m"
+		blue="\e[34m"
+		lightblue="\e[94m"
+		magenta="\e[35m"
+		lightmagenta="\e[95m"
+		cyan="\e[36m"
+		lightcyan="\e[96m"
+		darkgrey="\e[90m"
+		lightgrey="\e[37m"
+		white="\e[97m"
+	fi
+	# carriage return & erase to end of line.
+	creeol="\r\033[K"
+}
+
+fn_sleep_time() {
+	if [ "${sleeptime}" != "0" ] || [ "${travistest}" != "1" ]; then
+		if [ -z "${sleeptime}" ]; then
+			sleeptime=0.5
+		fi
+		sleep "${sleeptime}"
+	fi
+}
+
+# Log display
+########################
+## Feb 28 14:56:58 ut99-server: Monitor:
+fn_script_log() {
+	if [ -d "${lgsmlogdir}" ]; then
+		if [ -n "${commandname}" ]; then
+			echo -e "$(date '+%b %d %H:%M:%S.%3N') ${selfname}: ${commandname}: ${1}" >> "${lgsmlog}"
+		else
+			echo -e "$(date '+%b %d %H:%M:%S.%3N') ${selfname}: ${1}" >> "${lgsmlog}"
+		fi
+	fi
+}
+
+## Feb 28 14:56:58 ut99-server: Monitor: PASS:
+fn_script_log_pass() {
+	if [ -d "${lgsmlogdir}" ]; then
+
+		if [ -n "${commandname}" ]; then
+			echo -e "$(date '+%b %d %H:%M:%S.%3N') ${selfname}: ${commandname}: PASS: ${1}" >> "${lgsmlog}"
+		else
+			echo -e "$(date '+%b %d %H:%M:%S.%3N') ${selfname}: PASS: ${1}" >> "${lgsmlog}"
+		fi
+	fi
+	exitcode=0
+}
+
+## Feb 28 14:56:58 ut99-server: Monitor: FATAL:
+fn_script_log_fatal() {
+	if [ -d "${lgsmlogdir}" ]; then
+		if [ -n "${commandname}" ]; then
+			echo -e "$(date '+%b %d %H:%M:%S.%3N') ${selfname}: ${commandname}: FATAL: ${1}" >> "${lgsmlog}"
+		else
+			echo -e "$(date '+%b %d %H:%M:%S.%3N') ${selfname}: FATAL: ${1}" >> "${lgsmlog}"
+		fi
+	fi
+	exitcode=1
+}
+
+## Feb 28 14:56:58 ut99-server: Monitor: ERROR:
+fn_script_log_error() {
+	if [ -d "${lgsmlogdir}" ]; then
+		if [ -n "${commandname}" ]; then
+			echo -e "$(date '+%b %d %H:%M:%S.%3N') ${selfname}: ${commandname}: ERROR: ${1}" >> "${lgsmlog}"
+		else
+			echo -e "$(date '+%b %d %H:%M:%S.%3N') ${selfname}: ERROR: ${1}" >> "${lgsmlog}"
+		fi
+	fi
+	exitcode=2
+}
+
+## Feb 28 14:56:58 ut99-server: Monitor: WARN:
+fn_script_log_warn() {
+	if [ -d "${lgsmlogdir}" ]; then
+		if [ -n "${commandname}" ]; then
+			echo -e "$(date '+%b %d %H:%M:%S.%3N') ${selfname}: ${commandname}: WARN: ${1}" >> "${lgsmlog}"
+		else
+			echo -e "$(date '+%b %d %H:%M:%S.%3N') ${selfname}: WARN: ${1}" >> "${lgsmlog}"
+		fi
+	fi
+	exitcode=3
+}
+
+## Feb 28 14:56:58 ut99-server: Monitor: INFO:
+fn_script_log_info() {
+	if [ -d "${lgsmlogdir}" ]; then
+		if [ -n "${commandname}" ]; then
+			echo -e "$(date '+%b %d %H:%M:%S.%3N') ${selfname}: ${commandname}: INFO: ${1}" >> "${lgsmlog}"
+		else
+			echo -e "$(date '+%b %d %H:%M:%S.%3N') ${selfname}: INFO: ${1}" >> "${lgsmlog}"
+		fi
+	fi
+}
+
+## Feb 28 14:56:58 ut99-server: Monitor: UPDATE:
+fn_script_log_update() {
+	if [ -d "${lgsmlogdir}" ]; then
+		if [ -n "${commandname}" ]; then
+			echo -e "$(date '+%b %d %H:%M:%S.%3N') ${selfname}: ${commandname}: UPDATE: ${1}" >> "${lgsmlog}"
+		else
+			echo -e "$(date '+%b %d %H:%M:%S.%3N') ${selfname}: UPDATE: ${1}" >> "${lgsmlog}"
+		fi
+	fi
+}
+
+# On-Screen - Automated functions
+##################################
+
+# [ .... ]
+fn_print_dots() {
+	if [ "${commandaction}" ]; then
+		echo -en "${creeol}[ .... ] ${commandaction} ${selfname}: $*"
+	else
+		echo -en "${creeol}[ .... ] $*"
+	fi
+	fn_sleep_time
+}
+
+fn_print_dots_nl() {
+	if [ "${commandaction}" ]; then
+		echo -e "${creeol}[ .... ] ${commandaction} ${selfname}: $*"
+	else
+		echo -e "${creeol}[ .... ] $*"
+	fi
+	fn_sleep_time
+	echo -en "\n"
+}
+
+# [  OK  ]
+fn_print_ok() {
+	if [ "${commandaction}" ]; then
+		echo -en "${creeol}[${green}  OK  ${default}] ${commandaction} ${selfname}: $*"
+	else
+		echo -en "${creeol}[${green}  OK  ${default}] $*"
+	fi
+	fn_sleep_time
+}
+
+fn_print_ok_nl() {
+	if [ "${commandaction}" ]; then
+		echo -en "${creeol}[${green}  OK  ${default}] ${commandaction} ${selfname}: $*"
+	else
+		echo -en "${creeol}[${green}  OK  ${default}] $*"
+	fi
+	fn_sleep_time
+	echo -en "\n"
+}
+
+# [ FAIL ]
+fn_print_fail() {
+	if [ "${commandaction}" ]; then
+		echo -en "${creeol}[${red} FAIL ${default}] ${commandaction} ${selfname}: $*"
+	else
+		echo -en "${creeol}[${red} FAIL ${default}] $*"
+	fi
+	fn_sleep_time
+}
+
+fn_print_fail_nl() {
+	if [ "${commandaction}" ]; then
+		echo -en "${creeol}[${red} FAIL ${default}] ${commandaction} ${selfname}: $*"
+	else
+		echo -en "${creeol}[${red} FAIL ${default}] $*"
+	fi
+	fn_sleep_time
+	echo -en "\n"
+}
+
+# [ ERROR ]
+fn_print_error() {
+	if [ "${commandaction}" ]; then
+		echo -en "${creeol}[${red} ERROR ${default}] ${commandaction} ${selfname}: $*"
+	else
+		echo -en "${creeol}[${red} ERROR ${default}] $*"
+	fi
+	fn_sleep_time
+}
+
+fn_print_error_nl() {
+	if [ "${commandaction}" ]; then
+		echo -en "${creeol}[${red} ERROR ${default}] ${commandaction} ${selfname}: $*"
+	else
+		echo -en "${creeol}[${red} ERROR ${default}] $*"
+	fi
+	fn_sleep_time
+	echo -en "\n"
+}
+
+# [ WARN ]
+fn_print_warn() {
+	if [ "${commandaction}" ]; then
+		echo -en "${creeol}[${lightyellow} WARN ${default}] ${commandaction} ${selfname}: $*"
+	else
+		echo -en "${creeol}[${lightyellow} WARN ${default}] $*"
+	fi
+	fn_sleep_time
+}
+
+fn_print_warn_nl() {
+	if [ "${commandaction}" ]; then
+		echo -en "${creeol}[${lightyellow} WARN ${default}] ${commandaction} ${selfname}: $*"
+	else
+		echo -en "${creeol}[${lightyellow} WARN ${default}] $*"
+	fi
+	fn_sleep_time
+	echo -en "\n"
+}
+
+# [ INFO ]
+fn_print_info() {
+	if [ "${commandaction}" ]; then
+		echo -en "${creeol}[${cyan} INFO ${default}] ${commandaction} ${selfname}: $*"
+	else
+		echo -en "${creeol}[${cyan} INFO ${default}] $*"
+	fi
+	fn_sleep_time
+}
+
+fn_print_info_nl() {
+	if [ "${commandaction}" ]; then
+		echo -en "${creeol}[${cyan} INFO ${default}] ${commandaction} ${selfname}: $*"
+	else
+		echo -en "${creeol}[${cyan} INFO ${default}] $*"
+	fi
+	fn_sleep_time
+	echo -en "\n"
+}
+
+# [ START ]
+fn_print_start() {
+	if [ "${commandaction}" ]; then
+		echo -en "${creeol}[${lightgreen} START ${default}] ${commandaction} ${selfname}: $*"
+	else
+		echo -en "${creeol}[${lightgreen} START ${default}] $*"
+	fi
+	fn_sleep_time
+}
+
+fn_print_start_nl() {
+	if [ "${commandaction}" ]; then
+		echo -en "${creeol}[${lightgreen} START ${default}] ${commandaction} ${selfname}: $*"
+	else
+		echo -en "${creeol}[${lightgreen} START ${default}] $*"
+	fi
+	fn_sleep_time
+	echo -en "\n"
+}
+
+# On-Screen - Interactive messages
+##################################
+
+# No More Room in Hell Debug
+# =================================
+fn_print_header() {
+	echo -e ""
+	echo -e "${lightyellow}${gamename} ${commandaction}${default}"
+	echo -e "=================================${default}"
+}
+
+# Complete!
+fn_print_complete() {
+	echo -en "${green}Complete!${default} $*"
+	fn_sleep_time
+}
+
+fn_print_complete_nl() {
+	echo -e "${green}Complete!${default} $*"
+	fn_sleep_time
+}
+
+# Failure!
+fn_print_failure() {
+	echo -en "${red}Failure!${default} $*"
+	fn_sleep_time
+}
+
+fn_print_failure_nl() {
+	echo -e "${red}Failure!${default} $*"
+	fn_sleep_time
+}
+
+# Error!
+fn_print_error2() {
+	echo -en "${red}Error!${default} $*"
+	fn_sleep_time
+}
+
+fn_print_error2_nl() {
+	echo -e "${red}Error!${default} $*"
+	fn_sleep_time
+}
+
+# Warning!
+fn_print_warning() {
+	echo -en "${lightyellow}Warning!${default} $*"
+	fn_sleep_time
+}
+
+fn_print_warning_nl() {
+	echo -e "${lightyellow}Warning!${default} $*"
+	fn_sleep_time
+}
+
+# Information!
+fn_print_information() {
+	echo -en "${cyan}Information!${default} $*"
+	fn_sleep_time
+}
+
+fn_print_information_nl() {
+	echo -e "${cyan}Information!${default} $*"
+	fn_sleep_time
+}
+
+# Y/N Prompt
+fn_prompt_yn() {
+	local prompt="$1"
+	local initial="$2"
+
+	if [ "${initial}" == "Y" ]; then
+		prompt+=" [Y/n] "
+	elif [ "${initial}" == "N" ]; then
+		prompt+=" [y/N] "
+	else
+		prompt+=" [y/n] "
+	fi
+
+	while true; do
+		read -e -i "${initial}" -p "${prompt}" -r yn
+		case "${yn}" in
+			[Yy] | [Yy][Ee][Ss]) return 0 ;;
+			[Nn] | [Nn][Oo]) return 1 ;;
+			*) echo -e "Please answer yes or no." ;;
+		esac
+	done
+}
+
+# Prompt for message
+fn_prompt_message() {
+	while true; do
+		unset prompt
+		local prompt="$1"
+		read -e -p "${prompt}" -r answer
+		if fn_prompt_yn "Continue" Y; then
+			break
+		fi
+	done
+	echo "${answer}"
+}
+
+# On-Screen End of Line
+##################################
+
+# YES
+fn_print_yes_eol() {
+	echo -en "${cyan}YES${default}"
+	fn_sleep_time
+}
+
+fn_print_yes_eol_nl() {
+	echo -e "${cyan}YES${default}"
+	fn_sleep_time
+}
+
+# NO
+fn_print_no_eol() {
+	echo -en "${red}NO${default}"
+	fn_sleep_time
+}
+
+fn_print_no_eol_nl() {
+	echo -e "${red}NO${default}"
+	fn_sleep_time
+}
+
+# OK
+fn_print_ok_eol() {
+	echo -en "${green}OK${default}"
+	fn_sleep_time
+}
+
+fn_print_ok_eol_nl() {
+	echo -e "${green}OK${default}"
+	fn_sleep_time
+}
+
+# FAIL
+fn_print_fail_eol() {
+	echo -en "${red}FAIL${default}"
+	fn_sleep_time
+}
+
+fn_print_fail_eol_nl() {
+	echo -e "${red}FAIL${default}"
+	fn_sleep_time
+}
+
+# ERROR
+fn_print_error_eol() {
+	echo -en "${red}ERROR${default}"
+	fn_sleep_time
+}
+
+fn_print_error_eol_nl() {
+	echo -e "${red}ERROR${default}"
+	fn_sleep_time
+}
+
+# WAIT
+fn_print_wait_eol() {
+	echo -en "${cyan}WAIT${default}"
+	fn_sleep_time
+}
+
+fn_print_wait_eol_nl() {
+	echo -e "${cyan}WAIT${default}"
+	fn_sleep_time
+}
+
+# WARN
+fn_print_warn_eol() {
+	echo -en "${lightyellow}WARN${default}"
+	fn_sleep_time
+}
+
+fn_print_warn_eol_nl() {
+	echo -e "${lightyellow}WARN${default}"
+	fn_sleep_time
+}
+
+# INFO
+fn_print_info_eol() {
+	echo -en "${cyan}INFO${default}"
+	fn_sleep_time
+}
+
+fn_print_info_eol_nl() {
+	echo -e "${cyan}INFO${default}"
+	fn_sleep_time
+}
+
+# QUERYING
+fn_print_querying_eol() {
+	echo -en "${cyan}QUERYING${default}"
+	fn_sleep_time
+}
+
+fn_print_querying_eol_nl() {
+	echo -e "${cyan}QUERYING${default}"
+	fn_sleep_time
+}
+
+# CHECKING
+fn_print_checking_eol() {
+	echo -en "${cyan}CHECKING${default}"
+	fn_sleep_time
+}
+
+fn_print_checking_eol_nl() {
+	echo -e "${cyan}CHECKING${default}"
+	fn_sleep_time
+}
+
+# DELAY
+fn_print_delay_eol() {
+	echo -en "${green}DELAY${default}"
+	fn_sleep_time
+}
+
+fn_print_delay_eol_nl() {
+	echo -e "${green}DELAY${default}"
+	fn_sleep_time
+}
+
+# CANCELED
+fn_print_canceled_eol() {
+	echo -en "${lightyellow}CANCELED${default}"
+	fn_sleep_time
+}
+
+fn_print_canceled_eol_nl() {
+	echo -e "${lightyellow}CANCELED${default}"
+	fn_sleep_time
+}
+
+# REMOVED
+fn_print_removed_eol() {
+	echo -en "${red}REMOVED${default}"
+	fn_sleep_time
+}
+
+fn_print_removed_eol_nl() {
+	echo -e "${red}REMOVED${default}"
+	fn_sleep_time
+}
+
+# UPDATE
+fn_print_update_eol() {
+	echo -en "${cyan}UPDATE${default}"
+	fn_sleep_time
+}
+
+fn_print_update_eol_nl() {
+	echo -e "${cyan}UPDATE${default}"
+	fn_sleep_time
+}
+
+fn_print_ascii_logo() {
+	echo -e ""
+	echo -e "                                mdMMMMbm"
+	echo -e "                              mMMMMMMMMMMm"
+	echo -e "                              mMMMMMMMMMMMMm"
+	echo -e "                             mMMMMMMMMMMMMMMm"
+	echo -e "                             hMMMV^VMMV^VMMMh"
+	echo -e "                             MMMMM  MM  MMMMM"
+	echo -e "                             hMMs   vv   sMMh"
+	echo -e "                            hMMM:        :MMMh"
+	echo -e "                          .hMMMh          hMMMh."
+	echo -e "                         -dMMMh     ${lightgrey}__${default}     hMMMd-"
+	echo -e "                        :mMMMs      ${lightgrey}||${default}      sMMMm:"
+	echo -e "                       :MMMM+       ${lightgrey}||${default} ${red}_${default}     +NMMN:"
+	echo -e "                      .mMMM+     ${lightgrey}========${default}     +MMMm."
+	echo -e "                      yMMMy   ${darkgrey}##############${default}   yMMMy"
+	echo -e "                      mMMM:   ${darkgrey}##############${default}   :MMMm"
+	echo -e "                      mMM   ${lightyellow}nn${default}   ${lightyellow}nn${default}    ${lightyellow}nn${default}   ${lightyellow}nn${default}   MMm"
+	echo -e "                      o   ${lightyellow}nNNNNNNNn${default}    ${lightyellow}nNNNNNNNn${default}   o"
+	echo -e "                         ${lightyellow}nNNNNNNNNNn${default}  ${lightyellow}nNNNNNNNNNn${default}"
+	echo -e "                        ${lightyellow}nNNNNNNNNNNN${default}  ${lightyellow}NNNNNNNNNNNn${default}"
+	echo -e "                         ${lightyellow}+NNNNNNNNN:${default}  ${lightyellow}:NNNNNNNNN+${default}"
+	echo -e "                           ${lightyellow}nNNNNNNN${default} /\ ${lightyellow}NNNNNNNn${default}"
+	echo -e "                             ${lightyellow}nnnnn${default}  db  ${lightyellow}nnnnn${default}"
+	echo -e ""
+	echo -e "${lightyellow}888${default}      ${lightyellow}d8b${default}                             ${default}.d8888b.   .d8888b.  888b     d888"
+	echo -e "${lightyellow}888      Y8P                            ${default}d88P  Y88b d88P  Y88b 8888b   d8888"
+	echo -e "${lightyellow}888${default}                                     ${default}888${default}    888 Y88b.      88888b.d88888"
+	echo -e "${lightyellow}888${default}      ${lightyellow}888${default} ${lightyellow}88888b.${default}  ${lightyellow}888${default}  ${lightyellow}888${default} ${lightyellow}888${default}  ${lightyellow}888${default} 888          Y888b.   888Y88888P888"
+	echo -e "${lightyellow}888${default}      ${lightyellow}888${default} ${lightyellow}888${default}  ${lightyellow}88b${default} ${lightyellow}888${default}  ${lightyellow}888${default}  ${lightyellow}Y8bd8P${default}  888  88888      Y88b. 888 Y888P 888"
+	echo -e "${lightyellow}888${default}      ${lightyellow}888${default} ${lightyellow}888${default}  ${lightyellow}888${default} ${lightyellow}888${default}  ${lightyellow}888${default}   ${lightyellow}X88K${default}   888    888        888 888  Y8P  888"
+	echo -e "${lightyellow}888${default}      ${lightyellow}888${default} ${lightyellow}888${default}  ${lightyellow}888${default} ${lightyellow}Y88b${default} ${lightyellow}88Y${default} ${lightyellow}.d8pq8b.${default} Y88b  d88P Y88b  d88P 888   *   888"
+	echo -e "${lightyellow}LinuxGSM${default} ${lightyellow}888${default} ${lightyellow}888${default}  ${lightyellow}888${default}  ${lightyellow}Y8888Y${default}  ${lightyellow}888${default}  ${lightyellow}888${default}   Y2012P88   Y8888P   888       888"
+	echo -e ""
+}
+
+fn_print_restart_warning() {
+	fn_print_warn "${selfname} will be restarted"
+	fn_script_log_warn "${selfname} will be restarted"
+	totalseconds=3
+	for seconds in {3..1}; do
+		fn_print_warn "${selfname} will be restarted: ${totalseconds}"
+		totalseconds=$((totalseconds - 1))
+		sleep 1
+		if [ "${seconds}" == "0" ]; then
+			break
+		fi
+	done
+	fn_print_warn_nl "${selfname} will be restarted"
+}
+
+# Functions below are used to ensure that logs and UI correctly reflect the command it is actually running.
+# Useful when a command has to call upon another command causing the other command to overrite commandname variables
+
+# Used to remember the command that ran first.
+fn_firstcommand_set() {
+	if [ -z "${firstcommandname}" ]; then
+		firstcommandname="${commandname}"
+		firstcommandaction="${commandaction}"
+	fi
+}
+
+# Used to reset commandname variables to the command the script ran first.
+fn_firstcommand_reset() {
+	commandname="${firstcommandname}"
+	commandaction="${firstcommandaction}"
+}

+ 816 - 0
lgsm/modules/core_modules.sh

@@ -0,0 +1,816 @@
+#!/bin/bash
+# LinuxGSM core_modules.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Defines all modules to allow download and execution of modules using fn_fetch_module.
+# This module is called first before any other module. Without this file other modules will not load.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+modulesversion="v23.2.0"
+
+# Core
+
+core_dl.sh() {
+	modulefile="${FUNCNAME[0]}"
+	if [ "$(type fn_fetch_core_dl 2> /dev/null)" ]; then
+		fn_fetch_core_dl "lgsm/modules" "core_dl.sh" "${modulesdir}" "chmodx" "run" "noforcedl" "nohash"
+	else
+		fn_bootstrap_fetch_file_github "lgsm/modules" "core_dl.sh" "${modulesdir}" "chmodx" "run" "noforcedl" "nohash"
+	fi
+}
+
+core_messages.sh() {
+	modulefile="${FUNCNAME[0]}"
+	if [ "$(type fn_fetch_core_dl 2> /dev/null)" ]; then
+		fn_fetch_core_dl "lgsm/modules" "core_messages.sh" "${modulesdir}" "chmodx" "run" "noforcedl" "nohash"
+	else
+		fn_bootstrap_fetch_file_github "lgsm/modules" "core_messages.sh" "${modulesdir}" "chmodx" "run" "noforcedl" "nohash"
+	fi
+}
+
+core_legacy.sh() {
+	modulefile="${FUNCNAME[0]}"
+	if [ "$(type fn_fetch_core_dl 2> /dev/null)" ]; then
+		fn_fetch_core_dl "lgsm/modules" "core_legacy.sh" "${modulesdir}" "chmodx" "run" "noforcedl" "nohash"
+	else
+		fn_bootstrap_fetch_file_github "lgsm/modules" "core_legacy.sh" "${modulesdir}" "chmodx" "run" "noforcedl" "nohash"
+	fi
+}
+
+core_exit.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+core_getopt.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+core_trap.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+core_steamcmd.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+core_github.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+# Commands
+
+command_backup.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_console.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_debug.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_details.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_sponsor.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_postdetails.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_test_alert.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_monitor.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_start.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_stop.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_validate.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_install.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_install_resources_mta.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_squad_license.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_mods_install.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_mods_update.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_mods_remove.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_fastdl.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_ts3_server_pass.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_restart.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_skeleton.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_wipe.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_send.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+# Checks
+
+check.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_config.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_deps.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_executable.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_glibc.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_ip.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_last_update.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_logs.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_permissions.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_root.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_status.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_steamcmd.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_system_dir.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_system_requirements.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_tmuxception.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+check_version.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+# Compress
+
+compress_unreal2_maps.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+compress_ut99_maps.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+# Mods
+
+mods_list.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+mods_core.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+# Dev
+
+command_dev_clear_modules.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_dev_debug.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_dev_detect_deps.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_dev_detect_glibc.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_dev_detect_ldd.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_dev_query_raw.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+# Fix
+
+fix.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_ark.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_av.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_arma3.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_armar.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_bt.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_bo.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_cmw.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_csgo.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_dst.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_hw.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_ins.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_kf.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_kf2.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_lo.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_mcb.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_mta.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_nmrih.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_onset.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_ro.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_rust.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_rw.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_sfc.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_st.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_steamcmd.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_terraria.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_tf2.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_ut3.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_rust.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_samp.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_sdtd.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_sof2.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_squad.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_ts3.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_ut2k4.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_ut.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_unt.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_vh.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_wurm.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fix_zmr.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+# Info
+
+info_distro.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+info_game.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+info_messages.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+info_stats.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+# Alert
+
+alert.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+alert_discord.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+alert_email.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+alert_ifttt.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+alert_mailgun.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+alert_pushbullet.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+alert_pushover.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+alert_gotify.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+alert_telegram.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+alert_rocketchat.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+alert_slack.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+# Logs
+
+core_logs.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+# Query
+
+query_gamedig.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+# Update
+
+command_update_modules.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_update_linuxgsm.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_update.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+command_check_update.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+update_ts3.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+update_minecraft.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+update_minecraft_bedrock.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+update_papermc.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+update_mta.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+update_factorio.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+update_jediknight2.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+update_steamcmd.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+update_vintagestory.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+update_ut99.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+fn_update_modules.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+#
+## Installer modules
+#
+
+fn_autoinstall() {
+	autoinstall=1
+	command_install.sh
+}
+
+install_complete.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_config.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_factorio_save.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_dst_token.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_eula.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_gsquery.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_gslt.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_header.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_logs.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_retry.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_server_dir.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+install_server_files.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_stats.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_steamcmd.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_ts3.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_ts3db.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_ut2k4.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_dl_ut2k4.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+install_ut2k4_key.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
+# Calls code required for legacy servers
+core_legacy.sh
+
+# Creates tmp dir if missing
+if [ ! -d "${tmpdir}" ]; then
+	mkdir -p "${tmpdir}"
+fi
+
+# Creates lock dir if missing
+if [ ! -d "${lockdir}" ]; then
+	mkdir -p "${lockdir}"
+fi
+
+# Calls on-screen messages (bootstrap)
+core_messages.sh
+
+#Calls file downloader (bootstrap)
+core_dl.sh
+
+# Calls the global Ctrl-C trap
+core_trap.sh

+ 330 - 0
lgsm/modules/core_steamcmd.sh

@@ -0,0 +1,330 @@
+#!/bin/bash
+# LinuxGSM core_steamcmd.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Core modules for SteamCMD
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+fn_install_steamcmd() {
+	if [ "${shortname}" == "ark" ] && [ "${installsteamcmd}" == "1" ]; then
+		steamcmddir="${serverfiles}/Engine/Binaries/ThirdParty/SteamCMD/Linux"
+	fi
+	if [ ! -d "${steamcmddir}" ]; then
+		mkdir -p "${steamcmddir}"
+	fi
+	fn_fetch_file "http://media.steampowered.com/client/steamcmd_linux.tar.gz" "" "" "" "${tmpdir}" "steamcmd_linux.tar.gz" "nochmodx" "norun" "noforce" "nohash"
+	fn_dl_extract "${tmpdir}" "steamcmd_linux.tar.gz" "${steamcmddir}"
+	chmod +x "${steamcmddir}/steamcmd.sh"
+}
+
+fn_check_steamcmd_user() {
+	# Checks if steamuser is setup.
+	if [ "${steamuser}" == "username" ]; then
+		fn_print_fail_nl "Steam login not set. Update steamuser in ${configdirserver}"
+		echo -e "	* Change steamuser=\"username\" to a valid steam login."
+		if [ -d "${lgsmlogdir}" ]; then
+			fn_script_log_fatal "Steam login not set. Update steamuser in ${configdirserver}"
+		fi
+		core_exit.sh
+	fi
+	# Anonymous user is set if steamuser is missing.
+	if [ -z "${steamuser}" ]; then
+		if [ -d "${lgsmlogdir}" ]; then
+			fn_script_log_info "Using anonymous Steam login"
+		fi
+		steamuser="anonymous"
+		steampass=''
+	fi
+}
+
+fn_check_steamcmd() {
+	# Checks if SteamCMD exists when starting or updating a server.
+	# Only install if steamcmd package is missing or steamcmd dir is missing.
+	if [ ! -f "${steamcmddir}/steamcmd.sh" ] && [ -z "$(command -v steamcmd 2> /dev/null)" ]; then
+		if [ "${commandname}" == "INSTALL" ]; then
+			fn_install_steamcmd
+		else
+			fn_print_warn_nl "SteamCMD is missing"
+			fn_script_log_warn "SteamCMD is missing"
+			fn_install_steamcmd
+		fi
+	elif [ "${commandname}" == "INSTALL" ]; then
+		fn_print_information "SteamCMD is already installed..."
+		fn_print_ok_eol_nl
+	fi
+}
+
+fn_check_steamcmd_dir() {
+	# Worksround that pre-installs the correct steam directories to ensure all packages use the correct Standard.
+	# https://github.com/ValveSoftware/steam-for-linux/issues/6976#issuecomment-610446347
+
+	# Create Steam installation directory.
+	if [ ! -d "${XDG_DATA_HOME:="${HOME}/.local/share"}/Steam" ]; then
+		mkdir -p "${XDG_DATA_HOME:="${HOME}/.local/share"}/Steam"
+	fi
+
+	# Create common Steam directory.
+	if [ ! -d "${HOME}/.steam" ]; then
+		mkdir -p "${HOME}/.steam"
+	fi
+
+	# Symbolic links to Steam installation directory.
+	if [ ! -L "${HOME}/.steam/root" ]; then
+		if [ -d "${HOME}/.steam/root" ]; then
+			rm -f "${HOME:?}/.steam/root"
+		fi
+		ln -s "${XDG_DATA_HOME:="${HOME}/.local/share"}/Steam" "${HOME}/.steam/root"
+	fi
+
+	if [ ! -L "${HOME}/.steam/steam" ]; then
+		if [ -d "${HOME}/.steam/steam" ]; then
+			rm -rf "${HOME}/.steam/steam"
+		fi
+		ln -s "${XDG_DATA_HOME:="${HOME}/.local/share"}/Steam" "${HOME}/.steam/steam"
+	fi
+}
+
+fn_check_steamcmd_dir_legacy() {
+	# Remove old Steam installation directories ~/Steam and ${rootdir}/steamcmd
+	if [ -d "${rootdir}/steamcmd" ] && [ "${steamcmddir}" == "${XDG_DATA_HOME:="${HOME}/.local/share"}/Steam" ]; then
+		rm -rf "${rootdir:?}/steamcmd"
+	fi
+
+	if [ -d "${HOME}/Steam" ] && [ "${steamcmddir}" == "${XDG_DATA_HOME:="${HOME}/.local/share"}/Steam" ]; then
+		rm -rf "${HOME}/Steam"
+	fi
+}
+
+fn_check_steamcmd_steamapp() {
+	# Check that steamapp directory fixes issue #3481
+	if [ ! -d "${serverfiles}/steamapps" ]; then
+		mkdir -p "${serverfiles}/steamapps"
+	fi
+}
+
+fn_check_steamcmd_ark() {
+	# Checks if SteamCMD exists in
+	# Engine/Binaries/ThirdParty/SteamCMD/Linux
+	# to allow ark mods to work
+	if [ ! -f "${serverfiles}/Engine/Binaries/ThirdParty/SteamCMD/Linux/steamcmd.sh" ]; then
+		installsteamcmd=1
+		if [ "${commandname}" == "INSTALL" ]; then
+			fn_install_steamcmd
+		else
+			fn_print_warn_nl "ARK mods SteamCMD is missing"
+			fn_script_log_warn "ARK mods SteamCMD is missing"
+			fn_install_steamcmd
+		fi
+	elif [ "${commandname}" == "INSTALL" ]; then
+		fn_print_information "ARK mods SteamCMD is already installed..."
+		fn_print_ok_eol_nl
+	fi
+}
+
+fn_check_steamcmd_clear() {
+	# Will remove steamcmd dir if steamcmd package is installed.
+	if [ "$(command -v steamcmd 2> /dev/null)" ] && [ -d "${rootdir}/steamcmd" ]; then
+		rm -rf "${steamcmddir:?}"
+		exitcode=$?
+		if [ "${exitcode}" != 0 ]; then
+			fn_script_log_fatal "Removing ${rootdir}/steamcmd"
+		else
+			fn_script_log_pass "Removing ${rootdir}/steamcmd"
+		fi
+	fi
+}
+
+fn_check_steamcmd_exec() {
+	if [ "$(command -v steamcmd 2> /dev/null)" ]; then
+		steamcmdcommand="steamcmd"
+	else
+		steamcmdcommand="./steamcmd.sh"
+	fi
+}
+
+fn_update_steamcmd_localbuild() {
+	# Gets local build info.
+	fn_print_dots "Checking local build: ${remotelocation}"
+	fn_appmanifest_check
+	# Uses appmanifest to find local build.
+	localbuild=$(grep buildid "${appmanifestfile}" | tr '[:blank:]"' ' ' | tr -s ' ' | cut -d\  -f3)
+
+	# Set branch to public if no custom branch.
+	if [ -z "${branch}" ]; then
+		branch="public"
+	fi
+
+	# Checks if localbuild variable has been set.
+	if [ -z "${localbuild}" ]; then
+		fn_print_fail "Checking local build: ${remotelocation}: missing local build info"
+		fn_script_log_fatal "Missing local build info"
+		core_exit.sh
+	else
+		fn_print_ok "Checking local build: ${remotelocation}"
+		fn_script_log_pass "Checking local build"
+	fi
+}
+
+fn_update_steamcmd_remotebuild() {
+	# Get remote build info.
+	if [ -d "${steamcmddir}" ]; then
+		cd "${steamcmddir}" || exit
+	fi
+
+	# Removes appinfo.vdf as a fix for not always getting up to date version info from SteamCMD.
+	if [ "$(find "${HOME}" -type f -name "appinfo.vdf" | wc -l)" -ne "0" ]; then
+		find "${HOME}" -type f -name "appinfo.vdf" -exec rm -f {} \;
+	fi
+
+	# password for branch not needed to check the buildid
+	remotebuildversion=$(${steamcmdcommand} +login "${steamuser}" "${steampass}" +app_info_update 1 +app_info_print "${appid}" +quit | sed -e '/"branches"/,/^}/!d' | sed -n "/\"${branch}\"/,/}/p" | grep -m 1 buildid | tr -cd '[:digit:]')
+
+	if [ "${firstcommandname}" != "INSTALL" ]; then
+		fn_print_dots "Checking remote build: ${remotelocation}"
+		# Checks if remotebuildversion variable has been set.
+		if [ -z "${remotebuildversion}" ] || [ "${remotebuildversion}" == "null" ]; then
+			fn_print_fail "Checking remote build: ${remotelocation}"
+			fn_script_log_fatal "Checking remote build"
+			core_exit.sh
+		else
+			fn_print_ok "Checking remote build: ${remotelocation}"
+			fn_script_log_pass "Checking remote build"
+		fi
+	else
+		# Checks if remotebuild variable has been set.
+		if [ -z "${remotebuildversion}" ] || [ "${remotebuildversion}" == "null" ]; then
+			fn_print_failure "Unable to get remote build"
+			fn_script_log_fatal "Unable to get remote build"
+			core_exit.sh
+		fi
+	fi
+}
+
+fn_update_steamcmd_compare() {
+	fn_print_dots "Checking for update: ${remotelocation}"
+	if [ "${localbuild}" != "${remotebuildversion}" ] || [ "${forceupdate}" == "1" ]; then
+		fn_print_ok_nl "Checking for update: ${remotelocation}"
+		echo -en "\n"
+		echo -e "Update available"
+		echo -e "* Local build: ${red}${localbuild}${default}"
+		echo -e "* Remote build: ${green}${remotebuildversion}${default}"
+		if [ -n "${branch}" ]; then
+			echo -e "* Branch: ${branch}"
+		fi
+		if [ -n "${betapassword}" ]; then
+			echo -e "* Branch password: ${betapassword}"
+		fi
+		echo -e "https://steamdb.info/app/${appid}/"
+		echo -en "\n"
+		fn_script_log_info "Update available"
+		fn_script_log_info "Local build: ${localbuild}"
+		fn_script_log_info "Remote build: ${remotebuildversion}"
+		if [ -n "${branch}" ]; then
+			fn_script_log_info "Branch: ${branch}"
+		fi
+		if [ -n "${betapassword}" ]; then
+			fn_script_log_info "Branch password: ${betapassword}"
+		fi
+		fn_script_log_info "${localbuild} > ${remotebuildversion}"
+
+		if [ "${commandname}" == "UPDATE" ]; then
+			unset updateonstart
+			check_status.sh
+			# If server stopped.
+			if [ "${status}" == "0" ]; then
+				fn_dl_steamcmd
+			# If server started.
+			else
+				fn_print_restart_warning
+				exitbypass=1
+				command_stop.sh
+				fn_firstcommand_reset
+				exitbypass=1
+				fn_dl_steamcmd
+				exitbypass=1
+				command_start.sh
+				fn_firstcommand_reset
+			fi
+			unset exitbypass
+			date +%s > "${lockdir}/lastupdate.lock"
+			alert="update"
+		elif [ "${commandname}" == "CHECK-UPDATE" ]; then
+			alert="check-update"
+		fi
+		alert.sh
+	else
+		fn_print_ok_nl "Checking for update: ${remotelocation}"
+		echo -en "\n"
+		echo -e "No update available"
+		echo -e "* Local build: ${green}${localbuild}${default}"
+		echo -e "* Remote build: ${green}${remotebuildversion}${default}"
+		if [ -n "${branch}" ]; then
+			echo -e "* Branch: ${branch}"
+		fi
+		if [ -n "${betapassword}" ]; then
+			echo -e "* Branch password: ${betapassword}"
+		fi
+		echo -e "https://steamdb.info/app/${appid}/"
+		echo -en "\n"
+		fn_script_log_info "No update available"
+		fn_script_log_info "Local build: ${localbuild}"
+		fn_script_log_info "Remote build: ${remotebuildversion}"
+		if [ -n "${branch}" ]; then
+			fn_script_log_info "Branch: ${branch}"
+		fi
+		if [ -n "${betapassword}" ]; then
+			fn_script_log_info "Branch password: ${betapassword}"
+		fi
+	fi
+}
+
+fn_appmanifest_info() {
+	appmanifestfile=$(find -L "${serverfiles}" -type f -name "appmanifest_${appid}.acf")
+	appmanifestfilewc=$(find -L "${serverfiles}" -type f -name "appmanifest_${appid}.acf" | wc -l)
+}
+
+fn_appmanifest_check() {
+	fn_appmanifest_info
+	# Multiple or no matching appmanifest files may sometimes be present.
+	# This error is corrected if required.
+	if [ "${appmanifestfilewc}" -ge "2" ]; then
+		fn_print_error "Multiple appmanifest_${appid}.acf files found"
+		fn_script_log_error "Multiple appmanifest_${appid}.acf files found"
+		fn_print_dots "Removing x${appmanifestfilewc} appmanifest_${appid}.acf files"
+		for appfile in ${appmanifestfile}; do
+			rm -f "${appfile:?}"
+		done
+		appmanifestfilewc1="${appmanifestfilewc}"
+		fn_appmanifest_info
+		# if error can not be resolved.
+		if [ "${appmanifestfilewc}" -ge "2" ]; then
+			fn_print_fail "Unable to remove x${appmanifestfilewc} appmanifest_${appid}.acf files"
+			fn_script_log_fatal "Unable to remove x${appmanifestfilewc} appmanifest_${appid}.acf files"
+			echo -e "* Check user permissions"
+			for appfile in ${appmanifestfile}; do
+				echo -e "	${appfile}"
+			done
+			core_exit.sh
+		else
+			fn_print_ok "Removed x${appmanifestfilewc1} appmanifest_${appid}.acf files"
+			fn_script_log_pass "Removed x${appmanifestfilewc1} appmanifest_${appid}.acf files"
+			fn_print_info_nl "Forcing update to correct issue"
+			fn_script_log_info "Forcing update to correct issue"
+			fn_dl_steamcmd
+		fi
+	elif [ "${appmanifestfilewc}" -eq "0" ]; then
+		fn_print_error_nl "No appmanifest_${appid}.acf found"
+		fn_script_log_error "No appmanifest_${appid}.acf found"
+		fn_print_info_nl "Forcing update to correct issue"
+		fn_script_log_info "Forcing update to correct issue"
+		fn_dl_steamcmd
+		fn_appmanifest_info
+		if [ "${appmanifestfilewc}" -eq "0" ]; then
+			fn_print_fail_nl "Still no appmanifest_${appid}.acf found"
+			fn_script_log_fatal "Still no appmanifest_${appid}.acf found"
+			core_exit.sh
+		fi
+	fi
+}

+ 22 - 0
lgsm/modules/core_trap.sh

@@ -0,0 +1,22 @@
+#!/bin/bash
+# LinuxGSM core_trap.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Handles CTRL-C trap to give an exit code.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+fn_exit_trap() {
+	if [ -z "${exitcode}" ]; then
+		exitcode=$?
+	fi
+	echo -e ""
+	if [ -z "${exitcode}" ]; then
+		exitcode=0
+	fi
+	core_exit.sh
+}
+
+# trap to give an exit code.
+trap fn_exit_trap INT

+ 4 - 4
lgsm/functions/fix.sh → lgsm/modules/fix.sh

@@ -3,10 +3,10 @@
 # Author: Daniel Gibbs
 # Contributors: http://linuxgsm.com/contrib
 # Website: https://linuxgsm.com
-# Description: Overall function for managing fixes.
-# Runs functions that will fix an issue.
+# Description: Overall module for managing fixes.
+# Runs modules that will fix an issue.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 # Messages that are displayed for some fixes.
 fn_fix_msg_start() {
@@ -59,7 +59,7 @@ apply_post_install_fix=(av kf kf2 lo ro samp ut2k4 ut ut3)
 for fix in "${apply_pre_start_fix[@]}" "${apply_post_install_fix[@]}"; do
 	if ! fn_exists_fix "${fix}"; then
 		fn_print_fail_nl "fix_${fix}.sh is registered but doesn't exist. Typo or did you miss to modify core_functions.sh?"
-		exitcode 1
+		exitcode=1
 		core_exit.sh
 	fi
 done

+ 1 - 1
lgsm/functions/fix_ark.sh → lgsm/modules/fix_ark.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Resolves various issues with ARK: Survival Evolved.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 # removes mulitple appworkshop_346110.acf if found.
 steamappsfilewc="$(find "${HOME}" -name appworkshop_346110.acf | wc -l)"

+ 1 - 1
lgsm/functions/fix_arma3.sh → lgsm/modules/fix_arma3.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Resolves an issue with ARMA3.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 # Fixes: 20150 Segmentation fault (core dumped) error.
 if [ ! -d "${XDG_DATA_HOME:="${HOME}/.local/share"}/Arma 3" ] || [ ! -d "${XDG_DATA_HOME:="${HOME}/.local/share"}/Arma 3 - Other Profiles" ]; then

+ 1 - 1
lgsm/functions/fix_armar.sh → lgsm/modules/fix_armar.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Resolves an issue with Arma Reforger.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+module_selfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 # Fixes: Profile directory doesn't exist.
 # Issue Link: https://feedback.bistudio.com/T164845

+ 1 - 1
lgsm/functions/fix_av.sh → lgsm/modules/fix_av.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Resolves startup issue with Avorion
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${serverfiles}:${serverfiles}/linux64"
 

+ 1 - 1
lgsm/functions/fix_bo.sh → lgsm/modules/fix_bo.sh

@@ -5,6 +5,6 @@
 # Website: https://linuxgsm.com
 # Description: Resolves various issues with Ballistic Overkill.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${serverfiles}:${serverfiles}/BODS_Data/Plugins/x86_64"

+ 1 - 1
lgsm/functions/fix_bt.sh → lgsm/modules/fix_bt.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Resolves an issue with Barotrauma.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+module_selfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 # Fixes: Missing user data directory error.
 if [ ! -d "${XDG_DATA_HOME:="${HOME}/.local/share"}/Daedalic Entertainment GmbH/Barotrauma" ]; then

+ 1 - 1
lgsm/functions/fix_cmw.sh → lgsm/modules/fix_cmw.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Resolves the issue of the not starting server on linux
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 if [ ! -f "${executabledir}/steam_appid.txt" ]; then
 	fixname="steam_appid.txt"

+ 1 - 1
lgsm/functions/fix_csgo.sh → lgsm/modules/fix_csgo.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Resolves various issues with CS:GO.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 # Fixes: server not always creating steam_appid.txt file.
 if [ ! -f "${serverfiles}/steam_appid.txt" ]; then

+ 1 - 1
lgsm/functions/fix_dst.sh → lgsm/modules/fix_dst.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Resolves various issues with Don't Starve Together.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 # Fixes: ./dontstarve_dedicated_server_nullrenderer: ./lib32/libcurl-gnutls.so.4: no version information available (required by ./dontstarve_dedicated_server_nullrenderer).
 # Issue only occures on CentOS as libcurl-gnutls.so.4 is called libcurl.so.4 on CentOS.

+ 1 - 1
lgsm/functions/fix_hw.sh → lgsm/modules/fix_hw.sh

@@ -5,6 +5,6 @@
 # Website: https://linuxgsm.com
 # Description: Resolves various issues with Hurtworld.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${serverfiles}:${serverfiles}/Hurtworld_Data/Plugins/x86_64"

+ 1 - 1
lgsm/functions/fix_ins.sh → lgsm/modules/fix_ins.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Resolves various issues with Insurgency.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 # Fixes: ./srcds_linux: error while loading shared libraries: libtier0.so: cannot open shared object file: No such file or directory.
 

+ 1 - 1
lgsm/functions/fix_kf.sh → lgsm/modules/fix_kf.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Resolves various issues with Killing Floor.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 echo -e "Applying WebAdmin ROOst.css fix."
 echo -e "http://forums.tripwireinteractive.com/showpost.php?p=585435&postcount=13"

+ 1 - 1
lgsm/functions/fix_kf2.sh → lgsm/modules/fix_kf2.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Resolves various issues with Killing Floor 2.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 startparameters="\"${defaultmap}?Game=KFGameContent.KFGameInfo_VersusSurvival\""
 

+ 2 - 2
lgsm/functions/fix_lo.sh → lgsm/modules/fix_lo.sh

@@ -1,10 +1,10 @@
 #!/bin/bash
-# LinuxGSM fix_lo.sh function
+# LinuxGSM fix_lo.sh module
 # Author: Daniel Gibbs
 # Website: https://linuxgsm.com
 # Description: Resolves installation issue with Last Oasis
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 appidfile=${executabledir}/steam_appid.txt
 if [ ! -f "${appidfile}" ]; then

+ 1 - 1
lgsm/functions/fix_mcb.sh → lgsm/modules/fix_mcb.sh

@@ -5,7 +5,7 @@
 # Website: https://linuxgsm.com
 # Description: Resolves possible startup issue with Minecraft Bedrock.
 
-functionselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
 
 # official docs state that the server should be started with: LD_LIBRARY_PATH=. ./bedrock_server
 export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${serverfiles}"

Деякі файли не було показано, через те що забагато файлів було змінено