Просмотр исходного кода

feat(bmpserver): add BeamMP server (#5212)

Adds BeamMP (bmpserver) for BeamNG.drive multiplayer. Installs the official BeamMP-Server release for the distro with a SHA256 check, fetches the default config from Game-Server-Configs, and refuses to start until an AuthKey from keymaster.beammp.com is set.

Fixes #4495
Daniel Gibbs 2 дней назад
Родитель
Сommit
f775d10476

+ 1 - 0
LICENSE.md

@@ -25,3 +25,4 @@ SOFTWARE.
 The following files are not covered by the MIT License above and remain under their own licenses.
 The following files are not covered by the MIT License above and remain under their own licenses.
 
 
 - `lgsm/data/gameicons/luanti-icon.png`: Luanti icon by erle, licensed under [CC BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/). Copied without modification from [Luanti 5.17.0](https://github.com/luanti-org/luanti/blob/5.17.0/misc/luanti-icon-24x24.png); see the [upstream license and attribution](https://github.com/luanti-org/luanti/blob/5.17.0/LICENSE.txt).
 - `lgsm/data/gameicons/luanti-icon.png`: Luanti icon by erle, licensed under [CC BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/). Copied without modification from [Luanti 5.17.0](https://github.com/luanti-org/luanti/blob/5.17.0/misc/luanti-icon-24x24.png); see the [upstream license and attribution](https://github.com/luanti-org/luanti/blob/5.17.0/LICENSE.txt).
+- `lgsm/data/gameicons/bmp-icon.png`: BeamMP logo, copyright BeamMP Ltd. and its contributors, not covered by the MIT License. Resized from the favicon at [beammp.com](https://beammp.com).

+ 203 - 0
lgsm/config-default/config-lgsm/bmpserver/_default.cfg

@@ -0,0 +1,203 @@
+##################################
+######## 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="30814"
+
+## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters
+startparameters="--config=${servercfgfullpath} --working-directory=${serverfiles} --port=${port}"
+
+## Extra Parameters | https://docs.linuxgsm.com/configuration/start-parameters#extra-parameters
+# Added to the end of startparameters.
+extraparams=""
+
+#### 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"
+
+# Alert on Start/Stop/Restart
+statusalert="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"
+
+# ntfy Alerts | https://docs.linuxgsm.com/alerts/ntfy
+ntfyalert="off"
+ntfytopic="LinuxGSM"
+ntfyserver="https://ntfy.sh"
+ntfytoken=""
+ntfyusername=""
+ntfypassword=""
+ntfypriority=""
+ntfytags=""
+
+# Matrix Alerts | https://docs.linuxgsm.com/alerts/matrix
+matrixalert="off"
+matrixhomeserver="matrix.org"
+matrixtoken="accesstoken"
+matrixroom=""
+
+# 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"
+
+# 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 all".
+telegramapi="api.telegram.org"
+telegramalert="off"
+telegramtoken="accesstoken"
+telegramchatid=""
+telegramthreadid=""
+telegramsilentnotification="false"
+curlcustomstring=""
+
+## Stop | https://docs.linuxgsm.com/commands/start-stop-restart
+stoponlyifnoplayers="off"
+stoponlyifnoplayersallcommands="on"
+
+## Player Warnings | https://docs.linuxgsm.com/features/player-warnings
+# Minutes to warn players in-game before a stop, restart or update. 0 to disable.
+# e.g. 15 warns at 15, 10, 5, 3 and 1 minutes.
+warnplayerstimer="0"
+
+## 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"
+
+## 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="5"
+querytype=""
+
+## Console type
+consoleverbose="yes"
+consoleinteract="yes"
+
+## Game Server Details
+# Do not edit
+gamename="BeamMP"
+engine="bmp"
+glibc="2.35"
+
+#### Directories ####
+# Edit with care
+
+## Game Server Directories
+systemdir="${serverfiles}"
+executabledir="${serverfiles}"
+executable="./BeamMP-Server"
+servercfgdir="${systemdir}"
+servercfg="${selfname}.toml"
+servercfgdefault="ServerConfig.toml"
+servercfgfullpath="${servercfgdir}/${servercfg}"
+
+## Backup Directory
+backupdir="${lgsmdir}/backup"
+
+## Logging Directories
+[ -n "${LGSM_LOGDIR}" ] && logdir="${LGSM_LOGDIR}" || logdir="${rootdir}/log"
+gamelogdir="${logdir}/server"
+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 - 0
lgsm/data/almalinux-8.csv

@@ -1,4 +1,5 @@
 all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,procps-ng,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,pigz,procps-ng,python36,tar,tmux,unzip,util-linux,wget,xz
+bmp
 steamcmd,glibc.i686,libstdc++.i686
 steamcmd,glibc.i686,libstdc++.i686
 ac
 ac
 ahl
 ahl

+ 1 - 0
lgsm/data/almalinux-9.csv

@@ -1,4 +1,5 @@
 all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,procps-ng,python3,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,pigz,procps-ng,python3,tar,tmux,unzip,util-linux,wget,xz
+bmp
 steamcmd,glibc.i686,libstdc++.i686
 steamcmd,glibc.i686,libstdc++.i686
 ac
 ac
 ahl
 ahl

+ 1 - 0
lgsm/data/centos-7.csv

@@ -1,4 +1,5 @@
 all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,procps-ng,python3,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,pigz,procps-ng,python3,tar,tmux,unzip,util-linux,wget,xz
+bmp
 steamcmd,glibc.i686,libstdc++.i686
 steamcmd,glibc.i686,libstdc++.i686
 ac
 ac
 ahl
 ahl

+ 1 - 0
lgsm/data/centos-8.csv

@@ -1,4 +1,5 @@
 all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,procps-ng,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,pigz,procps-ng,python36,tar,tmux,unzip,util-linux,wget,xz
+bmp
 steamcmd,glibc.i686,libstdc++.i686
 steamcmd,glibc.i686,libstdc++.i686
 ac
 ac
 ahl
 ahl

+ 1 - 0
lgsm/data/centos-9.csv

@@ -1,4 +1,5 @@
 all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,procps-ng,python3,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,pigz,procps-ng,python3,tar,tmux,unzip,util-linux,wget,xz
+bmp
 steamcmd,glibc.i686,libstdc++.i686
 steamcmd,glibc.i686,libstdc++.i686
 ac
 ac
 ahl
 ahl

+ 1 - 0
lgsm/data/debian-10.csv

@@ -14,6 +14,7 @@ bf1942,libc6:i386
 bfe
 bfe
 bfv,libc6:i386
 bfv,libc6:i386
 bmdm,libncurses5:i386
 bmdm,libncurses5:i386
+bmp,liblua5.3-0
 bo
 bo
 bs
 bs
 bt,dos2unix,libxml2-utils
 bt,dos2unix,libxml2-utils

+ 1 - 0
lgsm/data/debian-11.csv

@@ -1,4 +1,5 @@
 all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils
 all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils
+bmp,liblua5.3-0
 steamcmd,lib32gcc-s1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd
 steamcmd,lib32gcc-s1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd
 ac
 ac
 ahl
 ahl

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

@@ -1,4 +1,5 @@
 all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat-openbsd,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils
 all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat-openbsd,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils
+bmp,liblua5.3-0
 steamcmd,lib32gcc-s1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd
 steamcmd,lib32gcc-s1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd
 ac
 ac
 ahl
 ahl

+ 1 - 0
lgsm/data/debian-13.csv

@@ -1,4 +1,5 @@
 all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat-openbsd,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils
 all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat-openbsd,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils
+bmp,liblua5.3-0
 steamcmd,lib32gcc-s1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd
 steamcmd,lib32gcc-s1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd
 ac
 ac
 ahl
 ahl

+ 1 - 0
lgsm/data/debian-9.csv

@@ -1,4 +1,5 @@
 all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc1,lib32stdc++6,netcat,pigz,procps,python3,tar,tmux,unzip,util-linux,wget,xz-utils
 all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc1,lib32stdc++6,netcat,pigz,procps,python3,tar,tmux,unzip,util-linux,wget,xz-utils
+bmp,liblua5.3-0
 steamcmd,lib32gcc1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd
 steamcmd,lib32gcc1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd
 ac
 ac
 ahl
 ahl

BIN
lgsm/data/gameicons/bmp-icon.png


+ 1 - 0
lgsm/data/name-left.csv

@@ -7,6 +7,7 @@ angry
 awesome
 awesome
 beautiful
 beautiful
 blissful
 blissful
+bmp
 bold
 bold
 boring
 boring
 brave
 brave

+ 1 - 0
lgsm/data/name-right.csv

@@ -21,6 +21,7 @@ bhaskara
 black
 black
 blackburn
 blackburn
 blackwell
 blackwell
+bmp
 bohr
 bohr
 booth
 booth
 borg
 borg

+ 1 - 0
lgsm/data/rhel-7.csv

@@ -1,4 +1,5 @@
 all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,procps-ng,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,pigz,procps-ng,python36,tar,tmux,unzip,util-linux,wget,xz
+bmp
 steamcmd,glibc.i686,libstdc++.i686
 steamcmd,glibc.i686,libstdc++.i686
 ac
 ac
 ahl
 ahl

+ 1 - 0
lgsm/data/rhel-8.csv

@@ -1,4 +1,5 @@
 all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,procps-ng,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,pigz,procps-ng,python36,tar,tmux,unzip,util-linux,wget,xz
+bmp
 steamcmd,glibc.i686,libstdc++.i686
 steamcmd,glibc.i686,libstdc++.i686
 ac
 ac
 ahl
 ahl

+ 1 - 0
lgsm/data/rhel-9.csv

@@ -1,4 +1,5 @@
 all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,procps-ng,python3,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,pigz,procps-ng,python3,tar,tmux,unzip,util-linux,wget,xz
+bmp
 steamcmd,glibc.i686,libstdc++.i686
 steamcmd,glibc.i686,libstdc++.i686
 ac
 ac
 ahl
 ahl

+ 1 - 0
lgsm/data/rocky-8.csv

@@ -1,4 +1,5 @@
 all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,procps-ng,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,pigz,procps-ng,python36,tar,tmux,unzip,util-linux,wget,xz
+bmp
 steamcmd,glibc.i686,libstdc++.i686
 steamcmd,glibc.i686,libstdc++.i686
 ac
 ac
 ahl
 ahl

+ 1 - 0
lgsm/data/rocky-9.csv

@@ -1,4 +1,5 @@
 all,bc,binutils,bzip2,cpio,curl,epel-release,file,glibc.i686,gzip,hostname,jq,libstdc++,libstdc++.i686,nmap-ncat,pigz,procps-ng,python3,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,pigz,procps-ng,python3,tar,tmux,unzip,util-linux,wget,xz
+bmp
 steamcmd,glibc.i686,libstdc++.i686
 steamcmd,glibc.i686,libstdc++.i686
 ac
 ac
 ahl
 ahl

+ 1 - 0
lgsm/data/serverlist.csv

@@ -14,6 +14,7 @@ bf1942,bf1942server,Battlefield 1942,ubuntu-26.04
 bfe,bfeserver,Battlefront Eternal,ubuntu-26.04
 bfe,bfeserver,Battlefront Eternal,ubuntu-26.04
 bfv,bfvserver,Battlefield: Vietnam,ubuntu-26.04
 bfv,bfvserver,Battlefield: Vietnam,ubuntu-26.04
 bmdm,bmdmserver,Black Mesa: Deathmatch,ubuntu-26.04
 bmdm,bmdmserver,Black Mesa: Deathmatch,ubuntu-26.04
+bmp,bmpserver,BeamMP,ubuntu-26.04
 bo,boserver,Ballistic Overkill,ubuntu-26.04
 bo,boserver,Ballistic Overkill,ubuntu-26.04
 bs,bsserver,Blade Symphony,ubuntu-26.04
 bs,bsserver,Blade Symphony,ubuntu-26.04
 bt,btserver,Barotrauma,ubuntu-26.04
 bt,btserver,Barotrauma,ubuntu-26.04

+ 1 - 0
lgsm/data/ubuntu-16.04.csv

@@ -1,4 +1,5 @@
 all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,file,gzip,hostname,jq,lib32gcc1,lib32stdc++6,netcat,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils
 all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,file,gzip,hostname,jq,lib32gcc1,lib32stdc++6,netcat,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils
+bmp,liblua5.3-0
 steamcmd,lib32gcc1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd
 steamcmd,lib32gcc1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd
 ac
 ac
 ahl
 ahl

+ 1 - 0
lgsm/data/ubuntu-18.04.csv

@@ -1,4 +1,5 @@
 all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc1,lib32stdc++6,netcat,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils
 all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc1,lib32stdc++6,netcat,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils
+bmp,liblua5.3-0
 steamcmd,lib32gcc1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd
 steamcmd,lib32gcc1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd
 ac
 ac
 ahl
 ahl

+ 1 - 0
lgsm/data/ubuntu-20.04.csv

@@ -1,4 +1,5 @@
 all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc1,lib32stdc++6,netcat,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils
 all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc1,lib32stdc++6,netcat,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils
+bmp,liblua5.3-0
 steamcmd,lib32gcc1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd
 steamcmd,lib32gcc1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd
 ac
 ac
 ahl
 ahl

+ 1 - 0
lgsm/data/ubuntu-22.04.csv

@@ -1,4 +1,5 @@
 all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils
 all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils
+bmp,liblua5.3-0
 steamcmd,lib32gcc-s1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd
 steamcmd,lib32gcc-s1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd
 ac
 ac
 ahl
 ahl

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

@@ -1,4 +1,5 @@
 all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat-openbsd,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils
 all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat-openbsd,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils
+bmp,liblua5.3-0
 steamcmd,lib32gcc-s1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd
 steamcmd,lib32gcc-s1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd
 ac
 ac
 ahl
 ahl

+ 1 - 0
lgsm/data/ubuntu-23.10.csv

@@ -1,4 +1,5 @@
 all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat-openbsd,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils
 all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat-openbsd,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils
+bmp,liblua5.3-0
 steamcmd,lib32gcc-s1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd
 steamcmd,lib32gcc-s1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd
 ac
 ac
 ahl
 ahl

+ 1 - 0
lgsm/data/ubuntu-24.04.csv

@@ -1,4 +1,5 @@
 all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat-openbsd,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils
 all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat-openbsd,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils
+bmp,liblua5.3-0
 steamcmd,lib32gcc-s1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd
 steamcmd,lib32gcc-s1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd
 ac
 ac
 ahl
 ahl

+ 1 - 0
lgsm/data/ubuntu-26.04.csv

@@ -1,4 +1,5 @@
 all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat-openbsd,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils
 all,bc,binutils,bsdmainutils,bzip2,ca-certificates,cpio,curl,distro-info,file,gzip,hostname,jq,lib32gcc-s1,lib32stdc++6,netcat-openbsd,pigz,procps,python3,tar,tmux,unzip,util-linux,uuid-runtime,wget,xz-utils
+bmp,liblua5.3-0
 steamcmd,lib32gcc-s1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd
 steamcmd,lib32gcc-s1,lib32stdc++6,libsdl2-2.0-0:i386,steamcmd
 ac
 ac
 ahl
 ahl

+ 10 - 0
lgsm/modules/check_config.sh

@@ -65,3 +65,13 @@ if [ "${shortname}" == "fivem" ] && ! grep -qE "^[[:space:]]*(set[[:space:]]+)?s
 		core_exit.sh
 		core_exit.sh
 	fi
 	fi
 fi
 fi
+
+if [ "${shortname}" == "bmp" ] && ! grep -qE '^[[:space:]]*AuthKey[[:space:]]*=[[:space:]]*"[^"]+"' "${servercfgfullpath}" 2> /dev/null; then
+	fn_print_fail_nl "BeamMP AuthKey is not set"
+	echo -e "* Get a key from ${italic}https://keymaster.beammp.com${default}"
+	echo -e "* Set AuthKey in ${servercfgfullpath}"
+	fn_script_log_fail "BeamMP AuthKey is not set"
+	if [ "${commandname}" == "START" ] || [ "${commandname}" == "DEBUG" ]; then
+		core_exit.sh
+	fi
+fi

+ 2 - 0
lgsm/modules/command_check_update.sh

@@ -34,6 +34,8 @@ elif [ "${shortname}" == "jk2" ]; then
 	update_jk2.sh
 	update_jk2.sh
 elif [ "${shortname}" == "jk3" ]; then
 elif [ "${shortname}" == "jk3" ]; then
 	update_jk3.sh
 	update_jk3.sh
+elif [ "${shortname}" == "bmp" ]; then
+	update_bmp.sh
 elif [ "${shortname}" == "luanti" ]; then
 elif [ "${shortname}" == "luanti" ]; then
 	update_luanti.sh
 	update_luanti.sh
 elif [ "${shortname}" == "orar" ]; then
 elif [ "${shortname}" == "orar" ]; then

+ 2 - 0
lgsm/modules/command_update.sh

@@ -76,6 +76,8 @@ elif [ "${shortname}" == "jk2" ]; then
 	update_jk2.sh
 	update_jk2.sh
 elif [ "${shortname}" == "jk3" ]; then
 elif [ "${shortname}" == "jk3" ]; then
 	update_jk3.sh
 	update_jk3.sh
+elif [ "${shortname}" == "bmp" ]; then
+	update_bmp.sh
 elif [ "${shortname}" == "luanti" ]; then
 elif [ "${shortname}" == "luanti" ]; then
 	update_luanti.sh
 	update_luanti.sh
 elif [ "${shortname}" == "orar" ]; then
 elif [ "${shortname}" == "orar" ]; then

+ 5 - 0
lgsm/modules/core_modules.sh

@@ -869,6 +869,11 @@ update_bb.sh() {
 	fn_fetch_module
 	fn_fetch_module
 }
 }
 
 
+update_bmp.sh() {
+	modulefile="${FUNCNAME[0]}"
+	fn_fetch_module
+}
+
 update_luanti.sh() {
 update_luanti.sh() {
 	modulefile="${FUNCNAME[0]}"
 	modulefile="${FUNCNAME[0]}"
 	fn_fetch_module
 	fn_fetch_module

+ 16 - 0
lgsm/modules/info_game.sh

@@ -2311,6 +2311,20 @@ fn_info_game_vh() {
 	servername="${servername:-"NOT SET"}"
 	servername="${servername:-"NOT SET"}"
 }
 }
 
 
+# Config Type: TOML (key value pairs)
+# Comment: #
+fn_info_game_bmp() {
+	if [ -f "${servercfgfullpath}" ]; then
+		fn_info_game_keyvalue_pairs_equals "servername" "Name"
+		fn_info_game_keyvalue_pairs_equals "maxplayers" "MaxPlayers"
+		fn_info_game_keyvalue_pairs_equals "configip" "IP"
+	fi
+	servername="${servername:-"NOT SET"}"
+	maxplayers="${maxplayers:-"8"}"
+	configip="${configip:-"::"}"
+	queryport="${port}"
+}
+
 # Config Type: Key Value Pairs (Equals Delimited)
 # Config Type: Key Value Pairs (Equals Delimited)
 # Comment: #
 # Comment: #
 fn_info_game_luanti() {
 fn_info_game_luanti() {
@@ -2651,6 +2665,8 @@ elif [ "${shortname}" == "ut99" ]; then
 	fn_info_game_ut99
 	fn_info_game_ut99
 elif [ "${shortname}" == "vh" ]; then
 elif [ "${shortname}" == "vh" ]; then
 	fn_info_game_vh
 	fn_info_game_vh
+elif [ "${shortname}" == "bmp" ]; then
+	fn_info_game_bmp
 elif [ "${shortname}" == "luanti" ]; then
 elif [ "${shortname}" == "luanti" ]; then
 	fn_info_game_luanti
 	fn_info_game_luanti
 elif [ "${shortname}" == "orar" ]; then
 elif [ "${shortname}" == "orar" ]; then

+ 11 - 1
lgsm/modules/info_messages.sh

@@ -771,7 +771,7 @@ fn_info_messages_ports_edit() {
 		fi
 		fi
 	done
 	done
 	# engines/games that require editing the start parameters.
 	# engines/games that require editing the start parameters.
-	local ports_edit_array=("av" "ce" "ck" "col" "cs2" "fctr" "goldsrc" "hcu" "hw" "hyt" "luanti" "iw3.0" "ioquake3" "openra" "pw" "qfusion" "rsdw" "rust" "scpsl" "sf" "sol" "spark" "source" "unreal4" "arma3" "dayz" "unt" "vh")
+	local ports_edit_array=("av" "ce" "ck" "col" "cs2" "fctr" "goldsrc" "hcu" "hw" "bmp" "hyt" "luanti" "iw3.0" "ioquake3" "openra" "pw" "qfusion" "rsdw" "rust" "scpsl" "sf" "sol" "spark" "source" "unreal4" "arma3" "dayz" "unt" "vh")
 	for port_edit in "${ports_edit_array[@]}"; do
 	for port_edit in "${ports_edit_array[@]}"; do
 		if [ "${engine}" == "${port_edit}" ] || [ "${gamename}" == "${port_edit}" ] || [ "${shortname}" == "${port_edit}" ]; then
 		if [ "${engine}" == "${port_edit}" ] || [ "${gamename}" == "${port_edit}" ] || [ "${shortname}" == "${port_edit}" ]; then
 			startparameterslocation="${configdirserver}"
 			startparameterslocation="${configdirserver}"
@@ -1861,6 +1861,14 @@ fn_info_messages_vh() {
 	} | column -s $'\t' -t
 	} | column -s $'\t' -t
 }
 }
 
 
+fn_info_messages_bmp() {
+	{
+		fn_port "header"
+		fn_port "Game" port tcp
+		fn_port "Game" port udp
+	} | column -s $'\t' -t
+}
+
 fn_info_messages_luanti() {
 fn_info_messages_luanti() {
 	{
 	{
 		fn_port "header"
 		fn_port "header"
@@ -2091,6 +2099,8 @@ fn_info_messages_select_engine() {
 		fn_info_messages_unt
 		fn_info_messages_unt
 	elif [ "${shortname}" == "vh" ]; then
 	elif [ "${shortname}" == "vh" ]; then
 		fn_info_messages_vh
 		fn_info_messages_vh
+	elif [ "${shortname}" == "bmp" ]; then
+		fn_info_messages_bmp
 	elif [ "${shortname}" == "luanti" ]; then
 	elif [ "${shortname}" == "luanti" ]; then
 		fn_info_messages_luanti
 		fn_info_messages_luanti
 	elif [ "${shortname}" == "orar" ]; then
 	elif [ "${shortname}" == "orar" ]; then

+ 8 - 1
lgsm/modules/install_config.sh

@@ -256,7 +256,14 @@ fn_list_config_locations() {
 	echo -e "Config documentation: ${italic}https://docs.linuxgsm.com/configuration${default}"
 	echo -e "Config documentation: ${italic}https://docs.linuxgsm.com/configuration${default}"
 }
 }
 
 
-if [ "${shortname}" == "luanti" ]; then
+if [ "${shortname}" == "bmp" ]; then
+	array_configs+=(ServerConfig.toml)
+	fn_default_config_remote
+	fn_set_config_vars
+	echo -e "BeamMP requires an AuthKey from ${italic}https://keymaster.beammp.com${default}"
+	echo -e "Set AuthKey in ${servercfgfullpath}"
+	fn_list_config_locations
+elif [ "${shortname}" == "luanti" ]; then
 	luanticfgexisted="0"
 	luanticfgexisted="0"
 	if [ -e "${servercfgfullpath}" ] || [ -L "${servercfgfullpath}" ]; then
 	if [ -e "${servercfgfullpath}" ] || [ -L "${servercfgfullpath}" ]; then
 		luanticfgexisted="1"
 		luanticfgexisted="1"

+ 2 - 0
lgsm/modules/install_server_files.sh

@@ -273,6 +273,8 @@ elif [ "${shortname}" == "jk2" ]; then
 	update_jk2.sh
 	update_jk2.sh
 elif [ "${shortname}" == "jk3" ]; then
 elif [ "${shortname}" == "jk3" ]; then
 	update_jk3.sh
 	update_jk3.sh
+elif [ "${shortname}" == "bmp" ]; then
+	update_bmp.sh
 elif [ "${shortname}" == "luanti" ]; then
 elif [ "${shortname}" == "luanti" ]; then
 	update_luanti.sh
 	update_luanti.sh
 elif [ "${shortname}" == "orar" ]; then
 elif [ "${shortname}" == "orar" ]; then

+ 165 - 0
lgsm/modules/update_bmp.sh

@@ -0,0 +1,165 @@
+#!/bin/bash
+# LinuxGSM update_bmp.sh module
+# Author: Daniel Gibbs
+# Contributors: https://linuxgsm.com/contrib
+# Website: https://linuxgsm.com
+# Description: Handles updating of BeamMP servers.
+
+moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+fn_update_dl() {
+	fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "${remotebuildfilename}" "chmodx" "norun" "force" "${remotebuildhash}"
+	mv -f "${tmpdir}/${remotebuildfilename}" "${executabledir}/${executable#./}"
+	fn_clear_tmp
+}
+
+fn_update_localbuild() {
+	local mode="${1:-}"
+	if [ "${mode}" != "silent" ]; then
+		fn_print_dots "Checking local build: ${remotelocation}"
+	fi
+	localbuild=$("${executabledir}/${executable#./}" --version 2> /dev/null | awk '/^BeamMP-Server / {print $2; exit}')
+	localbuild="${localbuild:-0}"
+	if [ "${mode}" != "silent" ]; then
+		fn_print_ok "Checking local build: ${remotelocation}"
+	fi
+}
+
+fn_update_remotebuild() {
+	info_distro.sh
+	case "$(uname -m)" in
+		x86_64) bmparch="x86_64" ;;
+		aarch64) bmparch="arm64" ;;
+		*)
+			fn_print_fail_nl "Unsupported BeamMP architecture: $(uname -m)"
+			fn_script_log_fail "Unsupported BeamMP architecture: $(uname -m)"
+			core_exit.sh
+			;;
+	esac
+	apiurl="https://api.github.com/repos/BeamMP/BeamMP-Server/releases/latest"
+	remotebuildresponse=$(curl -fsSL --retry 3 "${apiurl}")
+	remotebuild=$(echo "${remotebuildresponse}" | jq -r '.tag_name // empty')
+	bmpdistroid="${distroid,,}"
+	bmpdistroversion=""
+	bmpmatchversion="${distroversion}"
+	case "${bmpdistroid}" in
+		rhel | rocky | almalinux | centos)
+			if [ "${distroversion%%.*}" -ge 10 ] 2> /dev/null; then
+				bmpdistroid="ubuntu"
+				bmpmatchversion="24.04"
+			fi
+			;;
+	esac
+	while read -r bmpcandidate; do
+		if [ "$(printf '%s\n%s\n' "${bmpcandidate}" "${bmpmatchversion}" | sort -V | tail -n 1)" == "${bmpmatchversion}" ]; then
+			bmpdistroversion="${bmpcandidate}"
+		fi
+	done < <(echo "${remotebuildresponse}" | jq -r --arg id "${bmpdistroid}" --arg arch "${bmparch}" '.assets[]?.name | capture("^BeamMP-Server\\." + $id + "\\.(?<v>[0-9.]+)\\." + $arch + "$")? | .v' | sort -V)
+	remotebuildfilename="BeamMP-Server.${bmpdistroid}.${bmpdistroversion}.${bmparch}"
+	remotebuildurl=$(echo "${remotebuildresponse}" | jq -r --arg name "${remotebuildfilename}" '.assets[]? | select(.name == $name) | .browser_download_url')
+	remotebuildhash=$(echo "${remotebuildresponse}" | jq -r --arg name "${remotebuildfilename}" '.assets[]? | select(.name == $name) | .digest // empty' | sed 's/^sha256://')
+	if [ -z "${remotebuild}" ] || [ -z "${remotebuildurl}" ] || [[ ! "${remotebuildhash}" =~ ^[0-9a-f]{64}$ ]]; then
+		fn_print_fail_nl "Unable to get a BeamMP release, download URL or SHA256 checksum for ${distroid} ${distroversion} (${bmparch})"
+		fn_script_log_fail "Unable to get a BeamMP release, download URL or SHA256 checksum for ${distroid} ${distroversion} (${bmparch})"
+		core_exit.sh
+	fi
+}
+
+fn_update_compare() {
+	fn_print_dots "Checking for update: ${remotelocation}"
+	# Update has been found or force update.
+	if [ "${localbuild}" != "${remotebuild}" ] || [ "${forceupdate}" == "1" ]; then
+		# Create update lockfile.
+		date '+%s' > "${lockdir:?}/update.lock"
+		fn_print_ok_nl "Checking for update: ${remotelocation}"
+		fn_print "\n"
+		fn_print_nl "${bold}${underline}Update${default} available"
+		fn_print_nl "* Local build: ${red}${localbuild}${default}"
+		fn_print_nl "* Remote build: ${green}${remotebuild}${default}"
+		if [ -n "${branch}" ]; then
+			fn_print_nl "* Branch: ${branch}"
+		fi
+		if [ -f "${rootdir}/.dev-debug" ]; then
+			fn_print_nl "Remote build info"
+			fn_print_nl "* apiurl: ${apiurl}"
+			fn_print_nl "* remotebuildfilename: ${remotebuildfilename}"
+			fn_print_nl "* remotebuildurl: ${remotebuildurl}"
+			fn_print_nl "* remotebuild: ${remotebuild}"
+		fi
+		fn_print "\n"
+		fn_script_log_info "Update available"
+		fn_script_log_info "Local build: ${localbuild}"
+		fn_script_log_info "Remote build: ${remotebuild}"
+		if [ -n "${branch}" ]; then
+			fn_script_log_info "Branch: ${branch}"
+		fi
+		fn_script_log_info "${localbuild} > ${remotebuild}"
+
+		if [ "${commandname}" == "UPDATE" ]; then
+			# Keep track of the build before updating for alert purposes.
+			previousbuild="${localbuild}"
+			unset updateonstart
+			fn_update_apply fn_update_dl
+			# Refresh local build value after update (silent) so alerts show new version.
+			fn_update_localbuild silent
+			# Verify the update applied correctly unless forced update to same version.
+			if [ "${localbuild}" != "${remotebuild}" ]; then
+				# If forced update and version unchanged treat as acceptable; otherwise failure.
+				if [ "${forceupdate}" != "1" ] || [ "${previousbuild}" = "${localbuild}" ]; then
+					fn_script_log_error "Update verification failed: expected ${remotebuild}, got ${localbuild}"
+					fn_print_fail_nl "Update verification failed: expected ${remotebuild}, got ${localbuild}"
+					updatefailureexpected="${remotebuild}"
+					updatefailuregot="${localbuild}"
+					alert="update-failed"
+					alert.sh
+					core_exit.sh
+				fi
+			else
+				fn_script_log_pass "Update verification success: ${previousbuild} -> ${localbuild}"
+			fi
+			unset exitbypass
+			alert="update"
+		elif [ "${commandname}" == "CHECK-UPDATE" ]; then
+			alert="check-update"
+		fi
+		alert.sh
+	else
+		fn_print_ok_nl "Checking for update: ${remotelocation}"
+		fn_print "\n"
+		fn_print_nl "${bold}${underline}No update${default} available"
+		fn_print_nl "* Local build: ${green}${localbuild}${default}"
+		fn_print_nl "* Remote build: ${green}${remotebuild}${default}"
+		if [ -n "${branch}" ]; then
+			fn_print_nl "* Branch: ${branch}"
+		fi
+		fn_print "\n"
+		fn_script_log_info "No update available"
+		fn_script_log_info "Local build: ${localbuild}"
+		fn_script_log_info "Remote build: ${remotebuild}"
+		if [ -n "${branch}" ]; then
+			fn_script_log_info "Branch: ${branch}"
+		fi
+		if [ -f "${rootdir}/.dev-debug" ]; then
+			fn_print_nl "Remote build info"
+			fn_print_nl "* apiurl: ${apiurl}"
+			fn_print_nl "* remotebuildfilename: ${remotebuildfilename}"
+			fn_print_nl "* remotebuildurl: ${remotebuildurl}"
+			fn_print_nl "* remotebuild: ${remotebuild}"
+		fi
+	fi
+}
+
+# The location where the builds are checked and downloaded.
+remotelocation="github.com/BeamMP/BeamMP-Server"
+
+if [ "${firstcommandname}" == "INSTALL" ]; then
+	fn_update_remotebuild
+	fn_update_dl
+else
+	fn_print_dots "Checking for update"
+	fn_print_dots "Checking for update: ${remotelocation}"
+	fn_script_log_info "Checking for update: ${remotelocation}"
+	fn_update_localbuild
+	fn_update_remotebuild
+	fn_update_compare
+fi