From 1fd8be01805905aea027988f34403f7a429a4ad8 Mon Sep 17 00:00:00 2001 From: Lukrecja Date: Mon, 2 Feb 2026 14:21:05 +0100 Subject: [PATCH] stop the server if no players are detected for a given time --- Cargo.lock | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 1 + src/main.rs | 41 ++++++++++++++++++++++++ 3 files changed, 133 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index e6bc000..73cacec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,6 +20,20 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" 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]] name = "errno" version = "0.3.14" @@ -49,6 +63,7 @@ dependencies = [ name = "mc-proxy-controller" version = "0.1.0" dependencies = [ + "rcon", "tokio", ] @@ -92,6 +107,30 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" 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]] name = "proc-macro2" version = "1.0.106" @@ -110,6 +149,16 @@ dependencies = [ "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]] name = "redox_syscall" version = "0.5.18" @@ -119,6 +168,12 @@ dependencies = [ "bitflags", ] +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + [[package]] name = "scopeguard" version = "1.2.0" @@ -151,6 +206,17 @@ dependencies = [ "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]] name = "syn" version = "2.0.114" @@ -162,6 +228,18 @@ dependencies = [ "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]] name = "tokio" version = "1.49.0" @@ -187,7 +265,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.114", ] [[package]] @@ -196,6 +274,18 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" 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]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 4ecb395..ec3eeb9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,4 +4,5 @@ version = "0.1.0" edition = "2024" [dependencies] +rcon = { version = "0.6.0", features = ["rt-tokio"] } tokio = { version = "1.49.0", features = ["full"] } diff --git a/src/main.rs b/src/main.rs index 1ad0806..dfc4d1c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,18 +1,59 @@ use std::error::Error; +use std::time::Duration; +use rcon::Connection; +use tokio::time::Instant; use tokio::{io::copy_bidirectional, main}; use tokio::net::{TcpListener, TcpStream}; +fn parse_players_online(s: &str) -> Option { + s.split_whitespace() + .find_map(|tok| tok.parse::().ok()) +} + #[main] async fn main() -> Result<(), Box> { let listen_addr = "0.0.0.0:8080"; let server_addr = "127.0.0.1:25565"; + let rcon_addr = "127.0.0.1:25575"; println!("Listening on {listen_addr}"); println!("Proxying to {server_addr}"); let listener = TcpListener::bind(listen_addr).await?; + tokio::spawn(async move { + let mut conn = >::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 { let mut outbound = TcpStream::connect(server_addr).await?;