From a266b2e12b122f4952d1edaa264828937b401d84 Mon Sep 17 00:00:00 2001 From: xeon Date: Thu, 12 Dec 2024 21:53:27 +0300 Subject: [PATCH] Implement #[property_accessors] proc macro to reduce boilerplate for accessing optional properties --- crates/game-server/src/database.rs | 2 +- .../src/level/event_graph_runner.rs | 17 +- crates/game-server/src/player_util.rs | 4 +- crates/game-server/src/rpc_ptc/item.rs | 16 +- crates/game-server/src/rpc_ptc/main_city.rs | 10 +- crates/game-server/src/rpc_ptc/player.rs | 4 +- crates/game-server/src/rpc_ptc/quest.rs | 22 ++- crates/game-server/src/rpc_ptc/world.rs | 96 ++++-------- crates/game-server/src/scene_section_util.rs | 15 +- crates/protocol/protocol-macros/src/lib.rs | 8 + .../protocol-macros/src/property_accessors.rs | 62 ++++++++ crates/protocol/src/player_info.rs | 9 ++ crates/protocol/src/util.rs | 147 +++++------------- 13 files changed, 182 insertions(+), 230 deletions(-) create mode 100644 crates/protocol/protocol-macros/src/property_accessors.rs diff --git a/crates/game-server/src/database.rs b/crates/game-server/src/database.rs index 40bfbc7..a1580fc 100644 --- a/crates/game-server/src/database.rs +++ b/crates/game-server/src/database.rs @@ -75,7 +75,7 @@ impl DbContext { } pub async fn save_player_data(&self, last_uid: u32, player_info: &PlayerInfo) -> Result<()> { - let player_uid = player_info.uid.unwrap(); + let player_uid = *player_info.uid(); let _: PlayerData = self .0 diff --git a/crates/game-server/src/level/event_graph_runner.rs b/crates/game-server/src/level/event_graph_runner.rs index 387e882..90ca876 100644 --- a/crates/game-server/src/level/event_graph_runner.rs +++ b/crates/game-server/src/level/event_graph_runner.rs @@ -73,8 +73,8 @@ pub fn execute_action( match action { ActionCreateNpcCfg { id, tag_id } => { let uid = session.uid_counter.next(); - let sdg = session.player_info.single_dungeon_group.as_mut().unwrap(); - sdg.npcs.as_mut().unwrap().insert( + let sdg = session.player_info.single_dungeon_group_mut(); + sdg.npcs_mut().insert( scene_uid, uid, NpcInfo { @@ -100,10 +100,8 @@ pub fn execute_action( section_listen_events, .. } => { - let sdg = session.player_info.single_dungeon_group.as_mut().unwrap(); - sdg.npcs - .as_ref() - .unwrap() + let sdg = session.player_info.single_dungeon_group_mut(); + sdg.npcs() .iter() .filter(|(s_uid, _, _)| **s_uid == scene_uid) .for_each(|(_, &uid, npc)| { @@ -133,12 +131,7 @@ pub fn execute_action( }); } ActionSetMainCityObjectState { object_state, .. } => { - let main_city_objects_state = session - .player_info - .main_city_objects_state - .as_mut() - .unwrap(); - + let main_city_objects_state = session.player_info.main_city_objects_state_mut(); object_state .iter() .for_each(|(&obj, &state)| main_city_objects_state.insert(obj, state)); diff --git a/crates/game-server/src/player_util.rs b/crates/game-server/src/player_util.rs index 47a3f1f..0229b8d 100644 --- a/crates/game-server/src/player_util.rs +++ b/crates/game-server/src/player_util.rs @@ -323,7 +323,7 @@ pub fn create_starting_player_info(uid: u64, nick_name: &str) -> (UidCounter, Pl .filter(|tmpl| tmpl.camp() != 0) .for_each(|tmpl| { let uid = counter.next(); - player_info.items.as_mut().unwrap().insert( + player_info.items_mut().insert( uid, ItemInfo::AvatarInfo { uid, @@ -354,7 +354,7 @@ pub fn create_starting_player_info(uid: u64, nick_name: &str) -> (UidCounter, Pl .iter() .for_each(|tmpl| { let uid = counter.next(); - player_info.items.as_mut().unwrap().insert( + player_info.items_mut().insert( uid, ItemInfo::Weapon { uid, diff --git a/crates/game-server/src/rpc_ptc/item.rs b/crates/game-server/src/rpc_ptc/item.rs index 0bccf3a..e516953 100644 --- a/crates/game-server/src/rpc_ptc/item.rs +++ b/crates/game-server/src/rpc_ptc/item.rs @@ -75,9 +75,7 @@ pub async fn on_rpc_weapon_dress_arg( ) -> Result { let Some(target_avatar_uid) = session .player_info - .items - .as_ref() - .unwrap() + .items() .iter() .find(|(_, item)| { if let ItemInfo::AvatarInfo { id, .. } = item { @@ -94,9 +92,7 @@ pub async fn on_rpc_weapon_dress_arg( let Some((_, ItemInfo::Weapon { avatar_uid, .. })) = session .player_info - .items - .as_mut() - .unwrap() + .items_mut() .iter_mut() .find(|(uid, _)| (*uid & 0xFFFFFFFF) as u32 == arg.weapon_uid) else { @@ -124,9 +120,7 @@ pub async fn on_rpc_weapon_un_dress_arg( ) -> Result { let Some(target_avatar_uid) = session .player_info - .items - .as_ref() - .unwrap() + .items() .iter() .find(|(_, item)| { if let ItemInfo::AvatarInfo { id, .. } = item { @@ -143,9 +137,7 @@ pub async fn on_rpc_weapon_un_dress_arg( session .player_info - .items - .as_mut() - .unwrap() + .items_mut() .iter_mut() .for_each(|(_, item)| { if let ItemInfo::Weapon { avatar_uid, .. } = item { diff --git a/crates/game-server/src/rpc_ptc/main_city.rs b/crates/game-server/src/rpc_ptc/main_city.rs index c91e048..ec1c064 100644 --- a/crates/game-server/src/rpc_ptc/main_city.rs +++ b/crates/game-server/src/rpc_ptc/main_city.rs @@ -118,17 +118,13 @@ pub async fn on_rpc_mod_time_arg( debug!("{arg:?}"); let player_info = &mut session.player_info; - let scene_uid = player_info.scene_uid.unwrap(); - let dungeon_collection = player_info.dungeon_collection.as_mut().unwrap(); + let scene_uid = *player_info.scene_uid(); + let dungeon_collection = player_info.dungeon_collection_mut(); if let Some(protocol::scene_info::SceneInfo::Hall { main_city_time_info, .. - }) = dungeon_collection - .scenes - .as_mut() - .unwrap() - .get_mut(&scene_uid) + }) = dungeon_collection.scenes_mut().get_mut(&scene_uid) { let prev_time = main_city_time_info.initial_time; main_city_time_info.initial_time = match arg.time_period { diff --git a/crates/game-server/src/rpc_ptc/player.rs b/crates/game-server/src/rpc_ptc/player.rs index 81aa9cf..89198ce 100644 --- a/crates/game-server/src/rpc_ptc/player.rs +++ b/crates/game-server/src/rpc_ptc/player.rs @@ -99,8 +99,8 @@ pub async fn on_rpc_player_transaction_arg( session: &mut PlayerSession, _: RpcPlayerTransactionArg, ) -> Result { - let player_uid = session.player_info.uid.unwrap_or_default(); - let scene_uid = session.player_info.scene_uid.unwrap_or_default(); + let player_uid = session.player_info.uid(); + let scene_uid = session.player_info.scene_uid(); Ok(RpcPlayerTransactionRet { retcode: 0, diff --git a/crates/game-server/src/rpc_ptc/quest.rs b/crates/game-server/src/rpc_ptc/quest.rs index 86c9e6e..2efa59b 100644 --- a/crates/game-server/src/rpc_ptc/quest.rs +++ b/crates/game-server/src/rpc_ptc/quest.rs @@ -17,20 +17,18 @@ pub async fn on_rpc_get_archive_info_arg( session: &mut PlayerSession, _: RpcGetArchiveInfoArg, ) -> Result { - let archive_info = session.player_info.archive_info.as_ref().unwrap(); + let archive_info = session.player_info.archive_info(); Ok(RpcGetArchiveInfoRet { retcode: 0, archive_info: ArchiveInfo { hollow_archive_id_list: archive_info - .hollow_archive_id - .as_ref() - .map(|set| set.iter().map(|id| *id as u32).collect()) - .unwrap_or_default(), + .hollow_archive_id() + .iter() + .map(|id| *id as u32) + .collect(), videotaps_info: archive_info - .videotaps_info - .as_ref() - .unwrap() + .videotaps_info() .iter() .map(|(id, videotape)| VideotapeInfo { archive_file_id: *id as u32, @@ -52,10 +50,10 @@ pub async fn on_rpc_get_yorozuya_info_arg( retcode: 0, yorozuya_info: YorozuyaInfo { unlock_hollow_id_list: yorozuya_info - .unlock_hollow_id - .as_ref() - .map(|list| list.iter().map(|id| *id as u32).collect()) - .unwrap_or_default(), + .unlock_hollow_id() + .iter() + .map(|id| *id as u32) + .collect(), }, }) } diff --git a/crates/game-server/src/rpc_ptc/world.rs b/crates/game-server/src/rpc_ptc/world.rs index 2ddfaf3..0bfd055 100644 --- a/crates/game-server/src/rpc_ptc/world.rs +++ b/crates/game-server/src/rpc_ptc/world.rs @@ -15,14 +15,7 @@ pub async fn on_rpc_enter_world_arg( ) -> Result { let player_info = &mut session.player_info; - if player_info - .dungeon_collection - .as_ref() - .unwrap() - .default_scene_uid - .unwrap() - == 0 - { + if *player_info.dungeon_collection().default_scene_uid() == 0 { let dungeon_uid = session.uid_counter.next(); let scene_uid = session.uid_counter.next(); @@ -79,38 +72,25 @@ pub async fn on_rpc_enter_world_arg( }, }; - let dungeon_collection = player_info.dungeon_collection.as_mut().unwrap(); + let dungeon_collection = player_info.dungeon_collection_mut(); dungeon_collection - .dungeons - .as_mut() - .unwrap() + .dungeons_mut() .insert(dungeon_uid, dungeon_info); dungeon_collection - .scenes - .as_mut() - .unwrap() + .scenes_mut() .insert(scene_uid, scene_info); - dungeon_collection.default_scene_uid = Some(scene_uid); + *dungeon_collection.default_scene_uid_mut() = scene_uid; } - let scene_uid = session - .player_info - .dungeon_collection - .as_ref() - .unwrap() - .default_scene_uid - .unwrap(); + let scene_uid = *session.player_info.dungeon_collection().default_scene_uid(); + session.player_info.scene_uid = Some(scene_uid); if let Some(section_id) = session .player_info - .dungeon_collection - .as_ref() - .unwrap() - .scenes - .as_ref() - .unwrap() + .dungeon_collection() + .scenes() .get(&scene_uid) .map(|sc| *sc.get_section_id()) { @@ -154,13 +134,11 @@ pub async fn on_rpc_save_pos_in_main_city_arg( session: &mut PlayerSession, arg: RpcSavePosInMainCityArg, ) -> Result { - let pos_in_main_city = session.player_info.pos_in_main_city.as_mut().unwrap(); - - let scene_uid = session.player_info.scene_uid.unwrap(); - let dungeon_collection = session.player_info.dungeon_collection.as_ref().unwrap(); + let scene_uid = *session.player_info.scene_uid(); + let dungeon_collection = session.player_info.dungeon_collection(); let Some(protocol::scene_info::SceneInfo::Hall { section_id, .. }) = - dungeon_collection.scenes.as_ref().unwrap().get(&scene_uid) + dungeon_collection.scenes().get(&scene_uid) else { return Err(-1); }; @@ -170,9 +148,10 @@ pub async fn on_rpc_save_pos_in_main_city_arg( arg.position.position.clone().try_into(), arg.position.rotation.clone().try_into(), ) { - pos_in_main_city.position = Some(position); - pos_in_main_city.rotation = Some(rotation); - pos_in_main_city.initial_pos_id = Some(String::with_capacity(0)); + session.player_info.pos_in_main_city_mut().position = Some(position); + session.player_info.pos_in_main_city_mut().rotation = Some(rotation); + session.player_info.pos_in_main_city_mut().initial_pos_id = + Some(String::with_capacity(0)); debug!( "player_uid: {}, pos in main city updated: {arg:?}", @@ -195,24 +174,19 @@ pub async fn on_rpc_enter_section_arg( arg: RpcEnterSectionArg, ) -> Result { let player_info = &mut session.player_info; - let cur_scene_uid = player_info.scene_uid.unwrap(); + let cur_scene_uid = *player_info.scene_uid(); - let dungeon_collection = player_info.dungeon_collection.as_mut().unwrap(); + let dungeon_collection = player_info.dungeon_collection_mut(); - let Some(scene_info::SceneInfo::Hall { section_id, .. }) = dungeon_collection - .scenes - .as_mut() - .unwrap() - .get_mut(&cur_scene_uid) + let Some(scene_info::SceneInfo::Hall { section_id, .. }) = + dungeon_collection.scenes_mut().get_mut(&cur_scene_uid) else { error!("RpcEnterSection: current scene is not Hall!"); return Err(-1); }; *section_id = arg.section_id as i32; - - let player_pos_in_main_city = player_info.pos_in_main_city.as_mut().unwrap(); - player_pos_in_main_city.initial_pos_id = Some(arg.transform_id); + player_info.pos_in_main_city_mut().initial_pos_id = Some(arg.transform_id); scene_section_util::init_hall_scene_section(session, cur_scene_uid, arg.section_id as i32); level::on_section_enter(session, cur_scene_uid, arg.section_id as i32); @@ -249,7 +223,7 @@ pub async fn on_rpc_begin_training_course_battle_arg( let dungeon_uid = session.uid_counter.next(); let scene_uid = session.uid_counter.next(); - let cur_scene_uid = player_info.scene_uid.unwrap(); + let cur_scene_uid = *player_info.scene_uid(); let dungeon_info = protocol::dungeon_info::DungeonInfo { uid: dungeon_uid, id: 12254000, @@ -327,16 +301,12 @@ pub async fn on_rpc_begin_training_course_battle_arg( weather: WeatherType::Rain, }; - let dungeon_collection = player_info.dungeon_collection.as_mut().unwrap(); + let dungeon_collection = player_info.dungeon_collection_mut(); dungeon_collection - .dungeons - .as_mut() - .unwrap() + .dungeons_mut() .insert(dungeon_uid, dungeon_info); dungeon_collection - .scenes - .as_mut() - .unwrap() + .scenes_mut() .insert(scene_uid, scene_info); let mut scene_info = build_client_scene_info(&session.player_info, scene_uid).unwrap(); @@ -371,23 +341,13 @@ pub async fn on_rpc_leave_cur_dungeon_arg( session: &mut PlayerSession, _: RpcLeaveCurDungeonArg, ) -> Result { - let scene_uid = session - .player_info - .dungeon_collection - .as_ref() - .unwrap() - .default_scene_uid - .unwrap(); + let scene_uid = *session.player_info.dungeon_collection().default_scene_uid(); session.player_info.scene_uid = Some(scene_uid); if let Some(section_id) = session .player_info - .dungeon_collection - .as_ref() - .unwrap() - .scenes - .as_ref() - .unwrap() + .dungeon_collection() + .scenes() .get(&scene_uid) .map(|sc| *sc.get_section_id()) { diff --git a/crates/game-server/src/scene_section_util.rs b/crates/game-server/src/scene_section_util.rs index 34da3ee..89ad6f8 100644 --- a/crates/game-server/src/scene_section_util.rs +++ b/crates/game-server/src/scene_section_util.rs @@ -10,18 +10,15 @@ use qwer::{phashmap, phashset, PropertyHashMap, PropertyHashSet}; use crate::{level, PlayerSession}; pub fn init_hall_scene_section(session: &mut PlayerSession, scene_uid: u64, section_id: i32) { - let single_dungeon_group = session.player_info.single_dungeon_group.as_mut().unwrap(); + let single_dungeon_group = session.player_info.single_dungeon_group_mut(); if single_dungeon_group - .section - .as_ref() - .unwrap() + .section() .contains(&scene_uid, §ion_id) { return; } - let section_map = single_dungeon_group.section.as_mut().unwrap(); - section_map.insert( + single_dungeon_group.section_mut().insert( scene_uid, section_id, SectionInfo { @@ -67,10 +64,8 @@ fn build_scene_unit_protocol_info( scene_uid: u64, section_id: u32, ) -> Vec { - let sdg = session.player_info.single_dungeon_group.as_ref().unwrap(); - sdg.npcs - .as_ref() - .unwrap() + let sdg = session.player_info.single_dungeon_group(); + sdg.npcs() .iter() .filter(|(s_uid, _, npc)| { **s_uid == scene_uid && npc.scene_data.section_id == section_id as i32 diff --git a/crates/protocol/protocol-macros/src/lib.rs b/crates/protocol/protocol-macros/src/lib.rs index 4e0acc3..ec7c0d4 100644 --- a/crates/protocol/protocol-macros/src/lib.rs +++ b/crates/protocol/protocol-macros/src/lib.rs @@ -1,8 +1,16 @@ use polymorphic::implement_polymorphic; use proc_macro::TokenStream; +use property_accessors::implement_property_accessors; + mod polymorphic; +mod property_accessors; #[proc_macro] pub fn polymorphic(input: TokenStream) -> TokenStream { implement_polymorphic(input) } + +#[proc_macro_attribute] +pub fn property_accessors(_attr: TokenStream, item: TokenStream) -> TokenStream { + implement_property_accessors(item) +} diff --git a/crates/protocol/protocol-macros/src/property_accessors.rs b/crates/protocol/protocol-macros/src/property_accessors.rs new file mode 100644 index 0000000..6723420 --- /dev/null +++ b/crates/protocol/protocol-macros/src/property_accessors.rs @@ -0,0 +1,62 @@ +use proc_macro::TokenStream; +use quote::{format_ident, quote}; +use syn::{parse_macro_input, Fields, GenericArgument, ItemStruct, PathArguments, Type}; + +pub fn implement_property_accessors(input: TokenStream) -> TokenStream { + let input_struct = parse_macro_input!(input as ItemStruct); + let struct_name = &input_struct.ident; + + let Fields::Named(fields) = &input_struct.fields else { + panic!("only structs with named fields are supported by #[property_accessors]"); + }; + + let mut get_methods = proc_macro2::TokenStream::new(); + let mut get_mut_methods = proc_macro2::TokenStream::new(); + + for field in fields.named.iter() { + let name = field.ident.as_ref().unwrap(); + let ty = get_underlying_type(&field.ty); + + get_methods.extend(quote! { + pub fn #name(&self) -> &#ty { + self.#name.as_ref().unwrap() + } + }); + + let mut_getter_name = format_ident!("{}_mut", name); + get_mut_methods.extend(quote! { + pub fn #mut_getter_name(&mut self) -> &mut #ty { + self.#name.as_mut().unwrap() + } + }); + } + + quote! { + #input_struct + + impl #struct_name { + #get_methods + #get_mut_methods + } + } + .into() +} + +fn get_underlying_type(ty: &Type) -> &Type { + let Type::Path(path) = ty else { + panic!("all fields of struct for #[property_accessor] should be Option"); + }; + + let last_segment = path.path.segments.last(); + let last_segment = last_segment.as_ref().unwrap(); + + let PathArguments::AngleBracketed(args) = &last_segment.arguments else { + panic!("all fields of struct for #[property_accessor] should be Option"); + }; + + if let GenericArgument::Type(ty) = args.args.first().unwrap() { + ty + } else { + panic!("all fields of struct for #[property_accessor] should be Option"); + } +} diff --git a/crates/protocol/src/player_info.rs b/crates/protocol/src/player_info.rs index 8c2eb22..6c62ab4 100644 --- a/crates/protocol/src/player_info.rs +++ b/crates/protocol/src/player_info.rs @@ -1,5 +1,6 @@ use std::collections::{HashMap, HashSet}; +use protocol_macros::property_accessors; use qwer::{OctData, PropertyDoubleKeyHashMap, PropertyHashMap, PropertyHashSet}; use crate::action_info::ActionInfo; @@ -86,6 +87,7 @@ pub struct EventGraphsInfo { #[derive(OctData, Clone, Debug, Default)] #[property_object(u16, 0x01)] #[root] +#[property_accessors] pub struct PlayerInfo { #[tag = 1] pub uid: Option, @@ -215,6 +217,7 @@ pub struct PlayerInfo { #[derive(OctData, Clone, Debug, Default)] #[property_object] +#[property_accessors] pub struct DungeonCollection { #[tag = 1] pub dungeons: Option>, @@ -264,6 +267,7 @@ pub struct VideotapeInfo { #[derive(OctData, Clone, Debug, Default)] #[property_object] +#[property_accessors] pub struct ArchiveInfo { #[tag = 1] pub videotaps_info: Option>, @@ -283,6 +287,7 @@ pub struct UnlockInfo { #[derive(OctData, Clone, Debug, Default)] #[property_object] +#[property_accessors] pub struct YorozuyaInfo { #[tag = 1] pub last_refresh_timestamp_common: Option, @@ -333,6 +338,7 @@ pub struct EquipGachaInfo { #[derive(OctData, Clone, Debug)] #[property_object] +#[property_accessors] pub struct BeginnerProcedureInfo { #[tag = 1] pub procedure_id: Option, @@ -340,6 +346,7 @@ pub struct BeginnerProcedureInfo { #[derive(OctData, Clone, Debug, Default)] #[property_object] +#[property_accessors] pub struct PlayerPosInMainCity { #[tag = 1] pub position: Option, @@ -777,6 +784,7 @@ pub struct SectionInfo { #[derive(OctData, Clone, Debug, Default)] #[property_object] +#[property_accessors] pub struct SingleDungeonGroup { #[tag = 1] pub dungeons: Option>, @@ -874,6 +882,7 @@ pub struct AreasInfo { #[derive(OctData, Clone, Debug)] #[property_object] +#[property_accessors] pub struct BGMInfo { #[tag = 1] pub bgm_id: Option, diff --git a/crates/protocol/src/util.rs b/crates/protocol/src/util.rs index c085aa7..851804f 100644 --- a/crates/protocol/src/util.rs +++ b/crates/protocol/src/util.rs @@ -8,18 +8,12 @@ use crate::{ pub fn build_player_basic_info(player_info: &PlayerInfo) -> PlayerBasicInfo { PlayerBasicInfo { - last_enter_world_timestamp: player_info.last_enter_world_timestamp.unwrap_or_default() - as i64, - avatar_id: player_info.avatar_id.unwrap_or_default(), - player_avatar_id: player_info.avatar_id.unwrap_or_default(), - main_city_avatar_id: player_info.main_city_avatar_id.unwrap_or_default(), - nick_name: player_info.nick_name.clone().unwrap_or_default(), - level: player_info - .yorozuya_info - .as_ref() - .map(|yi| yi.yorozuya_level) - .flatten() - .unwrap_or_default(), + last_enter_world_timestamp: *player_info.last_enter_world_timestamp() as i64, + avatar_id: *player_info.avatar_id(), + player_avatar_id: *player_info.avatar_id(), + main_city_avatar_id: *player_info.main_city_avatar_id(), + nick_name: player_info.nick_name().clone(), + level: *player_info.yorozuya_info().yorozuya_level(), } } @@ -27,16 +21,13 @@ pub fn build_client_scene_info( player_info: &PlayerInfo, scene_uid: u64, ) -> Option { - let dungeon_collection = player_info.dungeon_collection.as_ref().unwrap(); - let Some(scene_info) = dungeon_collection.scenes.as_ref().unwrap().get(&scene_uid) else { + let dungeon_collection = player_info.dungeon_collection(); + let Some(scene_info) = dungeon_collection.scenes().get(&scene_uid) else { return None; }; - let player_pos_in_main_city = player_info.pos_in_main_city.as_ref().unwrap(); - let initial_transform = player_pos_in_main_city - .initial_pos_id - .clone() - .unwrap_or_default(); + let player_pos_in_main_city = player_info.pos_in_main_city(); + let initial_transform = player_pos_in_main_city.initial_pos_id().clone(); Some(match scene_info { SceneInfo::Hall { @@ -49,35 +40,22 @@ pub fn build_client_scene_info( scene_type: 1, hall_scene_info: Some(crate::HallSceneInfo { section_id: *section_id as u32, - player_avatar_id: player_info.avatar_id.unwrap_or_default(), - main_city_avatar_id: player_info.main_city_avatar_id.unwrap_or_default(), - bgm_id: player_info - .bgm_info - .as_ref() - .map(|bgm| bgm.bgm_id.clone()) - .flatten() - .unwrap_or_default(), + player_avatar_id: *player_info.avatar_id(), + main_city_avatar_id: *player_info.main_city_avatar_id(), + bgm_id: *player_info.bgm_info().bgm_id(), day_of_week: main_city_time_info.day_of_week as u32, time_of_day: main_city_time_info.initial_time, camera_x: *camera_x, camera_y: *camera_y, position: initial_transform.is_empty().then(|| crate::Transform { - position: player_pos_in_main_city - .position - .clone() - .unwrap_or_default() - .into(), - rotation: player_pos_in_main_city - .rotation - .clone() - .unwrap_or_default() - .into(), + position: player_pos_in_main_city.position().clone().into(), + rotation: player_pos_in_main_city.rotation().clone().into(), }), main_city_objects_state: player_info - .main_city_objects_state - .as_ref() - .map(|map| map.iter().map(|(&k, &v)| (k, v)).collect()) - .unwrap_or_default(), + .main_city_objects_state() + .iter() + .map(|(&k, &v)| (k, v)) + .collect(), scene_unit_list: Vec::new(), transform_id: initial_transform, }), @@ -86,12 +64,7 @@ pub fn build_client_scene_info( SceneInfo::Fresh { .. } => crate::SceneInfo { scene_type: 4, fresh_scene_info: Some(crate::FreshSceneInfo { - beginner_procedure_id: player_info - .beginner_procedure_info - .as_ref() - .unwrap() - .procedure_id - .unwrap_or_default() as u32, + beginner_procedure_id: *player_info.beginner_procedure_info().procedure_id() as u32, }), ..Default::default() }, @@ -123,8 +96,8 @@ pub fn build_client_dungeon_info( player_info: &PlayerInfo, scene_uid: u64, ) -> Option { - let dungeon_collection = player_info.dungeon_collection.as_ref().unwrap(); - let Some(scene_info) = dungeon_collection.scenes.as_ref().unwrap().get(&scene_uid) else { + let dungeon_collection = player_info.dungeon_collection(); + let Some(scene_info) = dungeon_collection.scenes().get(&scene_uid) else { return None; }; @@ -134,9 +107,7 @@ pub fn build_client_dungeon_info( } let dungeon_info = dungeon_collection - .dungeons - .as_ref() - .unwrap() + .dungeons() .get(scene_info.get_dungeon_uid()) .unwrap(); @@ -147,7 +118,7 @@ pub fn build_client_dungeon_info( .avatars .iter() .map(|(_, unit)| { - let avatar_info = player_info.items.as_ref().unwrap().get(&unit.uid).unwrap(); + let avatar_info = player_info.items().get(&unit.uid).unwrap(); AvatarUnitInfo { avatar_id: *avatar_info.get_id() as u32, } @@ -162,13 +133,9 @@ pub fn build_hall_refresh_arg( hall_scene_uid: u64, refresh_immediately: bool, ) -> Option { - let dungeon_collection = player_info.dungeon_collection.as_ref().unwrap(); - let scene_info = dungeon_collection - .scenes - .as_ref() - .unwrap() - .get(&hall_scene_uid); - let player_pos_in_main_city = player_info.pos_in_main_city.as_ref().unwrap(); + let dungeon_collection = player_info.dungeon_collection(); + let scene_info = dungeon_collection.scenes().get(&hall_scene_uid); + let player_pos_in_main_city = player_info.pos_in_main_city(); match scene_info { Some(SceneInfo::Hall { @@ -180,39 +147,23 @@ pub fn build_hall_refresh_arg( }) => Some(PtcHallRefreshArg { refresh_immediately, section_id: *section_id as u32, - player_avatar_id: player_info.avatar_id.unwrap_or_default(), - main_city_avatar_id: player_info.main_city_avatar_id.unwrap_or_default(), - transform_id: player_pos_in_main_city - .initial_pos_id - .clone() - .unwrap_or_default(), - bgm_id: player_info - .bgm_info - .as_ref() - .map(|bgm| bgm.bgm_id.clone()) - .flatten() - .unwrap_or_default(), + player_avatar_id: *player_info.avatar_id(), + main_city_avatar_id: *player_info.main_city_avatar_id(), + transform_id: player_pos_in_main_city.initial_pos_id().clone(), + bgm_id: *player_info.bgm_info().bgm_id(), day_of_week: main_city_time_info.day_of_week as u32, time_of_day: main_city_time_info.initial_time, camera_x: *camera_x, camera_y: *camera_y, position: crate::Transform { - position: player_pos_in_main_city - .position - .clone() - .unwrap_or_default() - .into(), - rotation: player_pos_in_main_city - .rotation - .clone() - .unwrap_or_default() - .into(), + position: player_pos_in_main_city.position().clone().into(), + rotation: player_pos_in_main_city.rotation().clone().into(), }, main_city_objects_state: player_info - .main_city_objects_state - .as_ref() - .map(|map| map.iter().map(|(&k, &v)| (k, v)).collect()) - .unwrap_or_default(), + .main_city_objects_state() + .iter() + .map(|(&k, &v)| (k, v)) + .collect(), scene_unit_list: Vec::new(), }), _ => None, @@ -221,9 +172,7 @@ pub fn build_hall_refresh_arg( pub fn build_sync_avatar_info_list(player_info: &PlayerInfo) -> Vec { player_info - .items - .as_ref() - .unwrap() + .items() .iter() .map(|(uid, item)| { if let ItemInfo::AvatarInfo { @@ -249,9 +198,7 @@ pub fn build_sync_avatar_info_list(player_info: &PlayerInfo) -> Vec first_get_time: *first_get_time as i64, talent_switch_list: talent_switch.clone(), cur_weapon_uid: player_info - .items - .as_ref() - .unwrap() + .items() .iter() .find(|(_, item)| { if let ItemInfo::Weapon { avatar_uid, .. } = item { @@ -280,9 +227,7 @@ pub fn build_sync_avatar_info_list(player_info: &PlayerInfo) -> Vec pub fn build_sync_weapon_info_list(player_info: &PlayerInfo) -> Vec { player_info - .items - .as_ref() - .unwrap() + .items() .iter() .map(|(_, item)| { if let ItemInfo::Weapon { @@ -315,9 +260,7 @@ pub fn build_sync_weapon_info_list(player_info: &PlayerInfo) -> Vec pub fn build_sync_equip_info_list(player_info: &PlayerInfo) -> Vec { player_info - .items - .as_ref() - .unwrap() + .items() .iter() .map(|(_, item)| { if let ItemInfo::Equip { @@ -348,9 +291,7 @@ pub fn build_sync_equip_info_list(player_info: &PlayerInfo) -> Vec { pub fn build_sync_resource_info_list(player_info: &PlayerInfo) -> Vec { player_info - .items - .as_ref() - .unwrap() + .items() .iter() .map(|(_, item)| match item { ItemInfo::Currency { id, count, .. } => Some(ResourceInfo { @@ -379,9 +320,7 @@ pub fn build_sync_auto_recovery_info( player_info: &PlayerInfo, ) -> HashMap { player_info - .auto_recovery_info - .as_ref() - .unwrap() + .auto_recovery_info() .iter() .map(|(id, info)| (*id as u32, info.clone())) .collect()