diff options
| author | 1992414357@qq.com <1992414357@qq.com> | 2025-05-29 14:20:04 +0800 |
|---|---|---|
| committer | 1992414357@qq.com <1992414357@qq.com> | 2025-05-29 14:20:04 +0800 |
| commit | 3d23632d7c6330e0ec98dad53656dfed5f5767b0 (patch) | |
| tree | d8d59726ca5b046b55ba502f1b8d5ba3a561a569 /core | |
| parent | 9d3d6d4195e58c51166811d8357a331d53c4cdd4 (diff) | |
1. 优化了服务器的消息处理方式
2. 将c和c#的绑定移动到了./bindings/文件夹
Diffstat (limited to 'core')
| -rw-r--r-- | core/Cargo.toml | 2 | ||||
| -rw-r--r-- | core/examples/start_client_console.rs | 8 | ||||
| -rw-r--r-- | core/examples/start_server_console.rs | 17 | ||||
| -rw-r--r-- | core/src/pad_data/game_layout.rs | 9 | ||||
| -rw-r--r-- | core/src/pad_data/layout.rs | 137 | ||||
| -rw-r--r-- | core/src/pad_data/mod.rs | 2 | ||||
| -rw-r--r-- | core/src/pad_service/client.rs | 25 | ||||
| -rw-r--r-- | core/src/pad_service/server.rs | 287 | ||||
| -rw-r--r-- | core/src/pad_service/server_debug_cli.rs | 64 |
9 files changed, 449 insertions, 102 deletions
diff --git a/core/Cargo.toml b/core/Cargo.toml index e41697e..b4bfdb1 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -5,6 +5,7 @@ homepage = "https://github.com/CatilGrass/NoGamepads" repository = "https://github.com/CatilGrass/NoGamepads" readme = "../README.md" +workspace = "../../NoGamepads" edition = "2024" [dependencies] @@ -17,6 +18,7 @@ serde = { version = "1.0.219", features = ["derive"] } clap = { version = "4.5.38", features = ["derive"] } sha1 = "0.10.6" log = "0.4.27" +prettytable-rs = "0.10.0" [lib] name = "nogamepads_lib_rs" diff --git a/core/examples/start_client_console.rs b/core/examples/start_client_console.rs index 8116299..c4e0126 100644 --- a/core/examples/start_client_console.rs +++ b/core/examples/start_client_console.rs @@ -2,14 +2,14 @@ use std::net::{IpAddr, Ipv4Addr}; use nogamepads_lib_rs::pad_data::pad_player_info::nogamepads_player_info::PlayerInfo; use nogamepads_lib_rs::pad_service::client::nogamepads_client::PadClient; -const PASSWORD : &str = "password"; - fn main() { // 构建玩家信息 let mut player_info = PlayerInfo::new(); - player_info.setup_account_info("juliet", PASSWORD); - player_info.set_nickname("Juliet_Smile"); + player_info.setup_account_info( + env!("TEST_PLAYER_ACCOUNT"), + env!("TEST_PLAYER_PASSWORD")); + player_info.set_nickname(env!("TEST_PLAYER_NICKNAME")); player_info.set_customize_color_hsv(320, 0.5, 1.0); // PINK // 构建客户端 diff --git a/core/examples/start_server_console.rs b/core/examples/start_server_console.rs index 560a378..cbe081f 100644 --- a/core/examples/start_server_console.rs +++ b/core/examples/start_server_console.rs @@ -11,10 +11,11 @@ fn main() { // 构建服务端 let server = PadServer::default() - .addr( - IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), - DEFAULT_PORT - ) + + // 地址 + .addr(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), DEFAULT_PORT) + + // 配置信息 .put_profile( GameProfile::default() .game_name("My Multiplayer Game") @@ -22,6 +23,14 @@ fn main() { .version("0.1 alpha") .to_owned() ) + + // 键位注册 + .register_button(0, "Shoot") + .register_button(1, "Jump") + .register_direction(0, "Walk") + .register_axis(0, "View Yaw") + + // 控制台 .enable_console() // .quiet() .build(); diff --git a/core/src/pad_data/game_layout.rs b/core/src/pad_data/game_layout.rs deleted file mode 100644 index 62afbcc..0000000 --- a/core/src/pad_data/game_layout.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub mod game_layout { - use bincode::{Decode, Encode}; - use serde::{Deserialize, Serialize}; - - #[derive(Encode, Decode, Serialize, Deserialize, PartialEq, Debug)] - pub struct GameLayout { - - } -}
\ No newline at end of file diff --git a/core/src/pad_data/layout.rs b/core/src/pad_data/layout.rs new file mode 100644 index 0000000..4c5f53f --- /dev/null +++ b/core/src/pad_data/layout.rs @@ -0,0 +1,137 @@ +pub mod layout_data { + use std::collections::{HashMap, VecDeque}; + use bincode::{Decode, Encode}; + use serde::{Deserialize, Serialize}; + use crate::pad_data::pad_messages::nogamepads_messages::ControlMessage; + use crate::pad_data::pad_player_info::nogamepads_player_info::PlayerInfo; + use crate::pad_service::server::nogamepads_server::PadServer; + + + #[derive(Encode, Decode, Serialize, Deserialize, PartialEq, Debug, Clone)] + pub struct LayoutKeyRegisters { + pub direction_keys : HashMap<u8, String>, // 注册方向键 + pub axis_keys : HashMap<u8, String>, // 注册轴向键 + pub button_keys : HashMap<u8, String>, // 注册按钮 + } + + impl Default for LayoutKeyRegisters { + fn default() -> LayoutKeyRegisters { + LayoutKeyRegisters { + direction_keys: Default::default(), + axis_keys: Default::default(), + button_keys: Default::default(), + } + } + } + + pub struct LayoutKeyRuntimeData { + directions : HashMap<u8, HashMap<String, (f64, f64)>>, // <键, <玩家Hash, (x, y)>> + axes : HashMap<u8, HashMap<String, f64>>, // <键, <玩家Hash, 轴向>> + button : HashMap<u8, HashMap<String, bool>>, // <键, <玩家Hash, 是否按下>> + + events : VecDeque<(String, ControlMessage)>, // (玩家Hash, 信息) + } + + impl Default for LayoutKeyRuntimeData { + fn default() -> Self { + LayoutKeyRuntimeData { + directions: Default::default(), + axes: Default::default(), + button: Default::default(), + events: Default::default(), + } + } + } + + impl LayoutKeyRuntimeData { + + // 输入控制信息到数据 + pub fn insert_control(&mut self, who: PlayerInfo, msg: ControlMessage) { + match msg { + // 消息放入信息队列待读取 + ControlMessage::Msg(_) => { + self.events.push_back((who.account.player_hash, msg)) + } + + // 按钮更新对应玩家的状态,并且放入信息队列待读取 + ControlMessage::Pressed(button_key) => { + self.button.entry(button_key) + .or_insert_with(HashMap::new) + .insert(who.account.player_hash.clone(), true); + self.events.push_back((who.account.player_hash, msg)) + } + ControlMessage::Released(button_key) => { + self.button.entry(button_key) + .or_insert_with(HashMap::new) + .insert(who.account.player_hash.clone(), false); + self.events.push_back((who.account.player_hash, msg)) + } + + // 轴向更新直接传入玩家状态 + ControlMessage::Axis(axis_key, axis) => { + self.axes.entry(axis_key) + .or_insert_with(HashMap::new) + .insert(who.account.player_hash.clone(), axis); + } + ControlMessage::Dir(dir_key, (x, y)) => { + self.directions.entry(dir_key) + .or_insert_with(HashMap::new) + .insert(who.account.player_hash.clone(), (x, y)); + } + _ => { } + } + } + + pub fn pop_control_event(&mut self, server: &PadServer) -> Option<(PlayerInfo, ControlMessage)> { + let pop = self.events.pop_front(); + if pop.is_some() { + let (hash, msg) = pop.unwrap(); + let info = server.find_online_player(hash); + if info.is_some() { + Some((info.unwrap(), msg)) + } else { + None + } + } else { + None + } + } + + pub fn get_direction(&self, who: &PlayerInfo, key: &u8) -> Option<(f64, f64)> { + Self::get(&self.directions, who, key) + } + + pub fn get_axis(&self, who: &PlayerInfo, key: &u8) -> Option<f64> { + Self::get(&self.axes, who, key) + } + + pub fn get_button_status(&self, who: &PlayerInfo, key: &u8) -> Option<bool> { + Self::get(&self.button, who, key) + } + + fn get<V: Clone>(map: &HashMap<u8, HashMap<String, V>>, who: &PlayerInfo, key: &u8) -> Option<V> { + let key = map.get(key); + if key.is_some() { + let value = key.unwrap().get(&who.account.player_hash); + if value.is_some() { + let result = value.unwrap(); + Some(result.clone()) + } else { None } + } else { None } + } + } +} + +pub mod layout_gamepad { + use bincode::{Decode, Encode}; + use serde::{Deserialize, Serialize}; + + #[derive(Encode, Decode, Serialize, Deserialize, PartialEq, Debug)] + pub struct PadLayout { + + } + + pub trait ButtonArea { + + } +}
\ No newline at end of file diff --git a/core/src/pad_data/mod.rs b/core/src/pad_data/mod.rs index 8ff024a..e041524 100644 --- a/core/src/pad_data/mod.rs +++ b/core/src/pad_data/mod.rs @@ -1,4 +1,4 @@ pub mod pad_messages; pub mod pad_player_info; pub mod game_profile; -mod game_layout;
\ No newline at end of file +pub mod layout;
\ No newline at end of file diff --git a/core/src/pad_service/client.rs b/core/src/pad_service/client.rs index c0b8282..ea0f4ba 100644 --- a/core/src/pad_service/client.rs +++ b/core/src/pad_service/client.rs @@ -21,6 +21,7 @@ pub mod nogamepads_client { use crate::DEFAULT_PORT; use crate::pad_data::game_profile::game_profile::GameProfile; use crate::pad_data::pad_messages::nogamepads_message_encoder::NgpdMessageEncoder; + use crate::pad_data::pad_messages::nogamepads_messages::ControlMessage::{Axis, Dir, Msg, Pressed, Released}; type WriteList = Arc<Mutex<VecDeque<ControlMessage>>>; type ReadList = Arc<Mutex<VecDeque<GameMessage>>>; @@ -129,6 +130,30 @@ pub mod nogamepads_client { // 客户端消息管理 impl PadClient { + pub fn key_press(&self, key_id: u8) { + self.put_msg(Pressed(key_id)); + } + + pub fn key_release(&self, key_id: u8) { + self.put_msg(Released(key_id)); + } + + pub fn change_axis(&self, axis_id: u8, axis: f64) { + self.put_msg(Axis(axis_id, axis)); + } + + pub fn change_direction(&self, direction_id: u8, x: f64, y: f64) { + self.put_msg(Dir(direction_id, (x.clamp(0.0, 1.0), y.clamp(0.0, 1.0)))); + } + + pub fn say_str(&self, msg: &str) { + self.put_msg(Msg(msg.to_owned())); + } + + pub fn say(&self, msg: String) { + self.put_msg(Msg(msg)); + } + pub fn put_msg(&self, msg: ControlMessage) { let mut guard = self.write_list.lock().unwrap(); guard.push_back(msg); diff --git a/core/src/pad_service/server.rs b/core/src/pad_service/server.rs index 66ab56d..eeadb01 100644 --- a/core/src/pad_service/server.rs +++ b/core/src/pad_service/server.rs @@ -5,21 +5,24 @@ pub mod nogamepads_server { use crate::pad_data::pad_messages::nogamepads_messages::{ConnectionCallbackMessage, ConnectionMessage, ControlMessage, GameMessage, LeaveReason}; use log::{error, info, warn}; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + use std::ops::Deref; use std::process::exit; use std::sync::atomic::AtomicBool; use std::sync::atomic::Ordering::SeqCst; use std::sync::{Arc, Mutex, MutexGuard, PoisonError}; use std::time::Duration; use clap::CommandFactory; + use clearscreen::clear; + use prettytable::{Row, Table}; use tokio::io::{AsyncReadExt, AsyncWriteExt, ReadHalf, WriteHalf}; use tokio::net::{TcpListener, TcpStream}; - use tokio::{io, spawn}; + use tokio::{io, signal, spawn}; use tokio::runtime::Runtime; use nogamepads::console_utils::debug_console::read_cli; - use nogamepads::convert_utils::convert_deque_to_vec; use nogamepads::logger_utils::logger_build; use crate::DEFAULT_PORT; use crate::pad_data::game_profile::game_profile::GameProfile; + use crate::pad_data::layout::layout_data::{LayoutKeyRegisters, LayoutKeyRuntimeData}; use crate::pad_data::pad_messages::nogamepads_messages::ConnectionErrorType::{ContainSamePlayer, GameLocked, PlayerBanned, WhatTheHell}; use crate::pad_data::pad_messages::nogamepads_messages::GameMessage::Leave; use crate::pad_data::pad_messages::nogamepads_messages::LeaveReason::ServerClosed; @@ -28,7 +31,6 @@ pub mod nogamepads_server { type PlayerMap = Arc<Mutex<HashMap<String, PlayerInfo>>>; type WriteList = Arc<Mutex<HashMap<String, VecDeque<GameMessage>>>>; - type ReadList = Arc<Mutex<HashMap<String, VecDeque<ControlMessage>>>>; #[repr(C)] pub struct PadServer { @@ -50,13 +52,17 @@ pub mod nogamepads_server { // 保持安静,不初始化 env_logger quiet: bool, + // 键位表 + keys: LayoutKeyRegisters, + // --- 运行时参数 --- + // 发送信息列表 write_list: WriteList, - // 读取信息列表 - read_list: ReadList, + // 运行环境信息 + control_data: Arc<Mutex<LayoutKeyRuntimeData>>, // 在线玩家 online_players: PlayerMap, @@ -69,6 +75,9 @@ pub mod nogamepads_server { // 是否停止服务器 stop: AtomicBool, + + // 调试模式 - 实时信息显示模式 + monitor_view: AtomicBool, } impl Clone for PadServer { @@ -79,13 +88,15 @@ pub mod nogamepads_server { port: self.port.clone(), enable_console: self.enable_console, quiet: self.quiet, + keys: self.keys.clone(), write_list: self.write_list.clone(), - read_list: self.read_list.clone(), + control_data: self.control_data.clone(), online_players: self.online_players.clone(), banned_players: self.banned_players.clone(), game_locked: AtomicBool::new((&self.game_locked.load(SeqCst)).clone()), stop: AtomicBool::new((&self.stop.load(SeqCst)).clone()), + monitor_view: AtomicBool::new((&self.monitor_view.load(SeqCst)).clone()) } } } @@ -98,13 +109,15 @@ pub mod nogamepads_server { port: DEFAULT_PORT, enable_console: false, quiet: false, + keys: LayoutKeyRegisters::default(), write_list: WriteList::default(), - read_list: ReadList::default(), + control_data: Arc::new(Mutex::new(LayoutKeyRuntimeData::default())), online_players: PlayerMap::default(), banned_players: PlayerMap::default(), game_locked: AtomicBool::new(false), stop: AtomicBool::new(false), + monitor_view: AtomicBool::new(false), } } } @@ -151,10 +164,29 @@ pub mod nogamepads_server { self } + pub fn register_keys(&mut self, keys: LayoutKeyRegisters) -> &mut PadServer { + self.keys = keys; + self + } + + pub fn register_button(&mut self, key: u8, name: &str) -> &mut PadServer { + self.keys.button_keys.insert(key, name.to_string()); + self + } + + pub fn register_axis(&mut self, key: u8, name: &str) -> &mut PadServer { + self.keys.axis_keys.insert(key, name.to_string()); + self + } + + pub fn register_direction(&mut self, key: u8, name: &str) -> &mut PadServer { + self.keys.direction_keys.insert(key, name.to_string()); + self + } + pub fn build(&self) -> Arc<PadServer> { Arc::new(self.clone()) } - } // 服务端消息管理 @@ -189,43 +221,50 @@ pub mod nogamepads_server { } } - pub fn pop_a_msg(&self, player: &PlayerInfo) -> Option<ControlMessage> { - match self.read_list.lock() { + pub fn pop_a_msg(&self) -> Option<(PlayerInfo, ControlMessage)> { + match self.control_data.lock() { Ok(mut guard) => { - match guard.get_mut(&player.account.player_hash) { - None => { None } - Some(queue) => { - if ! queue.is_empty() { - queue.pop_front() - } else { - guard.remove(&player.account.player_hash); - None - } - } - } + guard.pop_control_event(self) + } + Err(_) => { + None + } + } + } + } + + // 操控信息管理 + impl PadServer { + pub fn get_player_direction(&self, player: &PlayerInfo, key: &u8) -> Option<(f64, f64)> { + match self.control_data.lock() { + Ok(guard) => { + guard.get_direction(player, &key) } Err(_) => { - error!("Cannot lock \"{:?}\" in read_list", player.account.player_hash); None } } } - pub fn pop_msg_or(&self, player: &PlayerInfo, or: ControlMessage) -> ControlMessage { - self.pop_a_msg(player).unwrap_or(or) + pub fn get_player_axis(&self, player: &PlayerInfo, key: &u8) -> Option<f64> { + match self.control_data.lock() { + Ok(guard) => { + guard.get_axis(player, &key) + } + Err(_) => { + None + } + } } - pub fn list_received(&self, player: &PlayerInfo) -> Vec<ControlMessage> { - match self.read_list.lock() { + pub fn get_player_button_status(&self, player: &PlayerInfo, key: &u8) -> Option<bool> { + match self.control_data.lock() { Ok(guard) => { - match guard.get_key_value(player.account.player_hash.as_str()) { - None => { Vec::new() } - Some(result) => { - convert_deque_to_vec(result.1) - } - } + guard.get_button_status(player, &key) + } + Err(_) => { + None } - Err(_) => { Vec::new() } } } } @@ -303,6 +342,15 @@ pub mod nogamepads_server { Err(err) => Err(err) } } + + pub fn find_online_player(&self, hash: String) -> Option<PlayerInfo> { + match self.online_players.lock() { + Ok(guard) => { + guard.get(&hash).cloned() + } + Err(_) => None + } + } } // 服务端状态控制 @@ -360,6 +408,13 @@ pub mod nogamepads_server { } }); + let ctrl_c_thread = spawn({ + let client = Arc::clone(&self); + async move { + Self::process_ctrl_c(client).await + } + }); + if debug { let debug_cli = spawn({ let client = Arc::clone(&self); @@ -368,9 +423,9 @@ pub mod nogamepads_server { } }); - let _ = tokio::join!(debug_cli, main_thread, background_thread); + let _ = tokio::join!(ctrl_c_thread, debug_cli, main_thread, background_thread); } else { - let _ = tokio::join!(main_thread, background_thread); + let _ = tokio::join!(ctrl_c_thread, main_thread, background_thread); } } } @@ -387,6 +442,14 @@ pub mod nogamepads_server { self.game_locked.load(SeqCst) } + pub fn enter_monitor(&self) { + self.monitor_view.store(true, SeqCst); + } + + pub fn exit_monitor(&self) { + self.monitor_view.store(false, SeqCst); + } + async fn main_request_thread(self: Arc<Self>) { let addr_str = format!("{}:{}", self.address.to_string(), self.port); @@ -527,19 +590,19 @@ pub mod nogamepads_server { Ok(0) => break, Ok(n) => { let msg = ControlMessage::de(buf[0..n].to_vec()); - { - match self.read_list.lock() { - Ok(mut guard) => { - info!("{:?} from {}({})", &msg, player_info.customize.nickname, player_info.account.id); - guard - .entry(player_hash.clone()) - .or_insert_with(VecDeque::new) - .push_back(msg); - - } - Err(_) => { + match self.control_data.lock() { + Ok(mut guard) => { + info!("{:?} from {}({})", &msg, player_info.customize.nickname, player_info.account.id); + let player_info = self.find_online_player(player_hash.clone()); + if player_info.is_some() { + let player_info = player_info.unwrap(); + guard.insert_control(player_info, msg); + } else { + warn!("Player \"{}\" not found!", player_hash); } } + Err(_) => { + } } } Err(e) => { @@ -620,24 +683,136 @@ pub mod nogamepads_server { } } + async fn process_ctrl_c(self: Arc<Self>) { + loop { + signal::ctrl_c().await.unwrap(); + if self.monitor_view.load(SeqCst) { + self.exit_monitor(); + } else { + self.stop_server(); + info!("Stopping server..."); + break; + } + } + } + async fn process_debug_cli(self: Arc<Self>) { loop { if self.stop.load(SeqCst) { info!("Debug console exited"); return; } - tokio::time::sleep(Duration::from_secs_f64(0.2)).await; - let option: Option<Psc> = read_cli( - format!("SERVER {}> ", self.address.to_string()).as_str(), - "psc".to_string(), - Psc::command() - ).await; - match option { - None => {} - Some(cmd) => { - process_debug_cmd(cmd, Arc::clone(&self)); + + if ! self.monitor_view.load(SeqCst) { + tokio::time::sleep(Duration::from_secs_f64(0.2)).await; + + // 控制台模式 + let option: Option<Psc> = read_cli( + format!("SERVER {}> ", self.address.to_string()).as_str(), + "psc".to_string(), + Psc::command() + ).await; + match option { + None => {} + Some(cmd) => { + process_debug_cmd(cmd, Arc::clone(&self)); + } } + } else { + tokio::time::sleep(Duration::from_secs_f64(0.2)).await; + + // 实时信息模式 + + // 表头文本 + let mut header : Vec<String> = Vec::new(); + header.push("PLAYER \\ KEYS".to_string()); + self.all_keys(|key, name, i|{ + if i == 0 { + header.push(format!("{}(btn:{})", name, key)); + } else if i == 1 { + header.push(format!("{}(dir:{})", name, key)); + } else if i == 2 { + header.push(format!("{}(ax:{})", name, key)); + } + }); + + let mut info_table = Table::new(); + + // 添加表头 + info_table.add_row(Row::from_iter(header)); + + // 玩家 + let players = &self.deref().online_players; + match players.lock() { + Ok(guard) => { + for (_player_hash, player) in guard.iter() { + + // 行 + let mut line = Vec::new(); + line.push(player.account.id.to_string()); + self.all_keys(|key, _, i|{ + if i == 0 { + // 按钮 + let r = self.get_player_button_status(player, key); + if r.is_some() { + let r = r.unwrap(); + if r { + line.push("TRUE".to_string()); + } else { + line.push("FALSE".to_string()); + } + } else { + line.push("UNKNOWN".to_string()); + } + + } else if i == 1 { + // 方向 + let r = self.get_player_direction(player, key); + if r.is_some() { + let r = r.unwrap(); + line.push(format!("{}, {}", r.0, r.1)); + } else { + line.push("UNKNOWN".to_string()); + } + + } else if i == 2 { + // 轴向 + let r = self.get_player_axis(player, key); + if r.is_some() { + let r = r.unwrap(); + line.push(format!("{}", r)); + } else { + line.push("UNKNOWN".to_string()); + } + } + }); + + // 添加行文本 + info_table.add_row(Row::from_iter(line)); + } + } + Err(_) => {} + } + + let result = info_table.to_string(); + let _ = clear(); + println!("[HELP] Ctrl + C to exit monitor.\n{}", result); + } + } + } + + fn all_keys<F>(self: &Arc<Self>, mut f: F) + where F: FnMut(&u8, &String, i32){ + let mut i = 0; + for iter in [ + self.keys.button_keys.iter(), + self.keys.direction_keys.iter(), + self.keys.axis_keys.iter(), + ] { + for (key, name) in iter { + f(key, name, i); } + i += 1; } } } diff --git a/core/src/pad_service/server_debug_cli.rs b/core/src/pad_service/server_debug_cli.rs index ab9e5a5..ac52253 100644 --- a/core/src/pad_service/server_debug_cli.rs +++ b/core/src/pad_service/server_debug_cli.rs @@ -1,8 +1,7 @@ use std::collections::HashMap; -use crate::pad_data::pad_messages::nogamepads_messages::{ControlMessage, GameMessage}; +use crate::pad_data::pad_messages::nogamepads_messages::{GameMessage}; use crate::pad_service::server::nogamepads_server::PadServer; use clap::{Args, Parser, Subcommand}; -use std::ops::{Index}; use std::sync::{Arc, MutexGuard, PoisonError}; use log::{error, info}; use crate::pad_data::pad_player_info::nogamepads_player_info::PlayerInfo; @@ -22,6 +21,9 @@ enum Commands { #[command(about = "Clean the screen")] Clear, + #[command(about = "Enter monitor")] + Monitor, + // 关闭服务器 #[command(about = "Close the server")] Stop, @@ -34,13 +36,9 @@ enum Commands { #[command(about = "List all banned players")] Banned, - // 检查收到的消息 - #[command(about = "Check received")] - Received(ReceivedArgs), - // 取出一条消息 #[command(about = "Pop a message")] - Pop(PlayerArgs), + Pop, // 踢出玩家 #[command(about = "Kick a player")] @@ -54,6 +52,14 @@ enum Commands { #[command(about = "Pardon a player")] Pardon(PlayerArgs), + // 锁定游戏 + #[command(about = "Lock this game")] + Lock, + + // 解锁游戏 + #[command(about = "Unlock this game")] + Unlock, + // 激活事件触发器 #[command(about = "Send SkinEventTrigger")] Event(EventArgs) @@ -98,6 +104,10 @@ pub fn process_debug_cmd (cmd: Psc, server: Arc<PadServer>) { clearscreen::clear().expect("Failed to clear screen"); } + Commands::Monitor => { + server.enter_monitor(); + } + Commands::Stop => { server.stop_server(); } @@ -110,27 +120,11 @@ pub fn process_debug_cmd (cmd: Psc, server: Arc<PadServer>) { print_player_list(server.list_players_banned()); } - Commands::Received(args) => { - let players = server.list_players().unwrap_or(Vec::new()); - let player = players.index(args.player.clamp(0, players.iter().count() -1)); - if args.list { - for msg in server.list_received(player) { - info!("{:?}", msg); - } - } else { - info!("Total {} messsage(s)!", server.list_received(player).iter().count()); - } - } - - Commands::Pop(args) => { - match get_player_by_index(&server, args.index) { - None => { - error!("Pup message failed : Player index \"{}\" not found!", args.index); - } - Some(player) => { - let message = server.pop_msg_or(&player, ControlMessage::Err); - info!("{:?}", message); - } + Commands::Pop => { + let message = server.pop_a_msg(); + if message.is_some() { + let (player, msg) = message.unwrap(); + info!("{:?} from \"{}\"({})", msg, player.customize.nickname, player.account.id); } } @@ -158,6 +152,20 @@ pub fn process_debug_cmd (cmd: Psc, server: Arc<PadServer>) { } } + Commands::Lock => { + if ! server.is_game_locked() { + server.lock_game(); + info!("Game locked"); + } + } + + Commands::Unlock => { + if server.is_game_locked() { + server.unlock_game(); + info!("Game unlocked"); + } + } + Commands::Event(args) => { put_to_list(server, args.index, GameMessage::SkinEventTrigger(args.message)); } |
