Initial work on creating a WASM interface for PkmnLibRs
This commit is contained in:
		| @@ -0,0 +1,18 @@ | ||||
| use crate::app_interface::StaticData; | ||||
| use crate::{impl_extern_ctor, ExternRef}; | ||||
|  | ||||
| pub struct BattleLibrary { | ||||
|     ptr: ExternRef<BattleLibrary>, | ||||
| } | ||||
|  | ||||
| impl_extern_ctor!(BattleLibrary); | ||||
|  | ||||
| impl BattleLibrary { | ||||
|     pub fn data_library(&self) -> StaticData { | ||||
|         unsafe { StaticData::new(battle_library_get_static_data(self.ptr)) } | ||||
|     } | ||||
| } | ||||
|  | ||||
| extern "wasm" { | ||||
|     fn battle_library_get_static_data(ptr: ExternRef<BattleLibrary>) -> ExternRef<StaticData>; | ||||
| } | ||||
							
								
								
									
										5
									
								
								pkmn_lib_interface/src/app_interface/battling/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								pkmn_lib_interface/src/app_interface/battling/mod.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| mod battle_library; | ||||
| mod turn_choices; | ||||
|  | ||||
| pub use battle_library::BattleLibrary; | ||||
| pub use turn_choices::*; | ||||
| @@ -0,0 +1 @@ | ||||
| pub struct BaseTurnChoice {} | ||||
| @@ -0,0 +1,64 @@ | ||||
| use crate::app_interface::{DataLibrary, Item}; | ||||
| use crate::handling::Cacheable; | ||||
| use crate::{ExternRef, StringKey}; | ||||
| use alloc::collections::BTreeMap; | ||||
| use alloc::rc::Rc; | ||||
| use spin::rwlock::RwLock; | ||||
|  | ||||
| struct ItemLibraryInner { | ||||
|     ptr: ExternRef<ItemLibrary>, | ||||
|     cache: RwLock<BTreeMap<u32, Item>>, | ||||
| } | ||||
|  | ||||
| #[derive(Clone)] | ||||
| pub struct ItemLibrary { | ||||
|     inner: Rc<ItemLibraryInner>, | ||||
| } | ||||
|  | ||||
| impl ItemLibrary { | ||||
|     pub(crate) fn new(ptr: ExternRef<Self>) -> Self { | ||||
|         Self { | ||||
|             inner: Rc::new(ItemLibraryInner { | ||||
|                 ptr, | ||||
|                 cache: Default::default(), | ||||
|             }), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl DataLibrary<Item> for ItemLibrary { | ||||
|     fn get_cache(&self) -> &spin::rwlock::RwLock<BTreeMap<u32, Item>> { | ||||
|         &self.inner.cache | ||||
|     } | ||||
|  | ||||
|     fn get_self_ref(&self) -> ExternRef<Self> { | ||||
|         self.inner.ptr.clone() | ||||
|     } | ||||
|  | ||||
|     fn _get_ref_by_name(ptr: ExternRef<Self>, name: ExternRef<StringKey>) -> ExternRef<Item> { | ||||
|         unsafe { move_library_get_move(ptr, name) } | ||||
|     } | ||||
|  | ||||
|     fn _get_ref_by_hash(ptr: ExternRef<Self>, hash: u32) -> ExternRef<Item> { | ||||
|         unsafe { move_library_get_move_by_hash(ptr, hash) } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Cacheable for ItemLibrary { | ||||
|     fn get_cache<'a>() -> &'a mut BTreeMap<ExternRef<Self>, Self> | ||||
|     where | ||||
|         Self: Sized, | ||||
|     { | ||||
|         unsafe { &mut CACHE } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static mut CACHE: BTreeMap<ExternRef<ItemLibrary>, ItemLibrary> = BTreeMap::new(); | ||||
|  | ||||
| extern "wasm" { | ||||
|     fn move_library_get_move( | ||||
|         ptr: ExternRef<ItemLibrary>, | ||||
|         name: ExternRef<StringKey>, | ||||
|     ) -> ExternRef<Item>; | ||||
|     fn move_library_get_move_by_hash(ptr: ExternRef<ItemLibrary>, hash: u32) -> ExternRef<Item>; | ||||
| } | ||||
| @@ -0,0 +1,73 @@ | ||||
| use crate::{impl_extern_ctor, ExternRef, ExternalReferenceType, StringKey}; | ||||
| use alloc::collections::BTreeMap; | ||||
| use move_library::MoveLibrary; | ||||
| use spin::rwlock::RwLock; | ||||
|  | ||||
| pub mod item_library; | ||||
| pub mod move_library; | ||||
|  | ||||
| use crate::handling::Cacheable; | ||||
| pub use item_library::*; | ||||
| pub use move_library::*; | ||||
|  | ||||
| pub struct StaticData { | ||||
|     ptr: ExternRef<Self>, | ||||
| } | ||||
|  | ||||
| impl_extern_ctor!(StaticData); | ||||
| impl StaticData { | ||||
|     pub fn move_library(&self) -> MoveLibrary { | ||||
|         unsafe { MoveLibrary::new(static_data_get_move_library(self.ptr)) } | ||||
|     } | ||||
| } | ||||
|  | ||||
| extern "wasm" { | ||||
|     fn static_data_get_move_library(ptr: ExternRef<StaticData>) -> ExternRef<MoveLibrary>; | ||||
| } | ||||
|  | ||||
| pub trait DataLibrary<T>: Cacheable | ||||
| where | ||||
|     T: ExternalReferenceType, | ||||
|     T: Clone, | ||||
| { | ||||
|     fn get_cache(&self) -> &RwLock<BTreeMap<u32, T>>; | ||||
|     fn get_self_ref(&self) -> ExternRef<Self> | ||||
|     where | ||||
|         Self: Sized; | ||||
|     fn _get_ref_by_name(ptr: ExternRef<Self>, name: ExternRef<StringKey>) -> ExternRef<T> | ||||
|     where | ||||
|         Self: Sized; | ||||
|     fn _get_ref_by_hash(ptr: ExternRef<Self>, hash: u32) -> ExternRef<T> | ||||
|     where | ||||
|         Self: Sized; | ||||
|  | ||||
|     fn get(&self, name: &StringKey) -> Option<T> | ||||
|     where | ||||
|         Self: Sized, | ||||
|     { | ||||
|         if let Some(v) = self.get_cache().read().get(&name.hash()) { | ||||
|             return Some(v.clone()); | ||||
|         } | ||||
|  | ||||
|         let v = Self::_get_ref_by_name(self.get_self_ref(), name.ptr()).get_value(); | ||||
|         if let Some(v) = &v { | ||||
|             self.get_cache().write().insert(name.hash(), v.clone()); | ||||
|         } | ||||
|         v | ||||
|     } | ||||
|  | ||||
|     fn get_by_hash(&self, hash: u32) -> Option<T> | ||||
|     where | ||||
|         Self: Sized, | ||||
|     { | ||||
|         if let Some(v) = self.get_cache().read().get(&hash) { | ||||
|             return Some(v.clone()); | ||||
|         } | ||||
|  | ||||
|         let v = Self::_get_ref_by_hash(self.get_self_ref(), hash).get_value(); | ||||
|         if let Some(v) = &v { | ||||
|             self.get_cache().write().insert(hash, v.clone()); | ||||
|         } | ||||
|         v | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,66 @@ | ||||
| use crate::app_interface::data_libraries::DataLibrary; | ||||
| use crate::app_interface::{MoveData, StringKey}; | ||||
| use crate::handling::Cacheable; | ||||
| use crate::ExternRef; | ||||
| use alloc::collections::BTreeMap; | ||||
| use alloc::rc::Rc; | ||||
| use spin::RwLock; | ||||
|  | ||||
| struct MoveLibraryInner { | ||||
|     ptr: ExternRef<MoveLibrary>, | ||||
|     cache: RwLock<BTreeMap<u32, MoveData>>, | ||||
| } | ||||
|  | ||||
| #[derive(Clone)] | ||||
| pub struct MoveLibrary { | ||||
|     inner: Rc<MoveLibraryInner>, | ||||
| } | ||||
|  | ||||
| impl MoveLibrary { | ||||
|     pub(crate) fn new(ptr: ExternRef<Self>) -> Self { | ||||
|         Self { | ||||
|             inner: Rc::new(MoveLibraryInner { | ||||
|                 ptr, | ||||
|                 cache: Default::default(), | ||||
|             }), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl DataLibrary<MoveData> for MoveLibrary { | ||||
|     fn get_cache(&self) -> &spin::rwlock::RwLock<BTreeMap<u32, MoveData>> { | ||||
|         &self.inner.cache | ||||
|     } | ||||
|  | ||||
|     fn get_self_ref(&self) -> ExternRef<Self> { | ||||
|         self.inner.ptr.clone() | ||||
|     } | ||||
|  | ||||
|     fn _get_ref_by_name(ptr: ExternRef<Self>, name: ExternRef<StringKey>) -> ExternRef<MoveData> { | ||||
|         unsafe { move_library_get_move(ptr, name) } | ||||
|     } | ||||
|  | ||||
|     fn _get_ref_by_hash(ptr: ExternRef<Self>, hash: u32) -> ExternRef<MoveData> { | ||||
|         unsafe { move_library_get_move_by_hash(ptr, hash) } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Cacheable for MoveLibrary { | ||||
|     fn get_cache<'a>() -> &'a mut BTreeMap<ExternRef<Self>, Self> | ||||
|     where | ||||
|         Self: Sized, | ||||
|     { | ||||
|         unsafe { &mut CACHE } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static mut CACHE: BTreeMap<ExternRef<MoveLibrary>, MoveLibrary> = BTreeMap::new(); | ||||
|  | ||||
| extern "wasm" { | ||||
|     fn move_library_get_move( | ||||
|         ptr: ExternRef<MoveLibrary>, | ||||
|         name: ExternRef<StringKey>, | ||||
|     ) -> ExternRef<MoveData>; | ||||
|     fn move_library_get_move_by_hash(ptr: ExternRef<MoveLibrary>, hash: u32) | ||||
|         -> ExternRef<MoveData>; | ||||
| } | ||||
| @@ -0,0 +1,68 @@ | ||||
| use crate::app_interface::StringKey; | ||||
| use crate::{ExternRef, ExternalReferenceType}; | ||||
| use core::fmt::{Display, Formatter}; | ||||
|  | ||||
| #[repr(u8)] | ||||
| enum EffectParameterType { | ||||
|     None, | ||||
|     Bool, | ||||
|     Int, | ||||
|     Float, | ||||
|     String, | ||||
| } | ||||
|  | ||||
| #[derive(Clone)] | ||||
| pub enum EffectParameter { | ||||
|     None, | ||||
|     Bool(bool), | ||||
|     Int(i64), | ||||
|     Float(f32), | ||||
|     String(StringKey), | ||||
| } | ||||
|  | ||||
| impl EffectParameter { | ||||
|     pub(crate) fn create(ptr: ExternRef<Self>) -> Self { | ||||
|         unsafe { | ||||
|             match effect_parameter_get_type(ptr) { | ||||
|                 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::String => { | ||||
|                     Self::String(StringKey::new(effect_parameter_as_string(ptr))) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl ExternalReferenceType for EffectParameter { | ||||
|     fn from_extern_value(reference: ExternRef<Self>) -> Self | ||||
|     where | ||||
|         Self: Sized, | ||||
|     { | ||||
|         EffectParameter::create(reference) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Display for EffectParameter { | ||||
|     fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { | ||||
|         match self { | ||||
|             EffectParameter::None => f.write_str("EffectParameter::None"), | ||||
|             EffectParameter::Bool(b) => f.write_fmt(format_args!("EffectParameter::Bool({})", b)), | ||||
|             EffectParameter::Int(i) => f.write_fmt(format_args!("EffectParameter::Int({})", i)), | ||||
|             EffectParameter::Float(r) => f.write_fmt(format_args!("EffectParameter::Float({})", r)), | ||||
|             EffectParameter::String(s) => { | ||||
|                 f.write_fmt(format_args!("EffectParameter::String(\"{}\")", s)) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| extern "wasm" { | ||||
|     fn effect_parameter_get_type(ptr: ExternRef<EffectParameter>) -> EffectParameterType; | ||||
|     fn effect_parameter_as_bool(ptr: ExternRef<EffectParameter>) -> bool; | ||||
|     fn effect_parameter_as_int(ptr: ExternRef<EffectParameter>) -> i64; | ||||
|     fn effect_parameter_as_float(ptr: ExternRef<EffectParameter>) -> f32; | ||||
|     fn effect_parameter_as_string(ptr: ExternRef<EffectParameter>) -> ExternRef<StringKey>; | ||||
| } | ||||
							
								
								
									
										110
									
								
								pkmn_lib_interface/src/app_interface/library/item.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								pkmn_lib_interface/src/app_interface/library/item.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,110 @@ | ||||
| use crate::handling::cached_value::CachedValue; | ||||
| use crate::handling::Cacheable; | ||||
| use crate::{cached_value, ExternRef, ExternalReferenceType, StringKey}; | ||||
| use alloc::rc::Rc; | ||||
|  | ||||
| /// An item category defines which bag slot items are stored in. | ||||
| #[repr(u8)] | ||||
| #[derive(Clone)] | ||||
| pub enum ItemCategory { | ||||
|     /// This is where most items should go. | ||||
|     MiscItem, | ||||
|     /// Pokeballs are used for capturing Pokemons. | ||||
|     Pokeball, | ||||
|     /// Medicine is used for healing HP, PP, and status effects | ||||
|     Medicine, | ||||
|     /// Berry is used for all berries. | ||||
|     Berry, | ||||
|     /// TMHM is used for Technical and Hidden Machines. | ||||
|     TMHM, | ||||
|     /// Form Changer is used for items that change forms, such as mega stones. | ||||
|     FormChanger, | ||||
|     /// Key Items are single stored items, generally used for story progression. | ||||
|     KeyItem, | ||||
|     /// Mail is used for mail items. | ||||
|     Mail, | ||||
| } | ||||
|  | ||||
| /// A battle item category defines how the item is categorized when in battle. | ||||
| #[repr(u8)] | ||||
| #[derive(Clone)] | ||||
| pub enum BattleItemCategory { | ||||
|     /// This item can't be used in battle. | ||||
|     None, | ||||
|     /// This item is used for healing Pokemon. | ||||
|     Healing, | ||||
|     /// This item is used for healing Pokemon from a status. | ||||
|     StatusHealing, | ||||
|     /// This item is used for capturing Pokemon. | ||||
|     Pokeball, | ||||
|     /// This item does not belong in above categories, but is still a battle item. | ||||
|     MiscBattleItem, | ||||
| } | ||||
|  | ||||
| struct ItemInner { | ||||
|     ptr: ExternRef<Item>, | ||||
|     name: CachedValue<StringKey>, | ||||
|     category: CachedValue<ItemCategory>, | ||||
|     battle_category: CachedValue<BattleItemCategory>, | ||||
|     price: CachedValue<i32>, | ||||
| } | ||||
|  | ||||
| /// An item is an object which the player can pick up, keep in their Bag, and use in some manner | ||||
| #[derive(Clone)] | ||||
| pub struct Item { | ||||
|     inner: Rc<ItemInner>, | ||||
| } | ||||
|  | ||||
| impl Item { | ||||
|     pub(crate) fn new(ptr: ExternRef<Self>) -> Self { | ||||
|         Self::from_ref(ptr, &|ptr| Self { | ||||
|             inner: Rc::new(ItemInner { | ||||
|                 ptr, | ||||
|                 name: cached_value!({ StringKey::new(item_get_name(ptr)) }), | ||||
|                 category: cached_value!({ item_get_category(ptr) }), | ||||
|                 battle_category: cached_value!({ item_get_battle_category(ptr) }), | ||||
|                 price: cached_value!({ item_get_price(ptr) }), | ||||
|             }), | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     pub(crate) fn ptr(&self) -> ExternRef<Self> { | ||||
|         self.inner.ptr | ||||
|     } | ||||
|  | ||||
|     /// The name of the item. | ||||
|     pub fn name(&self) -> StringKey { | ||||
|         self.inner.name.value() | ||||
|     } | ||||
|     /// Which bag slot items are stored in. | ||||
|     pub fn category(&self) -> ItemCategory { | ||||
|         self.inner.category.value() | ||||
|     } | ||||
|     /// How the item is categorized when in battle. | ||||
|     pub fn battle_category(&self) -> BattleItemCategory { | ||||
|         self.inner.battle_category.value() | ||||
|     } | ||||
|     /// The buying value of the item. | ||||
|     pub fn price(&self) -> i32 { | ||||
|         self.inner.price.value() | ||||
|     } | ||||
|     pub fn has_flag(&self, flag: &StringKey) -> bool { | ||||
|         unsafe { item_has_flag(self.ptr(), flag.ptr()) } | ||||
|     } | ||||
| } | ||||
|  | ||||
| crate::handling::cacheable::cacheable!(Item); | ||||
|  | ||||
| impl ExternalReferenceType for Item { | ||||
|     fn from_extern_value(reference: ExternRef<Self>) -> Self { | ||||
|         Item::new(reference) | ||||
|     } | ||||
| } | ||||
|  | ||||
| extern "wasm" { | ||||
|     fn item_get_name(ptr: ExternRef<Item>) -> ExternRef<StringKey>; | ||||
|     fn item_get_category(ptr: ExternRef<Item>) -> ItemCategory; | ||||
|     fn item_get_battle_category(ptr: ExternRef<Item>) -> BattleItemCategory; | ||||
|     fn item_get_price(ptr: ExternRef<Item>) -> i32; | ||||
|     fn item_has_flag(ptr: ExternRef<Item>, flag: ExternRef<StringKey>) -> bool; | ||||
| } | ||||
							
								
								
									
										11
									
								
								pkmn_lib_interface/src/app_interface/library/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								pkmn_lib_interface/src/app_interface/library/mod.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| pub mod data_libraries; | ||||
| pub mod effect_parameter; | ||||
| pub mod item; | ||||
| pub mod move_data; | ||||
| pub mod species; | ||||
|  | ||||
| pub use data_libraries::*; | ||||
| pub use effect_parameter::EffectParameter; | ||||
| pub use item::*; | ||||
| pub use move_data::*; | ||||
| pub use species::*; | ||||
							
								
								
									
										120
									
								
								pkmn_lib_interface/src/app_interface/library/move_data.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								pkmn_lib_interface/src/app_interface/library/move_data.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,120 @@ | ||||
| use crate::app_interface::StringKey; | ||||
| use crate::handling::cached_value::CachedValue; | ||||
| use crate::handling::Cacheable; | ||||
| use crate::{cached_value, ExternRef, ExternalReferenceType}; | ||||
| use alloc::collections::BTreeMap; | ||||
| use alloc::rc::Rc; | ||||
|  | ||||
| #[repr(u8)] | ||||
| #[derive(Clone)] | ||||
| pub enum MoveCategory { | ||||
|     Physical = 0, | ||||
|     Special = 1, | ||||
|     Status = 2, | ||||
| } | ||||
|  | ||||
| #[repr(u8)] | ||||
| #[derive(Clone)] | ||||
| pub enum MoveTarget { | ||||
|     Adjacent, | ||||
|     AdjacentAlly, | ||||
|     AdjacentAllySelf, | ||||
|     AdjacentOpponent, | ||||
|  | ||||
|     All, | ||||
|     AllAdjacent, | ||||
|     AllAdjacentOpponent, | ||||
|     AllAlly, | ||||
|     AllOpponent, | ||||
|  | ||||
|     Any, | ||||
|  | ||||
|     RandomOpponent, | ||||
|     OnSelf, | ||||
| } | ||||
|  | ||||
| struct MoveDataInner { | ||||
|     ptr: ExternRef<MoveData>, | ||||
|     name: CachedValue<StringKey>, | ||||
|     move_type: CachedValue<u8>, | ||||
|     category: CachedValue<MoveCategory>, | ||||
|     base_power: CachedValue<u8>, | ||||
|     accuracy: CachedValue<u8>, | ||||
|     base_usages: CachedValue<u8>, | ||||
|     target: CachedValue<MoveTarget>, | ||||
|     priority: CachedValue<i8>, | ||||
| } | ||||
|  | ||||
| #[derive(Clone)] | ||||
| pub struct MoveData { | ||||
|     inner: Rc<MoveDataInner>, | ||||
| } | ||||
|  | ||||
| impl MoveData { | ||||
|     pub(crate) fn new(ptr: ExternRef<Self>) -> Self { | ||||
|         MoveData::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) }), | ||||
|             }), | ||||
|         }) | ||||
|     } | ||||
|     pub(crate) fn ptr(&self) -> ExternRef<Self> { | ||||
|         self.inner.ptr | ||||
|     } | ||||
|  | ||||
|     pub fn name(&self) -> StringKey { | ||||
|         self.inner.name.value() | ||||
|     } | ||||
|     pub fn move_type(&self) -> u8 { | ||||
|         self.inner.move_type.value() | ||||
|     } | ||||
|     pub fn category(&self) -> MoveCategory { | ||||
|         self.inner.category.value() | ||||
|     } | ||||
|     pub fn base_power(&self) -> u8 { | ||||
|         self.inner.base_power.value() | ||||
|     } | ||||
|     pub fn accuracy(&self) -> u8 { | ||||
|         self.inner.accuracy.value() | ||||
|     } | ||||
|     pub fn base_usages(&self) -> u8 { | ||||
|         self.inner.base_usages.value() | ||||
|     } | ||||
|     pub fn target(&self) -> MoveTarget { | ||||
|         self.inner.target.value() | ||||
|     } | ||||
|     pub fn priority(&self) -> i8 { | ||||
|         self.inner.priority.value() | ||||
|     } | ||||
|     pub fn has_flag(&self, flag: &StringKey) -> bool { | ||||
|         unsafe { move_data_has_flag(self.ptr(), flag.ptr()) } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl ExternalReferenceType for MoveData { | ||||
|     fn from_extern_value(reference: ExternRef<Self>) -> Self { | ||||
|         MoveData::new(reference) | ||||
|     } | ||||
| } | ||||
|  | ||||
| crate::handling::cacheable::cacheable!(MoveData); | ||||
|  | ||||
| extern "wasm" { | ||||
|     fn move_data_get_name(ptr: ExternRef<MoveData>) -> ExternRef<StringKey>; | ||||
|     fn move_data_get_type(ptr: ExternRef<MoveData>) -> u8; | ||||
|     fn move_data_get_category(ptr: ExternRef<MoveData>) -> MoveCategory; | ||||
|     fn move_data_get_base_power(ptr: ExternRef<MoveData>) -> u8; | ||||
|     fn move_data_get_accuracy(ptr: ExternRef<MoveData>) -> u8; | ||||
|     fn move_data_get_base_usages(ptr: ExternRef<MoveData>) -> u8; | ||||
|     fn move_data_get_target(ptr: ExternRef<MoveData>) -> MoveTarget; | ||||
|     fn move_data_get_priority(ptr: ExternRef<MoveData>) -> i8; | ||||
|     fn move_data_has_flag(ptr: ExternRef<MoveData>, flag: ExternRef<StringKey>) -> bool; | ||||
| } | ||||
							
								
								
									
										149
									
								
								pkmn_lib_interface/src/app_interface/library/species.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								pkmn_lib_interface/src/app_interface/library/species.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,149 @@ | ||||
| use crate::handling::cached_value::CachedValue; | ||||
| use crate::handling::Cacheable; | ||||
| use crate::{ | ||||
|     cached_value, ExternRef, ExternalReferenceType, FFIArray, ImmutableList, StringKey, | ||||
|     VecExternRef, | ||||
| }; | ||||
| use alloc::rc::Rc; | ||||
| use alloc::vec::Vec; | ||||
|  | ||||
| #[repr(u8)] | ||||
| pub enum Gender { | ||||
|     Male = 0, | ||||
|     Female = 1, | ||||
|     Genderless = 2, | ||||
| } | ||||
|  | ||||
| #[repr(u8)] | ||||
| pub enum Statistic { | ||||
|     HP = 0, | ||||
|     Attack = 1, | ||||
|     Defense = 2, | ||||
|     SpecialAttack = 3, | ||||
|     SpecialDefense = 4, | ||||
|     Speed = 5, | ||||
| } | ||||
|  | ||||
| pub struct ImmutableStatisticSetInner { | ||||
|     ptr: ExternRef<ImmutableStatisticSet>, | ||||
|     /// The health point stat value. | ||||
|     hp: CachedValue<u16>, | ||||
|     /// The physical attack stat value. | ||||
|     attack: CachedValue<u16>, | ||||
|     /// The physical defense stat value. | ||||
|     defense: CachedValue<u16>, | ||||
|     /// The special attack stat value. | ||||
|     special_attack: CachedValue<u16>, | ||||
|     /// The special defense stat value. | ||||
|     special_defense: CachedValue<u16>, | ||||
|     /// The speed stat value. | ||||
|     speed: CachedValue<u16>, | ||||
| } | ||||
|  | ||||
| #[derive(Clone)] | ||||
| pub struct ImmutableStatisticSet { | ||||
|     inner: Rc<ImmutableStatisticSetInner>, | ||||
| } | ||||
|  | ||||
| impl ImmutableStatisticSet { | ||||
|     pub(crate) fn new(ptr: ExternRef<Self>) -> Self { | ||||
|         Self::from_ref(ptr, &|ptr| Self { | ||||
|             inner: Rc::new(ImmutableStatisticSetInner { | ||||
|                 ptr, | ||||
|                 hp: cached_value!({ static_statistics_set_get_hp(ptr) }), | ||||
|                 attack: cached_value!({ static_statistics_set_get_attack(ptr) }), | ||||
|                 defense: cached_value!({ static_statistics_set_get_defense(ptr) }), | ||||
|                 special_attack: cached_value!({ static_statistics_set_get_special_attack(ptr) }), | ||||
|                 special_defense: cached_value!({ static_statistics_set_get_special_defense(ptr) }), | ||||
|                 speed: cached_value!({ static_statistics_set_get_speed(ptr) }), | ||||
|             }), | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     pub fn hp(&self) -> u16 { | ||||
|         self.inner.hp.value() | ||||
|     } | ||||
|     pub fn attack(&self) -> u16 { | ||||
|         self.inner.attack.value() | ||||
|     } | ||||
|     pub fn defense(&self) -> u16 { | ||||
|         self.inner.defense.value() | ||||
|     } | ||||
|     pub fn special_attack(&self) -> u16 { | ||||
|         self.inner.special_attack.value() | ||||
|     } | ||||
|     pub fn special_defense(&self) -> u16 { | ||||
|         self.inner.special_defense.value() | ||||
|     } | ||||
|     pub fn speed(&self) -> u16 { | ||||
|         self.inner.speed.value() | ||||
|     } | ||||
| } | ||||
|  | ||||
| struct FormInner { | ||||
|     ptr: ExternRef<Form>, | ||||
|     name: CachedValue<StringKey>, | ||||
|     height: CachedValue<f32>, | ||||
|     weight: CachedValue<f32>, | ||||
|     types: CachedValue<Vec<u8>>, | ||||
|     base_experience: CachedValue<u32>, | ||||
|     base_stats: CachedValue<ImmutableStatisticSet>, | ||||
|     abilities: CachedValue<ImmutableList<StringKey>>, | ||||
|     hidden_abilities: CachedValue<ImmutableList<StringKey>>, | ||||
|     // moves: CachedValue<LearnableMoves>, | ||||
| } | ||||
|  | ||||
| #[derive(Clone)] | ||||
| pub struct Form { | ||||
|     inner: Rc<FormInner>, | ||||
| } | ||||
|  | ||||
| impl Form { | ||||
|     pub(crate) fn new(ptr: ExternRef<Self>) -> Self { | ||||
|         Self::from_ref(ptr, &|ptr| Self { | ||||
|             inner: Rc::new(FormInner { | ||||
|                 ptr, | ||||
|                 name: cached_value!({ form_get_name(ptr).get_value().unwrap() }), | ||||
|                 height: cached_value!({ form_get_height(ptr) }), | ||||
|                 weight: cached_value!({ form_get_weight(ptr) }), | ||||
|                 types: cached_value!({ | ||||
|                     let raw = form_get_types(ptr); | ||||
|                     Vec::from_raw_parts(raw.ptr(), raw.len(), raw.len()) | ||||
|                 }), | ||||
|                 base_experience: cached_value!({ form_get_base_experience(ptr) }), | ||||
|                 base_stats: cached_value!({ form_get_base_stats(ptr).get_value().unwrap() }), | ||||
|                 abilities: cached_value!({ form_get_abilities(ptr).get_immutable_list() }), | ||||
|                 hidden_abilities: cached_value!({ | ||||
|                     form_get_hidden_abilities(ptr).get_immutable_list() | ||||
|                 }), | ||||
|             }), | ||||
|         }) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl ExternalReferenceType for ImmutableStatisticSet { | ||||
|     fn from_extern_value(reference: ExternRef<Self>) -> Self { | ||||
|         ImmutableStatisticSet::new(reference) | ||||
|     } | ||||
| } | ||||
|  | ||||
| crate::handling::cacheable::cacheable!(ImmutableStatisticSet); | ||||
| crate::handling::cacheable::cacheable!(Form); | ||||
|  | ||||
| extern "wasm" { | ||||
|     fn static_statistics_set_get_hp(r: ExternRef<ImmutableStatisticSet>) -> u16; | ||||
|     fn static_statistics_set_get_attack(r: ExternRef<ImmutableStatisticSet>) -> u16; | ||||
|     fn static_statistics_set_get_defense(r: ExternRef<ImmutableStatisticSet>) -> u16; | ||||
|     fn static_statistics_set_get_special_attack(r: ExternRef<ImmutableStatisticSet>) -> u16; | ||||
|     fn static_statistics_set_get_special_defense(r: ExternRef<ImmutableStatisticSet>) -> u16; | ||||
|     fn static_statistics_set_get_speed(r: ExternRef<ImmutableStatisticSet>) -> u16; | ||||
|  | ||||
|     fn form_get_name(r: ExternRef<Form>) -> ExternRef<StringKey>; | ||||
|     fn form_get_height(r: ExternRef<Form>) -> f32; | ||||
|     fn form_get_weight(r: ExternRef<Form>) -> f32; | ||||
|     fn form_get_types(r: ExternRef<Form>) -> FFIArray<u8>; | ||||
|     fn form_get_base_experience(r: ExternRef<Form>) -> u32; | ||||
|     fn form_get_base_stats(r: ExternRef<Form>) -> ExternRef<ImmutableStatisticSet>; | ||||
|     fn form_get_abilities(r: ExternRef<Form>) -> VecExternRef<StringKey>; | ||||
|     fn form_get_hidden_abilities(r: ExternRef<Form>) -> VecExternRef<StringKey>; | ||||
| } | ||||
							
								
								
									
										74
									
								
								pkmn_lib_interface/src/app_interface/list.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								pkmn_lib_interface/src/app_interface/list.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | ||||
| use crate::{ExternalReferenceType, VecExternRef}; | ||||
| use alloc::boxed::Box; | ||||
| use alloc::collections::BTreeMap; | ||||
| use alloc::vec::Vec; | ||||
| use core::marker::PhantomData; | ||||
|  | ||||
| struct ImmutableListInner<T: Clone> { | ||||
|     extern_ref: VecExternRef<T>, | ||||
|     resource_type: PhantomData<T>, | ||||
|     values: spin::RwLock<Vec<Option<Option<T>>>>, | ||||
| } | ||||
|  | ||||
| #[derive(Clone)] | ||||
| pub struct ImmutableList<T> | ||||
| where | ||||
|     T: Clone, | ||||
|     T: ExternalReferenceType, | ||||
| { | ||||
|     inner: *const ImmutableListInner<T>, | ||||
| } | ||||
|  | ||||
| impl<T> ImmutableList<T> | ||||
| where | ||||
|     T: Clone, | ||||
|     T: ExternalReferenceType, | ||||
| { | ||||
|     fn new(extern_ref: VecExternRef<T>) -> Self { | ||||
|         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); | ||||
|         ImmutableList { | ||||
|             inner: inner_ptr as *const ImmutableListInner<T>, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub(crate) fn from_ref(extern_ref: VecExternRef<T>) -> Self { | ||||
|         unsafe { | ||||
|             let existing = CACHE.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); | ||||
|                 v | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn get(&self, index: u32) -> Option<T> { | ||||
|         unsafe { | ||||
|             let inner = self.inner.as_ref().unwrap(); | ||||
|             { | ||||
|                 let rg = inner.values.read(); | ||||
|                 let v = rg.get(index as usize).unwrap(); | ||||
|                 if let Some(v) = v { | ||||
|                     return v.clone(); | ||||
|                 } | ||||
|             } | ||||
|             let r = inner.extern_ref.at(index); | ||||
|             let value = r.get_value(); | ||||
|             let mut wg = inner.values.write(); | ||||
|             wg[index as usize] = Some(value); | ||||
|             wg[index as usize].as_ref().unwrap().clone() | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static mut CACHE: BTreeMap<u32, *const u8> = BTreeMap::new(); | ||||
							
								
								
									
										9
									
								
								pkmn_lib_interface/src/app_interface/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								pkmn_lib_interface/src/app_interface/mod.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| pub mod battling; | ||||
| pub mod library; | ||||
| pub mod list; | ||||
| pub mod string_key; | ||||
|  | ||||
| pub use battling::*; | ||||
| pub use library::*; | ||||
| pub use string_key::get_hash; | ||||
| pub use string_key::StringKey; | ||||
							
								
								
									
										129
									
								
								pkmn_lib_interface/src/app_interface/string_key.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								pkmn_lib_interface/src/app_interface/string_key.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | ||||
| use crate::handling::Cacheable; | ||||
| use crate::{ExternRef, ExternalReferenceType}; | ||||
| use alloc::rc::Rc; | ||||
| use core::cell::RefCell; | ||||
| use core::fmt::{Display, Formatter}; | ||||
| use cstr_core::{c_char, CString}; | ||||
|  | ||||
| struct StringKeyInner { | ||||
|     ptr: ExternRef<StringKey>, | ||||
|     str: RefCell<Option<CString>>, | ||||
|     hash: RefCell<Option<u32>>, | ||||
| } | ||||
|  | ||||
| #[derive(Clone)] | ||||
| pub struct StringKey { | ||||
|     data: Rc<StringKeyInner>, | ||||
| } | ||||
|  | ||||
| impl StringKey { | ||||
|     pub(crate) fn new(ptr: ExternRef<Self>) -> Self { | ||||
|         StringKey::from_ref(ptr, &|ptr| -> StringKey { | ||||
|             StringKey { | ||||
|                 data: Rc::new(StringKeyInner { | ||||
|                     ptr, | ||||
|                     str: RefCell::new(None), | ||||
|                     hash: RefCell::new(None), | ||||
|                 }), | ||||
|             } | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     pub(super) fn ptr(&self) -> ExternRef<Self> { | ||||
|         self.data.ptr | ||||
|     } | ||||
|  | ||||
|     pub fn str(&self) -> &CString { | ||||
|         if self.data.str.borrow().is_none() { | ||||
|             unsafe { | ||||
|                 self.data | ||||
|                     .str | ||||
|                     .replace(Some(CString::from_raw(string_key_get_str(self.ptr())))); | ||||
|             } | ||||
|         } | ||||
|         unsafe { (*self.data.str.as_ptr()).as_ref().unwrap() } | ||||
|     } | ||||
|     pub fn hash(&self) -> u32 { | ||||
|         if self.data.hash.borrow().is_none() { | ||||
|             unsafe { | ||||
|                 self.data | ||||
|                     .hash | ||||
|                     .replace(Some(string_key_get_hash(self.ptr()))); | ||||
|             } | ||||
|         } | ||||
|         self.data.hash.borrow().unwrap() | ||||
|     } | ||||
| } | ||||
|  | ||||
| crate::handling::cacheable::cacheable!(StringKey); | ||||
|  | ||||
| impl ExternalReferenceType for StringKey { | ||||
|     fn from_extern_value(reference: ExternRef<Self>) -> Self { | ||||
|         StringKey::new(reference) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Display for StringKey { | ||||
|     fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { | ||||
|         let s = self.str(); | ||||
|         f.write_str(s.to_str().as_ref().unwrap()) | ||||
|     } | ||||
| } | ||||
|  | ||||
| extern "wasm" { | ||||
|     fn string_key_get_str(ptr: ExternRef<StringKey>) -> *mut c_char; | ||||
|     fn string_key_get_hash(ptr: ExternRef<StringKey>) -> u32; | ||||
| } | ||||
|  | ||||
| const CRC_TABLE: &[u32] = &[ | ||||
|     0, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, | ||||
|     0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, | ||||
|     0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, | ||||
|     0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, | ||||
|     0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, | ||||
|     0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, | ||||
|     0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, | ||||
|     0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, | ||||
|     0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, | ||||
|     0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, | ||||
|     0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, | ||||
|     0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, | ||||
|     0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, | ||||
|     0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, | ||||
|     0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, | ||||
|     0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, | ||||
|     0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, | ||||
|     0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, | ||||
|     0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, | ||||
|     0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, | ||||
|     0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, | ||||
|     0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, | ||||
|     0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, | ||||
|     0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, | ||||
|     0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, | ||||
|     0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, | ||||
|     0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, | ||||
|     0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, | ||||
|     0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, | ||||
|     0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, | ||||
|     0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, | ||||
|     0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D, | ||||
| ]; | ||||
|  | ||||
| const fn to_lower(c: u8) -> u8 { | ||||
|     if c >= b'A' && c <= b'Z' { | ||||
|         return c + (b'a' - b'A'); | ||||
|     } | ||||
|     c | ||||
| } | ||||
|  | ||||
| pub const fn get_hash<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 | ||||
| } | ||||
		Reference in New Issue
	
	Block a user