Gen7ScriptsRs/pkmn_lib_interface/src/app_interface/dynamic_data/battle.rs

194 lines
6.9 KiB
Rust
Executable File

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<BattleParty>;
fn sides(&self) -> ImmutableList<BattleSide>;
fn random(&self) -> BattleRandom;
fn choice_queue(&self) -> ChoiceQueue;
fn get_pokemon(&self, side: u8, index: u8) -> Option<Pokemon>;
fn find_party_for_pokemon(&self, pokemon: &Pokemon) -> Option<BattleParty>;
fn weather_name(&self) -> Option<StringKey>;
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<dyn BattleTrait>;
#[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<BattleImpl>,
library: CachedValue<DynamicLibrary>,
parties: CachedValue<ImmutableList<BattleParty>>,
sides: CachedValue<ImmutableList<BattleSide>>,
random: CachedValue<Rc<BattleRandomImpl>>,
choice_queue: CachedValue<Rc<ChoiceQueueImpl>>,
}
#[derive(Clone)]
pub struct BattleImpl {
inner: Rc<BattleInner>,
}
#[cfg(not(feature = "mock_data"))]
impl BattleImpl {
pub fn new(reference: ExternRef<BattleImpl>) -> 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<BattleParty>;
fn sides(&self) -> ImmutableList<BattleSide>;
fn random(&self) -> BattleRandom;
fn choice_queue(&self) -> ChoiceQueue;
}
fn get_pokemon(&self, side: u8, index: u8) -> Option<Pokemon> {
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<BattleParty> {
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<StringKey> {
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 {
Self::new(reference)
}
}
#[cfg(not(feature = "mock_data"))]
extern "wasm" {
fn battle_get_library(r: ExternRef<BattleImpl>) -> ExternRef<DynamicLibraryImpl>;
fn battle_get_parties(r: ExternRef<BattleImpl>) -> VecExternRef<BattlePartyImpl>;
fn battle_get_sides(r: ExternRef<BattleImpl>) -> VecExternRef<BattleSideImpl>;
fn battle_get_random(r: ExternRef<BattleImpl>) -> ExternRef<BattleRandomImpl>;
fn battle_get_choice_queue(r: ExternRef<BattleImpl>) -> ExternRef<ChoiceQueueImpl>;
fn battle_get_pokemon(
r: ExternRef<BattleImpl>,
side: u8,
index: u8,
) -> ExternRef<PokemonImpl>;
fn battle_find_party_for_pokemon(
r: ExternRef<BattleImpl>,
mon: ExternRef<PokemonImpl>,
) -> ExternRef<BattlePartyImpl>;
fn battle_get_weather_name(r: ExternRef<BattleImpl>) -> ExternRef<StringKey>;
}
}
#[cfg(not(feature = "mock_data"))]
pub use implementation::*;