From 6ed714b86350b3d93170ccba42630642ba8c99ae Mon Sep 17 00:00:00 2001 From: Luuk van Oijen Date: Wed, 22 Nov 2023 11:02:53 +0100 Subject: [PATCH] closing tui no longer crashes + onShutdown event --- Resources/Server/TestPlugin/main.lua | 5 +++++ src/main.rs | 7 ++++-- src/server/client.rs | 4 ++-- src/server/mod.rs | 33 ++++++++++------------------ src/server/plugins/backend_lua.rs | 1 + src/server/plugins/mod.rs | 8 +++++++ src/tui.rs | 14 ++++++------ 7 files changed, 39 insertions(+), 33 deletions(-) diff --git a/Resources/Server/TestPlugin/main.lua b/Resources/Server/TestPlugin/main.lua index 85a3be2..ba210d1 100644 --- a/Resources/Server/TestPlugin/main.lua +++ b/Resources/Server/TestPlugin/main.lua @@ -5,6 +5,10 @@ function onPluginLoaded() print("HI!") end +function onShutdown() + print("BYE!") +end + function onPlayerAuthenticated(joined_name, role, is_guest, identifiers) print("hi welcome mista " .. joined_name) print("u a guest? " .. tostring(is_guest)) @@ -36,5 +40,6 @@ function onPlayerDisconnect(pid, name, identifiers) end MP.RegisterEventHandler("onInit", "onPluginLoaded") +MP.RegisterEventHandler("onShutdown", "onShutdown") MP.RegisterEventHandler("onPlayerAuth", "onPlayerAuthenticated") MP.RegisterEventHandler("onPlayerDisconnect", "onPlayerDisconnect") diff --git a/src/main.rs b/src/main.rs index 6078d51..0fcce91 100644 --- a/src/main.rs +++ b/src/main.rs @@ -72,7 +72,7 @@ async fn server_main(user_config: Arc, mut cmd_rx: mpsc::Receive let mut status = server.get_server_status(); hb_tx.send(status.clone()).await; - loop { + 'server: loop { // TODO: Error handling if server.clients.len() > 0 { tokio::select! { @@ -111,7 +111,10 @@ async fn server_main(user_config: Arc, mut cmd_rx: mpsc::Receive match cmd_rx.try_recv() { Ok(cmd) => if cmd.len() > 0 { match cmd[0].as_str() { - "exit" => break, + "exit" => { + server.close().await; + break 'server; + }, _ => info!("Unknown command!"), } } else { diff --git a/src/server/client.rs b/src/server/client.rs index 6e9f1aa..7d3349d 100644 --- a/src/server/client.rs +++ b/src/server/client.rs @@ -212,14 +212,14 @@ impl Client { Some(v) => "/".to_string() + v.to_str().unwrap(), None => { error!("Client requests invalid mod. Disconnecting"); - self.kick("Invalid mod request"); + self.kick("Invalid mod request").await; return Ok(()); }, // client requested path (fResources/Client/) or nothing at all (f) - invalid }; let mod_path = format!("Resources/Client{mod_name}"); if !std::path::Path::new(&mod_path).exists() { error!("Client requests inexistent mod. Disconnecting"); - self.kick("Invalid mod request"); + self.kick("Invalid mod request").await; return Ok(()) // client requested mod that doesnt exists within "Resources/Client/*" } diff --git a/src/server/mod.rs b/src/server/mod.rs index ac911c5..fd07635 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -327,29 +327,18 @@ impl Server { } } - pub async fn process_tcp(&mut self, index: usize, raw_packet: RawPacket) -> anyhow::Result<()> { - // if self.clients.len() > 0 { - // let (result, index, _) = futures::future::select_all( - // self.clients.iter_mut().map(|client| Box::pin(client.process_blocking())) - // ).await; - // - // match result { - // Ok(packet_opt) => { - // if let Some(raw_packet) = packet_opt { - // self.parse_packet(index, raw_packet).await?; - // } - // }, - // Err(e) => { - // if let Some(client) = self.clients.get_mut(index) { - // client.kick(&format!("Kicked: {:?}", e)).await; - // } - // } - // } - // } else { - // // TODO: Find a better solution than this lol - // tokio::time::sleep(tokio::time::Duration::from_millis(20)).await; - // } + pub async fn close(mut self) { + self.connect_runtime_handle.abort(); + for mut client in self.clients.drain(..) { + client.kick("Server is closing!").await; + } + // TODO: We can probably race these with futures::future::select_all? + for plugin in self.plugins.drain(..) { + plugin.close().await; + } + } + pub async fn process_tcp(&mut self, index: usize, raw_packet: RawPacket) -> anyhow::Result<()> { self.parse_packet(index, raw_packet).await?; Ok(()) diff --git a/src/server/plugins/backend_lua.rs b/src/server/plugins/backend_lua.rs index d780927..d85e993 100644 --- a/src/server/plugins/backend_lua.rs +++ b/src/server/plugins/backend_lua.rs @@ -137,6 +137,7 @@ impl Backend for BackendLua { fn call_event_handler(&mut self, event: ScriptEvent, resp: Option>) { let (event_name, args) = match event { ScriptEvent::OnPluginLoaded => ("onInit", vec![]), + ScriptEvent::OnShutdown => ("onShutdown", vec![]), ScriptEvent::OnPlayerAuthenticated { name, role, is_guest, identifiers } => ("onPlayerAuth", vec![Argument::String(name), Argument::String(role), Argument::Boolean(is_guest), Argument::Table(identifiers.to_map())]), ScriptEvent::OnPlayerDisconnect { pid, name } => ("onPlayerDisconnect", vec![Argument::Number(pid as f32), Argument::String(name)]), }; diff --git a/src/server/plugins/mod.rs b/src/server/plugins/mod.rs index 3b4a65c..bec89e6 100644 --- a/src/server/plugins/mod.rs +++ b/src/server/plugins/mod.rs @@ -45,6 +45,7 @@ impl PlayerIdentifiers { #[derive(Debug)] pub enum ScriptEvent { OnPluginLoaded, + OnShutdown, OnPlayerAuthenticated { name: String, role: String, is_guest: bool, identifiers: PlayerIdentifiers }, @@ -114,6 +115,13 @@ impl Plugin { }) } + pub async fn close(mut self) { + let (tx, mut rx) = oneshot::channel(); + self.send_event(PluginBoundPluginEvent::CallEventHandler((ScriptEvent::OnShutdown, Some(tx)))).await; + let _ = rx.await; // We just wait for it to finish shutting down + self.runtime.shutdown_background(); + } + // TODO: For performance I think we can turn this into an iterator instead of first allocating // a full vector? pub fn get_events(&mut self) -> Vec { diff --git a/src/tui.rs b/src/tui.rs index 3a3b66f..f6b715b 100644 --- a/src/tui.rs +++ b/src/tui.rs @@ -109,17 +109,17 @@ impl Tui { let mut lines = Vec::new(); for (i, (level, msg)) in self.log_buffer.iter().enumerate() { if i >= (area.height as usize - 5) { break; } - let level_style = match level { - Level::Info => Style::default().green(), - Level::Warn => Style::default().yellow(), - Level::Error => Style::default().red(), - Level::Debug => Style::default().gray(), - Level::Trace => Style::default().cyan(), + let (level_style, spacer) = match level { + Level::Info => (Style::default().green(), " "), + Level::Warn => (Style::default().yellow(), " "), + Level::Error => (Style::default().red(), ""), + Level::Debug => (Style::default().gray(), ""), + Level::Trace => (Style::default().cyan(), ""), }; lines.push(Line::from(vec![ Span::styled("[", Style::default()), Span::styled(format!("{}", level), level_style), - Span::styled(format!("] {}", msg), Style::default()), + Span::styled(format!("]{} {}", spacer, msg), Style::default()), ])); } lines.reverse();