use alloc::rc::Rc; use crate::app_interface::list::ImmutableList; use crate::app_interface::{ BattleParty, 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 random(&self) -> BattleRandom; fn choice_queue(&self) -> ChoiceQueue; fn get_pokemon(&self, side: u8, index: u8) -> Option; fn find_party_for_pokemon(&self, pokemon: &Pokemon) -> Option; fn weather_name(&self) -> Option; fn has_weather(&self, name: &str) -> bool; fn can_flee(&self) -> bool; fn number_of_sides(&self) -> u8; fn pokemon_per_side(&self) -> u8; fn has_ended(&self) -> bool; fn has_ended_conclusively(&self) -> bool; fn winning_side(&self) -> u8; fn current_turn(&self) -> u32; } pub type Battle = Rc; #[cfg(feature = "mock_data")] pub type MockBattle = MockBattleTrait; #[cfg(not(feature = "mock_data"))] mod implementation { use super::*; use crate::app_interface::dynamic_data::dynamic_library::DynamicLibraryImpl; use crate::app_interface::list::{ BattlePartyImmutableList, BattleSideImmutableList, ImmutableListWasm, }; use crate::app_interface::PokemonImpl; use crate::app_interface::{ BattleParty, BattlePartyImpl, BattleRandom, BattleRandomImpl, BattleSide, BattleSideImpl, ChoiceQueue, ChoiceQueueImpl, Pokemon, }; use crate::handling::cached_value::CachedValue; use crate::handling::Cacheable; use crate::{ cached_value, cached_value_getters, wasm_value_getters_extern, wasm_value_getters_funcs, ExternRef, ExternalReferenceType, StringKey, VecExternRef, }; struct BattleInner { reference: ExternRef, library: CachedValue, parties: CachedValue>, sides: CachedValue>, random: CachedValue>, choice_queue: CachedValue>, } #[derive(Clone)] pub struct BattleImpl { inner: Rc, } #[cfg(not(feature = "mock_data"))] impl BattleImpl { pub fn new(reference: ExternRef) -> Self { Self::from_ref(reference, &|reference| Self { inner: Rc::new(BattleInner { reference, library: cached_value!({ Rc::new(battle_get_library(reference).get_value().unwrap()) }), 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()) }), choice_queue: cached_value!({ Rc::new(battle_get_choice_queue(reference).get_value().unwrap()) }), }), }) } } #[cfg(not(feature = "mock_data"))] impl BattleTrait for BattleImpl { cached_value_getters! { fn library(&self) -> DynamicLibrary; 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 { unsafe { let v = battle_get_pokemon(self.inner.reference, side, index).get_value(); if let Some(v) = v { Some(Rc::new(v)) } else { None } } } fn find_party_for_pokemon(&self, pokemon: &Pokemon) -> Option { unsafe { let b = battle_find_party_for_pokemon(self.inner.reference, pokemon.reference().into()) .get_value(); if let Some(b) = b { Some(Rc::new(b)) } else { None } } } fn weather_name(&self) -> Option { unsafe { battle_get_weather_name(self.inner.reference).get_value() } } fn has_weather(&self, name: &str) -> bool { if let Some(weather) = self.weather_name() { if weather.equals_str(name) { return true; } } false } wasm_value_getters_funcs! { Battle, fn can_flee(&self) -> bool; fn number_of_sides(&self) -> u8; fn pokemon_per_side(&self) -> u8; fn has_ended(&self) -> bool; fn has_ended_conclusively(&self) -> bool; fn winning_side(&self) -> u8; fn current_turn(&self) -> u32; } } wasm_value_getters_extern! { BattleImpl, Battle, pub fn can_flee(&self) -> bool; pub fn number_of_sides(&self) -> u8; pub fn pokemon_per_side(&self) -> u8; pub fn has_ended(&self) -> bool; pub fn has_ended_conclusively(&self) -> bool; pub fn winning_side(&self) -> u8; pub fn current_turn(&self) -> u32; } crate::handling::cacheable::cacheable!(BattleImpl); #[cfg(not(feature = "mock_data"))] impl ExternalReferenceType for BattleImpl { fn from_extern_value(reference: ExternRef) -> Self { Self::new(reference) } } #[cfg(not(feature = "mock_data"))] extern "wasm" { fn battle_get_library(r: ExternRef) -> ExternRef; fn battle_get_parties(r: ExternRef) -> VecExternRef; fn battle_get_sides(r: ExternRef) -> VecExternRef; fn battle_get_random(r: ExternRef) -> ExternRef; fn battle_get_choice_queue(r: ExternRef) -> ExternRef; fn battle_get_pokemon( r: ExternRef, side: u8, index: u8, ) -> ExternRef; fn battle_find_party_for_pokemon( r: ExternRef, mon: ExternRef, ) -> ExternRef; fn battle_get_weather_name(r: ExternRef) -> ExternRef; } } #[cfg(not(feature = "mock_data"))] pub use implementation::*;