From 92ff5bd0a175cd19708501f48e906023f07a908c Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Sun, 19 May 2024 16:37:19 +0200 Subject: [PATCH] Update to rune 0.14, more tests --- Cargo.toml | 10 +- src/dynamic_data/models/pokemon.rs | 2 +- src/script_implementations/rune/script.rs | 28 +- .../rune/script_resolver.rs | 4 +- .../rune/wrappers/dynamic_data/battle.rs | 15 +- .../wrappers/dynamic_data/executing_move.rs | 12 +- .../wrappers/dynamic_data/learned_move.rs | 4 +- .../rune/wrappers/dynamic_data/mod.rs | 3 +- .../rune/wrappers/dynamic_data/pokemon.rs | 36 +- .../rune/wrappers/dynamic_data/turn_choice.rs | 12 +- .../rune/wrappers/mod.rs | 478 ++++++++++-------- .../rune/wrappers/parameters.rs | 7 +- .../rune/wrappers/static_data/ability.rs | 102 +++- .../rune/wrappers/static_data/form.rs | 278 +++++++++- .../rune/wrappers/static_data/growth_rate.rs | 54 +- .../rune/wrappers/static_data/item.rs | 32 +- .../wrappers/static_data/learnable_moves.rs | 6 +- .../wrappers/static_data/libraries/mod.rs | 6 +- .../static_data/libraries/nature_library.rs | 4 +- .../static_data/libraries/static_data.rs | 18 +- .../static_data/libraries/type_library.rs | 4 +- .../rune/wrappers/static_data/move_data.rs | 10 +- .../rune/wrappers/static_data/species.rs | 12 +- src/static_data/items.rs | 13 + src/static_data/mod.rs | 2 + src/static_data/species_data/form.rs | 84 +-- src/static_data/species_data/mod.rs | 1 + src/static_data/statistics.rs | 6 + tests/datatests/mod.rs | 6 +- 29 files changed, 862 insertions(+), 387 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 81e9706..6dea105 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,14 +51,14 @@ chrono = "0.4" rand = "0.8" rand_pcg = "0.3" hashbrown = "0.14" -indexmap = "2.0" +indexmap = "2.2" parking_lot = "0.12" serde = { version = "1.0", optional = true, features = ["derive"] } serde_repr = "0.1" serde-xml-rs = { version = "0.6", optional = true } -uuid = "1.5" +uuid = "1.8" paste = { version = "1.0" } -arcstr = { version = "1.1", features = ["std"] } +arcstr = { version = "1.2", features = ["std"] } enum-display-derive = "0.1" anyhow = "1.0" anyhow_ext = "0.2" @@ -66,12 +66,12 @@ thiserror = "1.0" stdext = "0.3" wasmer = { version = "4.2", optional = true, default-features = false, features = ["sys", "wat", "llvm"] } -rune = { version = "0.13.2", optional = true } +rune = { version = "0.14.0", optional = true, git = "https://github.com/rune-rs/rune" } [dev-dependencies] csv = "1.3" project-root = "0.2" -serde_yaml = "0.9" +serde_yml = "0.0.7" serde_json = "1.0" serde_plain = "1.0" # Allow us to assert whether floats are approximately a value diff --git a/src/dynamic_data/models/pokemon.rs b/src/dynamic_data/models/pokemon.rs index e2ad91a..ca446c5 100755 --- a/src/dynamic_data/models/pokemon.rs +++ b/src/dynamic_data/models/pokemon.rs @@ -427,7 +427,7 @@ impl Pokemon { .library .static_data() .abilities() - .get(ability) + .get(&ability) .ok_or(PkmnError::InvalidAbilityName { ability: ability.clone(), })?) diff --git a/src/script_implementations/rune/script.rs b/src/script_implementations/rune/script.rs index 3058aa8..1d0a46a 100644 --- a/src/script_implementations/rune/script.rs +++ b/src/script_implementations/rune/script.rs @@ -4,7 +4,7 @@ use crate::script_implementations::rune::RuneScriptType; use crate::static_data::Parameter; use crate::StringKey; use hashbrown::HashMap; -use rune::runtime::{Object, RuntimeContext, Shared, VmError, VmResult}; +use rune::runtime::{RuntimeContext, VmError, VmResult}; use rune::{Unit, Value}; use std::convert::TryFrom; use std::sync::atomic::{AtomicBool, AtomicUsize}; @@ -12,7 +12,7 @@ use std::sync::Arc; pub struct RuneScript { name: StringKey, - state: Shared, + state: Value, /// Returns an atomic bool for internal marking of deletion. This is currently only specifically /// used for deletion of a script while we are holding a reference to it (i.e. executing a script /// hook on it). @@ -34,7 +34,7 @@ unsafe impl Sync for RuneScript {} impl RuneScript { pub fn new( name: StringKey, - object: Shared, + object: Value, script_type: Arc, runtime: Arc, unit: Arc, @@ -50,7 +50,7 @@ impl RuneScript { } } - pub(crate) fn get_state(&self) -> Shared { self.state.clone() } + pub(crate) fn get_state(&self) -> Value { self.state.clone() } } impl Script for RuneScript { @@ -68,12 +68,12 @@ impl Script for RuneScript { if pars.is_empty() { return Ok(()); } - let state = self.state.clone(); + + let mut binding = self.state.clone().into_struct()?; + let state = binding.data_mut(); for par in pars { let key = rune::alloc::string::String::try_from(par.0.str())?; - state - .borrow_mut()? - .insert(key, parameter_to_rune_value(par.1.as_ref())?)?; + state.insert(key, parameter_to_rune_value(par.1.as_ref())?)?; } Ok(()) } @@ -87,8 +87,8 @@ impl Script for RuneScript { .execute( hash, vec![ - Value::Object(self.state.clone()), - Value::from(choice.wrap()), + rune::to_value(self.state.clone())?, + rune::to_value(choice.wrap())?, speed_handle.clone(), ], )? @@ -116,10 +116,10 @@ impl Script for RuneScript { vm.execute( hash, vec![ - Value::Object(self.state.clone()), - Value::from(move_data.wrap()), - Value::from(target.wrap()), - Value::from(hit), + self.state.clone(), + move_data.wrap(), + target.wrap(), + rune::to_value(hit)?, block_critical_handle.clone(), ], )?; diff --git a/src/script_implementations/rune/script_resolver.rs b/src/script_implementations/rune/script_resolver.rs index d675d6b..6403725 100644 --- a/src/script_implementations/rune/script_resolver.rs +++ b/src/script_implementations/rune/script_resolver.rs @@ -8,7 +8,7 @@ use hashbrown::HashMap; use rune::compile::meta::AssociatedKind; use rune::compile::{ComponentRef, MetaError}; use rune::diagnostics::Diagnostic; -use rune::runtime::{RuntimeContext, Shared}; +use rune::runtime::RuntimeContext; use rune::{Context, Diagnostics, Options, Source, Sources, Unit}; use std::any::Any; use std::convert::TryFrom; @@ -52,7 +52,7 @@ impl ScriptResolver for RuneScriptResolver { o.insert(rune::alloc::String::try_from("owner")?, owner_obj.into())?; } - let state = Shared::new(o)?; + let state = rune::to_value(o)?; let script = Arc::new(RuneScript::new( script_key.clone(), state, diff --git a/src/script_implementations/rune/wrappers/dynamic_data/battle.rs b/src/script_implementations/rune/wrappers/dynamic_data/battle.rs index 789ba62..2a3b4ae 100644 --- a/src/script_implementations/rune/wrappers/dynamic_data/battle.rs +++ b/src/script_implementations/rune/wrappers/dynamic_data/battle.rs @@ -1,7 +1,6 @@ use crate::dynamic_data::Battle; use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper}; -use rune::runtime::{AnyObj, Shared}; -use rune::Any; +use rune::{Any, Value}; pub fn register(module: &mut rune::Module) -> anyhow::Result<()> { module.ty::()?; @@ -27,10 +26,10 @@ impl_rune_wrapper!(&Battle, RuneBattle); impl RuneBattle { #[rune::function] - fn library(&self) -> Shared { self.0.library().wrap() } + fn library(&self) -> Value { self.0.library().wrap() } #[rune::function] - fn parties(&self) -> Vec> { self.0.parties().iter().map(|p| p.wrap()).collect() } + fn parties(&self) -> Vec { self.0.parties().iter().map(|p| p.wrap()).collect() } #[rune::function] fn can_flee(&self) -> bool { self.0.can_flee() } @@ -42,10 +41,10 @@ impl RuneBattle { fn pokemon_per_side(&self) -> u8 { self.0.pokemon_per_side() } #[rune::function] - fn sides(&self) -> Vec> { self.0.sides().iter().map(|s| s.wrap()).collect() } + fn sides(&self) -> Vec { self.0.sides().iter().map(|s| s.wrap()).collect() } #[rune::function] - fn random(&self) -> Shared { self.0.random().wrap() } + fn random(&self) -> Value { self.0.random().wrap() } #[rune::function] fn has_ended(&self) -> bool { self.0.has_ended() } @@ -54,9 +53,7 @@ impl RuneBattle { fn current_turn(&self) -> u32 { self.0.current_turn() } #[rune::function] - fn get_pokemon(&self, side: u8, index: u8) -> Option> { - self.0.get_pokemon(side, index).map(|v| v.wrap()) - } + fn get_pokemon(&self, side: u8, index: u8) -> Option { self.0.get_pokemon(side, index).map(|v| v.wrap()) } #[rune::function] fn set_weather(&self, weather: Option) -> anyhow::Result<()> { diff --git a/src/script_implementations/rune/wrappers/dynamic_data/executing_move.rs b/src/script_implementations/rune/wrappers/dynamic_data/executing_move.rs index 11ee3ea..9556b9c 100644 --- a/src/script_implementations/rune/wrappers/dynamic_data/executing_move.rs +++ b/src/script_implementations/rune/wrappers/dynamic_data/executing_move.rs @@ -2,7 +2,7 @@ use crate::dynamic_data::{ExecutingMove, HitData}; use crate::script_implementations::rune::wrappers::dynamic_data::pokemon::RunePokemon; use crate::script_implementations::rune::wrappers::dynamic_data::resolve_script_data; use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneWrapper}; -use rune::runtime::{AnyObj, Object, Shared}; +use rune::runtime::Value; use rune::Any; use std::sync::Arc; @@ -29,19 +29,19 @@ impl RuneExecutingMove { #[rune::function] fn number_of_hits(&self) -> u8 { self.0.number_of_hits() } #[rune::function] - fn user(&self) -> Shared { self.0.user().wrap() } + fn user(&self) -> Value { self.0.user().wrap() } #[rune::function] - fn chosen_move(&self) -> Shared { self.0.chosen_move().wrap() } + fn chosen_move(&self) -> Value { self.0.chosen_move().wrap() } #[rune::function] - fn use_move(&self) -> Shared { self.0.use_move().wrap() } + fn use_move(&self) -> Value { self.0.use_move().wrap() } #[rune::function] - fn script(&self) -> Option> { resolve_script_data(self.0.script()) } + fn script(&self) -> Option { resolve_script_data(self.0.script()) } #[rune::function] - fn get_hit_data(&self, for_target: RunePokemon, hit: u8) -> anyhow::Result> { + fn get_hit_data(&self, for_target: RunePokemon, hit: u8) -> anyhow::Result { self.0.get_hit_data(&for_target.0, hit).map(|hit_data| hit_data.wrap()) } } diff --git a/src/script_implementations/rune/wrappers/dynamic_data/learned_move.rs b/src/script_implementations/rune/wrappers/dynamic_data/learned_move.rs index a7f1c0f..9b2e44d 100644 --- a/src/script_implementations/rune/wrappers/dynamic_data/learned_move.rs +++ b/src/script_implementations/rune/wrappers/dynamic_data/learned_move.rs @@ -1,6 +1,6 @@ use crate::dynamic_data::{LearnedMove, MoveLearnMethod}; use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneWrapper}; -use rune::runtime::{AnyObj, Shared}; +use rune::runtime::Value; use rune::Any; use std::sync::Arc; @@ -24,7 +24,7 @@ impl_rune_wrapper!(&Arc, RuneLearnedMove); impl RuneLearnedMove { #[rune::function] - fn move_data(&self) -> Shared { self.0.move_data().wrap() } + fn move_data(&self) -> Value { self.0.move_data().wrap() } #[rune::function] fn max_pp(&self) -> u8 { self.0.max_pp() } diff --git a/src/script_implementations/rune/wrappers/dynamic_data/mod.rs b/src/script_implementations/rune/wrappers/dynamic_data/mod.rs index 76baf41..477d5eb 100644 --- a/src/script_implementations/rune/wrappers/dynamic_data/mod.rs +++ b/src/script_implementations/rune/wrappers/dynamic_data/mod.rs @@ -1,6 +1,5 @@ use crate::dynamic_data::ScriptContainer; use crate::script_implementations::rune::script::RuneScript; -use rune::runtime::{Object, Shared}; mod battle; mod battle_party; @@ -26,7 +25,7 @@ pub fn register(module: &mut rune::Module) -> anyhow::Result<()> { Ok(()) } -fn resolve_script_data(container: &ScriptContainer) -> Option> { +fn resolve_script_data(container: &ScriptContainer) -> Option { container .get() .map(|v| { diff --git a/src/script_implementations/rune/wrappers/dynamic_data/pokemon.rs b/src/script_implementations/rune/wrappers/dynamic_data/pokemon.rs index e071354..b6e159f 100644 --- a/src/script_implementations/rune/wrappers/dynamic_data/pokemon.rs +++ b/src/script_implementations/rune/wrappers/dynamic_data/pokemon.rs @@ -5,7 +5,7 @@ use crate::script_implementations::rune::wrappers::static_data::form::RuneForm; use crate::script_implementations::rune::wrappers::static_data::item::RuneItem; use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper}; use crate::static_data::{Gender, Statistic}; -use rune::runtime::{AnyObj, Object, Shared}; +use rune::runtime::Value; use rune::Any; pub fn register(module: &mut rune::Module) -> anyhow::Result<()> { @@ -69,25 +69,25 @@ pub struct RunePokemon(pub Pokemon); impl RunePokemon { #[rune::function] - fn library(&self) -> Shared { self.0.library().wrap() } + fn library(&self) -> Value { self.0.library().wrap() } #[rune::function] - fn species(&self) -> Shared { self.0.species().wrap() } + fn species(&self) -> Value { self.0.species().wrap() } #[rune::function] - fn form(&self) -> Shared { self.0.form().wrap() } + fn form(&self) -> Value { self.0.form().wrap() } #[rune::function] fn has_different_display_species(&self) -> bool { self.0.has_different_display_species() } #[rune::function] - fn display_species(&self) -> Shared { self.0.display_species().wrap() } + fn display_species(&self) -> Value { self.0.display_species().wrap() } #[rune::function] fn has_different_display_form(&self) -> bool { self.0.has_different_display_form() } #[rune::function] - fn display_form(&self) -> Shared { self.0.display_form().wrap() } + fn display_form(&self) -> Value { self.0.display_form().wrap() } #[rune::function] fn level(&self) -> LevelInt { self.0.level() } @@ -105,18 +105,16 @@ impl RunePokemon { fn coloring(&self) -> u8 { self.0.coloring() } #[rune::function] - fn held_item(&self) -> Option> { self.0.held_item().map(|v| v.wrap()) } + fn held_item(&self) -> Option { self.0.held_item().map(|v| v.wrap()) } #[rune::function] fn has_held_item(&self, key: RuneStringKey) -> bool { self.0.has_held_item(&key.0) } #[rune::function] - fn set_held_item(&mut self, key: RuneItem) -> Option> { - self.0.set_held_item(&key.0).map(|v| v.wrap()) - } + fn set_held_item(&mut self, key: RuneItem) -> Option { self.0.set_held_item(&key.0).map(|v| v.wrap()) } #[rune::function] - fn remove_held_item(&mut self) -> Option> { self.0.remove_held_item().map(|v| v.wrap()) } + fn remove_held_item(&mut self) -> Option { self.0.remove_held_item().map(|v| v.wrap()) } #[rune::function] fn consume_held_item(&mut self) -> anyhow::Result { self.0.consume_held_item() } @@ -149,19 +147,19 @@ impl RunePokemon { fn types(&self) -> Vec { self.0.types().iter().map(|v| u8::from(*v)).collect() } #[rune::function] - fn learned_moves(&self) -> Vec>> { + fn learned_moves(&self) -> Vec> { let l = self.0.learned_moves().read(); l.iter().map(|v| v.as_ref().map(|l| l.wrap())).collect() } #[rune::function] - fn flat_stats(&self) -> Shared { self.0.flat_stats().wrap() } + fn flat_stats(&self) -> Value { self.0.flat_stats().wrap() } #[rune::function] fn is_egg(&self) -> bool { self.0.is_egg() } #[rune::function] - fn boosted_stats(&self) -> Shared { self.0.boosted_stats().wrap() } + fn boosted_stats(&self) -> Value { self.0.boosted_stats().wrap() } #[rune::function] fn stat_boost(&self, stat: Statistic) -> i8 { self.0.stat_boost(stat) } @@ -178,7 +176,7 @@ impl RunePokemon { fn get_effort_value(&self, stat: Statistic) -> u8 { self.0.effort_values().get_stat(stat) } #[rune::function] - fn get_battle(&self) -> Option> { self.0.get_battle().map(|v| v.wrap()) } + fn get_battle(&self) -> Option { self.0.get_battle().map(|v| v.wrap()) } #[rune::function] fn get_battle_side_index(&self) -> Option { self.0.get_battle_side_index() } @@ -190,13 +188,13 @@ impl RunePokemon { fn is_ability_overridden(&self) -> bool { self.0.is_ability_overridden() } #[rune::function] - fn active_ability(&self) -> anyhow::Result> { self.0.active_ability().map(|v| v.wrap()) } + fn active_ability(&self) -> anyhow::Result { self.0.active_ability().map(|v| v.wrap()) } #[rune::function] fn allowed_experience_gain(&self) -> bool { self.0.allowed_experience_gain() } #[rune::function] - fn nature(&self) -> Shared { self.0.nature().wrap() } + fn nature(&self) -> Value { self.0.nature().wrap() } #[rune::function] fn change_form(&self, form: RuneForm) -> anyhow::Result<()> { self.0.change_form(&form.0) } @@ -219,10 +217,10 @@ impl RunePokemon { fn clear_status(&self) { self.0.clear_status() } #[rune::function] - fn status_script(&self) -> Option> { resolve_script_data(&self.0.status()) } + fn status_script(&self) -> Option { resolve_script_data(&self.0.status()) } #[rune::function] - fn ability_script(&self) -> Option> { resolve_script_data(&self.0.ability_script()) } + fn ability_script(&self) -> Option { resolve_script_data(&self.0.ability_script()) } } impl_rune_wrapper!(&Pokemon, RunePokemon); diff --git a/src/script_implementations/rune/wrappers/dynamic_data/turn_choice.rs b/src/script_implementations/rune/wrappers/dynamic_data/turn_choice.rs index a7a570d..564e001 100644 --- a/src/script_implementations/rune/wrappers/dynamic_data/turn_choice.rs +++ b/src/script_implementations/rune/wrappers/dynamic_data/turn_choice.rs @@ -1,6 +1,6 @@ use crate::dynamic_data::TurnChoice; use crate::script_implementations::rune::wrappers::RuneWrapper; -use rune::runtime::{AnyObj, Shared}; +use rune::runtime::Value; use rune::Any; use std::sync::Arc; @@ -62,7 +62,7 @@ impl RuneTurnChoice { } #[rune::function] - fn user(&self) -> Shared { self.get_turn_choice().user().wrap() } + fn user(&self) -> Value { self.get_turn_choice().user().wrap() } #[rune::function] fn speed(&self) -> u32 { self.get_turn_choice().speed() } @@ -75,7 +75,7 @@ impl RuneTurnChoice { } impl RuneWrapper for &Arc { - fn wrap(self) -> Shared { + fn wrap(self) -> Value { let o = match self.as_ref() { TurnChoice::Move(_) => RuneTurnChoice::Move(RuneMoveChoice(self.clone())), TurnChoice::Item(_) => RuneTurnChoice::Item(RuneItemChoice(self.clone())), @@ -83,7 +83,7 @@ impl RuneWrapper for &Arc { TurnChoice::Flee(_) => RuneTurnChoice::Flee(RuneFleeChoice(self.clone())), TurnChoice::Pass(_) => RuneTurnChoice::Pass(RunePassChoice(self.clone())), }; - Shared::new(AnyObj::new(o).unwrap()).unwrap() + rune::to_value(o).unwrap() } } @@ -96,7 +96,7 @@ impl RuneMoveChoice { } #[rune::function] - fn used_move(&self) -> Shared { self.move_choice().used_move().wrap() } + fn used_move(&self) -> Value { self.move_choice().used_move().wrap() } #[rune::function] fn target_side(&self) -> u8 { self.move_choice().target_side() } @@ -108,5 +108,5 @@ impl RuneMoveChoice { fn priority(&self) -> i8 { self.move_choice().priority() } #[rune::function] - fn user(&self) -> Shared { self.move_choice().user().wrap() } + fn user(&self) -> Value { self.move_choice().user().wrap() } } diff --git a/src/script_implementations/rune/wrappers/mod.rs b/src/script_implementations/rune/wrappers/mod.rs index 09bf8d0..0c2cf8b 100644 --- a/src/script_implementations/rune/wrappers/mod.rs +++ b/src/script_implementations/rune/wrappers/mod.rs @@ -1,5 +1,5 @@ use rune::alloc::fmt::TryWrite; -use rune::runtime::{AnyObj, Protocol, Shared, VmResult}; +use rune::runtime::{Protocol, VmResult}; use rune::{Any, Value}; use std::num::Saturating; @@ -8,7 +8,7 @@ mod parameters; mod static_data; pub trait RuneWrapper { - fn wrap(self) -> Shared; + fn wrap(self) -> Value; } pub fn module() -> anyhow::Result { @@ -33,6 +33,8 @@ pub fn module() -> anyhow::Result { module.ty::()?; module.function_meta(RuneStringKey::string_display)?; + module.associated_function(Protocol::PARTIAL_EQ, RuneStringKey::eq)?; + module.associated_function(Protocol::EQ, RuneStringKey::eq)?; parameters::register(&mut module)?; dynamic_data::register(&mut module)?; @@ -40,30 +42,24 @@ pub fn module() -> anyhow::Result { Ok(module) } -pub fn wrap_int_reference(value: i64) -> anyhow::Result { - Ok(Value::Any(Shared::new(AnyObj::new(RuneValueIntWrapper::new(value))?)?)) -} +pub fn wrap_int_reference(value: i64) -> anyhow::Result { Ok(rune::to_value(RuneValueIntWrapper::new(value))?) } pub fn wrap_bool_reference(value: bool) -> anyhow::Result { - Ok(Value::Any(Shared::new(AnyObj::new(RuneValueBoolWrapper::new(value))?)?)) + Ok(rune::to_value(RuneValueBoolWrapper::new(value))?) } pub fn get_int_reference_value(value: Value) -> anyhow::Result { - let obj = value.into_any().into_result()?; - let obj = obj.take()?; - let obj = match obj.downcast_borrow_ref::() { - Some(obj) => obj, - None => return Err(anyhow::anyhow!("Value is not a RuneValueIntWrapper")), + let obj = match value.into_any::() { + Ok(obj) => obj, + Err(_) => return Err(anyhow::anyhow!("Value is not a RuneValueIntWrapper")), }; Ok(obj.as_int()) } pub fn get_bool_reference_value(value: Value) -> anyhow::Result { - let obj = value.into_any().into_result()?; - let obj = obj.take()?; - let obj = match obj.downcast_borrow_ref::() { - Some(obj) => obj, - None => return Err(anyhow::anyhow!("Value is not a RuneValueBoolWrapper")), + let obj = match value.into_any::() { + Ok(obj) => obj, + Err(_) => return Err(anyhow::anyhow!("Value is not a RuneValueBoolWrapper")), }; Ok(obj.as_bool()) } @@ -71,9 +67,7 @@ pub fn get_bool_reference_value(value: Value) -> anyhow::Result { macro_rules! impl_rune_wrapper { ($t:ty, $wrapped_type:ident) => { impl crate::script_implementations::rune::wrappers::RuneWrapper for $t { - fn wrap(self) -> rune::runtime::Shared { - rune::runtime::Shared::new(rune::runtime::AnyObj::new($wrapped_type(self.clone())).unwrap()).unwrap() - } + fn wrap(self) -> rune::runtime::Value { rune::to_value($wrapped_type(self.clone())).unwrap() } } }; } @@ -82,6 +76,7 @@ use crate::StringKey; use impl_rune_wrapper; #[derive(Any, Clone)] +#[rune(name = RefInt)] struct RuneValueIntWrapper { value: Saturating, } @@ -106,10 +101,12 @@ impl RuneValueIntWrapper { fn sub_assign(&mut self, other: i64) { self.value -= other; } fn div_assign(&mut self, other: Value) { - match other { - Value::Integer(other) => self.value /= other, - Value::Float(other) => self.div_assign_f64(other), - _ => (), + match other.as_integer() { + Ok(other) => self.value /= other, + Err(_) => match other.as_float() { + Ok(other) => self.div_assign_f64(other), + Err(_) => (), + }, } } @@ -125,10 +122,12 @@ impl RuneValueIntWrapper { } fn mul_assign(&mut self, other: Value) { - match other { - Value::Integer(other) => self.value *= other, - Value::Float(other) => self.mul_assign_f64(other), - _ => (), + match other.as_integer() { + Ok(other) => self.value *= other, + Err(_) => match other.as_float() { + Ok(other) => self.mul_assign_f64(other), + Err(_) => (), + }, } } @@ -155,6 +154,7 @@ impl RuneValueIntWrapper { } #[derive(Any, Clone)] +#[rune(name = RefBool)] struct RuneValueBoolWrapper(bool); impl RuneValueBoolWrapper { @@ -178,6 +178,7 @@ impl RuneValueBoolWrapper { } #[derive(Any, Clone, Debug)] +#[rune(name = StringKey)] pub(super) struct RuneStringKey(pub StringKey); impl RuneStringKey { @@ -188,24 +189,39 @@ impl RuneStringKey { rune::vm_write!(f, "{}", self.0); VmResult::Ok(()) } + + fn eq(&self, b: Value) -> VmResult { + match b.borrow_string_ref() { + Ok(s) => VmResult::Ok(self.0 == StringKey::new(&s)), + Err(_) => { + let b = b.borrow_any_ref::(); + match b { + Ok(b) => VmResult::Ok(self.0 == b.0), + _ => VmResult::Ok(false), + } + } + } + } } impl RuneWrapper for &StringKey { - fn wrap(self) -> Shared { Shared::new(AnyObj::new(RuneStringKey(self.clone())).unwrap()).unwrap() } + fn wrap(self) -> Value { rune::to_value(RuneStringKey(self.clone())).unwrap() } } #[cfg(test)] -mod test { +mod tests { use super::*; + use anyhow::Result; + use rune::diagnostics::Diagnostic; use rune::{Context, Diagnostics, Options, Source, Vm}; use std::sync::Arc; - pub fn setup_script(script: &str) -> Vm { - let mut context = Context::with_default_modules().unwrap(); - context.install(module().unwrap()).unwrap(); + pub fn setup_script(script: &str) -> Result { + let mut context = Context::with_default_modules()?; + context.install(module()?)?; let mut sources = rune::Sources::new(); - sources.insert(Source::memory(script).unwrap()).unwrap(); + sources.insert(Source::memory(script)?)?; let mut diagnostics = Diagnostics::new(); let mut options = Options::default(); @@ -218,381 +234,431 @@ mod test { .with_context(&context) .with_diagnostics(&mut diagnostics) .with_options(&options) - .build() - .unwrap(); - if !diagnostics.is_empty() { - panic!("Diagnostics: {:?}", diagnostics); + .build(); + if !diagnostics.is_empty() && diagnostics.has_error() { + let error_message = diagnostics + .diagnostics() + .iter() + .filter_map(|d| match d { + Diagnostic::Fatal(f) => Some(f.to_string()), + _ => None, + }) + .collect::>() + .join("\n"); + + return Err(anyhow::anyhow!("Error building Rune script: {}", error_message)); } - Vm::new(Arc::new(context.runtime().unwrap()), Arc::new(unit)) + Ok(Vm::new(Arc::new(context.runtime()?), Arc::new(unit?))) } macro_rules! execute_vm { ($vm:expr, $func:expr, $val:expr) => {{ let args = vec![$val.clone()]; - $vm.execute([$func], args).unwrap().complete().into_result().unwrap() + $vm.execute([$func], args)?.complete().into_result()? }}; } + pub(crate) use execute_vm; + #[test] - fn test_int_wrapper_set_value() { + fn test_int_wrapper_set_value() -> Result<()> { let mut vm = setup_script( r#" pub fn test_int(a) { a.set_value(5); } "#, - ); - let val = wrap_int_reference(10).unwrap(); + )?; + let val = wrap_int_reference(10)?; execute_vm!(vm, "test_int", val); - let v = get_int_reference_value(val).unwrap(); + let v = get_int_reference_value(val)?; assert_eq!(v, 5); + Ok(()) } #[test] - fn test_int_wrapper_as_int() { + fn test_int_wrapper_as_int() -> Result<()> { let mut vm = setup_script( r#" - pub fn test_int(a) { - a.as_int() - } - "#, - ); - let val = wrap_int_reference(10).unwrap(); + pub fn test_int(a) { + a.as_int() + } + "#, + )?; + let val = wrap_int_reference(10)?; let res = execute_vm!(vm, "test_int", val); - let res = res.as_integer().unwrap(); + let res = res.as_integer()?; assert_eq!(res, 10); + Ok(()) } #[test] - fn test_int_wrapper_add() { + fn test_int_wrapper_add() -> Result<()> { let mut vm = setup_script( r#" - pub fn test_int(a) { - a += 5; - } - "#, - ); - let val = wrap_int_reference(10).unwrap(); + pub fn test_int(a) { + a += 5; + } + "#, + )?; + let val = wrap_int_reference(10)?; execute_vm!(vm, "test_int", val); - let v = get_int_reference_value(val).unwrap(); + let v = get_int_reference_value(val)?; assert_eq!(v, 15); + Ok(()) } #[test] - fn test_int_wrapper_add_overflow() { + fn test_int_wrapper_add_overflow() -> Result<()> { let mut vm = setup_script( r#" - pub fn test_int(a) { - a += 5; - } - "#, - ); - let val = wrap_int_reference(i64::MAX).unwrap(); + pub fn test_int(a) { + a += 5; + } + "#, + )?; + let val = wrap_int_reference(i64::MAX)?; execute_vm!(vm, "test_int", val); - let v = get_int_reference_value(val).unwrap(); + let v = get_int_reference_value(val)?; assert_eq!(v, i64::MAX); + Ok(()) } #[test] - fn test_int_wrapper_sub() { + fn test_int_wrapper_sub() -> Result<()> { let mut vm = setup_script( r#" - pub fn test_int(a) { - a -= 5; - } - "#, - ); - let val = wrap_int_reference(10).unwrap(); + pub fn test_int(a) { + a -= 5; + } + "#, + )?; + let val = wrap_int_reference(10)?; execute_vm!(vm, "test_int", val); - let v = get_int_reference_value(val).unwrap(); + let v = get_int_reference_value(val)?; assert_eq!(v, 5); + Ok(()) } #[test] - fn test_int_wrapper_underflow() { + fn test_int_wrapper_underflow() -> Result<()> { let mut vm = setup_script( r#" - pub fn test_int(a) { - a -= 5; - } - "#, - ); - let val = wrap_int_reference(i64::MIN).unwrap(); + pub fn test_int(a) { + a -= 5; + } + "#, + )?; + let val = wrap_int_reference(i64::MIN)?; execute_vm!(vm, "test_int", val); - let v = get_int_reference_value(val).unwrap(); + let v = get_int_reference_value(val)?; assert_eq!(v, i64::MIN); + Ok(()) } #[test] - fn test_int_wrapper_mul() { + fn test_int_wrapper_mul() -> Result<()> { let mut vm = setup_script( r#" - pub fn test_int(a) { - a *= 5; - } - "#, - ); - let val = wrap_int_reference(10).unwrap(); + pub fn test_int(a) { + a *= 5; + } + "#, + )?; + let val = wrap_int_reference(10)?; execute_vm!(vm, "test_int", val); - let v = get_int_reference_value(val).unwrap(); + let v = get_int_reference_value(val)?; assert_eq!(v, 50); + Ok(()) } #[test] - fn test_int_wrapper_mul_float() { + fn test_int_wrapper_mul_float() -> Result<()> { let mut vm = setup_script( r#" - pub fn test_int(a) { - a *= 0.5; - } - "#, - ); - let val = wrap_int_reference(10).unwrap(); + pub fn test_int(a) { + a *= 0.5; + } + "#, + )?; + let val = wrap_int_reference(10)?; execute_vm!(vm, "test_int", val); - let v = get_int_reference_value(val).unwrap(); + let v = get_int_reference_value(val)?; assert_eq!(v, 5); + Ok(()) } - #[test] - fn test_int_wrapper_mul_overflow() { + fn test_int_wrapper_mul_overflow() -> Result<()> { let mut vm = setup_script( r#" - pub fn test_int(a) { - a *= 5; - } - "#, - ); - let val = wrap_int_reference(i64::MAX).unwrap(); + pub fn test_int(a) { + a *= 5; + } + "#, + )?; + let val = wrap_int_reference(i64::MAX)?; execute_vm!(vm, "test_int", val); - let v = get_int_reference_value(val).unwrap(); + let v = get_int_reference_value(val)?; assert_eq!(v, i64::MAX); + Ok(()) } #[test] - fn test_int_wrapper_mul_float_overflow() { + fn test_int_wrapper_mul_float_overflow() -> Result<()> { let mut vm = setup_script( r#" - pub fn test_int(a) { - a *= 10.0; - } - "#, - ); - let val = wrap_int_reference(i64::MAX).unwrap(); + pub fn test_int(a) { + a *= 10.0; + } + "#, + )?; + let val = wrap_int_reference(i64::MAX)?; execute_vm!(vm, "test_int", val); - let v = get_int_reference_value(val).unwrap(); + let v = get_int_reference_value(val)?; assert_eq!(v, i64::MAX); + Ok(()) } #[test] - fn test_int_wrapper_mul_float_underflow() { + fn test_int_wrapper_mul_float_underflow() -> Result<()> { let mut vm = setup_script( r#" - pub fn test_int(a) { - a *= 10.0; - } - "#, - ); - let val = wrap_int_reference(i64::MIN).unwrap(); + pub fn test_int(a) { + a *= 10.0; + } + "#, + )?; + let val = wrap_int_reference(i64::MIN)?; execute_vm!(vm, "test_int", val); - let v = get_int_reference_value(val).unwrap(); + let v = get_int_reference_value(val)?; assert_eq!(v, i64::MIN); + Ok(()) } #[test] - fn test_int_wrapper_div() { + fn test_int_wrapper_div() -> Result<()> { let mut vm = setup_script( r#" - pub fn test_int(a) { - a /= 5; - } - "#, - ); - let val = wrap_int_reference(10).unwrap(); + pub fn test_int(a) { + a /= 5; + } + "#, + )?; + let val = wrap_int_reference(10)?; execute_vm!(vm, "test_int", val); - let v = get_int_reference_value(val).unwrap(); + let v = get_int_reference_value(val)?; assert_eq!(v, 2); + Ok(()) } #[test] - fn test_int_wrapper_div_float() { + fn test_int_wrapper_div_float() -> Result<()> { let mut vm = setup_script( r#" - pub fn test_int(a) { - a /= 0.5; - } - "#, - ); - let val = wrap_int_reference(10).unwrap(); + pub fn test_int(a) { + a /= 0.5; + } + "#, + )?; + let val = wrap_int_reference(10)?; execute_vm!(vm, "test_int", val); - let v = get_int_reference_value(val).unwrap(); + let v = get_int_reference_value(val)?; assert_eq!(v, 20); + Ok(()) } #[test] - fn test_int_wrapper_div_float_overflow() { + fn test_int_wrapper_div_float_overflow() -> Result<()> { let mut vm = setup_script( r#" - pub fn test_int(a) { - a /= 0.0001; - } - "#, - ); - let val = wrap_int_reference(i64::MAX).unwrap(); + pub fn test_int(a) { + a /= 0.0001; + } + "#, + )?; + let val = wrap_int_reference(i64::MAX)?; execute_vm!(vm, "test_int", val); - let v = get_int_reference_value(val).unwrap(); + let v = get_int_reference_value(val)?; assert_eq!(v, i64::MAX); + Ok(()) } #[test] - fn test_int_wrapper_div_float_underflow() { + fn test_int_wrapper_div_float_underflow() -> Result<()> { let mut vm = setup_script( r#" - pub fn test_int(a) { - a /= 0.0001; - } - "#, - ); - let val = wrap_int_reference(i64::MIN).unwrap(); + pub fn test_int(a) { + a /= 0.0001; + } + "#, + )?; + let val = wrap_int_reference(i64::MIN)?; execute_vm!(vm, "test_int", val); - let v = get_int_reference_value(val).unwrap(); + let v = get_int_reference_value(val)?; assert_eq!(v, i64::MIN); + Ok(()) } #[test] - fn test_int_wrapper_eq() { + fn test_int_wrapper_eq() -> Result<()> { let mut vm = setup_script( r#" - pub fn test_int(a) { - a == 5 - } - "#, - ); - let val = wrap_int_reference(5).unwrap(); + pub fn test_int(a) { + a == 5 + } + "#, + )?; + let val = wrap_int_reference(5)?; let res = execute_vm!(vm, "test_int", val); - let res = res.as_bool().unwrap(); + let res = res.as_bool()?; assert_eq!(res, true); + Ok(()) } #[test] - fn test_int_wrapper_ineq() { + fn test_int_wrapper_ineq() -> Result<()> { let mut vm = setup_script( r#" - pub fn test_int(a) { - a == 5 - } - "#, - ); - let val = wrap_int_reference(6).unwrap(); + pub fn test_int(a) { + a == 5 + } + "#, + )?; + let val = wrap_int_reference(6)?; let res = execute_vm!(vm, "test_int", val); - let res = res.as_bool().unwrap(); + let res = res.as_bool()?; assert_eq!(res, false); + Ok(()) } #[test] - fn test_int_wrapper_string_display() { + fn test_int_wrapper_string_display() -> Result<()> { let mut vm = setup_script( r#" - pub fn test_int(a) { - `${a}` - } - "#, - ); - let val = wrap_int_reference(5).unwrap(); + pub fn test_int(a) { + `${a}` + } + "#, + )?; + let val = wrap_int_reference(5)?; let res = execute_vm!(vm, "test_int", val); - let res = res.into_string().unwrap().take().unwrap().into_std(); + let res = res.into_string()?.into_std(); assert_eq!(res, "5"); + Ok(()) } #[test] - fn test_bool_wrapper_set_value() { + fn test_bool_wrapper_set_value() -> Result<()> { let mut vm = setup_script( r#" pub fn test_bool(a) { a.set_value(true); } "#, - ); - let val = wrap_bool_reference(false).unwrap(); + )?; + let val = wrap_bool_reference(false)?; execute_vm!(vm, "test_bool", val); - let v = get_bool_reference_value(val).unwrap(); + let v = get_bool_reference_value(val)?; assert_eq!(v, true); + Ok(()) } #[test] - fn test_bool_wrapper_as_bool() { + fn test_bool_wrapper_as_bool() -> Result<()> { let mut vm = setup_script( r#" pub fn test_bool(a) { a.as_bool() } "#, - ); - let val = wrap_bool_reference(true).unwrap(); + )?; + let val = wrap_bool_reference(true)?; let res = execute_vm!(vm, "test_bool", val); - let res = res.as_bool().unwrap(); + let res = res.as_bool()?; assert_eq!(res, true); + Ok(()) } #[test] - fn test_bool_wrapper_eq() { + fn test_bool_wrapper_eq() -> Result<()> { let mut vm = setup_script( r#" pub fn test_bool(a) { a == true } "#, - ); - let val = wrap_bool_reference(true).unwrap(); + )?; + let val = wrap_bool_reference(true)?; let res = execute_vm!(vm, "test_bool", val); - let res = res.as_bool().unwrap(); + let res = res.as_bool()?; assert_eq!(res, true); + Ok(()) } #[test] - fn test_bool_wrapper_ineq() { + fn test_bool_wrapper_ineq() -> Result<()> { let mut vm = setup_script( r#" pub fn test_bool(a) { a == true } "#, - ); - let val = wrap_bool_reference(false).unwrap(); + )?; + let val = wrap_bool_reference(false)?; let res = execute_vm!(vm, "test_bool", val); - let res = res.as_bool().unwrap(); + let res = res.as_bool()?; assert_eq!(res, false); + Ok(()) } #[test] - fn test_bool_wrapper_string_display() { + fn test_bool_wrapper_string_display() -> Result<()> { let mut vm = setup_script( r#" pub fn test_bool(a) { `${a}` } "#, - ); - let val = wrap_bool_reference(true).unwrap(); + )?; + let val = wrap_bool_reference(true)?; let res = execute_vm!(vm, "test_bool", val); - let res = res.into_string().unwrap().take().unwrap().into_std(); + let res = res.into_string()?.into_std(); assert_eq!(res, "true"); + Ok(()) } #[test] - fn test_string_key_wrapper_string_display() { + fn test_string_key_wrapper_string_display() -> Result<()> { let mut vm = setup_script( r#" pub fn test_string_key(a) { `${a}` } "#, - ); - let val = RuneStringKey::new(StringKey::from("test")); - let val = Shared::new(AnyObj::new(val).unwrap()).unwrap(); - let arg = Value::Any(val); + )?; + let val = StringKey::from("test"); + let arg = val.wrap(); let res = execute_vm!(vm, "test_string_key", arg); - let res = res.into_string().unwrap().take().unwrap().into_std(); + let res = res.into_string()?.into_std(); assert_eq!(res, "test"); + Ok(()) + } + + #[test] + fn test_string_key_wrapper_eq() -> Result<()> { + let mut vm = setup_script( + r#" + pub fn test_string_key(a) { + a == "test" + } + "#, + )?; + let val = StringKey::from("test"); + let arg = val.wrap(); + let res = execute_vm!(vm, "test_string_key", arg); + let res = res.as_bool()?; + assert_eq!(res, true); + Ok(()) } } diff --git a/src/script_implementations/rune/wrappers/parameters.rs b/src/script_implementations/rune/wrappers/parameters.rs index 3b9b756..a8d10e3 100644 --- a/src/script_implementations/rune/wrappers/parameters.rs +++ b/src/script_implementations/rune/wrappers/parameters.rs @@ -1,6 +1,6 @@ use crate::script_implementations::rune::wrappers::{RuneStringKey, RuneWrapper}; use crate::static_data::Parameter; -use rune::runtime::{AnyObj, Shared}; +use rune::runtime::Value; use rune::Any; use std::ops::Deref; use std::sync::Arc; @@ -11,6 +11,7 @@ pub fn register(module: &mut rune::Module) -> anyhow::Result<()> { } #[derive(Debug, Any)] +#[rune(name = Parameter)] pub(super) enum RuneParameter { Int(#[rune(get)] i32), Float(#[rune(get)] f32), @@ -19,13 +20,13 @@ pub(super) enum RuneParameter { } impl RuneWrapper for &Arc { - fn wrap(self) -> Shared { + fn wrap(self) -> Value { let p = match self.deref() { Parameter::Bool(b) => RuneParameter::Bool(*b), Parameter::Int(i) => RuneParameter::Int(*i as i32), Parameter::Float(f) => RuneParameter::Float(*f), Parameter::String(s) => RuneParameter::String(RuneStringKey::new(s.clone())), }; - Shared::new(AnyObj::new(p).unwrap()).unwrap() + rune::to_value(p).unwrap() } } diff --git a/src/script_implementations/rune/wrappers/static_data/ability.rs b/src/script_implementations/rune/wrappers/static_data/ability.rs index 102478e..a32c915 100644 --- a/src/script_implementations/rune/wrappers/static_data/ability.rs +++ b/src/script_implementations/rune/wrappers/static_data/ability.rs @@ -1,6 +1,7 @@ use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper}; use crate::static_data::Ability; -use rune::runtime::{AnyObj, Shared}; +use crate::StringKey; +use rune::runtime::Value; use rune::Any; use std::sync::Arc; @@ -19,16 +20,101 @@ impl_rune_wrapper!(&Arc, RuneAbility); impl RuneAbility { #[rune::function] - fn name(&self) -> Shared { self.0.name().wrap() } + fn name(&self) -> Value { self.0.name().wrap() } #[rune::function] - fn effect(&self) -> Shared { self.0.effect().wrap() } + fn effect(&self) -> Value { self.0.effect().wrap() } - #[rune::function(vm_result)] - fn get_parameter(&self, key: RuneStringKey) -> Option> { - match self.0.parameters().get(&key.0) { - None => None, - Some(p) => Some(p.wrap()), + #[rune::function] + fn get_parameter(&self, key: Value) -> Option { + if let Ok(s) = key.borrow_string_ref() { + return self.0.parameters().get(&StringKey::new(&s)).map(|v| v.wrap()); + } + if let Ok(v) = key.into_any::() { + self.0.parameters().get(&v.0).map(|v| v.wrap()) + } else { + None } } } + +#[cfg(test)] +mod tests { + use super::super::super::tests::{execute_vm, setup_script}; + use super::*; + use crate::static_data::tests::MockAbility; + use crate::static_data::Parameter; + use hashbrown::HashMap; + + #[test] + fn test_ability_name() -> anyhow::Result<()> { + let mut vm = setup_script( + r#" + pub fn test_ability(ability) { + let name = ability.name(); + assert_eq!(name, "TestAbility"); + } + "#, + )?; + let mut ability = MockAbility::new(); + ability.expect_name().once().return_const(StringKey::new("TestAbility")); + let ability: Arc = Arc::new(ability); + let wrapped = ability.wrap(); + execute_vm!(&mut vm, "test_ability", wrapped); + Ok(()) + } + + #[test] + fn test_ability_effect() -> anyhow::Result<()> { + let mut vm = setup_script( + r#" + pub fn test_ability(ability) { + let effect = ability.effect(); + assert_eq!(effect, "TestEffect"); + } + "#, + )?; + let mut ability = MockAbility::new(); + ability + .expect_effect() + .once() + .return_const(StringKey::new("TestEffect")); + let ability: Arc = Arc::new(ability); + let wrapped = ability.wrap(); + execute_vm!(&mut vm, "test_ability", wrapped); + Ok(()) + } + + #[test] + fn test_ability_get_parameter() -> anyhow::Result<()> { + let mut vm = setup_script( + r#" + pub fn test_ability(ability) { + let value = ability.get_parameter("test_key"); + match value { + Some(v) => { + match v { + Parameter::String(s) => assert_eq!(s, "TestValue"), + _ => panic!("Invalid value type"), + } + } + None => panic!("Value not found"), + } + } + "#, + )?; + let mut ability = MockAbility::new(); + ability.expect_parameters().once().return_const({ + let mut map = HashMap::new(); + map.insert( + StringKey::new("test_key"), + Arc::new(Parameter::String(StringKey::new("TestValue"))), + ); + map + }); + let a: Arc = Arc::new(ability); + let wrapped = a.wrap(); + execute_vm!(&mut vm, "test_ability", wrapped); + Ok(()) + } +} diff --git a/src/script_implementations/rune/wrappers/static_data/form.rs b/src/script_implementations/rune/wrappers/static_data/form.rs index db0290a..8126731 100644 --- a/src/script_implementations/rune/wrappers/static_data/form.rs +++ b/src/script_implementations/rune/wrappers/static_data/form.rs @@ -1,6 +1,7 @@ use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper}; use crate::static_data::{AbilityIndex, Form, Statistic}; -use rune::runtime::{AnyObj, Shared}; +use crate::StringKey; +use rune::runtime::Value; use rune::Any; use std::sync::Arc; @@ -22,13 +23,14 @@ pub fn register(module: &mut rune::Module) -> anyhow::Result<()> { } #[derive(Debug, Any)] +#[rune(name = Form)] pub struct RuneForm(pub Arc); impl_rune_wrapper!(&Arc, RuneForm); impl RuneForm { #[rune::function] - fn name(&self) -> Shared { self.0.name().wrap() } + fn name(&self) -> Value { self.0.name().wrap() } #[rune::function] fn height(&self) -> f32 { self.0.height() } @@ -40,28 +42,286 @@ impl RuneForm { fn base_experience(&self) -> u32 { self.0.base_experience() } #[rune::function] - fn types(&self) -> Vec { self.0.types().iter().map(|t| u8::from(*t)).collect() } + fn types(&self) -> Vec { self.0.types().iter().map(|t| u8::from(*t) as i64).collect() } #[rune::function] - fn base_stats(&self) -> Shared { self.0.base_stats().wrap() } + fn base_stats(&self) -> Value { self.0.base_stats().wrap() } #[rune::function] - fn abilities(&self) -> Vec> { self.0.abilities().iter().map(|a| a.wrap()).collect() } + fn abilities(&self) -> Vec { self.0.abilities().iter().map(|a| a.wrap()).collect() } #[rune::function] - fn hidden_abilities(&self) -> Vec> { self.0.hidden_abilities().iter().map(|a| a.wrap()).collect() } + fn hidden_abilities(&self) -> Vec { self.0.hidden_abilities().iter().map(|a| a.wrap()).collect() } #[rune::function] - fn has_flag(&self, key: &RuneStringKey) -> bool { self.0.has_flag(&key.0) } + fn has_flag(&self, key: Value) -> bool { + if let Ok(s) = key.borrow_string_ref() { + return self.0.has_flag(&StringKey::new(&s)); + } + if let Ok(v) = key.into_any::() { + return self.0.has_flag(&v.0); + } + false + } #[rune::function] - fn get_type(&self, index: usize) -> anyhow::Result { self.0.get_type(index).map(|t| u8::from(t)) } + fn get_type(&self, index: usize) -> anyhow::Result { self.0.get_type(index).map(|t| u8::from(t) as i64) } #[rune::function] fn get_base_stat(&self, statistic: Statistic) -> u16 { self.0.get_base_stat(statistic) } #[rune::function] - fn get_ability(&self, hidden: bool, index: u8) -> anyhow::Result> { + fn get_ability(&self, hidden: bool, index: i64) -> anyhow::Result { + if index > u8::MAX as i64 || index < 0 { + return Err(anyhow::anyhow!("Index out of bounds")); + } + let index = index as u8; self.0.get_ability(AbilityIndex { hidden, index }).map(|a| a.wrap()) } } + +#[cfg(test)] +mod tests { + use super::super::super::tests::{execute_vm, setup_script}; + use super::*; + use crate::static_data::tests::MockForm; + use crate::static_data::{StaticStatisticSet, TypeIdentifier}; + + #[test] + fn test_form_name() -> anyhow::Result<()> { + let mut vm = setup_script( + r#" + pub fn test_form(form) { + let name = form.name(); + assert_eq!(name, "TestForm"); + } + "#, + )?; + let mut form = MockForm::new(); + form.expect_name().once().return_const(StringKey::new("TestForm")); + let form: Arc = Arc::new(form); + let wrapped = form.wrap(); + execute_vm!(&mut vm, "test_form", wrapped); + Ok(()) + } + + #[test] + fn test_form_height() -> anyhow::Result<()> { + let mut vm = setup_script( + r#" + pub fn test_form(form) { + let height = form.height(); + assert_eq!(height, 1.0); + } + "#, + )?; + let mut form = MockForm::new(); + form.expect_height().once().return_const(1.0); + let form: Arc = Arc::new(form); + let wrapped = form.wrap(); + execute_vm!(&mut vm, "test_form", wrapped); + Ok(()) + } + + #[test] + fn test_form_weight() -> anyhow::Result<()> { + let mut vm = setup_script( + r#" + pub fn test_form(form) { + let weight = form.weight(); + assert_eq!(weight, 1.0); + } + "#, + )?; + let mut form = MockForm::new(); + form.expect_weight().once().return_const(1.0); + let form: Arc = Arc::new(form); + let wrapped = form.wrap(); + execute_vm!(&mut vm, "test_form", wrapped); + Ok(()) + } + + #[test] + fn test_form_base_experience() -> anyhow::Result<()> { + let mut vm = setup_script( + r#" + pub fn test_form(form) { + let base_experience = form.base_experience(); + assert_eq!(base_experience, 1); + } + "#, + )?; + let mut form = MockForm::new(); + form.expect_base_experience().once().return_const(1u32); + let form: Arc = Arc::new(form); + let wrapped = form.wrap(); + execute_vm!(&mut vm, "test_form", wrapped); + Ok(()) + } + + #[test] + fn test_form_types() -> anyhow::Result<()> { + let mut vm = setup_script( + r#" + pub fn test_form(form) { + let types = form.types(); + assert_eq!(types[0], 1); + assert_eq!(types[1], 2); + } + "#, + )?; + let mut form = MockForm::new(); + form.expect_types() + .once() + .return_const(vec![TypeIdentifier::from(1u8), TypeIdentifier::from(2u8)]); + let form: Arc = Arc::new(form); + let wrapped = form.wrap(); + execute_vm!(&mut vm, "test_form", wrapped); + Ok(()) + } + + #[test] + fn test_form_base_stats() -> anyhow::Result<()> { + let mut vm = setup_script( + r#" + pub fn test_form(form) { + let base_stats = form.base_stats(); + assert_eq!(base_stats.hp(), 1); + assert_eq!(base_stats.attack(), 2); + assert_eq!(base_stats.defense(), 3); + assert_eq!(base_stats.special_attack(), 4); + assert_eq!(base_stats.special_defense(), 5); + assert_eq!(base_stats.speed(), 6); + } + "#, + )?; + let mut form = MockForm::new(); + form.expect_base_stats() + .once() + .return_const(Arc::new(StaticStatisticSet::::new(1, 2, 3, 4, 5, 6))); + let form: Arc = Arc::new(form); + let wrapped = form.wrap(); + execute_vm!(&mut vm, "test_form", wrapped); + Ok(()) + } + + #[test] + fn test_form_abilities() -> anyhow::Result<()> { + let mut vm = setup_script( + r#" + pub fn test_form(form) { + let abilities = form.abilities(); + assert_eq!(abilities.len(), 1); + assert_eq!(abilities[0], "TestAbility"); + } + "#, + )?; + let mut form = MockForm::new(); + form.expect_abilities() + .once() + .return_const(vec![StringKey::new("TestAbility")]); + let form: Arc = Arc::new(form); + let wrapped = form.wrap(); + execute_vm!(&mut vm, "test_form", wrapped); + Ok(()) + } + + #[test] + fn test_form_hidden_abilities() -> anyhow::Result<()> { + let mut vm = setup_script( + r#" + pub fn test_form(form) { + let abilities = form.hidden_abilities(); + assert_eq!(abilities.len(), 1); + assert_eq!(abilities[0], "TestAbility"); + } + "#, + )?; + let mut form = MockForm::new(); + form.expect_hidden_abilities() + .once() + .return_const(vec![StringKey::new("TestAbility")]); + let form: Arc = Arc::new(form); + let wrapped = form.wrap(); + execute_vm!(&mut vm, "test_form", wrapped); + Ok(()) + } + + #[test] + fn test_form_has_flag() -> anyhow::Result<()> { + let mut vm = setup_script( + r#" + pub fn test_form(form) { + let has_flag = form.has_flag("test_key"); + assert_eq!(has_flag, true); + } + "#, + )?; + let mut form = MockForm::new(); + form.expect_has_flag().once().return_const(true); + let form: Arc = Arc::new(form); + let wrapped = form.wrap(); + execute_vm!(&mut vm, "test_form", wrapped); + Ok(()) + } + + #[test] + fn test_form_get_type() -> anyhow::Result<()> { + let mut vm = setup_script( + r#" + pub fn test_form(form) { + let type_id = form.get_type(0)?; + assert_eq!(type_id, 1); + } + "#, + )?; + let mut form = MockForm::new(); + form.expect_get_type() + .once() + .returning(|_| Ok(TypeIdentifier::from(1u8))); + let form: Arc = Arc::new(form); + let wrapped = form.wrap(); + execute_vm!(&mut vm, "test_form", wrapped); + Ok(()) + } + + #[test] + fn test_form_get_base_stat() -> anyhow::Result<()> { + let mut vm = setup_script( + r#" + pub fn test_form(form) { + let base_stat = form.get_base_stat(Statistic::HP); + assert_eq!(base_stat, 1); + } + "#, + )?; + let mut form = MockForm::new(); + form.expect_get_base_stat() + .once() + .return_const(StaticStatisticSet::::new(1, 2, 3, 4, 5, 6).hp()); + let form: Arc = Arc::new(form); + let wrapped = form.wrap(); + execute_vm!(&mut vm, "test_form", wrapped); + Ok(()) + } + + #[test] + fn test_form_get_ability() -> anyhow::Result<()> { + let mut vm = setup_script( + r#" + pub fn test_form(form) { + let ability = form.get_ability(false, 0)?; + assert_eq!(ability, "TestAbility"); + } + "#, + )?; + let mut form = MockForm::new(); + form.expect_get_ability() + .once() + .returning(move |_| Ok(StringKey::new("TestAbility"))); + let form: Arc = Arc::new(form); + let wrapped = form.wrap(); + execute_vm!(&mut vm, "test_form", wrapped); + Ok(()) + } +} diff --git a/src/script_implementations/rune/wrappers/static_data/growth_rate.rs b/src/script_implementations/rune/wrappers/static_data/growth_rate.rs index a589475..9681c80 100644 --- a/src/script_implementations/rune/wrappers/static_data/growth_rate.rs +++ b/src/script_implementations/rune/wrappers/static_data/growth_rate.rs @@ -21,7 +21,59 @@ impl RuneGrowthRate { fn calculate_level(&self, experience: u32) -> i32 { self.0.calculate_level(experience) as i32 } #[rune::function] - fn calculate_experience(&self, level: LevelInt) -> Result { + fn calculate_experience(&self, level: i64) -> Result { + if level < 0 { + return Err("Level cannot be negative".to_string()); + } + if level > LevelInt::MAX as i64 { + return Err(format!("Level cannot be greater than {}", LevelInt::MAX)); + } + let level = level as LevelInt; + self.0.calculate_experience(level).map_err(|e| e.to_string()) } } + +#[cfg(test)] +mod tests { + use super::super::super::tests::{execute_vm, setup_script}; + use super::*; + use crate::script_implementations::rune::wrappers::RuneWrapper; + use crate::static_data::tests::MockGrowthRate; + + #[test] + fn test_calculate_level() -> anyhow::Result<()> { + let mut vm = setup_script( + r#" + pub fn test_growth_rate(growth_rate) { + let level = growth_rate.calculate_level(10); + assert_eq!(level, 10); + } + "#, + )?; + let mut growth_rate = MockGrowthRate::new(); + growth_rate.expect_calculate_level().returning(|_| 10); + let growth_rate: Arc = Arc::new(growth_rate); + let wrapped = growth_rate.wrap(); + execute_vm!(&mut vm, "test_growth_rate", wrapped); + Ok(()) + } + + #[test] + fn test_calculate_experience() -> anyhow::Result<()> { + let mut vm = setup_script( + r#" + pub fn test_growth_rate(growth_rate) { + let experience = growth_rate.calculate_experience(10)?; + assert_eq!(experience, 10); + } + "#, + )?; + let mut growth_rate = MockGrowthRate::new(); + growth_rate.expect_calculate_experience().returning(|_| Ok(10)); + let growth_rate: Arc = Arc::new(growth_rate); + let wrapped = growth_rate.wrap(); + execute_vm!(&mut vm, "test_growth_rate", wrapped); + Ok(()) + } +} diff --git a/src/script_implementations/rune/wrappers/static_data/item.rs b/src/script_implementations/rune/wrappers/static_data/item.rs index f17b23e..3aae64d 100644 --- a/src/script_implementations/rune/wrappers/static_data/item.rs +++ b/src/script_implementations/rune/wrappers/static_data/item.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use rune::runtime::{AnyObj, Shared}; +use rune::runtime::Value; use rune::Any; use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper}; @@ -28,7 +28,7 @@ impl_rune_wrapper!(&Arc, RuneItem); impl RuneItem { #[rune::function] - fn name(&self) -> Shared { self.0.name().clone().wrap() } + fn name(&self) -> Value { self.0.name().clone().wrap() } #[rune::function] fn category(&self) -> ItemCategory { self.0.category() } @@ -40,8 +40,34 @@ impl RuneItem { fn price(&self) -> i32 { self.0.price() } #[rune::function] - fn flags(&self) -> Vec> { self.0.flags().iter().map(|s| s.clone().wrap()).collect() } + fn flags(&self) -> Vec { self.0.flags().iter().map(|s| s.clone().wrap()).collect() } #[rune::function] fn has_flag(&self, key: &RuneStringKey) -> bool { self.0.has_flag(&key.0) } } + +#[cfg(test)] +mod tests { + use super::super::super::tests::{execute_vm, setup_script}; + use super::*; + use crate::static_data::tests::MockItem; + use crate::StringKey; + + #[test] + fn test_get_name() -> anyhow::Result<()> { + let mut vm = setup_script( + r#" + pub fn test_item(item) { + let name = item.name(); + assert_eq!(name, "Test Item"); + } + "#, + )?; + let mut item = MockItem::new(); + item.expect_name().once().return_const(StringKey::new("Test Item")); + let item: Arc = Arc::new(item); + let wrapped = item.wrap(); + execute_vm!(&mut vm, "test_item", wrapped); + Ok(()) + } +} diff --git a/src/script_implementations/rune/wrappers/static_data/learnable_moves.rs b/src/script_implementations/rune/wrappers/static_data/learnable_moves.rs index 47bc6a1..228f45f 100644 --- a/src/script_implementations/rune/wrappers/static_data/learnable_moves.rs +++ b/src/script_implementations/rune/wrappers/static_data/learnable_moves.rs @@ -1,7 +1,7 @@ use crate::defines::LevelInt; use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper}; use crate::static_data::LearnableMoves; -use rune::runtime::{AnyObj, Shared}; +use rune::runtime::Value; use rune::Any; use std::sync::Arc; @@ -20,14 +20,14 @@ impl_rune_wrapper!(&Arc, RuneLearnableMoves); impl RuneLearnableMoves { #[rune::function] - fn get_learned_by_level(&self, level: LevelInt) -> Option>> { + fn get_learned_by_level(&self, level: LevelInt) -> Option> { self.0 .get_learned_by_level(level) .map(|v| v.into_iter().map(|s| s.wrap()).collect()) } #[rune::function] - fn get_distinct_level_moves(&self) -> Vec> { + fn get_distinct_level_moves(&self) -> Vec { self.0 .get_distinct_level_moves() .into_iter() diff --git a/src/script_implementations/rune/wrappers/static_data/libraries/mod.rs b/src/script_implementations/rune/wrappers/static_data/libraries/mod.rs index 2a900fd..7c30c7b 100644 --- a/src/script_implementations/rune/wrappers/static_data/libraries/mod.rs +++ b/src/script_implementations/rune/wrappers/static_data/libraries/mod.rs @@ -6,7 +6,7 @@ mod type_library; use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper}; use crate::static_data::{AbilityLibrary, ItemLibrary, MoveLibrary, SpeciesLibrary}; -use rune::runtime::{AnyObj, Shared}; +use rune::runtime::Value; use std::sync::Arc; pub fn register(module: &mut rune::Module) -> anyhow::Result<()> { @@ -49,13 +49,13 @@ macro_rules! impl_rune_data_library_wrapper { impl $t { #[rune::function] - fn get(&self, key: &RuneStringKey) -> Option> { self.0.get(&key.0).map(|v| v.wrap()) } + fn get(&self, key: &RuneStringKey) -> Option { self.0.get(&key.0).map(|v| v.wrap()) } #[rune::function] fn len(&self) -> usize { self.0.len() } #[rune::function] - fn get_key_by_index(&self, index: usize) -> Option> { + fn get_key_by_index(&self, index: usize) -> Option { self.0.get_key_by_index(index).map(|v| v.wrap()) } } diff --git a/src/script_implementations/rune/wrappers/static_data/libraries/nature_library.rs b/src/script_implementations/rune/wrappers/static_data/libraries/nature_library.rs index 5b5d920..f0c1159 100644 --- a/src/script_implementations/rune/wrappers/static_data/libraries/nature_library.rs +++ b/src/script_implementations/rune/wrappers/static_data/libraries/nature_library.rs @@ -1,7 +1,7 @@ use crate::script_implementations::rune::wrappers::static_data::nature::RuneNature; use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper}; use crate::static_data::NatureLibrary; -use rune::runtime::{AnyObj, Shared}; +use rune::runtime::Value; use std::sync::Arc; pub fn register(module: &mut rune::Module) -> anyhow::Result<()> { @@ -18,7 +18,7 @@ impl_rune_wrapper!(&Arc, RuneNatureLibrary); impl RuneNatureLibrary { #[rune::function] - fn get_nature(&self, key: RuneStringKey) -> Option> { self.0.get_nature(&key.0).map(|v| v.wrap()) } + fn get_nature(&self, key: RuneStringKey) -> Option { self.0.get_nature(&key.0).map(|v| v.wrap()) } #[rune::function] fn get_nature_name(&self, nature: &RuneNature) -> RuneStringKey { diff --git a/src/script_implementations/rune/wrappers/static_data/libraries/static_data.rs b/src/script_implementations/rune/wrappers/static_data/libraries/static_data.rs index fc0acaa..d36fc80 100644 --- a/src/script_implementations/rune/wrappers/static_data/libraries/static_data.rs +++ b/src/script_implementations/rune/wrappers/static_data/libraries/static_data.rs @@ -1,6 +1,6 @@ use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneWrapper}; use crate::static_data::StaticData; -use rune::runtime::{AnyObj, Shared}; +use rune::runtime::Value; use std::sync::Arc; pub fn register(module: &mut rune::Module) -> anyhow::Result<()> { @@ -23,26 +23,26 @@ impl_rune_wrapper!(&Arc, RuneStaticData); impl RuneStaticData { #[rune::function] - fn settings(&self) -> Shared { self.0.settings().wrap() } + fn settings(&self) -> Value { self.0.settings().wrap() } #[rune::function] - fn species(&self) -> Shared { self.0.species().wrap() } + fn species(&self) -> Value { self.0.species().wrap() } #[rune::function] - fn moves(&self) -> Shared { self.0.moves().wrap() } + fn moves(&self) -> Value { self.0.moves().wrap() } #[rune::function] - fn items(&self) -> Shared { self.0.items().wrap() } + fn items(&self) -> Value { self.0.items().wrap() } #[rune::function] - fn growth_rates(&self) -> Shared { self.0.growth_rates().wrap() } + fn growth_rates(&self) -> Value { self.0.growth_rates().wrap() } #[rune::function] - fn types(&self) -> Shared { self.0.types().wrap() } + fn types(&self) -> Value { self.0.types().wrap() } #[rune::function] - fn natures(&self) -> Shared { self.0.natures().wrap() } + fn natures(&self) -> Value { self.0.natures().wrap() } #[rune::function] - fn abilities(&self) -> Shared { self.0.abilities().wrap() } + fn abilities(&self) -> Value { self.0.abilities().wrap() } } diff --git a/src/script_implementations/rune/wrappers/static_data/libraries/type_library.rs b/src/script_implementations/rune/wrappers/static_data/libraries/type_library.rs index 55868ba..1a4af3b 100644 --- a/src/script_implementations/rune/wrappers/static_data/libraries/type_library.rs +++ b/src/script_implementations/rune/wrappers/static_data/libraries/type_library.rs @@ -1,6 +1,6 @@ use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper}; use crate::static_data::TypeLibrary; -use rune::runtime::{AnyObj, Shared}; +use rune::runtime::Value; use std::sync::Arc; pub fn register(module: &mut rune::Module) -> anyhow::Result<()> { @@ -22,7 +22,7 @@ impl RuneTypeLibrary { fn get_type_id(&self, key: &RuneStringKey) -> Option { self.0.get_type_id(&key.0).map(|v| v.into()) } #[rune::function] - fn get_type_name(&self, t: u8) -> Option> { self.0.get_type_name(t.into()).map(|v| v.wrap()) } + fn get_type_name(&self, t: u8) -> Option { self.0.get_type_name(t.into()).map(|v| v.wrap()) } #[rune::function] fn get_single_effectiveness(&self, attacking: u8, defending: u8) -> anyhow::Result { diff --git a/src/script_implementations/rune/wrappers/static_data/move_data.rs b/src/script_implementations/rune/wrappers/static_data/move_data.rs index 15b07d3..6372177 100644 --- a/src/script_implementations/rune/wrappers/static_data/move_data.rs +++ b/src/script_implementations/rune/wrappers/static_data/move_data.rs @@ -1,7 +1,7 @@ use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper}; use crate::static_data::{MoveCategory, MoveData, MoveTarget, SecondaryEffect}; -use rune::runtime::{AnyObj, Object, Shared}; -use rune::{Any, Value}; +use rune::runtime::{Object, Value}; +use rune::Any; use std::convert::TryFrom; use std::sync::Arc; @@ -35,7 +35,7 @@ impl_rune_wrapper!(&Arc, RuneMoveData); impl RuneMoveData { #[rune::function] - fn name(&self) -> Shared { self.0.name().wrap() } + fn name(&self) -> Value { self.0.name().wrap() } #[rune::function] fn move_type(&self) -> u8 { u8::from(self.0.move_type()) } @@ -59,7 +59,7 @@ impl RuneMoveData { fn priority(&self) -> i8 { self.0.priority() } #[rune::function] - fn secondary_effect(&self) -> Option> { self.0.secondary_effect().as_ref().map(|x| x.wrap()) } + fn secondary_effect(&self) -> Option { self.0.secondary_effect().as_ref().map(|x| x.wrap()) } #[rune::function] fn has_flag(&self, flag: RuneStringKey) -> bool { self.0.has_flag(&flag.0) } @@ -75,7 +75,7 @@ impl RuneSecondaryEffect { fn chance(&self) -> f32 { self.0.chance() } #[rune::function] - fn effect_name(&self) -> Shared { self.0.effect_name().wrap() } + fn effect_name(&self) -> Value { self.0.effect_name().wrap() } #[rune::function] fn parameters(&self) -> anyhow::Result { diff --git a/src/script_implementations/rune/wrappers/static_data/species.rs b/src/script_implementations/rune/wrappers/static_data/species.rs index 11c214a..b06db04 100644 --- a/src/script_implementations/rune/wrappers/static_data/species.rs +++ b/src/script_implementations/rune/wrappers/static_data/species.rs @@ -1,6 +1,6 @@ use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper}; use crate::static_data::Species; -use rune::runtime::{AnyObj, Shared}; +use rune::runtime::Value; use rune::Any; use std::sync::Arc; @@ -29,13 +29,13 @@ impl RuneSpecies { fn id(&self) -> u16 { self.0.id() } #[rune::function] - fn name(&self) -> Shared { self.0.name().wrap() } + fn name(&self) -> Value { self.0.name().wrap() } #[rune::function] fn gender_rate(&self) -> f32 { self.0.gender_rate() } #[rune::function] - fn growth_rate(&self) -> Shared { self.0.growth_rate().wrap() } + fn growth_rate(&self) -> Value { self.0.growth_rate().wrap() } #[rune::function] fn capture_rate(&self) -> u8 { self.0.capture_rate() } @@ -44,12 +44,10 @@ impl RuneSpecies { fn base_happiness(&self) -> u8 { self.0.base_happiness() } #[rune::function] - fn get_form(&self, name: &RuneStringKey) -> Option> { - self.0.get_form(&name.0).map(|form| form.wrap()) - } + fn get_form(&self, name: &RuneStringKey) -> Option { self.0.get_form(&name.0).map(|form| form.wrap()) } #[rune::function] - fn get_default_form(&self) -> anyhow::Result> { self.0.get_default_form().map(|v| v.wrap()) } + fn get_default_form(&self) -> anyhow::Result { self.0.get_default_form().map(|v| v.wrap()) } #[rune::function] fn has_flag(&self, key: &RuneStringKey) -> bool { self.0.has_flag(&key.0) } diff --git a/src/static_data/items.rs b/src/static_data/items.rs index 93dac03..60a89aa 100755 --- a/src/static_data/items.rs +++ b/src/static_data/items.rs @@ -12,20 +12,28 @@ use crate::StringKey; #[repr(u8)] pub enum ItemCategory { /// This is where most items should go. + #[cfg_attr(feature = "rune", rune(constructor))] MiscItem, /// Pokeballs are used for capturing Pokemons. + #[cfg_attr(feature = "rune", rune(constructor))] Pokeball, /// Medicine is used for healing HP, PP, and status effects + #[cfg_attr(feature = "rune", rune(constructor))] Medicine, /// Berry is used for all berries. + #[cfg_attr(feature = "rune", rune(constructor))] Berry, /// TMHM is used for Technical and Hidden Machines. + #[cfg_attr(feature = "rune", rune(constructor))] TMHM, /// Form Changer is used for items that change forms, such as mega stones. + #[cfg_attr(feature = "rune", rune(constructor))] FormChanger, /// Key Items are single stored items, generally used for story progression. + #[cfg_attr(feature = "rune", rune(constructor))] KeyItem, /// Mail is used for mail items. + #[cfg_attr(feature = "rune", rune(constructor))] Mail, } @@ -36,14 +44,19 @@ pub enum ItemCategory { #[repr(u8)] pub enum BattleItemCategory { /// This item can't be used in battle. + #[cfg_attr(feature = "rune", rune(constructor))] None, /// This item is used for healing Pokemon. + #[cfg_attr(feature = "rune", rune(constructor))] Healing, /// This item is used for healing Pokemon from a status. + #[cfg_attr(feature = "rune", rune(constructor))] StatusHealing, /// This item is used for capturing Pokemon. + #[cfg_attr(feature = "rune", rune(constructor))] Pokeball, /// This item does not belong in above categories, but is still a battle item. + #[cfg_attr(feature = "rune", rune(constructor))] MiscBattleItem, } diff --git a/src/static_data/mod.rs b/src/static_data/mod.rs index 21dc08f..d8c3b2f 100755 --- a/src/static_data/mod.rs +++ b/src/static_data/mod.rs @@ -14,6 +14,8 @@ use std::fmt::{Display, Formatter}; #[cfg(test)] pub(crate) mod tests { use super::*; + #[doc(inline)] pub use growth_rates::tests::*; + #[doc(inline)] pub use items::tests::*; #[doc(inline)] pub use moves::tests::*; #[doc(inline)] pub use natures::tests::*; #[doc(inline)] pub use species_data::tests::*; diff --git a/src/static_data/species_data/form.rs b/src/static_data/species_data/form.rs index 5fbc98f..bd512fc 100755 --- a/src/static_data/species_data/form.rs +++ b/src/static_data/species_data/form.rs @@ -44,12 +44,12 @@ pub trait Form: Debug { fn find_ability_index(&self, ability: &dyn Ability) -> Option; /// Gets an ability from the form. - fn get_ability(&self, index: AbilityIndex) -> Result<&StringKey>; + fn get_ability(&self, index: AbilityIndex) -> Result; /// Gets a random ability from the form. - fn get_random_ability(&self, rand: &mut Random) -> Result<&StringKey>; + fn get_random_ability(&self, rand: &mut Random) -> Result; /// Gets a random hidden ability from the form. - fn get_random_hidden_ability(&self, rand: &mut Random) -> Result<&StringKey>; + fn get_random_hidden_ability(&self, rand: &mut Random) -> Result; /// Check if the form has a specific flag set. fn has_flag(&self, key: &StringKey) -> bool; @@ -118,56 +118,32 @@ impl FormImpl { impl Form for FormImpl { /// The name of the form. - fn name(&self) -> &StringKey { - &self.name - } + fn name(&self) -> &StringKey { &self.name } /// The height of the form in meters. - fn height(&self) -> f32 { - self.height - } + fn height(&self) -> f32 { self.height } /// The weight of the form in kilograms. - fn weight(&self) -> f32 { - self.weight - } + fn weight(&self) -> f32 { self.weight } /// The base amount of experience that is gained when beating a Pokemon with this form. - fn base_experience(&self) -> u32 { - self.base_experience - } + fn base_experience(&self) -> u32 { self.base_experience } /// The normal types a Pokemon with this form has. - fn types(&self) -> &Vec { - &self.types - } + fn types(&self) -> &Vec { &self.types } /// The inherent values of a form of species that are used for the stats of a Pokemon. - fn base_stats(&self) -> &Arc> { - &self.base_stats - } + fn base_stats(&self) -> &Arc> { &self.base_stats } /// The possible abilities a Pokemon with this form can have. - fn abilities(&self) -> &Vec { - &self.abilities - } + fn abilities(&self) -> &Vec { &self.abilities } /// The possible hidden abilities a Pokemon with this form can have. - fn hidden_abilities(&self) -> &Vec { - &self.hidden_abilities - } + fn hidden_abilities(&self) -> &Vec { &self.hidden_abilities } /// The moves a Pokemon with this form can learn. - fn moves(&self) -> &Arc { - &self.moves - } + fn moves(&self) -> &Arc { &self.moves } /// Arbitrary flags can be set on a form for scripting use. - fn flags(&self) -> &HashSet { - &self.flags - } + fn flags(&self) -> &HashSet { &self.flags } /// Get a type of the move at a certain index. - fn get_type(&self, index: usize) -> Result { - Ok(*self.types.get_res(index)?) - } + fn get_type(&self, index: usize) -> Result { Ok(*self.types.get_res(index)?) } /// Gets a single base stat value. - fn get_base_stat(&self, stat: Statistic) -> u16 { - self.base_stats.get_stat(stat) - } + fn get_base_stat(&self, stat: Statistic) -> u16 { self.base_stats.get_stat(stat) } /// Find the index of an ability that can be on this form. fn find_ability_index(&self, ability: &dyn Ability) -> Option { @@ -191,39 +167,35 @@ impl Form for FormImpl { } /// Gets an ability from the form. - fn get_ability(&self, index: AbilityIndex) -> Result<&StringKey> { + fn get_ability(&self, index: AbilityIndex) -> Result { if index.hidden { - Ok(self.hidden_abilities.get_res(index.index as usize)?) + self.hidden_abilities.get_res(index.index as usize).map(|s| s.clone()) } else { - Ok(self.abilities.get_res(index.index as usize)?) + self.abilities.get_res(index.index as usize).map(|s| s.clone()) } } /// Gets a random ability from the form. - fn get_random_ability(&self, rand: &mut Random) -> Result<&StringKey> { + fn get_random_ability(&self, rand: &mut Random) -> Result { ensure!(!self.abilities.is_empty(), "No abilities on form"); self.abilities .get_res(rand.get_between_unsigned(0, self.abilities.len() as u32) as usize) + .map(|s| s.clone()) } /// Gets a random hidden ability from the form. - fn get_random_hidden_ability(&self, rand: &mut Random) -> Result<&StringKey> { + fn get_random_hidden_ability(&self, rand: &mut Random) -> Result { ensure!(!self.hidden_abilities.is_empty(), "No hidden abilities on form"); self.hidden_abilities .get_res(rand.get_between_unsigned(0, self.hidden_abilities.len() as u32) as usize) + .map(|s| s.clone()) } /// Check if the form has a specific flag set. - fn has_flag(&self, key: &StringKey) -> bool { - self.flags.contains(key) - } + fn has_flag(&self, key: &StringKey) -> bool { self.flags.contains(key) } - fn has_flag_by_hash(&self, key_hash: u32) -> bool { - self.flags.contains::(&key_hash) - } + fn has_flag_by_hash(&self, key_hash: u32) -> bool { self.flags.contains::(&key_hash) } - fn eq(&self, other: &dyn Form) -> bool { - std::ptr::eq(self, other as *const dyn Form as *const Self) - } + fn eq(&self, other: &dyn Form) -> bool { std::ptr::eq(self, other as *const dyn Form as *const Self) } } #[cfg(test)] @@ -249,9 +221,9 @@ pub(crate) mod tests { fn get_type(&self, index: usize) -> Result; fn get_base_stat(&self, stat: Statistic) -> u16; fn find_ability_index(&self, ability: &dyn Ability) -> Option; - fn get_ability<'a>(&'a self, index: AbilityIndex) -> Result<&'a StringKey>; - fn get_random_ability<'a>(&'a self, rand: &mut Random) -> Result<&'a StringKey>; - fn get_random_hidden_ability<'a>(&'a self, rand: &mut Random) -> Result<&'a StringKey>; + fn get_ability(&self, index: AbilityIndex) -> Result; + fn get_random_ability(&self, rand: &mut Random) -> Result; + fn get_random_hidden_ability(&self, rand: &mut Random) -> Result; fn has_flag(&self, key: &StringKey) -> bool; fn has_flag_by_hash(&self, key_hash: u32) -> bool; fn eq(&self, other: &dyn Form) -> bool; diff --git a/src/static_data/species_data/mod.rs b/src/static_data/species_data/mod.rs index f0e1753..513b5d1 100755 --- a/src/static_data/species_data/mod.rs +++ b/src/static_data/species_data/mod.rs @@ -9,6 +9,7 @@ pub(crate) mod tests { pub use super::form::tests::*; pub use super::species::tests::*; + pub use super::ability::tests::*; } /// An ability is a passive effect in battle that is attached to a Pokemon. diff --git a/src/static_data/statistics.rs b/src/static_data/statistics.rs index ade129b..b1a996a 100755 --- a/src/static_data/statistics.rs +++ b/src/static_data/statistics.rs @@ -7,15 +7,21 @@ #[repr(u8)] pub enum Statistic { /// Health Points determine how much damage a Pokemon can receive before fainting. + #[cfg_attr(feature = "rune", rune(constructor))] HP, /// Attack determines how much damage a Pokemon deals when using a physical attack. + #[cfg_attr(feature = "rune", rune(constructor))] Attack, /// Defense determines how much damage a Pokemon receives when it is hit by a physical attack. + #[cfg_attr(feature = "rune", rune(constructor))] Defense, /// Special Attack determines how much damage a Pokemon deals when using a special attack. + #[cfg_attr(feature = "rune", rune(constructor))] SpecialAttack, /// Special Defense determines how much damage a Pokemon receives when it is hit by a special attack. + #[cfg_attr(feature = "rune", rune(constructor))] SpecialDefense, /// Speed determines the order that a Pokemon can act in battle. + #[cfg_attr(feature = "rune", rune(constructor))] Speed, } diff --git a/tests/datatests/mod.rs b/tests/datatests/mod.rs index d8188f0..68be2bf 100644 --- a/tests/datatests/mod.rs +++ b/tests/datatests/mod.rs @@ -10,12 +10,10 @@ fn integration_tests(input: &Path) { let mut str: String = "".to_string(); let mut file = File::open(input).unwrap(); file.read_to_string(&mut str).unwrap(); - let test_case = serde_yaml::from_str::(&str).unwrap(); + let test_case = serde_yml::from_str::(&str).unwrap(); println!(" Running integration test {}", test_case.name); test_case.run_test(get_library()); } #[test] -fn basic_single_turn() { - integration_tests(Path::new("tests/test_cases/basic_single_turn.yaml")); -} +fn basic_single_turn() { integration_tests(Path::new("tests/test_cases/basic_single_turn.yaml")); }