Rework ScriptOwners to be a little easier to use
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Deukhoofd 2023-01-06 11:10:30 +01:00
parent d4c30d50aa
commit 258c497982
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
4 changed files with 96 additions and 23 deletions

View File

@ -5,6 +5,7 @@ use core::sync::atomic::{AtomicBool, Ordering};
use pkmn_lib_interface::app_interface::{ use pkmn_lib_interface::app_interface::{
BattleSide, DamageSource, ExecutingMove, Pokemon, TurnChoice, WithVolatile, BattleSide, DamageSource, ExecutingMove, Pokemon, TurnChoice, WithVolatile,
}; };
use pkmn_lib_interface::handling::script::ScriptOwner;
use pkmn_lib_interface::handling::{Script, ScriptCapabilities}; use pkmn_lib_interface::handling::{Script, ScriptCapabilities};
script!(Assurance, "assurance"); script!(Assurance, "assurance");
@ -86,9 +87,8 @@ impl Script for AssuranceData {
&[ScriptCapabilities::OnEndTurn, ScriptCapabilities::OnDamage] &[ScriptCapabilities::OnEndTurn, ScriptCapabilities::OnDamage]
} }
#[cfg(not(test))]
fn on_end_turn(&self) { fn on_end_turn(&self) {
let side: pkmn_lib_interface::app_interface::BattleSideImpl = self.get_owner().unwrap(); let side = self.get_owner().unwrap().as_side();
side.remove_volatile(self); side.remove_volatile(self);
} }

View File

@ -63,7 +63,6 @@ impl Script for AuroraVeilEffect {
&[ScriptCapabilities::ChangeIncomingDamage, OnEndTurn] &[ScriptCapabilities::ChangeIncomingDamage, OnEndTurn]
} }
#[cfg(not(test))]
fn change_incoming_damage( fn change_incoming_damage(
&self, &self,
mv: ExecutingMove, mv: ExecutingMove,
@ -74,7 +73,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: pkmn_lib_interface::app_interface::BattleSideImpl = self.get_owner().unwrap(); let side = self.get_owner().unwrap().as_side();
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,13 +1,14 @@
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, BattleSide, DamageSource, DynamicLibrary, EffectParameter, ExecutingMove, Item,
TurnChoice, TypeIdentifier, Pokemon, Statistic, TurnChoice, TypeIdentifier,
}; };
use crate::handling::ScriptCapabilities; use crate::handling::ScriptCapabilities;
use crate::{ExternRef, ExternalReferenceType, StringKey}; use crate::{ExternRef, ExternalReferenceType, StringKey};
use alloc::rc::Rc; use alloc::rc::Rc;
use core::any::Any; use core::any::Any;
use core::fmt::Debug; use core::fmt::{Debug, Display, Formatter};
use core::panicking::panic;
pub trait Script { pub trait Script {
fn new() -> Self fn new() -> Self
@ -346,25 +347,11 @@ pub trait Script {
fn as_any(&self) -> &dyn Any; fn as_any(&self) -> &dyn Any;
#[cfg(not(feature = "mock_data"))] fn get_owner(&self) -> Option<ScriptOwner>
fn get_owner<T>(&self) -> Option<T>
where
T: ExternalReferenceType,
Self: Sized,
{
unsafe {
script_get_owner(crate::implementation::ScriptPtr::from_existing(self))
.cast::<T>()
.get_value()
}
}
#[cfg(feature = "mock_data")]
fn get_owner<T>(&self) -> Option<T>
where where
Self: Sized, Self: Sized,
{ {
unimplemented!() ScriptOwner::from_script(self)
} }
} }
@ -376,5 +363,91 @@ impl Debug for dyn Script {
#[cfg(not(feature = "mock_data"))] #[cfg(not(feature = "mock_data"))]
extern "wasm" { extern "wasm" {
fn script_get_owner_kind(pointer: crate::implementation::ScriptPtr) -> u8;
fn script_get_owner(pointer: crate::implementation::ScriptPtr) -> ExternRef<u8>; fn script_get_owner(pointer: crate::implementation::ScriptPtr) -> ExternRef<u8>;
} }
pub enum ScriptOwner {
Pokemon(Pokemon),
BattleSide(BattleSide),
Battle(Battle),
None,
}
impl ScriptOwner {
#[cfg(not(feature = "mock_data"))]
fn from_script(script: &dyn Script) -> Option<ScriptOwner> {
let script_ptr = crate::implementation::ScriptPtr::from_existing(script);
unsafe {
let kind = script_get_owner_kind(script_ptr);
match kind {
0 => {
let r = script_get_owner(script_ptr)
.cast::<crate::app_interface::PokemonImpl>()
.get_value();
if r.is_none() {
None
} else {
Some(ScriptOwner::Pokemon(Rc::new(r.unwrap())))
}
}
1 => {
let r = script_get_owner(script_ptr)
.cast::<crate::app_interface::BattleSideImpl>()
.get_value();
if r.is_none() {
None
} else {
Some(ScriptOwner::BattleSide(Rc::new(r.unwrap())))
}
}
2 => {
let r = script_get_owner(script_ptr)
.cast::<crate::app_interface::BattleImpl>()
.get_value();
if r.is_none() {
None
} else {
Some(ScriptOwner::Battle(Rc::new(r.unwrap())))
}
}
_ => panic!("Unknown script owner kind: {}", kind),
}
}
}
#[cfg(feature = "mock_data")]
fn from_script(script: &dyn Script) -> Option<ScriptOwner> {
unimplemented!();
}
pub fn as_pokemon(&self) -> Pokemon {
if let ScriptOwner::Pokemon(p) = self {
return p.clone();
}
panic!("ScriptOwner was not a Pokemon, but a {self}");
}
pub fn as_side(&self) -> BattleSide {
if let ScriptOwner::BattleSide(p) = self {
return p.clone();
}
panic!("ScriptOwner was not a BattleSide, but a {self}");
}
pub fn as_battle(&self) -> Battle {
if let ScriptOwner::Battle(p) = self {
return p.clone();
}
panic!("ScriptOwner was not a Battle, but a {self}");
}
}
impl Display for ScriptOwner {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
ScriptOwner::Pokemon(_) => f.write_str("Pokemon"),
ScriptOwner::BattleSide(_) => f.write_str("BattleSide"),
ScriptOwner::Battle(_) => f.write_str("Battle"),
ScriptOwner::None => f.write_str("None"),
}
}
}

View File

@ -80,6 +80,7 @@ mod implementation {
static mut SCRIPT_INDEX_COUNTER: AtomicU32 = AtomicU32::new(1); static mut SCRIPT_INDEX_COUNTER: AtomicU32 = AtomicU32::new(1);
#[repr(C)] #[repr(C)]
#[derive(Copy, Clone)]
pub struct ScriptPtr { pub struct ScriptPtr {
index: u32, index: u32,
} }