stop the server if no players are detected for a given time

This commit is contained in:
2026-02-02 14:21:05 +01:00
parent 4c9593283e
commit 1fd8be0180
3 changed files with 133 additions and 1 deletions

92
Cargo.lock generated
View File

@@ -20,6 +20,20 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "err-derive"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c34a887c8df3ed90498c1c437ce21f211c8e27672921a8ffa293cb8d6d4caa9e"
dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"rustversion",
"syn 1.0.109",
"synstructure",
]
[[package]] [[package]]
name = "errno" name = "errno"
version = "0.3.14" version = "0.3.14"
@@ -49,6 +63,7 @@ dependencies = [
name = "mc-proxy-controller" name = "mc-proxy-controller"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"rcon",
"tokio", "tokio",
] ]
@@ -92,6 +107,30 @@ version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn 1.0.109",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.106" version = "1.0.106"
@@ -110,6 +149,16 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "rcon"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "618babf41c041e7d6f4baf27f6d92434be58c1eb637edac7f9af7900f247417b"
dependencies = [
"err-derive",
"tokio",
]
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.5.18" version = "0.5.18"
@@ -119,6 +168,12 @@ dependencies = [
"bitflags", "bitflags",
] ]
[[package]]
name = "rustversion"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.2.0" version = "1.2.0"
@@ -151,6 +206,17 @@ dependencies = [
"windows-sys 0.60.2", "windows-sys 0.60.2",
] ]
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.114" version = "2.0.114"
@@ -162,6 +228,18 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "synstructure"
version = "0.12.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
"unicode-xid",
]
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.49.0" version = "1.49.0"
@@ -187,7 +265,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -196,6 +274,18 @@ version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
[[package]]
name = "unicode-xid"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]] [[package]]
name = "wasi" name = "wasi"
version = "0.11.1+wasi-snapshot-preview1" version = "0.11.1+wasi-snapshot-preview1"

View File

@@ -4,4 +4,5 @@ version = "0.1.0"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
rcon = { version = "0.6.0", features = ["rt-tokio"] }
tokio = { version = "1.49.0", features = ["full"] } tokio = { version = "1.49.0", features = ["full"] }

View File

@@ -1,18 +1,59 @@
use std::error::Error; use std::error::Error;
use std::time::Duration;
use rcon::Connection;
use tokio::time::Instant;
use tokio::{io::copy_bidirectional, main}; use tokio::{io::copy_bidirectional, main};
use tokio::net::{TcpListener, TcpStream}; use tokio::net::{TcpListener, TcpStream};
fn parse_players_online(s: &str) -> Option<u32> {
s.split_whitespace()
.find_map(|tok| tok.parse::<u32>().ok())
}
#[main] #[main]
async fn main() -> Result<(), Box<dyn Error>> { async fn main() -> Result<(), Box<dyn Error>> {
let listen_addr = "0.0.0.0:8080"; let listen_addr = "0.0.0.0:8080";
let server_addr = "127.0.0.1:25565"; let server_addr = "127.0.0.1:25565";
let rcon_addr = "127.0.0.1:25575";
println!("Listening on {listen_addr}"); println!("Listening on {listen_addr}");
println!("Proxying to {server_addr}"); println!("Proxying to {server_addr}");
let listener = TcpListener::bind(listen_addr).await?; let listener = TcpListener::bind(listen_addr).await?;
tokio::spawn(async move {
let mut conn = <Connection<TcpStream>>::builder()
.enable_minecraft_quirks(true)
.connect(rcon_addr, "Lusia669")
.await.unwrap();
let mut idle = false;
let mut last_online = Instant::now();
let idle_timeout = Duration::from_secs(10);
loop {
let players_cmd_output = conn.cmd("list").await.unwrap();
let players_number = parse_players_online(&players_cmd_output).unwrap();
if players_number > 0 {
last_online = Instant::now();
}
println!("{players_number} {idle}");
if Instant::now() - last_online > idle_timeout {
idle = true;
println!("Stopping the server");
conn.cmd("stop").await.unwrap();
} else {
idle = false;
}
tokio::time::sleep(Duration::from_millis(250)).await;
};
});
while let Ok((mut inbound, _)) = listener.accept().await { while let Ok((mut inbound, _)) = listener.accept().await {
let mut outbound = TcpStream::connect(server_addr).await?; let mut outbound = TcpStream::connect(server_addr).await?;