diff --git a/src/ship/location.rs b/src/ship/location.rs index 2248d5a..8b36055 100644 --- a/src/ship/location.rs +++ b/src/ship/location.rs @@ -133,15 +133,18 @@ pub struct ClientLocation { client_location: HashMap, } -impl ClientLocation { - pub fn new() -> ClientLocation { +impl Default for ClientLocation { + fn default() -> ClientLocation { ClientLocation { lobbies: [Lobby([None; 12]); 15], rooms: [None; MAX_ROOMS], client_location: HashMap::new(), } } +} + +impl ClientLocation { pub fn add_client_to_lobby(&mut self, id: ClientId, lobby: LobbyId) -> Result<(), JoinLobbyError> { let l = self.lobbies.get_mut(lobby.0).ok_or(JoinLobbyError::LobbyDoesNotExist)?; let (index, empty_slot) = l.0.iter_mut() @@ -389,7 +392,7 @@ mod test { #[test] fn test_add_client_to_lobby() { - let mut cl = ClientLocation::new(); + let mut cl = ClientLocation::default(); cl.add_client_to_lobby(ClientId(12), LobbyId(0)); cl.add_client_to_lobby(ClientId(13), LobbyId(1)); cl.add_client_to_lobby(ClientId(14), LobbyId(0)); @@ -402,7 +405,7 @@ mod test { #[test] fn test_add_client_to_full_lobby() { - let mut cl = ClientLocation::new(); + let mut cl = ClientLocation::default(); (0..12).for_each(|i| { cl.add_client_to_lobby(ClientId(i), LobbyId(0)); }); @@ -411,7 +414,7 @@ mod test { #[test] fn test_add_client_to_next_available_lobby() { - let mut cl = ClientLocation::new(); + let mut cl = ClientLocation::default(); (1..4).for_each(|lobby| { (0..12).for_each(|i| { cl.add_client_to_lobby(ClientId(lobby*12+i), LobbyId(lobby)); @@ -422,7 +425,7 @@ mod test { #[test] fn test_add_to_lobby_when_all_are_full() { - let mut cl = ClientLocation::new(); + let mut cl = ClientLocation::default(); (0..15).for_each(|lobby| { (0..12).for_each(|i| { cl.add_client_to_lobby(ClientId(lobby*12+i), LobbyId(lobby)); @@ -433,13 +436,13 @@ mod test { #[test] fn test_new_room() { - let mut cl = ClientLocation::new(); + let mut cl = ClientLocation::default(); assert!(cl.create_new_room(ClientId(12)) == Ok(RoomId(0))); } #[test] fn test_add_client_to_room() { - let mut cl = ClientLocation::new(); + let mut cl = ClientLocation::default(); let room = cl.create_new_room(ClientId(12)).unwrap(); assert!(cl.add_client_to_room(ClientId(234), room) == Ok(())); assert!(cl.get_clients_in_room(room).unwrap().into_iter().map(|c| (c.client, c.local_client)).collect::>() == vec![ @@ -450,7 +453,7 @@ mod test { #[test] fn test_no_new_room_slots() { - let mut cl = ClientLocation::new(); + let mut cl = ClientLocation::default(); for i in 0..128 { cl.create_new_room(ClientId(i)); } @@ -459,7 +462,7 @@ mod test { #[test] fn test_joining_full_room() { - let mut cl = ClientLocation::new(); + let mut cl = ClientLocation::default(); let room = cl.create_new_room(ClientId(0)).unwrap(); assert!(cl.add_client_to_room(ClientId(1), room) == Ok(())); assert!(cl.add_client_to_room(ClientId(2), room) == Ok(())); @@ -469,7 +472,7 @@ mod test { #[test] fn test_adding_client_to_room_removes_from_lobby() { - let mut cl = ClientLocation::new(); + let mut cl = ClientLocation::default(); cl.add_client_to_lobby(ClientId(93), LobbyId(0)); cl.add_client_to_lobby(ClientId(23), LobbyId(0)); cl.add_client_to_lobby(ClientId(51), LobbyId(0)); @@ -489,7 +492,7 @@ mod test { #[test] fn test_getting_neighbors() { - let mut cl = ClientLocation::new(); + let mut cl = ClientLocation::default(); cl.add_client_to_lobby(ClientId(93), LobbyId(0)); cl.add_client_to_lobby(ClientId(23), LobbyId(0)); cl.add_client_to_lobby(ClientId(51), LobbyId(0)); @@ -504,7 +507,7 @@ mod test { #[test] fn test_failing_to_join_lobby_does_not_remove_from_current_area() { - let mut cl = ClientLocation::new(); + let mut cl = ClientLocation::default(); (0..12).for_each(|i| { cl.add_client_to_lobby(ClientId(i), LobbyId(0)); }); @@ -518,7 +521,7 @@ mod test { #[test] fn test_get_leader() { - let mut cl = ClientLocation::new(); + let mut cl = ClientLocation::default(); cl.add_client_to_lobby(ClientId(93), LobbyId(0)); cl.add_client_to_lobby(ClientId(23), LobbyId(0)); cl.add_client_to_lobby(ClientId(51), LobbyId(0)); @@ -529,7 +532,7 @@ mod test { #[test] fn test_remove_client_from_room() { - let mut cl = ClientLocation::new(); + let mut cl = ClientLocation::default(); let room = cl.create_new_room(ClientId(51)).unwrap(); cl.add_client_to_room(ClientId(93), room); cl.add_client_to_room(ClientId(23), room); @@ -545,7 +548,7 @@ mod test { #[test] fn test_leader_changes_on_leader_leaving() { - let mut cl = ClientLocation::new(); + let mut cl = ClientLocation::default(); let room = cl.create_new_room(ClientId(51)).unwrap(); cl.add_client_to_room(ClientId(93), room); cl.add_client_to_room(ClientId(23), room); diff --git a/src/ship/packet/handler/auth.rs b/src/ship/packet/handler/auth.rs index bc3cc59..23f261d 100644 --- a/src/ship/packet/handler/auth.rs +++ b/src/ship/packet/handler/auth.rs @@ -8,15 +8,16 @@ use crate::ship::items::ItemManager; use crate::common::interserver::ShipMessage; pub async fn validate_login(id: ClientId, - pkt: &Login, - entity_gateway: &mut EG, - clients: &mut Clients, - item_manager: &mut ItemManager, - shipgate_sender: &Option>, - ship_name: &String) + pkt: &Login, + entity_gateway: &mut EG, + clients: &mut Clients, + item_manager: &mut ItemManager, + shipgate_sender: &Option>, + ship_name: &String, + num_blocks: usize) -> Result, anyhow::Error> { Ok(match get_login_status(entity_gateway, pkt).await { - Ok(mut user) => { + 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; @@ -34,7 +35,7 @@ pub async fn validate_login(id: ClientId, shipgate_sender(ShipMessage::AddUser(user.id.clone())); } clients.insert(id, ClientState::new(user, settings, character, pkt.session)); - vec![SendShipPacket::LoginResponse(response), SendShipPacket::ShipBlockList(ShipBlockList::new(&&ship_name, 1))] + vec![SendShipPacket::LoginResponse(response), SendShipPacket::ShipBlockList(ShipBlockList::new(&&ship_name, num_blocks))] }, 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 4954a27..7570591 100644 --- a/src/ship/packet/handler/lobby.rs +++ b/src/ship/packet/handler/lobby.rs @@ -17,7 +17,7 @@ pub fn block_selected(id: ClientId, level_table: &CharacterLevelTable) -> Result, anyhow::Error> { let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; - client.block = pkt.item as u32; + client.block = pkt.item as usize - 1; let (level, stats) = level_table.get_stats_from_exp(client.character.char_class, client.character.exp); diff --git a/src/ship/ship.rs b/src/ship/ship.rs index 89d3015..91ec726 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -70,6 +70,7 @@ pub enum ShipError { GatewayError(#[from] GatewayError), UnknownMonster(crate::ship::monster::MonsterType), InvalidShip(usize), + InvalidBlock(usize), } #[derive(Debug)] @@ -242,7 +243,7 @@ pub struct ClientState { pub character: CharacterEntity, session: Session, //guildcard: GuildCard, - pub block: u32, + pub block: usize, pub item_drop_location: Option, pub done_loading_quest: bool, //pub loading_quest: Option, @@ -310,6 +311,7 @@ pub struct ShipServerStateBuilder { ip: Option, port: Option, auth_token: Option, + num_blocks: usize, } impl ShipServerStateBuilder { @@ -320,6 +322,7 @@ impl ShipServerStateBuilder { ip: None, port: None, auth_token: None, + num_blocks: 2, } } @@ -348,19 +351,26 @@ impl ShipServerStateBuilder { self } + pub fn blocks(mut self, num_blocks: usize) -> ShipServerStateBuilder { + self.num_blocks = num_blocks; + self + } + pub fn build(self) -> ShipServerState { + let blocks = std::iter::repeat_with(Block::default).take(self.num_blocks).collect(); // Block doesn't have a Clone impl which limits the easy ways to init this ShipServerState { entity_gateway: self.entity_gateway.unwrap(), clients: HashMap::new(), - client_location: Box::new(ClientLocation::new()), level_table: CharacterLevelTable::new(), name: self.name.unwrap_or("NAMENOTSET".into()), - rooms: Box::new([None; MAX_ROOMS]), item_manager: items::ItemManager::new(), quests: quests::load_quests("data/quests.toml".into()).unwrap(), ip: self.ip.unwrap_or(Ipv4Addr::new(127,0,0,1)), port: self.port.unwrap_or(SHIP_PORT), shops: Box::new(ItemShops::new()), + + blocks: Blocks(blocks), + auth_token: self.auth_token.unwrap_or(AuthToken("".into())), ship_list: Vec::new(), shipgate_sender: None, @@ -368,20 +378,44 @@ impl ShipServerStateBuilder { } } + +struct Block { + client_location: Box, + rooms: Box, +} + +impl Default for Block { + fn default() -> Block { + Block { + client_location: Box::new(ClientLocation::default()), + rooms: Box::new([None; MAX_ROOMS]), + } + } +} + +struct Blocks(Vec); + +impl Blocks { + fn with_client(&mut self, id: ClientId, clients: &Clients) -> Result<&mut Block, ShipError> { + let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; + self.0.get_mut(client.block).ok_or(ShipError::InvalidBlock(client.block)) + } +} + pub struct ShipServerState { entity_gateway: EG, pub clients: Clients, - client_location: Box, level_table: CharacterLevelTable, name: String, - pub rooms: Box, item_manager: items::ItemManager, quests: quests::QuestList, + shops: Box, + blocks: Blocks, + ip: Ipv4Addr, port: u16, - shops: Box, - auth_token: AuthToken, + auth_token: AuthToken, ship_list: Vec, shipgate_sender: Option>, } @@ -398,34 +432,41 @@ impl ShipServerState { async fn message(&mut self, id: ClientId, msg: &Message) -> Result + Send>, anyhow::Error> { Ok(match &msg.msg { GameMessage::RequestExp(request_exp) => { - handler::message::request_exp(id, request_exp, &mut self.entity_gateway, &self.client_location, &mut self.clients, &mut self.rooms, &self.level_table).await? + let block = self.blocks.with_client(id, &self.clients)?; + handler::message::request_exp(id, request_exp, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut block.rooms, &self.level_table).await? }, GameMessage::PlayerDropItem(player_drop_item) => { - handler::message::player_drop_item(id, player_drop_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.rooms, &mut self.item_manager).await? + let block = self.blocks.with_client(id, &self.clients)?; + handler::message::player_drop_item(id, player_drop_item, &mut self.entity_gateway, &mut block.client_location, &mut self.clients, &mut block.rooms, &mut self.item_manager).await? }, GameMessage::DropCoordinates(drop_coordinates) => { - handler::message::drop_coordinates(id, drop_coordinates, &self.client_location, &mut self.clients, &self.rooms)? + let block = self.blocks.with_client(id, &self.clients)?; + handler::message::drop_coordinates(id, drop_coordinates, &block.client_location, &mut self.clients, &block.rooms)? }, GameMessage::PlayerNoLongerHasItem(no_longer_has_item) => { - handler::message::split_item_stack(id, no_longer_has_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager).await? + let block = self.blocks.with_client(id, &self.clients)?; + handler::message::split_item_stack(id, no_longer_has_item, &mut self.entity_gateway, &mut block.client_location, &mut self.clients, &mut self.item_manager).await? }, GameMessage::PlayerChangedMap(_) | GameMessage::PlayerChangedMap2(_) | GameMessage::TellOtherPlayerMyLocation(_) | GameMessage::PlayerWarpingToFloor(_) | GameMessage::PlayerTeleported(_) | GameMessage::PlayerStopped(_) | GameMessage::PlayerLoadedIn(_) | GameMessage::PlayerWalking(_) | GameMessage::PlayerRunning(_) | GameMessage::PlayerWarped(_) | GameMessage::PlayerChangedFloor(_) | GameMessage::InitializeSpeechNpc(_) => { - handler::message::update_player_position(id, &msg, &mut self.clients, &mut self.client_location, &self.rooms)? + let block = self.blocks.with_client(id, &self.clients)?; + handler::message::update_player_position(id, &msg, &mut self.clients, &mut block.client_location, &block.rooms)? }, GameMessage::ChargeAttack(charge_attack) => { handler::message::charge_attack(id, charge_attack, &mut self.clients, &mut self.entity_gateway).await? }, GameMessage::PlayerUseItem(player_use_item) => { - handler::message::use_item(id, player_use_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager).await? + let block = self.blocks.with_client(id, &self.clients)?; + handler::message::use_item(id, player_use_item, &mut self.entity_gateway, &mut block.client_location, &mut self.clients, &mut self.item_manager).await? }, GameMessage::PlayerUsedMedicalCenter(player_used_medical_center) => { handler::message::player_used_medical_center(id, &player_used_medical_center, &mut self.entity_gateway, &mut self.clients).await? }, GameMessage::PlayerFeedMag(player_feed_mag) => { - handler::message::player_feed_mag(id, &player_feed_mag, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager).await? + let block = self.blocks.with_client(id, &self.clients)?; + handler::message::player_feed_mag(id, &player_feed_mag, &mut self.entity_gateway, &mut block.client_location, &mut self.clients, &mut self.item_manager).await? }, GameMessage::PlayerEquipItem(player_equip_item) => { handler::message::player_equips_item(id, &player_equip_item, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager).await? @@ -438,7 +479,8 @@ impl ShipServerState { }, _ => { let cmsg = msg.clone(); - Box::new(self.client_location.get_client_neighbors(id).unwrap().into_iter() + let block = self.blocks.with_client(id, &self.clients)?; + Box::new(block.client_location.get_client_neighbors(id).unwrap().into_iter() .map(move |client| { (client.client, SendShipPacket::Message(cmsg.clone())) })) @@ -450,32 +492,40 @@ impl ShipServerState { let target = msg.flag; Ok(match &msg.msg { GameMessage::GuildcardSend(guildcard_send) => { - handler::direct_message::guildcard_send(id, guildcard_send, target, &self.client_location, &self.clients) + let block = self.blocks.with_client(id, &self.clients)?; + handler::direct_message::guildcard_send(id, guildcard_send, target, &block.client_location, &self.clients) }, GameMessage::RequestItem(request_item) => { - handler::direct_message::request_item(id, request_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.rooms, &mut self.item_manager).await? + let block = self.blocks.with_client(id, &self.clients)?; + handler::direct_message::request_item(id, request_item, &mut self.entity_gateway, &mut block.client_location, &mut self.clients, &mut block.rooms, &mut self.item_manager).await? }, GameMessage::PickupItem(pickup_item) => { - handler::direct_message::pickup_item(id, pickup_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager).await? + let block = self.blocks.with_client(id, &self.clients)?; + handler::direct_message::pickup_item(id, pickup_item, &mut self.entity_gateway, &mut block.client_location, &mut self.clients, &mut self.item_manager).await? }, GameMessage::BoxDropRequest(box_drop_request) => { - handler::direct_message::request_box_item(id, box_drop_request, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.rooms, &mut self.item_manager).await? + let block = self.blocks.with_client(id, &self.clients)?; + handler::direct_message::request_box_item(id, box_drop_request, &mut self.entity_gateway, &mut block.client_location, &mut self.clients, &mut block.rooms, &mut self.item_manager).await? }, GameMessage::BankRequest(_bank_request) => { handler::direct_message::send_bank_list(id, &self.clients, &mut self.item_manager).await? }, GameMessage::BankInteraction(bank_interaction) => { - handler::direct_message::bank_interaction(id, bank_interaction, &mut self.entity_gateway, &self.client_location, &mut self.clients, &mut self.item_manager).await? + let block = self.blocks.with_client(id, &self.clients)?; + handler::direct_message::bank_interaction(id, bank_interaction, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_manager).await? }, GameMessage::ShopRequest(shop_request) => { - handler::direct_message::shop_request(id, shop_request, &self.client_location, &mut self.clients, &self.rooms, &self.level_table, &mut self.shops).await? + let block = self.blocks.with_client(id, &self.clients)?; + handler::direct_message::shop_request(id, shop_request, &block.client_location, &mut self.clients, &block.rooms, &self.level_table, &mut self.shops).await? }, GameMessage::BuyItem(buy_item) => { - handler::direct_message::buy_item(id, buy_item, &mut self.entity_gateway, &self.client_location, &mut self.clients, &mut self.item_manager).await? + let block = self.blocks.with_client(id, &self.clients)?; + handler::direct_message::buy_item(id, buy_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_manager).await? }, _ => { let cmsg = msg.clone(); - Box::new(self.client_location.get_all_clients_by_client(id).unwrap().into_iter() + let block = self.blocks.with_client(id, &self.clients)?; + Box::new(block.client_location.get_all_clients_by_client(id).unwrap().into_iter() .filter(move |client| client.local_client.id() == target as u8) .map(move |client| { (client.client, SendShipPacket::DirectMessage(cmsg.clone())) @@ -509,7 +559,8 @@ impl ServerState for ShipServerState { -> Result + Send>, anyhow::Error> { Ok(match pkt { RecvShipPacket::Login(login) => { - Box::new(handler::auth::validate_login(id, login, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager, &self.shipgate_sender, &self.name).await?.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_manager, &self.shipgate_sender, &self.name, self.blocks.0.len()) + .await?.into_iter().map(move |pkt| (id, pkt))) }, RecvShipPacket::QuestDetailRequest(questdetailrequest) => { match questdetailrequest.menu { @@ -518,37 +569,41 @@ impl ServerState for ShipServerState { } }, RecvShipPacket::MenuSelect(menuselect) => { + let block = self.blocks.with_client(id, &self.clients)?; match menuselect.menu { SHIP_MENU_ID => handler::ship::selected_ship(id, menuselect, &self.ship_list)?, BLOCK_MENU_ID => Box::new(handler::lobby::block_selected(id, menuselect, &mut self.clients, &self.item_manager, &self.level_table)?.into_iter().map(move |pkt| (id, pkt))), - ROOM_MENU_ID => handler::room::join_room(id, menuselect, &mut self.client_location, &mut self.clients, &mut self.item_manager, &self.level_table, &mut self.rooms)?, + ROOM_MENU_ID => handler::room::join_room(id, menuselect, &mut block.client_location, &mut self.clients, &mut self.item_manager, &self.level_table, &mut block.rooms)?, QUEST_CATEGORY_MENU_ID => handler::quest::select_quest_category(id, menuselect, &self.quests)?, _ => unreachable!(), } }, RecvShipPacket::QuestMenuSelect(questmenuselect) => { - handler::quest::load_quest(id, questmenuselect, &self.quests, &mut self.clients, &self.client_location, &mut self.rooms)? + let block = self.blocks.with_client(id, &self.clients)?; + handler::quest::load_quest(id, questmenuselect, &self.quests, &mut self.clients, &block.client_location, &mut block.rooms)? }, RecvShipPacket::MenuDetail(_menudetail) => { //unreachable!(); Box::new(Vec::new().into_iter()) }, RecvShipPacket::RoomPasswordReq(room_password_req) => { - if room_password_req.password == self.rooms[room_password_req.item as usize].as_ref() + let block = self.blocks.with_client(id, &self.clients)?; + if room_password_req.password == block.rooms[room_password_req.item as usize].as_ref() .ok_or(ShipError::InvalidRoom(room_password_req.item))? .password { - let menuselect = MenuSelect { - menu: room_password_req.menu, - item: room_password_req.item, - }; - handler::room::join_room(id, &menuselect, &mut self.client_location, &mut self.clients, &mut self.item_manager, &self.level_table, &mut self.rooms)? - } + let menuselect = MenuSelect { + menu: room_password_req.menu, + item: room_password_req.item, + }; + handler::room::join_room(id, &menuselect, &mut block.client_location, &mut self.clients, &mut self.item_manager, &self.level_table, &mut block.rooms)? + } else { Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("Incorrect password".into())))].into_iter()) } }, RecvShipPacket::CharData(chardata) => { - Box::new(handler::lobby::send_player_to_lobby(id, chardata, &mut self.client_location, &self.clients, &self.item_manager, &self.level_table)?.into_iter()) + let block = self.blocks.with_client(id, &self.clients)?; + Box::new(handler::lobby::send_player_to_lobby(id, chardata, &mut block.client_location, &self.clients, &self.item_manager, &self.level_table)?.into_iter()) }, RecvShipPacket::Message(msg) => { self.message(id, msg).await? @@ -557,41 +612,50 @@ impl ServerState for ShipServerState { self.direct_message(id, msg).await? }, RecvShipPacket::PlayerChat(msg) => { - Box::new(handler::communication::player_chat(id, msg, &self.client_location, &self.clients)?.into_iter()) + let block = self.blocks.with_client(id, &self.clients)?; + Box::new(handler::communication::player_chat(id, msg, &block.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.item_manager, &mut self.rooms)? + let block = self.blocks.with_client(id, &self.clients)?; + handler::room::create_room(id, create_room, &mut block.client_location, &mut self.clients, &mut self.item_manager, &mut block.rooms)? }, RecvShipPacket::RoomNameRequest(_req) => { - handler::room::room_name_request(id, &self.client_location, &self.rooms) + let block = self.blocks.with_client(id, &self.clients)?; + handler::room::room_name_request(id, &block.client_location, &block.rooms) }, RecvShipPacket::UpdateConfig(pkt) => { handler::settings::update_config(id, pkt, &mut self.clients, &mut self.entity_gateway).await }, RecvShipPacket::ViewInfoboardRequest(_pkt) => { - handler::communication::request_infoboard(id, &self.client_location, &self.clients) + let block = self.blocks.with_client(id, &self.clients)?; + handler::communication::request_infoboard(id, &block.client_location, &self.clients) }, RecvShipPacket::WriteInfoboard(pkt) => { handler::communication::write_infoboard(id, pkt, &mut self.clients, &mut self.entity_gateway).await }, RecvShipPacket::RoomListRequest(_req) => { - handler::room::request_room_list(id, &self.client_location, &self.rooms) + let block = self.blocks.with_client(id, &self.clients)?; + handler::room::request_room_list(id, &block.client_location, &block.rooms) }, RecvShipPacket::Like62ButCooler(cool62) => { - handler::room::cool_62(id, cool62, &self.client_location) + let block = self.blocks.with_client(id, &self.clients)?; + handler::room::cool_62(id, cool62, &block.client_location) }, RecvShipPacket::ClientCharacterData(_) => { // TOOD: validate this in some way? Box::new(None.into_iter()) }, RecvShipPacket::DoneBursting(_) => { - handler::room::done_bursting(id, &self.client_location, &mut self.rooms) + let block = self.blocks.with_client(id, &self.clients)?; + handler::room::done_bursting(id, &block.client_location, &mut block.rooms) }, RecvShipPacket::DoneBursting2(_) => { - handler::room::done_bursting(id, &self.client_location, &mut self.rooms) + let block = self.blocks.with_client(id, &self.clients)?; + handler::room::done_bursting(id, &block.client_location, &mut block.rooms) }, RecvShipPacket::LobbySelect(pkt) => { - Box::new(handler::lobby::change_lobby(id, pkt.lobby, &mut self.client_location, &self.clients, &mut self.item_manager, &self.level_table, &mut self.rooms, &mut self.entity_gateway).await?.into_iter()) + let block = self.blocks.with_client(id, &self.clients)?; + Box::new(handler::lobby::change_lobby(id, pkt.lobby, &mut block.client_location, &self.clients, &mut self.item_manager, &self.level_table, &mut block.rooms, &mut self.entity_gateway).await?.into_iter()) }, RecvShipPacket::RequestQuestList(_) => { handler::quest::send_quest_category_list(id, &self.quests)? @@ -603,7 +667,8 @@ impl ServerState for ShipServerState { handler::quest::quest_chunk_ack(id, quest_chunk_ack, &self.quests)? }, RecvShipPacket::DoneLoadingQuest(_) => { - handler::quest::done_loading_quest(id, &mut self.clients, &self.client_location)? + let block = self.blocks.with_client(id, &self.clients)?; + handler::quest::done_loading_quest(id, &mut self.clients, &block.client_location)? }, RecvShipPacket::FullCharacterData(_full_character_data) => { Box::new(None.into_iter()) @@ -622,19 +687,20 @@ impl ServerState for ShipServerState { async fn on_disconnect(&mut self, id: ClientId) -> Result, anyhow::Error> { let client = self.clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; - let area_client = self.client_location.get_local_client(id)?; - let neighbors = self.client_location.get_client_neighbors(id)?; + let block = self.blocks.with_client(id, &self.clients)?; + let area_client = block.client_location.get_local_client(id)?; + let neighbors = block.client_location.get_client_neighbors(id)?; - let pkt = match self.client_location.get_area(id)? { + let pkt = match block.client_location.get_area(id)? { RoomLobby::Room(room) => { if neighbors.len() == 0 { - self.rooms[room.0] = None; + block.rooms[room.0] = None; } - let leader = self.client_location.get_room_leader(room)?; + let leader = block.client_location.get_room_leader(room)?; SendShipPacket::LeaveRoom(LeaveRoom::new(area_client.local_client.id(), leader.local_client.id())) }, RoomLobby::Lobby(lobby) => { - let leader = self.client_location.get_lobby_leader(lobby)?; + let leader = block.client_location.get_lobby_leader(lobby)?; SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id())) } }; @@ -643,7 +709,7 @@ impl ServerState for ShipServerState { shipgate_sender(ShipMessage::RemoveUser(client.user.id.clone())); } - self.client_location.remove_client_from_area(id); + block.client_location.remove_client_from_area(id); self.item_manager.remove_character_from_room(&client.character); if let Some(mut client) = self.clients.remove(&id) {