Implements first few actual move effects.
This commit is contained in:
		| @@ -1,4 +1,4 @@ | ||||
| use crate::app_interface::{BattleParty, BattleRandom, BattleSide, Pokemon}; | ||||
| use crate::app_interface::{BattleParty, BattleRandom, BattleSide, ChoiceQueue, Pokemon}; | ||||
| use crate::handling::cached_value::CachedValue; | ||||
| use crate::handling::Cacheable; | ||||
| use crate::{ | ||||
| @@ -13,6 +13,7 @@ struct BattleInner { | ||||
|     parties: CachedValue<ImmutableList<BattleParty>>, | ||||
|     sides: CachedValue<ImmutableList<BattleSide>>, | ||||
|     random: CachedValue<BattleRandom>, | ||||
|     choice_queue: CachedValue<ChoiceQueue>, | ||||
| } | ||||
|  | ||||
| #[derive(Clone)] | ||||
| @@ -30,6 +31,9 @@ impl Battle { | ||||
|                 parties: cached_value!({ battle_get_parties(reference).get_immutable_list() }), | ||||
|                 sides: cached_value!({ battle_get_sides(reference).get_immutable_list() }), | ||||
|                 random: cached_value!({ battle_get_random(reference).get_value().unwrap() }), | ||||
|                 choice_queue: cached_value!({ | ||||
|                     battle_get_choice_queue(reference).get_value().unwrap() | ||||
|                 }), | ||||
|             }), | ||||
|         }) | ||||
|     } | ||||
| @@ -38,6 +42,8 @@ impl Battle { | ||||
|         pub fn library(&self) -> DynamicLibrary; | ||||
|         pub fn parties(&self) -> ImmutableList<BattleParty>; | ||||
|         pub fn sides(&self) -> ImmutableList<BattleSide>; | ||||
|         pub fn random(&self) -> BattleRandom; | ||||
|         pub fn choice_queue(&self) -> ChoiceQueue; | ||||
|     } | ||||
|  | ||||
|     #[cfg(not(feature = "mock_data"))] | ||||
| @@ -72,5 +78,6 @@ extern "wasm" { | ||||
|     fn battle_get_parties(r: ExternRef<Battle>) -> VecExternRef<BattleParty>; | ||||
|     fn battle_get_sides(r: ExternRef<Battle>) -> VecExternRef<BattleSide>; | ||||
|     fn battle_get_random(r: ExternRef<Battle>) -> ExternRef<BattleRandom>; | ||||
|     fn battle_get_choice_queue(r: ExternRef<Battle>) -> ExternRef<ChoiceQueue>; | ||||
|     fn battle_get_pokemon(r: ExternRef<Battle>, side: u8, index: u8) -> ExternRef<Pokemon>; | ||||
| } | ||||
|   | ||||
| @@ -39,7 +39,6 @@ impl ExternalReferenceType for BattleParty { | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| #[cfg(not(feature = "mock_data"))] | ||||
| extern "wasm" { | ||||
|     fn battle_party_get_party(r: ExternRef<BattleParty>) -> ExternRef<Party>; | ||||
|   | ||||
| @@ -0,0 +1,31 @@ | ||||
| use crate::{ExternRef, ExternalReferenceType, Pokemon}; | ||||
|  | ||||
| #[derive(Clone)] | ||||
| pub struct ChoiceQueue { | ||||
|     reference: ExternRef<ChoiceQueue>, | ||||
| } | ||||
|  | ||||
| impl ChoiceQueue { | ||||
|     #[cfg(not(feature = "mock_data"))] | ||||
|     pub fn new(reference: ExternRef<ChoiceQueue>) -> Self { | ||||
|         Self { reference } | ||||
|     } | ||||
|  | ||||
|     pub fn move_pokemon_choice_next(&self, pokemon: &Pokemon) -> bool { | ||||
|         unsafe { choice_queue_move_pokemon_choice_next(self.reference, pokemon.reference()) } | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(not(feature = "mock_data"))] | ||||
| impl ExternalReferenceType for ChoiceQueue { | ||||
|     fn from_extern_value(reference: ExternRef<Self>) -> Self { | ||||
|         Self::new(reference) | ||||
|     } | ||||
| } | ||||
|  | ||||
| extern "wasm" { | ||||
|     fn choice_queue_move_pokemon_choice_next( | ||||
|         r: ExternRef<ChoiceQueue>, | ||||
|         pokemon: ExternRef<Pokemon>, | ||||
|     ) -> bool; | ||||
| } | ||||
| @@ -0,0 +1,161 @@ | ||||
| use crate::app_interface::{LearnedMove, MoveData, Pokemon}; | ||||
| use crate::handling::cached_value::CachedValue; | ||||
| use crate::handling::temporary::Temporary; | ||||
| use crate::{cached_value, ExternRef, ExternalReferenceType, Script}; | ||||
|  | ||||
| struct ExecutingMoveInner { | ||||
|     reference: ExternRef<ExecutingMove>, | ||||
|     number_of_hits: CachedValue<u8>, | ||||
|     user: CachedValue<Pokemon>, | ||||
|     chosen_move: CachedValue<LearnedMove>, | ||||
|     use_move: CachedValue<MoveData>, | ||||
| } | ||||
|  | ||||
| #[derive(Clone)] | ||||
| pub struct ExecutingMove { | ||||
|     inner: Temporary<ExecutingMoveInner>, | ||||
| } | ||||
|  | ||||
| impl ExecutingMove { | ||||
|     pub(crate) fn new(reference: ExternRef<ExecutingMove>) -> Self { | ||||
|         Self { | ||||
|             inner: Temporary::new( | ||||
|                 reference.get_internal_index(), | ||||
|                 ExecutingMoveInner { | ||||
|                     reference, | ||||
|                     number_of_hits: cached_value!({ executing_move_get_number_of_hits(reference) }), | ||||
|                     user: cached_value!({ | ||||
|                         executing_move_get_user(reference).get_value().unwrap() | ||||
|                     }), | ||||
|                     chosen_move: cached_value!({ | ||||
|                         executing_move_get_chosen_move(reference) | ||||
|                             .get_value() | ||||
|                             .unwrap() | ||||
|                     }), | ||||
|                     use_move: cached_value!({ | ||||
|                         executing_move_get_use_move(reference).get_value().unwrap() | ||||
|                     }), | ||||
|                 }, | ||||
|             ), | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn number_of_hits(&self) -> u8 { | ||||
|         self.inner.value().number_of_hits.value() | ||||
|     } | ||||
|     pub fn user(&self) -> Pokemon { | ||||
|         self.inner.value().user.value() | ||||
|     } | ||||
|     pub fn chosen_move(&self) -> LearnedMove { | ||||
|         self.inner.value().chosen_move.value() | ||||
|     } | ||||
|     pub fn use_move(&self) -> MoveData { | ||||
|         self.inner.value().use_move.value() | ||||
|     } | ||||
|     pub fn move_script(&self) -> Option<&dyn Script> { | ||||
|         unsafe { executing_move_get_script(self.inner.value().reference).as_ref() } | ||||
|     } | ||||
|     pub fn number_of_targets(&self) -> usize { | ||||
|         unsafe { executing_move_get_number_of_targets(self.inner.value().reference) } | ||||
|     } | ||||
|     pub fn is_pokemon_target(&self, pokemon: &Pokemon) -> bool { | ||||
|         unsafe { | ||||
|             executing_move_is_pokemon_target(self.inner.value().reference, pokemon.reference()) | ||||
|         } | ||||
|     } | ||||
|     pub fn get_hit_data(&self, pokemon: &Pokemon, hit: u8) -> HitData { | ||||
|         unsafe { | ||||
|             executing_move_get_hit_data(self.inner.value().reference, pokemon.reference(), hit) | ||||
|                 .get_value() | ||||
|                 .unwrap() | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[derive(Clone)] | ||||
| pub struct HitData { | ||||
|     reference: ExternRef<HitData>, | ||||
| } | ||||
|  | ||||
| impl HitData { | ||||
|     pub fn is_critical(&self) -> bool { | ||||
|         unsafe { hit_data_is_critical(self.reference) } | ||||
|     } | ||||
|     pub fn base_power(&self) -> u8 { | ||||
|         unsafe { hit_data_get_base_power(self.reference) } | ||||
|     } | ||||
|     pub fn effectiveness(&self) -> f32 { | ||||
|         unsafe { hit_data_get_effectiveness(self.reference) } | ||||
|     } | ||||
|     pub fn damage(&self) -> u32 { | ||||
|         unsafe { hit_data_get_damage(self.reference) } | ||||
|     } | ||||
|     pub fn move_type(&self) -> u8 { | ||||
|         unsafe { hit_data_get_move_type(self.reference) } | ||||
|     } | ||||
|     pub fn has_failed(&self) -> bool { | ||||
|         unsafe { hit_data_is_critical(self.reference) } | ||||
|     } | ||||
|  | ||||
|     pub fn set_critical(&self, critical: bool) { | ||||
|         unsafe { hit_data_set_critical(self.reference, critical) } | ||||
|     } | ||||
|     pub fn set_effectiveness(&self, effectiveness: f32) { | ||||
|         unsafe { hit_data_set_effectiveness(self.reference, effectiveness) } | ||||
|     } | ||||
|     pub fn set_damage(&self, damage: u32) { | ||||
|         unsafe { hit_data_set_damage(self.reference, damage) } | ||||
|     } | ||||
|     pub fn set_move_type(&self, move_type: u8) { | ||||
|         unsafe { hit_data_set_move_type(self.reference, move_type) } | ||||
|     } | ||||
|     pub fn fail(&self) { | ||||
|         unsafe { hit_data_fail(self.reference) } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl ExternalReferenceType for ExecutingMove { | ||||
|     fn from_extern_value(reference: ExternRef<Self>) -> Self { | ||||
|         Self::new(reference) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl ExternalReferenceType for HitData { | ||||
|     fn from_extern_value(reference: ExternRef<Self>) -> Self { | ||||
|         Self { reference } | ||||
|     } | ||||
| } | ||||
|  | ||||
| extern "wasm" { | ||||
|     fn executing_move_get_number_of_targets(r: ExternRef<ExecutingMove>) -> usize; | ||||
|     fn executing_move_get_number_of_hits(r: ExternRef<ExecutingMove>) -> u8; | ||||
|     fn executing_move_get_user(r: ExternRef<ExecutingMove>) -> ExternRef<Pokemon>; | ||||
|     fn executing_move_get_chosen_move(r: ExternRef<ExecutingMove>) -> ExternRef<LearnedMove>; | ||||
|     fn executing_move_get_use_move(r: ExternRef<ExecutingMove>) -> ExternRef<MoveData>; | ||||
|     #[allow(improper_ctypes)] | ||||
|     fn executing_move_get_script(r: ExternRef<ExecutingMove>) -> *const dyn Script; | ||||
|  | ||||
|     fn executing_move_is_pokemon_target( | ||||
|         r: ExternRef<ExecutingMove>, | ||||
|         pokemon: ExternRef<Pokemon>, | ||||
|     ) -> bool; | ||||
|     fn executing_move_get_hit_data( | ||||
|         r: ExternRef<ExecutingMove>, | ||||
|         target: ExternRef<Pokemon>, | ||||
|         hit: u8, | ||||
|     ) -> ExternRef<HitData>; | ||||
|  | ||||
|     fn hit_data_is_critical(r: ExternRef<HitData>) -> bool; | ||||
|     fn hit_data_get_base_power(r: ExternRef<HitData>) -> u8; | ||||
|     fn hit_data_get_effectiveness(r: ExternRef<HitData>) -> f32; | ||||
|     fn hit_data_get_damage(r: ExternRef<HitData>) -> u32; | ||||
|     fn hit_data_get_move_type(r: ExternRef<HitData>) -> u8; | ||||
|     fn hit_data_has_failed(r: ExternRef<HitData>) -> bool; | ||||
|  | ||||
|     fn hit_data_set_critical(r: ExternRef<HitData>, critical: bool); | ||||
|     fn hit_data_set_base_power(r: ExternRef<HitData>, power: u8); | ||||
|     fn hit_data_set_effectiveness(r: ExternRef<HitData>, effectiveness: f32); | ||||
|     fn hit_data_set_damage(r: ExternRef<HitData>, damage: u32); | ||||
|     fn hit_data_set_move_type(r: ExternRef<HitData>, move_type: u8); | ||||
|     fn hit_data_fail(r: ExternRef<HitData>); | ||||
| } | ||||
| @@ -2,7 +2,9 @@ mod battle; | ||||
| mod battle_party; | ||||
| mod battle_random; | ||||
| mod battle_side; | ||||
| mod choice_queue; | ||||
| mod dynamic_library; | ||||
| mod executing_move; | ||||
| mod learned_move; | ||||
| mod party; | ||||
| mod pokemon; | ||||
| @@ -13,7 +15,9 @@ pub use battle::*; | ||||
| pub use battle_party::*; | ||||
| pub use battle_random::*; | ||||
| pub use battle_side::*; | ||||
| pub use choice_queue::*; | ||||
| pub use dynamic_library::DynamicLibrary; | ||||
| pub use executing_move::*; | ||||
| pub use learned_move::*; | ||||
| pub use party::*; | ||||
| pub use pokemon::*; | ||||
|   | ||||
| @@ -7,7 +7,7 @@ use crate::handling::cached_value::CachedValue; | ||||
| use crate::handling::Cacheable; | ||||
| use crate::{ | ||||
|     cached_value, cached_value_getters, wasm_optional_reference_getters, wasm_reference_getters, | ||||
|     wasm_value_getters, DynamicLibrary, ExternRef, ExternalReferenceType, Script, | ||||
|     wasm_value_getters, DynamicLibrary, ExternRef, ExternalReferenceType, Script, TypeIdentifier, | ||||
| }; | ||||
| use alloc::boxed::Box; | ||||
| use alloc::rc::Rc; | ||||
| @@ -61,6 +61,10 @@ impl Pokemon { | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     pub(crate) fn reference(&self) -> ExternRef<Self> { | ||||
|         self.inner.reference | ||||
|     } | ||||
|  | ||||
|     cached_value_getters! { | ||||
|         pub fn library(&self) -> DynamicLibrary; | ||||
|         pub fn flat_stats(&self) -> StatisticSet<u32>; | ||||
| @@ -101,8 +105,8 @@ impl Pokemon { | ||||
|         unsafe { pokemon_get_type(self.inner.reference, index) } | ||||
|     } | ||||
|     #[cfg(not(feature = "mock_data"))] | ||||
|     pub fn has_type(&self, type_identifier: u8) -> bool { | ||||
|         unsafe { pokemon_has_type(self.inner.reference, type_identifier) } | ||||
|     pub fn has_type(&self, type_identifier: TypeIdentifier) -> bool { | ||||
|         unsafe { pokemon_has_type(self.inner.reference, type_identifier.into()) } | ||||
|     } | ||||
|     #[cfg(not(feature = "mock_data"))] | ||||
|     pub fn has_type_by_name(&self, type_name: &str) -> bool { | ||||
| @@ -206,6 +210,12 @@ wasm_value_getters! { | ||||
|     pub fn is_usable(&self) -> bool; | ||||
| } | ||||
|  | ||||
| impl PartialEq for Pokemon { | ||||
|     fn eq(&self, other: &Self) -> bool { | ||||
|         self.inner.reference == other.inner.reference | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// A source of damage. This should be as unique as possible. | ||||
| #[derive(Debug, Clone, Copy)] | ||||
| #[repr(u8)] | ||||
| @@ -246,6 +256,7 @@ extern "wasm" { | ||||
|         diff_amount: i8, | ||||
|         self_inflicted: bool, | ||||
|     ) -> bool; | ||||
|     #[allow(improper_ctypes)] | ||||
|     fn pokemon_get_ability_script(r: ExternRef<Pokemon>) -> *const Box<dyn Script>; | ||||
|     fn pokemon_change_species( | ||||
|         r: ExternRef<Pokemon>, | ||||
|   | ||||
| @@ -3,10 +3,9 @@ use crate::handling::cached_value::CachedValue; | ||||
| use crate::handling::temporary::Temporary; | ||||
| use crate::ExternRef; | ||||
| #[cfg(not(feature = "mock_data"))] | ||||
| use crate::{cached_value, wasm_value_getters, ExternalReferenceType, Script}; | ||||
| use crate::{cached_value, ExternalReferenceType, Script}; | ||||
| #[cfg(not(feature = "mock_data"))] | ||||
| use alloc::boxed::Box; | ||||
| use alloc::rc::Rc; | ||||
|  | ||||
| struct BaseTurnChoiceData { | ||||
|     reference: ExternRef<TurnChoice>, | ||||
| @@ -19,12 +18,10 @@ struct MoveTurnChoiceDataInner { | ||||
|     target_side: CachedValue<u8>, | ||||
|     target_index: CachedValue<u8>, | ||||
| } | ||||
|  | ||||
| #[derive(Clone)] | ||||
| struct MoveTurnChoiceDataTemporary { | ||||
|     inner: Rc<MoveTurnChoiceDataInner>, | ||||
| } | ||||
| pub struct MoveTurnChoiceData { | ||||
|     temp: Temporary<MoveTurnChoiceDataTemporary>, | ||||
|     inner: Temporary<MoveTurnChoiceDataInner>, | ||||
| } | ||||
|  | ||||
| pub enum TurnChoice { | ||||
| @@ -38,7 +35,7 @@ pub enum TurnChoice { | ||||
| impl TurnChoice { | ||||
|     fn base(&self) -> &BaseTurnChoiceData { | ||||
|         match self { | ||||
|             TurnChoice::Move(d) => &d.temp.value_ref().inner.base, | ||||
|             TurnChoice::Move(d) => &d.inner.value_ref().base, | ||||
|             TurnChoice::Item() => unimplemented!(), | ||||
|             TurnChoice::Switch() => unimplemented!(), | ||||
|             TurnChoice::Flee => unimplemented!(), | ||||
| @@ -68,22 +65,22 @@ impl TurnChoice { | ||||
|  | ||||
| impl MoveTurnChoiceData { | ||||
|     pub fn used_move(&self) -> LearnedMove { | ||||
|         self.temp.value().inner.used_move.value() | ||||
|         self.inner.value().used_move.value() | ||||
|     } | ||||
|     pub fn target_side(&self) -> u8 { | ||||
|         self.temp.value().inner.target_side.value() | ||||
|         self.inner.value().target_side.value() | ||||
|     } | ||||
|     pub fn target_index(&self) -> u8 { | ||||
|         self.temp.value().inner.target_index.value() | ||||
|         self.inner.value().target_index.value() | ||||
|     } | ||||
|     #[cfg(not(feature = "mock_data"))] | ||||
|     pub fn priority(&self) -> i8 { | ||||
|         unsafe { turn_choice_move_priority(self.temp.value().inner.base.reference.cast()) } | ||||
|         unsafe { turn_choice_move_priority(self.inner.value().base.reference.cast()) } | ||||
|     } | ||||
|  | ||||
|     #[cfg(not(feature = "mock_data"))] | ||||
|     pub fn move_script(&self) -> Option<&Box<dyn Script>> { | ||||
|         unsafe { turn_choice_move_script(self.temp.value().inner.base.reference.cast()).as_ref() } | ||||
|         unsafe { turn_choice_move_script(self.inner.value().base.reference.cast()).as_ref() } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -93,7 +90,10 @@ impl ExternalReferenceType for TurnChoice { | ||||
|         let kind = unsafe { turn_choice_get_kind(reference) }; | ||||
|         match kind { | ||||
|             0 => TurnChoice::Move(MoveTurnChoiceData { | ||||
|                 temp: Temporary::from_reference(reference.cast()), | ||||
|                 inner: Temporary::new( | ||||
|                     reference.get_internal_index(), | ||||
|                     MoveTurnChoiceDataInner::from_reference(reference.cast()), | ||||
|                 ), | ||||
|             }), | ||||
|             _ => panic!("Unknown turn choice type"), | ||||
|         } | ||||
| @@ -101,24 +101,22 @@ impl ExternalReferenceType for TurnChoice { | ||||
| } | ||||
|  | ||||
| #[cfg(not(feature = "mock_data"))] | ||||
| impl ExternalReferenceType for MoveTurnChoiceDataTemporary { | ||||
|     fn from_extern_value(reference: ExternRef<Self>) -> Self { | ||||
| impl MoveTurnChoiceDataInner { | ||||
|     fn from_reference(reference: ExternRef<MoveTurnChoiceData>) -> Self { | ||||
|         Self { | ||||
|             inner: Rc::new(MoveTurnChoiceDataInner { | ||||
|                 base: BaseTurnChoiceData { | ||||
|                     reference: reference.cast(), | ||||
|                     user: cached_value!({ | ||||
|                         turn_choice_get_user(reference.cast()).get_value().unwrap() | ||||
|                     }), | ||||
|                 }, | ||||
|                 used_move: cached_value!({ | ||||
|                     turn_choice_move_used_move(reference.cast()) | ||||
|                         .get_value() | ||||
|                         .unwrap() | ||||
|             base: BaseTurnChoiceData { | ||||
|                 reference: reference.cast(), | ||||
|                 user: cached_value!({ | ||||
|                     turn_choice_get_user(reference.cast()).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()) }), | ||||
|             }, | ||||
|             used_move: cached_value!({ | ||||
|                 turn_choice_move_used_move(reference.cast()) | ||||
|                     .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()) }), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -135,14 +133,6 @@ extern "wasm" { | ||||
|     fn turn_choice_move_target_side(r: ExternRef<MoveTurnChoiceData>) -> u8; | ||||
|     fn turn_choice_move_target_index(r: ExternRef<MoveTurnChoiceData>) -> u8; | ||||
|     fn turn_choice_move_priority(r: ExternRef<MoveTurnChoiceData>) -> i8; | ||||
|     #[allow(improper_ctypes)] | ||||
|     fn turn_choice_move_script(r: ExternRef<MoveTurnChoiceData>) -> *const Box<dyn Script>; | ||||
| } | ||||
|  | ||||
| #[no_mangle] | ||||
| #[cfg(not(feature = "mock_data"))] | ||||
| unsafe extern "wasm" fn turn_choice_mark_deleted(r: ExternRef<TurnChoice>, kind: u8) { | ||||
|     match kind { | ||||
|         0 => Temporary::<MoveTurnChoiceDataTemporary>::mark_as_deleted(r.cast()), | ||||
|         _ => panic!("Unknown turn choice type"), | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| use crate::{ExternalReferenceType, VecExternRef}; | ||||
| use alloc::boxed::Box; | ||||
| use alloc::collections::BTreeMap; | ||||
| #[cfg(feature = "mock_data")] | ||||
| use alloc::rc::Rc; | ||||
| use alloc::vec::Vec; | ||||
| use core::marker::PhantomData; | ||||
| @@ -44,13 +44,22 @@ where | ||||
|  | ||||
|     pub(crate) fn from_ref(extern_ref: VecExternRef<T>) -> Self { | ||||
|         unsafe { | ||||
|             let existing = CACHE.get(&extern_ref.get_internal_index()); | ||||
|             if let None = CACHE { | ||||
|                 CACHE = Some(hashbrown::HashMap::new()); | ||||
|             } | ||||
|             let existing = CACHE | ||||
|                 .as_ref() | ||||
|                 .unwrap() | ||||
|                 .get(&extern_ref.get_internal_index()); | ||||
|             if let Some(v) = existing { | ||||
|                 let inner = *v as *const ImmutableListInner<T>; | ||||
|                 ImmutableList { inner } | ||||
|             } else { | ||||
|                 let v = Self::new(extern_ref); | ||||
|                 CACHE.insert(extern_ref.get_internal_index(), v.inner as *const u8); | ||||
|                 CACHE | ||||
|                     .as_mut() | ||||
|                     .unwrap() | ||||
|                     .insert(extern_ref.get_internal_index(), v.inner as *const u8); | ||||
|                 v | ||||
|             } | ||||
|         } | ||||
| @@ -102,4 +111,4 @@ where | ||||
|     } | ||||
| } | ||||
|  | ||||
| static mut CACHE: BTreeMap<u32, *const u8> = BTreeMap::new(); | ||||
| static mut CACHE: Option<hashbrown::HashMap<u32, *const u8>> = None; | ||||
|   | ||||
| @@ -5,5 +5,4 @@ pub mod string_key; | ||||
|  | ||||
| pub use dynamic_data::*; | ||||
| pub use static_data::*; | ||||
| pub use string_key::get_hash_const; | ||||
| pub use string_key::StringKey; | ||||
| pub use string_key::*; | ||||
|   | ||||
| @@ -1,12 +1,11 @@ | ||||
| use crate::app_interface::{DataLibrary, Item}; | ||||
| use crate::{ExternRef, ExternalReferenceType, StringKey}; | ||||
| use alloc::collections::BTreeMap; | ||||
| use alloc::rc::Rc; | ||||
| use spin::rwlock::RwLock; | ||||
|  | ||||
| struct ItemLibraryInner { | ||||
|     ptr: ExternRef<ItemLibrary>, | ||||
|     cache: RwLock<BTreeMap<u32, Item>>, | ||||
|     cache: RwLock<hashbrown::HashMap<u32, Item>>, | ||||
| } | ||||
|  | ||||
| #[derive(Clone)] | ||||
| @@ -27,7 +26,7 @@ impl ItemLibrary { | ||||
| } | ||||
|  | ||||
| impl DataLibrary<Item> for ItemLibrary { | ||||
|     fn get_cache(&self) -> &spin::rwlock::RwLock<BTreeMap<u32, Item>> { | ||||
|     fn get_cache(&self) -> &spin::rwlock::RwLock<hashbrown::HashMap<u32, Item>> { | ||||
|         &self.inner.cache | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| use crate::{cached_value, cached_value_getters, ExternRef, ExternalReferenceType, StringKey}; | ||||
| use alloc::collections::BTreeMap; | ||||
| use alloc::rc::Rc; | ||||
| use move_library::MoveLibrary; | ||||
| use spin::rwlock::RwLock; | ||||
| @@ -51,6 +50,11 @@ impl StaticData { | ||||
|                 type_library: cached_value!({ | ||||
|                     static_data_get_type_library(reference).get_value().unwrap() | ||||
|                 }), | ||||
|                 settings: cached_value!({ | ||||
|                     static_data_get_library_settings(reference) | ||||
|                         .get_value() | ||||
|                         .unwrap() | ||||
|                 }), | ||||
|             }), | ||||
|         }) | ||||
|     } | ||||
| @@ -88,7 +92,7 @@ crate::handling::cacheable::cacheable!(StaticData); | ||||
| #[cfg(not(feature = "mock_data"))] | ||||
| impl ExternalReferenceType for StaticData { | ||||
|     fn from_extern_value(reference: ExternRef<Self>) -> Self { | ||||
|         StaticData::mock(reference) | ||||
|         StaticData::new(reference) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -125,12 +129,20 @@ impl LibrarySettings { | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(not(feature = "mock_data"))] | ||||
| impl ExternalReferenceType for LibrarySettings { | ||||
|     fn from_extern_value(reference: ExternRef<Self>) -> Self { | ||||
|         LibrarySettings::new(reference) | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(not(feature = "mock_data"))] | ||||
| extern "wasm" { | ||||
|     fn static_data_get_move_library(ptr: ExternRef<StaticData>) -> ExternRef<MoveLibrary>; | ||||
|     fn static_data_get_item_library(ptr: ExternRef<StaticData>) -> ExternRef<ItemLibrary>; | ||||
|     fn static_data_get_species_library(ptr: ExternRef<StaticData>) -> ExternRef<SpeciesLibrary>; | ||||
|     fn static_data_get_type_library(ptr: ExternRef<StaticData>) -> ExternRef<TypeLibrary>; | ||||
|     fn static_data_get_library_settings(ptr: ExternRef<StaticData>) -> ExternRef<LibrarySettings>; | ||||
|  | ||||
|     fn library_settings_get_maximum_level(ptr: ExternRef<LibrarySettings>) -> LevelInt; | ||||
| } | ||||
| @@ -141,7 +153,7 @@ where | ||||
|     T: ExternalReferenceType, | ||||
|     T: Clone, | ||||
| { | ||||
|     fn get_cache(&self) -> &RwLock<BTreeMap<u32, T>>; | ||||
|     fn get_cache(&self) -> &RwLock<hashbrown::HashMap<u32, T>>; | ||||
|     fn get_self_ref(&self) -> ExternRef<Self> | ||||
|     where | ||||
|         Self: Sized; | ||||
| @@ -188,7 +200,7 @@ pub trait DataLibrary<T>: Cacheable | ||||
| where | ||||
|     T: Clone, | ||||
| { | ||||
|     fn get_cache(&self) -> &RwLock<BTreeMap<u32, T>>; | ||||
|     fn get_cache(&self) -> &RwLock<hashbrown::HashMap<u32, T>>; | ||||
|     fn get_self_ref(&self) -> ExternRef<Self> | ||||
|     where | ||||
|         Self: Sized; | ||||
|   | ||||
| @@ -1,13 +1,12 @@ | ||||
| use crate::app_interface::data_libraries::DataLibrary; | ||||
| use crate::app_interface::{MoveData, StringKey}; | ||||
| use crate::{ExternRef, ExternalReferenceType}; | ||||
| use alloc::collections::BTreeMap; | ||||
| use alloc::rc::Rc; | ||||
| use spin::RwLock; | ||||
|  | ||||
| struct MoveLibraryInner { | ||||
|     ptr: ExternRef<MoveLibrary>, | ||||
|     cache: RwLock<BTreeMap<u32, MoveData>>, | ||||
|     cache: RwLock<hashbrown::HashMap<u32, MoveData>>, | ||||
| } | ||||
|  | ||||
| #[derive(Clone)] | ||||
| @@ -38,7 +37,7 @@ impl MoveLibrary { | ||||
| } | ||||
|  | ||||
| impl DataLibrary<MoveData> for MoveLibrary { | ||||
|     fn get_cache(&self) -> &spin::rwlock::RwLock<BTreeMap<u32, MoveData>> { | ||||
|     fn get_cache(&self) -> &spin::rwlock::RwLock<hashbrown::HashMap<u32, MoveData>> { | ||||
|         &self.inner.cache | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -1,12 +1,11 @@ | ||||
| use crate::app_interface::{DataLibrary, Species}; | ||||
| use crate::{ExternRef, ExternalReferenceType, StringKey}; | ||||
| use alloc::collections::BTreeMap; | ||||
| use alloc::rc::Rc; | ||||
| use spin::RwLock; | ||||
|  | ||||
| struct SpeciesLibraryInner { | ||||
|     ptr: ExternRef<SpeciesLibrary>, | ||||
|     cache: RwLock<BTreeMap<u32, Species>>, | ||||
|     cache: RwLock<hashbrown::HashMap<u32, Species>>, | ||||
| } | ||||
|  | ||||
| #[derive(Clone)] | ||||
| @@ -37,7 +36,7 @@ impl SpeciesLibrary { | ||||
| } | ||||
|  | ||||
| impl DataLibrary<Species> for SpeciesLibrary { | ||||
|     fn get_cache(&self) -> &spin::rwlock::RwLock<BTreeMap<u32, Species>> { | ||||
|     fn get_cache(&self) -> &spin::rwlock::RwLock<hashbrown::HashMap<u32, Species>> { | ||||
|         &self.inner.cache | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| use crate::{ExternRef, ExternalReferenceType}; | ||||
| use alloc::collections::BTreeMap; | ||||
| use crate::{ExternRef, ExternalReferenceType, TypeIdentifier}; | ||||
| use alloc::rc::Rc; | ||||
| use alloc::string::{String, ToString}; | ||||
| use cstr_core::{c_char, CString}; | ||||
| @@ -7,8 +6,8 @@ use spin::RwLock; | ||||
|  | ||||
| struct TypeLibraryInner { | ||||
|     reference: ExternRef<TypeLibrary>, | ||||
|     name_to_type_cache: RwLock<BTreeMap<String, u8>>, | ||||
|     effectiveness_cache: RwLock<BTreeMap<(u8, u8), f32>>, | ||||
|     name_to_type_cache: RwLock<hashbrown::HashMap<String, TypeIdentifier>>, | ||||
|     effectiveness_cache: RwLock<hashbrown::HashMap<(TypeIdentifier, TypeIdentifier), f32>>, | ||||
| } | ||||
|  | ||||
| #[derive(Clone)] | ||||
| @@ -39,7 +38,7 @@ impl TypeLibrary { | ||||
|     } | ||||
|  | ||||
|     #[cfg(not(feature = "mock_data"))] | ||||
|     pub fn get_type_from_name(&self, name: &str) -> Option<u8> { | ||||
|     pub fn get_type_from_name(&self, name: &str) -> Option<TypeIdentifier> { | ||||
|         if let Some(cached) = self.inner.name_to_type_cache.read().get(name) { | ||||
|             return Some(*cached); | ||||
|         } | ||||
| @@ -48,6 +47,7 @@ impl TypeLibrary { | ||||
|         if v == 255 { | ||||
|             return None; | ||||
|         } | ||||
|         let v = v.into(); | ||||
|         self.inner | ||||
|             .name_to_type_cache | ||||
|             .write() | ||||
| @@ -56,7 +56,11 @@ impl TypeLibrary { | ||||
|     } | ||||
|  | ||||
|     #[cfg(not(feature = "mock_data"))] | ||||
|     pub fn get_single_effectiveness(&self, attacking_type: u8, defending_type: u8) -> f32 { | ||||
|     pub fn get_single_effectiveness( | ||||
|         &self, | ||||
|         attacking_type: TypeIdentifier, | ||||
|         defending_type: TypeIdentifier, | ||||
|     ) -> f32 { | ||||
|         if let Some(cached) = self | ||||
|             .inner | ||||
|             .effectiveness_cache | ||||
| @@ -68,8 +72,8 @@ impl TypeLibrary { | ||||
|         let effectiveness = unsafe { | ||||
|             type_library_get_single_effectiveness( | ||||
|                 self.inner.reference, | ||||
|                 attacking_type, | ||||
|                 defending_type, | ||||
|                 attacking_type.into(), | ||||
|                 defending_type.into(), | ||||
|             ) | ||||
|         }; | ||||
|         self.inner | ||||
| @@ -80,7 +84,11 @@ impl TypeLibrary { | ||||
|     } | ||||
|  | ||||
|     #[cfg(not(feature = "mock_data"))] | ||||
|     pub fn get_effectiveness(&self, attacking_type: u8, defending_types: &[u8]) -> f32 { | ||||
|     pub fn get_effectiveness( | ||||
|         &self, | ||||
|         attacking_type: TypeIdentifier, | ||||
|         defending_types: &[TypeIdentifier], | ||||
|     ) -> f32 { | ||||
|         let mut f = 1.0; | ||||
|         for defending_type in defending_types { | ||||
|             f *= self.get_single_effectiveness(attacking_type, *defending_type); | ||||
|   | ||||
| @@ -96,7 +96,7 @@ crate::handling::cacheable::cacheable!(Item); | ||||
| #[cfg(not(feature = "mock_data"))] | ||||
| impl ExternalReferenceType for Item { | ||||
|     fn from_extern_value(reference: ExternRef<Self>) -> Self { | ||||
|         Item::mock(reference) | ||||
|         Item::new(reference) | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -14,3 +14,23 @@ pub use nature::*; | ||||
| pub use species::*; | ||||
|  | ||||
| pub type LevelInt = u8; | ||||
|  | ||||
| /// A unique key that can be used to store a reference to a type. Opaque reference to a byte | ||||
| /// internally. | ||||
| #[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash)] | ||||
| pub struct TypeIdentifier { | ||||
|     /// The unique internal value. | ||||
|     val: u8, | ||||
| } | ||||
|  | ||||
| impl From<u8> for TypeIdentifier { | ||||
|     fn from(val: u8) -> Self { | ||||
|         Self { val } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<TypeIdentifier> for u8 { | ||||
|     fn from(id: TypeIdentifier) -> Self { | ||||
|         id.val | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| use crate::app_interface::{get_hash_const, StringKey}; | ||||
| use crate::app_interface::{get_hash, StringKey}; | ||||
| use crate::handling::cached_value::CachedValue; | ||||
| use crate::handling::Cacheable; | ||||
| use crate::{cached_value, cached_value_getters, ExternRef, ExternalReferenceType}; | ||||
| @@ -104,8 +104,8 @@ impl MoveData { | ||||
|     } | ||||
|  | ||||
|     #[cfg(not(feature = "mock_data"))] | ||||
|     pub fn has_flag<const N: usize>(&self, flag: &[u8; N]) -> bool { | ||||
|         let hash = get_hash_const(flag); | ||||
|     pub fn has_flag(&self, flag: &str) -> bool { | ||||
|         let hash = get_hash(flag); | ||||
|         unsafe { move_data_has_flag_by_hash(self.inner.ptr, hash) } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,11 +1,10 @@ | ||||
| use crate::app_interface::get_hash_const; | ||||
| use crate::app_interface::get_hash; | ||||
| use crate::handling::cached_value::CachedValue; | ||||
| use crate::handling::Cacheable; | ||||
| use crate::{ | ||||
|     cached_value, cached_value_getters, ExternRef, ExternalReferenceType, FFIArray, ImmutableList, | ||||
|     StringKey, VecExternRef, | ||||
| }; | ||||
| use alloc::collections::BTreeMap; | ||||
| use alloc::rc::Rc; | ||||
| use alloc::vec::Vec; | ||||
| use spin::RwLock; | ||||
| @@ -147,8 +146,8 @@ impl Form { | ||||
|     } | ||||
|  | ||||
|     #[cfg(not(feature = "mock_data"))] | ||||
|     pub fn has_flag<const N: usize>(&self, flag: &[u8; N]) -> bool { | ||||
|         let hash = get_hash_const(flag); | ||||
|     pub fn has_flag(&self, flag: &str) -> bool { | ||||
|         let hash = get_hash(flag); | ||||
|         unsafe { form_has_flag_by_hash(self.inner.reference, hash) } | ||||
|     } | ||||
| } | ||||
| @@ -160,7 +159,7 @@ pub struct SpeciesInner { | ||||
|     gender_rate: CachedValue<f32>, | ||||
|     growth_rate: CachedValue<StringKey>, | ||||
|     capture_rate: CachedValue<u8>, | ||||
|     forms: RwLock<BTreeMap<u32, Option<Form>>>, | ||||
|     forms: RwLock<hashbrown::HashMap<u32, Option<Form>>>, | ||||
| } | ||||
|  | ||||
| #[derive(Clone)] | ||||
| @@ -205,8 +204,8 @@ impl Species { | ||||
|     } | ||||
|  | ||||
|     #[cfg(not(feature = "mock_data"))] | ||||
|     pub fn get_form<const N: usize>(&self, form_name: &[u8; N]) -> Option<Form> { | ||||
|         let hash = get_hash_const(form_name); | ||||
|     pub fn get_form(&self, form_name: &str) -> Option<Form> { | ||||
|         let hash = get_hash(form_name); | ||||
|         unsafe { | ||||
|             if let Some(v) = self.inner.forms.read().get(&hash) { | ||||
|                 v.clone() | ||||
| @@ -220,8 +219,8 @@ impl Species { | ||||
|     } | ||||
|  | ||||
|     #[cfg(not(feature = "mock_data"))] | ||||
|     pub fn has_flag<const N: usize>(&self, flag: &[u8; N]) -> bool { | ||||
|         let hash = get_hash_const(flag); | ||||
|     pub fn has_flag(&self, flag: &str) -> bool { | ||||
|         let hash = get_hash(flag); | ||||
|         unsafe { species_has_flag_by_hash(self.inner.reference, hash) } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -31,7 +31,7 @@ impl StringKey { | ||||
|     } | ||||
|  | ||||
|     #[cfg(not(feature = "mock_data"))] | ||||
|     pub(super) fn ptr(&self) -> ExternRef<Self> { | ||||
|     pub(crate) fn ptr(&self) -> ExternRef<Self> { | ||||
|         self.data.ptr | ||||
|     } | ||||
|  | ||||
| @@ -70,6 +70,12 @@ impl StringKey { | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl PartialEq for StringKey { | ||||
|     fn eq(&self, other: &Self) -> bool { | ||||
|         self.data.ptr == other.data.ptr | ||||
|     } | ||||
| } | ||||
|  | ||||
| crate::handling::cacheable::cacheable!(StringKey); | ||||
|  | ||||
| #[cfg(not(feature = "mock_data"))] | ||||
| @@ -134,23 +140,12 @@ const fn to_lower(c: u8) -> u8 { | ||||
|     c | ||||
| } | ||||
|  | ||||
| pub const fn get_hash_const<const N: usize>(s: &[u8; N]) -> u32 { | ||||
|     let mut crc: u32 = 0xffffffff; | ||||
|  | ||||
|     let mut i: usize = 0; | ||||
|     while i < N { | ||||
|         crc = (crc >> 8) ^ CRC_TABLE[((crc ^ (to_lower(s[i]) as u32)) & 0xff) as usize]; | ||||
|         i += 1; | ||||
|     } | ||||
|     crc ^ 0xffffffff | ||||
| } | ||||
|  | ||||
| pub const fn get_hash(s: &[u8]) -> u32 { | ||||
| pub const fn get_hash(s: &str) -> u32 { | ||||
|     let mut crc: u32 = 0xffffffff; | ||||
|  | ||||
|     let mut i: usize = 0; | ||||
|     while i < s.len() { | ||||
|         crc = (crc >> 8) ^ CRC_TABLE[((crc ^ (to_lower(s[i]) as u32)) & 0xff) as usize]; | ||||
|         crc = (crc >> 8) ^ CRC_TABLE[((crc ^ (to_lower(s.as_bytes()[i]) as u32)) & 0xff) as usize]; | ||||
|         i += 1; | ||||
|     } | ||||
|     crc ^ 0xffffffff | ||||
|   | ||||
		Reference in New Issue
	
	Block a user