diff --git a/src/dynamic_data/libraries/misc_library.rs b/src/dynamic_data/libraries/misc_library.rs index 77ed7a7..60c4a59 100755 --- a/src/dynamic_data/libraries/misc_library.rs +++ b/src/dynamic_data/libraries/misc_library.rs @@ -6,7 +6,7 @@ use hashbrown::HashSet; use crate::dynamic_data::choices::{MoveChoice, TurnChoice}; use crate::dynamic_data::Pokemon; use crate::dynamic_data::{LearnedMove, MoveLearnMethod}; -use crate::static_data::{MoveCategory, MoveData, MoveTarget, SecondaryEffectImpl}; +use crate::static_data::{MoveCategory, MoveData, MoveDataImpl, MoveTarget, SecondaryEffectImpl}; use crate::{StringKey, ValueIdentifiable, ValueIdentifier}; /// The misc library holds several misc functions required for the battle to run. @@ -31,7 +31,7 @@ pub struct Gen7MiscLibrary { impl Gen7MiscLibrary { /// Instantiates a new MiscLibrary. pub fn new() -> Self { - let struggle_data = Arc::new(MoveData::new( + let struggle_data: Arc = Arc::new(MoveDataImpl::new( &StringKey::new("struggle"), 0.into(), MoveCategory::Physical, diff --git a/src/dynamic_data/models/executing_move.rs b/src/dynamic_data/models/executing_move.rs index ea0d9aa..0ab0056 100755 --- a/src/dynamic_data/models/executing_move.rs +++ b/src/dynamic_data/models/executing_move.rs @@ -101,7 +101,7 @@ pub struct ExecutingMove { /// The move the user has actually chosen to do. chosen_move: Arc, /// The move that the user is actually going to do. - use_move: Arc, + use_move: Arc, /// The script of the move. script: ScriptContainer, /// The targets for this move. @@ -117,7 +117,7 @@ impl ExecutingMove { number_of_hits: u8, user: Arc, chosen_move: Arc, - use_move: Arc, + use_move: Arc, script: ScriptContainer, ) -> Self { let total_hits = number_of_hits as usize * targets.len(); @@ -155,7 +155,7 @@ impl ExecutingMove { &self.chosen_move } /// The move that the user is actually going to do. - pub fn use_move(&self) -> &Arc { + pub fn use_move(&self) -> &Arc { &self.use_move } /// The script of the move. diff --git a/src/dynamic_data/models/learned_move.rs b/src/dynamic_data/models/learned_move.rs index 84f95ee..115461a 100755 --- a/src/dynamic_data/models/learned_move.rs +++ b/src/dynamic_data/models/learned_move.rs @@ -11,7 +11,7 @@ pub struct LearnedMove { /// A unique identifier so we know what value this is. identifier: ValueIdentifier, /// The immutable move information of the move. - move_data: Arc, + move_data: Arc, /// The maximal power points for this move. max_pp: u8, /// The amount of remaining power points. If this is 0, we can not use the move anymore. @@ -33,7 +33,7 @@ pub enum MoveLearnMethod { impl LearnedMove { /// Instantiate a new learned move. - pub fn new(move_data: &Arc, learn_method: MoveLearnMethod) -> Self { + pub fn new(move_data: &Arc, learn_method: MoveLearnMethod) -> Self { Self { identifier: Default::default(), move_data: move_data.clone(), @@ -44,7 +44,7 @@ impl LearnedMove { } /// The immutable move information of the move. - pub fn move_data(&self) -> &Arc { + pub fn move_data(&self) -> &Arc { &self.move_data } /// The maximal power points for this move. @@ -100,11 +100,11 @@ impl ValueIdentifiable for LearnedMove { #[cfg(test)] mod tests { use super::*; - use crate::static_data::{MoveCategory, MoveTarget}; + use crate::static_data::{MoveCategory, MoveDataImpl, MoveTarget}; #[test] fn create_learned_move_restore_uses() { - let data = Arc::new(MoveData::new( + let data: Arc = Arc::new(MoveDataImpl::new( &"foo".into(), 0u8.into(), MoveCategory::Special, diff --git a/src/ffi/dynamic_data/models/learned_move.rs b/src/ffi/dynamic_data/models/learned_move.rs index abcac96..6b3048c 100644 --- a/src/ffi/dynamic_data/models/learned_move.rs +++ b/src/ffi/dynamic_data/models/learned_move.rs @@ -7,7 +7,7 @@ use std::sync::Arc; /// Instantiate a new learned move. #[no_mangle] extern "C" fn learned_move_new( - move_data: ExternPointer>, + move_data: ExternPointer>, learn_method: MoveLearnMethod, ) -> IdentifiablePointer> { Arc::new(LearnedMove::new(move_data.as_ref(), learn_method)).into() @@ -23,7 +23,7 @@ extern "C" fn learned_move_drop(learned_move: OwnedPtr>) { #[no_mangle] extern "C" fn learned_move_move_data( learned_move: ExternPointer>, -) -> IdentifiablePointer> { +) -> IdentifiablePointer> { learned_move.as_ref().move_data().clone().into() } diff --git a/src/ffi/static_data/libraries/mod.rs b/src/ffi/static_data/libraries/mod.rs index 4117053..e1c7b52 100644 --- a/src/ffi/static_data/libraries/mod.rs +++ b/src/ffi/static_data/libraries/mod.rs @@ -73,6 +73,6 @@ macro_rules! library_interface { } library_interface!(SpeciesLibrary, Species); -library_interface!(MoveLibrary, MoveData); +library_interface!(MoveLibrary, dyn MoveData); library_interface!(AbilityLibrary, dyn Ability); library_interface!(ItemLibrary, dyn Item); diff --git a/src/ffi/static_data/move_data.rs b/src/ffi/static_data/move_data.rs index 2a02664..a244db5 100644 --- a/src/ffi/static_data/move_data.rs +++ b/src/ffi/static_data/move_data.rs @@ -1,6 +1,7 @@ use crate::ffi::{ffi_arc_getter, BorrowedPtr, ExternPointer, IdentifiablePointer, OwnedPtr}; use crate::static_data::{ - EffectParameter, MoveCategory, MoveData, MoveTarget, SecondaryEffect, SecondaryEffectImpl, TypeIdentifier, + EffectParameter, MoveCategory, MoveData, MoveDataImpl, MoveTarget, SecondaryEffect, SecondaryEffectImpl, + TypeIdentifier, }; use crate::StringKey; use hashbrown::HashSet; @@ -22,7 +23,7 @@ unsafe extern "C" fn move_data_new( secondary_effect: *mut Box, flags: *const *const c_char, flags_length: usize, -) -> IdentifiablePointer> { +) -> IdentifiablePointer> { let flags = std::slice::from_raw_parts(flags, flags_length); let name: StringKey = CStr::from_ptr(name).to_str().unwrap().into(); let mut flags_set: HashSet = HashSet::with_capacity(flags_length); @@ -34,7 +35,7 @@ unsafe extern "C" fn move_data_new( } else { Some(*Box::from_raw(secondary_effect)) }; - Arc::new(MoveData::new( + let a: Arc = Arc::new(MoveDataImpl::new( &name, move_type, category, @@ -45,42 +46,42 @@ unsafe extern "C" fn move_data_new( priority, secondary_effect, flags_set, - )) - .into() + )); + a.into() } /// Drops a reference counted move. #[no_mangle] -unsafe extern "C" fn move_data_drop(ptr: OwnedPtr>) { +unsafe extern "C" fn move_data_drop(ptr: OwnedPtr>) { drop_in_place(ptr) } /// The name of the move. #[no_mangle] -unsafe extern "C" fn move_data_name(ptr: ExternPointer>) -> OwnedPtr { +unsafe extern "C" fn move_data_name(ptr: ExternPointer>) -> OwnedPtr { let name = ptr.as_ref().name(); CString::new(name.str()).unwrap().into_raw() } -ffi_arc_getter!(MoveData, move_type, TypeIdentifier); -ffi_arc_getter!(MoveData, category, MoveCategory); -ffi_arc_getter!(MoveData, base_power, u8); -ffi_arc_getter!(MoveData, accuracy, u8); -ffi_arc_getter!(MoveData, base_usages, u8); -ffi_arc_getter!(MoveData, target, MoveTarget); -ffi_arc_getter!(MoveData, priority, i8); +ffi_arc_getter!(dyn MoveData, move_type, TypeIdentifier); +ffi_arc_getter!(dyn MoveData, category, MoveCategory); +ffi_arc_getter!(dyn MoveData, base_power, u8); +ffi_arc_getter!(dyn MoveData, accuracy, u8); +ffi_arc_getter!(dyn MoveData, base_usages, u8); +ffi_arc_getter!(dyn MoveData, target, MoveTarget); +ffi_arc_getter!(dyn MoveData, priority, i8); /// The optional secondary effect the move has. #[no_mangle] unsafe extern "C" fn move_data_secondary_effect( - ptr: ExternPointer>, + ptr: ExternPointer>, ) -> IdentifiablePointer> { ptr.as_ref().secondary_effect().into() } /// Arbitrary flags that can be applied to the move. #[no_mangle] -unsafe extern "C" fn move_data_has_flag(ptr: ExternPointer>, flag: *const c_char) -> u8 { +unsafe extern "C" fn move_data_has_flag(ptr: ExternPointer>, flag: *const c_char) -> u8 { let flag = CStr::from_ptr(flag).into(); u8::from(ptr.as_ref().has_flag(&flag)) } diff --git a/src/script_implementations/wasm/export_registry/dynamic_data/executing_move.rs b/src/script_implementations/wasm/export_registry/dynamic_data/executing_move.rs index 7493e08..cc84a62 100755 --- a/src/script_implementations/wasm/export_registry/dynamic_data/executing_move.rs +++ b/src/script_implementations/wasm/export_registry/dynamic_data/executing_move.rs @@ -16,15 +16,15 @@ register! { fn executing_move_get_use_move( env: FunctionEnvMut, executing_move: ExternRef, - ) -> ExternRef { - ExternRef::func_new(&env, executing_move.value_func(&env).unwrap().use_move().as_ref()) + ) -> ExternRef { + ExternRef::func_new(&env, executing_move.value_func(&env).unwrap().use_move()) } fn executing_move_get_chosen_move( env: FunctionEnvMut, executing_move: ExternRef, ) -> ExternRef { - ExternRef::func_new(&env, executing_move.value_func(&env).unwrap().chosen_move().as_ref()) + ExternRef::func_new(&env, executing_move.value_func_arc(&env).unwrap().chosen_move().as_ref()) } fn executing_move_get_number_of_hits( diff --git a/src/script_implementations/wasm/export_registry/dynamic_data/learned_move.rs b/src/script_implementations/wasm/export_registry/dynamic_data/learned_move.rs index 6c4c535..002be07 100755 --- a/src/script_implementations/wasm/export_registry/dynamic_data/learned_move.rs +++ b/src/script_implementations/wasm/export_registry/dynamic_data/learned_move.rs @@ -20,7 +20,7 @@ register! { fn learned_move_get_move_data( env: FunctionEnvMut, turn_choice: ExternRef, - ) -> ExternRef { + ) -> ExternRef { ExternRef::func_new(&env, turn_choice.value_func(&env).unwrap().move_data()) } } diff --git a/src/script_implementations/wasm/export_registry/static_data/moves.rs b/src/script_implementations/wasm/export_registry/static_data/moves.rs index 9b96bed..b75a4fb 100755 --- a/src/script_implementations/wasm/export_registry/static_data/moves.rs +++ b/src/script_implementations/wasm/export_registry/static_data/moves.rs @@ -10,7 +10,7 @@ fn move_library_get_move( env: FunctionEnvMut, lib: ExternRef, string_key: ExternRef, -) -> ExternRef { +) -> ExternRef { let lib = lib.value_func(&env).unwrap(); let m = lib.get(string_key.value_func(&env).unwrap()); if let Some(v) = m { @@ -20,7 +20,7 @@ fn move_library_get_move( } } -fn move_library_get_move_by_hash(env: FunctionEnvMut, lib: ExternRef, hash: u32) -> ExternRef { +fn move_library_get_move_by_hash(env: FunctionEnvMut, lib: ExternRef, hash: u32) -> ExternRef { let lib = lib.value_func(&env).unwrap(); let m = lib.get_by_hash(hash); if let Some(v) = m { @@ -30,35 +30,35 @@ fn move_library_get_move_by_hash(env: FunctionEnvMut, lib: Exter } } -fn move_data_get_name(env: FunctionEnvMut, move_data: ExternRef) -> ExternRef { - ExternRef::func_new(&env, move_data.value_func(&env).unwrap().name()) +fn move_data_get_name(env: FunctionEnvMut, move_data: ExternRef) -> ExternRef { + ExternRef::func_new(&env, move_data.value_func_arc(&env).unwrap().name()) } -fn move_data_get_type(env: FunctionEnvMut, move_data: ExternRef) -> u8 { - move_data.value_func(&env).unwrap().move_type().into() +fn move_data_get_type(env: FunctionEnvMut, move_data: ExternRef) -> u8 { + move_data.value_func_arc(&env).unwrap().move_type().into() } -fn move_data_get_category(env: FunctionEnvMut, move_data: ExternRef) -> u8 { - move_data.value_func(&env).unwrap().category() as u8 +fn move_data_get_category(env: FunctionEnvMut, move_data: ExternRef) -> u8 { + move_data.value_func_arc(&env).unwrap().category() as u8 } -fn move_data_get_base_power(env: FunctionEnvMut, move_data: ExternRef) -> u8 { - move_data.value_func(&env).unwrap().base_power() +fn move_data_get_base_power(env: FunctionEnvMut, move_data: ExternRef) -> u8 { + move_data.value_func_arc(&env).unwrap().base_power() } -fn move_data_get_accuracy(env: FunctionEnvMut, move_data: ExternRef) -> u8 { - move_data.value_func(&env).unwrap().accuracy() +fn move_data_get_accuracy(env: FunctionEnvMut, move_data: ExternRef) -> u8 { + move_data.value_func_arc(&env).unwrap().accuracy() } -fn move_data_get_base_usages(env: FunctionEnvMut, move_data: ExternRef) -> u8 { - move_data.value_func(&env).unwrap().base_usages() +fn move_data_get_base_usages(env: FunctionEnvMut, move_data: ExternRef) -> u8 { + move_data.value_func_arc(&env).unwrap().base_usages() } -fn move_data_get_target(env: FunctionEnvMut, move_data: ExternRef) -> u8 { - move_data.value_func(&env).unwrap().target() as u8 +fn move_data_get_target(env: FunctionEnvMut, move_data: ExternRef) -> u8 { + move_data.value_func_arc(&env).unwrap().target() as u8 } -fn move_data_get_priority(env: FunctionEnvMut, move_data: ExternRef) -> i8 { - move_data.value_func(&env).unwrap().priority() +fn move_data_get_priority(env: FunctionEnvMut, move_data: ExternRef) -> i8 { + move_data.value_func_arc(&env).unwrap().priority() } -fn move_data_has_flag(env: FunctionEnvMut, move_data: ExternRef, flag: ExternRef) -> u8 { - u8::from(move_data.value_func(&env).unwrap().has_flag(flag.value_func(&env).unwrap())) +fn move_data_has_flag(env: FunctionEnvMut, move_data: ExternRef, flag: ExternRef) -> u8 { + u8::from(move_data.value_func_arc(&env).unwrap().has_flag(flag.value_func(&env).unwrap())) } -fn move_data_has_flag_by_hash(env: FunctionEnvMut, move_data: ExternRef, flag_hash: u32) -> u8 { - u8::from(move_data.value_func(&env).unwrap().has_flag_by_hash(flag_hash)) +fn move_data_has_flag_by_hash(env: FunctionEnvMut, move_data: ExternRef, flag_hash: u32) -> u8 { + u8::from(move_data.value_func_arc(&env).unwrap().has_flag_by_hash(flag_hash)) } } diff --git a/src/static_data/libraries/move_library.rs b/src/static_data/libraries/move_library.rs index 3ccce46..81fa76e 100755 --- a/src/static_data/libraries/move_library.rs +++ b/src/static_data/libraries/move_library.rs @@ -13,7 +13,7 @@ pub struct MoveLibrary { /// A unique identifier so we know what value this is. identifier: ValueIdentifier, /// The underlying map. - map: IndexMap>, + map: IndexMap>, } impl MoveLibrary { @@ -26,11 +26,11 @@ impl MoveLibrary { } } -impl DataLibrary for MoveLibrary { - fn map(&self) -> &IndexMap> { +impl DataLibrary for MoveLibrary { + fn map(&self) -> &IndexMap> { &self.map } - fn get_modify(&mut self) -> &mut IndexMap> { + fn get_modify(&mut self) -> &mut IndexMap> { &mut self.map } } @@ -48,11 +48,11 @@ pub mod tests { use crate::static_data::libraries::data_library::DataLibrary; use crate::static_data::libraries::move_library::MoveLibrary; - use crate::static_data::{MoveCategory, MoveData, MoveTarget}; + use crate::static_data::{MoveCategory, MoveDataImpl, MoveTarget}; use crate::StringKey; - fn build_move() -> MoveData { - MoveData::new( + fn build_move() -> MoveDataImpl { + MoveDataImpl::new( &"foo".into(), 0.into(), MoveCategory::Physical, diff --git a/src/static_data/moves/move_data.rs b/src/static_data/moves/move_data.rs index 98b56c0..aed331f 100755 --- a/src/static_data/moves/move_data.rs +++ b/src/static_data/moves/move_data.rs @@ -1,6 +1,7 @@ use hashbrown::HashSet; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; +use std::fmt::Debug; use crate::static_data::{SecondaryEffect, TypeIdentifier}; use crate::{StringKey, ValueIdentifiable, ValueIdentifier}; @@ -59,9 +60,40 @@ pub enum MoveTarget { SelfUse, } +/// A move is the skill Pokémon primarily use in battle. This is the data related to that. +pub trait MoveData: Debug + ValueIdentifiable { + /// The name of the move. + fn name(&self) -> &StringKey; + /// The attacking type of the move. + fn move_type(&self) -> TypeIdentifier; + /// The category of the move. + fn category(&self) -> MoveCategory; + /// The base power, not considering any modifiers, the move has. + fn base_power(&self) -> u8; + /// The accuracy of the move in percentage. Should be 255 for moves that always hit. + fn accuracy(&self) -> u8; + /// The number of times the move can be used. This can be modified on actually learned moves using + /// PP-Ups + fn base_usages(&self) -> u8; + /// How the move handles targets. + fn target(&self) -> MoveTarget; + + /// The priority of the move. A higher priority means the move should go before other moves. + fn priority(&self) -> i8; + + /// The optional secondary effect the move has. + fn secondary_effect(&self) -> &Option>; + + /// Arbitrary flags that can be applied to the move. + fn has_flag(&self, key: &StringKey) -> bool; + + /// Arbitrary flags that can be applied to the move. + fn has_flag_by_hash(&self, key_hash: u32) -> bool; +} + /// A move is the skill Pokémon primarily use in battle. This is the data related to that. #[derive(Debug)] -pub struct MoveData { +pub struct MoveDataImpl { /// A unique identifier so we know what value this is. identifier: ValueIdentifier, /// The name of the move. @@ -87,7 +119,7 @@ pub struct MoveData { flags: HashSet, } -impl MoveData { +impl MoveDataImpl { /// Instantiates a new move. pub fn new( name: &StringKey, @@ -100,8 +132,8 @@ impl MoveData { priority: i8, secondary_effect: Option>, flags: HashSet, - ) -> MoveData { - MoveData { + ) -> Self { + Self { identifier: Default::default(), name: name.clone(), move_type, @@ -115,58 +147,61 @@ impl MoveData { flags, } } +} + +impl MoveData for MoveDataImpl { /// The name of the move. - pub fn name(&self) -> &StringKey { + fn name(&self) -> &StringKey { &self.name } /// The attacking type of the move. - pub fn move_type(&self) -> TypeIdentifier { + fn move_type(&self) -> TypeIdentifier { self.move_type } /// The category of the move. - pub fn category(&self) -> MoveCategory { + fn category(&self) -> MoveCategory { self.category } /// The base power, not considering any modifiers, the move has. - pub fn base_power(&self) -> u8 { + fn base_power(&self) -> u8 { self.base_power } /// The accuracy of the move in percentage. Should be 255 for moves that always hit. - pub fn accuracy(&self) -> u8 { + fn accuracy(&self) -> u8 { self.accuracy } /// The number of times the move can be used. This can be modified on actually learned moves using /// PP-Ups - pub fn base_usages(&self) -> u8 { + fn base_usages(&self) -> u8 { self.base_usages } /// How the move handles targets. - pub fn target(&self) -> MoveTarget { + fn target(&self) -> MoveTarget { self.target } /// The priority of the move. A higher priority means the move should go before other moves. - pub fn priority(&self) -> i8 { + fn priority(&self) -> i8 { self.priority } /// The optional secondary effect the move has. - pub fn secondary_effect(&self) -> &Option> { + fn secondary_effect(&self) -> &Option> { &self.secondary_effect } /// Arbitrary flags that can be applied to the move. - pub fn has_flag(&self, key: &StringKey) -> bool { + fn has_flag(&self, key: &StringKey) -> bool { self.flags.contains::(key) } /// Arbitrary flags that can be applied to the move. - pub fn has_flag_by_hash(&self, key_hash: u32) -> bool { + fn has_flag_by_hash(&self, key_hash: u32) -> bool { self.flags.contains::(&key_hash) } } -impl ValueIdentifiable for MoveData { +impl ValueIdentifiable for MoveDataImpl { fn value_identifier(&self) -> ValueIdentifier { self.identifier } diff --git a/tests/common/library_loader.rs b/tests/common/library_loader.rs index d648f2e..d711ed6 100755 --- a/tests/common/library_loader.rs +++ b/tests/common/library_loader.rs @@ -17,8 +17,9 @@ use pkmn_lib::dynamic_data::Gen7MiscLibrary; use pkmn_lib::script_implementations::wasm::script_resolver::WebAssemblyScriptResolver; use pkmn_lib::static_data::{ AbilityImpl, AbilityLibrary, BattleItemCategory, DataLibrary, EffectParameter, Form, GrowthRateLibrary, ItemImpl, - ItemLibrary, LearnableMoves, LibrarySettings, LookupGrowthRate, MoveData, MoveLibrary, NatureImpl, NatureLibrary, - SecondaryEffect, SecondaryEffectImpl, Species, StaticData, StaticStatisticSet, Statistic, TypeLibrary, + ItemLibrary, LearnableMoves, LibrarySettings, LookupGrowthRate, MoveDataImpl, MoveLibrary, NatureImpl, + NatureLibrary, SecondaryEffect, SecondaryEffectImpl, Species, StaticData, StaticStatisticSet, Statistic, + TypeLibrary, }; use pkmn_lib::StringKey; @@ -214,7 +215,7 @@ pub fn load_moves(path: &String, lib: &mut StaticData) { lib.moves_mut().add( &move_name, - Arc::new(MoveData::new( + Arc::new(MoveDataImpl::new( &move_name.clone(), move_type_id, move_category,