Moves a bunch of libraries to traits
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Deukhoofd 2022-12-24 12:00:50 +01:00
parent bce636b97e
commit 47df85e8d3
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
47 changed files with 730 additions and 358 deletions

View File

@ -132,8 +132,8 @@ impl ValueIdentifiable for ChoiceQueue {
mod tests { mod tests {
use super::*; use super::*;
use crate::defines::LevelInt; use crate::defines::LevelInt;
use crate::dynamic_data::PassChoice; use crate::dynamic_data::{DynamicLibrary, PassChoice};
use crate::static_data::{AbilityIndex, DataLibrary, Gender}; use crate::static_data::{AbilityIndex, Gender};
use std::sync::Arc; use std::sync::Arc;
#[test] #[test]

View File

@ -9,7 +9,7 @@ use crate::dynamic_data::Battle;
use crate::dynamic_data::DamageSource; use crate::dynamic_data::DamageSource;
use crate::dynamic_data::ExecutingMove; use crate::dynamic_data::ExecutingMove;
use crate::dynamic_data::Pokemon; use crate::dynamic_data::Pokemon;
use crate::static_data::{DataLibrary, MoveCategory}; use crate::static_data::MoveCategory;
use crate::{run_scripts, script_hook, PkmnResult}; use crate::{run_scripts, script_hook, PkmnResult};
impl Battle { impl Battle {

View File

@ -137,3 +137,23 @@ impl ValueIdentifiable for Gen7BattleStatCalculator {
self.identifier self.identifier
} }
} }
#[cfg(test)]
pub mod tests {
use super::*;
mockall::mock! {
#[derive(Debug)]
pub BattleStatCalculator{}
impl BattleStatCalculator for BattleStatCalculator {
fn calculate_flat_stats(&self, pokemon: &Pokemon, stats: &StatisticSet<u32>);
fn calculate_flat_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32;
fn calculate_boosted_stats(&self, pokemon: &Pokemon, stats: &StatisticSet<u32>);
fn calculate_boosted_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32;
}
impl ValueIdentifiable for BattleStatCalculator {
fn value_identifier(&self) -> ValueIdentifier{
ValueIdentifier::new(0)
}
}
}
}

View File

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

View File

@ -47,7 +47,7 @@ impl Gen7MiscLibrary {
))), ))),
HashSet::new(), HashSet::new(),
)); ));
let struggle_learned_move = Arc::new(LearnedMove::new(&struggle_data, MoveLearnMethod::Unknown)); let struggle_learned_move = Arc::new(LearnedMove::new(struggle_data, MoveLearnMethod::Unknown));
Self { Self {
identifier: Default::default(), identifier: Default::default(),
struggle_learned_move, struggle_learned_move,

View File

@ -26,7 +26,7 @@ pub struct Battle {
/// A unique identifier so we know what value this is. /// A unique identifier so we know what value this is.
identifier: ValueIdentifier, identifier: ValueIdentifier,
/// The library the battle uses for handling. /// The library the battle uses for handling.
library: Arc<DynamicLibrary>, library: Arc<dyn DynamicLibrary>,
/// A list of all different parties in the battle. /// A list of all different parties in the battle.
parties: Vec<BattleParty>, parties: Vec<BattleParty>,
/// Whether or not Pokemon can flee from the battle. /// Whether or not Pokemon can flee from the battle.
@ -62,7 +62,7 @@ pub struct Battle {
impl Battle { impl Battle {
/// Initializes a new battle. /// Initializes a new battle.
pub fn new( pub fn new(
library: Arc<DynamicLibrary>, library: Arc<dyn DynamicLibrary>,
parties: Vec<BattleParty>, parties: Vec<BattleParty>,
can_flee: bool, can_flee: bool,
number_of_sides: u8, number_of_sides: u8,
@ -110,7 +110,7 @@ impl Battle {
} }
/// The library the battle uses for handling. /// The library the battle uses for handling.
pub fn library(&self) -> &Arc<DynamicLibrary> { pub fn library(&self) -> &Arc<dyn DynamicLibrary> {
&self.library &self.library
} }
/// A list of all different parties in the battle. /// A list of all different parties in the battle.

View File

@ -33,12 +33,13 @@ pub enum MoveLearnMethod {
impl LearnedMove { impl LearnedMove {
/// Instantiate a new learned move. /// Instantiate a new learned move.
pub fn new(move_data: &Arc<dyn MoveData>, learn_method: MoveLearnMethod) -> Self { pub fn new(move_data: Arc<dyn MoveData>, learn_method: MoveLearnMethod) -> Self {
let max_pp = move_data.base_usages();
Self { Self {
identifier: Default::default(), identifier: Default::default(),
move_data: move_data.clone(), move_data,
max_pp: move_data.base_usages(), max_pp,
remaining_pp: AtomicU8::new(move_data.base_usages()), remaining_pp: AtomicU8::new(max_pp),
learn_method, learn_method,
} }
} }
@ -107,7 +108,7 @@ mod tests {
let mut mock = MockMoveData::new(); let mut mock = MockMoveData::new();
mock.expect_base_usages().return_const(30); mock.expect_base_usages().return_const(30);
let data: Arc<dyn MoveData> = Arc::new(mock); let data: Arc<dyn MoveData> = Arc::new(mock);
let learned_move = LearnedMove::new(&data, MoveLearnMethod::Level); let learned_move = LearnedMove::new(data, MoveLearnMethod::Level);
assert!(learned_move.try_use(15)); assert!(learned_move.try_use(15));
learned_move.restore_uses(5); learned_move.restore_uses(5);
assert_eq!(20, learned_move.remaining_pp()); assert_eq!(20, learned_move.remaining_pp());

View File

@ -12,6 +12,7 @@ use crate::dynamic_data::models::battle::Battle;
use crate::dynamic_data::models::learned_move::{LearnedMove, MoveLearnMethod}; use crate::dynamic_data::models::learned_move::{LearnedMove, MoveLearnMethod};
use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, ScriptWrapper}; use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, ScriptWrapper};
use crate::dynamic_data::{DynamicLibrary, Script, ScriptCategory, ScriptContainer, ScriptSet, VolatileScriptsOwner}; use crate::dynamic_data::{DynamicLibrary, Script, ScriptCategory, ScriptContainer, ScriptSet, VolatileScriptsOwner};
use crate::static_data::AbilityIndex;
use crate::static_data::Form; use crate::static_data::Form;
use crate::static_data::Gender; use crate::static_data::Gender;
use crate::static_data::Item; use crate::static_data::Item;
@ -19,7 +20,6 @@ use crate::static_data::Nature;
use crate::static_data::Species; use crate::static_data::Species;
use crate::static_data::TypeIdentifier; use crate::static_data::TypeIdentifier;
use crate::static_data::{Ability, Statistic}; use crate::static_data::{Ability, Statistic};
use crate::static_data::{AbilityIndex, DataLibrary};
use crate::static_data::{ClampedStatisticSet, StatisticSet}; use crate::static_data::{ClampedStatisticSet, StatisticSet};
use crate::utils::Random; use crate::utils::Random;
use crate::{script_hook, PkmnResult, StringKey, ValueIdentifiable, ValueIdentifier}; use crate::{script_hook, PkmnResult, StringKey, ValueIdentifiable, ValueIdentifier};
@ -30,7 +30,7 @@ pub struct Pokemon {
/// A unique identifier so we know what value this is. /// A unique identifier so we know what value this is.
identifier: ValueIdentifier, identifier: ValueIdentifier,
/// The library data of the Pokemon. /// The library data of the Pokemon.
library: Arc<DynamicLibrary>, library: Arc<dyn DynamicLibrary>,
/// The species of the Pokemon. /// The species of the Pokemon.
species: RwLock<Arc<dyn Species>>, species: RwLock<Arc<dyn Species>>,
/// The form of the Pokemon. /// The form of the Pokemon.
@ -120,7 +120,7 @@ pub struct Pokemon {
impl Pokemon { impl Pokemon {
/// Instantiates a new Pokemon. /// Instantiates a new Pokemon.
pub fn new( pub fn new(
library: Arc<DynamicLibrary>, library: Arc<dyn DynamicLibrary>,
species: Arc<dyn Species>, species: Arc<dyn Species>,
form: &Arc<dyn Form>, form: &Arc<dyn Form>,
ability: AbilityIndex, ability: AbilityIndex,
@ -188,7 +188,7 @@ impl Pokemon {
} }
/// The library data of the Pokemon. /// The library data of the Pokemon.
pub fn library(&self) -> &Arc<DynamicLibrary> { pub fn library(&self) -> &Arc<dyn DynamicLibrary> {
&self.library &self.library
} }
/// The species of the Pokemon. /// The species of the Pokemon.
@ -416,9 +416,9 @@ impl Pokemon {
self.override_ability.is_some() self.override_ability.is_some()
} }
/// Returns the currently active ability. /// Returns the currently active ability.
pub fn active_ability(&self) -> &Arc<dyn Ability> { pub fn active_ability(&self) -> Arc<dyn Ability> {
if let Some(v) = &self.override_ability { if let Some(v) = &self.override_ability {
return v; return v.clone();
} }
self.library self.library
.static_data() .static_data()
@ -523,7 +523,7 @@ impl Pokemon {
.set(ability_script) .set(ability_script)
.as_ref() .as_ref()
// Ensure the ability script gets initialized with the parameters for the ability. // Ensure the ability script gets initialized with the parameters for the ability.
.on_initialize(self.library.as_ref(), self.active_ability().parameters().to_vec()) .on_initialize(&self.library, self.active_ability().parameters().to_vec())
} else { } else {
self.ability_script.clear(); self.ability_script.clear();
} }
@ -829,14 +829,69 @@ pub enum DamageSource {
#[cfg(test)] #[cfg(test)]
pub mod test { pub mod test {
use crate::dynamic_data::libraries::test::MockDynamicLibrary;
use crate::dynamic_data::models::pokemon::Pokemon; use crate::dynamic_data::models::pokemon::Pokemon;
use crate::static_data::Gender; use crate::dynamic_data::tests::MockBattleStatCalculator;
use crate::static_data::{AbilityIndex, DataLibrary}; use crate::dynamic_data::DynamicLibrary;
use crate::static_data::growth_rate_library::tests::MockGrowthRateLibrary;
use crate::static_data::nature_library::tests::MockNatureLibrary;
use crate::static_data::species_library::tests::MockSpeciesLibrary;
use crate::static_data::test::MockStaticData;
use crate::static_data::tests::{MockForm, MockNature, MockSpecies};
use crate::static_data::{AbilityIndex, Species};
use crate::static_data::{Form, Gender};
use crate::StringKey;
use std::sync::Arc; use std::sync::Arc;
pub fn mock_library() -> Arc<dyn DynamicLibrary> {
let mut species_lib = MockSpeciesLibrary::new();
species_lib.expect_get().return_once(|_| {
let mut species = MockSpecies::new();
species.expect_get_form().return_once(|_| {
let mut form = MockForm::new();
form.expect_name().return_const(StringKey::new("default"));
form.expect_weight().return_const(100.0);
form.expect_height().return_const(20.0);
form.expect_types().return_const(vec![0u8.into()]);
let a: Arc<dyn Form> = Arc::new(form);
Some(a)
});
species.expect_growth_rate().return_const(StringKey::empty());
species.expect_name().return_const(StringKey::new("test_species"));
let s: Arc<dyn Species> = Arc::new(species);
Some(s)
});
let mut static_lib = MockStaticData::new();
static_lib.expect_species().return_const(Box::new(species_lib));
let mut growth_rate_lib = MockGrowthRateLibrary::new();
growth_rate_lib.expect_calculate_experience().return_const(1000u32);
let mut nature_lib = MockNatureLibrary::new();
nature_lib.expect_get_nature().returning(|_| {
let n = MockNature::new();
Some(Arc::new(n))
});
static_lib.expect_growth_rates().return_const(Box::new(growth_rate_lib));
static_lib.expect_natures().return_const(Box::new(nature_lib));
let mut stat_calculator = MockBattleStatCalculator::new();
stat_calculator.expect_calculate_flat_stats().returning(|_, _| {});
stat_calculator.expect_calculate_boosted_stats().returning(|_, _| {});
let mut lib = MockDynamicLibrary::new();
lib.expect_static_data().return_const(Box::new(static_lib));
lib.expect_stat_calculator().return_const(Box::new(stat_calculator));
Arc::new(lib)
}
#[test] #[test]
fn construct_pokemon() { fn construct_pokemon() {
let lib = Arc::new(crate::dynamic_data::libraries::dynamic_library::test::build()); let lib = mock_library();
let species = lib.static_data().species().get(&"foo".into()).unwrap().clone(); let species = lib.static_data().species().get(&"foo".into()).unwrap().clone();
let form = species.get_form(&"default".into()).unwrap(); let form = species.get_form(&"default".into()).unwrap();
@ -854,7 +909,7 @@ pub mod test {
0, 0,
&"test_nature".into(), &"test_nature".into(),
); );
assert_eq!(pokemon.species().name(), &"foo".into()); assert_eq!(pokemon.species().name(), &"test_species".into());
assert_eq!(pokemon.form().name(), &"default".into()); assert_eq!(pokemon.form().name(), &"default".into());
} }
} }

View File

@ -4,13 +4,13 @@ use crate::defines::LevelInt;
use crate::dynamic_data::models::learned_move::MoveLearnMethod; use crate::dynamic_data::models::learned_move::MoveLearnMethod;
use crate::dynamic_data::models::pokemon::Pokemon; use crate::dynamic_data::models::pokemon::Pokemon;
use crate::dynamic_data::DynamicLibrary; use crate::dynamic_data::DynamicLibrary;
use crate::static_data::{AbilityIndex, DataLibrary, Gender}; use crate::static_data::{AbilityIndex, Gender};
use crate::{Random, StringKey}; use crate::{Random, StringKey};
/// This allows for the easy chain building of a Pokemon. /// This allows for the easy chain building of a Pokemon.
pub struct PokemonBuilder { pub struct PokemonBuilder {
/// The library of the Pokemon. /// The library of the Pokemon.
library: Arc<DynamicLibrary>, library: Arc<dyn DynamicLibrary>,
/// The name of the species of the Pokemon. /// The name of the species of the Pokemon.
species: StringKey, species: StringKey,
/// The level of the Pokemon. /// The level of the Pokemon.
@ -23,7 +23,7 @@ pub struct PokemonBuilder {
impl PokemonBuilder { impl PokemonBuilder {
/// Creates a new PokemonBuilder with a library, species, and level. /// Creates a new PokemonBuilder with a library, species, and level.
pub fn new(library: Arc<DynamicLibrary>, species: StringKey, level: LevelInt) -> Self { pub fn new(library: Arc<dyn DynamicLibrary>, species: StringKey, level: LevelInt) -> Self {
Self { Self {
library, library,
species, species,

View File

@ -64,7 +64,7 @@ pub trait Script: Send + Sync {
/// This function is ran when this script stops being in effect, and is removed from its owner. /// This function is ran when this script stops being in effect, and is removed from its owner.
fn on_remove(&self) {} fn on_remove(&self) {}
/// This function is ran when this script starts being in effect. /// This function is ran when this script starts being in effect.
fn on_initialize(&self, _library: &DynamicLibrary, _pars: Vec<EffectParameter>) {} fn on_initialize(&self, _library: &Arc<dyn DynamicLibrary>, _pars: Vec<EffectParameter>) {}
/// This function is ran just before the start of the turn. Everyone has made its choices here, /// This function is ran just before the start of the turn. Everyone has made its choices here,
/// and the turn is about to start. This is a great place to initialize data if you need to know /// and the turn is about to start. This is a great place to initialize data if you need to know
/// something has happened during a turn. /// something has happened during a turn.

View File

@ -1,4 +1,6 @@
use crate::dynamic_data::{BattleStatCalculator, DamageLibrary, DynamicLibrary, MiscLibrary, ScriptResolver}; use crate::dynamic_data::{
BattleStatCalculator, DamageLibrary, DynamicLibrary, DynamicLibraryImpl, MiscLibrary, ScriptResolver,
};
use crate::ffi::{IdentifiablePointer, OwnedPtr}; use crate::ffi::{IdentifiablePointer, OwnedPtr};
use crate::static_data::StaticData; use crate::static_data::StaticData;
use std::sync::Arc; use std::sync::Arc;
@ -6,20 +8,20 @@ use std::sync::Arc;
/// Instantiates a new DynamicLibrary with given parameters. /// Instantiates a new DynamicLibrary with given parameters.
#[no_mangle] #[no_mangle]
extern "C" fn dynamic_library_new( extern "C" fn dynamic_library_new(
static_data: OwnedPtr<StaticData>, static_data: OwnedPtr<Box<dyn StaticData>>,
stat_calculator: OwnedPtr<Box<dyn BattleStatCalculator>>, stat_calculator: OwnedPtr<Box<dyn BattleStatCalculator>>,
damage_library: OwnedPtr<Box<dyn DamageLibrary>>, damage_library: OwnedPtr<Box<dyn DamageLibrary>>,
misc_library: OwnedPtr<Box<dyn MiscLibrary>>, misc_library: OwnedPtr<Box<dyn MiscLibrary>>,
script_resolver: OwnedPtr<Box<dyn ScriptResolver>>, script_resolver: OwnedPtr<Box<dyn ScriptResolver>>,
) -> IdentifiablePointer<Arc<DynamicLibrary>> { ) -> IdentifiablePointer<Arc<dyn DynamicLibrary>> {
unsafe { unsafe {
Arc::new(DynamicLibrary::new( let a: Arc<dyn DynamicLibrary> = Arc::new(DynamicLibraryImpl::new(
*Box::from_raw(static_data), *Box::from_raw(static_data),
*Box::from_raw(stat_calculator), *Box::from_raw(stat_calculator),
*Box::from_raw(damage_library), *Box::from_raw(damage_library),
*Box::from_raw(misc_library), *Box::from_raw(misc_library),
*Box::from_raw(script_resolver), *Box::from_raw(script_resolver),
)) ));
.into() a.into()
} }
} }

View File

@ -9,7 +9,7 @@ use std::sync::Arc;
/// Initializes a new battle. /// Initializes a new battle.
#[no_mangle] #[no_mangle]
extern "C" fn battle_new( extern "C" fn battle_new(
library: ExternPointer<Arc<DynamicLibrary>>, library: ExternPointer<Arc<dyn DynamicLibrary>>,
parties: *const OwnedPtr<BattleParty>, parties: *const OwnedPtr<BattleParty>,
parties_length: usize, parties_length: usize,
can_flee: u8, can_flee: u8,
@ -46,7 +46,7 @@ extern "C" fn battle_new(
/// The library the battle uses for handling. /// The library the battle uses for handling.
#[no_mangle] #[no_mangle]
extern "C" fn battle_library(ptr: ExternPointer<Arc<Battle>>) -> IdentifiablePointer<Arc<DynamicLibrary>> { extern "C" fn battle_library(ptr: ExternPointer<Arc<Battle>>) -> IdentifiablePointer<Arc<dyn DynamicLibrary>> {
ptr.as_ref().library().clone().into() ptr.as_ref().library().clone().into()
} }

View File

@ -10,7 +10,7 @@ extern "C" fn learned_move_new(
move_data: ExternPointer<Arc<dyn MoveData>>, move_data: ExternPointer<Arc<dyn MoveData>>,
learn_method: MoveLearnMethod, learn_method: MoveLearnMethod,
) -> IdentifiablePointer<Arc<LearnedMove>> { ) -> IdentifiablePointer<Arc<LearnedMove>> {
Arc::new(LearnedMove::new(move_data.as_ref(), learn_method)).into() Arc::new(LearnedMove::new(move_data.as_ref().clone(), learn_method)).into()
} }
/// Drops a learned move. /// Drops a learned move.

View File

@ -11,7 +11,7 @@ use std::sync::Arc;
/// Instantiates a new Pokemon. /// Instantiates a new Pokemon.
#[no_mangle] #[no_mangle]
extern "C" fn pokemon_new( extern "C" fn pokemon_new(
library: ExternPointer<Arc<DynamicLibrary>>, library: ExternPointer<Arc<dyn DynamicLibrary>>,
species: ExternPointer<Arc<dyn Species>>, species: ExternPointer<Arc<dyn Species>>,
form: ExternPointer<Arc<dyn Form>>, form: ExternPointer<Arc<dyn Form>>,
hidden_ability: bool, hidden_ability: bool,
@ -48,7 +48,7 @@ unsafe extern "C" fn pokemon_drop(ptr: OwnedPtr<Arc<Pokemon>>) {
/// The library data of the Pokemon. /// The library data of the Pokemon.
#[no_mangle] #[no_mangle]
extern "C" fn pokemon_library(ptr: ExternPointer<Arc<Pokemon>>) -> IdentifiablePointer<Arc<DynamicLibrary>> { extern "C" fn pokemon_library(ptr: ExternPointer<Arc<Pokemon>>) -> IdentifiablePointer<Arc<dyn DynamicLibrary>> {
ptr.as_ref().library().clone().into() ptr.as_ref().library().clone().into()
} }

View File

@ -163,6 +163,16 @@ impl<T: ValueIdentifiable + ?Sized> From<Box<T>> for IdentifiablePointer<Box<T>>
} }
} }
impl<T: ValueIdentifiable + ?Sized> From<&Box<T>> for IdentifiablePointer<Box<T>> {
fn from(v: &Box<T>) -> Self {
let id = unsafe { transmute(v.value_identifier()) };
Self {
ptr: v as *const Box<T>,
id,
}
}
}
impl<T: ValueIdentifiable + ?Sized> From<Option<Box<T>>> for IdentifiablePointer<Box<T>> { impl<T: ValueIdentifiable + ?Sized> From<Option<Box<T>>> for IdentifiablePointer<Box<T>> {
fn from(v: Option<Box<T>>) -> Self { fn from(v: Option<Box<T>>) -> Self {
if let Some(v) = v { if let Some(v) = v {

View File

@ -1,25 +1,26 @@
use crate::defines::LevelInt; use crate::defines::LevelInt;
use crate::ffi::{BorrowedPtr, ExternPointer, IdentifiablePointer, OwnedPtr}; use crate::ffi::{BorrowedPtr, ExternPointer, IdentifiablePointer, OwnedPtr};
use crate::static_data::{GrowthRate, GrowthRateLibrary}; use crate::static_data::{GrowthRate, GrowthRateLibrary, GrowthRateLibraryImpl};
use std::ffi::{c_char, CStr}; use std::ffi::{c_char, CStr};
use std::ptr::drop_in_place; use std::ptr::drop_in_place;
/// Instantiates a new growth rate library with a capacity /// Instantiates a new growth rate library with a capacity
#[no_mangle] #[no_mangle]
extern "C" fn growth_rate_library_new(capacity: usize) -> IdentifiablePointer<GrowthRateLibrary> { extern "C" fn growth_rate_library_new(capacity: usize) -> IdentifiablePointer<Box<dyn GrowthRateLibrary>> {
Box::new(GrowthRateLibrary::new(capacity)).into() let b: Box<dyn GrowthRateLibrary> = Box::new(GrowthRateLibraryImpl::new(capacity));
b.into()
} }
/// Drops the growthrate library. /// Drops the growthrate library.
#[no_mangle] #[no_mangle]
unsafe extern "C" fn growth_rate_library_drop(ptr: OwnedPtr<GrowthRateLibrary>) { unsafe extern "C" fn growth_rate_library_drop(ptr: OwnedPtr<Box<dyn GrowthRateLibrary>>) {
drop_in_place(ptr) drop_in_place(ptr)
} }
/// Calculates the level for a given growth key name and a certain experience. /// Calculates the level for a given growth key name and a certain experience.
#[no_mangle] #[no_mangle]
unsafe extern "C" fn growth_rate_library_calculate_level( unsafe extern "C" fn growth_rate_library_calculate_level(
ptr: ExternPointer<GrowthRateLibrary>, ptr: ExternPointer<Box<dyn GrowthRateLibrary>>,
growth_rate: BorrowedPtr<c_char>, growth_rate: BorrowedPtr<c_char>,
experience: u32, experience: u32,
) -> LevelInt { ) -> LevelInt {
@ -30,7 +31,7 @@ unsafe extern "C" fn growth_rate_library_calculate_level(
/// Calculates the experience for a given growth key name and a certain level. /// Calculates the experience for a given growth key name and a certain level.
#[no_mangle] #[no_mangle]
unsafe extern "C" fn growth_rate_library_calculate_experience( unsafe extern "C" fn growth_rate_library_calculate_experience(
ptr: ExternPointer<GrowthRateLibrary>, ptr: ExternPointer<Box<dyn GrowthRateLibrary>>,
growth_rate: BorrowedPtr<c_char>, growth_rate: BorrowedPtr<c_char>,
level: LevelInt, level: LevelInt,
) -> u32 { ) -> u32 {
@ -41,7 +42,7 @@ unsafe extern "C" fn growth_rate_library_calculate_experience(
/// Adds a new growth rate with a name and value. /// Adds a new growth rate with a name and value.
#[no_mangle] #[no_mangle]
unsafe extern "C" fn growth_rate_library_add_growth_rate( unsafe extern "C" fn growth_rate_library_add_growth_rate(
mut ptr: ExternPointer<GrowthRateLibrary>, mut ptr: ExternPointer<Box<dyn GrowthRateLibrary>>,
name: BorrowedPtr<c_char>, name: BorrowedPtr<c_char>,
growth_rate: OwnedPtr<Box<dyn GrowthRate>>, growth_rate: OwnedPtr<Box<dyn GrowthRate>>,
) { ) {

View File

@ -1,22 +1,23 @@
use crate::defines::LevelInt; use crate::defines::LevelInt;
use crate::ffi::{ExternPointer, IdentifiablePointer, OwnedPtr}; use crate::ffi::{ExternPointer, IdentifiablePointer, OwnedPtr};
use crate::static_data::LibrarySettings; use crate::static_data::{LibrarySettings, LibrarySettingsImpl};
use std::ptr::drop_in_place; use std::ptr::drop_in_place;
/// Creates a new settings library. /// Creates a new settings library.
#[no_mangle] #[no_mangle]
extern "C" fn library_settings_new(max_level: LevelInt) -> IdentifiablePointer<LibrarySettings> { extern "C" fn library_settings_new(max_level: LevelInt) -> IdentifiablePointer<Box<dyn LibrarySettings>> {
Box::new(LibrarySettings::new(max_level)).into() let b: Box<dyn LibrarySettings> = Box::new(LibrarySettingsImpl::new(max_level));
b.into()
} }
/// Drop a library settings object. /// Drop a library settings object.
#[no_mangle] #[no_mangle]
unsafe extern "C" fn library_settings_drop(ptr: OwnedPtr<LibrarySettings>) { unsafe extern "C" fn library_settings_drop(ptr: OwnedPtr<Box<dyn LibrarySettings>>) {
drop_in_place(ptr) drop_in_place(ptr)
} }
/// The highest level a Pokemon can be. /// The highest level a Pokemon can be.
#[no_mangle] #[no_mangle]
extern "C" fn library_settings_maximum_level(ptr: ExternPointer<LibrarySettings>) -> LevelInt { extern "C" fn library_settings_maximum_level(ptr: ExternPointer<Box<dyn LibrarySettings>>) -> LevelInt {
ptr.as_ref().maximum_level() ptr.as_ref().maximum_level()
} }

View File

@ -17,32 +17,33 @@ use std::sync::Arc;
/// Generates foreign function interfaces for a DataLibrary trait implementation. /// Generates foreign function interfaces for a DataLibrary trait implementation.
macro_rules! library_interface { macro_rules! library_interface {
($library_type:ty, $return_type:ty) => { ($library_type_name:ident, $library_type:ty, $return_type:ty) => {
paste::paste! { paste::paste! {
#[no_mangle] #[no_mangle]
extern "C" fn [< $library_type:snake _new >](capacity: usize) -> IdentifiablePointer<$library_type> { extern "C" fn [< $library_type_name:snake _new >](capacity: usize) -> IdentifiablePointer<$library_type> {
Box::new($library_type::new(capacity)).into() let value: $library_type = Box::new([<$library_type_name Impl>]::new(capacity));
value.into()
} }
#[no_mangle] #[no_mangle]
unsafe extern "C" fn [< $library_type:snake _drop >](ptr: OwnedPtr<$library_type>) { unsafe extern "C" fn [< $library_type_name:snake _drop >](ptr: OwnedPtr<$library_type>) {
drop_in_place(ptr); drop_in_place(ptr);
} }
#[no_mangle] #[no_mangle]
unsafe extern "C" fn [< $library_type:snake _add >](ptr: OwnedPtr<$library_type>, key: BorrowedPtr<c_char>, value: OwnedPtr<Arc<$return_type>>) { unsafe extern "C" fn [< $library_type_name:snake _add >](ptr: OwnedPtr<$library_type>, key: BorrowedPtr<c_char>, value: OwnedPtr<Arc<$return_type>>) {
let lib = ptr.as_mut().unwrap(); let lib = ptr.as_mut().unwrap();
lib.add(&CStr::from_ptr(key).into(), *Box::from_raw(value)); lib.add(&CStr::from_ptr(key).into(), *Box::from_raw(value));
} }
#[no_mangle] #[no_mangle]
unsafe extern "C" fn [< $library_type:snake _remove >](ptr: OwnedPtr<$library_type>, key: BorrowedPtr<c_char>) { unsafe extern "C" fn [< $library_type_name:snake _remove >](ptr: OwnedPtr<$library_type>, key: BorrowedPtr<c_char>) {
let lib = ptr.as_mut().unwrap(); let lib = ptr.as_mut().unwrap();
lib.remove(&CStr::from_ptr(key).into()); lib.remove(&CStr::from_ptr(key).into());
} }
#[no_mangle] #[no_mangle]
unsafe extern "C" fn [< $library_type:snake _get >](ptr: OwnedPtr<$library_type>, key: BorrowedPtr<c_char>) -> IdentifiablePointer<Arc<$return_type>> { unsafe extern "C" fn [< $library_type_name:snake _get >](ptr: OwnedPtr<$library_type>, key: BorrowedPtr<c_char>) -> IdentifiablePointer<Arc<$return_type>> {
let lib = ptr.as_mut().unwrap(); let lib = ptr.as_mut().unwrap();
let v = lib.get(&CStr::from_ptr(key).into()); let v = lib.get(&CStr::from_ptr(key).into());
if let Some(value) = v { if let Some(value) = v {
@ -53,7 +54,7 @@ macro_rules! library_interface {
} }
#[no_mangle] #[no_mangle]
unsafe extern "C" fn [< $library_type:snake _get_key_by_index >](ptr: OwnedPtr<$library_type>, index: usize) -> OwnedPtr<c_char> { unsafe extern "C" fn [< $library_type_name:snake _get_key_by_index >](ptr: OwnedPtr<$library_type>, index: usize) -> OwnedPtr<c_char> {
let lib = ptr.as_mut().unwrap(); let lib = ptr.as_mut().unwrap();
let v = lib.get_key_by_index(index); let v = lib.get_key_by_index(index);
if let Some(value) = v { if let Some(value) = v {
@ -64,7 +65,7 @@ macro_rules! library_interface {
} }
#[no_mangle] #[no_mangle]
unsafe extern "C" fn [< $library_type:snake _len >](ptr: OwnedPtr<$library_type>) -> usize { unsafe extern "C" fn [< $library_type_name:snake _len >](ptr: OwnedPtr<$library_type>) -> usize {
let lib = ptr.as_mut().unwrap(); let lib = ptr.as_mut().unwrap();
lib.len() lib.len()
} }
@ -72,7 +73,7 @@ macro_rules! library_interface {
}; };
} }
library_interface!(SpeciesLibrary, dyn Species); library_interface!(SpeciesLibrary, Box<dyn SpeciesLibrary>, dyn Species);
library_interface!(MoveLibrary, dyn MoveData); library_interface!(MoveLibrary, Box<dyn MoveLibrary>, dyn MoveData);
library_interface!(AbilityLibrary, dyn Ability); library_interface!(AbilityLibrary, Box<dyn AbilityLibrary>, dyn Ability);
library_interface!(ItemLibrary, dyn Item); library_interface!(ItemLibrary, Box<dyn ItemLibrary>, dyn Item);

View File

@ -1,25 +1,26 @@
use crate::ffi::{BorrowedPtr, ExternPointer, IdentifiablePointer, OwnedPtr}; use crate::ffi::{BorrowedPtr, ExternPointer, IdentifiablePointer, OwnedPtr};
use crate::static_data::{Nature, NatureLibrary}; use crate::static_data::{Nature, NatureLibrary, NatureLibraryImpl};
use std::ffi::{c_char, CStr, CString}; use std::ffi::{c_char, CStr, CString};
use std::ptr::drop_in_place; use std::ptr::drop_in_place;
use std::sync::Arc; use std::sync::Arc;
/// Creates a new nature library with a given capacity. /// Creates a new nature library with a given capacity.
#[no_mangle] #[no_mangle]
extern "C" fn nature_library_new(capacity: usize) -> IdentifiablePointer<NatureLibrary> { extern "C" fn nature_library_new(capacity: usize) -> IdentifiablePointer<Box<dyn NatureLibrary>> {
Box::new(NatureLibrary::new(capacity)).into() let b: Box<dyn NatureLibrary> = Box::new(NatureLibraryImpl::new(capacity));
b.into()
} }
/// Drop a nature library. /// Drop a nature library.
#[no_mangle] #[no_mangle]
unsafe extern "C" fn nature_library_drop(ptr: OwnedPtr<NatureLibrary>) { unsafe extern "C" fn nature_library_drop(ptr: OwnedPtr<Box<dyn NatureLibrary>>) {
drop_in_place(ptr); drop_in_place(ptr);
} }
/// Adds a new nature with name to the library. /// Adds a new nature with name to the library.
#[no_mangle] #[no_mangle]
unsafe extern "C" fn nature_library_load_nature( unsafe extern "C" fn nature_library_load_nature(
mut ptr: ExternPointer<NatureLibrary>, mut ptr: ExternPointer<Box<dyn NatureLibrary>>,
name: BorrowedPtr<c_char>, name: BorrowedPtr<c_char>,
nature: OwnedPtr<Arc<dyn Nature>>, nature: OwnedPtr<Arc<dyn Nature>>,
) { ) {
@ -30,7 +31,7 @@ unsafe extern "C" fn nature_library_load_nature(
/// Gets a nature by name. /// Gets a nature by name.
#[no_mangle] #[no_mangle]
unsafe extern "C" fn nature_library_get_nature( unsafe extern "C" fn nature_library_get_nature(
ptr: ExternPointer<NatureLibrary>, ptr: ExternPointer<Box<dyn NatureLibrary>>,
name: BorrowedPtr<c_char>, name: BorrowedPtr<c_char>,
) -> IdentifiablePointer<Arc<dyn Nature>> { ) -> IdentifiablePointer<Arc<dyn Nature>> {
if let Some(nature) = ptr.as_ref().get_nature(&CStr::from_ptr(name).into()) { if let Some(nature) = ptr.as_ref().get_nature(&CStr::from_ptr(name).into()) {
@ -43,7 +44,7 @@ unsafe extern "C" fn nature_library_get_nature(
/// Finds a nature name by nature. /// Finds a nature name by nature.
#[no_mangle] #[no_mangle]
unsafe extern "C" fn nature_library_get_nature_name( unsafe extern "C" fn nature_library_get_nature_name(
ptr: ExternPointer<NatureLibrary>, ptr: ExternPointer<Box<dyn NatureLibrary>>,
nature: BorrowedPtr<Arc<dyn Nature>>, nature: BorrowedPtr<Arc<dyn Nature>>,
) -> OwnedPtr<c_char> { ) -> OwnedPtr<c_char> {
CString::new(ptr.as_ref().get_nature_name(nature.as_ref().unwrap()).str()) CString::new(ptr.as_ref().get_nature_name(nature.as_ref().unwrap()).str())

View File

@ -1,68 +1,85 @@
use crate::ffi::{ExternPointer, IdentifiablePointer, OwnedPtr}; use crate::ffi::{ExternPointer, IdentifiablePointer, OwnedPtr};
use crate::static_data::{ use crate::static_data::{
AbilityLibrary, GrowthRateLibrary, ItemLibrary, LibrarySettings, MoveLibrary, NatureLibrary, SpeciesLibrary, AbilityLibrary, GrowthRateLibrary, ItemLibrary, LibrarySettings, MoveLibrary, NatureLibrary, SpeciesLibrary,
StaticData, TypeLibrary, StaticData, StaticDataImpl, TypeLibrary,
}; };
use std::ptr::drop_in_place; use std::ptr::drop_in_place;
/// Instantiates a new data collection. /// Instantiates a new data collection.
#[no_mangle] #[no_mangle]
unsafe extern "C" fn static_data_new(settings: OwnedPtr<LibrarySettings>) -> IdentifiablePointer<StaticData> { unsafe extern "C" fn static_data_new(
Box::new(StaticData::new(*Box::from_raw(settings))).into() settings: OwnedPtr<Box<dyn LibrarySettings>>,
) -> IdentifiablePointer<Box<dyn StaticData>> {
let b: Box<dyn StaticData> = Box::new(StaticDataImpl::new(*Box::from_raw(settings)));
b.into()
} }
/// Drop a static data. /// Drop a static data.
#[no_mangle] #[no_mangle]
unsafe extern "C" fn static_data_drop(ptr: OwnedPtr<StaticData>) { unsafe extern "C" fn static_data_drop(ptr: OwnedPtr<Box<dyn StaticData>>) {
drop_in_place(ptr) drop_in_place(ptr)
} }
/// Several misc settings for the library. /// Several misc settings for the library.
#[no_mangle] #[no_mangle]
unsafe extern "C" fn static_data_settings(mut data: ExternPointer<StaticData>) -> IdentifiablePointer<LibrarySettings> { unsafe extern "C" fn static_data_settings(
(data.as_mut().settings() as *const LibrarySettings).into() mut data: ExternPointer<Box<dyn StaticData>>,
) -> IdentifiablePointer<Box<dyn LibrarySettings>> {
data.as_mut().settings().into()
} }
/// All data for Pokemon species. /// All data for Pokemon species.
#[no_mangle] #[no_mangle]
unsafe extern "C" fn static_data_species(mut data: ExternPointer<StaticData>) -> IdentifiablePointer<SpeciesLibrary> { unsafe extern "C" fn static_data_species(
(data.as_mut().species_mut() as *const SpeciesLibrary).into() mut data: ExternPointer<Box<dyn StaticData>>,
) -> IdentifiablePointer<Box<dyn SpeciesLibrary>> {
data.as_mut().species().into()
} }
/// All data for the moves. /// All data for the moves.
#[no_mangle] #[no_mangle]
unsafe extern "C" fn static_data_moves(mut data: ExternPointer<StaticData>) -> IdentifiablePointer<MoveLibrary> { unsafe extern "C" fn static_data_moves(
(data.as_mut().moves_mut() as *const MoveLibrary).into() mut data: ExternPointer<Box<dyn StaticData>>,
) -> IdentifiablePointer<Box<dyn MoveLibrary>> {
data.as_mut().moves().into()
} }
/// All data for the items. /// All data for the items.
#[no_mangle] #[no_mangle]
unsafe extern "C" fn static_data_items(mut data: ExternPointer<StaticData>) -> IdentifiablePointer<ItemLibrary> { unsafe extern "C" fn static_data_items(
(data.as_mut().items_mut() as *const ItemLibrary).into() mut data: ExternPointer<Box<dyn StaticData>>,
) -> IdentifiablePointer<Box<dyn ItemLibrary>> {
(data.as_mut().items()).into()
} }
/// All data for growth rates. /// All data for growth rates.
#[no_mangle] #[no_mangle]
unsafe extern "C" fn static_data_growth_rates( unsafe extern "C" fn static_data_growth_rates(
mut data: ExternPointer<StaticData>, mut data: ExternPointer<Box<dyn StaticData>>,
) -> IdentifiablePointer<GrowthRateLibrary> { ) -> IdentifiablePointer<Box<dyn GrowthRateLibrary>> {
(data.as_mut().growth_rates_mut() as *const GrowthRateLibrary).into() data.as_mut().growth_rates().into()
} }
/// All data related to types and type effectiveness. /// All data related to types and type effectiveness.
#[no_mangle] #[no_mangle]
unsafe extern "C" fn static_data_types(mut data: ExternPointer<StaticData>) -> IdentifiablePointer<TypeLibrary> { unsafe extern "C" fn static_data_types(
(data.as_mut().types_mut() as *const TypeLibrary).into() mut data: ExternPointer<Box<dyn StaticData>>,
) -> IdentifiablePointer<Box<dyn TypeLibrary>> {
data.as_mut().types().into()
} }
/// All data related to natures. /// All data related to natures.
#[no_mangle] #[no_mangle]
unsafe extern "C" fn static_data_natures(mut data: ExternPointer<StaticData>) -> IdentifiablePointer<NatureLibrary> { unsafe extern "C" fn static_data_natures(
(data.as_mut().natures_mut() as *const NatureLibrary).into() data: ExternPointer<Box<dyn StaticData>>,
) -> IdentifiablePointer<Box<dyn NatureLibrary>> {
data.as_ref().natures().into()
} }
/// All data related to abilities. /// All data related to abilities.
#[no_mangle] #[no_mangle]
unsafe extern "C" fn static_data_abilities(mut data: ExternPointer<StaticData>) -> IdentifiablePointer<AbilityLibrary> { unsafe extern "C" fn static_data_abilities(
(data.as_mut().abilities_mut() as *const AbilityLibrary).into() mut data: ExternPointer<Box<dyn StaticData>>,
) -> IdentifiablePointer<Box<dyn AbilityLibrary>> {
(data.as_mut().abilities()).into()
} }

View File

@ -1,24 +1,25 @@
use crate::ffi::{BorrowedPtr, ExternPointer, IdentifiablePointer, OwnedPtr}; use crate::ffi::{BorrowedPtr, ExternPointer, IdentifiablePointer, OwnedPtr};
use crate::static_data::{TypeIdentifier, TypeLibrary}; use crate::static_data::{TypeIdentifier, TypeLibrary, TypeLibraryImpl};
use std::ffi::{c_char, CStr, CString}; use std::ffi::{c_char, CStr, CString};
use std::ptr::drop_in_place; use std::ptr::drop_in_place;
/// Instantiates a new type library with a specific capacity. /// Instantiates a new type library with a specific capacity.
#[no_mangle] #[no_mangle]
extern "C" fn type_library_new(capacity: usize) -> IdentifiablePointer<TypeLibrary> { extern "C" fn type_library_new(capacity: usize) -> IdentifiablePointer<Box<dyn TypeLibrary>> {
Box::new(TypeLibrary::new(capacity)).into() let b: Box<dyn TypeLibrary> = Box::new(TypeLibraryImpl::new(capacity));
b.into()
} }
/// Drops a type library. /// Drops a type library.
#[no_mangle] #[no_mangle]
unsafe extern "C" fn type_library_drop(ptr: OwnedPtr<TypeLibrary>) { unsafe extern "C" fn type_library_drop(ptr: OwnedPtr<Box<dyn TypeLibrary>>) {
drop_in_place(ptr); drop_in_place(ptr);
} }
/// Gets the type identifier for a type with a name. /// Gets the type identifier for a type with a name.
#[no_mangle] #[no_mangle]
unsafe extern "C" fn type_library_get_type_id( unsafe extern "C" fn type_library_get_type_id(
ptr: ExternPointer<TypeLibrary>, ptr: ExternPointer<Box<dyn TypeLibrary>>,
key: BorrowedPtr<c_char>, key: BorrowedPtr<c_char>,
found: *mut bool, found: *mut bool,
) -> TypeIdentifier { ) -> TypeIdentifier {
@ -34,7 +35,7 @@ unsafe extern "C" fn type_library_get_type_id(
/// Gets the type name from the type identifier. /// Gets the type name from the type identifier.
#[no_mangle] #[no_mangle]
unsafe extern "C" fn type_library_get_type_name( unsafe extern "C" fn type_library_get_type_name(
ptr: ExternPointer<TypeLibrary>, ptr: ExternPointer<Box<dyn TypeLibrary>>,
type_id: TypeIdentifier, type_id: TypeIdentifier,
found: *mut bool, found: *mut bool,
) -> *mut c_char { ) -> *mut c_char {
@ -50,7 +51,7 @@ unsafe extern "C" fn type_library_get_type_name(
/// Gets the effectiveness for a single attacking type against a single defending type. /// Gets the effectiveness for a single attacking type against a single defending type.
#[no_mangle] #[no_mangle]
extern "C" fn type_library_get_single_effectiveness( extern "C" fn type_library_get_single_effectiveness(
ptr: ExternPointer<TypeLibrary>, ptr: ExternPointer<Box<dyn TypeLibrary>>,
attacking: TypeIdentifier, attacking: TypeIdentifier,
defending: TypeIdentifier, defending: TypeIdentifier,
) -> f32 { ) -> f32 {
@ -62,7 +63,7 @@ extern "C" fn type_library_get_single_effectiveness(
/// and multiplying the results with each other. /// and multiplying the results with each other.
#[no_mangle] #[no_mangle]
unsafe extern "C" fn type_library_get_effectiveness( unsafe extern "C" fn type_library_get_effectiveness(
ptr: ExternPointer<TypeLibrary>, ptr: ExternPointer<Box<dyn TypeLibrary>>,
attacking: TypeIdentifier, attacking: TypeIdentifier,
defending: OwnedPtr<TypeIdentifier>, defending: OwnedPtr<TypeIdentifier>,
defending_length: usize, defending_length: usize,
@ -74,7 +75,7 @@ unsafe extern "C" fn type_library_get_effectiveness(
/// Registers a new type in the library. /// Registers a new type in the library.
#[no_mangle] #[no_mangle]
unsafe extern "C" fn type_library_register_type( unsafe extern "C" fn type_library_register_type(
mut ptr: ExternPointer<TypeLibrary>, mut ptr: ExternPointer<Box<dyn TypeLibrary>>,
name: BorrowedPtr<c_char>, name: BorrowedPtr<c_char>,
) -> TypeIdentifier { ) -> TypeIdentifier {
ptr.as_mut().register_type(&CStr::from_ptr(name).into()) ptr.as_mut().register_type(&CStr::from_ptr(name).into())
@ -83,7 +84,7 @@ unsafe extern "C" fn type_library_register_type(
/// Sets the effectiveness for an attacking type against a defending type. /// Sets the effectiveness for an attacking type against a defending type.
#[no_mangle] #[no_mangle]
unsafe extern "C" fn type_library_set_effectiveness( unsafe extern "C" fn type_library_set_effectiveness(
mut ptr: ExternPointer<TypeLibrary>, mut ptr: ExternPointer<Box<dyn TypeLibrary>>,
attacking: TypeIdentifier, attacking: TypeIdentifier,
defending: TypeIdentifier, defending: TypeIdentifier,
effectiveness: f32, effectiveness: f32,

View File

@ -1,5 +1,6 @@
#![allow(clippy::too_many_arguments, clippy::needless_range_loop)] #![allow(clippy::too_many_arguments, clippy::needless_range_loop)]
#![allow(clippy::not_unsafe_ptr_arg_deref)] #![allow(clippy::not_unsafe_ptr_arg_deref)]
#![allow(clippy::borrowed_box)]
#![allow(incomplete_features)] #![allow(incomplete_features)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![deny(clippy::missing_docs_in_private_items)] #![deny(clippy::missing_docs_in_private_items)]

View File

@ -37,8 +37,8 @@ register! {
fn battle_get_library( fn battle_get_library(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>, battle: ExternRef<Battle>,
) -> ExternRef<DynamicLibrary> { ) -> ExternRef<dyn DynamicLibrary> {
ExternRef::func_new(&env, battle.value_func(&env).unwrap().library().as_ref()) ExternRef::func_new(&env, &battle.value_func_arc(&env).unwrap().library().clone())
} }
fn battle_get_sides( fn battle_get_sides(

View File

@ -31,9 +31,9 @@ mod turn_choice;
register! { register! {
fn dynamic_library_get_static_data( fn dynamic_library_get_static_data(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
dynamic_lib: ExternRef<DynamicLibrary>, dynamic_lib: ExternRef<dyn DynamicLibrary>,
) -> ExternRef<StaticData> { ) -> ExternRef<dyn StaticData> {
ExternRef::func_new(&env, dynamic_lib.value_func(&env).unwrap().static_data()) ExternRef::func_new(&env, dynamic_lib.value_func_arc(&env).unwrap().static_data())
} }
fn script_get_owner( fn script_get_owner(

View File

@ -15,9 +15,9 @@ register! {
fn pokemon_get_library( fn pokemon_get_library(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> ExternRef<DynamicLibrary> { ) -> ExternRef<dyn DynamicLibrary> {
let lib = pokemon.value_func(&env).unwrap().library().as_ref(); let lib = pokemon.value_func(&env).unwrap().library().clone();
ExternRef::func_new(&env, lib) ExternRef::func_new(&env, &lib)
} }
fn pokemon_get_boosted_stats( fn pokemon_get_boosted_stats(

View File

@ -1,7 +1,8 @@
use crate::script_implementations::wasm::export_registry::register; use crate::script_implementations::wasm::export_registry::register;
use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::extern_ref::ExternRef;
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
use crate::static_data::{DataLibrary, Item, ItemLibrary}; use crate::static_data::Item;
use crate::static_data::ItemLibrary;
use crate::StringKey; use crate::StringKey;
use std::mem::transmute; use std::mem::transmute;
use wasmer::FunctionEnvMut; use wasmer::FunctionEnvMut;
@ -9,23 +10,23 @@ use wasmer::FunctionEnvMut;
register! { register! {
fn item_library_get_item( fn item_library_get_item(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
lib: ExternRef<ItemLibrary>, lib: ExternRef<dyn ItemLibrary>,
string_key: ExternRef<StringKey>, string_key: ExternRef<StringKey>,
) -> ExternRef<dyn Item> { ) -> ExternRef<dyn Item> {
let lib = lib.value_func(&env).unwrap(); let lib = lib.value_func_box(&env).unwrap();
let m = lib.get(string_key.value_func(&env).unwrap()); let m = lib.get(string_key.value_func(&env).unwrap());
if let Some(v) = m { if let Some(v) = m {
ExternRef::func_new(&env, v) ExternRef::func_new(&env, &v)
} else { } else {
ExternRef::null() ExternRef::null()
} }
} }
fn item_library_get_item_by_hash(env: FunctionEnvMut<WebAssemblyEnv>, lib: ExternRef<ItemLibrary>, hash: u32) -> ExternRef<dyn Item> { fn item_library_get_item_by_hash(env: FunctionEnvMut<WebAssemblyEnv>, lib: ExternRef<dyn ItemLibrary>, hash: u32) -> ExternRef<dyn Item> {
let lib = lib.value_func(&env).unwrap(); let lib = lib.value_func_box(&env).unwrap();
let m = lib.get_by_hash(hash); let m = lib.get_by_hash(hash);
if let Some(v) = m { if let Some(v) = m {
ExternRef::func_new(&env, v) ExternRef::func_new(&env, &v)
} else { } else {
ExternRef::null() ExternRef::null()
} }

View File

@ -17,34 +17,34 @@ mod moves;
mod species; mod species;
register! { register! {
fn static_data_get_move_library(env: FunctionEnvMut<WebAssemblyEnv>, data_library: ExternRef<StaticData>) -> ExternRef<MoveLibrary> { fn static_data_get_move_library(env: FunctionEnvMut<WebAssemblyEnv>, data_library: ExternRef<dyn StaticData>) -> ExternRef<dyn MoveLibrary> {
ExternRef::func_new(&env, data_library.value_func(&env).unwrap().moves()) ExternRef::func_new(&env, data_library.value_func_box(&env).unwrap().moves())
} }
fn static_data_get_species_library( fn static_data_get_species_library(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
data_library: ExternRef<StaticData>, data_library: ExternRef<dyn StaticData>,
) -> ExternRef<SpeciesLibrary> { ) -> ExternRef<dyn SpeciesLibrary> {
ExternRef::func_new(&env, data_library.value_func(&env).unwrap().species()) ExternRef::func_new(&env, data_library.value_func_box(&env).unwrap().species())
} }
fn static_data_get_item_library(env: FunctionEnvMut<WebAssemblyEnv>, data_library: ExternRef<StaticData>) -> ExternRef<ItemLibrary> { fn static_data_get_item_library(env: FunctionEnvMut<WebAssemblyEnv>, data_library: ExternRef<dyn StaticData>) -> ExternRef<dyn ItemLibrary> {
ExternRef::func_new(&env, data_library.value_func(&env).unwrap().items()) ExternRef::func_new(&env, data_library.value_func_box(&env).unwrap().items())
} }
fn static_data_get_type_library(env: FunctionEnvMut<WebAssemblyEnv>, data_library: ExternRef<StaticData>) -> ExternRef<TypeLibrary> { fn static_data_get_type_library(env: FunctionEnvMut<WebAssemblyEnv>, data_library: ExternRef<dyn StaticData>) -> ExternRef<dyn TypeLibrary> {
ExternRef::func_new(&env, data_library.value_func(&env).unwrap().types()) ExternRef::func_new(&env, data_library.value_func_box(&env).unwrap().types())
} }
fn static_data_get_library_settings( fn static_data_get_library_settings(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
data_library: ExternRef<StaticData>, data_library: ExternRef<dyn StaticData>,
) -> ExternRef<LibrarySettings> { ) -> ExternRef<dyn LibrarySettings> {
ExternRef::func_new(&env, data_library.value_func(&env).unwrap().settings()) ExternRef::func_new(&env, data_library.value_func_box(&env).unwrap().settings())
} }
fn library_settings_get_maximum_level(env: FunctionEnvMut<WebAssemblyEnv>, data_library: ExternRef<LibrarySettings>) -> LevelInt { fn library_settings_get_maximum_level(env: FunctionEnvMut<WebAssemblyEnv>, data_library: ExternRef<dyn LibrarySettings>) -> LevelInt {
data_library.value_func(&env).unwrap().maximum_level() data_library.value_func_box(&env).unwrap().maximum_level()
} }
fn statistic_set_get(env: FunctionEnvMut<WebAssemblyEnv>, statistics_set: ExternRef<StatisticSet<u32>>, stat: u8) -> i64 { fn statistic_set_get(env: FunctionEnvMut<WebAssemblyEnv>, statistics_set: ExternRef<StatisticSet<u32>>, stat: u8) -> i64 {

View File

@ -1,30 +1,30 @@
use crate::script_implementations::wasm::export_registry::register; use crate::script_implementations::wasm::export_registry::register;
use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::extern_ref::ExternRef;
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
use crate::static_data::{DataLibrary, MoveData, MoveLibrary}; use crate::static_data::{MoveData, MoveLibrary};
use crate::StringKey; use crate::StringKey;
use wasmer::FunctionEnvMut; use wasmer::FunctionEnvMut;
register! { register! {
fn move_library_get_move( fn move_library_get_move(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
lib: ExternRef<MoveLibrary>, lib: ExternRef<dyn MoveLibrary>,
string_key: ExternRef<StringKey>, string_key: ExternRef<StringKey>,
) -> ExternRef<dyn MoveData> { ) -> ExternRef<dyn MoveData> {
let lib = lib.value_func(&env).unwrap(); let lib = lib.value_func_box(&env).unwrap();
let m = lib.get(string_key.value_func(&env).unwrap()); let m = lib.get(string_key.value_func(&env).unwrap());
if let Some(v) = m { if let Some(v) = m {
ExternRef::func_new(&env, v) ExternRef::func_new(&env, &v)
} else { } else {
ExternRef::null() ExternRef::null()
} }
} }
fn move_library_get_move_by_hash(env: FunctionEnvMut<WebAssemblyEnv>, lib: ExternRef<MoveLibrary>, hash: u32) -> ExternRef<dyn MoveData> { fn move_library_get_move_by_hash(env: FunctionEnvMut<WebAssemblyEnv>, lib: ExternRef<dyn MoveLibrary>, hash: u32) -> ExternRef<dyn MoveData> {
let lib = lib.value_func(&env).unwrap(); let lib = lib.value_func_box(&env).unwrap();
let m = lib.get_by_hash(hash); let m = lib.get_by_hash(hash);
if let Some(v) = m { if let Some(v) = m {
ExternRef::func_new(&env, v) ExternRef::func_new(&env, &v)
} else { } else {
ExternRef::null() ExternRef::null()
} }

View File

@ -1,7 +1,8 @@
use crate::script_implementations::wasm::export_registry::register; use crate::script_implementations::wasm::export_registry::register;
use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::extern_ref::ExternRef;
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
use crate::static_data::{DataLibrary, Species, SpeciesLibrary}; use crate::static_data::Species;
use crate::static_data::SpeciesLibrary;
use crate::StringKey; use crate::StringKey;
use wasmer::FunctionEnvMut; use wasmer::FunctionEnvMut;
@ -9,13 +10,13 @@ register! {
fn species_library_get_species( fn species_library_get_species(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
lib: ExternRef<SpeciesLibrary>, lib: ExternRef<dyn SpeciesLibrary>,
string_key: ExternRef<StringKey>, string_key: ExternRef<StringKey>,
) -> ExternRef<dyn Species> { ) -> ExternRef<dyn Species> {
let lib = lib.value_func(&env).unwrap(); let lib = lib.value_func_box(&env).unwrap();
let m = lib.get(string_key.value_func(&env).unwrap()); let m = lib.get(string_key.value_func(&env).unwrap());
if let Some(v) = m { if let Some(v) = m {
ExternRef::func_new(&env, v) ExternRef::func_new(&env, &v)
} else { } else {
ExternRef::null() ExternRef::null()
} }

View File

@ -74,6 +74,15 @@ impl<T: ValueIdentifiable + ?Sized> ExternRef<T> {
self.value_arc(&env.data().data()) self.value_arc(&env.data().data())
} }
/// Returns the real value for a given ExternRef. Note that the requested type must be the same as the type of the
/// value when it was passed before. If these types do not match, this will panic.
pub fn value_func_box(&self, env: &FunctionEnvMut<WebAssemblyEnv>) -> Option<&Box<T>>
where
T: 'static,
{
self.value_box(&env.data().data())
}
/// Returns the real value for a given ExternRef. Note that the requested type must be the same as the type of the /// Returns the real value for a given ExternRef. Note that the requested type must be the same as the type of the
/// value when it was passed before. If these types do not match, this will panic. /// value when it was passed before. If these types do not match, this will panic.
pub fn value<'a, 'b, 'c>(&'a self, env: &'b Arc<WebAssemblyEnvironmentData>) -> Option<&'c T> pub fn value<'a, 'b, 'c>(&'a self, env: &'b Arc<WebAssemblyEnvironmentData>) -> Option<&'c T>
@ -93,6 +102,15 @@ impl<T: ValueIdentifiable + ?Sized> ExternRef<T> {
.downcast_ref::<Arc<T>>() .downcast_ref::<Arc<T>>()
.cloned() .cloned()
} }
/// Returns the real value for a given ExternRef. Note that the requested type must be the same as the type of the
/// value when it was passed before. If these types do not match, this will panic.
pub fn value_box(&self, env: &Arc<WebAssemblyEnvironmentData>) -> Option<&Box<T>>
where
T: 'static,
{
env.get_extern_ref_value::<T>(self.index).downcast_ref::<Box<T>>()
}
} }
unsafe impl<T: ?Sized> FromToNativeWasmType for ExternRef<T> { unsafe impl<T: ?Sized> FromToNativeWasmType for ExternRef<T> {

View File

@ -125,7 +125,7 @@ impl Script for WebAssemblyScript {
} }
} }
fn on_initialize(&self, library: &DynamicLibrary, pars: Vec<EffectParameter>) { fn on_initialize(&self, library: &Arc<dyn DynamicLibrary>, pars: Vec<EffectParameter>) {
if !self.has_capability(&WebAssemblyScriptCapabilities::Initialize) { if !self.has_capability(&WebAssemblyScriptCapabilities::Initialize) {
return; return;
} }

View File

@ -117,7 +117,7 @@ unsafe impl<T> FromToNativeWasmType for WasmPtr<T> {
script_function_cache! { script_function_cache! {
stack() stack()
on_remove() on_remove()
on_initialize(ExternRef<DynamicLibrary>, VecExternRef<EffectParameter>) on_initialize(ExternRef<dyn DynamicLibrary>, VecExternRef<EffectParameter>)
on_before_turn(ExternRef<TurnChoice>) on_before_turn(ExternRef<TurnChoice>)
change_speed(ExternRef<TurnChoice>, WasmPtr<u32>) change_speed(ExternRef<TurnChoice>, WasmPtr<u32>)
change_priority(ExternRef<TurnChoice>, WasmPtr<i8>) change_priority(ExternRef<TurnChoice>, WasmPtr<i8>)

View File

@ -1,3 +1,4 @@
use std::fmt::Debug;
use std::sync::Arc; use std::sync::Arc;
use indexmap::IndexMap; use indexmap::IndexMap;
@ -6,26 +7,31 @@ use crate::static_data::Ability;
use crate::static_data::DataLibrary; use crate::static_data::DataLibrary;
use crate::{StringKey, ValueIdentifiable, ValueIdentifier}; use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
/// A storage for all abilities that can be used in this data library.
pub trait AbilityLibrary: DataLibrary<dyn Ability> + ValueIdentifiable + Debug {}
/// A storage for all abilities that can be used in this data library. /// A storage for all abilities that can be used in this data library.
#[derive(Debug)] #[derive(Debug)]
pub struct AbilityLibrary { pub struct AbilityLibraryImpl {
/// A unique identifier so we know what value this is. /// A unique identifier so we know what value this is.
identifier: ValueIdentifier, identifier: ValueIdentifier,
/// The underlying map for the library. /// The underlying map for the library.
map: IndexMap<StringKey, Arc<dyn Ability>>, map: IndexMap<StringKey, Arc<dyn Ability>>,
} }
impl AbilityLibrary { impl AbilityLibraryImpl {
/// Instantiates a new ability library. /// Instantiates a new ability library.
pub fn new(capacity: usize) -> AbilityLibrary { pub fn new(capacity: usize) -> Self {
AbilityLibrary { Self {
identifier: Default::default(), identifier: Default::default(),
map: IndexMap::with_capacity(capacity), map: IndexMap::with_capacity(capacity),
} }
} }
} }
impl DataLibrary<dyn Ability> for AbilityLibrary { impl AbilityLibrary for AbilityLibraryImpl {}
impl DataLibrary<dyn Ability> for AbilityLibraryImpl {
fn map(&self) -> &IndexMap<StringKey, Arc<dyn Ability>> { fn map(&self) -> &IndexMap<StringKey, Arc<dyn Ability>> {
&self.map &self.map
} }
@ -34,7 +40,7 @@ impl DataLibrary<dyn Ability> for AbilityLibrary {
} }
} }
impl ValueIdentifiable for AbilityLibrary { impl ValueIdentifiable for AbilityLibraryImpl {
fn value_identifier(&self) -> ValueIdentifier { fn value_identifier(&self) -> ValueIdentifier {
self.identifier self.identifier
} }
@ -42,14 +48,14 @@ impl ValueIdentifiable for AbilityLibrary {
#[cfg(test)] #[cfg(test)]
pub mod tests { pub mod tests {
use crate::static_data::libraries::ability_library::AbilityLibraryImpl;
use crate::static_data::AbilityImpl; use crate::static_data::AbilityImpl;
use crate::static_data::AbilityLibrary;
use crate::static_data::DataLibrary; use crate::static_data::DataLibrary;
use crate::StringKey; use crate::StringKey;
use std::sync::Arc; use std::sync::Arc;
pub fn build() -> AbilityLibrary { pub fn build() -> AbilityLibraryImpl {
let mut lib = AbilityLibrary::new(1); let mut lib = AbilityLibraryImpl::new(1);
lib.add( lib.add(
&StringKey::new("test_ability"), &StringKey::new("test_ability"),
Arc::new(AbilityImpl::new( Arc::new(AbilityImpl::new(

View File

@ -24,13 +24,13 @@ pub trait DataLibrary<T: ?Sized> {
} }
/// Gets a value from the library. /// Gets a value from the library.
fn get(&self, key: &StringKey) -> Option<&Arc<T>> { fn get(&self, key: &StringKey) -> Option<Arc<T>> {
self.map().get::<StringKey>(key) self.map().get::<StringKey>(key).cloned()
} }
/// Gets a value from the library. /// Gets a value from the library.
fn get_by_hash(&self, key: u32) -> Option<&Arc<T>> { fn get_by_hash(&self, key: u32) -> Option<Arc<T>> {
self.map().get::<u32>(&key) self.map().get::<u32>(&key).cloned()
} }
/// Gets a value from the library by the index where it is stored. /// Gets a value from the library by the index where it is stored.

View File

@ -8,44 +8,56 @@ use crate::static_data::GrowthRate;
use crate::{StringKey, ValueIdentifiable, ValueIdentifier}; use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
/// A library to store all growth rates. /// A library to store all growth rates.
pub struct GrowthRateLibrary { pub trait GrowthRateLibrary: Debug + ValueIdentifiable {
/// Calculates the level for a given growth key name and a certain experience.
fn calculate_level(&self, growth_rate: &StringKey, experience: u32) -> LevelInt;
/// Calculates the experience for a given growth key name and a certain level.
fn calculate_experience(&self, growth_rate: &StringKey, level: LevelInt) -> u32;
/// Adds a new growth rate with a name and value.
fn add_growth_rate(&mut self, key: &StringKey, value: Box<dyn GrowthRate>);
}
/// A library to store all growth rates.
pub struct GrowthRateLibraryImpl {
/// A unique identifier so we know what value this is. /// A unique identifier so we know what value this is.
identifier: ValueIdentifier, identifier: ValueIdentifier,
/// The underlying data structure. /// The underlying data structure.
growth_rates: HashMap<StringKey, Box<dyn GrowthRate>>, growth_rates: HashMap<StringKey, Box<dyn GrowthRate>>,
} }
impl GrowthRateLibrary { impl GrowthRateLibraryImpl {
/// Instantiates a new growth rate library with a capacity. /// Instantiates a new growth rate library with a capacity.
pub fn new(capacity: usize) -> GrowthRateLibrary { pub fn new(capacity: usize) -> Self {
GrowthRateLibrary { Self {
identifier: Default::default(), identifier: Default::default(),
growth_rates: HashMap::with_capacity(capacity), growth_rates: HashMap::with_capacity(capacity),
} }
} }
}
impl GrowthRateLibrary for GrowthRateLibraryImpl {
/// Calculates the level for a given growth key name and a certain experience. /// Calculates the level for a given growth key name and a certain experience.
pub fn calculate_level(&self, growth_rate: &StringKey, experience: u32) -> LevelInt { fn calculate_level(&self, growth_rate: &StringKey, experience: u32) -> LevelInt {
self.growth_rates[growth_rate].calculate_level(experience) self.growth_rates[growth_rate].calculate_level(experience)
} }
/// Calculates the experience for a given growth key name and a certain level. /// Calculates the experience for a given growth key name and a certain level.
pub fn calculate_experience(&self, growth_rate: &StringKey, level: LevelInt) -> u32 { fn calculate_experience(&self, growth_rate: &StringKey, level: LevelInt) -> u32 {
self.growth_rates[growth_rate].calculate_experience(level) self.growth_rates[growth_rate].calculate_experience(level)
} }
/// Adds a new growth rate with a name and value. /// Adds a new growth rate with a name and value.
pub fn add_growth_rate(&mut self, key: &StringKey, value: Box<dyn GrowthRate>) { fn add_growth_rate(&mut self, key: &StringKey, value: Box<dyn GrowthRate>) {
self.growth_rates.insert(key.clone(), value); self.growth_rates.insert(key.clone(), value);
} }
} }
impl ValueIdentifiable for GrowthRateLibrary { impl ValueIdentifiable for GrowthRateLibraryImpl {
fn value_identifier(&self) -> ValueIdentifier { fn value_identifier(&self) -> ValueIdentifier {
self.identifier self.identifier
} }
} }
impl Debug for GrowthRateLibrary { impl Debug for GrowthRateLibraryImpl {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("GrowthRateLibrary").finish() f.debug_struct("GrowthRateLibrary").finish()
} }
@ -53,11 +65,13 @@ impl Debug for GrowthRateLibrary {
#[cfg(test)] #[cfg(test)]
pub mod tests { pub mod tests {
use super::*;
use crate::static_data::growth_rates::LookupGrowthRate; use crate::static_data::growth_rates::LookupGrowthRate;
use crate::static_data::libraries::growth_rate_library::GrowthRateLibrary; use crate::static_data::libraries::growth_rate_library::GrowthRateLibrary;
use crate::static_data::GrowthRateLibraryImpl;
pub fn build() -> GrowthRateLibrary { pub fn build() -> GrowthRateLibraryImpl {
let mut lib = GrowthRateLibrary::new(1); let mut lib = GrowthRateLibraryImpl::new(1);
// Borrow as mut so we can insert // Borrow as mut so we can insert
let w = &mut lib; let w = &mut lib;
@ -70,6 +84,21 @@ pub mod tests {
lib lib
} }
mockall::mock! {
#[derive(Debug)]
pub GrowthRateLibrary{}
impl GrowthRateLibrary for GrowthRateLibrary {
fn calculate_level(&self, growth_rate: &StringKey, experience: u32) -> LevelInt;
fn calculate_experience(&self, growth_rate: &StringKey, level: LevelInt) -> u32;
fn add_growth_rate(&mut self, key: &StringKey, value: Box<dyn GrowthRate>);
}
impl ValueIdentifiable for GrowthRateLibrary {
fn value_identifier(&self) -> ValueIdentifier{
ValueIdentifier::new(0)
}
}
}
#[test] #[test]
fn add_growth_rate_to_library_and_calculate_level() { fn add_growth_rate_to_library_and_calculate_level() {
let lib = build(); let lib = build();

View File

@ -1,3 +1,4 @@
use std::fmt::Debug;
use std::sync::Arc; use std::sync::Arc;
use indexmap::IndexMap; use indexmap::IndexMap;
@ -7,26 +8,30 @@ use crate::static_data::Item;
use crate::{StringKey, ValueIdentifiable, ValueIdentifier}; use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
/// A library to store all items. /// A library to store all items.
#[derive(Debug)] pub trait ItemLibrary: DataLibrary<dyn Item> + ValueIdentifiable + Debug {}
pub struct ItemLibrary { /// A library to store all items.
#[derive(Debug)]
pub struct ItemLibraryImpl {
/// A unique identifier so we know what value this is. /// A unique identifier so we know what value this is.
identifier: ValueIdentifier, identifier: ValueIdentifier,
/// The underlying data structure. /// The underlying data structure.
map: IndexMap<StringKey, Arc<dyn Item>>, map: IndexMap<StringKey, Arc<dyn Item>>,
} }
impl ItemLibrary { impl ItemLibraryImpl {
/// Instantiates a new Item Library. /// Instantiates a new Item Library.
pub fn new(capacity: usize) -> ItemLibrary { pub fn new(capacity: usize) -> Self {
ItemLibrary { Self {
identifier: Default::default(), identifier: Default::default(),
map: IndexMap::with_capacity(capacity), map: IndexMap::with_capacity(capacity),
} }
} }
} }
impl DataLibrary<dyn Item> for ItemLibrary { impl ItemLibrary for ItemLibraryImpl {}
impl DataLibrary<dyn Item> for ItemLibraryImpl {
fn map(&self) -> &IndexMap<StringKey, Arc<dyn Item>> { fn map(&self) -> &IndexMap<StringKey, Arc<dyn Item>> {
&self.map &self.map
} }
@ -36,7 +41,7 @@ impl DataLibrary<dyn Item> for ItemLibrary {
} }
} }
impl ValueIdentifiable for ItemLibrary { impl ValueIdentifiable for ItemLibraryImpl {
fn value_identifier(&self) -> ValueIdentifier { fn value_identifier(&self) -> ValueIdentifier {
self.identifier self.identifier
} }
@ -49,8 +54,8 @@ pub mod tests {
use crate::static_data::libraries::data_library::DataLibrary; use crate::static_data::libraries::data_library::DataLibrary;
use crate::static_data::libraries::item_library::ItemLibrary; use crate::static_data::libraries::item_library::ItemLibrary;
use crate::static_data::ItemImpl;
use crate::static_data::{BattleItemCategory, ItemCategory}; use crate::static_data::{BattleItemCategory, ItemCategory};
use crate::static_data::{ItemImpl, ItemLibraryImpl};
fn build_item() -> ItemImpl { fn build_item() -> ItemImpl {
ItemImpl::new( ItemImpl::new(
@ -62,14 +67,14 @@ pub mod tests {
) )
} }
pub fn build() -> ItemLibrary { pub fn build() -> Box<dyn ItemLibrary> {
let mut lib = ItemLibrary::new(1); let mut lib = ItemLibraryImpl::new(1);
let m = build_item(); let m = build_item();
// Borrow as mut so we can insert // Borrow as mut so we can insert
let w = &mut lib; let w = &mut lib;
w.add(&"foo".into(), Arc::new(m)); w.add(&"foo".into(), Arc::new(m));
// Drops borrow as mut // Drops borrow as mut
lib Box::new(lib)
} }
} }

View File

@ -1,16 +1,23 @@
use crate::defines::LevelInt; use crate::defines::LevelInt;
use crate::{ValueIdentifiable, ValueIdentifier}; use crate::{ValueIdentifiable, ValueIdentifier};
use std::fmt::Debug;
/// This library holds several misc settings for the library.
pub trait LibrarySettings: Debug + ValueIdentifiable {
/// The highest level a Pokemon can be.
fn maximum_level(&self) -> LevelInt;
}
/// This library holds several misc settings for the library. /// This library holds several misc settings for the library.
#[derive(Debug)] #[derive(Debug)]
pub struct LibrarySettings { pub struct LibrarySettingsImpl {
/// A unique identifier so we know what value this is. /// A unique identifier so we know what value this is.
identifier: ValueIdentifier, identifier: ValueIdentifier,
/// The highest level a Pokemon can be. /// The highest level a Pokemon can be.
maximum_level: LevelInt, maximum_level: LevelInt,
} }
impl LibrarySettings { impl LibrarySettingsImpl {
/// Creates a new settings library. /// Creates a new settings library.
pub fn new(maximum_level: LevelInt) -> Self { pub fn new(maximum_level: LevelInt) -> Self {
Self { Self {
@ -18,14 +25,16 @@ impl LibrarySettings {
maximum_level, maximum_level,
} }
} }
}
impl LibrarySettings for LibrarySettingsImpl {
/// The highest level a Pokemon can be. /// The highest level a Pokemon can be.
pub fn maximum_level(&self) -> LevelInt { fn maximum_level(&self) -> LevelInt {
self.maximum_level self.maximum_level
} }
} }
impl ValueIdentifiable for LibrarySettings { impl ValueIdentifiable for LibrarySettingsImpl {
fn value_identifier(&self) -> ValueIdentifier { fn value_identifier(&self) -> ValueIdentifier {
self.identifier self.identifier
} }

View File

@ -1,21 +1,21 @@
#[doc(inline)] #[doc(inline)]
pub use ability_library::AbilityLibrary; pub use ability_library::*;
#[doc(inline)] #[doc(inline)]
pub use data_library::DataLibrary; pub use data_library::*;
#[doc(inline)] #[doc(inline)]
pub use growth_rate_library::GrowthRateLibrary; pub use growth_rate_library::*;
#[doc(inline)] #[doc(inline)]
pub use item_library::ItemLibrary; pub use item_library::*;
#[doc(inline)] #[doc(inline)]
pub use library_settings::LibrarySettings; pub use library_settings::*;
#[doc(inline)] #[doc(inline)]
pub use move_library::MoveLibrary; pub use move_library::*;
#[doc(inline)] #[doc(inline)]
pub use nature_library::*; pub use nature_library::*;
#[doc(inline)] #[doc(inline)]
pub use species_library::SpeciesLibrary; pub use species_library::*;
#[doc(inline)] #[doc(inline)]
pub use static_data::StaticData; pub use static_data::*;
#[doc(inline)] #[doc(inline)]
pub use type_library::*; pub use type_library::*;
@ -23,22 +23,22 @@ pub use type_library::*;
pub(crate) mod tests {} pub(crate) mod tests {}
/// The library data for abilities. /// The library data for abilities.
mod ability_library; pub(crate) mod ability_library;
/// Basic helper trait for libraries. /// Basic helper trait for libraries.
mod data_library; pub(crate) mod data_library;
/// The library data for groth rates. /// The library data for groth rates.
mod growth_rate_library; pub(crate) mod growth_rate_library;
/// The library data for items. /// The library data for items.
mod item_library; pub(crate) mod item_library;
/// The library data for misc settings. /// The library data for misc settings.
mod library_settings; pub(crate) mod library_settings;
/// The library data for moves. /// The library data for moves.
mod move_library; pub(crate) mod move_library;
/// The library data for natures. /// The library data for natures.
mod nature_library; pub(crate) mod nature_library;
/// The library data for species. /// The library data for species.
mod species_library; pub(crate) mod species_library;
/// The combination of all libraries. /// The combination of all libraries.
pub(crate) mod static_data; pub(crate) mod static_data;
/// The library data for types. /// The library data for types.
mod type_library; pub(crate) mod type_library;

View File

@ -1,3 +1,4 @@
use std::fmt::Debug;
use std::sync::Arc; use std::sync::Arc;
use indexmap::IndexMap; use indexmap::IndexMap;
@ -7,26 +8,30 @@ use crate::static_data::MoveData;
use crate::{StringKey, ValueIdentifiable, ValueIdentifier}; use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
/// A library to store all data for moves. /// A library to store all data for moves.
#[derive(Debug)] pub trait MoveLibrary: DataLibrary<dyn MoveData> + ValueIdentifiable + Debug {}
pub struct MoveLibrary { /// A library to store all data for moves.
#[derive(Debug)]
pub struct MoveLibraryImpl {
/// A unique identifier so we know what value this is. /// A unique identifier so we know what value this is.
identifier: ValueIdentifier, identifier: ValueIdentifier,
/// The underlying map. /// The underlying map.
map: IndexMap<StringKey, Arc<dyn MoveData>>, map: IndexMap<StringKey, Arc<dyn MoveData>>,
} }
impl MoveLibrary { impl MoveLibraryImpl {
/// Instantiates a new Move Library. /// Instantiates a new Move Library.
pub fn new(capacity: usize) -> MoveLibrary { pub fn new(capacity: usize) -> Self {
MoveLibrary { Self {
identifier: Default::default(), identifier: Default::default(),
map: IndexMap::with_capacity(capacity), map: IndexMap::with_capacity(capacity),
} }
} }
} }
impl DataLibrary<dyn MoveData> for MoveLibrary { impl MoveLibrary for MoveLibraryImpl {}
impl DataLibrary<dyn MoveData> for MoveLibraryImpl {
fn map(&self) -> &IndexMap<StringKey, Arc<dyn MoveData>> { fn map(&self) -> &IndexMap<StringKey, Arc<dyn MoveData>> {
&self.map &self.map
} }
@ -35,7 +40,7 @@ impl DataLibrary<dyn MoveData> for MoveLibrary {
} }
} }
impl ValueIdentifiable for MoveLibrary { impl ValueIdentifiable for MoveLibraryImpl {
fn value_identifier(&self) -> ValueIdentifier { fn value_identifier(&self) -> ValueIdentifier {
self.identifier self.identifier
} }
@ -48,7 +53,7 @@ pub mod tests {
use crate::static_data::libraries::data_library::DataLibrary; use crate::static_data::libraries::data_library::DataLibrary;
use crate::static_data::libraries::move_library::MoveLibrary; use crate::static_data::libraries::move_library::MoveLibrary;
use crate::static_data::{MoveCategory, MoveDataImpl, MoveTarget}; use crate::static_data::{MoveCategory, MoveDataImpl, MoveLibraryImpl, MoveTarget};
use crate::StringKey; use crate::StringKey;
fn build_move() -> MoveDataImpl { fn build_move() -> MoveDataImpl {
@ -66,14 +71,14 @@ pub mod tests {
) )
} }
pub fn build() -> MoveLibrary { pub fn build() -> Box<dyn MoveLibrary> {
let mut lib = MoveLibrary::new(1); let mut lib = MoveLibraryImpl::new(1);
let m = build_move(); let m = build_move();
// Borrow as mut so we can insert // Borrow as mut so we can insert
let w = &mut lib; let w = &mut lib;
w.add(&StringKey::new("foo"), Arc::new(m)); w.add(&StringKey::new("foo"), Arc::new(m));
// Drops borrow as mut // Drops borrow as mut
lib Box::new(lib)
} }
} }

View File

@ -1,38 +1,51 @@
use crate::static_data::Nature; use crate::static_data::Nature;
use crate::{StringKey, ValueIdentifiable, ValueIdentifier}; use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
use hashbrown::HashMap; use hashbrown::HashMap;
use std::fmt::Debug;
use std::sync::Arc; use std::sync::Arc;
/// A library of all natures that can be used, stored by their names.
pub trait NatureLibrary: Debug + ValueIdentifiable {
/// Adds a new nature with name to the library.
fn load_nature(&mut self, name: StringKey, nature: Arc<dyn Nature>);
/// Gets a nature by name.
fn get_nature(&self, key: &StringKey) -> Option<Arc<dyn Nature>>;
/// Finds a nature name by nature.
fn get_nature_name(&self, nature: &Arc<dyn Nature>) -> StringKey;
}
/// A library of all natures that can be used, stored by their names. /// A library of all natures that can be used, stored by their names.
#[derive(Debug)] #[derive(Debug)]
pub struct NatureLibrary { pub struct NatureLibraryImpl {
/// A unique identifier so we know what value this is. /// A unique identifier so we know what value this is.
identifier: ValueIdentifier, identifier: ValueIdentifier,
/// The underlying data structure. /// The underlying data structure.
map: HashMap<StringKey, Arc<dyn Nature>>, map: HashMap<StringKey, Arc<dyn Nature>>,
} }
impl NatureLibrary { impl NatureLibraryImpl {
/// Creates a new nature library with a given capacity. /// Creates a new nature library with a given capacity.
pub fn new(capacity: usize) -> Self { pub fn new(capacity: usize) -> Self {
NatureLibrary { Self {
identifier: Default::default(), identifier: Default::default(),
map: HashMap::with_capacity(capacity), map: HashMap::with_capacity(capacity),
} }
} }
}
impl NatureLibrary for NatureLibraryImpl {
/// Adds a new nature with name to the library. /// Adds a new nature with name to the library.
pub fn load_nature(&mut self, name: StringKey, nature: Arc<dyn Nature>) { fn load_nature(&mut self, name: StringKey, nature: Arc<dyn Nature>) {
self.map.insert(name, nature); self.map.insert(name, nature);
} }
/// Gets a nature by name. /// Gets a nature by name.
pub fn get_nature(&self, key: &StringKey) -> Option<&Arc<dyn Nature>> { fn get_nature(&self, key: &StringKey) -> Option<Arc<dyn Nature>> {
self.map.get(key) self.map.get(key).cloned()
} }
/// Finds a nature name by nature. /// Finds a nature name by nature.
pub fn get_nature_name(&self, nature: &Arc<dyn Nature>) -> StringKey { fn get_nature_name(&self, nature: &Arc<dyn Nature>) -> StringKey {
for kv in &self.map { for kv in &self.map {
// As natures can't be copied, and should always be the same reference as the value // As natures can't be copied, and should always be the same reference as the value
// in the map, we just compare by reference. // in the map, we just compare by reference.
@ -44,7 +57,7 @@ impl NatureLibrary {
} }
} }
impl ValueIdentifiable for NatureLibrary { impl ValueIdentifiable for NatureLibraryImpl {
fn value_identifier(&self) -> ValueIdentifier { fn value_identifier(&self) -> ValueIdentifier {
self.identifier self.identifier
} }
@ -52,11 +65,12 @@ impl ValueIdentifiable for NatureLibrary {
#[cfg(test)] #[cfg(test)]
pub mod tests { pub mod tests {
use super::*;
use crate::static_data::statistics::Statistic; use crate::static_data::statistics::Statistic;
use crate::static_data::{NatureImpl, NatureLibrary}; use crate::static_data::{NatureImpl, NatureLibrary, NatureLibraryImpl};
pub fn build() -> NatureLibrary { pub fn build() -> NatureLibraryImpl {
let mut lib = NatureLibrary::new(2); let mut lib = NatureLibraryImpl::new(2);
lib.load_nature( lib.load_nature(
"test_nature".into(), "test_nature".into(),
@ -66,9 +80,24 @@ pub mod tests {
lib lib
} }
mockall::mock! {
#[derive(Debug)]
pub NatureLibrary{}
impl NatureLibrary for NatureLibrary {
fn load_nature(&mut self, name: StringKey, nature: Arc<dyn Nature>);
fn get_nature(&self, key: &StringKey) -> Option<Arc<dyn Nature>>;
fn get_nature_name(&self, nature: &Arc<dyn Nature>) -> StringKey;
}
impl ValueIdentifiable for NatureLibrary {
fn value_identifier(&self) -> ValueIdentifier{
ValueIdentifier::new(0)
}
}
}
#[test] #[test]
fn create_nature_library_insert_and_retrieve() { fn create_nature_library_insert_and_retrieve() {
let mut lib = NatureLibrary::new(2); let mut lib = NatureLibraryImpl::new(2);
lib.load_nature( lib.load_nature(
"foo".into(), "foo".into(),
NatureImpl::new(Statistic::HP, Statistic::Attack, 1.1, 0.9), NatureImpl::new(Statistic::HP, Statistic::Attack, 1.1, 0.9),
@ -86,7 +115,7 @@ pub mod tests {
#[test] #[test]
fn create_nature_library_insert_and_get_name() { fn create_nature_library_insert_and_get_name() {
let mut lib = NatureLibrary::new(2); let mut lib = NatureLibraryImpl::new(2);
lib.load_nature( lib.load_nature(
"foo".into(), "foo".into(),
NatureImpl::new(Statistic::HP, Statistic::Attack, 1.1, 0.9), NatureImpl::new(Statistic::HP, Statistic::Attack, 1.1, 0.9),
@ -97,10 +126,10 @@ pub mod tests {
); );
let n1 = lib.get_nature(&"foo".into()).expect("Nature was not found"); let n1 = lib.get_nature(&"foo".into()).expect("Nature was not found");
let name = lib.get_nature_name(n1); let name = lib.get_nature_name(&n1);
assert_eq!(name, "foo".into()); assert_eq!(name, "foo".into());
let n2 = lib.get_nature(&"bar".into()).expect("Nature was not found"); let n2 = lib.get_nature(&"bar".into()).expect("Nature was not found");
let name2 = lib.get_nature_name(n2); let name2 = lib.get_nature_name(&n2);
assert_eq!(name2, "bar".into()); assert_eq!(name2, "bar".into());
} }
} }

View File

@ -1,3 +1,4 @@
use std::fmt::Debug;
use std::sync::Arc; use std::sync::Arc;
use indexmap::IndexMap; use indexmap::IndexMap;
@ -7,26 +8,30 @@ use crate::static_data::Species;
use crate::{StringKey, ValueIdentifiable, ValueIdentifier}; use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
/// A library to store all data for Pokemon species. /// A library to store all data for Pokemon species.
#[derive(Debug)] pub trait SpeciesLibrary: DataLibrary<dyn Species> + ValueIdentifiable + Debug {}
pub struct SpeciesLibrary { /// A library to store all data for Pokemon species.
#[derive(Debug)]
pub struct SpeciesLibraryImpl {
/// A unique identifier so we know what value this is. /// A unique identifier so we know what value this is.
identifier: ValueIdentifier, identifier: ValueIdentifier,
/// The underlying map. /// The underlying map.
map: IndexMap<StringKey, Arc<dyn Species>>, map: IndexMap<StringKey, Arc<dyn Species>>,
} }
impl SpeciesLibrary { impl SpeciesLibraryImpl {
/// Instantiates a new Species Library. /// Instantiates a new Species Library.
pub fn new(capacity: usize) -> SpeciesLibrary { pub fn new(capacity: usize) -> Self {
SpeciesLibrary { Self {
identifier: Default::default(), identifier: Default::default(),
map: IndexMap::with_capacity(capacity), map: IndexMap::with_capacity(capacity),
} }
} }
} }
impl DataLibrary<dyn Species> for SpeciesLibrary { impl SpeciesLibrary for SpeciesLibraryImpl {}
impl DataLibrary<dyn Species> for SpeciesLibraryImpl {
fn map(&self) -> &IndexMap<StringKey, Arc<dyn Species>> { fn map(&self) -> &IndexMap<StringKey, Arc<dyn Species>> {
&self.map &self.map
} }
@ -35,7 +40,7 @@ impl DataLibrary<dyn Species> for SpeciesLibrary {
} }
} }
impl ValueIdentifiable for SpeciesLibrary { impl ValueIdentifiable for SpeciesLibraryImpl {
fn value_identifier(&self) -> ValueIdentifier { fn value_identifier(&self) -> ValueIdentifier {
self.identifier self.identifier
} }
@ -43,14 +48,27 @@ impl ValueIdentifiable for SpeciesLibrary {
#[cfg(test)] #[cfg(test)]
pub mod tests { pub mod tests {
use super::*;
use crate::static_data::{FormImpl, LearnableMovesImpl, SpeciesImpl, StaticStatisticSet};
use hashbrown::HashSet; use hashbrown::HashSet;
use std::sync::Arc; use std::sync::Arc;
use crate::static_data::libraries::data_library::DataLibrary; mockall::mock! {
use crate::static_data::libraries::species_library::SpeciesLibrary; #[derive(Debug)]
use crate::static_data::LearnableMovesImpl; pub SpeciesLibrary{}
use crate::static_data::{FormImpl, StaticStatisticSet}; impl SpeciesLibrary for SpeciesLibrary {}
use crate::static_data::{Species, SpeciesImpl}; impl DataLibrary<dyn Species> for SpeciesLibrary {
fn get<'a, 'b>(&'a self, key: &'b StringKey) -> Option<Arc<dyn Species>> ;
fn get_by_hash<'a>(&'a self, key: u32) -> Option<Arc<dyn Species>>;
fn map(&self) -> &IndexMap<StringKey, Arc<dyn Species>>;
fn get_modify(&mut self) -> &mut IndexMap<StringKey, Arc<dyn Species>>;
}
impl ValueIdentifiable for SpeciesLibrary {
fn value_identifier(&self) -> ValueIdentifier{
ValueIdentifier::new(0)
}
}
}
fn build_species() -> Arc<dyn Species> { fn build_species() -> Arc<dyn Species> {
Arc::new(SpeciesImpl::new( Arc::new(SpeciesImpl::new(
@ -75,15 +93,15 @@ pub mod tests {
)) ))
} }
pub fn build() -> SpeciesLibrary { pub fn build() -> Box<dyn SpeciesLibrary> {
let mut lib = SpeciesLibrary::new(1); let mut lib = SpeciesLibraryImpl::new(1);
let species = build_species(); let species = build_species();
// Borrow as mut so we can insert // Borrow as mut so we can insert
let w = &mut lib; let w = &mut lib;
w.add(&"foo".into(), species); w.add(&"foo".into(), species);
// Drops borrow as mut // Drops borrow as mut
lib Box::new(lib)
} }
#[test] #[test]
@ -94,8 +112,9 @@ pub mod tests {
let r = &lib; let r = &lib;
let mon = r.get(&"foo".into()); let mon = r.get(&"foo".into());
assert!(mon.is_some()); assert!(mon.is_some());
assert_eq!(mon.unwrap().id(), 0_u16); let mon = mon.unwrap();
assert_eq!(mon.unwrap().as_ref().name(), &"foo".into()); assert_eq!(mon.id(), 0_u16);
assert_eq!(mon.name(), &"foo".into());
assert_eq!(r.len(), 1); assert_eq!(r.len(), 1);
} }

View File

@ -1,115 +1,154 @@
use crate::static_data::AbilityLibrary;
use crate::static_data::GrowthRateLibrary;
use crate::static_data::ItemLibrary;
use crate::static_data::LibrarySettings;
use crate::static_data::MoveLibrary; use crate::static_data::MoveLibrary;
use crate::static_data::NatureLibrary; use crate::static_data::NatureLibrary;
use crate::static_data::SpeciesLibrary; use crate::static_data::SpeciesLibrary;
use crate::static_data::TypeLibrary; use crate::static_data::TypeLibrary;
use crate::static_data::{AbilityLibrary, AbilityLibraryImpl, ItemLibraryImpl, MoveLibraryImpl, SpeciesLibraryImpl};
use crate::static_data::{GrowthRateLibrary, GrowthRateLibraryImpl};
use crate::static_data::{ItemLibrary, NatureLibraryImpl};
use crate::static_data::{LibrarySettings, TypeLibraryImpl};
use crate::{ValueIdentifiable, ValueIdentifier}; use crate::{ValueIdentifiable, ValueIdentifier};
use std::fmt::Debug;
/// The storage for all different libraries.
pub trait StaticData: Debug + ValueIdentifiable {
/// Several misc settings for the library.
fn settings(&self) -> &Box<dyn LibrarySettings>;
/// All data for Pokemon species.
fn species(&self) -> &Box<dyn SpeciesLibrary>;
/// All data for Pokemon species.
fn species_mut(&mut self) -> &mut Box<dyn SpeciesLibrary>;
/// All data for the moves.
fn moves(&self) -> &Box<dyn MoveLibrary>;
/// All data for the moves.
fn moves_mut(&mut self) -> &mut Box<dyn MoveLibrary>;
/// All data for the items.
fn items(&self) -> &Box<dyn ItemLibrary>;
/// All data for the items.
fn items_mut(&mut self) -> &mut Box<dyn ItemLibrary>;
/// All data for growth rates.
fn growth_rates(&self) -> &Box<dyn GrowthRateLibrary>;
/// All data for growth rates.
fn growth_rates_mut(&mut self) -> &mut Box<dyn GrowthRateLibrary>;
/// All data related to types and type effectiveness.
fn types(&self) -> &Box<dyn TypeLibrary>;
/// All data related to types and type effectiveness.
fn types_mut(&mut self) -> &mut Box<dyn TypeLibrary>;
/// All data related to natures.
fn natures(&self) -> &Box<dyn NatureLibrary>;
/// All data related to natures.
fn natures_mut(&mut self) -> &mut Box<dyn NatureLibrary>;
/// All data related to abilities.
fn abilities(&self) -> &Box<dyn AbilityLibrary>;
/// All data related to abilities.
fn abilities_mut(&mut self) -> &mut Box<dyn AbilityLibrary>;
}
/// The storage for all different libraries. /// The storage for all different libraries.
#[derive(Debug)] #[derive(Debug)]
pub struct StaticData { pub struct StaticDataImpl {
/// A unique identifier so we know what value this is. /// A unique identifier so we know what value this is.
identifier: ValueIdentifier, identifier: ValueIdentifier,
/// Several misc settings for the library. /// Several misc settings for the library.
settings: LibrarySettings, settings: Box<dyn LibrarySettings>,
/// All data for Pokemon species. /// All data for Pokemon species.
species: SpeciesLibrary, species: Box<dyn SpeciesLibrary>,
/// All data for the moves. /// All data for the moves.
moves: MoveLibrary, moves: Box<dyn MoveLibrary>,
/// All data for the items. /// All data for the items.
items: ItemLibrary, items: Box<dyn ItemLibrary>,
/// All data for growth rates. /// All data for growth rates.
growth_rates: GrowthRateLibrary, growth_rates: Box<dyn GrowthRateLibrary>,
/// All data related to types and type effectiveness. /// All data related to types and type effectiveness.
types: TypeLibrary, types: Box<dyn TypeLibrary>,
/// All data related to natures. /// All data related to natures.
natures: NatureLibrary, natures: Box<dyn NatureLibrary>,
/// All data related to abilities. /// All data related to abilities.
abilities: AbilityLibrary, abilities: Box<dyn AbilityLibrary>,
} }
impl StaticData { impl StaticDataImpl {
/// Instantiates a new data collection. /// Instantiates a new data collection.
pub fn new(settings: LibrarySettings) -> Self { pub fn new(settings: Box<dyn LibrarySettings>) -> Self {
Self { Self {
identifier: Default::default(), identifier: Default::default(),
settings, settings,
species: SpeciesLibrary::new(0), species: Box::new(SpeciesLibraryImpl::new(0)),
moves: MoveLibrary::new(0), moves: Box::new(MoveLibraryImpl::new(0)),
items: ItemLibrary::new(0), items: Box::new(ItemLibraryImpl::new(0)),
growth_rates: GrowthRateLibrary::new(0), growth_rates: Box::new(GrowthRateLibraryImpl::new(0)),
types: TypeLibrary::new(0), types: Box::new(TypeLibraryImpl::new(0)),
natures: NatureLibrary::new(0), natures: Box::new(NatureLibraryImpl::new(0)),
abilities: AbilityLibrary::new(0), abilities: Box::new(AbilityLibraryImpl::new(0)),
} }
} }
}
impl StaticData for StaticDataImpl {
/// Several misc settings for the library. /// Several misc settings for the library.
pub fn settings(&self) -> &LibrarySettings { fn settings(&self) -> &Box<dyn LibrarySettings> {
&self.settings &self.settings
} }
/// All data for Pokemon species. /// All data for Pokemon species.
pub fn species(&self) -> &SpeciesLibrary { fn species(&self) -> &Box<dyn SpeciesLibrary> {
&self.species &self.species
} }
/// All data for Pokemon species. /// All data for Pokemon species.
pub fn species_mut(&mut self) -> &mut SpeciesLibrary { fn species_mut(&mut self) -> &mut Box<dyn SpeciesLibrary> {
&mut self.species &mut self.species
} }
/// All data for the moves. /// All data for the moves.
pub fn moves(&self) -> &MoveLibrary { fn moves(&self) -> &Box<dyn MoveLibrary> {
&self.moves &self.moves
} }
/// All data for the moves. /// All data for the moves.
pub fn moves_mut(&mut self) -> &mut MoveLibrary { fn moves_mut(&mut self) -> &mut Box<dyn MoveLibrary> {
&mut self.moves &mut self.moves
} }
/// All data for the items. /// All data for the items.
pub fn items(&self) -> &ItemLibrary { fn items(&self) -> &Box<dyn ItemLibrary> {
&self.items &self.items
} }
/// All data for the items. /// All data for the items.
pub fn items_mut(&mut self) -> &mut ItemLibrary { fn items_mut(&mut self) -> &mut Box<dyn ItemLibrary> {
&mut self.items &mut self.items
} }
/// All data for growth rates. /// All data for growth rates.
pub fn growth_rates(&self) -> &GrowthRateLibrary { fn growth_rates(&self) -> &Box<dyn GrowthRateLibrary> {
&self.growth_rates &self.growth_rates
} }
/// All data for growth rates. /// All data for growth rates.
pub fn growth_rates_mut(&mut self) -> &mut GrowthRateLibrary { fn growth_rates_mut(&mut self) -> &mut Box<dyn GrowthRateLibrary> {
&mut self.growth_rates &mut self.growth_rates
} }
/// All data related to types and type effectiveness. /// All data related to types and type effectiveness.
pub fn types(&self) -> &TypeLibrary { fn types(&self) -> &Box<dyn TypeLibrary> {
&self.types &self.types
} }
/// All data related to types and type effectiveness. /// All data related to types and type effectiveness.
pub fn types_mut(&mut self) -> &mut TypeLibrary { fn types_mut(&mut self) -> &mut Box<dyn TypeLibrary> {
&mut self.types &mut self.types
} }
/// All data related to natures. /// All data related to natures.
pub fn natures(&self) -> &NatureLibrary { fn natures(&self) -> &Box<dyn NatureLibrary> {
&self.natures &self.natures
} }
/// All data related to natures. /// All data related to natures.
pub fn natures_mut(&mut self) -> &mut NatureLibrary { fn natures_mut(&mut self) -> &mut Box<dyn NatureLibrary> {
&mut self.natures &mut self.natures
} }
/// All data related to abilities. /// All data related to abilities.
pub fn abilities(&self) -> &AbilityLibrary { fn abilities(&self) -> &Box<dyn AbilityLibrary> {
&self.abilities &self.abilities
} }
/// All data related to abilities. /// All data related to abilities.
pub fn abilities_mut(&mut self) -> &mut AbilityLibrary { fn abilities_mut(&mut self) -> &mut Box<dyn AbilityLibrary> {
&mut self.abilities &mut self.abilities
} }
} }
impl ValueIdentifiable for StaticData { impl ValueIdentifiable for StaticDataImpl {
fn value_identifier(&self) -> ValueIdentifier { fn value_identifier(&self) -> ValueIdentifier {
self.identifier self.identifier
} }
@ -117,23 +156,48 @@ impl ValueIdentifiable for StaticData {
#[cfg(test)] #[cfg(test)]
pub mod test { pub mod test {
use crate::static_data::libraries::library_settings::LibrarySettings; use super::*;
use crate::static_data::libraries::static_data::StaticData; use crate::static_data::LibrarySettingsImpl;
use crate::static_data::libraries::{
ability_library, growth_rate_library, item_library, move_library, nature_library, species_library, type_library,
};
pub fn build() -> StaticData { mockall::mock! {
StaticData { #[derive(Debug)]
pub StaticData{}
impl StaticData for StaticData {
fn settings(&self) -> &Box<dyn LibrarySettings>;
fn species(&self) -> &Box<dyn SpeciesLibrary>;
fn species_mut(&mut self) -> &mut Box<dyn SpeciesLibrary>;
fn moves(&self) -> &Box<dyn MoveLibrary>;
fn moves_mut(&mut self) -> &mut Box<dyn MoveLibrary>;
fn items(&self) -> &Box<dyn ItemLibrary>;
fn items_mut(&mut self) -> &mut Box<dyn ItemLibrary>;
fn growth_rates(&self) -> & Box<dyn GrowthRateLibrary>;
fn growth_rates_mut(&mut self) -> &mut Box<dyn GrowthRateLibrary>;
fn types(&self) -> &Box<dyn TypeLibrary>;
fn types_mut(&mut self) -> &mut Box<dyn TypeLibrary>;
fn natures(&self) -> &Box<dyn NatureLibrary>;
fn natures_mut(&mut self) -> &mut Box<dyn NatureLibrary>;
fn abilities(&self) -> &Box<dyn AbilityLibrary>;
fn abilities_mut(&mut self) -> &mut Box<dyn AbilityLibrary>;
}
impl ValueIdentifiable for StaticData {
fn value_identifier(&self) -> ValueIdentifier{
ValueIdentifier::new(0)
}
}
}
pub fn build() -> StaticDataImpl {
StaticDataImpl {
identifier: Default::default(), identifier: Default::default(),
settings: LibrarySettings::new(100), settings: Box::new(LibrarySettingsImpl::new(100)),
species: species_library::tests::build(), species: crate::static_data::libraries::species_library::tests::build(),
moves: move_library::tests::build(), moves: crate::static_data::libraries::move_library::tests::build(),
items: item_library::tests::build(), items: crate::static_data::libraries::item_library::tests::build(),
growth_rates: growth_rate_library::tests::build(), growth_rates: Box::new(crate::static_data::libraries::growth_rate_library::tests::build()),
types: type_library::tests::build(), types: Box::new(crate::static_data::libraries::type_library::tests::build()),
natures: nature_library::tests::build(), natures: Box::new(crate::static_data::libraries::nature_library::tests::build()),
abilities: ability_library::tests::build(), abilities: Box::new(crate::static_data::libraries::ability_library::tests::build()),
} }
} }
} }

View File

@ -1,5 +1,6 @@
use atomig::Atom; use atomig::Atom;
use hashbrown::HashMap; use hashbrown::HashMap;
use std::fmt::Debug;
use crate::{StringKey, ValueIdentifiable, ValueIdentifier}; use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
@ -24,9 +25,32 @@ impl From<TypeIdentifier> for u8 {
} }
} }
/// All data related to types and effectiveness.
pub trait TypeLibrary: Debug + ValueIdentifiable {
/// Gets the type identifier for a type with a name.
fn get_type_id(&self, key: &StringKey) -> Option<TypeIdentifier>;
/// Gets the type name from the type identifier.
fn get_type_name(&self, t: TypeIdentifier) -> Option<StringKey>;
/// Gets the effectiveness for a single attacking type against a single defending type.
fn get_single_effectiveness(&self, attacking: TypeIdentifier, defending: TypeIdentifier) -> f32;
/// Gets the effectiveness for a single attacking type against an amount of defending types.
/// This is equivalent to running [`get_single_effectiveness`] on each defending type, and
/// multiplying the results with each other.
fn get_effectiveness(&self, attacking: TypeIdentifier, defending: &[TypeIdentifier]) -> f32;
/// Registers a new type in the library.
fn register_type(&mut self, name: &StringKey) -> TypeIdentifier;
/// Sets the effectiveness for an attacking type against a defending type.
fn set_effectiveness(&mut self, attacking: TypeIdentifier, defending: TypeIdentifier, effectiveness: f32);
}
/// All data related to types and effectiveness. /// All data related to types and effectiveness.
#[derive(Debug)] #[derive(Debug)]
pub struct TypeLibrary { pub struct TypeLibraryImpl {
/// A unique identifier so we know what value this is. /// A unique identifier so we know what value this is.
identifier: ValueIdentifier, identifier: ValueIdentifier,
/// A list of types /// A list of types
@ -35,23 +59,25 @@ pub struct TypeLibrary {
effectiveness: Vec<Vec<f32>>, effectiveness: Vec<Vec<f32>>,
} }
impl TypeLibrary { impl TypeLibraryImpl {
/// Instantiates a new type library with a specific capacity. /// Instantiates a new type library with a specific capacity.
pub fn new(capacity: usize) -> TypeLibrary { pub fn new(capacity: usize) -> Self {
TypeLibrary { Self {
identifier: Default::default(), identifier: Default::default(),
types: HashMap::with_capacity(capacity), types: HashMap::with_capacity(capacity),
effectiveness: vec![], effectiveness: vec![],
} }
} }
}
impl TypeLibrary for TypeLibraryImpl {
/// Gets the type identifier for a type with a name. /// Gets the type identifier for a type with a name.
pub fn get_type_id(&self, key: &StringKey) -> Option<TypeIdentifier> { fn get_type_id(&self, key: &StringKey) -> Option<TypeIdentifier> {
self.types.get(key).cloned() self.types.get(key).cloned()
} }
/// Gets the type name from the type identifier. /// Gets the type name from the type identifier.
pub fn get_type_name(&self, t: TypeIdentifier) -> Option<StringKey> { fn get_type_name(&self, t: TypeIdentifier) -> Option<StringKey> {
for kv in &self.types { for kv in &self.types {
if *kv.1 == t { if *kv.1 == t {
return Some(kv.0.clone()); return Some(kv.0.clone());
@ -61,14 +87,14 @@ impl TypeLibrary {
} }
/// Gets the effectiveness for a single attacking type against a single defending type. /// Gets the effectiveness for a single attacking type against a single defending type.
pub fn get_single_effectiveness(&self, attacking: TypeIdentifier, defending: TypeIdentifier) -> f32 { fn get_single_effectiveness(&self, attacking: TypeIdentifier, defending: TypeIdentifier) -> f32 {
self.effectiveness[(attacking.val - 1) as usize][(defending.val - 1) as usize] self.effectiveness[(attacking.val - 1) as usize][(defending.val - 1) as usize]
} }
/// Gets the effectiveness for a single attacking type against an amount of defending types. /// Gets the effectiveness for a single attacking type against an amount of defending types.
/// This is equivalent to running [`get_single_effectiveness`] on each defending type, and /// This is equivalent to running [`get_single_effectiveness`] on each defending type, and
/// multiplying the results with each other. /// multiplying the results with each other.
pub fn get_effectiveness(&self, attacking: TypeIdentifier, defending: &[TypeIdentifier]) -> f32 { fn get_effectiveness(&self, attacking: TypeIdentifier, defending: &[TypeIdentifier]) -> f32 {
let mut e = 1.0; let mut e = 1.0;
for def in defending { for def in defending {
e *= self.get_single_effectiveness(attacking, *def); e *= self.get_single_effectiveness(attacking, *def);
@ -77,7 +103,7 @@ impl TypeLibrary {
} }
/// Registers a new type in the library. /// Registers a new type in the library.
pub fn register_type(&mut self, name: &StringKey) -> TypeIdentifier { fn register_type(&mut self, name: &StringKey) -> TypeIdentifier {
let id = TypeIdentifier { let id = TypeIdentifier {
val: (self.types.len() + 1) as u8, val: (self.types.len() + 1) as u8,
}; };
@ -90,12 +116,12 @@ impl TypeLibrary {
} }
/// Sets the effectiveness for an attacking type against a defending type. /// Sets the effectiveness for an attacking type against a defending type.
pub fn set_effectiveness(&mut self, attacking: TypeIdentifier, defending: TypeIdentifier, effectiveness: f32) { fn set_effectiveness(&mut self, attacking: TypeIdentifier, defending: TypeIdentifier, effectiveness: f32) {
self.effectiveness[(attacking.val - 1) as usize][(defending.val - 1) as usize] = effectiveness; self.effectiveness[(attacking.val - 1) as usize][(defending.val - 1) as usize] = effectiveness;
} }
} }
impl ValueIdentifiable for TypeLibrary { impl ValueIdentifiable for TypeLibraryImpl {
fn value_identifier(&self) -> ValueIdentifier { fn value_identifier(&self) -> ValueIdentifier {
self.identifier self.identifier
} }
@ -105,10 +131,11 @@ impl ValueIdentifiable for TypeLibrary {
pub mod tests { pub mod tests {
use assert_approx_eq::assert_approx_eq; use assert_approx_eq::assert_approx_eq;
use super::*;
use crate::static_data::libraries::type_library::TypeLibrary; use crate::static_data::libraries::type_library::TypeLibrary;
pub fn build() -> TypeLibrary { pub fn build() -> TypeLibraryImpl {
let mut lib = TypeLibrary::new(2); let mut lib = TypeLibraryImpl::new(2);
// Borrow as mut so we can insert // Borrow as mut so we can insert
let w = &mut lib; let w = &mut lib;
@ -124,7 +151,7 @@ pub mod tests {
#[test] #[test]
fn add_two_types_retrieve_them() { fn add_two_types_retrieve_them() {
let mut lib = TypeLibrary::new(2); let mut lib = TypeLibraryImpl::new(2);
// Borrow as mut so we can insert // Borrow as mut so we can insert
let w = &mut lib; let w = &mut lib;
@ -140,7 +167,7 @@ pub mod tests {
#[test] #[test]
fn add_two_types_set_effectiveness_retrieve() { fn add_two_types_set_effectiveness_retrieve() {
let mut lib = TypeLibrary::new(2); let mut lib = TypeLibraryImpl::new(2);
// Borrow as mut so we can insert // Borrow as mut so we can insert
let w = &mut lib; let w = &mut lib;
@ -158,7 +185,7 @@ pub mod tests {
#[test] #[test]
fn add_two_types_get_aggregate_effectiveness() { fn add_two_types_get_aggregate_effectiveness() {
let mut lib = TypeLibrary::new(2); let mut lib = TypeLibraryImpl::new(2);
// Borrow as mut so we can insert // Borrow as mut so we can insert
let w = &mut lib; let w = &mut lib;
@ -176,7 +203,7 @@ pub mod tests {
#[test] #[test]
fn add_two_types_get_type_name() { fn add_two_types_get_type_name() {
let mut lib = TypeLibrary::new(2); let mut lib = TypeLibraryImpl::new(2);
// Borrow as mut so we can insert // Borrow as mut so we can insert
let w = &mut lib; let w = &mut lib;

View File

@ -28,7 +28,6 @@ pub trait Form: ValueIdentifiable + Debug {
/// The possible hidden abilities a Pokemon with this form can have. /// The possible hidden abilities a Pokemon with this form can have.
fn hidden_abilities(&self) -> &Vec<StringKey>; fn hidden_abilities(&self) -> &Vec<StringKey>;
#[allow(clippy::borrowed_box)]
/// The moves a Pokemon with this form can learn. /// The moves a Pokemon with this form can learn.
fn moves(&self) -> &Box<dyn LearnableMoves>; fn moves(&self) -> &Box<dyn LearnableMoves>;
/// Arbitrary flags can be set on a form for scripting use. /// Arbitrary flags can be set on a form for scripting use.
@ -146,7 +145,6 @@ impl Form for FormImpl {
&self.hidden_abilities &self.hidden_abilities
} }
#[allow(clippy::borrowed_box)]
/// The moves a Pokemon with this form can learn. /// The moves a Pokemon with this form can learn.
fn moves(&self) -> &Box<dyn LearnableMoves> { fn moves(&self) -> &Box<dyn LearnableMoves> {
&self.moves &self.moves
@ -233,7 +231,6 @@ pub(crate) mod tests {
fn base_stats(&self) -> &StaticStatisticSet<u16>; fn base_stats(&self) -> &StaticStatisticSet<u16>;
fn abilities(&self) -> &Vec<StringKey>; fn abilities(&self) -> &Vec<StringKey>;
fn hidden_abilities(&self) -> &Vec<StringKey>; fn hidden_abilities(&self) -> &Vec<StringKey>;
#[allow(clippy::borrowed_box)]
fn moves(&self) -> &Box<dyn LearnableMoves>; fn moves(&self) -> &Box<dyn LearnableMoves>;
fn flags(&self) -> &HashSet<StringKey>; fn flags(&self) -> &HashSet<StringKey>;
fn get_type(&self, index: usize) -> TypeIdentifier; fn get_type(&self, index: usize) -> TypeIdentifier;

View File

@ -10,24 +10,24 @@ use project_root::get_project_root;
use serde_json::Value; use serde_json::Value;
use pkmn_lib::defines::LevelInt; use pkmn_lib::defines::LevelInt;
use pkmn_lib::dynamic_data::DynamicLibrary;
use pkmn_lib::dynamic_data::Gen7BattleStatCalculator; use pkmn_lib::dynamic_data::Gen7BattleStatCalculator;
use pkmn_lib::dynamic_data::Gen7DamageLibrary; use pkmn_lib::dynamic_data::Gen7DamageLibrary;
use pkmn_lib::dynamic_data::Gen7MiscLibrary; use pkmn_lib::dynamic_data::Gen7MiscLibrary;
use pkmn_lib::dynamic_data::{DynamicLibrary, DynamicLibraryImpl};
use pkmn_lib::script_implementations::wasm::script_resolver::WebAssemblyScriptResolver; use pkmn_lib::script_implementations::wasm::script_resolver::WebAssemblyScriptResolver;
use pkmn_lib::static_data::{ use pkmn_lib::static_data::{
AbilityImpl, AbilityLibrary, BattleItemCategory, DataLibrary, EffectParameter, Form, FormImpl, GrowthRateLibrary, AbilityImpl, AbilityLibrary, BattleItemCategory, EffectParameter, Form, FormImpl, GrowthRateLibrary, ItemImpl,
ItemImpl, ItemLibrary, LearnableMoves, LearnableMovesImpl, LibrarySettings, LookupGrowthRate, MoveDataImpl, ItemLibrary, LearnableMoves, LearnableMovesImpl, LibrarySettingsImpl, LookupGrowthRate, MoveDataImpl, MoveLibrary,
MoveLibrary, NatureImpl, NatureLibrary, SecondaryEffect, SecondaryEffectImpl, SpeciesImpl, StaticData, NatureImpl, NatureLibrary, SecondaryEffect, SecondaryEffectImpl, SpeciesImpl, StaticData, StaticDataImpl,
StaticStatisticSet, Statistic, TypeLibrary, StaticStatisticSet, Statistic, TypeLibrary, TypeLibraryImpl,
}; };
use pkmn_lib::StringKey; use pkmn_lib::StringKey;
pub fn load_library() -> DynamicLibrary { pub fn load_library() -> Arc<dyn DynamicLibrary> {
let mut path = get_project_root().unwrap(); let mut path = get_project_root().unwrap();
path.push("tests/data/"); path.push("tests/data/");
let path = path.to_str().unwrap().to_string(); let path = path.to_str().unwrap().to_string();
let mut data = StaticData::new(LibrarySettings::new(100)); let mut data = StaticDataImpl::new(Box::new(LibrarySettingsImpl::new(100)));
load_types(&path, data.types_mut()); load_types(&path, data.types_mut());
load_natures(&path, data.natures_mut()); load_natures(&path, data.natures_mut());
load_items(&path, data.items_mut()); load_items(&path, data.items_mut());
@ -38,16 +38,16 @@ pub fn load_library() -> DynamicLibrary {
let mut resolver = WebAssemblyScriptResolver::new(); let mut resolver = WebAssemblyScriptResolver::new();
load_wasm(&path, resolver.as_mut()); load_wasm(&path, resolver.as_mut());
DynamicLibrary::new( Arc::new(DynamicLibraryImpl::new(
data, Box::new(data),
Box::new(Gen7BattleStatCalculator::new()), Box::new(Gen7BattleStatCalculator::new()),
Box::new(Gen7DamageLibrary::new(false)), Box::new(Gen7DamageLibrary::new(false)),
Box::new(Gen7MiscLibrary::new()), Box::new(Gen7MiscLibrary::new()),
resolver, resolver,
) ))
} }
pub fn load_types(path: &String, type_library: &mut TypeLibrary) { pub fn load_types(path: &String, type_library: &mut Box<dyn TypeLibrary>) {
let mut reader = csv::ReaderBuilder::new() let mut reader = csv::ReaderBuilder::new()
.delimiter(b'|') .delimiter(b'|')
.from_path(path.to_string() + "Types.csv") .from_path(path.to_string() + "Types.csv")
@ -69,7 +69,7 @@ pub fn load_types(path: &String, type_library: &mut TypeLibrary) {
} }
} }
pub fn load_natures(path: &String, nature_library: &mut NatureLibrary) { pub fn load_natures(path: &String, nature_library: &mut Box<dyn NatureLibrary>) {
let mut reader = csv::ReaderBuilder::new() let mut reader = csv::ReaderBuilder::new()
.delimiter(b'|') .delimiter(b'|')
.from_path(path.to_string() + "Natures.csv") .from_path(path.to_string() + "Natures.csv")
@ -93,7 +93,7 @@ pub fn load_natures(path: &String, nature_library: &mut NatureLibrary) {
} }
} }
pub fn load_items(path: &String, lib: &mut ItemLibrary) { pub fn load_items(path: &String, lib: &mut Box<dyn ItemLibrary>) {
let mut file = File::open(path.to_string() + "Items.json").unwrap(); let mut file = File::open(path.to_string() + "Items.json").unwrap();
let mut data = String::new(); let mut data = String::new();
file.read_to_string(&mut data).unwrap(); file.read_to_string(&mut data).unwrap();
@ -123,7 +123,7 @@ pub fn load_items(path: &String, lib: &mut ItemLibrary) {
} }
} }
pub fn load_growth_rates(path: &String, growth_rate_library: &mut GrowthRateLibrary) { pub fn load_growth_rates(path: &String, growth_rate_library: &mut Box<dyn GrowthRateLibrary>) {
let mut file = File::open(path.to_string() + "GrowthRates.json").unwrap(); let mut file = File::open(path.to_string() + "GrowthRates.json").unwrap();
let mut data = String::new(); let mut data = String::new();
file.read_to_string(&mut data).unwrap(); file.read_to_string(&mut data).unwrap();
@ -142,7 +142,7 @@ pub fn load_growth_rates(path: &String, growth_rate_library: &mut GrowthRateLibr
} }
} }
pub fn load_abilities(path: &String, ability_library: &mut AbilityLibrary) { pub fn load_abilities(path: &String, ability_library: &mut Box<dyn AbilityLibrary>) {
let mut file = File::open(path.to_string() + "Abilities.json").unwrap(); let mut file = File::open(path.to_string() + "Abilities.json").unwrap();
let mut data = String::new(); let mut data = String::new();
file.read_to_string(&mut data).unwrap(); file.read_to_string(&mut data).unwrap();
@ -166,7 +166,7 @@ pub fn load_abilities(path: &String, ability_library: &mut AbilityLibrary) {
} }
} }
pub fn load_moves(path: &String, lib: &mut StaticData) { pub fn load_moves(path: &String, lib: &mut dyn StaticData) {
let mut file = File::open(path.to_string() + "Moves.json").unwrap(); let mut file = File::open(path.to_string() + "Moves.json").unwrap();
let mut data = String::new(); let mut data = String::new();
file.read_to_string(&mut data).unwrap(); file.read_to_string(&mut data).unwrap();
@ -231,7 +231,7 @@ pub fn load_moves(path: &String, lib: &mut StaticData) {
} }
} }
pub fn load_species(path: &String, library: &mut StaticData) { pub fn load_species(path: &String, library: &mut dyn StaticData) {
let mut file = File::open(path.to_string() + "Pokemon.json").unwrap(); let mut file = File::open(path.to_string() + "Pokemon.json").unwrap();
let mut data = String::new(); let mut data = String::new();
file.read_to_string(&mut data).unwrap(); file.read_to_string(&mut data).unwrap();
@ -285,7 +285,7 @@ fn load_wasm(path: &String, library: &mut WebAssemblyScriptResolver) {
library.finalize(); library.finalize();
} }
fn parse_form(name: StringKey, value: &Value, library: &mut StaticData) -> Arc<dyn Form> { fn parse_form(name: StringKey, value: &Value, library: &mut dyn StaticData) -> Arc<dyn Form> {
let mut abilities = Vec::new(); let mut abilities = Vec::new();
for a in value.get("abilities").unwrap().as_array().unwrap() { for a in value.get("abilities").unwrap().as_array().unwrap() {
abilities.push(a.as_str().unwrap().into()); abilities.push(a.as_str().unwrap().into());
@ -308,7 +308,7 @@ fn parse_form(name: StringKey, value: &Value, library: &mut StaticData) -> Arc<d
.map(|a| library.types().get_type_id(&a.as_str().unwrap().into()).unwrap()) .map(|a| library.types().get_type_id(&a.as_str().unwrap().into()).unwrap())
.collect(); .collect();
let moves = parse_moves(value.get("moves").unwrap(), library.moves()); let moves = parse_moves(value.get("moves").unwrap(), library.moves_mut());
Arc::new(FormImpl::new( Arc::new(FormImpl::new(
&name, &name,
@ -368,7 +368,7 @@ where
) )
} }
fn parse_moves(value: &Value, move_library: &MoveLibrary) -> Box<dyn LearnableMoves> { fn parse_moves(value: &Value, move_library: &mut Box<dyn MoveLibrary>) -> Box<dyn LearnableMoves> {
let mut moves = LearnableMovesImpl::default(); let mut moves = LearnableMovesImpl::default();
let level_moves = value.get("levelMoves").unwrap().as_array().unwrap(); let level_moves = value.get("levelMoves").unwrap().as_array().unwrap();
@ -410,7 +410,7 @@ fn parse_effect_parameter(value: &Value) -> EffectParameter {
fn test_type_library_loaded() { fn test_type_library_loaded() {
let mut path = get_project_root().unwrap(); let mut path = get_project_root().unwrap();
path.push("tests/data/"); path.push("tests/data/");
let mut lib = TypeLibrary::new(18); let mut lib: Box<dyn TypeLibrary> = Box::new(TypeLibraryImpl::new(18));
load_types(&path.to_str().unwrap().to_string(), &mut lib); load_types(&path.to_str().unwrap().to_string(), &mut lib);
assert_eq!( assert_eq!(

View File

@ -43,7 +43,7 @@ struct TestPokemon {
} }
impl TestCase { impl TestCase {
pub fn run_test(&self, library: Arc<DynamicLibrary>) { pub fn run_test(&self, library: Arc<dyn DynamicLibrary>) {
let mut parties = Vec::new(); let mut parties = Vec::new();
for party in &self.battle_setup.parties { for party in &self.battle_setup.parties {
let pokemon = party let pokemon = party
@ -73,7 +73,7 @@ impl TestCase {
} }
impl TestPokemon { impl TestPokemon {
fn to_pokemon(&self, library: Arc<DynamicLibrary>) -> Pokemon { fn to_pokemon(&self, library: Arc<dyn DynamicLibrary>) -> Pokemon {
let mut builder = PokemonBuilder::new(library, self.species.as_str().into(), self.level); let mut builder = PokemonBuilder::new(library, self.species.as_str().into(), self.level);
for move_name in &self.moves { for move_name in &self.moves {
builder = builder.learn_move(StringKey::new(move_name)); builder = builder.learn_move(StringKey::new(move_name));

View File

@ -17,8 +17,8 @@ use crate::common::{library_loader, TestCase};
pub mod common; pub mod common;
fn get_library() -> Arc<DynamicLibrary> { fn get_library() -> Arc<dyn DynamicLibrary> {
Arc::new(library_loader::load_library()) library_loader::load_library()
} }
#[test] #[test]