diff options
| author | 1992414357@qq.com <1992414357@qq.com> | 2025-05-27 07:21:37 +0800 |
|---|---|---|
| committer | 1992414357@qq.com <1992414357@qq.com> | 2025-05-27 07:21:37 +0800 |
| commit | f8336ed832fa8e1ddd2f1783bdfc23d3279d5e6a (patch) | |
| tree | 42097cd72e46736ac3a544bd3d6dc50e2327a677 /core/src/pad_data | |
First commit
Diffstat (limited to 'core/src/pad_data')
| -rw-r--r-- | core/src/pad_data/game_layout.rs | 9 | ||||
| -rw-r--r-- | core/src/pad_data/game_profile.rs | 99 | ||||
| -rw-r--r-- | core/src/pad_data/mod.rs | 4 | ||||
| -rw-r--r-- | core/src/pad_data/pad_messages.rs | 176 | ||||
| -rw-r--r-- | core/src/pad_data/pad_player_info.rs | 126 |
5 files changed, 414 insertions, 0 deletions
diff --git a/core/src/pad_data/game_layout.rs b/core/src/pad_data/game_layout.rs new file mode 100644 index 0000000..62afbcc --- /dev/null +++ b/core/src/pad_data/game_layout.rs @@ -0,0 +1,9 @@ +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/game_profile.rs b/core/src/pad_data/game_profile.rs new file mode 100644 index 0000000..8d6e279 --- /dev/null +++ b/core/src/pad_data/game_profile.rs @@ -0,0 +1,99 @@ +pub mod game_profile { + use std::fmt::Display; + use bincode::{Decode, Encode}; + use serde::{Deserialize, Serialize}; + + #[derive(Encode, Decode, Serialize, Deserialize, PartialEq, Debug)] + pub struct GameProfile { + + // 游戏名称 + pub game_name: String, + + // 游戏描述 + pub game_description: String, + + // 游戏组织 + pub organization: String, + + // 游戏版本 + pub version: String, + + // 工作室 & 游戏 主页 + pub website: String, + + // 交流邮箱 + pub email: String + } + + impl Default for GameProfile { + fn default() -> Self { + GameProfile { + game_name: "Unnamed Game".to_string(), + game_description: "".to_string(), + organization: "".to_string(), + version: "0.1".to_string(), + website: "".to_string(), + email: "".to_string() + } + } + } + + impl Clone for GameProfile { + fn clone(&self) -> Self { + GameProfile { + game_name: self.game_name.clone(), + game_description: self.game_description.clone(), + organization: self.organization.clone(), + version: self.version.clone(), + website: self.website.clone(), + email: self.email.clone() + } + } + } + + impl Display for GameProfile { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut string = String::new(); + string += format!("Game Name: {}\n", self.game_name).as_str(); + if !self.game_description.eq("") { string += format!("Description: {}\n", self.game_description).as_str(); } + if !self.organization.eq("") { string += format!("Org: {}\n", self.organization).as_str(); } + if !self.website.eq("") { string += format!("- Web: {}\n", self.website).as_str(); } + if !self.version.eq("") { string += format!("Version: {}\n", self.version).as_str(); } + if !self.email.eq("") { string += format!("- E-mail: {}\n", self.email).as_str(); } + + write!(f, "{}", string) + } + } + + impl GameProfile { + pub fn game_name(&mut self, game_name: &str) -> &mut GameProfile { + self.game_name = game_name.to_string(); + self + } + + pub fn game_description(&mut self, game_description: &str) -> &mut GameProfile { + self.game_description = game_description.to_string(); + self + } + + pub fn organization(&mut self, organization: &str) -> &mut GameProfile { + self.organization = organization.to_string(); + self + } + + pub fn version(&mut self, version: &str) -> &mut GameProfile { + self.version = version.to_string(); + self + } + + pub fn website(&mut self, website: &str) -> &mut GameProfile { + self.website = website.to_string(); + self + } + + pub fn email(&mut self, email: &str) -> &mut GameProfile { + self.email = email.to_string(); + self + } + } +}
\ No newline at end of file diff --git a/core/src/pad_data/mod.rs b/core/src/pad_data/mod.rs new file mode 100644 index 0000000..8ff024a --- /dev/null +++ b/core/src/pad_data/mod.rs @@ -0,0 +1,4 @@ +pub mod pad_messages; +pub mod pad_player_info; +pub mod game_profile; +mod game_layout;
\ No newline at end of file diff --git a/core/src/pad_data/pad_messages.rs b/core/src/pad_data/pad_messages.rs new file mode 100644 index 0000000..f081e5d --- /dev/null +++ b/core/src/pad_data/pad_messages.rs @@ -0,0 +1,176 @@ +pub mod nogamepads_messages { + use bincode::{Decode, Encode}; + use crate::pad_data::game_profile::game_profile::GameProfile; + use crate::pad_data::pad_player_info::nogamepads_player_info::PlayerInfo; + + #[derive(Encode, Decode, PartialEq, Debug, Clone)] + pub enum ControlMessage { + + Msg(String), + + Pressed(u8), + + Released(u8), + + Axis(u8, f64), + + Dir(u8, (f64, f64)), + + Exit, + + Err + } + + #[derive(Encode, Decode, PartialEq, Debug, Clone)] + pub enum GameMessage { + + SkinEventTrigger(u8), + + DisableKey(u8), + + EnableKey(u8), + + Leave(LeaveReason), + + Err + } + + #[derive(Encode, Decode, PartialEq, Debug, Clone)] + pub enum LeaveReason { + + GameOver, + + ServerClosed, + + YouAreKicked, + + YouAreBanned + } + + #[derive(Encode, Decode, PartialEq, Debug, Clone)] + pub enum ConnectionMessage { + + Connection(PlayerInfo), + + RequestProfile, + + RequestLayoutConfigure, + + RequestSkinPackage, + + Ready, + + Err + } + + #[derive(Encode, Decode, PartialEq, Debug, Clone)] + pub enum ConnectionCallbackMessage { + + Profile(GameProfile), + + Deny(ConnectionErrorType), + + Fail(ConnectionErrorType), + + Ok, + + Welcome, + + Err + } + + #[derive(Encode, Decode, PartialEq, Debug, Clone)] + pub enum ConnectionErrorType { + + ContainSamePlayer, + + PlayerBanned, + + Timeout, + + GameLocked, + + WhatTheHell + } +} + +pub mod nogamepads_message_encoder { + use bincode::{Decode, Encode}; + use crate::{BINCODE_CONFIG, BINCODE_CONVERT_FAILED}; + use crate::pad_data::pad_messages::nogamepads_messages::{ConnectionCallbackMessage, ConnectionMessage, ControlMessage, GameMessage}; + + pub trait NgpdMessageEncoder<Message: Encode + Decode<()>> { + fn err_result_decode () -> Message; + fn err_result_encode () -> Vec<u8> { + BINCODE_CONVERT_FAILED + } + + fn en(&self) -> Vec<u8> where Self : Encode { + bincode::encode_to_vec(self, BINCODE_CONFIG) + .unwrap_or_else(|_| Self::err_result_encode()) + } + + fn de(encoded : Vec<u8>) -> Message { + match bincode::decode_from_slice(&encoded[..], BINCODE_CONFIG) { + Ok((decoded, _)) => decoded, + Err(_) => Self::err_result_decode() + } + } + } + + impl NgpdMessageEncoder<ControlMessage> for ControlMessage { + fn err_result_decode() -> ControlMessage { + ControlMessage::Err + } + } + + impl NgpdMessageEncoder<GameMessage> for GameMessage { + fn err_result_decode() -> GameMessage { + GameMessage::Err + } + } + + impl NgpdMessageEncoder<ConnectionMessage> for ConnectionMessage { + fn err_result_decode() -> ConnectionMessage { + ConnectionMessage::Err + } + } + + impl NgpdMessageEncoder<ConnectionCallbackMessage> for ConnectionCallbackMessage { + fn err_result_decode() -> ConnectionCallbackMessage { + ConnectionCallbackMessage::Err + } + } +} + +pub mod nogamepads_message_transfer { + use bincode::{Decode, Encode}; + use log::error; + use tokio::io::{AsyncReadExt, AsyncWriteExt}; + use tokio::net::TcpStream; + use crate::pad_data::pad_messages::nogamepads_message_encoder::NgpdMessageEncoder; + + pub async fn send_msg <Message>(stream: &mut TcpStream, msg: impl NgpdMessageEncoder<Message> + Decode<()> + Encode) + where Message: NgpdMessageEncoder<Message> + Decode<()> + Encode { + match stream.write_all(NgpdMessageEncoder::en(&msg).as_slice()).await { + Ok(_) => {} + Err(_) => { + error!("Failed to send message."); + } + } + } + + pub async fn read_msg<Message>(buffer: &mut [u8], stream: &mut TcpStream) -> Message + where Message: NgpdMessageEncoder<Message> + Decode<()> + Encode { + match stream.read(buffer).await { + Ok(read) => { + let received = &buffer[..read]; + <Message as NgpdMessageEncoder<Message>>::de(Vec::from(received)) + } + Err(err) => { + error!("Error reading from socket: {}", err); + <Message as NgpdMessageEncoder<Message>>::err_result_decode() + } + } + } +}
\ No newline at end of file diff --git a/core/src/pad_data/pad_player_info.rs b/core/src/pad_data/pad_player_info.rs new file mode 100644 index 0000000..ab0f6fd --- /dev/null +++ b/core/src/pad_data/pad_player_info.rs @@ -0,0 +1,126 @@ +pub mod nogamepads_player_info { + + use bincode::{Decode, Encode}; + use hex::encode; + use sha1::{Digest, Sha1}; + use serde::{Deserialize, Serialize}; + + pub const ACCOUNT_HASH_SALT : &str = "Mr.Weicao"; + + #[derive(Encode, Decode, + Serialize, Deserialize, + PartialEq, Debug)] + pub struct PlayerInfo { + pub account: PlayerAccountInfo, + pub customize: PlayerCustomizeInfo + } + + #[derive(Encode, Decode, + Serialize, Deserialize, + PartialEq, Debug)] + pub struct PlayerAccountInfo { + pub id: String, + pub player_hash: String + } + + #[derive(Encode, Decode, + Serialize, Deserialize, + PartialEq, Debug)] + pub struct PlayerCustomizeInfo { + pub nickname: String, + + pub color_hue: i32, // 0 - 360 + pub color_saturation: f64, // 0 - 1 + pub color_value: f64 // 0 - 1 + } + + impl PlayerInfo { + + pub fn new() -> PlayerInfo { + PlayerInfo { + customize: PlayerCustomizeInfo::default(), + account: PlayerAccountInfo::default() + } + } + + pub fn set_nickname(&mut self, name: &str) -> &mut PlayerInfo { + self.customize.nickname = String::from(name); + self + } + + pub fn set_customize_color_hue(&mut self, mut hue: i32) -> &mut PlayerInfo { + hue = hue.clamp(0, 360); + self.customize.color_hue = hue; + self + } + + pub fn set_customize_color_hsv(&mut self, mut hue: i32, mut saturation: f64, mut value: f64) -> &mut PlayerInfo { + hue = hue.clamp(0, 360); + saturation = saturation.clamp(0.0, 1.0); + value = value.clamp(0.0, 1.0); + + self.customize.color_hue = hue; + self.customize.color_saturation = saturation; + self.customize.color_value = value; + self + } + + pub fn setup_account_info(&mut self, id: &str, password: &str) -> &mut PlayerInfo { + + let combined = format!("{}{}{}", id, password, ACCOUNT_HASH_SALT); + let mut hasher = Sha1::new(); + hasher.update(combined); + let result = hasher.finalize(); + + self.account.id = String::from(id); + self.account.player_hash = encode(&result[..]); + self + } + } + + impl Clone for PlayerInfo { + fn clone(&self) -> PlayerInfo { + PlayerInfo { + account: PlayerAccountInfo { + id: String::from(self.account.id.clone()), + player_hash: String::from(self.account.player_hash.clone()) + }, + customize: PlayerCustomizeInfo { + nickname: self.customize.nickname.clone(), + color_hue: self.customize.color_hue.clone(), + color_saturation: self.customize.color_saturation.clone(), + color_value: self.customize.color_value.clone() + } + } + } + } + + impl Default for PlayerCustomizeInfo { + fn default() -> Self { + PlayerCustomizeInfo { + nickname: String::from("unnamed"), + + color_hue: 120, + color_saturation: 1.0, + color_value: 1.0 + } + } + } + + impl Default for PlayerAccountInfo { + fn default() -> Self { + PlayerAccountInfo { + id: String::from("empty"), + player_hash: String::from("") + } + } + } +} + +#[cfg(test)] +mod player_info_test { + #[test] + fn test_player_info_setup() { + + } +}
\ No newline at end of file |
