diff --git a/Cargo.toml b/Cargo.toml index fbedaf9..d6b459c 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ path = "src/lib.rs" [features] ffi = [] serde = ["dep:serde"] -wasm = ["dep:wasmer", "dep:unique-type-id", "dep:unique-type-id-derive"] +wasm = ["dep:wasmer"] default = ["serde", "wasm", "ffi"] [profile.dev] @@ -53,8 +53,7 @@ indexmap = "1.8.2" parking_lot = "0.12.1" serde = { version = "1.0.137", optional = true, features = ["derive"] } wasmer = { version = "3.0.0-beta", optional = true, default-features = true } -unique-type-id = { version = "1.0.0", optional = true } -unique-type-id-derive = { version = "1.0.0", optional = true } +uuid = "1.2.2" paste = { version = "1.0.8" } arcstr = { version = "1.1.4", features = ["std"] } enum-display-derive = "0.1.1" diff --git a/src/dynamic_data/choices.rs b/src/dynamic_data/choices.rs index bf63f9b..ec70603 100755 --- a/src/dynamic_data/choices.rs +++ b/src/dynamic_data/choices.rs @@ -32,7 +32,6 @@ struct CommonChoiceData { /// This enum defines a single choice for a Pokemon for a battle turn. #[derive(Debug)] -#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] pub enum TurnChoice { /// A move choice tells a Pokemon to use a move on a target for this turn. Move(MoveChoice), diff --git a/src/dynamic_data/flow/choice_queue.rs b/src/dynamic_data/flow/choice_queue.rs index 7a3cb94..7908d1f 100755 --- a/src/dynamic_data/flow/choice_queue.rs +++ b/src/dynamic_data/flow/choice_queue.rs @@ -1,7 +1,7 @@ use crate::dynamic_data::choices::TurnChoice; use crate::dynamic_data::script_handling::ScriptSource; use crate::dynamic_data::Pokemon; -use crate::{script_hook, ValueIdentifiable}; +use crate::{script_hook, ValueIdentifiable, ValueIdentifier}; use parking_lot::lock_api::MappedRwLockReadGuard; use parking_lot::{RawRwLock, RwLock, RwLockReadGuard}; @@ -12,8 +12,10 @@ use parking_lot::{RawRwLock, RwLock, RwLockReadGuard}; /// helper functions to change the turn order while doing the execution. This is needed, as several /// moves in Pokemon actively mess with this order. #[derive(Debug)] -#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] + pub struct ChoiceQueue { + /// A unique identifier so we know what value this is. + identifier: ValueIdentifier, /// Our storage of turn choices. Starts out completely filled, then slowly empties as turns get /// executed. queue: RwLock>>, @@ -26,6 +28,7 @@ impl ChoiceQueue { pub(crate) fn new(mut queue: Vec>) -> Self { queue.sort_unstable_by(|a, b| b.cmp(a)); Self { + identifier: Default::default(), queue: RwLock::new(queue), current: 0, } @@ -119,6 +122,12 @@ impl ChoiceQueue { } } +impl ValueIdentifiable for ChoiceQueue { + fn value_identifier(&self) -> ValueIdentifier { + self.identifier + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/dynamic_data/libraries/dynamic_library.rs b/src/dynamic_data/libraries/dynamic_library.rs index 2b6b18e..fa710bb 100755 --- a/src/dynamic_data/libraries/dynamic_library.rs +++ b/src/dynamic_data/libraries/dynamic_library.rs @@ -14,7 +14,6 @@ use crate::{PkmnResult, StringKey, ValueIdentifiable, ValueIdentifier}; /// The dynamic library stores a static data library, as well as holding different libraries and /// calculators that might be customized between different generations and implementations. #[derive(Debug)] -#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] pub struct DynamicLibrary { /// A unique identifier so we know what value this is. identifier: ValueIdentifier, @@ -87,7 +86,7 @@ impl DynamicLibrary { /// Loads an item script with the given unique key. If no script can be created with this /// combinations, returns None. Note that ItemScripts are immutable, as their script should be /// shared between all different usages. - pub fn load_item_script(&self, _key: &Arc) -> PkmnResult>> { + pub fn load_item_script(&self, _key: &Arc) -> PkmnResult>> { todo!() } } diff --git a/src/dynamic_data/libraries/script_resolver.rs b/src/dynamic_data/libraries/script_resolver.rs index 141ddd9..8e19970 100755 --- a/src/dynamic_data/libraries/script_resolver.rs +++ b/src/dynamic_data/libraries/script_resolver.rs @@ -21,7 +21,7 @@ pub trait ScriptResolver: Debug + ValueIdentifiable { /// Loads an item script with the given unique key. If no script can be created with this /// combinations, returns None. Note that ItemScripts are immutable, as their script should be /// shared between all different usages. - fn load_item_script(&self, _key: &Item) -> PkmnResult>>; + fn load_item_script(&self, _key: &dyn Item) -> PkmnResult>>; } use std::fmt::Display; @@ -77,7 +77,7 @@ impl ScriptResolver for EmptyScriptResolver { Ok(None) } - fn load_item_script(&self, _key: &Item) -> PkmnResult>> { + fn load_item_script(&self, _key: &dyn Item) -> PkmnResult>> { Ok(None) } } diff --git a/src/dynamic_data/models/battle.rs b/src/dynamic_data/models/battle.rs index 7693b2c..d60247a 100755 --- a/src/dynamic_data/models/battle.rs +++ b/src/dynamic_data/models/battle.rs @@ -22,7 +22,6 @@ use crate::{script_hook, PkmnResult, StringKey, ValueIdentifiable, ValueIdentifi /// A pokemon battle, with any amount of sides and pokemon per side. #[derive(Debug)] -#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] pub struct Battle { /// A unique identifier so we know what value this is. identifier: ValueIdentifier, diff --git a/src/dynamic_data/models/battle_party.rs b/src/dynamic_data/models/battle_party.rs index 2fcd692..3fb612f 100755 --- a/src/dynamic_data/models/battle_party.rs +++ b/src/dynamic_data/models/battle_party.rs @@ -7,7 +7,6 @@ use crate::{ValueIdentifiable, ValueIdentifier}; /// A battle party is a wrapper around a party, with the indices for which the party is responsible /// on the field attached. #[derive(Debug)] -#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] pub struct BattleParty { /// A unique identifier so we know what value this is. identifier: ValueIdentifier, diff --git a/src/dynamic_data/models/battle_random.rs b/src/dynamic_data/models/battle_random.rs index 1ccbcb5..24c3690 100755 --- a/src/dynamic_data/models/battle_random.rs +++ b/src/dynamic_data/models/battle_random.rs @@ -9,7 +9,6 @@ use crate::{script_hook, ValueIdentifiable, ValueIdentifier}; /// The RNG for a battle. #[derive(Default)] -#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] pub struct BattleRandom { /// A unique identifier so we know what value this is. identifier: ValueIdentifier, diff --git a/src/dynamic_data/models/battle_side.rs b/src/dynamic_data/models/battle_side.rs index cb3aaae..fb44b52 100755 --- a/src/dynamic_data/models/battle_side.rs +++ b/src/dynamic_data/models/battle_side.rs @@ -18,7 +18,6 @@ use crate::{script_hook, PkmnResult, StringKey, ValueIdentifiable, ValueIdentifi /// A side on a battle. #[derive(Debug)] -#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] pub struct BattleSide { /// A unique identifier so we know what value this is. identifier: ValueIdentifier, diff --git a/src/dynamic_data/models/executing_move.rs b/src/dynamic_data/models/executing_move.rs index 16ddcc4..ea0d9aa 100755 --- a/src/dynamic_data/models/executing_move.rs +++ b/src/dynamic_data/models/executing_move.rs @@ -11,12 +11,14 @@ use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, Scrip use crate::dynamic_data::ScriptContainer; use crate::dynamic_data::TargetList; use crate::static_data::{MoveData, TypeIdentifier}; -use crate::{PkmnResult, PokemonError}; +use crate::{PkmnResult, PokemonError, ValueIdentifiable, ValueIdentifier}; /// A hit data is the data for a single hit, on a single target. #[derive(Default, Debug)] -#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] + pub struct HitData { + /// A unique identifier so we know what value this is. + identifier: ValueIdentifier, /// Whether or not the hit is critical. critical: AtomicBool, /// The base power of the hit. @@ -85,8 +87,10 @@ impl HitData { /// An executing move is the data of the move for while it is executing. #[derive(Debug)] -#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] + pub struct ExecutingMove { + /// A unique identifier so we know what value this is. + identifier: ValueIdentifier, /// The number of hits this move has. number_of_hits: u8, /// A list of hits for this move. For multi target multi hit moves, this stores the hits linearly, @@ -122,6 +126,7 @@ impl ExecutingMove { hits.push(HitData::default()) } Self { + identifier: Default::default(), number_of_hits, hits, user, @@ -218,3 +223,15 @@ impl ScriptSource for ExecutingMove { self.user.get_own_scripts(scripts); } } + +impl ValueIdentifiable for ExecutingMove { + fn value_identifier(&self) -> ValueIdentifier { + self.identifier + } +} + +impl ValueIdentifiable for HitData { + fn value_identifier(&self) -> ValueIdentifier { + self.identifier + } +} diff --git a/src/dynamic_data/models/learned_move.rs b/src/dynamic_data/models/learned_move.rs index ea10441..84f95ee 100755 --- a/src/dynamic_data/models/learned_move.rs +++ b/src/dynamic_data/models/learned_move.rs @@ -7,7 +7,6 @@ use crate::{ValueIdentifiable, ValueIdentifier}; /// A learned move is the data attached to a Pokemon for a move it has learned. It has information /// such as the remaining amount of users, how it has been learned, etc. #[derive(Debug)] -#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] pub struct LearnedMove { /// A unique identifier so we know what value this is. identifier: ValueIdentifier, diff --git a/src/dynamic_data/models/pokemon.rs b/src/dynamic_data/models/pokemon.rs index 246057b..7137d57 100755 --- a/src/dynamic_data/models/pokemon.rs +++ b/src/dynamic_data/models/pokemon.rs @@ -26,7 +26,6 @@ use crate::{script_hook, PkmnResult, StringKey, ValueIdentifiable, ValueIdentifi /// An individual Pokemon as we know and love them. #[derive(Debug)] -#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] pub struct Pokemon { /// A unique identifier so we know what value this is. identifier: ValueIdentifier, @@ -57,7 +56,7 @@ pub struct Pokemon { /// currently not used, and can be used for other implementations. coloring: u8, /// The held item of the Pokemon. - held_item: RwLock>>, + held_item: RwLock>>, /// The remaining health points of the Pokemon. current_health: AtomicU32, @@ -238,7 +237,7 @@ impl Pokemon { self.coloring } /// Gets the held item of a Pokemon - pub fn held_item(&self) -> &RwLock>> { + pub fn held_item(&self) -> &RwLock>> { &self.held_item } /// Checks whether the Pokemon is holding a specific item. @@ -250,11 +249,11 @@ impl Pokemon { false } /// Changes the held item of the Pokemon. Returns the previously held item. - pub fn set_held_item(&self, item: &Arc) -> Option> { + pub fn set_held_item(&self, item: &Arc) -> Option> { self.held_item.write().replace(item.clone()) } /// Removes the held item from the Pokemon. Returns the previously held item. - pub fn remove_held_item(&self) -> Option> { + pub fn remove_held_item(&self) -> Option> { self.held_item.write().take() } /// Makes the Pokemon uses its held item. @@ -524,7 +523,7 @@ impl Pokemon { .set(ability_script) .as_ref() // Ensure the ability script gets initialized with the parameters for the ability. - .on_initialize(self.library.as_ref(), self.active_ability().parameters()) + .on_initialize(self.library.as_ref(), self.active_ability().parameters().to_vec()) } else { self.ability_script.clear(); } diff --git a/src/dynamic_data/models/pokemon_party.rs b/src/dynamic_data/models/pokemon_party.rs index 332ac55..30accf4 100755 --- a/src/dynamic_data/models/pokemon_party.rs +++ b/src/dynamic_data/models/pokemon_party.rs @@ -7,7 +7,6 @@ use crate::{ValueIdentifiable, ValueIdentifier}; /// A list of Pokemon belonging to a trainer. #[derive(Debug)] -#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] pub struct PokemonParty { /// A unique identifier so we know what value this is. identifier: ValueIdentifier, diff --git a/src/dynamic_data/script_handling/script.rs b/src/dynamic_data/script_handling/script.rs index d981e1e..9fd2647 100755 --- a/src/dynamic_data/script_handling/script.rs +++ b/src/dynamic_data/script_handling/script.rs @@ -64,7 +64,7 @@ pub trait Script: Send + Sync { /// This function is ran when this script stops being in effect, and is removed from its owner. fn on_remove(&self) {} /// This function is ran when this script starts being in effect. - fn on_initialize(&self, _library: &DynamicLibrary, _pars: &[EffectParameter]) {} + fn on_initialize(&self, _library: &DynamicLibrary, _pars: Vec) {} /// 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. @@ -240,7 +240,7 @@ pub trait Script: Send + Sync { fn on_switch_in(&self, _pokemon: &Pokemon) {} /// 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: &dyn Item) {} /// 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(&self, _fainted_mon: &Pokemon, _winning_mon: &Pokemon, _amount: &mut u32) {} @@ -253,7 +253,7 @@ pub trait Script: Send + Sync { /// 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: &dyn Item, _modifier: &mut u8) {} /// Helper function to turn the self into an Any for downcasting. fn as_any(&self) -> &dyn Any; diff --git a/src/ffi/dynamic_data/models/pokemon.rs b/src/ffi/dynamic_data/models/pokemon.rs index e6fb2c9..6126e08 100644 --- a/src/ffi/dynamic_data/models/pokemon.rs +++ b/src/ffi/dynamic_data/models/pokemon.rs @@ -84,7 +84,7 @@ ffi_arc_getter!(Pokemon, coloring, u8); /// Gets the held item of a Pokemon #[no_mangle] -extern "C" fn pokemon_held_item(ptr: ExternPointer>) -> IdentifiablePointer> { +extern "C" fn pokemon_held_item(ptr: ExternPointer>) -> IdentifiablePointer> { if let Some(v) = ptr.as_ref().held_item().read().as_ref() { v.clone().into() } else { @@ -103,8 +103,8 @@ extern "C" fn pokemon_has_held_item(ptr: ExternPointer>, name: *con #[no_mangle] extern "C" fn pokemon_set_held_item( ptr: ExternPointer>, - item: ExternPointer>, -) -> IdentifiablePointer> { + item: ExternPointer>, +) -> IdentifiablePointer> { if let Some(v) = ptr.as_ref().set_held_item(item.as_ref()) { v.into() } else { @@ -114,7 +114,7 @@ extern "C" fn pokemon_set_held_item( /// Removes the held item from the Pokemon. Returns the previously held item. #[no_mangle] -extern "C" fn pokemon_remove_held_item(ptr: ExternPointer>) -> IdentifiablePointer> { +extern "C" fn pokemon_remove_held_item(ptr: ExternPointer>) -> IdentifiablePointer> { if let Some(v) = ptr.as_ref().remove_held_item() { v.into() } else { diff --git a/src/ffi/mod.rs b/src/ffi/mod.rs index 49a033b..a7c269e 100644 --- a/src/ffi/mod.rs +++ b/src/ffi/mod.rs @@ -129,9 +129,9 @@ impl From<*mut T> for ExternPointer { } } -impl From> for IdentifiablePointer> { +impl From> for IdentifiablePointer> { fn from(v: Arc) -> Self { - let id = unsafe { transmute(v.value_identifier()) }; + let id = v.value_identifier().value(); Self { ptr: Box::into_raw(Box::new(v)), id, diff --git a/src/ffi/static_data/item.rs b/src/ffi/static_data/item.rs index e0dd060..282a290 100644 --- a/src/ffi/static_data/item.rs +++ b/src/ffi/static_data/item.rs @@ -1,5 +1,5 @@ use crate::ffi::{ffi_arc_getter, ExternPointer, IdentifiablePointer, OwnedPtr}; -use crate::static_data::{BattleItemCategory, Item, ItemCategory}; +use crate::static_data::{BattleItemCategory, Item, ItemCategory, ItemImpl}; use crate::StringKey; use hashbrown::HashSet; use std::ffi::{c_char, CStr, CString}; @@ -15,36 +15,38 @@ unsafe extern "C" fn item_new( price: i32, flags: *const *const c_char, flags_length: usize, -) -> IdentifiablePointer> { +) -> IdentifiablePointer> { let flags = std::slice::from_raw_parts(flags, flags_length); let name: StringKey = CStr::from_ptr(name).to_str().unwrap().into(); let mut flags_set: HashSet = HashSet::with_capacity(flags_length); for flag in flags { flags_set.insert(CStr::from_ptr(*flag).to_str().unwrap().into()); } - Arc::new(Item::new(&name, category, battle_category, price, flags_set)).into() + + let item: Arc = Arc::new(ItemImpl::new(&name, category, battle_category, price, flags_set)); + item.into() } /// Drops a reference counted item. #[no_mangle] -unsafe extern "C" fn item_drop(ptr: OwnedPtr>) { +unsafe extern "C" fn item_drop(ptr: OwnedPtr>) { drop_in_place(ptr) } /// The name of the item. #[no_mangle] -unsafe extern "C" fn item_name(ptr: ExternPointer>) -> OwnedPtr { +unsafe extern "C" fn item_name(ptr: ExternPointer>) -> OwnedPtr { let name = ptr.as_ref().name(); CString::new(name.str()).unwrap().into_raw() } -ffi_arc_getter!(Item, category, ItemCategory); -ffi_arc_getter!(Item, battle_category, BattleItemCategory); -ffi_arc_getter!(Item, price, i32); +ffi_arc_getter!(dyn Item, category, ItemCategory); +ffi_arc_getter!(dyn Item, battle_category, BattleItemCategory); +ffi_arc_getter!(dyn Item, price, i32); /// Checks whether the item has a specific flag. #[no_mangle] -unsafe extern "C" fn item_has_flag(ptr: ExternPointer>, flag: *const c_char) -> u8 { +unsafe extern "C" fn item_has_flag(ptr: ExternPointer>, flag: *const c_char) -> u8 { let flag = CStr::from_ptr(flag).into(); u8::from(ptr.as_ref().has_flag(&flag)) } diff --git a/src/ffi/static_data/libraries/mod.rs b/src/ffi/static_data/libraries/mod.rs index 47bb230..429293e 100644 --- a/src/ffi/static_data/libraries/mod.rs +++ b/src/ffi/static_data/libraries/mod.rs @@ -75,4 +75,4 @@ macro_rules! library_interface { library_interface!(SpeciesLibrary, Species); library_interface!(MoveLibrary, MoveData); library_interface!(AbilityLibrary, Ability); -library_interface!(ItemLibrary, Item); +library_interface!(ItemLibrary, dyn Item); diff --git a/src/lib.rs b/src/lib.rs index af88a08..09d3f7f 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ -// The too many arguments is annoying, especially for when we create constructor, disable. #![allow(clippy::too_many_arguments, clippy::needless_range_loop)] #![allow(clippy::not_unsafe_ptr_arg_deref)] +#![allow(incomplete_features)] #![deny(missing_docs)] #![deny(clippy::missing_docs_in_private_items)] #![feature(test)] @@ -12,6 +12,7 @@ #![feature(strict_provenance)] #![feature(fn_traits)] #![feature(unboxed_closures)] +#![feature(trait_upcasting)] //! PkmnLib //! PkmnLib is a full featured implementation of Pokemon. while currently focused on implementing diff --git a/src/script_implementations/wasm/export_registry/dynamic_data/battle_side.rs b/src/script_implementations/wasm/export_registry/dynamic_data/battle_side.rs index 1081a51..871205a 100755 --- a/src/script_implementations/wasm/export_registry/dynamic_data/battle_side.rs +++ b/src/script_implementations/wasm/export_registry/dynamic_data/battle_side.rs @@ -77,7 +77,7 @@ register! { side: ExternRef, script_ptr: u32 ) -> u32 { - let side = side.value_func(&env).unwrap(); + let side : &BattleSide = side.value_func(&env).unwrap(); unsafe{ let env = env.data().data(); let name_ptr = env.script_function_cache().script_get_name(&env).unwrap().call(&mut env.store_mut(), script_ptr).unwrap(); diff --git a/src/script_implementations/wasm/export_registry/dynamic_data/mod.rs b/src/script_implementations/wasm/export_registry/dynamic_data/mod.rs index 233846c..f8fd4a8 100755 --- a/src/script_implementations/wasm/export_registry/dynamic_data/mod.rs +++ b/src/script_implementations/wasm/export_registry/dynamic_data/mod.rs @@ -44,9 +44,9 @@ register! { let script = env.data().data().get_loaded_script(script); if let Some(script) = script { match script.get_owner() { - ScriptOwnerData::Pokemon(p) => env.data().data().get_extern_ref_index(p.load(Ordering::Relaxed).as_ref().unwrap()), - ScriptOwnerData::BattleSide(p) => env.data().data().get_extern_ref_index(p.load(Ordering::Relaxed).as_ref().unwrap()), - ScriptOwnerData::Battle(p) => env.data().data().get_extern_ref_index(p.load(Ordering::Relaxed).as_ref().unwrap()), + ScriptOwnerData::Pokemon(p) => env.data().data().get_extern_ref_index::(p.load(Ordering::Relaxed).as_ref().unwrap()) as u32, + ScriptOwnerData::BattleSide(p) => env.data().data().get_extern_ref_index::(p.load(Ordering::Relaxed).as_ref().unwrap()) as u32, + ScriptOwnerData::Battle(p) => env.data().data().get_extern_ref_index::(p.load(Ordering::Relaxed).as_ref().unwrap()) as u32, ScriptOwnerData::None => 0, } } else { diff --git a/src/script_implementations/wasm/export_registry/dynamic_data/pokemon.rs b/src/script_implementations/wasm/export_registry/dynamic_data/pokemon.rs index cb08e61..055c62f 100755 --- a/src/script_implementations/wasm/export_registry/dynamic_data/pokemon.rs +++ b/src/script_implementations/wasm/export_registry/dynamic_data/pokemon.rs @@ -16,7 +16,7 @@ register! { env: FunctionEnvMut, pokemon: ExternRef, ) -> ExternRef { - let lib = pokemon.value_func(&env).unwrap().library(); + let lib = pokemon.value_func(&env).unwrap().library().as_ref(); ExternRef::func_new(&env, lib) } @@ -174,7 +174,7 @@ register! { fn pokemon_get_held_item( env: FunctionEnvMut, pokemon: ExternRef, - ) -> ExternRef { + ) -> ExternRef { let read_lock = pokemon.value_func(&env).unwrap().held_item().read(); if let Some(item) = read_lock.as_ref() { ExternRef::func_new(&env, item.as_ref()) @@ -231,7 +231,7 @@ register! { pokemon: ExternRef, script_ptr: u32 ) -> u32 { - let pokemon = pokemon.value_func(&env).unwrap(); + let pokemon : &Pokemon = pokemon.value_func(&env).unwrap(); unsafe{ let env = env.data().data(); let name_ptr = env.script_function_cache().script_get_name(&env).unwrap().call(&mut env.store_mut(), script_ptr).unwrap(); diff --git a/src/script_implementations/wasm/export_registry/mod.rs b/src/script_implementations/wasm/export_registry/mod.rs index e814f86..e86fade 100755 --- a/src/script_implementations/wasm/export_registry/mod.rs +++ b/src/script_implementations/wasm/export_registry/mod.rs @@ -109,7 +109,9 @@ fn _error(env: FunctionEnvMut, message: u32, file: u32, line: u3 /// Get a single item from an earlier passed VecExternRef fn _vec_extern_ref_get_value(env: FunctionEnvMut, reference: u32, index: u32) -> u32 { - env.data().data().get_extern_vec_ref_extern_ref(reference, index) + env.data() + .data() + .get_extern_vec_ref_extern_ref(reference as usize, index as usize) as u32 } /// Gets the hash value of a StringKey. diff --git a/src/script_implementations/wasm/export_registry/static_data/item.rs b/src/script_implementations/wasm/export_registry/static_data/item.rs index 1ea754e..b51f087 100755 --- a/src/script_implementations/wasm/export_registry/static_data/item.rs +++ b/src/script_implementations/wasm/export_registry/static_data/item.rs @@ -1,38 +1,62 @@ use crate::script_implementations::wasm::export_registry::register; use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; -use crate::static_data::Item; +use crate::static_data::{DataLibrary, Item, ItemLibrary}; use crate::StringKey; use std::mem::transmute; use wasmer::FunctionEnvMut; register! { + fn item_library_get_item( + env: FunctionEnvMut, + lib: ExternRef, + string_key: ExternRef, + ) -> ExternRef { + let lib = lib.value_func(&env).unwrap(); + let m = lib.get(string_key.value_func(&env).unwrap()); + if let Some(v) = m { + ExternRef::func_new(&env, v) + } else { + ExternRef::null() + } + } + + fn item_library_get_item_by_hash(env: FunctionEnvMut, lib: ExternRef, hash: u32) -> ExternRef { + let lib = lib.value_func(&env).unwrap(); + let m = lib.get_by_hash(hash); + if let Some(v) = m { + ExternRef::func_new(&env, v) + } else { + ExternRef::null() + } + } + + fn item_get_price( env: FunctionEnvMut, - item: ExternRef, + item: ExternRef, ) -> i32 { - item.value_func(&env).unwrap().price() + item.value_func_arc(&env).unwrap().price() } fn item_get_name( env: FunctionEnvMut, - item: ExternRef, + item: ExternRef, ) -> ExternRef { - ExternRef::func_new(&env, item.value_func(&env).unwrap().name()) + ExternRef::func_new(&env, item.value_func_arc(&env).unwrap().name()) } fn item_get_category( env: FunctionEnvMut, - item: ExternRef, + item: ExternRef, ) -> u8 { - unsafe { transmute(item.value_func(&env).unwrap().category()) } - + unsafe { transmute(item.value_func_arc(&env).unwrap().category()) } } fn item_get_battle_category( env: FunctionEnvMut, - item: ExternRef, + item: ExternRef, ) -> u8 { - unsafe { transmute(item.value_func(&env).unwrap().battle_category()) } + unsafe { transmute(item.value_func_arc(&env).unwrap().battle_category()) } } } diff --git a/src/script_implementations/wasm/extern_ref.rs b/src/script_implementations/wasm/extern_ref.rs index 48d4efb..7e0e242 100755 --- a/src/script_implementations/wasm/extern_ref.rs +++ b/src/script_implementations/wasm/extern_ref.rs @@ -1,3 +1,5 @@ +use crate::ValueIdentifiable; +use std::any::Any; use std::marker::PhantomData; use std::mem::transmute; use std::sync::Arc; @@ -5,7 +7,6 @@ use std::sync::Arc; use crate::script_implementations::wasm::script_resolver::{ WebAssemblyEnv, WebAssemblyEnvironmentData, WebAssemblyScriptResolver, }; -use unique_type_id::UniqueTypeId; use wasmer::FromToNativeWasmType; use wasmer::FunctionEnvMut; @@ -13,36 +14,36 @@ use wasmer::FunctionEnvMut; /// requiring us to make copies. Instead, we pass a simple increment index, that we can then use /// to find the relevant data. #[derive(Copy, Clone)] -pub(crate) struct ExternRef> { +pub(crate) struct ExternRef { /// The lookup index we can use to find the data. - index: u32, + index: usize, /// Phantom data so we can get a type generic. _phantom: PhantomData, } -impl> ExternRef { +impl ExternRef { /// Instantiates a new ExternRef for a bit of data. If we already have made an Extern Ref for /// this data and type, we use that instead. - pub fn new(env: &WebAssemblyEnvironmentData, value: &T) -> Self { + pub fn new(env: &WebAssemblyEnvironmentData, value: &dyn Any) -> Self { Self { - index: env.get_extern_ref_index(value), + index: env.get_extern_ref_index::(value), _phantom: Default::default(), } } /// Instantiates a new ExternRef for a bit of data using the function environment. If we already /// have made an Extern Ref for this data and type, we use that instead. - pub fn func_new(env: &FunctionEnvMut, value: &T) -> Self { + pub fn func_new(env: &FunctionEnvMut, value: &dyn Any) -> Self { Self { - index: env.data().data().get_extern_ref_index(value), + index: env.data().data().get_extern_ref_index::(value), _phantom: Default::default(), } } /// Creates an ExternRef with a given resolver. This can be used in cases where we do not have an environment variable. - pub(crate) fn new_with_resolver(resolver: &WebAssemblyScriptResolver, value: &T) -> Self { + pub(crate) fn new_with_resolver(resolver: &WebAssemblyScriptResolver, value: &dyn Any) -> Self { Self { - index: resolver.environment_data().get_extern_ref_index(value), + index: resolver.environment_data().get_extern_ref_index::(value), _phantom: Default::default(), } } @@ -57,24 +58,49 @@ impl> ExternRef { /// Returns the real value for a given ExternRef. Note that the requested type must be the same as the type of the /// value when it was passed before. If these types do not match, this will panic. - pub fn value_func<'a, 'b>(&'a self, env: &'b FunctionEnvMut) -> Option<&'b T> { + pub fn value_func<'a, 'b>(&'a self, env: &'b FunctionEnvMut) -> Option<&'b T> + where + T: Sized + 'static, + { self.value(&env.data().data()) } /// Returns the real value for a given ExternRef. Note that the requested type must be the same as the type of the /// value when it was passed before. If these types do not match, this will panic. - pub fn value<'a, 'b, 'c>(&'a self, env: &'b Arc) -> Option<&'c T> { - let ptr = env.get_extern_ref_value(self.index) as *const T; - unsafe { ptr.as_ref() } + pub fn value_func_arc(&self, env: &FunctionEnvMut) -> Option> + where + T: 'static, + { + self.value_arc(&env.data().data()) + } + + /// Returns the real value for a given ExternRef. Note that the requested type must be the same as the type of the + /// value when it was passed before. If these types do not match, this will panic. + pub fn value<'a, 'b, 'c>(&'a self, env: &'b Arc) -> Option<&'c T> + where + T: Sized + 'static, + { + env.get_extern_ref_value::(self.index).downcast_ref::() + } + + /// Returns the real value for a given ExternRef. Note that the requested type must be the same as the type of the + /// value when it was passed before. If these types do not match, this will panic. + pub fn value_arc(&self, env: &Arc) -> Option> + where + T: 'static, + { + env.get_extern_ref_value::(self.index) + .downcast_ref::>() + .cloned() } } -unsafe impl> FromToNativeWasmType for ExternRef { +unsafe impl FromToNativeWasmType for ExternRef { type Native = i32; fn from_native(native: Self::Native) -> Self { Self { - index: native as u32, + index: native as usize, _phantom: Default::default(), } } @@ -88,16 +114,16 @@ unsafe impl> FromToNativeWasmType for ExternRef { /// actually passing raw memory, or requiring us to make copies. pub(crate) struct VecExternRef { /// The lookup index we can use to find the data. - index: u32, + index: usize, /// The number of items in the vec. size: u32, /// Phantom data so we can get a type generic. _phantom: PhantomData, } -impl> VecExternRef { +impl VecExternRef { /// Instantiates a new VecExternRef for a given slice. - pub fn new(env: &WebAssemblyEnvironmentData, value: &[T]) -> Self { + pub fn new(env: &WebAssemblyEnvironmentData, value: &Vec) -> Self { Self { index: env.get_extern_vec_ref_index(value), size: value.len() as u32, @@ -106,20 +132,20 @@ impl> VecExternRef { } } -unsafe impl> FromToNativeWasmType for VecExternRef { +unsafe impl FromToNativeWasmType for VecExternRef { type Native = i64; fn from_native(native: Self::Native) -> Self { let split: (u32, u32) = unsafe { transmute(native) }; Self { - index: split.0, + index: split.0 as usize, size: split.1, _phantom: Default::default(), } } fn to_native(self) -> Self::Native { - let v: i64 = unsafe { transmute((self.index, self.size)) }; + let v: i64 = unsafe { transmute((self.index as u32, self.size)) }; v } } diff --git a/src/script_implementations/wasm/script.rs b/src/script_implementations/wasm/script.rs index f2e7274..36b800f 100755 --- a/src/script_implementations/wasm/script.rs +++ b/src/script_implementations/wasm/script.rs @@ -125,14 +125,14 @@ impl Script for WebAssemblyScript { } } - fn on_initialize(&self, library: &DynamicLibrary, pars: &[EffectParameter]) { + fn on_initialize(&self, library: &DynamicLibrary, pars: Vec) { if !self.has_capability(&WebAssemblyScriptCapabilities::Initialize) { return; } let env = &self.environment; if let Some(func) = env.script_function_cache().on_initialize(env) { - call_func!(func, env, self, ex_ref!(env, library), vec_ex_ref!(env, pars)); + call_func!(func, env, self, ex_ref!(env, library), vec_ex_ref!(env, &pars)); } } @@ -757,7 +757,7 @@ impl Script for WebAssemblyScript { } } - fn on_after_held_item_consume(&self, pokemon: &Pokemon, item: &Item) { + fn on_after_held_item_consume(&self, pokemon: &Pokemon, item: &dyn Item) { if !self.has_capability(&WebAssemblyScriptCapabilities::OnAfterHeldItemConsume) { return; } @@ -807,7 +807,7 @@ impl Script for WebAssemblyScript { } } - fn change_capture_rate_bonus(&self, target: &Pokemon, pokeball: &Item, modifier: &mut u8) { + fn change_capture_rate_bonus(&self, target: &Pokemon, pokeball: &dyn Item, modifier: &mut u8) { if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeCaptureRate) { return; } diff --git a/src/script_implementations/wasm/script_function_cache.rs b/src/script_implementations/wasm/script_function_cache.rs index 00ae6d0..212bd4a 100755 --- a/src/script_implementations/wasm/script_function_cache.rs +++ b/src/script_implementations/wasm/script_function_cache.rs @@ -165,11 +165,11 @@ script_function_cache! { on_damage(ExternRef, u8, u32, u32) on_faint(ExternRef, u8) on_switch_in(ExternRef) - on_after_held_item_consume(ExternRef, ExternRef) + on_after_held_item_consume(ExternRef, ExternRef) change_experience_gained(ExternRef, ExternRef, WasmPtr) share_experience(ExternRef, ExternRef, WasmPtr) block_weather(ExternRef, WasmPtr) - change_capture_rate_bonus(ExternRef, ExternRef, WasmPtr) + change_capture_rate_bonus(ExternRef, ExternRef, WasmPtr) } impl ScriptFunctionCache { diff --git a/src/script_implementations/wasm/script_resolver.rs b/src/script_implementations/wasm/script_resolver.rs index 46beaef..3444c07 100755 --- a/src/script_implementations/wasm/script_resolver.rs +++ b/src/script_implementations/wasm/script_resolver.rs @@ -1,3 +1,4 @@ +use std::any::Any; use std::fmt::{Debug, Formatter}; use std::mem::{align_of, forget, size_of}; use std::sync::{Arc, Weak}; @@ -5,7 +6,6 @@ use std::sync::{Arc, Weak}; use hashbrown::{HashMap, HashSet}; use parking_lot::lock_api::RwLockReadGuard; use parking_lot::{RawRwLock, RwLock}; -use unique_type_id::UniqueTypeId; use wasmer::{ AsStoreMut, AsStoreRef, Cranelift, EngineBuilder, Extern, Features, Function, FunctionEnv, Imports, Instance, Memory, Module, Store, StoreMut, StoreRef, TypedFunction, Value, @@ -189,7 +189,7 @@ impl ScriptResolver for WebAssemblyScriptResolver { self.environment_data.setup_script(script, category, script_key, owner) } - fn load_item_script(&self, _key: &Item) -> PkmnResult>> { + fn load_item_script(&self, _key: &dyn Item) -> PkmnResult>> { todo!() } } @@ -215,17 +215,17 @@ pub struct WebAssemblyEnvironmentData { /// we instead keep track of all the data we've sent to WASM, and pass the ID of that data to WASM. This allows us /// to only operate on data we know WASM owns. We currently store this data in this continuous Vec, and give the index /// of the data as the ID. - extern_ref_pointers: RwLock>, + extern_ref_pointers: RwLock>, /// To make sure we send the same identifier to WASM when we send the same piece of data multiple times, we have a /// backwards lookup on extern_ref_pointers. This allows us to get the index for a given piece of data. - extern_ref_pointers_lookup: RwLock>, + extern_ref_pointers_lookup: RwLock>, /// As an added security measure on our extern refs, we keep track of the types of the extern ref data we've sent. /// This prevents illegal arbitrary memory operations, where we expect type X, but the actual type is Y, which would /// allow for modifying memory we might not want to. If we get a type mismatch, we will panic, preventing this. extern_ref_type_lookup: RwLock>, /// Additional security for data slices passed to WASM. - extern_vec_ref_lookup: RwLock>>, + extern_vec_ref_lookup: RwLock>>, /// The memory inside of the WASM container. memory: RwLock>, @@ -257,14 +257,13 @@ pub struct WebAssemblyEnvironmentData { } /// A quick lookup so we can find the extern ref of the value. +#[allow(clippy::vtable_address_comparisons)] #[derive(Clone, Eq, PartialEq, Hash)] struct ExternRefLookupKey { /// The raw pointer to the data - pub ptr: *const u8, + pub ptr: *const dyn Any, /// Whether or not the reference is a Vec pub is_vec: bool, - /// The unique identifier of the type. - pub t: u64, } impl WebAssemblyEnvironmentData { @@ -359,8 +358,8 @@ impl WebAssemblyEnvironmentData { /// when extern refs get actually properly implemented at compile time we might want to get rid /// of this code. #[inline(always)] - pub fn get_extern_ref_index + ?Sized>(&self, value: &T) -> u32 { - self.get_extern_ref_from_ptr(value as *const T as *const u8, T::id().0, false) + pub fn get_extern_ref_index(&self, value: &dyn Any) -> usize { + self.get_extern_ref_from_identifier::(value, false) } /// Get a numeric value from any given value. This is not a true Extern Ref from WASM, as this @@ -369,18 +368,18 @@ impl WebAssemblyEnvironmentData { /// access can be touched through this, and we ensure the value is the correct type. In the future, /// when extern refs get actually properly implemented at compile time we might want to get rid /// of this code. - pub fn get_extern_vec_ref_index>(&self, value: &[T]) -> u32 { + pub fn get_extern_vec_ref_index(&self, value: &Vec) -> usize { let mut vec = Vec::with_capacity(value.len()); for v in value { - vec.push(self.get_extern_ref_index(v)); + vec.push(self.get_extern_ref_index::(v)); } - let p = self.get_extern_ref_from_ptr(value as *const [T] as *const u8, T::id().0, true); + let p = self.get_extern_ref_from_identifier::>(value, true); self.extern_vec_ref_lookup.write().insert(p, vec); p } /// Get an extern ref belonging to a vector we have passed to WASM. - pub fn get_extern_vec_ref_extern_ref(&self, extern_vec_ref: u32, index: u32) -> u32 { + pub fn get_extern_vec_ref_extern_ref(&self, extern_vec_ref: usize, index: usize) -> usize { let r = self.extern_vec_ref_lookup.read(); let v = r.get(&extern_vec_ref).unwrap(); v[index as usize] @@ -389,47 +388,43 @@ impl WebAssemblyEnvironmentData { /// Gets the extern ref index belonging to a specific pointer. If none exists, this will create /// a new one. #[inline(always)] - fn get_extern_ref_from_ptr(&self, ptr: *const u8, type_id: u64, is_vec: bool) -> u32 { + fn get_extern_ref_from_identifier(&self, value: &dyn Any, is_vec: bool) -> usize { if let Some(v) = self.extern_ref_pointers_lookup.read().get(&ExternRefLookupKey { - ptr, + ptr: value as *const dyn Any, is_vec, - t: type_id, }) { - return *v as u32; + return *v as usize; } let index = { let mut extern_ref_guard = self.extern_ref_pointers.write(); - extern_ref_guard.push(ptr); - extern_ref_guard.len() as u32 + extern_ref_guard.push(value as *const dyn Any); + extern_ref_guard.len() }; self.extern_ref_pointers_lookup.write().insert( ExternRefLookupKey { - ptr, + ptr: value as *const dyn Any, is_vec, - t: type_id, }, index, ); self.extern_ref_type_lookup.write().insert(ExternRefLookupKey { - ptr, + ptr: value as *const dyn Any, is_vec, - t: type_id, }); index } /// Gets a value from the extern ref lookup. This turns an earlier registered index back into /// its proper value, validates its type, and returns the value. - pub fn get_extern_ref_value>(&self, index: u32) -> &T { + pub fn get_extern_ref_value<'a, 'b, T: ?Sized>(&'a self, index: usize) -> &'b dyn Any { let read_guard = self.extern_ref_pointers.read(); - let ptr = read_guard.get((index - 1) as usize).unwrap(); + let ptr = read_guard.get(index - 1).unwrap(); if self .extern_ref_type_lookup .read() .get(&ExternRefLookupKey { ptr: *ptr, is_vec: false, - t: T::id().0, }) .is_none() { @@ -439,7 +434,7 @@ impl WebAssemblyEnvironmentData { ); } - unsafe { (*ptr as *const T).as_ref().unwrap() } + unsafe { ptr.as_ref().unwrap() } } /// The WASM store. diff --git a/src/static_data/items.rs b/src/static_data/items.rs index 8c1671b..9397567 100755 --- a/src/static_data/items.rs +++ b/src/static_data/items.rs @@ -1,6 +1,8 @@ use hashbrown::HashSet; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; +use std::any::Any; +use std::fmt::Debug; use crate::{StringKey, ValueIdentifiable, ValueIdentifier}; @@ -44,10 +46,26 @@ pub enum BattleItemCategory { MiscBattleItem, } +/// An item is an object which the player can pick up, keep in their Bag, and use in some manner +pub trait Item: ValueIdentifiable + Debug + Any { + /// The name of the item. + fn name(&self) -> &StringKey; + /// Which bag slot items are stored in. + fn category(&self) -> ItemCategory; + /// How the item is categorized when in battle. + fn battle_category(&self) -> BattleItemCategory; + /// The buying value of the item. + fn price(&self) -> i32; + /// A set of arbitrary flags that can be set on the item. + fn flags(&self) -> &HashSet; + + /// Checks whether the item has a specific flag. + fn has_flag(&self, key: &StringKey) -> bool; +} + /// An item is an object which the player can pick up, keep in their Bag, and use in some manner #[derive(Debug)] -#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] -pub struct Item { +pub struct ItemImpl { /// A unique identifier so we know what value this is. identifier: ValueIdentifier, /// The name of the item. @@ -62,7 +80,7 @@ pub struct Item { flags: HashSet, } -impl Item { +impl ItemImpl { /// Instantiates an item. pub fn new( name: &StringKey, @@ -70,8 +88,8 @@ impl Item { battle_category: BattleItemCategory, price: i32, flags: HashSet, - ) -> Item { - Item { + ) -> ItemImpl { + ItemImpl { identifier: Default::default(), name: name.clone(), category, @@ -80,35 +98,37 @@ impl Item { flags, } } +} +impl Item for ItemImpl { /// The name of the item. - pub fn name(&self) -> &StringKey { + fn name(&self) -> &StringKey { &self.name } /// Which bag slot items are stored in. - pub fn category(&self) -> ItemCategory { + fn category(&self) -> ItemCategory { self.category } /// How the item is categorized when in battle. - pub fn battle_category(&self) -> BattleItemCategory { + fn battle_category(&self) -> BattleItemCategory { self.battle_category } /// The buying value of the item. - pub fn price(&self) -> i32 { + fn price(&self) -> i32 { self.price } /// A set of arbitrary flags that can be set on the item. - pub fn flags(&self) -> &HashSet { + fn flags(&self) -> &HashSet { &self.flags } /// Checks whether the item has a specific flag. - pub fn has_flag(&self, key: &StringKey) -> bool { + fn has_flag(&self, key: &StringKey) -> bool { self.flags.contains(key) } } -impl ValueIdentifiable for Item { +impl ValueIdentifiable for ItemImpl { fn value_identifier(&self) -> ValueIdentifier { self.identifier } diff --git a/src/static_data/libraries/ability_library.rs b/src/static_data/libraries/ability_library.rs index c73ac51..c9cf1a2 100755 --- a/src/static_data/libraries/ability_library.rs +++ b/src/static_data/libraries/ability_library.rs @@ -25,7 +25,7 @@ impl AbilityLibrary { } } -impl DataLibrary<'_, Ability> for AbilityLibrary { +impl DataLibrary for AbilityLibrary { fn map(&self) -> &IndexMap> { &self.map } diff --git a/src/static_data/libraries/data_library.rs b/src/static_data/libraries/data_library.rs index 45158a5..b483320 100755 --- a/src/static_data/libraries/data_library.rs +++ b/src/static_data/libraries/data_library.rs @@ -7,7 +7,7 @@ use crate::StringKey; /// A data library is a collection of methods to set up a default library, where values are stored /// by both key, while keeping their insertion order. -pub trait DataLibrary<'a, T: 'a> { +pub trait DataLibrary { /// Returns the underlying map. fn map(&self) -> &IndexMap>; /// Returns the underlying map in mutable manner. @@ -24,18 +24,18 @@ pub trait DataLibrary<'a, T: 'a> { } /// Gets a value from the library. - fn get(&'a self, key: &StringKey) -> Option<&Arc> { + fn get(&self, key: &StringKey) -> Option<&Arc> { self.map().get::(key) } /// Gets a value from the library. - fn get_by_hash(&'a self, key: u32) -> Option<&Arc> { + fn get_by_hash(&self, key: u32) -> Option<&Arc> { self.map().get::(&key) } /// Gets a value from the library by the index where it is stored. - fn get_key_by_index(&'a self, index: usize) -> Option<&StringKey> { - self.map().get_index(index).map(|a| a.0) + fn get_key_by_index(&self, index: usize) -> Option { + self.map().get_index(index).map(|a| a.0.clone()) } /// Gets the amount of values in the library. diff --git a/src/static_data/libraries/item_library.rs b/src/static_data/libraries/item_library.rs index cd9b943..ee27b47 100755 --- a/src/static_data/libraries/item_library.rs +++ b/src/static_data/libraries/item_library.rs @@ -8,12 +8,12 @@ use crate::{StringKey, ValueIdentifiable, ValueIdentifier}; /// A library to store all items. #[derive(Debug)] -#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] + pub struct ItemLibrary { /// A unique identifier so we know what value this is. identifier: ValueIdentifier, /// The underlying data structure. - map: IndexMap>, + map: IndexMap>, } impl ItemLibrary { @@ -26,12 +26,12 @@ impl ItemLibrary { } } -impl DataLibrary<'_, Item> for ItemLibrary { - fn map(&self) -> &IndexMap> { +impl DataLibrary for ItemLibrary { + fn map(&self) -> &IndexMap> { &self.map } - fn get_modify(&mut self) -> &mut IndexMap> { + fn get_modify(&mut self) -> &mut IndexMap> { &mut self.map } } @@ -49,11 +49,11 @@ pub mod tests { use crate::static_data::libraries::data_library::DataLibrary; use crate::static_data::libraries::item_library::ItemLibrary; - use crate::static_data::Item; + use crate::static_data::ItemImpl; use crate::static_data::{BattleItemCategory, ItemCategory}; - fn build_item() -> Item { - Item::new( + fn build_item() -> ItemImpl { + ItemImpl::new( &"foo".into(), ItemCategory::MiscItem, BattleItemCategory::MiscBattleItem, diff --git a/src/static_data/libraries/library_settings.rs b/src/static_data/libraries/library_settings.rs index 8745e06..298cabf 100755 --- a/src/static_data/libraries/library_settings.rs +++ b/src/static_data/libraries/library_settings.rs @@ -3,7 +3,6 @@ use crate::{ValueIdentifiable, ValueIdentifier}; /// This library holds several misc settings for the library. #[derive(Debug)] -#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] pub struct LibrarySettings { /// A unique identifier so we know what value this is. identifier: ValueIdentifier, diff --git a/src/static_data/libraries/move_library.rs b/src/static_data/libraries/move_library.rs index e35b929..3ccce46 100755 --- a/src/static_data/libraries/move_library.rs +++ b/src/static_data/libraries/move_library.rs @@ -8,7 +8,7 @@ use crate::{StringKey, ValueIdentifiable, ValueIdentifier}; /// A library to store all data for moves. #[derive(Debug)] -#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] + pub struct MoveLibrary { /// A unique identifier so we know what value this is. identifier: ValueIdentifier, @@ -26,7 +26,7 @@ impl MoveLibrary { } } -impl DataLibrary<'_, MoveData> for MoveLibrary { +impl DataLibrary for MoveLibrary { fn map(&self) -> &IndexMap> { &self.map } diff --git a/src/static_data/libraries/species_library.rs b/src/static_data/libraries/species_library.rs index c923dab..1855a2b 100755 --- a/src/static_data/libraries/species_library.rs +++ b/src/static_data/libraries/species_library.rs @@ -8,7 +8,7 @@ use crate::{StringKey, ValueIdentifiable, ValueIdentifier}; /// A library to store all data for Pokemon species. #[derive(Debug)] -#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] + pub struct SpeciesLibrary { /// A unique identifier so we know what value this is. identifier: ValueIdentifier, @@ -26,7 +26,7 @@ impl SpeciesLibrary { } } -impl<'a> DataLibrary<'a, Species> for SpeciesLibrary { +impl DataLibrary for SpeciesLibrary { fn map(&self) -> &IndexMap> { &self.map } diff --git a/src/static_data/libraries/static_data.rs b/src/static_data/libraries/static_data.rs index 51cf3a6..115e98d 100755 --- a/src/static_data/libraries/static_data.rs +++ b/src/static_data/libraries/static_data.rs @@ -10,7 +10,6 @@ use crate::{ValueIdentifiable, ValueIdentifier}; /// The storage for all different libraries. #[derive(Debug)] -#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] pub struct StaticData { /// A unique identifier so we know what value this is. identifier: ValueIdentifier, diff --git a/src/static_data/libraries/type_library.rs b/src/static_data/libraries/type_library.rs index 2fecbf5..5b52016 100755 --- a/src/static_data/libraries/type_library.rs +++ b/src/static_data/libraries/type_library.rs @@ -26,7 +26,6 @@ impl From for u8 { /// All data related to types and effectiveness. #[derive(Debug)] -#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] pub struct TypeLibrary { /// A unique identifier so we know what value this is. identifier: ValueIdentifier, diff --git a/src/static_data/mod.rs b/src/static_data/mod.rs index eac374e..ac208d8 100755 --- a/src/static_data/mod.rs +++ b/src/static_data/mod.rs @@ -36,8 +36,7 @@ mod statistics; /// A parameter for an effect. This is basically a simple way to dynamically store multiple different /// primitives on data. -#[derive(PartialEq, Debug)] -#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] +#[derive(PartialEq, Debug, Clone)] pub enum EffectParameter { /// A boolean value. Bool(ValueIdentifier, bool), diff --git a/src/static_data/moves/move_data.rs b/src/static_data/moves/move_data.rs index 9ffa746..2b86626 100755 --- a/src/static_data/moves/move_data.rs +++ b/src/static_data/moves/move_data.rs @@ -61,7 +61,6 @@ pub enum MoveTarget { /// A move is the skill Pokémon primarily use in battle. This is the data related to that. #[derive(PartialEq, Debug)] -#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] pub struct MoveData { /// A unique identifier so we know what value this is. identifier: ValueIdentifier, diff --git a/src/static_data/species_data/species.rs b/src/static_data/species_data/species.rs index 8e5f99e..3a7c935 100755 --- a/src/static_data/species_data/species.rs +++ b/src/static_data/species_data/species.rs @@ -11,7 +11,6 @@ use crate::{Random, ValueIdentifiable, ValueIdentifier}; /// The data belonging to a Pokemon with certain characteristics. #[derive(Debug)] -#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] pub struct Species { /// A unique identifier so we know what value this is. identifier: ValueIdentifier, diff --git a/src/static_data/statistic_set.rs b/src/static_data/statistic_set.rs index 36b1c91..6bd32e7 100755 --- a/src/static_data/statistic_set.rs +++ b/src/static_data/statistic_set.rs @@ -12,7 +12,6 @@ use super::statistics::Statistic; /// /// As all data in this type is atomic, threaded access to this struct is completely legal. #[derive(Default, Debug)] -#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] pub struct StatisticSet where T: PrimitiveAtom, @@ -236,7 +235,6 @@ where /// A clamped statistic set holds the 6 normal stats for a Pokemon, but ensures it always remains /// between two values (inclusive on the two values). #[derive(Default, Debug)] -#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] pub struct ClampedStatisticSet where T: PrimitiveAtom, diff --git a/src/utils/string_key.rs b/src/utils/string_key.rs index 11cce62..802eac4 100755 --- a/src/utils/string_key.rs +++ b/src/utils/string_key.rs @@ -1,3 +1,4 @@ +use crate::{ValueIdentifiable, ValueIdentifier}; use arcstr::ArcStr; use hashbrown::HashMap; use parking_lot::RwLock; @@ -13,7 +14,7 @@ use std::sync::LazyLock; /// free speed out of it. Note that StringKeys also compare case insensitive, so that for example /// `charmander` == `Charmander`. #[derive(Clone, Debug)] -#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] + pub struct StringKey { /// The underlying reference counted string. str: ArcStr, @@ -122,6 +123,12 @@ impl From<&CStr> for StringKey { } } +impl ValueIdentifiable for StringKey { + fn value_identifier(&self) -> ValueIdentifier { + ValueIdentifier::new(self.hash as usize) + } +} + /// Converts a character to lowercased in a const safe way. const fn to_lower(c: u8) -> u8 { if c >= b'A' && c <= b'Z' { diff --git a/src/utils/value_identifier.rs b/src/utils/value_identifier.rs index 60cd3e6..0304f99 100644 --- a/src/utils/value_identifier.rs +++ b/src/utils/value_identifier.rs @@ -4,7 +4,7 @@ use std::sync::atomic::{AtomicUsize, Ordering}; static CURRENT: AtomicUsize = AtomicUsize::new(1); /// An extremely basic way to identify a piece of data. -#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)] +#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] #[repr(C)] pub struct ValueIdentifier(usize); @@ -14,6 +14,18 @@ impl Default for ValueIdentifier { } } +impl ValueIdentifier { + /// Creates an identifier by number. + pub(crate) fn new(v: usize) -> Self { + Self(v) + } + + /// Get the underlying numeric integer of the value + pub fn value(&self) -> usize { + self.0 + } +} + /// An object with a specific identifier. pub trait ValueIdentifiable { /// Get the identifier for the current object. diff --git a/tests/common/library_loader.rs b/tests/common/library_loader.rs index cacabbb..948499f 100755 --- a/tests/common/library_loader.rs +++ b/tests/common/library_loader.rs @@ -16,7 +16,7 @@ use pkmn_lib::dynamic_data::Gen7DamageLibrary; use pkmn_lib::dynamic_data::Gen7MiscLibrary; use pkmn_lib::script_implementations::wasm::script_resolver::WebAssemblyScriptResolver; use pkmn_lib::static_data::{ - Ability, AbilityLibrary, BattleItemCategory, DataLibrary, EffectParameter, Form, GrowthRateLibrary, Item, + Ability, AbilityLibrary, BattleItemCategory, DataLibrary, EffectParameter, Form, GrowthRateLibrary, ItemImpl, ItemLibrary, LearnableMoves, LibrarySettings, LookupGrowthRate, MoveData, MoveLibrary, Nature, NatureLibrary, SecondaryEffect, Species, StaticData, StaticStatisticSet, Statistic, TypeLibrary, }; @@ -117,7 +117,7 @@ pub fn load_items(path: &String, lib: &mut ItemLibrary) { lib.add( &name, - Arc::new(Item::new(&name, category, battle_category, price as i32, flags)), + Arc::new(ItemImpl::new(&name, category, battle_category, price as i32, flags)), ); } } diff --git a/tests/data/gen7_scripts.wasm b/tests/data/gen7_scripts.wasm index e183ff8..4ccdd18 100755 Binary files a/tests/data/gen7_scripts.wasm and b/tests/data/gen7_scripts.wasm differ