From 881b7c8e46ce793cde49b7b8a7615643f36181a3 Mon Sep 17 00:00:00 2001 From: jake Date: Tue, 21 Apr 2020 21:47:41 -0600 Subject: [PATCH 01/11] begin moving packet handlers to own module, send_player_to_lobby --- src/ship/mod.rs | 1 + src/ship/packet/builder/mod.rs | 0 src/ship/packet/handler/lobby.rs | 101 +++++++++++++++++++++++++++++++ src/ship/packet/handler/mod.rs | 1 + src/ship/packet/mod.rs | 2 + src/ship/ship.rs | 96 ++--------------------------- 6 files changed, 110 insertions(+), 91 deletions(-) create mode 100644 src/ship/packet/builder/mod.rs create mode 100644 src/ship/packet/handler/lobby.rs create mode 100644 src/ship/packet/handler/mod.rs create mode 100644 src/ship/packet/mod.rs diff --git a/src/ship/mod.rs b/src/ship/mod.rs index 4b6b4d0..c0b74b2 100644 --- a/src/ship/mod.rs +++ b/src/ship/mod.rs @@ -7,3 +7,4 @@ pub mod item_stats; pub mod map; pub mod monster; pub mod drops; +pub mod packet; diff --git a/src/ship/packet/builder/mod.rs b/src/ship/packet/builder/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/ship/packet/handler/lobby.rs b/src/ship/packet/handler/lobby.rs new file mode 100644 index 0000000..9efe3bd --- /dev/null +++ b/src/ship/packet/handler/lobby.rs @@ -0,0 +1,101 @@ +use std::collections::HashMap; +use libpso::packet::ship::*; +use crate::common::serverstate::ClientId; +use crate::common::leveltable::CharacterLevelTable; +use crate::ship::ship::{SendShipPacket, ShipError, ClientState}; +use crate::ship::character::{CharacterBytesBuilder, FullCharacterBytesBuilder}; +use crate::ship::location::{ClientLocation, LobbyId, RoomId, RoomLobby, MAX_ROOMS}; +use libpso::character::character; + + +pub fn send_player_to_lobby(id: ClientId, + _pkt: &CharData, + client_location: &mut ClientLocation, + clients: &HashMap, + level_table: &CharacterLevelTable) -> Result, ShipError> { + let lobby = client_location.add_client_to_next_available_lobby(id, LobbyId(0)).map_err(|_| ShipError::TooManyClients)?; + let lobby_clients = client_location.get_clients_in_lobby(lobby).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; + let playerinfo = lobby_clients.iter() + .map(|room_client| { + let client = clients.get(&room_client.client).ok_or(ShipError::ClientNotFound(id)).unwrap(); + let (level, stats) = level_table.get_stats_from_exp(client.character.char_class, client.character.exp); + let c = CharacterBytesBuilder::new() + .character(&client.character) + .stats(&stats) + .level(level - 1) + .build(); + PlayerInfo { + header: PlayerHeader { + tag: 0x100, + guildcard: client.user.id.0, + _unknown1: [0; 5], + client_id: room_client.local_client.id() as u32, + name: c.name, + _unknown2: 2, + }, + inventory: character::Inventory { + item_count: 0, + hp_mats_used: 0, + tp_mats_used: 0, + language: 0, + items: [character::InventoryItem::default(); 30], + }, + character: c, + } + }); + let area_client = client_location.get_local_client(id).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; + let leader = client_location.get_lobby_leader(lobby).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; + + let join_lobby = JoinLobby { + client: area_client.local_client.id(), + leader: leader.local_client.id(), + one: 1, + lobby: lobby.id(), + block: 1, + event: 0, + padding: 0, + playerinfo: playerinfo.collect(), + }; + + let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; + let (level, stats) = level_table.get_stats_from_exp(client.character.char_class, client.character.exp); + let c = CharacterBytesBuilder::new() + .character(&client.character) + .stats(&stats) + .level(level - 1) + .build(); + let addto = AddToLobby { + flag: 1, + client: area_client.local_client.id(), + leader: leader.local_client.id(), + one: 1, + lobby: lobby.id(), + block: 1, + event: 0, + padding: 0, + playerinfo: PlayerInfo { + header: PlayerHeader { + tag: 0x100, + guildcard: client.user.id.0, + _unknown1: [0; 5], + client_id: area_client.local_client.id() as u32, + name: c.name, + _unknown2: 2, + }, + inventory: character::Inventory { + item_count: 0, + hp_mats_used: 0, + tp_mats_used: 0, + language: 0, + items: [character::InventoryItem::default(); 30], + }, + character: c, + }, + }; + + let neighbors = client_location.get_client_neighbors(id).unwrap(); + Ok(vec![(id, SendShipPacket::JoinLobby(join_lobby))] + .into_iter() + .chain(neighbors.into_iter() + .map(|c| (c.client, SendShipPacket::AddToLobby(addto.clone())))).collect()) +} diff --git a/src/ship/packet/handler/mod.rs b/src/ship/packet/handler/mod.rs new file mode 100644 index 0000000..36bd53c --- /dev/null +++ b/src/ship/packet/handler/mod.rs @@ -0,0 +1 @@ +pub mod lobby; diff --git a/src/ship/packet/mod.rs b/src/ship/packet/mod.rs new file mode 100644 index 0000000..5b46ce1 --- /dev/null +++ b/src/ship/packet/mod.rs @@ -0,0 +1,2 @@ +pub mod builder; +pub mod handler; diff --git a/src/ship/ship.rs b/src/ship/ship.rs index 483e61c..709805f 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -25,6 +25,7 @@ use crate::ship::location::{ClientLocation, LobbyId, RoomId, RoomLobby, MAX_ROOM use crate::ship::character::{CharacterBytesBuilder, FullCharacterBytesBuilder}; use crate::ship::items; use crate::ship::room; +use crate::ship::packet::handler; pub const SHIP_PORT: u16 = 23423; @@ -133,10 +134,10 @@ impl SendServerPacket for SendShipPacket { } } -struct ClientState { - user: UserAccountEntity, +pub struct ClientState { + pub user: UserAccountEntity, settings: UserSettingsEntity, - character: CharacterEntity, + pub character: CharacterEntity, session: Session, //guildcard: GuildCard, inventory: items::ActiveInventory, @@ -337,93 +338,6 @@ impl ShipServerState { } } - fn send_player_to_lobby(&mut self, id: ClientId, _pkt: &CharData) -> Result, ShipError> { - let lobby = self.client_location.add_client_to_next_available_lobby(id, LobbyId(0)).map_err(|_| ShipError::TooManyClients)?; - let clients = self.client_location.get_clients_in_lobby(lobby).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; - let playerinfo = clients.iter() - .map(|room_client| { - let client = self.clients.get(&room_client.client).ok_or(ShipError::ClientNotFound(id)).unwrap(); - let (level, stats) = self.level_table.get_stats_from_exp(client.character.char_class, client.character.exp); - let c = CharacterBytesBuilder::new() - .character(&client.character) - .stats(&stats) - .level(level - 1) - .build(); - PlayerInfo { - header: PlayerHeader { - tag: 0x100, - guildcard: client.user.id.0, - _unknown1: [0; 5], - client_id: room_client.local_client.id() as u32, - name: c.name, - _unknown2: 2, - }, - inventory: character::Inventory { - item_count: 0, - hp_mats_used: 0, - tp_mats_used: 0, - language: 0, - items: [character::InventoryItem::default(); 30], - }, - character: c, - } - }); - let area_client = self.client_location.get_local_client(id).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; - let leader = self.client_location.get_lobby_leader(lobby).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; - - let join_lobby = JoinLobby { - client: area_client.local_client.id(), - leader: leader.local_client.id(), - one: 1, - lobby: lobby.id(), - block: 1, - event: 0, - padding: 0, - playerinfo: playerinfo.collect(), - }; - - let client = self.clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; - let (level, stats) = self.level_table.get_stats_from_exp(client.character.char_class, client.character.exp); - let c = CharacterBytesBuilder::new() - .character(&client.character) - .stats(&stats) - .level(level - 1) - .build(); - let addto = AddToLobby { - flag: 1, - client: area_client.local_client.id(), - leader: leader.local_client.id(), - one: 1, - lobby: lobby.id(), - block: 1, - event: 0, - padding: 0, - playerinfo: PlayerInfo { - header: PlayerHeader { - tag: 0x100, - guildcard: client.user.id.0, - _unknown1: [0; 5], - client_id: area_client.local_client.id() as u32, - name: c.name, - _unknown2: 2, - }, - inventory: character::Inventory { - item_count: 0, - hp_mats_used: 0, - tp_mats_used: 0, - language: 0, - items: [character::InventoryItem::default(); 30], - }, - character: c, - }, - }; - - let neighbors = self.client_location.get_client_neighbors(id).unwrap(); - Ok(vec![(id, SendShipPacket::JoinLobby(join_lobby))] - .into_iter() - .chain(neighbors.into_iter() - .map(|c| (c.client, SendShipPacket::AddToLobby(addto.clone())))).collect()) - } fn done_bursting(&mut self, id: ClientId) -> Box + Send> { let area = self.client_location.get_area(id).unwrap(); @@ -694,7 +608,7 @@ impl ServerState for ShipServerState { } }, RecvShipPacket::CharData(chardata) => { - Box::new(self.send_player_to_lobby(id, chardata)?.into_iter()) + Box::new(handler::lobby::send_player_to_lobby(id, chardata, &mut self.client_location, &self.clients, &self.level_table)?.into_iter()) }, RecvShipPacket::Message(msg) => { self.message(id, msg) From 4a01beb9e8e053815267bf610e857e3fbbb6ac7d Mon Sep 17 00:00:00 2001 From: jake Date: Tue, 21 Apr 2020 22:18:57 -0600 Subject: [PATCH 02/11] move validate_login --- src/ship/packet/handler/auth.rs | 40 ++++++++++++++++++++++++++++++++ src/ship/packet/handler/lobby.rs | 3 ++- src/ship/packet/handler/mod.rs | 1 + src/ship/ship.rs | 29 ++--------------------- 4 files changed, 45 insertions(+), 28 deletions(-) create mode 100644 src/ship/packet/handler/auth.rs diff --git a/src/ship/packet/handler/auth.rs b/src/ship/packet/handler/auth.rs new file mode 100644 index 0000000..0268ba4 --- /dev/null +++ b/src/ship/packet/handler/auth.rs @@ -0,0 +1,40 @@ +use std::collections::HashMap; +use libpso::packet::login::{Login, LoginResponse, AccountStatus, Session}; +use libpso::packet::ship::*; +use crate::common::serverstate::ClientId; +use crate::ship::ship::{SendShipPacket, ShipError, ClientState}; +use crate::login::login::get_login_status; +use crate::entity::gateway::EntityGateway; +use crate::ship::items::ActiveItemDatabase; + +pub fn validate_login(id: ClientId, + pkt: &Login, + entity_gateway: &mut EG, + clients: &mut HashMap, + item_database: &mut ActiveItemDatabase, + ship_name: &String) + -> Result, ShipError> { + Ok(match get_login_status(entity_gateway, pkt) { + Ok(user) => { + let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new()); + response.guildcard = user.id.0 as u32; + response.team_id = user.team_id.map_or(31, |ti| ti) as u32; + let characters = entity_gateway.get_characters_by_user(&user); + let character = characters + .get(pkt.session.character_slot as usize) + .ok_or(ShipError::InvalidSlot(id, pkt.session.character_slot as u32))?.as_ref() + .ok_or(ShipError::NoCharacterInSlot(id, pkt.session.character_slot as u32))? + .clone(); + let settings = entity_gateway.get_user_settings_by_user(&user) + .ok_or(ShipError::ClientNotFound(id))?; + let inventory = item_database.get_character_inventory(entity_gateway, &character); + + clients.insert(id, ClientState::new(user, settings, character, inventory, pkt.session)); + vec![SendShipPacket::LoginResponse(response), SendShipPacket::ShipBlockList(ShipBlockList::new(&&ship_name, 3))] + }, + Err(err) => { + vec![SendShipPacket::LoginResponse(LoginResponse::by_status(err, Session::new()))] + } + }) +} + diff --git a/src/ship/packet/handler/lobby.rs b/src/ship/packet/handler/lobby.rs index 9efe3bd..2972cc3 100644 --- a/src/ship/packet/handler/lobby.rs +++ b/src/ship/packet/handler/lobby.rs @@ -12,7 +12,8 @@ pub fn send_player_to_lobby(id: ClientId, _pkt: &CharData, client_location: &mut ClientLocation, clients: &HashMap, - level_table: &CharacterLevelTable) -> Result, ShipError> { + level_table: &CharacterLevelTable) + -> Result, ShipError> { let lobby = client_location.add_client_to_next_available_lobby(id, LobbyId(0)).map_err(|_| ShipError::TooManyClients)?; let lobby_clients = client_location.get_clients_in_lobby(lobby).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; let playerinfo = lobby_clients.iter() diff --git a/src/ship/packet/handler/mod.rs b/src/ship/packet/handler/mod.rs index 36bd53c..337c58f 100644 --- a/src/ship/packet/handler/mod.rs +++ b/src/ship/packet/handler/mod.rs @@ -1 +1,2 @@ +pub mod auth; pub mod lobby; diff --git a/src/ship/ship.rs b/src/ship/ship.rs index 709805f..b13ec3a 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -20,7 +20,6 @@ use crate::entity::gateway::EntityGateway; use crate::entity::account::{UserAccountEntity, UserSettingsEntity, USERFLAG_NEWCHAR, USERFLAG_DRESSINGROOM}; use crate::entity::character::CharacterEntity; use crate::entity::item::{ItemLocation, ItemEntity}; -use crate::login::login::get_login_status; use crate::ship::location::{ClientLocation, LobbyId, RoomId, RoomLobby, MAX_ROOMS}; use crate::ship::character::{CharacterBytesBuilder, FullCharacterBytesBuilder}; use crate::ship::items; @@ -146,7 +145,7 @@ pub struct ClientState { } impl ClientState { - fn new(user: UserAccountEntity, settings: UserSettingsEntity, character: CharacterEntity, inventory: items::ActiveInventory, /*bank: Bank,*/ session: Session) -> ClientState { + pub fn new(user: UserAccountEntity, settings: UserSettingsEntity, character: CharacterEntity, inventory: items::ActiveInventory, /*bank: Bank,*/ session: Session) -> ClientState { ClientState { user: user, settings: settings, @@ -183,30 +182,6 @@ impl ShipServerState { } } - fn validate_login(&mut self, id: ClientId, pkt: &Login) -> Result, ShipError> { - Ok(match get_login_status(&self.entity_gateway, pkt) { - Ok(user) => { - let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new()); - response.guildcard = user.id.0 as u32; - response.team_id = user.team_id.map_or(31, |ti| ti) as u32; - let characters = self.entity_gateway.get_characters_by_user(&user); - let character = characters - .get(pkt.session.character_slot as usize) - .ok_or(ShipError::InvalidSlot(id, pkt.session.character_slot as u32))?.as_ref() - .ok_or(ShipError::NoCharacterInSlot(id, pkt.session.character_slot as u32))? - .clone(); - let settings = self.entity_gateway.get_user_settings_by_user(&user) - .ok_or(ShipError::ClientNotFound(id))?; - let inventory = self.item_database.get_character_inventory(&mut self.entity_gateway, &character); - - self.clients.insert(id, ClientState::new(user, settings, character, inventory, pkt.session)); - vec![SendShipPacket::LoginResponse(response), SendShipPacket::ShipBlockList(ShipBlockList::new(&self.name, 3))] - }, - Err(err) => { - vec![SendShipPacket::LoginResponse(LoginResponse::by_status(err, Session::new()))] - } - }) - } fn block_selected(&mut self, id: ClientId, pkt: &MenuSelect) -> Result, ShipError> { let client = self.clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; @@ -598,7 +573,7 @@ impl ServerState for ShipServerState { -> Result + Send>, ShipError> { Ok(match pkt { RecvShipPacket::Login(login) => { - Box::new(self.validate_login(id, login)?.into_iter().map(move |pkt| (id, pkt))) + Box::new(handler::auth::validate_login(id, login, &mut self.entity_gateway, &mut self.clients, &mut self.item_database, &self.name)?.into_iter().map(move |pkt| (id, pkt))) }, RecvShipPacket::MenuSelect(menuselect) => { match menuselect.menu { From f38e3357f46a31b691c28ccb1340a5ecd0f1463a Mon Sep 17 00:00:00 2001 From: jake Date: Tue, 21 Apr 2020 23:15:11 -0600 Subject: [PATCH 03/11] move room packet handlers to own file --- src/ship/packet/handler/mod.rs | 1 + src/ship/packet/handler/room.rs | 253 ++++++++++++++++++++++++++++++++ src/ship/ship.rs | 235 +---------------------------- 3 files changed, 262 insertions(+), 227 deletions(-) create mode 100644 src/ship/packet/handler/room.rs diff --git a/src/ship/packet/handler/mod.rs b/src/ship/packet/handler/mod.rs index 337c58f..df41e32 100644 --- a/src/ship/packet/handler/mod.rs +++ b/src/ship/packet/handler/mod.rs @@ -1,2 +1,3 @@ pub mod auth; pub mod lobby; +pub mod room; diff --git a/src/ship/packet/handler/room.rs b/src/ship/packet/handler/room.rs new file mode 100644 index 0000000..3553dda --- /dev/null +++ b/src/ship/packet/handler/room.rs @@ -0,0 +1,253 @@ +use std::collections::HashMap; +use libpso::packet::ship::*; +use crate::common::serverstate::ClientId; +use crate::common::leveltable::CharacterLevelTable; +use crate::ship::ship::{SendShipPacket, ShipError, ClientState, Rooms}; +use crate::ship::character::{CharacterBytesBuilder, FullCharacterBytesBuilder}; +use crate::ship::location::{ClientLocation, LobbyId, RoomId, RoomLobby, MAX_ROOMS}; +use libpso::character::character; +use crate::ship::room; + +pub fn create_room(id: ClientId, + create_room: &CreateRoom, + client_location: &mut ClientLocation, + clients: &mut HashMap, + rooms: &mut Rooms) + -> Box + Send> { + let area = client_location.get_area(id).unwrap(); + let area_client = client_location.get_local_client(id).unwrap(); + let lobby_neighbors = client_location.get_client_neighbors(id).unwrap(); + let room_id = client_location.create_new_room(id).unwrap(); + + let client = clients.get_mut(&id).unwrap();//.ok_or(ShipError::ClientNotFound(id)).unwrap(); + let mut room = room::RoomState::from_create_room(create_room, client.character.section_id).unwrap(); + room.bursting = true; + + let players = [PlayerHeader { + tag: 0x10000, + guildcard: client.user.id.0, + _unknown1: [0; 5], + client_id: 0, + name: libpso::utf8_to_utf16_array!(client.character.name, 16), + _unknown2: 2, + }, PlayerHeader::default(), PlayerHeader::default(), PlayerHeader::default()]; + + let join_room = JoinRoom { + flag: 1, + maps: room.maps.map_headers(), + players: players, + client: 0, + leader: 0, + one: 1, + difficulty: create_room.difficulty, + battle: create_room.battle, + event: 0, + section: 0, // TODO + challenge: create_room.challenge, + random_seed: 23, // TODO + episode: create_room.episode, + one2: 1, + single_player: create_room.single_player, + unknown: 0, + }; + rooms[room_id.0] = Some(room); + + let leader = client_location.get_area_leader(area); + let result = vec![(id, SendShipPacket::JoinRoom(join_room))].into_iter(); + match leader { + Ok(leader) => Box::new(result.chain(lobby_neighbors + .into_iter() + .map(move |c| { + (c.client, SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id()))) + }))), + Err(_) => Box::new(result) + } +} + +pub fn room_name_request(id: ClientId, + client_location: &ClientLocation, + rooms: &Rooms) + -> Box + Send> { + let area = client_location.get_area(id).unwrap(); + match area { + RoomLobby::Room(room) => Box::new(vec![(id, SendShipPacket::RoomNameResponse(RoomNameResponse {name: rooms[room.0].as_ref().unwrap().name.clone()}))].into_iter()), + RoomLobby::Lobby(_) => panic!() + } +} + +pub fn join_room(id: ClientId, + pkt: &MenuSelect, + client_location: &mut ClientLocation, + clients: &mut HashMap, + level_table: &CharacterLevelTable, + rooms: &mut Rooms) + -> Result, ShipError> { + let original_area = client_location.get_area(id).unwrap(); + let original_neighbors = client_location.get_client_neighbors(id).unwrap(); + let room = rooms.get(pkt.item as usize) + .ok_or_else(|| ShipError::InvalidRoom(pkt.item))?.as_ref() + .ok_or_else(|| ShipError::InvalidRoom(pkt.item))?; + if room.bursting { + return Ok(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("player is bursting\nplease wait".into())))]) + } + let room_id = RoomId(pkt.item as usize); + let original_room_clients = client_location.get_clients_in_room(room_id).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; + client_location.add_client_to_room(id, room_id).unwrap(); // TODO: show room full error or whatever + + let all_clients = client_location.get_clients_in_room(room_id).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; + let player_headers = all_clients.iter() + .enumerate() + .fold([PlayerHeader::default(); 4], |mut acc, (i, c)| { + let header_client = clients.get(&c.client).ok_or(ShipError::ClientNotFound(id)).unwrap(); + acc[i] = PlayerHeader { + tag: 0x100, + guildcard: header_client.user.id.0, + _unknown1: [0,0,0, c.local_client.id() as u32, 0], + client_id: 0, + name: libpso::utf8_to_utf16_array!(header_client.character.name, 16), + _unknown2: 2, + }; + acc + }); + + let area_client = client_location.get_local_client(id).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; + let leader = client_location.get_room_leader(room_id).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; + + let join_room = JoinRoom { + flag: all_clients.len() as u32, + maps: room.map_headers(), + players: player_headers, + client: area_client.local_client.id(), + leader: leader.local_client.id(), + one: 1, + difficulty: room.mode.difficulty().into(), + battle: matches!(room.mode, room::RoomMode::Battle {..}) as u8, + event: 0, + section: room.section_id.into(), + challenge: matches!(room.mode, room::RoomMode::Challenge {..}) as u8, + random_seed: room.random_seed, + episode: room.mode.episode().into(), + one2: 1, + single_player: 0, // TODO + unknown: 0, + }; + + let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; + let (level, stats) = level_table.get_stats_from_exp(client.character.char_class, client.character.exp); + let c = CharacterBytesBuilder::new() + .character(&client.character) + .stats(&stats) + .level(level - 1) + .build(); + let add_to = AddToRoom { + flag: 0x10000, + client: area_client.local_client.id(), + leader: leader.local_client.id(), + one: 0, // TODO: ?????????? + lobby: 0xff, + block: 0, + event: 0, + padding: 1, + playerinfo: PlayerInfo { + header: PlayerHeader { + tag: 0x10000, + guildcard: client.user.id.0, + _unknown1: [0; 5], + client_id: area_client.local_client.id() as u32, + name: libpso::utf8_to_utf16_array!(client.character.name, 16), + _unknown2: 2, + }, + inventory: character::Inventory { + item_count: 0, + hp_mats_used: 0, + tp_mats_used: 0, + language: 0, + items: [character::InventoryItem::default(); 30], // TOOD: this should be something + }, + character: c, + }, + }; + + let result = vec![(id, SendShipPacket::JoinRoom(join_room))] + .into_iter() + .chain(original_room_clients.clone().into_iter() + .map(|c| (c.client, SendShipPacket::AddToRoom(add_to.clone()))) + ); + + let room = rooms.get_mut(room_id.0).unwrap().as_mut().unwrap(); + room.bursting = true; + if let Ok(leader) = client_location.get_area_leader(original_area) { + let leave_lobby = SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id())); + Ok(result.chain(original_neighbors.into_iter() + .map(|c| (c.client, leave_lobby.clone()))).collect()) + } + else { + Ok(result.collect()) + } +} + +pub fn done_bursting(id: ClientId, + client_location: &ClientLocation, + rooms: &mut Rooms) + -> Box + Send> { + let area = client_location.get_area(id).unwrap(); + if let RoomLobby::Room(room_id) = area { + let room = rooms.get_mut(room_id.0).unwrap().as_mut().unwrap(); + room.bursting = false; + } + Box::new(client_location.get_client_neighbors(id).unwrap().into_iter() + .map(move |client| { + vec![ + (client.client, SendShipPacket::BurstDone72(BurstDone72::new())), + ] + }).flatten()) +} + + +pub fn request_room_list(id: ClientId, + client_location: &ClientLocation, + rooms: &Rooms) + -> Box + Send> { + let active_room_list = rooms.iter() + .enumerate() + .filter_map(|(i, r)| { + r.as_ref().map(|room| { + RoomList { + menu_id: ROOM_MENU_ID, + item_id: i as u32, + difficulty: room.get_difficulty_for_room_list(), + players: client_location.get_clients_in_room(RoomId(i)).unwrap().len() as u8, + name: libpso::utf8_to_utf16_array!(room.name, 16), + episode: room.get_episode_for_room_list(), + flags: room.get_flags_for_room_list(), + } + }) + }); + let baseroom: RoomList = RoomList { + menu_id: ROOM_MENU_ID, + item_id: ROOM_MENU_ID, + difficulty: 0x00, + players: 0x00, + name: libpso::utf8_to_utf16_array!("Room list menu", 16), + episode: 0, + flags: 0, + }; + + Box::new(vec![(id, SendShipPacket::RoomListResponse(RoomListResponse { + baseroom, + rooms: active_room_list.collect() + }))].into_iter()) +} + +pub fn cool_62(id: ClientId, + cool_62: &Like62ButCooler, + client_location: &ClientLocation) + -> Box + Send> { + let target = cool_62.flag as u8; + let cool_62 = cool_62.clone(); + Box::new(client_location.get_client_neighbors(id).unwrap().into_iter() + .filter(move |client| client.local_client.id() == target) + .map(move |client| { + (client.client, SendShipPacket::Like62ButCooler(cool_62.clone())) + })) +} diff --git a/src/ship/ship.rs b/src/ship/ship.rs index b13ec3a..dc47b89 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -27,6 +27,7 @@ use crate::ship::room; use crate::ship::packet::handler; pub const SHIP_PORT: u16 = 23423; +pub type Rooms = [Option; MAX_ROOMS]; #[derive(Debug)] pub enum ShipError { @@ -165,7 +166,7 @@ pub struct ShipServerState { client_location: ClientLocation, level_table: CharacterLevelTable, name: String, - rooms: [Option; MAX_ROOMS], + rooms: Rooms, item_database: items::ActiveItemDatabase, } @@ -182,7 +183,6 @@ impl ShipServerState { } } - fn block_selected(&mut self, id: ClientId, pkt: &MenuSelect) -> Result, ShipError> { let client = self.clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; client.block = pkt.item as u32; @@ -208,126 +208,9 @@ impl ShipServerState { ]) } - fn join_room(&mut self, id: ClientId, pkt: &MenuSelect) -> Result, ShipError> { - let original_area = self.client_location.get_area(id).unwrap(); - let original_neighbors = self.client_location.get_client_neighbors(id).unwrap(); - let room = self.rooms.get(pkt.item as usize) - .ok_or_else(|| ShipError::InvalidRoom(pkt.item))?.as_ref() - .ok_or_else(|| ShipError::InvalidRoom(pkt.item))?; - if room.bursting { - return Ok(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("player is bursting\nplease wait".into())))]) - } - let room_id = RoomId(pkt.item as usize); - let original_room_clients = self.client_location.get_clients_in_room(room_id).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; - self.client_location.add_client_to_room(id, room_id).unwrap(); // TODO: show room full error or whatever - - let all_clients = self.client_location.get_clients_in_room(room_id).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; - let player_headers = all_clients.iter() - .enumerate() - .fold([PlayerHeader::default(); 4], |mut acc, (i, c)| { - let header_client = self.clients.get(&c.client).ok_or(ShipError::ClientNotFound(id)).unwrap(); - acc[i] = PlayerHeader { - tag: 0x100, - guildcard: header_client.user.id.0, - _unknown1: [0,0,0, c.local_client.id() as u32, 0], - client_id: 0, - name: libpso::utf8_to_utf16_array!(header_client.character.name, 16), - _unknown2: 2, - }; - acc - }); - - let area_client = self.client_location.get_local_client(id).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; - let leader = self.client_location.get_room_leader(room_id).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; - - let join_room = JoinRoom { - flag: all_clients.len() as u32, - maps: room.map_headers(), - players: player_headers, - client: area_client.local_client.id(), - leader: leader.local_client.id(), - one: 1, - difficulty: room.mode.difficulty().into(), - battle: matches!(room.mode, room::RoomMode::Battle {..}) as u8, - event: 0, - section: room.section_id.into(), - challenge: matches!(room.mode, room::RoomMode::Challenge {..}) as u8, - random_seed: room.random_seed, - episode: room.mode.episode().into(), - one2: 1, - single_player: 0, // TODO - unknown: 0, - }; - let client = self.clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; - let (level, stats) = self.level_table.get_stats_from_exp(client.character.char_class, client.character.exp); - let c = CharacterBytesBuilder::new() - .character(&client.character) - .stats(&stats) - .level(level - 1) - .build(); - let add_to = AddToRoom { - flag: 0x10000, - client: area_client.local_client.id(), - leader: leader.local_client.id(), - one: 0, // TODO: ?????????? - lobby: 0xff, - block: 0, - event: 0, - padding: 1, - playerinfo: PlayerInfo { - header: PlayerHeader { - tag: 0x10000, - guildcard: client.user.id.0, - _unknown1: [0; 5], - client_id: area_client.local_client.id() as u32, - name: libpso::utf8_to_utf16_array!(client.character.name, 16), - _unknown2: 2, - }, - inventory: character::Inventory { - item_count: 0, - hp_mats_used: 0, - tp_mats_used: 0, - language: 0, - items: [character::InventoryItem::default(); 30], // TOOD: this should be something - }, - character: c, - }, - }; - - let result = vec![(id, SendShipPacket::JoinRoom(join_room))] - .into_iter() - .chain(original_room_clients.clone().into_iter() - .map(|c| (c.client, SendShipPacket::AddToRoom(add_to.clone()))) - ); - - let room = self.rooms.get_mut(room_id.0).unwrap().as_mut().unwrap(); - room.bursting = true; - if let Ok(leader) = self.client_location.get_area_leader(original_area) { - let leave_lobby = SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id())); - Ok(result.chain(original_neighbors.into_iter() - .map(|c| (c.client, leave_lobby.clone()))).collect()) - } - else { - Ok(result.collect()) - } - } - fn done_bursting(&mut self, id: ClientId) -> Box + Send> { - let area = self.client_location.get_area(id).unwrap(); - if let RoomLobby::Room(room_id) = area { - let room = self.rooms.get_mut(room_id.0).unwrap().as_mut().unwrap(); - room.bursting = false; - } - Box::new(self.client_location.get_client_neighbors(id).unwrap().into_iter() - .map(move |client| { - vec![ - (client.client, SendShipPacket::BurstDone72(BurstDone72::new())), - ] - }).flatten()) - } - fn message(&mut self, id: ClientId, msg: &Message) -> Box + Send> { match &msg.msg { GameMessage::RequestExp(killmonster) => { @@ -419,65 +302,6 @@ impl ShipServerState { }))) } - fn create_room(&mut self, id: ClientId, create_room: &CreateRoom) -> Box + Send> { - let area = self.client_location.get_area(id).unwrap(); - let area_client = self.client_location.get_local_client(id).unwrap(); - let lobby_neighbors = self.client_location.get_client_neighbors(id).unwrap(); - let room_id = self.client_location.create_new_room(id).unwrap(); - - let client = self.clients.get_mut(&id).unwrap();//.ok_or(ShipError::ClientNotFound(id)).unwrap(); - let mut room = room::RoomState::from_create_room(create_room, client.character.section_id).unwrap(); - room.bursting = true; - - let players = [PlayerHeader { - tag: 0x10000, - guildcard: client.user.id.0, - _unknown1: [0; 5], - client_id: 0, - name: libpso::utf8_to_utf16_array!(client.character.name, 16), - _unknown2: 2, - }, PlayerHeader::default(), PlayerHeader::default(), PlayerHeader::default()]; - - let join_room = JoinRoom { - flag: 1, - maps: room.maps.map_headers(), - players: players, - client: 0, - leader: 0, - one: 1, - difficulty: create_room.difficulty, - battle: create_room.battle, - event: 0, - section: 0, // TODO - challenge: create_room.challenge, - random_seed: 23, // TODO - episode: create_room.episode, - one2: 1, - single_player: create_room.single_player, - unknown: 0, - }; - self.rooms[room_id.0] = Some(room); - - let leader = self.client_location.get_area_leader(area); - let result = vec![(id, SendShipPacket::JoinRoom(join_room))].into_iter(); - match leader { - Ok(leader) => Box::new(result.chain(lobby_neighbors - .into_iter() - .map(move |c| { - (c.client, SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id()))) - }))), - Err(_) => Box::new(result) - } - } - - fn room_name_request(&mut self, id: ClientId) -> Box + Send> { - let area = self.client_location.get_area(id).unwrap(); - match area { - RoomLobby::Room(room) => Box::new(vec![(id, SendShipPacket::RoomNameResponse(RoomNameResponse {name: self.rooms[room.0].as_ref().unwrap().name.clone()}))].into_iter()), - RoomLobby::Lobby(_) => panic!() - } - } - fn update_config(&mut self, id: ClientId, update_config: &UpdateConfig) -> Box + Send> { let client = self.clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); client.character.config.update(update_config); @@ -507,47 +331,6 @@ impl ShipServerState { Box::new(None.into_iter()) } - fn request_room_list(&mut self, id: ClientId) -> Box + Send> { - let active_room_list = self.rooms.iter() - .enumerate() - .filter_map(|(i, r)| { - r.as_ref().map(|room| { - RoomList { - menu_id: ROOM_MENU_ID, - item_id: i as u32, - difficulty: room.get_difficulty_for_room_list(), - players: self.client_location.get_clients_in_room(RoomId(i)).unwrap().len() as u8, - name: libpso::utf8_to_utf16_array!(room.name, 16), - episode: room.get_episode_for_room_list(), - flags: room.get_flags_for_room_list(), - } - }) - }); - let baseroom: RoomList = RoomList { - menu_id: ROOM_MENU_ID, - item_id: ROOM_MENU_ID, - difficulty: 0x00, - players: 0x00, - name: libpso::utf8_to_utf16_array!("Room list menu", 16), - episode: 0, - flags: 0, - }; - - Box::new(vec![(id, SendShipPacket::RoomListResponse(RoomListResponse { - baseroom, - rooms: active_room_list.collect() - }))].into_iter()) - } - - fn cool_62(&mut self, id: ClientId, cool_62: &Like62ButCooler) -> Box + Send> { - let target = cool_62.flag as u8; - let cool_62 = cool_62.clone(); - Box::new(self.client_location.get_client_neighbors(id).unwrap().into_iter() - .filter(move |client| client.local_client.id() == target) - .map(move |client| { - (client.client, SendShipPacket::Like62ButCooler(cool_62.clone())) - })) - } } impl ServerState for ShipServerState { @@ -578,7 +361,7 @@ impl ServerState for ShipServerState { RecvShipPacket::MenuSelect(menuselect) => { match menuselect.menu { BLOCK_MENU_ID => Box::new(self.block_selected(id, menuselect)?.into_iter().map(move |pkt| (id, pkt))), - ROOM_MENU_ID => Box::new(self.join_room(id, menuselect)?.into_iter()), + ROOM_MENU_ID => Box::new(handler::room::join_room(id, menuselect, &mut self.client_location, &mut self.clients, &self.level_table, &mut self.rooms)?.into_iter()), _ => unreachable!(), } }, @@ -596,10 +379,10 @@ impl ServerState for ShipServerState { Box::new(self.player_chat(id, msg)?.into_iter()) }, RecvShipPacket::CreateRoom(create_room) => { - self.create_room(id, create_room) + handler::room::create_room(id, create_room, &mut self.client_location, &mut self.clients, &mut self.rooms) }, RecvShipPacket::RoomNameRequest(_req) => { - self.room_name_request(id) + handler::room::room_name_request(id, &self.client_location, &self.rooms) }, RecvShipPacket::UpdateConfig(pkt) => { self.update_config(id, pkt) @@ -608,23 +391,21 @@ impl ServerState for ShipServerState { RecvShipPacket::ViewInfoboardRequest(pkt) => { self.request_infoboard(id, pkt) }, - RecvShipPacket::WriteInfoboard(pkt) => { self.write_infoboard(id, pkt) }, - RecvShipPacket::RoomListRequest(_req) => { - self.request_room_list(id) + handler::room::request_room_list(id, &self.client_location, &self.rooms) }, RecvShipPacket::Like62ButCooler(cool62) => { - self.cool_62(id, cool62) + handler::room::cool_62(id, cool62, &self.client_location) }, RecvShipPacket::ClientCharacterData(_) => { // TOOD: validate this in some way? Box::new(None.into_iter()) }, RecvShipPacket::DoneBursting(_) => { - self.done_bursting(id) + handler::room::done_bursting(id, &self.client_location, &mut self.rooms) } }) } From 90d0af87a40bfbcc7f435a501287ec3031f48fb4 Mon Sep 17 00:00:00 2001 From: jake Date: Tue, 21 Apr 2020 23:40:44 -0600 Subject: [PATCH 04/11] move chat functionality --- src/ship/packet/handler/communication.rs | 52 ++++++++++++++++++++++++ src/ship/packet/handler/mod.rs | 1 + src/ship/ship.rs | 49 ++-------------------- 3 files changed, 56 insertions(+), 46 deletions(-) create mode 100644 src/ship/packet/handler/communication.rs diff --git a/src/ship/packet/handler/communication.rs b/src/ship/packet/handler/communication.rs new file mode 100644 index 0000000..17916e4 --- /dev/null +++ b/src/ship/packet/handler/communication.rs @@ -0,0 +1,52 @@ +use std::collections::HashMap; +use libpso::packet::ship::*; +use crate::common::serverstate::ClientId; +use crate::common::leveltable::CharacterLevelTable; +use crate::ship::ship::{SendShipPacket, ShipError, ClientState}; +use crate::ship::character::{CharacterBytesBuilder, FullCharacterBytesBuilder}; +use crate::ship::location::{ClientLocation, LobbyId, RoomId, RoomLobby, MAX_ROOMS}; +use libpso::character::character; +use crate::entity::gateway::EntityGateway; + +pub fn player_chat(id: ClientId, + msg: &PlayerChat, + client_location: &ClientLocation, + clients: &HashMap) -> Result + Send>, ShipError> { + let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; + let cmsg = PlayerChat::new(client.user.id.0, msg.message.clone()); + + Ok(Box::new(client_location.get_all_clients_by_client(id).unwrap().into_iter() + .map(move |client| { + (client.client, SendShipPacket::PlayerChat(cmsg.clone())) + }))) +} + +pub fn request_infoboard(id: ClientId, + request_infoboard: &ViewInfoboardRequest, + client_location: &ClientLocation, + clients: &HashMap) + -> Box + Send> { + let area_clients = client_location.get_client_neighbors(id).unwrap(); + let r = area_clients.iter() + .filter_map(|c| { + clients.get(&c.client) + }) + .map(|client| { + InfoboardResponse { + name: libpso::utf8_to_utf16_array!(client.character.name, 16), + message: client.character.info_board.as_bytes(), + } + }).collect(); + Box::new(vec![(id, SendShipPacket::ViewInfoboardResponse(ViewInfoboardResponse {response: r}))].into_iter()) +} + +pub fn write_infoboard(id: ClientId, + new_infoboard: &WriteInfoboard, + clients: &mut HashMap, + entity_gateway: &mut EG) + -> Box + Send> { + let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); + client.character.info_board.update_infoboard(new_infoboard); + entity_gateway.save_character(&client.character); + Box::new(None.into_iter()) +} diff --git a/src/ship/packet/handler/mod.rs b/src/ship/packet/handler/mod.rs index df41e32..0928362 100644 --- a/src/ship/packet/handler/mod.rs +++ b/src/ship/packet/handler/mod.rs @@ -1,3 +1,4 @@ pub mod auth; +pub mod communication; pub mod lobby; pub mod room; diff --git a/src/ship/ship.rs b/src/ship/ship.rs index dc47b89..02f6926 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -208,9 +208,6 @@ impl ShipServerState { ]) } - - - fn message(&mut self, id: ClientId, msg: &Message) -> Box + Send> { match &msg.msg { GameMessage::RequestExp(killmonster) => { @@ -232,11 +229,6 @@ impl ShipServerState { })) } - /*fn generate_item_drop(&mut self, id: ClientId, monster: MonsterType) -> Option { - let room = self.rooms[self.client_location.get_area_by_user(id).index]; - let item_drop = room.drop_table.get_drop() - }*/ - fn direct_message(&mut self, id: ClientId, msg: &DirectMessage) -> Box + Send> { let cmsg = msg.clone(); let client = self.clients.get_mut(&id).unwrap(); @@ -292,45 +284,12 @@ impl ShipServerState { } } - fn player_chat(&mut self, id: ClientId, msg: &PlayerChat) -> Result + Send>, ShipError> { - let client = self.clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; - let cmsg = PlayerChat::new(client.user.id.0, msg.message.clone()); - - Ok(Box::new(self.client_location.get_all_clients_by_client(id).unwrap().into_iter() - .map(move |client| { - (client.client, SendShipPacket::PlayerChat(cmsg.clone())) - }))) - } - fn update_config(&mut self, id: ClientId, update_config: &UpdateConfig) -> Box + Send> { let client = self.clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); client.character.config.update(update_config); self.entity_gateway.save_character(&client.character); Box::new(None.into_iter()) } - - fn request_infoboard(&mut self, id: ClientId, request_infoboard: &ViewInfoboardRequest) -> Box + Send> { - let clients = self.client_location.get_client_neighbors(id).unwrap(); - let r = clients.iter() - .filter_map(|c| { - self.clients.get(&c.client) - }) - .map(|client| { - InfoboardResponse { - name: libpso::utf8_to_utf16_array!(client.character.name, 16), - message: client.character.info_board.as_bytes(), - } - }).collect(); - Box::new(vec![(id, SendShipPacket::ViewInfoboardResponse(ViewInfoboardResponse {response: r}))].into_iter()) - } - - fn write_infoboard(&mut self, id: ClientId, new_infoboard: &WriteInfoboard) -> Box + Send> { - let client = self.clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); - client.character.info_board.update_infoboard(new_infoboard); - self.entity_gateway.save_character(&client.character); - Box::new(None.into_iter()) - } - } impl ServerState for ShipServerState { @@ -374,9 +333,8 @@ impl ServerState for ShipServerState { RecvShipPacket::DirectMessage(msg) => { self.direct_message(id, msg) }, - RecvShipPacket::PlayerChat(msg) => { - Box::new(self.player_chat(id, msg)?.into_iter()) + Box::new(handler::communication::player_chat(id, msg, &self.client_location, &self.clients)?.into_iter()) }, RecvShipPacket::CreateRoom(create_room) => { handler::room::create_room(id, create_room, &mut self.client_location, &mut self.clients, &mut self.rooms) @@ -387,12 +345,11 @@ impl ServerState for ShipServerState { RecvShipPacket::UpdateConfig(pkt) => { self.update_config(id, pkt) }, - RecvShipPacket::ViewInfoboardRequest(pkt) => { - self.request_infoboard(id, pkt) + handler::communication::request_infoboard(id, pkt, &self.client_location, &self.clients) }, RecvShipPacket::WriteInfoboard(pkt) => { - self.write_infoboard(id, pkt) + handler::communication::write_infoboard(id, pkt, &mut self.clients, &mut self.entity_gateway) }, RecvShipPacket::RoomListRequest(_req) => { handler::room::request_room_list(id, &self.client_location, &self.rooms) From 832a53821da18ebbe0476c31240ce4be199c4634 Mon Sep 17 00:00:00 2001 From: jake Date: Tue, 21 Apr 2020 23:45:40 -0600 Subject: [PATCH 05/11] move settings --- src/ship/packet/handler/mod.rs | 1 + src/ship/packet/handler/settings.rs | 20 ++++++++++++++++++++ src/ship/ship.rs | 9 +-------- 3 files changed, 22 insertions(+), 8 deletions(-) create mode 100644 src/ship/packet/handler/settings.rs diff --git a/src/ship/packet/handler/mod.rs b/src/ship/packet/handler/mod.rs index 0928362..b9ba696 100644 --- a/src/ship/packet/handler/mod.rs +++ b/src/ship/packet/handler/mod.rs @@ -2,3 +2,4 @@ pub mod auth; pub mod communication; pub mod lobby; pub mod room; +pub mod settings; diff --git a/src/ship/packet/handler/settings.rs b/src/ship/packet/handler/settings.rs new file mode 100644 index 0000000..096f512 --- /dev/null +++ b/src/ship/packet/handler/settings.rs @@ -0,0 +1,20 @@ +use std::collections::HashMap; +use libpso::packet::ship::*; +use crate::common::serverstate::ClientId; +use crate::common::leveltable::CharacterLevelTable; +use crate::ship::ship::{SendShipPacket, ShipError, ClientState}; +use crate::ship::character::{CharacterBytesBuilder, FullCharacterBytesBuilder}; +use crate::ship::location::{ClientLocation, LobbyId, RoomId, RoomLobby, MAX_ROOMS}; +use libpso::character::character; +use crate::entity::gateway::EntityGateway; + +pub fn update_config(id: ClientId, + update_config: &UpdateConfig, + clients: &mut HashMap, + entity_gateway: &mut EG) + -> Box + Send> { + let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); + client.character.config.update(update_config); + entity_gateway.save_character(&client.character); + Box::new(None.into_iter()) +} diff --git a/src/ship/ship.rs b/src/ship/ship.rs index 02f6926..548ef33 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -283,13 +283,6 @@ impl ShipServerState { }, } } - - fn update_config(&mut self, id: ClientId, update_config: &UpdateConfig) -> Box + Send> { - let client = self.clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); - client.character.config.update(update_config); - self.entity_gateway.save_character(&client.character); - Box::new(None.into_iter()) - } } impl ServerState for ShipServerState { @@ -343,7 +336,7 @@ impl ServerState for ShipServerState { handler::room::room_name_request(id, &self.client_location, &self.rooms) }, RecvShipPacket::UpdateConfig(pkt) => { - self.update_config(id, pkt) + handler::settings::update_config(id, pkt, &mut self.clients, &mut self.entity_gateway) }, RecvShipPacket::ViewInfoboardRequest(pkt) => { handler::communication::request_infoboard(id, pkt, &self.client_location, &self.clients) From 0b04701156cc560a4f36d3e460853dc9a49cbc00 Mon Sep 17 00:00:00 2001 From: jake Date: Wed, 22 Apr 2020 07:14:59 -0600 Subject: [PATCH 06/11] move message packet handlers --- src/ship/packet/handler/direct_message.rs | 48 +++++++++++++++ src/ship/packet/handler/message.rs | 27 +++++++++ src/ship/packet/handler/mod.rs | 2 + src/ship/ship.rs | 72 +++++------------------ 4 files changed, 91 insertions(+), 58 deletions(-) create mode 100644 src/ship/packet/handler/direct_message.rs create mode 100644 src/ship/packet/handler/message.rs diff --git a/src/ship/packet/handler/direct_message.rs b/src/ship/packet/handler/direct_message.rs new file mode 100644 index 0000000..ceb4e05 --- /dev/null +++ b/src/ship/packet/handler/direct_message.rs @@ -0,0 +1,48 @@ +use std::collections::HashMap; +use log::warn; +use libpso::packet::ship::*; +use libpso::packet::messages::*; +use crate::common::serverstate::ClientId; +use crate::common::leveltable::CharacterLevelTable; +use crate::ship::ship::{SendShipPacket, ShipError, ClientState, Rooms}; +use crate::ship::character::{CharacterBytesBuilder, FullCharacterBytesBuilder}; +use crate::ship::location::{ClientLocation, LobbyId, RoomId, RoomLobby, MAX_ROOMS}; +use libpso::character::character; +use crate::entity::gateway::EntityGateway; +use libpso::{utf8_to_array, utf8_to_utf16_array}; + +fn send_to_client(id: ClientId, target: u8, msg: DirectMessage, client_location: &ClientLocation) + -> Box + Send> { + Box::new(client_location.get_all_clients_by_client(id).unwrap().into_iter() + .filter(move |client| client.local_client.id() == target) + .map(move |client| { + (client.client, SendShipPacket::DirectMessage(msg.clone())) + })) +} + + + +pub fn guildcard_send(id: ClientId, + guildcard_send: &GuildcardSend, + target: u32, + client_location: &ClientLocation, + clients: &HashMap) + -> Box + Send> { + let client = clients.get(&id).unwrap(); + let msg = DirectMessage{ + flag: target, + msg: GameMessage::GuildcardRecv(GuildcardRecv { + client: guildcard_send.client, + target: guildcard_send.target, + guildcard: client.user.id.0, + name: utf8_to_utf16_array!(client.character.name, 0x18), + team: [0; 0x10], // TODO: teams not yet implemented + desc: utf8_to_utf16_array!(client.character.guildcard.description, 0x58), + one: 1, + language: 0, // TODO: add language flag to character + section_id: client.character.section_id.into(), + class: client.character.char_class.into(), + }), + }; + send_to_client(id, target as u8, msg, &client_location) +} diff --git a/src/ship/packet/handler/message.rs b/src/ship/packet/handler/message.rs new file mode 100644 index 0000000..a58de7c --- /dev/null +++ b/src/ship/packet/handler/message.rs @@ -0,0 +1,27 @@ +use std::collections::HashMap; +use log::warn; +use libpso::packet::ship::*; +use libpso::packet::messages::*; +use crate::common::serverstate::ClientId; +use crate::common::leveltable::CharacterLevelTable; +use crate::ship::ship::{SendShipPacket, ShipError, ClientState, Rooms}; +use crate::ship::character::{CharacterBytesBuilder, FullCharacterBytesBuilder}; +use crate::ship::location::{ClientLocation, LobbyId, RoomId, RoomLobby, MAX_ROOMS}; +use libpso::character::character; +use crate::entity::gateway::EntityGateway; + +pub fn request_exp(id: ClientId, + request_exp: &RequestExp, + client_location: &ClientLocation, + rooms: &Rooms) + -> Box + Send> { + + match client_location.get_area(id).unwrap() { + RoomLobby::Room(room) => { + let r = rooms[room.0].as_ref().unwrap(); + warn!("killed a {:?}", r.maps.enemy_by_id(request_exp.enemy_id as usize).monster); + }, + _ => {} + }; + Box::new(None.into_iter()) +} diff --git a/src/ship/packet/handler/mod.rs b/src/ship/packet/handler/mod.rs index b9ba696..2021066 100644 --- a/src/ship/packet/handler/mod.rs +++ b/src/ship/packet/handler/mod.rs @@ -1,5 +1,7 @@ pub mod auth; pub mod communication; +pub mod direct_message; pub mod lobby; +pub mod message; pub mod room; pub mod settings; diff --git a/src/ship/ship.rs b/src/ship/ship.rs index 548ef33..7f1d60a 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -210,73 +210,29 @@ impl ShipServerState { fn message(&mut self, id: ClientId, msg: &Message) -> Box + Send> { match &msg.msg { - GameMessage::RequestExp(killmonster) => { - match self.client_location.get_area(id).unwrap() { - RoomLobby::Room(room) => { - let r = self.rooms[room.0].as_ref().unwrap(); - warn!("killed a {:?}", r.maps.enemy_by_id(killmonster.enemy_id as usize).monster); - }, - _ => {} - } + GameMessage::RequestExp(request_exp) => { + handler::message::request_exp(id, request_exp, &self.client_location, &self.rooms) + }, + _ => { + let cmsg = msg.clone(); + Box::new(self.client_location.get_client_neighbors(id).unwrap().into_iter() + .map(move |client| { + (client.client, SendShipPacket::Message(cmsg.clone())) + })) }, - _ => {}, } - - let cmsg = msg.clone(); - Box::new(self.client_location.get_client_neighbors(id).unwrap().into_iter() - .map(move |client| { - (client.client, SendShipPacket::Message(cmsg.clone())) - })) } fn direct_message(&mut self, id: ClientId, msg: &DirectMessage) -> Box + Send> { - let cmsg = msg.clone(); - let client = self.clients.get_mut(&id).unwrap(); - match &cmsg.msg { + let target = msg.flag; + match &msg.msg { GameMessage::GuildcardSend(guildcard_send) => { - let out_msg = DirectMessage{ - flag: cmsg.flag, - msg: GameMessage::GuildcardRecv(GuildcardRecv { - client: guildcard_send.client, - target: guildcard_send.target, - guildcard: client.user.id.0, - name: utf8_to_utf16_array!(client.character.name, 0x18), - team: [0; 0x10], // TODO: teams not yet implemented - desc: utf8_to_utf16_array!(client.character.guildcard.description, 0x58), - one: 1, - language: 0, // TODO: add language flag to character - section_id: client.character.section_id.into(), - class: client.character.char_class.into(), - }), - }; - let msg_flag = cmsg.flag as u8; - Box::new(self.client_location.get_all_clients_by_client(id).unwrap().into_iter() - .filter(move |client| client.local_client.id() == msg_flag) - .map(move |client| { - (client.client, SendShipPacket::DirectMessage(out_msg.clone())) - })) + handler::direct_message::guildcard_send(id, guildcard_send, target, &self.client_location, &self.clients) }, - /*GameMessage::RequestItem(req_item) => { - let item = self.generate_item_drop(id); - Box::new(vec![(id, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(ItemDrop { - client: req_item.client, - target: req_item.target, - area: req_item.area, - variety: 0, - unknown: 0, - x: req_item.x, - z: req_item.z, - unknown2: 0, - item_bytes: item[0..12].try_into().unwrap(), - item_id: 0, - item_bytes2: item[12..16].try_into().unwrap(), - unknown3: 0, - }))))].into_iter()) - },*/ _ => { - let msg_flag = cmsg.flag as u8; + let cmsg = msg.clone(); Box::new(self.client_location.get_all_clients_by_client(id).unwrap().into_iter() - .filter(move |client| client.local_client.id() == msg_flag) + .filter(move |client| client.local_client.id() == target as u8) .map(move |client| { (client.client, SendShipPacket::DirectMessage(cmsg.clone())) })) From 07403fe815697ecdc4a3420adb5cfebaff14c32a Mon Sep 17 00:00:00 2001 From: jake Date: Wed, 22 Apr 2020 07:30:59 -0600 Subject: [PATCH 07/11] move block_selected --- src/ship/packet/handler/lobby.rs | 29 ++++++++++++++++++++++++++++ src/ship/ship.rs | 33 ++++---------------------------- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/src/ship/packet/handler/lobby.rs b/src/ship/packet/handler/lobby.rs index 2972cc3..9b48e12 100644 --- a/src/ship/packet/handler/lobby.rs +++ b/src/ship/packet/handler/lobby.rs @@ -7,6 +7,35 @@ use crate::ship::character::{CharacterBytesBuilder, FullCharacterBytesBuilder}; use crate::ship::location::{ClientLocation, LobbyId, RoomId, RoomLobby, MAX_ROOMS}; use libpso::character::character; +// this function needs a better home +pub fn block_selected(id: ClientId, + pkt: &MenuSelect, + clients: &mut HashMap, + level_table: &CharacterLevelTable) + -> Result, ShipError> { + let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; + client.block = pkt.item as u32; + + let (level, stats) = level_table.get_stats_from_exp(client.character.char_class, client.character.exp); + + let fc = FullCharacterBytesBuilder::new() + .character(&client.character) + .stats(&stats) + .level(level) + .inventory(&client.inventory) + .key_config(&client.settings.settings.key_config) + .joystick_config(&client.settings.settings.joystick_config) + .symbol_chat(&client.settings.settings.symbol_chats) + .tech_menu(&client.character.tech_menu.as_bytes()) + .build(); + + Ok(vec![ + SendShipPacket::FullCharacter(FullCharacter { + character: fc, + }), + SendShipPacket::CharDataRequest(CharDataRequest {}), + ]) +} pub fn send_player_to_lobby(id: ClientId, _pkt: &CharData, diff --git a/src/ship/ship.rs b/src/ship/ship.rs index 7f1d60a..f95eafc 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -136,13 +136,13 @@ impl SendServerPacket for SendShipPacket { pub struct ClientState { pub user: UserAccountEntity, - settings: UserSettingsEntity, + pub settings: UserSettingsEntity, pub character: CharacterEntity, session: Session, //guildcard: GuildCard, - inventory: items::ActiveInventory, + pub inventory: items::ActiveInventory, //bank: Bank, - block: u32, + pub block: u32, } impl ClientState { @@ -183,31 +183,6 @@ impl ShipServerState { } } - fn block_selected(&mut self, id: ClientId, pkt: &MenuSelect) -> Result, ShipError> { - let client = self.clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; - client.block = pkt.item as u32; - - let (level, stats) = self.level_table.get_stats_from_exp(client.character.char_class, client.character.exp); - - let fc = FullCharacterBytesBuilder::new() - .character(&client.character) - .stats(&stats) - .level(level) - .inventory(&client.inventory) - .key_config(&client.settings.settings.key_config) - .joystick_config(&client.settings.settings.joystick_config) - .symbol_chat(&client.settings.settings.symbol_chats) - .tech_menu(&client.character.tech_menu.as_bytes()) - .build(); - - Ok(vec![ - SendShipPacket::FullCharacter(FullCharacter { - character: fc, - }), - SendShipPacket::CharDataRequest(CharDataRequest {}), - ]) - } - fn message(&mut self, id: ClientId, msg: &Message) -> Box + Send> { match &msg.msg { GameMessage::RequestExp(request_exp) => { @@ -268,7 +243,7 @@ impl ServerState for ShipServerState { }, RecvShipPacket::MenuSelect(menuselect) => { match menuselect.menu { - BLOCK_MENU_ID => Box::new(self.block_selected(id, menuselect)?.into_iter().map(move |pkt| (id, pkt))), + BLOCK_MENU_ID => Box::new(handler::lobby::block_selected(id, menuselect, &mut self.clients, &self.level_table)?.into_iter().map(move |pkt| (id, pkt))), ROOM_MENU_ID => Box::new(handler::room::join_room(id, menuselect, &mut self.client_location, &mut self.clients, &self.level_table, &mut self.rooms)?.into_iter()), _ => unreachable!(), } From 728ac715c04e623f1136dd77c1903ae0118cb0a3 Mon Sep 17 00:00:00 2001 From: jake Date: Wed, 22 Apr 2020 22:59:01 -0600 Subject: [PATCH 08/11] move lobby joining packet creations to their own functions --- src/ship/packet/builder/lobby.rs | 92 ++++++++++++++++++++++++++++++++ src/ship/packet/builder/mod.rs | 1 + src/ship/packet/handler/lobby.rs | 81 ++-------------------------- 3 files changed, 96 insertions(+), 78 deletions(-) create mode 100644 src/ship/packet/builder/lobby.rs diff --git a/src/ship/packet/builder/lobby.rs b/src/ship/packet/builder/lobby.rs new file mode 100644 index 0000000..56aaf66 --- /dev/null +++ b/src/ship/packet/builder/lobby.rs @@ -0,0 +1,92 @@ +use std::collections::HashMap; +use libpso::packet::ship::*; +use crate::common::serverstate::ClientId; +use crate::common::leveltable::CharacterLevelTable; +use crate::ship::ship::{SendShipPacket, ShipError, ClientState}; +use crate::ship::character::{CharacterBytesBuilder, FullCharacterBytesBuilder}; +use crate::ship::location::{ClientLocation, LobbyId, AreaClient}; +use crate::entity::character::CharacterEntity; +use crate::ship::items::{ActiveInventory}; +use libpso::character::character::{Inventory, InventoryItem}; +use libpso::utf8_to_utf16_array; + +fn player_header(tag: u32, client: &ClientState, area_client: &AreaClient) -> PlayerHeader { + PlayerHeader { + tag: tag, + guildcard: client.user.id.0, + _unknown1: [0; 5], + client_id: area_client.local_client.id() as u32, + name: libpso::utf8_to_utf16_array!(client.character.name, 16), + _unknown2: 2, + } +} + +fn player_info(tag: u32, client: &ClientState, area_client: &AreaClient, level_table: &CharacterLevelTable) -> PlayerInfo { + let (level, stats) = level_table.get_stats_from_exp(client.character.char_class, client.character.exp); + let character = CharacterBytesBuilder::new() + .character(&client.character) + .stats(&stats) + .level(level - 1) + .build(); + PlayerInfo { + header: player_header(tag, client, area_client), + inventory: Inventory { + item_count: client.inventory.count() as u8, + hp_mats_used: 0, // TODO: materials + tp_mats_used: 0, // TODO: materials + language: 0, // TODO: account language + items: client.inventory.as_client_inventory_items(), + }, + character: character, + } +} + +pub fn join_lobby(id: ClientId, + lobby: LobbyId, + client_location: &ClientLocation, + clients: &HashMap, + level_table: &CharacterLevelTable) + -> Result { + let lobby_clients = client_location.get_clients_in_lobby(lobby).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; + let playerinfo = lobby_clients.iter() + .map(|area_client| { + let client = clients.get(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client)).unwrap(); + player_info(0x100, &client, area_client, level_table) + }); + + let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); + let area_client = client_location.get_local_client(id).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; + let leader = client_location.get_lobby_leader(lobby).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; + Ok(JoinLobby { + client: area_client.local_client.id(), + leader: leader.local_client.id(), + one: 1, + lobby: lobby.id(), + block: client.block as u16, + event: 0, + padding: 0, + playerinfo: playerinfo.collect(), + }) +} + +pub fn add_to_lobby(id: ClientId, + lobby: LobbyId, + client_location: &ClientLocation, + clients: &HashMap, + level_table: &CharacterLevelTable) + -> Result { + let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); + let area_client = client_location.get_local_client(id).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; + let leader = client_location.get_lobby_leader(lobby).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; + Ok(AddToLobby { + flag: 1, + client: area_client.local_client.id(), + leader: leader.local_client.id(), + one: 1, + lobby: lobby.id(), + block: client.block as u16, + event: 0, + padding: 0, + playerinfo: player_info(0x100, &client, &area_client, level_table), + }) +} diff --git a/src/ship/packet/builder/mod.rs b/src/ship/packet/builder/mod.rs index e69de29..36bd53c 100644 --- a/src/ship/packet/builder/mod.rs +++ b/src/ship/packet/builder/mod.rs @@ -0,0 +1 @@ +pub mod lobby; diff --git a/src/ship/packet/handler/lobby.rs b/src/ship/packet/handler/lobby.rs index 9b48e12..dcc627d 100644 --- a/src/ship/packet/handler/lobby.rs +++ b/src/ship/packet/handler/lobby.rs @@ -5,6 +5,7 @@ use crate::common::leveltable::CharacterLevelTable; use crate::ship::ship::{SendShipPacket, ShipError, ClientState}; use crate::ship::character::{CharacterBytesBuilder, FullCharacterBytesBuilder}; use crate::ship::location::{ClientLocation, LobbyId, RoomId, RoomLobby, MAX_ROOMS}; +use crate::ship::packet; use libpso::character::character; // this function needs a better home @@ -44,84 +45,8 @@ pub fn send_player_to_lobby(id: ClientId, level_table: &CharacterLevelTable) -> Result, ShipError> { let lobby = client_location.add_client_to_next_available_lobby(id, LobbyId(0)).map_err(|_| ShipError::TooManyClients)?; - let lobby_clients = client_location.get_clients_in_lobby(lobby).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; - let playerinfo = lobby_clients.iter() - .map(|room_client| { - let client = clients.get(&room_client.client).ok_or(ShipError::ClientNotFound(id)).unwrap(); - let (level, stats) = level_table.get_stats_from_exp(client.character.char_class, client.character.exp); - let c = CharacterBytesBuilder::new() - .character(&client.character) - .stats(&stats) - .level(level - 1) - .build(); - PlayerInfo { - header: PlayerHeader { - tag: 0x100, - guildcard: client.user.id.0, - _unknown1: [0; 5], - client_id: room_client.local_client.id() as u32, - name: c.name, - _unknown2: 2, - }, - inventory: character::Inventory { - item_count: 0, - hp_mats_used: 0, - tp_mats_used: 0, - language: 0, - items: [character::InventoryItem::default(); 30], - }, - character: c, - } - }); - let area_client = client_location.get_local_client(id).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; - let leader = client_location.get_lobby_leader(lobby).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; - - let join_lobby = JoinLobby { - client: area_client.local_client.id(), - leader: leader.local_client.id(), - one: 1, - lobby: lobby.id(), - block: 1, - event: 0, - padding: 0, - playerinfo: playerinfo.collect(), - }; - - let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; - let (level, stats) = level_table.get_stats_from_exp(client.character.char_class, client.character.exp); - let c = CharacterBytesBuilder::new() - .character(&client.character) - .stats(&stats) - .level(level - 1) - .build(); - let addto = AddToLobby { - flag: 1, - client: area_client.local_client.id(), - leader: leader.local_client.id(), - one: 1, - lobby: lobby.id(), - block: 1, - event: 0, - padding: 0, - playerinfo: PlayerInfo { - header: PlayerHeader { - tag: 0x100, - guildcard: client.user.id.0, - _unknown1: [0; 5], - client_id: area_client.local_client.id() as u32, - name: c.name, - _unknown2: 2, - }, - inventory: character::Inventory { - item_count: 0, - hp_mats_used: 0, - tp_mats_used: 0, - language: 0, - items: [character::InventoryItem::default(); 30], - }, - character: c, - }, - }; + let join_lobby = packet::builder::lobby::join_lobby(id, lobby, client_location, clients, level_table)?; + let addto = packet::builder::lobby::add_to_lobby(id, lobby, client_location, clients, level_table)?; let neighbors = client_location.get_client_neighbors(id).unwrap(); Ok(vec![(id, SendShipPacket::JoinLobby(join_lobby))] From a8b7e4fa4ec5923686042ee8ecd85ac00acf3d0d Mon Sep 17 00:00:00 2001 From: jake Date: Wed, 22 Apr 2020 23:49:49 -0600 Subject: [PATCH 09/11] HashMap -> Clients --- src/ship/packet/builder/lobby.rs | 6 +++--- src/ship/packet/handler/auth.rs | 4 ++-- src/ship/packet/handler/communication.rs | 8 ++++---- src/ship/packet/handler/direct_message.rs | 4 ++-- src/ship/packet/handler/lobby.rs | 6 +++--- src/ship/packet/handler/room.rs | 6 +++--- src/ship/packet/handler/settings.rs | 4 ++-- src/ship/ship.rs | 3 ++- 8 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/ship/packet/builder/lobby.rs b/src/ship/packet/builder/lobby.rs index 56aaf66..6c89536 100644 --- a/src/ship/packet/builder/lobby.rs +++ b/src/ship/packet/builder/lobby.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use libpso::packet::ship::*; use crate::common::serverstate::ClientId; use crate::common::leveltable::CharacterLevelTable; -use crate::ship::ship::{SendShipPacket, ShipError, ClientState}; +use crate::ship::ship::{SendShipPacket, ShipError, ClientState, Clients}; use crate::ship::character::{CharacterBytesBuilder, FullCharacterBytesBuilder}; use crate::ship::location::{ClientLocation, LobbyId, AreaClient}; use crate::entity::character::CharacterEntity; @@ -44,7 +44,7 @@ fn player_info(tag: u32, client: &ClientState, area_client: &AreaClient, level_t pub fn join_lobby(id: ClientId, lobby: LobbyId, client_location: &ClientLocation, - clients: &HashMap, + clients: &Clients, level_table: &CharacterLevelTable) -> Result { let lobby_clients = client_location.get_clients_in_lobby(lobby).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; @@ -72,7 +72,7 @@ pub fn join_lobby(id: ClientId, pub fn add_to_lobby(id: ClientId, lobby: LobbyId, client_location: &ClientLocation, - clients: &HashMap, + clients: &Clients, level_table: &CharacterLevelTable) -> Result { let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); diff --git a/src/ship/packet/handler/auth.rs b/src/ship/packet/handler/auth.rs index 0268ba4..4b61d6b 100644 --- a/src/ship/packet/handler/auth.rs +++ b/src/ship/packet/handler/auth.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use libpso::packet::login::{Login, LoginResponse, AccountStatus, Session}; use libpso::packet::ship::*; use crate::common::serverstate::ClientId; -use crate::ship::ship::{SendShipPacket, ShipError, ClientState}; +use crate::ship::ship::{SendShipPacket, ShipError, ClientState, Clients}; use crate::login::login::get_login_status; use crate::entity::gateway::EntityGateway; use crate::ship::items::ActiveItemDatabase; @@ -10,7 +10,7 @@ use crate::ship::items::ActiveItemDatabase; pub fn validate_login(id: ClientId, pkt: &Login, entity_gateway: &mut EG, - clients: &mut HashMap, + clients: &mut Clients, item_database: &mut ActiveItemDatabase, ship_name: &String) -> Result, ShipError> { diff --git a/src/ship/packet/handler/communication.rs b/src/ship/packet/handler/communication.rs index 17916e4..e2c84aa 100644 --- a/src/ship/packet/handler/communication.rs +++ b/src/ship/packet/handler/communication.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use libpso::packet::ship::*; use crate::common::serverstate::ClientId; use crate::common::leveltable::CharacterLevelTable; -use crate::ship::ship::{SendShipPacket, ShipError, ClientState}; +use crate::ship::ship::{SendShipPacket, ShipError, ClientState, Clients}; use crate::ship::character::{CharacterBytesBuilder, FullCharacterBytesBuilder}; use crate::ship::location::{ClientLocation, LobbyId, RoomId, RoomLobby, MAX_ROOMS}; use libpso::character::character; @@ -11,7 +11,7 @@ use crate::entity::gateway::EntityGateway; pub fn player_chat(id: ClientId, msg: &PlayerChat, client_location: &ClientLocation, - clients: &HashMap) -> Result + Send>, ShipError> { + clients: &Clients) -> Result + Send>, ShipError> { let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; let cmsg = PlayerChat::new(client.user.id.0, msg.message.clone()); @@ -24,7 +24,7 @@ pub fn player_chat(id: ClientId, pub fn request_infoboard(id: ClientId, request_infoboard: &ViewInfoboardRequest, client_location: &ClientLocation, - clients: &HashMap) + clients: &Clients) -> Box + Send> { let area_clients = client_location.get_client_neighbors(id).unwrap(); let r = area_clients.iter() @@ -42,7 +42,7 @@ pub fn request_infoboard(id: ClientId, pub fn write_infoboard(id: ClientId, new_infoboard: &WriteInfoboard, - clients: &mut HashMap, + clients: &mut Clients, entity_gateway: &mut EG) -> Box + Send> { let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); diff --git a/src/ship/packet/handler/direct_message.rs b/src/ship/packet/handler/direct_message.rs index ceb4e05..a824684 100644 --- a/src/ship/packet/handler/direct_message.rs +++ b/src/ship/packet/handler/direct_message.rs @@ -4,7 +4,7 @@ use libpso::packet::ship::*; use libpso::packet::messages::*; use crate::common::serverstate::ClientId; use crate::common::leveltable::CharacterLevelTable; -use crate::ship::ship::{SendShipPacket, ShipError, ClientState, Rooms}; +use crate::ship::ship::{SendShipPacket, ShipError, ClientState, Clients, Rooms}; use crate::ship::character::{CharacterBytesBuilder, FullCharacterBytesBuilder}; use crate::ship::location::{ClientLocation, LobbyId, RoomId, RoomLobby, MAX_ROOMS}; use libpso::character::character; @@ -26,7 +26,7 @@ pub fn guildcard_send(id: ClientId, guildcard_send: &GuildcardSend, target: u32, client_location: &ClientLocation, - clients: &HashMap) + clients: &Clients) -> Box + Send> { let client = clients.get(&id).unwrap(); let msg = DirectMessage{ diff --git a/src/ship/packet/handler/lobby.rs b/src/ship/packet/handler/lobby.rs index dcc627d..9be8556 100644 --- a/src/ship/packet/handler/lobby.rs +++ b/src/ship/packet/handler/lobby.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use libpso::packet::ship::*; use crate::common::serverstate::ClientId; use crate::common::leveltable::CharacterLevelTable; -use crate::ship::ship::{SendShipPacket, ShipError, ClientState}; +use crate::ship::ship::{SendShipPacket, ShipError, ClientState, Clients}; use crate::ship::character::{CharacterBytesBuilder, FullCharacterBytesBuilder}; use crate::ship::location::{ClientLocation, LobbyId, RoomId, RoomLobby, MAX_ROOMS}; use crate::ship::packet; @@ -11,7 +11,7 @@ use libpso::character::character; // this function needs a better home pub fn block_selected(id: ClientId, pkt: &MenuSelect, - clients: &mut HashMap, + clients: &mut Clients, level_table: &CharacterLevelTable) -> Result, ShipError> { let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; @@ -41,7 +41,7 @@ pub fn block_selected(id: ClientId, pub fn send_player_to_lobby(id: ClientId, _pkt: &CharData, client_location: &mut ClientLocation, - clients: &HashMap, + clients: &Clients, level_table: &CharacterLevelTable) -> Result, ShipError> { let lobby = client_location.add_client_to_next_available_lobby(id, LobbyId(0)).map_err(|_| ShipError::TooManyClients)?; diff --git a/src/ship/packet/handler/room.rs b/src/ship/packet/handler/room.rs index 3553dda..fa046d8 100644 --- a/src/ship/packet/handler/room.rs +++ b/src/ship/packet/handler/room.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use libpso::packet::ship::*; use crate::common::serverstate::ClientId; use crate::common::leveltable::CharacterLevelTable; -use crate::ship::ship::{SendShipPacket, ShipError, ClientState, Rooms}; +use crate::ship::ship::{SendShipPacket, ShipError, ClientState, Rooms, Clients}; use crate::ship::character::{CharacterBytesBuilder, FullCharacterBytesBuilder}; use crate::ship::location::{ClientLocation, LobbyId, RoomId, RoomLobby, MAX_ROOMS}; use libpso::character::character; @@ -11,7 +11,7 @@ use crate::ship::room; pub fn create_room(id: ClientId, create_room: &CreateRoom, client_location: &mut ClientLocation, - clients: &mut HashMap, + clients: &mut Clients, rooms: &mut Rooms) -> Box + Send> { let area = client_location.get_area(id).unwrap(); @@ -78,7 +78,7 @@ pub fn room_name_request(id: ClientId, pub fn join_room(id: ClientId, pkt: &MenuSelect, client_location: &mut ClientLocation, - clients: &mut HashMap, + clients: &mut Clients, level_table: &CharacterLevelTable, rooms: &mut Rooms) -> Result, ShipError> { diff --git a/src/ship/packet/handler/settings.rs b/src/ship/packet/handler/settings.rs index 096f512..93ed14a 100644 --- a/src/ship/packet/handler/settings.rs +++ b/src/ship/packet/handler/settings.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use libpso::packet::ship::*; use crate::common::serverstate::ClientId; use crate::common::leveltable::CharacterLevelTable; -use crate::ship::ship::{SendShipPacket, ShipError, ClientState}; +use crate::ship::ship::{SendShipPacket, ShipError, ClientState, Clients}; use crate::ship::character::{CharacterBytesBuilder, FullCharacterBytesBuilder}; use crate::ship::location::{ClientLocation, LobbyId, RoomId, RoomLobby, MAX_ROOMS}; use libpso::character::character; @@ -10,7 +10,7 @@ use crate::entity::gateway::EntityGateway; pub fn update_config(id: ClientId, update_config: &UpdateConfig, - clients: &mut HashMap, + clients: &mut Clients, entity_gateway: &mut EG) -> Box + Send> { let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); diff --git a/src/ship/ship.rs b/src/ship/ship.rs index f95eafc..5ef4728 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -28,6 +28,7 @@ use crate::ship::packet::handler; pub const SHIP_PORT: u16 = 23423; pub type Rooms = [Option; MAX_ROOMS]; +pub type Clients = HashMap; #[derive(Debug)] pub enum ShipError { @@ -162,7 +163,7 @@ impl ClientState { pub struct ShipServerState { entity_gateway: EG, - clients: HashMap, + clients: Clients, client_location: ClientLocation, level_table: CharacterLevelTable, name: String, From 628ad056b4d93981ce84fadb2645b2f5b1db39b7 Mon Sep 17 00:00:00 2001 From: jake Date: Fri, 24 Apr 2020 20:38:56 -0600 Subject: [PATCH 10/11] functions to create room joining packets --- src/ship/packet/builder/lobby.rs | 33 +------- src/ship/packet/builder/mod.rs | 40 +++++++++ src/ship/packet/builder/room.rs | 77 +++++++++++++++++ src/ship/packet/handler/room.rs | 138 ++++++------------------------- src/ship/room.rs | 21 +++++ src/ship/ship.rs | 4 +- 6 files changed, 165 insertions(+), 148 deletions(-) create mode 100644 src/ship/packet/builder/room.rs diff --git a/src/ship/packet/builder/lobby.rs b/src/ship/packet/builder/lobby.rs index 6c89536..29a1b8b 100644 --- a/src/ship/packet/builder/lobby.rs +++ b/src/ship/packet/builder/lobby.rs @@ -6,40 +6,11 @@ use crate::ship::ship::{SendShipPacket, ShipError, ClientState, Clients}; use crate::ship::character::{CharacterBytesBuilder, FullCharacterBytesBuilder}; use crate::ship::location::{ClientLocation, LobbyId, AreaClient}; use crate::entity::character::CharacterEntity; -use crate::ship::items::{ActiveInventory}; +use crate::ship::items::ActiveInventory; +use crate::ship::packet::builder::{player_header, player_info}; use libpso::character::character::{Inventory, InventoryItem}; use libpso::utf8_to_utf16_array; -fn player_header(tag: u32, client: &ClientState, area_client: &AreaClient) -> PlayerHeader { - PlayerHeader { - tag: tag, - guildcard: client.user.id.0, - _unknown1: [0; 5], - client_id: area_client.local_client.id() as u32, - name: libpso::utf8_to_utf16_array!(client.character.name, 16), - _unknown2: 2, - } -} - -fn player_info(tag: u32, client: &ClientState, area_client: &AreaClient, level_table: &CharacterLevelTable) -> PlayerInfo { - let (level, stats) = level_table.get_stats_from_exp(client.character.char_class, client.character.exp); - let character = CharacterBytesBuilder::new() - .character(&client.character) - .stats(&stats) - .level(level - 1) - .build(); - PlayerInfo { - header: player_header(tag, client, area_client), - inventory: Inventory { - item_count: client.inventory.count() as u8, - hp_mats_used: 0, // TODO: materials - tp_mats_used: 0, // TODO: materials - language: 0, // TODO: account language - items: client.inventory.as_client_inventory_items(), - }, - character: character, - } -} pub fn join_lobby(id: ClientId, lobby: LobbyId, diff --git a/src/ship/packet/builder/mod.rs b/src/ship/packet/builder/mod.rs index 36bd53c..19120f1 100644 --- a/src/ship/packet/builder/mod.rs +++ b/src/ship/packet/builder/mod.rs @@ -1 +1,41 @@ pub mod lobby; +pub mod room; + +use libpso::character::character::Inventory; +use libpso::packet::ship::{PlayerHeader, PlayerInfo}; +use libpso::utf8_to_utf16_array; +use crate::common::leveltable::CharacterLevelTable; +use crate::ship::character::CharacterBytesBuilder; +use crate::ship::ship::ClientState; +use crate::ship::location::AreaClient; + +pub fn player_header(tag: u32, client: &ClientState, area_client: &AreaClient) -> PlayerHeader { + PlayerHeader { + tag: tag, + guildcard: client.user.id.0, + _unknown1: [0; 5], + client_id: area_client.local_client.id() as u32, + name: libpso::utf8_to_utf16_array!(client.character.name, 16), + _unknown2: 2, + } +} + +pub fn player_info(tag: u32, client: &ClientState, area_client: &AreaClient, level_table: &CharacterLevelTable) -> PlayerInfo { + let (level, stats) = level_table.get_stats_from_exp(client.character.char_class, client.character.exp); + let character = CharacterBytesBuilder::new() + .character(&client.character) + .stats(&stats) + .level(level - 1) + .build(); + PlayerInfo { + header: player_header(tag, client, area_client), + inventory: Inventory { + item_count: client.inventory.count() as u8, + hp_mats_used: 0, // TODO: materials + tp_mats_used: 0, // TODO: materials + language: 0, // TODO: account language + items: client.inventory.as_client_inventory_items(), + }, + character: character, + } +} diff --git a/src/ship/packet/builder/room.rs b/src/ship/packet/builder/room.rs new file mode 100644 index 0000000..26abdb3 --- /dev/null +++ b/src/ship/packet/builder/room.rs @@ -0,0 +1,77 @@ +use std::collections::HashMap; +use libpso::packet::ship::*; +use crate::common::serverstate::ClientId; +use crate::common::leveltable::CharacterLevelTable; +use crate::ship::ship::{SendShipPacket, ShipError, ClientState, Clients}; +use crate::ship::character::{CharacterBytesBuilder, FullCharacterBytesBuilder}; +use crate::ship::location::{ClientLocation, RoomId, AreaClient}; +use crate::entity::character::CharacterEntity; +use crate::ship::items::ActiveInventory; +use crate::ship::room::RoomState; +use crate::ship::packet::builder::{player_header, player_info}; +use libpso::character::character::{Inventory, InventoryItem}; +use libpso::utf8_to_utf16_array; + +pub fn join_room(id: ClientId, + clients: &Clients, + client_location: &ClientLocation, + room_id: RoomId, + room: &RoomState) + -> Result { + let all_clients = client_location.get_clients_in_room(room_id).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; + let players = all_clients.iter() + .enumerate() + .fold(Ok([PlayerHeader::default(); 4]), |acc, (i, c)| { + let header_client = clients.get(&c.client).ok_or(ShipError::ClientNotFound(id))?; + let header_area_client = client_location.get_local_client(id).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; + acc.map(|mut a| { + a[i] = player_header(0x10000, &header_client, &header_area_client); + a + }) + })?; + + let area_client = client_location.get_local_client(id).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; + let leader = client_location.get_room_leader(room_id).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; + Ok(JoinRoom { + flag: all_clients.len() as u32, + maps: room.maps.map_headers(), + players: players, + client: area_client.local_client.id(), + leader: leader.local_client.id(), + one: 1, + difficulty: room.mode.difficulty().into(), + battle: room.mode.battle(), + event: 0, + section: room.section_id.into(), + challenge: room.mode.challenge(), + random_seed: room.random_seed, + episode: room.mode.episode().into(), + one2: 1, + single_player: room.mode.single_player(), + unknown: 0, + }) +} + + +pub fn add_to_room(id: ClientId, + client: &ClientState, + area_client: &AreaClient, + leader: &AreaClient, + level_table: &CharacterLevelTable, + room_id: RoomId, +) + -> Result { + + Ok(AddToRoom { + flag: 1, + client: area_client.local_client.id(), + leader: leader.local_client.id(), + one: 0, // TODO: ???????? + lobby: 0xFF, + block: 0, + event: 0, + padding: 0, + playerinfo: player_info(0x10000, client, &area_client, level_table), + }) +} + diff --git a/src/ship/packet/handler/room.rs b/src/ship/packet/handler/room.rs index fa046d8..2d4b228 100644 --- a/src/ship/packet/handler/room.rs +++ b/src/ship/packet/handler/room.rs @@ -5,6 +5,7 @@ use crate::common::leveltable::CharacterLevelTable; use crate::ship::ship::{SendShipPacket, ShipError, ClientState, Rooms, Clients}; use crate::ship::character::{CharacterBytesBuilder, FullCharacterBytesBuilder}; use crate::ship::location::{ClientLocation, LobbyId, RoomId, RoomLobby, MAX_ROOMS}; +use crate::ship::packet::builder; use libpso::character::character; use crate::ship::room; @@ -13,7 +14,7 @@ pub fn create_room(id: ClientId, client_location: &mut ClientLocation, clients: &mut Clients, rooms: &mut Rooms) - -> Box + Send> { + -> Result + Send>, ShipError> { let area = client_location.get_area(id).unwrap(); let area_client = client_location.get_local_client(id).unwrap(); let lobby_neighbors = client_location.get_client_neighbors(id).unwrap(); @@ -23,44 +24,18 @@ pub fn create_room(id: ClientId, let mut room = room::RoomState::from_create_room(create_room, client.character.section_id).unwrap(); room.bursting = true; - let players = [PlayerHeader { - tag: 0x10000, - guildcard: client.user.id.0, - _unknown1: [0; 5], - client_id: 0, - name: libpso::utf8_to_utf16_array!(client.character.name, 16), - _unknown2: 2, - }, PlayerHeader::default(), PlayerHeader::default(), PlayerHeader::default()]; - - let join_room = JoinRoom { - flag: 1, - maps: room.maps.map_headers(), - players: players, - client: 0, - leader: 0, - one: 1, - difficulty: create_room.difficulty, - battle: create_room.battle, - event: 0, - section: 0, // TODO - challenge: create_room.challenge, - random_seed: 23, // TODO - episode: create_room.episode, - one2: 1, - single_player: create_room.single_player, - unknown: 0, - }; + let join_room = builder::room::join_room(id, clients, client_location, room_id, &room)?; rooms[room_id.0] = Some(room); let leader = client_location.get_area_leader(area); let result = vec![(id, SendShipPacket::JoinRoom(join_room))].into_iter(); match leader { - Ok(leader) => Box::new(result.chain(lobby_neighbors + Ok(leader) => Ok(Box::new(result.chain(lobby_neighbors .into_iter() .map(move |c| { (c.client, SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id()))) - }))), - Err(_) => Box::new(result) + })))), + Err(_) => Ok(Box::new(result)) } } @@ -81,109 +56,42 @@ pub fn join_room(id: ClientId, clients: &mut Clients, level_table: &CharacterLevelTable, rooms: &mut Rooms) - -> Result, ShipError> { + -> Result + Send>, ShipError> { let original_area = client_location.get_area(id).unwrap(); let original_neighbors = client_location.get_client_neighbors(id).unwrap(); let room = rooms.get(pkt.item as usize) .ok_or_else(|| ShipError::InvalidRoom(pkt.item))?.as_ref() .ok_or_else(|| ShipError::InvalidRoom(pkt.item))?; if room.bursting { - return Ok(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("player is bursting\nplease wait".into())))]) + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("player is bursting\nplease wait".into())))].into_iter())) } let room_id = RoomId(pkt.item as usize); let original_room_clients = client_location.get_clients_in_room(room_id).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; client_location.add_client_to_room(id, room_id).unwrap(); // TODO: show room full error or whatever - let all_clients = client_location.get_clients_in_room(room_id).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; - let player_headers = all_clients.iter() - .enumerate() - .fold([PlayerHeader::default(); 4], |mut acc, (i, c)| { - let header_client = clients.get(&c.client).ok_or(ShipError::ClientNotFound(id)).unwrap(); - acc[i] = PlayerHeader { - tag: 0x100, - guildcard: header_client.user.id.0, - _unknown1: [0,0,0, c.local_client.id() as u32, 0], - client_id: 0, - name: libpso::utf8_to_utf16_array!(header_client.character.name, 16), - _unknown2: 2, - }; - acc - }); - + let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; let area_client = client_location.get_local_client(id).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; let leader = client_location.get_room_leader(room_id).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; - - let join_room = JoinRoom { - flag: all_clients.len() as u32, - maps: room.map_headers(), - players: player_headers, - client: area_client.local_client.id(), - leader: leader.local_client.id(), - one: 1, - difficulty: room.mode.difficulty().into(), - battle: matches!(room.mode, room::RoomMode::Battle {..}) as u8, - event: 0, - section: room.section_id.into(), - challenge: matches!(room.mode, room::RoomMode::Challenge {..}) as u8, - random_seed: room.random_seed, - episode: room.mode.episode().into(), - one2: 1, - single_player: 0, // TODO - unknown: 0, - }; - - let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; - let (level, stats) = level_table.get_stats_from_exp(client.character.char_class, client.character.exp); - let c = CharacterBytesBuilder::new() - .character(&client.character) - .stats(&stats) - .level(level - 1) - .build(); - let add_to = AddToRoom { - flag: 0x10000, - client: area_client.local_client.id(), - leader: leader.local_client.id(), - one: 0, // TODO: ?????????? - lobby: 0xff, - block: 0, - event: 0, - padding: 1, - playerinfo: PlayerInfo { - header: PlayerHeader { - tag: 0x10000, - guildcard: client.user.id.0, - _unknown1: [0; 5], - client_id: area_client.local_client.id() as u32, - name: libpso::utf8_to_utf16_array!(client.character.name, 16), - _unknown2: 2, - }, - inventory: character::Inventory { - item_count: 0, - hp_mats_used: 0, - tp_mats_used: 0, - language: 0, - items: [character::InventoryItem::default(); 30], // TOOD: this should be something - }, - character: c, - }, - }; - - let result = vec![(id, SendShipPacket::JoinRoom(join_room))] - .into_iter() - .chain(original_room_clients.clone().into_iter() - .map(|c| (c.client, SendShipPacket::AddToRoom(add_to.clone()))) - ); + let join_room = builder::room::join_room(id, clients, client_location, room_id, &room)?; + let add_to = builder::room::add_to_room(id, &client, &area_client, &leader, level_table, room_id)?; let room = rooms.get_mut(room_id.0).unwrap().as_mut().unwrap(); room.bursting = true; + + let mut result: Box + Send> = Box::new( + vec![(id, SendShipPacket::JoinRoom(join_room))] + .into_iter() + .chain(original_room_clients.clone().into_iter() + .map(move |c| (c.client, SendShipPacket::AddToRoom(add_to.clone()))) + )); + if let Ok(leader) = client_location.get_area_leader(original_area) { let leave_lobby = SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id())); - Ok(result.chain(original_neighbors.into_iter() - .map(|c| (c.client, leave_lobby.clone()))).collect()) - } - else { - Ok(result.collect()) + result = Box::new(result.chain(original_neighbors.into_iter() + .map(move |c| (c.client, leave_lobby.clone())))) } + + Ok(result) } pub fn done_bursting(id: ClientId, diff --git a/src/ship/room.rs b/src/ship/room.rs index b91c790..66c7830 100644 --- a/src/ship/room.rs +++ b/src/ship/room.rs @@ -117,6 +117,27 @@ impl RoomMode { RoomMode::Challenge {episode, ..} => *episode, } } + + pub fn battle(&self) -> u8 { + match self { + RoomMode::Battle {..} => 1, + _ => 0, + } + } + + pub fn challenge(&self) -> u8 { + match self { + RoomMode::Challenge {..} => 1, + _ => 0, + } + } + + pub fn single_player(&self) -> u8 { + match self { + RoomMode::Single {..} => 1, + _ => 0, + } + } } diff --git a/src/ship/ship.rs b/src/ship/ship.rs index 5ef4728..595dc64 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -245,7 +245,7 @@ impl ServerState for ShipServerState { RecvShipPacket::MenuSelect(menuselect) => { match menuselect.menu { BLOCK_MENU_ID => Box::new(handler::lobby::block_selected(id, menuselect, &mut self.clients, &self.level_table)?.into_iter().map(move |pkt| (id, pkt))), - ROOM_MENU_ID => Box::new(handler::room::join_room(id, menuselect, &mut self.client_location, &mut self.clients, &self.level_table, &mut self.rooms)?.into_iter()), + ROOM_MENU_ID => handler::room::join_room(id, menuselect, &mut self.client_location, &mut self.clients, &self.level_table, &mut self.rooms)?, _ => unreachable!(), } }, @@ -262,7 +262,7 @@ impl ServerState for ShipServerState { Box::new(handler::communication::player_chat(id, msg, &self.client_location, &self.clients)?.into_iter()) }, RecvShipPacket::CreateRoom(create_room) => { - handler::room::create_room(id, create_room, &mut self.client_location, &mut self.clients, &mut self.rooms) + handler::room::create_room(id, create_room, &mut self.client_location, &mut self.clients, &mut self.rooms)? }, RecvShipPacket::RoomNameRequest(_req) => { handler::room::room_name_request(id, &self.client_location, &self.rooms) From 2886f537ba8b5b698fd0d6d91a1d5676bcbd4cb7 Mon Sep 17 00:00:00 2001 From: jake Date: Fri, 24 Apr 2020 22:22:19 -0600 Subject: [PATCH 11/11] simplify leaving lobby packet sending --- src/ship/packet/handler/room.rs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/ship/packet/handler/room.rs b/src/ship/packet/handler/room.rs index 2d4b228..ff82422 100644 --- a/src/ship/packet/handler/room.rs +++ b/src/ship/packet/handler/room.rs @@ -27,16 +27,19 @@ pub fn create_room(id: ClientId, let join_room = builder::room::join_room(id, clients, client_location, room_id, &room)?; rooms[room_id.0] = Some(room); - let leader = client_location.get_area_leader(area); - let result = vec![(id, SendShipPacket::JoinRoom(join_room))].into_iter(); - match leader { - Ok(leader) => Ok(Box::new(result.chain(lobby_neighbors - .into_iter() - .map(move |c| { - (c.client, SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id()))) - })))), - Err(_) => Ok(Box::new(result)) + let mut result: Box + Send> = Box::new( + vec![(id, SendShipPacket::JoinRoom(join_room))].into_iter() + ); + if let Ok(leader) = client_location.get_area_leader(area) { + let leave_lobby = SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id())); + result = Box::new(result.chain(lobby_neighbors + .into_iter() + .map(move |c| { + (c.client, leave_lobby.clone()) + }))); } + + Ok(result) } pub fn room_name_request(id: ClientId,