Rework in line with PkmnLib for moving towards Result
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2023-06-22 16:40:51 +02:00
parent 2df5feab26
commit 5e0bd632b9
58 changed files with 1901 additions and 1345 deletions

View File

@@ -8,12 +8,11 @@ edition = "2021"
mock_data = ["mockall"]
[dependencies]
cstr_core = { version = "0.2.6", features = ["nightly"]}
cstr_core = { version = "0.2.6", features = ["nightly"] }
enumflags2 = { version = "0.7.5", default-features = false }
spin = { version = "0.9.4", default-features = false, features = ["rwlock"] }
paste = { version = "1.0.7" }
hashbrown = { version = "0.12.3" }
hashbrown = { version = "0.13.2" }
dlmalloc = { version = "0.2.4", features = ["global"] }
mockall = { version = "0.11.2", optional = true, features = ["nightly"] }
num-traits = { version = "0.2", default-features = false }

View File

@@ -1,28 +1,28 @@
use alloc::rc::Rc;
use crate::app_interface::list::ImmutableList;
use crate::app_interface::{
BattleParty, BattleRandom, BattleSide, ChoiceQueue, DynamicLibrary, Pokemon, StringKey,
};
use alloc::vec::Vec;
#[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 parties(&self) -> Vec<BattleParty>;
fn sides(&self) -> Vec<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;
fn get_pokemon(&self, side: u8, index: u8) -> PkmnResult<Option<Pokemon>>;
fn find_party_for_pokemon(&self, pokemon: &Pokemon) -> PkmnResult<Option<BattleParty>>;
fn weather_name(&self) -> PkmnResult<Option<StringKey>>;
fn has_weather(&self, name: &str) -> PkmnResult<bool>;
fn can_flee(&self) -> PkmnResult<bool>;
fn number_of_sides(&self) -> PkmnResult<u8>;
fn pokemon_per_side(&self) -> PkmnResult<u8>;
fn has_ended(&self) -> PkmnResult<bool>;
fn has_ended_conclusively(&self) -> PkmnResult<bool>;
fn winning_side(&self) -> PkmnResult<u8>;
fn current_turn(&self) -> PkmnResult<u32>;
}
pub type Battle = Rc<dyn BattleTrait>;
@@ -33,26 +33,26 @@ pub type MockBattle = MockBattleTrait;
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::ffi_array::FFIArray;
use crate::handling::wasm_result::WasmResult;
use crate::handling::Cacheable;
use crate::{
cached_value, cached_value_getters, wasm_value_getters_extern, wasm_value_getters_funcs,
ExternRef, ExternalReferenceType, StringKey, VecExternRef,
ExternRef, ExternalReferenceType, PkmnResult, StringKey,
};
use alloc::vec::Vec;
struct BattleInner {
reference: ExternRef<BattleImpl>,
library: CachedValue<DynamicLibrary>,
parties: CachedValue<ImmutableList<BattleParty>>,
sides: CachedValue<ImmutableList<BattleSide>>,
parties: CachedValue<Vec<BattleParty>>,
sides: CachedValue<Vec<BattleSide>>,
random: CachedValue<Rc<BattleRandomImpl>>,
choice_queue: CachedValue<Rc<ChoiceQueueImpl>>,
}
@@ -69,21 +69,39 @@ mod implementation {
inner: Rc::new(BattleInner {
reference,
library: cached_value!({
Rc::new(battle_get_library(reference).get_value().unwrap())
Rc::new(battle_get_library(reference).unwrap().get_value().unwrap())
}),
parties: cached_value!({
let reference = battle_get_parties(reference);
Rc::new(BattlePartyImmutableList::from_ref(reference))
let parties: FFIArray<ExternRef<BattlePartyImpl>> =
FFIArray::from_u64(battle_get_parties(reference).unwrap());
let parties =
Vec::from_raw_parts(parties.ptr(), parties.len(), parties.len());
let parties = parties
.into_iter()
.map::<BattleParty, _>(|r| Rc::new(BattlePartyImpl::new(r)))
.collect::<Vec<_>>();
parties
}),
sides: cached_value!({
let reference = battle_get_sides(reference);
Rc::new(BattleSideImmutableList::from_ref(reference))
let sides: FFIArray<ExternRef<BattleSideImpl>> =
FFIArray::from_u64(battle_get_sides(reference).unwrap());
let sides = Vec::from_raw_parts(sides.ptr(), sides.len(), sides.len());
let sides = sides
.into_iter()
.map::<BattleSide, _>(|r| Rc::new(BattleSideImpl::new(r)))
.collect::<Vec<_>>();
sides
}),
random: cached_value!({
Rc::new(battle_get_random(reference).get_value().unwrap())
Rc::new(battle_get_random(reference).unwrap().get_value().unwrap())
}),
choice_queue: cached_value!({
Rc::new(battle_get_choice_queue(reference).get_value().unwrap())
Rc::new(
battle_get_choice_queue(reference)
.unwrap()
.get_value()
.unwrap(),
)
}),
}),
})
@@ -94,46 +112,53 @@ mod implementation {
impl BattleTrait for BattleImpl {
cached_value_getters! {
fn library(&self) -> DynamicLibrary;
fn parties(&self) -> ImmutableList<BattleParty>;
fn sides(&self) -> ImmutableList<BattleSide>;
fn parties(&self) -> Vec<BattleParty>;
fn sides(&self) -> Vec<BattleSide>;
fn random(&self) -> BattleRandom;
fn choice_queue(&self) -> ChoiceQueue;
}
fn get_pokemon(&self, side: u8, index: u8) -> Option<Pokemon> {
fn get_pokemon(&self, side: u8, index: u8) -> PkmnResult<Option<Pokemon>> {
unsafe {
let v = battle_get_pokemon(self.inner.reference, side, index).get_value();
let v = battle_get_pokemon(self.inner.reference, side, index)
.as_res()?
.get_value();
if let Some(v) = v {
Some(Rc::new(v))
Ok(Some(Rc::new(v)))
} else {
None
Ok(None)
}
}
}
fn find_party_for_pokemon(&self, pokemon: &Pokemon) -> Option<BattleParty> {
fn find_party_for_pokemon(&self, pokemon: &Pokemon) -> PkmnResult<Option<BattleParty>> {
unsafe {
let b =
battle_find_party_for_pokemon(self.inner.reference, pokemon.reference().into())
.as_res()?
.get_value();
if let Some(b) = b {
Ok(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 weather_name(&self) -> PkmnResult<Option<StringKey>> {
unsafe {
Ok(battle_get_weather_name(self.inner.reference)
.as_res()?
.get_value())
}
}
fn has_weather(&self, name: &str) -> bool {
if let Some(weather) = self.weather_name() {
fn has_weather(&self, name: &str) -> PkmnResult<bool> {
if let Some(weather) = self.weather_name()? {
if weather.equals_str(name) {
return true;
return Ok(true);
}
}
false
Ok(false)
}
wasm_value_getters_funcs! {
@@ -170,24 +195,29 @@ mod implementation {
#[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_library(
r: ExternRef<BattleImpl>,
) -> WasmResult<ExternRef<DynamicLibraryImpl>>;
fn battle_get_parties(r: ExternRef<BattleImpl>) -> WasmResult<u64>;
fn battle_get_sides(r: ExternRef<BattleImpl>) -> WasmResult<u64>;
fn battle_get_random(r: ExternRef<BattleImpl>) -> WasmResult<ExternRef<BattleRandomImpl>>;
fn battle_get_choice_queue(
r: ExternRef<BattleImpl>,
) -> WasmResult<ExternRef<ChoiceQueueImpl>>;
fn battle_get_pokemon(
r: ExternRef<BattleImpl>,
side: u8,
index: u8,
) -> ExternRef<PokemonImpl>;
) -> WasmResult<ExternRef<PokemonImpl>>;
fn battle_find_party_for_pokemon(
r: ExternRef<BattleImpl>,
mon: ExternRef<PokemonImpl>,
) -> ExternRef<BattlePartyImpl>;
) -> WasmResult<ExternRef<BattlePartyImpl>>;
fn battle_get_weather_name(r: ExternRef<BattleImpl>) -> ExternRef<StringKey>;
fn battle_get_weather_name(r: ExternRef<BattleImpl>) -> WasmResult<ExternRef<StringKey>>;
}
}
use crate::PkmnResult;
#[cfg(not(feature = "mock_data"))]
pub use implementation::*;

View File

@@ -15,6 +15,7 @@ mod implementation {
use crate::app_interface::{BattlePartyTrait, Party, PartyImpl};
use crate::handling::cached_value::CachedValue;
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
use crate::handling::wasm_result::WasmResult;
use crate::handling::Cacheable;
use crate::{cached_value, cached_value_getters};
use alloc::rc::Rc;
@@ -35,7 +36,12 @@ mod implementation {
inner: Rc::new(BattlePartyInner {
reference,
party: cached_value!({
Rc::new(battle_party_get_party(reference).get_value().unwrap())
Rc::new(
battle_party_get_party(reference)
.unwrap()
.get_value()
.unwrap(),
)
}),
}),
})
@@ -59,7 +65,9 @@ mod implementation {
#[cfg(not(feature = "mock_data"))]
extern "wasm" {
fn battle_party_get_party(r: ExternRef<BattlePartyImpl>) -> ExternRef<PartyImpl>;
fn battle_party_get_party(
r: ExternRef<BattlePartyImpl>,
) -> WasmResult<ExternRef<PartyImpl>>;
}
}

View File

@@ -1,10 +1,11 @@
use crate::PkmnResult;
use alloc::rc::Rc;
#[cfg_attr(feature = "mock_data", mockall::automock)]
pub trait BattleRandomTrait {
fn get(&self) -> i32;
fn get_max(&self, max: i32) -> i32;
fn get_between(&self, min: i32, max: i32) -> i32;
fn get(&self) -> PkmnResult<i32>;
fn get_max(&self, max: i32) -> PkmnResult<i32>;
fn get_between(&self, min: i32, max: i32) -> PkmnResult<i32>;
}
pub type BattleRandom = Rc<dyn BattleRandomTrait>;
@@ -17,6 +18,7 @@ pub use implementation::*;
#[cfg(not(feature = "mock_data"))]
mod implementation {
use super::*;
use crate::handling::wasm_result::WasmResult;
use crate::{ExternRef, ExternalReferenceType};
#[derive(Clone)]
@@ -26,16 +28,16 @@ mod implementation {
impl BattleRandomTrait for BattleRandomImpl {
#[cfg(not(feature = "mock_data"))]
fn get(&self) -> i32 {
unsafe { battle_random_get(self.reference) }
fn get(&self) -> PkmnResult<i32> {
unsafe { battle_random_get(self.reference).as_res() }
}
#[cfg(not(feature = "mock_data"))]
fn get_max(&self, max: i32) -> i32 {
unsafe { battle_random_get_max(self.reference, max) }
fn get_max(&self, max: i32) -> PkmnResult<i32> {
unsafe { battle_random_get_max(self.reference, max).as_res() }
}
#[cfg(not(feature = "mock_data"))]
fn get_between(&self, min: i32, max: i32) -> i32 {
unsafe { battle_random_get_between(self.reference, min, max) }
fn get_between(&self, min: i32, max: i32) -> PkmnResult<i32> {
unsafe { battle_random_get_between(self.reference, min, max).as_res() }
}
// TODO: effect_chance()
}
@@ -48,9 +50,13 @@ mod implementation {
#[cfg(not(feature = "mock_data"))]
extern "wasm" {
fn battle_random_get(r: ExternRef<BattleRandomImpl>) -> i32;
fn battle_random_get_max(r: ExternRef<BattleRandomImpl>, max: i32) -> i32;
fn battle_random_get_between(r: ExternRef<BattleRandomImpl>, min: i32, max: i32) -> i32;
fn battle_random_get(r: ExternRef<BattleRandomImpl>) -> WasmResult<i32>;
fn battle_random_get_max(r: ExternRef<BattleRandomImpl>, max: i32) -> WasmResult<i32>;
fn battle_random_get_between(
r: ExternRef<BattleRandomImpl>,
min: i32,
max: i32,
) -> WasmResult<i32>;
}
}

View File

@@ -6,8 +6,8 @@ pub trait BattleSideTrait: WithVolatile {
fn pokemon_per_side(&self) -> u8;
fn battle(&self) -> Battle;
fn get_pokemon(&self, index: usize) -> Option<Pokemon>;
fn has_fled_battle(&self) -> bool;
fn is_defeated(&self) -> bool;
fn has_fled_battle(&self) -> PkmnResult<bool>;
fn is_defeated(&self) -> PkmnResult<bool>;
}
pub type BattleSide = Rc<dyn BattleSideTrait>;
@@ -18,10 +18,11 @@ mod implementation {
use crate::app_interface::{BattleImpl, PokemonImpl};
use crate::handling::cached_value::CachedValue;
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
use crate::handling::wasm_result::{WasmResult, WasmVoidResult};
use crate::handling::{Cacheable, Script};
use crate::{
cached_value, cached_value_getters, wasm_value_getters_extern, wasm_value_getters_funcs,
ScriptPtr,
PkmnResult, ScriptPtr,
};
use alloc::boxed::Box;
use cstr_core::{c_char, CString};
@@ -43,10 +44,17 @@ mod implementation {
Self::from_ref(reference, &|reference| Self {
inner: Rc::new(BattleSideInner {
reference,
side_index: cached_value!({ battleside_get_side_index(reference) }),
pokemon_per_side: cached_value!({ battleside_get_pokemon_per_side(reference) }),
side_index: cached_value!({ battleside_get_side_index(reference).unwrap() }),
pokemon_per_side: cached_value!({
battleside_get_pokemon_per_side(reference).unwrap()
}),
battle: cached_value!({
Rc::new(battleside_get_battle(reference).get_value().unwrap())
Rc::new(
battleside_get_battle(reference)
.unwrap()
.get_value()
.unwrap(),
)
}),
}),
})
@@ -62,7 +70,9 @@ mod implementation {
fn get_pokemon(&self, index: usize) -> Option<Pokemon> {
unsafe {
let p = battleside_get_pokemon(self.inner.reference, index).get_value();
let p = battleside_get_pokemon(self.inner.reference, index)
.unwrap()
.get_value();
if let Some(p) = p {
Some(Rc::new(p))
} else {
@@ -79,39 +89,51 @@ mod implementation {
}
impl WithVolatile for BattleSideImpl {
fn has_volatile(&self, script_name: &str) -> bool {
fn has_volatile(&self, script_name: &str) -> PkmnResult<bool> {
unsafe {
let script_name = CString::new(script_name).unwrap();
battleside_has_volatile(self.inner.reference, script_name.as_ptr())
battleside_has_volatile(self.inner.reference, script_name.as_ptr()).as_res()
}
}
fn add_volatile(&self, script: Box<dyn Script>) -> &dyn Script {
fn add_volatile(&self, script: Box<dyn Script>) -> PkmnResult<&dyn Script> {
unsafe {
battleside_add_volatile(self.inner.reference, ScriptPtr::new(script))
.val()
.unwrap()
Ok(
battleside_add_volatile(self.inner.reference, ScriptPtr::new(script))
.as_res()?
.val()
.unwrap(),
)
}
}
fn add_volatile_by_name(&self, script_name: &str) -> &dyn Script {
fn add_volatile_by_name(&self, script_name: &str) -> PkmnResult<&dyn Script> {
unsafe {
let ptr = CString::new(script_name).unwrap();
battleside_add_volatile_by_name(self.inner.reference, ptr.as_ptr())
.val()
.unwrap()
Ok(
battleside_add_volatile_by_name(self.inner.reference, ptr.as_ptr())
.as_res()?
.val()
.unwrap(),
)
}
}
fn remove_volatile(&self, script: &dyn Script) {
fn remove_volatile(&self, script: &dyn Script) -> PkmnResult<()> {
unsafe {
let name = CString::new(script.get_name()).unwrap();
battleside_remove_volatile(self.inner.reference, name.as_ptr());
battleside_remove_volatile(self.inner.reference, name.as_ptr()).as_res()
}
}
fn get_volatile_script(&self, script_name: &str) -> Option<&dyn Script> {
fn get_volatile_script(&self, script_name: &str) -> PkmnResult<Option<&dyn Script>> {
let script_name = CString::new(script_name).unwrap();
unsafe { battleside_get_volatile(self.inner.reference, script_name.as_ptr()).val() }
unsafe {
Ok(
battleside_get_volatile(self.inner.reference, script_name.as_ptr())
.as_res()?
.val(),
)
}
}
}
@@ -130,24 +152,38 @@ mod implementation {
}
extern "wasm" {
fn battleside_get_side_index(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_side_index(r: ExternRef<BattleSideImpl>) -> WasmResult<u8>;
fn battleside_get_pokemon_per_side(r: ExternRef<BattleSideImpl>) -> WasmResult<u8>;
fn battleside_get_battle(r: ExternRef<BattleSideImpl>)
-> WasmResult<ExternRef<BattleImpl>>;
fn battleside_get_pokemon(
r: ExternRef<BattleSideImpl>,
index: usize,
) -> ExternRef<PokemonImpl>;
) -> WasmResult<ExternRef<PokemonImpl>>;
fn battleside_add_volatile_by_name(
r: ExternRef<BattleSideImpl>,
name: *const c_char,
) -> ScriptPtr;
fn battleside_add_volatile(r: ExternRef<BattleSideImpl>, script: ScriptPtr) -> ScriptPtr;
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_get_volatile(r: ExternRef<BattleSideImpl>, name: *const c_char) -> ScriptPtr;
) -> WasmResult<ScriptPtr>;
fn battleside_add_volatile(
r: ExternRef<BattleSideImpl>,
script: ScriptPtr,
) -> WasmResult<ScriptPtr>;
fn battleside_has_volatile(
r: ExternRef<BattleSideImpl>,
name: *const c_char,
) -> WasmResult<bool>;
fn battleside_remove_volatile(
r: ExternRef<BattleSideImpl>,
name: *const c_char,
) -> WasmVoidResult;
fn battleside_get_volatile(
r: ExternRef<BattleSideImpl>,
name: *const c_char,
) -> WasmResult<ScriptPtr>;
}
}
use crate::PkmnResult;
#[cfg(not(feature = "mock_data"))]
pub use implementation::*;

View File

@@ -3,7 +3,7 @@ use alloc::rc::Rc;
#[cfg_attr(feature = "mock_data", mockall::automock)]
pub trait ChoiceQueueTrait {
fn move_pokemon_choice_next(&self, pokemon: &Pokemon) -> bool;
fn move_pokemon_choice_next(&self, pokemon: &Pokemon) -> PkmnResult<bool>;
}
pub type ChoiceQueue = Rc<dyn ChoiceQueueTrait>;
@@ -14,7 +14,8 @@ pub type MockChoiceQueue = MockChoiceQueueTrait;
mod implementation {
use super::*;
use crate::app_interface::PokemonImpl;
use crate::{ExternRef, ExternalReferenceType};
use crate::handling::wasm_result::WasmResult;
use crate::{ExternRef, ExternalReferenceType, PkmnResult};
#[derive(Clone)]
pub struct ChoiceQueueImpl {
@@ -28,9 +29,10 @@ mod implementation {
}
impl ChoiceQueueTrait for ChoiceQueueImpl {
fn move_pokemon_choice_next(&self, pokemon: &Pokemon) -> bool {
fn move_pokemon_choice_next(&self, pokemon: &Pokemon) -> PkmnResult<bool> {
unsafe {
choice_queue_move_pokemon_choice_next(self.reference, pokemon.reference().into())
.as_res()
}
}
}
@@ -45,9 +47,10 @@ mod implementation {
fn choice_queue_move_pokemon_choice_next(
r: ExternRef<ChoiceQueueImpl>,
pokemon: ExternRef<PokemonImpl>,
) -> bool;
) -> WasmResult<bool>;
}
}
use crate::PkmnResult;
#[cfg(not(feature = "mock_data"))]
pub use implementation::*;

View File

@@ -15,6 +15,7 @@ mod implementation {
use crate::cached_value;
use crate::handling::cached_value::CachedValue;
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
use crate::handling::wasm_result::WasmResult;
use crate::handling::Cacheable;
use alloc::rc::Rc;
@@ -36,7 +37,12 @@ mod implementation {
inner: Rc::new(DynamicLibraryInner {
ptr,
static_data: cached_value!({
Rc::new(dynamic_library_get_static_data(ptr).get_value().unwrap())
Rc::new(
dynamic_library_get_static_data(ptr)
.unwrap()
.get_value()
.unwrap(),
)
}),
}),
})
@@ -58,7 +64,7 @@ mod implementation {
extern "wasm" {
fn dynamic_library_get_static_data(
ptr: ExternRef<DynamicLibraryImpl>,
) -> ExternRef<StaticDataImpl>;
) -> WasmResult<ExternRef<StaticDataImpl>>;
}
}

View File

@@ -1,5 +1,6 @@
use crate::app_interface::{LearnedMove, MoveData, Pokemon};
use crate::handling::Script;
use alloc::boxed::Box;
use alloc::rc::Rc;
#[cfg_attr(feature = "mock_data", mockall::automock)]
@@ -8,25 +9,25 @@ pub trait ExecutingMoveTrait {
fn user(&self) -> Pokemon;
fn chosen_move(&self) -> LearnedMove;
fn use_move(&self) -> MoveData;
fn move_script<'a>(&'a self) -> Option<&'a dyn Script>;
fn number_of_targets(&self) -> usize;
fn is_pokemon_target(&self, pokemon: &Pokemon) -> bool;
fn get_hit_data(&self, pokemon: &Pokemon, hit: u8) -> HitData;
fn move_script<'a>(&'a self) -> PkmnResult<Option<&'a Box<dyn Script>>>;
fn number_of_targets(&self) -> PkmnResult<usize>;
fn is_pokemon_target(&self, pokemon: &Pokemon) -> PkmnResult<bool>;
fn get_hit_data(&self, pokemon: &Pokemon, hit: u8) -> PkmnResult<HitData>;
}
#[cfg_attr(feature = "mock_data", mockall::automock)]
pub trait HitDataTrait {
fn is_critical(&self) -> bool;
fn base_power(&self) -> u8;
fn effectiveness(&self) -> f32;
fn damage(&self) -> u32;
fn move_type(&self) -> u8;
fn has_failed(&self) -> bool;
fn set_critical(&self, critical: bool);
fn set_effectiveness(&self, effectiveness: f32);
fn set_damage(&self, damage: u32);
fn set_move_type(&self, move_type: u8);
fn fail(&self);
fn is_critical(&self) -> PkmnResult<bool>;
fn base_power(&self) -> PkmnResult<u8>;
fn effectiveness(&self) -> PkmnResult<f32>;
fn damage(&self) -> PkmnResult<u32>;
fn move_type(&self) -> PkmnResult<u8>;
fn has_failed(&self) -> PkmnResult<bool>;
fn set_critical(&self, critical: bool) -> PkmnResult<()>;
fn set_effectiveness(&self, effectiveness: f32) -> PkmnResult<()>;
fn set_damage(&self, damage: u32) -> PkmnResult<()>;
fn set_move_type(&self, move_type: u8) -> PkmnResult<()>;
fn fail(&self) -> PkmnResult<()>;
}
pub type ExecutingMove = Rc<dyn ExecutingMoveTrait>;
@@ -37,6 +38,7 @@ pub type HitData = Rc<dyn HitDataTrait>;
#[cfg(feature = "mock_data")]
pub type MockHitData = MockHitDataTrait;
use crate::PkmnResult;
#[cfg(not(feature = "mock_data"))]
pub use implementation::*;
@@ -44,10 +46,12 @@ pub use implementation::*;
mod implementation {
use super::*;
use crate::app_interface::{LearnedMoveImpl, MoveDataImpl, PokemonImpl};
use crate::cached_value;
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};
use alloc::boxed::Box;
#[derive(Clone)]
pub struct ExecutingMoveImpl {
@@ -71,20 +75,31 @@ mod implementation {
ExecutingMoveInner {
reference,
number_of_hits: cached_value!({
executing_move_get_number_of_hits(reference)
executing_move_get_number_of_hits(reference).unwrap()
}),
user: cached_value!({
Rc::new(executing_move_get_user(reference).get_value().unwrap())
Rc::new(
executing_move_get_user(reference)
.unwrap()
.get_value()
.unwrap(),
)
}),
chosen_move: cached_value!({
Rc::new(
executing_move_get_chosen_move(reference)
.unwrap()
.get_value()
.unwrap(),
)
}),
use_move: cached_value!({
Rc::new(executing_move_get_use_move(reference).get_value().unwrap())
Rc::new(
executing_move_get_use_move(reference)
.unwrap()
.get_value()
.unwrap(),
)
}),
},
),
@@ -106,31 +121,39 @@ mod implementation {
fn use_move(&self) -> MoveData {
self.inner.value().use_move.value()
}
fn move_script(&self) -> Option<&dyn Script> {
unsafe { executing_move_get_script(self.inner.value().reference).as_ref() }
fn move_script(&self) -> PkmnResult<Option<&Box<dyn Script>>> {
unsafe {
Ok(
(executing_move_get_script(self.inner.value().reference).as_res()?
as *const Box<dyn Script>)
.as_ref(),
)
}
}
fn number_of_targets(&self) -> usize {
unsafe { executing_move_get_number_of_targets(self.inner.value().reference) }
fn number_of_targets(&self) -> PkmnResult<usize> {
unsafe { executing_move_get_number_of_targets(self.inner.value().reference).as_res() }
}
fn is_pokemon_target(&self, pokemon: &Pokemon) -> bool {
fn is_pokemon_target(&self, pokemon: &Pokemon) -> PkmnResult<bool> {
unsafe {
executing_move_is_pokemon_target(
self.inner.value().reference,
pokemon.reference().into(),
)
.as_res()
}
}
fn get_hit_data(&self, pokemon: &Pokemon, hit: u8) -> HitData {
fn get_hit_data(&self, pokemon: &Pokemon, hit: u8) -> PkmnResult<HitData> {
unsafe {
Rc::new(
Ok(Rc::new(
executing_move_get_hit_data(
self.inner.value().reference,
pokemon.reference().into(),
hit,
)
.as_res()?
.get_value()
.unwrap(),
)
))
}
}
}
@@ -142,39 +165,39 @@ mod implementation {
#[cfg(not(feature = "mock_data"))]
impl HitDataTrait for HitDataImpl {
fn is_critical(&self) -> bool {
unsafe { hit_data_is_critical(self.reference) }
fn is_critical(&self) -> PkmnResult<bool> {
unsafe { hit_data_is_critical(self.reference).as_res() }
}
fn base_power(&self) -> u8 {
unsafe { hit_data_get_base_power(self.reference) }
fn base_power(&self) -> PkmnResult<u8> {
unsafe { hit_data_get_base_power(self.reference).as_res() }
}
fn effectiveness(&self) -> f32 {
unsafe { hit_data_get_effectiveness(self.reference) }
fn effectiveness(&self) -> PkmnResult<f32> {
unsafe { hit_data_get_effectiveness(self.reference).as_res() }
}
fn damage(&self) -> u32 {
unsafe { hit_data_get_damage(self.reference) }
fn damage(&self) -> PkmnResult<u32> {
unsafe { hit_data_get_damage(self.reference).as_res() }
}
fn move_type(&self) -> u8 {
unsafe { hit_data_get_move_type(self.reference) }
fn move_type(&self) -> PkmnResult<u8> {
unsafe { hit_data_get_move_type(self.reference).as_res() }
}
fn has_failed(&self) -> bool {
unsafe { hit_data_is_critical(self.reference) }
fn has_failed(&self) -> PkmnResult<bool> {
unsafe { hit_data_is_critical(self.reference).as_res() }
}
fn set_critical(&self, critical: bool) {
unsafe { hit_data_set_critical(self.reference, critical) }
fn set_critical(&self, critical: bool) -> PkmnResult<()> {
unsafe { hit_data_set_critical(self.reference, critical).as_res() }
}
fn set_effectiveness(&self, effectiveness: f32) {
unsafe { hit_data_set_effectiveness(self.reference, effectiveness) }
fn set_effectiveness(&self, effectiveness: f32) -> PkmnResult<()> {
unsafe { hit_data_set_effectiveness(self.reference, effectiveness).as_res() }
}
fn set_damage(&self, damage: u32) {
unsafe { hit_data_set_damage(self.reference, damage) }
fn set_damage(&self, damage: u32) -> PkmnResult<()> {
unsafe { hit_data_set_damage(self.reference, damage).as_res() }
}
fn set_move_type(&self, move_type: u8) {
unsafe { hit_data_set_move_type(self.reference, move_type) }
fn set_move_type(&self, move_type: u8) -> PkmnResult<()> {
unsafe { hit_data_set_move_type(self.reference, move_type).as_res() }
}
fn fail(&self) {
unsafe { hit_data_fail(self.reference) }
fn fail(&self) -> PkmnResult<()> {
unsafe { hit_data_fail(self.reference).as_res() }
}
}
@@ -194,38 +217,47 @@ mod implementation {
#[cfg(not(feature = "mock_data"))]
extern "wasm" {
fn executing_move_get_number_of_targets(r: ExternRef<ExecutingMoveImpl>) -> usize;
fn executing_move_get_number_of_hits(r: ExternRef<ExecutingMoveImpl>) -> u8;
fn executing_move_get_user(r: ExternRef<ExecutingMoveImpl>) -> ExternRef<PokemonImpl>;
fn executing_move_get_number_of_targets(
r: ExternRef<ExecutingMoveImpl>,
) -> WasmResult<usize>;
fn executing_move_get_number_of_hits(r: ExternRef<ExecutingMoveImpl>) -> WasmResult<u8>;
fn executing_move_get_user(
r: ExternRef<ExecutingMoveImpl>,
) -> WasmResult<ExternRef<PokemonImpl>>;
fn executing_move_get_chosen_move(
r: ExternRef<ExecutingMoveImpl>,
) -> ExternRef<LearnedMoveImpl>;
fn executing_move_get_use_move(r: ExternRef<ExecutingMoveImpl>) -> ExternRef<MoveDataImpl>;
) -> WasmResult<ExternRef<LearnedMoveImpl>>;
fn executing_move_get_use_move(
r: ExternRef<ExecutingMoveImpl>,
) -> WasmResult<ExternRef<MoveDataImpl>>;
#[allow(improper_ctypes)]
fn executing_move_get_script(r: ExternRef<ExecutingMoveImpl>) -> *const dyn Script;
fn executing_move_get_script(r: ExternRef<ExecutingMoveImpl>) -> WasmResult<u32>;
fn executing_move_is_pokemon_target(
r: ExternRef<ExecutingMoveImpl>,
pokemon: ExternRef<PokemonImpl>,
) -> bool;
) -> WasmResult<bool>;
fn executing_move_get_hit_data(
r: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>,
hit: u8,
) -> ExternRef<HitDataImpl>;
) -> WasmResult<ExternRef<HitDataImpl>>;
fn hit_data_is_critical(r: ExternRef<HitDataImpl>) -> bool;
fn hit_data_get_base_power(r: ExternRef<HitDataImpl>) -> u8;
fn hit_data_get_effectiveness(r: ExternRef<HitDataImpl>) -> f32;
fn hit_data_get_damage(r: ExternRef<HitDataImpl>) -> u32;
fn hit_data_get_move_type(r: ExternRef<HitDataImpl>) -> u8;
fn hit_data_has_failed(r: ExternRef<HitDataImpl>) -> bool;
fn hit_data_is_critical(r: ExternRef<HitDataImpl>) -> WasmResult<bool>;
fn hit_data_get_base_power(r: ExternRef<HitDataImpl>) -> WasmResult<u8>;
fn hit_data_get_effectiveness(r: ExternRef<HitDataImpl>) -> WasmResult<f32>;
fn hit_data_get_damage(r: ExternRef<HitDataImpl>) -> WasmResult<u32>;
fn hit_data_get_move_type(r: ExternRef<HitDataImpl>) -> WasmResult<u8>;
fn hit_data_has_failed(r: ExternRef<HitDataImpl>) -> WasmResult<bool>;
fn hit_data_set_critical(r: ExternRef<HitDataImpl>, critical: bool);
fn hit_data_set_base_power(r: ExternRef<HitDataImpl>, power: u8);
fn hit_data_set_effectiveness(r: ExternRef<HitDataImpl>, effectiveness: f32);
fn hit_data_set_damage(r: ExternRef<HitDataImpl>, damage: u32);
fn hit_data_set_move_type(r: ExternRef<HitDataImpl>, move_type: u8);
fn hit_data_fail(r: ExternRef<HitDataImpl>);
fn hit_data_set_critical(r: ExternRef<HitDataImpl>, critical: bool) -> WasmResult<()>;
fn hit_data_set_base_power(r: ExternRef<HitDataImpl>, power: u8) -> WasmResult<()>;
fn hit_data_set_effectiveness(
r: ExternRef<HitDataImpl>,
effectiveness: f32,
) -> WasmResult<()>;
fn hit_data_set_damage(r: ExternRef<HitDataImpl>, damage: u32) -> WasmResult<()>;
fn hit_data_set_move_type(r: ExternRef<HitDataImpl>, move_type: u8) -> WasmResult<()>;
fn hit_data_fail(r: ExternRef<HitDataImpl>) -> WasmResult<()>;
}
}

View File

@@ -29,6 +29,7 @@ mod implementation {
use crate::app_interface::MoveDataImpl;
use crate::handling::cached_value::CachedValue;
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
use crate::handling::wasm_result::WasmResult;
use crate::handling::Cacheable;
use crate::{cached_value, cached_value_getters, wasm_value_getters};
use alloc::rc::Rc;
@@ -58,9 +59,16 @@ mod implementation {
inner: Rc::new(LearnedMoveInner {
reference,
move_data: cached_value!({
Rc::new(learned_move_get_move_data(reference).get_value().unwrap())
Rc::new(
learned_move_get_move_data(reference)
.unwrap()
.get_value()
.unwrap(),
)
}),
learn_method: cached_value!({
learned_move_get_learn_method(reference).unwrap()
}),
learn_method: cached_value!({ learned_move_get_learn_method(reference) }),
}),
})
}
@@ -92,10 +100,14 @@ mod implementation {
}
extern "wasm" {
fn learned_move_get_move_data(r: ExternRef<LearnedMoveImpl>) -> ExternRef<MoveDataImpl>;
fn learned_move_get_learn_method(r: ExternRef<LearnedMoveImpl>) -> MoveLearnMethod;
fn learned_move_restore_uses(r: ExternRef<LearnedMoveImpl>, uses: u8);
fn learned_move_restore_all_uses(r: ExternRef<LearnedMoveImpl>);
fn learned_move_get_move_data(
r: ExternRef<LearnedMoveImpl>,
) -> WasmResult<ExternRef<MoveDataImpl>>;
fn learned_move_get_learn_method(
r: ExternRef<LearnedMoveImpl>,
) -> WasmResult<MoveLearnMethod>;
fn learned_move_restore_uses(r: ExternRef<LearnedMoveImpl>, uses: u8) -> WasmResult<()>;
fn learned_move_restore_all_uses(r: ExternRef<LearnedMoveImpl>) -> WasmResult<()>;
}
}

View File

@@ -5,8 +5,8 @@ use core::iter::IntoIterator;
#[cfg_attr(feature = "mock_data", mockall::automock)]
pub trait PartyTrait {
fn get_pokemon(&self, index: usize) -> Option<Pokemon>;
fn length(&self) -> usize;
fn get_pokemon(&self, index: usize) -> PkmnResult<Option<Pokemon>>;
fn length(&self) -> PkmnResult<usize>;
}
pub type Party = Rc<dyn PartyTrait>;
@@ -16,7 +16,10 @@ impl<'a> IntoIterator for &'a dyn PartyTrait {
type IntoIter = ExternIterator<'a, Self::Item>;
fn into_iter(self) -> Self::IntoIter {
ExternIterator::new(self.length(), Box::new(move |i| self.get_pokemon(i)))
ExternIterator::new(
self.length().unwrap(),
Box::new(move |i| self.get_pokemon(i).unwrap()),
)
}
}
@@ -28,6 +31,8 @@ mod implementation {
use super::*;
use crate::app_interface::PokemonImpl;
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
use crate::handling::wasm_result::WasmResult;
use crate::PkmnResult;
#[derive(Clone)]
pub struct PartyImpl {
@@ -41,19 +46,21 @@ mod implementation {
}
impl PartyTrait for PartyImpl {
fn get_pokemon(&self, index: usize) -> Option<Pokemon> {
fn get_pokemon(&self, index: usize) -> PkmnResult<Option<Pokemon>> {
unsafe {
let v = party_get_pokemon(self.reference, index).get_value();
if let Some(v) = v {
let v = party_get_pokemon(self.reference, index)
.as_res()?
.get_value();
Ok(if let Some(v) = v {
Some(Rc::new(v))
} else {
None
}
})
}
}
fn length(&self) -> usize {
unsafe { party_get_length(self.reference) }
fn length(&self) -> PkmnResult<usize> {
unsafe { party_get_length(self.reference).as_res() }
}
}
@@ -64,11 +71,15 @@ mod implementation {
}
extern "wasm" {
fn party_get_pokemon(r: ExternRef<PartyImpl>, index: usize) -> ExternRef<PokemonImpl>;
fn party_get_length(r: ExternRef<PartyImpl>) -> usize;
fn party_get_pokemon(
r: ExternRef<PartyImpl>,
index: usize,
) -> WasmResult<ExternRef<PokemonImpl>>;
fn party_get_length(r: ExternRef<PartyImpl>) -> WasmResult<usize>;
}
}
use crate::utils::ExternIterator;
use crate::PkmnResult;
#[cfg(not(feature = "mock_data"))]
pub use implementation::*;

View File

@@ -8,36 +8,37 @@ use alloc::boxed::Box;
use alloc::rc::Rc;
use cstr_core::c_char;
use crate::PkmnResult;
#[cfg(not(feature = "mock_data"))]
pub use implementation::*;
pub trait PokemonTrait: WithVolatile {
fn reference(&self) -> u32;
fn species(&self) -> Species;
fn form(&self) -> Form;
fn active_ability(&self) -> Ability;
fn nature(&self) -> Nature;
fn display_species(&self) -> Species;
fn display_form(&self) -> Form;
fn held_item(&self) -> Option<Item>;
fn battle(&self) -> Option<Battle>;
fn level(&self) -> LevelInt;
fn experience(&self) -> u32;
fn unique_identifier(&self) -> u32;
fn gender(&self) -> Gender;
fn coloring(&self) -> u8;
fn current_health(&self) -> u32;
fn weight(&self) -> f32;
fn height(&self) -> f32;
fn nickname(&self) -> *const c_char;
fn real_ability(&self) -> AbilityIndex;
fn types_length(&self) -> usize;
fn battle_side_index(&self) -> u8;
fn battle_index(&self) -> u8;
fn is_ability_overriden(&self) -> u8;
fn allowed_experience_gain(&self) -> bool;
fn is_usable(&self) -> bool;
fn species(&self) -> PkmnResult<Species>;
fn form(&self) -> PkmnResult<Form>;
fn active_ability(&self) -> PkmnResult<Ability>;
fn nature(&self) -> PkmnResult<Nature>;
fn display_species(&self) -> PkmnResult<Species>;
fn display_form(&self) -> PkmnResult<Form>;
fn held_item(&self) -> PkmnResult<Option<Item>>;
fn battle(&self) -> PkmnResult<Option<Battle>>;
fn level(&self) -> PkmnResult<LevelInt>;
fn experience(&self) -> PkmnResult<u32>;
fn unique_identifier(&self) -> PkmnResult<u32>;
fn gender(&self) -> PkmnResult<Gender>;
fn coloring(&self) -> PkmnResult<u8>;
fn current_health(&self) -> PkmnResult<u32>;
fn weight(&self) -> PkmnResult<f32>;
fn height(&self) -> PkmnResult<f32>;
fn nickname(&self) -> PkmnResult<*const c_char>;
fn real_ability(&self) -> PkmnResult<AbilityIndex>;
fn types_length(&self) -> PkmnResult<usize>;
fn battle_side_index(&self) -> PkmnResult<u8>;
fn battle_index(&self) -> PkmnResult<u8>;
fn is_ability_overriden(&self) -> PkmnResult<u8>;
fn allowed_experience_gain(&self) -> PkmnResult<bool>;
fn is_usable(&self) -> PkmnResult<bool>;
fn library(&self) -> DynamicLibrary;
fn flat_stats(&self) -> StatisticSet<u32>;
@@ -45,25 +46,30 @@ pub trait PokemonTrait: WithVolatile {
fn boosted_stats(&self) -> StatisticSet<u32>;
fn individual_values(&self) -> ClampedStatisticSet<u8>;
fn effort_values(&self) -> ClampedStatisticSet<u8>;
fn has_held_item(&self, name: &str) -> bool;
fn set_held_item(&self, item: &Item) -> Option<Item>;
fn remove_held_item(&self) -> Option<Item>;
fn consume_held_item(&self) -> bool;
fn max_health(&self) -> u32;
fn get_type(&self, index: usize) -> u8;
fn has_type(&self, type_identifier: TypeIdentifier) -> bool;
fn has_type_by_name(&self, type_name: &str) -> bool;
fn get_learned_move(&self, index: usize) -> Option<LearnedMove>;
fn change_stat_boost(&self, stat: Statistic, diff_amount: i8, self_inflicted: bool) -> bool;
fn ability_script(&self) -> Option<&Box<dyn Script>>;
fn has_held_item(&self, name: &str) -> PkmnResult<bool>;
fn set_held_item(&self, item: &Item) -> PkmnResult<Option<Item>>;
fn remove_held_item(&self) -> PkmnResult<Option<Item>>;
fn consume_held_item(&self) -> PkmnResult<bool>;
fn max_health(&self) -> PkmnResult<u32>;
fn get_type(&self, index: usize) -> PkmnResult<u8>;
fn has_type(&self, type_identifier: TypeIdentifier) -> PkmnResult<bool>;
fn has_type_by_name(&self, type_name: &str) -> PkmnResult<bool>;
fn get_learned_move(&self, index: usize) -> PkmnResult<Option<LearnedMove>>;
fn change_stat_boost(
&self,
stat: Statistic,
diff_amount: i8,
self_inflicted: bool,
) -> PkmnResult<bool>;
fn ability_script(&self) -> PkmnResult<Option<&Box<dyn Script>>>;
fn change_species(&self, species: Species, form: Form);
fn change_form(&self, form: Form);
fn is_fainted(&self) -> bool;
fn damage(&self, damage: u32, source: DamageSource);
fn heal(&self, amount: u32, allow_revive: bool) -> bool;
fn is_fainted(&self) -> PkmnResult<bool>;
fn damage(&self, damage: u32, source: DamageSource) -> PkmnResult<()>;
fn heal(&self, amount: u32, allow_revive: bool) -> PkmnResult<bool>;
fn set_weight(&self, weight: f32);
fn clear_status(&self);
fn battle_side(&self) -> BattleSide;
fn battle_side(&self) -> PkmnResult<BattleSide>;
fn equals(&self, other: &Pokemon) -> bool;
}
@@ -84,6 +90,7 @@ pub enum DamageSource {
#[cfg(not(feature = "mock_data"))]
mod implementation {
use super::*;
use core::mem::transmute;
use cstr_core::CString;
use crate::app_interface::dynamic_data::dynamic_library::DynamicLibraryImpl;
@@ -92,12 +99,13 @@ mod implementation {
StatisticSetImpl,
};
use crate::handling::cached_value::CachedValue;
use crate::handling::wasm_result::WasmResult;
use crate::handling::Cacheable;
use crate::implementation::ScriptPtr;
use crate::{
cached_value, cached_value_getters, wasm_optional_reference_getters_extern,
wasm_reference_getters_extern, wasm_value_getters_extern, wasm_value_getters_funcs,
ExternRef, ExternalReferenceType,
ExternRef, ExternalReferenceType, PkmnResult,
};
struct PokemonInner {
@@ -134,90 +142,154 @@ mod implementation {
fn effort_values(&self) -> ClampedStatisticSet<u8>;
}
fn active_ability(&self) -> Ability {
fn nickname(&self) -> PkmnResult<*const u8> {
unsafe {
let nickname = pokemon_get_nickname(self.inner.reference).as_res()?;
Ok(nickname as *const u8)
}
}
fn species(&self) -> PkmnResult<Species> {
Ok(unsafe {
Rc::new(
pokemon_get_species(self.inner.reference)
.as_res()?
.get_value()
.unwrap(),
)
})
}
fn form(&self) -> PkmnResult<Form> {
Ok(unsafe {
Rc::new(
pokemon_get_form(self.inner.reference)
.as_res()?
.get_value()
.unwrap(),
)
})
}
fn active_ability(&self) -> PkmnResult<Ability> {
Ok(unsafe {
let implementation = pokemon_get_active_ability(self.reference())
.as_res()?
.get_value()
.unwrap();
Rc::new(implementation)
}
})
}
fn held_item(&self) -> Option<Item> {
unsafe {
let i = pokemon_get_held_item(self.inner.reference).get_value();
if let Some(i) = i {
Some(Rc::new(i))
} else {
None
}
}
fn nature(&self) -> PkmnResult<Nature> {
Ok(unsafe {
Rc::new(
pokemon_get_nature(self.inner.reference)
.as_res()?
.get_value()
.unwrap(),
)
})
}
fn battle(&self) -> Option<Battle> {
unsafe {
let b = pokemon_get_battle(self.reference()).get_value();
if let Some(b) = b {
Some(Rc::new(b))
} else {
None
}
}
fn display_species(&self) -> PkmnResult<Species> {
Ok(unsafe {
Rc::new(
pokemon_get_display_species(self.inner.reference)
.as_res()?
.get_value()
.unwrap(),
)
})
}
fn has_held_item(&self, name: &str) -> bool {
let cstr = CString::new(name).unwrap();
unsafe { pokemon_has_held_item(self.inner.reference, cstr.as_ptr()) }
fn display_form(&self) -> PkmnResult<Form> {
Ok(unsafe {
Rc::new(
pokemon_get_display_form(self.inner.reference)
.as_res()?
.get_value()
.unwrap(),
)
})
}
fn set_held_item(&self, item: &Item) -> Option<Item> {
unsafe {
let i = pokemon_set_held_item(self.inner.reference, item.reference().into())
fn held_item(&self) -> PkmnResult<Option<Item>> {
Ok(unsafe {
let i = pokemon_get_held_item(self.inner.reference)
.as_res()?
.get_value();
if let Some(i) = i {
Some(Rc::new(i))
} else {
None
}
}
})
}
fn remove_held_item(&self) -> Option<Item> {
unsafe {
let i = pokemon_remove_held_item(self.inner.reference).get_value();
if let Some(i) = i {
Some(Rc::new(i))
fn battle(&self) -> PkmnResult<Option<Battle>> {
Ok(unsafe {
let b = pokemon_get_battle(self.reference()).as_res()?.get_value();
if let Some(b) = b {
Some(Rc::new(b))
} else {
None
}
})
}
fn has_held_item(&self, name: &str) -> PkmnResult<bool> {
let cstr = CString::new(name).unwrap();
unsafe { pokemon_has_held_item(self.inner.reference, cstr.as_ptr()).as_res() }
}
fn set_held_item(&self, item: &Item) -> PkmnResult<Option<Item>> {
unsafe {
let i = pokemon_set_held_item(self.inner.reference, item.reference().into())
.as_res()?
.get_value();
Ok(if let Some(i) = i {
Some(Rc::new(i))
} else {
None
})
}
}
fn consume_held_item(&self) -> bool {
unsafe { pokemon_consume_held_item(self.inner.reference) }
fn remove_held_item(&self) -> PkmnResult<Option<Item>> {
unsafe {
let i = pokemon_remove_held_item(self.inner.reference)
.as_res()?
.get_value();
Ok(if let Some(i) = i {
Some(Rc::new(i))
} else {
None
})
}
}
fn max_health(&self) -> u32 {
fn consume_held_item(&self) -> PkmnResult<bool> {
unsafe { pokemon_consume_held_item(self.inner.reference).as_res() }
}
fn max_health(&self) -> PkmnResult<u32> {
self.boosted_stats().hp()
}
fn get_type(&self, index: usize) -> u8 {
unsafe { pokemon_get_type(self.inner.reference, index) }
fn get_type(&self, index: usize) -> PkmnResult<u8> {
unsafe { pokemon_get_type(self.inner.reference, index).as_res() }
}
fn has_type(&self, type_identifier: TypeIdentifier) -> bool {
unsafe { pokemon_has_type(self.inner.reference, type_identifier.into()) }
fn has_type(&self, type_identifier: TypeIdentifier) -> PkmnResult<bool> {
unsafe { pokemon_has_type(self.inner.reference, type_identifier.into()).as_res() }
}
fn has_type_by_name(&self, type_name: &str) -> bool {
fn has_type_by_name(&self, type_name: &str) -> PkmnResult<bool> {
let type_identifier = self
.library()
.data_library()
.type_library()
.get_type_from_name(type_name);
.get_type_from_name(type_name)?;
if let Some(type_identifier) = type_identifier {
return self.has_type(type_identifier);
}
false
Ok(false)
}
fn get_learned_move(&self, index: usize) -> Option<LearnedMove> {
fn get_learned_move(&self, index: usize) -> PkmnResult<Option<LearnedMove>> {
unsafe {
let v = pokemon_get_learned_move(self.inner.reference, index).get_value();
if let Some(v) = v {
let v = pokemon_get_learned_move(self.inner.reference, index)
.as_res()?
.get_value();
Ok(if let Some(v) = v {
Some(Rc::new(v))
} else {
None
}
})
}
}
fn change_stat_boost(
@@ -225,13 +297,18 @@ mod implementation {
stat: Statistic,
diff_amount: i8,
self_inflicted: bool,
) -> bool {
) -> PkmnResult<bool> {
unsafe {
pokemon_change_stat_boost(self.inner.reference, stat, diff_amount, self_inflicted)
.as_res()
}
}
fn ability_script(&self) -> Option<&Box<dyn Script>> {
unsafe { pokemon_get_ability_script(self.inner.reference).as_ref() }
fn ability_script(&self) -> PkmnResult<Option<&Box<dyn Script>>> {
unsafe {
Ok((pokemon_get_ability_script(self.inner.reference).as_res()?
as *const Box<dyn Script>)
.as_ref())
}
}
fn change_species(&self, species: Species, form: Form) {
unsafe {
@@ -245,81 +322,44 @@ mod implementation {
);
}
}
fn change_form(&self, form: Form) {
unsafe {
let form_impl = form.as_any().downcast_ref_unchecked::<FormImpl>();
pokemon_change_form(self.inner.reference, form_impl.reference());
}
}
fn is_fainted(&self) -> bool {
self.current_health() == 0
fn is_fainted(&self) -> PkmnResult<bool> {
Ok(self.current_health()? == 0)
}
fn damage(&self, damage: u32, source: DamageSource) {
unsafe { pokemon_damage(self.inner.reference, damage, source) }
fn damage(&self, damage: u32, source: DamageSource) -> PkmnResult<()> {
unsafe { pokemon_damage(self.inner.reference, damage, source).as_res() }
}
fn heal(&self, amount: u32, allow_revive: bool) -> bool {
unsafe { pokemon_heal(self.inner.reference, amount, allow_revive) }
fn heal(&self, amount: u32, allow_revive: bool) -> PkmnResult<bool> {
unsafe { pokemon_heal(self.inner.reference, amount, allow_revive).as_res() }
}
fn set_weight(&self, weight: f32) {
unsafe {
pokemon_set_weight(self.reference(), weight);
}
}
fn nature(&self) -> Nature {
unsafe {
Rc::new(
pokemon_get_nature(self.inner.reference)
.get_value()
.unwrap(),
)
}
}
fn species(&self) -> Species {
unsafe {
Rc::new(
pokemon_get_species(self.inner.reference)
.get_value()
.unwrap(),
)
}
}
fn form(&self) -> Form {
unsafe { Rc::new(pokemon_get_form(self.inner.reference).get_value().unwrap()) }
}
fn clear_status(&self) {
unsafe {
pokemon_clear_status(self.reference());
}
}
fn display_species(&self) -> Species {
unsafe {
Rc::new(
pokemon_get_display_species(self.inner.reference)
.get_value()
.unwrap(),
)
}
}
fn display_form(&self) -> Form {
unsafe {
Rc::new(
pokemon_get_display_form(self.inner.reference)
.get_value()
.unwrap(),
)
}
}
fn battle_side(&self) -> BattleSide {
self.battle()
fn battle_side(&self) -> PkmnResult<BattleSide> {
Ok(self
.battle()?
.unwrap()
.sides()
.get(self.battle_side_index() as u32)
.get(self.battle_side_index()? as usize)
.unwrap()
.clone())
}
#[cfg(not(feature = "mock_data"))]
@@ -333,8 +373,6 @@ mod implementation {
fn current_health(&self) -> u32;
fn weight(&self) -> f32;
fn height(&self) -> f32;
fn nickname(&self) -> *const c_char;
fn real_ability(&self) -> AbilityIndex;
fn types_length(&self) -> usize;
fn battle_side_index(&self) -> u8;
fn battle_index(&self) -> u8;
@@ -349,45 +387,66 @@ mod implementation {
.get_internal_index()
.eq(&other.reference())
}
fn real_ability(&self) -> PkmnResult<AbilityIndex> {
unsafe {
let real_ability = pokemon_get_real_ability(self.reference()).as_res()?;
let split: (u8, u8) = transmute(real_ability);
Ok(AbilityIndex {
index: split.0,
hidden: split.1 == 1,
})
}
}
}
#[cfg(not(feature = "mock_data"))]
impl WithVolatile for PokemonImpl {
fn has_volatile(&self, script_name: &str) -> bool {
fn has_volatile(&self, script_name: &str) -> PkmnResult<bool> {
unsafe {
let ptr = CString::new(script_name).unwrap();
pokemon_has_volatile(self.inner.reference, ptr.as_ptr())
pokemon_has_volatile(self.inner.reference, ptr.as_ptr()).as_res()
}
}
fn add_volatile(&self, script: Box<dyn Script>) -> &dyn Script {
fn add_volatile(&self, script: Box<dyn Script>) -> PkmnResult<&dyn Script> {
unsafe {
pokemon_add_volatile(self.inner.reference, ScriptPtr::new(script))
.val()
.unwrap()
Ok(
pokemon_add_volatile(self.inner.reference, ScriptPtr::new(script))
.as_res()?
.val()
.unwrap(),
)
}
}
fn add_volatile_by_name(&self, script_name: &str) -> &dyn Script {
fn add_volatile_by_name(&self, script_name: &str) -> PkmnResult<&dyn Script> {
unsafe {
let ptr = CString::new(script_name).unwrap();
pokemon_add_volatile_by_name(self.inner.reference, ptr.as_ptr())
.val()
.unwrap()
Ok(
pokemon_add_volatile_by_name(self.inner.reference, ptr.as_ptr())
.as_res()?
.val()
.unwrap(),
)
}
}
fn remove_volatile(&self, script: &dyn Script) {
fn remove_volatile(&self, script: &dyn Script) -> PkmnResult<()> {
unsafe {
let name = CString::new(script.get_name()).unwrap();
pokemon_remove_volatile(self.inner.reference, name.as_ptr());
pokemon_remove_volatile(self.inner.reference, name.as_ptr()).as_res()
}
}
fn get_volatile_script(&self, script_name: &str) -> Option<&dyn Script> {
fn get_volatile_script(&self, script_name: &str) -> PkmnResult<Option<&dyn Script>> {
unsafe {
let script_name = CString::new(script_name).unwrap();
pokemon_get_volatile(self.inner.reference, script_name.as_ptr()).val()
Ok(
pokemon_get_volatile(self.inner.reference, script_name.as_ptr())
.as_res()?
.val(),
)
}
}
}
@@ -398,24 +457,41 @@ mod implementation {
inner: Rc::new(PokemonInner {
reference,
library: cached_value!({
Rc::new(pokemon_get_library(reference).get_value().unwrap())
Rc::new(pokemon_get_library(reference).unwrap().get_value().unwrap())
}),
flat_stats: cached_value!({
Rc::new(pokemon_get_flat_stats(reference).get_value().unwrap())
Rc::new(
pokemon_get_flat_stats(reference)
.unwrap()
.get_value()
.unwrap(),
)
}),
stat_boosts: cached_value!({
pokemon_get_stat_boosts(reference).get_value().unwrap()
pokemon_get_stat_boosts(reference)
.unwrap()
.get_value()
.unwrap()
}),
boosted_stats: cached_value!({
Rc::new(pokemon_get_boosted_stats(reference).get_value().unwrap())
Rc::new(
pokemon_get_boosted_stats(reference)
.unwrap()
.get_value()
.unwrap(),
)
}),
individual_values: cached_value!({
pokemon_get_individual_values(reference)
.unwrap()
.get_value()
.unwrap()
}),
effort_values: cached_value!({
pokemon_get_effort_values(reference).get_value().unwrap()
pokemon_get_effort_values(reference)
.unwrap()
.get_value()
.unwrap()
}),
}),
})
@@ -430,14 +506,14 @@ mod implementation {
PokemonImpl, Pokemon,
pub fn species(&self) -> SpeciesImpl;
pub fn form(&self) -> FormImpl;
pub fn display_species(&self) -> SpeciesImpl;
pub fn display_form(&self) -> FormImpl;
pub fn active_ability(&self) -> AbilityImpl;
pub fn nature(&self) -> NatureImpl;
}
wasm_optional_reference_getters_extern! {
PokemonImpl, Pokemon,
pub fn display_species(&self) -> Option<SpeciesImpl>;
pub fn display_form(&self) -> Option<FormImpl>;
pub fn held_item(&self) -> Option<ItemImpl>;
pub fn battle(&self) -> Option<BattleImpl>;
}
@@ -452,8 +528,7 @@ mod implementation {
pub fn current_health(&self) -> u32;
pub fn weight(&self) -> f32;
pub fn height(&self) -> f32;
pub fn nickname(&self) -> *const c_char;
pub fn real_ability(&self) -> AbilityIndex;
pub fn real_ability(&self) -> u16;
pub fn types_length(&self) -> usize;
pub fn battle_side_index(&self) -> u8;
pub fn battle_index(&self) -> u8;
@@ -477,58 +552,89 @@ mod implementation {
}
extern "wasm" {
fn pokemon_get_library(r: ExternRef<PokemonImpl>) -> ExternRef<DynamicLibraryImpl>;
fn pokemon_get_flat_stats(r: ExternRef<PokemonImpl>) -> ExternRef<StatisticSetImpl<u32>>;
fn pokemon_get_stat_boosts(r: ExternRef<PokemonImpl>)
-> ExternRef<ClampedStatisticSet<i8>>;
fn pokemon_get_boosted_stats(r: ExternRef<PokemonImpl>)
-> ExternRef<StatisticSetImpl<u32>>;
fn pokemon_get_nickname(r: ExternRef<PokemonImpl>) -> WasmResult<u32>;
fn pokemon_get_library(
r: ExternRef<PokemonImpl>,
) -> WasmResult<ExternRef<DynamicLibraryImpl>>;
fn pokemon_get_flat_stats(
r: ExternRef<PokemonImpl>,
) -> WasmResult<ExternRef<StatisticSetImpl<u32>>>;
fn pokemon_get_stat_boosts(
r: ExternRef<PokemonImpl>,
) -> WasmResult<ExternRef<ClampedStatisticSet<i8>>>;
fn pokemon_get_boosted_stats(
r: ExternRef<PokemonImpl>,
) -> WasmResult<ExternRef<StatisticSetImpl<u32>>>;
fn pokemon_get_individual_values(
r: ExternRef<PokemonImpl>,
) -> ExternRef<ClampedStatisticSet<u8>>;
) -> WasmResult<ExternRef<ClampedStatisticSet<u8>>>;
fn pokemon_get_effort_values(
r: ExternRef<PokemonImpl>,
) -> ExternRef<ClampedStatisticSet<u8>>;
fn pokemon_has_held_item(r: ExternRef<PokemonImpl>, name: *const c_char) -> bool;
) -> WasmResult<ExternRef<ClampedStatisticSet<u8>>>;
fn pokemon_has_held_item(
r: ExternRef<PokemonImpl>,
name: *const c_char,
) -> WasmResult<bool>;
fn pokemon_set_held_item(
r: ExternRef<PokemonImpl>,
item: ExternRef<ItemImpl>,
) -> ExternRef<ItemImpl>;
fn pokemon_remove_held_item(r: ExternRef<PokemonImpl>) -> ExternRef<ItemImpl>;
fn pokemon_consume_held_item(r: ExternRef<PokemonImpl>) -> bool;
fn pokemon_get_type(r: ExternRef<PokemonImpl>, index: usize) -> u8;
fn pokemon_has_type(r: ExternRef<PokemonImpl>, identifier: u8) -> bool;
) -> WasmResult<ExternRef<ItemImpl>>;
fn pokemon_remove_held_item(r: ExternRef<PokemonImpl>) -> WasmResult<ExternRef<ItemImpl>>;
fn pokemon_consume_held_item(r: ExternRef<PokemonImpl>) -> WasmResult<bool>;
fn pokemon_get_type(r: ExternRef<PokemonImpl>, index: usize) -> WasmResult<u8>;
fn pokemon_has_type(r: ExternRef<PokemonImpl>, identifier: u8) -> WasmResult<bool>;
fn pokemon_get_learned_move(
r: ExternRef<PokemonImpl>,
index: usize,
) -> ExternRef<LearnedMoveImpl>;
) -> WasmResult<ExternRef<LearnedMoveImpl>>;
fn pokemon_change_stat_boost(
r: ExternRef<PokemonImpl>,
tat: Statistic,
diff_amount: i8,
self_inflicted: bool,
) -> bool;
) -> WasmResult<bool>;
#[allow(improper_ctypes)]
fn pokemon_get_ability_script(r: ExternRef<PokemonImpl>) -> *const Box<dyn Script>;
fn pokemon_get_ability_script(r: ExternRef<PokemonImpl>) -> WasmResult<u32>;
fn pokemon_change_species(
r: ExternRef<PokemonImpl>,
species: ExternRef<SpeciesImpl>,
form: ExternRef<FormImpl>,
);
fn pokemon_change_form(r: ExternRef<PokemonImpl>, form: ExternRef<FormImpl>);
fn pokemon_damage(r: ExternRef<PokemonImpl>, damage: u32, source: DamageSource);
fn pokemon_heal(r: ExternRef<PokemonImpl>, amount: u32, allow_revive: bool) -> bool;
fn pokemon_set_weight(r: ExternRef<PokemonImpl>, weight: f32);
fn pokemon_clear_status(r: ExternRef<PokemonImpl>);
) -> WasmResult<()>;
fn pokemon_change_form(
r: ExternRef<PokemonImpl>,
form: ExternRef<FormImpl>,
) -> WasmResult<()>;
fn pokemon_damage(
r: ExternRef<PokemonImpl>,
damage: u32,
source: DamageSource,
) -> WasmResult<()>;
fn pokemon_heal(
r: ExternRef<PokemonImpl>,
amount: u32,
allow_revive: bool,
) -> WasmResult<bool>;
fn pokemon_set_weight(r: ExternRef<PokemonImpl>, weight: f32) -> WasmResult<()>;
fn pokemon_clear_status(r: ExternRef<PokemonImpl>) -> WasmResult<()>;
fn pokemon_add_volatile_by_name(
r: ExternRef<PokemonImpl>,
name: *const c_char,
) -> ScriptPtr;
fn pokemon_add_volatile(r: ExternRef<PokemonImpl>, script: ScriptPtr) -> ScriptPtr;
fn pokemon_has_volatile(r: ExternRef<PokemonImpl>, name: *const c_char) -> bool;
fn pokemon_remove_volatile(r: ExternRef<PokemonImpl>, name: *const c_char);
fn pokemon_get_volatile(r: ExternRef<PokemonImpl>, name: *const c_char) -> ScriptPtr;
) -> WasmResult<ScriptPtr>;
fn pokemon_add_volatile(
r: ExternRef<PokemonImpl>,
script: ScriptPtr,
) -> WasmResult<ScriptPtr>;
fn pokemon_has_volatile(r: ExternRef<PokemonImpl>, name: *const c_char)
-> WasmResult<bool>;
fn pokemon_remove_volatile(
r: ExternRef<PokemonImpl>,
name: *const c_char,
) -> WasmResult<()>;
fn pokemon_get_volatile(
r: ExternRef<PokemonImpl>,
name: *const c_char,
) -> WasmResult<ScriptPtr>;
}
}
@@ -537,30 +643,30 @@ mockall::mock!(
pub Pokemon {}
impl PokemonTrait for Pokemon {
fn reference(&self) -> u32;
fn species(&self) -> Species;
fn form(&self) -> Form;
fn active_ability(&self) -> Ability;
fn nature(&self) -> Nature;
fn display_species(&self) -> Species;
fn display_form(&self) -> Form;
fn held_item(&self) -> Option<Item>;
fn battle(&self) -> Option<Battle>;
fn level(&self) -> LevelInt;
fn experience(&self) -> u32;
fn unique_identifier(&self) -> u32;
fn gender(&self) -> Gender;
fn coloring(&self) -> u8;
fn current_health(&self) -> u32;
fn weight(&self) -> f32;
fn height(&self) -> f32;
fn nickname(&self) -> *const c_char;
fn real_ability(&self) -> AbilityIndex;
fn types_length(&self) -> usize;
fn battle_side_index(&self) -> u8;
fn battle_index(&self) -> u8;
fn is_ability_overriden(&self) -> u8;
fn allowed_experience_gain(&self) -> bool;
fn is_usable(&self) -> bool;
fn species(&self) -> PkmnResult<Species>;
fn form(&self) -> PkmnResult<Form>;
fn active_ability(&self) -> PkmnResult<Ability>;
fn nature(&self) -> PkmnResult<Nature>;
fn display_species(&self) -> PkmnResult<Species>;
fn display_form(&self) -> PkmnResult<Form>;
fn held_item(&self) -> PkmnResult<Option<Item>>;
fn battle(&self) -> PkmnResult<Option<Battle>>;
fn level(&self) -> PkmnResult<LevelInt>;
fn experience(&self) -> PkmnResult<u32>;
fn unique_identifier(&self) -> PkmnResult<u32>;
fn gender(&self) -> PkmnResult<Gender>;
fn coloring(&self) -> PkmnResult<u8>;
fn current_health(&self) -> PkmnResult<u32>;
fn weight(&self) -> PkmnResult<f32>;
fn height(&self) -> PkmnResult<f32>;
fn nickname(&self) -> PkmnResult<*const c_char>;
fn real_ability(&self) -> PkmnResult<AbilityIndex>;
fn types_length(&self) -> PkmnResult<usize>;
fn battle_side_index(&self) -> PkmnResult<u8>;
fn battle_index(&self) -> PkmnResult<u8>;
fn is_ability_overriden(&self) -> PkmnResult<u8>;
fn allowed_experience_gain(&self) -> PkmnResult<bool>;
fn is_usable(&self) -> PkmnResult<bool>;
fn library(&self) -> DynamicLibrary;
fn flat_stats(&self) -> StatisticSet<u32>;
@@ -568,44 +674,44 @@ mockall::mock!(
fn boosted_stats(&self) -> StatisticSet<u32>;
fn individual_values(&self) -> ClampedStatisticSet<u8>;
fn effort_values(&self) -> ClampedStatisticSet<u8>;
fn has_held_item(&self, name: &str) -> bool;
fn set_held_item(&self, item: &Item) -> Option<Item>;
fn remove_held_item(&self) -> Option<Item>;
fn consume_held_item(&self) -> bool;
fn max_health(&self) -> u32;
fn get_type(&self, index: usize) -> u8;
fn has_type(&self, type_identifier: TypeIdentifier) -> bool;
fn has_type_by_name(&self, type_name: &str) -> bool;
fn get_learned_move(&self, index: usize) -> Option<LearnedMove>;
fn change_stat_boost(&self, stat: Statistic, diff_amount: i8, self_inflicted: bool) -> bool;
fn ability_script<'a>(&'a self) -> Option<&'a Box<dyn Script>>;
fn has_held_item(&self, name: &str) -> PkmnResult<bool>;
fn set_held_item(&self, item: &Item) -> PkmnResult<Option<Item>>;
fn remove_held_item(&self) -> PkmnResult<Option<Item>>;
fn consume_held_item(&self) -> PkmnResult<bool>;
fn max_health(&self) -> PkmnResult<u32>;
fn get_type(&self, index: usize) -> PkmnResult<u8>;
fn has_type(&self, type_identifier: TypeIdentifier) -> PkmnResult<bool>;
fn has_type_by_name(&self, type_name: &str) -> PkmnResult<bool>;
fn get_learned_move(&self, index: usize) -> PkmnResult<Option<LearnedMove>>;
fn change_stat_boost(&self, stat: Statistic, diff_amount: i8, self_inflicted: bool) -> PkmnResult<bool>;
fn ability_script<'a>(&'a self) -> PkmnResult<Option<&'a Box<dyn Script>>>;
fn change_species(&self, species: Species, form: Form);
fn change_form(&self, form: Form);
fn is_fainted(&self) -> bool;
fn damage(&self, damage: u32, source: DamageSource);
fn heal(&self, amount: u32, allow_revive: bool) -> bool;
fn is_fainted(&self) -> PkmnResult<bool>;
fn damage(&self, damage: u32, source: DamageSource) -> PkmnResult<()>;
fn heal(&self, amount: u32, allow_revive: bool) -> PkmnResult<bool>;
fn set_weight(&self, weight: f32);
fn clear_status(&self);
fn battle_side(&self) -> BattleSide;
fn battle_side(&self) -> PkmnResult<BattleSide>;
fn equals(&self, other: &Pokemon) -> bool;
}
);
#[cfg(feature = "mock_data")]
impl WithVolatile for MockPokemon {
fn has_volatile(&self, _script_name: &str) -> bool {
fn has_volatile(&self, _script_name: &str) -> PkmnResult<bool> {
unimplemented!()
}
fn add_volatile(&self, _script: Box<dyn Script>) -> &dyn Script {
fn add_volatile(&self, _script: Box<dyn Script>) -> PkmnResult<&dyn Script> {
unimplemented!()
}
fn add_volatile_by_name(&self, _script_name: &str) -> &dyn Script {
fn add_volatile_by_name(&self, _script_name: &str) -> PkmnResult<&dyn Script> {
unimplemented!()
}
fn remove_volatile(&self, _script: &dyn Script) {
fn remove_volatile(&self, _script: &dyn Script) -> PkmnResult<()> {
unimplemented!()
}
fn get_volatile_script<'a>(&'a self, _script_name: &str) -> Option<&'a dyn Script> {
fn get_volatile_script<'a>(&'a self, _script_name: &str) -> PkmnResult<Option<&'a dyn Script>> {
unimplemented!()
}
}

View File

@@ -1,5 +1,7 @@
use crate::app_interface::Statistic;
use crate::{ExternRef, ExternalReferenceType};
#[cfg(not(feature = "mock_data"))]
use crate::handling::wasm_result::WasmResult;
use crate::{ExternRef, ExternalReferenceType, PkmnResult};
use alloc::rc::Rc;
use core::convert::{TryFrom, TryInto};
use core::fmt::Debug;
@@ -12,28 +14,28 @@ where
<T as TryFrom<i64>>::Error: Debug,
<T as TryInto<i64>>::Error: Debug,
{
fn hp(&self) -> T {
fn hp(&self) -> PkmnResult<T> {
self.get_stat(Statistic::Attack)
}
fn attack(&self) -> T {
fn attack(&self) -> PkmnResult<T> {
self.get_stat(Statistic::Attack)
}
fn defense(&self) -> T {
fn defense(&self) -> PkmnResult<T> {
self.get_stat(Statistic::Defense)
}
fn special_attack(&self) -> T {
fn special_attack(&self) -> PkmnResult<T> {
self.get_stat(Statistic::SpecialAttack)
}
fn special_defense(&self) -> T {
fn special_defense(&self) -> PkmnResult<T> {
self.get_stat(Statistic::SpecialDefense)
}
fn speed(&self) -> T {
fn speed(&self) -> PkmnResult<T> {
self.get_stat(Statistic::Speed)
}
fn get_stat(&self, stat: Statistic) -> T;
fn set_stat(&self, stat: Statistic, value: T);
fn increase_stat(&self, stat: Statistic, value: T);
fn decrease_stat(&self, stat: Statistic, value: T);
fn get_stat(&self, stat: Statistic) -> PkmnResult<T>;
fn set_stat(&self, stat: Statistic, value: T) -> PkmnResult<()>;
fn increase_stat(&self, stat: Statistic, value: T) -> PkmnResult<()>;
fn decrease_stat(&self, stat: Statistic, value: T) -> PkmnResult<()>;
}
pub type StatisticSet<T> = Rc<dyn StatisticSetTrait<T>>;
@@ -74,24 +76,29 @@ where
<T as TryFrom<i64>>::Error: Debug,
<T as TryInto<i64>>::Error: Debug,
{
fn get_stat(&self, stat: Statistic) -> T {
fn get_stat(&self, stat: Statistic) -> PkmnResult<T> {
unsafe {
statistic_set_get(self.reference.cast(), stat)
Ok(statistic_set_get(self.reference.cast(), stat)
.as_res()?
.try_into()
.unwrap()
.unwrap())
}
}
fn set_stat(&self, stat: Statistic, value: T) {
unsafe { statistic_set_set(self.reference.cast(), stat, value.try_into().unwrap()) }
fn set_stat(&self, stat: Statistic, value: T) -> PkmnResult<()> {
unsafe {
statistic_set_set(self.reference.cast(), stat, value.try_into().unwrap()).as_res()
}
}
fn increase_stat(&self, stat: Statistic, value: T) {
fn increase_stat(&self, stat: Statistic, value: T) -> PkmnResult<()> {
unsafe {
statistic_set_increase_stat(self.reference.cast(), stat, value.try_into().unwrap())
.as_res()
}
}
fn decrease_stat(&self, stat: Statistic, value: T) {
fn decrease_stat(&self, stat: Statistic, value: T) -> PkmnResult<()> {
unsafe {
statistic_set_decrease_stat(self.reference.cast(), stat, value.try_into().unwrap())
.as_res()
}
}
}
@@ -136,62 +143,68 @@ where
}
#[cfg(not(feature = "mock_data"))]
pub fn hp(&self) -> T {
pub fn hp(&self) -> PkmnResult<T> {
self.get_stat(Statistic::HP)
}
#[cfg(not(feature = "mock_data"))]
pub fn attack(&self) -> T {
pub fn attack(&self) -> PkmnResult<T> {
self.get_stat(Statistic::Attack)
}
#[cfg(not(feature = "mock_data"))]
pub fn defense(&self) -> T {
pub fn defense(&self) -> PkmnResult<T> {
self.get_stat(Statistic::Defense)
}
#[cfg(not(feature = "mock_data"))]
pub fn special_attack(&self) -> T {
pub fn special_attack(&self) -> PkmnResult<T> {
self.get_stat(Statistic::SpecialAttack)
}
#[cfg(not(feature = "mock_data"))]
pub fn special_defense(&self) -> T {
pub fn special_defense(&self) -> PkmnResult<T> {
self.get_stat(Statistic::SpecialDefense)
}
#[cfg(not(feature = "mock_data"))]
pub fn speed(&self) -> T {
pub fn speed(&self) -> PkmnResult<T> {
self.get_stat(Statistic::Speed)
}
#[cfg(not(feature = "mock_data"))]
pub fn get_stat(&self, stat: Statistic) -> T {
pub fn get_stat(&self, stat: Statistic) -> PkmnResult<T> {
unsafe {
clamped_statistic_set_get(self.reference.cast(), stat)
Ok(clamped_statistic_set_get(self.reference.cast(), stat)
.as_res()?
.try_into()
.unwrap()
.unwrap())
}
}
#[cfg(not(feature = "mock_data"))]
pub fn set_stat(&self, stat: Statistic, value: T) {
unsafe { clamped_statistic_set_set(self.reference.cast(), stat, value.try_into().unwrap()) }
pub fn set_stat(&self, stat: Statistic, value: T) -> PkmnResult<()> {
unsafe {
clamped_statistic_set_set(self.reference.cast(), stat, value.try_into().unwrap())
.as_res()
}
}
#[cfg(not(feature = "mock_data"))]
pub fn increase_stat(&self, stat: Statistic, value: T) -> bool {
pub fn increase_stat(&self, stat: Statistic, value: T) -> PkmnResult<bool> {
unsafe {
clamped_statistic_set_increase_stat(
self.reference.cast(),
stat,
value.try_into().unwrap(),
)
.as_res()
}
}
#[cfg(not(feature = "mock_data"))]
pub fn decrease_stat(&self, stat: Statistic, value: T) -> bool {
pub fn decrease_stat(&self, stat: Statistic, value: T) -> PkmnResult<bool> {
unsafe {
clamped_statistic_set_decrease_stat(
self.reference.cast(),
stat,
value.try_into().unwrap(),
)
.as_res()
}
}
}
@@ -210,33 +223,40 @@ where
#[cfg(not(feature = "mock_data"))]
extern "wasm" {
fn statistic_set_get(r: ExternRef<StatisticSetImpl<i64>>, stat: Statistic) -> i64;
fn statistic_set_set(r: ExternRef<StatisticSetImpl<i64>>, stat: Statistic, value: i64);
fn statistic_set_get(r: ExternRef<StatisticSetImpl<i64>>, stat: Statistic) -> WasmResult<i64>;
fn statistic_set_set(
r: ExternRef<StatisticSetImpl<i64>>,
stat: Statistic,
value: i64,
) -> WasmResult<()>;
fn statistic_set_increase_stat(
r: ExternRef<StatisticSetImpl<i64>>,
stat: Statistic,
value: i64,
);
) -> WasmResult<()>;
fn statistic_set_decrease_stat(
r: ExternRef<StatisticSetImpl<i64>>,
stat: Statistic,
value: i64,
);
) -> WasmResult<()>;
fn clamped_statistic_set_get(r: ExternRef<ClampedStatisticSet<i64>>, stat: Statistic) -> i64;
fn clamped_statistic_set_get(
r: ExternRef<ClampedStatisticSet<i64>>,
stat: Statistic,
) -> WasmResult<i64>;
fn clamped_statistic_set_set(
r: ExternRef<ClampedStatisticSet<i64>>,
stat: Statistic,
value: i64,
);
) -> WasmResult<()>;
fn clamped_statistic_set_increase_stat(
r: ExternRef<ClampedStatisticSet<i64>>,
stat: Statistic,
value: i64,
) -> bool;
) -> WasmResult<bool>;
fn clamped_statistic_set_decrease_stat(
r: ExternRef<ClampedStatisticSet<i64>>,
stat: Statistic,
value: i64,
) -> bool;
) -> WasmResult<bool>;
}

View File

@@ -25,13 +25,13 @@ impl TurnChoice {
pub fn user(&self) -> Pokemon {
self.base().user()
}
pub fn speed(&self) -> u32 {
pub fn speed(&self) -> PkmnResult<u32> {
self.base().speed()
}
pub fn has_failed(&self) -> bool {
pub fn has_failed(&self) -> PkmnResult<bool> {
self.base().has_failed()
}
pub fn fail(&self) {
pub fn fail(&self) -> PkmnResult<()> {
self.base().fail()
}
}
@@ -40,9 +40,9 @@ impl TurnChoice {
pub trait BaseTurnChoiceDataTrait {
fn reference(&self) -> u32;
fn user(&self) -> Pokemon;
fn speed(&self) -> u32;
fn has_failed(&self) -> bool;
fn fail(&self);
fn speed(&self) -> PkmnResult<u32>;
fn has_failed(&self) -> PkmnResult<bool>;
fn fail(&self) -> PkmnResult<()>;
}
pub type BaseTurnChoiceData = Rc<dyn BaseTurnChoiceDataTrait>;
@@ -55,8 +55,8 @@ pub trait MoveTurnChoiceDataTrait {
fn used_move(&self) -> LearnedMove;
fn target_side(&self) -> u8;
fn target_index(&self) -> u8;
fn priority(&self) -> i8;
fn move_script<'a>(&self) -> Option<&'a Box<dyn Script>>;
fn priority(&self) -> PkmnResult<i8>;
fn move_script<'a>(&self) -> PkmnResult<Option<&'a Box<dyn Script>>>;
}
#[cfg(feature = "mock_data")]
pub type MockMoveTurnChoiceData = MockMoveTurnChoiceDataTrait;
@@ -65,10 +65,11 @@ pub type MockMoveTurnChoiceData = MockMoveTurnChoiceDataTrait;
mod implementation {
use super::*;
use crate::app_interface::{LearnedMoveImpl, PokemonImpl};
use crate::cached_value;
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>,
@@ -83,14 +84,14 @@ mod implementation {
fn user(&self) -> Pokemon {
self.user.value()
}
fn speed(&self) -> u32 {
unsafe { turn_choice_get_speed(self.reference) }
fn speed(&self) -> PkmnResult<u32> {
unsafe { turn_choice_get_speed(self.reference).as_res() }
}
fn has_failed(&self) -> bool {
unsafe { turn_choice_has_failed(self.reference) }
fn has_failed(&self) -> PkmnResult<bool> {
unsafe { turn_choice_has_failed(self.reference).as_res() }
}
fn fail(&self) {
unsafe { turn_choice_fail(self.reference) }
fn fail(&self) -> PkmnResult<()> {
unsafe { turn_choice_fail(self.reference).as_res() }
}
}
@@ -121,18 +122,24 @@ mod implementation {
fn target_index(&self) -> u8 {
self.inner.value().target_index.value()
}
fn priority(&self) -> i8 {
unsafe { turn_choice_move_priority(self.base().reference().into()) }
fn priority(&self) -> PkmnResult<i8> {
unsafe { turn_choice_move_priority(self.base().reference().into()).as_res() }
}
fn move_script<'a>(&self) -> Option<&'a Box<dyn Script>> {
unsafe { turn_choice_move_script(self.base().reference().into()).as_ref() }
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) };
let kind = unsafe { turn_choice_get_kind(reference).unwrap() };
match kind {
0 => TurnChoice::Move(Box::new(MoveTurnChoiceDataImpl {
inner: Temporary::new(
@@ -152,39 +159,50 @@ mod implementation {
base: Rc::new(BaseTurnChoiceDataImpl {
reference: reference.cast(),
user: cached_value!({
Rc::new(turn_choice_get_user(reference.cast()).get_value().unwrap())
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()) }),
target_index: cached_value!({ turn_choice_move_target_index(reference.cast()) }),
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>) -> u8;
fn turn_choice_get_user(r: ExternRef<TurnChoice>) -> ExternRef<PokemonImpl>;
fn turn_choice_get_speed(r: ExternRef<TurnChoice>) -> u32;
fn turn_choice_has_failed(r: ExternRef<TurnChoice>) -> bool;
fn turn_choice_fail(r: ExternRef<TurnChoice>);
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>,
) -> ExternRef<LearnedMoveImpl>;
fn turn_choice_move_target_side(r: ExternRef<MoveTurnChoiceDataImpl>) -> u8;
fn turn_choice_move_target_index(r: ExternRef<MoveTurnChoiceDataImpl>) -> u8;
fn turn_choice_move_priority(r: ExternRef<MoveTurnChoiceDataImpl>) -> i8;
) -> 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>) -> *const Box<dyn Script>;
fn turn_choice_move_script(r: ExternRef<MoveTurnChoiceDataImpl>) -> WasmResult<u32>;
}
}
use crate::PkmnResult;
#[cfg(not(feature = "mock_data"))]
pub use implementation::*;

View File

@@ -1,22 +1,26 @@
use crate::handling::Script;
use crate::PkmnResult;
use alloc::boxed::Box;
pub trait WithVolatile {
fn has_volatile(&self, script_name: &str) -> bool;
fn add_volatile(&self, script: Box<dyn Script>) -> &dyn Script;
fn add_volatile_by_name(&self, script_name: &str) -> &dyn Script;
fn remove_volatile(&self, script: &dyn Script);
fn get_volatile_script(&self, script_name: &str) -> Option<&dyn Script>;
fn has_volatile(&self, script_name: &str) -> PkmnResult<bool>;
fn add_volatile(&self, script: Box<dyn Script>) -> PkmnResult<&dyn Script>;
fn add_volatile_by_name(&self, script_name: &str) -> PkmnResult<&dyn Script>;
fn remove_volatile(&self, script: &dyn Script) -> PkmnResult<()>;
fn get_volatile_script(&self, script_name: &str) -> PkmnResult<Option<&dyn Script>>;
}
pub fn get_volatile_as<'a, T>(v: &'a dyn WithVolatile, script_name: &str) -> Option<&'a T>
pub fn get_volatile_as<'a, T>(
v: &'a dyn WithVolatile,
script_name: &str,
) -> PkmnResult<Option<&'a T>>
where
T: Script + 'static,
{
let s = v.get_volatile_script(script_name);
let s = v.get_volatile_script(script_name)?;
if let Some(s) = s {
Some(s.as_any().downcast_ref::<T>().unwrap())
Ok(Some(s.as_any().downcast_ref::<T>().unwrap()))
} else {
None
Ok(None)
}
}

View File

@@ -1,204 +0,0 @@
use alloc::rc::Rc;
pub trait ImmutableListTrait<T> {
fn get(&self, index: u32) -> Option<T>;
}
pub type ImmutableList<T> = Rc<dyn ImmutableListTrait<T>>;
#[cfg(not(feature = "mock_data"))]
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>,
resource_type: PhantomData<T>,
values: spin::RwLock<Vec<Option<Option<Rc<T>>>>>,
}
pub(crate) trait ImmutableListWasm<T: Clone + ExternalReferenceType> {
fn initialize(inner: *const ImmutableListInner<T>) -> Self
where
Self: Sized;
fn new(extern_ref: VecExternRef<T>) -> Self
where
Self: Sized,
{
let mut values = Vec::new();
values.resize(extern_ref.len() as usize, None);
let inner = Box::new(ImmutableListInner {
extern_ref,
resource_type: Default::default(),
values: spin::RwLock::new(values),
});
let inner_ptr = Box::into_raw(inner);
Self::initialize(inner_ptr)
}
fn from_ref(extern_ref: VecExternRef<T>) -> Self
where
Self: Sized,
{
unsafe {
if let None = CACHE {
CACHE = Some(hashbrown::HashMap::new());
}
let existing = CACHE
.as_ref()
.unwrap()
.get(&extern_ref.get_internal_index());
if let Some(v) = existing {
let inner = *v as *const ImmutableListInner<T>;
Self::initialize(inner)
} else {
let v = Self::new(extern_ref);
CACHE.as_mut().unwrap().insert(
extern_ref.get_internal_index(),
v.get_inner_ptr() as *const u8,
);
v
}
}
}
fn get_inner(&self) -> &ImmutableListInner<T> {
unsafe { self.get_inner_ptr().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 v = rg.get(index as usize).unwrap();
if let Some(v) = v {
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 value = r.get_value();
let value = if let Some(value) = value {
Some(Rc::new(value))
} else {
None
};
let mut wg = inner.values.write();
wg[index as usize] = Some(value);
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(not(feature = "mock_data"))]
pub use implementation::*;

View File

@@ -1,5 +1,4 @@
pub mod dynamic_data;
pub mod list;
pub mod static_data;
pub mod string_key;

View File

@@ -9,7 +9,7 @@ pub trait AbilityTrait {
pub type Ability = Rc<dyn AbilityTrait>;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
#[repr(C)]
pub struct AbilityIndex {
pub hidden: bool,
@@ -19,21 +19,20 @@ pub struct AbilityIndex {
#[cfg(not(feature = "mock_data"))]
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::handling::extern_ref::{ExternRef, ExternalReferenceType};
use crate::handling::ffi_array::FFIArray;
use crate::handling::{Cacheable, WasmResult};
use crate::{cached_value, cached_value_getters};
use alloc::rc::Rc;
use alloc::vec::Vec;
struct AbilityInner {
reference: ExternRef<AbilityImpl>,
name: CachedValue<StringKey>,
effect: CachedValue<StringKey>,
parameters: CachedValue<ImmutableList<Rc<EffectParameter>>>,
parameters: CachedValue<Vec<Rc<EffectParameter>>>,
}
#[derive(Clone)]
@@ -47,12 +46,21 @@ mod implementation {
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() }),
name: cached_value!({
ability_get_name(reference).unwrap().get_value().unwrap()
}),
effect: cached_value!({
ability_get_effect(reference).unwrap().get_value().unwrap()
}),
parameters: cached_value!({
Rc::new(EffectParameterImmutableList::from_ref(
ability_get_parameters(reference),
))
let pars: FFIArray<ExternRef<EffectParameter>> =
FFIArray::from_u64(ability_get_parameters(reference).unwrap());
let pars = Vec::from_raw_parts(pars.ptr(), pars.len(), pars.len());
let pars = pars
.into_iter()
.map(|r| Rc::new(EffectParameter::new(r).unwrap()))
.collect::<Vec<_>>();
pars
}),
}),
})
@@ -77,9 +85,9 @@ mod implementation {
#[cfg(not(feature = "mock_data"))]
extern "wasm" {
fn ability_get_name(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_name(r: ExternRef<AbilityImpl>) -> WasmResult<ExternRef<StringKey>>;
fn ability_get_effect(r: ExternRef<AbilityImpl>) -> WasmResult<ExternRef<StringKey>>;
fn ability_get_parameters(r: ExternRef<AbilityImpl>) -> WasmResult<u64>;
}
}

View File

@@ -35,7 +35,7 @@ mod implementation {
use crate::app_interface::{get_hash, StringKey};
use crate::handling::cached_value::CachedValue;
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
use crate::handling::Cacheable;
use crate::handling::{Cacheable, WasmResult};
use crate::{cached_value, cached_value_getters};
use spin::RwLock;
@@ -60,24 +60,41 @@ mod implementation {
inner: Rc::new(StaticDataInner {
reference,
move_library: cached_value!({
Rc::new(static_data_get_move_library(reference).get_value().unwrap())
Rc::new(
static_data_get_move_library(reference)
.unwrap()
.get_value()
.unwrap(),
)
}),
item_library: cached_value!({
Rc::new(static_data_get_item_library(reference).get_value().unwrap())
Rc::new(
static_data_get_item_library(reference)
.unwrap()
.get_value()
.unwrap(),
)
}),
species_library: cached_value!({
Rc::new(
static_data_get_species_library(reference)
.unwrap()
.get_value()
.unwrap(),
)
}),
type_library: cached_value!({
Rc::new(static_data_get_type_library(reference).get_value().unwrap())
Rc::new(
static_data_get_type_library(reference)
.unwrap()
.get_value()
.unwrap(),
)
}),
settings: cached_value!({
Rc::new(
static_data_get_library_settings(reference)
.unwrap()
.get_value()
.unwrap(),
)
@@ -119,7 +136,9 @@ mod implementation {
pub(crate) fn new(ptr: ExternRef<LibrarySettingsImpl>) -> Self {
Self {
inner: Rc::new(LibrarySettingsInner {
maximum_level: cached_value!({ library_settings_get_maximum_level(ptr) }),
maximum_level: cached_value!({
library_settings_get_maximum_level(ptr).unwrap()
}),
}),
}
}
@@ -142,21 +161,23 @@ mod implementation {
extern "wasm" {
fn static_data_get_move_library(
ptr: ExternRef<StaticDataImpl>,
) -> ExternRef<MoveLibraryImpl>;
) -> WasmResult<ExternRef<MoveLibraryImpl>>;
fn static_data_get_item_library(
ptr: ExternRef<StaticDataImpl>,
) -> ExternRef<ItemLibraryImpl>;
) -> WasmResult<ExternRef<ItemLibraryImpl>>;
fn static_data_get_species_library(
ptr: ExternRef<StaticDataImpl>,
) -> ExternRef<SpeciesLibraryImpl>;
) -> WasmResult<ExternRef<SpeciesLibraryImpl>>;
fn static_data_get_type_library(
ptr: ExternRef<StaticDataImpl>,
) -> ExternRef<TypeLibraryImpl>;
) -> WasmResult<ExternRef<TypeLibraryImpl>>;
fn static_data_get_library_settings(
ptr: ExternRef<StaticDataImpl>,
) -> ExternRef<LibrarySettingsImpl>;
) -> WasmResult<ExternRef<LibrarySettingsImpl>>;
fn library_settings_get_maximum_level(ptr: ExternRef<LibrarySettingsImpl>) -> LevelInt;
fn library_settings_get_maximum_level(
ptr: ExternRef<LibrarySettingsImpl>,
) -> WasmResult<LevelInt>;
}
pub trait DataLibrary<T>: Cacheable
@@ -182,14 +203,16 @@ mod implementation {
where
Self: Sized,
{
if let Some(v) = self.get_cache().read().get(&name.hash()) {
if let Some(v) = self.get_cache().read().get(&name.hash().unwrap()) {
return Some(v.clone());
}
let index = Self::_get_ref_by_name(self.get_self_ref(), name.ptr());
let v = Self::_from_external_ref_index(index);
if let Some(v) = &v {
self.get_cache().write().insert(name.hash(), v.clone());
self.get_cache()
.write()
.insert(name.hash().unwrap(), v.clone());
}
v
}
@@ -242,7 +265,7 @@ mod mocked {
where
Self: Sized,
{
self.get_cache().read().get(&name.hash()).cloned()
self.get_cache().read().get(&name.hash().unwrap()).cloned()
}
fn get_by_hash(&self, hash: u32) -> Option<T>

View File

@@ -2,17 +2,17 @@ use crate::app_interface::TypeIdentifier;
use alloc::rc::Rc;
pub trait TypeLibraryTrait {
fn get_type_from_name(&self, name: &str) -> Option<TypeIdentifier>;
fn get_type_from_name(&self, name: &str) -> PkmnResult<Option<TypeIdentifier>>;
fn get_single_effectiveness(
&self,
attacking_type: TypeIdentifier,
defending_type: TypeIdentifier,
) -> f32;
) -> PkmnResult<f32>;
fn get_effectiveness(
&self,
attacking_type: TypeIdentifier,
defending_types: &[TypeIdentifier],
) -> f32;
) -> PkmnResult<f32>;
}
pub type Typelibrary = Rc<dyn TypeLibraryTrait>;
@@ -21,6 +21,8 @@ pub type Typelibrary = Rc<dyn TypeLibraryTrait>;
mod implementation {
use super::*;
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
use crate::handling::WasmResult;
use crate::PkmnResult;
use alloc::rc::Rc;
use alloc::string::{String, ToString};
use cstr_core::{c_char, CString};
@@ -51,35 +53,37 @@ mod implementation {
}
impl TypeLibraryTrait for TypeLibraryImpl {
fn get_type_from_name(&self, name: &str) -> Option<TypeIdentifier> {
fn get_type_from_name(&self, name: &str) -> PkmnResult<Option<TypeIdentifier>> {
if let Some(cached) = self.inner.name_to_type_cache.read().get(name) {
return Some(*cached);
return Ok(Some(*cached));
}
let cstr = CString::new(name).unwrap();
let v = unsafe { type_library_get_type_by_name(self.inner.reference, cstr.as_ptr()) };
let v = unsafe {
type_library_get_type_by_name(self.inner.reference, cstr.as_ptr()).as_res()?
};
if v == 255 {
return None;
return Ok(None);
}
let v = v.into();
self.inner
.name_to_type_cache
.write()
.insert(name.to_string(), v);
Some(v)
Ok(Some(v))
}
fn get_single_effectiveness(
&self,
attacking_type: TypeIdentifier,
defending_type: TypeIdentifier,
) -> f32 {
) -> PkmnResult<f32> {
if let Some(cached) = self
.inner
.effectiveness_cache
.read()
.get(&(attacking_type, defending_type))
{
return *cached;
return Ok(*cached);
}
let effectiveness = unsafe {
type_library_get_single_effectiveness(
@@ -87,24 +91,25 @@ mod implementation {
attacking_type.into(),
defending_type.into(),
)
};
}
.as_res()?;
self.inner
.effectiveness_cache
.write()
.insert((attacking_type, defending_type), effectiveness);
effectiveness
Ok(effectiveness)
}
fn get_effectiveness(
&self,
attacking_type: TypeIdentifier,
defending_types: &[TypeIdentifier],
) -> f32 {
) -> PkmnResult<f32> {
let mut f = 1.0;
for defending_type in defending_types {
f *= self.get_single_effectiveness(attacking_type, *defending_type);
f *= self.get_single_effectiveness(attacking_type, *defending_type)?;
}
f
Ok(f)
}
}
@@ -123,10 +128,14 @@ mod implementation {
r: ExternRef<TypeLibraryImpl>,
attacking_type: u8,
defending_type: u8,
) -> f32;
fn type_library_get_type_by_name(r: ExternRef<TypeLibraryImpl>, name: *const c_char) -> u8;
) -> WasmResult<f32>;
fn type_library_get_type_by_name(
r: ExternRef<TypeLibraryImpl>,
name: *const c_char,
) -> WasmResult<u8>;
}
}
use crate::PkmnResult;
#[cfg(not(feature = "mock_data"))]
pub use implementation::*;

View File

@@ -1,9 +1,10 @@
use crate::app_interface::StringKey;
#[cfg(not(feature = "mock_data"))]
use crate::{ExternRef, ExternalReferenceType};
use crate::{handling::WasmResult, ExternRef, ExternalReferenceType, PkmnResult};
use core::fmt::{Display, Formatter};
#[repr(u8)]
#[derive(Copy, Clone)]
enum EffectParameterType {
None,
Bool,
@@ -12,6 +13,12 @@ enum EffectParameterType {
String,
}
impl Default for EffectParameterType {
fn default() -> Self {
Self::None
}
}
#[derive(Clone)]
pub enum EffectParameter {
None,
@@ -23,18 +30,18 @@ pub enum EffectParameter {
impl EffectParameter {
#[cfg(not(feature = "mock_data"))]
pub(crate) fn new(ptr: ExternRef<Self>) -> Self {
unsafe {
match effect_parameter_get_type(ptr) {
pub(crate) fn new(ptr: ExternRef<Self>) -> PkmnResult<Self> {
Ok(unsafe {
match effect_parameter_get_type(ptr).as_res()? {
EffectParameterType::None => Self::None,
EffectParameterType::Bool => Self::Bool(effect_parameter_as_bool(ptr)),
EffectParameterType::Int => Self::Int(effect_parameter_as_int(ptr)),
EffectParameterType::Float => Self::Float(effect_parameter_as_float(ptr)),
EffectParameterType::Bool => Self::Bool(effect_parameter_as_bool(ptr).as_res()?),
EffectParameterType::Int => Self::Int(effect_parameter_as_int(ptr).as_res()?),
EffectParameterType::Float => Self::Float(effect_parameter_as_float(ptr).as_res()?),
EffectParameterType::String => {
Self::String(StringKey::new(effect_parameter_as_string(ptr)))
Self::String(StringKey::new(effect_parameter_as_string(ptr).as_res()?))
}
}
}
})
}
pub fn as_bool(&self) -> bool {
@@ -72,7 +79,7 @@ impl ExternalReferenceType for EffectParameter {
where
Self: Sized,
{
EffectParameter::new(reference)
EffectParameter::new(reference).unwrap()
}
}
@@ -92,9 +99,13 @@ impl Display for EffectParameter {
#[cfg(not(feature = "mock_data"))]
extern "wasm" {
fn effect_parameter_get_type(ptr: ExternRef<EffectParameter>) -> EffectParameterType;
fn effect_parameter_as_bool(ptr: ExternRef<EffectParameter>) -> bool;
fn effect_parameter_as_int(ptr: ExternRef<EffectParameter>) -> i64;
fn effect_parameter_as_float(ptr: ExternRef<EffectParameter>) -> f32;
fn effect_parameter_as_string(ptr: ExternRef<EffectParameter>) -> ExternRef<StringKey>;
fn effect_parameter_get_type(
ptr: ExternRef<EffectParameter>,
) -> WasmResult<EffectParameterType>;
fn effect_parameter_as_bool(ptr: ExternRef<EffectParameter>) -> WasmResult<bool>;
fn effect_parameter_as_int(ptr: ExternRef<EffectParameter>) -> WasmResult<i64>;
fn effect_parameter_as_float(ptr: ExternRef<EffectParameter>) -> WasmResult<f32>;
fn effect_parameter_as_string(
ptr: ExternRef<EffectParameter>,
) -> WasmResult<ExternRef<StringKey>>;
}

View File

@@ -23,6 +23,12 @@ pub enum ItemCategory {
Mail,
}
impl Default for ItemCategory {
fn default() -> Self {
Self::MiscItem
}
}
/// A battle item category defines how the item is categorized when in battle.
#[repr(u8)]
#[derive(Clone)]
@@ -39,6 +45,12 @@ pub enum BattleItemCategory {
MiscBattleItem,
}
impl Default for BattleItemCategory {
fn default() -> Self {
Self::None
}
}
#[cfg_attr(feature = "mock_data", mockall::automock)]
pub trait ItemTrait {
fn reference(&self) -> u32;
@@ -50,7 +62,7 @@ pub trait ItemTrait {
fn battle_category(&self) -> BattleItemCategory;
/// The buying value of the item.
fn price(&self) -> i32;
fn has_flag(&self, flag: &StringKey) -> bool;
fn has_flag(&self, flag: &StringKey) -> PkmnResult<bool>;
}
pub type Item = Rc<dyn ItemTrait>;
@@ -62,8 +74,8 @@ mod implementation {
use crate::app_interface::{BattleItemCategory, ItemCategory, ItemTrait, StringKey};
use crate::handling::cached_value::CachedValue;
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
use crate::handling::Cacheable;
use crate::{cached_value, cached_value_getters};
use crate::handling::{Cacheable, WasmResult};
use crate::{cached_value, cached_value_getters, PkmnResult};
use alloc::rc::Rc;
struct ItemInner {
@@ -86,10 +98,12 @@ mod implementation {
Self::from_ref(reference, &|reference| Self {
inner: Rc::new(ItemInner {
reference,
name: cached_value!({ StringKey::new(item_get_name(reference)) }),
category: cached_value!({ item_get_category(reference) }),
battle_category: cached_value!({ item_get_battle_category(reference) }),
price: cached_value!({ item_get_price(reference) }),
name: cached_value!({ StringKey::new(item_get_name(reference).unwrap()) }),
category: cached_value!({ item_get_category(reference).unwrap() }),
battle_category: cached_value!({
item_get_battle_category(reference).unwrap()
}),
price: cached_value!({ item_get_price(reference).unwrap() }),
}),
})
}
@@ -116,8 +130,8 @@ mod implementation {
fn price(&self) -> i32;
}
fn has_flag(&self, flag: &StringKey) -> bool {
unsafe { item_has_flag(self.inner.reference, flag.ptr()) }
fn has_flag(&self, flag: &StringKey) -> PkmnResult<bool> {
unsafe { item_has_flag(self.inner.reference, flag.ptr()).as_res() }
}
}
@@ -131,13 +145,14 @@ mod implementation {
}
extern "wasm" {
fn item_get_name(ptr: ExternRef<ItemImpl>) -> ExternRef<StringKey>;
fn item_get_category(ptr: ExternRef<ItemImpl>) -> ItemCategory;
fn item_get_battle_category(ptr: ExternRef<ItemImpl>) -> BattleItemCategory;
fn item_get_price(ptr: ExternRef<ItemImpl>) -> i32;
fn item_has_flag(ptr: ExternRef<ItemImpl>, flag: ExternRef<StringKey>) -> bool;
fn item_get_name(ptr: ExternRef<ItemImpl>) -> WasmResult<ExternRef<StringKey>>;
fn item_get_category(ptr: ExternRef<ItemImpl>) -> WasmResult<ItemCategory>;
fn item_get_battle_category(ptr: ExternRef<ItemImpl>) -> WasmResult<BattleItemCategory>;
fn item_get_price(ptr: ExternRef<ItemImpl>) -> WasmResult<i32>;
fn item_has_flag(ptr: ExternRef<ItemImpl>, flag: ExternRef<StringKey>) -> WasmResult<bool>;
}
}
use crate::PkmnResult;
#[cfg(not(feature = "mock_data"))]
pub use implementation::*;

View File

@@ -9,6 +9,12 @@ pub enum MoveCategory {
Status = 2,
}
impl Default for MoveCategory {
fn default() -> Self {
Self::Physical
}
}
#[repr(u8)]
#[derive(Clone, Eq, PartialEq)]
pub enum MoveTarget {
@@ -29,6 +35,12 @@ pub enum MoveTarget {
OnSelf,
}
impl Default for MoveTarget {
fn default() -> Self {
Self::Adjacent
}
}
#[cfg_attr(feature = "mock_data", mockall::automock)]
pub trait MoveDataTrait {
fn name(&self) -> StringKey;
@@ -39,7 +51,7 @@ pub trait MoveDataTrait {
fn base_usages(&self) -> u8;
fn target(&self) -> MoveTarget;
fn priority(&self) -> i8;
fn has_flag(&self, flag: &str) -> bool;
fn has_flag(&self, flag: &str) -> PkmnResult<bool>;
}
pub type MoveData = Rc<dyn MoveDataTrait>;
@@ -52,8 +64,8 @@ mod implementation {
use crate::app_interface::get_hash;
use crate::handling::cached_value::CachedValue;
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
use crate::handling::Cacheable;
use crate::{cached_value, cached_value_getters};
use crate::handling::{Cacheable, WasmResult};
use crate::{cached_value, cached_value_getters, PkmnResult};
struct MoveDataInner {
ptr: ExternRef<MoveDataImpl>,
@@ -77,14 +89,14 @@ mod implementation {
MoveDataImpl::from_ref(ptr, &|ptr| Self {
inner: Rc::new(MoveDataInner {
ptr,
name: cached_value!({ StringKey::new(move_data_get_name(ptr)) }),
move_type: cached_value!({ move_data_get_type(ptr) }),
category: cached_value!({ move_data_get_category(ptr) }),
base_power: cached_value!({ move_data_get_base_power(ptr) }),
accuracy: cached_value!({ move_data_get_accuracy(ptr) }),
base_usages: cached_value!({ move_data_get_base_power(ptr) }),
target: cached_value!({ move_data_get_target(ptr) }),
priority: cached_value!({ move_data_get_priority(ptr) }),
name: cached_value!({ StringKey::new(move_data_get_name(ptr).unwrap()) }),
move_type: cached_value!({ move_data_get_type(ptr).unwrap() }),
category: cached_value!({ move_data_get_category(ptr).unwrap() }),
base_power: cached_value!({ move_data_get_base_power(ptr).unwrap() }),
accuracy: cached_value!({ move_data_get_accuracy(ptr).unwrap() }),
base_usages: cached_value!({ move_data_get_base_power(ptr).unwrap() }),
target: cached_value!({ move_data_get_target(ptr).unwrap() }),
priority: cached_value!({ move_data_get_priority(ptr).unwrap() }),
}),
})
}
@@ -102,9 +114,9 @@ mod implementation {
fn priority(&self) -> i8;
}
fn has_flag(&self, flag: &str) -> bool {
fn has_flag(&self, flag: &str) -> PkmnResult<bool> {
let hash = get_hash(flag);
unsafe { move_data_has_flag_by_hash(self.inner.ptr, hash) }
unsafe { move_data_has_flag_by_hash(self.inner.ptr, hash).as_res() }
}
}
@@ -117,17 +129,21 @@ mod implementation {
crate::handling::cacheable::cacheable!(MoveDataImpl);
extern "wasm" {
fn move_data_get_name(ptr: ExternRef<MoveDataImpl>) -> ExternRef<StringKey>;
fn move_data_get_type(ptr: ExternRef<MoveDataImpl>) -> u8;
fn move_data_get_category(ptr: ExternRef<MoveDataImpl>) -> MoveCategory;
fn move_data_get_base_power(ptr: ExternRef<MoveDataImpl>) -> u8;
fn move_data_get_accuracy(ptr: ExternRef<MoveDataImpl>) -> u8;
fn move_data_get_base_usages(ptr: ExternRef<MoveDataImpl>) -> u8;
fn move_data_get_target(ptr: ExternRef<MoveDataImpl>) -> MoveTarget;
fn move_data_get_priority(ptr: ExternRef<MoveDataImpl>) -> i8;
fn move_data_has_flag_by_hash(ptr: ExternRef<MoveDataImpl>, flag_hash: u32) -> bool;
fn move_data_get_name(ptr: ExternRef<MoveDataImpl>) -> WasmResult<ExternRef<StringKey>>;
fn move_data_get_type(ptr: ExternRef<MoveDataImpl>) -> WasmResult<u8>;
fn move_data_get_category(ptr: ExternRef<MoveDataImpl>) -> WasmResult<MoveCategory>;
fn move_data_get_base_power(ptr: ExternRef<MoveDataImpl>) -> WasmResult<u8>;
fn move_data_get_accuracy(ptr: ExternRef<MoveDataImpl>) -> WasmResult<u8>;
fn move_data_get_base_usages(ptr: ExternRef<MoveDataImpl>) -> WasmResult<u8>;
fn move_data_get_target(ptr: ExternRef<MoveDataImpl>) -> WasmResult<MoveTarget>;
fn move_data_get_priority(ptr: ExternRef<MoveDataImpl>) -> WasmResult<i8>;
fn move_data_has_flag_by_hash(
ptr: ExternRef<MoveDataImpl>,
flag_hash: u32,
) -> WasmResult<bool>;
}
}
use crate::PkmnResult;
#[cfg(not(feature = "mock_data"))]
pub use implementation::*;

View File

@@ -14,7 +14,7 @@ pub type Nature = Rc<dyn NatureTrait>;
mod implementation {
use super::*;
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
use crate::handling::Cacheable;
use crate::handling::{Cacheable, WasmResult};
struct NatureInner {
reference: ExternRef<NatureImpl>,
@@ -41,10 +41,10 @@ mod implementation {
Self {
inner: Rc::new(NatureInner {
reference,
increase_stat: nature_get_increase_stat(reference),
decrease_stat: nature_get_decrease_stat(reference),
increase_modifier: nature_get_increase_modifier(reference),
decrease_modifier: nature_get_decrease_modifier(reference),
increase_stat: nature_get_increase_stat(reference).unwrap(),
decrease_stat: nature_get_decrease_stat(reference).unwrap(),
increase_modifier: nature_get_increase_modifier(reference).unwrap(),
decrease_modifier: nature_get_decrease_modifier(reference).unwrap(),
}),
}
})
@@ -76,10 +76,10 @@ mod implementation {
}
extern "wasm" {
fn nature_get_increase_stat(r: ExternRef<NatureImpl>) -> Statistic;
fn nature_get_decrease_stat(r: ExternRef<NatureImpl>) -> Statistic;
fn nature_get_increase_modifier(r: ExternRef<NatureImpl>) -> f32;
fn nature_get_decrease_modifier(r: ExternRef<NatureImpl>) -> f32;
fn nature_get_increase_stat(r: ExternRef<NatureImpl>) -> WasmResult<Statistic>;
fn nature_get_decrease_stat(r: ExternRef<NatureImpl>) -> WasmResult<Statistic>;
fn nature_get_increase_modifier(r: ExternRef<NatureImpl>) -> WasmResult<f32>;
fn nature_get_decrease_modifier(r: ExternRef<NatureImpl>) -> WasmResult<f32>;
}
}

View File

@@ -1,27 +1,32 @@
use crate::app_interface::list::ImmutableList;
use crate::app_interface::{ImmutableStatisticSet, StringKey};
use alloc::rc::Rc;
use alloc::vec::Vec;
use core::any::Any;
#[repr(u8)]
#[derive(Eq, PartialEq, Debug)]
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
pub enum Gender {
Male = 0,
Female = 1,
Genderless = 2,
}
impl Default for Gender {
fn default() -> Self {
Self::Genderless
}
}
pub trait FormTrait {
fn name(&self) -> StringKey;
fn height(&self) -> f32;
fn weight(&self) -> f32;
fn base_experience(&self) -> u32;
fn base_stats(&self) -> ImmutableStatisticSet;
fn abilities(&self) -> ImmutableList<Rc<StringKey>>;
fn hidden_abilities(&self) -> ImmutableList<Rc<StringKey>>;
fn abilities(&self) -> Vec<Rc<StringKey>>;
fn hidden_abilities(&self) -> Vec<Rc<StringKey>>;
fn types(&self) -> &Vec<u8>;
fn has_flag(&self, flag: &str) -> bool;
fn has_flag(&self, flag: &str) -> PkmnResult<bool>;
fn as_any(&self) -> &dyn Any;
}
@@ -39,7 +44,7 @@ pub trait SpeciesTrait {
/// uncatchable.
fn capture_rate(&self) -> u8;
fn get_form(&self, form_name: &str) -> Option<Form>;
fn has_flag(&self, flag: &str) -> bool;
fn has_flag(&self, flag: &str) -> PkmnResult<bool>;
fn as_any(&self) -> &dyn Any;
}
@@ -50,13 +55,13 @@ pub type Species = Rc<dyn SpeciesTrait>;
#[cfg(not(feature = "mock_data"))]
mod implementation {
use super::*;
use crate::app_interface::list::ImmutableListWasm;
use crate::app_interface::{get_hash, ImmutableStatisticSetImpl};
use crate::handling::cached_value::CachedValue;
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType, VecExternRef};
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
use crate::handling::ffi_array::FFIArray;
use crate::handling::wasm_result::WasmResult;
use crate::handling::Cacheable;
use crate::{cached_value, cached_value_getters};
use crate::{cached_value, cached_value_getters, PkmnResult};
use spin::RwLock;
struct FormInner {
@@ -67,8 +72,8 @@ mod implementation {
types: CachedValue<Vec<u8>>,
base_experience: CachedValue<u32>,
base_stats: CachedValue<ImmutableStatisticSet>,
abilities: CachedValue<ImmutableList<Rc<StringKey>>>,
hidden_abilities: CachedValue<ImmutableList<Rc<StringKey>>>,
abilities: CachedValue<Vec<Rc<StringKey>>>,
hidden_abilities: CachedValue<Vec<Rc<StringKey>>>,
// moves: CachedValue<LearnableMoves>,
}
@@ -82,30 +87,38 @@ mod implementation {
Self::from_ref(reference, &|reference| Self {
inner: Rc::new(FormInner {
reference,
name: cached_value!({ form_get_name(reference).get_value().unwrap() }),
height: cached_value!({ form_get_height(reference) }),
weight: cached_value!({ form_get_weight(reference) }),
name: cached_value!({ form_get_name(reference).unwrap().get_value().unwrap() }),
height: cached_value!({ form_get_height(reference).unwrap() }),
weight: cached_value!({ form_get_weight(reference).unwrap() }),
types: cached_value!({
let raw = form_get_types(reference);
let raw = FFIArray::from_u64(form_get_types(reference).unwrap());
Vec::from_raw_parts(raw.ptr(), raw.len(), raw.len())
}),
base_experience: cached_value!({ form_get_base_experience(reference) }),
base_experience: cached_value!({
form_get_base_experience(reference).unwrap()
}),
base_stats: cached_value!({
Rc::new(form_get_base_stats(reference).get_value().unwrap())
Rc::new(form_get_base_stats(reference).unwrap().get_value().unwrap())
}),
abilities: cached_value!({
Rc::new(
crate::app_interface::list::StringKeyImmutableList::from_ref(
form_get_abilities(reference),
),
)
let abilities: FFIArray<ExternRef<StringKey>> =
FFIArray::from_u64(form_get_abilities(reference).unwrap());
let abilities =
Vec::from_raw_parts(abilities.ptr(), abilities.len(), abilities.len());
abilities
.into_iter()
.map::<Rc<StringKey>, _>(|r| Rc::new(StringKey::new(r)))
.collect()
}),
hidden_abilities: cached_value!({
Rc::new(
crate::app_interface::list::StringKeyImmutableList::from_ref(
form_get_hidden_abilities(reference),
),
)
let abilities: FFIArray<ExternRef<StringKey>> =
FFIArray::from_u64(form_get_hidden_abilities(reference).unwrap());
let abilities =
Vec::from_raw_parts(abilities.ptr(), abilities.len(), abilities.len());
abilities
.into_iter()
.map::<Rc<StringKey>, _>(|r| Rc::new(StringKey::new(r)))
.collect()
}),
}),
})
@@ -123,16 +136,16 @@ mod implementation {
fn weight(&self) -> f32;
fn base_experience(&self) -> u32;
fn base_stats(&self) -> ImmutableStatisticSet;
fn abilities(&self) -> ImmutableList<Rc<StringKey>>;
fn hidden_abilities(&self) -> ImmutableList<Rc<StringKey>>;
fn abilities(&self) -> Vec<Rc<StringKey>>;
fn hidden_abilities(&self) -> Vec<Rc<StringKey>>;
}
fn types(&self) -> &Vec<u8> {
self.inner.types.value_ref()
}
fn has_flag(&self, flag: &str) -> bool {
fn has_flag(&self, flag: &str) -> PkmnResult<bool> {
let hash = get_hash(flag);
unsafe { form_has_flag_by_hash(self.inner.reference, hash) }
unsafe { form_has_flag_by_hash(self.inner.reference, hash).as_res() }
}
fn as_any(&self) -> &dyn Any {
@@ -160,13 +173,18 @@ mod implementation {
Self {
inner: Rc::new(SpeciesInner {
reference,
id: cached_value!({ species_get_id(reference) }),
name: cached_value!({ species_get_name(reference).get_value().unwrap() }),
gender_rate: cached_value!({ species_get_gender_rate(reference) }),
growth_rate: cached_value!({
species_get_growth_rate(reference).get_value().unwrap()
id: cached_value!({ species_get_id(reference).unwrap() }),
name: cached_value!({
species_get_name(reference).unwrap().get_value().unwrap()
}),
capture_rate: cached_value!({ species_get_capture_rate(reference) }),
gender_rate: cached_value!({ species_get_gender_rate(reference).unwrap() }),
growth_rate: cached_value!({
species_get_growth_rate(reference)
.unwrap()
.get_value()
.unwrap()
}),
capture_rate: cached_value!({ species_get_capture_rate(reference).unwrap() }),
forms: Default::default(),
}),
}
@@ -198,7 +216,7 @@ mod implementation {
if let Some(v) = self.inner.forms.read().get(&hash) {
v.clone()
} else {
let r = species_get_form_by_hash(self.inner.reference, hash);
let r = species_get_form_by_hash(self.inner.reference, hash).unwrap();
let value = r.get_value();
let value: Option<Form> = if let Some(value) = value {
Some(Rc::new(value))
@@ -211,9 +229,9 @@ mod implementation {
}
}
fn has_flag(&self, flag: &str) -> bool {
fn has_flag(&self, flag: &str) -> PkmnResult<bool> {
let hash = get_hash(flag);
unsafe { species_has_flag_by_hash(self.inner.reference, hash) }
unsafe { species_has_flag_by_hash(self.inner.reference, hash).as_res() }
}
fn as_any(&self) -> &dyn Any {
@@ -237,25 +255,31 @@ mod implementation {
crate::handling::cacheable::cacheable!(SpeciesImpl);
extern "wasm" {
fn form_get_name(r: ExternRef<FormImpl>) -> ExternRef<StringKey>;
fn form_get_height(r: ExternRef<FormImpl>) -> f32;
fn form_get_weight(r: ExternRef<FormImpl>) -> f32;
fn form_get_types(r: ExternRef<FormImpl>) -> FFIArray<u8>;
fn form_get_base_experience(r: ExternRef<FormImpl>) -> u32;
fn form_get_base_stats(r: ExternRef<FormImpl>) -> ExternRef<ImmutableStatisticSetImpl>;
fn form_get_abilities(r: ExternRef<FormImpl>) -> VecExternRef<StringKey>;
fn form_get_hidden_abilities(r: ExternRef<FormImpl>) -> VecExternRef<StringKey>;
fn form_has_flag_by_hash(r: ExternRef<FormImpl>, hash: u32) -> bool;
fn form_get_name(r: ExternRef<FormImpl>) -> WasmResult<ExternRef<StringKey>>;
fn form_get_height(r: ExternRef<FormImpl>) -> WasmResult<f32>;
fn form_get_weight(r: ExternRef<FormImpl>) -> WasmResult<f32>;
fn form_get_types(r: ExternRef<FormImpl>) -> WasmResult<u64>;
fn form_get_base_experience(r: ExternRef<FormImpl>) -> WasmResult<u32>;
fn form_get_base_stats(
r: ExternRef<FormImpl>,
) -> WasmResult<ExternRef<ImmutableStatisticSetImpl>>;
fn form_get_abilities(r: ExternRef<FormImpl>) -> WasmResult<u64>;
fn form_get_hidden_abilities(r: ExternRef<FormImpl>) -> WasmResult<u64>;
fn form_has_flag_by_hash(r: ExternRef<FormImpl>, hash: u32) -> WasmResult<bool>;
fn species_get_id(r: ExternRef<SpeciesImpl>) -> u16;
fn species_get_name(r: ExternRef<SpeciesImpl>) -> ExternRef<StringKey>;
fn species_get_gender_rate(r: ExternRef<SpeciesImpl>) -> f32;
fn species_get_growth_rate(r: ExternRef<SpeciesImpl>) -> ExternRef<StringKey>;
fn species_get_capture_rate(r: ExternRef<SpeciesImpl>) -> u8;
fn species_get_form_by_hash(r: ExternRef<SpeciesImpl>, hash: u32) -> ExternRef<FormImpl>;
fn species_has_flag_by_hash(r: ExternRef<SpeciesImpl>, flag_hash: u32) -> bool;
fn species_get_id(r: ExternRef<SpeciesImpl>) -> WasmResult<u16>;
fn species_get_name(r: ExternRef<SpeciesImpl>) -> WasmResult<ExternRef<StringKey>>;
fn species_get_gender_rate(r: ExternRef<SpeciesImpl>) -> WasmResult<f32>;
fn species_get_growth_rate(r: ExternRef<SpeciesImpl>) -> WasmResult<ExternRef<StringKey>>;
fn species_get_capture_rate(r: ExternRef<SpeciesImpl>) -> WasmResult<u8>;
fn species_get_form_by_hash(
r: ExternRef<SpeciesImpl>,
hash: u32,
) -> WasmResult<ExternRef<FormImpl>>;
fn species_has_flag_by_hash(r: ExternRef<SpeciesImpl>, flag_hash: u32) -> WasmResult<bool>;
}
}
use crate::PkmnResult;
#[cfg(not(feature = "mock_data"))]
pub use implementation::*;

View File

@@ -11,6 +11,12 @@ pub enum Statistic {
Speed = 5,
}
impl Default for Statistic {
fn default() -> Self {
Self::HP
}
}
pub trait ImmutableStatisticSetTrait {
fn hp(&self) -> u16;
fn attack(&self) -> u16;
@@ -28,7 +34,7 @@ mod implementation {
use crate::cached_value;
use crate::handling::cached_value::CachedValue;
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
use crate::handling::Cacheable;
use crate::handling::{Cacheable, WasmResult};
pub struct ImmutableStatisticSetInner {
reference: ExternRef<ImmutableStatisticSetImpl>,
@@ -56,21 +62,24 @@ mod implementation {
Self::from_ref(reference, &|reference| Self {
inner: Rc::new(ImmutableStatisticSetInner {
reference,
hp: cached_value!({ static_statistics_set_get_stat(reference, Statistic::HP) }),
hp: cached_value!({
static_statistics_set_get_stat(reference, Statistic::HP).unwrap()
}),
attack: cached_value!({
static_statistics_set_get_stat(reference, Statistic::Attack)
static_statistics_set_get_stat(reference, Statistic::Attack).unwrap()
}),
defense: cached_value!({
static_statistics_set_get_stat(reference, Statistic::Defense)
static_statistics_set_get_stat(reference, Statistic::Defense).unwrap()
}),
special_attack: cached_value!({
static_statistics_set_get_stat(reference, Statistic::SpecialAttack)
static_statistics_set_get_stat(reference, Statistic::SpecialAttack).unwrap()
}),
special_defense: cached_value!({
static_statistics_set_get_stat(reference, Statistic::SpecialDefense)
.unwrap()
}),
speed: cached_value!({
static_statistics_set_get_stat(reference, Statistic::Speed)
static_statistics_set_get_stat(reference, Statistic::Speed).unwrap()
}),
}),
})
@@ -110,7 +119,7 @@ mod implementation {
fn static_statistics_set_get_stat(
r: ExternRef<ImmutableStatisticSetImpl>,
stat: Statistic,
) -> u16;
) -> WasmResult<u16>;
}
}
#[cfg(not(feature = "mock_data"))]

View File

@@ -1,7 +1,12 @@
#[cfg(not(feature = "mock_data"))]
use crate::alloc::string::ToString;
#[cfg(not(feature = "mock_data"))]
use crate::handling::wasm_result::WasmResult;
#[cfg(not(feature = "mock_data"))]
use crate::handling::Cacheable;
use crate::PkmnResult;
#[cfg(not(feature = "mock_data"))]
use crate::{ExternRef, ExternalReferenceType};
use crate::{pkmn_err, ExternRef, ExternalReferenceType, PkmnErr};
use alloc::rc::Rc;
use core::cell::RefCell;
use core::fmt::{Debug, Display, Formatter};
@@ -21,7 +26,10 @@ pub struct StringKey {
impl Debug for StringKey {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
write!(f, "\"{}\"", self.str().to_str().unwrap())
match self.str() {
Ok(s) => write!(f, "\"{}\"", s.to_str().unwrap()),
Err(e) => write!(f, "Error: {}", e),
}
}
}
@@ -45,41 +53,44 @@ impl StringKey {
}
#[cfg(not(feature = "mock_data"))]
pub fn str(&self) -> &CString {
pub fn str(&self) -> PkmnResult<&CString> {
if self.data.str.borrow().is_none() {
unsafe {
self.data
.str
.replace(Some(CString::from_raw(string_key_get_str(self.ptr()))));
let ptr = string_key_get_str(self.ptr()).as_res()?;
let ptr = ptr as *mut cstr_core::c_char;
self.data.str.replace(Some(CString::from_raw(ptr)));
}
}
unsafe { (*self.data.str.as_ptr()).as_ref().unwrap() }
Ok(unsafe {
(*self.data.str.as_ptr())
.as_ref()
.ok_or(pkmn_err!("Stringkey was null"))?
})
}
#[cfg(feature = "mock_data")]
pub fn str(&self) -> &CString {
unsafe { (*self.data.str.as_ptr()).as_ref().unwrap() }
pub fn str(&self) -> PkmnResult<&CString> {
Ok(unsafe { (*self.data.str.as_ptr()).as_ref().unwrap() })
}
#[cfg(not(feature = "mock_data"))]
pub fn hash(&self) -> u32 {
pub fn hash(&self) -> PkmnResult<u32> {
if self.data.hash.borrow().is_none() {
unsafe {
self.data
.hash
.replace(Some(string_key_get_hash(self.ptr())));
let hash = string_key_get_hash(self.ptr()).as_res()?;
self.data.hash.replace(Some(hash));
}
}
self.data.hash.borrow().unwrap()
Ok(self.data.hash.borrow().unwrap())
}
#[cfg(feature = "mock_data")]
pub fn hash(&self) -> u32 {
self.data.hash.borrow().unwrap()
pub fn hash(&self) -> PkmnResult<u32> {
Ok(self.data.hash.borrow().unwrap())
}
pub fn equals_str(&self, other: &str) -> bool {
self.hash() == get_hash(other)
self.hash().unwrap() == get_hash(other)
}
}
@@ -107,15 +118,15 @@ impl ExternalReferenceType for StringKey {
impl Display for StringKey {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
let s = self.str();
let s = self.str().unwrap();
f.write_str(s.to_str().as_ref().unwrap())
}
}
#[cfg(not(feature = "mock_data"))]
extern "wasm" {
fn string_key_get_str(ptr: ExternRef<StringKey>) -> *mut cstr_core::c_char;
fn string_key_get_hash(ptr: ExternRef<StringKey>) -> u32;
fn string_key_get_str(ptr: ExternRef<StringKey>) -> WasmResult<u32>;
fn string_key_get_hash(ptr: ExternRef<StringKey>) -> WasmResult<u32>;
}
const CRC_TABLE: &[u32] = &[

View File

@@ -7,7 +7,7 @@ pub struct CachedValue<T> {
}
#[cfg(not(feature = "mock_data"))]
impl<T> CachedValue<T> {
impl<T: Clone> CachedValue<T> {
pub fn new(init_fn: Box<dyn Fn() -> T>) -> Self {
Self {
init_fn,
@@ -15,13 +15,15 @@ impl<T> CachedValue<T> {
}
}
#[inline(always)]
fn init_if_empty(&self) {
if self.value.is_none() {
unsafe {
let s = self as *const Self as *mut Self;
s.as_mut().unwrap().value.replace((self.init_fn)());
}
fn init_if_empty(&self) -> T
where
T: Clone,
{
unsafe {
let s = self as *const Self as *mut Self;
let v = (self.init_fn)();
s.as_mut().unwrap().value.replace(v.clone());
v
}
}
@@ -30,8 +32,10 @@ impl<T> CachedValue<T> {
where
T: Clone,
{
self.init_if_empty();
self.value.as_ref().unwrap().clone()
match self.value {
Some(ref v) => v.clone(),
None => self.init_if_empty(),
}
}
#[inline]

View File

@@ -1,8 +1,6 @@
use alloc::rc::Rc;
use core::cmp::Ordering;
use core::hash::{Hash, Hasher};
#[cfg(not(feature = "mock_data"))]
use core::intrinsics::transmute;
use core::marker::PhantomData;
#[repr(C)]
@@ -82,6 +80,15 @@ impl<T> Clone for ExternRef<T> {
impl<T> Copy for ExternRef<T> {}
impl<T> Default for ExternRef<T> {
fn default() -> Self {
Self {
p: 0,
resource_type: Default::default(),
}
}
}
impl<T> Eq for ExternRef<T> {}
impl<T> PartialEq<Self> for ExternRef<T> {
@@ -117,70 +124,6 @@ impl<T> From<u32> for ExternRef<T> {
}
}
#[repr(C)]
pub struct VecExternRef<T> {
v: u64,
resource_type: PhantomData<T>,
}
impl<T> VecExternRef<T> {
pub fn is_null(&self) -> bool {
self.v == 0
}
#[cfg(not(feature = "mock_data"))]
pub(crate) fn get_internal_index(&self) -> u32 {
let v: (u32, u32) = unsafe { transmute(self.v) };
v.0
}
#[cfg(not(feature = "mock_data"))]
pub(crate) fn len(&self) -> u32 {
let v: (u32, u32) = unsafe { transmute(self.v) };
v.1
}
#[cfg(not(feature = "mock_data"))]
pub(crate) fn at(&self, index: u32) -> ExternRef<T> {
let p = unsafe { _vec_extern_ref_get_value(self.get_internal_index(), index) };
ExternRef {
p,
resource_type: Default::default(),
}
}
}
impl<T> Clone for VecExternRef<T> {
fn clone(&self) -> Self {
Self {
v: self.v,
resource_type: Default::default(),
}
}
}
impl<T> Copy for VecExternRef<T> {}
impl<T> Eq for VecExternRef<T> {}
impl<T> PartialEq<Self> for VecExternRef<T> {
fn eq(&self, other: &Self) -> bool {
u64::eq(&self.v, &other.v)
}
}
impl<T> PartialOrd<Self> for VecExternRef<T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
u64::partial_cmp(&self.v, &other.v)
}
}
impl<T> Ord for VecExternRef<T> {
fn cmp(&self, other: &Self) -> Ordering {
u64::cmp(&self.v, &other.v)
}
}
pub trait ExternalReferenceType {
fn from_extern_value(reference: ExternRef<Self>) -> Self
where
@@ -222,8 +165,3 @@ macro_rules! impl_extern_ctor {
}
};
}
#[cfg(not(feature = "mock_data"))]
extern "wasm" {
fn _vec_extern_ref_get_value(extern_ref: u32, index: u32) -> u32;
}

View File

@@ -19,6 +19,24 @@ impl<T> FFIArray<T> {
mem::forget(boxed_slice);
r
}
#[cfg(not(feature = "mock_data"))]
pub(crate) fn from_u64(v: u64) -> Self {
let v: (u32, u32) = unsafe { core::mem::transmute(v) };
Self {
ptr: v.0 as *mut T,
len: v.1 as usize,
}
}
}
impl<T> Default for FFIArray<T> {
fn default() -> Self {
Self {
ptr: core::ptr::null_mut(),
len: 0,
}
}
}
#[cfg(not(feature = "mock_data"))]

View File

@@ -8,6 +8,7 @@ pub mod ffi_array;
pub mod script;
#[cfg(not(feature = "mock_data"))]
pub(crate) mod temporary;
pub(crate) mod wasm_result;
pub use capabilities::*;
@@ -15,6 +16,7 @@ pub use capabilities::*;
pub(crate) use cacheable::Cacheable;
pub use script::Script;
pub use script::ScriptOwner;
pub use wasm_result::*;
#[repr(u8)]
pub enum ScriptCategory {
@@ -41,7 +43,7 @@ macro_rules! wasm_reference_getters_extern {
extern "wasm" {
$(
paste::paste!{
fn [<$type_name:snake _get_ $name>](r: ExternRef<$base_type>) -> ExternRef<$type>;
fn [<$type_name:snake _get_ $name>](r: ExternRef<$base_type>) -> WasmResult<ExternRef<$type>>;
}
)*
}
@@ -151,7 +153,7 @@ macro_rules! wasm_optional_reference_getters_extern {
extern "wasm" {
$(
paste::paste!{
fn [<$type_name:snake _get_ $name>](r: ExternRef<$base_type>) -> ExternRef<$type>;
fn [<$type_name:snake _get_ $name>](r: ExternRef<$base_type>) -> WasmResult<ExternRef<$type>>;
}
)*
}
@@ -228,7 +230,7 @@ macro_rules! wasm_value_getters_extern {
extern "wasm" {
$(
paste::paste!{
fn [<$type_name:snake _get_ $name>](r: ExternRef<$base_type>) -> $type;
fn [<$type_name:snake _get_ $name>](r: ExternRef<$base_type>) -> WasmResult<$type>;
}
)*
}
@@ -246,10 +248,10 @@ macro_rules! wasm_value_getters_funcs {
) => {
$(
$(#[$attr])*
$v fn $name(&self) -> $type {
$v fn $name(&self) -> PkmnResult<$type> {
paste::paste!{
unsafe{
[<$base_type:snake _get_ $name>](self.inner.reference)
[<$base_type:snake _get_ $name>](self.inner.reference).as_res()
}
}
}

View File

@@ -1,4 +1,3 @@
use crate::app_interface::list::ImmutableList;
use crate::app_interface::{
Battle, BattleSide, DamageSource, DynamicLibrary, EffectParameter, ExecutingMove, Item,
Pokemon, Statistic, TurnChoice, TypeIdentifier,
@@ -6,8 +5,10 @@ use crate::app_interface::{
use crate::handling::ScriptCapabilities;
use crate::StringKey;
use alloc::rc::Rc;
use alloc::vec::Vec;
use core::any::Any;
use core::fmt::{Debug, Display, Formatter};
type Result<T> = crate::result::PkmnResult<T>;
pub trait Script {
fn new() -> Self
@@ -18,58 +19,97 @@ pub trait Script {
/// This function is ran when a volatile effect is added while that volatile effect already is
/// in place. Instead of adding the volatile effect twice, it will execute this function instead.
fn stack(&self) {}
fn stack(&self) -> Result<()> {
Ok(())
}
/// This function is ran when this script stops being in effect, and is removed from its owner.
fn on_remove(&self) {}
fn on_remove(&self) -> Result<()> {
Ok(())
}
/// This function is ran when this script starts being in effect.
fn on_initialize(
&self,
_library: DynamicLibrary,
_parameters: Option<ImmutableList<Rc<EffectParameter>>>,
) {
_parameters: Option<Vec<Rc<EffectParameter>>>,
) -> Result<()> {
Ok(())
}
/// This function is ran just before the start of the turn. Everyone has made its choices here,
/// and the turn is about to start. This is a great place to initialize data if you need to know
/// something has happened during a turn.
fn on_before_turn(&self, _choice: TurnChoice) {}
fn on_before_turn(&self, _choice: TurnChoice) -> Result<()> {
Ok(())
}
/// This function allows you to modify the effective speed of the Pokemon. This is ran before
/// turn ordering, so overriding here will allow you to put certain Pokemon before others.
fn change_speed(&self, _choice: TurnChoice, _speed: &mut u32) {}
fn change_speed(&self, _choice: TurnChoice, _speed: &mut u32) -> Result<()> {
Ok(())
}
/// This function allows you to modify the effective priority of the Pokemon. This is ran before
/// turn ordering, so overriding here will allow you to put certain Pokemon before others. Note
/// that this is only relevant on move choices, as other turn choice types do not have a priority.
fn change_priority(&self, _choice: TurnChoice, _priority: &mut i8) {}
fn change_priority(&self, _choice: TurnChoice, _priority: &mut i8) -> Result<()> {
Ok(())
}
/// This function allows you to change the move that is used during execution. This is useful for
/// moves such as metronome, where the move chosen actually differs from the move used.
fn change_move(&self, _choice: TurnChoice, _move_name: &mut StringKey) {}
fn change_move(&self, _choice: TurnChoice, _move_name: &mut StringKey) -> Result<()> {
Ok(())
}
/// This function allows you to change a move into a multi-hit move. The number of hits set here
/// gets used as the number of hits. If set to 0, this will behave as if the move missed on its
/// first hit.
fn change_number_of_hits(&self, _choice: TurnChoice, _number_of_hits: &mut u8) {}
fn change_number_of_hits(&self, _choice: TurnChoice, _number_of_hits: &mut u8) -> Result<()> {
Ok(())
}
/// This function allows you to prevent a move from running. If this gets set to true, the move
/// ends execution here. No PP will be decreased in this case.
fn prevent_move(&self, _move: ExecutingMove, _prevent: &mut bool) {}
fn prevent_move(&self, _move: ExecutingMove, _prevent: &mut bool) -> Result<()> {
Ok(())
}
/// This function makes the move fail. If the fail field gets set to true, the move ends execution,
/// and fail events get triggered.
fn fail_move(&self, _move: ExecutingMove, _fail: &mut bool) {}
fn fail_move(&self, _move: ExecutingMove, _fail: &mut bool) -> Result<()> {
Ok(())
}
/// Similar to [`Self::prevent_move`]. This function will also stop execution, but PP will be
/// decreased.
fn stop_before_move(&self, _move: ExecutingMove, _stop: &mut bool) {}
fn stop_before_move(&self, _move: ExecutingMove, _stop: &mut bool) -> Result<()> {
Ok(())
}
/// This function runs just before the move starts its execution.
fn on_before_move(&self, _move: ExecutingMove) {}
fn on_before_move(&self, _move: ExecutingMove) -> Result<()> {
Ok(())
}
/// This function allows a script to prevent a move that is targeted at its owner. If set to true
/// the move fails, and fail events get triggered.
fn fail_incoming_move(&self, _move: ExecutingMove, _target: Pokemon, _fail: &mut bool) {}
fn fail_incoming_move(
&self,
_move: ExecutingMove,
_target: Pokemon,
_fail: &mut bool,
) -> Result<()> {
Ok(())
}
/// This function allows a script to make its owner invulnerable to an incoming move.
fn is_invulnerable(&self, _move: ExecutingMove, _target: Pokemon, _invulnerable: &mut bool) {}
fn is_invulnerable(
&self,
_move: ExecutingMove,
_target: Pokemon,
_invulnerable: &mut bool,
) -> Result<()> {
Ok(())
}
/// This function occurs when a move gets missed. This runs on the scripts belonging to the executing
/// move, which include the scripts that are attached to the owner of the script.
fn on_move_miss(&self, _move: ExecutingMove, _target: Pokemon) {}
fn on_move_miss(&self, _move: ExecutingMove, _target: Pokemon) -> Result<()> {
Ok(())
}
/// This function allows the script to change the actual type that is used for the move on a target.
fn change_move_type(
&self,
@@ -77,7 +117,8 @@ pub trait Script {
_target: Pokemon,
_hit: u8,
_move_type: &mut TypeIdentifier,
) {
) -> Result<()> {
Ok(())
}
/// This function allows the script to change how effective a move is on a target.
fn change_effectiveness(
@@ -86,7 +127,8 @@ pub trait Script {
_target: Pokemon,
_hit: u8,
_effectiveness: &mut f32,
) {
) -> Result<()> {
Ok(())
}
/// This function allows a script to block an outgoing move from being critical.
fn block_critical(
@@ -95,7 +137,8 @@ pub trait Script {
_target: Pokemon,
_hit: u8,
_block_critical: &mut bool,
) {
) -> Result<()> {
Ok(())
}
/// This function allows a script to block an incoming move from being critical.
fn block_incoming_critical(
@@ -104,7 +147,8 @@ pub trait Script {
_target: Pokemon,
_hit: u8,
_block_critical: &mut bool,
) {
) -> Result<()> {
Ok(())
}
/// This function allows a script to modify the accuracy of a move used. This value represents
/// the percentage accuracy, so anything above 100% will make it always hit.
@@ -114,7 +158,8 @@ pub trait Script {
_target: Pokemon,
_hit: u8,
_accuracy: &mut u8,
) {
) -> Result<()> {
Ok(())
}
/// This function allows a script to change the critical stage of the move used.
@@ -124,7 +169,8 @@ pub trait Script {
_target: Pokemon,
_hit: u8,
_stage: &mut u8,
) {
) -> Result<()> {
Ok(())
}
/// This function allows a script to change the damage modifier of a critical hit. This will only
/// run when a hit is critical.
@@ -134,7 +180,8 @@ pub trait Script {
_target: Pokemon,
_hit: u8,
_modifier: &mut f32,
) {
) -> Result<()> {
Ok(())
}
/// This function allows a script to change the damage modifier of a Same Type Attack Bonus, which
/// occurs when the user has the move type as one of its own types.
@@ -144,7 +191,8 @@ pub trait Script {
_target: Pokemon,
_hit: u8,
_modifier: &mut f32,
) {
) -> Result<()> {
Ok(())
}
/// This function allows a script to change the effective base power of a move hit.
@@ -154,7 +202,8 @@ pub trait Script {
_target: Pokemon,
_hit: u8,
_base_power: &mut u8,
) {
) -> Result<()> {
Ok(())
}
/// This function allows a script to bypass defensive stat boosts for a move hit.
fn bypass_defensive_stat_boost(
@@ -163,7 +212,8 @@ pub trait Script {
_target: Pokemon,
_hit: u8,
_bypass: &mut bool,
) {
) -> Result<()> {
Ok(())
}
/// This function allows a script to bypass offensive stat boosts for a move hit.
fn bypass_offensive_stat_boost(
@@ -172,7 +222,8 @@ pub trait Script {
_target: Pokemon,
_hit: u8,
_bypass: &mut bool,
) {
) -> Result<()> {
Ok(())
}
/// This function allows a script to change the actual offensive stat values used when calculating damage
fn change_offensive_stat_value(
@@ -181,7 +232,8 @@ pub trait Script {
_target: Pokemon,
_hit: u8,
_amount: &mut u32,
) {
) -> Result<()> {
Ok(())
}
/// This function allows a script to change the actual defensive stat values used when calculating damage.
fn change_defensive_stat_value(
@@ -190,7 +242,8 @@ pub trait Script {
_target: Pokemon,
_hit: u8,
_amount: &mut u32,
) {
) -> Result<()> {
Ok(())
}
/// This function allows a script to change the raw modifier we retrieved from the stats of the
@@ -201,7 +254,8 @@ pub trait Script {
_target: Pokemon,
_hit: u8,
_modifier: &mut f32,
) {
) -> Result<()> {
Ok(())
}
/// This function allows a script to apply a raw multiplier to the damage done by a move.
fn change_damage_modifier(
@@ -210,10 +264,19 @@ pub trait Script {
_target: Pokemon,
_hit: u8,
_modifier: &mut f32,
) {
) -> Result<()> {
Ok(())
}
/// This function allows a script to modify the outgoing damage done by a move.
fn change_damage(&self, _move: ExecutingMove, _target: Pokemon, _hit: u8, _damage: &mut u32) {}
fn change_damage(
&self,
_move: ExecutingMove,
_target: Pokemon,
_hit: u8,
_damage: &mut u32,
) -> Result<()> {
Ok(())
}
/// This function allows a script to modify the incoming damage done by a move.
fn change_incoming_damage(
&self,
@@ -221,13 +284,18 @@ pub trait Script {
_target: Pokemon,
_hit: u8,
_damage: &mut u32,
) {
) -> Result<()> {
Ok(())
}
/// This function triggers when an incoming hit happens. This triggers after the damage is done,
/// but before the secondary effect of the move happens.
fn on_incoming_hit(&self, _move: ExecutingMove, _target: Pokemon, _hit: u8) {}
fn on_incoming_hit(&self, _move: ExecutingMove, _target: Pokemon, _hit: u8) -> Result<()> {
Ok(())
}
/// This function triggers when an opponent on the field faints.
fn on_opponent_faints(&self, _move: ExecutingMove, _target: Pokemon, _hit: u8) {}
fn on_opponent_faints(&self, _move: ExecutingMove, _target: Pokemon, _hit: u8) -> Result<()> {
Ok(())
}
/// This function allows a script attached to a Pokemon or its parents to prevent stat boost
/// changes on that Pokemon.
fn prevent_stat_boost_change(
@@ -237,7 +305,8 @@ pub trait Script {
_amount: i8,
_self_inflicted: bool,
_prevent: &mut bool,
) {
) -> Result<()> {
Ok(())
}
/// This function allows a script attached to a Pokemon or its parents to modify the amount by
/// which the stat boost will change. If the stat boost is done by the user itself, self
@@ -248,7 +317,8 @@ pub trait Script {
_stat: Statistic,
_self_inflicted: bool,
_amount: &mut i8,
) {
) -> Result<()> {
Ok(())
}
/// This function allows a script attached to a Pokemon or its parents to prevent an incoming
/// secondary effect. This means the move will still hit and do damage, but not trigger its
@@ -259,7 +329,8 @@ pub trait Script {
_target: Pokemon,
_hit: u8,
_prevent: &mut bool,
) {
) -> Result<()> {
Ok(())
}
/// This function allows a script attached to a move or its parents to change the chance the
/// secondary effect of a move will trigger. The chance is depicted in percentage here, so
@@ -271,7 +342,8 @@ pub trait Script {
_target: Pokemon,
_hit: u8,
_chance: &mut f32,
) {
) -> Result<()> {
Ok(())
}
/// This function allows a script attached to a Pokemon or its parents to change the chance the
/// secondary effect of an incoming move will trigger. The chance is depicted in percentage here,
@@ -283,30 +355,49 @@ pub trait Script {
_target: Pokemon,
_hit: u8,
_chance: &mut f32,
) {
) -> Result<()> {
Ok(())
}
/// This function triggers when the move uses its secondary effect. Moves should implement their
/// secondary effects here. Status moves should implement their actual functionality in this
/// function as well, as status moves effects are defined as secondary effects for simplicity.
fn on_secondary_effect(&self, _move: ExecutingMove, _target: Pokemon, _hit: u8) {}
fn on_secondary_effect(&self, _move: ExecutingMove, _target: Pokemon, _hit: u8) -> Result<()> {
Ok(())
}
/// This function triggers on a move or its parents when all hits on a target are finished.
fn on_after_hits(&self, _move: ExecutingMove, _target: Pokemon) {}
fn on_after_hits(&self, _move: ExecutingMove, _target: Pokemon) -> Result<()> {
Ok(())
}
/// This function prevents the Pokemon it is attached to from being able to switch out.
fn prevent_self_switch(&self, _choice: TurnChoice, _prevent: &mut bool) {}
fn prevent_self_switch(&self, _choice: TurnChoice, _prevent: &mut bool) -> Result<()> {
Ok(())
}
/// This function allows the prevention of switching for any opponent.
fn prevent_opponent_switch(&self, _choice: TurnChoice, _prevent: &mut bool) {}
fn prevent_opponent_switch(&self, _choice: TurnChoice, _prevent: &mut bool) -> Result<()> {
Ok(())
}
/// This function is called on a move and its parents when the move fails.
fn on_fail(&self, _target: Pokemon) {}
fn on_fail(&self, _target: Pokemon) -> Result<()> {
Ok(())
}
/// This function is called on a script when an opponent fails.
fn on_opponent_fail(&self, _target: Pokemon) {}
fn on_opponent_fail(&self, _target: Pokemon) -> Result<()> {
Ok(())
}
/// This function allows preventing the running away of the Pokemon its attached to
fn prevent_self_run_away(&self, _choice: TurnChoice, _prevent: &mut bool) {}
fn prevent_self_run_away(&self, _choice: TurnChoice, _prevent: &mut bool) -> Result<()> {
Ok(())
}
/// This function prevents a Pokemon on another side than where its attached to from running away.
fn prevent_opponent_run_away(&self, _choice: TurnChoice, _prevent: &mut bool) {}
fn prevent_opponent_run_away(&self, _choice: TurnChoice, _prevent: &mut bool) -> Result<()> {
Ok(())
}
/// This function id triggered on all scripts active in the battle after all choices have finished
/// running. Note that choices are not active anymore here, so their scripts do not call this
/// function.
fn on_end_turn(&self) {}
fn on_end_turn(&self) -> Result<()> {
Ok(())
}
/// This function is triggered on a Pokemon and its parents when the given Pokemon takes damage.
fn on_damage(
&self,
@@ -314,16 +405,23 @@ pub trait Script {
_source: DamageSource,
_old_health: u32,
_new_health: u32,
) {
) -> Result<()> {
Ok(())
}
/// This function is triggered on a Pokemon and its parents when the given Pokemon faints.
fn on_faint(&self, _pokemon: Pokemon, _source: DamageSource) {}
fn on_faint(&self, _pokemon: Pokemon, _source: DamageSource) -> Result<()> {
Ok(())
}
/// This function is triggered on a Pokemon and its parents when the given Pokemon is switched into
/// the battlefield.
fn on_switch_in(&self, _pokemon: Pokemon) {}
fn on_switch_in(&self, _pokemon: Pokemon) -> Result<()> {
Ok(())
}
/// This function is triggered on a Pokemon and its parents when the given Pokemon consumes the
/// held item it had.
fn on_after_held_item_consume(&self, _pokemon: Pokemon, _item: Item) {}
fn on_after_held_item_consume(&self, _pokemon: Pokemon, _item: Item) -> Result<()> {
Ok(())
}
/// This function is triggered on a Pokemon and its parents when the given Pokemon gains experience,
/// and allows for changing this amount of experience.
fn change_experience_gained(
@@ -331,18 +429,35 @@ pub trait Script {
_fainted_mon: Pokemon,
_winning_mon: Pokemon,
_amount: &mut u32,
) {
) -> Result<()> {
Ok(())
}
/// This function is triggered on a Pokemon and its parents when the given Pokemon gains experience,
/// and allows for making the experience be shared across multiple Pokemon.
fn share_experience(&self, _fainted_mon: Pokemon, _winning_mon: Pokemon, _shares: &mut bool) {}
fn share_experience(
&self,
_fainted_mon: Pokemon,
_winning_mon: Pokemon,
_shares: &mut bool,
) -> Result<()> {
Ok(())
}
/// This function is triggered on a battle and its parents when something attempts to change the
/// weather, and allows for blocking the weather change.
fn block_weather(&self, _battle: Battle, _blocked: &mut bool) {}
fn block_weather(&self, _battle: Battle, _blocked: &mut bool) -> Result<()> {
Ok(())
}
/// This function is called when a Pokeball is thrown at a Pokemon, and allows modifying the catch
/// rate of this attempt. Pokeball modifier effects should be implemented here, as well as for
/// example status effects that change capture rates.
fn change_capture_rate_bonus(&self, _target: Pokemon, _pokeball: Item, _modifier: &mut u8) {}
fn change_capture_rate_bonus(
&self,
_target: Pokemon,
_pokeball: Item,
_modifier: &mut u8,
) -> Result<()> {
Ok(())
}
fn as_any(&self) -> &dyn Any;

View File

@@ -0,0 +1,90 @@
use crate::{pkmn_err, PkmnErr, PkmnResult};
use alloc::string::ToString;
use cstr_core::{c_char, CString};
#[repr(C)]
#[repr(packed)]
#[derive(Debug)]
pub struct WasmResult<T>
where
T: Default,
{
err_ptr: u32,
value: T,
}
pub type WasmVoidResult = WasmResult<()>;
impl<T> WasmResult<T>
where
T: Default,
{
pub fn unwrap(self) -> T {
unsafe {
if self.err_ptr == 0 {
self.value
} else {
let ptr = self.err_ptr as *mut c_char;
let s = CString::from_raw(ptr).to_string_lossy().to_string();
panic!("{}", s)
}
}
}
pub fn as_res(self) -> PkmnResult<T> {
PkmnResult::from(self)
}
pub fn ok(value: T) -> Self {
WasmResult { err_ptr: 0, value }
}
pub fn err(err: PkmnErr) -> Self {
let s: CString = err.into();
let ptr = s.into_raw();
WasmResult {
err_ptr: ptr as u32,
value: Default::default(),
}
}
pub fn from_res(res: PkmnResult<T>) -> Self {
WasmResult::from(res)
}
}
impl<T> From<WasmResult<T>> for crate::PkmnResult<T>
where
T: Default,
{
fn from(value: WasmResult<T>) -> Self {
unsafe {
if value.err_ptr == 0 {
Ok(value.value)
} else {
let ptr = value.err_ptr as *mut c_char;
let s = CString::from_raw(ptr).to_string_lossy().to_string();
Err(pkmn_err!(s))
}
}
}
}
impl<T> From<crate::PkmnResult<T>> for WasmResult<T>
where
T: Default,
{
fn from(value: PkmnResult<T>) -> Self {
match value {
Ok(value) => WasmResult { err_ptr: 0, value },
Err(e) => {
let s: CString = e.into();
let ptr = s.into_raw();
WasmResult {
err_ptr: ptr as u32,
value: Default::default(),
}
}
}
}
}

View File

@@ -12,11 +12,13 @@
#![feature(thread_local)]
#![feature(build_hasher_simple_hash_one)]
#![feature(adt_const_params)]
#![feature(try_trait_v2)]
#![cfg_attr(not(feature = "mock_data"), no_std)]
#![allow(incomplete_features)]
// These give false positives too often
#![allow(clippy::borrowed_box)]
#![allow(clippy::needless_lifetimes)]
#![allow(stable_features)]
extern crate alloc;
extern crate core;
@@ -33,25 +35,28 @@ use alloc::boxed::Box;
#[allow(dead_code)]
pub mod app_interface;
pub mod handling;
mod result;
pub mod utils;
pub use result::*;
pub type LoadScriptFnType = Box<dyn Fn(ScriptCategory, &StringKey) -> Option<Box<dyn Script>>>;
#[cfg(not(feature = "mock_data"))]
mod implementation {
use super::LoadScriptFnType;
use crate::app_interface::list::{EffectParameterImmutableList, ImmutableListWasm};
use crate::app_interface::{
BattleImpl, DamageSource, DynamicLibraryImpl, 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::wasm_result::WasmVoidResult;
use crate::handling::{Script, ScriptCapabilities, ScriptCategory};
use alloc::boxed::Box;
use alloc::rc::Rc;
use alloc::vec::Vec;
use core::sync::atomic::{AtomicU32, Ordering};
use cstr_core::{c_char, CString};
use hashbrown::HashMap;
@@ -86,7 +91,7 @@ mod implementation {
static mut SCRIPT_INDEX_COUNTER: AtomicU32 = AtomicU32::new(1);
#[repr(C)]
#[derive(Copy, Clone)]
#[derive(Copy, Clone, Default)]
pub struct ScriptPtr {
index: u32,
}
@@ -183,56 +188,64 @@ mod implementation {
FFIArray::new(c)
}
fn script_stack(script: ScriptPtr) {
script.val().unwrap().stack();
fn script_stack(script: ScriptPtr) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().stack())
}
fn script_on_remove(script: ScriptPtr) {
script.val().unwrap().on_remove();
fn script_on_remove(script: ScriptPtr) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().on_remove())
}
fn script_on_initialize(
script: ScriptPtr,
library: ExternRef<DynamicLibraryImpl>,
parameters: VecExternRef<EffectParameter>,
) {
let parameters = Rc::new(EffectParameterImmutableList::from_ref(parameters));
script.val().unwrap().on_initialize(library.not_null_rc(), Some(parameters));
parameters: u64,
) -> WasmVoidResult {
let parameters : FFIArray<ExternRef<EffectParameter>> = FFIArray::from_u64(parameters);
let parameters = Vec::from_raw_parts(parameters.ptr(), parameters.len(), parameters.len());
let parameters = parameters.into_iter().map(|p| Rc::new(EffectParameter::new(p).unwrap())).collect::<Vec<_>>();
WasmVoidResult::from_res(script.val().unwrap().on_initialize(library.not_null_rc(), Some(parameters)))
}
fn script_on_before_turn(
script: ScriptPtr,
choice: ExternRef<TurnChoice>,
) {
script.val().unwrap().on_before_turn(choice.not_null())
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().on_before_turn(choice.not_null()))
}
fn script_change_speed(
script:ScriptPtr,
choice: ExternRef<TurnChoice>,
speed: *mut u32,
) {
script.val().unwrap().change_speed(choice.not_null(), speed.as_mut().unwrap())
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().change_speed(choice.not_null(), speed.as_mut().unwrap()))
}
fn script_change_priority(
script: ScriptPtr,
choice: ExternRef<TurnChoice>,
priority: *mut i8,
) {
script.val().unwrap().change_priority(choice.not_null(), priority.as_mut().unwrap())
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().change_priority(choice.not_null(), priority.as_mut().unwrap()))
}
fn script_change_move(
script: ScriptPtr,
choice: ExternRef<TurnChoice>,
mv: *mut ExternRef<StringKey>,
) {
) -> WasmVoidResult {
let old = mv.as_ref().unwrap().not_null();
let mut new = old.clone();
script.val().unwrap().change_move(choice.not_null(), &mut new);
if old != new {
*mv = new.ptr();
let res = script.val().unwrap().change_move(choice.not_null(), &mut new);
match res {
Ok(_) => {
if old != new {
*mv = new.ptr();
}
WasmVoidResult::ok(())
}
Err(e) => WasmVoidResult::err(e),
}
}
@@ -240,39 +253,39 @@ mod implementation {
script: ScriptPtr,
choice: ExternRef<TurnChoice>,
out: *mut u8,
) {
script.val().unwrap().change_number_of_hits(choice.not_null(), out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().change_number_of_hits(choice.not_null(), out.as_mut().unwrap()))
}
fn script_prevent_move(
script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>,
out: *mut bool,
) {
script.val().unwrap().prevent_move(mv.not_null_rc(), out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().prevent_move(mv.not_null_rc(), out.as_mut().unwrap()))
}
fn script_fail_move(
script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>,
out: *mut bool,
) {
script.val().unwrap().fail_move(mv.not_null_rc(), out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().fail_move(mv.not_null_rc(), out.as_mut().unwrap()))
}
fn script_stop_before_move(
script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>,
out: *mut bool,
) {
script.val().unwrap().stop_before_move(mv.not_null_rc(), out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().stop_before_move(mv.not_null_rc(), out.as_mut().unwrap()))
}
fn script_on_before_move(
script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>,
) {
script.val().unwrap().on_before_move(mv.not_null_rc());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().on_before_move(mv.not_null_rc()))
}
fn script_fail_incoming_move(
@@ -280,8 +293,8 @@ mod implementation {
mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>,
out: *mut bool,
) {
script.val().unwrap().fail_incoming_move(mv.not_null_rc(), target.not_null_rc(), out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().fail_incoming_move(mv.not_null_rc(), target.not_null_rc(), out.as_mut().unwrap()))
}
fn script_is_invulnerable(
@@ -289,16 +302,16 @@ mod implementation {
mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>,
out: *mut bool,
) {
script.val().unwrap().is_invulnerable(mv.not_null_rc(), target.not_null_rc(), out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().is_invulnerable(mv.not_null_rc(), target.not_null_rc(), out.as_mut().unwrap()))
}
fn script_on_move_miss(
script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>,
) {
script.val().unwrap().on_move_miss(mv.not_null_rc(), target.not_null_rc());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().on_move_miss(mv.not_null_rc(), target.not_null_rc()))
}
fn script_change_move_type(
@@ -307,8 +320,8 @@ mod implementation {
target: ExternRef<PokemonImpl>,
hit: u8,
out: *mut TypeIdentifier,
) {
script.val().unwrap().change_move_type(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().change_move_type(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
}
fn script_change_effectiveness(
@@ -317,8 +330,8 @@ mod implementation {
target: ExternRef<PokemonImpl>,
hit: u8,
out: *mut f32,
) {
script.val().unwrap().change_effectiveness(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().change_effectiveness(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
}
fn script_block_critical(
@@ -327,8 +340,8 @@ mod implementation {
target: ExternRef<PokemonImpl>,
hit: u8,
out: *mut bool,
) {
script.val().unwrap().block_critical(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().block_critical(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
}
fn script_block_incoming_critical(
@@ -337,8 +350,8 @@ mod implementation {
target: ExternRef<PokemonImpl>,
hit: u8,
out: *mut bool,
) {
script.val().unwrap().block_incoming_critical(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().block_incoming_critical(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
}
fn script_change_accuracy(
@@ -347,8 +360,8 @@ mod implementation {
target: ExternRef<PokemonImpl>,
hit: u8,
out: *mut u8,
) {
script.val().unwrap().change_accuracy(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().change_accuracy(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
}
fn script_change_critical_stage(
@@ -357,8 +370,8 @@ mod implementation {
target: ExternRef<PokemonImpl>,
hit: u8,
out: *mut u8,
) {
script.val().unwrap().change_critical_stage(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().change_critical_stage(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
}
fn script_change_critical_modifier(
@@ -367,8 +380,8 @@ mod implementation {
target: ExternRef<PokemonImpl>,
hit: u8,
out: *mut f32,
) {
script.val().unwrap().change_critical_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().change_critical_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
}
fn script_change_stab_modifier(
@@ -377,8 +390,8 @@ mod implementation {
target: ExternRef<PokemonImpl>,
hit: u8,
out: *mut f32,
) {
script.val().unwrap().change_stab_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().change_stab_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
}
fn script_change_base_power(
@@ -387,8 +400,8 @@ mod implementation {
target: ExternRef<PokemonImpl>,
hit: u8,
out: *mut u8,
) {
script.val().unwrap().change_base_power(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(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(
@@ -397,8 +410,8 @@ mod implementation {
target: ExternRef<PokemonImpl>,
hit: u8,
out: *mut bool,
) {
script.val().unwrap().bypass_defensive_stat_boost(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(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(
@@ -407,8 +420,8 @@ mod implementation {
target: ExternRef<PokemonImpl>,
hit: u8,
out: *mut bool,
) {
script.val().unwrap().bypass_offensive_stat_boost(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(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(
@@ -417,8 +430,8 @@ mod implementation {
target: ExternRef<PokemonImpl>,
hit: u8,
out: *mut u32,
) {
script.val().unwrap().change_defensive_stat_value(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(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(
@@ -427,8 +440,8 @@ mod implementation {
target: ExternRef<PokemonImpl>,
hit: u8,
out: *mut u32,
) {
script.val().unwrap().change_offensive_stat_value(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(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(
@@ -437,8 +450,8 @@ mod implementation {
target: ExternRef<PokemonImpl>,
hit: u8,
out: *mut f32,
) {
script.val().unwrap().change_damage_stat_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(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(
@@ -447,8 +460,8 @@ mod implementation {
target: ExternRef<PokemonImpl>,
hit: u8,
out: *mut f32,
) {
script.val().unwrap().change_damage_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().change_damage_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
}
fn script_change_damage(
@@ -457,8 +470,8 @@ mod implementation {
target: ExternRef<PokemonImpl>,
hit: u8,
out: *mut u32,
) {
script.val().unwrap().change_damage(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().change_damage(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
}
fn script_change_incoming_damage(
@@ -467,8 +480,8 @@ mod implementation {
target: ExternRef<PokemonImpl>,
hit: u8,
out: *mut u32,
) {
script.val().unwrap().change_incoming_damage(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().change_incoming_damage(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
}
fn script_on_incoming_hit(
@@ -476,8 +489,8 @@ mod implementation {
mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>,
hit: u8,
) {
script.val().unwrap().on_incoming_hit(mv.not_null_rc(), target.not_null_rc(), hit);
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().on_incoming_hit(mv.not_null_rc(), target.not_null_rc(), hit))
}
fn script_on_opponent_faints(
@@ -485,8 +498,8 @@ mod implementation {
mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>,
hit: u8,
) {
script.val().unwrap().on_opponent_faints(mv.not_null_rc(), target.not_null_rc(), hit);
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().on_opponent_faints(mv.not_null_rc(), target.not_null_rc(), hit))
}
fn script_prevent_stat_boost_change(
@@ -496,8 +509,8 @@ mod implementation {
amount: i8,
self_inflicted: u8,
out: *mut bool,
) {
script.val().unwrap().prevent_stat_boost_change(target.not_null_rc(), stat, amount, self_inflicted == 1, out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(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(
@@ -506,8 +519,8 @@ mod implementation {
target: ExternRef<PokemonImpl>,
hit: u8,
out: *mut bool,
) {
script.val().unwrap().prevent_secondary_effect(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().prevent_secondary_effect(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
}
fn script_change_effect_chance(
@@ -516,8 +529,8 @@ mod implementation {
target: ExternRef<PokemonImpl>,
hit: u8,
out: *mut f32,
) {
script.val().unwrap().change_effect_chance(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(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(
@@ -526,8 +539,8 @@ mod implementation {
target: ExternRef<PokemonImpl>,
hit: u8,
out: *mut f32,
) {
script.val().unwrap().change_incoming_effect_chance(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(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(
@@ -535,68 +548,68 @@ mod implementation {
mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>,
hit: u8,
) {
script.val().unwrap().on_secondary_effect(mv.not_null_rc(), target.not_null_rc(), hit);
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().on_secondary_effect(mv.not_null_rc(), target.not_null_rc(), hit))
}
fn script_on_after_hits(
script: ScriptPtr,
mv: ExternRef<ExecutingMoveImpl>,
target: ExternRef<PokemonImpl>,
) {
script.val().unwrap().on_after_hits(mv.not_null_rc(), target.not_null_rc());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().on_after_hits(mv.not_null_rc(), target.not_null_rc()))
}
fn script_prevent_self_switch(
script: ScriptPtr,
choice: ExternRef<TurnChoice>,
out: *mut bool,
) {
script.val().unwrap().prevent_self_switch(choice.not_null(), out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().prevent_self_switch(choice.not_null(), out.as_mut().unwrap()))
}
fn script_prevent_opponent_switch(
script: ScriptPtr,
choice: ExternRef<TurnChoice>,
out: *mut bool,
) {
script.val().unwrap().prevent_opponent_switch(choice.not_null(), out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().prevent_opponent_switch(choice.not_null(), out.as_mut().unwrap()))
}
fn script_on_fail(
script: ScriptPtr,
pokemon: ExternRef<PokemonImpl>,
) {
script.val().unwrap().on_fail(pokemon.not_null_rc());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().on_fail(pokemon.not_null_rc()))
}
fn script_on_opponent_fail(
script: ScriptPtr,
pokemon: ExternRef<PokemonImpl>,
) {
script.val().unwrap().on_opponent_fail(pokemon.not_null_rc());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().on_opponent_fail(pokemon.not_null_rc()))
}
fn script_prevent_self_run_away(
script: ScriptPtr,
choice: ExternRef<TurnChoice>,
out: *mut bool,
) {
script.val().unwrap().prevent_self_run_away(choice.not_null(), out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().prevent_self_run_away(choice.not_null(), out.as_mut().unwrap()))
}
fn script_prevent_opponent_run_away(
script: ScriptPtr,
choice: ExternRef<TurnChoice>,
out: *mut bool,
) {
script.val().unwrap().prevent_opponent_run_away(choice.not_null(), out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().prevent_opponent_run_away(choice.not_null(), out.as_mut().unwrap()))
}
fn script_on_end_turn(
script: ScriptPtr,
) {
script.val().unwrap().on_end_turn();
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().on_end_turn())
}
fn script_on_damage(
@@ -605,31 +618,31 @@ mod implementation {
source: DamageSource,
old_health: u32,
new_health: u32,
) {
script.val().unwrap().on_damage(pokemon.not_null_rc(), source, old_health, new_health);
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().on_damage(pokemon.not_null_rc(), source, old_health, new_health))
}
fn script_on_faint(
script: ScriptPtr,
pokemon: ExternRef<PokemonImpl>,
source: DamageSource,
) {
script.val().unwrap().on_faint(pokemon.not_null_rc(), source);
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().on_faint(pokemon.not_null_rc(), source))
}
fn script_on_switch_in(
script: ScriptPtr,
pokemon: ExternRef<PokemonImpl>,
) {
script.val().unwrap().on_switch_in(pokemon.not_null_rc());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().on_switch_in(pokemon.not_null_rc()))
}
fn script_on_after_held_item_consume(
script: ScriptPtr,
pokemon: ExternRef<PokemonImpl>,
item: ExternRef<ItemImpl>
) {
script.val().unwrap().on_after_held_item_consume(pokemon.not_null_rc(), item.not_null_rc());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().on_after_held_item_consume(pokemon.not_null_rc(), item.not_null_rc()))
}
fn script_change_experience_gained(
@@ -637,8 +650,12 @@ mod implementation {
fainted_pokemon: ExternRef<PokemonImpl>,
winning_pokemon: ExternRef<PokemonImpl>,
out: *mut u32
) {
script.val().unwrap().change_experience_gained(fainted_pokemon.not_null_rc(), winning_pokemon.not_null_rc(), out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().change_experience_gained(
fainted_pokemon.not_null_rc(),
winning_pokemon.not_null_rc(),
out.as_mut().unwrap()
))
}
fn script_share_experience(
@@ -646,16 +663,20 @@ mod implementation {
fainted_pokemon: ExternRef<PokemonImpl>,
winning_pokemon: ExternRef<PokemonImpl>,
out: *mut bool,
) {
script.val().unwrap().share_experience(fainted_pokemon.not_null_rc(), winning_pokemon.not_null_rc(), out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().share_experience(
fainted_pokemon.not_null_rc(),
winning_pokemon.not_null_rc(),
out.as_mut().unwrap()
))
}
fn script_block_weather(
script: ScriptPtr,
battle: ExternRef<BattleImpl>,
out: *mut bool,
) {
script.val().unwrap().block_weather(battle.not_null_rc(), out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().block_weather(battle.not_null_rc(), out.as_mut().unwrap()))
}
fn script_change_capture_rate_bonus(
@@ -663,8 +684,12 @@ mod implementation {
target: ExternRef<PokemonImpl>,
pokeball: ExternRef<ItemImpl>,
out: *mut u8,
) {
script.val().unwrap().change_capture_rate_bonus(target.not_null_rc(), pokeball.not_null_rc(), out.as_mut().unwrap());
) -> WasmVoidResult {
WasmVoidResult::from_res(script.val().unwrap().change_capture_rate_bonus(
target.not_null_rc(),
pokeball.not_null_rc(),
out.as_mut().unwrap()
))
}
}
}

View File

@@ -0,0 +1,49 @@
use alloc::string::{String, ToString};
use core::fmt;
use core::fmt::{Debug, Display, Formatter};
use cstr_core::CString;
pub type PkmnResult<T> = Result<T, PkmnErr>;
pub struct PkmnErr {
pub file: &'static str,
pub line: u32,
pub message: String,
}
impl PkmnErr {
pub fn new(file: &'static str, line: u32, message: String) -> Self {
Self {
file,
line,
message,
}
}
}
impl Debug for PkmnErr {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "PkmnErr: {}:{}: {}", self.file, self.line, self.message)
}
}
impl Display for PkmnErr {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "PkmnErr: {}:{}: {}", self.file, self.line, self.message)
}
}
impl From<PkmnErr> for CString {
fn from(val: PkmnErr) -> Self {
CString::new(val.to_string()).unwrap()
}
}
#[macro_export]
macro_rules! pkmn_err {
($message: expr) => {
PkmnErr::new(file!(), line!(), $message.to_string())
};
}
pub use pkmn_err;

View File

@@ -1,8 +1,23 @@
use alloc::boxed::Box;
#[macro_export]
#[cfg(feature = "mock_data")]
macro_rules! println {
($($args:tt)*) => {};
}
#[macro_export]
#[cfg(not(feature = "mock_data"))]
macro_rules! println { ($($args:tt)*) => { crate::utils::print_raw(alloc::format!($($args)*).as_bytes()); } }
macro_rules! println { ($($args:tt)*) => { pkmn_lib_interface::utils::print_raw(alloc::format!($($args)*).as_bytes()); } }
#[cfg(not(feature = "mock_data"))]
#[allow(unused_macros)]
macro_rules! println_crate { ($($args:tt)*) => { crate::utils::print_raw(alloc::format!($($args)*).as_bytes()); } }
#[cfg(not(feature = "mock_data"))]
#[allow(unused_macros)]
#[allow(unused_imports)]
pub(crate) use println_crate;
#[macro_export]
#[cfg(not(feature = "mock_data"))]
@@ -18,13 +33,14 @@ macro_rules! dbg {
#[cfg(not(feature = "mock_data"))]
mod implementation {
use alloc::alloc::alloc;
use alloc::string::ToString;
use core::alloc::Layout;
use core::panic::PanicInfo;
use cstr_core::{c_char, CString};
extern "wasm" {
fn _print(s: *const u8);
fn _error(message: *const u8, file: *const u8, line: u32, position: u32);
fn _error(message: *const u8);
}
#[cfg(not(feature = "mock_data"))]
@@ -40,18 +56,11 @@ mod implementation {
#[cfg(not(feature = "mock_data"))]
#[cfg(not(test))]
pub fn begin_panic_handler(panic_info: &PanicInfo<'_>) -> ! {
let msg = CString::new(panic_info.message().unwrap().as_str().unwrap()).unwrap();
let mut line = 0;
let mut position = 0;
let mut file = CString::default();
if let Some(s) = panic_info.location() {
line = s.line();
position = s.column();
file = CString::new(s.file()).unwrap();
}
let payload = panic_info.to_string();
let msg = CString::new(payload.as_bytes()).unwrap();
unsafe {
_error(msg.as_ptr(), file.as_ptr(), line, position);
_error(msg.as_ptr());
}
loop {}
}