diff --git a/src/entity/character.rs b/src/entity/character.rs index 8a0aa0d..3bff770 100644 --- a/src/entity/character.rs +++ b/src/entity/character.rs @@ -2,8 +2,8 @@ use std::convert::{From, Into}; use std::collections::HashMap; use serde::{Serialize, Deserialize}; -use libpso::packet::ship::{UpdateConfig, WriteInfoboard, KeyboardConfig}; -use libpso::character::character::{DEFAULT_PALETTE_CONFIG, DEFAULT_TECH_MENU, DEFAULT_KEYBOARD_CONFIG1}; +use libpso::packet::ship::{UpdateConfig, WriteInfoboard, KeyboardConfig, GamepadConfig}; +use libpso::character::settings::{DEFAULT_PALETTE_CONFIG, DEFAULT_TECH_MENU, DEFAULT_KEYBOARD_CONFIG1, DEFAULT_KEYBOARD_CONFIG2, DEFAULT_KEYBOARD_CONFIG3, DEFAULT_KEYBOARD_CONFIG4, DEFAULT_GAMEPAD_CONFIG}; use crate::entity::item::tech::Technique; use crate::entity::account::UserAccountId; @@ -266,25 +266,71 @@ pub struct CharacterMaterials { #[derive(Clone)] pub struct CharacterKeyboardConfig { - pub keyboard: [u8; 0x16C], + pub keyboard_config: [u8; 0x16C], } impl CharacterKeyboardConfig { - fn new() -> CharacterKeyboardConfig { - CharacterKeyboardConfig { - keyboard: DEFAULT_KEYBOARD_CONFIG1, + fn new(preset: usize) -> CharacterKeyboardConfig { + match preset { + 1 => { + CharacterKeyboardConfig { + keyboard_config: DEFAULT_KEYBOARD_CONFIG1, + } + }, + 2 => { + CharacterKeyboardConfig { + keyboard_config: DEFAULT_KEYBOARD_CONFIG2, + } + }, + 3 => { + CharacterKeyboardConfig { + keyboard_config: DEFAULT_KEYBOARD_CONFIG3, + } + }, + 4 => { + CharacterKeyboardConfig { + keyboard_config: DEFAULT_KEYBOARD_CONFIG4, + } + }, + _ => { + CharacterKeyboardConfig { + keyboard_config: DEFAULT_KEYBOARD_CONFIG1, + } + }, } } pub fn update(&mut self, new_config: &KeyboardConfig) { - self.keyboard = new_config.keyboard_config; + self.keyboard_config = new_config.keyboard_config; } pub fn as_bytes(&self) -> [u8; 0x16C] { - self.keyboard + self.keyboard_config } } +#[derive(Clone)] +pub struct CharacterGamepadConfig { + pub gamepad_config: [u8; 56], +} + +impl Default for CharacterGamepadConfig { + fn default() -> CharacterGamepadConfig { + CharacterGamepadConfig { + gamepad_config: [0; 56], + } + } +} + +impl CharacterGamepadConfig { + pub fn update(&mut self, new_config: &GamepadConfig) { + self.gamepad_config = new_config.gamepad_config; + } + + pub fn as_bytes(&self) -> [u8; 56] { + self.gamepad_config + } +} #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Default, derive_more::Display)] pub struct CharacterEntityId(pub u32); @@ -309,6 +355,8 @@ pub struct NewCharacterEntity { pub tech_menu: CharacterTechMenu, pub option_flags: u32, + pub keyboard_config: CharacterKeyboardConfig, + pub gamepad_config: CharacterGamepadConfig, } impl NewCharacterEntity { @@ -328,6 +376,8 @@ impl NewCharacterEntity { materials: CharacterMaterials::default(), tech_menu: CharacterTechMenu::default(), option_flags: 0, + keyboard_config: CharacterKeyboardConfig::new(1), + gamepad_config: CharacterGamepadConfig::default(), } } } @@ -353,4 +403,6 @@ pub struct CharacterEntity { pub tech_menu: CharacterTechMenu, pub option_flags: u32, + pub keyboard_config: CharacterKeyboardConfig, + pub gamepad_config: CharacterGamepadConfig, } diff --git a/src/entity/gateway/inmemory.rs b/src/entity/gateway/inmemory.rs index 3d37761..5c7afb4 100644 --- a/src/entity/gateway/inmemory.rs +++ b/src/entity/gateway/inmemory.rs @@ -202,6 +202,8 @@ impl EntityGateway for InMemoryGateway { materials: character.materials, tech_menu: character.tech_menu, option_flags: character.option_flags, + keyboard_config: character.keyboard_config, + gamepad_config: character.gamepad_config, }; characters.insert(new_character.id, new_character.clone()); Ok(new_character) diff --git a/src/entity/gateway/postgres/models.rs b/src/entity/gateway/postgres/models.rs index 13df761..f2b8c94 100644 --- a/src/entity/gateway/postgres/models.rs +++ b/src/entity/gateway/postgres/models.rs @@ -49,8 +49,8 @@ pub struct PgUserSettings { id: i32, user_account: i32, blocked_users: Vec, //[u32; 0x1E], - key_config: Vec, //[u8; 0x16C], - joystick_config: Vec, //[u8; 0x38], + keyboard_config: Vec, //[u8; 0x16C], + gamepad_config: Vec, //[u8; 0x38], option_flags: i32, shortcuts: Vec, //[u8; 0xA40], symbol_chats: Vec, //[u8; 0x4E0], @@ -64,8 +64,8 @@ impl From for UserSettingsEntity { user_id: UserAccountId(other.user_account as u32), settings: settings::UserSettings { blocked_users: vec_to_array(other.blocked_users.chunks(4).map(|b| u32::from_le_bytes([b[0], b[1], b[2], b[3]])).collect()), - key_config: vec_to_array(other.key_config), - joystick_config: vec_to_array(other.joystick_config), + keyboard_config: vec_to_array(other.keyboard_config), + gamepad_config: vec_to_array(other.gamepad_config), option_flags: other.option_flags as u32, shortcuts: vec_to_array(other.shortcuts), symbol_chats: vec_to_array(other.symbol_chats), @@ -217,6 +217,8 @@ pub struct PgCharacter { tp: i16, tech_menu: Vec, + keyboard_config: Vec, + gamepad_config: Vec, } impl From for CharacterEntity { @@ -266,6 +268,12 @@ impl From for CharacterEntity { tech_menu: CharacterTechMenu { tech_menu: vec_to_array(other.tech_menu) }, + keyboard_config: CharacterKeyboardConfig { + keyboard_config: vec_to_array(other.keyboard_config) + }, + gamepad_config: CharacterGamepadConfig { + gamepad_config: vec_to_array(other.gamepad_config) + }, } } } diff --git a/src/entity/gateway/postgres/postgres.rs b/src/entity/gateway/postgres/postgres.rs index bbf116a..f52da90 100644 --- a/src/entity/gateway/postgres/postgres.rs +++ b/src/entity/gateway/postgres/postgres.rs @@ -144,12 +144,12 @@ impl EntityGateway for PostgresGateway { } async fn create_user_settings(&mut self, settings: NewUserSettingsEntity) -> Result { - let new_settings = sqlx::query_as::<_, PgUserSettings>("insert into user_settings (user_account, blocked_users, key_config, joystick_config, option_flags, shortcuts, symbol_chats, team_name) + let new_settings = sqlx::query_as::<_, PgUserSettings>("insert into user_settings (user_account, blocked_users, key_config, gamepad_config, option_flags, shortcuts, symbol_chats, team_name) values ($1, $2, $3, $4, $5, $6, $7, $8) returning *;") .bind(settings.user_id.0) .bind(settings.settings.blocked_users.iter().copied().flat_map(|i| i.to_le_bytes().to_vec()).collect::>()) - .bind(settings.settings.key_config.to_vec()) - .bind(settings.settings.joystick_config.to_vec()) + .bind(settings.settings.keyboard_config.to_vec()) + .bind(settings.settings.gamepad_config.to_vec()) .bind(settings.settings.option_flags as i32) .bind(settings.settings.shortcuts.to_vec()) .bind(settings.settings.symbol_chats.to_vec()) @@ -166,10 +166,10 @@ impl EntityGateway for PostgresGateway { } async fn save_user_settings(&mut self, settings: &UserSettingsEntity) -> Result<(), GatewayError> { - sqlx::query("update user_settings set blocked_users=$1, key_config=$2, joystick_config=$3, option_flags=$4, shortcuts=$5, symbol_chats=$6, team_name=$7 where id=$8") + sqlx::query("update user_settings set blocked_users=$1, key_config=$2, gamepad_config=$3, option_flags=$4, shortcuts=$5, symbol_chats=$6, team_name=$7 where id=$8") .bind(settings.settings.blocked_users.iter().copied().flat_map(|i| i.to_le_bytes().to_vec()).collect::>()) - .bind(&settings.settings.key_config.to_vec()) - .bind(&settings.settings.joystick_config.to_vec()) + .bind(&settings.settings.keyboard_config.to_vec()) + .bind(&settings.settings.gamepad_config.to_vec()) .bind(&settings.settings.option_flags) .bind(&settings.settings.shortcuts.to_vec()) .bind(&settings.settings.symbol_chats.to_vec()) diff --git a/src/login/character.rs b/src/login/character.rs index 69d43e7..c444a96 100644 --- a/src/login/character.rs +++ b/src/login/character.rs @@ -385,8 +385,8 @@ impl CharacterServerState { } }; - let pkt = SendKeyAndTeamSettings::new(settings.settings.key_config, - settings.settings.joystick_config, 0, 0); + let pkt = SendKeyAndTeamSettings::new(settings.settings.keyboard_config, + settings.settings.gamepad_config, 0, 0); let pkt = SendCharacterPacket::SendKeyAndTeamSettings(Box::new(pkt)); Ok(vec![pkt]) diff --git a/src/ship/character.rs b/src/ship/character.rs index e5d4429..0760b42 100644 --- a/src/ship/character.rs +++ b/src/ship/character.rs @@ -91,13 +91,31 @@ pub struct FullCharacterBytesBuilder<'a> { meseta: Option, inventory: Option<&'a CharacterInventory>, bank: Option<&'a CharacterBank>, - key_config: Option<&'a [u8; 0x16C]>, - joystick_config: Option<&'a [u8; 0x38]>, + keyboard_config: Option<&'a [u8; 0x16C]>, + gamepad_config: Option<&'a [u8; 0x38]>, symbol_chat: Option<&'a [u8; 1248]>, tech_menu: Option<&'a [u8; 40]>, option_flags: Option, } +impl<'a> Default for FullCharacterBytesBuilder<'a> { + fn default() -> FullCharacterBytesBuilder<'a> { + FullCharacterBytesBuilder { + character: None, + stats: None, + level: None, + inventory: None, + bank: None, + keyboard_config: None, + gamepad_config: None, + symbol_chat: None, + tech_menu: None, + option_flags: None, + } + } +} + + impl<'a> FullCharacterBytesBuilder<'a> { #[must_use] pub fn character(self, character: &'a CharacterEntity) -> FullCharacterBytesBuilder<'a> { @@ -148,17 +166,17 @@ impl<'a> FullCharacterBytesBuilder<'a> { } #[must_use] - pub fn key_config(self, key_config: &'a [u8; 0x16C]) -> FullCharacterBytesBuilder<'a> { + pub fn keyboard_config(self, keyboard_config: &'a [u8; 0x16C]) -> FullCharacterBytesBuilder<'a> { FullCharacterBytesBuilder { - key_config: Some(key_config), + keyboard_config: Some(keyboard_config), ..self } } #[must_use] - pub fn joystick_config(self, joystick_config: &'a [u8; 0x38]) -> FullCharacterBytesBuilder<'a> { + pub fn joystick_config(self, gamepad_config: &'a [u8; 0x38]) -> FullCharacterBytesBuilder<'a> { FullCharacterBytesBuilder { - joystick_config: Some(joystick_config), + gamepad_config: Some(gamepad_config), ..self } } @@ -194,8 +212,8 @@ impl<'a> FullCharacterBytesBuilder<'a> { let meseta = self.meseta.unwrap(); let inventory = self.inventory.unwrap(); let bank = self.bank.unwrap(); - let key_config = self.key_config.unwrap(); - let joystick_config = self.joystick_config.unwrap(); + let keyboard_config = self.keyboard_config.unwrap(); + let gamepad_config = self.gamepad_config.unwrap(); let symbol_chat = self.symbol_chat.unwrap(); let tech_menu = self.tech_menu.unwrap(); let option_flags = self.option_flags.unwrap(); @@ -222,8 +240,8 @@ impl<'a> FullCharacterBytesBuilder<'a> { ..character::Inventory::default() }, key_team_config: character::KeyTeamConfig { - key_config: *key_config, - joystick_config: *joystick_config, + keyboard_config: *keyboard_config, + gamepad_config: *gamepad_config, ..character::KeyTeamConfig::default() }, info_board: character.info_board.as_bytes(), diff --git a/src/ship/packet/handler/lobby.rs b/src/ship/packet/handler/lobby.rs index b0004fb..48973fc 100644 --- a/src/ship/packet/handler/lobby.rs +++ b/src/ship/packet/handler/lobby.rs @@ -32,8 +32,10 @@ pub fn block_selected(id: ClientId, .meseta(*meseta) .inventory(inventory) .bank(bank) - .key_config(&client.settings.settings.key_config) - .joystick_config(&client.settings.settings.joystick_config) + // .keyboard_config(&client.settings.settings.keyboard_config) + // .joystick_config(&client.settings.settings.joystick_config) + .keyboard_config(&client.character.keyboard_config.as_bytes()) + .joystick_config(&client.character.gamepad_config.as_bytes()) .symbol_chat(&client.settings.settings.symbol_chats) .tech_menu(&client.character.tech_menu.as_bytes()) .option_flags(client.character.option_flags) diff --git a/src/ship/packet/handler/settings.rs b/src/ship/packet/handler/settings.rs index 6063f74..17d0d64 100644 --- a/src/ship/packet/handler/settings.rs +++ b/src/ship/packet/handler/settings.rs @@ -26,13 +26,24 @@ pub async fn save_options(id: ClientId, Box::new(None.into_iter()) } -// pub async fn keyboard_config(id: ClientId, -// keyboard_config: &KeyboardConfig, -// clients: &mut Clients, -// entity_gateway: &mut EG) -// -> Box + Send> { -// let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); -// client.character.option_flags = save_options.options; -// entity_gateway.save_character(&client.character).await.unwrap(); -// Box::new(None.into_iter()) -// } \ No newline at end of file +pub async fn keyboard_config(id: ClientId, + keyboard_config: &KeyboardConfig, + clients: &mut Clients, + entity_gateway: &mut EG) + -> Box + Send> { + let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); + client.character.keyboard_config.update(keyboard_config); + entity_gateway.save_character(&client.character).await.unwrap(); + Box::new(None.into_iter()) +} + +pub async fn gamepad_config(id: ClientId, + gamepad_config: &GamepadConfig, + clients: &mut Clients, + entity_gateway: &mut EG) + -> Box + Send> { + let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); + client.character.gamepad_config.update(gamepad_config); + entity_gateway.save_character(&client.character).await.unwrap(); + Box::new(None.into_iter()) +} \ No newline at end of file diff --git a/src/ship/ship.rs b/src/ship/ship.rs index f76a441..40724b9 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -93,7 +93,6 @@ pub enum RecvShipPacket { PlayerChat(PlayerChat), CreateRoom(CreateRoom), RoomNameRequest(RoomNameRequest), - UpdateConfig(UpdateConfig), ViewInfoboardRequest(ViewInfoboardRequest), WriteInfoboard(WriteInfoboard), RoomListRequest(RoomListRequest), @@ -116,6 +115,8 @@ pub enum RecvShipPacket { ItemsToTrade(ItemsToTrade), TradeConfirmed(TradeConfirmed), KeyboardConfig(KeyboardConfig), + GamepadConfig(GamepadConfig), + UpdateConfig(UpdateConfig), } impl RecvServerPacket for RecvShipPacket { @@ -140,7 +141,6 @@ impl RecvServerPacket for RecvShipPacket { 0x06 => Ok(RecvShipPacket::PlayerChat(PlayerChat::from_bytes(data)?)), 0xC1 => Ok(RecvShipPacket::CreateRoom(CreateRoom::from_bytes(data)?)), 0x8A => Ok(RecvShipPacket::RoomNameRequest(RoomNameRequest::from_bytes(data)?)), - 0x7ED => Ok(RecvShipPacket::UpdateConfig(UpdateConfig::from_bytes(data)?)), 0xD8 => Ok(RecvShipPacket::ViewInfoboardRequest(ViewInfoboardRequest::from_bytes(data)?)), 0xD9 => Ok(RecvShipPacket::WriteInfoboard(WriteInfoboard::from_bytes(data)?)), 0x08 => Ok(RecvShipPacket::RoomListRequest(RoomListRequest::from_bytes(data)?)), @@ -158,6 +158,8 @@ impl RecvServerPacket for RecvShipPacket { 0xE7 => Ok(RecvShipPacket::FullCharacterData(Box::new(FullCharacterData::from_bytes(data)?))), 0x1ED => Ok(RecvShipPacket::SaveOptions(SaveOptions::from_bytes(data)?)), 0x4ED => Ok(RecvShipPacket::KeyboardConfig(KeyboardConfig::from_bytes(data)?)), + 0x5ED => Ok(RecvShipPacket::GamepadConfig(GamepadConfig::from_bytes(data)?)), + 0x7ED => Ok(RecvShipPacket::UpdateConfig(UpdateConfig::from_bytes(data)?)), _ => Err(PacketParseError::WrongPacketForServerType(u16::from_le_bytes([data[2], data[3]]), data.to_vec())) } } @@ -744,6 +746,12 @@ impl ServerState for ShipServerState { let block = self.blocks.with_client(id, &self.clients)?; handler::trade::trade_confirmed(id, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_manager, &mut self.trades).await? }, + RecvShipPacket::KeyboardConfig(keyboard_config) => { + handler::settings::keyboard_config(id, keyboard_config, &mut self.clients, &mut self.entity_gateway).await + }, + RecvShipPacket::GamepadConfig(gamepad_config) => { + handler::settings::gamepad_config(id, gamepad_config, &mut self.clients, &mut self.entity_gateway).await + }, }) }