use std::fmt::Debug; use std::ops::Deref; use std::sync::Arc; use crate::dynamic_data::libraries::battle_stat_calculator::BattleStatCalculator; use crate::dynamic_data::libraries::damage_library::DamageLibrary; use crate::dynamic_data::libraries::misc_library::MiscLibrary; use crate::dynamic_data::libraries::script_resolver::ScriptCategory; use crate::dynamic_data::{ItemScript, ScriptResolver}; use crate::dynamic_data::{Script, ScriptOwnerData}; use crate::static_data::Item; use crate::static_data::StaticData; use crate::{PkmnResult, StringKey, ValueIdentifiable, ValueIdentifier}; /// The dynamic library stores a static data library, as well as holding different libraries and /// calculators that might be customized between different generations and implementations. pub trait DynamicLibrary: Debug + ValueIdentifiable { /// The static data is the immutable storage data for this library. fn static_data(&self) -> &Box; /// The stat calculator deals with the calculation of flat and boosted stats, based on the /// Pokemons attributes. fn stat_calculator(&self) -> &dyn BattleStatCalculator; /// The damage calculator deals with the calculation of things relating to damage. fn damage_calculator(&self) -> &dyn DamageLibrary; /// The Misc Library holds minor functions that do not fall in any of the other libraries and /// calculators. fn misc_library(&self) -> &dyn MiscLibrary; /// Loads a standard script with a given unique combination of category and key. If no script /// can be created with this combination, returns None. fn load_script( &self, owner: ScriptOwnerData, _category: ScriptCategory, _key: &StringKey, ) -> PkmnResult>>; /// Loads an item script with the given unique key. If no script can be created with this /// combinations, returns None. Note that ItemScripts are immutable, as their script should be /// shared between all different usages. fn load_item_script(&self, _key: &Arc) -> PkmnResult>>; } /// The dynamic library stores a static data library, as well as holding different libraries and /// calculators that might be customized between different generations and implementations. #[derive(Debug)] pub struct DynamicLibraryImpl { /// A unique identifier so we know what value this is. identifier: ValueIdentifier, /// The static data is the immutable storage data for this library. static_data: Box, /// The stat calculator deals with the calculation of flat and boosted stats, based on the /// Pokemons attributes. stat_calculator: Box, /// The damage calculator deals with the calculation of things relating to damage. damage_calculator: Box, /// The Misc Library holds minor functions that do not fall in any of the other libraries and /// calculators. misc_library: Box, /// The script resolver deals with how to resolve the scripts from specific unique key combinations. script_resolver: Box, } impl DynamicLibraryImpl { /// Instantiates a new DynamicLibrary with given parameters. pub fn new( static_data: Box, stat_calculator: Box, damage_calculator: Box, misc_library: Box, script_resolver: Box, ) -> Self { Self { identifier: Default::default(), static_data, stat_calculator, damage_calculator, misc_library, script_resolver, } } } impl DynamicLibrary for DynamicLibraryImpl { /// The static data is the immutable storage data for this library. fn static_data(&self) -> &Box { &self.static_data } /// The stat calculator deals with the calculation of flat and boosted stats, based on the /// Pokemons attributes. fn stat_calculator(&self) -> &dyn BattleStatCalculator { self.stat_calculator.deref() } /// The damage calculator deals with the calculation of things relating to damage. fn damage_calculator(&self) -> &dyn DamageLibrary { self.damage_calculator.deref() } /// The Misc Library holds minor functions that do not fall in any of the other libraries and /// calculators. fn misc_library(&self) -> &dyn MiscLibrary { self.misc_library.deref() } /// Loads a standard script with a given unique combination of category and key. If no script /// can be created with this combination, returns None. fn load_script( &self, owner: ScriptOwnerData, _category: ScriptCategory, _key: &StringKey, ) -> PkmnResult>> { self.script_resolver.load_script(owner, _category, _key) } /// Loads an item script with the given unique key. If no script can be created with this /// combinations, returns None. Note that ItemScripts are immutable, as their script should be /// shared between all different usages. fn load_item_script(&self, _key: &Arc) -> PkmnResult>> { todo!() } } impl ValueIdentifiable for DynamicLibraryImpl { fn value_identifier(&self) -> ValueIdentifier { self.identifier } } #[cfg(test)] pub mod test { use super::*; use crate::dynamic_data::libraries::battle_stat_calculator::Gen7BattleStatCalculator; use crate::dynamic_data::libraries::damage_library::Gen7DamageLibrary; use crate::dynamic_data::libraries::misc_library::Gen7MiscLibrary; use crate::dynamic_data::EmptyScriptResolver; mockall::mock! { #[derive(Debug)] pub DynamicLibrary{} impl DynamicLibrary for DynamicLibrary { fn static_data(&self) -> &Box; fn stat_calculator(&self) -> &dyn BattleStatCalculator; fn damage_calculator(&self) -> &dyn DamageLibrary; fn misc_library(&self) -> &dyn MiscLibrary; fn load_script( &self, owner: ScriptOwnerData, _category: ScriptCategory, _key: &StringKey, ) -> PkmnResult>>; fn load_item_script(&self, _key: &Arc) -> PkmnResult>>; } impl ValueIdentifiable for DynamicLibrary{ fn value_identifier(&self) -> ValueIdentifier{ ValueIdentifier::new(0) } } } pub fn build() -> DynamicLibraryImpl { DynamicLibraryImpl { identifier: Default::default(), static_data: Box::new(crate::static_data::libraries::static_data::test::build()), stat_calculator: Box::new(Gen7BattleStatCalculator::new()), damage_calculator: Box::new(Gen7DamageLibrary::new(false)), misc_library: Box::new(Gen7MiscLibrary::new()), script_resolver: Box::new(EmptyScriptResolver { identifier: Default::default(), }), } } }