Merge pull request 'make CharacterLevelTable a global const lookup table cause whynot' (#118) from global_leveltable into master
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				continuous-integration/drone/push Build is passing
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	continuous-integration/drone/push Build is passing
				
			Reviewed-on: #118
This commit is contained in:
		
						commit
						2d880d8cf0
					
				| @ -1,7 +1,9 @@ | |||||||
| use std::collections::HashMap; |  | ||||||
| use std::fs::File; | use std::fs::File; | ||||||
| use serde_json::Value; | use serde_json::Value; | ||||||
| use crate::entity::character::CharacterClass; | use crate::entity::character::CharacterClass; | ||||||
|  | use std::sync::LazyLock; | ||||||
|  | 
 | ||||||
|  | pub static LEVEL_TABLE: LazyLock<CharacterLevelTable> = LazyLock::new(CharacterLevelTable::default); | ||||||
| 
 | 
 | ||||||
| #[derive(Default, Copy, Clone, Debug, PartialEq, Eq)] | #[derive(Default, Copy, Clone, Debug, PartialEq, Eq)] | ||||||
| pub struct CharacterStats { | pub struct CharacterStats { | ||||||
| @ -27,14 +29,14 @@ struct CharacterLevelEntry { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub struct CharacterLevelTable { | pub struct CharacterLevelTable { | ||||||
|     table: HashMap<CharacterClass, [CharacterLevelEntry; 200]>, |     table: Box<[[CharacterLevelEntry; 200]; 12]>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Default for CharacterLevelTable { | impl Default for CharacterLevelTable { | ||||||
|     fn default() -> CharacterLevelTable { |     fn default() -> CharacterLevelTable { | ||||||
|         let file = File::open("data/char_stats.json").unwrap(); |         let file = File::open("data/char_stats.json").unwrap(); | ||||||
|         let json: Value = serde_json::from_reader(file).unwrap(); |         let json: Value = serde_json::from_reader(file).unwrap(); | ||||||
|         let mut table = HashMap::new(); |         let mut table = Box::new([[CharacterLevelEntry::default(); 200]; 12]); | ||||||
| 
 | 
 | ||||||
|         for it in json.as_object().unwrap().iter(){ |         for it in json.as_object().unwrap().iter(){ | ||||||
|             let cl = match it.0.as_str() { |             let cl = match it.0.as_str() { | ||||||
| @ -67,7 +69,7 @@ impl Default for CharacterLevelTable { | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             table.insert(cl, statlist); |             table[u8::from(cl) as usize] = statlist; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         CharacterLevelTable { |         CharacterLevelTable { | ||||||
| @ -78,7 +80,7 @@ impl Default for CharacterLevelTable { | |||||||
| 
 | 
 | ||||||
| impl CharacterLevelTable { | impl CharacterLevelTable { | ||||||
|     pub fn get_level_from_exp(&self, ch_class: CharacterClass, exp: u32) -> u32 { |     pub fn get_level_from_exp(&self, ch_class: CharacterClass, exp: u32) -> u32 { | ||||||
|         if let Some(statlist) = self.table.get(&ch_class) { |         if let Some(statlist) = self.table.get(u8::from(ch_class) as usize) { | ||||||
|             statlist |             statlist | ||||||
|                 .iter() |                 .iter() | ||||||
|                 .filter(|stat| { |                 .filter(|stat| { | ||||||
| @ -92,7 +94,7 @@ impl CharacterLevelTable { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn get_stats_from_exp(&self, ch_class: CharacterClass, exp: u32) -> (u32, CharacterStats) { |     pub fn get_stats_from_exp(&self, ch_class: CharacterClass, exp: u32) -> (u32, CharacterStats) { | ||||||
|         if let Some(statlist) = self.table.get(&ch_class) { |         if let Some(statlist) = self.table.get(u8::from(ch_class) as usize) { | ||||||
|             statlist |             statlist | ||||||
|                 .iter() |                 .iter() | ||||||
|                 .filter(|stat| { |                 .filter(|stat| { | ||||||
|  | |||||||
| @ -1,3 +1,6 @@ | |||||||
|  | // this lint is currently bugged and suggests incorrect code https://github.com/rust-lang/rust-clippy/issues/9123
 | ||||||
|  | #![allow(clippy::explicit_auto_deref)] | ||||||
|  | 
 | ||||||
| use std::convert::{From, TryFrom, Into}; | use std::convert::{From, TryFrom, Into}; | ||||||
| use futures::{Future, TryStreamExt}; | use futures::{Future, TryStreamExt}; | ||||||
| use async_std::stream::StreamExt; | use async_std::stream::StreamExt; | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ | |||||||
| #![feature(inline_const)] | #![feature(inline_const)] | ||||||
| #![feature(drain_filter)] | #![feature(drain_filter)] | ||||||
| #![feature(try_blocks)] | #![feature(try_blocks)] | ||||||
|  | #![feature(once_cell)] | ||||||
| 
 | 
 | ||||||
| extern crate fix_hidden_lifetime_bug; | extern crate fix_hidden_lifetime_bug; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -16,6 +16,7 @@ use crate::ship::drops::generic_weapon::AttributeTable; | |||||||
| use crate::ship::drops::generic_armor::GenericArmorTable; | use crate::ship::drops::generic_armor::GenericArmorTable; | ||||||
| use crate::ship::drops::generic_shield::GenericShieldTable; | use crate::ship::drops::generic_shield::GenericShieldTable; | ||||||
| 
 | 
 | ||||||
|  | type ItemParseFn = Box<dyn Fn(&String) -> Option<RareDropItem>>; | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, Copy, Clone)] | #[derive(Debug, Copy, Clone)] | ||||||
| pub enum RareDropItem { | pub enum RareDropItem { | ||||||
| @ -29,7 +30,7 @@ pub enum RareDropItem { | |||||||
| 
 | 
 | ||||||
| impl RareDropItem { | impl RareDropItem { | ||||||
|     pub fn from_string(name: String) -> RareDropItem { |     pub fn from_string(name: String) -> RareDropItem { | ||||||
|         let parse_funcs: [Box<dyn Fn(&String) -> Option<RareDropItem>>; 6] = [ |         let parse_funcs: [ItemParseFn; 6] = [ | ||||||
|             Box::new(|i| Some(RareDropItem::Weapon(str::parse::<WeaponType>(i).ok()?))), |             Box::new(|i| Some(RareDropItem::Weapon(str::parse::<WeaponType>(i).ok()?))), | ||||||
|             Box::new(|i| Some(RareDropItem::Armor(str::parse::<ArmorType>(i).ok()?))), |             Box::new(|i| Some(RareDropItem::Armor(str::parse::<ArmorType>(i).ok()?))), | ||||||
|             Box::new(|i| Some(RareDropItem::Shield(str::parse::<ShieldType>(i).ok()?))), |             Box::new(|i| Some(RareDropItem::Shield(str::parse::<ShieldType>(i).ok()?))), | ||||||
|  | |||||||
| @ -330,7 +330,7 @@ impl<'a> ItemStateProxy<'a> { | |||||||
|         self.item_state.character_bank.extend(self.proxied_state.character_bank.clone()); |         self.item_state.character_bank.extend(self.proxied_state.character_bank.clone()); | ||||||
|         self.item_state.character_room.extend(self.proxied_state.character_room.clone()); |         self.item_state.character_room.extend(self.proxied_state.character_room.clone()); | ||||||
|         self.item_state.character_floor.extend(self.proxied_state.character_floor.clone()); |         self.item_state.character_floor.extend(self.proxied_state.character_floor.clone()); | ||||||
|         self.item_state.room_floor.extend(self.proxied_state.room_floor.clone()); |         self.item_state.room_floor.extend(self.proxied_state.room_floor); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,6 +1,5 @@ | |||||||
| use libpso::packet::ship::*; | use libpso::packet::ship::*; | ||||||
| use crate::common::serverstate::ClientId; | use crate::common::serverstate::ClientId; | ||||||
| use crate::common::leveltable::CharacterLevelTable; |  | ||||||
| use crate::ship::ship::{ShipError, Clients}; | use crate::ship::ship::{ShipError, Clients}; | ||||||
| use crate::ship::location::{ClientLocation, LobbyId, ClientLocationError}; | use crate::ship::location::{ClientLocation, LobbyId, ClientLocationError}; | ||||||
| use crate::ship::packet::builder::{player_info}; | use crate::ship::packet::builder::{player_info}; | ||||||
| @ -11,14 +10,13 @@ pub fn join_lobby(id: ClientId, | |||||||
|                   lobby: LobbyId, |                   lobby: LobbyId, | ||||||
|                   client_location: &ClientLocation, |                   client_location: &ClientLocation, | ||||||
|                   clients: &Clients, |                   clients: &Clients, | ||||||
|                   item_state: &ItemState, |                   item_state: &ItemState) | ||||||
|                   level_table: &CharacterLevelTable) |  | ||||||
|                   -> Result<JoinLobby, anyhow::Error> { |                   -> Result<JoinLobby, anyhow::Error> { | ||||||
|     let lobby_clients = client_location.get_clients_in_lobby(lobby).map_err(|err| -> ClientLocationError { err.into() })?; |     let lobby_clients = client_location.get_clients_in_lobby(lobby).map_err(|err| -> ClientLocationError { err.into() })?; | ||||||
|     let playerinfo = lobby_clients.iter() |     let playerinfo = lobby_clients.iter() | ||||||
|         .map(|area_client| { |         .map(|area_client| { | ||||||
|             let client = clients.get(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client)).unwrap(); |             let client = clients.get(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client)).unwrap(); | ||||||
|             player_info(0x100, client, area_client, item_state, level_table) |             player_info(0x100, client, area_client, item_state) | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|     let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); |     let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); | ||||||
| @ -40,8 +38,7 @@ pub fn add_to_lobby(id: ClientId, | |||||||
|                     lobby: LobbyId, |                     lobby: LobbyId, | ||||||
|                     client_location: &ClientLocation, |                     client_location: &ClientLocation, | ||||||
|                     clients: &Clients, |                     clients: &Clients, | ||||||
|                     item_state: &ItemState, |                     item_state: &ItemState) | ||||||
|                     level_table: &CharacterLevelTable) |  | ||||||
|                     -> Result<AddToLobby, ShipError> { |                     -> Result<AddToLobby, ShipError> { | ||||||
|     let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); |     let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); | ||||||
|     let area_client = client_location.get_local_client(id).map_err(|err| -> ClientLocationError { err.into() })?; |     let area_client = client_location.get_local_client(id).map_err(|err| -> ClientLocationError { err.into() })?; | ||||||
| @ -55,7 +52,7 @@ pub fn add_to_lobby(id: ClientId, | |||||||
|         block: client.block as u16, |         block: client.block as u16, | ||||||
|         event: 0, |         event: 0, | ||||||
|         padding: 0, |         padding: 0, | ||||||
|         playerinfo: player_info(0x100, client, &area_client, item_state, level_table), |         playerinfo: player_info(0x100, client, &area_client, item_state), | ||||||
|     }) |     }) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -6,7 +6,7 @@ pub mod ship; | |||||||
| 
 | 
 | ||||||
| use libpso::character::character::Inventory; | use libpso::character::character::Inventory; | ||||||
| use libpso::packet::ship::{PlayerHeader, PlayerInfo}; | use libpso::packet::ship::{PlayerHeader, PlayerInfo}; | ||||||
| use crate::common::leveltable::CharacterLevelTable; | use crate::common::leveltable::LEVEL_TABLE; | ||||||
| use crate::ship::character::CharacterBytesBuilder; | use crate::ship::character::CharacterBytesBuilder; | ||||||
| use crate::ship::ship::ClientState; | use crate::ship::ship::ClientState; | ||||||
| use crate::ship::location::AreaClient; | use crate::ship::location::AreaClient; | ||||||
| @ -23,8 +23,8 @@ pub fn player_header(tag: u32, client: &ClientState, area_client: &AreaClient) - | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn player_info(tag: u32, client: &ClientState, area_client: &AreaClient, item_state: &ItemState, level_table: &CharacterLevelTable) -> PlayerInfo { | pub fn player_info(tag: u32, client: &ClientState, area_client: &AreaClient, item_state: &ItemState) -> PlayerInfo { | ||||||
|     let (level, stats) = level_table.get_stats_from_exp(client.character.char_class, client.character.exp); |     let (level, stats) = LEVEL_TABLE.get_stats_from_exp(client.character.char_class, client.character.exp); | ||||||
|     let inventory = item_state.get_character_inventory(&client.character).unwrap(); |     let inventory = item_state.get_character_inventory(&client.character).unwrap(); | ||||||
|     let character = CharacterBytesBuilder::default() |     let character = CharacterBytesBuilder::default() | ||||||
|         .character(&client.character) |         .character(&client.character) | ||||||
|  | |||||||
| @ -1,6 +1,5 @@ | |||||||
| use libpso::packet::ship::*; | use libpso::packet::ship::*; | ||||||
| use crate::common::serverstate::ClientId; | use crate::common::serverstate::ClientId; | ||||||
| use crate::common::leveltable::CharacterLevelTable; |  | ||||||
| use crate::ship::ship::{ShipError, ClientState, Clients}; | use crate::ship::ship::{ShipError, ClientState, Clients}; | ||||||
| use crate::ship::location::{ClientLocation, RoomId, AreaClient, ClientLocationError}; | use crate::ship::location::{ClientLocation, RoomId, AreaClient, ClientLocationError}; | ||||||
| use crate::ship::room::RoomState; | use crate::ship::room::RoomState; | ||||||
| @ -54,7 +53,6 @@ pub fn add_to_room(_id: ClientId, | |||||||
|                    area_client: &AreaClient, |                    area_client: &AreaClient, | ||||||
|                    leader: &AreaClient, |                    leader: &AreaClient, | ||||||
|                    item_state: &ItemState, |                    item_state: &ItemState, | ||||||
|                    level_table: &CharacterLevelTable, |  | ||||||
|                    _room_id: RoomId, |                    _room_id: RoomId, | ||||||
| ) | ) | ||||||
|                    -> Result<AddToRoom, ShipError> { |                    -> Result<AddToRoom, ShipError> { | ||||||
| @ -68,7 +66,7 @@ pub fn add_to_room(_id: ClientId, | |||||||
|         block: 0, |         block: 0, | ||||||
|         event: 0, |         event: 0, | ||||||
|         padding: 0, |         padding: 0, | ||||||
|         playerinfo: player_info(0x10000, client, area_client, item_state, level_table), |         playerinfo: player_info(0x10000, client, area_client, item_state), | ||||||
|     }) |     }) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ use rand::Rng; | |||||||
| use rand::seq::SliceRandom; | use rand::seq::SliceRandom; | ||||||
| use libpso::packet::ship::*; | use libpso::packet::ship::*; | ||||||
| use libpso::packet::messages::*; | use libpso::packet::messages::*; | ||||||
| use crate::common::leveltable::CharacterLevelTable; | use crate::common::leveltable::LEVEL_TABLE; | ||||||
| use crate::common::serverstate::ClientId; | use crate::common::serverstate::ClientId; | ||||||
| use crate::ship::ship::{SendShipPacket, ShipError, Clients, Rooms, ItemShops}; | use crate::ship::ship::{SendShipPacket, ShipError, Clients, Rooms, ItemShops}; | ||||||
| use crate::ship::location::{ClientLocation, ClientLocationError}; | use crate::ship::location::{ClientLocation, ClientLocationError}; | ||||||
| @ -290,7 +290,6 @@ pub async fn shop_request(id: ClientId, | |||||||
|                           client_location: &ClientLocation, |                           client_location: &ClientLocation, | ||||||
|                           clients: &mut Clients, |                           clients: &mut Clients, | ||||||
|                           rooms: &Rooms, |                           rooms: &Rooms, | ||||||
|                           level_table: &CharacterLevelTable, |  | ||||||
|                           shops: &mut ItemShops) |                           shops: &mut ItemShops) | ||||||
|                           -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> |                           -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> | ||||||
| { | { | ||||||
| @ -300,7 +299,7 @@ pub async fn shop_request(id: ClientId, | |||||||
|         .ok_or(ShipError::InvalidRoom(room_id.0 as u32))? |         .ok_or(ShipError::InvalidRoom(room_id.0 as u32))? | ||||||
|         .as_ref() |         .as_ref() | ||||||
|         .ok_or(ShipError::InvalidRoom(room_id.0 as u32))?; |         .ok_or(ShipError::InvalidRoom(room_id.0 as u32))?; | ||||||
|     let level = level_table.get_level_from_exp(client.character.char_class, client.character.exp) as usize; |     let level = LEVEL_TABLE.get_level_from_exp(client.character.char_class, client.character.exp) as usize; | ||||||
|     let shop_list = match shop_request.shop_type { |     let shop_list = match shop_request.shop_type { | ||||||
|         SHOP_OPTION_WEAPON => { |         SHOP_OPTION_WEAPON => { | ||||||
|             client.weapon_shop = shops.weapon_shop.get_mut(&(room.mode.difficulty(), client.character.section_id)) |             client.weapon_shop = shops.weapon_shop.get_mut(&(room.mode.difficulty(), client.character.section_id)) | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| use libpso::packet::ship::*; | use libpso::packet::ship::*; | ||||||
| use crate::common::serverstate::ClientId; | use crate::common::serverstate::ClientId; | ||||||
| use crate::common::leveltable::CharacterLevelTable; | use crate::common::leveltable::LEVEL_TABLE; | ||||||
| use crate::ship::ship::{SendShipPacket, ShipError, Clients, Rooms}; | use crate::ship::ship::{SendShipPacket, ShipError, Clients, Rooms}; | ||||||
| use crate::ship::character::{FullCharacterBytesBuilder}; | use crate::ship::character::{FullCharacterBytesBuilder}; | ||||||
| use crate::ship::location::{ClientLocation, LobbyId, RoomLobby, ClientLocationError, RoomId}; | use crate::ship::location::{ClientLocation, LobbyId, RoomLobby, ClientLocationError, RoomId}; | ||||||
| @ -13,13 +13,12 @@ use crate::ship::map::MapArea; | |||||||
| pub fn block_selected(id: ClientId, | pub fn block_selected(id: ClientId, | ||||||
|                       pkt: &MenuSelect, |                       pkt: &MenuSelect, | ||||||
|                       clients: &mut Clients, |                       clients: &mut Clients, | ||||||
|                       item_state: &ItemState, |                       item_state: &ItemState) | ||||||
|                       level_table: &CharacterLevelTable) |  | ||||||
|                       -> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> { |                       -> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> { | ||||||
|     let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; |     let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; | ||||||
|     client.block = pkt.item as usize - 1; |     client.block = pkt.item as usize - 1; | ||||||
| 
 | 
 | ||||||
|     let (level, stats) = level_table.get_stats_from_exp(client.character.char_class, client.character.exp); |     let (level, stats) = LEVEL_TABLE.get_stats_from_exp(client.character.char_class, client.character.exp); | ||||||
| 
 | 
 | ||||||
|     let inventory = item_state.get_character_inventory(&client.character).unwrap(); |     let inventory = item_state.get_character_inventory(&client.character).unwrap(); | ||||||
|     let bank = item_state.get_character_bank(&client.character).unwrap(); |     let bank = item_state.get_character_bank(&client.character).unwrap(); | ||||||
| @ -51,12 +50,11 @@ pub fn send_player_to_lobby(id: ClientId, | |||||||
|                             _pkt: &CharData, |                             _pkt: &CharData, | ||||||
|                             client_location: &mut ClientLocation, |                             client_location: &mut ClientLocation, | ||||||
|                             clients: &Clients, |                             clients: &Clients, | ||||||
|                             item_state: &ItemState, |                             item_state: &ItemState) | ||||||
|                             level_table: &CharacterLevelTable) |  | ||||||
|                             -> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> { |                             -> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> { | ||||||
|     let lobby = client_location.add_client_to_next_available_lobby(id, LobbyId(0)).map_err(|_| ShipError::TooManyClients)?; |     let lobby = client_location.add_client_to_next_available_lobby(id, LobbyId(0)).map_err(|_| ShipError::TooManyClients)?; | ||||||
|     let join_lobby = packet::builder::lobby::join_lobby(id, lobby, client_location, clients, item_state, level_table)?; |     let join_lobby = packet::builder::lobby::join_lobby(id, lobby, client_location, clients, item_state)?; | ||||||
|     let addto = packet::builder::lobby::add_to_lobby(id, lobby, client_location, clients, item_state, level_table)?; |     let addto = packet::builder::lobby::add_to_lobby(id, lobby, client_location, clients, item_state)?; | ||||||
|     let neighbors = client_location.get_client_neighbors(id).unwrap(); |     let neighbors = client_location.get_client_neighbors(id).unwrap(); | ||||||
|     Ok(vec![(id, SendShipPacket::JoinLobby(join_lobby))] |     Ok(vec![(id, SendShipPacket::JoinLobby(join_lobby))] | ||||||
|        .into_iter() |        .into_iter() | ||||||
| @ -70,7 +68,6 @@ pub async fn change_lobby<EG: EntityGateway>(id: ClientId, | |||||||
|                                              client_location: &mut ClientLocation, |                                              client_location: &mut ClientLocation, | ||||||
|                                              clients: &Clients, |                                              clients: &Clients, | ||||||
|                                              item_state: &mut ItemState, |                                              item_state: &mut ItemState, | ||||||
|                                              level_table: &CharacterLevelTable, |  | ||||||
|                                              ship_rooms: &mut Rooms, |                                              ship_rooms: &mut Rooms, | ||||||
|                                              mut entity_gateway: EG) |                                              mut entity_gateway: EG) | ||||||
|                                              -> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> { |                                              -> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> { | ||||||
| @ -104,8 +101,8 @@ pub async fn change_lobby<EG: EntityGateway>(id: ClientId, | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     item_state.load_character(&mut entity_gateway, &client.character).await?; |     item_state.load_character(&mut entity_gateway, &client.character).await?; | ||||||
|     let join_lobby = packet::builder::lobby::join_lobby(id, lobby, client_location, clients, item_state, level_table)?; |     let join_lobby = packet::builder::lobby::join_lobby(id, lobby, client_location, clients, item_state)?; | ||||||
|     let addto = packet::builder::lobby::add_to_lobby(id, lobby, client_location, clients, item_state, level_table)?; |     let addto = packet::builder::lobby::add_to_lobby(id, lobby, client_location, clients, item_state)?; | ||||||
|     let neighbors = client_location.get_client_neighbors(id).unwrap(); |     let neighbors = client_location.get_client_neighbors(id).unwrap(); | ||||||
|     Ok(vec![(id, SendShipPacket::JoinLobby(join_lobby))] |     Ok(vec![(id, SendShipPacket::JoinLobby(join_lobby))] | ||||||
|         .into_iter() |         .into_iter() | ||||||
| @ -145,8 +142,7 @@ pub fn get_room_tab_info(id: ClientId, | |||||||
|             let gc = cs.user.guildcard; |             let gc = cs.user.guildcard; | ||||||
|             let name = &cs.character.name; |             let name = &cs.character.name; | ||||||
|             let cc = cs.character.char_class; |             let cc = cs.character.char_class; | ||||||
|             let leveltable = CharacterLevelTable::default(); |             let lv = LEVEL_TABLE.get_level_from_exp(cc, cs.character.exp); | ||||||
|             let lv = leveltable.get_level_from_exp(cc, cs.character.exp); |  | ||||||
|             let floor = cs.area.unwrap_or(MapArea::Pioneer2Ep1); |             let floor = cs.area.unwrap_or(MapArea::Pioneer2Ep1); | ||||||
| 
 | 
 | ||||||
|             room_info += format!("{} Lv{} {}\n{} {}\n", gc,lv,name,cc,floor).as_str(); |             room_info += format!("{} Lv{} {}\n{} {}\n", gc,lv,name,cc,floor).as_str(); | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ use libpso::packet::messages::*; | |||||||
| use crate::entity::gateway::EntityGateway; | use crate::entity::gateway::EntityGateway; | ||||||
| use crate::entity::item::Meseta; | use crate::entity::item::Meseta; | ||||||
| use crate::common::serverstate::ClientId; | use crate::common::serverstate::ClientId; | ||||||
| use crate::common::leveltable::CharacterLevelTable; | use crate::common::leveltable::LEVEL_TABLE; | ||||||
| use crate::ship::ship::{SendShipPacket, ShipError, Rooms, Clients, ItemDropLocation}; | use crate::ship::ship::{SendShipPacket, ShipError, Rooms, Clients, ItemDropLocation}; | ||||||
| use crate::ship::location::{ClientLocation, ClientLocationError}; | use crate::ship::location::{ClientLocation, ClientLocationError}; | ||||||
| use crate::ship::items::ClientItemId; | use crate::ship::items::ClientItemId; | ||||||
| @ -16,8 +16,7 @@ pub async fn request_exp<EG: EntityGateway>(id: ClientId, | |||||||
|                                             mut entity_gateway: EG, |                                             mut entity_gateway: EG, | ||||||
|                                             client_location: &ClientLocation, |                                             client_location: &ClientLocation, | ||||||
|                                             clients: &mut Clients, |                                             clients: &mut Clients, | ||||||
|                                             rooms: &mut Rooms, |                                             rooms: &mut Rooms) | ||||||
|                                             level_table: &CharacterLevelTable) |  | ||||||
|                                             -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> { |                                             -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> { | ||||||
|     let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; |     let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; | ||||||
|     let area_client = client_location.get_local_client(id).map_err(|err| -> ClientLocationError { err.into() })?; |     let area_client = client_location.get_local_client(id).map_err(|err| -> ClientLocationError { err.into() })?; | ||||||
| @ -44,13 +43,13 @@ pub async fn request_exp<EG: EntityGateway>(id: ClientId, | |||||||
|             (c.client, SendShipPacket::Message(Message::new(GameMessage::GiveCharacterExp(gain_exp_pkt.clone())))) |             (c.client, SendShipPacket::Message(Message::new(GameMessage::GiveCharacterExp(gain_exp_pkt.clone())))) | ||||||
|         })); |         })); | ||||||
| 
 | 
 | ||||||
|     let before_level = level_table.get_level_from_exp(client.character.char_class, client.character.exp); |     let before_level = LEVEL_TABLE.get_level_from_exp(client.character.char_class, client.character.exp); | ||||||
|     let after_level = level_table.get_level_from_exp(client.character.char_class, client.character.exp + exp_gain); |     let after_level = LEVEL_TABLE.get_level_from_exp(client.character.char_class, client.character.exp + exp_gain); | ||||||
|     let level_up = before_level != after_level; |     let level_up = before_level != after_level; | ||||||
| 
 | 
 | ||||||
|     if level_up { |     if level_up { | ||||||
|         let (_, before_stats) = level_table.get_stats_from_exp(client.character.char_class, client.character.exp); |         let (_, before_stats) = LEVEL_TABLE.get_stats_from_exp(client.character.char_class, client.character.exp); | ||||||
|         let (after_level, after_stats) = level_table.get_stats_from_exp(client.character.char_class, client.character.exp + exp_gain); |         let (after_level, after_stats) = LEVEL_TABLE.get_stats_from_exp(client.character.char_class, client.character.exp + exp_gain); | ||||||
| 
 | 
 | ||||||
|         let level_up_pkt = builder::message::character_leveled_up(area_client, after_level, before_stats, after_stats); |         let level_up_pkt = builder::message::character_leveled_up(area_client, after_level, before_stats, after_stats); | ||||||
|         exp_pkts = Box::new(exp_pkts.chain(clients_in_area.into_iter() |         exp_pkts = Box::new(exp_pkts.chain(clients_in_area.into_iter() | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| use libpso::packet::ship::*; | use libpso::packet::ship::*; | ||||||
| use libpso::packet::messages::*; | use libpso::packet::messages::*; | ||||||
| use crate::common::serverstate::ClientId; | use crate::common::serverstate::ClientId; | ||||||
| use crate::common::leveltable::CharacterLevelTable; | use crate::common::leveltable::LEVEL_TABLE; | ||||||
| use crate::ship::ship::{SendShipPacket, ShipError, Rooms, Clients}; | use crate::ship::ship::{SendShipPacket, ShipError, Rooms, Clients}; | ||||||
| use crate::ship::location::{ClientLocation, RoomId, RoomLobby, ClientLocationError}; | use crate::ship::location::{ClientLocation, RoomId, RoomLobby, ClientLocationError}; | ||||||
| use crate::ship::packet::builder; | use crate::ship::packet::builder; | ||||||
| @ -14,11 +14,10 @@ pub fn create_room(id: ClientId, | |||||||
|                    client_location: &mut ClientLocation, |                    client_location: &mut ClientLocation, | ||||||
|                    clients: &mut Clients, |                    clients: &mut Clients, | ||||||
|                    item_state: &mut ItemState, |                    item_state: &mut ItemState, | ||||||
|                    level_table: &CharacterLevelTable, |  | ||||||
|                    rooms: &mut Rooms) |                    rooms: &mut Rooms) | ||||||
|                    -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> { |                    -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> { | ||||||
|     let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; |     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 level = LEVEL_TABLE.get_level_from_exp(client.character.char_class, client.character.exp); | ||||||
|     match room::Difficulty::try_from(create_room.difficulty)? { |     match room::Difficulty::try_from(create_room.difficulty)? { | ||||||
|         room::Difficulty::Ultimate => { |         room::Difficulty::Ultimate => { | ||||||
|             if level < 80 { |             if level < 80 { | ||||||
| @ -81,11 +80,10 @@ pub fn join_room(id: ClientId, | |||||||
|                  client_location: &mut ClientLocation, |                  client_location: &mut ClientLocation, | ||||||
|                  clients: &mut Clients, |                  clients: &mut Clients, | ||||||
|                  item_state: &mut ItemState, |                  item_state: &mut ItemState, | ||||||
|                  level_table: &CharacterLevelTable, |  | ||||||
|                  rooms: &mut Rooms) |                  rooms: &mut Rooms) | ||||||
|                  -> Result<Box<dyn Iterator<Item=(ClientId, SendShipPacket)> + Send>, ShipError> { |                  -> Result<Box<dyn Iterator<Item=(ClientId, SendShipPacket)> + Send>, ShipError> { | ||||||
|     let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; |     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 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))? { |     if let Some(room) = rooms.get(pkt.item as usize).ok_or(ShipError::InvalidRoom(pkt.item))? { | ||||||
| 
 | 
 | ||||||
| @ -124,7 +122,7 @@ pub fn join_room(id: ClientId, | |||||||
| 
 | 
 | ||||||
|         let leader = client_location.get_room_leader(room_id).map_err(|err| -> ClientLocationError { err.into() })?; |         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 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_state, level_table, room_id)?; |         let add_to = builder::room::add_to_room(id, client, &area_client, &leader, item_state, room_id)?; | ||||||
| 
 | 
 | ||||||
|         let room = rooms.get_mut(room_id.0).unwrap().as_mut().unwrap(); |         let room = rooms.get_mut(room_id.0).unwrap().as_mut().unwrap(); | ||||||
|         room.bursting = true; |         room.bursting = true; | ||||||
|  | |||||||
| @ -15,7 +15,6 @@ use libpso::packet::ship::{BLOCK_MENU_ID, ROOM_MENU_ID}; | |||||||
| 
 | 
 | ||||||
| use crate::common::cipherkeys::{ELSEWHERE_PRIVATE_KEY, ELSEWHERE_PARRAY}; | use crate::common::cipherkeys::{ELSEWHERE_PRIVATE_KEY, ELSEWHERE_PARRAY}; | ||||||
| use crate::common::serverstate::{SendServerPacket, RecvServerPacket, ServerState, OnConnect, ClientId}; | use crate::common::serverstate::{SendServerPacket, RecvServerPacket, ServerState, OnConnect, ClientId}; | ||||||
| use crate::common::leveltable::CharacterLevelTable; |  | ||||||
| use crate::common::interserver::{AuthToken, Ship, ServerId, InterserverActor, LoginMessage, ShipMessage}; | use crate::common::interserver::{AuthToken, Ship, ServerId, InterserverActor, LoginMessage, ShipMessage}; | ||||||
| 
 | 
 | ||||||
| use crate::login::character::SHIP_MENU_ID; | use crate::login::character::SHIP_MENU_ID; | ||||||
| @ -437,7 +436,6 @@ impl<EG: EntityGateway + Clone> ShipServerStateBuilder<EG> { | |||||||
|         ShipServerState { |         ShipServerState { | ||||||
|             entity_gateway: self.entity_gateway.unwrap(), |             entity_gateway: self.entity_gateway.unwrap(), | ||||||
|             clients: HashMap::new(), |             clients: HashMap::new(), | ||||||
|             level_table: CharacterLevelTable::default(), |  | ||||||
|             name: self.name.unwrap_or_else(|| "NAMENOTSET".into()), |             name: self.name.unwrap_or_else(|| "NAMENOTSET".into()), | ||||||
|             item_state: items::state::ItemState::default(), |             item_state: items::state::ItemState::default(), | ||||||
|             ip: self.ip.unwrap_or_else(|| Ipv4Addr::new(127,0,0,1)), |             ip: self.ip.unwrap_or_else(|| Ipv4Addr::new(127,0,0,1)), | ||||||
| @ -481,7 +479,6 @@ impl Blocks { | |||||||
| pub struct ShipServerState<EG: EntityGateway + Clone> { | pub struct ShipServerState<EG: EntityGateway + Clone> { | ||||||
|     entity_gateway: EG, |     entity_gateway: EG, | ||||||
|     pub clients: Clients, |     pub clients: Clients, | ||||||
|     level_table: CharacterLevelTable, |  | ||||||
|     name: String, |     name: String, | ||||||
|     item_state: items::state::ItemState, |     item_state: items::state::ItemState, | ||||||
|     shops: Box<ItemShops>, |     shops: Box<ItemShops>, | ||||||
| @ -509,7 +506,7 @@ impl<EG: EntityGateway + Clone> ShipServerState<EG> { | |||||||
|         Ok(match &msg.msg { |         Ok(match &msg.msg { | ||||||
|             GameMessage::RequestExp(request_exp) => { |             GameMessage::RequestExp(request_exp) => { | ||||||
|                 let block = self.blocks.with_client(id, &self.clients)?; |                 let block = self.blocks.with_client(id, &self.clients)?; | ||||||
|                 handler::message::request_exp(id, request_exp, self.entity_gateway.clone(), &block.client_location, &mut self.clients, &mut block.rooms, &self.level_table).await? |                 handler::message::request_exp(id, request_exp, self.entity_gateway.clone(), &block.client_location, &mut self.clients, &mut block.rooms).await? | ||||||
|             }, |             }, | ||||||
|             GameMessage::PlayerDropItem(player_drop_item) => { |             GameMessage::PlayerDropItem(player_drop_item) => { | ||||||
|                 let block = self.blocks.with_client(id, &self.clients)?; |                 let block = self.blocks.with_client(id, &self.clients)?; | ||||||
| @ -592,7 +589,7 @@ impl<EG: EntityGateway + Clone> ShipServerState<EG> { | |||||||
|                 handler::direct_message::bank_interaction(id, bank_interaction, self.entity_gateway.clone(), &block.client_location, &mut self.clients, &mut self.item_state).await? |                 handler::direct_message::bank_interaction(id, bank_interaction, self.entity_gateway.clone(), &block.client_location, &mut self.clients, &mut self.item_state).await? | ||||||
|             }, |             }, | ||||||
|             GameMessage::ShopRequest(shop_request) => { |             GameMessage::ShopRequest(shop_request) => { | ||||||
|                 handler::direct_message::shop_request(id, shop_request, &block.client_location, &mut self.clients, &block.rooms, &self.level_table, &mut self.shops).await? |                 handler::direct_message::shop_request(id, shop_request, &block.client_location, &mut self.clients, &block.rooms, &mut self.shops).await? | ||||||
|             }, |             }, | ||||||
|             GameMessage::BuyItem(buy_item) => { |             GameMessage::BuyItem(buy_item) => { | ||||||
|                 handler::direct_message::buy_item(id, buy_item, self.entity_gateway.clone(), &block.client_location, &mut self.clients, &mut self.item_state).await? |                 handler::direct_message::buy_item(id, buy_item, self.entity_gateway.clone(), &block.client_location, &mut self.clients, &mut self.item_state).await? | ||||||
| @ -667,10 +664,10 @@ impl<EG: EntityGateway + Clone> ServerState for ShipServerState<EG> { | |||||||
|                     } |                     } | ||||||
|                     BLOCK_MENU_ID => { |                     BLOCK_MENU_ID => { | ||||||
|                         let leave_lobby = handler::lobby::remove_from_lobby(id, &mut block.client_location).into_iter().into_iter().flatten(); |                         let leave_lobby = handler::lobby::remove_from_lobby(id, &mut block.client_location).into_iter().into_iter().flatten(); | ||||||
|                         let select_block = handler::lobby::block_selected(id, menuselect, &mut self.clients, &self.item_state, &self.level_table)?.into_iter(); |                         let select_block = handler::lobby::block_selected(id, menuselect, &mut self.clients, &self.item_state)?.into_iter(); | ||||||
|                         Box::new(leave_lobby.chain(select_block)) |                         Box::new(leave_lobby.chain(select_block)) | ||||||
|                     } |                     } | ||||||
|                     ROOM_MENU_ID => handler::room::join_room(id, menuselect, &mut block.client_location, &mut self.clients, &mut self.item_state, &self.level_table, &mut block.rooms)?, |                     ROOM_MENU_ID => handler::room::join_room(id, menuselect, &mut block.client_location, &mut self.clients, &mut self.item_state, &mut block.rooms)?, | ||||||
|                     QUEST_CATEGORY_MENU_ID => handler::quest::select_quest_category(id, menuselect, &block.client_location, &mut block.rooms)?, |                     QUEST_CATEGORY_MENU_ID => handler::quest::select_quest_category(id, menuselect, &block.client_location, &mut block.rooms)?, | ||||||
|                     _ => unreachable!(), |                     _ => unreachable!(), | ||||||
|                 } |                 } | ||||||
| @ -692,7 +689,7 @@ impl<EG: EntityGateway + Clone> ServerState for ShipServerState<EG> { | |||||||
|                             menu: room_password_req.menu, |                             menu: room_password_req.menu, | ||||||
|                             item: room_password_req.item, |                             item: room_password_req.item, | ||||||
|                         }; |                         }; | ||||||
|                         handler::room::join_room(id, &menuselect, &mut block.client_location, &mut self.clients, &mut self.item_state, &self.level_table, &mut block.rooms)? |                         handler::room::join_room(id, &menuselect, &mut block.client_location, &mut self.clients, &mut self.item_state, &mut block.rooms)? | ||||||
|                     } |                     } | ||||||
|                 else { |                 else { | ||||||
|                     Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("Incorrect password".into())))].into_iter()) |                     Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("Incorrect password".into())))].into_iter()) | ||||||
| @ -700,7 +697,7 @@ impl<EG: EntityGateway + Clone> ServerState for ShipServerState<EG> { | |||||||
|             }, |             }, | ||||||
|             RecvShipPacket::CharData(chardata) => { |             RecvShipPacket::CharData(chardata) => { | ||||||
|                 let block = self.blocks.with_client(id, &self.clients)?; |                 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_state, &self.level_table)?.into_iter()) |                 Box::new(handler::lobby::send_player_to_lobby(id, chardata, &mut block.client_location, &self.clients, &self.item_state)?.into_iter()) | ||||||
|             }, |             }, | ||||||
|             RecvShipPacket::Message(msg) => { |             RecvShipPacket::Message(msg) => { | ||||||
|                 self.message(id, msg).await? |                 self.message(id, msg).await? | ||||||
| @ -714,7 +711,7 @@ impl<EG: EntityGateway + Clone> ServerState for ShipServerState<EG> { | |||||||
|             }, |             }, | ||||||
|             RecvShipPacket::CreateRoom(create_room) => { |             RecvShipPacket::CreateRoom(create_room) => { | ||||||
|                 let block = self.blocks.with_client(id, &self.clients)?; |                 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_state, &self.level_table, &mut block.rooms)? |                 handler::room::create_room(id, create_room, &mut block.client_location, &mut self.clients, &mut self.item_state, &mut block.rooms)? | ||||||
|             }, |             }, | ||||||
|             RecvShipPacket::RoomNameRequest(_req) => { |             RecvShipPacket::RoomNameRequest(_req) => { | ||||||
|                 let block = self.blocks.with_client(id, &self.clients)?; |                 let block = self.blocks.with_client(id, &self.clients)?; | ||||||
| @ -752,7 +749,7 @@ impl<EG: EntityGateway + Clone> ServerState for ShipServerState<EG> { | |||||||
|             }, |             }, | ||||||
|             RecvShipPacket::LobbySelect(pkt) => { |             RecvShipPacket::LobbySelect(pkt) => { | ||||||
|                 let block = self.blocks.with_client(id, &self.clients)?; |                 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_state, &self.level_table, &mut block.rooms, self.entity_gateway.clone()).await?.into_iter()) |                 Box::new(handler::lobby::change_lobby(id, pkt.lobby, &mut block.client_location, &self.clients, &mut self.item_state, &mut block.rooms, self.entity_gateway.clone()).await?.into_iter()) | ||||||
|             }, |             }, | ||||||
|             RecvShipPacket::RequestQuestList(rql) => { |             RecvShipPacket::RequestQuestList(rql) => { | ||||||
|                 let block = self.blocks.with_client(id, &self.clients)?; |                 let block = self.blocks.with_client(id, &self.clients)?; | ||||||
|  | |||||||
| @ -123,7 +123,7 @@ impl TradeState { | |||||||
|             return Err(TradeStateError::MismatchedTrade(c1.client, c2.client)); |             return Err(TradeStateError::MismatchedTrade(c1.client, c2.client)); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         Ok(func(&mut *c1, &mut *c2)) |         Ok(func(&mut c1, &mut c2)) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // TODO: is it possible for this to not return Options?
 |     // TODO: is it possible for this to not return Options?
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user