aboutsummaryrefslogtreecommitdiff
path: root/core/src/pad_service/client.rs
diff options
context:
space:
mode:
author1992414357@qq.com <1992414357@qq.com>2025-06-09 01:44:36 +0800
committer1992414357@qq.com <1992414357@qq.com>2025-06-09 01:44:36 +0800
commit49192dbb98e0ab1f2a66b4786fac86d63f69be64 (patch)
tree7cdf27c7cab5fb6b1aabc2ac7c44b7b492558945 /core/src/pad_service/client.rs
parentc9dbba0d288becb7f05cebe526be25c76e5a850a (diff)
重构所有部分
Diffstat (limited to 'core/src/pad_service/client.rs')
-rw-r--r--core/src/pad_service/client.rs520
1 files changed, 0 insertions, 520 deletions
diff --git a/core/src/pad_service/client.rs b/core/src/pad_service/client.rs
deleted file mode 100644
index b0b05a2..0000000
--- a/core/src/pad_service/client.rs
+++ /dev/null
@@ -1,520 +0,0 @@
-pub mod nogamepads_client {
- use std::collections::VecDeque;
- use crate::pad_data::pad_messages::nogamepads_message_transfer::{read_msg, send_msg};
- use crate::pad_data::pad_messages::nogamepads_messages::{ConnectionCallbackMessage, ConnectionErrorType, ConnectionMessage, ControlMessage, GameMessage, LeaveReason};
- use crate::pad_data::pad_player_info::nogamepads_player_info::PlayerInfo;
- use log::{error, info};
- use std::net::{IpAddr, Ipv4Addr};
- use std::process::exit;
- use std::sync::atomic::AtomicBool;
- use std::sync::atomic::Ordering::SeqCst;
- use std::sync::{Arc, Mutex};
- use std::time::Duration;
- use clap::CommandFactory;
- use tokio::io::{AsyncReadExt, AsyncWriteExt, ReadHalf, WriteHalf};
- use tokio::net::TcpStream;
- use tokio::{io, 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::pad_service::client_debug_cli::{process_debug_cmd, Pcc};
- 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>>>;
-
- #[repr(C)]
- pub struct PadClient {
-
- // --- 主要参数 ---
-
- // 目标地址
- target_address: IpAddr,
-
- // 目标端口
- #[allow(dead_code)]
- target_port: u16,
-
- // 绑定的玩家
- bind_player: PlayerInfo,
-
- // 调试模式
- enable_console: bool,
-
- // 保持安静,不初始化 env_logger
- quiet: bool,
-
- // --- 运行时参数 ---
-
- // 发送信息列表
- write_list: WriteList,
-
- // 读取信息列表
- read_list: ReadList,
-
- // 是否退出
- exit: AtomicBool,
- }
-
- impl Clone for PadClient {
- fn clone(&self) -> Self {
- PadClient {
- enable_console: self.enable_console.clone(),
- target_address: self.target_address.clone(),
- target_port: self.target_port.clone(),
- bind_player: self.bind_player.clone(),
- quiet: self.quiet.clone(),
-
- write_list: self.write_list.clone(),
- read_list: self.read_list.clone(),
- exit: AtomicBool::new(self.exit.load(SeqCst)),
- }
- }
- }
-
- impl Default for PadClient {
- fn default() -> Self {
- PadClient {
- enable_console: false,
- target_address: IpAddr::from(Ipv4Addr::new(127, 0, 0, 1)),
- target_port: DEFAULT_PORT,
- bind_player: PlayerInfo::new(),
- quiet: false,
-
- write_list: WriteList::default(),
- read_list: ReadList::default(),
- exit: AtomicBool::new(false)
- }
- }
- }
-
- // 客户端构建部分
- impl PadClient {
-
- pub fn bind_addr(address: IpAddr) -> PadClient {
- PadClient {
- target_address: address,
- ..PadClient::default()
- }
- }
-
- pub fn bind_addr_with_port(address: IpAddr, port: u16) -> PadClient {
- PadClient {
- target_address: address,
- target_port: port,
- ..PadClient::default()
- }
- }
-
- pub fn enable_console(&mut self) -> &mut PadClient {
- self.enable_console = true;
- self
- }
-
- pub fn quiet(&mut self) -> &mut PadClient {
- self.quiet = true;
- self
- }
-
- pub fn bind_player(&mut self, player: PlayerInfo) -> &mut PadClient {
- self.bind_player = player;
- self
- }
-
- pub fn clone_addr(&self) -> (IpAddr, u16) {
- (self.target_address, self.target_port)
- }
-
- pub fn is_quiet(&self) -> bool {
- self.quiet
- }
-
- pub fn is_enable_console(&self) -> bool {
- self.enable_console
- }
-
- pub fn unbind_player(&mut self) -> PlayerInfo {
- let player = self.bind_player.clone();
- self.bind_player = PlayerInfo::new();
- player
- }
- }
-
- // 客户端消息管理
- 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);
- }
-
- pub fn pop_a_msg(&self) -> Option<GameMessage> {
- let mut guard = self.read_list.lock().unwrap();
- if !guard.is_empty() {
- guard.pop_front()
- } else {
- None
- }
- }
-
- pub fn pop_msg_or(&self, or: GameMessage) -> GameMessage {
- self.pop_a_msg().unwrap_or(or)
- }
-
- pub fn list_received(&self) -> Vec<GameMessage> {
- match self.read_list.lock() {
- Ok(guard) => {
- convert_deque_to_vec(&guard.to_owned())
- }
- Err(_) => { Vec::new() }
- }
- }
- }
-
- // 客户端状态控制
- impl PadClient {
-
- pub fn connect(self) {
- self.connect_in_runtime(None);
- }
-
- pub fn connect_in_runtime(self, tokio_runtime: Option<Runtime>) {
-
- self.exit.store(false, SeqCst);
-
- // 构建 Logger
- if !self.quiet {
- logger_build();
- }
-
- info!("Starting \"NoGamepads Client\".");
-
- // 入口
- let entry = self.get_connect_entry();
-
- // 阻塞运行
- if tokio_runtime.is_some() {
- tokio_runtime.unwrap().block_on(entry);
- } else {
- let runtime = tokio::runtime::Builder::new_multi_thread()
- .thread_name("nogpad-pad_service")
- .thread_stack_size(32 * 1024 * 1024)
- .enable_time()
- .enable_io()
- .build()
- .unwrap();
- runtime.block_on(entry);
- }
- }
-
- pub fn get_connect_entry(self) -> impl Future<Output = ()> + Send + 'static {
-
- // 调试模式
- let debug = self.enable_console;
-
- // Arc
- let arc_client = Arc::new(self);
-
- async move {
- let main_thread = spawn({
- let client = Arc::clone(&arc_client);
- async move {
- Self::main_client_thread(client).await
- }
- });
-
- let background_thread = spawn({
- let client = Arc::clone(&arc_client);
- async move {
- Self::background_thread(client).await
- }
- });
-
- if debug {
- let debug_cli = spawn({
- let client = Arc::clone(&arc_client);
- async move {
- Self::process_debug_cli(client).await
- }
- });
- let _ = tokio::join!(debug_cli, main_thread, background_thread);
- } else {
- let _ = tokio::join!(main_thread, background_thread);
- }
- }
- }
-
- pub fn exit_server(&self) {
- self.exit.store(true, SeqCst);
- }
-
- async fn main_client_thread(self: Arc<Self>) {
- let mut buffer : [u8; 1024] = [0; 1024];
- let addr_str = format!("{}:{}", self.target_address.to_string(), DEFAULT_PORT);
-
- info!("Connected to {}", &addr_str);
-
- // 下载服务端配置文件
- {
- info!("Check: Downloaded game profile.");
- let profile = self.check_server_profile(&mut buffer, addr_str.clone()).await;
- if profile.is_some() {
- info!("Success: Downloaded.");
- let profile = profile.unwrap_or(GameProfile::default());
- for line in profile.to_string().split('\n') {
- info!("{}", line);
- }
- }
- else {
- error!("Failed: Can't download profile!");
- self.exit_server();
- }
- }
-
- // 尝试加入服务端,并建立长连接
- {
- if !self.try_join_game(&mut buffer, addr_str.clone()).await {
- error!("Failed: Can't join the game!");
- self.exit_server();
- return;
- }
- }
- }
-
- async fn check_server_profile(self: &Arc<Self>, buffer: &mut [u8], addr_str: String) -> Option<GameProfile> {
- match TcpStream::connect(&addr_str).await {
- Ok(mut stream) => {
- send_msg(&mut stream, ConnectionMessage::RequestProfile).await;
- let callback : ConnectionCallbackMessage = read_msg(buffer, &mut stream).await;
- match callback {
- ConnectionCallbackMessage::Profile(profile) => {
- Some(profile)
- }
- ConnectionCallbackMessage::Deny(err_type) => {
- error!("Request failed: Server denied your request! ({:?})", err_type);
- None
- }
- ConnectionCallbackMessage::Err => {
- error!("Connection failed: Can't connect to server!");
- None
- }
- _ => { None }
- }
- }
- Err(_err) => {
- None
- }
- }
- }
-
- async fn try_join_game(self: &Arc<Self>, buffer: &mut [u8], addr_str: String) -> bool {
-
- match TcpStream::connect(&addr_str).await {
- Ok(mut stream) => {
-
- // 发送连接请求
- let info = self.bind_player.clone();
- send_msg(&mut stream, ConnectionMessage::Connection(info)).await;
-
- // 读取回调
- let callback : ConnectionCallbackMessage = read_msg(buffer, &mut stream).await;
- match callback {
- ConnectionCallbackMessage::Deny(error) => {
- match error {
- ConnectionErrorType::ContainSamePlayer => {
- error!("Connection failed: Contains same player!");
- false
- }
- ConnectionErrorType::PlayerBanned => {
- error!("Connection failed: You are banned!");
- false
- }
- ConnectionErrorType::Timeout => {
- error!("Connection failed: Timeout!");
- false
- }
- ConnectionErrorType::GameLocked => {
- error!("Connection failed: Game was locked!");
- false
- }
- _ => { false }
- }
- }
- ConnectionCallbackMessage::Ok => {
-
- // 服务端检查完毕,发送 Ready 以示加入游戏
- send_msg(&mut stream, ConnectionMessage::Ready).await;
- let callback : ConnectionCallbackMessage = read_msg(buffer, &mut stream).await;
- match callback {
- ConnectionCallbackMessage::Welcome => {
- info!("Welcome!");
- Self::long_connection(Arc::clone(&self), stream).await;
- }
- ConnectionCallbackMessage::Deny(_error) => {
- error!("Request failed: Server denied your request",);
- }
- _ => {}
- }
- true
- }
- _ => { false }
- }
- }
- Err(err) => {
- error!("Failed to connect to server: {}", err);
- false
- }
- }
- }
-
- async fn long_connection(self: Arc<Self>, stream: TcpStream) {
- let (reader, writer) = io::split(stream);
- spawn(Self::read_task(Arc::clone(&self), reader));
- spawn(Self::write_task(Arc::clone(&self), writer));
- }
-
- async fn read_task(self: Arc<Self>, mut reader: ReadHalf<TcpStream>) {
- let mut buf = [0u8; 1024];
- loop {
- match reader.read(&mut buf).await {
- Ok(0) => break,
- Ok(n) => {
- let msg = GameMessage::de(buf[0..n].to_vec());
- {
- match self.read_list.lock() {
- Ok(mut guard) => {
- match &msg {
- GameMessage::Leave(reason) => {
- match reason {
- LeaveReason::GameOver => {
- info!("Leave Game: Game Over!");
- self.exit_server();
- }
- LeaveReason::ServerClosed => {
- info!("Leave Game: Server closed!");
- self.exit_server();
- }
- LeaveReason::YouAreKicked => {
- error!("Kick Game: You are kicked!");
- self.exit_server();
- }
- LeaveReason::YouAreBanned => {
- error!("Kick Game: You are banned!");
- self.exit_server();
- }
- }
- }
- _ => {
- info!("{:?}", &msg);
- guard.push_back(msg);
- }
- }
- }
- Err(_) => {}
- }
- }
- }
- Err(e) => {
- error!("Error reading from stream: {}", e);
- self.exit_server();
- break;
- }
- }
- }
- }
-
- async fn write_task(self: Arc<Self>, mut writer: WriteHalf<TcpStream>) {
- loop {
- let msg : Option<ControlMessage>;
- {
- let lock = self.write_list.lock();
- match lock {
- Ok(mut guard) => {
- if ! guard.is_empty() {
- msg = guard.pop_front();
- } else {
- msg = None;
- }
- }
- Err(_) => {
- msg = None;
- }
- }
- }
- if msg.is_some() {
- let msg = msg.unwrap();
- match &writer.write_all(NgpdMessageEncoder::en(&msg).as_slice()).await {
- Ok(_) => {
- info!("Sent {:?}", msg);
- }
- Err(_error) => {
- error!("Sent {:?} failed!", msg);
- }
- }
- }
- }
- }
-
- async fn background_thread(self: Arc<Self>) {
- loop {
- // 退出程序的监听
- if self.exit.load(SeqCst) {
- tokio::time::sleep(Duration::from_secs(1)).await;
- info!("Main thread exited.");
- exit(0);
- }
- }
- }
-
- async fn process_debug_cli(self: Arc<Self>) {
- loop {
- if self.exit.load(SeqCst) {
- info!("Debug console exited");
- break
- }
- tokio::time::sleep(Duration::from_secs_f64(0.2)).await;
- let option: Option<Pcc> = read_cli(
- format!("CLIENT {}/{}> ",
- self.target_address.to_string(),
- self.bind_player.account.id).as_str(),
- "pcc".to_string(),
- Pcc::command()
- ).await;
- match option {
- None => {}
- Some(cmd) => {
- process_debug_cmd(cmd, Arc::clone(&self));
- }
- }
- }
- }
- }
-} \ No newline at end of file