From b06d2fe1517ac10413b694136cb5e50c8c31239e Mon Sep 17 00:00:00 2001 From: Luuk van Oijen Date: Fri, 24 Nov 2023 14:37:07 +0100 Subject: [PATCH] say command + playerlist works now --- src/config.rs | 5 +++-- src/main.rs | 13 ++++++++++--- src/server/mod.rs | 14 +++++++++++++- src/tui.rs | 23 +++++++++++++++++++---- 4 files changed, 45 insertions(+), 10 deletions(-) diff --git a/src/config.rs b/src/config.rs index 03e4b3a..29cab79 100644 --- a/src/config.rs +++ b/src/config.rs @@ -38,13 +38,14 @@ pub struct GeneralSettings { #[serde(rename = "Map")] pub map: String, + #[serde(rename = "ResourceFolder")] + pub resource_folder: String, + // Options below are not yet supported #[serde(rename = "LogChat")] pub log_chat: bool, #[serde(rename = "Debug")] pub debug: bool, - #[serde(rename = "ResourceFolder")] - pub resource_folder: String, } impl GeneralSettings { diff --git a/src/main.rs b/src/main.rs index 24258b0..6534d4e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -68,15 +68,16 @@ async fn main() { let user_config = Arc::new(user_config); let (cmd_tx, cmd_rx) = mpsc::channel(100); + let (status_tx, status_rx) = mpsc::channel(100); if !args.disable_tui { - tokio::spawn(tui::tui_main(user_config.clone(), cmd_tx)); + tokio::spawn(tui::tui_main(user_config.clone(), cmd_tx, status_rx)); } - server_main(user_config, cmd_rx).await; + server_main(user_config, cmd_rx, status_tx).await; } -async fn server_main(user_config: Arc, mut cmd_rx: mpsc::Receiver>) { +async fn server_main(user_config: Arc, mut cmd_rx: mpsc::Receiver>, status_tx: mpsc::Sender) { let (hb_tx, hb_rx) = mpsc::channel(100); tokio::spawn(heartbeat::backend_heartbeat(user_config.clone(), hb_rx)); @@ -88,6 +89,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; + status_tx.send(status.clone()).await; 'server: loop { // TODO: Error handling if server.clients.len() > 0 { @@ -121,6 +123,7 @@ async fn server_main(user_config: Arc, mut cmd_rx: mpsc::Receive if status != new_status { status = new_status; hb_tx.send(status.clone()).await; + status_tx.send(status.clone()).await; } // Process commands @@ -141,6 +144,10 @@ async fn server_main(user_config: Arc, mut cmd_rx: mpsc::Receive } info!("{}", pl); }, + "say" => { + let msg = cmd[1..].iter().map(|s| s.as_str()).collect::>().join(" "); + server.send_chat_message(&msg, None).await; + }, _ => info!("Unknown command!"), } } else { diff --git a/src/server/mod.rs b/src/server/mod.rs index 8fc8fa7..1730436 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -73,7 +73,7 @@ fn load_plugins(server_resource_folder: String) -> Vec { plugins } -#[derive(PartialEq, Eq, Clone, Debug)] +#[derive(PartialEq, Eq, Clone, Debug, Default)] pub struct ServerStatus { pub player_count: usize, pub player_list: Vec<(u8, String)>, @@ -551,6 +551,18 @@ impl Server { Ok(()) } + pub async fn send_chat_message(&self, message: &str, target: Option) { + let packet = Packet::Raw(RawPacket::from_str(&format!("C:Server: {message}"))); + if let Some(_id) = target { + // TODO: Implement this! + todo!("Sending server chat messages to specific player is not supported yet!"); + // info!("[CHAT] Server @ {id}: {message}"); + } else { + info!("[CHAT] Server: {message}"); + self.broadcast(packet, None).await; + } + } + // NOTE: Skips all clients that are currently connecting or syncing resources! async fn broadcast(&self, packet: Packet, owner: Option) { for client in &self.clients { diff --git a/src/tui.rs b/src/tui.rs index edf170f..4591deb 100644 --- a/src/tui.rs +++ b/src/tui.rs @@ -16,12 +16,13 @@ use ratatui::{ use tokio::sync::mpsc; use crate::config::Config; +use crate::server::ServerStatus; -pub async fn tui_main(config: Arc, cmd_tx: mpsc::Sender>) { +pub async fn tui_main(config: Arc, cmd_tx: mpsc::Sender>, mut info_rx: mpsc::Receiver) { let mut tui = Tui::new().expect("Failed to initialize tui!"); 'app: loop { - if tui.update(&cmd_tx).await.expect("Failed to run tui.update!") { + if tui.update(&cmd_tx, &mut info_rx).await.expect("Failed to run tui.update!") { cmd_tx.send(vec!["exit".to_string()]).await.unwrap(); break 'app; } @@ -37,6 +38,8 @@ struct Tui { history_scroll: usize, input_history: Vec, input: String, + + server_status: ServerStatus, } impl Drop for Tui { @@ -62,6 +65,8 @@ impl Tui { history_scroll: 0, input_history: Vec::new(), input: String::new(), + + server_status: ServerStatus::default(), }) } @@ -71,7 +76,7 @@ impl Tui { Ok(()) } - async fn update(&mut self, cmd_tx: &mpsc::Sender>) -> Result { + async fn update(&mut self, cmd_tx: &mpsc::Sender>, info_rx: &mut mpsc::Receiver) -> Result { for (level, msg) in crate::logger::drain_log_buffer().await { self.log_buffer.push_front((level, msg)); if self.log_buffer.len() > 100 { @@ -79,6 +84,12 @@ impl Tui { } } + match info_rx.try_recv() { + Ok(status) => self.server_status = status, + Err(mpsc::error::TryRecvError::Empty) => {}, + Err(e) => return Ok(true), + } + if event::poll(std::time::Duration::from_millis(16))? { if let event::Event::Key(key) = event::read()? { if key.kind == KeyEventKind::Press { @@ -166,8 +177,12 @@ impl Tui { horiz_layout[0], ); + let mut lines = Vec::new(); + for (id, name) in &self.server_status.player_list { + lines.push(Line::from(format!("{id} - {name}"))); + } frame.render_widget( - Paragraph::new("0 - luuk-bepis\n1 - lion guy\n2 - the_racc").block(Block::new().borders(Borders::ALL).title("Player List")), + Paragraph::new(lines).block(Block::new().borders(Borders::ALL).title("Player List")), horiz_layout[1], );