diff --git a/CHANGELOG.md b/CHANGELOG.md index de0b049..be7e072 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ [Back to main](README.md#changelog) +## 2024-02-23 + +- Added new SERVER_SETTINGS_MODE called "rcononly" this will only setup up RCON, everything else is still manually to set (#221) +- Added RESTART_DEBUG_OVERRIDE for local testing +- Fixed expansion-bug from #224 & #225 by @Dashboy1998 +- Refactoring of code-duplication in webhook.sh +- Extended fixing for edge-cases of playernames from #226, #227 & #228 by @Dashboy1998 + - Default mechanic checks more steamid oriented, not comparing playernames directly + - Added mechanic for playername changes and temporary characters which are still in char-creation screen + - Also cut down on text in the announces on RCON, because messages can only be 40 chars long + - Stripped all special-chars from playername, using TR class [:alnum:] meaning only a-zA-z0-9 are valid + ## 2024-02-22 - Added RCON-Based player detection, for join and leave messages on console, rcon-broadcast and webhooks (#216) diff --git a/Dockerfile b/Dockerfile index 11339a0..6fdcd70 100644 --- a/Dockerfile +++ b/Dockerfile @@ -68,6 +68,7 @@ ENV DEBIAN_FRONTEND=noninteractive \ BACKUP_RETENTION_AMOUNT_TO_KEEP=72 \ # Restart-settings RESTART_ENABLED=false \ + RESTART_DEBUG_OVERRIDE=false \ RESTART_CRON_EXPRESSION="0 18 * * *" \ # RCON-Playerdection - NEEDS RCON ENABLED! RCON_PLAYER_DETECTION=true \ diff --git a/default.env b/default.env index 44bbd5c..0f797e8 100644 --- a/default.env +++ b/default.env @@ -12,6 +12,7 @@ BACKUP_RETENTION_POLICY=true BACKUP_RETENTION_AMOUNT_TO_KEEP=72 # Restart-settings RESTART_ENABLED=false +RESTART_DEBUG_OVERRIDE=false RESTART_CRON_EXPRESSION="0 18 * * *" # RCON-Playerdection - NEEDS RCON ENABLED! RCON_PLAYER_DETECTION=true diff --git a/docs/ENV_VARS.md b/docs/ENV_VARS.md index 28c4bb5..de0c9b8 100644 --- a/docs/ENV_VARS.md +++ b/docs/ENV_VARS.md @@ -22,10 +22,11 @@ These settings control the behavior of the Docker container: | BACKUP_RETENTION_POLICY | Set to enabled, will cleanup old backups | true | Boolean | | BACKUP_RETENTION_AMOUNT_TO_KEEP | Defines how many backups in numbers to keep | 72 | Integer | | RESTART_ENABLED | Automatic restarts the server | false | Boolean | +| RESTART_DEBUG_OVERRIDE | Automatic restarts down to 15 seconds instead of 15 minutes | false | Boolean | | RESTART_CRON_EXPRESSION | Needs a Cron-Expression - See [Cron expression](#cron-expression) | 0 3,15 * * * | Cron-Expression | | RCON_PLAYER_DETECTION | Set to enabled will send player join and leaves to console, rcon and webhooks, NEEDS `RCON_ENABLED` | true | Boolean | | RCON_PLAYER_DETECTION_STARTUP_DELAY | Initial delay for start checking for players, consider steam-updates and server start up in seconds | 60 | Integer | -| RCON_PLAYER_DETECTION_CHECK_INTERVAL | Interval in seconds to wait for next check in the infinite loop | 15 | Integer | +| RCON_PLAYER_DETECTION_CHECK_INTERVAL | Interval in seconds to wait for next check in the infinite loop | 15 | Integer | | WEBHOOK_ENABLED | Set to enabled will send webhook notifications, NEEDS `WEBHOOK_URL` | false | Boolean | | WEBHOOK_DEBUG_ENABLED | Set to enabled will enable feedback of curl and not use --silent | false | Boolean | | WEBHOOK_URL | Defines the url the webhook to send data to | | Url | @@ -36,6 +37,7 @@ These settings control the behavior of the Docker container: SERVER_SETTINGS_MODE accepts 2 values: - `auto`: Settings are modified only by environment variables, manual edits will be ignored +- `rcononly`: RCON-Settings are modified by environment variables (RCON_ENABLED, RCON_PORT, ADMIN_PASSWORD), everything else has to be done by editing the file directly, other environment variables are ignored - `manual`: Settings are modified only by editing the file directly, environment variables are ignored diff --git a/includes/config.sh b/includes/config.sh index a507c38..28c0c84 100644 --- a/includes/config.sh +++ b/includes/config.sh @@ -325,6 +325,10 @@ function setup_configs() { setup_engine_ini setup_palworld_settings_ini setup_rcon_yaml + elif [[ -n ${SERVER_SETTINGS_MODE} ]] && [[ ${SERVER_SETTINGS_MODE} == "rcononly" ]]; then + ew ">>> SERVER_SETTINGS_MODE is set to '${SERVER_SETTINGS_MODE}', using environment variables to ONLY configure RCON!" + ew ">>> ALL SETTINGS excluding setup of rcon.yaml has to be done manually by the user!" + setup_rcon_yaml else ew ">>> SERVER_SETTINGS_MODE is set to '${SERVER_SETTINGS_MODE}', NOT using environment variables to configure the server!" ew ">>> ALL SETTINGS including setup of rcon.yaml has to be done manually by the user!" diff --git a/includes/playerdetection.sh b/includes/playerdetection.sh index 30405e4..d6d3e8f 100644 --- a/includes/playerdetection.sh +++ b/includes/playerdetection.sh @@ -11,48 +11,173 @@ player_detection_loop() { sleep "$RCON_PLAYER_DETECTION_CHECK_INTERVAL" done } +#v1 +# # Function to compare current and previous player lists +# compare_players() { +# local old_players=("${current_players[@]}") +# readarray -t current_players < <(rcon showplayers | tail -n +2 | awk -F ',' '{print $1}') - # Function to compare current and previous player lists +# for player in "${current_players[@]}"; do +# local found=false +# for old_player in "${old_players[@]}"; do +# if [ "$old_player" = "$player" ]; then +# found=true +# break +# fi +# done +# if ! $found; then +# announce_join "$player" +# fi +# done +# for player in "${old_players[@]}"; do +# local found=false +# for current_player in "${current_players[@]}"; do +# if [ "$current_player" = "$player" ]; then +# found=true +# break +# fi +# done +# if ! $found; then +# announce_leave "$player" +# fi +# done +# } + +#v2 +# Function to compare current and previous player lists +# compare_players() { +# local old_players=("${current_players[@]}") +# readarray -t current_players < <(rcon showplayers | tail -n +2) + +# for player_info in "${current_players[@]}"; do +# # Extract player name, UID, and Steam ID from player info +# IFS=',' read -r name playeruid steamid <<< "$player_info" +# ew "$name" +# ew "$playeruid" +# ew "$steamid" + +# local found=false +# for old_player_info in "${old_players[@]}"; do +# IFS=',' read -r old_name old_playeruid old_steamid <<< "$old_player_info" +# ew "$old_name" +# ew "$old_playeruid" +# ew "$old_steamid" +# if [[ "$old_steamid" == "$steamid" ]]; then +# found=true +# if [[ "$old_playeruid" == "00000000" && "$playeruid" != "00000000" ]]; then +# announce_name_change "$old_name" "$name" +# fi +# break +# fi +# done +# if ! $found; then +# announce_join "$name" +# fi +# done + +# for old_player_info in "${old_players[@]}"; do +# IFS=',' read -r old_name old_playeruid old_steamid <<< "$old_player_info" +# local found=false +# for player_info in "${current_players[@]}"; do +# IFS=',' read -r name playeruid steamid <<< "$player_info" +# if [[ "$old_steamid" == "$steamid" ]]; then +# found=true +# break +# fi +# done +# if ! $found; then +# announce_leave "$old_name" +# fi +# done +# } + +#v3 +# Function to compare current and previous player lists compare_players() { local old_players=("${current_players[@]}") - readarray -t current_players < <(rcon showplayers | tail -n +2 | awk -F ',' '{print $1}') + readarray -t current_players < <(rcon showplayers | tail -n +2) + + for player_info in "${current_players[@]}"; do + # Extract player name, UID, and Steam ID from player info + IFS=',' read -r -a player_data <<< "$player_info" + local steamid="${player_data[-1]}" + local playeruid="${player_data[-2]}" + local name="${player_data[*]::${#player_data[@]}-2}" + + # Strip special characters from the player name + name="$(echo "$name" | tr -cd '[:alnum:]')" - for player in "${current_players[@]}"; do local found=false - for old_player in "${old_players[@]}"; do - if [ "$old_player" = "$player" ]; then + for old_player_info in "${old_players[@]}"; do + IFS=',' read -r -a old_player_data <<< "$old_player_info" + local old_steamid="${old_player_data[-1]}" + local old_playeruid="${old_player_data[-2]}" + local old_name="${old_player_data[*]::${#old_player_data[@]}-2}" + + # Strip special characters from the old player name + old_name="$(echo "$old_name" | tr -cd '[:alnum:]')" + + if [[ "$old_steamid" == "$steamid" ]]; then found=true + if [[ "$old_playeruid" == "00000000" && "$playeruid" != "00000000" ]]; then + announce_name_change "$old_name" "$name" + fi break fi done if ! $found; then - announce_join "$player" + announce_join "$name" fi done - for player in "${old_players[@]}"; do + + for old_player_info in "${old_players[@]}"; do + IFS=',' read -r -a old_player_data <<< "$old_player_info" + local old_steamid="${old_player_data[-1]}" + local old_playeruid="${old_player_data[-2]}" + local old_name="${old_player_data[*]::${#old_player_data[@]}-2}" + + # Strip special characters from the old player name + old_name="$(echo "$old_name" | tr -cd '[:alnum:]')" + local found=false - for current_player in "${current_players[@]}"; do - if [ "$current_player" = "$player" ]; then + for player_info in "${current_players[@]}"; do + IFS=',' read -r -a player_data <<< "$player_info" + local steamid="${player_data[-1]}" + if [[ "$old_steamid" == "$steamid" ]]; then found=true break fi done if ! $found; then - announce_leave "$player" + announce_leave "$old_name" fi done } + # Function to announce a player join announce_join() { time=$(date '+%H:%M:%S') message="Player $1 has joined the server." echo "${time}: $message" if [[ -n $WEBHOOK_ENABLED ]] && [[ $WEBHOOK_ENABLED == "true" ]]; then - send_player_join_notification "$message" + send_info_notification "$message" + fi + if [[ -n $RCON_ENABLED ]] && [[ $RCON_ENABLED == "true" ]]; then + broadcast_player_join "${1// /\-}" + fi +} + +# Function to announce a player join +announce_name_change() { + time=$(date '+%H:%M:%S') + message="Player $1 has changed their name to $2." + echo "${time}: $message" + if [[ -n $WEBHOOK_ENABLED ]] && [[ $WEBHOOK_ENABLED == "true" ]]; then + send_info_notification "$message" fi if [[ -n $RCON_ENABLED ]] && [[ $RCON_ENABLED == "true" ]]; then - broadcast_player_join "$1" + broadcast_player_name_change "${1// /\-}" "${2// /\-}" fi } @@ -62,9 +187,9 @@ announce_leave() { message="Player $1 has left the server." echo "${time}: $message" if [[ -n $WEBHOOK_ENABLED ]] && [[ $WEBHOOK_ENABLED == "true" ]]; then - send_player_leave_notification "$message" + send_info_notification "$message" fi if [[ -n $RCON_ENABLED ]] && [[ $RCON_ENABLED == "true" ]]; then - broadcast_player_leave "$1" + broadcast_player_leave "${1// /\-}" fi } \ No newline at end of file diff --git a/includes/rcon.sh b/includes/rcon.sh index fa8bbee..467bd57 100644 --- a/includes/rcon.sh +++ b/includes/rcon.sh @@ -42,10 +42,15 @@ function broadcast_backup_failed() { function broadcast_player_join() { time=$(date '+%H:%M:%S') - rconcli "broadcast ${time}-Player-$1-has-joined-the-server" + rconcli "broadcast ${time}-$1-joined-the-server" +} + +function broadcast_player_name_change() { + time=$(date '+%H:%M:%S') + rconcli "broadcast ${time}-$1-renamed-to-$2" } function broadcast_player_leave() { time=$(date '+%H:%M:%S') - rconcli "broadcast ${time}-Player-$1-has-left-the-server" + rconcli "broadcast ${time}-$1-left-the-server" } \ No newline at end of file diff --git a/includes/webhook.sh b/includes/webhook.sh index e5ffbcc..0ac3081 100644 --- a/includes/webhook.sh +++ b/includes/webhook.sh @@ -46,9 +46,6 @@ send_stop_notification() { send_update_notification() { send_webhook_notification "$WEBHOOK_UPDATE_TITLE" "$WEBHOOK_UPDATE_DESCRIPTION" "$WEBHOOK_UPDATE_COLOR" } -send_player_join_notification() { - send_webhook_notification "$WEBHOOK_INFO_TITLE" "$1" "$WEBHOOK_INFO_COLOR" -} -send_player_leave_notification() { +send_info_notification() { send_webhook_notification "$WEBHOOK_INFO_TITLE" "$1" "$WEBHOOK_INFO_COLOR" } diff --git a/scripts/restart.sh b/scripts/restart.sh index 753b566..bd234f4 100644 --- a/scripts/restart.sh +++ b/scripts/restart.sh @@ -18,7 +18,11 @@ function schedule_restart() { time=$(date '+%H:%M:%S') rconcli "broadcast ${time}-AUTOMATIC-RESTART-IN-$counter-MINUTES" fi - sleep 60 + if [[ -n $RESTART_DEBUG_OVERRIDE ]] && [[ $RESTART_DEBUG_OVERRIDE == "true" ]]; then + sleep 1 + else + sleep 60 + fi done if [[ -n $RCON_ENABLED ]] && [[ $RCON_ENABLED == "true" ]]; then