More work on mocking and removing the impls from the interface

This commit is contained in:
Deukhoofd 2023-01-05 12:54:18 +01:00
parent 6e15a26813
commit 417b776a83
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
19 changed files with 1107 additions and 950 deletions

View File

@ -8,6 +8,7 @@
extern crate alloc; extern crate alloc;
use alloc::boxed::Box; use alloc::boxed::Box;
#[cfg(not(test))]
use pkmn_lib_interface::set_load_script_fn; use pkmn_lib_interface::set_load_script_fn;
#[macro_use] #[macro_use]

View File

@ -39,3 +39,36 @@ impl Script for AfterYou {
self 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);
}
}

View File

@ -3,8 +3,7 @@ use alloc::boxed::Box;
use core::any::Any; use core::any::Any;
use core::sync::atomic::{AtomicBool, Ordering}; use core::sync::atomic::{AtomicBool, Ordering};
use pkmn_lib_interface::app_interface::{ use pkmn_lib_interface::app_interface::{
BattleSide, BattleSideImpl, DamageSource, DataLibrary, ExecutingMove, Pokemon, TurnChoice, BattleSide, DamageSource, DataLibrary, ExecutingMove, Pokemon, TurnChoice, WithVolatile,
WithVolatile,
}; };
use pkmn_lib_interface::handling::{Script, ScriptCapabilities}; 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) { fn on_before_turn(&self, choice: TurnChoice) {
if let TurnChoice::Move(data) = &choice { if let TurnChoice::Move(data) = &choice {
let side: BattleSideImpl = choice let side: BattleSide = choice
.user() .user()
.battle() .battle()
.unwrap() .unwrap()
@ -90,7 +88,7 @@ impl Script for AssuranceData {
#[cfg(not(test))] #[cfg(not(test))]
fn on_end_turn(&self) { 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); side.remove_volatile(self);
} }

View File

@ -6,7 +6,7 @@ use alloc::boxed::Box;
use core::any::Any; use core::any::Any;
use core::sync::atomic::{AtomicU32, Ordering}; use core::sync::atomic::{AtomicU32, Ordering};
use pkmn_lib_interface::app_interface::{ 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::ScriptCapabilities::OnEndTurn;
use pkmn_lib_interface::handling::{Script, ScriptCapabilities}; use pkmn_lib_interface::handling::{Script, ScriptCapabilities};
@ -76,7 +76,7 @@ impl Script for AuroraVeilEffect {
if mv.get_hit_data(&target, hit).is_critical() { if mv.get_hit_data(&target, hit).is_critical() {
return; 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()) if side.has_volatile(ReflectEffect::get_const_name())
&& mv.use_move().category() == MoveCategory::Physical && mv.use_move().category() == MoveCategory::Physical
{ {

View File

@ -1,7 +1,8 @@
use crate::script; use crate::script;
use alloc::rc::Rc;
use core::any::Any; use core::any::Any;
use core::sync::atomic::{AtomicI8, Ordering}; 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::{ use pkmn_lib_interface::app_interface::{
DynamicLibrary, EffectParameter, ExecutingMove, Pokemon, Statistic, DynamicLibrary, EffectParameter, ExecutingMove, Pokemon, Statistic,
}; };
@ -34,7 +35,7 @@ impl Script for ChangeAllTargetStats {
fn on_initialize( fn on_initialize(
&self, &self,
_library: &DynamicLibrary, _library: &DynamicLibrary,
parameters: Option<ImmutableList<EffectParameter>>, parameters: Option<ImmutableList<Rc<EffectParameter>>>,
) { ) {
self.amount.store( self.amount.store(
parameters.unwrap().get(0).unwrap().as_int() as i8, parameters.unwrap().get(0).unwrap().as_int() as i8,

View File

@ -1,3 +1,4 @@
use alloc::rc::Rc;
use core::any::Any; use core::any::Any;
use core::sync::atomic::{AtomicI8, Ordering}; use core::sync::atomic::{AtomicI8, Ordering};
use pkmn_lib_interface::app_interface::list::ImmutableList; use pkmn_lib_interface::app_interface::list::ImmutableList;
@ -42,7 +43,7 @@ macro_rules! change_stat_effect {
fn on_initialize( fn on_initialize(
&self, &self,
_library: &DynamicLibrary, _library: &DynamicLibrary,
parameters: Option<ImmutableList<EffectParameter>>, parameters: Option<ImmutableList<Rc<EffectParameter>>>,
) { ) {
self.amount.store( self.amount.store(
parameters.unwrap().get(0).unwrap().as_int() as i8, parameters.unwrap().get(0).unwrap().as_int() as i8,

View File

@ -1,8 +1,9 @@
use crate::script; use crate::script;
use alloc::rc::Rc;
use atomic_float::AtomicF32; use atomic_float::AtomicF32;
use core::any::Any; use core::any::Any;
use core::sync::atomic::Ordering; 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::app_interface::{DynamicLibrary, EffectParameter, ExecutingMove, Pokemon};
use pkmn_lib_interface::handling::{Script, ScriptCapabilities}; use pkmn_lib_interface::handling::{Script, ScriptCapabilities};
@ -29,7 +30,7 @@ impl Script for Drain {
fn on_initialize( fn on_initialize(
&self, &self,
_library: &DynamicLibrary, _library: &DynamicLibrary,
parameters: Option<ImmutableList<EffectParameter>>, parameters: Option<ImmutableList<Rc<EffectParameter>>>,
) { ) {
self.heal_modifier.store( self.heal_modifier.store(
parameters.unwrap().get(0).unwrap().as_float(), parameters.unwrap().get(0).unwrap().as_float(),

View File

@ -1,16 +1,16 @@
use alloc::rc::Rc; use alloc::rc::Rc;
use crate::app_interface::list::ImmutableList; use crate::app_interface::list::ImmutableList;
use crate::app_interface::BattleSideImpl;
use crate::app_interface::{ 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)] #[cfg_attr(feature = "mock_data", mockall::automock)]
pub trait BattleTrait { pub trait BattleTrait {
fn library(&self) -> DynamicLibrary; fn library(&self) -> DynamicLibrary;
fn parties(&self) -> ImmutableList<BattlePartyImpl>; fn parties(&self) -> ImmutableList<BattleParty>;
fn sides(&self) -> ImmutableList<BattleSideImpl>; fn sides(&self) -> ImmutableList<BattleSide>;
fn random(&self) -> BattleRandom; fn random(&self) -> BattleRandom;
fn choice_queue(&self) -> ChoiceQueue; fn choice_queue(&self) -> ChoiceQueue;
fn get_pokemon(&self, side: u8, index: u8) -> Option<Pokemon>; fn get_pokemon(&self, side: u8, index: u8) -> Option<Pokemon>;
@ -33,6 +33,9 @@ pub type MockBattle = MockBattleTrait;
#[cfg(not(feature = "mock_data"))] #[cfg(not(feature = "mock_data"))]
mod implementation { mod implementation {
use super::*; use super::*;
use crate::app_interface::list::{
BattlePartyImmutableList, BattleSideImmutableList, ImmutableListWasm,
};
use crate::app_interface::PokemonImpl; use crate::app_interface::PokemonImpl;
use crate::app_interface::{ use crate::app_interface::{
BattleParty, BattlePartyImpl, BattleRandom, BattleRandomImpl, BattleSide, BattleSideImpl, BattleParty, BattlePartyImpl, BattleRandom, BattleRandomImpl, BattleSide, BattleSideImpl,
@ -42,15 +45,14 @@ mod implementation {
use crate::handling::Cacheable; use crate::handling::Cacheable;
use crate::{ use crate::{
cached_value, cached_value_getters, wasm_value_getters, wasm_value_getters_extern, cached_value, cached_value_getters, wasm_value_getters, wasm_value_getters_extern,
wasm_value_getters_funcs, DynamicLibrary, ExternRef, ExternalReferenceType, ImmutableList, wasm_value_getters_funcs, ExternRef, ExternalReferenceType, StringKey, VecExternRef,
StringKey, VecExternRef,
}; };
struct BattleInner { struct BattleInner {
reference: ExternRef<BattleImpl>, reference: ExternRef<BattleImpl>,
library: CachedValue<DynamicLibrary>, library: CachedValue<DynamicLibrary>,
parties: CachedValue<ImmutableList<BattlePartyImpl>>, parties: CachedValue<ImmutableList<BattleParty>>,
sides: CachedValue<ImmutableList<BattleSideImpl>>, sides: CachedValue<ImmutableList<BattleSide>>,
random: CachedValue<Rc<BattleRandomImpl>>, random: CachedValue<Rc<BattleRandomImpl>>,
choice_queue: CachedValue<Rc<ChoiceQueueImpl>>, choice_queue: CachedValue<Rc<ChoiceQueueImpl>>,
} }
@ -67,8 +69,14 @@ mod implementation {
inner: Rc::new(BattleInner { inner: Rc::new(BattleInner {
reference, reference,
library: cached_value!({ battle_get_library(reference).get_value().unwrap() }), library: cached_value!({ battle_get_library(reference).get_value().unwrap() }),
parties: cached_value!({ battle_get_parties(reference).get_immutable_list() }), parties: cached_value!({
sides: cached_value!({ battle_get_sides(reference).get_immutable_list() }), 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!({ random: cached_value!({
Rc::new(battle_get_random(reference).get_value().unwrap()) Rc::new(battle_get_random(reference).get_value().unwrap())
}), }),
@ -84,8 +92,8 @@ mod implementation {
impl BattleTrait for BattleImpl { impl BattleTrait for BattleImpl {
cached_value_getters! { cached_value_getters! {
fn library(&self) -> DynamicLibrary; fn library(&self) -> DynamicLibrary;
fn parties(&self) -> ImmutableList<BattlePartyImpl>; fn parties(&self) -> ImmutableList<BattleParty>;
fn sides(&self) -> ImmutableList<BattleSideImpl>; fn sides(&self) -> ImmutableList<BattleSide>;
fn random(&self) -> BattleRandom; fn random(&self) -> BattleRandom;
fn choice_queue(&self) -> ChoiceQueue; fn choice_queue(&self) -> ChoiceQueue;
} }

View File

@ -1,15 +1,5 @@
use crate::app_interface::{Battle, Pokemon, WithVolatile}; 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 alloc::rc::Rc;
use cstr_core::{c_char, CString};
pub trait BattleSideTrait: WithVolatile { pub trait BattleSideTrait: WithVolatile {
fn side_index(&self) -> u8; fn side_index(&self) -> u8;
@ -23,21 +13,32 @@ pub trait BattleSideTrait: WithVolatile {
pub type BattleSide = Rc<dyn BattleSideTrait>; pub type BattleSide = Rc<dyn BattleSideTrait>;
#[cfg(not(feature = "mock_data"))] #[cfg(not(feature = "mock_data"))]
struct BattleSideInner { 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};
struct BattleSideInner {
reference: ExternRef<BattleSideImpl>, reference: ExternRef<BattleSideImpl>,
side_index: CachedValue<u8>, side_index: CachedValue<u8>,
pokemon_per_side: CachedValue<u8>, pokemon_per_side: CachedValue<u8>,
battle: CachedValue<Rc<BattleImpl>>, battle: CachedValue<Rc<BattleImpl>>,
} }
#[derive(Clone)] #[derive(Clone)]
pub struct BattleSideImpl { pub struct BattleSideImpl {
#[cfg(not(feature = "mock_data"))]
inner: Rc<BattleSideInner>, inner: Rc<BattleSideInner>,
} }
#[cfg(not(feature = "mock_data"))] impl BattleSideImpl {
impl BattleSideImpl {
pub fn new(reference: ExternRef<Self>) -> Self { pub fn new(reference: ExternRef<Self>) -> Self {
Self::from_ref(reference, &|reference| Self { Self::from_ref(reference, &|reference| Self {
inner: Rc::new(BattleSideInner { inner: Rc::new(BattleSideInner {
@ -50,10 +51,9 @@ impl BattleSideImpl {
}), }),
}) })
} }
} }
#[cfg(not(feature = "mock_data"))] impl BattleSideTrait for BattleSideImpl {
impl BattleSideTrait for BattleSideImpl {
cached_value_getters! { cached_value_getters! {
fn side_index(&self) -> u8; fn side_index(&self) -> u8;
fn pokemon_per_side(&self) -> u8; fn pokemon_per_side(&self) -> u8;
@ -76,10 +76,9 @@ impl BattleSideTrait for BattleSideImpl {
fn has_fled_battle(&self) -> bool; fn has_fled_battle(&self) -> bool;
fn is_defeated(&self) -> bool; fn is_defeated(&self) -> bool;
} }
} }
#[cfg(not(feature = "mock_data"))] impl WithVolatile for BattleSideImpl {
impl WithVolatile for BattleSideImpl {
fn has_volatile(&self, script_name: &str) -> bool { fn has_volatile(&self, script_name: &str) -> bool {
unsafe { unsafe {
let script_name = CString::new(script_name).unwrap(); let script_name = CString::new(script_name).unwrap();
@ -114,30 +113,30 @@ impl WithVolatile for BattleSideImpl {
let script_name = CString::new(script_name).unwrap(); let script_name = CString::new(script_name).unwrap();
unsafe { battleside_get_volatile(self.inner.reference, script_name.as_ptr()).val() } unsafe { battleside_get_volatile(self.inner.reference, script_name.as_ptr()).val() }
} }
} }
wasm_value_getters_extern! { wasm_value_getters_extern! {
BattleSideImpl, BattleSide, BattleSideImpl, BattleSide,
pub fn has_fled_battle(&self) -> bool; pub fn has_fled_battle(&self) -> bool;
pub fn is_defeated(&self) -> bool; pub fn is_defeated(&self) -> bool;
} }
crate::handling::cacheable::cacheable!(BattleSideImpl); crate::handling::cacheable::cacheable!(BattleSideImpl);
#[cfg(not(feature = "mock_data"))] impl ExternalReferenceType for BattleSideImpl {
impl ExternalReferenceType for BattleSideImpl {
fn from_extern_value(reference: ExternRef<Self>) -> Self { fn from_extern_value(reference: ExternRef<Self>) -> Self {
Self::new(reference) Self::new(reference)
} }
} }
#[cfg(not(feature = "mock_data"))] extern "wasm" {
extern "wasm" {
fn battleside_get_side_index(r: ExternRef<BattleSideImpl>) -> u8; fn battleside_get_side_index(r: ExternRef<BattleSideImpl>) -> u8;
fn battleside_get_pokemon_per_side(r: ExternRef<BattleSideImpl>) -> u8; fn battleside_get_pokemon_per_side(r: ExternRef<BattleSideImpl>) -> u8;
fn battleside_get_battle(r: ExternRef<BattleSideImpl>) -> ExternRef<BattleImpl>; fn battleside_get_battle(r: ExternRef<BattleSideImpl>) -> ExternRef<BattleImpl>;
fn battleside_get_pokemon(r: ExternRef<BattleSideImpl>, index: usize) fn battleside_get_pokemon(
-> ExternRef<PokemonImpl>; r: ExternRef<BattleSideImpl>,
index: usize,
) -> ExternRef<PokemonImpl>;
fn battleside_add_volatile_by_name( fn battleside_add_volatile_by_name(
r: ExternRef<BattleSideImpl>, r: ExternRef<BattleSideImpl>,
@ -147,4 +146,8 @@ extern "wasm" {
fn battleside_has_volatile(r: ExternRef<BattleSideImpl>, name: *const c_char) -> bool; fn battleside_has_volatile(r: ExternRef<BattleSideImpl>, name: *const c_char) -> bool;
fn battleside_remove_volatile(r: ExternRef<BattleSideImpl>, name: *const c_char); fn battleside_remove_volatile(r: ExternRef<BattleSideImpl>, name: *const c_char);
fn battleside_get_volatile(r: ExternRef<BattleSideImpl>, name: *const c_char) -> ScriptPtr; fn battleside_get_volatile(r: ExternRef<BattleSideImpl>, name: *const c_char) -> ScriptPtr;
}
} }
#[cfg(not(feature = "mock_data"))]
pub use implementation::*;

View File

@ -1,44 +1,53 @@
#[cfg(not(feature = "mock_data"))] use crate::app_interface::Pokemon;
use crate::app_interface::PokemonImpl;
use crate::{ExternRef, ExternalReferenceType, Pokemon};
use alloc::rc::Rc; use alloc::rc::Rc;
#[cfg_attr(feature = "mock_data", mockall::automock)]
pub trait ChoiceQueueTrait { pub trait ChoiceQueueTrait {
fn move_pokemon_choice_next(&self, pokemon: &Pokemon) -> bool; fn move_pokemon_choice_next(&self, pokemon: &Pokemon) -> bool;
} }
pub type ChoiceQueue = Rc<dyn ChoiceQueueTrait>; pub type ChoiceQueue = Rc<dyn ChoiceQueueTrait>;
#[cfg(feature = "mock_data")]
#[derive(Clone)] pub type MockChoiceQueue = MockChoiceQueueTrait;
pub struct ChoiceQueueImpl {
reference: ExternRef<ChoiceQueueImpl>,
}
#[cfg(not(feature = "mock_data"))] #[cfg(not(feature = "mock_data"))]
impl ChoiceQueueImpl { mod implementation {
use super::*;
use crate::app_interface::PokemonImpl;
use crate::{ExternRef, ExternalReferenceType};
#[derive(Clone)]
pub struct ChoiceQueueImpl {
reference: ExternRef<ChoiceQueueImpl>,
}
impl ChoiceQueueImpl {
pub fn new(reference: ExternRef<ChoiceQueueImpl>) -> Self { pub fn new(reference: ExternRef<ChoiceQueueImpl>) -> Self {
Self { reference } Self { reference }
} }
}
#[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 ChoiceQueueTrait for ChoiceQueueImpl {
impl ExternalReferenceType 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 { fn from_extern_value(reference: ExternRef<Self>) -> Self {
Self::new(reference) Self::new(reference)
} }
} }
#[cfg(not(feature = "mock_data"))] extern "wasm" {
extern "wasm" {
fn choice_queue_move_pokemon_choice_next( fn choice_queue_move_pokemon_choice_next(
r: ExternRef<ChoiceQueueImpl>, r: ExternRef<ChoiceQueueImpl>,
pokemon: ExternRef<PokemonImpl>, pokemon: ExternRef<PokemonImpl>,
) -> bool; ) -> bool;
}
} }
#[cfg(not(feature = "mock_data"))]
pub use implementation::*;

View File

@ -1,6 +1,6 @@
use crate::app_interface::{ use crate::app_interface::{
AbilityImpl, AbilityIndex, Battle, BattleSide, ClampedStatisticSet, DynamicLibrary, Form, Ability, AbilityIndex, Battle, BattleSide, ClampedStatisticSet, DynamicLibrary, Form, Gender,
Gender, Item, LearnedMove, LevelInt, Nature, Species, Statistic, StatisticSet, TypeIdentifier, Item, LearnedMove, LevelInt, Nature, Species, Statistic, StatisticSet, TypeIdentifier,
WithVolatile, WithVolatile,
}; };
use crate::handling::Script; use crate::handling::Script;
@ -16,7 +16,7 @@ pub trait PokemonTrait: WithVolatile {
fn species(&self) -> Species; fn species(&self) -> Species;
fn form(&self) -> Form; fn form(&self) -> Form;
fn active_ability(&self) -> AbilityImpl; fn active_ability(&self) -> Ability;
fn nature(&self) -> Nature; fn nature(&self) -> Nature;
fn display_species(&self) -> Option<Species>; fn display_species(&self) -> Option<Species>;
fn display_form(&self) -> Option<Form>; fn display_form(&self) -> Option<Form>;
@ -86,14 +86,15 @@ mod implementation {
use super::*; use super::*;
use cstr_core::CString; 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::cached_value::CachedValue;
use crate::handling::Cacheable; use crate::handling::Cacheable;
use crate::implementation::ScriptPtr;
use crate::{ use crate::{
cached_value, cached_value_getters, wasm_optional_reference_getters_extern, cached_value, cached_value_getters, wasm_optional_reference_getters_extern,
wasm_optional_reference_getters_funcs, wasm_reference_getters_extern, wasm_optional_reference_getters_funcs, wasm_reference_getters_extern,
wasm_reference_getters_funcs, wasm_value_getters_extern, wasm_value_getters_funcs, wasm_reference_getters_funcs, wasm_value_getters_extern, wasm_value_getters_funcs,
DynamicLibrary, ExternRef, ExternalReferenceType, Script, ScriptPtr, TypeIdentifier, ExternRef, ExternalReferenceType, Script,
}; };
struct PokemonInner { struct PokemonInner {
@ -234,23 +235,29 @@ mod implementation {
} }
} }
fn battle_side(&self) -> BattleSide { fn battle_side(&self) -> BattleSide {
Rc::new(
self.battle() self.battle()
.unwrap() .unwrap()
.sides() .sides()
.get(self.battle_side_index() as u32) .get(self.battle_side_index() as u32)
.unwrap(), .unwrap()
)
} }
wasm_reference_getters_funcs! { wasm_reference_getters_funcs! {
Pokemon, Pokemon,
fn species(&self) -> Species; fn species(&self) -> Species;
fn form(&self) -> Form; fn form(&self) -> Form;
fn active_ability(&self) -> AbilityImpl;
fn nature(&self) -> Nature; 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! { wasm_optional_reference_getters_funcs! {
Pokemon, Pokemon,
fn display_species(&self) -> Option<Species>; fn display_species(&self) -> Option<Species>;
@ -338,7 +345,6 @@ mod implementation {
} }
} }
#[cfg(not(feature = "mock_data"))]
impl PokemonImpl { impl PokemonImpl {
pub(crate) fn new(reference: ExternRef<Self>) -> Self { pub(crate) fn new(reference: ExternRef<Self>) -> Self {
Self::from_ref(reference, &|reference| Self { Self::from_ref(reference, &|reference| Self {
@ -371,7 +377,6 @@ mod implementation {
} }
} }
#[cfg(not(feature = "mock_data"))]
wasm_reference_getters_extern! { wasm_reference_getters_extern! {
PokemonImpl, Pokemon, PokemonImpl, Pokemon,
pub fn species(&self) -> Species; pub fn species(&self) -> Species;
@ -380,7 +385,6 @@ mod implementation {
pub fn nature(&self) -> Nature; pub fn nature(&self) -> Nature;
} }
#[cfg(not(feature = "mock_data"))]
wasm_optional_reference_getters_extern! { wasm_optional_reference_getters_extern! {
PokemonImpl, Pokemon, PokemonImpl, Pokemon,
pub fn display_species(&self) -> Option<Species>; pub fn display_species(&self) -> Option<Species>;
@ -389,7 +393,6 @@ mod implementation {
pub fn battle(&self) -> Option<BattleImpl>; pub fn battle(&self) -> Option<BattleImpl>;
} }
#[cfg(not(feature = "mock_data"))]
wasm_value_getters_extern! { wasm_value_getters_extern! {
PokemonImpl, Pokemon, PokemonImpl, Pokemon,
pub fn level(&self) -> LevelInt; pub fn level(&self) -> LevelInt;
@ -418,14 +421,12 @@ mod implementation {
crate::handling::cacheable::cacheable!(PokemonImpl); crate::handling::cacheable::cacheable!(PokemonImpl);
#[cfg(not(feature = "mock_data"))]
impl ExternalReferenceType for PokemonImpl { impl ExternalReferenceType for PokemonImpl {
fn from_extern_value(reference: ExternRef<Self>) -> Self { fn from_extern_value(reference: ExternRef<Self>) -> Self {
Self::new(reference) Self::new(reference)
} }
} }
#[cfg(not(feature = "mock_data"))]
extern "wasm" { extern "wasm" {
fn pokemon_get_library(r: ExternRef<PokemonImpl>) -> ExternRef<DynamicLibrary>; fn pokemon_get_library(r: ExternRef<PokemonImpl>) -> ExternRef<DynamicLibrary>;
fn pokemon_get_flat_stats(r: ExternRef<PokemonImpl>) -> ExternRef<StatisticSetImpl<u32>>; fn pokemon_get_flat_stats(r: ExternRef<PokemonImpl>) -> ExternRef<StatisticSetImpl<u32>>;
@ -489,7 +490,7 @@ mockall::mock!(
fn reference(&self) -> u32; fn reference(&self) -> u32;
fn species(&self) -> Species; fn species(&self) -> Species;
fn form(&self) -> Form; fn form(&self) -> Form;
fn active_ability(&self) -> AbilityImpl; fn active_ability(&self) -> Ability;
fn nature(&self) -> Nature; fn nature(&self) -> Nature;
fn display_species(&self) -> Option<Species>; fn display_species(&self) -> Option<Species>;
fn display_form(&self) -> Option<Form>; fn display_form(&self) -> Option<Form>;

View File

@ -1,34 +1,38 @@
use crate::{ExternalReferenceType, VecExternRef}; use crate::{ExternalReferenceType, VecExternRef};
use alloc::boxed::Box;
#[cfg(feature = "mock_data")]
use alloc::rc::Rc; use alloc::rc::Rc;
use alloc::vec::Vec;
use core::marker::PhantomData; pub trait ImmutableListTrait<T> {
fn get(&self, index: u32) -> Option<T>;
}
pub type ImmutableList<T> = Rc<dyn ImmutableListTrait<T>>;
#[cfg(not(feature = "mock_data"))] #[cfg(not(feature = "mock_data"))]
struct ImmutableListInner<T: Clone> { 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<T: Clone> {
extern_ref: VecExternRef<T>, extern_ref: VecExternRef<T>,
resource_type: PhantomData<T>, resource_type: PhantomData<T>,
values: spin::RwLock<Vec<Option<Option<T>>>>, values: spin::RwLock<Vec<Option<Option<Rc<T>>>>>,
} }
#[derive(Clone)] pub(crate) trait ImmutableListWasm<T: Clone + ExternalReferenceType> {
#[cfg(not(feature = "mock_data"))] fn initialize(inner: *const ImmutableListInner<T>) -> Self
pub struct ImmutableList<T> where
where Self: Sized;
T: Clone,
T: ExternalReferenceType,
{
inner: *const ImmutableListInner<T>,
}
#[cfg(not(feature = "mock_data"))] fn new(extern_ref: VecExternRef<T>) -> Self
impl<T> ImmutableList<T> where
where Self: Sized,
T: Clone, {
T: ExternalReferenceType,
{
fn new(extern_ref: VecExternRef<T>) -> Self {
let mut values = Vec::new(); let mut values = Vec::new();
values.resize(extern_ref.len() as usize, None); values.resize(extern_ref.len() as usize, None);
let inner = Box::new(ImmutableListInner { let inner = Box::new(ImmutableListInner {
@ -37,12 +41,13 @@ where
values: spin::RwLock::new(values), values: spin::RwLock::new(values),
}); });
let inner_ptr = Box::into_raw(inner); let inner_ptr = Box::into_raw(inner);
ImmutableList { Self::initialize(inner_ptr)
inner: inner_ptr as *const ImmutableListInner<T>,
}
} }
pub(crate) fn from_ref(extern_ref: VecExternRef<T>) -> Self { fn from_ref(extern_ref: VecExternRef<T>) -> Self
where
Self: Sized,
{
unsafe { unsafe {
if let None = CACHE { if let None = CACHE {
CACHE = Some(hashbrown::HashMap::new()); CACHE = Some(hashbrown::HashMap::new());
@ -53,62 +58,148 @@ where
.get(&extern_ref.get_internal_index()); .get(&extern_ref.get_internal_index());
if let Some(v) = existing { if let Some(v) = existing {
let inner = *v as *const ImmutableListInner<T>; let inner = *v as *const ImmutableListInner<T>;
ImmutableList { inner } Self::initialize(inner)
} else { } else {
let v = Self::new(extern_ref); let v = Self::new(extern_ref);
CACHE CACHE.as_mut().unwrap().insert(
.as_mut() extern_ref.get_internal_index(),
.unwrap() v.get_inner_ptr() as *const u8,
.insert(extern_ref.get_internal_index(), v.inner as *const u8); );
v v
} }
} }
} }
pub fn get(&self, index: u32) -> Option<T> { fn get_inner(&self) -> &ImmutableListInner<T> {
unsafe { unsafe { self.get_inner_ptr().as_ref().unwrap() }
let inner = self.inner.as_ref().unwrap(); }
{ fn get_inner_ptr(&self) -> *const ImmutableListInner<T>;
fn get_cached(&self, index: u32) -> Option<Rc<T>> {
let inner = self.get_inner();
let rg = inner.values.read(); let rg = inner.values.read();
let v = rg.get(index as usize).unwrap(); let v = rg.get(index as usize).unwrap();
if let Some(v) = v { if let Some(v) = v {
return v.clone(); return v.clone();
} }
return None;
} }
fn get_value(&self, index: u32) -> Option<Rc<T>> {
if let Some(cached) = self.get_cached(index) {
return Some(cached);
}
let inner = self.get_inner();
let r = inner.extern_ref.at(index); let r = inner.extern_ref.at(index);
let value = r.get_value(); let value = r.get_value();
let value = if let Some(value) = value {
Some(Rc::new(value))
} else {
None
};
let mut wg = inner.values.write(); let mut wg = inner.values.write();
wg[index as usize] = Some(value); wg[index as usize] = Some(value);
wg[index as usize].as_ref().unwrap().clone() let v = wg[index as usize].as_ref().unwrap().clone();
v
} }
} }
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<EffectParameter>,
}
impl ImmutableListWasm<EffectParameter> for EffectParameterImmutableList {
fn initialize(inner: *const ImmutableListInner<EffectParameter>) -> Self
where
Self: Sized,
{
Self { inner }
}
fn get_inner_ptr(&self) -> *const ImmutableListInner<EffectParameter> {
self.inner
}
}
impl ImmutableListTrait<Rc<EffectParameter>> for EffectParameterImmutableList {
fn get(&self, index: u32) -> Option<Rc<EffectParameter>> {
let v = self.get_value(index);
if let Some(v) = v {
Some(v)
} else {
None
}
}
}
#[derive(Clone)]
pub struct StringKeyImmutableList {
inner: *const ImmutableListInner<StringKey>,
}
impl ImmutableListWasm<StringKey> for StringKeyImmutableList {
fn initialize(inner: *const ImmutableListInner<StringKey>) -> Self
where
Self: Sized,
{
Self { inner }
}
fn get_inner_ptr(&self) -> *const ImmutableListInner<StringKey> {
self.inner
}
}
impl ImmutableListTrait<Rc<StringKey>> for StringKeyImmutableList {
fn get(&self, index: u32) -> Option<Rc<StringKey>> {
let v = self.get_value(index);
if let Some(v) = v {
Some(v)
} else {
None
}
}
}
static mut CACHE: Option<hashbrown::HashMap<u32, *const u8>> = None;
} }
#[cfg(feature = "mock_data")] #[cfg(not(feature = "mock_data"))]
pub struct ImmutableListInner<T> { pub use implementation::*;
values: Vec<T>,
}
#[cfg(feature = "mock_data")]
#[derive(Clone)]
pub struct ImmutableList<T> {
inner: Rc<ImmutableListInner<T>>,
}
#[cfg(feature = "mock_data")]
impl<T> ImmutableList<T>
where
T: Clone,
{
pub fn mock(values: Vec<T>) -> Self {
Self {
inner: Rc::new(ImmutableListInner { values }),
}
}
pub fn get(&self, index: u32) -> Option<T> {
self.inner.values.get(index as usize).cloned()
}
}
static mut CACHE: Option<hashbrown::HashMap<u32, *const u8>> = None;

View File

@ -1,60 +1,13 @@
use crate::handling::cacheable::Cacheable; use crate::StringKey;
use crate::handling::cached_value::CachedValue;
use crate::{
cached_value, cached_value_getters, EffectParameter, ExternRef, ExternalReferenceType,
ImmutableList, StringKey, VecExternRef,
};
use alloc::rc::Rc; use alloc::rc::Rc;
struct AbilityInner {
reference: ExternRef<AbilityImpl>,
name: CachedValue<StringKey>,
effect: CachedValue<StringKey>,
parameters: CachedValue<ImmutableList<EffectParameter>>,
}
#[cfg_attr(test, mockall::automock)] #[cfg_attr(test, mockall::automock)]
pub trait Ability { pub trait AbilityTrait {
fn name(&self) -> StringKey; fn name(&self) -> StringKey;
fn effect(&self) -> StringKey; fn effect(&self) -> StringKey;
} }
#[derive(Clone)] pub type Ability = Rc<dyn AbilityTrait>;
pub struct AbilityImpl {
inner: Rc<AbilityInner>,
}
impl AbilityImpl {
#[cfg(not(feature = "mock_data"))]
pub fn new(reference: ExternRef<Self>) -> 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 {
Self::new(reference)
}
}
crate::handling::cacheable::cacheable!(AbilityImpl);
#[derive(Copy, Clone, Debug, Eq, PartialEq)] #[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[repr(C)] #[repr(C)]
@ -64,8 +17,71 @@ pub struct AbilityIndex {
} }
#[cfg(not(feature = "mock_data"))] #[cfg(not(feature = "mock_data"))]
extern "wasm" { 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<AbilityImpl>,
name: CachedValue<StringKey>,
effect: CachedValue<StringKey>,
parameters: CachedValue<ImmutableList<Rc<EffectParameter>>>,
}
#[derive(Clone)]
pub struct AbilityImpl {
inner: Rc<AbilityInner>,
}
impl AbilityImpl {
#[cfg(not(feature = "mock_data"))]
pub fn new(reference: ExternRef<Self>) -> 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 {
Self::new(reference)
}
}
crate::handling::cacheable::cacheable!(AbilityImpl);
#[cfg(not(feature = "mock_data"))]
extern "wasm" {
fn ability_get_name(r: ExternRef<AbilityImpl>) -> ExternRef<StringKey>; fn ability_get_name(r: ExternRef<AbilityImpl>) -> ExternRef<StringKey>;
fn ability_get_effect(r: ExternRef<AbilityImpl>) -> ExternRef<StringKey>; fn ability_get_effect(r: ExternRef<AbilityImpl>) -> ExternRef<StringKey>;
fn ability_get_parameters(r: ExternRef<AbilityImpl>) -> VecExternRef<EffectParameter>; fn ability_get_parameters(r: ExternRef<AbilityImpl>) -> VecExternRef<EffectParameter>;
}
} }
#[cfg(not(feature = "mock_data"))]
pub use implementation::*;

View File

@ -1,4 +1,5 @@
use crate::{ExternRef, ExternalReferenceType, TypeIdentifier}; use crate::app_interface::TypeIdentifier;
use crate::{ExternRef, ExternalReferenceType};
use alloc::rc::Rc; use alloc::rc::Rc;
use alloc::string::{String, ToString}; use alloc::string::{String, ToString};
use cstr_core::{c_char, CString}; use cstr_core::{c_char, CString};

View File

@ -63,7 +63,6 @@ impl EffectParameter {
} }
panic!("Unexpected effect parameter type: {}", self); panic!("Unexpected effect parameter type: {}", self);
} }
} }
#[cfg(not(feature = "mock_data"))] #[cfg(not(feature = "mock_data"))]

View File

@ -1,9 +1,12 @@
use crate::app_interface::get_hash; 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::cached_value::CachedValue;
use crate::handling::ffi_array::FFIArray;
use crate::handling::Cacheable; use crate::handling::Cacheable;
use crate::{ use crate::{
cached_value, cached_value_getters, ExternRef, ExternalReferenceType, FFIArray, ImmutableList, cached_value, cached_value_getters, ExternRef, ExternalReferenceType, StringKey, VecExternRef,
StringKey, VecExternRef,
}; };
use alloc::rc::Rc; use alloc::rc::Rc;
use alloc::vec::Vec; use alloc::vec::Vec;
@ -97,8 +100,8 @@ struct FormInner {
types: CachedValue<Vec<u8>>, types: CachedValue<Vec<u8>>,
base_experience: CachedValue<u32>, base_experience: CachedValue<u32>,
base_stats: CachedValue<ImmutableStatisticSet>, base_stats: CachedValue<ImmutableStatisticSet>,
abilities: CachedValue<ImmutableList<StringKey>>, abilities: CachedValue<ImmutableList<Rc<StringKey>>>,
hidden_abilities: CachedValue<ImmutableList<StringKey>>, hidden_abilities: CachedValue<ImmutableList<Rc<StringKey>>>,
// moves: CachedValue<LearnableMoves>, // moves: CachedValue<LearnableMoves>,
} }
@ -122,9 +125,19 @@ impl Form {
}), }),
base_experience: cached_value!({ form_get_base_experience(reference) }), base_experience: cached_value!({ form_get_base_experience(reference) }),
base_stats: cached_value!({ form_get_base_stats(reference).get_value().unwrap() }), 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!({ 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 weight(&self) -> f32;
pub fn base_experience(&self) -> u32; pub fn base_experience(&self) -> u32;
pub fn base_stats(&self) -> ImmutableStatisticSet; pub fn base_stats(&self) -> ImmutableStatisticSet;
pub fn abilities(&self) -> ImmutableList<StringKey>; pub fn abilities(&self) -> ImmutableList<Rc<StringKey>>;
pub fn hidden_abilities(&self) -> ImmutableList<StringKey>; pub fn hidden_abilities(&self) -> ImmutableList<Rc<StringKey>>;
} }
pub fn types(&self) -> &Vec<u8> { pub fn types(&self) -> &Vec<u8> {
self.inner.types.value_ref() self.inner.types.value_ref()

View File

@ -1,4 +1,3 @@
use crate::app_interface::list::ImmutableList;
use alloc::rc::Rc; use alloc::rc::Rc;
use core::cmp::Ordering; use core::cmp::Ordering;
use core::hash::{Hash, Hasher}; use core::hash::{Hash, Hasher};
@ -152,15 +151,6 @@ impl<T> VecExternRef<T> {
resource_type: Default::default(), resource_type: Default::default(),
} }
} }
#[cfg(not(feature = "mock_data"))]
pub(crate) fn get_immutable_list(&self) -> ImmutableList<T>
where
T: Clone,
T: ExternalReferenceType,
{
ImmutableList::from_ref(*self)
}
} }
impl<T> Clone for VecExternRef<T> { impl<T> Clone for VecExternRef<T> {

View File

@ -1,10 +1,12 @@
use crate::app_interface::list::ImmutableList; use crate::app_interface::list::ImmutableList;
use crate::app_interface::{ use crate::app_interface::{
Battle, DamageSource, DynamicLibrary, EffectParameter, ExecutingMove, Item, Pokemon, Statistic, Battle, DamageSource, DynamicLibrary, EffectParameter, ExecutingMove, Item, Pokemon, Statistic,
TurnChoice, TypeIdentifier,
}; };
use crate::handling::ScriptCapabilities; use crate::handling::ScriptCapabilities;
use crate::{ExternRef, ExternalReferenceType, ScriptPtr, StringKey, TurnChoice, TypeIdentifier}; use crate::{ExternRef, ExternalReferenceType, StringKey};
use alloc::boxed::Box; use alloc::boxed::Box;
use alloc::rc::Rc;
use core::any::Any; use core::any::Any;
use core::fmt::Debug; use core::fmt::Debug;
@ -25,7 +27,7 @@ pub trait Script {
fn on_initialize( fn on_initialize(
&self, &self,
_library: &DynamicLibrary, _library: &DynamicLibrary,
_parameters: Option<ImmutableList<EffectParameter>>, _parameters: Option<ImmutableList<Rc<EffectParameter>>>,
) { ) {
} }
@ -352,7 +354,7 @@ pub trait Script {
Self: Sized, Self: Sized,
{ {
unsafe { unsafe {
script_get_owner(ScriptPtr::from_existing(self)) script_get_owner(crate::implementation::ScriptPtr::from_existing(self))
.cast::<T>() .cast::<T>()
.get_value() .get_value()
} }
@ -375,5 +377,5 @@ impl Debug for dyn Script {
#[cfg(not(feature = "mock_data"))] #[cfg(not(feature = "mock_data"))]
extern "wasm" { extern "wasm" {
fn script_get_owner(pointer: ScriptPtr) -> ExternRef<u8>; fn script_get_owner(pointer: crate::implementation::ScriptPtr) -> ExternRef<u8>;
} }

View File

@ -22,23 +22,9 @@ extern crate dlmalloc;
#[global_allocator] #[global_allocator]
static ALLOC: dlmalloc::GlobalDlmalloc = dlmalloc::GlobalDlmalloc {}; static ALLOC: dlmalloc::GlobalDlmalloc = dlmalloc::GlobalDlmalloc {};
use crate::app_interface::list::ImmutableList; pub(crate) use crate::app_interface::StringKey;
#[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::handling::extern_ref::*; pub(crate) use crate::handling::extern_ref::*;
use crate::handling::ffi_array::FFIArray; pub(crate) use crate::handling::Script;
#[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;
#[macro_use] #[macro_use]
#[allow(dead_code)] #[allow(dead_code)]
@ -46,17 +32,34 @@ pub mod app_interface;
pub mod handling; pub mod handling;
pub mod utils; pub mod utils;
pub type LoadScriptFnType = Box<dyn Fn(ScriptCategory, &StringKey) -> Option<Box<dyn Script>>>; #[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<LoadScriptFnType> = None; pub type LoadScriptFnType = Box<dyn Fn(ScriptCategory, &StringKey) -> Option<Box<dyn Script>>>;
pub fn set_load_script_fn(f: LoadScriptFnType) { static mut LOAD_SCRIPT_FN: Option<LoadScriptFnType> = None;
pub fn set_load_script_fn(f: LoadScriptFnType) {
unsafe { unsafe {
LOAD_SCRIPT_FN = Some(f); 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 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] #[no_mangle]
#[cfg(not(feature = "mock_data"))]
unsafe extern "wasm" fn $func_name( unsafe extern "wasm" fn $func_name(
$( $(
$par_name: $par_type, $par_name: $par_type,
@ -74,16 +76,16 @@ macro_rules! exported_functions {
}; };
} }
static mut SCRIPT_PTR_CACHE: Option<hashbrown::HashMap<*const dyn Script, u32>> = None; static mut SCRIPT_PTR_CACHE: Option<hashbrown::HashMap<*const dyn Script, u32>> = None;
static mut SCRIPT_PTR_REVERSE_CACHE: Option<hashbrown::HashMap<u32, Box<dyn Script>>> = None; static mut SCRIPT_PTR_REVERSE_CACHE: Option<hashbrown::HashMap<u32, Box<dyn Script>>> = None;
static mut SCRIPT_INDEX_COUNTER: AtomicU32 = AtomicU32::new(1); static mut SCRIPT_INDEX_COUNTER: AtomicU32 = AtomicU32::new(1);
#[repr(C)] #[repr(C)]
pub struct ScriptPtr { pub struct ScriptPtr {
index: u32, index: u32,
} }
impl ScriptPtr { impl ScriptPtr {
fn get_cache<'a>() -> &'a mut HashMap<*const dyn Script, u32> { fn get_cache<'a>() -> &'a mut HashMap<*const dyn Script, u32> {
unsafe { unsafe {
if let None = SCRIPT_PTR_CACHE { if let None = SCRIPT_PTR_CACHE {
@ -143,11 +145,11 @@ impl ScriptPtr {
None None
} }
} }
} }
exported_functions! { exported_functions! {
fn load_script(category: ScriptCategory, name: ExternRef<StringKey>) -> ScriptPtr { fn load_script(category: ScriptCategory, name: ExternRef<StringKey>) -> ScriptPtr {
let name_c = StringKey::new(name); let name_c = StringKey::new(name);
let boxed_script = unsafe { &LOAD_SCRIPT_FN }.as_ref().unwrap()(category, &name_c); let boxed_script = unsafe { &LOAD_SCRIPT_FN }.as_ref().unwrap()(category, &name_c);
if boxed_script.is_none() { if boxed_script.is_none() {
@ -155,524 +157,511 @@ fn load_script(category: ScriptCategory, name: ExternRef<StringKey>) -> ScriptPt
} }
let b = boxed_script.unwrap(); let b = boxed_script.unwrap();
ScriptPtr::new(b) ScriptPtr::new(b)
} }
fn destroy_script(script: *mut Box<dyn Script>) { fn destroy_script(script: *mut Box<dyn Script>) {
// By turning it from a raw pointer back into a Box with from_raw, we give ownership back to rust. // 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. // This lets Rust do the cleanup.
let boxed_script = Box::from_raw(script); let boxed_script = Box::from_raw(script);
drop(boxed_script); drop(boxed_script);
} }
fn script_get_name(script: ScriptPtr) -> *mut c_char { fn script_get_name(script: ScriptPtr) -> *mut c_char {
let c = script.val().unwrap().get_name(); let c = script.val().unwrap().get_name();
CString::new(c).unwrap().into_raw() CString::new(c).unwrap().into_raw()
} }
fn get_script_capabilities(script: ScriptPtr) -> FFIArray<ScriptCapabilities> { fn get_script_capabilities(script: ScriptPtr) -> FFIArray<ScriptCapabilities> {
let c = script.val().unwrap().get_capabilities(); let c = script.val().unwrap().get_capabilities();
FFIArray::new(c) FFIArray::new(c)
} }
fn script_stack(script: ScriptPtr) { fn script_stack(script: ScriptPtr) {
script.val().unwrap().stack(); script.val().unwrap().stack();
} }
fn script_on_remove(script: ScriptPtr) { fn script_on_remove(script: ScriptPtr) {
script.val().unwrap().on_remove(); script.val().unwrap().on_remove();
} }
fn script_on_initialize( fn script_on_initialize(
script: ScriptPtr, script: ScriptPtr,
library: ExternRef<DynamicLibrary>, library: ExternRef<DynamicLibrary>,
parameters: VecExternRef<EffectParameter>, parameters: VecExternRef<EffectParameter>,
) { ) {
let parameters = ImmutableList::from_ref(parameters); let parameters = Rc::new(EffectParameterImmutableList::from_ref(parameters));
script.val().unwrap().on_initialize(&library.not_null(), Some(parameters)); script.val().unwrap().on_initialize(&library.not_null(), Some(parameters));
} }
fn script_on_before_turn( fn script_on_before_turn(
script: ScriptPtr, script: ScriptPtr,
choice: ExternRef<TurnChoice>, choice: ExternRef<TurnChoice>,
) { ) {
script.val().unwrap().on_before_turn(choice.not_null()) script.val().unwrap().on_before_turn(choice.not_null())
} }
fn script_change_speed( fn script_change_speed(
script:ScriptPtr, script:ScriptPtr,
choice: ExternRef<TurnChoice>, choice: ExternRef<TurnChoice>,
speed: *mut u32, speed: *mut u32,
) { ) {
script.val().unwrap().change_speed(choice.not_null(), speed.as_mut().unwrap()) script.val().unwrap().change_speed(choice.not_null(), speed.as_mut().unwrap())
} }
fn script_change_priority( fn script_change_priority(
script: ScriptPtr, script: ScriptPtr,
choice: ExternRef<TurnChoice>, choice: ExternRef<TurnChoice>,
priority: *mut i8, priority: *mut i8,
) { ) {
script.val().unwrap().change_priority(choice.not_null(), priority.as_mut().unwrap()) script.val().unwrap().change_priority(choice.not_null(), priority.as_mut().unwrap())
} }
fn script_change_move( fn script_change_move(
script: ScriptPtr, script: ScriptPtr,
choice: ExternRef<TurnChoice>, choice: ExternRef<TurnChoice>,
mv: *mut ExternRef<StringKey>, mv: *mut ExternRef<StringKey>,
) { ) {
let old = mv.as_ref().unwrap().not_null(); let old = mv.as_ref().unwrap().not_null();
let mut new = old.clone(); let mut new = old.clone();
script.val().unwrap().change_move(choice.not_null(), &mut new); script.val().unwrap().change_move(choice.not_null(), &mut new);
if old != new { if old != new {
*mv = new.ptr(); *mv = new.ptr();
} }
} }
fn script_change_number_of_hits( fn script_change_number_of_hits(
script: ScriptPtr, script: ScriptPtr,
choice: ExternRef<TurnChoice>, choice: ExternRef<TurnChoice>,
out: *mut u8, out: *mut u8,
) { ) {
script.val().unwrap().change_number_of_hits(choice.not_null(), out.as_mut().unwrap()); script.val().unwrap().change_number_of_hits(choice.not_null(), out.as_mut().unwrap());
} }
fn script_prevent_move( fn script_prevent_move(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
out: *mut bool, out: *mut bool,
) { ) {
script.val().unwrap().prevent_move(mv.not_null_rc(), out.as_mut().unwrap()); script.val().unwrap().prevent_move(mv.not_null_rc(), out.as_mut().unwrap());
} }
fn script_fail_move( fn script_fail_move(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
out: *mut bool, out: *mut bool,
) { ) {
script.val().unwrap().fail_move(mv.not_null_rc(), out.as_mut().unwrap()); script.val().unwrap().fail_move(mv.not_null_rc(), out.as_mut().unwrap());
} }
fn script_stop_before_move( fn script_stop_before_move(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
out: *mut bool, out: *mut bool,
) { ) {
script.val().unwrap().stop_before_move(mv.not_null_rc(), out.as_mut().unwrap()); script.val().unwrap().stop_before_move(mv.not_null_rc(), out.as_mut().unwrap());
} }
fn script_on_before_move( fn script_on_before_move(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
) { ) {
script.val().unwrap().on_before_move(mv.not_null_rc()); script.val().unwrap().on_before_move(mv.not_null_rc());
} }
fn script_fail_incoming_move( fn script_fail_incoming_move(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
out: *mut bool, out: *mut bool,
) { ) {
script.val().unwrap().fail_incoming_move(mv.not_null_rc(), target.not_null_rc(), out.as_mut().unwrap()); script.val().unwrap().fail_incoming_move(mv.not_null_rc(), target.not_null_rc(), out.as_mut().unwrap());
} }
fn script_is_invulnerable( fn script_is_invulnerable(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
out: *mut bool, out: *mut bool,
) { ) {
script.val().unwrap().is_invulnerable(mv.not_null_rc(), target.not_null_rc(), out.as_mut().unwrap()); script.val().unwrap().is_invulnerable(mv.not_null_rc(), target.not_null_rc(), out.as_mut().unwrap());
} }
fn script_on_move_miss( fn script_on_move_miss(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
) { ) {
script.val().unwrap().on_move_miss(mv.not_null_rc(), target.not_null_rc()); script.val().unwrap().on_move_miss(mv.not_null_rc(), target.not_null_rc());
} }
fn script_change_move_type( fn script_change_move_type(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
hit: u8, hit: u8,
out: *mut TypeIdentifier, out: *mut TypeIdentifier,
) { ) {
script.val().unwrap().change_move_type(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); script.val().unwrap().change_move_type(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
} }
fn script_change_effectiveness( fn script_change_effectiveness(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
hit: u8, hit: u8,
out: *mut f32, out: *mut f32,
) { ) {
script.val().unwrap().change_effectiveness(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); script.val().unwrap().change_effectiveness(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
} }
fn script_block_critical( fn script_block_critical(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
hit: u8, hit: u8,
out: *mut bool, out: *mut bool,
) { ) {
script.val().unwrap().block_critical(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); script.val().unwrap().block_critical(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
} }
fn script_block_incoming_critical( fn script_block_incoming_critical(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
hit: u8, hit: u8,
out: *mut bool, out: *mut bool,
) { ) {
script.val().unwrap().block_incoming_critical(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); script.val().unwrap().block_incoming_critical(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
} }
fn script_change_accuracy( fn script_change_accuracy(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
hit: u8, hit: u8,
out: *mut u8, out: *mut u8,
) { ) {
script.val().unwrap().change_accuracy(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); script.val().unwrap().change_accuracy(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
} }
fn script_change_critical_stage( fn script_change_critical_stage(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
hit: u8, hit: u8,
out: *mut u8, out: *mut u8,
) { ) {
script.val().unwrap().change_critical_stage(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); script.val().unwrap().change_critical_stage(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
} }
fn script_change_critical_modifier( fn script_change_critical_modifier(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
hit: u8, hit: u8,
out: *mut f32, out: *mut f32,
) { ) {
script.val().unwrap().change_critical_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); script.val().unwrap().change_critical_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
} }
fn script_change_stab_modifier( fn script_change_stab_modifier(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
hit: u8, hit: u8,
out: *mut f32, out: *mut f32,
) { ) {
script.val().unwrap().change_stab_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); script.val().unwrap().change_stab_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
} }
fn script_change_base_power( fn script_change_base_power(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
hit: u8, hit: u8,
out: *mut u8, out: *mut u8,
) { ) {
script.val().unwrap().change_base_power(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); 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( fn script_bypass_defensive_stat_boost(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
hit: u8, hit: u8,
out: *mut bool, out: *mut bool,
) { ) {
script.val().unwrap().bypass_defensive_stat_boost(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); 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( fn script_bypass_offensive_stat_boost(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
hit: u8, hit: u8,
out: *mut bool, out: *mut bool,
) { ) {
script.val().unwrap().bypass_offensive_stat_boost(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); 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( fn script_change_defensive_stat_value(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
hit: u8, hit: u8,
out: *mut u32, out: *mut u32,
) { ) {
script.val().unwrap().change_defensive_stat_value(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); 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( fn script_change_offensive_stat_value(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
hit: u8, hit: u8,
out: *mut u32, out: *mut u32,
) { ) {
script.val().unwrap().change_offensive_stat_value(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); 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( fn script_change_damage_stat_modifier(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
hit: u8, hit: u8,
out: *mut f32, out: *mut f32,
) { ) {
script.val().unwrap().change_damage_stat_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); 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( fn script_change_damage_modifier(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
hit: u8, hit: u8,
out: *mut f32, out: *mut f32,
) { ) {
script.val().unwrap().change_damage_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); script.val().unwrap().change_damage_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
} }
fn script_change_damage( fn script_change_damage(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
hit: u8, hit: u8,
out: *mut u32, out: *mut u32,
) { ) {
script.val().unwrap().change_damage(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); script.val().unwrap().change_damage(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
} }
fn script_change_incoming_damage( fn script_change_incoming_damage(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
hit: u8, hit: u8,
out: *mut u32, out: *mut u32,
) { ) {
script.val().unwrap().change_incoming_damage(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); script.val().unwrap().change_incoming_damage(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
} }
fn script_on_incoming_hit( fn script_on_incoming_hit(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
hit: u8, hit: u8,
) { ) {
script.val().unwrap().on_incoming_hit(mv.not_null_rc(), target.not_null_rc(), hit); script.val().unwrap().on_incoming_hit(mv.not_null_rc(), target.not_null_rc(), hit);
} }
fn script_on_opponent_faints( fn script_on_opponent_faints(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
hit: u8, hit: u8,
) { ) {
script.val().unwrap().on_opponent_faints(mv.not_null_rc(), target.not_null_rc(), hit); script.val().unwrap().on_opponent_faints(mv.not_null_rc(), target.not_null_rc(), hit);
} }
fn script_prevent_stat_boost_change( fn script_prevent_stat_boost_change(
script: ScriptPtr, script: ScriptPtr,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
stat: Statistic, stat: Statistic,
amount: i8, amount: i8,
self_inflicted: u8, self_inflicted: u8,
out: *mut bool, out: *mut bool,
) { ) {
script.val().unwrap().prevent_stat_boost_change(target.not_null_rc(), stat, amount, self_inflicted == 1, out.as_mut().unwrap()); 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( fn script_prevent_secondary_effect(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
hit: u8, hit: u8,
out: *mut bool, out: *mut bool,
) { ) {
script.val().unwrap().prevent_secondary_effect(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); script.val().unwrap().prevent_secondary_effect(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
} }
fn script_change_effect_chance( fn script_change_effect_chance(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
hit: u8, hit: u8,
out: *mut f32, out: *mut f32,
) { ) {
script.val().unwrap().change_effect_chance(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); 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( fn script_change_incoming_effect_chance(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
hit: u8, hit: u8,
out: *mut f32, out: *mut f32,
) { ) {
script.val().unwrap().change_incoming_effect_chance(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()); 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( fn script_on_secondary_effect(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
hit: u8, hit: u8,
) { ) {
script.val().unwrap().on_secondary_effect(mv.not_null_rc(), target.not_null_rc(), hit); script.val().unwrap().on_secondary_effect(mv.not_null_rc(), target.not_null_rc(), hit);
} }
fn script_on_after_hits( fn script_on_after_hits(
script: ScriptPtr, script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>, mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
) { ) {
script.val().unwrap().on_after_hits(mv.not_null_rc(), target.not_null_rc()); script.val().unwrap().on_after_hits(mv.not_null_rc(), target.not_null_rc());
} }
fn script_prevent_self_switch( fn script_prevent_self_switch(
script: ScriptPtr, script: ScriptPtr,
choice: ExternRef<TurnChoice>, choice: ExternRef<TurnChoice>,
out: *mut bool, out: *mut bool,
) { ) {
script.val().unwrap().prevent_self_switch(choice.not_null(), out.as_mut().unwrap()); script.val().unwrap().prevent_self_switch(choice.not_null(), out.as_mut().unwrap());
} }
fn script_prevent_opponent_switch( fn script_prevent_opponent_switch(
script: ScriptPtr, script: ScriptPtr,
choice: ExternRef<TurnChoice>, choice: ExternRef<TurnChoice>,
out: *mut bool, out: *mut bool,
) { ) {
script.val().unwrap().prevent_opponent_switch(choice.not_null(), out.as_mut().unwrap()); script.val().unwrap().prevent_opponent_switch(choice.not_null(), out.as_mut().unwrap());
} }
fn script_on_fail( fn script_on_fail(
script: ScriptPtr, script: ScriptPtr,
pokemon: ExternRef<PokemonImpl>, pokemon: ExternRef<PokemonImpl>,
) { ) {
script.val().unwrap().on_fail(pokemon.not_null_rc()); script.val().unwrap().on_fail(pokemon.not_null_rc());
} }
fn script_on_opponent_fail( fn script_on_opponent_fail(
script: ScriptPtr, script: ScriptPtr,
pokemon: ExternRef<PokemonImpl>, pokemon: ExternRef<PokemonImpl>,
) { ) {
script.val().unwrap().on_opponent_fail(pokemon.not_null_rc()); script.val().unwrap().on_opponent_fail(pokemon.not_null_rc());
} }
fn script_prevent_self_run_away( fn script_prevent_self_run_away(
script: ScriptPtr, script: ScriptPtr,
choice: ExternRef<TurnChoice>, choice: ExternRef<TurnChoice>,
out: *mut bool, out: *mut bool,
) { ) {
script.val().unwrap().prevent_self_run_away(choice.not_null(), out.as_mut().unwrap()); script.val().unwrap().prevent_self_run_away(choice.not_null(), out.as_mut().unwrap());
} }
fn script_prevent_opponent_run_away( fn script_prevent_opponent_run_away(
script: ScriptPtr, script: ScriptPtr,
choice: ExternRef<TurnChoice>, choice: ExternRef<TurnChoice>,
out: *mut bool, out: *mut bool,
) { ) {
script.val().unwrap().prevent_opponent_run_away(choice.not_null(), out.as_mut().unwrap()); script.val().unwrap().prevent_opponent_run_away(choice.not_null(), out.as_mut().unwrap());
} }
fn script_on_end_turn( fn script_on_end_turn(
script: ScriptPtr, script: ScriptPtr,
) { ) {
script.val().unwrap().on_end_turn(); script.val().unwrap().on_end_turn();
} }
fn script_on_damage( fn script_on_damage(
script: ScriptPtr, script: ScriptPtr,
pokemon: ExternRef<PokemonImpl>, pokemon: ExternRef<PokemonImpl>,
source: DamageSource, source: DamageSource,
old_health: u32, old_health: u32,
new_health: u32, new_health: u32,
) { ) {
script.val().unwrap().on_damage(pokemon.not_null_rc(), source, old_health, new_health); script.val().unwrap().on_damage(pokemon.not_null_rc(), source, old_health, new_health);
} }
fn script_on_faint( fn script_on_faint(
script: ScriptPtr, script: ScriptPtr,
pokemon: ExternRef<PokemonImpl>, pokemon: ExternRef<PokemonImpl>,
source: DamageSource, source: DamageSource,
) { ) {
script.val().unwrap().on_faint(pokemon.not_null_rc(), source); script.val().unwrap().on_faint(pokemon.not_null_rc(), source);
} }
fn script_on_switch_in( fn script_on_switch_in(
script: ScriptPtr, script: ScriptPtr,
pokemon: ExternRef<PokemonImpl>, pokemon: ExternRef<PokemonImpl>,
) { ) {
script.val().unwrap().on_switch_in(pokemon.not_null_rc()); script.val().unwrap().on_switch_in(pokemon.not_null_rc());
} }
fn script_on_after_held_item_consume( fn script_on_after_held_item_consume(
script: ScriptPtr, script: ScriptPtr,
pokemon: ExternRef<PokemonImpl>, pokemon: ExternRef<PokemonImpl>,
item: ExternRef<ItemImpl> item: ExternRef<ItemImpl>
) { ) {
script.val().unwrap().on_after_held_item_consume(pokemon.not_null_rc(), item.not_null_rc()); script.val().unwrap().on_after_held_item_consume(pokemon.not_null_rc(), item.not_null_rc());
} }
fn script_change_experience_gained( fn script_change_experience_gained(
script: ScriptPtr, script: ScriptPtr,
fainted_pokemon: ExternRef<PokemonImpl>, fainted_pokemon: ExternRef<PokemonImpl>,
winning_pokemon: ExternRef<PokemonImpl>, winning_pokemon: ExternRef<PokemonImpl>,
out: *mut u32 out: *mut u32
) { ) {
script.val().unwrap().change_experience_gained(fainted_pokemon.not_null_rc(), winning_pokemon.not_null_rc(), out.as_mut().unwrap()); script.val().unwrap().change_experience_gained(fainted_pokemon.not_null_rc(), winning_pokemon.not_null_rc(), out.as_mut().unwrap());
} }
fn script_share_experience( fn script_share_experience(
script: ScriptPtr, script: ScriptPtr,
fainted_pokemon: ExternRef<PokemonImpl>, fainted_pokemon: ExternRef<PokemonImpl>,
winning_pokemon: ExternRef<PokemonImpl>, winning_pokemon: ExternRef<PokemonImpl>,
out: *mut bool, out: *mut bool,
) { ) {
script.val().unwrap().share_experience(fainted_pokemon.not_null_rc(), winning_pokemon.not_null_rc(), out.as_mut().unwrap()); script.val().unwrap().share_experience(fainted_pokemon.not_null_rc(), winning_pokemon.not_null_rc(), out.as_mut().unwrap());
} }
fn script_block_weather( fn script_block_weather(
script: ScriptPtr, script: ScriptPtr,
battle: ExternRef<BattleImpl>, battle: ExternRef<BattleImpl>,
out: *mut bool, out: *mut bool,
) { ) {
script.val().unwrap().block_weather(battle.not_null_rc(), out.as_mut().unwrap()); script.val().unwrap().block_weather(battle.not_null_rc(), out.as_mut().unwrap());
} }
fn script_change_capture_rate_bonus( fn script_change_capture_rate_bonus(
script: ScriptPtr, script: ScriptPtr,
target: ExternRef<PokemonImpl>, target: ExternRef<PokemonImpl>,
pokeball: ExternRef<ItemImpl>, pokeball: ExternRef<ItemImpl>,
out: *mut u8, out: *mut u8,
) { ) {
script.val().unwrap().change_capture_rate_bonus(target.not_null_rc(), pokeball.not_null_rc(), out.as_mut().unwrap()); 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::*;
}