From 4202ef8ff71c6ebbdae43963a34aa43128f140de Mon Sep 17 00:00:00 2001 From: andy Date: Thu, 7 Jul 2022 00:00:04 +0000 Subject: [PATCH] handle rooms that close after downloading the room list in the lobby --- src/ship/packet/handler/lobby.rs | 31 +++++---- src/ship/packet/handler/room.rs | 110 ++++++++++++++++--------------- src/ship/ship.rs | 2 +- 3 files changed, 76 insertions(+), 67 deletions(-) diff --git a/src/ship/packet/handler/lobby.rs b/src/ship/packet/handler/lobby.rs index ae9edee..ff2a0c2 100644 --- a/src/ship/packet/handler/lobby.rs +++ b/src/ship/packet/handler/lobby.rs @@ -134,21 +134,26 @@ pub fn remove_from_lobby(id: ClientId, pub fn get_room_tab_info(id: ClientId, pkt: &MenuDetail, client_location: &mut ClientLocation, - clients: &Clients) + clients: &Clients, + rooms: &mut Rooms) -> Result, anyhow::Error> { let room_id = RoomId(pkt.item as usize); - let clients_in_room = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?; - let mut room_info = String::new(); - for client in clients_in_room { - let cs = clients.get(&client.client).ok_or(ShipError::ClientNotFound(client.client))?; - let gc = cs.user.guildcard; - let name = &cs.character.name; - let cls = cs.character.char_class; - let leveltable = CharacterLevelTable::default(); - let lv = leveltable.get_level_from_exp(cls, cs.character.exp); - let floor = cs.area.unwrap_or(MapArea::Pioneer2Ep1); + if let Some(_room) = rooms.get(pkt.item as usize).ok_or(ShipError::InvalidRoom(pkt.item))? { + let mut room_info = String::new(); + let clients_in_room = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?; + for client in clients_in_room { + let cs = clients.get(&client.client).ok_or(ShipError::ClientNotFound(client.client))?; + let gc = cs.user.guildcard; + let name = &cs.character.name; + let cc = cs.character.char_class; + let leveltable = CharacterLevelTable::default(); + let lv = leveltable.get_level_from_exp(cc, cs.character.exp); + let floor = cs.area.unwrap_or(MapArea::Pioneer2Ep1); - room_info += format!("{} Lv{} {}\n{} {}\n", gc,lv,name,cls,floor).as_str(); + room_info += format!("{} Lv{} {}\n{} {}\n", gc,lv,name,cc,floor).as_str(); + } + Ok(vec![(id, SendShipPacket::SmallLeftDialog(SmallLeftDialog::new(room_info)))]) + } else { + Ok(vec![(id, SendShipPacket::SmallLeftDialog(SmallLeftDialog::new("Game is no longer active".into())))]) } - Ok(vec![(id, SendShipPacket::SmallLeftDialog(SmallLeftDialog::new(room_info)))]) } \ No newline at end of file diff --git a/src/ship/packet/handler/room.rs b/src/ship/packet/handler/room.rs index ba82b2b..9e89469 100644 --- a/src/ship/packet/handler/room.rs +++ b/src/ship/packet/handler/room.rs @@ -86,62 +86,66 @@ pub fn join_room(id: ClientId, -> Result + Send>, ShipError> { let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; let level = level_table.get_level_from_exp(client.character.char_class, client.character.exp); - let room = rooms.get(pkt.item as usize).ok_or(ShipError::InvalidRoom(pkt.item))?.as_ref().unwrap(); // clippy look what you made me do + // let room = rooms.get(pkt.item as usize).ok_or(ShipError::InvalidRoom(pkt.item))?.as_ref().unwrap(); // clippy look what you made me do + if let Some(room) = rooms.get(pkt.item as usize).ok_or(ShipError::InvalidRoom(pkt.item))? { - match room.mode.difficulty() { - room::Difficulty::Ultimate => { - if level < 80 { - return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 80 \nto join Ultimate rooms.".into())))].into_iter())) - } - }, - room::Difficulty::VeryHard => { - if level < 40 { - return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 40 \nto join Very Hard rooms.".into())))].into_iter())) - } - }, - room::Difficulty::Hard => { - if level < 20 { - return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 20 \nto join Hard rooms.".into())))].into_iter())) - } - }, - _ => {}, - }; - - let original_area = client_location.get_area(id).unwrap(); - let original_neighbors = client_location.get_client_neighbors(id).unwrap(); - if room.bursting { - 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| -> ClientLocationError { err.into() })?; - client_location.add_client_to_room(id, room_id).unwrap(); // TODO: show room full error or whatever - - let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; - let area_client = client_location.get_local_client(id).map_err(|err| -> ClientLocationError { err.into() })?; - - item_manager.add_character_to_room(room_id, &client.character, area_client); - - let leader = client_location.get_room_leader(room_id).map_err(|err| -> ClientLocationError { err.into() })?; - 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, item_manager, 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.into_iter() - .map(move |c| (c.client, SendShipPacket::AddToRoom(add_to.clone()))) - )); + match room.mode.difficulty() { + room::Difficulty::Ultimate => { + if level < 80 { + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 80 \nto join Ultimate rooms.".into())))].into_iter())) + } + }, + room::Difficulty::VeryHard => { + if level < 40 { + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 40 \nto join Very Hard rooms.".into())))].into_iter())) + } + }, + room::Difficulty::Hard => { + if level < 20 { + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 20 \nto join Hard rooms.".into())))].into_iter())) + } + }, + _ => {}, + }; - 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())); - result = Box::new(result.chain(original_neighbors.into_iter() - .map(move |c| (c.client, leave_lobby.clone())))) + let original_area = client_location.get_area(id).unwrap(); + let original_neighbors = client_location.get_client_neighbors(id).unwrap(); + if room.bursting { + 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| -> ClientLocationError { err.into() })?; + client_location.add_client_to_room(id, room_id).unwrap(); // TODO: show room full error or whatever + + let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; + let area_client = client_location.get_local_client(id).map_err(|err| -> ClientLocationError { err.into() })?; + + item_manager.add_character_to_room(room_id, &client.character, area_client); + + let leader = client_location.get_room_leader(room_id).map_err(|err| -> ClientLocationError { err.into() })?; + 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, item_manager, 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.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())); + result = Box::new(result.chain(original_neighbors.into_iter() + .map(move |c| (c.client, leave_lobby.clone())))) + } + + Ok(result) + } else { + Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("Game is no longer active".into())))].into_iter())) } - - Ok(result) } pub fn done_bursting(id: ClientId, diff --git a/src/ship/ship.rs b/src/ship/ship.rs index 304eac3..d375520 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -640,7 +640,7 @@ impl ServerState for ShipServerState { }, RecvShipPacket::MenuDetail(menudetail) => { let block = self.blocks.with_client(id, &self.clients)?; - Box::new(handler::lobby::get_room_tab_info(id, menudetail, &mut block.client_location, &mut self.clients)?.into_iter()) + Box::new(handler::lobby::get_room_tab_info(id, menudetail, &mut block.client_location, &mut self.clients, &mut block.rooms)?.into_iter()) }, RecvShipPacket::RoomPasswordReq(room_password_req) => { let block = self.blocks.with_client(id, &self.clients)?;