From 5e0bd632b997cd80d921f1d26562c666e07d862f Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Thu, 22 Jun 2023 16:40:51 +0200 Subject: [PATCH] Rework in line with PkmnLib for moving towards Result --- Cargo.toml | 3 + gen_7_scripts/src/common_usings.rs | 3 +- gen_7_scripts/src/moves/acrobatics.rs | 22 +- gen_7_scripts/src/moves/acupressure.rs | 26 +- gen_7_scripts/src/moves/after_you.rs | 28 +- gen_7_scripts/src/moves/assist.rs | 98 +-- gen_7_scripts/src/moves/assurance.rs | 30 +- gen_7_scripts/src/moves/attract.rs | 16 +- gen_7_scripts/src/moves/aurora_veil.rs | 41 +- gen_7_scripts/src/moves/automize.rs | 14 +- .../src/moves/change_all_target_stats.rs | 20 +- .../src/moves/change_target_stats.rs | 10 +- gen_7_scripts/src/moves/cure_party_status.rs | 14 +- gen_7_scripts/src/moves/drain.rs | 16 +- gen_7_scripts/src/moves/flinch.rs | 15 +- .../src/moves/heal_each_end_of_turn.rs | 10 +- gen_7_scripts/src/moves/multi_hit_move.rs | 12 +- gen_7_scripts/src/moves/struggle.rs | 27 +- .../src/pokemon/heal_each_end_of_turn.rs | 9 +- gen_7_scripts/src/pokemon/infatuated.rs | 5 +- gen_7_scripts/src/registered_scripts.rs | 8 +- .../src/util_scripts/force_effect_trigger.rs | 3 +- gen_7_scripts/src/utils/copyable_moves.rs | 2 +- pkmn_lib_interface/Cargo.toml | 7 +- .../src/app_interface/dynamic_data/battle.rs | 130 ++-- .../dynamic_data/battle_party.rs | 12 +- .../dynamic_data/battle_random.rs | 30 +- .../app_interface/dynamic_data/battle_side.rs | 96 ++- .../dynamic_data/choice_queue.rs | 11 +- .../dynamic_data/dynamic_library.rs | 10 +- .../dynamic_data/executing_move.rs | 170 ++--- .../dynamic_data/learned_move.rs | 24 +- .../src/app_interface/dynamic_data/party.rs | 33 +- .../src/app_interface/dynamic_data/pokemon.rs | 582 +++++++++++------- .../dynamic_data/statistic_set.rs | 98 +-- .../dynamic_data/turn_choices.rs | 84 ++- .../dynamic_data/with_volatile.rs | 22 +- pkmn_lib_interface/src/app_interface/list.rs | 204 ------ pkmn_lib_interface/src/app_interface/mod.rs | 1 - .../src/app_interface/static_data/ability.rs | 38 +- .../static_data/data_libraries/mod.rs | 51 +- .../data_libraries/type_library.rs | 43 +- .../static_data/effect_parameter.rs | 41 +- .../src/app_interface/static_data/item.rs | 43 +- .../app_interface/static_data/move_data.rs | 60 +- .../src/app_interface/static_data/nature.rs | 18 +- .../src/app_interface/static_data/species.rs | 136 ++-- .../app_interface/static_data/statistics.rs | 23 +- .../src/app_interface/string_key.rs | 51 +- .../src/handling/cached_value.rs | 24 +- pkmn_lib_interface/src/handling/extern_ref.rs | 80 +-- pkmn_lib_interface/src/handling/ffi_array.rs | 18 + pkmn_lib_interface/src/handling/mod.rs | 12 +- pkmn_lib_interface/src/handling/script.rs | 231 +++++-- .../src/handling/wasm_result.rs | 90 +++ pkmn_lib_interface/src/lib.rs | 259 ++++---- pkmn_lib_interface/src/result.rs | 49 ++ pkmn_lib_interface/src/utils.rs | 33 +- 58 files changed, 1901 insertions(+), 1345 deletions(-) delete mode 100755 pkmn_lib_interface/src/app_interface/list.rs create mode 100644 pkmn_lib_interface/src/handling/wasm_result.rs create mode 100644 pkmn_lib_interface/src/result.rs diff --git a/Cargo.toml b/Cargo.toml index 0cec100..32a06df 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,3 +12,6 @@ opt-level = "s" lto = false debug-assertions = true +[profile.release.package."*"] +opt-level = "s" +debug-assertions = false diff --git a/gen_7_scripts/src/common_usings.rs b/gen_7_scripts/src/common_usings.rs index 582619f..bc9f967 100644 --- a/gen_7_scripts/src/common_usings.rs +++ b/gen_7_scripts/src/common_usings.rs @@ -1,12 +1,13 @@ pub use crate::script; pub use alloc::boxed::Box; pub use alloc::rc::Rc; +pub use alloc::vec::Vec; pub use atomic_float::AtomicF32; pub use core::any::Any; pub use core::sync::atomic::{AtomicBool, AtomicI8, AtomicU32, Ordering}; -pub use pkmn_lib_interface::app_interface::list::ImmutableList; pub use pkmn_lib_interface::app_interface::{ get_volatile_as, BattleSide, DamageSource, DynamicLibrary, EffectParameter, ExecutingMove, Gender, MoveCategory, MoveData, Party, Pokemon, Statistic, StringKey, TurnChoice, }; pub use pkmn_lib_interface::handling::{Script, ScriptCapabilities, ScriptOwner}; +pub use pkmn_lib_interface::PkmnResult; diff --git a/gen_7_scripts/src/moves/acrobatics.rs b/gen_7_scripts/src/moves/acrobatics.rs index e3b07c4..b3cb268 100755 --- a/gen_7_scripts/src/moves/acrobatics.rs +++ b/gen_7_scripts/src/moves/acrobatics.rs @@ -1,4 +1,5 @@ use crate::common_usings::*; +use pkmn_lib_interface::PkmnResult; script!(Acrobatics, "acrobatics"); @@ -21,14 +22,15 @@ impl Script for Acrobatics { _target: Pokemon, _hit: u8, base_power: &mut u8, - ) { - if mv.user().held_item().is_none() { + ) -> PkmnResult<()> { + if mv.user().held_item()?.is_none() { if *base_power >= 128_u8 { *base_power = 255 } else { *base_power *= 2; } } + Ok(()) } fn as_any(&self) -> &dyn Any { @@ -47,11 +49,11 @@ mod tests { mv.expect_user().returning(move || { let mut user = MockPokemon::new(); user.expect_held_item().returning(move || { - if has_held_item { + Ok(if has_held_item { Some(Rc::new(MockItem::new())) } else { None - } + }) }); Rc::new(user) }); @@ -64,7 +66,9 @@ mod tests { let script = Acrobatics::new(); let mut base_power = 50u8; - script.change_base_power(mv, Rc::new(MockPokemon::new()), 0, &mut base_power); + script + .change_base_power(mv, Rc::new(MockPokemon::new()), 0, &mut base_power) + .unwrap(); assert_eq!(100, base_power); } @@ -74,7 +78,9 @@ mod tests { let script = Acrobatics::new(); let mut base_power = 200u8; - script.change_base_power(mv, Rc::new(MockPokemon::new()), 0, &mut base_power); + script + .change_base_power(mv, Rc::new(MockPokemon::new()), 0, &mut base_power) + .unwrap(); assert_eq!(255, base_power); } @@ -84,7 +90,9 @@ mod tests { let script = Acrobatics::new(); let mut base_power = 50u8; - script.change_base_power(mv, Rc::new(MockPokemon::new()), 0, &mut base_power); + script + .change_base_power(mv, Rc::new(MockPokemon::new()), 0, &mut base_power) + .unwrap(); assert_eq!(50, base_power); } } diff --git a/gen_7_scripts/src/moves/acupressure.rs b/gen_7_scripts/src/moves/acupressure.rs index 9aeb026..ddf26cc 100755 --- a/gen_7_scripts/src/moves/acupressure.rs +++ b/gen_7_scripts/src/moves/acupressure.rs @@ -1,5 +1,6 @@ use crate::common_usings::*; use core::mem::transmute; +use pkmn_lib_interface::PkmnResult; pub struct Acupressure {} @@ -22,14 +23,15 @@ impl Script for Acupressure { &[ScriptCapabilities::OnSecondaryEffect] } - fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, hit: u8) { + fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, hit: u8) -> PkmnResult<()> { if target.equals(&mv.user()) { - mv.get_hit_data(&target, hit).fail(); - return; + mv.get_hit_data(&target, hit)?.fail()?; + return Ok(()); } let rand_stat: Statistic = - unsafe { transmute(target.battle().unwrap().random().get_between(1, 6) as u8) }; - target.change_stat_boost(rand_stat, 2, false); + unsafe { transmute(target.battle()?.unwrap().random().get_between(1, 6)? as u8) }; + target.change_stat_boost(rand_stat, 2, false)?; + Ok(()) } fn as_any(&self) -> &dyn Any { @@ -56,13 +58,13 @@ mod tests { mv.expect_user().returning_st(move || user.clone()); let mut hit_data = MockHitData::new(); - hit_data.expect_fail().once(); + hit_data.expect_fail().returning(|| Ok(())).once(); let hit_data = Rc::new(hit_data); mv.expect_get_hit_data() - .returning_st(move |_, _| hit_data.clone()); + .returning_st(move |_, _| Ok(hit_data.clone())); let script = Acupressure::new(); - script.on_secondary_effect(Rc::new(mv), u, 0); + script.on_secondary_effect(Rc::new(mv), u, 0).unwrap(); } #[test] @@ -76,11 +78,11 @@ mod tests { random.expect_get_between().returning_st(|low, high| { assert_eq!(1, low); assert_eq!(6, high); - 1 + Ok(1) }); Rc::new(random) }); - Some(Rc::new(battle)) + Ok(Some(Rc::new(battle))) }); user.expect_change_stat_boost() .once() @@ -88,7 +90,7 @@ mod tests { assert_eq!(Statistic::Attack, stat); assert_eq!(2, amount); assert!(!self_inflicted); - true + Ok(true) }); let user = Rc::new(user); @@ -98,6 +100,6 @@ mod tests { mv.expect_user().returning_st(move || user.clone()); let script = Acupressure::new(); - script.on_secondary_effect(Rc::new(mv), u, 0); + script.on_secondary_effect(Rc::new(mv), u, 0).unwrap(); } } diff --git a/gen_7_scripts/src/moves/after_you.rs b/gen_7_scripts/src/moves/after_you.rs index 3655a7d..d8e8281 100755 --- a/gen_7_scripts/src/moves/after_you.rs +++ b/gen_7_scripts/src/moves/after_you.rs @@ -1,4 +1,5 @@ use crate::common_usings::*; +use pkmn_lib_interface::PkmnResult; pub struct AfterYou {} @@ -21,15 +22,16 @@ impl Script for AfterYou { &[ScriptCapabilities::OnSecondaryEffect] } - fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, hit: u8) { + fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, hit: u8) -> PkmnResult<()> { if !target - .battle() + .battle()? .unwrap() .choice_queue() - .move_pokemon_choice_next(&target) + .move_pokemon_choice_next(&target)? { - mv.get_hit_data(&target, hit).fail() + mv.get_hit_data(&target, hit)?.fail()? } + Ok(()) } fn as_any(&self) -> &dyn Any { @@ -53,7 +55,7 @@ mod tests { choice_queue .expect_move_pokemon_choice_next() .once() - .return_const(true); + .returning_st(move |_| Ok(true)); Rc::new(choice_queue) }); @@ -62,11 +64,13 @@ mod tests { target .expect_battle() .once() - .return_once_st(move || Some(battle)); + .return_once_st(move || Ok(Some(battle))); let target = Rc::new(target); let script = AfterYou::new(); - script.on_secondary_effect(Rc::new(MockExecutingMove::new()), target, 0); + script + .on_secondary_effect(Rc::new(MockExecutingMove::new()), target, 0) + .unwrap(); } #[test] @@ -77,7 +81,7 @@ mod tests { choice_queue .expect_move_pokemon_choice_next() .once() - .return_const(false); + .returning_st(move |_| Ok(false)); Rc::new(choice_queue) }); @@ -86,18 +90,18 @@ mod tests { target .expect_battle() .once() - .return_once_st(move || Some(battle)); + .return_once_st(move || Ok(Some(battle))); let target = Rc::new(target); let mut mv = MockExecutingMove::new(); mv.expect_get_hit_data().once().returning_st(move |_, _| { let mut hit = MockHitData::new(); - hit.expect_fail().once(); - Rc::new(hit) + hit.expect_fail().returning(|| Ok(())).once(); + Ok(Rc::new(hit)) }); let mv = Rc::new(mv); let script = AfterYou::new(); - script.on_secondary_effect(mv, target, 0); + script.on_secondary_effect(mv, target, 0).unwrap(); } } diff --git a/gen_7_scripts/src/moves/assist.rs b/gen_7_scripts/src/moves/assist.rs index 8b44385..eae75c3 100755 --- a/gen_7_scripts/src/moves/assist.rs +++ b/gen_7_scripts/src/moves/assist.rs @@ -1,12 +1,13 @@ use crate::common_usings::*; use alloc::vec::Vec; +use pkmn_lib_interface::PkmnResult; script!(Assist, "assist"); impl Assist { /// Gets all the learned moves from the entire party, except the ones from the user, and the ones /// that are not allowed to be copied. - fn get_party_moves(party: &Party, user: &Pokemon) -> Vec { + fn get_party_moves(party: &Party, user: &Pokemon) -> PkmnResult> { let mut possible_moves = Vec::new(); // Iterate over every mon in the party for mon in party.into_iter().flatten() { @@ -16,7 +17,7 @@ impl Assist { } // Iterate over all moves. We make the assumption of 4 moves. for move_index in 0..4 { - let mv = mon.get_learned_move(move_index); + let mv = mon.get_learned_move(move_index)?; if let Some(mv) = mv { // Make sure we can copy the move, otherwise add it as possible move. if crate::utils::copyable_moves::can_copy_move(&mv.move_data()) { @@ -25,7 +26,7 @@ impl Assist { } } } - possible_moves + Ok(possible_moves) } } @@ -42,24 +43,25 @@ impl Script for Assist { &[ScriptCapabilities::ChangeMove] } - fn change_move(&self, choice: TurnChoice, move_name: &mut StringKey) { + fn change_move(&self, choice: TurnChoice, move_name: &mut StringKey) -> PkmnResult<()> { let user = choice.user(); - let battle = user.battle().unwrap(); - let party = battle.find_party_for_pokemon(&user); + let battle = user.battle()?.unwrap(); + let party = battle.find_party_for_pokemon(&user)?; if party.is_none() { - choice.fail(); - return; + choice.fail()?; + return Ok(()); } let party = party.unwrap().party(); - let possible_moves = Self::get_party_moves(&party, &user); + let possible_moves = Self::get_party_moves(&party, &user)?; if possible_moves.is_empty() { - choice.fail(); - return; + choice.fail()?; + return Ok(()); } - let random = battle.random().get_max(possible_moves.len() as i32); + let random = battle.random().get_max(possible_moves.len() as i32)?; *move_name = possible_moves[random as usize].name(); + Ok(()) } fn as_any(&self) -> &dyn Any { @@ -93,9 +95,9 @@ mod tests { .returning_st(move || moves.get(index).unwrap().clone()); Rc::new(move_data) }); - Some(Rc::new(learned_move)) + Ok(Some(Rc::new(learned_move))) } else { - None + Ok(None) } }); mon.expect_equals().return_const(equals_user); @@ -105,16 +107,19 @@ mod tests { #[test] fn get_party_moves_returns_moves_from_party_length_1() { let mut party = MockParty::new(); - party.expect_length().once().return_const(1usize); + party + .expect_length() + .once() + .returning_st(move || Ok(1usize)); party .expect_get_pokemon() .times(1) - .returning_st(move |_| Some(mock_pokemon_with_moves(vec!["tackle".into()], false))); + .returning_st(move |_| Ok(Some(mock_pokemon_with_moves(vec!["tackle".into()], false)))); let party: Party = Rc::new(party); let user: Pokemon = Rc::new(MockPokemon::new()); - let moves = Assist::get_party_moves(&party, &user); + let moves = Assist::get_party_moves(&party, &user).unwrap(); assert_eq!(1, moves.len()); assert_eq!(moves[0].name(), "tackle".into()) } @@ -122,35 +127,38 @@ mod tests { #[test] fn get_party_moves_returns_moves_from_party_length_7() { let mut party = MockParty::new(); - party.expect_length().once().return_const(3usize); + party + .expect_length() + .once() + .returning_st(move || Ok(3usize)); party .expect_get_pokemon() .times(3) .returning_st(move |index| { if index == 0 { - Some(mock_pokemon_with_moves( + Ok(Some(mock_pokemon_with_moves( vec!["move1".into(), "move2".into(), "move3".into()], false, - )) + ))) } else if index == 1 { - Some(mock_pokemon_with_moves( + Ok(Some(mock_pokemon_with_moves( vec!["move1".into(), "move4".into()], false, - )) + ))) } else if index == 2 { - Some(mock_pokemon_with_moves( + Ok(Some(mock_pokemon_with_moves( vec!["move2".into(), "move5".into()], false, - )) + ))) } else { - None + Ok(None) } }); let party: Party = Rc::new(party); let user: Pokemon = Rc::new(MockPokemon::new()); - let moves = Assist::get_party_moves(&party, &user); + let moves = Assist::get_party_moves(&party, &user).unwrap(); assert_eq!(7, moves.len()); assert_eq!(moves[0].name(), "move1".into()); assert_eq!(moves[1].name(), "move2".into()); @@ -164,12 +172,15 @@ mod tests { #[test] fn get_party_moves_ignores_user() { let mut party = MockParty::new(); - party.expect_length().once().return_const(3usize); + party + .expect_length() + .once() + .returning_st(move || Ok(3usize)); party .expect_get_pokemon() .times(3) .returning_st(move |index| { - if index == 0 { + Ok(if index == 0 { Some(mock_pokemon_with_moves( vec!["move1".into(), "move2".into(), "move3".into()], false, @@ -186,13 +197,13 @@ mod tests { )) } else { None - } + }) }); let party: Party = Rc::new(party); let user: Pokemon = Rc::new(MockPokemon::new()); - let moves = Assist::get_party_moves(&party, &user); + let moves = Assist::get_party_moves(&party, &user).unwrap(); assert_eq!(5, moves.len()); assert_eq!(moves[0].name(), "move1".into()); assert_eq!(moves[1].name(), "move2".into()); @@ -204,26 +215,31 @@ mod tests { #[test] fn get_party_moves_ignores_non_copyable_move() { let mut party = MockParty::new(); - party.expect_length().once().return_const(1usize); party - .expect_get_pokemon() - .times(1) - .returning_st(move |_| Some(mock_pokemon_with_moves(vec!["chatter".into()], false))); + .expect_length() + .once() + .returning_st(move || Ok(1usize)); + party.expect_get_pokemon().times(1).returning_st(move |_| { + Ok(Some(mock_pokemon_with_moves(vec!["chatter".into()], false))) + }); let party: Party = Rc::new(party); let user: Pokemon = Rc::new(MockPokemon::new()); - let moves = Assist::get_party_moves(&party, &user); + let moves = Assist::get_party_moves(&party, &user).unwrap(); assert_eq!(0, moves.len()); } #[test] fn if_moves_found_assist_uses_that_move() { let mut party = MockParty::new(); - party.expect_length().once().return_const(1usize); + party + .expect_length() + .once() + .returning_st(move || Ok(1usize)); party .expect_get_pokemon() .times(1) - .returning_st(move |_| Some(mock_pokemon_with_moves(vec!["tackle".into()], false))); + .returning_st(move |_| Ok(Some(mock_pokemon_with_moves(vec!["tackle".into()], false)))); let party: Party = Rc::new(party); @@ -243,16 +259,16 @@ mod tests { let mut p = MockBattleParty::new(); p.expect_party().returning_st(move || party.clone()); - Some(Rc::new(p)) + Ok(Some(Rc::new(p))) }); battle.expect_random().returning_st(|| { let mut random = MockBattleRandom::new(); - random.expect_get_max().return_const(0); + random.expect_get_max().returning_st(move |_| Ok(0)); Rc::new(random) }); - Some(Rc::new(battle)) + Ok(Some(Rc::new(battle))) }); Rc::new(user) @@ -270,7 +286,7 @@ mod tests { let mut move_name: StringKey = "".into(); let script = Assist::new(); - script.change_move(choice_data, &mut move_name); + script.change_move(choice_data, &mut move_name).unwrap(); assert_eq!(move_name, "tackle".into()) } } diff --git a/gen_7_scripts/src/moves/assurance.rs b/gen_7_scripts/src/moves/assurance.rs index d22a6a7..151785d 100755 --- a/gen_7_scripts/src/moves/assurance.rs +++ b/gen_7_scripts/src/moves/assurance.rs @@ -1,4 +1,5 @@ use crate::common_usings::*; +use pkmn_lib_interface::PkmnResult; script!(Assurance, "assurance"); @@ -18,20 +19,22 @@ impl Script for Assurance { ] } - fn on_before_turn(&self, choice: TurnChoice) { + fn on_before_turn(&self, choice: TurnChoice) -> PkmnResult<()> { if let TurnChoice::Move(data) = &choice { let side: BattleSide = choice .user() - .battle() + .battle()? .unwrap() .sides() - .get(data.target_side() as u32) - .unwrap(); + .get(data.target_side() as usize) + .unwrap() + .clone(); side.add_volatile(Box::new(AssuranceData { for_position: data.target_index(), has_hit: AtomicBool::new(false), - })); + }))?; } + Ok(()) } fn change_base_power( @@ -40,15 +43,16 @@ impl Script for Assurance { target: Pokemon, _hit: u8, base_power: &mut u8, - ) { + ) -> PkmnResult<()> { if let Some(s) = get_volatile_as::( - target.battle_side().as_ref(), + target.battle_side()?.as_ref(), AssuranceData::get_const_name(), - ) { + )? { if s.has_hit.load(Ordering::Relaxed) { *base_power *= 2; } } + Ok(()) } fn as_any(&self) -> &dyn Any { @@ -79,9 +83,10 @@ impl Script for AssuranceData { &[ScriptCapabilities::OnEndTurn, ScriptCapabilities::OnDamage] } - fn on_end_turn(&self) { + fn on_end_turn(&self) -> PkmnResult<()> { let side = self.get_owner().unwrap().as_side(); - side.remove_volatile(self); + side.remove_volatile(self)?; + Ok(()) } fn on_damage( @@ -90,10 +95,11 @@ impl Script for AssuranceData { _source: DamageSource, _old_health: u32, _new_health: u32, - ) { - if pokemon.battle_index() == self.for_position { + ) -> PkmnResult<()> { + if pokemon.battle_index()? == self.for_position { self.has_hit.store(true, Ordering::Relaxed); } + Ok(()) } fn as_any(&self) -> &dyn Any { diff --git a/gen_7_scripts/src/moves/attract.rs b/gen_7_scripts/src/moves/attract.rs index cfef919..155c3fa 100644 --- a/gen_7_scripts/src/moves/attract.rs +++ b/gen_7_scripts/src/moves/attract.rs @@ -1,5 +1,6 @@ use crate::common_usings::*; use crate::pokemon::infatuated::Infatuated; +use pkmn_lib_interface::PkmnResult; script!(Attract, "attract"); @@ -16,19 +17,22 @@ impl Script for Attract { &[ScriptCapabilities::OnSecondaryEffect] } - fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, hit: u8) { - let user_gender = mv.user().gender(); - let target_gender = target.gender(); + fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, hit: u8) -> PkmnResult<()> { + let user_gender = mv.user().gender()?; + let target_gender = target.gender()?; // If the move is used on a Pokémon that is the same gender as the user, it will fail if target_gender == user_gender { - return mv.get_hit_data(&target, hit).fail(); + mv.get_hit_data(&target, hit)?.fail()?; + return Ok(()); } // It will also fail if used by or on a gender-unknown Pokémon if user_gender == Gender::Genderless || target_gender == Gender::Genderless { - return mv.get_hit_data(&target, hit).fail(); + mv.get_hit_data(&target, hit)?.fail()?; + return Ok(()); } // If the target is the opposite gender of the Pokémon who launched the move, the target becomes infatuated - target.add_volatile_by_name(Infatuated::get_const_name()); + target.add_volatile_by_name(Infatuated::get_const_name())?; + Ok(()) } fn as_any(&self) -> &dyn Any { diff --git a/gen_7_scripts/src/moves/aurora_veil.rs b/gen_7_scripts/src/moves/aurora_veil.rs index 59de72d..01fea48 100644 --- a/gen_7_scripts/src/moves/aurora_veil.rs +++ b/gen_7_scripts/src/moves/aurora_veil.rs @@ -2,6 +2,7 @@ use crate::common_usings::*; use crate::moves::light_screen::LightScreenEffect; use crate::moves::reflect::ReflectEffect; use crate::weather::hail::Hail; +use pkmn_lib_interface::PkmnResult; script!(AuroraVeil, "aurora_veil"); @@ -18,21 +19,27 @@ impl Script for AuroraVeil { &[ScriptCapabilities::OnSecondaryEffect] } - fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, hit: u8) { - if target.battle().unwrap().has_weather(Hail::get_const_name()) { - return mv.get_hit_data(&target, hit).fail(); + fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, hit: u8) -> PkmnResult<()> { + if target + .battle()? + .unwrap() + .has_weather(Hail::get_const_name())? + { + mv.get_hit_data(&target, hit)?.fail()?; + return Ok(()); } - let binding = target.battle_side(); + let binding = target.battle_side()?; let script = binding - .add_volatile(Box::new(AuroraVeilEffect::new())) + .add_volatile(Box::new(AuroraVeilEffect::new()))? .as_any() .downcast_ref::() .unwrap(); - if mv.user().has_held_item("light_clay") { + if mv.user().has_held_item("light_clay")? { script.turns.store(8, Ordering::SeqCst); } else { script.turns.store(5, Ordering::SeqCst); } + Ok(()) } fn as_any(&self) -> &dyn Any { @@ -66,30 +73,32 @@ impl Script for AuroraVeilEffect { target: Pokemon, hit: u8, damage: &mut u32, - ) { - if mv.get_hit_data(&target, hit).is_critical() { - return; + ) -> PkmnResult<()> { + if mv.get_hit_data(&target, hit)?.is_critical()? { + return Ok(()); } let side = self.get_owner().unwrap().as_side(); - if side.has_volatile(ReflectEffect::get_const_name()) + if side.has_volatile(ReflectEffect::get_const_name())? && mv.use_move().category() == MoveCategory::Physical { - return; + return Ok(()); } - if side.has_volatile(LightScreenEffect::get_const_name()) + if side.has_volatile(LightScreenEffect::get_const_name())? && mv.use_move().category() == MoveCategory::Special { - return; + return Ok(()); } let mut modifier = 2.0; - if target.battle().unwrap().pokemon_per_side() > 1 { + if target.battle()?.unwrap().pokemon_per_side()? > 1 { modifier = 1.5 } *damage = (*damage as f32 / modifier) as u32; + Ok(()) } - fn on_end_turn(&self) { - todo!() + fn on_end_turn(&self) -> PkmnResult<()> { + // TODO + Ok(()) } fn as_any(&self) -> &dyn Any { diff --git a/gen_7_scripts/src/moves/automize.rs b/gen_7_scripts/src/moves/automize.rs index 55d04b8..3db9d45 100644 --- a/gen_7_scripts/src/moves/automize.rs +++ b/gen_7_scripts/src/moves/automize.rs @@ -1,4 +1,5 @@ use crate::common_usings::*; +use pkmn_lib_interface::PkmnResult; script!(Automize, "automize"); @@ -15,18 +16,19 @@ impl Script for Automize { &[ScriptCapabilities::OnSecondaryEffect] } - fn on_secondary_effect(&self, mv: ExecutingMove, _target: Pokemon, _hit: u8) { + fn on_secondary_effect(&self, mv: ExecutingMove, _target: Pokemon, _hit: u8) -> PkmnResult<()> { let user = mv.user(); let stats = user.boosted_stats(); - let original_speed = stats.speed(); - let original_weight = user.weight(); - user.change_stat_boost(Statistic::Speed, 2, true); - if user.boosted_stats().speed() != original_speed { + let original_speed = stats.speed()?; + let original_weight = user.weight()?; + user.change_stat_boost(Statistic::Speed, 2, true)?; + if user.boosted_stats().speed()? != original_speed { user.set_weight(original_weight - 100.0); - if user.weight() != original_weight { + if user.weight()? != original_weight { // TODO: Became nimble dialog. } } + Ok(()) } fn as_any(&self) -> &dyn Any { diff --git a/gen_7_scripts/src/moves/change_all_target_stats.rs b/gen_7_scripts/src/moves/change_all_target_stats.rs index 7e33639..01bb1dd 100644 --- a/gen_7_scripts/src/moves/change_all_target_stats.rs +++ b/gen_7_scripts/src/moves/change_all_target_stats.rs @@ -1,4 +1,6 @@ use crate::common_usings::*; +use alloc::vec::Vec; +use pkmn_lib_interface::PkmnResult; script!( ChangeAllTargetStats, @@ -27,22 +29,24 @@ impl Script for ChangeAllTargetStats { fn on_initialize( &self, _library: DynamicLibrary, - parameters: Option>>, - ) { + parameters: Option>>, + ) -> PkmnResult<()> { self.amount.store( parameters.unwrap().get(0).unwrap().as_int() as i8, Ordering::SeqCst, ); + Ok(()) } - fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, _hit: u8) { + fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, _hit: u8) -> PkmnResult<()> { let user = mv.user(); let amount = self.amount.load(Ordering::SeqCst); - target.change_stat_boost(Statistic::Attack, amount, user.equals(&target)); - target.change_stat_boost(Statistic::Defense, amount, user.equals(&target)); - target.change_stat_boost(Statistic::SpecialAttack, amount, user.equals(&target)); - target.change_stat_boost(Statistic::SpecialDefense, amount, user.equals(&target)); - target.change_stat_boost(Statistic::Speed, amount, user.equals(&target)); + target.change_stat_boost(Statistic::Attack, amount, user.equals(&target))?; + target.change_stat_boost(Statistic::Defense, amount, user.equals(&target))?; + target.change_stat_boost(Statistic::SpecialAttack, amount, user.equals(&target))?; + target.change_stat_boost(Statistic::SpecialDefense, amount, user.equals(&target))?; + target.change_stat_boost(Statistic::Speed, amount, user.equals(&target))?; + Ok(()) } fn as_any(&self) -> &dyn Any { diff --git a/gen_7_scripts/src/moves/change_target_stats.rs b/gen_7_scripts/src/moves/change_target_stats.rs index a7e83c2..9c5a952 100644 --- a/gen_7_scripts/src/moves/change_target_stats.rs +++ b/gen_7_scripts/src/moves/change_target_stats.rs @@ -36,20 +36,22 @@ macro_rules! change_stat_effect { fn on_initialize( &self, _library: DynamicLibrary, - parameters: Option>>, - ) { + parameters: Option>>, + ) -> PkmnResult<()> { self.amount.store( parameters.unwrap().get(0).unwrap().as_int() as i8, Ordering::SeqCst, ); + Ok(()) } - fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, _hit: u8) { + fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, _hit: u8) -> PkmnResult<()> { target.change_stat_boost( Statistic::$stat, self.amount.load(Ordering::SeqCst), mv.user().equals(&target), - ); + )?; + Ok(()) } fn as_any(&self) -> &dyn Any { diff --git a/gen_7_scripts/src/moves/cure_party_status.rs b/gen_7_scripts/src/moves/cure_party_status.rs index b095ffb..0ac6eac 100644 --- a/gen_7_scripts/src/moves/cure_party_status.rs +++ b/gen_7_scripts/src/moves/cure_party_status.rs @@ -15,21 +15,19 @@ impl Script for CurePartyStatus { &[ScriptCapabilities::OnSecondaryEffect] } - fn on_secondary_effect(&self, mv: ExecutingMove, _target: Pokemon, _hit: u8) { + fn on_secondary_effect(&self, mv: ExecutingMove, _target: Pokemon, _hit: u8) -> PkmnResult<()> { let user = mv.user(); user.clear_status(); - let party = user.battle().unwrap().find_party_for_pokemon(&user); + let party = user.battle()?.unwrap().find_party_for_pokemon(&user)?; if let Some(party) = party { let p = party.party(); - for index in 0..p.length() { - let mon = p.get_pokemon(index); - if let Some(mon) = mon { - if !mon.equals(&user) { - mon.clear_status(); - } + for mon in p.as_ref().into_iter().flatten() { + if !mon.equals(&user) { + mon.clear_status(); } } } + Ok(()) } fn as_any(&self) -> &dyn Any { diff --git a/gen_7_scripts/src/moves/drain.rs b/gen_7_scripts/src/moves/drain.rs index ff66e2a..d49268e 100644 --- a/gen_7_scripts/src/moves/drain.rs +++ b/gen_7_scripts/src/moves/drain.rs @@ -23,22 +23,24 @@ impl Script for Drain { fn on_initialize( &self, _library: DynamicLibrary, - parameters: Option>>, - ) { + parameters: Option>>, + ) -> PkmnResult<()> { self.heal_modifier.store( parameters.unwrap().get(0).unwrap().as_float(), Ordering::SeqCst, ); + Ok(()) } - fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, hit: u8) { - let hit_data = mv.get_hit_data(&target, hit); - let damage = hit_data.damage(); + fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, hit: u8) -> PkmnResult<()> { + let hit_data = mv.get_hit_data(&target, hit)?; + let damage = hit_data.damage()?; let mut modifier = self.heal_modifier.load(Ordering::SeqCst); - if mv.user().has_held_item("big_root") { + if mv.user().has_held_item("big_root")? { modifier *= 1.3; } - mv.user().heal((damage as f32 * modifier) as u32, false); + mv.user().heal((damage as f32 * modifier) as u32, false)?; + Ok(()) } fn as_any(&self) -> &dyn Any { diff --git a/gen_7_scripts/src/moves/flinch.rs b/gen_7_scripts/src/moves/flinch.rs index b448153..1506542 100644 --- a/gen_7_scripts/src/moves/flinch.rs +++ b/gen_7_scripts/src/moves/flinch.rs @@ -15,8 +15,14 @@ impl Script for Flinch { &[ScriptCapabilities::OnSecondaryEffect] } - fn on_secondary_effect(&self, _move: ExecutingMove, target: Pokemon, _hit: u8) { - target.add_volatile(Box::new(FlinchEffect::new())); + fn on_secondary_effect( + &self, + _move: ExecutingMove, + target: Pokemon, + _hit: u8, + ) -> PkmnResult<()> { + target.add_volatile(Box::new(FlinchEffect::new()))?; + Ok(()) } fn as_any(&self) -> &dyn Any { @@ -39,9 +45,10 @@ impl Script for FlinchEffect { &[ScriptCapabilities::PreventMove] } - fn prevent_move(&self, mv: ExecutingMove, prevent: &mut bool) { + fn prevent_move(&self, mv: ExecutingMove, prevent: &mut bool) -> PkmnResult<()> { *prevent = true; - mv.user().remove_volatile(self); + mv.user().remove_volatile(self)?; + Ok(()) } fn as_any(&self) -> &dyn Any { diff --git a/gen_7_scripts/src/moves/heal_each_end_of_turn.rs b/gen_7_scripts/src/moves/heal_each_end_of_turn.rs index 1442b71..b01b6c7 100644 --- a/gen_7_scripts/src/moves/heal_each_end_of_turn.rs +++ b/gen_7_scripts/src/moves/heal_each_end_of_turn.rs @@ -28,16 +28,17 @@ impl Script for HealEachEndOfTurn { fn on_initialize( &self, _library: DynamicLibrary, - parameters: Option>>, - ) { + parameters: Option>>, + ) -> PkmnResult<()> { self.heal_percent.store( parameters.unwrap().get(0).unwrap().as_float() / 100.0, Ordering::SeqCst, ); + Ok(()) } - fn on_secondary_effect(&self, _mv: ExecutingMove, target: Pokemon, _hit: u8) { - let script = target.add_volatile_by_name("heal_each_end_of_turn_effect"); + fn on_secondary_effect(&self, _mv: ExecutingMove, target: Pokemon, _hit: u8) -> PkmnResult<()> { + let script = target.add_volatile_by_name("heal_each_end_of_turn_effect")?; let amount = self.heal_percent.load(Ordering::SeqCst); script .as_any() @@ -45,6 +46,7 @@ impl Script for HealEachEndOfTurn { .unwrap() .heal_percent .store(amount, Ordering::SeqCst); + Ok(()) } fn as_any(&self) -> &dyn Any { diff --git a/gen_7_scripts/src/moves/multi_hit_move.rs b/gen_7_scripts/src/moves/multi_hit_move.rs index 178c180..98df254 100755 --- a/gen_7_scripts/src/moves/multi_hit_move.rs +++ b/gen_7_scripts/src/moves/multi_hit_move.rs @@ -21,17 +21,23 @@ impl Script for MultiHitMove { &[ScriptCapabilities::ChangeNumberOfHits] } - 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) -> PkmnResult<()> { // 35% chance that it will hit 2 times, a 35% chance it will hit 3 times, a 15% chance it // will hit 4 times, and a 15% chance it will hit 5 times. - let rand_value = choice.user().battle().unwrap().random().get_between(0, 100); + let rand_value = choice + .user() + .battle()? + .unwrap() + .random() + .get_between(0, 100)?; *number_of_hits = match rand_value { 0..=34 => 2, 35..=69 => 3, 70..=84 => 4, 85..=100 => 5, _ => *number_of_hits, - } + }; + Ok(()) } fn as_any(&self) -> &dyn Any { diff --git a/gen_7_scripts/src/moves/struggle.rs b/gen_7_scripts/src/moves/struggle.rs index 9a93ef8..d1058aa 100644 --- a/gen_7_scripts/src/moves/struggle.rs +++ b/gen_7_scripts/src/moves/struggle.rs @@ -20,12 +20,23 @@ impl Script for Struggle { ] } - fn change_number_of_hits(&self, _choice: TurnChoice, number_of_hits: &mut u8) { - *number_of_hits = 1 + fn change_number_of_hits( + &self, + _choice: TurnChoice, + number_of_hits: &mut u8, + ) -> PkmnResult<()> { + *number_of_hits = 1; + Ok(()) } - fn is_invulnerable(&self, _move: ExecutingMove, _target: Pokemon, invulnerable: &mut bool) { + fn is_invulnerable( + &self, + _move: ExecutingMove, + _target: Pokemon, + invulnerable: &mut bool, + ) -> PkmnResult<()> { *invulnerable = false; + Ok(()) } fn change_effectiveness( @@ -34,16 +45,18 @@ impl Script for Struggle { _target: Pokemon, _hit: u8, effectiveness: &mut f32, - ) { + ) -> PkmnResult<()> { *effectiveness = 1.0; + Ok(()) } - fn on_secondary_effect(&self, mv: ExecutingMove, _target: Pokemon, _hit: u8) { - let mut damage = mv.user().max_health() / 4; + fn on_secondary_effect(&self, mv: ExecutingMove, _target: Pokemon, _hit: u8) -> PkmnResult<()> { + let mut damage = mv.user().max_health()? / 4; if damage == 0 { damage = 1 } - mv.user().damage(damage, DamageSource::Struggle); + mv.user().damage(damage, DamageSource::Struggle)?; + Ok(()) } fn as_any(&self) -> &dyn Any { diff --git a/gen_7_scripts/src/pokemon/heal_each_end_of_turn.rs b/gen_7_scripts/src/pokemon/heal_each_end_of_turn.rs index 7073bac..d724169 100644 --- a/gen_7_scripts/src/pokemon/heal_each_end_of_turn.rs +++ b/gen_7_scripts/src/pokemon/heal_each_end_of_turn.rs @@ -21,15 +21,16 @@ impl Script for HealEachEndOfTurnEffect { &[ScriptCapabilities::OnEndTurn] } - fn on_end_turn(&self) { + fn on_end_turn(&self) -> PkmnResult<()> { if let Some(ScriptOwner::Pokemon(pokemon)) = self.get_owner() { let mut amount = - pokemon.max_health() as f32 * self.heal_percent.load(Ordering::Relaxed); - if pokemon.has_held_item("big_root") { + pokemon.max_health()? as f32 * self.heal_percent.load(Ordering::Relaxed); + if pokemon.has_held_item("big_root")? { amount *= 1.3; } - pokemon.heal(amount as u32, false); + pokemon.heal(amount as u32, false)?; } + Ok(()) } fn as_any(&self) -> &dyn Any { diff --git a/gen_7_scripts/src/pokemon/infatuated.rs b/gen_7_scripts/src/pokemon/infatuated.rs index af321fb..fd30403 100644 --- a/gen_7_scripts/src/pokemon/infatuated.rs +++ b/gen_7_scripts/src/pokemon/infatuated.rs @@ -15,10 +15,11 @@ impl Script for Infatuated { &[ScriptCapabilities::PreventMove] } - fn prevent_move(&self, mv: ExecutingMove, prevent: &mut bool) { - if mv.user().battle().unwrap().random().get_max(2) == 0 { + fn prevent_move(&self, mv: ExecutingMove, prevent: &mut bool) -> PkmnResult<()> { + if mv.user().battle()?.unwrap().random().get_max(2)? == 0 { *prevent = true } + Ok(()) } fn as_any(&self) -> &dyn Any { diff --git a/gen_7_scripts/src/registered_scripts.rs b/gen_7_scripts/src/registered_scripts.rs index f0cc4a3..4f2cbd1 100755 --- a/gen_7_scripts/src/registered_scripts.rs +++ b/gen_7_scripts/src/registered_scripts.rs @@ -4,6 +4,7 @@ use crate::pokemon::*; use alloc::boxed::Box; use pkmn_lib_interface::app_interface::{get_hash, StringKey}; use pkmn_lib_interface::handling::{Script, ScriptCategory}; +use pkmn_lib_interface::println; macro_rules! resolve_match { ( @@ -24,10 +25,11 @@ macro_rules! resolve_match { } pub fn get_script(category: ScriptCategory, name: &StringKey) -> Option> { + println!("Getting script {:?}", name); match category { ScriptCategory::Move => { resolve_match! { - name.hash(), + name.hash().unwrap(), acrobatics::Acrobatics, acupressure::Acupressure, after_you::AfterYou, @@ -54,13 +56,13 @@ pub fn get_script(category: ScriptCategory, name: &StringKey) -> Option {} ScriptCategory::Pokemon => { resolve_match! { - name.hash(), + name.hash().unwrap(), infatuated::Infatuated, pokemon::heal_each_end_of_turn::HealEachEndOfTurnEffect, } } ScriptCategory::Battle => { - resolve_match! {name.hash(), crate::util_scripts::ForceEffectTriggerScript,} + resolve_match! {name.hash().unwrap(), crate::util_scripts::ForceEffectTriggerScript,} } ScriptCategory::Side => {} ScriptCategory::ItemBattleTrigger => {} diff --git a/gen_7_scripts/src/util_scripts/force_effect_trigger.rs b/gen_7_scripts/src/util_scripts/force_effect_trigger.rs index b881cc1..dd87b0f 100755 --- a/gen_7_scripts/src/util_scripts/force_effect_trigger.rs +++ b/gen_7_scripts/src/util_scripts/force_effect_trigger.rs @@ -27,9 +27,10 @@ impl Script for ForceEffectTriggerScript { _target: Pokemon, _hit: u8, chance: &mut f32, - ) { + ) -> PkmnResult<()> { // Set to 50_000% chance. *chance = 50_000.0; + Ok(()) } fn as_any(&self) -> &dyn Any { diff --git a/gen_7_scripts/src/utils/copyable_moves.rs b/gen_7_scripts/src/utils/copyable_moves.rs index a904191..5b77163 100755 --- a/gen_7_scripts/src/utils/copyable_moves.rs +++ b/gen_7_scripts/src/utils/copyable_moves.rs @@ -5,7 +5,7 @@ macro_rules! non_copyable { $mv:ident, $($move_name:literal),+ ) => { - match $mv.name().hash() { + match $mv.name().hash().unwrap() { 0 $( | const { get_hash($move_name) } diff --git a/pkmn_lib_interface/Cargo.toml b/pkmn_lib_interface/Cargo.toml index 4db7cd6..7095c68 100755 --- a/pkmn_lib_interface/Cargo.toml +++ b/pkmn_lib_interface/Cargo.toml @@ -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 } \ No newline at end of file diff --git a/pkmn_lib_interface/src/app_interface/dynamic_data/battle.rs b/pkmn_lib_interface/src/app_interface/dynamic_data/battle.rs index 2e3890d..2350e24 100755 --- a/pkmn_lib_interface/src/app_interface/dynamic_data/battle.rs +++ b/pkmn_lib_interface/src/app_interface/dynamic_data/battle.rs @@ -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; - fn sides(&self) -> ImmutableList; + fn parties(&self) -> Vec; + fn sides(&self) -> Vec; fn random(&self) -> BattleRandom; fn choice_queue(&self) -> ChoiceQueue; - fn get_pokemon(&self, side: u8, index: u8) -> Option; - fn find_party_for_pokemon(&self, pokemon: &Pokemon) -> Option; - fn weather_name(&self) -> Option; - fn has_weather(&self, name: &str) -> bool; - fn can_flee(&self) -> bool; - fn number_of_sides(&self) -> u8; - fn pokemon_per_side(&self) -> u8; - fn has_ended(&self) -> bool; - fn has_ended_conclusively(&self) -> bool; - fn winning_side(&self) -> u8; - fn current_turn(&self) -> u32; + fn get_pokemon(&self, side: u8, index: u8) -> PkmnResult>; + fn find_party_for_pokemon(&self, pokemon: &Pokemon) -> PkmnResult>; + fn weather_name(&self) -> PkmnResult>; + fn has_weather(&self, name: &str) -> PkmnResult; + fn can_flee(&self) -> PkmnResult; + fn number_of_sides(&self) -> PkmnResult; + fn pokemon_per_side(&self) -> PkmnResult; + fn has_ended(&self) -> PkmnResult; + fn has_ended_conclusively(&self) -> PkmnResult; + fn winning_side(&self) -> PkmnResult; + fn current_turn(&self) -> PkmnResult; } pub type Battle = Rc; @@ -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, library: CachedValue, - parties: CachedValue>, - sides: CachedValue>, + parties: CachedValue>, + sides: CachedValue>, random: CachedValue>, choice_queue: CachedValue>, } @@ -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> = + 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::(|r| Rc::new(BattlePartyImpl::new(r))) + .collect::>(); + parties }), sides: cached_value!({ - let reference = battle_get_sides(reference); - Rc::new(BattleSideImmutableList::from_ref(reference)) + let sides: FFIArray> = + 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::(|r| Rc::new(BattleSideImpl::new(r))) + .collect::>(); + 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; - fn sides(&self) -> ImmutableList; + fn parties(&self) -> Vec; + fn sides(&self) -> Vec; fn random(&self) -> BattleRandom; fn choice_queue(&self) -> ChoiceQueue; } - fn get_pokemon(&self, side: u8, index: u8) -> Option { + fn get_pokemon(&self, side: u8, index: u8) -> PkmnResult> { 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 { + fn find_party_for_pokemon(&self, pokemon: &Pokemon) -> PkmnResult> { 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 { - unsafe { battle_get_weather_name(self.inner.reference).get_value() } + fn weather_name(&self) -> PkmnResult> { + 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 { + 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) -> ExternRef; - fn battle_get_parties(r: ExternRef) -> VecExternRef; - fn battle_get_sides(r: ExternRef) -> VecExternRef; - fn battle_get_random(r: ExternRef) -> ExternRef; - fn battle_get_choice_queue(r: ExternRef) -> ExternRef; + fn battle_get_library( + r: ExternRef, + ) -> WasmResult>; + fn battle_get_parties(r: ExternRef) -> WasmResult; + fn battle_get_sides(r: ExternRef) -> WasmResult; + fn battle_get_random(r: ExternRef) -> WasmResult>; + fn battle_get_choice_queue( + r: ExternRef, + ) -> WasmResult>; fn battle_get_pokemon( r: ExternRef, side: u8, index: u8, - ) -> ExternRef; + ) -> WasmResult>; fn battle_find_party_for_pokemon( r: ExternRef, mon: ExternRef, - ) -> ExternRef; + ) -> WasmResult>; - fn battle_get_weather_name(r: ExternRef) -> ExternRef; + fn battle_get_weather_name(r: ExternRef) -> WasmResult>; } } +use crate::PkmnResult; #[cfg(not(feature = "mock_data"))] pub use implementation::*; diff --git a/pkmn_lib_interface/src/app_interface/dynamic_data/battle_party.rs b/pkmn_lib_interface/src/app_interface/dynamic_data/battle_party.rs index 8eb3afc..b274394 100755 --- a/pkmn_lib_interface/src/app_interface/dynamic_data/battle_party.rs +++ b/pkmn_lib_interface/src/app_interface/dynamic_data/battle_party.rs @@ -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) -> ExternRef; + fn battle_party_get_party( + r: ExternRef, + ) -> WasmResult>; } } diff --git a/pkmn_lib_interface/src/app_interface/dynamic_data/battle_random.rs b/pkmn_lib_interface/src/app_interface/dynamic_data/battle_random.rs index 37090c9..9b19ca6 100755 --- a/pkmn_lib_interface/src/app_interface/dynamic_data/battle_random.rs +++ b/pkmn_lib_interface/src/app_interface/dynamic_data/battle_random.rs @@ -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; + fn get_max(&self, max: i32) -> PkmnResult; + fn get_between(&self, min: i32, max: i32) -> PkmnResult; } pub type BattleRandom = Rc; @@ -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 { + 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 { + 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 { + 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) -> i32; - fn battle_random_get_max(r: ExternRef, max: i32) -> i32; - fn battle_random_get_between(r: ExternRef, min: i32, max: i32) -> i32; + fn battle_random_get(r: ExternRef) -> WasmResult; + fn battle_random_get_max(r: ExternRef, max: i32) -> WasmResult; + fn battle_random_get_between( + r: ExternRef, + min: i32, + max: i32, + ) -> WasmResult; } } diff --git a/pkmn_lib_interface/src/app_interface/dynamic_data/battle_side.rs b/pkmn_lib_interface/src/app_interface/dynamic_data/battle_side.rs index 1ef1692..392edb2 100755 --- a/pkmn_lib_interface/src/app_interface/dynamic_data/battle_side.rs +++ b/pkmn_lib_interface/src/app_interface/dynamic_data/battle_side.rs @@ -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; - fn has_fled_battle(&self) -> bool; - fn is_defeated(&self) -> bool; + fn has_fled_battle(&self) -> PkmnResult; + fn is_defeated(&self) -> PkmnResult; } pub type BattleSide = Rc; @@ -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 { 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 { 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 { + fn add_volatile(&self, script: Box) -> 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> { 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) -> u8; - fn battleside_get_pokemon_per_side(r: ExternRef) -> u8; - fn battleside_get_battle(r: ExternRef) -> ExternRef; + fn battleside_get_side_index(r: ExternRef) -> WasmResult; + fn battleside_get_pokemon_per_side(r: ExternRef) -> WasmResult; + fn battleside_get_battle(r: ExternRef) + -> WasmResult>; fn battleside_get_pokemon( r: ExternRef, index: usize, - ) -> ExternRef; + ) -> WasmResult>; fn battleside_add_volatile_by_name( r: ExternRef, name: *const c_char, - ) -> ScriptPtr; - fn battleside_add_volatile(r: ExternRef, script: ScriptPtr) -> ScriptPtr; - fn battleside_has_volatile(r: ExternRef, name: *const c_char) -> bool; - fn battleside_remove_volatile(r: ExternRef, name: *const c_char); - fn battleside_get_volatile(r: ExternRef, name: *const c_char) -> ScriptPtr; + ) -> WasmResult; + fn battleside_add_volatile( + r: ExternRef, + script: ScriptPtr, + ) -> WasmResult; + fn battleside_has_volatile( + r: ExternRef, + name: *const c_char, + ) -> WasmResult; + fn battleside_remove_volatile( + r: ExternRef, + name: *const c_char, + ) -> WasmVoidResult; + fn battleside_get_volatile( + r: ExternRef, + name: *const c_char, + ) -> WasmResult; } } +use crate::PkmnResult; #[cfg(not(feature = "mock_data"))] pub use implementation::*; diff --git a/pkmn_lib_interface/src/app_interface/dynamic_data/choice_queue.rs b/pkmn_lib_interface/src/app_interface/dynamic_data/choice_queue.rs index efecfd5..fb7ab66 100755 --- a/pkmn_lib_interface/src/app_interface/dynamic_data/choice_queue.rs +++ b/pkmn_lib_interface/src/app_interface/dynamic_data/choice_queue.rs @@ -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; } pub type ChoiceQueue = Rc; @@ -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 { 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, pokemon: ExternRef, - ) -> bool; + ) -> WasmResult; } } +use crate::PkmnResult; #[cfg(not(feature = "mock_data"))] pub use implementation::*; diff --git a/pkmn_lib_interface/src/app_interface/dynamic_data/dynamic_library.rs b/pkmn_lib_interface/src/app_interface/dynamic_data/dynamic_library.rs index 0c4e809..c3c7adb 100755 --- a/pkmn_lib_interface/src/app_interface/dynamic_data/dynamic_library.rs +++ b/pkmn_lib_interface/src/app_interface/dynamic_data/dynamic_library.rs @@ -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, - ) -> ExternRef; + ) -> WasmResult>; } } diff --git a/pkmn_lib_interface/src/app_interface/dynamic_data/executing_move.rs b/pkmn_lib_interface/src/app_interface/dynamic_data/executing_move.rs index d7fd8c2..1ab0469 100755 --- a/pkmn_lib_interface/src/app_interface/dynamic_data/executing_move.rs +++ b/pkmn_lib_interface/src/app_interface/dynamic_data/executing_move.rs @@ -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>>; + fn number_of_targets(&self) -> PkmnResult; + fn is_pokemon_target(&self, pokemon: &Pokemon) -> PkmnResult; + fn get_hit_data(&self, pokemon: &Pokemon, hit: u8) -> PkmnResult; } #[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; + fn base_power(&self) -> PkmnResult; + fn effectiveness(&self) -> PkmnResult; + fn damage(&self) -> PkmnResult; + fn move_type(&self) -> PkmnResult; + fn has_failed(&self) -> PkmnResult; + 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; @@ -37,6 +38,7 @@ pub type HitData = Rc; #[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>> { + unsafe { + Ok( + (executing_move_get_script(self.inner.value().reference).as_res()? + as *const Box) + .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 { + 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 { 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 { 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 { + 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 { + 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 { + unsafe { hit_data_get_effectiveness(self.reference).as_res() } } - fn damage(&self) -> u32 { - unsafe { hit_data_get_damage(self.reference) } + fn damage(&self) -> PkmnResult { + 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 { + 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 { + 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) -> usize; - fn executing_move_get_number_of_hits(r: ExternRef) -> u8; - fn executing_move_get_user(r: ExternRef) -> ExternRef; + fn executing_move_get_number_of_targets( + r: ExternRef, + ) -> WasmResult; + fn executing_move_get_number_of_hits(r: ExternRef) -> WasmResult; + fn executing_move_get_user( + r: ExternRef, + ) -> WasmResult>; fn executing_move_get_chosen_move( r: ExternRef, - ) -> ExternRef; - fn executing_move_get_use_move(r: ExternRef) -> ExternRef; + ) -> WasmResult>; + fn executing_move_get_use_move( + r: ExternRef, + ) -> WasmResult>; #[allow(improper_ctypes)] - fn executing_move_get_script(r: ExternRef) -> *const dyn Script; + fn executing_move_get_script(r: ExternRef) -> WasmResult; fn executing_move_is_pokemon_target( r: ExternRef, pokemon: ExternRef, - ) -> bool; + ) -> WasmResult; fn executing_move_get_hit_data( r: ExternRef, target: ExternRef, hit: u8, - ) -> ExternRef; + ) -> WasmResult>; - fn hit_data_is_critical(r: ExternRef) -> bool; - fn hit_data_get_base_power(r: ExternRef) -> u8; - fn hit_data_get_effectiveness(r: ExternRef) -> f32; - fn hit_data_get_damage(r: ExternRef) -> u32; - fn hit_data_get_move_type(r: ExternRef) -> u8; - fn hit_data_has_failed(r: ExternRef) -> bool; + fn hit_data_is_critical(r: ExternRef) -> WasmResult; + fn hit_data_get_base_power(r: ExternRef) -> WasmResult; + fn hit_data_get_effectiveness(r: ExternRef) -> WasmResult; + fn hit_data_get_damage(r: ExternRef) -> WasmResult; + fn hit_data_get_move_type(r: ExternRef) -> WasmResult; + fn hit_data_has_failed(r: ExternRef) -> WasmResult; - fn hit_data_set_critical(r: ExternRef, critical: bool); - fn hit_data_set_base_power(r: ExternRef, power: u8); - fn hit_data_set_effectiveness(r: ExternRef, effectiveness: f32); - fn hit_data_set_damage(r: ExternRef, damage: u32); - fn hit_data_set_move_type(r: ExternRef, move_type: u8); - fn hit_data_fail(r: ExternRef); + fn hit_data_set_critical(r: ExternRef, critical: bool) -> WasmResult<()>; + fn hit_data_set_base_power(r: ExternRef, power: u8) -> WasmResult<()>; + fn hit_data_set_effectiveness( + r: ExternRef, + effectiveness: f32, + ) -> WasmResult<()>; + fn hit_data_set_damage(r: ExternRef, damage: u32) -> WasmResult<()>; + fn hit_data_set_move_type(r: ExternRef, move_type: u8) -> WasmResult<()>; + fn hit_data_fail(r: ExternRef) -> WasmResult<()>; } } diff --git a/pkmn_lib_interface/src/app_interface/dynamic_data/learned_move.rs b/pkmn_lib_interface/src/app_interface/dynamic_data/learned_move.rs index 155cbb6..b21d5c2 100755 --- a/pkmn_lib_interface/src/app_interface/dynamic_data/learned_move.rs +++ b/pkmn_lib_interface/src/app_interface/dynamic_data/learned_move.rs @@ -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) -> ExternRef; - fn learned_move_get_learn_method(r: ExternRef) -> MoveLearnMethod; - fn learned_move_restore_uses(r: ExternRef, uses: u8); - fn learned_move_restore_all_uses(r: ExternRef); + fn learned_move_get_move_data( + r: ExternRef, + ) -> WasmResult>; + fn learned_move_get_learn_method( + r: ExternRef, + ) -> WasmResult; + fn learned_move_restore_uses(r: ExternRef, uses: u8) -> WasmResult<()>; + fn learned_move_restore_all_uses(r: ExternRef) -> WasmResult<()>; } } diff --git a/pkmn_lib_interface/src/app_interface/dynamic_data/party.rs b/pkmn_lib_interface/src/app_interface/dynamic_data/party.rs index 259df19..3bfbcae 100755 --- a/pkmn_lib_interface/src/app_interface/dynamic_data/party.rs +++ b/pkmn_lib_interface/src/app_interface/dynamic_data/party.rs @@ -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; - fn length(&self) -> usize; + fn get_pokemon(&self, index: usize) -> PkmnResult>; + fn length(&self) -> PkmnResult; } pub type Party = Rc; @@ -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 { + fn get_pokemon(&self, index: usize) -> PkmnResult> { 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 { + unsafe { party_get_length(self.reference).as_res() } } } @@ -64,11 +71,15 @@ mod implementation { } extern "wasm" { - fn party_get_pokemon(r: ExternRef, index: usize) -> ExternRef; - fn party_get_length(r: ExternRef) -> usize; + fn party_get_pokemon( + r: ExternRef, + index: usize, + ) -> WasmResult>; + fn party_get_length(r: ExternRef) -> WasmResult; } } use crate::utils::ExternIterator; +use crate::PkmnResult; #[cfg(not(feature = "mock_data"))] pub use implementation::*; diff --git a/pkmn_lib_interface/src/app_interface/dynamic_data/pokemon.rs b/pkmn_lib_interface/src/app_interface/dynamic_data/pokemon.rs index 78ac7fc..06dc2fd 100755 --- a/pkmn_lib_interface/src/app_interface/dynamic_data/pokemon.rs +++ b/pkmn_lib_interface/src/app_interface/dynamic_data/pokemon.rs @@ -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; - fn battle(&self) -> Option; - 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; + fn form(&self) -> PkmnResult
; + fn active_ability(&self) -> PkmnResult; + fn nature(&self) -> PkmnResult; + fn display_species(&self) -> PkmnResult; + fn display_form(&self) -> PkmnResult; + fn held_item(&self) -> PkmnResult>; + fn battle(&self) -> PkmnResult>; + fn level(&self) -> PkmnResult; + fn experience(&self) -> PkmnResult; + fn unique_identifier(&self) -> PkmnResult; + fn gender(&self) -> PkmnResult; + fn coloring(&self) -> PkmnResult; + fn current_health(&self) -> PkmnResult; + fn weight(&self) -> PkmnResult; + fn height(&self) -> PkmnResult; + fn nickname(&self) -> PkmnResult<*const c_char>; + fn real_ability(&self) -> PkmnResult; + fn types_length(&self) -> PkmnResult; + fn battle_side_index(&self) -> PkmnResult; + fn battle_index(&self) -> PkmnResult; + fn is_ability_overriden(&self) -> PkmnResult; + fn allowed_experience_gain(&self) -> PkmnResult; + fn is_usable(&self) -> PkmnResult; fn library(&self) -> DynamicLibrary; fn flat_stats(&self) -> StatisticSet; @@ -45,25 +46,30 @@ pub trait PokemonTrait: WithVolatile { fn boosted_stats(&self) -> StatisticSet; fn individual_values(&self) -> ClampedStatisticSet; fn effort_values(&self) -> ClampedStatisticSet; - fn has_held_item(&self, name: &str) -> bool; - fn set_held_item(&self, item: &Item) -> Option; - fn remove_held_item(&self) -> Option; - 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; - fn change_stat_boost(&self, stat: Statistic, diff_amount: i8, self_inflicted: bool) -> bool; - fn ability_script(&self) -> Option<&Box>; + fn has_held_item(&self, name: &str) -> PkmnResult; + fn set_held_item(&self, item: &Item) -> PkmnResult>; + fn remove_held_item(&self) -> PkmnResult>; + fn consume_held_item(&self) -> PkmnResult; + fn max_health(&self) -> PkmnResult; + fn get_type(&self, index: usize) -> PkmnResult; + fn has_type(&self, type_identifier: TypeIdentifier) -> PkmnResult; + fn has_type_by_name(&self, type_name: &str) -> PkmnResult; + fn get_learned_move(&self, index: usize) -> PkmnResult>; + fn change_stat_boost( + &self, + stat: Statistic, + diff_amount: i8, + self_inflicted: bool, + ) -> PkmnResult; + fn ability_script(&self) -> PkmnResult>>; 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; + fn damage(&self, damage: u32, source: DamageSource) -> PkmnResult<()>; + fn heal(&self, amount: u32, allow_revive: bool) -> PkmnResult; fn set_weight(&self, weight: f32); fn clear_status(&self); - fn battle_side(&self) -> BattleSide; + fn battle_side(&self) -> PkmnResult; 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; } - 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 { + Ok(unsafe { + Rc::new( + pokemon_get_species(self.inner.reference) + .as_res()? + .get_value() + .unwrap(), + ) + }) + } + fn form(&self) -> PkmnResult { + Ok(unsafe { + Rc::new( + pokemon_get_form(self.inner.reference) + .as_res()? + .get_value() + .unwrap(), + ) + }) + } + fn active_ability(&self) -> PkmnResult { + Ok(unsafe { let implementation = pokemon_get_active_ability(self.reference()) + .as_res()? .get_value() .unwrap(); Rc::new(implementation) - } + }) } - fn held_item(&self) -> Option { - 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 { + Ok(unsafe { + Rc::new( + pokemon_get_nature(self.inner.reference) + .as_res()? + .get_value() + .unwrap(), + ) + }) } - fn battle(&self) -> Option { - 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 { + 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 { + Ok(unsafe { + Rc::new( + pokemon_get_display_form(self.inner.reference) + .as_res()? + .get_value() + .unwrap(), + ) + }) } - fn set_held_item(&self, item: &Item) -> Option { - unsafe { - let i = pokemon_set_held_item(self.inner.reference, item.reference().into()) + fn held_item(&self) -> PkmnResult> { + 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 { - 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> { + 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 { + 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> { + 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> { + 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 { + unsafe { pokemon_consume_held_item(self.inner.reference).as_res() } + } + fn max_health(&self) -> PkmnResult { 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 { + 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 { + 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 { 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 { + fn get_learned_move(&self, index: usize) -> PkmnResult> { 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 { unsafe { pokemon_change_stat_boost(self.inner.reference, stat, diff_amount, self_inflicted) + .as_res() } } - fn ability_script(&self) -> Option<&Box> { - unsafe { pokemon_get_ability_script(self.inner.reference).as_ref() } + fn ability_script(&self) -> PkmnResult>> { + unsafe { + Ok((pokemon_get_ability_script(self.inner.reference).as_res()? + as *const Box) + .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::(); pokemon_change_form(self.inner.reference, form_impl.reference()); } } - fn is_fainted(&self) -> bool { - self.current_health() == 0 + + fn is_fainted(&self) -> PkmnResult { + 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 { + 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 { + 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 { + 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 { 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 { + fn add_volatile(&self, script: Box) -> 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> { 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; - pub fn display_form(&self) -> Option; pub fn held_item(&self) -> Option; pub fn battle(&self) -> Option; } @@ -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) -> ExternRef; - fn pokemon_get_flat_stats(r: ExternRef) -> ExternRef>; - fn pokemon_get_stat_boosts(r: ExternRef) - -> ExternRef>; - fn pokemon_get_boosted_stats(r: ExternRef) - -> ExternRef>; + fn pokemon_get_nickname(r: ExternRef) -> WasmResult; + fn pokemon_get_library( + r: ExternRef, + ) -> WasmResult>; + fn pokemon_get_flat_stats( + r: ExternRef, + ) -> WasmResult>>; + fn pokemon_get_stat_boosts( + r: ExternRef, + ) -> WasmResult>>; + fn pokemon_get_boosted_stats( + r: ExternRef, + ) -> WasmResult>>; fn pokemon_get_individual_values( r: ExternRef, - ) -> ExternRef>; + ) -> WasmResult>>; fn pokemon_get_effort_values( r: ExternRef, - ) -> ExternRef>; - fn pokemon_has_held_item(r: ExternRef, name: *const c_char) -> bool; + ) -> WasmResult>>; + fn pokemon_has_held_item( + r: ExternRef, + name: *const c_char, + ) -> WasmResult; fn pokemon_set_held_item( r: ExternRef, item: ExternRef, - ) -> ExternRef; - fn pokemon_remove_held_item(r: ExternRef) -> ExternRef; - fn pokemon_consume_held_item(r: ExternRef) -> bool; - fn pokemon_get_type(r: ExternRef, index: usize) -> u8; - fn pokemon_has_type(r: ExternRef, identifier: u8) -> bool; + ) -> WasmResult>; + fn pokemon_remove_held_item(r: ExternRef) -> WasmResult>; + fn pokemon_consume_held_item(r: ExternRef) -> WasmResult; + fn pokemon_get_type(r: ExternRef, index: usize) -> WasmResult; + fn pokemon_has_type(r: ExternRef, identifier: u8) -> WasmResult; fn pokemon_get_learned_move( r: ExternRef, index: usize, - ) -> ExternRef; + ) -> WasmResult>; fn pokemon_change_stat_boost( r: ExternRef, tat: Statistic, diff_amount: i8, self_inflicted: bool, - ) -> bool; + ) -> WasmResult; #[allow(improper_ctypes)] - fn pokemon_get_ability_script(r: ExternRef) -> *const Box; + fn pokemon_get_ability_script(r: ExternRef) -> WasmResult; fn pokemon_change_species( r: ExternRef, species: ExternRef, form: ExternRef, - ); - fn pokemon_change_form(r: ExternRef, form: ExternRef); - fn pokemon_damage(r: ExternRef, damage: u32, source: DamageSource); - fn pokemon_heal(r: ExternRef, amount: u32, allow_revive: bool) -> bool; - fn pokemon_set_weight(r: ExternRef, weight: f32); - fn pokemon_clear_status(r: ExternRef); + ) -> WasmResult<()>; + fn pokemon_change_form( + r: ExternRef, + form: ExternRef, + ) -> WasmResult<()>; + fn pokemon_damage( + r: ExternRef, + damage: u32, + source: DamageSource, + ) -> WasmResult<()>; + fn pokemon_heal( + r: ExternRef, + amount: u32, + allow_revive: bool, + ) -> WasmResult; + fn pokemon_set_weight(r: ExternRef, weight: f32) -> WasmResult<()>; + fn pokemon_clear_status(r: ExternRef) -> WasmResult<()>; fn pokemon_add_volatile_by_name( r: ExternRef, name: *const c_char, - ) -> ScriptPtr; - fn pokemon_add_volatile(r: ExternRef, script: ScriptPtr) -> ScriptPtr; - fn pokemon_has_volatile(r: ExternRef, name: *const c_char) -> bool; - fn pokemon_remove_volatile(r: ExternRef, name: *const c_char); - fn pokemon_get_volatile(r: ExternRef, name: *const c_char) -> ScriptPtr; + ) -> WasmResult; + fn pokemon_add_volatile( + r: ExternRef, + script: ScriptPtr, + ) -> WasmResult; + fn pokemon_has_volatile(r: ExternRef, name: *const c_char) + -> WasmResult; + fn pokemon_remove_volatile( + r: ExternRef, + name: *const c_char, + ) -> WasmResult<()>; + fn pokemon_get_volatile( + r: ExternRef, + name: *const c_char, + ) -> WasmResult; } } @@ -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; - fn battle(&self) -> Option; - 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; + fn form(&self) -> PkmnResult; + fn active_ability(&self) -> PkmnResult; + fn nature(&self) -> PkmnResult; + fn display_species(&self) -> PkmnResult; + fn display_form(&self) -> PkmnResult; + fn held_item(&self) -> PkmnResult>; + fn battle(&self) -> PkmnResult>; + fn level(&self) -> PkmnResult; + fn experience(&self) -> PkmnResult; + fn unique_identifier(&self) -> PkmnResult; + fn gender(&self) -> PkmnResult; + fn coloring(&self) -> PkmnResult; + fn current_health(&self) -> PkmnResult; + fn weight(&self) -> PkmnResult; + fn height(&self) -> PkmnResult; + fn nickname(&self) -> PkmnResult<*const c_char>; + fn real_ability(&self) -> PkmnResult; + fn types_length(&self) -> PkmnResult; + fn battle_side_index(&self) -> PkmnResult; + fn battle_index(&self) -> PkmnResult; + fn is_ability_overriden(&self) -> PkmnResult; + fn allowed_experience_gain(&self) -> PkmnResult; + fn is_usable(&self) -> PkmnResult; fn library(&self) -> DynamicLibrary; fn flat_stats(&self) -> StatisticSet; @@ -568,44 +674,44 @@ mockall::mock!( fn boosted_stats(&self) -> StatisticSet; fn individual_values(&self) -> ClampedStatisticSet; fn effort_values(&self) -> ClampedStatisticSet; - fn has_held_item(&self, name: &str) -> bool; - fn set_held_item(&self, item: &Item) -> Option; - fn remove_held_item(&self) -> Option; - 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; - fn change_stat_boost(&self, stat: Statistic, diff_amount: i8, self_inflicted: bool) -> bool; - fn ability_script<'a>(&'a self) -> Option<&'a Box>; + fn has_held_item(&self, name: &str) -> PkmnResult; + fn set_held_item(&self, item: &Item) -> PkmnResult>; + fn remove_held_item(&self) -> PkmnResult>; + fn consume_held_item(&self) -> PkmnResult; + fn max_health(&self) -> PkmnResult; + fn get_type(&self, index: usize) -> PkmnResult; + fn has_type(&self, type_identifier: TypeIdentifier) -> PkmnResult; + fn has_type_by_name(&self, type_name: &str) -> PkmnResult; + fn get_learned_move(&self, index: usize) -> PkmnResult>; + fn change_stat_boost(&self, stat: Statistic, diff_amount: i8, self_inflicted: bool) -> PkmnResult; + fn ability_script<'a>(&'a self) -> PkmnResult>>; 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; + fn damage(&self, damage: u32, source: DamageSource) -> PkmnResult<()>; + fn heal(&self, amount: u32, allow_revive: bool) -> PkmnResult; fn set_weight(&self, weight: f32); fn clear_status(&self); - fn battle_side(&self) -> BattleSide; + fn battle_side(&self) -> PkmnResult; 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 { unimplemented!() } - fn add_volatile(&self, _script: Box) -> &dyn Script { + fn add_volatile(&self, _script: Box) -> 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> { unimplemented!() } } diff --git a/pkmn_lib_interface/src/app_interface/dynamic_data/statistic_set.rs b/pkmn_lib_interface/src/app_interface/dynamic_data/statistic_set.rs index c03d181..7e183e5 100755 --- a/pkmn_lib_interface/src/app_interface/dynamic_data/statistic_set.rs +++ b/pkmn_lib_interface/src/app_interface/dynamic_data/statistic_set.rs @@ -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 >::Error: Debug, >::Error: Debug, { - fn hp(&self) -> T { + fn hp(&self) -> PkmnResult { self.get_stat(Statistic::Attack) } - fn attack(&self) -> T { + fn attack(&self) -> PkmnResult { self.get_stat(Statistic::Attack) } - fn defense(&self) -> T { + fn defense(&self) -> PkmnResult { self.get_stat(Statistic::Defense) } - fn special_attack(&self) -> T { + fn special_attack(&self) -> PkmnResult { self.get_stat(Statistic::SpecialAttack) } - fn special_defense(&self) -> T { + fn special_defense(&self) -> PkmnResult { self.get_stat(Statistic::SpecialDefense) } - fn speed(&self) -> T { + fn speed(&self) -> PkmnResult { 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; + 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 = Rc>; @@ -74,24 +76,29 @@ where >::Error: Debug, >::Error: Debug, { - fn get_stat(&self, stat: Statistic) -> T { + fn get_stat(&self, stat: Statistic) -> PkmnResult { 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 { self.get_stat(Statistic::HP) } #[cfg(not(feature = "mock_data"))] - pub fn attack(&self) -> T { + pub fn attack(&self) -> PkmnResult { self.get_stat(Statistic::Attack) } #[cfg(not(feature = "mock_data"))] - pub fn defense(&self) -> T { + pub fn defense(&self) -> PkmnResult { self.get_stat(Statistic::Defense) } #[cfg(not(feature = "mock_data"))] - pub fn special_attack(&self) -> T { + pub fn special_attack(&self) -> PkmnResult { self.get_stat(Statistic::SpecialAttack) } #[cfg(not(feature = "mock_data"))] - pub fn special_defense(&self) -> T { + pub fn special_defense(&self) -> PkmnResult { self.get_stat(Statistic::SpecialDefense) } #[cfg(not(feature = "mock_data"))] - pub fn speed(&self) -> T { + pub fn speed(&self) -> PkmnResult { 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 { 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 { 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 { 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>, stat: Statistic) -> i64; - fn statistic_set_set(r: ExternRef>, stat: Statistic, value: i64); + fn statistic_set_get(r: ExternRef>, stat: Statistic) -> WasmResult; + fn statistic_set_set( + r: ExternRef>, + stat: Statistic, + value: i64, + ) -> WasmResult<()>; fn statistic_set_increase_stat( r: ExternRef>, stat: Statistic, value: i64, - ); + ) -> WasmResult<()>; fn statistic_set_decrease_stat( r: ExternRef>, stat: Statistic, value: i64, - ); + ) -> WasmResult<()>; - fn clamped_statistic_set_get(r: ExternRef>, stat: Statistic) -> i64; + fn clamped_statistic_set_get( + r: ExternRef>, + stat: Statistic, + ) -> WasmResult; fn clamped_statistic_set_set( r: ExternRef>, stat: Statistic, value: i64, - ); + ) -> WasmResult<()>; fn clamped_statistic_set_increase_stat( r: ExternRef>, stat: Statistic, value: i64, - ) -> bool; + ) -> WasmResult; fn clamped_statistic_set_decrease_stat( r: ExternRef>, stat: Statistic, value: i64, - ) -> bool; + ) -> WasmResult; } diff --git a/pkmn_lib_interface/src/app_interface/dynamic_data/turn_choices.rs b/pkmn_lib_interface/src/app_interface/dynamic_data/turn_choices.rs index a3df874..f4ef155 100755 --- a/pkmn_lib_interface/src/app_interface/dynamic_data/turn_choices.rs +++ b/pkmn_lib_interface/src/app_interface/dynamic_data/turn_choices.rs @@ -25,13 +25,13 @@ impl TurnChoice { pub fn user(&self) -> Pokemon { self.base().user() } - pub fn speed(&self) -> u32 { + pub fn speed(&self) -> PkmnResult { self.base().speed() } - pub fn has_failed(&self) -> bool { + pub fn has_failed(&self) -> PkmnResult { 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; + fn has_failed(&self) -> PkmnResult; + fn fail(&self) -> PkmnResult<()>; } pub type BaseTurnChoiceData = Rc; @@ -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>; + fn priority(&self) -> PkmnResult; + fn move_script<'a>(&self) -> PkmnResult>>; } #[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, @@ -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 { + 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 { + 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 { + unsafe { turn_choice_move_priority(self.base().reference().into()).as_res() } } - fn move_script<'a>(&self) -> Option<&'a Box> { - unsafe { turn_choice_move_script(self.base().reference().into()).as_ref() } + fn move_script<'a>(&self) -> PkmnResult>> { + unsafe { + Ok( + (turn_choice_move_script(self.base().reference().into()).as_res()? + as *const Box) + .as_ref(), + ) + } } } #[cfg(not(feature = "mock_data"))] impl ExternalReferenceType for TurnChoice { fn from_extern_value(reference: ExternRef) -> 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) -> u8; - fn turn_choice_get_user(r: ExternRef) -> ExternRef; - fn turn_choice_get_speed(r: ExternRef) -> u32; - fn turn_choice_has_failed(r: ExternRef) -> bool; - fn turn_choice_fail(r: ExternRef); + fn turn_choice_get_kind(r: ExternRef) -> WasmResult; + fn turn_choice_get_user(r: ExternRef) -> WasmResult>; + fn turn_choice_get_speed(r: ExternRef) -> WasmResult; + fn turn_choice_has_failed(r: ExternRef) -> WasmResult; + fn turn_choice_fail(r: ExternRef) -> WasmResult<()>; fn turn_choice_move_used_move( r: ExternRef, - ) -> ExternRef; - fn turn_choice_move_target_side(r: ExternRef) -> u8; - fn turn_choice_move_target_index(r: ExternRef) -> u8; - fn turn_choice_move_priority(r: ExternRef) -> i8; + ) -> WasmResult>; + fn turn_choice_move_target_side(r: ExternRef) -> WasmResult; + fn turn_choice_move_target_index(r: ExternRef) -> WasmResult; + fn turn_choice_move_priority(r: ExternRef) -> WasmResult; #[allow(improper_ctypes)] - fn turn_choice_move_script(r: ExternRef) -> *const Box; + fn turn_choice_move_script(r: ExternRef) -> WasmResult; } } +use crate::PkmnResult; #[cfg(not(feature = "mock_data"))] pub use implementation::*; diff --git a/pkmn_lib_interface/src/app_interface/dynamic_data/with_volatile.rs b/pkmn_lib_interface/src/app_interface/dynamic_data/with_volatile.rs index 30744e4..71413fd 100644 --- a/pkmn_lib_interface/src/app_interface/dynamic_data/with_volatile.rs +++ b/pkmn_lib_interface/src/app_interface/dynamic_data/with_volatile.rs @@ -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; - 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; + fn add_volatile(&self, script: Box) -> 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>; } -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> 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::().unwrap()) + Ok(Some(s.as_any().downcast_ref::().unwrap())) } else { - None + Ok(None) } } diff --git a/pkmn_lib_interface/src/app_interface/list.rs b/pkmn_lib_interface/src/app_interface/list.rs deleted file mode 100755 index d91a5df..0000000 --- a/pkmn_lib_interface/src/app_interface/list.rs +++ /dev/null @@ -1,204 +0,0 @@ -use alloc::rc::Rc; - -pub trait ImmutableListTrait { - fn get(&self, index: u32) -> Option; -} - -pub type ImmutableList = Rc>; - -#[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 { - extern_ref: VecExternRef, - resource_type: PhantomData, - values: spin::RwLock>>>>, - } - - pub(crate) trait ImmutableListWasm { - fn initialize(inner: *const ImmutableListInner) -> Self - where - Self: Sized; - - fn new(extern_ref: VecExternRef) -> 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) -> 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; - 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 { - unsafe { self.get_inner_ptr().as_ref().unwrap() } - } - fn get_inner_ptr(&self) -> *const ImmutableListInner; - - fn get_cached(&self, index: u32) -> Option> { - 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> { - 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, - } - - impl ImmutableListWasm for EffectParameterImmutableList { - fn initialize(inner: *const ImmutableListInner) -> Self - where - Self: Sized, - { - Self { inner } - } - - fn get_inner_ptr(&self) -> *const ImmutableListInner { - self.inner - } - } - - impl ImmutableListTrait> for EffectParameterImmutableList { - fn get(&self, index: u32) -> Option> { - let v = self.get_value(index); - if let Some(v) = v { - Some(v) - } else { - None - } - } - } - - #[derive(Clone)] - pub struct StringKeyImmutableList { - inner: *const ImmutableListInner, - } - - impl ImmutableListWasm for StringKeyImmutableList { - fn initialize(inner: *const ImmutableListInner) -> Self - where - Self: Sized, - { - Self { inner } - } - - fn get_inner_ptr(&self) -> *const ImmutableListInner { - self.inner - } - } - - impl ImmutableListTrait> for StringKeyImmutableList { - fn get(&self, index: u32) -> Option> { - let v = self.get_value(index); - if let Some(v) = v { - Some(v) - } else { - None - } - } - } - - static mut CACHE: Option> = None; -} - -#[cfg(not(feature = "mock_data"))] -pub use implementation::*; diff --git a/pkmn_lib_interface/src/app_interface/mod.rs b/pkmn_lib_interface/src/app_interface/mod.rs index 71c48d7..caf1063 100755 --- a/pkmn_lib_interface/src/app_interface/mod.rs +++ b/pkmn_lib_interface/src/app_interface/mod.rs @@ -1,5 +1,4 @@ pub mod dynamic_data; -pub mod list; pub mod static_data; pub mod string_key; diff --git a/pkmn_lib_interface/src/app_interface/static_data/ability.rs b/pkmn_lib_interface/src/app_interface/static_data/ability.rs index e0871c8..b9f8970 100755 --- a/pkmn_lib_interface/src/app_interface/static_data/ability.rs +++ b/pkmn_lib_interface/src/app_interface/static_data/ability.rs @@ -9,7 +9,7 @@ pub trait AbilityTrait { pub type Ability = Rc; -#[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, name: CachedValue, effect: CachedValue, - parameters: CachedValue>>, + parameters: CachedValue>>, } #[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> = + 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::>(); + pars }), }), }) @@ -77,9 +85,9 @@ mod implementation { #[cfg(not(feature = "mock_data"))] extern "wasm" { - fn ability_get_name(r: ExternRef) -> ExternRef; - fn ability_get_effect(r: ExternRef) -> ExternRef; - fn ability_get_parameters(r: ExternRef) -> VecExternRef; + fn ability_get_name(r: ExternRef) -> WasmResult>; + fn ability_get_effect(r: ExternRef) -> WasmResult>; + fn ability_get_parameters(r: ExternRef) -> WasmResult; } } diff --git a/pkmn_lib_interface/src/app_interface/static_data/data_libraries/mod.rs b/pkmn_lib_interface/src/app_interface/static_data/data_libraries/mod.rs index a7d2d93..2413388 100755 --- a/pkmn_lib_interface/src/app_interface/static_data/data_libraries/mod.rs +++ b/pkmn_lib_interface/src/app_interface/static_data/data_libraries/mod.rs @@ -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) -> 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, - ) -> ExternRef; + ) -> WasmResult>; fn static_data_get_item_library( ptr: ExternRef, - ) -> ExternRef; + ) -> WasmResult>; fn static_data_get_species_library( ptr: ExternRef, - ) -> ExternRef; + ) -> WasmResult>; fn static_data_get_type_library( ptr: ExternRef, - ) -> ExternRef; + ) -> WasmResult>; fn static_data_get_library_settings( ptr: ExternRef, - ) -> ExternRef; + ) -> WasmResult>; - fn library_settings_get_maximum_level(ptr: ExternRef) -> LevelInt; + fn library_settings_get_maximum_level( + ptr: ExternRef, + ) -> WasmResult; } pub trait DataLibrary: 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 diff --git a/pkmn_lib_interface/src/app_interface/static_data/data_libraries/type_library.rs b/pkmn_lib_interface/src/app_interface/static_data/data_libraries/type_library.rs index 58f30ca..81f19bb 100755 --- a/pkmn_lib_interface/src/app_interface/static_data/data_libraries/type_library.rs +++ b/pkmn_lib_interface/src/app_interface/static_data/data_libraries/type_library.rs @@ -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; + fn get_type_from_name(&self, name: &str) -> PkmnResult>; fn get_single_effectiveness( &self, attacking_type: TypeIdentifier, defending_type: TypeIdentifier, - ) -> f32; + ) -> PkmnResult; fn get_effectiveness( &self, attacking_type: TypeIdentifier, defending_types: &[TypeIdentifier], - ) -> f32; + ) -> PkmnResult; } pub type Typelibrary = Rc; @@ -21,6 +21,8 @@ pub type Typelibrary = Rc; 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 { + fn get_type_from_name(&self, name: &str) -> PkmnResult> { 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 { 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 { 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, attacking_type: u8, defending_type: u8, - ) -> f32; - fn type_library_get_type_by_name(r: ExternRef, name: *const c_char) -> u8; + ) -> WasmResult; + fn type_library_get_type_by_name( + r: ExternRef, + name: *const c_char, + ) -> WasmResult; } } +use crate::PkmnResult; #[cfg(not(feature = "mock_data"))] pub use implementation::*; diff --git a/pkmn_lib_interface/src/app_interface/static_data/effect_parameter.rs b/pkmn_lib_interface/src/app_interface/static_data/effect_parameter.rs index da174df..15ec172 100755 --- a/pkmn_lib_interface/src/app_interface/static_data/effect_parameter.rs +++ b/pkmn_lib_interface/src/app_interface/static_data/effect_parameter.rs @@ -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 { - unsafe { - match effect_parameter_get_type(ptr) { + pub(crate) fn new(ptr: ExternRef) -> PkmnResult { + 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) -> EffectParameterType; - fn effect_parameter_as_bool(ptr: ExternRef) -> bool; - fn effect_parameter_as_int(ptr: ExternRef) -> i64; - fn effect_parameter_as_float(ptr: ExternRef) -> f32; - fn effect_parameter_as_string(ptr: ExternRef) -> ExternRef; + fn effect_parameter_get_type( + ptr: ExternRef, + ) -> WasmResult; + fn effect_parameter_as_bool(ptr: ExternRef) -> WasmResult; + fn effect_parameter_as_int(ptr: ExternRef) -> WasmResult; + fn effect_parameter_as_float(ptr: ExternRef) -> WasmResult; + fn effect_parameter_as_string( + ptr: ExternRef, + ) -> WasmResult>; } diff --git a/pkmn_lib_interface/src/app_interface/static_data/item.rs b/pkmn_lib_interface/src/app_interface/static_data/item.rs index 5e3eaa4..1b82c56 100755 --- a/pkmn_lib_interface/src/app_interface/static_data/item.rs +++ b/pkmn_lib_interface/src/app_interface/static_data/item.rs @@ -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; } pub type Item = Rc; @@ -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 { + 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) -> ExternRef; - fn item_get_category(ptr: ExternRef) -> ItemCategory; - fn item_get_battle_category(ptr: ExternRef) -> BattleItemCategory; - fn item_get_price(ptr: ExternRef) -> i32; - fn item_has_flag(ptr: ExternRef, flag: ExternRef) -> bool; + fn item_get_name(ptr: ExternRef) -> WasmResult>; + fn item_get_category(ptr: ExternRef) -> WasmResult; + fn item_get_battle_category(ptr: ExternRef) -> WasmResult; + fn item_get_price(ptr: ExternRef) -> WasmResult; + fn item_has_flag(ptr: ExternRef, flag: ExternRef) -> WasmResult; } } +use crate::PkmnResult; #[cfg(not(feature = "mock_data"))] pub use implementation::*; diff --git a/pkmn_lib_interface/src/app_interface/static_data/move_data.rs b/pkmn_lib_interface/src/app_interface/static_data/move_data.rs index 34b5511..3f00758 100755 --- a/pkmn_lib_interface/src/app_interface/static_data/move_data.rs +++ b/pkmn_lib_interface/src/app_interface/static_data/move_data.rs @@ -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; } pub type MoveData = Rc; @@ -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, @@ -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 { 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) -> ExternRef; - fn move_data_get_type(ptr: ExternRef) -> u8; - fn move_data_get_category(ptr: ExternRef) -> MoveCategory; - fn move_data_get_base_power(ptr: ExternRef) -> u8; - fn move_data_get_accuracy(ptr: ExternRef) -> u8; - fn move_data_get_base_usages(ptr: ExternRef) -> u8; - fn move_data_get_target(ptr: ExternRef) -> MoveTarget; - fn move_data_get_priority(ptr: ExternRef) -> i8; - fn move_data_has_flag_by_hash(ptr: ExternRef, flag_hash: u32) -> bool; + fn move_data_get_name(ptr: ExternRef) -> WasmResult>; + fn move_data_get_type(ptr: ExternRef) -> WasmResult; + fn move_data_get_category(ptr: ExternRef) -> WasmResult; + fn move_data_get_base_power(ptr: ExternRef) -> WasmResult; + fn move_data_get_accuracy(ptr: ExternRef) -> WasmResult; + fn move_data_get_base_usages(ptr: ExternRef) -> WasmResult; + fn move_data_get_target(ptr: ExternRef) -> WasmResult; + fn move_data_get_priority(ptr: ExternRef) -> WasmResult; + fn move_data_has_flag_by_hash( + ptr: ExternRef, + flag_hash: u32, + ) -> WasmResult; } } +use crate::PkmnResult; #[cfg(not(feature = "mock_data"))] pub use implementation::*; diff --git a/pkmn_lib_interface/src/app_interface/static_data/nature.rs b/pkmn_lib_interface/src/app_interface/static_data/nature.rs index 5b7f55b..7926f3c 100755 --- a/pkmn_lib_interface/src/app_interface/static_data/nature.rs +++ b/pkmn_lib_interface/src/app_interface/static_data/nature.rs @@ -14,7 +14,7 @@ pub type Nature = Rc; mod implementation { use super::*; use crate::handling::extern_ref::{ExternRef, ExternalReferenceType}; - use crate::handling::Cacheable; + use crate::handling::{Cacheable, WasmResult}; struct NatureInner { reference: ExternRef, @@ -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) -> Statistic; - fn nature_get_decrease_stat(r: ExternRef) -> Statistic; - fn nature_get_increase_modifier(r: ExternRef) -> f32; - fn nature_get_decrease_modifier(r: ExternRef) -> f32; + fn nature_get_increase_stat(r: ExternRef) -> WasmResult; + fn nature_get_decrease_stat(r: ExternRef) -> WasmResult; + fn nature_get_increase_modifier(r: ExternRef) -> WasmResult; + fn nature_get_decrease_modifier(r: ExternRef) -> WasmResult; } } diff --git a/pkmn_lib_interface/src/app_interface/static_data/species.rs b/pkmn_lib_interface/src/app_interface/static_data/species.rs index 49e55e3..108b040 100755 --- a/pkmn_lib_interface/src/app_interface/static_data/species.rs +++ b/pkmn_lib_interface/src/app_interface/static_data/species.rs @@ -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>; - fn hidden_abilities(&self) -> ImmutableList>; + fn abilities(&self) -> Vec>; + fn hidden_abilities(&self) -> Vec>; fn types(&self) -> &Vec; - fn has_flag(&self, flag: &str) -> bool; + fn has_flag(&self, flag: &str) -> PkmnResult; 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; - fn has_flag(&self, flag: &str) -> bool; + fn has_flag(&self, flag: &str) -> PkmnResult; fn as_any(&self) -> &dyn Any; } @@ -50,13 +55,13 @@ pub type Species = Rc; #[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>, base_experience: CachedValue, base_stats: CachedValue, - abilities: CachedValue>>, - hidden_abilities: CachedValue>>, + abilities: CachedValue>>, + hidden_abilities: CachedValue>>, // moves: CachedValue, } @@ -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> = + FFIArray::from_u64(form_get_abilities(reference).unwrap()); + let abilities = + Vec::from_raw_parts(abilities.ptr(), abilities.len(), abilities.len()); + abilities + .into_iter() + .map::, _>(|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> = + 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::, _>(|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>; - fn hidden_abilities(&self) -> ImmutableList>; + fn abilities(&self) -> Vec>; + fn hidden_abilities(&self) -> Vec>; } fn types(&self) -> &Vec { self.inner.types.value_ref() } - fn has_flag(&self, flag: &str) -> bool { + fn has_flag(&self, flag: &str) -> PkmnResult { 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 = 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 { 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) -> ExternRef; - fn form_get_height(r: ExternRef) -> f32; - fn form_get_weight(r: ExternRef) -> f32; - fn form_get_types(r: ExternRef) -> FFIArray; - fn form_get_base_experience(r: ExternRef) -> u32; - fn form_get_base_stats(r: ExternRef) -> ExternRef; - fn form_get_abilities(r: ExternRef) -> VecExternRef; - fn form_get_hidden_abilities(r: ExternRef) -> VecExternRef; - fn form_has_flag_by_hash(r: ExternRef, hash: u32) -> bool; + fn form_get_name(r: ExternRef) -> WasmResult>; + fn form_get_height(r: ExternRef) -> WasmResult; + fn form_get_weight(r: ExternRef) -> WasmResult; + fn form_get_types(r: ExternRef) -> WasmResult; + fn form_get_base_experience(r: ExternRef) -> WasmResult; + fn form_get_base_stats( + r: ExternRef, + ) -> WasmResult>; + fn form_get_abilities(r: ExternRef) -> WasmResult; + fn form_get_hidden_abilities(r: ExternRef) -> WasmResult; + fn form_has_flag_by_hash(r: ExternRef, hash: u32) -> WasmResult; - fn species_get_id(r: ExternRef) -> u16; - fn species_get_name(r: ExternRef) -> ExternRef; - fn species_get_gender_rate(r: ExternRef) -> f32; - fn species_get_growth_rate(r: ExternRef) -> ExternRef; - fn species_get_capture_rate(r: ExternRef) -> u8; - fn species_get_form_by_hash(r: ExternRef, hash: u32) -> ExternRef; - fn species_has_flag_by_hash(r: ExternRef, flag_hash: u32) -> bool; + fn species_get_id(r: ExternRef) -> WasmResult; + fn species_get_name(r: ExternRef) -> WasmResult>; + fn species_get_gender_rate(r: ExternRef) -> WasmResult; + fn species_get_growth_rate(r: ExternRef) -> WasmResult>; + fn species_get_capture_rate(r: ExternRef) -> WasmResult; + fn species_get_form_by_hash( + r: ExternRef, + hash: u32, + ) -> WasmResult>; + fn species_has_flag_by_hash(r: ExternRef, flag_hash: u32) -> WasmResult; } } +use crate::PkmnResult; #[cfg(not(feature = "mock_data"))] pub use implementation::*; diff --git a/pkmn_lib_interface/src/app_interface/static_data/statistics.rs b/pkmn_lib_interface/src/app_interface/static_data/statistics.rs index ad06ad3..dca61b3 100644 --- a/pkmn_lib_interface/src/app_interface/static_data/statistics.rs +++ b/pkmn_lib_interface/src/app_interface/static_data/statistics.rs @@ -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, @@ -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, stat: Statistic, - ) -> u16; + ) -> WasmResult; } } #[cfg(not(feature = "mock_data"))] diff --git a/pkmn_lib_interface/src/app_interface/string_key.rs b/pkmn_lib_interface/src/app_interface/string_key.rs index 345567c..5e3472d 100755 --- a/pkmn_lib_interface/src/app_interface/string_key.rs +++ b/pkmn_lib_interface/src/app_interface/string_key.rs @@ -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 { 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 { + 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) -> *mut cstr_core::c_char; - fn string_key_get_hash(ptr: ExternRef) -> u32; + fn string_key_get_str(ptr: ExternRef) -> WasmResult; + fn string_key_get_hash(ptr: ExternRef) -> WasmResult; } const CRC_TABLE: &[u32] = &[ diff --git a/pkmn_lib_interface/src/handling/cached_value.rs b/pkmn_lib_interface/src/handling/cached_value.rs index 9a6f52e..ea33756 100755 --- a/pkmn_lib_interface/src/handling/cached_value.rs +++ b/pkmn_lib_interface/src/handling/cached_value.rs @@ -7,7 +7,7 @@ pub struct CachedValue { } #[cfg(not(feature = "mock_data"))] -impl CachedValue { +impl CachedValue { pub fn new(init_fn: Box T>) -> Self { Self { init_fn, @@ -15,13 +15,15 @@ impl CachedValue { } } - #[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 CachedValue { 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] diff --git a/pkmn_lib_interface/src/handling/extern_ref.rs b/pkmn_lib_interface/src/handling/extern_ref.rs index 6b26b4d..145cf69 100755 --- a/pkmn_lib_interface/src/handling/extern_ref.rs +++ b/pkmn_lib_interface/src/handling/extern_ref.rs @@ -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 Clone for ExternRef { impl Copy for ExternRef {} +impl Default for ExternRef { + fn default() -> Self { + Self { + p: 0, + resource_type: Default::default(), + } + } +} + impl Eq for ExternRef {} impl PartialEq for ExternRef { @@ -117,70 +124,6 @@ impl From for ExternRef { } } -#[repr(C)] -pub struct VecExternRef { - v: u64, - resource_type: PhantomData, -} - -impl VecExternRef { - 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 { - let p = unsafe { _vec_extern_ref_get_value(self.get_internal_index(), index) }; - ExternRef { - p, - resource_type: Default::default(), - } - } -} - -impl Clone for VecExternRef { - fn clone(&self) -> Self { - Self { - v: self.v, - resource_type: Default::default(), - } - } -} - -impl Copy for VecExternRef {} - -impl Eq for VecExternRef {} - -impl PartialEq for VecExternRef { - fn eq(&self, other: &Self) -> bool { - u64::eq(&self.v, &other.v) - } -} - -impl PartialOrd for VecExternRef { - fn partial_cmp(&self, other: &Self) -> Option { - u64::partial_cmp(&self.v, &other.v) - } -} - -impl Ord for VecExternRef { - fn cmp(&self, other: &Self) -> Ordering { - u64::cmp(&self.v, &other.v) - } -} - pub trait ExternalReferenceType { fn from_extern_value(reference: ExternRef) -> 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; -} diff --git a/pkmn_lib_interface/src/handling/ffi_array.rs b/pkmn_lib_interface/src/handling/ffi_array.rs index a0bf2f0..58e6b78 100755 --- a/pkmn_lib_interface/src/handling/ffi_array.rs +++ b/pkmn_lib_interface/src/handling/ffi_array.rs @@ -19,6 +19,24 @@ impl FFIArray { 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 Default for FFIArray { + fn default() -> Self { + Self { + ptr: core::ptr::null_mut(), + len: 0, + } + } } #[cfg(not(feature = "mock_data"))] diff --git a/pkmn_lib_interface/src/handling/mod.rs b/pkmn_lib_interface/src/handling/mod.rs index e3d034e..099588a 100755 --- a/pkmn_lib_interface/src/handling/mod.rs +++ b/pkmn_lib_interface/src/handling/mod.rs @@ -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>; } )* } @@ -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>; } )* } @@ -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() } } } diff --git a/pkmn_lib_interface/src/handling/script.rs b/pkmn_lib_interface/src/handling/script.rs index 379024a..31217a5 100755 --- a/pkmn_lib_interface/src/handling/script.rs +++ b/pkmn_lib_interface/src/handling/script.rs @@ -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 = crate::result::PkmnResult; 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>>, - ) { + _parameters: Option>>, + ) -> 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; diff --git a/pkmn_lib_interface/src/handling/wasm_result.rs b/pkmn_lib_interface/src/handling/wasm_result.rs new file mode 100644 index 0000000..67ee8f9 --- /dev/null +++ b/pkmn_lib_interface/src/handling/wasm_result.rs @@ -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 +where + T: Default, +{ + err_ptr: u32, + value: T, +} + +pub type WasmVoidResult = WasmResult<()>; + +impl WasmResult +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 { + 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) -> Self { + WasmResult::from(res) + } +} + +impl From> for crate::PkmnResult +where + T: Default, +{ + fn from(value: WasmResult) -> 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 From> for WasmResult +where + T: Default, +{ + fn from(value: PkmnResult) -> 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(), + } + } + } + } +} diff --git a/pkmn_lib_interface/src/lib.rs b/pkmn_lib_interface/src/lib.rs index 1891190..877ce23 100755 --- a/pkmn_lib_interface/src/lib.rs +++ b/pkmn_lib_interface/src/lib.rs @@ -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 Option>>; #[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, - parameters: VecExternRef, - ) { - 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> = 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::>(); + WasmVoidResult::from_res(script.val().unwrap().on_initialize(library.not_null_rc(), Some(parameters))) } fn script_on_before_turn( script: ScriptPtr, choice: ExternRef, - ) { - 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, 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, 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, mv: *mut ExternRef, - ) { + ) -> 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, 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, 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, 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, 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, - ) { - 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, target: ExternRef, 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, target: ExternRef, 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, target: ExternRef, - ) { - 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, target: ExternRef, 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, target: ExternRef, 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, 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, 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, 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, target: ExternRef, 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, target: ExternRef, - ) { - 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, 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, 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, - ) { - 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, - ) { - 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, 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, 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, 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, - ) { - 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, item: ExternRef - ) { - 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, winning_pokemon: ExternRef, 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, winning_pokemon: ExternRef, 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, 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, pokeball: ExternRef, 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() + )) } } } diff --git a/pkmn_lib_interface/src/result.rs b/pkmn_lib_interface/src/result.rs new file mode 100644 index 0000000..00cd141 --- /dev/null +++ b/pkmn_lib_interface/src/result.rs @@ -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 = Result; + +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 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; diff --git a/pkmn_lib_interface/src/utils.rs b/pkmn_lib_interface/src/utils.rs index 841e7b0..4169a00 100755 --- a/pkmn_lib_interface/src/utils.rs +++ b/pkmn_lib_interface/src/utils.rs @@ -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 {} }