LinuxGSM icon indicating copy to clipboard operation
LinuxGSM copied to clipboard

[Feature]: Rustserver shutdown-warning in in-game chat

Open JuliusZet opened this issue 1 year ago • 3 comments

User story

As a player on a Rust server, I want to receive occasional warnings in the in-game chat before the server shuts down or restarts, so that I have a chance to prepare.

Game

Rust

Linux distro

No response

Command

command: stop

Further information

Hi there

When a Rust server is stopped, which can for example happen with the commands

  • ./rustserver stop
  • ./rustserver restart
  • ./rustserver (force-)update
  • ./rustserver backup

then it will send Ctrl+c to the tmux session. This shuts the server down immediately. I have two issues with this:

  1. Because this Ctrl+c does not explicitly execute a save, any progress of up to 300 seconds will be lost, depending on when the last save happened. (I am not 100 % sure on that, so please correct me if I am wrong.)
  2. When there are players connected to the server, they will be surprised by the shutdown and do hot have any chance to prepare.

To fix these, I would like to implement a new method to stop a Rust server, that sends the quit command via rcon to the Rust server after 15 minutes. During these 15 minutes, occasional warnings should be sent to the in-game chat, to warn any connected players, so that they can prepare. The quit command also ensures that the game is saved directly before the shutdown, so no progress is lost.

Please let me know what you think and have a great day! :)

Kind regards JuliusZet

JuliusZet avatar Dec 16 '23 13:12 JuliusZet

I have a few rough ideas on how that could work, but it would be great, if someone could implement this properly.

In modules/command_stop.sh Add a new stopmode:

fn_stop_graceful_select() {
	if [ "${stopmode}" == "1" ]; then
		fn_stop_tmux
[...]
	elif [ "${stopmode}" == "13" ]; then
		fn_stop_graceful_rust
	fi
}

Define the function fn_stop_graceful_rust() in modules/command_stop.sh:

fn_stop_graceful_rust() {
	fn_print_dots "Graceful: rcon quit: sending quit via rcon in 15 minutes"
	fn_script_log_info "Graceful: rcon quit: sending quit via rcon in 15 minutes"

	# wait 15 minutes and output occasional warnings in chat
	"${HOME}/.local/bin/rcon" -a 127.0.0.1:${rconport} -p ${rconpassword} -t web 'say :  ATTENTION! The server will restart in 15 minutes.'
	fn_print_dots "Graceful: rcon quit: 15-minute-warning sent"
	sleep "300"
	"${HOME}/.local/bin/rcon" -a 127.0.0.1:${rconport} -p ${rconpassword} -t web 'say :  ATTENTION! The server will restart in 10 minutes.'
	fn_print_dots "Graceful: rcon quit: 10-minute-warning sent"
	sleep "300"
	"${HOME}/.local/bin/rcon" -a 127.0.0.1:${rconport} -p ${rconpassword} -t web 'say :  ATTENTION! The server will restart in 5 minutes.'
	fn_print_dots "Graceful: rcon quit: 5-minute-warning sent"
	sleep "60"
	"${HOME}/.local/bin/rcon" -a 127.0.0.1:${rconport} -p ${rconpassword} -t web 'say :  ATTENTION! The server will restart in 4 minutes.'
	fn_print_dots "Graceful: rcon quit: 4-minute-warning sent"
	sleep "60"
	"${HOME}/.local/bin/rcon" -a 127.0.0.1:${rconport} -p ${rconpassword} -t web 'say :  ATTENTION! The server will restart in 3 minutes.'
	fn_print_dots "Graceful: rcon quit: 3-minute-warning sent"
	sleep "60"
	"${HOME}/.local/bin/rcon" -a 127.0.0.1:${rconport} -p ${rconpassword} -t web 'say :  ATTENTION! The server will restart in 2 minutes.'
	fn_print_dots "Graceful: rcon quit: 2-minute-warning sent"
	sleep "60"
	"${HOME}/.local/bin/rcon" -a 127.0.0.1:${rconport} -p ${rconpassword} -t web 'say :  ATTENTION! The server will restart in 1 minute.'
	fn_print_dots "Graceful: rcon quit: 1-minute-warning sent"
	sleep "30"
	"${HOME}/.local/bin/rcon" -a 127.0.0.1:${rconport} -p ${rconpassword} -t web 'say :  ATTENTION! The server will restart in 30 seconds.'
	fn_print_dots "Graceful: rcon quit: 30-second-warning sent"
	sleep "15"
	"${HOME}/.local/bin/rcon" -a 127.0.0.1:${rconport} -p ${rconpassword} -t web 'say :  ATTENTION! The server will restart in 15 seconds.'
	fn_print_dots "Graceful: rcon quit: 15-second-warning sent"
	sleep "5"
	"${HOME}/.local/bin/rcon" -a 127.0.0.1:${rconport} -p ${rconpassword} -t web 'say :  ATTENTION! The server will restart in 10 seconds.'
	fn_print_dots "Graceful: rcon quit: 10-second-warning sent"
	sleep "1"
	"${HOME}/.local/bin/rcon" -a 127.0.0.1:${rconport} -p ${rconpassword} -t web 'say :  ATTENTION! The server will restart in 9 seconds.'
	fn_print_dots "Graceful: rcon quit: 9-second-warning sent"
	sleep "1"
	"${HOME}/.local/bin/rcon" -a 127.0.0.1:${rconport} -p ${rconpassword} -t web 'say :  ATTENTION! The server will restart in 8 seconds.'
	fn_print_dots "Graceful: rcon quit: 8-second-warning sent"
	sleep "1"
	"${HOME}/.local/bin/rcon" -a 127.0.0.1:${rconport} -p ${rconpassword} -t web 'say :  ATTENTION! The server will restart in 7 seconds.'
	fn_print_dots "Graceful: rcon quit: 7-second-warning sent"
	sleep "1"
	"${HOME}/.local/bin/rcon" -a 127.0.0.1:${rconport} -p ${rconpassword} -t web 'say :  ATTENTION! The server will restart in 6 seconds.'
	fn_print_dots "Graceful: rcon quit: 6-second-warning sent"
	sleep "1"
	"${HOME}/.local/bin/rcon" -a 127.0.0.1:${rconport} -p ${rconpassword} -t web 'say :  ATTENTION! The server will restart in 5 seconds.'
	fn_print_dots "Graceful: rcon quit: 5-second-warning sent"
	sleep "1"
	"${HOME}/.local/bin/rcon" -a 127.0.0.1:${rconport} -p ${rconpassword} -t web 'say :  ATTENTION! The server will restart in 4 seconds.'
	fn_print_dots "Graceful: rcon quit: 4-second-warning sent"
	sleep "1"
	"${HOME}/.local/bin/rcon" -a 127.0.0.1:${rconport} -p ${rconpassword} -t web 'say :  ATTENTION! The server will restart in 3 seconds.'
	fn_print_dots "Graceful: rcon quit: 3-second-warning sent"
	sleep "1"
	"${HOME}/.local/bin/rcon" -a 127.0.0.1:${rconport} -p ${rconpassword} -t web 'say :  ATTENTION! The server will restart in 2 seconds.'
	fn_print_dots "Graceful: rcon quit: 2-second-warning sent"
	sleep "1"
	"${HOME}/.local/bin/rcon" -a 127.0.0.1:${rconport} -p ${rconpassword} -t web 'say :  ATTENTION! The server will restart in 1 second.'
	fn_print_dots "Graceful: rcon quit: 1-second-warning sent"
	sleep "1"

	# send "quit" via rcon
	"${HOME}/.local/bin/rcon" -a 127.0.0.1:${rconport} -p ${rconpassword} -t web 'quit'
	fn_print_dots "Graceful: rcon quit: quit command sent via rcon"

	# Waits up to 30 seconds giving the server time to shutdown gracefuly.
	for seconds in {1..30}; do
		check_status.sh
		if [ "${status}" == "0" ]; then
			fn_print_ok "Graceful: rcon quit: quit command sent via rcon - waiting for server shutdown to complete: ${seconds}: "
			fn_print_ok_eol_nl
			fn_script_log_pass "Graceful: rcon quit: OK: ${seconds} seconds"
			if [ "${statusalert}" == "on" ] && [ "${firstcommandname}" == "STOP" ]; then
				alert="stopped"
				alert.sh
			fi
			break
		fi
		fn_sleep_time_1
		fn_print_dots "Graceful: rcon quit: quit command sent via rcon - waiting for server shutdown to complete: ${seconds}"
	done
	check_status.sh
	if [ "${status}" != "0" ]; then
		fn_print_error "Graceful: rcon quit: "
		fn_print_fail_eol_nl
		fn_script_log_error "Graceful: rcon quit: FAIL"
	fi
}

This requires, that the user manually downloads the rcon executable (from https://github.com/gorcon/rcon-cli) to ~/.local/bin/. This should ideally happen automatically with the execution of ./rustserver install. Maybe there is a better place for it than ~/.local/bin/, for example in the lgsm/modules/ directory?

JuliusZet avatar Dec 16 '23 14:12 JuliusZet

Just a thought why not just send the required commands to the tmux instance ? something like tmux send "Server shutting down in x mins" ENTER rather than going for recon ?

JimTR avatar Dec 17 '23 08:12 JimTR

Just a thought why not just send the required commands to the tmux instance ? something like tmux send "Server shutting down in x mins" ENTER rather than going for recon ?

That is because the Rust server console in tmux is non-interactive. You can not enter any commands through it. :/

JuliusZet avatar Dec 17 '23 10:12 JuliusZet