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

209 lines
7.0 KiB
Rust
Executable File

use crate::app_interface::{LearnedMove, Pokemon};
use crate::handling::Script;
use alloc::boxed::Box;
use alloc::rc::Rc;
pub enum TurnChoice {
Move(Box<dyn MoveTurnChoiceDataTrait>),
Item(),
Switch(),
Flee,
Pass,
}
impl TurnChoice {
fn base(&self) -> BaseTurnChoiceData {
match self {
TurnChoice::Move(m) => m.base(),
TurnChoice::Item() => unimplemented!(),
TurnChoice::Switch() => unimplemented!(),
TurnChoice::Flee => unimplemented!(),
TurnChoice::Pass => unimplemented!(),
}
}
pub fn user(&self) -> Pokemon {
self.base().user()
}
pub fn speed(&self) -> PkmnResult<u32> {
self.base().speed()
}
pub fn has_failed(&self) -> PkmnResult<bool> {
self.base().has_failed()
}
pub fn fail(&self) -> PkmnResult<()> {
self.base().fail()
}
}
#[cfg_attr(feature = "mock_data", mockall::automock)]
pub trait BaseTurnChoiceDataTrait {
fn reference(&self) -> u32;
fn user(&self) -> Pokemon;
fn speed(&self) -> PkmnResult<u32>;
fn has_failed(&self) -> PkmnResult<bool>;
fn fail(&self) -> PkmnResult<()>;
}
pub type BaseTurnChoiceData = Rc<dyn BaseTurnChoiceDataTrait>;
#[cfg(feature = "mock_data")]
pub type MockBaseTurnChoiceData = MockBaseTurnChoiceDataTrait;
#[cfg_attr(feature = "mock_data", mockall::automock)]
pub trait MoveTurnChoiceDataTrait {
fn base(&self) -> BaseTurnChoiceData;
fn used_move(&self) -> LearnedMove;
fn target_side(&self) -> u8;
fn target_index(&self) -> u8;
fn priority(&self) -> PkmnResult<i8>;
fn move_script<'a>(&self) -> PkmnResult<Option<&'a Box<dyn Script>>>;
}
#[cfg(feature = "mock_data")]
pub type MockMoveTurnChoiceData = MockMoveTurnChoiceDataTrait;
#[cfg(not(feature = "mock_data"))]
mod implementation {
use super::*;
use crate::app_interface::{LearnedMoveImpl, PokemonImpl};
use crate::handling::cached_value::CachedValue;
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
use crate::handling::temporary::Temporary;
use crate::handling::wasm_result::WasmResult;
use crate::{cached_value, PkmnResult};
struct BaseTurnChoiceDataImpl {
reference: ExternRef<TurnChoice>,
user: CachedValue<Rc<PokemonImpl>>,
}
impl BaseTurnChoiceDataTrait for BaseTurnChoiceDataImpl {
fn reference(&self) -> u32 {
self.reference.get_internal_index()
}
fn user(&self) -> Pokemon {
self.user.value()
}
fn speed(&self) -> PkmnResult<u32> {
unsafe { turn_choice_get_speed(self.reference).as_res() }
}
fn has_failed(&self) -> PkmnResult<bool> {
unsafe { turn_choice_has_failed(self.reference).as_res() }
}
fn fail(&self) -> PkmnResult<()> {
unsafe { turn_choice_fail(self.reference).as_res() }
}
}
struct MoveTurnChoiceDataInner {
base: BaseTurnChoiceData,
used_move: CachedValue<LearnedMove>,
target_side: CachedValue<u8>,
target_index: CachedValue<u8>,
}
#[derive(Clone)]
pub struct MoveTurnChoiceDataImpl {
inner: Temporary<MoveTurnChoiceDataInner>,
}
#[cfg(not(feature = "mock_data"))]
impl MoveTurnChoiceDataTrait for MoveTurnChoiceDataImpl {
fn base(&self) -> BaseTurnChoiceData {
self.inner.value().base.clone()
}
fn used_move(&self) -> LearnedMove {
self.inner.value().used_move.value()
}
fn target_side(&self) -> u8 {
self.inner.value().target_side.value()
}
fn target_index(&self) -> u8 {
self.inner.value().target_index.value()
}
fn priority(&self) -> PkmnResult<i8> {
unsafe { turn_choice_move_priority(self.base().reference().into()).as_res() }
}
fn move_script<'a>(&self) -> PkmnResult<Option<&'a Box<dyn Script>>> {
unsafe {
Ok(
(turn_choice_move_script(self.base().reference().into()).as_res()?
as *const Box<dyn Script>)
.as_ref(),
)
}
}
}
#[cfg(not(feature = "mock_data"))]
impl ExternalReferenceType for TurnChoice {
fn from_extern_value(reference: ExternRef<Self>) -> Self {
let kind = unsafe { turn_choice_get_kind(reference).unwrap() };
match kind {
0 => TurnChoice::Move(Box::new(MoveTurnChoiceDataImpl {
inner: Temporary::new(
reference.get_internal_index(),
MoveTurnChoiceDataInner::from_reference(reference.cast()),
),
})),
_ => panic!("Unknown turn choice type"),
}
}
}
#[cfg(not(feature = "mock_data"))]
impl MoveTurnChoiceDataInner {
fn from_reference(reference: ExternRef<MoveTurnChoiceDataImpl>) -> Self {
Self {
base: Rc::new(BaseTurnChoiceDataImpl {
reference: reference.cast(),
user: cached_value!({
Rc::new(
turn_choice_get_user(reference.cast())
.unwrap()
.get_value()
.unwrap(),
)
}),
}),
used_move: cached_value!({
Rc::new(
turn_choice_move_used_move(reference.cast())
.unwrap()
.get_value()
.unwrap(),
)
}),
target_side: cached_value!({
turn_choice_move_target_side(reference.cast()).unwrap()
}),
target_index: cached_value!({
turn_choice_move_target_index(reference.cast()).unwrap()
}),
}
}
}
extern "wasm" {
fn turn_choice_get_kind(r: ExternRef<TurnChoice>) -> WasmResult<u8>;
fn turn_choice_get_user(r: ExternRef<TurnChoice>) -> WasmResult<ExternRef<PokemonImpl>>;
fn turn_choice_get_speed(r: ExternRef<TurnChoice>) -> WasmResult<u32>;
fn turn_choice_has_failed(r: ExternRef<TurnChoice>) -> WasmResult<bool>;
fn turn_choice_fail(r: ExternRef<TurnChoice>) -> WasmResult<()>;
fn turn_choice_move_used_move(
r: ExternRef<MoveTurnChoiceDataImpl>,
) -> WasmResult<ExternRef<LearnedMoveImpl>>;
fn turn_choice_move_target_side(r: ExternRef<MoveTurnChoiceDataImpl>) -> WasmResult<u8>;
fn turn_choice_move_target_index(r: ExternRef<MoveTurnChoiceDataImpl>) -> WasmResult<u8>;
fn turn_choice_move_priority(r: ExternRef<MoveTurnChoiceDataImpl>) -> WasmResult<i8>;
#[allow(improper_ctypes)]
fn turn_choice_move_script(r: ExternRef<MoveTurnChoiceDataImpl>) -> WasmResult<u32>;
}
}
use crate::PkmnResult;
#[cfg(not(feature = "mock_data"))]
pub use implementation::*;