Przeglądaj źródła

Merge branch 'release/v23.3.0'

Daniel Gibbs 3 lat temu
rodzic
commit
ddd5e732f8
100 zmienionych plików z 5582 dodań i 110 usunięć
  1. 1 0
      .github/ISSUE_TEMPLATE/bug_report.yml
  2. 1 0
      .github/ISSUE_TEMPLATE/feature_request.yml
  3. 74 0
      .github/workflows/details-check.yml
  4. 25 0
      .github/workflows/detals-check-generate-matrix.sh
  5. 22 0
      .github/workflows/serverlist-validate.sh
  6. 13 0
      .github/workflows/serverlist-validate.yml
  7. 1 1
      .github/workflows/version-check.sh
  8. 1 12
      .github/workflows/version-check.yml
  9. 0 0
      .prettierrc
  10. 0 1
      .vscode/extensions.json
  11. 0 2
      lgsm/config-default/config-lgsm/acserver/_default.cfg
  12. 0 2
      lgsm/config-default/config-lgsm/avserver/_default.cfg
  13. 0 1
      lgsm/config-default/config-lgsm/boserver/_default.cfg
  14. 182 0
      lgsm/config-default/config-lgsm/ctserver/_default.cfg
  15. 0 4
      lgsm/config-default/config-lgsm/dayzserver/_default.cfg
  16. 199 0
      lgsm/config-default/config-lgsm/hcuserver/_default.cfg
  17. 1 2
      lgsm/config-default/config-lgsm/hwserver/_default.cfg
  18. 1 1
      lgsm/config-default/config-lgsm/inssserver/_default.cfg
  19. 1 1
      lgsm/config-default/config-lgsm/kf2server/_default.cfg
  20. 1 2
      lgsm/config-default/config-lgsm/momserver/_default.cfg
  21. 3 2
      lgsm/config-default/config-lgsm/necserver/_default.cfg
  22. 4 4
      lgsm/config-default/config-lgsm/ns2cserver/_default.cfg
  23. 4 4
      lgsm/config-default/config-lgsm/ns2server/_default.cfg
  24. 191 0
      lgsm/config-default/config-lgsm/ohdserver/_default.cfg
  25. 1 1
      lgsm/config-default/config-lgsm/pc2server/_default.cfg
  26. 1 1
      lgsm/config-default/config-lgsm/pcserver/_default.cfg
  27. 3 3
      lgsm/config-default/config-lgsm/pstbsserver/_default.cfg
  28. 2 1
      lgsm/config-default/config-lgsm/pzserver/_default.cfg
  29. 2 2
      lgsm/config-default/config-lgsm/rustserver/_default.cfg
  30. 0 2
      lgsm/config-default/config-lgsm/sbotsserver/_default.cfg
  31. 5 5
      lgsm/config-default/config-lgsm/stserver/_default.cfg
  32. 4 1
      lgsm/config-default/config-lgsm/tiserver/_default.cfg
  33. 2 2
      lgsm/config-default/config-lgsm/vhserver/_default.cfg
  34. 6 2
      lgsm/data/almalinux-8.csv
  35. 7 3
      lgsm/data/almalinux-9.csv
  36. 6 2
      lgsm/data/centos-7.csv
  37. 6 2
      lgsm/data/centos-8.csv
  38. 7 3
      lgsm/data/centos-9.csv
  39. 7 3
      lgsm/data/debian-10.csv
  40. 7 3
      lgsm/data/debian-11.csv
  41. 135 0
      lgsm/data/debian-12.csv
  42. 7 3
      lgsm/data/debian-9.csv
  43. 6 2
      lgsm/data/rhel-7.csv
  44. 6 2
      lgsm/data/rhel-8.csv
  45. 7 3
      lgsm/data/rhel-9.csv
  46. 6 2
      lgsm/data/rocky-8.csv
  47. 7 3
      lgsm/data/rocky-9.csv
  48. 4 2
      lgsm/data/serverlist.csv
  49. 6 2
      lgsm/data/ubuntu-16.04.csv
  50. 7 3
      lgsm/data/ubuntu-18.04.csv
  51. 7 3
      lgsm/data/ubuntu-20.04.csv
  52. 7 3
      lgsm/data/ubuntu-21.04.csv
  53. 10 4
      lgsm/data/ubuntu-21.10.csv
  54. 7 3
      lgsm/data/ubuntu-22.04.csv
  55. 135 0
      lgsm/data/ubuntu-23.04.csv
  56. 816 0
      lgsm/functions/README.md
  57. 2 0
      lgsm/functions/core_steamcmd.sh
  58. 17 0
      lgsm/functions/info_stats.sh
  59. 238 0
      lgsm/modules/alert.sh
  60. 59 0
      lgsm/modules/alert_discord.sh
  61. 25 0
      lgsm/modules/alert_email.sh
  62. 30 0
      lgsm/modules/alert_gotify.sh
  63. 29 0
      lgsm/modules/alert_ifttt.sh
  64. 32 0
      lgsm/modules/alert_mailgun.sh
  65. 30 0
      lgsm/modules/alert_pushbullet.sh
  66. 33 0
      lgsm/modules/alert_pushover.sh
  67. 50 0
      lgsm/modules/alert_rocketchat.sh
  68. 75 0
      lgsm/modules/alert_slack.sh
  69. 30 0
      lgsm/modules/alert_telegram.sh
  70. 101 0
      lgsm/modules/check.sh
  71. 35 0
      lgsm/modules/check_config.sh
  72. 363 0
      lgsm/modules/check_deps.sh
  73. 20 0
      lgsm/modules/check_executable.sh
  74. 29 0
      lgsm/modules/check_glibc.sh
  75. 63 0
      lgsm/modules/check_ip.sh
  76. 26 0
      lgsm/modules/check_last_update.sh
  77. 26 0
      lgsm/modules/check_logs.sh
  78. 233 0
      lgsm/modules/check_permissions.sh
  79. 21 0
      lgsm/modules/check_root.sh
  80. 10 0
      lgsm/modules/check_status.sh
  81. 22 0
      lgsm/modules/check_steamcmd.sh
  82. 22 0
      lgsm/modules/check_system_dir.sh
  83. 55 0
      lgsm/modules/check_system_requirements.sh
  84. 33 0
      lgsm/modules/check_tmuxception.sh
  85. 23 0
      lgsm/modules/check_version.sh
  86. 268 0
      lgsm/modules/command_backup.sh
  87. 39 0
      lgsm/modules/command_check_update.sh
  88. 58 0
      lgsm/modules/command_console.sh
  89. 142 0
      lgsm/modules/command_debug.sh
  90. 42 0
      lgsm/modules/command_details.sh
  91. 24 0
      lgsm/modules/command_dev_clear_modules.sh
  92. 23 0
      lgsm/modules/command_dev_debug.sh
  93. 94 0
      lgsm/modules/command_dev_details.sh
  94. 231 0
      lgsm/modules/command_dev_detect_deps.sh
  95. 92 0
      lgsm/modules/command_dev_detect_glibc.sh
  96. 61 0
      lgsm/modules/command_dev_detect_ldd.sh
  97. 286 0
      lgsm/modules/command_dev_query_raw.sh
  98. 442 0
      lgsm/modules/command_fastdl.sh
  99. 52 0
      lgsm/modules/command_install.sh
  100. 32 0
      lgsm/modules/command_install_resources_mta.sh

+ 1 - 0
.github/ISSUE_TEMPLATE/bug_report.yml

@@ -34,6 +34,7 @@ body:
         - Ubuntu 20.04
         - Ubuntu 18.04
         - Ubuntu 16.04
+        - Debian 12
         - Debian 11
         - Debian 10
         - Debian 9

+ 1 - 0
.github/ISSUE_TEMPLATE/feature_request.yml

@@ -34,6 +34,7 @@ body:
         - Ubuntu 20.04
         - Ubuntu 18.04
         - Ubuntu 16.04
+        - Debian 12
         - Debian 11
         - Debian 10
         - Debian 9

+ 74 - 0
.github/workflows/details-check.yml

@@ -0,0 +1,74 @@
+name: Details Check
+# This action will check that LinuxGSM is picking up game server config and parameter variables.
+on:
+  workflow_dispatch:
+  push:
+
+jobs:
+  create-matrix:
+    runs-on: ubuntu-latest
+    outputs:
+      matrix: ${{ steps.set-matrix.outputs.matrix }}
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v3
+
+      - name: Generate matrix with generate-matrix.sh
+        run: chmod +x .github/workflows/detals-check-generate-matrix.sh; .github/workflows/detals-check-generate-matrix.sh
+
+      - id: set-matrix
+        run: |
+          shortnamearray=$(cat shortnamearray.json)
+          echo "${shortnamearray}"
+          echo -n "matrix=${shortnamearray}" >> $GITHUB_OUTPUT
+
+  details-check:
+    needs: create-matrix
+    continue-on-error: true
+    runs-on: ubuntu-latest
+
+    strategy:
+      matrix: ${{ fromJSON(needs.create-matrix.outputs.matrix) }}
+
+    steps:
+      - name: Install dependencies
+        run: sudo apt-get install libxml2-utils jq
+
+      - name: Download linuxgsm.sh
+        run: wget https://raw.githubusercontent.com/GameServerManagers/LinuxGSM/${GITHUB_REF#refs/heads/}/linuxgsm.sh; chmod +x linuxgsm.sh
+
+      - name: Grab server
+        run: LGSM_GITHUBBRANCH="${GITHUB_REF#refs/heads/}" ./linuxgsm.sh ${{ matrix.shortname }}server
+
+      - name: Enable developer mode
+        run: LGSM_GITHUBBRANCH="${GITHUB_REF#refs/heads/}" ./${{ matrix.shortname }}server developer
+
+      - id: sets-servercfgname
+        name: Generate servercfgname
+        run: |
+          servercfg=$(sed -n "/^\<servercfgdefault\>/ { s/.*= *\"\?\([^\"']*\)\"\?/\1/p;q }" lgsm/config-lgsm/${{ matrix.shortname }}server/_default.cfg)
+          echo "servercfgname=$servercfg" >> "$GITHUB_OUTPUT"
+
+      - name: Download config
+        run: |
+          if [ -z "${{ steps.sets-servercfgname.outputs.servercfgname }}" ]; then
+            echo "This game server has no config file."
+          else
+            curl -f -o config "https://raw.githubusercontent.com/GameServerManagers/Game-Server-Configs/rename/${{ matrix.shortname }}/${{ steps.sets-servercfgname.outputs.servercfgname }}"
+          fi
+      - name: Display config
+        run: |
+          if [ -z "${{ steps.sets-servercfgname.outputs.servercfgname }}" ]; then
+            echo "This game server has no config file."
+          else
+            cat config
+          fi
+
+      - name: Display parameters
+        run: grep "startparameters" lgsm/config-default/config-lgsm/${{ matrix.shortname }}server/_default.cfg
+
+      - name: Detect details
+        run: LGSM_GITHUBBRANCH="${GITHUB_REF#refs/heads/}" ./${{ matrix.shortname }}server detect-details
+
+      - name: Query Raw
+        run: LGSM_GITHUBBRANCH="${GITHUB_REF#refs/heads/}" ./${{ matrix.shortname }}server query-raw

+ 25 - 0
.github/workflows/detals-check-generate-matrix.sh

@@ -0,0 +1,25 @@
+#!/bin/bash
+
+curl "https://raw.githubusercontent.com/GameServerManagers/LinuxGSM/master/lgsm/data/serverlist.csv" | grep -v '^[[:blank:]]*$' > serverlist.csv
+
+echo -n "{" > "shortnamearray.json"
+echo -n "\"include\":[" >> "shortnamearray.json"
+
+while read -r line; do
+	shortname=$(echo "$line" | awk -F, '{ print $1 }')
+	export shortname
+	servername=$(echo "$line" | awk -F, '{ print $2 }')
+	export servername
+	gamename=$(echo "$line" | awk -F, '{ print $3 }')
+	export gamename
+	distro=$(echo "$line" | awk -F, '{ print $4 }')
+	export distro
+	echo -n "{" >> "shortnamearray.json"
+	echo -n "\"shortname\":" >> "shortnamearray.json"
+	echo -n "\"${shortname}\"" >> "shortnamearray.json"
+	echo -n "}," >> "shortnamearray.json"
+done < serverlist.csv
+sed -i '$ s/.$//' "shortnamearray.json"
+echo -n "]" >> "shortnamearray.json"
+echo -n "}" >> "shortnamearray.json"
+rm serverlist.csv

+ 22 - 0
.github/workflows/serverlist-validate.sh

@@ -0,0 +1,22 @@
+#!/bin/bash
+echo "Checking that all the game servers are listed in all csv files"
+echo "this check will ensure serverlist.csv has the same number of lines (-2 lines) as the other csv files"
+# count the number of lines in the serverlist.csv
+cd "lgsm/data" || exit
+serverlistcount="$(wc -l < serverlist.csv)"
+echo "serverlistcount: $serverlistcount"
+# get list of all csv files starting with ubunutu debian centos
+csvlist="$(ls -1 | grep -E '^(ubuntu|debian|centos|rhel|almalinux|rocky).*\.csv$')"
+# loop though each csv file and make sure the number of lines is the same as the serverlistcount
+for csv in $csvlist; do
+	csvcount="$(wc -l < "${csv}")"
+	csvcount=$((csvcount-2))
+	if [ "$csvcount" -ne "$serverlistcount" ]; then
+		echo "ERROR: $csv ($csvcount) does not match serverlist.csv ($serverlistcount)"
+		exitcode=1
+	else
+		echo "OK: $csv ($csvcount) and serverlist.csv ($serverlistcount) match"
+	fi
+done
+
+exit ${exitcode}

+ 13 - 0
.github/workflows/serverlist-validate.yml

@@ -0,0 +1,13 @@
+name: Server list Validation
+on:
+  workflow_dispatch:
+  push:
+
+jobs:
+  serverlist-validate:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
+
+      - name: compare versions
+        run: chmod +x .github/workflows/serverlist-validate.sh; .github/workflows/serverlist-validate.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"

+ 1 - 12
.github/workflows/version-check.yml

@@ -1,26 +1,15 @@
-# This is a basic workflow to help you get started with Actions
-
 name: Version Check
 
-# Controls when the action will run. Triggers the workflow on push or pull request
-# events but only for the master branch
 on: push
 
-# A workflow run is made up of one or more jobs that can run sequentially or in parallel
 permissions:
   contents: read
 
 jobs:
-  # This workflow contains a single job called "build"
-  Version-Check:
-    # The type of runner that the job will run on
+  version-Check:
     runs-on: ubuntu-latest
-
-    # Steps represent a sequence of tasks that will be executed as part of the job
     steps:
-      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
       - uses: actions/checkout@v3
 
-      # Runs a single command using the runners shell
       - name: compare versions
         run: chmod +x .github/workflows/version-check.sh; .github/workflows/version-check.sh

+ 0 - 0
.prettierrc.json → .prettierrc


+ 0 - 1
.vscode/extensions.json

@@ -5,7 +5,6 @@
     "yzhang.markdown-all-in-one",
     "esbenp.prettier-vscode",
     "timonwong.shellcheck",
-    "foxundermoon.shell-format",
     "redhat.vscode-yaml"
   ]
 }

+ 0 - 2
lgsm/config-default/config-lgsm/acserver/_default.cfg

@@ -12,8 +12,6 @@
 steamuser="username"
 steampass='password'
 
-## Predefined Parameters | https://docs.linuxgsm.com/configuration/start-parameters
-
 ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters
 startparameters="-c ${servercfgfullpath}"
 

+ 0 - 2
lgsm/config-default/config-lgsm/avserver/_default.cfg

@@ -8,8 +8,6 @@
 
 #### Game Server Settings ####
 
-## Predefined Parameters | https://docs.linuxgsm.com/configuration/start-parameters
-
 ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters
 startparameters="--galaxy-name ${selfname} --ip ${ip} --datapath ${avdatapath}"
 

+ 0 - 1
lgsm/config-default/config-lgsm/boserver/_default.cfg

@@ -12,7 +12,6 @@
 # GSLT can be used for running a public server.
 # More info: https://docs.linuxgsm.com/steamcmd/gslt
 gslt=""
-ip=""
 
 ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters
 startparameters="-batchmode -nographics -dedicated -configfile=${servercfgfullpath}"

+ 182 - 0
lgsm/config-default/config-lgsm/ctserver/_default.cfg

@@ -0,0 +1,182 @@
+##################################
+######## Default Settings ########
+##################################
+# DO NOT EDIT, ANY CHANGES WILL BE OVERWRITTEN!
+# Copy settings from here and use them in either:
+# common.cfg - applies settings to every instance.
+# [instance].cfg - applies settings to a specific instance.
+
+#### Game Server Settings ####
+
+## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters
+startparameters="-batchmode -showlogs"
+
+#### LinuxGSM Settings ####
+
+## LinuxGSM Stats
+# Send useful stats to LinuxGSM developers.
+# https://docs.linuxgsm.com/configuration/linuxgsm-stats
+# (on|off)
+stats="off"
+
+## Notification Alerts
+# (on|off)
+
+# Display IP | https://docs.linuxgsm.com/alerts#display-ip
+displayip=""
+
+# More info | https://docs.linuxgsm.com/alerts#more-info
+postalert="off"
+
+# Discord Alerts | https://docs.linuxgsm.com/alerts/discord
+discordalert="off"
+discordwebhook="webhook"
+
+# Email Alerts | https://docs.linuxgsm.com/alerts/email
+emailalert="off"
+email="email@example.com"
+emailfrom=""
+
+# Gotify Alerts | https://docs.linuxgsm.com/alerts/gotify
+gotifyalert="off"
+gotifytoken="token"
+gotifywebhook="webhook"
+
+# IFTTT Alerts | https://docs.linuxgsm.com/alerts/ifttt
+iftttalert="off"
+ifttttoken="accesstoken"
+iftttevent="linuxgsm_alert"
+
+# Mailgun Email Alerts | https://docs.linuxgsm.com/alerts/mailgun
+mailgunalert="off"
+mailgunapiregion="us"
+mailguntoken="accesstoken"
+mailgundomain="example.com"
+mailgunemailfrom="alert@example.com"
+mailgunemail="email@myemail.com"
+
+# Pushbullet Alerts | https://docs.linuxgsm.com/alerts/pushbullet
+pushbulletalert="off"
+pushbullettoken="accesstoken"
+channeltag=""
+
+# Pushover Alerts | https://docs.linuxgsm.com/alerts/pushover
+pushoveralert="off"
+pushovertoken="accesstoken"
+pushoveruserkey="userkey"
+
+# Rocket.Chat Alerts | https://docs.linuxgsm.com/alerts/rocket.chat
+rocketchatalert="off"
+rocketchatwebhook="webhook"
+rocketchattoken=""
+
+# Slack Alerts | https://docs.linuxgsm.com/alerts/slack
+slackalert="off"
+slackwebhook="webhook"
+
+# Telegram Alerts | https://docs.linuxgsm.com/alerts/telegram
+# You can add a custom cURL string eg proxy (useful in Russia) in "curlcustomstring".
+# For example "--socks5 ipaddr:port" for socks5 proxy see more in "curl --help".
+telegramapi="api.telegram.org"
+telegramalert="off"
+telegramtoken="accesstoken"
+telegramchatid=""
+curlcustomstring=""
+
+## Updating | https://docs.linuxgsm.com/commands/update
+updateonstart="off"
+
+## Backup | https://docs.linuxgsm.com/commands/backup
+maxbackups="4"
+maxbackupdays="30"
+stoponbackup="on"
+
+## Logging | https://docs.linuxgsm.com/features/logging
+consolelogging="on"
+logdays="7"
+
+## Monitor | https://docs.linuxgsm.com/commands/monitor
+# Query delay time
+querydelay="1"
+
+## ANSI Colors | https://docs.linuxgsm.com/features/ansi-colors
+ansi="on"
+
+#### Advanced Settings ####
+
+## Message Display Time | https://docs.linuxgsm.com/features/message-display-time
+sleeptime="0.5"
+
+## SteamCMD Settings | https://docs.linuxgsm.com/steamcmd
+# Server appid
+appid="1670340"
+steamcmdforcewindows="no"
+# SteamCMD Branch | https://docs.linuxgsm.com/steamcmd/branch
+branch=""
+betapassword=""
+# Master Server | https://docs.linuxgsm.com/steamcmd/steam-master-server
+steammaster="false"
+
+## Stop Mode | https://docs.linuxgsm.com/features/stop-mode
+# 1: tmux kill
+# 2: CTRL+c
+# 3: quit
+# 4: quit 120s
+# 5: stop
+# 6: q
+# 7: exit
+# 8: 7 Days to Die
+# 9: GoldSrc
+# 10: Avorion
+# 11: end
+stopmode="5"
+
+## Query mode
+# 1: session only
+# 2: gamedig (gsquery fallback)
+# 3: gamedig
+# 4: gsquery
+# 5: tcp
+querymode="1"
+querytype=""
+
+## Console type
+consoleverbose="no"
+consoleinteract="yes"
+
+## Game Server Details
+# Do not edit
+gamename="Craftopia"
+engine="unity3d"
+glibc="2.17"
+
+#### Directories ####
+# Edit with care
+
+## Game Server Directories
+systemdir="${serverfiles}"
+executabledir="${serverfiles}"
+executable="./Craftopia.x86_64"
+servercfgdir="${systemdir}"
+servercfg="ServerSetting.ini"
+servercfgdefault="ServerSetting.ini"
+servercfgfullpath="${servercfgdir}/${servercfg}"
+
+## Backup Directory
+backupdir="${lgsmdir}/backup"
+
+## Logging Directories
+logdir="${rootdir}/log"
+#gamelogdir="${serverfiles}"
+lgsmlogdir="${logdir}/script"
+consolelogdir="${logdir}/console"
+gamelog="${gamelogdir}/${selfname}-game.log"
+lgsmlog="${lgsmlogdir}/${selfname}-script.log"
+consolelog="${consolelogdir}/${selfname}-console.log"
+alertlog="${lgsmlogdir}/${selfname}-alert.log"
+postdetailslog="${lgsmlogdir}/${selfname}-postdetails.log"
+
+## Logs Naming
+gamelogdate="${gamelogdir}/${selfname}-game-$(date '+%Y-%m-%d-%H:%M:%S').log"
+lgsmlogdate="${lgsmlogdir}/${selfname}-script-$(date '+%Y-%m-%d-%H:%M:%S').log"
+consolelogdate="${consolelogdir}/${selfname}-console-$(date '+%Y-%m-%d-%H:%M:%S').log"

+ 0 - 4
lgsm/config-default/config-lgsm/dayzserver/_default.cfg

@@ -8,10 +8,6 @@
 
 #### Game Server Settings ####
 
-## SteamCMD Login | https://docs.linuxgsm.com/steamcmd#steamcmd-login
-# steamuser="username"
-# steampass='password'
-
 ## Predefined Parameters | https://docs.linuxgsm.com/configuration/start-parameters
 ip="0.0.0.0"
 port="2302"

+ 199 - 0
lgsm/config-default/config-lgsm/hcuserver/_default.cfg

@@ -0,0 +1,199 @@
+##################################
+######## Default Settings ########
+##################################
+# DO NOT EDIT, ANY CHANGES WILL BE OVERWRITTEN!
+# Copy settings from here and use them in either:
+# common.cfg - applies settings to every instance.
+# [instance].cfg - applies settings to a specific instance.
+
+#### Game Server Settings ####
+
+## Predefined Parameters | https://docs.linuxgsm.com/configuration/start-parameters
+defaultmap="KidsBedroom"
+ip="0.0.0.0"
+maxplayers="8"
+port="7777"
+queryport="27015"
+servername="LinuxGSM"
+
+## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters
+startparameters="${defaultmap}?Difficulty=1?Game=DM?MapList=KidsBedroom,Playground,Garden,Hallway_Simple,Bathroom,Hallway_Hard,Attic_Daytime,Shed,ToyPalace,Kitchen,Garage?MaxPlayers=${maxplayers}?WeaponTypes=7?TimeLimit=600?ScoreLimit=30?Teamplay -ServerName='${servername}' -Port=${port} -QueryPort=${queryport} -NOCONSOLE -unattended"
+
+## Server Parameters for Plague mode
+#startparameters="${defaultmap}?Game=PL?MapList=KidsBedroom,Garden,Hallway_Simple,Attic_Daytime,Garage,Shed,Kitchen,Hallway_Hard,ToyPalace,Bathroom?MaxPlayers=${maxplayers}?WeaponTypes=7?TimeLimit=600 -ServerName='${servername}' -Port=${port} -QueryPort=${queryport} -NOCONSOLE -unattended"
+
+## Server Parameters for Co-op mode
+#startparameters="${defaultmap}?Difficulty=1?Game=WV?MapList=KidsBedroom?MaxPlayers=4 -ServerName='${servername}' -Port=${port} -QueryPort=${queryport} -NOCONSOLE -unattended"
+
+
+#### LinuxGSM Settings ####
+
+## LinuxGSM Stats
+# Send useful stats to LinuxGSM developers.
+# https://docs.linuxgsm.com/configuration/linuxgsm-stats
+# (on|off)
+stats="off"
+
+## Notification Alerts
+# (on|off)
+
+# Display IP | https://docs.linuxgsm.com/alerts#display-ip
+displayip=""
+
+# More info | https://docs.linuxgsm.com/alerts#more-info
+postalert="off"
+
+# Discord Alerts | https://docs.linuxgsm.com/alerts/discord
+discordalert="off"
+discordwebhook="webhook"
+
+# Email Alerts | https://docs.linuxgsm.com/alerts/email
+emailalert="off"
+email="email@example.com"
+emailfrom=""
+
+# Gotify Alerts | https://docs.linuxgsm.com/alerts/gotify
+gotifyalert="off"
+gotifytoken="token"
+gotifywebhook="webhook"
+
+# IFTTT Alerts | https://docs.linuxgsm.com/alerts/ifttt
+iftttalert="off"
+ifttttoken="accesstoken"
+iftttevent="linuxgsm_alert"
+
+# Mailgun Email Alerts | https://docs.linuxgsm.com/alerts/mailgun
+mailgunalert="off"
+mailgunapiregion="us"
+mailguntoken="accesstoken"
+mailgundomain="example.com"
+mailgunemailfrom="alert@example.com"
+mailgunemail="email@myemail.com"
+
+# Pushbullet Alerts | https://docs.linuxgsm.com/alerts/pushbullet
+pushbulletalert="off"
+pushbullettoken="accesstoken"
+channeltag=""
+
+# Pushover Alerts | https://docs.linuxgsm.com/alerts/pushover
+pushoveralert="off"
+pushovertoken="accesstoken"
+pushoveruserkey="userkey"
+
+# Rocket.Chat Alerts | https://docs.linuxgsm.com/alerts/rocket.chat
+rocketchatalert="off"
+rocketchatwebhook="webhook"
+rocketchattoken=""
+
+# Slack Alerts | https://docs.linuxgsm.com/alerts/slack
+slackalert="off"
+slackwebhook="webhook"
+
+# Telegram Alerts | https://docs.linuxgsm.com/alerts/telegram
+# You can add a custom cURL string eg proxy (useful in Russia) in "curlcustomstring".
+# For example "--socks5 ipaddr:port" for socks5 proxy see more in "curl --help".
+telegramapi="api.telegram.org"
+telegramalert="off"
+telegramtoken="accesstoken"
+telegramchatid=""
+curlcustomstring=""
+
+## Updating | https://docs.linuxgsm.com/commands/update
+updateonstart="off"
+
+## Backup | https://docs.linuxgsm.com/commands/backup
+maxbackups="4"
+maxbackupdays="30"
+stoponbackup="on"
+
+## Logging | https://docs.linuxgsm.com/features/logging
+consolelogging="on"
+logdays="7"
+
+## Monitor | https://docs.linuxgsm.com/commands/monitor
+# Query delay time
+querydelay="5"
+
+## ANSI Colors | https://docs.linuxgsm.com/features/ansi-colors
+ansi="on"
+
+#### Advanced Settings ####
+
+## Message Display Time | https://docs.linuxgsm.com/features/message-display-time
+sleeptime="0.5"
+
+## SteamCMD Settings | https://docs.linuxgsm.com/steamcmd
+# Server appid
+appid="1045940"
+steamcmdforcewindows="no"
+# SteamCMD Branch | https://docs.linuxgsm.com/steamcmd/branch
+branch=""
+betapassword=""
+# Master Server | https://docs.linuxgsm.com/steamcmd/steam-master-server
+steammaster="false"
+
+## Stop Mode | https://docs.linuxgsm.com/features/stop-mode
+# 1: tmux kill
+# 2: CTRL+c
+# 3: quit
+# 4: quit 120s
+# 5: stop
+# 6: q
+# 7: exit
+# 8: 7 Days to Die
+# 9: GoldSrc
+# 10: Avorion
+# 11: end
+stopmode="2"
+
+## Query mode
+# 1: session only
+# 2: gamedig (gsquery fallback)
+# 3: gamedig
+# 4: gsquery
+# 5: tcp
+querymode="1"
+querytype=""
+
+## Console type
+consoleverbose="no"
+consoleinteract="no"
+
+## Game Server Details
+# Do not edit
+gamename="HYPERCHARGE: Unboxed"
+engine="unreal4"
+glibc="2.17"
+
+#### Directories ####
+# Edit with care
+
+## Game Server Directories
+systemdir="${serverfiles}/Unboxed"
+executabledir="${systemdir}/Binaries/Linux"
+executable="./UnboxedServer-Linux-Shipping"
+servercfgdir="${systemdir}/Saved/Config/LinuxServer"
+servercfg="GameUserSettings.ini"
+servercfgdefault="GameUserSettings.ini"
+servercfgfullpath="${servercfgdir}/${servercfg}"
+
+## Backup Directory
+backupdir="${lgsmdir}/backup"
+
+## Logging Directories
+logdir="${rootdir}/log"
+gamelogdir="${systemdir}/Saved/Logs"
+lgsmlogdir="${logdir}/script"
+consolelogdir="${logdir}/console"
+lgsmlog="${lgsmlogdir}/${selfname}-script.log"
+consolelog="${consolelogdir}/${selfname}-console.log"
+alertlog="${lgsmlogdir}/${selfname}-alert.log"
+postdetailslog="${lgsmlogdir}/${selfname}-postdetails.log"
+
+## Logs Naming
+lgsmlogdate="${lgsmlogdir}/${selfname}-script-$(date '+%Y-%m-%d-%H:%M:%S').log"
+consolelogdate="${consolelogdir}/${selfname}-console-$(date '+%Y-%m-%d-%H:%M:%S').log"
+
+## Log Parameters
+logtimestamp="off"
+logtimestampformat="%Y-%m-%d %H:%M:%S"

+ 1 - 2
lgsm/config-default/config-lgsm/hwserver/_default.cfg

@@ -16,7 +16,6 @@ queryport="12881"
 maxplayers="20"
 defaultmap=""    # Optional
 creativemode="0" # Free Build: creativemode="1"
-gamelog="gamelog.txt"
 
 ## Add admins using STEAMID64
 # Example : addadmin 012345678901234567; addadmin 987654321098765432
@@ -28,7 +27,7 @@ loadsave=""
 
 ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters
 # Edit with care | http://hurtworld.wikia.com/wiki/Hosting_A_Server
-startparameters="-batchmode -nographics -exec \"host ${port} ${defaultmap} ${loadsave};queryport ${queryport};maxplayers ${maxplayers};servername ${servername};creativemode ${creativemode};${admins}\""
+startparameters="-batchmode -nographics -logfile ${gamelog} -exec \"host ${port} ${defaultmap} ${loadsave};queryport ${queryport};maxplayers ${maxplayers};servername ${servername};creativemode ${creativemode};${admins}\""
 
 #### LinuxGSM Settings ####
 

+ 1 - 1
lgsm/config-default/config-lgsm/inssserver/_default.cfg

@@ -20,7 +20,7 @@ defaultscenario="Scenario_Crossing_Push_Security"
 maxplayers="28"
 
 ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters
-## Parameter Docs | https://sandstorm-support.newworldinteractive.com/hc/en-us/articles/360049211072-Server-Admin-Guide
+## Parameter Docs | https://mod.io/g/insurgencysandstorm/r/server-admin-guide
 startparameters="${defaultmap}?Scenario=${defaultscenario}?MaxPlayers=${maxplayers} -Port=${port} -QueryPort=${queryport} -hostname='${servername}' -Rcon -RconPassword=${rconpassword} -RconListenPort=${rconport} -log"
 
 #### LinuxGSM Settings ####

+ 1 - 1
lgsm/config-default/config-lgsm/kf2server/_default.cfg

@@ -121,7 +121,7 @@ steamcmdforcewindows="no"
 branch=""
 betapassword=""
 # Master Server | https://docs.linuxgsm.com/steamcmd/steam-master-server
-steammaster="false"
+steammaster="true"
 
 ## Stop Mode | https://docs.linuxgsm.com/features/stop-mode
 # 1: tmux kill

+ 1 - 2
lgsm/config-default/config-lgsm/momserver/_default.cfg

@@ -12,10 +12,9 @@
 ip="0.0.0.0"
 port="7777"
 beaconport="15000"
-maxplayers="32"
 
 ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters
-startparameters="-port="${port}" -beaconport="${beaconport}" -MULTIHOME="${ip}" -maxplayers=${maxplayers}"
+startparameters="-port="${port}" -beaconport="${beaconport}" -MULTIHOME="${ip}""
 
 #### LinuxGSM Settings ####
 

+ 3 - 2
lgsm/config-default/config-lgsm/necserver/_default.cfg

@@ -7,6 +7,7 @@
 # [instance].cfg - applies settings to a specific instance.
 
 #### Game Server Settings ####
+
 ## Pre-defined Paramters | https://docs.linuxgsm.com/configuration/start-parameters#predefined-parameters
 worldname="MyWorld"
 
@@ -139,8 +140,8 @@ stopmode="2"
 # 3: gamedig
 # 4: gsquery
 # 5: tcp
-querymode="2"
-querytype="protocol-valve"
+querymode="1"
+querytype=""
 
 ## Console type
 consoleverbose="yes"

+ 4 - 4
lgsm/config-default/config-lgsm/ns2cserver/_default.cfg

@@ -14,9 +14,9 @@ port="27015"
 defaultmap="co_core"
 maxplayers="24"
 servername="LinuxGSM Server"
-webadminuser="admin"
-webadminpass="admin"
-webadminport="8080"
+httpuser="admin"
+httppassword="admin"
+httpport="8080"
 mods=""
 serverpassword=""
 # Add the following line to the parms if you want a private server. Ensuring
@@ -24,7 +24,7 @@ serverpassword=""
 # -password \"${serverpassword}\"
 
 ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters
-startparameters="-name \"${servername}\" -port ${port} -webadmin -webdomain ${ip} -webuser ${webadminuser} -webpassword \"${webadminpass}\" -webport ${webadminport} -map ${defaultmap} -limit ${maxplayers} -config_path \"${servercfgdir}\" -modstorage \"${modstoragedir}\" -mods \"${mods}\""
+startparameters="-name \"${servername}\" -port ${port} -webadmin -webdomain ${ip} -webuser ${httpuser} -webpassword \"${httppassword}\" -webport ${httpport} -map ${defaultmap} -limit ${maxplayers} -config_path \"${servercfgdir}\" -modstorage \"${modstoragedir}\" -mods \"${mods}\""
 
 #### LinuxGSM Settings ####
 

+ 4 - 4
lgsm/config-default/config-lgsm/ns2server/_default.cfg

@@ -14,9 +14,9 @@ port="27015"
 defaultmap="ns2_summit"
 maxplayers="24"
 servername="LinuxGSM Server"
-webadminuser="admin"
-webadminpass="admin"
-webadminport="8080"
+httpuser="admin"
+httppassword="admin"
+httpport="8080"
 mods=""
 serverpassword=""
 # Add the following line to the parms if you want a private server. Ensuring
@@ -24,7 +24,7 @@ serverpassword=""
 # -password \"${serverpassword}\"
 
 ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters
-startparameters="-name \"${servername}\" -port ${port} -webadmin -webdomain ${ip} -webuser ${webadminuser} -webpassword \"${webadminpass}\" -webport ${webadminport} -map ${defaultmap} -limit ${maxplayers} -config_path \"${servercfgdir}\" -logdir \"${gamelogdir}\" -modstorage \"${modstoragedir}\" -mods2 \"${mods}\""
+startparameters="-name \"${servername}\" -port ${port} -webadmin -webdomain ${ip} -webuser ${httpuser} -webpassword \"${httppassword}\" -webport ${httpport} -map ${defaultmap} -limit ${maxplayers} -config_path \"${servercfgdir}\" -logdir \"${gamelogdir}\" -modstorage \"${modstoragedir}\" -mods2 \"${mods}\""
 
 #### LinuxGSM Settings ####
 

+ 191 - 0
lgsm/config-default/config-lgsm/ohdserver/_default.cfg

@@ -0,0 +1,191 @@
+##################################
+######## Default Settings ########
+##################################
+# DO NOT EDIT, ANY CHANGES WILL BE OVERWRITTEN!
+# Copy settings from here and use them in either:
+# common.cfg - applies settings to every instance.
+# [instance].cfg - applies settings to a specific instance.
+
+#### Game Server Settings ####
+
+## Predefined Parameters | https://docs.linuxgsm.com/configuration/start-parameters
+ip="0.0.0.0"
+port="7777"
+queryport="27005"
+servername="LinuxGSM Server"
+serverpassword=""
+# Maps: risala, khafji_p, lamdong, montecassino, argonne
+defaultmap="AAS-TestMap"
+maxplayers="16"
+
+## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters
+startparameters="${defaultmap}?MaxPlayers=${maxplayers}?Password=${serverpassword} -Port=${port} -QueryPort=${queryport} -SteamServerName='${servername}' -log"
+
+#### LinuxGSM Settings ####
+
+## LinuxGSM Stats
+# Send useful stats to LinuxGSM developers.
+# https://docs.linuxgsm.com/configuration/linuxgsm-stats
+# (on|off)
+stats="off"
+
+## Notification Alerts
+# (on|off)
+
+# Display IP | https://docs.linuxgsm.com/alerts#display-ip
+displayip=""
+
+# More info | https://docs.linuxgsm.com/alerts#more-info
+postalert="off"
+
+# Discord Alerts | https://docs.linuxgsm.com/alerts/discord
+discordalert="off"
+discordwebhook="webhook"
+
+# Email Alerts | https://docs.linuxgsm.com/alerts/email
+emailalert="off"
+email="email@example.com"
+emailfrom=""
+
+# Gotify Alerts | https://docs.linuxgsm.com/alerts/gotify
+gotifyalert="off"
+gotifytoken="token"
+gotifywebhook="webhook"
+
+# IFTTT Alerts | https://docs.linuxgsm.com/alerts/ifttt
+iftttalert="off"
+ifttttoken="accesstoken"
+iftttevent="linuxgsm_alert"
+
+# Mailgun Email Alerts | https://docs.linuxgsm.com/alerts/mailgun
+mailgunalert="off"
+mailgunapiregion="us"
+mailguntoken="accesstoken"
+mailgundomain="example.com"
+mailgunemailfrom="alert@example.com"
+mailgunemail="email@myemail.com"
+
+# Pushbullet Alerts | https://docs.linuxgsm.com/alerts/pushbullet
+pushbulletalert="off"
+pushbullettoken="accesstoken"
+channeltag=""
+
+# Pushover Alerts | https://docs.linuxgsm.com/alerts/pushover
+pushoveralert="off"
+pushovertoken="accesstoken"
+pushoveruserkey="userkey"
+
+# Rocket.Chat Alerts | https://docs.linuxgsm.com/alerts/rocket.chat
+rocketchatalert="off"
+rocketchatwebhook="webhook"
+rocketchattoken=""
+
+# Slack Alerts | https://docs.linuxgsm.com/alerts/slack
+slackalert="off"
+slackwebhook="webhook"
+
+# Telegram Alerts | https://docs.linuxgsm.com/alerts/telegram
+# You can add a custom cURL string eg proxy (useful in Russia) in "curlcustomstring".
+# For example "--socks5 ipaddr:port" for socks5 proxy see more in "curl --help".
+telegramapi="api.telegram.org"
+telegramalert="off"
+telegramtoken="accesstoken"
+telegramchatid=""
+curlcustomstring=""
+
+## Updating | https://docs.linuxgsm.com/commands/update
+updateonstart="off"
+
+## Backup | https://docs.linuxgsm.com/commands/backup
+maxbackups="4"
+maxbackupdays="30"
+stoponbackup="on"
+
+## Logging | https://docs.linuxgsm.com/features/logging
+consolelogging="on"
+logdays="7"
+
+## Monitor | https://docs.linuxgsm.com/commands/monitor
+# Query delay time
+querydelay="1"
+
+## ANSI Colors | https://docs.linuxgsm.com/features/ansi-colors
+ansi="on"
+
+#### Advanced Settings ####
+
+## Message Display Time | https://docs.linuxgsm.com/features/message-display-time
+sleeptime="0.5"
+
+## SteamCMD Settings | https://docs.linuxgsm.com/steamcmd
+# Server appid
+appid="950900"
+steamcmdforcewindows="no"
+# SteamCMD Branch | https://docs.linuxgsm.com/steamcmd/branch
+branch=""
+betapassword=""
+# Master Server | https://docs.linuxgsm.com/steamcmd/steam-master-server
+steammaster="false"
+
+## Stop Mode | https://docs.linuxgsm.com/features/stop-mode
+# 1: tmux kill
+# 2: CTRL+c
+# 3: quit
+# 4: quit 120s
+# 5: stop
+# 6: q
+# 7: exit
+# 8: 7 Days to Die
+# 9: GoldSrc
+# 10: Avorion
+# 11: end
+stopmode="2"
+
+## Query mode
+# 1: session only
+# 2: gamedig (gsquery fallback)
+# 3: gamedig
+# 4: gsquery
+# 5: tcp
+querymode="2"
+querytype="protocol-valve"
+
+## Console type
+consoleverbose="yes"
+consoleinteract="no"
+
+## Game Server Details
+# Do not edit
+gamename="Operation: Harsh Doorstop"
+engine="unreal4"
+glibc="2.17"
+
+#### Directories ####
+# Edit with care
+
+## Game Server Directories
+systemdir="${serverfiles}/HarshDoorstop"
+executabledir="${systemdir}/Binaries/Linux"
+executable="./HarshDoorstopServer-Linux-Shipping"
+servercfgdir="${systemdir}/Saved/Config/LinuxServer"
+servercfg="Game.ini"
+servercfgdefault="Game.ini"
+servercfgfullpath="${servercfgdir}/${servercfg}"
+
+## Backup Directory
+backupdir="${lgsmdir}/backup"
+
+## Logging Directories
+logdir="${rootdir}/log"
+gamelogdir="${systemdir}/Saved/Logs"
+lgsmlogdir="${logdir}/script"
+consolelogdir="${logdir}/console"
+gamelog="${gamelogdir}/${selfname}-game.log"
+lgsmlog="${lgsmlogdir}/${selfname}-script.log"
+consolelog="${consolelogdir}/${selfname}-console.log"
+alertlog="${lgsmlogdir}/${selfname}-alert.log"
+postdetailslog="${lgsmlogdir}/${selfname}-postdetails.log"
+
+## Logs Naming
+lgsmlogdate="${lgsmlogdir}/${selfname}-script-$(date '+%Y-%m-%d-%H:%M:%S').log"
+consolelogdate="${consolelogdir}/${selfname}-console-$(date '+%Y-%m-%d-%H:%M:%S').log"

+ 1 - 1
lgsm/config-default/config-lgsm/pc2server/_default.cfg

@@ -119,7 +119,7 @@ steamcmdforcewindows="no"
 branch=""
 betapassword=""
 # Master Server | https://docs.linuxgsm.com/steamcmd/steam-master-server
-steammaster="false"
+steammaster="true"
 
 ## Stop Mode | https://docs.linuxgsm.com/features/stop-mode
 # 1: tmux kill

+ 1 - 1
lgsm/config-default/config-lgsm/pcserver/_default.cfg

@@ -115,7 +115,7 @@ steamcmdforcewindows="no"
 branch=""
 betapassword=""
 # Master Server | https://docs.linuxgsm.com/steamcmd/steam-master-server
-steammaster="false"
+steammaster="true"
 
 ## Stop Mode | https://docs.linuxgsm.com/features/stop-mode
 # 1: tmux kill

+ 3 - 3
lgsm/config-default/config-lgsm/pstbsserver/_default.cfg

@@ -10,15 +10,15 @@
 
 ## Predefined Parameters | https://docs.linuxgsm.com/configuration/start-parameters
 ip="0.0.0.0"
+maxplayers="40"
 port="10027"
 queryport="10037"
-rconport="21114"
 randommap="NONE"
-maxplayers="40"
 reservedslots="0"
+tickrate="50"
 
 ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters
-startparameters="MULTIHOME=${ip} RANDOM=${randommap} Port=${port} QueryPort=${queryport} RCONPORT=${rconport} FIXEDMAXPLAYERS=${maxplayers} NumReservedSlots=${reservedslots}"
+startparameters="MULTIHOME=${ip} RANDOM=${randommap} Port=${port} QueryPort=${queryport} FIXEDMAXPLAYERS=${maxplayers} FIXEDMAXTICKRATE=${tickrate} NumReservedSlots=${reservedslots}"
 
 #### LinuxGSM Settings ####
 

+ 2 - 1
lgsm/config-default/config-lgsm/pzserver/_default.cfg

@@ -10,10 +10,11 @@
 
 ## Predefined Parameters | https://docs.linuxgsm.com/configuration/start-parameters
 ip="0.0.0.0"
+javaram="8192" # -Xmx$8192M
 adminpassword="CHANGE_ME"
 
 ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters
-startparameters="--ip ${ip} -adminpassword \"${adminpassword}\" -servername ${selfname}"
+startparameters="--ip ${ip} -adminpassword \"${adminpassword}\" -servername ${selfname} -Xmx${javaram}M"
 
 #### LinuxGSM Settings ####
 

+ 2 - 2
lgsm/config-default/config-lgsm/rustserver/_default.cfg

@@ -12,8 +12,8 @@
 ip="0.0.0.0"
 port="28015"
 rconport="28016"
-appport=28082
-queryport=28017
+appport="28082"
+queryport="28017"
 rconpassword="CHANGE_ME"
 rconweb="1" # Value is: 1 for the Facepunch web panel, Rustadmin desktop and Rustadmin Online; 0 for RCON tools like Rusty.
 servername="Rust"

+ 0 - 2
lgsm/config-default/config-lgsm/sbotsserver/_default.cfg

@@ -13,8 +13,6 @@ port="7777"
 queryport="27015"
 defaultmap="StationKappa"
 servername="LinuxGSM Server"
-serverpassword="NOT SET" # Can't be adjusted currently
-maxplayers="8"           # Can't be adjusted currently
 
 ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters
 startparameters="Port=${port}?QueryPort=${queryport} -startup_map ${defaultmap} -server_name \"${servername}\""

+ 5 - 5
lgsm/config-default/config-lgsm/stserver/_default.cfg

@@ -10,17 +10,17 @@
 
 ## Predefined Parameters | https://docs.linuxgsm.com/configuration/start-parameters
 ip="0.0.0.0"
-servername="LinuxGSM"
+maxplayers="10"
 port="27500"
 queryport="27015"
-worldtype="Moon"
-maxplayers="10"
-autosaveinterval=300
+saveinterval="300"
+servername="LinuxGSM"
 worldname="moon_save"
+worldtype="Moon"
 
 ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters
 # Edit with care
-startparameters="-LOADLATEST ${worldname} ${worldtype} -settings ServerName ${servername} StartLocalHost true ServerVisible true ServerMaxPlayers ${maxplayers} GamePort ${port} UpdatePort ${queryport} UPNPEnabled true AutoSave true SaveInterval ${autosaveinterval}"
+startparameters="-LOADLATEST ${worldname} ${worldtype} -settings ServerName ${servername} StartLocalHost true ServerVisible true ServerMaxPlayers ${maxplayers} GamePort ${port} UpdatePort ${queryport} UPNPEnabled true AutoSave true SaveInterval ${saveinterval}"
 
 #### LinuxGSM Settings ####
 

+ 4 - 1
lgsm/config-default/config-lgsm/tiserver/_default.cfg

@@ -15,8 +15,11 @@ queryport="27015"
 # Possible maps, see: https://isle.fandom.com/wiki/The_Isle_Server_Settings_and_Configuration#Optional_Maps
 map=""
 
+# EAC start parameters
+eaclaunch="-ini:Engine:[EpicOnlineServices]:DedicatedServerClientId=xyza7891gk5PRo3J7G9puCJGFJjmEguW -ini:Engine:[EpicOnlineServices]:DedicatedServerClientSecret=pKWl6t5i9NJK8gTpVlAxzENZ65P8hYzodV8Dqe5Rlc8"
+
 ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters
-startparameters="${map} -MultiHome=${ip} -Port=${port} -QueryPort=${queryport} -log"
+startparameters="${map} -MultiHome=${ip} -Port=${port} -QueryPort=${queryport} -log ${eaclaunch}"
 
 #### LinuxGSM Settings ####
 

+ 2 - 2
lgsm/config-default/config-lgsm/vhserver/_default.cfg

@@ -13,7 +13,7 @@ servername="Valheim Server"
 # Minimum password length is 5.
 serverpassword=""
 port="2456"
-gameworld="${selfname}"
+worldname="${selfname}"
 public="1"
 savedir="$HOME/.config/unity3d/IronGate/Valheim"
 logFile=""
@@ -26,7 +26,7 @@ backuplong="43200"
 crossplay=""
 
 ## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters
-startparameters="-name '${servername}' -password ${serverpassword} -port ${port} -world ${gameworld} -public ${public} -savedir '${savedir}' -logFile '${logFile}' -saveinterval ${saveinterval} -backups ${backups} -backupshort ${backupshort} -backuplong ${backuplong} ${crossplay:+-crossplay}"
+startparameters="-name '${servername}' -password ${serverpassword} -port ${port} -world ${worldname} -public ${public} -savedir '${savedir}' -logFile '${logFile}' -saveinterval ${saveinterval} -backups ${backups} -backupshort ${backupshort} -backuplong ${backuplong} ${crossplay:+-crossplay}"
 
 #### LinuxGSM Settings ####
 

+ 6 - 2
lgsm/data/almalinux-8.csv

@@ -32,6 +32,7 @@ cs
 cscz
 csgo
 css,ncurses-libs.i686
+ct
 dab
 dayz
 dmc
@@ -48,6 +49,7 @@ ets2
 fctr
 fof
 gmod,ncurses-libs.i686
+hcu
 hl2dm
 hldm
 hldms
@@ -68,16 +70,18 @@ mcb,libnsl
 mh
 mohaa,compat-libstdc++-33.i686
 mom
-mta,ncurses-compat-libs
+mta,ncurses-compat-libs,libxml2
 nd
 nec
 nmrih,ncurses-libs.i686
 ns
 ns2,speex,tbb
 ns2c,speex.i686,tbb.i686
+ohd
 onset,mariadb-connector-c
 opfor
 pc
+pc2
 pmc,java-17-openjdk
 pstbs,GConf2
 pvkii
@@ -97,7 +101,7 @@ sb
 sbots
 scpsl
 scpslsm
-sdtd,telnet,expect
+sdtd,telnet,expect,libxml2
 sf
 sfc,ncurses-libs.i686
 sof2

+ 7 - 3
lgsm/data/almalinux-9.csv

@@ -1,4 +1,4 @@
-all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,python36,tar,tmux,unzip,util-linux,wget,xz
+all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,python3,tar,tmux,unzip,util-linux,wget,xz
 steamcmd,glibc.i686,libstdc++.i686
 ac
 ahl
@@ -32,6 +32,7 @@ cs
 cscz
 csgo
 css,ncurses-libs.i686
+ct
 dab
 dayz
 dmc
@@ -48,6 +49,7 @@ ets2
 fctr
 fof
 gmod,ncurses-libs.i686
+hcu
 hl2dm
 hldm
 hldms
@@ -68,16 +70,18 @@ mcb,libnsl
 mh
 mohaa,compat-libstdc++-33.i686
 mom
-mta,ncurses-compat-libs
+mta,ncurses-compat-libs,libxml2
 nd
 nec
 nmrih,ncurses-libs.i686
 ns
 ns2,speex,tbb
 ns2c,speex.i686,tbb.i686
+ohd
 onset,mariadb-connector-c
 opfor
 pc
+pc2
 pmc,java-17-openjdk
 pstbs,GConf2
 pvkii
@@ -97,7 +101,7 @@ sb
 sbots
 scpsl
 scpslsm
-sdtd,telnet,expect
+sdtd,telnet,expect,libxml2
 sf
 sfc,ncurses-libs.i686
 sof2

+ 6 - 2
lgsm/data/centos-7.csv

@@ -32,6 +32,7 @@ cs
 cscz
 csgo
 css,ncurses-libs.i686
+ct
 dab
 dayz
 dmc
@@ -48,6 +49,7 @@ ets2
 fctr
 fof
 gmod,ncurses-libs.i686
+hcu
 hl2dm
 hldm
 hldms
@@ -68,16 +70,18 @@ mcb,libnsl
 mh
 mohaa,compat-libstdc++-33.i686
 mom
-mta,ncurses-libs
+mta,ncurses-libs,libxml2
 nd
 nec
 nmrih,ncurses-libs.i686
 ns
 ns2,speex,tbb
 ns2c,speex.i686,tbb.i686
+ohd
 onset,mariadb-connector-c
 opfor
 pc
+pc2
 pmc,java-11-openjdk
 pstbs,GConf2
 pvkii
@@ -97,7 +101,7 @@ sb
 sbots
 scpsl
 scpslsm
-sdtd,telnet,expect
+sdtd,telnet,expect,libxml2
 sf
 sfc,ncurses-libs.i686
 sof2

+ 6 - 2
lgsm/data/centos-8.csv

@@ -32,6 +32,7 @@ cs
 cscz
 csgo
 css,ncurses-libs.i686
+ct
 dab
 dayz
 dmc
@@ -48,6 +49,7 @@ ets2
 fctr
 fof
 gmod,ncurses-libs.i686
+hcu
 hl2dm
 hldm
 hldms
@@ -68,16 +70,18 @@ mcb,libnsl
 mh
 mohaa,compat-libstdc++-33.i686
 mom
-mta,ncurses-compat-libs
+mta,ncurses-compat-libs,libxml2
 nd
 nec
 nmrih,ncurses-libs.i686
 ns
 ns2,speex,tbb
 ns2c,speex.i686,tbb.i686
+ohd
 onset,mariadb-connector-c
 opfor
 pc
+pc2
 pmc,java-17-openjdk
 pstbs,GConf2
 pvkii
@@ -97,7 +101,7 @@ sb
 sbots
 scpsl
 scpslsm
-sdtd,telnet,expect
+sdtd,telnet,expect,libxml2
 sf
 sfc,ncurses-libs.i686
 sof2

+ 7 - 3
lgsm/data/centos-9.csv

@@ -1,4 +1,4 @@
-all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,python36,tar,tmux,unzip,util-linux,wget,xz
+all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,python3,tar,tmux,unzip,util-linux,wget,xz
 steamcmd,glibc.i686,libstdc++.i686
 ac
 ahl
@@ -32,6 +32,7 @@ cs
 cscz
 csgo
 css,ncurses-libs.i686
+ct
 dab
 dayz
 dmc
@@ -48,6 +49,7 @@ ets2
 fctr
 fof
 gmod,ncurses-libs.i686
+hcu
 hl2dm
 hldm
 hldms
@@ -68,16 +70,18 @@ mcb,libnsl
 mh
 mohaa,compat-libstdc++-33.i686
 mom
-mta,ncurses-compat-libs
+mta,ncurses-compat-libs,libxml2
 nd
 nec
 nmrih,ncurses-libs.i686
 ns
 ns2,speex,tbb
 ns2c,speex.i686,tbb.i686
+ohd
 onset,mariadb-connector-c
 opfor
 pc
+pc2
 pmc,java-17-openjdk
 pstbs,GConf2
 pvkii
@@ -97,7 +101,7 @@ sb
 sbots
 scpsl
 scpslsm
-sdtd,telnet,expect
+sdtd,telnet,expect,libxml2
 sf
 sfc,ncurses-libs.i686
 sof2

+ 7 - 3
lgsm/data/debian-10.csv

@@ -20,7 +20,7 @@ bt,libicu-dev,dos2unix
 btl
 cc
 cd
-ck,xvfb
+ck,xvfb,libxi6
 cmw
 cod,libstdc++5:i386
 cod2,libstdc++5:i386
@@ -32,6 +32,7 @@ cs
 cscz
 csgo
 css,libtinfo5:i386
+ct
 dab
 dayz
 dmc
@@ -48,6 +49,7 @@ ets2
 fctr
 fof
 gmod,libtinfo5:i386
+hcu
 hl2dm
 hldm
 hldms
@@ -68,16 +70,18 @@ mcb
 mh
 mohaa,libstdc++5:i386
 mom
-mta,libncursesw5
+mta,libncursesw5,libxml2-utils
 nd
 nec
 nmrih,libtinfo5:i386
 ns
 ns2,speex,libtbb2
 ns2c,speex:i386,libtbb2
+ohd
 onset,libmariadb-dev
 opfor
 pc
+pc2
 pmc,openjdk-11-jre
 pstbs,libgconf-2-4
 pvkii
@@ -97,7 +101,7 @@ sb
 sbots
 scpsl,mono-complete
 scpslsm,mono-complete
-sdtd,telnet,expect
+sdtd,telnet,expect,libxml2-utils
 sf
 sfc,libtinfo5:i386
 sof2

+ 7 - 3
lgsm/data/debian-11.csv

@@ -20,7 +20,7 @@ bt,libicu-dev,dos2unix
 btl
 cc
 cd
-ck,xvfb
+ck,xvfb,libxi6
 cmw
 cod,libstdc++5:i386
 cod2,libstdc++5:i386
@@ -32,6 +32,7 @@ cs
 cscz
 csgo
 css,libtinfo5:i386
+ct
 dab
 dayz
 dmc
@@ -48,6 +49,7 @@ ets2
 fctr
 fof
 gmod,libtinfo5:i386
+hcu
 hl2dm
 hldm
 hldms
@@ -68,16 +70,18 @@ mcb
 mh
 mohaa,libstdc++5:i386
 mom
-mta,libncursesw5
+mta,libncursesw5,libxml2-utils
 nd
 nec
 nmrih,libtinfo5:i386
 ns
 ns2,speex,libtbb2
 ns2c,speex:i386,libtbb2
+ohd
 onset,libmariadb-dev
 opfor
 pc
+pc2
 pmc,openjdk-17-jre
 pstbs,libgconf-2-4
 pvkii
@@ -97,7 +101,7 @@ sb
 sbots
 scpsl,mono-complete
 scpslsm,mono-complete
-sdtd,telnet,expect
+sdtd,telnet,expect,libxml2-utils
 sf
 sfc,libtinfo5:i386
 sof2

+ 135 - 0
lgsm/data/debian-12.csv

@@ -0,0 +1,135 @@
+all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat-traditional,python3,tar,tmux,unzip,util-linux,wget,xz-utils
+steamcmd,lib32gcc-s1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd
+ac
+ahl
+ahl2
+ark
+arma3
+armar,libcurl4
+ats
+av
+bb
+bb2,libcurl4-gnutls-dev:i386
+bd
+bf1942,libncurses5:i386,libtinfo5:i386
+bfv,libncurses5:i386,libstdc++5:i386
+bmdm,libncurses5:i386
+bo
+bs
+bt,libicu-dev,dos2unix
+btl
+cc
+cd
+ck,xvfb,libxi6
+cmw
+cod,libstdc++5:i386
+cod2,libstdc++5:i386
+cod4
+coduo,libstdc++5:i386
+codwaw
+col
+cs
+cscz
+csgo
+css,libtinfo5:i386
+ct
+dab
+dayz
+dmc
+dod
+dodr
+dods
+doi
+dst,libcurl4-gnutls-dev:i386
+dys
+eco,libgdiplus
+em
+etl
+ets2
+fctr
+fof
+gmod,libtinfo5:i386
+hcu
+hl2dm
+hldm
+hldms
+hw,lib32z1
+ins
+inss
+ios
+jc2
+jc3
+jk2
+kf
+kf2
+l4d
+l4d2
+lo
+mc,openjdk-17-jre
+mcb
+mh
+mohaa,libstdc++5:i386
+mom
+mta,libncursesw5,libxml2-utils
+nd
+nec
+nmrih,libtinfo5:i386
+ns
+ns2,speex,libtbb12
+ns2c,speex:i386,libtbb12
+ohd
+onset,libmariadb-dev
+opfor
+pc
+pc2
+pmc,openjdk-17-jre
+pstbs,libgconf-2-4
+pvkii
+pvr,libc++1
+pz,openjdk-17-jre,rng-tools5
+q2
+q3
+ql
+qw
+ricochet
+ro
+rtcw
+rust,lib32z1
+rw,openjdk-17-jre
+samp
+sb
+sbots
+scpsl,mono-complete
+scpslsm,mono-complete
+sdtd,telnet,expect,libxml2-utils
+sf
+sfc,libtinfo5:i386
+sof2
+sol
+squad
+st
+stn
+sven,libssl3:i386,zlib1g:i386
+terraria
+tf2,libcurl4-gnutls-dev:i386
+tfc
+ti
+ts
+ts3
+tu
+tw
+unt
+ut
+ut2k4
+ut3
+ut99
+vh,libc6-dev
+vints,mono-complete
+vpmc,openjdk-17-jre
+vs
+wet
+wf
+wmc,openjdk-17-jre
+wurm,xvfb
+zmr,libtinfo5:i386
+zps,libtinfo5:i386

+ 7 - 3
lgsm/data/debian-9.csv

@@ -20,7 +20,7 @@ bt,libicu-dev,dos2unix
 btl
 cc
 cd
-ck,xvfb
+ck,xvfb,libxi6
 cmw
 cod,libstdc++5:i386
 cod2,libstdc++5:i386
@@ -32,6 +32,7 @@ cs
 cscz
 csgo
 css,libtinfo5:i386
+ct
 dab
 dayz
 dmc
@@ -48,6 +49,7 @@ ets2
 fctr
 fof
 gmod,libtinfo5:i386
+hcu
 hl2dm
 hldm
 hldms
@@ -68,16 +70,18 @@ mcb
 mh
 mohaa,libstdc++5:i386
 mom
-mta,libncursesw5
+mta,libncursesw5,libxml2-utils
 nd
 nec
 nmrih,libtinfo5:i386
 ns
 ns2,speex,libtbb2
 ns2c,speex:i386,libtbb2
+ohd
 onset,libmariadb-dev
 opfor
 pc
+pc2
 pmc,openjdk-8-jre
 pstbs,libgconf-2-4
 pvkii
@@ -97,7 +101,7 @@ sb
 sbots
 scpsl,mono-complete
 scpslsm,mono-complete
-sdtd,telnet,expect
+sdtd,telnet,expect,libxml2-utils
 sf
 sfc,libtinfo5:i386
 sof2

+ 6 - 2
lgsm/data/rhel-7.csv

@@ -32,6 +32,7 @@ cs
 cscz
 csgo
 css,ncurses-libs.i686
+ct
 dab
 dayz
 dmc
@@ -48,6 +49,7 @@ ets2
 fctr
 fof
 gmod,ncurses-libs.i686
+hcu
 hl2dm
 hldm
 hldms
@@ -68,16 +70,18 @@ mcb,libnsl
 mh
 mohaa,compat-libstdc++-33.i686
 mom
-mta,ncurses-libs
+mta,ncurses-libs,libxml2
 nd
 nec
 nmrih,ncurses-libs.i686
 ns
 ns2,speex,tbb
 ns2c,speex.i686,tbb.i686
+ohd
 onset,mariadb-connector-c
 opfor
 pc
+pc2
 pmc,java-11-openjdk
 pstbs,GConf2
 pvkii
@@ -97,7 +101,7 @@ sb
 sbots
 scpsl
 scpslsm
-sdtd,telnet,expect
+sdtd,telnet,expect,libxml2
 sf
 sfc,ncurses-libs.i686
 sof2

+ 6 - 2
lgsm/data/rhel-8.csv

@@ -32,6 +32,7 @@ cs
 cscz
 csgo
 css,ncurses-libs.i686
+ct
 dab
 dayz
 dmc
@@ -48,6 +49,7 @@ ets2
 fctr
 fof
 gmod,ncurses-libs.i686
+hcu
 hl2dm
 hldm
 hldms
@@ -68,16 +70,18 @@ mcb,libnsl
 mh
 mohaa,compat-libstdc++-33.i686
 mom
-mta,ncurses-compat-libs
+mta,ncurses-compat-libs,libxml2
 nd
 nec
 nmrih,ncurses-libs.i686
 ns
 ns2,speex,tbb
 ns2c,speex.i686,tbb.i686
+ohd
 onset,mariadb-connector-c
 opfor
 pc
+pc2
 pmc,java-17-openjdk
 pstbs,GConf2
 pvkii
@@ -97,7 +101,7 @@ sb
 sbots
 scpsl
 scpslsm
-sdtd,telnet,expect
+sdtd,telnet,expect,libxml2
 sf
 sfc,ncurses-libs.i686
 sof2

+ 7 - 3
lgsm/data/rhel-9.csv

@@ -1,4 +1,4 @@
-all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,python36,tar,tmux,unzip,util-linux,wget,xz
+all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,python3,tar,tmux,unzip,util-linux,wget,xz
 steamcmd,glibc.i686,libstdc++.i686
 ac
 ahl
@@ -32,6 +32,7 @@ cs
 cscz
 csgo
 css,ncurses-libs.i686
+ct
 dab
 dayz
 dmc
@@ -48,6 +49,7 @@ ets2
 fctr
 fof
 gmod,ncurses-libs.i686
+hcu
 hl2dm
 hldm
 hldms
@@ -68,16 +70,18 @@ mcb,libnsl
 mh
 mohaa,compat-libstdc++-33.i686
 mom
-mta,ncurses-compat-libs
+mta,ncurses-compat-libs,libxml2
 nd
 nec
 nmrih,ncurses-libs.i686
 ns
 ns2,speex,tbb
 ns2c,speex.i686,tbb.i686
+ohd
 onset,mariadb-connector-c
 opfor
 pc
+pc2
 pmc,java-17-openjdk
 pstbs,GConf2
 pvkii
@@ -97,7 +101,7 @@ sb
 sbots
 scpsl
 scpslsm
-sdtd,telnet,expect
+sdtd,telnet,expect,libxml2
 sf
 sfc,ncurses-libs.i686
 sof2

+ 6 - 2
lgsm/data/rocky-8.csv

@@ -32,6 +32,7 @@ cs
 cscz
 csgo
 css,ncurses-libs.i686
+ct
 dab
 dayz
 dmc
@@ -48,6 +49,7 @@ ets2
 fctr
 fof
 gmod,ncurses-libs.i686
+hcu
 hl2dm
 hldm
 hldms
@@ -68,16 +70,18 @@ mcb,libnsl
 mh
 mohaa,compat-libstdc++-33.i686
 mom
-mta,ncurses-compat-libs
+mta,ncurses-compat-libs,libxml2
 nd
 nec
 nmrih,ncurses-libs.i686
 ns
 ns2,speex,tbb
 ns2c,speex.i686,tbb.i686
+ohd
 onset,mariadb-connector-c
 opfor
 pc
+pc2
 pmc,java-17-openjdk
 pstbs,GConf2
 pvkii
@@ -97,7 +101,7 @@ sb
 sbots
 scpsl
 scpslsm
-sdtd,telnet,expect
+sdtd,telnet,expect,libxml2
 sf
 sfc,ncurses-libs.i686
 sof2

+ 7 - 3
lgsm/data/rocky-9.csv

@@ -1,4 +1,4 @@
-all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,python36,tar,tmux,unzip,util-linux,wget,xz
+all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,python3,tar,tmux,unzip,util-linux,wget,xz
 steamcmd,glibc.i686,libstdc++.i686
 ac
 ahl
@@ -32,6 +32,7 @@ cs
 cscz
 csgo
 css,ncurses-libs.i686
+ct
 dab
 dayz
 dmc
@@ -48,6 +49,7 @@ ets2
 fctr
 fof
 gmod,ncurses-libs.i686
+hcu
 hl2dm
 hldm
 hldms
@@ -68,16 +70,18 @@ mcb,libnsl
 mh
 mohaa,compat-libstdc++-33.i686
 mom
-mta,ncurses-compat-libs
+mta,ncurses-compat-libs,libxml2
 nd
 nec
 nmrih,ncurses-libs.i686
 ns
 ns2,speex,tbb
 ns2c,speex.i686,tbb.i686
+ohd
 onset,mariadb-connector-c
 opfor
 pc
+pc2
 pmc,java-17-openjdk
 pstbs,GConf2
 pvkii
@@ -97,7 +101,7 @@ sb
 sbots
 scpsl
 scpslsm
-sdtd,telnet,expect
+sdtd,telnet,expect,libxml2
 sf
 sfc,ncurses-libs.i686
 sof2

+ 4 - 2
lgsm/data/serverlist.csv

@@ -4,7 +4,7 @@ ahl2,ahl2server,Action: Source,ubuntu-22.04
 ark,arkserver,ARK: Survival Evolved,ubuntu-22.04
 arma3,arma3server,ARMA 3,ubuntu-22.04
 armar,armarserver,Arma Reforger,ubuntu-20.04
-ats,atsserver,American Truck Simulator
+ats,atsserver,American Truck Simulator,ubuntu-22.04
 av,avserver,Avorion,ubuntu-22.04
 bb,bbserver,BrainBread,ubuntu-22.04
 bb2,bb2server,BrainBread 2,ubuntu-22.04
@@ -30,6 +30,7 @@ cs,csserver,Counter-Strike 1.6,ubuntu-22.04
 cscz,csczserver,Counter-Strike: Condition Zero,ubuntu-22.04
 csgo,csgoserver,Counter-Strike: Global Offensive,ubuntu-22.04
 css,cssserver,Counter-Strike: Source,ubuntu-22.04
+ct,ctserver,Craftopia,ubuntu-22.04
 dab,dabserver,Double Action: Boogaloo,ubuntu-22.04
 dayz,dayzserver,DayZ,ubuntu-22.04
 dmc,dmcserver,Deathmatch Classic,ubuntu-22.04
@@ -46,6 +47,7 @@ ets2,ets2server,Euro Truck Simulator 2,ubuntu-22.04
 fctr,fctrserver,Factorio,ubuntu-22.04
 fof,fofserver,Fistful of Frags,ubuntu-22.04
 gmod,gmodserver,Garrys Mod,ubuntu-22.04
+hcu,hcuserver,HYPERCHARGE: Unboxed,ubuntu-22.04
 hl2dm,hl2dmserver,Half-Life 2: Deathmatch,ubuntu-22.04
 hldm,hldmserver,Half-Life: Deathmatch,ubuntu-22.04
 hldms,hldmsserver,Half-Life Deathmatch: Source,ubuntu-22.04
@@ -73,6 +75,7 @@ nmrih,nmrihserver,No More Room in Hell,ubuntu-22.04
 ns,nsserver,Natural Selection,ubuntu-22.04
 ns2,ns2server,Natural Selection 2,ubuntu-22.04
 ns2c,ns2cserver,NS2: Combat,ubuntu-22.04
+ohd,ohdserver,Operation: Harsh Doorstop,ubuntu-22.04
 onset,onsetserver,Onset,ubuntu-20.04
 opfor,opforserver,Opposing Force,ubuntu-22.04
 pc,pcserver,Project Cars,ubuntu-22.04
@@ -128,4 +131,3 @@ wmc,wmcserver,WaterfallMC,ubuntu-22.04
 wurm,wurmserver,Wurm Unlimited,ubuntu-22.04
 zmr,zmrserver,Zombie Master: Reborn,ubuntu-22.04
 zps,zpsserver,Zombie Panic! Source,ubuntu-22.04
-

+ 6 - 2
lgsm/data/ubuntu-16.04.csv

@@ -20,7 +20,7 @@ bt,libicu-dev,dos2unix
 btl
 cc
 cd
-ck,xvfb
+ck,xvfb,libxi6
 cmw
 cod,libstdc++5:i386
 cod2,libstdc++5:i386
@@ -32,6 +32,7 @@ cs
 cscz
 csgo
 css,libtinfo5:i386
+ct
 dab
 dayz
 dmc
@@ -48,6 +49,7 @@ ets2
 fctr
 fof
 gmod,libtinfo5:i386
+hcu
 hl2dm
 hldm
 hldms
@@ -75,9 +77,11 @@ nmrih,libtinfo5:i386
 ns
 ns2,speex,libtbb2
 ns2c,speex:i386,libtbb2
+ohd
 onset,libmariadb-dev
 opfor
 pc
+pc2
 pmc,openjdk-8-jre
 pstbs,libgconf-2-4
 pvkii
@@ -97,7 +101,7 @@ sb
 sbots
 scpsl,mono-complete
 scpslsm,mono-complete
-sdtd,telnet,expect
+sdtd,telnet,expect,libxml2-utils
 sf
 sfc,libtinfo5:i386
 sof2

+ 7 - 3
lgsm/data/ubuntu-18.04.csv

@@ -20,7 +20,7 @@ bt,libicu-dev,dos2unix
 btl
 cc
 cd
-ck,xvfb
+ck,xvfb,libxi6
 cmw
 cod,libstdc++5:i386
 cod2,libstdc++5:i386
@@ -32,6 +32,7 @@ cs
 cscz
 csgo
 css,libtinfo5:i386
+ct
 dab
 dayz
 dmc
@@ -48,6 +49,7 @@ ets2
 fctr
 fof
 gmod,libtinfo5:i386
+hcu
 hl2dm
 hldm
 hldms
@@ -68,16 +70,18 @@ mcb
 mh
 mohaa,libstdc++5:i386
 mom
-mta,libncursesw5
+mta,libncursesw5,libxml2-utils
 nd
 nec
 nmrih,libtinfo5:i386
 ns
 ns2,speex,libtbb2
 ns2c,speex:i386,libtbb2
+ohd
 onset,libmariadb-dev
 opfor
 pc
+pc2
 pmc,openjdk-11-jre
 pstbs,libgconf-2-4
 pvkii
@@ -97,7 +101,7 @@ sb
 sbots
 scpsl,mono-complete
 scpslsm,mono-complete
-sdtd,telnet,expect
+sdtd,telnet,expect,libxml2-utils
 sf
 sfc,libtinfo5:i386
 sof2

+ 7 - 3
lgsm/data/ubuntu-20.04.csv

@@ -20,7 +20,7 @@ bt,libicu-dev,dos2unix
 btl
 cc
 cd
-ck,xvfb
+ck,xvfb,libxi6
 cmw
 cod,libstdc++5:i386
 cod2,libstdc++5:i386
@@ -32,6 +32,7 @@ cs
 cscz
 csgo
 css,libtinfo5:i386
+ct
 dab
 dayz
 dmc
@@ -48,6 +49,7 @@ ets2
 fctr
 fof
 gmod,libtinfo5:i386
+hcu
 hl2dm
 hldm
 hldms
@@ -68,16 +70,18 @@ mcb
 mh
 mohaa,libstdc++5:i386
 mom
-mta,libncursesw5
+mta,libncursesw5,libxml2-utils
 nd
 nec
 nmrih,libtinfo5:i386
 ns
 ns2,speex,libtbb2
 ns2c,speex:i386,libtbb2
+ohd
 onset,libmariadb-dev
 opfor
 pc
+pc2
 pmc,openjdk-17-jre
 pstbs,libgconf-2-4
 pvkii
@@ -97,7 +101,7 @@ sb
 sbots
 scpsl,mono-complete
 scpslsm,mono-complete
-sdtd,telnet,expect
+sdtd,telnet,expect,libxml2-utils
 sf
 sfc,libtinfo5:i386
 sof2

+ 7 - 3
lgsm/data/ubuntu-21.04.csv

@@ -20,7 +20,7 @@ bt,libicu-dev,dos2unix
 btl
 cc
 cd
-ck,xvfb
+ck,xvfb,libxi6
 cmw
 cod,libstdc++5:i386
 cod2,libstdc++5:i386
@@ -32,6 +32,7 @@ cs
 cscz
 csgo
 css,libtinfo5:i386
+ct
 dab
 dayz
 dmc
@@ -48,6 +49,7 @@ ets2
 fctr
 fof
 gmod,libtinfo5:i386
+hcu
 hl2dm
 hldm
 hldms
@@ -68,16 +70,18 @@ mcb
 mh
 mohaa,libstdc++5:i386
 mom
-mta,libncursesw5
+mta,libncursesw5,libxml2-utils
 nd
 nec
 nmrih,libtinfo5:i386
 ns
 ns2,speex,libtbb2
 ns2c,speex:i386,libtbb2
+ohd
 onset,libmariadb-dev
 opfor
 pc
+pc2
 pmc,openjdk-17-jre
 pstbs,libgconf-2-4
 pvkii
@@ -97,7 +101,7 @@ sb
 sbots
 scpsl,mono-complete
 scpslsm,mono-complete
-sdtd,telnet,expect
+sdtd,telnet,expect,libxml2-utils
 sf
 sfc,libtinfo5:i386
 sof2

+ 10 - 4
lgsm/data/ubuntu-21.10.csv

@@ -16,10 +16,11 @@ bfv,libncurses5:i386,libstdc++5:i386
 bmdm,libncurses5:i386
 bo
 bs
-bt,libicu-dev
+bt,libicu-dev,dos2unix
 btl
 cc
-ck,xvfb
+cd
+ck,xvfb,libxi6
 cmw
 cod,libstdc++5:i386
 cod2,libstdc++5:i386
@@ -31,7 +32,9 @@ cs
 cscz
 csgo
 css,libtinfo5:i386
+ct
 dab
+dayz
 dmc
 dod
 dodr
@@ -46,6 +49,7 @@ ets2
 fctr
 fof
 gmod,libtinfo5:i386
+hcu
 hl2dm
 hldm
 hldms
@@ -66,16 +70,18 @@ mcb
 mh
 mohaa,libstdc++5:i386
 mom
-mta,libncursesw5
+mta,libncursesw5,libxml2-utils
 nd
 nec
 nmrih,libtinfo5:i386
 ns
 ns2,speex,libtbb2
 ns2c,speex:i386,libtbb2
+ohd
 onset,libmariadb-dev
 opfor
 pc
+pc2
 pmc,openjdk-17-jre
 pstbs,libgconf-2-4
 pvkii
@@ -95,7 +101,7 @@ sb
 sbots
 scpsl,mono-complete
 scpslsm,mono-complete
-sdtd,telnet,expect
+sdtd,telnet,expect,libxml2-utils
 sf
 sfc,libtinfo5:i386
 sof2

+ 7 - 3
lgsm/data/ubuntu-22.04.csv

@@ -19,8 +19,8 @@ bs
 bt,libicu-dev,dos2unix
 btl
 cc
-ck,xvfb
 cd
+ck,xvfb,libxi6
 cmw
 cod,libstdc++5:i386
 cod2,libstdc++5:i386
@@ -32,6 +32,7 @@ cs
 cscz
 csgo
 css,libtinfo5:i386
+ct
 dab
 dayz
 dmc
@@ -48,6 +49,7 @@ ets2
 fctr
 fof
 gmod,libtinfo5:i386
+hcu
 hl2dm
 hldm
 hldms
@@ -68,16 +70,18 @@ mcb
 mh
 mohaa,libstdc++5:i386
 mom
-mta,libncursesw5
+mta,libncursesw5,libxml2-utils
 nd
 nec
 nmrih,libtinfo5:i386
 ns
 ns2,speex,libtbb2
 ns2c,speex:i386,libtbb2
+ohd
 onset,libmariadb-dev
 opfor
 pc
+pc2
 pmc,openjdk-17-jre
 pstbs,libgconf-2-4
 pvkii
@@ -97,7 +101,7 @@ sb
 sbots
 scpsl,mono-complete
 scpslsm,mono-complete
-sdtd,telnet,expect
+sdtd,telnet,expect,libxml2-utils
 sf
 sfc,libtinfo5:i386
 sof2

+ 135 - 0
lgsm/data/ubuntu-23.04.csv

@@ -0,0 +1,135 @@
+all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat,python3,tar,tmux,unzip,util-linux,wget,xz-utils
+steamcmd,lib32gcc-s1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd
+ac
+ahl
+ahl2
+ark
+arma3
+armar,libcurl4
+ats
+av
+bb
+bb2,libcurl4-gnutls-dev:i386
+bd
+bf1942,libncurses5:i386,libtinfo5:i386
+bfv,libncurses5:i386,libstdc++5:i386
+bmdm,libncurses5:i386
+bo
+bs
+bt,libicu-dev,dos2unix
+btl
+cc
+cd
+ck,xvfb,libxi6
+cmw
+cod,libstdc++5:i386
+cod2,libstdc++5:i386
+cod4
+coduo,libstdc++5:i386
+codwaw
+col
+cs
+cscz
+csgo
+css,libtinfo5:i386
+ct
+dab
+dayz
+dmc
+dod
+dodr
+dods
+doi
+dst,libcurl4-gnutls-dev:i386
+dys
+eco,libgdiplus
+em
+etl
+ets2
+fctr
+fof
+gmod,libtinfo5:i386
+hcu
+hl2dm
+hldm
+hldms
+hw,lib32z1
+ins
+inss
+ios
+jc2
+jc3
+jk2
+kf
+kf2
+l4d
+l4d2
+lo
+mc,openjdk-17-jre
+mcb
+mh
+mohaa,libstdc++5:i386
+mom
+mta,libncursesw5,libxml2-utils
+nd
+nec
+nmrih,libtinfo5:i386
+ns
+ns2,speex,libtbb2
+ns2c,speex:i386,libtbb2
+ohd
+onset,libmariadb-dev
+opfor
+pc
+pc2
+pmc,openjdk-17-jre
+pstbs,libgconf-2-4
+pvkii
+pvr,libc++1
+pz,openjdk-17-jre,rng-tools5
+q2
+q3
+ql
+qw
+ricochet
+ro
+rtcw
+rust,lib32z1
+rw,openjdk-17-jre
+samp
+sb
+sbots
+scpsl,mono-complete
+scpslsm,mono-complete
+sdtd,telnet,expect,libxml2-utils
+sf
+sfc,libtinfo5:i386
+sof2
+sol
+squad
+st
+stn
+sven,libssl1.1:i386,zlib1g:i386
+terraria
+tf2,libcurl4-gnutls-dev:i386
+tfc
+ti
+ts
+ts3
+tu
+tw
+unt
+ut
+ut2k4
+ut3
+ut99
+vh,libc6-dev
+vints,mono-complete
+vpmc,openjdk-17-jre
+vs
+wet
+wf
+wmc,openjdk-17-jre
+wurm,xvfb
+zmr,libtinfo5:i386
+zps,libtinfo5:i386

+ 816 - 0
lgsm/functions/README.md

@@ -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.3"
+
+# 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 - 0
lgsm/functions/core_steamcmd.sh

@@ -1719,6 +1719,8 @@ fn_info_message_select_engine() {
 		fn_info_message_etl
 	elif [ "${shortname}" == "fctr" ]; then
 		fn_info_message_fctr
+	elif [ "${shortname}" == "hcu" ]; then
+		fn_info_message_hcu
 	elif [ "${shortname}" == "hw" ]; then
 		fn_info_message_hw
 	elif [ "${shortname}" == "ins" ]; then

+ 17 - 0
lgsm/functions/info_stats.sh

@@ -0,0 +1,17 @@
+# LinuxGSM - Modules
+
+These modules are scripts that are called upon by the primary script linuxgsm.sh
+
+## Module Names
+
+Modules have been named to give an idea of what the function does.
+
+-   core: Essential modules that will always run first.
+-   command: Primary command function.
+-   check: Runs checks that will either halt on or fix an issue.
+-   dev: development modules.
+-   fix: Applies a game server specific fix.
+-   info: retrieves information from a source such as config file or the OS.
+-   install: modules related to the installer.
+-   monitor: modules related to monitor.
+-   update: modules that update the game server.

+ 238 - 0
lgsm/modules/alert.sh

@@ -0,0 +1,238 @@
+#!/bin/bash
+# LinuxGSM alert.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Overall module for managing alerts.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+# Generates alert log of the details at the time of the alert.
+# Used with email alerts.
+fn_alert_log() {
+	info_distro.sh
+	info_game.sh
+	info_messages.sh
+	if [ -f "${alertlog}" ]; then
+		rm -f "${alertlog:?}"
+	fi
+
+	{
+		fn_info_message_head
+		fn_info_message_distro
+		fn_info_message_server_resource
+		fn_info_message_gameserver_resource
+		fn_info_message_gameserver
+		fn_info_logs
+	} | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g" | tee -a "${alertlog}" > /dev/null 2>&1
+}
+
+fn_alert_test() {
+	fn_script_log_info "Sending test alert"
+	alertsubject="Alert - ${selfname} - Test"
+	alertemoji="🚧"
+	alertsound="1"
+	alerturl="not enabled"
+	alertbody="Testing LinuxGSM Alert. No action to be taken."
+}
+
+fn_alert_restart() {
+	fn_script_log_info "Sending alert: Restarted: ${executable} not running"
+	alertsubject="Alert - ${selfname} - Restarted"
+	alertemoji="🚨"
+	alertsound="2"
+	alerturl="not enabled"
+	alertbody="${selfname} ${executable} not running"
+}
+
+fn_alert_restart_query() {
+	fn_script_log_info "Sending alert: Restarted: ${selfname}"
+	alertsubject="Alert - ${selfname} - Restarted"
+	alertemoji="🚨"
+	alertsound="2"
+	alerturl="not enabled"
+	alertbody="Unable to query: ${selfname}"
+}
+
+fn_alert_update() {
+	fn_script_log_info "Sending alert: Updated"
+	alertsubject="Alert - ${selfname} - Updated"
+	alertemoji="🎮"
+	alertsound="1"
+	alerturl="not enabled"
+	alertbody="${gamename} received update: ${remotebuildversion}"
+}
+
+fn_alert_check_update() {
+	fn_script_log_info "Sending alert: Update available"
+	alertsubject="Alert - ${selfname} - Update available"
+	alertemoji="🎮"
+	alertsound="1"
+	alerturl="not enabled"
+	alertbody="${gamename} update available: ${remotebuildversion}"
+}
+
+fn_alert_permissions() {
+	fn_script_log_info "Sending alert: Permissions error"
+	alertsubject="Alert - ${selfname}: Permissions error"
+	alertemoji="❗"
+	alertsound="2"
+	alerturl="not enabled"
+	alertbody="${selfname} has permissions issues"
+}
+
+fn_alert_config() {
+	fn_script_log_info "Sending alert: New _default.cfg"
+	alertsubject="Alert - ${selfname} - New _default.cfg"
+	alertemoji="🎮"
+	alertsound="1"
+	alerturl="not enabled"
+	alertbody="${selfname} has received a new _default.cfg. Check file for changes."
+}
+
+if [ "${alert}" == "permissions" ]; then
+	fn_alert_permissions
+elif [ "${alert}" == "restart" ]; then
+	fn_alert_restart
+elif [ "${alert}" == "restartquery" ]; then
+	fn_alert_restart_query
+elif [ "${alert}" == "test" ]; then
+	fn_alert_test
+elif [ "${alert}" == "update" ]; then
+	fn_alert_update
+elif [ "${alert}" == "check-update" ]; then
+	fn_alert_check_update
+elif [ "${alert}" == "config" ]; then
+	fn_alert_config
+fi
+
+# Generate alert log.
+fn_alert_log
+
+# Generates the more info link.
+if [ "${postalert}" == "on" ] && [ -n "${postalert}" ]; then
+	exitbypass=1
+	command_postdetails.sh
+	fn_firstcommand_reset
+	unset exitbypass
+elif [ "${postalert}" != "on" ] && [ "${commandname}" == "TEST-ALERT" ]; then
+	fn_print_warn_nl "More Info not enabled"
+	fn_script_log_warn "More Info alerts not enabled"
+fi
+
+if [ "${discordalert}" == "on" ] && [ -n "${discordalert}" ]; then
+	alert_discord.sh
+elif [ "${discordalert}" != "on" ] && [ "${commandname}" == "TEST-ALERT" ]; then
+	fn_print_warn_nl "Discord alerts not enabled"
+	fn_script_log_warn "Discord alerts not enabled"
+elif [ -z "${discordtoken}" ] && [ "${commandname}" == "TEST-ALERT" ]; then
+	fn_print_error_nl "Discord token not set"
+	echo -e "* https://docs.linuxgsm.com/alerts/discord"
+	fn_script_error "Discord token not set"
+fi
+
+if [ "${emailalert}" == "on" ] && [ -n "${email}" ]; then
+	alert_email.sh
+elif [ "${emailalert}" != "on" ] && [ "${commandname}" == "TEST-ALERT" ]; then
+	fn_print_warn_nl "Email alerts not enabled"
+	fn_script_log_warn "Email alerts not enabled"
+elif [ -z "${email}" ] && [ "${commandname}" == "TEST-ALERT" ]; then
+	fn_print_error_nl "Email not set"
+	fn_script_log_error "Email not set"
+fi
+
+if [ "${gotifyalert}" == "on" ] && [ -n "${gotifyalert}" ]; then
+	alert_gotify.sh
+elif [ "${gotifyalert}" != "on" ] && [ "${commandname}" == "TEST-ALERT" ]; then
+	fn_print_warn_nl "Gotify alerts not enabled"
+	fn_script_log_warn "Gotify alerts not enabled"
+elif [ -z "${gotifytoken}" ] && [ "${commandname}" == "TEST-ALERT" ]; then
+	fn_print_error_nl "Gotify token not set"
+	echo -e "* https://docs.linuxgsm.com/alerts/gotify"
+	fn_script_error "Gotify token not set"
+elif [ -z "${gotifywebhook}" ] && [ "${commandname}" == "TEST-ALERT" ]; then
+	fn_print_error_nl "Gotify webhook not set"
+	echo -e "* https://docs.linuxgsm.com/alerts/gotify"
+	fn_script_error "Gotify webhook not set"
+fi
+
+if [ "${iftttalert}" == "on" ] && [ -n "${iftttalert}" ]; then
+	alert_ifttt.sh
+elif [ "${iftttalert}" != "on" ] && [ "${commandname}" == "TEST-ALERT" ]; then
+	fn_print_warn_nl "IFTTT alerts not enabled"
+	fn_script_log_warn "IFTTT alerts not enabled"
+elif [ -z "${ifttttoken}" ] && [ "${commandname}" == "TEST-ALERT" ]; then
+	fn_print_error_nl "IFTTT token not set"
+	echo -e "* https://docs.linuxgsm.com/alerts/ifttt"
+	fn_script_error "IFTTT token not set"
+fi
+
+if [ "${mailgunalert}" == "on" ] && [ -n "${mailgunalert}" ]; then
+	alert_mailgun.sh
+elif [ "${mailgunalert}" != "on" ] && [ "${commandname}" == "TEST-ALERT" ]; then
+	fn_print_warn_nl "Mailgun alerts not enabled"
+	fn_script_log_warn "Mailgun alerts not enabled"
+elif [ -z "${mailguntoken}" ] && [ "${commandname}" == "TEST-ALERT" ]; then
+	fn_print_error_nl "Mailgun token not set"
+	echo -e "* https://docs.linuxgsm.com/alerts/mailgun"
+	fn_script_error "Mailgun token not set"
+fi
+
+if [ "${pushbulletalert}" == "on" ] && [ -n "${pushbullettoken}" ]; then
+	alert_pushbullet.sh
+elif [ "${pushbulletalert}" != "on" ] && [ "${commandname}" == "TEST-ALERT" ]; then
+	fn_print_warn_nl "Pushbullet alerts not enabled"
+	fn_script_log_warn "Pushbullet alerts not enabled"
+elif [ -z "${pushbullettoken}" ] && [ "${commandname}" == "TEST-ALERT" ]; then
+	fn_print_error_nl "Pushbullet token not set"
+	echo -e "* https://docs.linuxgsm.com/alerts/pushbullet"
+	fn_script_error "Pushbullet token not set"
+fi
+
+if [ "${pushoveralert}" == "on" ] && [ -n "${pushoveralert}" ]; then
+	alert_pushover.sh
+elif [ "${pushoveralert}" != "on" ] && [ "${commandname}" == "TEST-ALERT" ]; then
+	fn_print_warn_nl "Pushover alerts not enabled"
+	fn_script_log_warn "Pushover alerts not enabled"
+elif [ -z "${pushovertoken}" ] && [ "${commandname}" == "TEST-ALERT" ]; then
+	fn_print_error_nl "Pushover token not set"
+	echo -e "* https://docs.linuxgsm.com/alerts/pushover"
+	fn_script_error "Pushover token not set"
+fi
+
+if [ "${telegramalert}" == "on" ] && [ -n "${telegramtoken}" ]; then
+	alert_telegram.sh
+elif [ "${telegramalert}" != "on" ] && [ "${commandname}" == "TEST-ALERT" ]; then
+	fn_print_warn_nl "Telegram Messages not enabled"
+	fn_script_log_warn "Telegram Messages not enabled"
+elif [ -z "${telegramtoken}" ] && [ "${commandname}" == "TEST-ALERT" ]; then
+	fn_print_error_nl "Telegram token not set."
+	echo -e "* https://docs.linuxgsm.com/alerts/telegram"
+	fn_script_error "Telegram token not set."
+elif [ -z "${telegramchatid}" ] && [ "${commandname}" == "TEST-ALERT" ]; then
+	fn_print_error_nl "Telegram chat id not set."
+	echo -e "* https://docs.linuxgsm.com/alerts/telegram"
+	fn_script_error "Telegram chat id not set."
+fi
+
+if [ "${rocketchatalert}" == "on" ] && [ -n "${rocketchatalert}" ]; then
+	alert_rocketchat.sh
+elif [ "${rocketchatalert}" != "on" ] && [ "${commandname}" == "TEST-ALERT" ]; then
+	fn_print_warn_nl "Rocketchat alerts not enabled"
+	fn_script_log_warn "Rocketchat alerts not enabled"
+elif [ -z "${rocketchattoken}" ] && [ "${commandname}" == "TEST-ALERT" ]; then
+	fn_print_error_nl "Rocketchat token not set"
+	#echo -e "* https://docs.linuxgsm.com/alerts/slack"
+	fn_script_error "Rocketchat token not set"
+fi
+
+if [ "${slackalert}" == "on" ] && [ -n "${slackalert}" ]; then
+	alert_slack.sh
+elif [ "${slackalert}" != "on" ] && [ "${commandname}" == "TEST-ALERT" ]; then
+	fn_print_warn_nl "Slack alerts not enabled"
+	fn_script_log_warn "Slack alerts not enabled"
+elif [ -z "${slacktoken}" ] && [ "${commandname}" == "TEST-ALERT" ]; then
+	fn_print_error_nl "Slack token not set"
+	echo -e "* https://docs.linuxgsm.com/alerts/slack"
+	fn_script_error "Slack token not set"
+fi

+ 59 - 0
lgsm/modules/alert_discord.sh

@@ -0,0 +1,59 @@
+#!/bin/bash
+# LinuxGSM alert_discord.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Sends Discord alert.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+json=$(
+	cat << EOF
+{
+	"username":"LinuxGSM",
+	"avatar_url":"https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/lgsm/data/alert_discord_logo.jpg",
+	"file":"content",
+	"embeds": [{
+		"color": "2067276",
+		"author": {
+			"name": "${alertemoji} ${alertsubject} ${alertemoji}",
+			"icon_url": "https://raw.githubusercontent.com/${githubuser}/${githubrepo}/${githubbranch}/lgsm/data/alert_discord_logo.jpg"
+		},
+		"title": "${servername}",
+		"description": "${alertbody} \n More info: ${alerturl}",
+		"url": "",
+		"type": "content",
+		"thumbnail": {},
+		"fields": [
+			{
+				"name": "Game",
+				"value": "${gamename}",
+				"inline": true
+			},
+			{
+				"name": "Server IP",
+				"value": "[${alertip}:${port}](https://www.gametracker.com/server_info/${alertip}:${port})",
+				"inline": true
+			},
+			{
+				"name": "Hostname",
+				"value": "${HOSTNAME}",
+				"inline": true
+			}
+		]
+	}]
+}
+EOF
+)
+
+fn_print_dots "Sending Discord alert"
+
+discordsend=$(curl --connect-timeout 10 -sSL -H "Content-Type: application/json" -X POST -d "$(echo -n "${json}" | jq -c .)" "${discordwebhook}")
+
+if [ -n "${discordsend}" ]; then
+	fn_print_fail_nl "Sending Discord alert: ${discordsend}"
+	fn_script_log_fatal "Sending Discord alert: ${discordsend}"
+else
+	fn_print_ok_nl "Sending Discord alert"
+	fn_script_log_pass "Sending Discord alert"
+fi

+ 25 - 0
lgsm/modules/alert_email.sh

@@ -0,0 +1,25 @@
+#!/bin/bash
+# LinuxGSM alert_email.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Sends email alert.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+fn_print_dots "Sending Email alert: ${email}"
+fn_sleep_time
+
+if [ -n "${emailfrom}" ]; then
+	mail -s "${alertsubject}" -r "${emailfrom}" "${email}" < "${alertlog}"
+else
+	mail -s "${alertsubject}" "${email}" < "${alertlog}"
+fi
+exitcode=$?
+if [ "${exitcode}" == "0" ]; then
+	fn_print_ok_nl "Sending Email alert: ${email}"
+	fn_script_log_pass "Sending Email alert: ${email}"
+else
+	fn_print_fail_nl "Sending Email alert: ${email}"
+	fn_script_log_fatal "Sending Email alert: ${email}"
+fi

+ 30 - 0
lgsm/modules/alert_gotify.sh

@@ -0,0 +1,30 @@
+#!/bin/bash
+# LinuxGSM alert_gotify.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Sends Gotify alert.
+
+module_selfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+json=$(
+	cat << EOF
+{
+	"title": "${alertemoji} ${alertsubject} ${alertemoji}",
+	"message": "Server name\n${servername}\n\nMessage\n${alertbody}\n\nGame\n${gamename}\n\nServer IP\n${alertip}:${port}\n\nHostname\n${HOSTNAME}\n\nMore info\n${alerturl}",
+	"priority": 5
+}
+EOF
+)
+
+fn_print_dots "Sending Gotify alert"
+
+gotifysend=$(curl --connect-timeout 10 -sSL "${gotifywebhook}/message"?token="${gotifytoken}" -H "Content-Type: application/json" -X POST -d "$(echo -n "${json}" | jq -c .)")
+
+if [ -n "${gotifysend}" ]; then
+	fn_print_ok_nl "Sending Gotify alert"
+	fn_script_log_pass "Sending Gotify alert"
+else
+	fn_print_fail_nl "Sending Gotify alert: ${gotifysend}"
+	fn_script_log_fatal "Sending Gotify alert: ${gotifysend}"
+fi

+ 29 - 0
lgsm/modules/alert_ifttt.sh

@@ -0,0 +1,29 @@
+#!/bin/bash
+# LinuxGSM alert_ifttt.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Sends IFTTT alert.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+json=$(
+	cat << EOF
+{
+	"value1": "${selfname}",
+	"value2": "${alertemoji} ${alertsubject} ${alertemoji}",
+	"value3": "Message: \n${alertbody}\n\nGame: \n${gamename}\n\nServer name: \n${servername}\n\nHostname: \n${HOSTNAME}\n\nServer IP: \n${alertip}:${port}\n\nMore info: \n${alerturl}"
+}
+EOF
+)
+
+fn_print_dots "Sending IFTTT alert"
+iftttsend=$(curl --connect-timeout 10 -sSL -H "Content-Type: application/json" -X POST -d "$(echo -n "${json}" | jq -c .)" "https://maker.ifttt.com/trigger/${iftttevent}/with/key/${ifttttoken}" | grep "Bad Request")
+
+if [ -n "${iftttsend}" ]; then
+	fn_print_fail_nl "Sending IFTTT alert: ${pushbulletsend}"
+	fn_script_log_fatal "Sending IFTTT alert: ${pushbulletsend}"
+else
+	fn_print_ok_nl "Sending IFTTT alert"
+	fn_script_log_pass "Sent IFTTT alert"
+fi

+ 32 - 0
lgsm/modules/alert_mailgun.sh

@@ -0,0 +1,32 @@
+#!/bin/bash
+# LinuxGSM alert_mailgun.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Sends Mailgun Email alert.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+if [ "${mailgunapiregion}" == "eu" ]; then
+	mailgunapiurl="https://api.eu.mailgun.net"
+else
+	mailgunapiurl="https://api.mailgun.net"
+fi
+
+fn_print_dots "Sending Email alert: Mailgun: ${mailgunemail}"
+
+mailgunsend=$(curl --connect-timeout 10 -s --user "api:${mailguntoken}" \
+	-F from="LinuxGSM <${mailgunemailfrom}>" \
+	-F to="LinuxGSM Admin <${mailgunemail}>" \
+	-F subject="${alertemoji} ${alertsubject} ${alertemoji}" \
+	-F o:tag='alert' \
+	-F o:tag='LinuxGSM' \
+	-F text="$(cat "${alertlog}")" "${mailgunapiurl}/v3/${mailgundomain}/messages")
+
+if [ -z "${mailgunsend}" ]; then
+	fn_print_fail_nl "Sending Email alert: Mailgun: ${mailgunemail}"
+	fn_script_log_fatal "Sending Email alert: Mailgun: ${mailgunemail}"
+else
+	fn_print_ok_nl "Sending Email alert: Mailgun: ${mailgunemail}"
+	fn_script_log_pass "Sending Email alert: Mailgun: ${mailgunemail}"
+fi

+ 30 - 0
lgsm/modules/alert_pushbullet.sh

@@ -0,0 +1,30 @@
+#!/bin/bash
+# LinuxGSM alert_pushbullet.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Sends Pushbullet Messenger alert.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+json=$(
+	cat << EOF
+{
+	"channel_tag": "${channeltag}",
+	"type": "note",
+	"title": "${alertemoji} ${alertsubject} ${alertemoji}",
+	"body": "Server name\n${servername}\n\nMessage\n${alertbody}\n\nGame\n${gamename}\n\nServer IP\n${alertip}:${port}\n\nHostname\n${HOSTNAME}\n\nMore info\n${alerturl}"
+}
+EOF
+)
+
+fn_print_dots "Sending Pushbullet alert"
+pushbulletsend=$(curl --connect-timeout 10 -sSL -u """${pushbullettoken}"":" -H "Content-Type: application/json" -X POST -d "$(echo -n "${json}" | jq -c .)" "https://api.pushbullet.com/v2/pushes" | grep "error_code")
+
+if [ -n "${pushbulletsend}" ]; then
+	fn_print_fail_nl "Sending Pushbullet alert: ${pushbulletsend}"
+	fn_script_log_fatal "Sending Pushbullet alert: ${pushbulletsend}"
+else
+	fn_print_ok_nl "Sending Pushbullet alert"
+	fn_script_log_pass "Sent Pushbullet alert"
+fi

+ 33 - 0
lgsm/modules/alert_pushover.sh

@@ -0,0 +1,33 @@
+#!/bin/bash
+# LinuxGSM alert_pushover.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Sends Pushover alert.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+fn_print_dots "Sending Pushover alert"
+
+# Different alerts are given different priorities and notification sounds.
+if [ "${alertsound}" == "1" ]; then
+	alertsound=""
+	alertpriority="0"
+elif [ "${alertsound}" == "2" ]; then
+	# restarted.
+	alertsound="siren"
+	alertpriority="1"
+else
+	alertsound=""
+	alertpriority="0"
+fi
+
+pushoversend=$(curl --connect-timeout 10 -sS -F token="${pushovertoken}" -F user="${pushoveruserkey}" -F html="1" -F sound="${alertsound}" -F priority="${alertpriority}" -F title="${alertemoji} ${alertsubject} ${alertemoji}" -F message=" <b>Server name</b><br>${servername}<br><br><b>Message</b><br>${alertbody}<br><br><b>Game</b><br>${gamename}<br><br><b>Server IP</b><br><a href='https://www.gametracker.com/server_info/${alertip}:${port}'>${alertip}:${port}</a><br><br><b>Hostname</b><br>${HOSTNAME}<br><br><b>More info</b><br><a href='${alerturl}'>${alerturl}</a>" "https://api.pushover.net/1/messages.json" | grep errors)
+
+if [ -n "${pushoversend}" ]; then
+	fn_print_fail_nl "Sending Pushover alert: ${pushoversend}"
+	fn_script_log_fatal "Sending Pushover alert: ${pushoversend}"
+else
+	fn_print_ok_nl "Sending Pushover alert"
+	fn_script_log_pass "Sent Pushover alert"
+fi

+ 50 - 0
lgsm/modules/alert_rocketchat.sh

@@ -0,0 +1,50 @@
+#!/bin/bash
+# LinuxGSM alert_rocketchat.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Sends Rocketchat alert.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+json=$(
+	cat << EOF
+{
+	"alias": "LinuxGSM",
+	"text": "*${alertemoji} ${alertsubject} ${alertemoji}* \n *${servername}* \n ${alertbody} \n More info: ${alerturl}",
+	"attachments": [
+		{
+			"fields": [
+				{
+					"short": true,
+					"title": "Game:",
+					"value": "${gamename}"
+				},
+				{
+					"short": true,
+					"title": "Server IP:",
+					"value": "${alertip}:${port}"
+				},
+				{
+					"short": true,
+					"title": "Hostname:",
+					"value": "${HOSTNAME}"
+				}
+			]
+		}
+	]
+}
+EOF
+)
+
+fn_print_dots "Sending Rocketchat alert"
+
+rocketchatsend=$(curl --connect-timeout 10 -sSL -H "Content-Type: application/json" -X POST -d "$(echo -n "${json}" | jq -c .)" "${rocketchatwebhook}")
+
+if [ -n "${rocketchatsend}" ]; then
+	fn_print_ok_nl "Sending Rocketchat alert"
+	fn_script_log_pass "Sending Rocketchat alert"
+else
+	fn_print_fail_nl "Sending Rocketchat alert: ${rocketchatsend}"
+	fn_script_log_fatal "Sending Rocketchat alert: ${rocketchatsend}"
+fi

+ 75 - 0
lgsm/modules/alert_slack.sh

@@ -0,0 +1,75 @@
+#!/bin/bash
+# LinuxGSM alert_slack.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Sends Slack alert.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+json=$(
+	cat << EOF
+{
+		"attachments": [
+			{
+				"color": "#36a64f",
+				"blocks": [
+					{
+										"type": "section",
+										"text": {
+												"type": "mrkdwn",
+												"text": "*LinuxGSM Alert*"
+										}
+								},
+								{
+										"type": "section",
+										"text": {
+												"type": "mrkdwn",
+												"text": "*${alertemoji} ${alertsubject}* \n ${alertbody}"
+										}
+								},
+								{
+										"type": "divider"
+								},
+								{
+										"type": "section",
+										"fields": [
+												{
+														"type": "mrkdwn",
+														"text": "*Game:* \n ${gamename}"
+												},
+												{
+														"type": "mrkdwn",
+														"text": "*Server IP:* \n ${alertip}:${port}"
+												},
+												{
+														"type": "mrkdwn",
+														"text": "*Server Name:* \n ${servername}"
+												}
+										]
+								},
+					 {
+										"type": "section",
+										"text": {
+														"type": "mrkdwn",
+														"text": "Hostname: ${HOSTNAME} / More info: ${alerturl}"
+										}
+								}
+						]
+			}
+		]
+}
+EOF
+)
+
+fn_print_dots "Sending Slack alert"
+
+slacksend=$(curl --connect-timeout 10 -sSL -H "Content-Type: application/json" -X POST -d "$(echo -n "${json}" | jq -c .)" "${slackwebhook}")
+
+if [ "${slacksend}" == "ok" ]; then
+	fn_print_ok_nl "Sending Slack alert"
+	fn_script_log_pass "Sending Slack alert"
+else
+	fn_print_fail_nl "Sending Slack alert: ${slacksend}"
+	fn_script_log_fatal "Sending Slack alert: ${slacksend}"
+fi

+ 30 - 0
lgsm/modules/alert_telegram.sh

@@ -0,0 +1,30 @@
+#!/bin/bash
+# LinuxGSM alert_telegram.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Sends Telegram Messenger alert.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+json=$(
+	cat << EOF
+{
+	"chat_id": "${telegramchatid}",
+	"parse_mode": "HTML",
+	"text": "<b>${alertemoji} ${alertsubject} ${alertemoji}</b>\n\n<b>Server name</b>\n${servername}\n\n<b>Message</b>\n${alertbody}\n\n<b>Game</b>\n${gamename}\n\n<b>Server IP</b>\n<a href='https://www.gametracker.com/server_info/${alertip}:${port}'>${alertip}:${port}</a>\n\n<b>Hostname</b>\n${HOSTNAME}\n\n<b>More info</b>\n<a href='${alerturl}'>${alerturl}</a>",
+	"disable_web_page_preview": "yes"
+}
+EOF
+)
+
+fn_print_dots "Sending Telegram alert"
+telegramsend=$(curl --connect-timeout 10 -sSL -H "Content-Type: application/json" -X POST -d "$(echo -n "${json}" | jq -c .)" ${curlcustomstring} "https://${telegramapi}/bot${telegramtoken}/sendMessage" | grep "error_code")
+
+if [ -n "${telegramsend}" ]; then
+	fn_print_fail_nl "Sending Telegram alert: ${telegramsend}"
+	fn_script_log_fatal "Sending Telegram alert: ${telegramsend}"
+else
+	fn_print_ok_nl "Sending Telegram alert"
+	fn_script_log_pass "Sent Telegram alert"
+fi

+ 101 - 0
lgsm/modules/check.sh

@@ -0,0 +1,101 @@
+#!/bin/bash
+# LinuxGSM check.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Overall module for managing checks.
+# Runs checks that will either halt on or fix an issue.
+
+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.
+
+if [ "${commandname}" != "INSTALL" ]; then
+	check_root.sh
+fi
+
+if [ "${commandname}" != "UPDATE-LGSM" ]; then
+	check_version.sh
+fi
+
+check_tmuxception.sh
+
+if [ "$(whoami)" != "root" ] || [ -f /.dockerenv ]; then
+	if [ "${commandname}" != "MONITOR" ]; then
+		check_permissions.sh
+	fi
+fi
+
+if [ "${commandname}" != "INSTALL" ] && [ "${commandname}" != "UPDATE-LGSM" ] && [ "${commandname}" != "DETAILS" ] && [ "${commandname}" != "POST-DETAILS" ]; then
+	check_system_dir.sh
+fi
+
+allowed_commands_array=(START DEBUG)
+for allowed_command in "${allowed_commands_array[@]}"; do
+	if [ "${allowed_command}" == "${commandname}" ]; then
+		check_executable.sh
+	fi
+done
+
+if [ "$(whoami)" != "root" ] || [ -f /.dockerenv ]; then
+	allowed_commands_array=(DEBUG START INSTALL)
+	for allowed_command in "${allowed_commands_array[@]}"; do
+		if [ "${allowed_command}" == "${commandname}" ]; then
+			check_glibc.sh
+		fi
+	done
+fi
+
+allowed_commands_array=(BACKUP CONSOLE DEBUG DETAILS MAP-COMPRESSOR FASTDL MODS-INSTALL MODS-REMOVE MODS-UPDATE MONITOR POST-DETAILS RESTART START STOP TEST-ALERT CHANGE-PASSWORD UPDATE UPDATE-LGSM VALIDATE WIPE)
+for allowed_command in "${allowed_commands_array[@]}"; do
+	if [ "${allowed_command}" == "${commandname}" ]; then
+		check_logs.sh
+	fi
+done
+
+allowed_commands_array=(DEBUG START)
+for allowed_command in "${allowed_commands_array[@]}"; do
+	if [ "${allowed_command}" == "${commandname}" ]; then
+		check_deps.sh
+	fi
+done
+
+allowed_commands_array=(CONSOLE DEBUG MONITOR START STOP)
+for allowed_command in "${allowed_commands_array[@]}"; do
+	if [ "${allowed_command}" == "${commandname}" ]; then
+		check_config.sh
+	fi
+done
+
+allowed_commands_array=(DEBUG DETAILS DEV-QUERY-RAW MONITOR POST_DETAILS START STOP POST-DETAILS)
+for allowed_command in "${allowed_commands_array[@]}"; do
+	if [ "${allowed_command}" == "${commandname}" ]; then
+		if [ -z "${installflag}" ]; then
+			check_ip.sh
+		fi
+	fi
+done
+
+allowed_commands_array=(DEBUG START UPDATE VALIDATE CHECK-UPDATE)
+for allowed_command in "${allowed_commands_array[@]}"; do
+	if [ "${allowed_command}" == "${commandname}" ]; then
+		if [ "${appid}" ]; then
+			check_steamcmd.sh
+		fi
+	fi
+done
+
+allowed_commands_array=(CHANGE-PASSWORD DETAILS MONITOR START STOP UPDATE VALIDATE POST-DETAILS)
+for allowed_command in "${allowed_commands_array[@]}"; do
+	if [ "${allowed_command}" == "${commandname}" ]; then
+		check_status.sh
+	fi
+done
+
+allowed_commands_array=(DEBUG START INSTALL)
+for allowed_command in "${allowed_commands_array[@]}"; do
+	if [ "${allowed_command}" == "${commandname}" ]; then
+		check_system_requirements.sh
+	fi
+done

+ 35 - 0
lgsm/modules/check_config.sh

@@ -0,0 +1,35 @@
+#!/bin/bash
+# LinuxGSM check_config.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Checks if the server config is missing and warns the user if needed.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+if [ -n "${servercfgfullpath}" ] && [ ! -f "${servercfgfullpath}" ]; then
+	fn_print_dots ""
+	fn_print_warn_nl "Configuration file missing!"
+	echo -e "${servercfgfullpath}"
+	fn_script_log_warn "Configuration file missing!"
+	fn_script_log_warn "${servercfgfullpath}"
+	install_config.sh
+fi
+
+if [ "${shortname}" == "rust" ] && [ -v rconpassword ] && [ -z "${rconpassword}" ]; then
+	fn_print_dots ""
+	fn_print_fail_nl "RCON password is not set"
+	fn_script_log_warn "RCON password is not set"
+elif [ -v rconpassword ] && [ "${rconpassword}" == "CHANGE_ME" ]; then
+	fn_print_dots ""
+	fn_print_warn_nl "Default RCON Password detected"
+	fn_script_log_warn "Default RCON Password detected"
+fi
+
+if [ "${shortname}" == "vh" ] && [ -z "${serverpassword}" ]; then
+	fn_print_fail_nl "serverpassword is not set"
+	fn_script_log_fatal "serverpassword is not set"
+elif [ "${shortname}" == "vh" ] && [ "${#serverpassword}" -le "4" ]; then
+	fn_print_fail_nl "serverpassword is to short (min 5 chars)"
+	fn_script_log_fatal "serverpassword is to short (min 5 chars)"
+fi

+ 363 - 0
lgsm/modules/check_deps.sh

@@ -0,0 +1,363 @@
+#!/bin/bash
+# LinuxGSM check_deps.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Checks and installs missing dependencies.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+fn_install_mono_repo() {
+	if [ "${autodepinstall}" == "0" ]; then
+		fn_print_information_nl "Automatically adding Mono repository."
+		fn_script_log_info "Automatically adding Mono repository."
+		echo -en ".\r"
+		sleep 1
+		echo -en "..\r"
+		sleep 1
+		echo -en "...\r"
+		sleep 1
+		echo -en "   \r"
+		if [ "${distroid}" == "ubuntu" ]; then
+			if [ "${distroversion}" == "20.04" ]; then
+				cmd="sudo apt install gnupg ca-certificates;sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF;echo 'deb https://download.mono-project.com/repo/ubuntu stable-focal main' | sudo tee /etc/apt/sources.list.d/mono-official-stable.list;sudo apt update"
+			elif [ "${distroversion}" == "18.04" ]; then
+				cmd="sudo apt install gnupg ca-certificates;sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF;echo 'deb https://download.mono-project.com/repo/ubuntu stable-bionic main' | sudo tee /etc/apt/sources.list.d/mono-official-stable.list;sudo apt update"
+			elif [ "${distroversion}" == "16.04" ]; then
+				cmd="sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF;sudo apt install apt-transport-https ca-certificates;echo 'deb https://download.mono-project.com/repo/ubuntu stable-xenial main' | sudo tee /etc/apt/sources.list.d/mono-official-stable.list;sudo apt update"
+			else
+				monoautoinstall="1"
+			fi
+		elif [ "${distroid}" == "debian" ]; then
+			if [ "${distroversion}" == "10" ]; then
+				cmd="sudo apt install apt-transport-https dirmngr gnupg ca-certificates;sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF;echo 'deb https://download.mono-project.com/repo/debian stable-buster main' | sudo tee /etc/apt/sources.list.d/mono-official-stable.list;sudo apt update"
+			elif [ "${distroversion}" == "9" ]; then
+				cmd="sudo apt install apt-transport-https dirmngr gnupg ca-certificates;sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF;echo 'deb https://download.mono-project.com/repo/debian stable-stretch main' | sudo tee /etc/apt/sources.list.d/mono-official-stable.list;sudo apt update"
+			else
+				monoautoinstall="1"
+			fi
+		elif [ "${distroid}" == "centos" ] || [ "${distroid}" == "almalinux" ] || [ "${distroid}" == "rocky" ]; then
+			if [ "${distroversion}" == "8" ]; then
+				cmd="sudo rpmkeys --import 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF';su -c 'curl https://download.mono-project.com/repo/centos8-stable.repo | tee /etc/yum.repos.d/mono-centos8-stable.repo'"
+			elif [ "${distroversion}" == "7" ]; then
+				cmd="sudo rpmkeys --import 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF';su -c 'curl https://download.mono-project.com/repo/centos7-stable.repo | tee /etc/yum.repos.d/mono-centos7-stable.repo'"
+			else
+				monoautoinstall="1"
+			fi
+		elif [ "${distroid}" == "fedora" ]; then
+			if [ "${distroversion}" -ge "29" ]; then
+				cmd="sudo rpm --import 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF';su -c 'curl https://download.mono-project.com/repo/centos8-stable.repo | tee /etc/yum.repos.d/mono-centos8-stable.repo';dnf update"
+			else
+				cmd="sudo rpm --import 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF';su -c 'curl https://download.mono-project.com/repo/centos7-stable.repo | tee /etc/yum.repos.d/mono-centos7-stable.repo';dnf update"
+			fi
+		else
+			monoautoinstall="1"
+		fi
+
+		# Run the mono repo install.
+		eval "${cmd}"
+
+		# Did Mono repo install correctly?
+		if [ "${monoautoinstall}" != "1" ]; then
+			if [ $? != 0 ]; then
+				fn_print_failure_nl "Unable to install Mono repository."
+				fn_script_log_fatal "Unable to install Mono repository."
+			else
+				fn_print_complete_nl "Installing Mono repository completed."
+				fn_script_log_pass "Installing Mono repository completed."
+			fi
+		fi
+
+		# Mono can not be auto installed with this distro.
+		if [ "${monoautoinstall}" == "1" ]; then
+			fn_print_warning_nl "Mono auto install not available for ${distroname}."
+			echo -e "Follow instructions on Mono website to install."
+			echo -e "https://www.mono-project.com/download/stable/#download-lin"
+			fn_script_log_warn "Unable to install Mono repository. Mono auto install not available for ${distroname}."
+		fi
+
+	else
+		fn_print_information_nl "Installing Mono repository."
+		fn_print_warning_nl "$(whoami) does not have sudo access."
+		echo -e "Follow instructions on Mono website to install."
+		echo -e "https://www.mono-project.com/download/stable/#download-lin"
+		fn_script_log_warn "Unable to install Mono repository. $(whoami) does not have sudo access."
+	fi
+}
+
+fn_deps_email() {
+	# Adds postfix to required dependencies if email alert is enabled.
+	if [ "${emailalert}" == "on" ]; then
+		if [ -f /usr/bin/mailx ]; then
+			if [ -d /etc/exim4 ]; then
+				array_deps_required+=(exim4)
+			elif [ -d /etc/sendmail ]; then
+				array_deps_required+=(sendmail)
+			elif [ "$(command -v dpkg-query 2> /dev/null)" ]; then
+				array_deps_required+=(mailutils postfix)
+			elif [ "$(command -v rpm 2> /dev/null)" ]; then
+				array_deps_required+=(mailx postfix)
+			fi
+		else
+			if [ "$(command -v dpkg-query 2> /dev/null)" ]; then
+				array_deps_required+=(mailutils postfix)
+			elif [ "$(command -v rpm 2> /dev/null)" ]; then
+				array_deps_required+=(mailx postfix)
+			fi
+		fi
+	fi
+}
+
+fn_install_missing_deps() {
+	# If any dependencies are not installed.
+	if [ "${#array_deps_missing[*]}" != "0" ]; then
+		if [ "${commandname}" == "INSTALL" ]; then
+			fn_print_warning_nl "Missing dependencies: ${red}${array_deps_missing[*]}${default}"
+			fn_script_log_warn "Missing dependencies: ${array_deps_missing[*]}"
+		else
+			fn_print_dots "Missing dependencies"
+			fn_print_warn "Missing dependencies: ${red}${array_deps_missing[*]}${default}"
+			fn_script_log_warn "Missing dependencies: ${array_deps_missing[*]}"
+		fi
+		fn_sleep_time
+
+		# Attempt automatic dependency installation
+		if [ "${autoinstall}" == "1" ]; then
+			sudo -n true > /dev/null 2>&1
+		else
+			sudo -v > /dev/null 2>&1
+		fi
+		autodepinstall="$?"
+
+		if [ "${monostatus}" == "1" ]; then
+			fn_install_mono_repo
+		fi
+
+		if [ "${commandname}" == "INSTALL" ]; then
+			if [ "${autodepinstall}" == "0" ]; then
+				fn_print_information_nl "$(whoami) has sudo access."
+				fn_script_log_info "$(whoami) has sudo access."
+			else
+				fn_print_warning_nl "$(whoami) does not have sudo access. Manually install dependencies."
+				fn_script_log_warn "$(whoami) does not have sudo access. Manually install dependencies."
+			fi
+		fi
+
+		# Add sudo dpkg --add-architecture i386 if using i386 packages.
+		if [ "$(command -v dpkg-query 2> /dev/null)" ]; then
+			if printf '%s\n' "${array_deps_required[@]}" | grep -q -P 'i386'; then
+				i386installcommand="sudo dpkg --add-architecture i386; "
+			fi
+		fi
+
+		# If automatic dependency install is available
+		if [ "${autodepinstall}" == "0" ]; then
+			fn_print_information_nl "Automatically installing missing dependencies."
+			fn_script_log_info "Automatically installing missing dependencies."
+			echo -en ".\r"
+			sleep 1
+			echo -en "..\r"
+			sleep 1
+			echo -en "...\r"
+			sleep 1
+			echo -en "   \r"
+			if [ "$(command -v dpkg-query 2> /dev/null)" ]; then
+				cmd="echo steamcmd steam/question select \"I AGREE\" | sudo debconf-set-selections; echo steamcmd steam/license note '' | sudo debconf-set-selections; ${i386installcommand}sudo apt-get update; sudo apt-get -y install ${array_deps_missing[*]}"
+				eval "${cmd}"
+			elif [ "$(command -v dnf 2> /dev/null)" ]; then
+				cmd="sudo dnf -y install ${array_deps_missing[*]}"
+				eval "${cmd}"
+			elif [ "$(command -v yum 2> /dev/null)" ]; then
+				cmd="sudo yum -y install ${array_deps_missing[*]}"
+				eval "${cmd}"
+			fi
+			autodepinstall="$?"
+
+			# If auto install passes remove steamcmd install failure.
+			if [ "${autodepinstall}" == "0" ]; then
+				unset steamcmdfail
+			fi
+		fi
+
+		# If automatic dependency install is unavailable.
+		if [ "${autodepinstall}" != "0" ]; then
+			if [ "$(command -v dpkg-query 2> /dev/null)" ]; then
+				echo -e "${i386installcommand}sudo apt update; sudo apt install ${array_deps_missing[*]}"
+			elif [ "$(command -v dnf 2> /dev/null)" ]; then
+				echo -e "sudo dnf install ${array_deps_missing[*]}"
+			elif [ "$(command -v yum 2> /dev/null)" ]; then
+				echo -e "sudo yum install ${array_deps_missing[*]}"
+			fi
+		fi
+
+		if [ "${steamcmdfail}" ]; then
+			if [ "${commandname}" == "INSTALL" ]; then
+				fn_print_failure_nl "Missing dependencies required to run SteamCMD."
+				fn_script_log_fatal "Missing dependencies required to run SteamCMD."
+				core_exit.sh
+			else
+				fn_print_error_nl "Missing dependencies required to run SteamCMD."
+				fn_script_log_error "Missing dependencies required to run SteamCMD."
+			fi
+		fi
+
+	else
+		if [ "${commandname}" == "INSTALL" ]; then
+			fn_print_information_nl "Required dependencies already installed."
+			fn_script_log_info "Required dependencies already installed."
+		fi
+	fi
+}
+
+fn_check_loop() {
+	# Loop though required depenencies checking if they are installed.
+	for deptocheck in ${array_deps_required[*]}; do
+		fn_deps_detector
+	done
+
+	# user will be informed of any missing dependencies.
+	fn_install_missing_deps
+}
+
+# Checks if dependency is installed or not.
+fn_deps_detector() {
+	## Check.
+	# SteamCMD: Will be removed from required array if no appid is present or non-free repo is not available.
+	# This will cause SteamCMD to be installed using tar.
+	if [ "${deptocheck}" == "libsdl2-2.0-0:i386" ] && [ -z "${appid}" ]; then
+		array_deps_required=("${array_deps_required[@]/libsdl2-2.0-0:i386/}")
+		steamcmdstatus=1
+	elif [ "${deptocheck}" == "steamcmd" ] && [ -z "${appid}" ]; then
+		array_deps_required=("${array_deps_required[@]/steamcmd/}")
+		steamcmdstatus=1
+	elif [ "${deptocheck}" == "steamcmd" ] && [ "${distroid}" == "debian" ] && ! grep -qE "^deb .*non-free" /etc/apt/sources.list; then
+		array_deps_required=("${array_deps_required[@]/steamcmd/}")
+		steamcmdstatus=1
+	# Java: Added for users using Oracle JRE to bypass check.
+	elif [[ ${deptocheck} == "openjdk"* ]] || [[ ${deptocheck} == "java"* ]]; then
+		# Is java already installed?
+		if [ -n "${javaversion}" ]; then
+			# Added for users using Oracle JRE to bypass check.
+			depstatus=0
+			deptocheck="${javaversion}"
+		else
+			depstatus=1
+		fi
+	# Mono: A Mono repo needs to be installed.
+	elif [ "${deptocheck}" == "mono-complete" ]; then
+		if [ -n "${monoversion}" ] && [ "${monoversion}" -ge "5" ]; then
+			# Mono >= 5.0.0 already installed.
+			depstatus=0
+			monostatus=0
+		else
+			# Mono not installed or installed Mono < 5.0.0.
+			depstatus=1
+			monostatus=1
+		fi
+	elif [ "$(command -v dpkg-query 2> /dev/null)" ]; then
+		dpkg-query -W -f='${Status}' "${deptocheck}" 2> /dev/null | grep -q -P '^install ok installed'
+		depstatus=$?
+	elif [ "$(command -v dnf 2> /dev/null)" ]; then
+		dnf list installed "${deptocheck}" > /dev/null 2>&1
+		depstatus=$?
+	elif [ "$(command -v rpm 2> /dev/null)" ]; then
+		rpm -q "${deptocheck}" > /dev/null 2>&1
+		depstatus=$?
+	fi
+
+	# Outcome of Check.
+	if [ "${steamcmdstatus}" == "1" ]; then
+		# If SteamCMD is not available in repo dont check for it.
+		unset steamcmdstatus
+	elif [ "${depstatus}" == "0" ]; then
+		# If dependency is found.
+		missingdep=0
+		if [ "${commandname}" == "INSTALL" ]; then
+			echo -e "${green}${deptocheck}${default}"
+			sleep 0.1
+		fi
+	elif [ "${depstatus}" != "0" ]; then
+		# If dependency is not found.
+		missingdep=1
+		if [ "${commandname}" == "INSTALL" ]; then
+			echo -e "${red}${deptocheck}${default}"
+			sleep 0.1
+		fi
+		# If SteamCMD requirements are not met install will fail.
+		if [ -n "${appid}" ]; then
+			for steamcmddeptocheck in ${array_deps_required_steamcmd[*]}; do
+				if [ "${deptocheck}" != "steamcmd" ] && [ "${deptocheck}" == "${steamcmddeptocheck}" ]; then
+					steamcmdfail=1
+				fi
+			done
+		fi
+	fi
+	unset depstatus
+
+	# Missing dependencies are added to array_deps_missing.
+	if [ "${missingdep}" == "1" ]; then
+		array_deps_missing+=("${deptocheck}")
+	fi
+}
+
+if [ "${commandname}" == "INSTALL" ]; then
+	if [ "$(whoami)" == "root" ] && [ ! -f /.dockerenv ]; then
+		echo -e ""
+		echo -e "${lightyellow}Checking Dependencies as root${default}"
+		echo -e "================================="
+		fn_print_information_nl "Checking any missing dependencies for ${gamename} server only."
+		fn_print_information_nl "This will NOT install a ${gamename} server."
+		fn_sleep_time
+	else
+		echo -e ""
+		echo -e "${lightyellow}Checking Dependencies${default}"
+		echo -e "================================="
+	fi
+fi
+
+# Will warn user if their distro is no longer supported by the vendor.
+if [ -n "${distrosupport}" ]; then
+	if [ "${distrosupport}" == "unsupported" ]; then
+		fn_print_warning_nl "${distroname} is no longer supported by the vendor. Upgrading is recommended."
+		fn_script_log_warn "${distroname} is no longer supported by the vendor. Upgrading is recommended."
+	fi
+fi
+
+info_distro.sh
+
+if [ ! -f "${tmpdir}/dependency-no-check.tmp" ] && [ ! -f "${datadir}/${distroid}-${distroversioncsv}.csv" ]; then
+	# Check that the distro dependency csv file exists.
+	fn_check_file_github "lgsm/data" "${distroid}-${distroversioncsv}.csv"
+	if [ -n "${checkflag}" ] && [ "${checkflag}" == "0" ]; then
+		fn_fetch_file_github "lgsm/data" "${distroid}-${distroversioncsv}.csv" "lgsm/data" "chmodx" "norun" "noforce" "nohash"
+	fi
+fi
+
+# If the file successfully downloaded run the dependency check.
+if [ -f "${datadir}/${distroid}-${distroversioncsv}.csv" ]; then
+	depall=$(awk -F, '$1=="all" {$1=""; print $0}' "${datadir}/${distroid}-${distroversioncsv}.csv")
+	depsteamcmd=$(awk -F, '$1=="steamcmd" {$1=""; print $0}' "${datadir}/${distroid}-${distroversioncsv}.csv")
+	depshortname=$(awk -v shortname="${shortname}" -F, '$1==shortname {$1=""; print $0}' "${datadir}/${distroid}-${distroversioncsv}.csv")
+
+	# Generate array of missing deps.
+	array_deps_missing=()
+
+	array_deps_required=("${depall} ${depsteamcmd} ${depshortname}")
+	array_deps_required_steamcmd=("${depsteamcmd}")
+	fn_deps_email
+	# Unique sort dependency array.
+	IFS=" " read -r -a array_deps_required <<< "$(echo "${array_deps_required[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' ')"
+
+	fn_check_loop
+# Warn the user that dependency checking is unavailable for their distro.
+elif [ "${commandname}" == "INSTALL" ] || [ -n "${checkflag}" ] && [ "${checkflag}" != "0" ]; then
+	fn_print_warning_nl "LinuxGSM dependency checking currently unavailable for ${distroname}."
+	# Prevent future dependency checking if unavailable for the distro.
+	echo "${version}" > "${tmpdir}/dependency-no-check.tmp"
+elif [ -f "${tmpdir}/dependency-no-check.tmp" ]; then
+	# Allow LinuxGSM to try a dependency check if LinuxGSM has been recently updated.
+	nocheckversion=$(cat "${tmpdir}/dependency-no-check.tmp")
+	if [ "${version}" != "${nocheckversion}" ]; then
+		rm -f "${tmpdir:?}/dependency-no-check.tmp"
+	fi
+fi

+ 20 - 0
lgsm/modules/check_executable.sh

@@ -0,0 +1,20 @@
+#!/bin/bash
+# LinuxGSM check_executable.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Checks if server executable exists.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+# Check if executable exists
+execname=$(basename "${executable}")
+if [ ! -f "${executabledir}/${execname}" ]; then
+	fn_print_fail_nl "executable was not found"
+	echo -e "* ${executabledir}/${execname}"
+	if [ -d "${lgsmlogdir}" ]; then
+		fn_script_log_fatal "Executable was not found: ${executabledir}/${execname}"
+	fi
+	unset exitbypass
+	core_exit.sh
+fi

+ 29 - 0
lgsm/modules/check_glibc.sh

@@ -0,0 +1,29 @@
+#!/bin/bash
+# LinuxGSM check_glibc.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Checks if the server has the correct Glibc version.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+info_distro.sh
+
+if [ "${glibc}" == "null" ]; then
+	# Glibc is not required.
+	:
+elif [ -z "${glibc}" ]; then
+	fn_print_dots "glibc"
+	fn_print_error_nl "glibc requirement unknown"
+	fn_script_log_error "glibc requirement unknown"
+elif [ "$(printf '%s\n'${glibc}'\n' "${glibcversion}" | sort -V | head -n 1)" != "${glibc}" ]; then
+	fn_print_dots "glibc"
+	fn_print_error_nl "glibc requirements not met"
+	fn_script_log_error "glibc requirements not met"
+	echo -en "\n"
+	echo -e "	* glibc required: ${glibc}"
+	echo -e "	* glibc installed: ${red}${glibcversion}${default}"
+	echo -en "\n"
+	fn_print_information_nl "distro upgrade is required"
+	fn_script_log_info "distro upgrade is required"
+fi

+ 63 - 0
lgsm/modules/check_ip.sh

@@ -0,0 +1,63 @@
+#!/bin/bash
+# LinuxGSM check_ip.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# 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".
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+info_game.sh
+
+ip_commands_array=("ip" "/bin/ip" "/usr/sbin/ip")
+for ip_command in "${ip_commands_array[@]}"; do
+	if [ "$(command -v "${ip_command}" 2> /dev/null)" ]; then
+		ipcommand="${ip_command}"
+		break
+	fi
+done
+
+ethtool_commands_array=("ethtool" "/bin/ethtool" "/usr/sbin/ethtool")
+for ethtool_command in "${ethtool_commands_array[@]}"; do
+	if [ "$(command -v "${ethtool_command}" 2> /dev/null)" ]; then
+		ethtoolcommand="${ethtool_command}"
+		break
+	fi
+done
+
+mapfile -t current_ips < <(${ipcommand} -o -4 addr | awk '{print $4}' | grep -oe '\([0-9]\{1,3\}\.\?\)\{4\}' | sort -u | grep -v 127.0.0)
+
+function fn_is_valid_ip() {
+	local ip="${1}"
+	# excluding 0.* ips also
+	grep -qEe '^[1-9]+[0-9]*\.[0-9]+\.[0-9]+\.[0-9]+$' <<< "${ip}"
+}
+
+# Check if server has multiple IP addresses.
+
+# If the IP variable has been set by user.
+if fn_is_valid_ip "${ip}"; then
+	queryips=("${ip}")
+	httpip=("${ip}")
+	telnetip=("${ip}")
+# If the game config has an IP set.
+elif fn_is_valid_ip "${configip}"; then
+	queryips=("${configip}")
+	ip="${configip}"
+	httpip=("${configip}")
+	telnetip=("${configip}")
+# If there is only 1 server IP address.
+# Some IP details can automatically use the one IP.
+elif [ "${#current_ips[@]}" == "1" ]; then
+	queryips=("127.0.0.1" "${current_ips[@]}")
+	ip="0.0.0.0"
+	httpip=("${current_ips[@]}")
+	telnetip=("${current_ips[@]}")
+# If no ip is set by the user and server has more than one IP.
+else
+	queryips=("127.0.0.1" "${current_ips[@]}")
+	ip="0.0.0.0"
+	httpip=("${ip}")
+	telnetip=("${ip}")
+fi

+ 26 - 0
lgsm/modules/check_last_update.sh

@@ -0,0 +1,26 @@
+#!/bin/bash
+# LinuxGSM check_last_update.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Checks lock file to see when last update happened.
+# Will reboot server if instance not rebooted since update.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+if [ -f "${lockdir}/${selfname}-laststart.lock" ]; then
+	laststart=$(cat "${lockdir}/${selfname}-laststart.lock")
+fi
+if [ -f "${lockdir}/lastupdate.lock" ]; then
+	lastupdate=$(cat "${lockdir}/lastupdate.lock")
+fi
+
+check_status.sh
+if [ -f "${lockdir}/lastupdate.lock" ] && [ "${status}" != "0" ]; then
+	if [ ! -f "${lockdir}/${selfname}-laststart.lock" ] || [ "${laststart}" -lt "${lastupdate}" ]; then
+		fn_print_info "${selfname} has not been restarted since last update"
+		fn_script_log_info "${selfname} has not been restarted since last update"
+		command_restart.sh
+		fn_firstcommand_reset
+	fi
+fi

+ 26 - 0
lgsm/modules/check_logs.sh

@@ -0,0 +1,26 @@
+#!/bin/bash
+# LinuxGSM check_logs.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Checks if log files exist.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+fn_check_logs() {
+	fn_print_dots "Checking for log files"
+	fn_print_info_nl "Checking for log files: Creating log files"
+	checklogs=1
+	install_logs.sh
+}
+
+# Create directories for the script and console logs.
+if [ ! -d "${lgsmlogdir}" ] || [ ! -d "${consolelogdir}" ]; then
+	fn_check_logs
+fi
+
+# Create gamelogdir.
+# If variable exists gamelogdir exists and log/server does not.
+if [ "${gamelogdir}" ] && [ -d "${gamelogdir}" ] && [ ! -d "${logdir}/server" ]; then
+	fn_check_logs
+fi

+ 233 - 0
lgsm/modules/check_permissions.sh

@@ -0,0 +1,233 @@
+#!/bin/bash
+# LinuxGSM check_permissions.sh
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Checks ownership & permissions of scripts, files and directories.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+fn_check_ownership() {
+	if [ -f "${rootdir}/${selfname}" ]; then
+		if [ "$(find "${rootdir}/${selfname}" -not -user "$(whoami)" | wc -l)" -ne "0" ]; then
+			selfownissue=1
+		fi
+	fi
+	if [ -d "${modulesdir}" ]; then
+		if [ "$(find "${modulesdir}" -not -user "$(whoami)" | wc -l)" -ne "0" ]; then
+			funcownissue=1
+		fi
+	fi
+	if [ -d "${serverfiles}" ]; then
+		if [ "$(find "${serverfiles}" -not -user "$(whoami)" | wc -l)" -ne "0" ]; then
+			filesownissue=1
+		fi
+	fi
+	if [ "${selfownissue}" == "1" ] || [ "${funcownissue}" == "1" ] || [ "${filesownissue}" == "1" ]; then
+		fn_print_fail_nl "Ownership issues found"
+		fn_script_log_fatal "Ownership issues found"
+		fn_print_information_nl "The current user ($(whoami)) does not have ownership of the following files:"
+		fn_script_log_info "The current user ($(whoami)) does not have ownership of the following files:"
+		{
+			echo -e "User\tGroup\tFile\n"
+			if [ "${selfownissue}" == "1" ]; then
+				find "${rootdir}/${selfname}" -not -user "$(whoami)" -printf "%u\t%g\t%p\n"
+			fi
+			if [ "${funcownissue}" == "1" ]; then
+				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"
+			fi
+
+		} | column -s $'\t' -t | tee -a "${lgsmlog}"
+		echo -e ""
+		fn_print_information_nl "please see https://docs.linuxgsm.com/support/faq#fail-starting-game-server-permission-issues-found"
+		fn_script_log "For more information, please see https://docs.linuxgsm.com/support/faq#fail-starting-game-server-permission-issues-found"
+		if [ "${monitorflag}" == 1 ]; then
+			alert="permissions"
+			alert.sh
+		fi
+		core_exit.sh
+	fi
+}
+
+fn_check_permissions() {
+	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 "${modulesdir}" -type f -not -executable -printf "%p\n"
+			} | column -s $'\t' -t | tee -a "${lgsmlog}"
+			if [ "${monitorflag}" == 1 ]; then
+				alert="permissions"
+				alert.sh
+			fi
+			core_exit.sh
+		fi
+	fi
+
+	# Check rootdir permissions.
+	if [ "${rootdir}" ]; then
+		# Get permission numbers on directory under the form 775.
+		rootdirperm=$(stat -c %a "${rootdir}")
+		# Grab the first and second digit for user and group permission.
+		userrootdirperm="${rootdirperm:0:1}"
+		grouprootdirperm="${rootdirperm:1:1}"
+		if [ "${userrootdirperm}" != "7" ] && [ "${grouprootdirperm}" != "7" ]; then
+			fn_print_fail_nl "Permissions issues found"
+			fn_script_log_fatal "Permissions issues found"
+			fn_print_information_nl "The following directory does not have the correct permissions:"
+			fn_script_log_info "The following directory does not have the correct permissions:"
+			fn_script_log_info "${rootdir}"
+			ls -l "${rootdir}"
+			if [ "${monitorflag}" == 1 ]; then
+				alert="permissions"
+				alert.sh
+			fi
+			core_exit.sh
+		fi
+	fi
+	# Check if executable is executable and attempt to fix it.
+	# First get executable name.
+	execname=$(basename "${executable}")
+	if [ -f "${executabledir}/${execname}" ]; then
+		# Get permission numbers on file under the form 775.
+		execperm=$(stat -c %a "${executabledir}/${execname}")
+		# Grab the first and second digit for user and group permission.
+		userexecperm="${execperm:0:1}"
+		groupexecperm="${execperm:1:1}"
+		# Check for invalid user permission.
+		if [ "${userexecperm}" == "0" ] || [ "${userexecperm}" == "2" ] || [ "${userexecperm}" == "4" ] || [ "${userexecperm}" == "6" ]; then
+			# If user permission is invalid, then check for invalid group permissions.
+			if [ "${groupexecperm}" == "0" ] || [ "${groupexecperm}" == "2" ] || [ "${groupexecperm}" == "4" ] || [ "${groupexecperm}" == "6" ]; then
+				# If permission issues are found.
+				fn_print_warn_nl "Permissions issue found"
+				fn_script_log_warn "Permissions issue found"
+				fn_print_information_nl "The following file is not executable:"
+				ls -l "${executabledir}/${execname}"
+				fn_script_log_info "The following file is not executable:"
+				fn_script_log_info "${executabledir}/${execname}"
+				fn_print_information_nl "Applying chmod u+x,g+x ${executabledir}/${execname}"
+				fn_script_log_info "Applying chmod u+x,g+x ${execperm}"
+				# Make the executable executable.
+				chmod u+x,g+x "${executabledir}/${execname}"
+				# Second check to see if it's been successfully applied.
+				# Get permission numbers on file under the form 775.
+				execperm=$(stat -c %a "${executabledir}/${execname}")
+				# Grab the first and second digit for user and group permission.
+				userexecperm="${execperm:0:1}"
+				groupexecperm="${execperm:1:1}"
+				if [ "${userexecperm}" == "0" ] || [ "${userexecperm}" == "2" ] || [ "${userexecperm}" == "4" ] || [ "${userexecperm}" == "6" ]; then
+					if [ "${groupexecperm}" == "0" ] || [ "${groupexecperm}" == "2" ] || [ "${groupexecperm}" == "4" ] || [ "${groupexecperm}" == "6" ]; then
+						# If errors are still found.
+						fn_print_fail_nl "The following file could not be set executable:"
+						ls -l "${executabledir}/${execname}"
+						fn_script_log_warn "The following file could not be set executable:"
+						fn_script_log_info "${executabledir}/${execname}"
+						if [ "${monitorflag}" == "1" ]; then
+							alert="permissions"
+							alert.sh
+						fi
+						core_exit.sh
+					fi
+				fi
+			fi
+		fi
+	fi
+}
+
+## 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() {
+	# Reset test variables.
+	sysdirpermerror="0"
+	classdirpermerror="0"
+	netdirpermerror="0"
+	# Check permissions.
+	# /sys, /sys/class and /sys/class/net should be readable & executable.
+	if [ ! -r "/sys" ] || [ ! -x "/sys" ]; then
+		sysdirpermerror="1"
+	fi
+	if [ ! -r "/sys/class" ] || [ ! -x "/sys/class" ]; then
+		classdirpermerror="1"
+	fi
+	if [ ! -r "/sys/class/net" ] || [ ! -x "/sys/class/net" ]; then
+		netdirpermerror="1"
+	fi
+}
+
+# Display a message on how to fix the issue manually.
+fn_sys_perm_fix_manually_msg() {
+	echo -e ""
+	fn_print_information_nl "This error causes servers to fail starting properly"
+	fn_script_log_info "This error causes servers to fail starting properly."
+	echo -e "	* To fix this issue, run the following command as root:"
+	fn_script_log_info "To fix this issue, run the following command as root:"
+	echo -e "	  chmod a+rx /sys /sys/class /sys/class/net"
+	fn_script_log "chmod a+rx /sys /sys/class /sys/class/net"
+	fn_sleep_time
+	if [ "${monitorflag}" == 1 ]; then
+		alert="permissions"
+		alert.sh
+	fi
+	core_exit.sh
+}
+
+# Attempt to fix /sys related permission errors if sudo is available, exits otherwise.
+fn_sys_perm_errors_fix() {
+	if sudo -n true > /dev/null 2>&1; then
+		fn_print_dots "Automatically fixing /sys permissions"
+		fn_script_log_info "Automatically fixing /sys permissions."
+		if [ "${sysdirpermerror}" == "1" ]; then
+			sudo chmod a+rx "/sys"
+		fi
+		if [ "${classdirpermerror}" == "1" ]; then
+			sudo chmod a+rx "/sys/class"
+		fi
+		if [ "${netdirpermerror}" == "1" ]; then
+			sudo chmod a+rx "/sys/class/net"
+		fi
+		# Run check again to see if it's fixed.
+		fn_sys_perm_errors_detect
+		if [ "${sysdirpermerror}" == "1" ] || [ "${classdirpermerror}" == "1" ] || [ "${netdirpermerror}" == "1" ]; then
+			fn_print_error "Could not fix /sys permissions"
+			fn_script_log_error "Could not fix /sys permissions."
+			fn_sleep_time
+			# Show the user how to fix.
+			fn_sys_perm_fix_manually_msg
+		else
+			fn_print_ok_nl "Automatically fixing /sys permissions"
+			fn_script_log_pass "Permissions in /sys fixed"
+		fi
+	else
+		# Show the user how to fix.
+		fn_sys_perm_fix_manually_msg
+	fi
+}
+
+# Processes to the /sys related permission errors check & fix/info.
+fn_sys_perm_error_process() {
+	fn_sys_perm_errors_detect
+	# If any error was found.
+	if [ "${sysdirpermerror}" == "1" ] || [ "${classdirpermerror}" == "1" ] || [ "${netdirpermerror}" == "1" ]; then
+		fn_print_error_nl "Permission error(s) found in /sys"
+		fn_script_log_error "Permission error(s) found in /sys"
+		# Run the fix
+		fn_sys_perm_errors_fix
+	fi
+}
+
+## Run permisions checks when not root or docker.
+if [ "$(whoami)" != "root" ] && [ ! -f /.dockerenv ]; then
+	fn_check_ownership
+	fn_check_permissions
+	if [ "${commandname}" == "START" ]; then
+		fn_sys_perm_error_process
+	fi
+fi

+ 21 - 0
lgsm/modules/check_root.sh

@@ -0,0 +1,21 @@
+#!/bin/bash
+# LinuxGSM check_root.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Checks if the user tried to run the script as root.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+if [ "$(whoami)" == "root" ] && [ ! -f /.dockerenv ]; then
+	if [ "${commandname}" != "INSTALL" ]; then
+		fn_print_fail_nl "Do NOT run this script as root!"
+		if [ -d "${lgsmlogdir}" ]; then
+			fn_script_log_fatal "${selfname} attempted to run as root."
+		else
+			# Forces exit code is log does not yet exist.
+			exitcode=1
+		fi
+		core_exit.sh
+	fi
+fi

+ 10 - 0
lgsm/modules/check_status.sh

@@ -0,0 +1,10 @@
+#!/bin/bash
+# LinuxGSM check_status.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Checks the process status of the server. Either online or offline.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+status=$(tmux list-sessions -F "#{session_name}" 2> /dev/null | grep -Ecx "^${sessionname}")

+ 22 - 0
lgsm/modules/check_steamcmd.sh

@@ -0,0 +1,22 @@
+#!/bin/bash
+# LinuxGSM check_steamcmd.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Checks if SteamCMD is installed correctly.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+# init steamcmd functions.
+core_steamcmd.sh
+
+fn_check_steamcmd_clear
+fn_check_steamcmd
+if [ "${shortname}" == "ark" ]; then
+	fn_check_steamcmd_ark
+fi
+fn_check_steamcmd_dir
+fn_check_steamcmd_dir_legacy
+fn_check_steamcmd_steamapp
+fn_check_steamcmd_user
+fn_check_steamcmd_exec

+ 22 - 0
lgsm/modules/check_system_dir.sh

@@ -0,0 +1,22 @@
+#!/bin/bash
+# LinuxGSM check_system_dir.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Checks if systemdir/serverfiles is accessible.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+if [ "${commandname}" != "VALIDATE" ]; then
+	checkdir="${serverfiles}"
+else
+	checkdir="${systemdir}"
+fi
+
+if [ ! -d "${checkdir}" ]; then
+	fn_print_fail_nl "Cannot access ${checkdir}: No such directory"
+	if [ -d "${lgsmlogdir}" ]; then
+		fn_script_log_fatal "Cannot access ${checkdir}: No such directory."
+	fi
+	core_exit.sh
+fi

+ 55 - 0
lgsm/modules/check_system_requirements.sh

@@ -0,0 +1,55 @@
+#!/bin/bash
+# LinuxGSM check_system_requirements.sh
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Checks RAM requirements.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+info_distro.sh
+
+# RAM requirements in megabytes for each game or engine.
+
+if [ "${shortname}" == "ark" ]; then
+	ramrequirementmb="4000"
+	ramrequirementgb="4"
+elif [ "${shortname}" == "bt" ]; then
+	ramrequirementmb="1000"
+	ramrequirementgb="1"
+elif [ "${shortname}" == "mh" ]; then
+	ramrequirementmb="4000"
+	ramrequirementgb="4"
+elif [ "${shortname}" == "arma3" ]; then
+	ramrequirementmb="1000"
+	ramrequirementgb="1"
+elif [ "${shortname}" == "rust" ]; then
+	ramrequirementmb="4000"
+	ramrequirementgb="4"
+elif [ "${shortname}" == "mc" ] || [ "${shortname}" == "pmc" ] || [ "${shortname}" == "wmc" ]; then
+	ramrequirementmb="1000"
+	ramrequirementgb="1"
+elif [ "${shortname}" == "pstbs" ]; then
+	ramrequirementmb="2000"
+	ramrequirementgb="2"
+elif [ "${shortname}" == "ns2" ] || [ "${shortname}" == "ns2c" ]; then
+	ramrequirementmb="1000"
+	ramrequirementgb="1"
+elif [ "${shortname}" == "st" ]; then
+	ramrequirementmb="1000"
+	ramrequirementgb="1"
+elif [ "${shortname}" == "pvr" ]; then
+	ramrequirementmb="2000"
+	ramrequirementgb="2"
+fi
+
+# If the game or engine has a minimum RAM Requirement, compare it to system's available RAM.
+if [ "${ramrequirementmb}" ]; then
+	if [ "${physmemtotalmb}" -lt "${ramrequirementmb}" ]; then
+		fn_print_dots "Check RAM"
+		# Warn the user.
+		fn_print_warn_nl "Check RAM: ${ramrequirementgb}G required, ${physmemtotal} available"
+		echo "* ${gamename} server may fail to run or experience poor performance."
+		fn_sleep_time
+	fi
+fi

+ 33 - 0
lgsm/modules/check_tmuxception.sh

@@ -0,0 +1,33 @@
+#!/bin/bash
+# LinuxGSM check_config.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Checks if run from tmux or screen.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+fn_check_is_in_tmux() {
+	if [ "${TMUX}" ]; then
+		fn_print_fail_nl "tmuxception error: Sorry Cobb you cannot start a tmux session inside of a tmux session."
+		fn_script_log_fatal "Tmuxception error: Attempted to start a tmux session inside of a tmux session."
+		fn_print_information_nl "LinuxGSM creates a tmux session when starting the server."
+		echo -e "It is not possible to run a tmux session inside another tmux session"
+		echo -e "https://docs.linuxgsm.com/requirements/tmux#tmuxception"
+		core_exit.sh
+	fi
+}
+
+fn_check_is_in_screen() {
+	if [ "${STY}" ]; then
+		fn_print_fail_nl "tmuxception error: Sorry Cobb you cannot start a tmux session inside of a screen session."
+		fn_script_log_fatal "Tmuxception error: Attempted to start a tmux session inside of a screen session."
+		fn_print_information_nl "LinuxGSM creates a tmux session when starting the server."
+		echo -e "It is not possible to run a tmux session inside screen session"
+		echo -e "https://docs.linuxgsm.com/requirements/tmux#tmuxception"
+		core_exit.sh
+	fi
+}
+
+fn_check_is_in_tmux
+fn_check_is_in_screen

+ 23 - 0
lgsm/modules/check_version.sh

@@ -0,0 +1,23 @@
+#!/bin/bash
+# LinuxGSM command_version.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# 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.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+if [ -n "${modulesversion}" ] && [ -n "${version}" ] && [ "${version}" != "${modulesversion}" ]; then
+	exitbypass=1
+	echo -e ""
+	fn_print_error_nl "LinuxGSM version mismatch"
+	echo -e ""
+	echo -e "* ${selfname}: ${version}"
+	echo -e "* modules: ${modulesversion}"
+	echo -e ""
+	fn_sleep_time
+	fn_script_log_error "LinuxGSM Version mismatch: ${selfname}: ${version}: modules: ${modulesversion}"
+	command_update_linuxgsm.sh
+	fn_firstcommand_reset
+fi

+ 268 - 0
lgsm/modules/command_backup.sh

@@ -0,0 +1,268 @@
+#!/bin/bash
+# LinuxGSM command_backup.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Creates a .tar.gz file in the backup directory.
+
+commandname="BACKUP"
+commandaction="Backing up"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+fn_firstcommand_set
+
+check.sh
+
+# Trap to remove lockfile on quit.
+fn_backup_trap() {
+	echo -e ""
+	echo -en "backup ${backupname}.tar.gz..."
+	fn_print_canceled_eol_nl
+	fn_script_log_info "Backup ${backupname}.tar.gz: CANCELED"
+	rm -f "${backupdir:?}/${backupname}.tar.gz" | tee -a "${lgsmlog}"
+	echo -en "backup ${backupname}.tar.gz..."
+	fn_print_removed_eol_nl
+	fn_script_log_info "Backup ${backupname}.tar.gz: REMOVED"
+	# Remove lock file.
+	rm -f "${lockdir:?}/backup.lock"
+	fn_backup_start_server
+	unset exitbypass
+	core_exit.sh
+}
+
+# Check if a backup is pending or has been aborted using backup.lock.
+fn_backup_check_lockfile() {
+	if [ -f "${lockdir}/backup.lock" ]; then
+		fn_print_info_nl "Lock file found: Backup is currently running"
+		fn_script_log_error "Lock file found: Backup is currently running: ${lockdir}/backup.lock"
+		core_exit.sh
+	fi
+}
+
+# Initialisation.
+fn_backup_init() {
+	# Backup file name with selfname and current date.
+	backupname="${selfname}-$(date '+%Y-%m-%d-%H%M%S')"
+
+	info_distro.sh
+	fn_print_dots "Backup starting"
+	fn_script_log_info "Backup starting"
+	fn_print_ok_nl "Backup starting"
+	if [ ! -d "${backupdir}" ] || [ "${backupcount}" == "0" ]; then
+		fn_print_info_nl "There are no previous backups"
+	else
+		if [ "${lastbackupdaysago}" == "0" ]; then
+			daysago="less than 1 day ago"
+		elif [ "${lastbackupdaysago}" == "1" ]; then
+			daysago="1 day ago"
+		else
+			daysago="${lastbackupdaysago} days ago"
+		fi
+		echo -e "* Previous backup was created ${daysago}, total size ${lastbackupsize}"
+	fi
+}
+
+# Check if server is started and whether to stop it.
+fn_backup_stop_server() {
+	check_status.sh
+	# Server is running but will not be stopped.
+	if [ "${stoponbackup}" == "off" ]; then
+		fn_print_warn_nl "${selfname} is currently running"
+		echo -e "* Although unlikely; creating a backup while ${selfname} is running might corrupt the backup."
+		fn_script_log_warn "${selfname} is currently running"
+		fn_script_log_warn "Although unlikely; creating a backup while ${selfname} is running might corrupt the backup"
+	# Server is running and will be stopped if stoponbackup=on or unset.
+	# If server is started
+	elif [ "${status}" != "0" ]; then
+		fn_print_restart_warning
+		startserver="1"
+		exitbypass=1
+		command_stop.sh
+		fn_firstcommand_reset
+	fi
+}
+
+# Create required folders.
+fn_backup_dir() {
+	# Create backupdir if it doesn't exist.
+	if [ ! -d "${backupdir}" ]; then
+		mkdir -p "${backupdir}"
+	fi
+}
+
+# Migrate Backups from old dir before refactor
+fn_backup_migrate_olddir() {
+	# Check if old backup dir is there before the refactor and move the backups
+	if [ -d "${rootdir}/backups" ]; then
+		if [ "${rootdir}/backups" != "${backupdir}" ]; then
+			fn_print_dots "Backup directory is being migrated"
+			fn_script_log_info "Backup directory is being migrated"
+			fn_script_log_info "${rootdir}/backups > ${backupdir}"
+			mv "${rootdir}/backups/"* "${backupdir}" 2> /dev/null
+			exitcode=$?
+			if [ "${exitcode}" == 0 ]; then
+				rmdir "${rootdir}/backups" 2> /dev/null
+				exitcode=$?
+			fi
+			if [ "${exitcode}" != 0 ]; then
+				fn_print_error_nl "Backup directory is being migrated"
+				fn_script_log_error "Backup directory is being migrated"
+			else
+
+				fn_print_ok_nl "Backup directory is being migrated"
+				fn_script_log_pass "Backup directory is being migrated"
+			fi
+		fi
+	fi
+}
+
+fn_backup_create_lockfile() {
+	# Create lockfile.
+	date '+%s' > "${lockdir}/backup.lock"
+	fn_script_log_info "Lockfile generated"
+	fn_script_log_info "${lockdir}/backup.lock"
+	# trap to remove lockfile on quit.
+	trap fn_backup_trap INT
+}
+
+# Compressing files.
+fn_backup_compression() {
+	# Tells how much will be compressed using rootdirduexbackup value from info_distro and prompt for continue.
+	fn_print_info "A total of ${rootdirduexbackup} will be compressed."
+	fn_script_log_info "A total of ${rootdirduexbackup} will be compressed: ${backupdir}/${backupname}.tar.gz"
+	fn_print_dots "Backup (${rootdirduexbackup}) ${backupname}.tar.gz, in progress..."
+	fn_script_log_info "backup ${rootdirduexbackup} ${backupname}.tar.gz, in progress"
+	excludedir=$(fn_backup_relpath)
+
+	# Check that excludedir is a valid path.
+	if [ ! -d "${excludedir}" ]; then
+		fn_print_fail_nl "Problem identifying the previous backup directory for exclusion."
+		fn_script_log_fatal "Problem identifying the previous backup directory for exclusion"
+		core_exit.sh
+	fi
+
+	tar -czf "${backupdir}/${backupname}.tar.gz" -C "${rootdir}" --exclude "${excludedir}" --exclude "${lockdir}/backup.lock" ./.
+	local exitcode=$?
+	if [ "${exitcode}" != 0 ]; then
+		fn_print_fail_eol
+		fn_script_log_fatal "Backup in progress: FAIL"
+		echo -e "${extractcmd}" | tee -a "${lgsmlog}"
+		fn_print_fail_nl "Starting backup"
+		fn_script_log_fatal "Starting backup"
+	else
+		fn_print_ok_eol
+		fn_print_ok_nl "Completed: ${backupname}.tar.gz, total size $(du -sh "${backupdir}/${backupname}.tar.gz" | awk '{print $1}')"
+		fn_script_log_pass "Backup created: ${backupname}.tar.gz, total size $(du -sh "${backupdir}/${backupname}.tar.gz" | awk '{print $1}')"
+	fi
+	# Remove lock file
+	rm -f "${lockdir:?}/backup.lock"
+}
+
+# Clear old backups according to maxbackups and maxbackupdays variables.
+fn_backup_prune() {
+	# Clear if backup variables are set.
+	if [ "${maxbackups}" ] && [ -n "${maxbackupdays}" ]; then
+		# How many backups there are.
+		info_distro.sh
+		# How many backups exceed maxbackups.
+		backupquotadiff=$((backupcount - maxbackups))
+		# How many backups exceed maxbackupdays.
+		backupsoudatedcount=$(find "${backupdir}"/ -type f -name "*.tar.gz" -mtime +"${maxbackupdays}" | wc -l)
+		# If anything can be cleared.
+		if [ "${backupquotadiff}" -gt "0" ] || [ "${backupsoudatedcount}" -gt "0" ]; then
+			fn_print_dots "Pruning"
+			fn_script_log_info "Backup pruning activated"
+			fn_print_ok_nl "Pruning"
+			# If maxbackups greater or equal to backupsoutdatedcount, then it is over maxbackupdays.
+			if [ "${backupquotadiff}" -ge "${backupsoudatedcount}" ]; then
+				# Display how many backups will be cleared.
+				echo -e "* Pruning: ${backupquotadiff} backup(s) has exceeded the ${maxbackups} backups limit"
+				fn_script_log_info "Pruning: ${backupquotadiff} backup(s) has exceeded the ${maxbackups} backups limit"
+				fn_sleep_time
+				fn_print_dots "Pruning: Clearing ${backupquotadiff} backup(s)"
+				fn_script_log_info "Pruning: Clearing ${backupquotadiff} backup(s)"
+				# Clear backups over quota.
+				find "${backupdir}"/ -type f -name "*.tar.gz" -printf '%T@ %p\n' | sort -rn | tail -${backupquotadiff} | cut -f2- -d" " | xargs rm
+				fn_print_ok_nl "Pruning: Clearing ${backupquotadiff} backup(s)"
+				fn_script_log_pass "Pruning: Cleared ${backupquotadiff} backup(s)"
+			# If maxbackupdays is used over maxbackups.
+			elif [ "${backupquotadiff}" -lt "${backupsoudatedcount}" ]; then
+				# Display how many backups will be cleared.
+				echo -e "* Pruning: ${backupsoudatedcount} backup(s) are older than ${maxbackupdays} days."
+				fn_script_log_info "Pruning: ${backupsoudatedcount} backup(s) older than ${maxbackupdays} days."
+				fn_sleep_time
+				fn_print_dots "Pruning: Clearing ${backupquotadiff} backup(s)."
+				fn_script_log_info "Pruning: Clearing ${backupquotadiff} backup(s)"
+				# Clear backups over quota
+				find "${backupdir}"/ -type f -mtime +"${maxbackupdays}" -exec rm -f {} \;
+				fn_print_ok_nl "Pruning: Clearing ${backupquotadiff} backup(s)"
+				fn_script_log_pass "Pruning: Cleared ${backupquotadiff} backup(s)"
+			fi
+		fi
+	fi
+}
+
+fn_backup_relpath() {
+	# Written by CedarLUG as a "realpath --relative-to" alternative in bash.
+	# Populate an array of tokens initialized from the rootdir components.
+	declare -a rdirtoks=($(readlink -f "${rootdir}" | sed "s/\// /g"))
+	if [ ${#rdirtoks[@]} -eq 0 ]; then
+		fn_print_fail_nl "Problem assessing rootdir during relative path assessment"
+		fn_script_log_fatal "Problem assessing rootdir during relative path assessment: ${rootdir}"
+		core_exit.sh
+	fi
+
+	# Populate an array of tokens initialized from the backupdir components.
+	declare -a bdirtoks=($(readlink -f "${backupdir}" | sed "s/\// /g"))
+	if [ ${#bdirtoks[@]} -eq 0 ]; then
+		fn_print_fail_nl "Problem assessing backupdir during relative path assessment"
+		fn_script_log_fatal "Problem assessing backupdir during relative path assessment: ${rootdir}"
+		core_exit.sh
+	fi
+
+	# Compare the leading entries of each array.  These common elements will be clipped off.
+	# for the relative path output.
+	for ((base = 0; base < ${#rdirtoks[@]}; base++)); do
+		[[ "${rdirtoks[$base]}" != "${bdirtoks[$base]}" ]] && break
+	done
+
+	# Next, climb out of the remaining rootdir location with updir references.
+	for ((x = base; x < ${#rdirtoks[@]}; x++)); do
+		echo -n "../"
+	done
+
+	# Climb down the remaining components of the backupdir location.
+	for ((x = base; x < $((${#bdirtoks[@]} - 1)); x++)); do
+		echo -n "${bdirtoks[$x]}/"
+	done
+
+	# In the event there were no directories left in the backupdir above to
+	# traverse down, just add a newline. Otherwise at this point, there is
+	# one remaining directory component in the backupdir to navigate.
+	if (("$base" < "${#bdirtoks[@]}")); then
+		echo -e "${bdirtoks[$((${#bdirtoks[@]} - 1))]}"
+	else
+		echo
+	fi
+}
+
+# Start the server if it was stopped for the backup.
+fn_backup_start_server() {
+	if [ -n "${startserver}" ]; then
+		exitbypass=1
+		command_start.sh
+		fn_firstcommand_reset
+	fi
+}
+
+# Run functions.
+fn_backup_check_lockfile
+fn_backup_init
+fn_backup_stop_server
+fn_backup_dir
+fn_backup_migrate_olddir
+fn_backup_create_lockfile
+fn_backup_compression
+fn_backup_prune
+fn_backup_start_server
+
+core_exit.sh

+ 39 - 0
lgsm/modules/command_check_update.sh

@@ -0,0 +1,39 @@
+#!/bin/bash
+# LinuxGSM command_check_update.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Handles updating of servers.
+
+commandname="CHECK-UPDATE"
+commandaction="Check for Update"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+fn_firstcommand_set
+
+fn_print_dots ""
+check.sh
+core_logs.sh
+
+if [ "${shortname}" == "ts3" ]; then
+	update_ts3.sh
+elif [ "${shortname}" == "mc" ]; then
+	update_minecraft.sh
+elif [ "${shortname}" == "mcb" ]; then
+	update_minecraft_bedrock.sh
+elif [ "${shortname}" == "pmc" ] || [ "${shortname}" == "vpmc" ] || [ "${shortname}" == "wmc" ]; then
+	update_papermc.sh
+elif [ "${shortname}" == "fctr" ]; then
+	update_factorio.sh
+elif [ "${shortname}" == "mta" ]; then
+	update_mta.sh
+elif [ "${shortname}" == "jk2" ]; then
+	update_jediknight2.sh
+elif [ "${shortname}" == "vints" ]; then
+	update_vintagestory.sh
+elif [ "${shortname}" == "ut99" ]; then
+	update_ut99.sh
+else
+	update_steamcmd.sh
+fi
+
+core_exit.sh

+ 58 - 0
lgsm/modules/command_console.sh

@@ -0,0 +1,58 @@
+#!/bin/bash
+# LinuxGSM command_console.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Gives access to the server tmux console.
+
+commandname="CONSOLE"
+commandaction="Access console"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+fn_firstcommand_set
+
+check.sh
+fn_print_header
+
+if [ "${consoleverbose}" == "yes" ]; then
+	echo -e "* Verbose output: ${lightgreen}yes${default}"
+elif [ "${consoleverbose}" == "no" ]; then
+	echo -e "* Verbose output: ${red}no${default}"
+else
+	echo -e "* Verbose output: ${red}unknown${default}"
+fi
+
+if [ "${consoleinteract}" == "yes" ]; then
+	echo -e "* Interactive output: ${lightgreen}yes${default}"
+elif [ "${consoleinteract}" == "no" ]; then
+	echo -e "* Interactive output: ${red}no${default}"
+else
+	echo -e "* Interactive output: ${red}unknown${default}"
+fi
+echo ""
+fn_print_information_nl "Press \"CTRL+b\" then \"d\" to exit console."
+fn_print_warning_nl "Do NOT press CTRL+c to exit."
+echo -e "* https://docs.linuxgsm.com/commands/console"
+echo -e ""
+if ! fn_prompt_yn "Continue?" Y; then
+	exitcode=0
+	core_exit.sh
+fi
+fn_print_dots "Accessing console"
+check_status.sh
+if [ "${status}" != "0" ]; then
+	fn_print_ok_nl "Accessing console"
+	fn_script_log_pass "Console accessed"
+	tmux attach-session -t "${sessionname}"
+	fn_print_ok_nl "Closing console"
+	fn_script_log_pass "Console closed"
+else
+	fn_print_error_nl "Server not running"
+	fn_script_log_error "Failed to access: Server not running"
+	if fn_prompt_yn "Do you want to start the server?" Y; then
+		exitbypass=1
+		command_start.sh
+		fn_firstcommand_reset
+	fi
+fi
+
+core_exit.sh

+ 142 - 0
lgsm/modules/command_debug.sh

@@ -0,0 +1,142 @@
+#!/bin/bash
+# LinuxGSM command_debug.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Runs the server without tmux and directly from the terminal.
+
+commandname="DEBUG"
+commandaction="Debuging"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+fn_firstcommand_set
+
+# Trap to remove lockfile on quit.
+fn_lockfile_trap() {
+	# Remove lockfile.
+	rm -f "${lockdir:?}/${selfname}.lock"
+	# resets terminal. Servers can sometimes mess up the terminal on exit.
+	reset
+	fn_print_dots "Stopping debug"
+	fn_print_ok_nl "Stopping debug"
+	fn_script_log_pass "Stopping debug"
+	# remove trap.
+	trap - INT
+	core_exit.sh
+}
+
+check.sh
+fix.sh
+info_distro.sh
+info_game.sh
+fn_print_header
+{
+	echo -e "${lightblue}Distro:\t\t${default}${distroname}"
+	echo -e "${lightblue}Architecture:\t\t${default}${arch}"
+	echo -e "${lightblue}Kernel:\t\t${default}${kernel}"
+	echo -e "${lightblue}Hostname:\t\t${default}${HOSTNAME}"
+	echo -e "${lightblue}tmux:\t\t${default}${tmuxv}"
+	echo -e "${lightblue}Avg Load:\t\t${default}${load}"
+	echo -e "${lightblue}Free Memory:\t\t${default}${physmemfree}"
+	echo -e "${lightblue}Free Disk:\t\t${default}${availspace}"
+} | column -s $'\t' -t
+
+# glibc required.
+if [ -n "${glibc}" ]; then
+	if [ "${glibc}" == "null" ]; then
+		# Glibc is not required.
+		:
+	elif [ -z "${glibc}" ]; then
+		echo -e "${lightblue}glibc required:\t${red}UNKNOWN${default}"
+	elif [ "$(printf '%s\n'${glibc}'\n' ${glibcversion} | sort -V | head -n 1)" != "${glibc}" ]; then
+		echo -e "${lightblue}glibc required:\t${red}${glibc} ${default}(${red}distro glibc ${glibcversion} too old${default})"
+	else
+		echo -e "${lightblue}glibc required:\t${green}${glibc}${default}"
+	fi
+fi
+
+# Server IP.
+echo -e "${lightblue}Game Server IP:\t${default}${ip}:${port}"
+
+# External server IP.
+if [ "${extip}" ]; then
+	if [ "${ip}" != "${extip}" ]; then
+		echo -e "${lightblue}Internet IP:\t${default}${extip}:${port}"
+	fi
+fi
+
+# Server password.
+if [ "${serverpassword}" ]; then
+	echo -e "${lightblue}Server password:\t${default}${serverpassword}"
+fi
+
+fn_reload_startparameters
+echo -e "${lightblue}Start parameters:${default}"
+if [ "${engine}" == "source" ] || [ "${engine}" == "goldsrc" ]; then
+	echo -e "${executable} ${startparameters} -debug"
+elif [ "${engine}" == "quake" ]; then
+	echo -e "${executable} ${startparameters} -condebug"
+else
+	echo -e "${preexecutable} ${executable} ${startparameters}"
+fi
+echo -e ""
+echo -e "Use debug for identifying server issues only!"
+echo -e "Press CTRL+c to drop out of debug mode."
+fn_print_warning_nl "If ${selfname} is already running it will be stopped."
+echo -e ""
+if ! fn_prompt_yn "Continue?" Y; then
+	exitcode=0
+	core_exit.sh
+fi
+
+fn_print_info_nl "Stopping any running servers"
+fn_script_log_info "Stopping any running servers"
+exitbypass=1
+command_stop.sh
+fn_firstcommand_reset
+unset exitbypass
+fn_print_dots "Starting debug"
+fn_script_log_info "Starting debug"
+fn_print_ok_nl "Starting debug"
+
+# Create lockfile.
+date '+%s' > "${lockdir}/${selfname}.lock"
+echo "${version}" >> "${lockdir}/${selfname}.lock"
+echo "${port}" >> "${lockdir}/${selfname}.lock"
+fn_script_log_info "Lockfile generated"
+fn_script_log_info "${lockdir}/${selfname}.lock"
+
+if [ "${shortname}" == "av" ]; then
+	cd "${systemdir}" || exit
+else
+	cd "${executabledir}" || exit
+fi
+
+# Note: do not add double quotes to ${executable} ${startparameters}.
+if [ "${engine}" == "source" ] || [ "${engine}" == "goldsrc" ]; then
+	eval "${executable} ${startparameters} -debug"
+elif [ "${engine}" == "quake" ]; then
+	eval "${executable} ${startparameters} -condebug"
+else
+	# shellcheck disable=SC2086
+	eval "${preexecutable} ${executable} ${startparameters}"
+fi
+
+if [ $? -ne 0 ]; then
+	fn_print_error_nl "Server has stopped: exit code: $?"
+	fn_script_log_error "Server has stopped: exit code: $?"
+	fn_print_error_nl "Press ENTER to exit debug mode"
+	read -r
+else
+	fn_print_ok_nl "Server has stopped"
+	fn_script_log_pass "Server has stopped"
+	fn_print_ok_nl "Press ENTER to exit debug mode"
+	read -r
+fi
+
+fn_lockfile_trap
+
+fn_print_dots "Stopping debug"
+fn_print_ok_nl "Stopping debug"
+fn_script_log_info "Stopping debug"
+
+core_exit.sh

+ 42 - 0
lgsm/modules/command_details.sh

@@ -0,0 +1,42 @@
+#!/bin/bash
+# LinuxGSM command_details.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Displays server information.
+
+commandname="DETAILS"
+commandaction="Viewing details"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+fn_firstcommand_set
+
+# Run checks and gathers details to display.
+check.sh
+info_distro.sh
+info_game.sh
+info_messages.sh
+if [ "${querymode}" == "2" ] || [ "${querymode}" == "3" ]; then
+	for queryip in "${queryips[@]}"; do
+		query_gamedig.sh
+		if [ "${querystatus}" == "0" ]; then
+			break
+		fi
+	done
+fi
+fn_info_message_distro
+fn_info_message_server_resource
+fn_info_message_gameserver_resource
+fn_info_message_gameserver
+fn_info_message_script
+fn_info_message_backup
+# Some game servers do not have parms.
+if [ "${shortname}" != "jc2" ] && [ "${shortname}" != "dst" ] && [ "${shortname}" != "pz" ] && [ "${engine}" != "renderware" ]; then
+	fn_info_message_commandlineparms
+fi
+fn_info_message_ports_edit
+fn_info_message_ports
+fn_info_message_select_engine
+fn_info_message_statusbottom
+
+exitcode=0
+core_exit.sh

+ 24 - 0
lgsm/modules/command_dev_clear_modules.sh

@@ -0,0 +1,24 @@
+#!/bin/bash
+# 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 modules dir.
+
+commandname="DEV-CLEAR-MODULES"
+commandaction="Clearing modules"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+fn_firstcommand_set
+
+echo -e "================================="
+echo -e "Clear Modules"
+echo -e "================================="
+echo -e ""
+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"
+fi
+
+core_exit.sh

+ 23 - 0
lgsm/modules/command_dev_debug.sh

@@ -0,0 +1,23 @@
+#!/bin/bash
+# LinuxGSM command_dev_debug.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Dev only: Enables debugging log to be saved to dev-debug.log.
+
+commandname="DEV-DEBUG"
+commandaction="Developer debug"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+fn_firstcommand_reset
+
+if [ -f "${rootdir}/.dev-debug" ]; then
+	rm -f "${rootdir:?}/.dev-debug"
+	fn_print_ok_nl "Disabled dev-debug"
+	fn_script_log_info "Disabled dev-debug"
+else
+	date '+%s' > "${rootdir}/.dev-debug"
+	fn_print_ok_nl "Enabled dev-debug"
+	fn_script_log_info "Enabled dev-debug"
+fi
+
+core_exit.sh

+ 94 - 0
lgsm/modules/command_dev_details.sh

@@ -0,0 +1,94 @@
+#!/bin/bash
+# LinuxGSM command_dev_debug.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Dev only: Enables debugging log to be saved to dev-debug.log.
+
+if [ -f "config" ]; then
+	servercfgfullpath="config"
+fi
+if [ -f "clusterconfig" ]; then
+	clustercfgfullpath="clusterconfig"
+fi
+
+info_game.sh
+
+carriagereturn=$(file -b "${servercfgfullpath}" | grep -q CRLF && echo "${red}CRLF${default}" || echo "${lightgreen}LF${default}")
+
+echo -e ""
+echo -e "${lightgreen}Server Details${default}"
+echo -e "=================================================================="
+echo -e ""
+
+echo -e "Game: ${gamename}"
+echo -e "Config type: ${configtype}"
+echo -e "Config file: ${servercfgfullpath}"
+if [ -f "${clustercfgfullpath}" ]; then
+	echo -e "Cluster config file: ${clustercfgfullpath}"
+fi
+echo -e "Carriage Return: ${carriagereturn}"
+
+# Create an associative array of the server details.
+declare -A server_details=(
+	['Admin Password']="${adminpassword}"
+	['API Port']="${apiport}"
+	['Cave']="${cave}"
+	['Cluster']="${cluster}"
+	['Config IP']="${configip}"
+	['Default Map']="${defaultmap}"
+	['Game Mode']="${gamemode}"
+	['Game Type']="${gametype}"
+	['HTTP Enabled']="${httpenabled}"
+	['HTTP IP']="${httpip}"
+	['HTTP Password']="${httppassword}"
+	['HTTP Port']="${httpport}"
+	['HTTP User']="${httpuser}"
+	['ip']="${ip}"
+	['LAN Port']="${lanport}"
+	['Master Port']="${masterport}"
+	['Master']="${master}"
+	['Maxplayers']="${maxplayers}"
+	['OldQueryPortNumber']="${oldqueryportnumber}"
+	['Port']="${port}"
+	['Query Port']="${queryport}"
+	['RCON Enabled']="${rconenabled}"
+	['RCON Password']="${rconpassword}"
+	['RCON Port']="${rconport}"
+	['Reserved Slots']="${reservedslots}"
+	['Server Password']="${serverpassword}"
+	['Servername']="${servername}"
+	['Shard']="${shard}"
+	['Sharding']="${sharding}"
+	['Steam Auth Port']="${steamauthport}"
+	['Telnet IP']="${telnetip}"
+	['Tickrate']="${tickrate}"
+	['World Name']="${worldname}"
+	['World Type']="${worldtype}"
+)
+
+# Initialize a variable to keep track of missing server details.
+missing_details=""
+
+# Loop through the server details and output them.
+echo -e ""
+echo -e "${lightgreen}Available Server Details${default}"
+echo -e "================================="
+for key in "${!server_details[@]}"; do
+	value=${server_details[$key]}
+	if [ -z "$value" ]; then
+		missing_details+="\n${key}"
+	else
+		echo -e "$key: $value "
+	fi
+done
+
+# Output the missing server details if there are any.
+if [ -n "$missing_details" ]; then
+	echo -e ""
+	echo -e "${lightgreen}Missing Server Details${default}"
+	echo -e "================================="
+	echo -e "${missing_details}"
+fi
+
+core_exit.sh

+ 231 - 0
lgsm/modules/command_dev_detect_deps.sh

@@ -0,0 +1,231 @@
+#!/bin/bash
+# LinuxGSM command_dev_detect_deps.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Detects dependencies the server binary requires.
+
+commandname="DEV-DETECT-DEPS"
+commandaction="Developer detect deps"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+fn_firstcommand_set
+
+echo -e "================================="
+echo -e "Dependencies Checker"
+echo -e "================================="
+echo -e "Checking directory: "
+echo -e "${serverfiles}"
+if [ "$(command -v eu-readelf 2> /dev/null)" ]; then
+	readelf=eu-readelf
+elif [ "$(command -v readelf 2> /dev/null)" ]; then
+	readelf=readelf
+else
+	echo -e "readelf/eu-readelf not installed"
+fi
+files=$(find "${serverfiles}" | wc -l)
+find "${serverfiles}" -type f -print0 \
+	| while IFS= read -r -d $'\0' line; do
+		if [ "${readelf}" == "eu-readelf" ]; then
+			${readelf} -d "${line}" 2> /dev/null | grep NEEDED | awk '{ print $4 }' | sed 's/\[//g;s/\]//g' >> "${tmpdir}/.depdetect_readelf"
+		else
+			${readelf} -d "${line}" 2> /dev/null | grep NEEDED | awk '{ print $5 }' | sed 's/\[//g;s/\]//g' >> "${tmpdir}/.depdetect_readelf"
+		fi
+		echo -n "${i} / ${files}" $'\r'
+		((i++))
+	done
+
+sort "${tmpdir}/.depdetect_readelf" | uniq > "${tmpdir}/.depdetect_readelf_uniq"
+
+touch "${tmpdir}/.depdetect_centos_list"
+touch "${tmpdir}/.depdetect_ubuntu_list"
+touch "${tmpdir}/.depdetect_debian_list"
+
+while read -r lib; do
+	echo -e "${lib}"
+	libs_array=(libm.so.6 libc.so.6 libtcmalloc_minimal.so.4 libpthread.so.0 libdl.so.2 libnsl.so.1 libgcc_s.so.1 librt.so.1 ld-linux.so.2 libdbus-glib-1.so.2 libgio-2.0.so.0 libglib-2.0.so.0 libGL.so.1 libgobject-2.0.so.0 libnm-glib.so.4 libnm-util.so.2)
+	for lib_file in "${libs_array[@]}"; do
+		if [ "${lib}" == "${lib_file}" ]; then
+			echo -e "glibc.i686" >> "${tmpdir}/.depdetect_centos_list"
+			echo -e "lib32gcc1" >> "${tmpdir}/.depdetect_ubuntu_list"
+			echo -e "lib32gcc1" >> "${tmpdir}/.depdetect_debian_list"
+			libdetected=1
+		fi
+	done
+
+	libs_array=(libawt.so libjava.so libjli.so libjvm.so libnet.so libnio.so libverify.so)
+	for lib_file in "${libs_array[@]}"; do
+		if [ "${lib}" == "${lib_file}" ]; then
+			echo -e "java-1.8.0-openjdk" >> "${tmpdir}/.depdetect_centos_list"
+			echo -e "default-jre" >> "${tmpdir}/.depdetect_ubuntu_list"
+			echo -e "default-jre" >> "${tmpdir}/.depdetect_debian_list"
+			libdetected=1
+		fi
+	done
+
+	libs_array=(libtier0.so libtier0_srv.so libvstdlib_srv.so Core.so libvstdlib.so libtier0_s.so Editor.so Engine.so liblua.so libsteam_api.so ld-linux-x86-64.so.2 libPhysX3_x86.so libPhysX3Common_x86.so libPhysX3Cooking_x86.so)
+	for lib_file in "${libs_array[@]}"; do
+		# Known shared libs what dont requires dependencies.
+		if [ "${lib}" == "${lib_file}" ]; then
+			libdetected=1
+		fi
+	done
+
+	if [ "${lib}" == "libstdc++.so.6" ]; then
+		echo -e "libstdc++.i686" >> "${tmpdir}/.depdetect_centos_list"
+		echo -e "libstdc++6:i386" >> "${tmpdir}/.depdetect_ubuntu_list"
+		echo -e "libstdc++6:i386" >> "${tmpdir}/.depdetect_debian_list"
+		libdetected=1
+	elif [ "${lib}" == "libstdc++.so.5" ]; then
+		echo -e "compat-libstdc++-33.i686" >> "${tmpdir}/.depdetect_centos_list"
+		echo -e "libstdc++5:i386" >> "${tmpdir}/.depdetect_ubuntu_list"
+		echo -e "libstdc++5:i386" >> "${tmpdir}/.depdetect_debian_list"
+		libdetected=1
+	elif [ "${lib}" == "libcurl-gnutls.so.4" ]; then
+		echo -e "libcurl.i686" >> "${tmpdir}/.depdetect_centos_list"
+		echo -e "libcurl4-gnutls-dev:i386" >> "${tmpdir}/.depdetect_ubuntu_list"
+		echo -e "libcurl4-gnutls-dev:i386" >> "${tmpdir}/.depdetect_debian_list"
+		libdetected=1
+	elif [ "${lib}" == "libspeex.so.1" ] || [ "${lib}" == "libspeexdsp.so.1" ]; then
+		echo -e "speex.i686" >> "${tmpdir}/.depdetect_centos_list"
+		echo -e "speex:i386" >> "${tmpdir}/.depdetect_ubuntu_list"
+		echo -e "speex:i386" >> "${tmpdir}/.depdetect_debian_list"
+		libdetected=1
+	elif [ "${lib}" == "./libSDL-1.2.so.0" ] || [ "${lib}" == "libSDL-1.2.so.0" ]; then
+		echo -e "SDL.i686" >> "${tmpdir}/.depdetect_centos_list"
+		echo -e "libsdl1.2debian" >> "${tmpdir}/.depdetect_ubuntu_list"
+		echo -e "libsdl1.2debian" >> "${tmpdir}/.depdetect_debian_list"
+		libdetected=1
+	elif [ "${lib}" == "libtbb.so.2" ]; then
+		echo -e "tbb.i686" >> "${tmpdir}/.depdetect_centos_list"
+		echo -e "libtbb2" >> "${tmpdir}/.depdetect_ubuntu_list"
+		echo -e "libtbb2" >> "${tmpdir}/.depdetect_debian_list"
+		libdetected=1
+
+	elif [ "${lib}" == "libXrandr.so.2" ]; then
+		echo -e "libXrandr" >> "${tmpdir}/.depdetect_centos_list"
+		echo -e "libxrandr2" >> "${tmpdir}/.depdetect_ubuntu_list"
+		echo -e "libxrandr2" >> "${tmpdir}/.depdetect_debian_list"
+		libdetected=1
+	elif [ "${lib}" == "libXext.so.6" ]; then
+		echo -e "libXext" >> "${tmpdir}/.depdetect_centos_list"
+		echo -e "libxext6" >> "${tmpdir}/.depdetect_ubuntu_list"
+		echo -e "libxext6" >> "${tmpdir}/.depdetect_debian_list"
+		libdetected=1
+	elif [ "${lib}" == "libXtst.so.6" ]; then
+		echo -e "libXtst" >> "${tmpdir}/.depdetect_centos_list"
+		echo -e "libxtst6" >> "${tmpdir}/.depdetect_ubuntu_list"
+		echo -e "libxtst6" >> "${tmpdir}/.depdetect_debian_list"
+		libdetected=1
+	elif [ "${lib}" == "libpulse.so.0" ]; then
+		echo -e "pulseaudio-libs" >> "${tmpdir}/.depdetect_centos_list"
+		echo -e "libpulse0" >> "${tmpdir}/.depdetect_ubuntu_list"
+		echo -e "libpulse0" >> "${tmpdir}/.depdetect_debian_list"
+		libdetected=1
+	elif [ "${lib}" == "libopenal.so.1" ]; then
+		echo -e "" >> "${tmpdir}/.depdetect_centos_list"
+		echo -e "libopenal1" >> "${tmpdir}/.depdetect_ubuntu_list"
+		echo -e "libopenal1" >> "${tmpdir}/.depdetect_debian_list"
+		libdetected=1
+	elif [ "${lib}" == "libgconf-2.so.4" ]; then
+		echo -e "GConf2" >> "${tmpdir}/.depdetect_centos_list"
+		echo -e "libgconf2-4" >> "${tmpdir}/.depdetect_ubuntu_list"
+		echo -e "libgconf2-4" >> "${tmpdir}/.depdetect_debian_list"
+		libdetected=1
+	elif [ "${lib}" == "libz.so.1" ]; then
+		echo -e "zlib" >> "${tmpdir}/.depdetect_centos_list"
+		echo -e "zlib1g" >> "${tmpdir}/.depdetect_ubuntu_list"
+		echo -e "zlib1g" >> "${tmpdir}/.depdetect_debian_list"
+		libdetected=1
+	elif [ "${lib}" == "libatk-1.0.so.0" ]; then
+		echo -e "atk" >> "${tmpdir}/.depdetect_centos_list"
+		echo -e "libatk1.0-0" >> "${tmpdir}/.depdetect_ubuntu_list"
+		echo -e "libatk1.0-0" >> "${tmpdir}/.depdetect_debian_list"
+		libdetected=1
+	elif [ "${lib}" == "libcairo.so.2" ]; then
+		echo -e "cairo" >> "${tmpdir}/.depdetect_centos_list"
+		echo -e "libcairo2" >> "${tmpdir}/.depdetect_ubuntu_list"
+		echo -e "libcairo2" >> "${tmpdir}/.depdetect_debian_list"
+		libdetected=1
+	elif [ "${lib}" == "libfontconfig.so.1" ]; then
+		echo -e "fontconfig" >> "${tmpdir}/.depdetect_centos_list"
+		echo -e "libfontconfig1" >> "${tmpdir}/.depdetect_ubuntu_list"
+		echo -e "libfontconfig1" >> "${tmpdir}/.depdetect_debian_list"
+		libdetected=1
+	elif [ "${lib}" == "libfreetype.so.6" ]; then
+		echo -e "freetype" >> "${tmpdir}/.depdetect_centos_list"
+		echo -e "libfreetype6" >> "${tmpdir}/.depdetect_ubuntu_list"
+		echo -e "libfreetype6" >> "${tmpdir}/.depdetect_debian_list"
+		libdetected=1
+	elif [ "${lib}" == "libc++.so.1" ]; then
+		echo -e "libcxx" >> "${tmpdir}/.depdetect_centos_list"
+		echo -e "libc++1" >> "${tmpdir}/.depdetect_ubuntu_list"
+		echo -e "libc++1" >> "${tmpdir}/.depdetect_debian_list"
+		libdetected=1
+	fi
+
+	if [ "${libdetected}" != "1" ]; then
+		unknownlib=1
+		echo -e "${lib}" >> "${tmpdir}/.depdetect_unknown"
+	fi
+	unset libdetected
+done < "${tmpdir}/.depdetect_readelf_uniq"
+
+sort "${tmpdir}/.depdetect_centos_list" | uniq >> "${tmpdir}/.depdetect_centos_list_uniq"
+sort "${tmpdir}/.depdetect_ubuntu_list" | uniq >> "${tmpdir}/.depdetect_ubuntu_list_uniq"
+sort "${tmpdir}/.depdetect_debian_list" | uniq >> "${tmpdir}/.depdetect_debian_list_uniq"
+if [ "${unknownlib}" == "1" ]; then
+	sort "${tmpdir}/.depdetect_unknown" | uniq >> "${tmpdir}/.depdetect_unknown_uniq"
+fi
+
+awk -vORS='' '{ print $1,$2 }' "${tmpdir}/.depdetect_centos_list_uniq" > "${tmpdir}/.depdetect_centos_line"
+awk -vORS='' '{ print $1,$2 }' "${tmpdir}/.depdetect_ubuntu_list_uniq" > "${tmpdir}/.depdetect_ubuntu_line"
+awk -vORS='' '{ print $1,$2 }' "${tmpdir}/.depdetect_debian_list_uniq" > "${tmpdir}/.depdetect_debian_line"
+echo -e ""
+echo -e ""
+echo -e "Required Dependencies"
+echo -e "================================="
+echo -e "${executable}"
+echo -e ""
+echo -e "CentOS"
+echo -e "================================="
+cat "${tmpdir}/.depdetect_centos_line"
+echo -e ""
+echo -e ""
+echo -e "Ubuntu"
+echo -e "================================="
+cat "${tmpdir}/.depdetect_ubuntu_line"
+echo -e ""
+echo -e ""
+echo -e "Debian"
+echo -e "================================="
+cat "${tmpdir}/.depdetect_debian_line"
+echo -e ""
+if [ "${unknownlib}" == "1" ]; then
+	echo -e ""
+	echo -e "Unknown shared Library"
+	echo -e "================================="
+	cat "${tmpdir}/.depdetect_unknown"
+fi
+echo -e ""
+echo -e "Required Librarys"
+echo -e "================================="
+sort "${tmpdir}/.depdetect_readelf" | uniq
+echo -en "\n"
+rm -f "${tmpdir:?}/.depdetect_centos_line"
+rm -f "${tmpdir:?}/.depdetect_centos_list"
+rm -f "${tmpdir:?}/.depdetect_centos_list_uniq"
+
+rm -f "${tmpdir:?}/.depdetect_debian_line"
+rm -f "${tmpdir:?}/.depdetect_debian_list"
+rm -f "${tmpdir:?}/.depdetect_debian_list_uniq"
+
+rm -f "${tmpdir:?}/.depdetect_ubuntu_line"
+rm -f "${tmpdir:?}/.depdetect_ubuntu_list"
+rm -f "${tmpdir:?}/.depdetect_ubuntu_list_uniq"
+
+rm -f "${tmpdir:?}/.depdetect_readelf"
+rm -f "${tmpdir:?}/.depdetect_readelf_uniq"
+rm -f "${tmpdir:?}/.depdetect_unknown"
+rm -f "${tmpdir:?}/.depdetect_unknown_uniq"
+
+core_exit.sh

+ 92 - 0
lgsm/modules/command_dev_detect_glibc.sh

@@ -0,0 +1,92 @@
+#!/bin/bash
+# LinuxGSM command_dev_detect_glibc.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Automatically detects the version of GLIBC that is required.
+# Can check a file or directory recursively.
+
+commandname="DEV-DETECT-GLIBC"
+commandaction="Developer detect glibc"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+fn_firstcommand_set
+
+echo -e "================================="
+echo -e "glibc Requirements Checker"
+echo -e "================================="
+
+if [ ! "$(command -v objdump)" ]; then
+	fn_print_failure_nl "objdump is missing"
+	fn_script_log_fatal "objdump is missing"
+	core_exit.sh
+fi
+
+if [ -z "${serverfiles}" ]; then
+	dir=$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")
+fi
+
+if [ -d "${serverfiles}" ]; then
+	echo -e "Checking directory: "
+	echo -e "${serverfiles}"
+elif [ -f "${serverfiles}" ]; then
+	echo -e "Checking file: "
+	echo -e "${serverfiles}"
+fi
+echo -e ""
+
+glibc_check_dir_array=(steamcmddir serverfiles)
+for glibc_check_var in "${glibc_check_dir_array[@]}"; do
+	if [ "${glibc_check_var}" == "serverfiles" ]; then
+		glibc_check_dir="${serverfiles}"
+		glibc_check_name="${gamename}"
+	elif [ "${glibc_check_var}" == "steamcmddir" ]; then
+		glibc_check_dir="${steamcmddir}"
+		glibc_check_name="SteamCMD"
+	fi
+
+	if [ -d "${glibc_check_dir}" ]; then
+		glibc_check_files=$(find "${glibc_check_dir}" | wc -l)
+		find "${glibc_check_dir}" -type f -print0 \
+			| while IFS= read -r -d $'\0' line; do
+				glibcversion=$(objdump -T "${line}" 2> /dev/null | grep -oP "GLIBC[^ ]+" | grep -v GLIBCXX | sort | uniq | sort -r --version-sort | head -n 1)
+				if [ "${glibcversion}" ]; then
+					echo -e "${glibcversion}: ${line}" >> "${tmpdir}/detect_glibc_files_${glibc_check_var}.tmp"
+				fi
+				objdump -T "${line}" 2> /dev/null | grep -oP "GLIBC[^ ]+" >> "${tmpdir}/detect_glibc_${glibc_check_var}.tmp"
+				echo -n "${i} / ${glibc_check_files}" $'\r'
+				((i++))
+			done
+		echo -e ""
+		echo -e ""
+		echo -e "${glibc_check_name} glibc Requirements"
+		echo -e "================================="
+		if [ -f "${tmpdir}/detect_glibc_files_${glibc_check_var}.tmp" ]; then
+			echo -e "Required glibc"
+			cat "${tmpdir}/detect_glibc_${glibc_check_var}.tmp" | sort | uniq | sort -r --version-sort | head -1 | tee -a "${tmpdir}/detect_glibc_highest.tmp"
+			echo -e ""
+			echo -e "Files requiring GLIBC"
+			echo -e "Highest verion required: filename"
+			cat "${tmpdir}/detect_glibc_files_${glibc_check_var}.tmp"
+			echo -e ""
+			echo -e "All required GLIBC versions"
+			cat "${tmpdir}/detect_glibc_${glibc_check_var}.tmp" | sort | uniq | sort -r --version-sort
+			rm -f "${tmpdir:?}/detect_glibc_${glibc_check_var}.tmp"
+			rm -f "${tmpdir:?}/detect_glibc_files_${glibc_check_var}.tmp"
+		else
+			fn_print_information_nl "glibc is not required"
+		fi
+	else
+		fn_print_information_nl "${glibc_check_name} is not installed"
+	fi
+done
+echo -e ""
+echo -e "Final glibc Requirement"
+echo -e "================================="
+if [ -f "${tmpdir}/detect_glibc_highest.tmp" ]; then
+	cat "${tmpdir}/detect_glibc_highest.tmp" | sort | uniq | sort -r --version-sort | head -1
+	rm -f "${tmpdir:?}/detect_glibc_highest.tmp"
+else
+	fn_print_information_nl "glibc is not required"
+fi
+
+core_exit.sh

+ 61 - 0
lgsm/modules/command_dev_detect_ldd.sh

@@ -0,0 +1,61 @@
+#!/bin/bash
+# LinuxGSM command_dev_detect_ldd.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Automatically detects required deps using ldd.
+# Can check a file or directory recursively.
+
+commandname="DEV-DETECT-LDD"
+commandaction="Developer detect ldd"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+fn_firstcommand_set
+
+echo -e "================================="
+echo -e "Shared Object dependencies Checker"
+echo -e "================================="
+
+if [ -z "${serverfiles}" ]; then
+	dir=$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")
+fi
+
+if [ -d "${serverfiles}" ]; then
+	echo -e "Checking directory: "
+	echo -e "${serverfiles}"
+elif [ -f "${serverfiles}" ]; then
+	echo -e "Checking file: "
+	echo -e "${serverfiles}"
+fi
+echo -e ""
+touch "${tmpdir}/detect_ldd.tmp"
+touch "${tmpdir}/detect_ldd_not_found.tmp"
+
+files=$(find "${serverfiles}" | wc -l)
+find "${serverfiles}" -type f -print0 \
+	| while IFS= read -r -d $'\0' line; do
+		if ldd "${line}" 2> /dev/null | grep -v "not a dynamic executable"; then
+			echo -e "${line}" >> "${tmpdir}/detect_ldd.tmp"
+			ldd "${line}" 2> /dev/null | grep -v "not a dynamic executable" >> "${tmpdir}/detect_ldd.tmp"
+			if ldd "${line}" 2> /dev/null | grep -v "not a dynamic executable" | grep "not found"; then
+				echo -e "${line}" >> "${tmpdir}/detect_ldd_not_found.tmp"
+				ldd "${line}" 2> /dev/null | grep -v "not a dynamic executable" | grep "not found" >> "${tmpdir}/detect_ldd_not_found.tmp"
+			fi
+		fi
+		echo -n "$i / $files" $'\r'
+		((i++))
+	done
+echo -e ""
+echo -e ""
+echo -e "All"
+echo -e "================================="
+cat "${tmpdir}/detect_ldd.tmp"
+
+echo -e ""
+echo -e "Not Found"
+echo -e "================================="
+cat "${tmpdir}/detect_ldd_not_found.tmp"
+
+rm -f "${tmpdir:?}/detect_ldd.tmp"
+rm -f "${tmpdir:?}/detect_ldd_not_found.tmp"
+
+core_exit.sh

+ 286 - 0
lgsm/modules/command_dev_query_raw.sh

@@ -0,0 +1,286 @@
+#!/bin/bash
+# LinuxGSM command_dev_query_raw.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Raw gamedig output of the server.
+
+commandname="DEV-QUERY-RAW"
+commandaction="Developer query raw"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+fn_firstcommand_set
+
+check.sh
+info_game.sh
+info_distro.sh
+info_messages.sh
+
+echo -e ""
+echo -e "${lightgreen}Query IP Addresses${default}"
+echo -e "=================================================================="
+echo -e ""
+for queryip in "${queryips[@]}"; do
+	echo -e "${queryip}"
+done
+echo -e ""
+echo -e "${lightgreen}Game Server Ports${default}"
+echo -e "=================================================================="
+{
+	echo -e "${lightblue}Port Name \tPort Number \tStatus \tTCP \tUDP${default}"
+	if [ -v port ]; then
+		echo -e "Game: \t${port} \t$(ss -tupl | grep -c "${port}") \t$(ss -tupl | grep "${port}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${port}" | grep udp | awk '{ print $2 }')"
+	else
+		echo -e "Game:"
+	fi
+	if [ "${shortname}" == "rw" ]; then
+		if [ -v port2 ]; then
+			echo -e "Game+1: \t${port2} \t$(ss -tupl | grep -c "${port}") \t$(ss -tupl | grep "${port2}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${port2}" | grep udp | awk '{ print $2 }')"
+		else
+			echo -e "Game+1:"
+		fi
+
+		if [ -v port3 ]; then
+			echo -e "Game+2: \t${port3} \t$(ss -tupl | grep -c "${port}") \t$(ss -tupl | grep "${port3}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${port3}" | grep udp | awk '{ print $2 }')"
+		else
+			echo -e "Game+2:"
+		fi
+
+		if [ -v port4 ]; then
+			echo -e "Game+3: \t${port4} \t$(ss -tupl | grep -c "${port}") \t$(ss -tupl | grep "${port4}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${port4}" | grep udp | awk '{ print $2 }')"
+		else
+			echo -e "Game+3:"
+		fi
+	fi
+	if [ "${shortname}" == "pvr" ]; then
+		if [ -v port401 ]; then
+			echo -e "Game+400: \t${port401} \t$(ss -tupl | grep -c "${port401}") \t$(ss -tupl | grep "${port401}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${port401}" | grep udp | awk '{ print $2 }')"
+		else
+			echo -e "Game+400:"
+		fi
+	fi
+
+	if [ "${shortname}" == "mcb" ]; then
+		if [ -v portipv6 ]; then
+			echo -e "Game ipv6: \t${portipv6} \t$(ss -tupl | grep -c "${portipv6}") \t$(ss -tupl | grep "${portipv6}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${portipv6}" | grep udp | awk '{ print $2 }')"
+		else
+			echo -e "Game ipv6:"
+		fi
+	fi
+
+	if [ -v queryport ]; then
+		echo -e "Query: \t${queryport} \t$(ss -tupl | grep -c "${queryport}") \t$(ss -tupl | grep "${queryport}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${queryport}" | grep udp | awk '{ print $2 }')"
+	else
+		echo -e "Query:"
+	fi
+
+	if [ -v apiport ]; then
+		echo -e "Game: \t${apiport} \t$(ss -tupl | grep -c "${apiport}") \t$(ss -tupl | grep "${apiport}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${apiport}" | grep udp | awk '{ print $2 }')"
+	else
+		echo -e "API:"
+	fi
+
+	if [ -v appport ]; then
+		echo -e "App: \t${appport} \t$(ss -tupl | grep -c "${appport}") \t$(ss -tupl | grep "${appport}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${appport}" | grep udp | awk '{ print $2 }')"
+	else
+		echo -e "App:"
+	fi
+
+	if [ -v battleeyeport ]; then
+		echo -e "BattleEye: \t${battleeyeport} \t$(ss -tupl | grep -c "${battleeyeport}") \t$(ss -tupl | grep "${battleeyeport}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${battleeyeport}" | grep udp | awk '{ print $2 }')"
+	else
+		echo -e "BattleEye:"
+	fi
+
+	if [ -v beaconport ]; then
+		echo -e "Beacon: \t${beaconport} \t$(ss -tupl | grep -c "${beaconport}") \t$(ss -tupl | grep "${beaconport}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${beaconport}" | grep udp | awk '{ print $2 }')"
+	else
+		echo -e "Beacon:"
+	fi
+
+	if [ -v clientport ]; then
+		echo -e "Client: \t${clientport} \t$(ss -tupl | grep -c "${clientport}") \t$(ss -tupl | grep "${clientport}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${clientport}" | grep udp | awk '{ print $2 }')"
+	else
+		echo -e "Client:"
+	fi
+
+	if [ -v fileport ]; then
+		echo -e "File: \t${fileport} \t$(ss -tupl | grep -c "${fileport}") \t$(ss -tupl | grep "${fileport}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${fileport}" | grep udp | awk '{ print $2 }')"
+	else
+		echo -e "File:"
+	fi
+
+	if [ -v httpport ]; then
+		echo -e "HTTP: \t${httpport} \t$(ss -tupl | grep -c "${httpport}") \t$(ss -tupl | grep "${httpport}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${httpport}" | grep udp | awk '{ print $2 }')"
+	else
+		echo -e "HTTP:"
+	fi
+
+	if [ -v httpqueryport ]; then
+		echo -e "HTTP Query: \t${httpqueryport} \t$(ss -tupl | grep -c "${httpqueryport}") \t$(ss -tupl | grep" ${httpqueryport}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${httpqueryport}" | grep udp | awk '{ print $2 }')"
+	else
+		echo -e "HTTP Query:"
+	fi
+
+	if [ -v httpport ]; then
+		echo -e "Web Interface: \t${httpport} \t$(ss -tupl | grep -c "${httpport}") \t$(ss -tupl | grep "${httpport}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${httpport}" | grep udp | awk '{ print $2 }')"
+	else
+		echo -e "Web Interface:"
+	fi
+
+	if [ -v masterport ]; then
+		echo -e "Game: Master: \t${masterport} \t$(ss -tupl | grep -c "${masterport}") \t$(ss -tupl | grep "${masterport}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${masterport}" | grep udp | awk '{ print $2 }')"
+	else
+		echo -e "Game: Master:"
+	fi
+
+	if [ -v rawport ]; then
+		echo -e "RAW UDP Socket: \t${rawport} \t$(ss -tupl | grep -c "${rawport}") \t$(ss -tupl | grep "${rawport}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${rawport}" | grep udp | awk '{ print $2 }')"
+	else
+		echo -e "RAW UDP Socket:"
+	fi
+
+	if [ -v rconport ]; then
+		echo -e "RCON: \t${rconport} \t$(ss -tupl | grep -c "${rconport}") \t$(ss -tupl | grep "${rconport}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${rconport}" | grep udp | awk '{ print $2 }')"
+	else
+		echo -e "RCON:"
+	fi
+
+	if [ -v steamport ]; then
+		echo -e "Steam: \t${steamport} \t$(ss -tupl | grep -c "${steamport}") \t$(ss -tupl | grep "${steamport}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${steamport}" | grep udp | awk '{ print $2 }')"
+	else
+		echo -e "Steam:"
+	fi
+
+	if [ -v steamworksport ]; then
+		echo -e "Steamworks P2P: \t${steamworksport} \t$(ss -tupl | grep -c "${steamworksport}") \t$(ss -tupl | grep "${steamworksport}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${steamworksport}" | grep udp | awk '{ print $2 }')"
+	else
+		echo -e "Steamworks P2P:"
+	fi
+
+	if [ -v steamauthport ]; then
+		echo -e "Steam: Auth: \t${steamauthport} \t$(ss -tupl | grep -c "${steamauthport}") \t$(ss -tupl | grep "${steamauthport}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${steamauthport}" | grep udp | awk '{ print $2 }')"
+	else
+		echo -e "Steam: Auth:"
+	fi
+
+	if [ -v telnetport ]; then
+		echo -e "Telnet: \t${telnetport} \t$(ss -tupl | grep -c "${telnetport}") \t$(ss -tupl | grep "${telnetport}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${telnetport}" | grep udp | awk '{ print $2 }')"
+	else
+		echo -e "Telnet:"
+	fi
+
+	if [ -v statsport ]; then
+		echo -e "Stats: \t${battleeyeport} \t$(ss -tupl | grep -c "${statsport}") \t$(ss -tupl | grep "${statsport}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${statsport}" | grep udp | awk '{ print $2 }')"
+	else
+		echo -e "Stats:"
+	fi
+
+	if [ -v sourcetvport ]; then
+		echo -e "SourceTV: \t${sourcetvport} \t$(ss -tupl | grep -c "${sourcetvport}") \t$(ss -tupl | grep "${sourcetvport}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${sourcetvport}" | grep udp | awk '{ print $2 }')"
+	else
+		echo -e "SourceTV:"
+	fi
+
+	if [ -v udplinkport ]; then
+		echo -e "UDP Link: \t${udplinkport} \t$(ss -tupl | grep -c "${udplinkport}") \t$(ss -tupl | grep "${udplinkport}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${udplinkport}" | grep udp | awk '{ print $2 }')"
+	else
+		echo -e "UDP Link:"
+	fi
+
+	if [ -v voiceport ]; then
+		echo -e "Voice: \t${voiceport} \t$(ss -tupl | grep -c "${voiceport}") \t$(ss -tupl | grep "${voiceport}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${voiceport}" | grep udp | awk '{ print $2 }')"
+	else
+		echo -e "Voice:"
+	fi
+
+	if [ -v voiceunusedport ]; then
+		echo -e "Voice (Unused): \t${voiceunusedport} \t$(ss -tupl | grep -c "${voiceunusedport}") \t$(ss -tupl | grep "${voiceunusedport}" | grep tcp | awk '{ print $2 }') \t$(ss -tupl | grep "${voiceunusedport}" | grep udp | awk '{ print $2 }')"
+	else
+		echo -e "Voice (Unused):"
+	fi
+
+} \
+	| column -s $'\t' -t
+echo -e ""
+echo -e "${lightgreen}SS Output${default}"
+echo -e "================================="
+fn_info_message_ports
+eval "${portcommand}"
+echo -e ""
+echo -e "${lightgreen}Query Port - Raw Output${default}"
+echo -e "=================================================================="
+echo -e ""
+echo -e "PORT: ${port}"
+echo -e "QUERY PORT: ${queryport}"
+echo -e ""
+echo -e "${lightgreen}Gamedig Raw Output${default}"
+echo -e "================================="
+echo -e ""
+if [ ! "$(command -v gamedig 2> /dev/null)" ]; then
+	fn_print_failure_nl "gamedig not installed"
+fi
+if [ ! "$(command -v jq 2> /dev/null)" ]; then
+	fn_print_failure_nl "jq not installed"
+fi
+for queryip in "${queryips[@]}"; do
+	query_gamedig.sh
+	echo -e "${gamedigcmd}"
+	echo""
+	echo "${gamedigraw}" | jq
+done
+echo -e ""
+echo -e "${lightgreen}gsquery Raw Output${default}"
+echo -e "================================="
+echo -e ""
+for queryip in "${queryips[@]}"; do
+	echo -e "./query_gsquery.py -a \"${queryip}\" -p \"${queryport}\" -e \"${querytype}\""
+	echo -e ""
+	if [ ! -f "${modulesdir}/query_gsquery.py" ]; then
+		fn_fetch_file_github "lgsm/modules" "query_gsquery.py" "${modulesdir}" "chmodx" "norun" "noforce" "nohash"
+	fi
+	"${modulesdir}"/query_gsquery.py -a "${queryip}" -p "${queryport}" -e "${querytype}"
+done
+echo -e ""
+echo -e "${lightgreen}TCP Raw Output${default}"
+echo -e "================================="
+echo -e ""
+for queryip in "${queryips[@]}"; do
+	echo -e "bash -c 'exec 3<> /dev/tcp/'${queryip}'/'${queryport}''"
+	echo -e ""
+	timeout 3 bash -c 'exec 3<> /dev/tcp/'${queryip}'/'${queryport}''
+	querystatus="$?"
+	echo -e ""
+	if [ "${querystatus}" == "0" ]; then
+		echo -e "TCP query PASS"
+	else
+		echo -e "TCP query FAIL"
+	fi
+done
+echo -e ""
+echo -e "${lightgreen}Game Port - Raw Output${default}"
+echo -e "=================================================================="
+echo -e ""
+echo -e "${lightgreen}TCP Raw Output${default}"
+echo -e "================================="
+echo -e ""
+for queryip in "${queryips[@]}"; do
+	echo -e "bash -c 'exec 3<> /dev/tcp/'${queryip}'/'${port}''"
+	echo -e ""
+	timeout 3 bash -c 'exec 3<> /dev/tcp/'${queryip}'/'${port}''
+	querystatus="$?"
+	echo -e ""
+	if [ "${querystatus}" == "0" ]; then
+		echo -e "TCP query PASS"
+	else
+		echo -e "TCP query FAIL"
+	fi
+done
+echo -e ""
+echo -e "${lightgreen}Steam Master Server Response${default}"
+echo -e "=================================================================="
+echo -e ""
+echo -e "Response: ${displaymasterserver}"
+echo -e ""
+
+exitcode=0
+core_exit.sh

+ 442 - 0
lgsm/modules/command_fastdl.sh

@@ -0,0 +1,442 @@
+#!/bin/bash
+# LinuxGSM command_fastdl.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Creates a FastDL directory.
+
+commandname="FASTDL"
+commandaction="Fastdl"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+fn_firstcommand_set
+
+check.sh
+
+# Directories.
+if [ -z "${webdir}" ]; then
+	webdir="${rootdir}/public_html"
+fi
+fastdldir="${webdir}/fastdl"
+addonsdir="${systemdir}/addons"
+# Server lua autorun dir, used to autorun lua on client connect to the server.
+luasvautorundir="${systemdir}/lua/autorun/server"
+luafastdlfile="lgsm_cl_force_fastdl.lua"
+luafastdlfullpath="${luasvautorundir}/${luafastdlfile}"
+
+# Check if bzip2 is installed.
+if [ ! "$(command -v bzip2 2> /dev/null)" ]; then
+	fn_print_fail "bzip2 is not installed"
+	fn_script_log_fatal "bzip2 is not installed"
+	core_exit.sh
+fi
+
+# Header
+fn_print_header
+echo -e "More info: https://docs.linuxgsm.com/commands/fastdl"
+echo -e ""
+
+# Prompts user for FastDL creation settings.
+echo -e "${commandaction} setup"
+echo -e "================================="
+
+# Prompt for clearing old files if directory was already here.
+if [ -d "${fastdldir}" ]; then
+	fn_print_warning_nl "FastDL directory already exists."
+	echo -e "${fastdldir}"
+	echo -e ""
+	if fn_prompt_yn "Overwrite existing directory?" Y; then
+		fn_script_log_info "Overwrite existing directory: YES"
+	else
+		core_exit.sh
+	fi
+fi
+
+# Garry's Mod Specific.
+if [ "${shortname}" == "gmod" ]; then
+	# Prompt for download enforcer, which is using a .lua addfile resource generator.
+	if fn_prompt_yn "Force clients to download files?" Y; then
+		luaresource="on"
+		fn_script_log_info "Force clients to download files: YES"
+	else
+		luaresource="off"
+		fn_script_log_info "Force clients to download filesr: NO"
+	fi
+fi
+
+# Clears any fastdl directory content.
+fn_clear_old_fastdl() {
+	# Clearing old FastDL.
+	if [ -d "${fastdldir}" ]; then
+		echo -en "clearing existing FastDL directory ${fastdldir}..."
+		rm -rf "${fastdldir:?}"
+		exitcode=$?
+		if [ "${exitcode}" != 0 ]; then
+			fn_print_fail_eol_nl
+			fn_script_log_fatal "Clearing existing FastDL directory ${fastdldir}"
+			core_exit.sh
+		else
+			fn_print_ok_eol_nl
+			fn_script_log_pass "Clearing existing FastDL directory ${fastdldir}"
+		fi
+	fi
+}
+
+fn_fastdl_dirs() {
+	# Check and create directories.
+	if [ ! -d "${webdir}" ]; then
+		echo -en "creating web directory ${webdir}..."
+		mkdir -p "${webdir}"
+		exitcode=$?
+		if [ "${exitcode}" != 0 ]; then
+			fn_print_fail_eol_nl
+			fn_script_log_fatal "Creating web directory ${webdir}"
+			core_exit.sh
+		else
+			fn_print_ok_eol_nl
+			fn_script_log_pass "Creating web directory ${webdir}"
+		fi
+	fi
+	if [ ! -d "${fastdldir}" ]; then
+		echo -en "creating fastdl directory ${fastdldir}..."
+		mkdir -p "${fastdldir}"
+		exitcode=$?
+		if [ "${exitcode}" != 0 ]; then
+			fn_print_fail_eol_nl
+			fn_script_log_fatal "Creating fastdl directory ${fastdldir}"
+			core_exit.sh
+		else
+			fn_print_ok_eol_nl
+			fn_script_log_pass "Creating fastdl directory ${fastdldir}"
+		fi
+	fi
+}
+
+# Using this gist https://gist.github.com/agunnerson-ibm/efca449565a3e7356906
+fn_human_readable_file_size() {
+	local abbrevs=(
+		$((1 << 60)):ZB
+		$((1 << 50)):EB
+		$((1 << 40)):TB
+		$((1 << 30)):GB
+		$((1 << 20)):MB
+		$((1 << 10)):KB
+		$((1)):bytes
+	)
+
+	local bytes="${1}"
+	local precision="${2}"
+
+	if [[ "${bytes}" == "1" ]]; then
+		echo -e "1 byte"
+	else
+		for item in "${abbrevs[@]}"; do
+			local factor="${item%:*}"
+			local abbrev="${item#*:}"
+			if [[ "${bytes}" -ge "${factor}" ]]; then
+				size=$(bc -l <<< "${bytes} / ${factor}")
+				printf "%.*f %s\n" "${precision}" "${size}" "${abbrev}"
+				break
+			fi
+		done
+	fi
+}
+
+# Provides info about the fastdl directory content and prompts for confirmation.
+fn_fastdl_preview() {
+	# Remove any file list.
+	if [ -f "${tmpdir}/fastdl_files_to_compress.txt" ]; then
+		rm -f "${tmpdir:?}/fastdl_files_to_compress.txt"
+	fi
+	echo -e "analysing required files"
+	fn_script_log_info "Analysing required files"
+	# Garry's Mod
+	if [ "${shortname}" == "gmod" ]; then
+		cd "${systemdir}" || exit
+		allowed_extentions_array=("*.ain" "*.bsp" "*.mdl" "*.mp3" "*.ogg" "*.otf" "*.pcf" "*.phy" "*.png" "*.svg" "*.vtf" "*.vmt" "*.vtx" "*.vvd" "*.ttf" "*.wav")
+		for allowed_extention in "${allowed_extentions_array[@]}"; do
+			fileswc=0
+			tput sc
+			while read -r ext; do
+				((fileswc++))
+				tput rc
+				tput el
+				echo -e "gathering ${allowed_extention} : ${fileswc}..."
+				echo -e "${ext}" >> "${tmpdir}/fastdl_files_to_compress.txt"
+			done < <(find . -type f -iname "${allowed_extention}")
+			if [ ${fileswc} != 0 ]; then
+				fn_print_ok_eol_nl
+			else
+				fn_print_info_eol_nl
+			fi
+		done
+	# Source engine
+	else
+		fastdl_directories_array=("maps" "materials" "models" "particles" "sound" "resources")
+		for directory in "${fastdl_directories_array[@]}"; do
+			if [ -d "${systemdir}/${directory}" ]; then
+				if [ "${directory}" == "maps" ]; then
+					local allowed_extentions_array=("*.bsp" "*.ain" "*.nav" "*.jpg" "*.txt")
+				elif [ "${directory}" == "materials" ]; then
+					local allowed_extentions_array=("*.vtf" "*.vmt" "*.vbf" "*.png" "*.svg")
+				elif [ "${directory}" == "models" ]; then
+					local allowed_extentions_array=("*.vtx" "*.vvd" "*.mdl" "*.phy" "*.jpg" "*.png" "*.vmt" "*.vtf")
+				elif [ "${directory}" == "particles" ]; then
+					local allowed_extentions_array=("*.pcf")
+				elif [ "${directory}" == "sound" ]; then
+					local allowed_extentions_array=("*.wav" "*.mp3" "*.ogg")
+				fi
+				for allowed_extention in "${allowed_extentions_array[@]}"; do
+					fileswc=0
+					tput sc
+					while read -r ext; do
+						((fileswc++))
+						tput rc
+						tput el
+						echo -e "gathering ${directory} ${allowed_extention} : ${fileswc}..."
+						echo -e "${ext}" >> "${tmpdir}/fastdl_files_to_compress.txt"
+					done < <(find "${systemdir}/${directory}" -type f -iname "${allowed_extention}")
+					tput rc
+					tput el
+					echo -e "gathering ${directory} ${allowed_extention} : ${fileswc}..."
+					if [ ${fileswc} != 0 ]; then
+						fn_print_ok_eol_nl
+					else
+						fn_print_info_eol_nl
+					fi
+				done
+			fi
+		done
+	fi
+	if [ -f "${tmpdir}/fastdl_files_to_compress.txt" ]; then
+		echo -e "calculating total file size..."
+		fn_sleep_time
+		totalfiles=$(wc -l < "${tmpdir}/fastdl_files_to_compress.txt")
+		# Calculates total file size.
+		while read -r dufile; do
+			filesize=$(stat -c %s "${dufile}")
+			filesizetotal=$((filesizetotal + filesize))
+			exitcode=$?
+			if [ "${exitcode}" != 0 ]; then
+				fn_print_fail_eol_nl
+				fn_script_log_fatal "Calculating total file size."
+				core_exit.sh
+			fi
+		done < "${tmpdir}/fastdl_files_to_compress.txt"
+	else
+		fn_print_fail_eol_nl "generating file list"
+		fn_script_log_fatal "Generating file list."
+		core_exit.sh
+	fi
+	echo -e "about to compress ${totalfiles} files, total size $(fn_human_readable_file_size ${filesizetotal} 0)"
+	fn_script_log_info "${totalfiles} files, total size $(fn_human_readable_file_size ${filesizetotal} 0)"
+	rm -f "${tmpdir:?}/fastdl_files_to_compress.txt"
+	if ! fn_prompt_yn "Continue?" Y; then
+		fn_script_log "User exited"
+		core_exit.sh
+	fi
+}
+
+# Builds Garry's Mod fastdl directory content.
+fn_fastdl_gmod() {
+	cd "${systemdir}" || exit
+	for allowed_extention in "${allowed_extentions_array[@]}"; do
+		fileswc=0
+		tput sc
+		while read -r fastdlfile; do
+			((fileswc++))
+			tput rc
+			tput el
+			echo -e "copying ${allowed_extention} : ${fileswc}..."
+			cp --parents "${fastdlfile}" "${fastdldir}"
+			exitcode=$?
+			if [ "${exitcode}" != 0 ]; then
+				fn_print_fail_eol_nl
+				fn_script_log_fatal "Copying ${fastdlfile} > ${fastdldir}"
+				core_exit.sh
+			else
+				fn_script_log_pass "Copying ${fastdlfile} > ${fastdldir}"
+			fi
+		done < <(find . -type f -iname "${allowed_extention}")
+		if [ ${fileswc} != 0 ]; then
+			fn_print_ok_eol_nl
+		fi
+	done
+	# Correct addons directory structure for FastDL.
+	if [ -d "${fastdldir}/addons" ]; then
+		echo -en "updating addons file structure..."
+		cp -Rf "${fastdldir}"/addons/*/* "${fastdldir}"
+		exitcode=$?
+		if [ "${exitcode}" != 0 ]; then
+			fn_print_fail_eol_nl
+			fn_script_log_fatal "Updating addons file structure"
+			core_exit.sh
+		else
+			fn_print_ok_eol_nl
+			fn_script_log_pass "Updating addons file structure"
+		fi
+		# Clear addons directory in fastdl.
+		echo -en "clearing addons dir from fastdl dir..."
+		fn_sleep_time
+		rm -rf "${fastdldir:?}/addons"
+		exitcode=$?
+		if [ "${exitcode}" != 0 ]; then
+			fn_print_fail_eol_nl
+			fn_script_log_fatal "Clearing addons dir from fastdl dir"
+			core_exit.sh
+		else
+			fn_print_ok_eol_nl
+			fn_script_log_pass "Clearing addons dir from fastdl dir"
+		fi
+	fi
+	# Correct content that may be into a lua directory by mistake like some darkrpmodification addons.
+	if [ -d "${fastdldir}/lua" ]; then
+		echo -en "correcting DarkRP files..."
+		fn_sleep_time
+		cp -Rf "${fastdldir}/lua/"* "${fastdldir}"
+		exitcode=$?
+		if [ "${exitcode}" != 0 ]; then
+			fn_print_fail_eol_nl
+			fn_script_log_fatal "Correcting DarkRP files"
+			core_exit.sh
+		else
+			fn_print_ok_eol_nl
+			fn_script_log_pass "Correcting DarkRP files"
+		fi
+	fi
+	if [ -f "${tmpdir}/fastdl_files_to_compress.txt" ]; then
+		totalfiles=$(wc -l < "${tmpdir}/fastdl_files_to_compress.txt")
+		# Calculates total file size.
+		while read -r dufile; do
+			filesize=$(du -b "${dufile}" | awk '{ print $1 }')
+			filesizetotal=$((filesizetotal + filesize))
+		done < "${tmpdir}/fastdl_files_to_compress.txt"
+	fi
+}
+
+fn_fastdl_source() {
+	for directory in "${fastdl_directories_array[@]}"; do
+		if [ -d "${systemdir}/${directory}" ]; then
+			if [ "${directory}" == "maps" ]; then
+				local allowed_extentions_array=("*.bsp" "*.ain" "*.nav" "*.jpg" "*.txt")
+			elif [ "${directory}" == "materials" ]; then
+				local allowed_extentions_array=("*.vtf" "*.vmt" "*.vbf" "*.png" "*.svg")
+			elif [ "${directory}" == "models" ]; then
+				local allowed_extentions_array=("*.vtx" "*.vvd" "*.mdl" "*.phy" "*.jpg" "*.png")
+			elif [ "${directory}" == "particles" ]; then
+				local allowed_extentions_array=("*.pcf")
+			elif [ "${directory}" == "sound" ]; then
+				local allowed_extentions_array=("*.wav" "*.mp3" "*.ogg")
+			fi
+			for allowed_extention in "${allowed_extentions_array[@]}"; do
+				fileswc=0
+				tput sc
+				while read -r fastdlfile; do
+					((fileswc++))
+					tput rc
+					tput el
+					echo -e "copying ${directory} ${allowed_extention} : ${fileswc}..."
+					fn_sleep_time
+					# get relative path of file in the dir
+					tmprelfilepath="${fastdlfile#"${systemdir}/"}"
+					copytodir="${tmprelfilepath%/*}"
+					# create relative path for fastdl
+					if [ ! -d "${fastdldir}/${copytodir}" ]; then
+						mkdir -p "${fastdldir}/${copytodir}"
+					fi
+					cp "${fastdlfile}" "${fastdldir}/${copytodir}"
+					exitcode=$?
+					if [ "${exitcode}" != 0 ]; then
+						fn_print_fail_eol_nl
+						fn_script_log_fatal "Copying ${fastdlfile} > ${fastdldir}/${copytodir}"
+						core_exit.sh
+					else
+						fn_script_log_pass "Copying ${fastdlfile} > ${fastdldir}/${copytodir}"
+					fi
+				done < <(find "${systemdir}/${directory}" -type f -iname "${allowed_extention}")
+				if [ ${fileswc} != 0 ]; then
+					fn_print_ok_eol_nl
+				fi
+			done
+		fi
+	done
+}
+
+# Builds the fastdl directory content.
+fn_fastdl_build() {
+	# Copy all needed files for FastDL.
+	echo -e "copying files to ${fastdldir}"
+	fn_script_log_info "Copying files to ${fastdldir}"
+	if [ "${shortname}" == "gmod" ]; then
+		fn_fastdl_gmod
+		fn_fastdl_gmod_dl_enforcer
+	else
+		fn_fastdl_source
+	fi
+}
+
+# Generate lua file that will force download any file into the FastDL directory.
+fn_fastdl_gmod_dl_enforcer() {
+	# Clear old lua file.
+	if [ -f "${luafastdlfullpath}" ]; then
+		echo -en "removing existing download enforcer: ${luafastdlfile}..."
+		rm -f "${luafastdlfullpath:?}"
+		exitcode=$?
+		if [ "${exitcode}" != 0 ]; then
+			fn_print_fail_eol_nl
+			fn_script_log_fatal "Removing existing download enforcer ${luafastdlfullpath}"
+			core_exit.sh
+		else
+			fn_print_ok_eol_nl
+			fn_script_log_pass "Removing existing download enforcer ${luafastdlfullpath}"
+		fi
+	fi
+	# Generate new one if user said yes.
+	if [ "${luaresource}" == "on" ]; then
+		echo -en "creating new download enforcer: ${luafastdlfile}..."
+		touch "${luafastdlfullpath}"
+		# Read all filenames and put them into a lua file at the right path.
+		while read -r line; do
+			echo -e "resource.AddFile( \"${line}\" )" >> "${luafastdlfullpath}"
+		done < <(find "${fastdldir:?}" \( -type f ! -name "*.bz2" \) -printf '%P\n')
+		exitcode=$?
+		if [ "${exitcode}" != 0 ]; then
+			fn_print_fail_eol_nl
+			fn_script_log_fatal "Creating new download enforcer ${luafastdlfullpath}"
+			core_exit.sh
+		else
+			fn_print_ok_eol_nl
+			fn_script_log_pass "Creating new download enforcer ${luafastdlfullpath}"
+		fi
+	fi
+}
+
+# Compresses FastDL files using bzip2.
+fn_fastdl_bzip2() {
+	while read -r filetocompress; do
+		echo -en "\r\033[Kcompressing ${filetocompress}..."
+		bzip2 -f "${filetocompress}"
+		exitcode=$?
+		if [ "${exitcode}" != 0 ]; then
+			fn_print_fail_eol_nl
+			fn_script_log_fatal "Compressing ${filetocompress}"
+			core_exit.sh
+		else
+			fn_script_log_pass "Compressing ${filetocompress}"
+		fi
+	done < <(find "${fastdldir:?}" \( -type f ! -name "*.bz2" \))
+	fn_print_ok_eol_nl
+}
+
+# Run functions.
+fn_fastdl_preview
+fn_clear_old_fastdl
+fn_fastdl_dirs
+fn_fastdl_build
+fn_fastdl_bzip2
+# Finished message.
+echo -e "FastDL files are located in:"
+echo -e "${fastdldir}"
+echo -e "FastDL completed"
+fn_script_log_info "FastDL completed"
+
+core_exit.sh

+ 52 - 0
lgsm/modules/command_install.sh

@@ -0,0 +1,52 @@
+#!/bin/bash
+# LinuxGSM command_install.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Overall module for the installer.
+
+commandname="INSTALL"
+commandaction="Installing"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+fn_firstcommand_set
+
+check.sh
+if [ "$(whoami)" == "root" ] && [ ! -f /.dockerenv ]; then
+	check_deps.sh
+else
+	install_header.sh
+	install_server_dir.sh
+	install_logs.sh
+	check_deps.sh
+	installflag=1
+	# Download and install.
+	if [ "${shortname}" == "ut2k4" ]; then
+		install_server_files.sh
+		install_ut2k4_key.sh
+	elif [ -z "${appid}" ]; then
+		install_server_files.sh
+	elif [ "${appid}" ]; then
+		install_steamcmd.sh
+		install_server_files.sh
+	fi
+
+	# Configuration.
+	install_config.sh
+	if [ -v gslt ]; then
+		install_gslt.sh
+	elif [ "${shortname}" == "dst" ]; then
+		install_dst_token.sh
+	elif [ "${shortname}" == "squad" ]; then
+		install_squad_license.sh
+	elif [ "${shortname}" == "ts3" ]; then
+		install_ts3db.sh
+	elif [ "${shortname}" == "mta" ]; then
+		command_install_resources_mta.sh
+		fn_firstcommand_reset
+	fi
+
+	fix.sh
+	install_stats.sh
+	install_complete.sh
+fi
+core_exit.sh

+ 32 - 0
lgsm/modules/command_install_resources_mta.sh

@@ -0,0 +1,32 @@
+#!/bin/bash
+# LinuxGSM command_install_resources_mta.sh module
+# Author: Daniel Gibbs
+# Contributors: http://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Installs the default resources for Multi Theft Auto.
+
+commandname="DEFAULT-RESOURCES"
+commandaction="Default Resources"
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+fn_firstcommand_set
+
+fn_install_resources() {
+	echo -e ""
+	echo -e "${lightyellow}Installing Default Resources${default}"
+	echo -e "================================="
+	fn_fetch_file "http://mirror.mtasa.com/mtasa/resources/mtasa-resources-latest.zip" "" "" "" "${tmpdir}" "mtasa-resources-latest.zip" "nochmodx" "norun" "noforce" "nohash"
+	fn_dl_extract "${tmpdir}" "mtasa-resources-latest.zip" "${resourcesdir}"
+	echo -e "Default Resources Installed."
+}
+
+fn_print_header
+
+if [ -z "${autoinstall}" ]; then
+	fn_print_warning_nl "Installing the default resources with existing resources may cause issues."
+	if fn_prompt_yn "Do you want to install MTA default resources?" Y; then
+		fn_install_resources
+	fi
+else
+	fn_print_warning_nl "Default resources are not installed when using ./${selfname} auto-install."
+	fn_print_information_nl "To install default resources use ./${selfname} install"
+fi

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików