diff --git a/gen_7_scripts/src/lib.rs b/gen_7_scripts/src/lib.rs index 63d844a..43ece70 100755 --- a/gen_7_scripts/src/lib.rs +++ b/gen_7_scripts/src/lib.rs @@ -8,6 +8,7 @@ extern crate alloc; use alloc::boxed::Box; +#[cfg(not(test))] use pkmn_lib_interface::set_load_script_fn; #[macro_use] diff --git a/gen_7_scripts/src/moves/after_you.rs b/gen_7_scripts/src/moves/after_you.rs index 2e925c0..09ac776 100755 --- a/gen_7_scripts/src/moves/after_you.rs +++ b/gen_7_scripts/src/moves/after_you.rs @@ -39,3 +39,36 @@ impl Script for AfterYou { self } } + +#[cfg(test)] +mod tests { + use super::*; + use alloc::rc::Rc; + use pkmn_lib_interface::app_interface::{ + MockBattle, MockChoiceQueue, MockExecutingMove, MockPokemon, + }; + + #[test] + fn move_pokemon_choice_next_gets_called_once() { + let mut battle = MockBattle::new(); + battle.expect_choice_queue().once().return_once_st(move || { + let mut choice_queue = MockChoiceQueue::new(); + choice_queue + .expect_move_pokemon_choice_next() + .once() + .return_const(true); + Rc::new(choice_queue) + }); + + let battle = Rc::new(battle); + let mut target = MockPokemon::new(); + target + .expect_battle() + .once() + .return_once_st(move || Some(battle.clone())); + let target = Rc::new(target); + + let script = AfterYou::new(); + script.on_secondary_effect(Rc::new(MockExecutingMove::new()), target, 0); + } +} diff --git a/gen_7_scripts/src/moves/assurance.rs b/gen_7_scripts/src/moves/assurance.rs index 3b8b990..505a12d 100755 --- a/gen_7_scripts/src/moves/assurance.rs +++ b/gen_7_scripts/src/moves/assurance.rs @@ -3,8 +3,7 @@ use alloc::boxed::Box; use core::any::Any; use core::sync::atomic::{AtomicBool, Ordering}; use pkmn_lib_interface::app_interface::{ - BattleSide, BattleSideImpl, DamageSource, DataLibrary, ExecutingMove, Pokemon, TurnChoice, - WithVolatile, + BattleSide, DamageSource, DataLibrary, ExecutingMove, Pokemon, TurnChoice, WithVolatile, }; use pkmn_lib_interface::handling::{Script, ScriptCapabilities}; @@ -26,10 +25,9 @@ impl Script for Assurance { ] } - #[cfg(not(test))] fn on_before_turn(&self, choice: TurnChoice) { if let TurnChoice::Move(data) = &choice { - let side: BattleSideImpl = choice + let side: BattleSide = choice .user() .battle() .unwrap() @@ -90,7 +88,7 @@ impl Script for AssuranceData { #[cfg(not(test))] fn on_end_turn(&self) { - let side: BattleSideImpl = self.get_owner().unwrap(); + let side: pkmn_lib_interface::app_interface::BattleSideImpl = self.get_owner().unwrap(); side.remove_volatile(self); } diff --git a/gen_7_scripts/src/moves/aurora_veil.rs b/gen_7_scripts/src/moves/aurora_veil.rs index f1dd484..1e92247 100644 --- a/gen_7_scripts/src/moves/aurora_veil.rs +++ b/gen_7_scripts/src/moves/aurora_veil.rs @@ -6,7 +6,7 @@ use alloc::boxed::Box; use core::any::Any; use core::sync::atomic::{AtomicU32, Ordering}; use pkmn_lib_interface::app_interface::{ - BattleSide, BattleSideImpl, ExecutingMove, MoveCategory, Pokemon, WithVolatile, + BattleSide, ExecutingMove, MoveCategory, Pokemon, WithVolatile, }; use pkmn_lib_interface::handling::ScriptCapabilities::OnEndTurn; use pkmn_lib_interface::handling::{Script, ScriptCapabilities}; @@ -76,7 +76,7 @@ impl Script for AuroraVeilEffect { if mv.get_hit_data(&target, hit).is_critical() { return; } - let side: BattleSideImpl = self.get_owner().unwrap(); + let side: pkmn_lib_interface::app_interface::BattleSideImpl = self.get_owner().unwrap(); if side.has_volatile(ReflectEffect::get_const_name()) && mv.use_move().category() == MoveCategory::Physical { diff --git a/gen_7_scripts/src/moves/change_all_target_stats.rs b/gen_7_scripts/src/moves/change_all_target_stats.rs index 9212d08..b543008 100644 --- a/gen_7_scripts/src/moves/change_all_target_stats.rs +++ b/gen_7_scripts/src/moves/change_all_target_stats.rs @@ -1,7 +1,8 @@ use crate::script; +use alloc::rc::Rc; use core::any::Any; use core::sync::atomic::{AtomicI8, Ordering}; -use pkmn_lib_interface::app_interface::list::ImmutableList; +use pkmn_lib_interface::app_interface::list::{ImmutableList, ImmutableListTrait}; use pkmn_lib_interface::app_interface::{ DynamicLibrary, EffectParameter, ExecutingMove, Pokemon, Statistic, }; @@ -34,7 +35,7 @@ impl Script for ChangeAllTargetStats { fn on_initialize( &self, _library: &DynamicLibrary, - parameters: Option>, + parameters: Option>>, ) { self.amount.store( parameters.unwrap().get(0).unwrap().as_int() as i8, diff --git a/gen_7_scripts/src/moves/change_target_stats.rs b/gen_7_scripts/src/moves/change_target_stats.rs index 970341e..d6281ff 100644 --- a/gen_7_scripts/src/moves/change_target_stats.rs +++ b/gen_7_scripts/src/moves/change_target_stats.rs @@ -1,3 +1,4 @@ +use alloc::rc::Rc; use core::any::Any; use core::sync::atomic::{AtomicI8, Ordering}; use pkmn_lib_interface::app_interface::list::ImmutableList; @@ -42,7 +43,7 @@ macro_rules! change_stat_effect { fn on_initialize( &self, _library: &DynamicLibrary, - parameters: Option>, + parameters: Option>>, ) { self.amount.store( parameters.unwrap().get(0).unwrap().as_int() as i8, diff --git a/gen_7_scripts/src/moves/drain.rs b/gen_7_scripts/src/moves/drain.rs index 1571d34..2847fef 100644 --- a/gen_7_scripts/src/moves/drain.rs +++ b/gen_7_scripts/src/moves/drain.rs @@ -1,8 +1,9 @@ use crate::script; +use alloc::rc::Rc; use atomic_float::AtomicF32; use core::any::Any; use core::sync::atomic::Ordering; -use pkmn_lib_interface::app_interface::list::ImmutableList; +use pkmn_lib_interface::app_interface::list::{ImmutableList, ImmutableListTrait}; use pkmn_lib_interface::app_interface::{DynamicLibrary, EffectParameter, ExecutingMove, Pokemon}; use pkmn_lib_interface::handling::{Script, ScriptCapabilities}; @@ -29,7 +30,7 @@ impl Script for Drain { fn on_initialize( &self, _library: &DynamicLibrary, - parameters: Option>, + parameters: Option>>, ) { self.heal_modifier.store( parameters.unwrap().get(0).unwrap().as_float(), diff --git a/pkmn_lib_interface/src/app_interface/dynamic_data/battle.rs b/pkmn_lib_interface/src/app_interface/dynamic_data/battle.rs index f0112cf..817450f 100755 --- a/pkmn_lib_interface/src/app_interface/dynamic_data/battle.rs +++ b/pkmn_lib_interface/src/app_interface/dynamic_data/battle.rs @@ -1,16 +1,16 @@ use alloc::rc::Rc; use crate::app_interface::list::ImmutableList; -use crate::app_interface::BattleSideImpl; use crate::app_interface::{ - BattleParty, BattlePartyImpl, BattleRandom, ChoiceQueue, DynamicLibrary, Pokemon, StringKey, + BattleParty, BattlePartyImpl, BattleRandom, BattleSide, ChoiceQueue, DynamicLibrary, Pokemon, + StringKey, }; #[cfg_attr(feature = "mock_data", mockall::automock)] pub trait BattleTrait { fn library(&self) -> DynamicLibrary; - fn parties(&self) -> ImmutableList; - fn sides(&self) -> ImmutableList; + fn parties(&self) -> ImmutableList; + fn sides(&self) -> ImmutableList; fn random(&self) -> BattleRandom; fn choice_queue(&self) -> ChoiceQueue; fn get_pokemon(&self, side: u8, index: u8) -> Option; @@ -33,6 +33,9 @@ pub type MockBattle = MockBattleTrait; #[cfg(not(feature = "mock_data"))] mod implementation { use super::*; + use crate::app_interface::list::{ + BattlePartyImmutableList, BattleSideImmutableList, ImmutableListWasm, + }; use crate::app_interface::PokemonImpl; use crate::app_interface::{ BattleParty, BattlePartyImpl, BattleRandom, BattleRandomImpl, BattleSide, BattleSideImpl, @@ -42,15 +45,14 @@ mod implementation { use crate::handling::Cacheable; use crate::{ cached_value, cached_value_getters, wasm_value_getters, wasm_value_getters_extern, - wasm_value_getters_funcs, DynamicLibrary, ExternRef, ExternalReferenceType, ImmutableList, - StringKey, VecExternRef, + wasm_value_getters_funcs, ExternRef, ExternalReferenceType, StringKey, VecExternRef, }; struct BattleInner { reference: ExternRef, library: CachedValue, - parties: CachedValue>, - sides: CachedValue>, + parties: CachedValue>, + sides: CachedValue>, random: CachedValue>, choice_queue: CachedValue>, } @@ -67,8 +69,14 @@ mod implementation { inner: Rc::new(BattleInner { reference, library: cached_value!({ battle_get_library(reference).get_value().unwrap() }), - parties: cached_value!({ battle_get_parties(reference).get_immutable_list() }), - sides: cached_value!({ battle_get_sides(reference).get_immutable_list() }), + parties: cached_value!({ + let reference = battle_get_parties(reference); + Rc::new(BattlePartyImmutableList::from_ref(reference)) + }), + sides: cached_value!({ + let reference = battle_get_sides(reference); + Rc::new(BattleSideImmutableList::from_ref(reference)) + }), random: cached_value!({ Rc::new(battle_get_random(reference).get_value().unwrap()) }), @@ -84,8 +92,8 @@ mod implementation { impl BattleTrait for BattleImpl { cached_value_getters! { fn library(&self) -> DynamicLibrary; - fn parties(&self) -> ImmutableList; - fn sides(&self) -> ImmutableList; + fn parties(&self) -> ImmutableList; + fn sides(&self) -> ImmutableList; fn random(&self) -> BattleRandom; fn choice_queue(&self) -> ChoiceQueue; } diff --git a/pkmn_lib_interface/src/app_interface/dynamic_data/battle_side.rs b/pkmn_lib_interface/src/app_interface/dynamic_data/battle_side.rs index a0a8b53..1ef1692 100755 --- a/pkmn_lib_interface/src/app_interface/dynamic_data/battle_side.rs +++ b/pkmn_lib_interface/src/app_interface/dynamic_data/battle_side.rs @@ -1,15 +1,5 @@ use crate::app_interface::{Battle, Pokemon, WithVolatile}; -#[cfg(not(feature = "mock_data"))] -use crate::app_interface::{BattleImpl, PokemonImpl}; -use crate::handling::cacheable::Cacheable; -use crate::handling::cached_value::CachedValue; -use crate::{ - cached_value, cached_value_getters, wasm_value_getters, wasm_value_getters_extern, - wasm_value_getters_funcs, ExternRef, ExternalReferenceType, Script, ScriptPtr, -}; -use alloc::boxed::Box; use alloc::rc::Rc; -use cstr_core::{c_char, CString}; pub trait BattleSideTrait: WithVolatile { fn side_index(&self) -> u8; @@ -23,128 +13,141 @@ pub trait BattleSideTrait: WithVolatile { pub type BattleSide = Rc; #[cfg(not(feature = "mock_data"))] -struct BattleSideInner { - reference: ExternRef, - side_index: CachedValue, - pokemon_per_side: CachedValue, - battle: CachedValue>, -} +mod implementation { + use super::*; + use crate::app_interface::{BattleImpl, PokemonImpl}; + use crate::handling::cached_value::CachedValue; + use crate::handling::extern_ref::{ExternRef, ExternalReferenceType}; + use crate::handling::{Cacheable, Script}; + use crate::{ + cached_value, cached_value_getters, wasm_value_getters_extern, wasm_value_getters_funcs, + ScriptPtr, + }; + use alloc::boxed::Box; + use cstr_core::{c_char, CString}; -#[derive(Clone)] -pub struct BattleSideImpl { - #[cfg(not(feature = "mock_data"))] - inner: Rc, -} + struct BattleSideInner { + reference: ExternRef, + side_index: CachedValue, + pokemon_per_side: CachedValue, + battle: CachedValue>, + } -#[cfg(not(feature = "mock_data"))] -impl BattleSideImpl { - pub fn new(reference: ExternRef) -> Self { - Self::from_ref(reference, &|reference| Self { - inner: Rc::new(BattleSideInner { - reference, - side_index: cached_value!({ battleside_get_side_index(reference) }), - pokemon_per_side: cached_value!({ battleside_get_pokemon_per_side(reference) }), - battle: cached_value!({ - Rc::new(battleside_get_battle(reference).get_value().unwrap()) + #[derive(Clone)] + pub struct BattleSideImpl { + inner: Rc, + } + + impl BattleSideImpl { + pub fn new(reference: ExternRef) -> Self { + Self::from_ref(reference, &|reference| Self { + inner: Rc::new(BattleSideInner { + reference, + side_index: cached_value!({ battleside_get_side_index(reference) }), + pokemon_per_side: cached_value!({ battleside_get_pokemon_per_side(reference) }), + battle: cached_value!({ + Rc::new(battleside_get_battle(reference).get_value().unwrap()) + }), }), - }), - }) - } -} - -#[cfg(not(feature = "mock_data"))] -impl BattleSideTrait for BattleSideImpl { - cached_value_getters! { - fn side_index(&self) -> u8; - fn pokemon_per_side(&self) -> u8; - fn battle(&self) -> Battle; + }) + } } - fn get_pokemon(&self, index: usize) -> Option { - unsafe { - let p = battleside_get_pokemon(self.inner.reference, index).get_value(); - if let Some(p) = p { - Some(Rc::new(p)) - } else { - None + impl BattleSideTrait for BattleSideImpl { + cached_value_getters! { + fn side_index(&self) -> u8; + fn pokemon_per_side(&self) -> u8; + fn battle(&self) -> Battle; + } + + fn get_pokemon(&self, index: usize) -> Option { + unsafe { + let p = battleside_get_pokemon(self.inner.reference, index).get_value(); + if let Some(p) = p { + Some(Rc::new(p)) + } else { + None + } } } + + wasm_value_getters_funcs! { + BattleSide, + fn has_fled_battle(&self) -> bool; + fn is_defeated(&self) -> bool; + } } - wasm_value_getters_funcs! { - BattleSide, - fn has_fled_battle(&self) -> bool; - fn is_defeated(&self) -> bool; - } -} + impl WithVolatile for BattleSideImpl { + fn has_volatile(&self, script_name: &str) -> bool { + unsafe { + let script_name = CString::new(script_name).unwrap(); + battleside_has_volatile(self.inner.reference, script_name.as_ptr()) + } + } + fn add_volatile(&self, script: Box) -> &dyn Script { + unsafe { + battleside_add_volatile(self.inner.reference, ScriptPtr::new(script)) + .val() + .unwrap() + } + } -#[cfg(not(feature = "mock_data"))] -impl WithVolatile for BattleSideImpl { - fn has_volatile(&self, script_name: &str) -> bool { - unsafe { + fn add_volatile_by_name(&self, script_name: &str) -> &dyn Script { + unsafe { + let ptr = CString::new(script_name).unwrap(); + battleside_add_volatile_by_name(self.inner.reference, ptr.as_ptr()) + .val() + .unwrap() + } + } + + fn remove_volatile(&self, script: &dyn Script) { + unsafe { + let name = CString::new(script.get_name()).unwrap(); + battleside_remove_volatile(self.inner.reference, name.as_ptr()); + } + } + + fn get_volatile_script(&self, script_name: &str) -> Option<&dyn Script> { let script_name = CString::new(script_name).unwrap(); - battleside_has_volatile(self.inner.reference, script_name.as_ptr()) - } - } - fn add_volatile(&self, script: Box) -> &dyn Script { - unsafe { - battleside_add_volatile(self.inner.reference, ScriptPtr::new(script)) - .val() - .unwrap() + unsafe { battleside_get_volatile(self.inner.reference, script_name.as_ptr()).val() } } } - fn add_volatile_by_name(&self, script_name: &str) -> &dyn Script { - unsafe { - let ptr = CString::new(script_name).unwrap(); - battleside_add_volatile_by_name(self.inner.reference, ptr.as_ptr()) - .val() - .unwrap() + wasm_value_getters_extern! { + BattleSideImpl, BattleSide, + pub fn has_fled_battle(&self) -> bool; + pub fn is_defeated(&self) -> bool; + } + + crate::handling::cacheable::cacheable!(BattleSideImpl); + + impl ExternalReferenceType for BattleSideImpl { + fn from_extern_value(reference: ExternRef) -> Self { + Self::new(reference) } } - fn remove_volatile(&self, script: &dyn Script) { - unsafe { - let name = CString::new(script.get_name()).unwrap(); - battleside_remove_volatile(self.inner.reference, name.as_ptr()); - } - } + extern "wasm" { + fn battleside_get_side_index(r: ExternRef) -> u8; + fn battleside_get_pokemon_per_side(r: ExternRef) -> u8; + fn battleside_get_battle(r: ExternRef) -> ExternRef; + fn battleside_get_pokemon( + r: ExternRef, + index: usize, + ) -> ExternRef; - fn get_volatile_script(&self, script_name: &str) -> Option<&dyn Script> { - let script_name = CString::new(script_name).unwrap(); - unsafe { battleside_get_volatile(self.inner.reference, script_name.as_ptr()).val() } - } -} - -wasm_value_getters_extern! { - BattleSideImpl, BattleSide, - pub fn has_fled_battle(&self) -> bool; - pub fn is_defeated(&self) -> bool; -} - -crate::handling::cacheable::cacheable!(BattleSideImpl); - -#[cfg(not(feature = "mock_data"))] -impl ExternalReferenceType for BattleSideImpl { - fn from_extern_value(reference: ExternRef) -> Self { - Self::new(reference) + fn battleside_add_volatile_by_name( + r: ExternRef, + name: *const c_char, + ) -> ScriptPtr; + fn battleside_add_volatile(r: ExternRef, script: ScriptPtr) -> ScriptPtr; + fn battleside_has_volatile(r: ExternRef, name: *const c_char) -> bool; + fn battleside_remove_volatile(r: ExternRef, name: *const c_char); + fn battleside_get_volatile(r: ExternRef, name: *const c_char) -> ScriptPtr; } } #[cfg(not(feature = "mock_data"))] -extern "wasm" { - fn battleside_get_side_index(r: ExternRef) -> u8; - fn battleside_get_pokemon_per_side(r: ExternRef) -> u8; - fn battleside_get_battle(r: ExternRef) -> ExternRef; - fn battleside_get_pokemon(r: ExternRef, index: usize) - -> ExternRef; - - fn battleside_add_volatile_by_name( - r: ExternRef, - name: *const c_char, - ) -> ScriptPtr; - fn battleside_add_volatile(r: ExternRef, script: ScriptPtr) -> ScriptPtr; - fn battleside_has_volatile(r: ExternRef, name: *const c_char) -> bool; - fn battleside_remove_volatile(r: ExternRef, name: *const c_char); - fn battleside_get_volatile(r: ExternRef, name: *const c_char) -> ScriptPtr; -} +pub use implementation::*; diff --git a/pkmn_lib_interface/src/app_interface/dynamic_data/choice_queue.rs b/pkmn_lib_interface/src/app_interface/dynamic_data/choice_queue.rs index ddf2061..efecfd5 100755 --- a/pkmn_lib_interface/src/app_interface/dynamic_data/choice_queue.rs +++ b/pkmn_lib_interface/src/app_interface/dynamic_data/choice_queue.rs @@ -1,44 +1,53 @@ -#[cfg(not(feature = "mock_data"))] -use crate::app_interface::PokemonImpl; -use crate::{ExternRef, ExternalReferenceType, Pokemon}; +use crate::app_interface::Pokemon; use alloc::rc::Rc; +#[cfg_attr(feature = "mock_data", mockall::automock)] pub trait ChoiceQueueTrait { fn move_pokemon_choice_next(&self, pokemon: &Pokemon) -> bool; } pub type ChoiceQueue = Rc; - -#[derive(Clone)] -pub struct ChoiceQueueImpl { - reference: ExternRef, -} +#[cfg(feature = "mock_data")] +pub type MockChoiceQueue = MockChoiceQueueTrait; #[cfg(not(feature = "mock_data"))] -impl ChoiceQueueImpl { - pub fn new(reference: ExternRef) -> Self { - Self { reference } +mod implementation { + use super::*; + use crate::app_interface::PokemonImpl; + use crate::{ExternRef, ExternalReferenceType}; + + #[derive(Clone)] + pub struct ChoiceQueueImpl { + reference: ExternRef, + } + + impl ChoiceQueueImpl { + pub fn new(reference: ExternRef) -> Self { + Self { reference } + } + } + + impl ChoiceQueueTrait for ChoiceQueueImpl { + fn move_pokemon_choice_next(&self, pokemon: &Pokemon) -> bool { + unsafe { + choice_queue_move_pokemon_choice_next(self.reference, pokemon.reference().into()) + } + } + } + + impl ExternalReferenceType for ChoiceQueueImpl { + fn from_extern_value(reference: ExternRef) -> Self { + Self::new(reference) + } + } + + extern "wasm" { + fn choice_queue_move_pokemon_choice_next( + r: ExternRef, + pokemon: ExternRef, + ) -> bool; } } #[cfg(not(feature = "mock_data"))] -impl ChoiceQueueTrait for ChoiceQueueImpl { - fn move_pokemon_choice_next(&self, pokemon: &Pokemon) -> bool { - unsafe { choice_queue_move_pokemon_choice_next(self.reference, pokemon.reference().into()) } - } -} - -#[cfg(not(feature = "mock_data"))] -impl ExternalReferenceType for ChoiceQueueImpl { - fn from_extern_value(reference: ExternRef) -> Self { - Self::new(reference) - } -} - -#[cfg(not(feature = "mock_data"))] -extern "wasm" { - fn choice_queue_move_pokemon_choice_next( - r: ExternRef, - pokemon: ExternRef, - ) -> bool; -} +pub use implementation::*; diff --git a/pkmn_lib_interface/src/app_interface/dynamic_data/pokemon.rs b/pkmn_lib_interface/src/app_interface/dynamic_data/pokemon.rs index 8fe2586..68de0bd 100755 --- a/pkmn_lib_interface/src/app_interface/dynamic_data/pokemon.rs +++ b/pkmn_lib_interface/src/app_interface/dynamic_data/pokemon.rs @@ -1,6 +1,6 @@ use crate::app_interface::{ - AbilityImpl, AbilityIndex, Battle, BattleSide, ClampedStatisticSet, DynamicLibrary, Form, - Gender, Item, LearnedMove, LevelInt, Nature, Species, Statistic, StatisticSet, TypeIdentifier, + Ability, AbilityIndex, Battle, BattleSide, ClampedStatisticSet, DynamicLibrary, Form, Gender, + Item, LearnedMove, LevelInt, Nature, Species, Statistic, StatisticSet, TypeIdentifier, WithVolatile, }; use crate::handling::Script; @@ -16,7 +16,7 @@ pub trait PokemonTrait: WithVolatile { fn species(&self) -> Species; fn form(&self) -> Form; - fn active_ability(&self) -> AbilityImpl; + fn active_ability(&self) -> Ability; fn nature(&self) -> Nature; fn display_species(&self) -> Option; fn display_form(&self) -> Option
; @@ -86,14 +86,15 @@ mod implementation { use super::*; use cstr_core::CString; - use crate::app_interface::{BattleImpl, ItemImpl, StatisticSetImpl}; + use crate::app_interface::{AbilityImpl, BattleImpl, ItemImpl, StatisticSetImpl}; use crate::handling::cached_value::CachedValue; use crate::handling::Cacheable; + use crate::implementation::ScriptPtr; use crate::{ cached_value, cached_value_getters, wasm_optional_reference_getters_extern, wasm_optional_reference_getters_funcs, wasm_reference_getters_extern, wasm_reference_getters_funcs, wasm_value_getters_extern, wasm_value_getters_funcs, - DynamicLibrary, ExternRef, ExternalReferenceType, Script, ScriptPtr, TypeIdentifier, + ExternRef, ExternalReferenceType, Script, }; struct PokemonInner { @@ -234,23 +235,29 @@ mod implementation { } } fn battle_side(&self) -> BattleSide { - Rc::new( - self.battle() - .unwrap() - .sides() - .get(self.battle_side_index() as u32) - .unwrap(), - ) + self.battle() + .unwrap() + .sides() + .get(self.battle_side_index() as u32) + .unwrap() } wasm_reference_getters_funcs! { Pokemon, fn species(&self) -> Species; fn form(&self) -> Form; - fn active_ability(&self) -> AbilityImpl; fn nature(&self) -> Nature; } + fn active_ability(&self) -> Ability { + unsafe { + let implementation = pokemon_get_active_ability(self.reference()) + .get_value() + .unwrap(); + Rc::new(implementation) + } + } + wasm_optional_reference_getters_funcs! { Pokemon, fn display_species(&self) -> Option; @@ -338,7 +345,6 @@ mod implementation { } } - #[cfg(not(feature = "mock_data"))] impl PokemonImpl { pub(crate) fn new(reference: ExternRef) -> Self { Self::from_ref(reference, &|reference| Self { @@ -371,7 +377,6 @@ mod implementation { } } - #[cfg(not(feature = "mock_data"))] wasm_reference_getters_extern! { PokemonImpl, Pokemon, pub fn species(&self) -> Species; @@ -380,7 +385,6 @@ mod implementation { pub fn nature(&self) -> Nature; } - #[cfg(not(feature = "mock_data"))] wasm_optional_reference_getters_extern! { PokemonImpl, Pokemon, pub fn display_species(&self) -> Option; @@ -389,7 +393,6 @@ mod implementation { pub fn battle(&self) -> Option; } - #[cfg(not(feature = "mock_data"))] wasm_value_getters_extern! { PokemonImpl, Pokemon, pub fn level(&self) -> LevelInt; @@ -418,14 +421,12 @@ mod implementation { crate::handling::cacheable::cacheable!(PokemonImpl); - #[cfg(not(feature = "mock_data"))] impl ExternalReferenceType for PokemonImpl { fn from_extern_value(reference: ExternRef) -> Self { Self::new(reference) } } - #[cfg(not(feature = "mock_data"))] extern "wasm" { fn pokemon_get_library(r: ExternRef) -> ExternRef; fn pokemon_get_flat_stats(r: ExternRef) -> ExternRef>; @@ -489,7 +490,7 @@ mockall::mock!( fn reference(&self) -> u32; fn species(&self) -> Species; fn form(&self) -> Form; - fn active_ability(&self) -> AbilityImpl; + fn active_ability(&self) -> Ability; fn nature(&self) -> Nature; fn display_species(&self) -> Option; fn display_form(&self) -> Option; diff --git a/pkmn_lib_interface/src/app_interface/list.rs b/pkmn_lib_interface/src/app_interface/list.rs index ec6d055..48c1848 100755 --- a/pkmn_lib_interface/src/app_interface/list.rs +++ b/pkmn_lib_interface/src/app_interface/list.rs @@ -1,114 +1,205 @@ use crate::{ExternalReferenceType, VecExternRef}; -use alloc::boxed::Box; -#[cfg(feature = "mock_data")] use alloc::rc::Rc; -use alloc::vec::Vec; -use core::marker::PhantomData; -#[cfg(not(feature = "mock_data"))] -struct ImmutableListInner { - extern_ref: VecExternRef, - resource_type: PhantomData, - values: spin::RwLock>>>, +pub trait ImmutableListTrait { + fn get(&self, index: u32) -> Option; } -#[derive(Clone)] -#[cfg(not(feature = "mock_data"))] -pub struct ImmutableList -where - T: Clone, - T: ExternalReferenceType, -{ - inner: *const ImmutableListInner, -} +pub type ImmutableList = Rc>; #[cfg(not(feature = "mock_data"))] -impl ImmutableList -where - T: Clone, - T: ExternalReferenceType, -{ - fn new(extern_ref: VecExternRef) -> Self { - let mut values = Vec::new(); - values.resize(extern_ref.len() as usize, None); - let inner = Box::new(ImmutableListInner { - extern_ref, - resource_type: Default::default(), - values: spin::RwLock::new(values), - }); - let inner_ptr = Box::into_raw(inner); - ImmutableList { - inner: inner_ptr as *const ImmutableListInner, - } +mod implementation { + use super::*; + use crate::app_interface::{ + BattleParty, BattlePartyImpl, BattleSide, BattleSideImpl, EffectParameter, StringKey, + }; + use crate::handling::extern_ref::{ExternalReferenceType, VecExternRef}; + use alloc::boxed::Box; + use alloc::vec::Vec; + use core::marker::PhantomData; + + pub(crate) struct ImmutableListInner { + extern_ref: VecExternRef, + resource_type: PhantomData, + values: spin::RwLock>>>>, } - pub(crate) fn from_ref(extern_ref: VecExternRef) -> Self { - unsafe { - if let None = CACHE { - CACHE = Some(hashbrown::HashMap::new()); - } - let existing = CACHE - .as_ref() - .unwrap() - .get(&extern_ref.get_internal_index()); - if let Some(v) = existing { - let inner = *v as *const ImmutableListInner; - ImmutableList { inner } - } else { - let v = Self::new(extern_ref); - CACHE - .as_mut() + pub(crate) trait ImmutableListWasm { + fn initialize(inner: *const ImmutableListInner) -> Self + where + Self: Sized; + + fn new(extern_ref: VecExternRef) -> Self + where + Self: Sized, + { + let mut values = Vec::new(); + values.resize(extern_ref.len() as usize, None); + let inner = Box::new(ImmutableListInner { + extern_ref, + resource_type: Default::default(), + values: spin::RwLock::new(values), + }); + let inner_ptr = Box::into_raw(inner); + Self::initialize(inner_ptr) + } + + fn from_ref(extern_ref: VecExternRef) -> Self + where + Self: Sized, + { + unsafe { + if let None = CACHE { + CACHE = Some(hashbrown::HashMap::new()); + } + let existing = CACHE + .as_ref() .unwrap() - .insert(extern_ref.get_internal_index(), v.inner as *const u8); - v - } - } - } - - pub fn get(&self, index: u32) -> Option { - unsafe { - let inner = self.inner.as_ref().unwrap(); - { - let rg = inner.values.read(); - let v = rg.get(index as usize).unwrap(); - if let Some(v) = v { - return v.clone(); + .get(&extern_ref.get_internal_index()); + if let Some(v) = existing { + let inner = *v as *const ImmutableListInner; + Self::initialize(inner) + } else { + let v = Self::new(extern_ref); + CACHE.as_mut().unwrap().insert( + extern_ref.get_internal_index(), + v.get_inner_ptr() as *const u8, + ); + v } } + } + + fn get_inner(&self) -> &ImmutableListInner { + unsafe { self.get_inner_ptr().as_ref().unwrap() } + } + fn get_inner_ptr(&self) -> *const ImmutableListInner; + + fn get_cached(&self, index: u32) -> Option> { + let inner = self.get_inner(); + let rg = inner.values.read(); + let v = rg.get(index as usize).unwrap(); + if let Some(v) = v { + return v.clone(); + } + return None; + } + + fn get_value(&self, index: u32) -> Option> { + if let Some(cached) = self.get_cached(index) { + return Some(cached); + } + let inner = self.get_inner(); let r = inner.extern_ref.at(index); let value = r.get_value(); + let value = if let Some(value) = value { + Some(Rc::new(value)) + } else { + None + }; let mut wg = inner.values.write(); wg[index as usize] = Some(value); - wg[index as usize].as_ref().unwrap().clone() - } - } -} - -#[cfg(feature = "mock_data")] -pub struct ImmutableListInner { - values: Vec, -} - -#[cfg(feature = "mock_data")] -#[derive(Clone)] -pub struct ImmutableList { - inner: Rc>, -} - -#[cfg(feature = "mock_data")] -impl ImmutableList -where - T: Clone, -{ - pub fn mock(values: Vec) -> Self { - Self { - inner: Rc::new(ImmutableListInner { values }), + let v = wg[index as usize].as_ref().unwrap().clone(); + v } } - pub fn get(&self, index: u32) -> Option { - self.inner.values.get(index as usize).cloned() + macro_rules! immutable_list_type { + ($type_name:ident, $underlying:ident) => { + paste::paste! { + pub struct [<$type_name ImmutableList>] { + inner: *const ImmutableListInner<$underlying>, + } + + impl ImmutableListWasm<$underlying> for [<$type_name ImmutableList>] { + fn initialize(inner: *const ImmutableListInner<$underlying>) -> Self + where + Self: Sized, + { + Self { inner } + } + + fn get_inner_ptr(&self) -> *const ImmutableListInner<$underlying> { + self.inner + } + } + + impl ImmutableListTrait<$type_name> for [<$type_name ImmutableList>] { + fn get(&self, index: u32) -> Option<$type_name> { + let v = self.get_value(index); + if let Some(v) = v { + Some(v) + } else { + None + } + } + } + } + }; } + + immutable_list_type!(BattleSide, BattleSideImpl); + immutable_list_type!(BattleParty, BattlePartyImpl); + + pub struct EffectParameterImmutableList { + inner: *const ImmutableListInner, + } + + impl ImmutableListWasm for EffectParameterImmutableList { + fn initialize(inner: *const ImmutableListInner) -> Self + where + Self: Sized, + { + Self { inner } + } + + fn get_inner_ptr(&self) -> *const ImmutableListInner { + self.inner + } + } + + impl ImmutableListTrait> for EffectParameterImmutableList { + fn get(&self, index: u32) -> Option> { + let v = self.get_value(index); + if let Some(v) = v { + Some(v) + } else { + None + } + } + } + + #[derive(Clone)] + pub struct StringKeyImmutableList { + inner: *const ImmutableListInner, + } + + impl ImmutableListWasm for StringKeyImmutableList { + fn initialize(inner: *const ImmutableListInner) -> Self + where + Self: Sized, + { + Self { inner } + } + + fn get_inner_ptr(&self) -> *const ImmutableListInner { + self.inner + } + } + + impl ImmutableListTrait> for StringKeyImmutableList { + fn get(&self, index: u32) -> Option> { + let v = self.get_value(index); + if let Some(v) = v { + Some(v) + } else { + None + } + } + } + + static mut CACHE: Option> = None; } -static mut CACHE: Option> = None; +#[cfg(not(feature = "mock_data"))] +pub use implementation::*; diff --git a/pkmn_lib_interface/src/app_interface/static_data/ability.rs b/pkmn_lib_interface/src/app_interface/static_data/ability.rs index 2833996..e0871c8 100755 --- a/pkmn_lib_interface/src/app_interface/static_data/ability.rs +++ b/pkmn_lib_interface/src/app_interface/static_data/ability.rs @@ -1,60 +1,13 @@ -use crate::handling::cacheable::Cacheable; -use crate::handling::cached_value::CachedValue; -use crate::{ - cached_value, cached_value_getters, EffectParameter, ExternRef, ExternalReferenceType, - ImmutableList, StringKey, VecExternRef, -}; +use crate::StringKey; use alloc::rc::Rc; -struct AbilityInner { - reference: ExternRef, - name: CachedValue, - effect: CachedValue, - parameters: CachedValue>, -} - #[cfg_attr(test, mockall::automock)] -pub trait Ability { +pub trait AbilityTrait { fn name(&self) -> StringKey; fn effect(&self) -> StringKey; } -#[derive(Clone)] -pub struct AbilityImpl { - inner: Rc, -} - -impl AbilityImpl { - #[cfg(not(feature = "mock_data"))] - pub fn new(reference: ExternRef) -> Self { - Self::from_ref(reference, &|reference| Self { - inner: Rc::new(AbilityInner { - reference, - name: cached_value!({ ability_get_name(reference).get_value().unwrap() }), - effect: cached_value!({ ability_get_effect(reference).get_value().unwrap() }), - parameters: cached_value!({ - ability_get_parameters(reference).get_immutable_list() - }), - }), - }) - } -} - -impl Ability for AbilityImpl { - cached_value_getters! { - fn name(&self) -> StringKey; - fn effect(&self) -> StringKey; - } -} - -#[cfg(not(feature = "mock_data"))] -impl ExternalReferenceType for AbilityImpl { - fn from_extern_value(reference: ExternRef) -> Self { - Self::new(reference) - } -} - -crate::handling::cacheable::cacheable!(AbilityImpl); +pub type Ability = Rc; #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[repr(C)] @@ -64,8 +17,71 @@ pub struct AbilityIndex { } #[cfg(not(feature = "mock_data"))] -extern "wasm" { - fn ability_get_name(r: ExternRef) -> ExternRef; - fn ability_get_effect(r: ExternRef) -> ExternRef; - fn ability_get_parameters(r: ExternRef) -> VecExternRef; +mod implementation { + use super::*; + use crate::app_interface::list::{ + EffectParameterImmutableList, ImmutableList, ImmutableListWasm, + }; + use crate::app_interface::{EffectParameter, StringKey}; + use crate::handling::cached_value::CachedValue; + use crate::handling::extern_ref::{ExternRef, ExternalReferenceType, VecExternRef}; + use crate::handling::Cacheable; + use crate::{cached_value, cached_value_getters}; + use alloc::rc::Rc; + + struct AbilityInner { + reference: ExternRef, + name: CachedValue, + effect: CachedValue, + parameters: CachedValue>>, + } + + #[derive(Clone)] + pub struct AbilityImpl { + inner: Rc, + } + + impl AbilityImpl { + #[cfg(not(feature = "mock_data"))] + pub fn new(reference: ExternRef) -> Self { + Self::from_ref(reference, &|reference| Self { + inner: Rc::new(AbilityInner { + reference, + name: cached_value!({ ability_get_name(reference).get_value().unwrap() }), + effect: cached_value!({ ability_get_effect(reference).get_value().unwrap() }), + parameters: cached_value!({ + Rc::new(EffectParameterImmutableList::from_ref( + ability_get_parameters(reference), + )) + }), + }), + }) + } + } + + impl AbilityTrait for AbilityImpl { + cached_value_getters! { + fn name(&self) -> StringKey; + fn effect(&self) -> StringKey; + } + } + + #[cfg(not(feature = "mock_data"))] + impl ExternalReferenceType for AbilityImpl { + fn from_extern_value(reference: ExternRef) -> Self { + Self::new(reference) + } + } + + crate::handling::cacheable::cacheable!(AbilityImpl); + + #[cfg(not(feature = "mock_data"))] + extern "wasm" { + fn ability_get_name(r: ExternRef) -> ExternRef; + fn ability_get_effect(r: ExternRef) -> ExternRef; + fn ability_get_parameters(r: ExternRef) -> VecExternRef; + } } + +#[cfg(not(feature = "mock_data"))] +pub use implementation::*; diff --git a/pkmn_lib_interface/src/app_interface/static_data/data_libraries/type_library.rs b/pkmn_lib_interface/src/app_interface/static_data/data_libraries/type_library.rs index 271af21..5d328fe 100755 --- a/pkmn_lib_interface/src/app_interface/static_data/data_libraries/type_library.rs +++ b/pkmn_lib_interface/src/app_interface/static_data/data_libraries/type_library.rs @@ -1,4 +1,5 @@ -use crate::{ExternRef, ExternalReferenceType, TypeIdentifier}; +use crate::app_interface::TypeIdentifier; +use crate::{ExternRef, ExternalReferenceType}; use alloc::rc::Rc; use alloc::string::{String, ToString}; use cstr_core::{c_char, CString}; diff --git a/pkmn_lib_interface/src/app_interface/static_data/effect_parameter.rs b/pkmn_lib_interface/src/app_interface/static_data/effect_parameter.rs index 7411375..616e391 100755 --- a/pkmn_lib_interface/src/app_interface/static_data/effect_parameter.rs +++ b/pkmn_lib_interface/src/app_interface/static_data/effect_parameter.rs @@ -35,7 +35,7 @@ impl EffectParameter { } } } - + pub fn as_bool(&self) -> bool { if let EffectParameter::Bool(b) = self { return *b; @@ -63,7 +63,6 @@ impl EffectParameter { } panic!("Unexpected effect parameter type: {}", self); } - } #[cfg(not(feature = "mock_data"))] diff --git a/pkmn_lib_interface/src/app_interface/static_data/species.rs b/pkmn_lib_interface/src/app_interface/static_data/species.rs index 62985b3..2ff4399 100755 --- a/pkmn_lib_interface/src/app_interface/static_data/species.rs +++ b/pkmn_lib_interface/src/app_interface/static_data/species.rs @@ -1,9 +1,12 @@ use crate::app_interface::get_hash; +use crate::app_interface::list::ImmutableList; +#[cfg(not(feature = "mock_data"))] +use crate::app_interface::list::ImmutableListWasm; use crate::handling::cached_value::CachedValue; +use crate::handling::ffi_array::FFIArray; use crate::handling::Cacheable; use crate::{ - cached_value, cached_value_getters, ExternRef, ExternalReferenceType, FFIArray, ImmutableList, - StringKey, VecExternRef, + cached_value, cached_value_getters, ExternRef, ExternalReferenceType, StringKey, VecExternRef, }; use alloc::rc::Rc; use alloc::vec::Vec; @@ -97,8 +100,8 @@ struct FormInner { types: CachedValue>, base_experience: CachedValue, base_stats: CachedValue, - abilities: CachedValue>, - hidden_abilities: CachedValue>, + abilities: CachedValue>>, + hidden_abilities: CachedValue>>, // moves: CachedValue, } @@ -122,9 +125,19 @@ impl Form { }), base_experience: cached_value!({ form_get_base_experience(reference) }), base_stats: cached_value!({ form_get_base_stats(reference).get_value().unwrap() }), - abilities: cached_value!({ form_get_abilities(reference).get_immutable_list() }), + abilities: cached_value!({ + Rc::new( + crate::app_interface::list::StringKeyImmutableList::from_ref( + form_get_abilities(reference), + ), + ) + }), hidden_abilities: cached_value!({ - form_get_hidden_abilities(reference).get_immutable_list() + Rc::new( + crate::app_interface::list::StringKeyImmutableList::from_ref( + form_get_hidden_abilities(reference), + ), + ) }), }), }) @@ -140,8 +153,8 @@ impl Form { pub fn weight(&self) -> f32; pub fn base_experience(&self) -> u32; pub fn base_stats(&self) -> ImmutableStatisticSet; - pub fn abilities(&self) -> ImmutableList; - pub fn hidden_abilities(&self) -> ImmutableList; + pub fn abilities(&self) -> ImmutableList>; + pub fn hidden_abilities(&self) -> ImmutableList>; } pub fn types(&self) -> &Vec { self.inner.types.value_ref() diff --git a/pkmn_lib_interface/src/handling/extern_ref.rs b/pkmn_lib_interface/src/handling/extern_ref.rs index f1b06b5..1b63d10 100755 --- a/pkmn_lib_interface/src/handling/extern_ref.rs +++ b/pkmn_lib_interface/src/handling/extern_ref.rs @@ -1,4 +1,3 @@ -use crate::app_interface::list::ImmutableList; use alloc::rc::Rc; use core::cmp::Ordering; use core::hash::{Hash, Hasher}; @@ -152,15 +151,6 @@ impl VecExternRef { resource_type: Default::default(), } } - - #[cfg(not(feature = "mock_data"))] - pub(crate) fn get_immutable_list(&self) -> ImmutableList - where - T: Clone, - T: ExternalReferenceType, - { - ImmutableList::from_ref(*self) - } } impl Clone for VecExternRef { diff --git a/pkmn_lib_interface/src/handling/script.rs b/pkmn_lib_interface/src/handling/script.rs index 2ddea9b..baebd09 100755 --- a/pkmn_lib_interface/src/handling/script.rs +++ b/pkmn_lib_interface/src/handling/script.rs @@ -1,10 +1,12 @@ use crate::app_interface::list::ImmutableList; use crate::app_interface::{ Battle, DamageSource, DynamicLibrary, EffectParameter, ExecutingMove, Item, Pokemon, Statistic, + TurnChoice, TypeIdentifier, }; use crate::handling::ScriptCapabilities; -use crate::{ExternRef, ExternalReferenceType, ScriptPtr, StringKey, TurnChoice, TypeIdentifier}; +use crate::{ExternRef, ExternalReferenceType, StringKey}; use alloc::boxed::Box; +use alloc::rc::Rc; use core::any::Any; use core::fmt::Debug; @@ -25,7 +27,7 @@ pub trait Script { fn on_initialize( &self, _library: &DynamicLibrary, - _parameters: Option>, + _parameters: Option>>, ) { } @@ -352,7 +354,7 @@ pub trait Script { Self: Sized, { unsafe { - script_get_owner(ScriptPtr::from_existing(self)) + script_get_owner(crate::implementation::ScriptPtr::from_existing(self)) .cast::() .get_value() } @@ -375,5 +377,5 @@ impl Debug for dyn Script { #[cfg(not(feature = "mock_data"))] extern "wasm" { - fn script_get_owner(pointer: ScriptPtr) -> ExternRef; + fn script_get_owner(pointer: crate::implementation::ScriptPtr) -> ExternRef; } diff --git a/pkmn_lib_interface/src/lib.rs b/pkmn_lib_interface/src/lib.rs index 6d4c523..19191ef 100755 --- a/pkmn_lib_interface/src/lib.rs +++ b/pkmn_lib_interface/src/lib.rs @@ -22,23 +22,9 @@ extern crate dlmalloc; #[global_allocator] static ALLOC: dlmalloc::GlobalDlmalloc = dlmalloc::GlobalDlmalloc {}; -use crate::app_interface::list::ImmutableList; -#[cfg(not(feature = "mock_data"))] -use crate::app_interface::{BattleImpl, ExecutingMoveImpl, PokemonImpl}; -use crate::app_interface::{ - DamageSource, DynamicLibrary, EffectParameter, Item, ItemImpl, Pokemon, Statistic, StringKey, - TurnChoice, TypeIdentifier, -}; - +pub(crate) use crate::app_interface::StringKey; pub(crate) use crate::handling::extern_ref::*; -use crate::handling::ffi_array::FFIArray; -#[cfg(not(feature = "mock_data"))] -use crate::handling::ScriptCapabilities; -use crate::handling::{Script, ScriptCategory}; -use alloc::boxed::Box; -use core::sync::atomic::{AtomicU32, Ordering}; -use cstr_core::{c_char, CString}; -use hashbrown::HashMap; +pub(crate) use crate::handling::Script; #[macro_use] #[allow(dead_code)] @@ -46,17 +32,34 @@ pub mod app_interface; pub mod handling; pub mod utils; -pub type LoadScriptFnType = Box Option>>; +#[cfg(not(feature = "mock_data"))] +mod implementation { + use crate::app_interface::list::{EffectParameterImmutableList, ImmutableListWasm}; + use crate::app_interface::{ + BattleImpl, DamageSource, DynamicLibrary, EffectParameter, ExecutingMoveImpl, ItemImpl, + PokemonImpl, Statistic, StringKey, TurnChoice, TypeIdentifier, + }; + use crate::handling::extern_ref::ExternRef; + use crate::handling::extern_ref::VecExternRef; + use crate::handling::ffi_array::FFIArray; + use crate::handling::{Script, ScriptCapabilities, ScriptCategory}; + use alloc::boxed::Box; + use alloc::rc::Rc; + use core::sync::atomic::{AtomicU32, Ordering}; + use cstr_core::{c_char, CString}; + use hashbrown::HashMap; -static mut LOAD_SCRIPT_FN: Option = None; + pub type LoadScriptFnType = Box Option>>; -pub fn set_load_script_fn(f: LoadScriptFnType) { - unsafe { - LOAD_SCRIPT_FN = Some(f); + static mut LOAD_SCRIPT_FN: Option = None; + + pub fn set_load_script_fn(f: LoadScriptFnType) { + unsafe { + LOAD_SCRIPT_FN = Some(f); + } } -} -macro_rules! exported_functions { + macro_rules! exported_functions { ( $( fn $func_name:ident($($par_name:ident: $par_type:ty),*$(,)?) $(-> $return_type:ty)? $func_body:block @@ -64,7 +67,6 @@ macro_rules! exported_functions { ) => { $( #[no_mangle] - #[cfg(not(feature = "mock_data"))] unsafe extern "wasm" fn $func_name( $( $par_name: $par_type, @@ -74,605 +76,592 @@ macro_rules! exported_functions { }; } -static mut SCRIPT_PTR_CACHE: Option> = None; -static mut SCRIPT_PTR_REVERSE_CACHE: Option>> = None; -static mut SCRIPT_INDEX_COUNTER: AtomicU32 = AtomicU32::new(1); + static mut SCRIPT_PTR_CACHE: Option> = None; + static mut SCRIPT_PTR_REVERSE_CACHE: Option>> = None; + static mut SCRIPT_INDEX_COUNTER: AtomicU32 = AtomicU32::new(1); -#[repr(C)] -pub struct ScriptPtr { - index: u32, -} + #[repr(C)] + pub struct ScriptPtr { + index: u32, + } -impl ScriptPtr { - fn get_cache<'a>() -> &'a mut HashMap<*const dyn Script, u32> { - unsafe { - if let None = SCRIPT_PTR_CACHE { - SCRIPT_PTR_CACHE = Some(hashbrown::HashMap::new()); + impl ScriptPtr { + fn get_cache<'a>() -> &'a mut HashMap<*const dyn Script, u32> { + unsafe { + if let None = SCRIPT_PTR_CACHE { + SCRIPT_PTR_CACHE = Some(hashbrown::HashMap::new()); + } + let cache = SCRIPT_PTR_CACHE.as_mut().unwrap(); + cache } - let cache = SCRIPT_PTR_CACHE.as_mut().unwrap(); - cache } - } - fn get_reverse_cache<'a>() -> &'a mut HashMap> { - unsafe { - if let None = SCRIPT_PTR_REVERSE_CACHE { - SCRIPT_PTR_REVERSE_CACHE = Some(hashbrown::HashMap::new()); + fn get_reverse_cache<'a>() -> &'a mut HashMap> { + unsafe { + if let None = SCRIPT_PTR_REVERSE_CACHE { + SCRIPT_PTR_REVERSE_CACHE = Some(hashbrown::HashMap::new()); + } + let cache = SCRIPT_PTR_REVERSE_CACHE.as_mut().unwrap(); + cache } - let cache = SCRIPT_PTR_REVERSE_CACHE.as_mut().unwrap(); - cache } - } - pub fn from_existing(ptr: &dyn Script) -> Self { - let cache = Self::get_cache(); - let index = *cache.get(&(ptr as *const dyn Script)).unwrap(); - Self { index } - } - - pub fn new(ptr: Box) -> Self { - unsafe { + pub fn from_existing(ptr: &dyn Script) -> Self { let cache = Self::get_cache(); - let mut index = cache.get(&(ptr.as_ref() as *const dyn Script)).cloned(); - if index.is_none() { - index = Some(SCRIPT_INDEX_COUNTER.fetch_add(1, Ordering::SeqCst)); - let reverse_cache = Self::get_reverse_cache(); - reverse_cache.insert(index.unwrap(), ptr); + let index = *cache.get(&(ptr as *const dyn Script)).unwrap(); + Self { index } + } - let v = reverse_cache.get(&index.unwrap()).unwrap(); - cache.insert(v.as_ref(), index.unwrap()); + pub fn new(ptr: Box) -> Self { + unsafe { + let cache = Self::get_cache(); + let mut index = cache.get(&(ptr.as_ref() as *const dyn Script)).cloned(); + if index.is_none() { + index = Some(SCRIPT_INDEX_COUNTER.fetch_add(1, Ordering::SeqCst)); + let reverse_cache = Self::get_reverse_cache(); + reverse_cache.insert(index.unwrap(), ptr); + + let v = reverse_cache.get(&index.unwrap()).unwrap(); + cache.insert(v.as_ref(), index.unwrap()); + } + Self { + index: index.unwrap(), + } } - Self { - index: index.unwrap(), + } + + pub fn null() -> Self { + Self { index: 0 } + } + + pub fn val<'a, 'b>(&'a self) -> Option<&'b dyn Script> { + if self.index == 0 { + return None; + } + let cache = Self::get_reverse_cache(); + if let Some(c) = cache.get(&self.index) { + Some(c.as_ref()) + } else { + None } } } - pub fn null() -> Self { - Self { index: 0 } + exported_functions! { + + fn load_script(category: ScriptCategory, name: ExternRef) -> ScriptPtr { + let name_c = StringKey::new(name); + let boxed_script = unsafe { &LOAD_SCRIPT_FN }.as_ref().unwrap()(category, &name_c); + if boxed_script.is_none() { + return ScriptPtr::null(); + } + let b = boxed_script.unwrap(); + ScriptPtr::new(b) } - pub fn val<'a, 'b>(&'a self) -> Option<&'b dyn Script> { - if self.index == 0 { - return None; - } - let cache = Self::get_reverse_cache(); - if let Some(c) = cache.get(&self.index) { - Some(c.as_ref()) - } else { - None + fn destroy_script(script: *mut Box) { + // By turning it from a raw pointer back into a Box with from_raw, we give ownership back to rust. + // This lets Rust do the cleanup. + let boxed_script = Box::from_raw(script); + drop(boxed_script); + } + + fn script_get_name(script: ScriptPtr) -> *mut c_char { + let c = script.val().unwrap().get_name(); + CString::new(c).unwrap().into_raw() + } + + + fn get_script_capabilities(script: ScriptPtr) -> FFIArray { + let c = script.val().unwrap().get_capabilities(); + FFIArray::new(c) + } + + fn script_stack(script: ScriptPtr) { + script.val().unwrap().stack(); + } + + fn script_on_remove(script: ScriptPtr) { + script.val().unwrap().on_remove(); + } + + fn script_on_initialize( + script: ScriptPtr, + library: ExternRef, + parameters: VecExternRef, + ) { + let parameters = Rc::new(EffectParameterImmutableList::from_ref(parameters)); + script.val().unwrap().on_initialize(&library.not_null(), Some(parameters)); + } + + fn script_on_before_turn( + script: ScriptPtr, + choice: ExternRef, + ) { + script.val().unwrap().on_before_turn(choice.not_null()) + } + + fn script_change_speed( + script:ScriptPtr, + choice: ExternRef, + speed: *mut u32, + ) { + script.val().unwrap().change_speed(choice.not_null(), speed.as_mut().unwrap()) + } + + fn script_change_priority( + script: ScriptPtr, + choice: ExternRef, + priority: *mut i8, + ) { + script.val().unwrap().change_priority(choice.not_null(), priority.as_mut().unwrap()) + } + + fn script_change_move( + script: ScriptPtr, + choice: ExternRef, + mv: *mut ExternRef, + ) { + let old = mv.as_ref().unwrap().not_null(); + let mut new = old.clone(); + script.val().unwrap().change_move(choice.not_null(), &mut new); + if old != new { + *mv = new.ptr(); } } -} -exported_functions! { - -fn load_script(category: ScriptCategory, name: ExternRef) -> ScriptPtr { - let name_c = StringKey::new(name); - let boxed_script = unsafe { &LOAD_SCRIPT_FN }.as_ref().unwrap()(category, &name_c); - if boxed_script.is_none() { - return ScriptPtr::null(); + fn script_change_number_of_hits( + script: ScriptPtr, + choice: ExternRef, + out: *mut u8, + ) { + script.val().unwrap().change_number_of_hits(choice.not_null(), out.as_mut().unwrap()); } - let b = boxed_script.unwrap(); - ScriptPtr::new(b) -} -fn destroy_script(script: *mut Box) { - // By turning it from a raw pointer back into a Box with from_raw, we give ownership back to rust. - // This lets Rust do the cleanup. - let boxed_script = Box::from_raw(script); - drop(boxed_script); -} + fn script_prevent_move( + script: ScriptPtr, + mv: ExternRef, + out: *mut bool, + ) { + script.val().unwrap().prevent_move(mv.not_null_rc(), out.as_mut().unwrap()); + } -fn script_get_name(script: ScriptPtr) -> *mut c_char { - let c = script.val().unwrap().get_name(); - CString::new(c).unwrap().into_raw() -} + fn script_fail_move( + script: ScriptPtr, + mv: ExternRef, + out: *mut bool, + ) { + script.val().unwrap().fail_move(mv.not_null_rc(), out.as_mut().unwrap()); + } + fn script_stop_before_move( + script: ScriptPtr, + mv: ExternRef, + out: *mut bool, + ) { + script.val().unwrap().stop_before_move(mv.not_null_rc(), out.as_mut().unwrap()); + } -fn get_script_capabilities(script: ScriptPtr) -> FFIArray { - let c = script.val().unwrap().get_capabilities(); - FFIArray::new(c) -} + fn script_on_before_move( + script: ScriptPtr, + mv: ExternRef, + ) { + script.val().unwrap().on_before_move(mv.not_null_rc()); + } -fn script_stack(script: ScriptPtr) { - script.val().unwrap().stack(); -} + fn script_fail_incoming_move( + script: ScriptPtr, + mv: ExternRef, + target: ExternRef, + out: *mut bool, + ) { + script.val().unwrap().fail_incoming_move(mv.not_null_rc(), target.not_null_rc(), out.as_mut().unwrap()); + } -fn script_on_remove(script: ScriptPtr) { - script.val().unwrap().on_remove(); -} + fn script_is_invulnerable( + script: ScriptPtr, + mv: ExternRef, + target: ExternRef, + out: *mut bool, + ) { + script.val().unwrap().is_invulnerable(mv.not_null_rc(), target.not_null_rc(), out.as_mut().unwrap()); + } -fn script_on_initialize( - script: ScriptPtr, - library: ExternRef, - parameters: VecExternRef, -) { - let parameters = ImmutableList::from_ref(parameters); - script.val().unwrap().on_initialize(&library.not_null(), Some(parameters)); -} + fn script_on_move_miss( + script: ScriptPtr, + mv: ExternRef, + target: ExternRef, + ) { + script.val().unwrap().on_move_miss(mv.not_null_rc(), target.not_null_rc()); + } -fn script_on_before_turn( - script: ScriptPtr, - choice: ExternRef, -) { - script.val().unwrap().on_before_turn(choice.not_null()) -} + fn script_change_move_type( + script: ScriptPtr, + mv: ExternRef, + target: ExternRef, + hit: u8, + out: *mut TypeIdentifier, + ) { + script.val().unwrap().change_move_type(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); + } -fn script_change_speed( - script:ScriptPtr, - choice: ExternRef, - speed: *mut u32, -) { - script.val().unwrap().change_speed(choice.not_null(), speed.as_mut().unwrap()) -} + fn script_change_effectiveness( + script: ScriptPtr, + mv: ExternRef, + target: ExternRef, + hit: u8, + out: *mut f32, + ) { + script.val().unwrap().change_effectiveness(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); + } -fn script_change_priority( - script: ScriptPtr, - choice: ExternRef, - priority: *mut i8, -) { - script.val().unwrap().change_priority(choice.not_null(), priority.as_mut().unwrap()) -} + fn script_block_critical( + script: ScriptPtr, + mv: ExternRef, + target: ExternRef, + hit: u8, + out: *mut bool, + ) { + script.val().unwrap().block_critical(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); + } -fn script_change_move( - script: ScriptPtr, - choice: ExternRef, - mv: *mut ExternRef, -) { - let old = mv.as_ref().unwrap().not_null(); - let mut new = old.clone(); - script.val().unwrap().change_move(choice.not_null(), &mut new); - if old != new { - *mv = new.ptr(); + fn script_block_incoming_critical( + script: ScriptPtr, + mv: ExternRef, + target: ExternRef, + hit: u8, + out: *mut bool, + ) { + script.val().unwrap().block_incoming_critical(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); + } + + fn script_change_accuracy( + script: ScriptPtr, + mv: ExternRef, + target: ExternRef, + hit: u8, + out: *mut u8, + ) { + script.val().unwrap().change_accuracy(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); + } + + fn script_change_critical_stage( + script: ScriptPtr, + mv: ExternRef, + target: ExternRef, + hit: u8, + out: *mut u8, + ) { + script.val().unwrap().change_critical_stage(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); + } + + fn script_change_critical_modifier( + script: ScriptPtr, + mv: ExternRef, + target: ExternRef, + hit: u8, + out: *mut f32, + ) { + script.val().unwrap().change_critical_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); + } + + fn script_change_stab_modifier( + script: ScriptPtr, + mv: ExternRef, + target: ExternRef, + hit: u8, + out: *mut f32, + ) { + script.val().unwrap().change_stab_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); + } + + fn script_change_base_power( + script: ScriptPtr, + mv: ExternRef, + target: ExternRef, + hit: u8, + out: *mut u8, + ) { + script.val().unwrap().change_base_power(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); + } + + fn script_bypass_defensive_stat_boost( + script: ScriptPtr, + mv: ExternRef, + target: ExternRef, + hit: u8, + out: *mut bool, + ) { + script.val().unwrap().bypass_defensive_stat_boost(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); + } + + fn script_bypass_offensive_stat_boost( + script: ScriptPtr, + mv: ExternRef, + target: ExternRef, + hit: u8, + out: *mut bool, + ) { + script.val().unwrap().bypass_offensive_stat_boost(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); + } + + fn script_change_defensive_stat_value( + script: ScriptPtr, + mv: ExternRef, + target: ExternRef, + hit: u8, + out: *mut u32, + ) { + script.val().unwrap().change_defensive_stat_value(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); + } + + fn script_change_offensive_stat_value( + script: ScriptPtr, + mv: ExternRef, + target: ExternRef, + hit: u8, + out: *mut u32, + ) { + script.val().unwrap().change_offensive_stat_value(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); + } + + fn script_change_damage_stat_modifier( + script: ScriptPtr, + mv: ExternRef, + target: ExternRef, + hit: u8, + out: *mut f32, + ) { + script.val().unwrap().change_damage_stat_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); + } + + fn script_change_damage_modifier( + script: ScriptPtr, + mv: ExternRef, + target: ExternRef, + hit: u8, + out: *mut f32, + ) { + script.val().unwrap().change_damage_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); + } + + fn script_change_damage( + script: ScriptPtr, + mv: ExternRef, + target: ExternRef, + hit: u8, + out: *mut u32, + ) { + script.val().unwrap().change_damage(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); + } + + fn script_change_incoming_damage( + script: ScriptPtr, + mv: ExternRef, + target: ExternRef, + hit: u8, + out: *mut u32, + ) { + script.val().unwrap().change_incoming_damage(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); + } + + fn script_on_incoming_hit( + script: ScriptPtr, + mv: ExternRef, + target: ExternRef, + hit: u8, + ) { + script.val().unwrap().on_incoming_hit(mv.not_null_rc(), target.not_null_rc(), hit); + } + + fn script_on_opponent_faints( + script: ScriptPtr, + mv: ExternRef, + target: ExternRef, + hit: u8, + ) { + script.val().unwrap().on_opponent_faints(mv.not_null_rc(), target.not_null_rc(), hit); + } + + fn script_prevent_stat_boost_change( + script: ScriptPtr, + target: ExternRef, + stat: Statistic, + amount: i8, + self_inflicted: u8, + out: *mut bool, + ) { + script.val().unwrap().prevent_stat_boost_change(target.not_null_rc(), stat, amount, self_inflicted == 1, out.as_mut().unwrap()); + } + + fn script_prevent_secondary_effect( + script: ScriptPtr, + mv: ExternRef, + target: ExternRef, + hit: u8, + out: *mut bool, + ) { + script.val().unwrap().prevent_secondary_effect(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); + } + + fn script_change_effect_chance( + script: ScriptPtr, + mv: ExternRef, + target: ExternRef, + hit: u8, + out: *mut f32, + ) { + script.val().unwrap().change_effect_chance(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); + } + + fn script_change_incoming_effect_chance( + script: ScriptPtr, + mv: ExternRef, + target: ExternRef, + hit: u8, + out: *mut f32, + ) { + script.val().unwrap().change_incoming_effect_chance(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); + } + + fn script_on_secondary_effect( + script: ScriptPtr, + mv: ExternRef, + target: ExternRef, + hit: u8, + ) { + script.val().unwrap().on_secondary_effect(mv.not_null_rc(), target.not_null_rc(), hit); + } + + fn script_on_after_hits( + script: ScriptPtr, + mv: ExternRef, + target: ExternRef, + ) { + script.val().unwrap().on_after_hits(mv.not_null_rc(), target.not_null_rc()); + } + + fn script_prevent_self_switch( + script: ScriptPtr, + choice: ExternRef, + out: *mut bool, + ) { + script.val().unwrap().prevent_self_switch(choice.not_null(), out.as_mut().unwrap()); + } + + fn script_prevent_opponent_switch( + script: ScriptPtr, + choice: ExternRef, + out: *mut bool, + ) { + script.val().unwrap().prevent_opponent_switch(choice.not_null(), out.as_mut().unwrap()); + } + + fn script_on_fail( + script: ScriptPtr, + pokemon: ExternRef, + ) { + script.val().unwrap().on_fail(pokemon.not_null_rc()); + } + + fn script_on_opponent_fail( + script: ScriptPtr, + pokemon: ExternRef, + ) { + script.val().unwrap().on_opponent_fail(pokemon.not_null_rc()); + } + + fn script_prevent_self_run_away( + script: ScriptPtr, + choice: ExternRef, + out: *mut bool, + ) { + script.val().unwrap().prevent_self_run_away(choice.not_null(), out.as_mut().unwrap()); + } + + fn script_prevent_opponent_run_away( + script: ScriptPtr, + choice: ExternRef, + out: *mut bool, + ) { + script.val().unwrap().prevent_opponent_run_away(choice.not_null(), out.as_mut().unwrap()); + } + + fn script_on_end_turn( + script: ScriptPtr, + ) { + script.val().unwrap().on_end_turn(); + } + + fn script_on_damage( + script: ScriptPtr, + pokemon: ExternRef, + source: DamageSource, + old_health: u32, + new_health: u32, + ) { + script.val().unwrap().on_damage(pokemon.not_null_rc(), source, old_health, new_health); + } + + fn script_on_faint( + script: ScriptPtr, + pokemon: ExternRef, + source: DamageSource, + ) { + script.val().unwrap().on_faint(pokemon.not_null_rc(), source); + } + + fn script_on_switch_in( + script: ScriptPtr, + pokemon: ExternRef, + ) { + script.val().unwrap().on_switch_in(pokemon.not_null_rc()); + } + + fn script_on_after_held_item_consume( + script: ScriptPtr, + pokemon: ExternRef, + item: ExternRef + ) { + script.val().unwrap().on_after_held_item_consume(pokemon.not_null_rc(), item.not_null_rc()); + } + + fn script_change_experience_gained( + script: ScriptPtr, + fainted_pokemon: ExternRef, + winning_pokemon: ExternRef, + out: *mut u32 + ) { + script.val().unwrap().change_experience_gained(fainted_pokemon.not_null_rc(), winning_pokemon.not_null_rc(), out.as_mut().unwrap()); + } + + fn script_share_experience( + script: ScriptPtr, + fainted_pokemon: ExternRef, + winning_pokemon: ExternRef, + out: *mut bool, + ) { + script.val().unwrap().share_experience(fainted_pokemon.not_null_rc(), winning_pokemon.not_null_rc(), out.as_mut().unwrap()); + } + + fn script_block_weather( + script: ScriptPtr, + battle: ExternRef, + out: *mut bool, + ) { + script.val().unwrap().block_weather(battle.not_null_rc(), out.as_mut().unwrap()); + } + + fn script_change_capture_rate_bonus( + script: ScriptPtr, + target: ExternRef, + pokeball: ExternRef, + out: *mut u8, + ) { + script.val().unwrap().change_capture_rate_bonus(target.not_null_rc(), pokeball.not_null_rc(), out.as_mut().unwrap()); + } } } -fn script_change_number_of_hits( - script: ScriptPtr, - choice: ExternRef, - out: *mut u8, -) { - script.val().unwrap().change_number_of_hits(choice.not_null(), out.as_mut().unwrap()); -} - -fn script_prevent_move( - script: ScriptPtr, - mv: ExternRef, - out: *mut bool, -) { - script.val().unwrap().prevent_move(mv.not_null_rc(), out.as_mut().unwrap()); -} - -fn script_fail_move( - script: ScriptPtr, - mv: ExternRef, - out: *mut bool, -) { - script.val().unwrap().fail_move(mv.not_null_rc(), out.as_mut().unwrap()); -} - -fn script_stop_before_move( - script: ScriptPtr, - mv: ExternRef, - out: *mut bool, -) { - script.val().unwrap().stop_before_move(mv.not_null_rc(), out.as_mut().unwrap()); -} - -fn script_on_before_move( - script: ScriptPtr, - mv: ExternRef, -) { - script.val().unwrap().on_before_move(mv.not_null_rc()); -} - -fn script_fail_incoming_move( - script: ScriptPtr, - mv: ExternRef, - target: ExternRef, - out: *mut bool, -) { - script.val().unwrap().fail_incoming_move(mv.not_null_rc(), target.not_null_rc(), out.as_mut().unwrap()); -} - -fn script_is_invulnerable( - script: ScriptPtr, - mv: ExternRef, - target: ExternRef, - out: *mut bool, -) { - script.val().unwrap().is_invulnerable(mv.not_null_rc(), target.not_null_rc(), out.as_mut().unwrap()); -} - -fn script_on_move_miss( - script: ScriptPtr, - mv: ExternRef, - target: ExternRef, -) { - script.val().unwrap().on_move_miss(mv.not_null_rc(), target.not_null_rc()); -} - -fn script_change_move_type( - script: ScriptPtr, - mv: ExternRef, - target: ExternRef, - hit: u8, - out: *mut TypeIdentifier, -) { - script.val().unwrap().change_move_type(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); -} - -fn script_change_effectiveness( - script: ScriptPtr, - mv: ExternRef, - target: ExternRef, - hit: u8, - out: *mut f32, -) { - script.val().unwrap().change_effectiveness(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); -} - -fn script_block_critical( - script: ScriptPtr, - mv: ExternRef, - target: ExternRef, - hit: u8, - out: *mut bool, -) { - script.val().unwrap().block_critical(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); -} - -fn script_block_incoming_critical( - script: ScriptPtr, - mv: ExternRef, - target: ExternRef, - hit: u8, - out: *mut bool, -) { - script.val().unwrap().block_incoming_critical(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); -} - -fn script_change_accuracy( - script: ScriptPtr, - mv: ExternRef, - target: ExternRef, - hit: u8, - out: *mut u8, -) { - script.val().unwrap().change_accuracy(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); -} - -fn script_change_critical_stage( - script: ScriptPtr, - mv: ExternRef, - target: ExternRef, - hit: u8, - out: *mut u8, -) { - script.val().unwrap().change_critical_stage(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); -} - -fn script_change_critical_modifier( - script: ScriptPtr, - mv: ExternRef, - target: ExternRef, - hit: u8, - out: *mut f32, -) { - script.val().unwrap().change_critical_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); -} - -fn script_change_stab_modifier( - script: ScriptPtr, - mv: ExternRef, - target: ExternRef, - hit: u8, - out: *mut f32, -) { - script.val().unwrap().change_stab_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); -} - -fn script_change_base_power( - script: ScriptPtr, - mv: ExternRef, - target: ExternRef, - hit: u8, - out: *mut u8, -) { - script.val().unwrap().change_base_power(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); -} - -fn script_bypass_defensive_stat_boost( - script: ScriptPtr, - mv: ExternRef, - target: ExternRef, - hit: u8, - out: *mut bool, -) { - script.val().unwrap().bypass_defensive_stat_boost(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); -} - -fn script_bypass_offensive_stat_boost( - script: ScriptPtr, - mv: ExternRef, - target: ExternRef, - hit: u8, - out: *mut bool, -) { - script.val().unwrap().bypass_offensive_stat_boost(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); -} - -fn script_change_defensive_stat_value( - script: ScriptPtr, - mv: ExternRef, - target: ExternRef, - hit: u8, - out: *mut u32, -) { - script.val().unwrap().change_defensive_stat_value(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); -} - -fn script_change_offensive_stat_value( - script: ScriptPtr, - mv: ExternRef, - target: ExternRef, - hit: u8, - out: *mut u32, -) { - script.val().unwrap().change_offensive_stat_value(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); -} - -fn script_change_damage_stat_modifier( - script: ScriptPtr, - mv: ExternRef, - target: ExternRef, - hit: u8, - out: *mut f32, -) { - script.val().unwrap().change_damage_stat_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); -} - -fn script_change_damage_modifier( - script: ScriptPtr, - mv: ExternRef, - target: ExternRef, - hit: u8, - out: *mut f32, -) { - script.val().unwrap().change_damage_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); -} - -fn script_change_damage( - script: ScriptPtr, - mv: ExternRef, - target: ExternRef, - hit: u8, - out: *mut u32, -) { - script.val().unwrap().change_damage(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); -} - -fn script_change_incoming_damage( - script: ScriptPtr, - mv: ExternRef, - target: ExternRef, - hit: u8, - out: *mut u32, -) { - script.val().unwrap().change_incoming_damage(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); -} - -fn script_on_incoming_hit( - script: ScriptPtr, - mv: ExternRef, - target: ExternRef, - hit: u8, -) { - script.val().unwrap().on_incoming_hit(mv.not_null_rc(), target.not_null_rc(), hit); -} - -fn script_on_opponent_faints( - script: ScriptPtr, - mv: ExternRef, - target: ExternRef, - hit: u8, -) { - script.val().unwrap().on_opponent_faints(mv.not_null_rc(), target.not_null_rc(), hit); -} - -fn script_prevent_stat_boost_change( - script: ScriptPtr, - target: ExternRef, - stat: Statistic, - amount: i8, - self_inflicted: u8, - out: *mut bool, -) { - script.val().unwrap().prevent_stat_boost_change(target.not_null_rc(), stat, amount, self_inflicted == 1, out.as_mut().unwrap()); -} - -fn script_prevent_secondary_effect( - script: ScriptPtr, - mv: ExternRef, - target: ExternRef, - hit: u8, - out: *mut bool, -) { - script.val().unwrap().prevent_secondary_effect(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); -} - -fn script_change_effect_chance( - script: ScriptPtr, - mv: ExternRef, - target: ExternRef, - hit: u8, - out: *mut f32, -) { - script.val().unwrap().change_effect_chance(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); -} - -fn script_change_incoming_effect_chance( - script: ScriptPtr, - mv: ExternRef, - target: ExternRef, - hit: u8, - out: *mut f32, -) { - script.val().unwrap().change_incoming_effect_chance(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); -} - -fn script_on_secondary_effect( - script: ScriptPtr, - mv: ExternRef, - target: ExternRef, - hit: u8, -) { - script.val().unwrap().on_secondary_effect(mv.not_null_rc(), target.not_null_rc(), hit); -} - -fn script_on_after_hits( - script: ScriptPtr, - mv: ExternRef, - target: ExternRef, -) { - script.val().unwrap().on_after_hits(mv.not_null_rc(), target.not_null_rc()); -} - -fn script_prevent_self_switch( - script: ScriptPtr, - choice: ExternRef, - out: *mut bool, -) { - script.val().unwrap().prevent_self_switch(choice.not_null(), out.as_mut().unwrap()); -} - -fn script_prevent_opponent_switch( - script: ScriptPtr, - choice: ExternRef, - out: *mut bool, -) { - script.val().unwrap().prevent_opponent_switch(choice.not_null(), out.as_mut().unwrap()); -} - -fn script_on_fail( - script: ScriptPtr, - pokemon: ExternRef, -) { - script.val().unwrap().on_fail(pokemon.not_null_rc()); -} - -fn script_on_opponent_fail( - script: ScriptPtr, - pokemon: ExternRef, -) { - script.val().unwrap().on_opponent_fail(pokemon.not_null_rc()); -} - -fn script_prevent_self_run_away( - script: ScriptPtr, - choice: ExternRef, - out: *mut bool, -) { - script.val().unwrap().prevent_self_run_away(choice.not_null(), out.as_mut().unwrap()); -} - -fn script_prevent_opponent_run_away( - script: ScriptPtr, - choice: ExternRef, - out: *mut bool, -) { - script.val().unwrap().prevent_opponent_run_away(choice.not_null(), out.as_mut().unwrap()); -} - -fn script_on_end_turn( - script: ScriptPtr, -) { - script.val().unwrap().on_end_turn(); -} - -fn script_on_damage( - script: ScriptPtr, - pokemon: ExternRef, - source: DamageSource, - old_health: u32, - new_health: u32, -) { - script.val().unwrap().on_damage(pokemon.not_null_rc(), source, old_health, new_health); -} - -fn script_on_faint( - script: ScriptPtr, - pokemon: ExternRef, - source: DamageSource, -) { - script.val().unwrap().on_faint(pokemon.not_null_rc(), source); -} - -fn script_on_switch_in( - script: ScriptPtr, - pokemon: ExternRef, -) { - script.val().unwrap().on_switch_in(pokemon.not_null_rc()); -} - -fn script_on_after_held_item_consume( - script: ScriptPtr, - pokemon: ExternRef, - item: ExternRef -) { - script.val().unwrap().on_after_held_item_consume(pokemon.not_null_rc(), item.not_null_rc()); -} - -fn script_change_experience_gained( - script: ScriptPtr, - fainted_pokemon: ExternRef, - winning_pokemon: ExternRef, - out: *mut u32 -) { - script.val().unwrap().change_experience_gained(fainted_pokemon.not_null_rc(), winning_pokemon.not_null_rc(), out.as_mut().unwrap()); -} - -fn script_share_experience( - script: ScriptPtr, - fainted_pokemon: ExternRef, - winning_pokemon: ExternRef, - out: *mut bool, -) { - script.val().unwrap().share_experience(fainted_pokemon.not_null_rc(), winning_pokemon.not_null_rc(), out.as_mut().unwrap()); -} - -fn script_block_weather( - script: ScriptPtr, - battle: ExternRef, - out: *mut bool, -) { - script.val().unwrap().block_weather(battle.not_null_rc(), out.as_mut().unwrap()); -} - -fn script_change_capture_rate_bonus( - script: ScriptPtr, - target: ExternRef, - pokeball: ExternRef, - out: *mut u8, -) { - script.val().unwrap().change_capture_rate_bonus(target.not_null_rc(), pokeball.not_null_rc(), out.as_mut().unwrap()); -} - - - - - - - - - - - - - - - - - -} +#[cfg(not(feature = "mock_data"))] +pub use implementation::*;