diff --git a/src/ship/packet/handler/room.rs b/src/ship/packet/handler/room.rs index 3a5fc6c..f5f2a85 100644 --- a/src/ship/packet/handler/room.rs +++ b/src/ship/packet/handler/room.rs @@ -7,12 +7,13 @@ use libpso::packet::ship::*; use libpso::packet::messages::*; use crate::common::serverstate::ClientId; use crate::common::leveltable::LEVEL_TABLE; +use crate::entity::character::SectionID; +use crate::ship::drops::DropTable; use crate::ship::ship::{SendShipPacket, Clients, ShipEvent}; -use crate::ship::room::Rooms; +use crate::ship::room::{Rooms, Episode, Difficulty, RoomState}; use crate::ship::map::MapBuilder; use crate::ship::location::{ClientLocation, RoomId, RoomLobby, GetAreaError}; use crate::ship::packet::builder; -use crate::ship::room; use crate::ship::items::state::ItemState; pub async fn create_room(id: ClientId, @@ -22,19 +23,20 @@ pub async fn create_room(id: ClientId, item_state: &mut ItemState, rooms: &Rooms, map_builder: Arc>, + drop_table_builder: Arc DropTable + Send + Sync>>, event: ShipEvent) -> Result, anyhow::Error> { let level = clients.with(id, |client| Box::pin(async move { LEVEL_TABLE.get_level_from_exp(client.character.char_class, client.character.exp) })).await?; - match room::Difficulty::try_from(create_room.difficulty)? { - room::Difficulty::Ultimate if level < 80 => { + match Difficulty::try_from(create_room.difficulty)? { + Difficulty::Ultimate if level < 80 => { return Ok(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 80 \nto create Ultimate rooms.".into())))]) }, - room::Difficulty::VeryHard if level < 40 => { + Difficulty::VeryHard if level < 40 => { return Ok(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 40 \nto create Very Hard rooms.".into())))]) }, - room::Difficulty::Hard if level < 20 => { + Difficulty::Hard if level < 20 => { return Ok(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 20 \nto create Hard rooms.".into())))]) }, _ => {}, @@ -49,7 +51,7 @@ pub async fn create_room(id: ClientId, let mut item_state = item_state.clone(); Box::pin(async move { item_state.add_character_to_room(room_id, &client.character, area_client).await; - let mut room = room::RoomState::from_create_room(&create_room, map_builder, client.character.section_id, event)?; + let mut room = RoomState::from_create_room(&create_room, map_builder, drop_table_builder, client.character.section_id, event)?; room.bursting = true; Ok::<_, anyhow::Error>(room) })}).await??; @@ -107,13 +109,13 @@ pub async fn join_room(id: ClientId, })).await?; match difficulty { - room::Difficulty::Ultimate if level < 80 => { + Difficulty::Ultimate if level < 80 => { return Ok(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 80 \nto join Ultimate rooms.".into())))]) }, - room::Difficulty::VeryHard if level < 40 => { + Difficulty::VeryHard if level < 40 => { return Ok(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 40 \nto join Very Hard rooms.".into())))]) }, - room::Difficulty::Hard if level < 20 => { + Difficulty::Hard if level < 20 => { return Ok(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 20 \nto join Hard rooms.".into())))]) }, _ => {}, diff --git a/src/ship/room.rs b/src/ship/room.rs index 31e0b87..6b9462a 100644 --- a/src/ship/room.rs +++ b/src/ship/room.rs @@ -359,6 +359,7 @@ impl RoomState { pub fn from_create_room(create_room: &libpso::packet::ship::CreateRoom, map_builder: Arc>, + drop_table_builder: Arc DropTable + Send + Sync>>, section_id: SectionID, event: ShipEvent) -> Result { @@ -418,8 +419,6 @@ impl RoomState { room_quests.push(quest_list); } - - Ok(RoomState { monster_stats: Box::new(load_monster_stats_table(&room_mode).map_err(|_| RoomCreationError::CouldNotLoadMonsterStats(room_mode))?), mode: room_mode, @@ -428,7 +427,7 @@ impl RoomState { password: create_room.password, maps: map_builder.generate_maps(room_mode, event), section_id, - drop_table: Box::new(DropTable::new(room_mode.episode(), room_mode.difficulty(), section_id)), + drop_table: Box::new(drop_table_builder(room_mode.episode(), room_mode.difficulty(), section_id)), bursting: false, map_areas: MapAreaLookup::new(&room_mode.episode()), quest_group: QuestCategoryType::Standard, diff --git a/src/ship/ship.rs b/src/ship/ship.rs index 02c2ecd..8576b69 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -30,9 +30,10 @@ use crate::entity::character::SectionID; use crate::ship::location::{ClientLocation, RoomLobby, ClientLocationError, RoomId}; +use crate::ship::drops::DropTable; use crate::ship::items; use crate::ship::room; -use crate::ship::map::{Maps, MapBuilder, FreeRoamMapBuilder, MapsError, MapAreaError}; +use crate::ship::map::{MapBuilder, FreeRoamMapBuilder, MapsError, MapAreaError}; use crate::ship::packet::handler; use crate::ship::shops::{WeaponShop, ToolShop, ArmorShop}; use crate::ship::trade::TradeState; @@ -380,6 +381,7 @@ pub struct ShipServerStateBuilder { auth_token: Option, event: Option, map_builder: Option>, + drop_table_builder: Option DropTable + Send + Sync>>, num_blocks: usize, } @@ -393,6 +395,7 @@ impl Default for ShipServerStateBuilder auth_token: None, event: None, map_builder: None, + drop_table_builder: None, num_blocks: 2, } } @@ -441,6 +444,12 @@ impl ShipServerStateBuilder { self } + #[must_use] + pub fn drop_table_builder(mut self, drop_table_builder: Box DropTable + Send + Sync>) -> ShipServerStateBuilder { + self.drop_table_builder = Some(drop_table_builder); + self + } + #[must_use] pub fn blocks(mut self, num_blocks: usize) -> ShipServerStateBuilder { self.num_blocks = num_blocks; @@ -460,6 +469,7 @@ impl ShipServerStateBuilder { blocks: Blocks(blocks), event: self.event.unwrap_or(ShipEvent::None), map_builder: Arc::new(self.map_builder.unwrap_or(Box::new(FreeRoamMapBuilder::new()))), + drop_table_builder: Arc::new(self.drop_table_builder.unwrap_or(Box::new(DropTable::new))), auth_token: self.auth_token.unwrap_or_else(|| AuthToken("".into())), ship_list: Arc::new(RwLock::new(Vec::new())), @@ -509,6 +519,7 @@ pub struct ShipServerState { shipgate_sender: Option>, trades: TradeState, map_builder: Arc>, + drop_table_builder: Arc DropTable + Send + Sync>>, } impl ShipServerState { @@ -735,7 +746,7 @@ impl ServerState for ShipServerState { }, RecvShipPacket::CreateRoom(create_room) => { let block = self.blocks.get_from_client(id, &self.clients).await?; - handler::room::create_room(id, create_room, &mut block.client_location, &self.clients, &mut self.item_state, &block.rooms, self.map_builder.clone(), self.event).await? + handler::room::create_room(id, create_room, &mut block.client_location, &self.clients, &mut self.item_state, &block.rooms, self.map_builder.clone(), self.drop_table_builder.clone(), self.event).await? }, RecvShipPacket::RoomNameRequest(_req) => { let block = self.blocks.get_from_client(id, &self.clients).await?;