Update to rune 0.14, more tests
continuous-integration/drone/push Build is failing Details

This commit is contained in:
Deukhoofd 2024-05-19 16:37:19 +02:00
parent 535f6bf79b
commit 92ff5bd0a1
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
29 changed files with 862 additions and 387 deletions

View File

@ -51,14 +51,14 @@ chrono = "0.4"
rand = "0.8" rand = "0.8"
rand_pcg = "0.3" rand_pcg = "0.3"
hashbrown = "0.14" hashbrown = "0.14"
indexmap = "2.0" indexmap = "2.2"
parking_lot = "0.12" parking_lot = "0.12"
serde = { version = "1.0", optional = true, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] }
serde_repr = "0.1" serde_repr = "0.1"
serde-xml-rs = { version = "0.6", optional = true } serde-xml-rs = { version = "0.6", optional = true }
uuid = "1.5" uuid = "1.8"
paste = { version = "1.0" } paste = { version = "1.0" }
arcstr = { version = "1.1", features = ["std"] } arcstr = { version = "1.2", features = ["std"] }
enum-display-derive = "0.1" enum-display-derive = "0.1"
anyhow = "1.0" anyhow = "1.0"
anyhow_ext = "0.2" anyhow_ext = "0.2"
@ -66,12 +66,12 @@ thiserror = "1.0"
stdext = "0.3" stdext = "0.3"
wasmer = { version = "4.2", optional = true, default-features = false, features = ["sys", "wat", "llvm"] } 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] [dev-dependencies]
csv = "1.3" csv = "1.3"
project-root = "0.2" project-root = "0.2"
serde_yaml = "0.9" serde_yml = "0.0.7"
serde_json = "1.0" serde_json = "1.0"
serde_plain = "1.0" serde_plain = "1.0"
# Allow us to assert whether floats are approximately a value # Allow us to assert whether floats are approximately a value

View File

@ -427,7 +427,7 @@ impl Pokemon {
.library .library
.static_data() .static_data()
.abilities() .abilities()
.get(ability) .get(&ability)
.ok_or(PkmnError::InvalidAbilityName { .ok_or(PkmnError::InvalidAbilityName {
ability: ability.clone(), ability: ability.clone(),
})?) })?)

View File

@ -4,7 +4,7 @@ use crate::script_implementations::rune::RuneScriptType;
use crate::static_data::Parameter; use crate::static_data::Parameter;
use crate::StringKey; use crate::StringKey;
use hashbrown::HashMap; use hashbrown::HashMap;
use rune::runtime::{Object, RuntimeContext, Shared, VmError, VmResult}; use rune::runtime::{RuntimeContext, VmError, VmResult};
use rune::{Unit, Value}; use rune::{Unit, Value};
use std::convert::TryFrom; use std::convert::TryFrom;
use std::sync::atomic::{AtomicBool, AtomicUsize}; use std::sync::atomic::{AtomicBool, AtomicUsize};
@ -12,7 +12,7 @@ use std::sync::Arc;
pub struct RuneScript { pub struct RuneScript {
name: StringKey, name: StringKey,
state: Shared<Object>, state: Value,
/// Returns an atomic bool for internal marking of deletion. This is currently only specifically /// 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 /// used for deletion of a script while we are holding a reference to it (i.e. executing a script
/// hook on it). /// hook on it).
@ -34,7 +34,7 @@ unsafe impl Sync for RuneScript {}
impl RuneScript { impl RuneScript {
pub fn new( pub fn new(
name: StringKey, name: StringKey,
object: Shared<Object>, object: Value,
script_type: Arc<RuneScriptType>, script_type: Arc<RuneScriptType>,
runtime: Arc<RuntimeContext>, runtime: Arc<RuntimeContext>,
unit: Arc<Unit>, unit: Arc<Unit>,
@ -50,7 +50,7 @@ impl RuneScript {
} }
} }
pub(crate) fn get_state(&self) -> Shared<Object> { self.state.clone() } pub(crate) fn get_state(&self) -> Value { self.state.clone() }
} }
impl Script for RuneScript { impl Script for RuneScript {
@ -68,12 +68,12 @@ impl Script for RuneScript {
if pars.is_empty() { if pars.is_empty() {
return Ok(()); return Ok(());
} }
let state = self.state.clone();
let mut binding = self.state.clone().into_struct()?;
let state = binding.data_mut();
for par in pars { for par in pars {
let key = rune::alloc::string::String::try_from(par.0.str())?; let key = rune::alloc::string::String::try_from(par.0.str())?;
state state.insert(key, parameter_to_rune_value(par.1.as_ref())?)?;
.borrow_mut()?
.insert(key, parameter_to_rune_value(par.1.as_ref())?)?;
} }
Ok(()) Ok(())
} }
@ -87,8 +87,8 @@ impl Script for RuneScript {
.execute( .execute(
hash, hash,
vec![ vec![
Value::Object(self.state.clone()), rune::to_value(self.state.clone())?,
Value::from(choice.wrap()), rune::to_value(choice.wrap())?,
speed_handle.clone(), speed_handle.clone(),
], ],
)? )?
@ -116,10 +116,10 @@ impl Script for RuneScript {
vm.execute( vm.execute(
hash, hash,
vec![ vec![
Value::Object(self.state.clone()), self.state.clone(),
Value::from(move_data.wrap()), move_data.wrap(),
Value::from(target.wrap()), target.wrap(),
Value::from(hit), rune::to_value(hit)?,
block_critical_handle.clone(), block_critical_handle.clone(),
], ],
)?; )?;

View File

@ -8,7 +8,7 @@ use hashbrown::HashMap;
use rune::compile::meta::AssociatedKind; use rune::compile::meta::AssociatedKind;
use rune::compile::{ComponentRef, MetaError}; use rune::compile::{ComponentRef, MetaError};
use rune::diagnostics::Diagnostic; use rune::diagnostics::Diagnostic;
use rune::runtime::{RuntimeContext, Shared}; use rune::runtime::RuntimeContext;
use rune::{Context, Diagnostics, Options, Source, Sources, Unit}; use rune::{Context, Diagnostics, Options, Source, Sources, Unit};
use std::any::Any; use std::any::Any;
use std::convert::TryFrom; use std::convert::TryFrom;
@ -52,7 +52,7 @@ impl ScriptResolver for RuneScriptResolver {
o.insert(rune::alloc::String::try_from("owner")?, owner_obj.into())?; 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( let script = Arc::new(RuneScript::new(
script_key.clone(), script_key.clone(),
state, state,

View File

@ -1,7 +1,6 @@
use crate::dynamic_data::Battle; use crate::dynamic_data::Battle;
use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper}; use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper};
use rune::runtime::{AnyObj, Shared}; use rune::{Any, Value};
use rune::Any;
pub fn register(module: &mut rune::Module) -> anyhow::Result<()> { pub fn register(module: &mut rune::Module) -> anyhow::Result<()> {
module.ty::<RuneBattle>()?; module.ty::<RuneBattle>()?;
@ -27,10 +26,10 @@ impl_rune_wrapper!(&Battle, RuneBattle);
impl RuneBattle { impl RuneBattle {
#[rune::function] #[rune::function]
fn library(&self) -> Shared<AnyObj> { self.0.library().wrap() } fn library(&self) -> Value { self.0.library().wrap() }
#[rune::function] #[rune::function]
fn parties(&self) -> Vec<Shared<AnyObj>> { self.0.parties().iter().map(|p| p.wrap()).collect() } fn parties(&self) -> Vec<Value> { self.0.parties().iter().map(|p| p.wrap()).collect() }
#[rune::function] #[rune::function]
fn can_flee(&self) -> bool { self.0.can_flee() } 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() } fn pokemon_per_side(&self) -> u8 { self.0.pokemon_per_side() }
#[rune::function] #[rune::function]
fn sides(&self) -> Vec<Shared<AnyObj>> { self.0.sides().iter().map(|s| s.wrap()).collect() } fn sides(&self) -> Vec<Value> { self.0.sides().iter().map(|s| s.wrap()).collect() }
#[rune::function] #[rune::function]
fn random(&self) -> Shared<AnyObj> { self.0.random().wrap() } fn random(&self) -> Value { self.0.random().wrap() }
#[rune::function] #[rune::function]
fn has_ended(&self) -> bool { self.0.has_ended() } fn has_ended(&self) -> bool { self.0.has_ended() }
@ -54,9 +53,7 @@ impl RuneBattle {
fn current_turn(&self) -> u32 { self.0.current_turn() } fn current_turn(&self) -> u32 { self.0.current_turn() }
#[rune::function] #[rune::function]
fn get_pokemon(&self, side: u8, index: u8) -> Option<Shared<AnyObj>> { fn get_pokemon(&self, side: u8, index: u8) -> Option<Value> { self.0.get_pokemon(side, index).map(|v| v.wrap()) }
self.0.get_pokemon(side, index).map(|v| v.wrap())
}
#[rune::function] #[rune::function]
fn set_weather(&self, weather: Option<RuneStringKey>) -> anyhow::Result<()> { fn set_weather(&self, weather: Option<RuneStringKey>) -> anyhow::Result<()> {

View File

@ -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::pokemon::RunePokemon;
use crate::script_implementations::rune::wrappers::dynamic_data::resolve_script_data; use crate::script_implementations::rune::wrappers::dynamic_data::resolve_script_data;
use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneWrapper}; use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneWrapper};
use rune::runtime::{AnyObj, Object, Shared}; use rune::runtime::Value;
use rune::Any; use rune::Any;
use std::sync::Arc; use std::sync::Arc;
@ -29,19 +29,19 @@ impl RuneExecutingMove {
#[rune::function] #[rune::function]
fn number_of_hits(&self) -> u8 { self.0.number_of_hits() } fn number_of_hits(&self) -> u8 { self.0.number_of_hits() }
#[rune::function] #[rune::function]
fn user(&self) -> Shared<AnyObj> { self.0.user().wrap() } fn user(&self) -> Value { self.0.user().wrap() }
#[rune::function] #[rune::function]
fn chosen_move(&self) -> Shared<AnyObj> { self.0.chosen_move().wrap() } fn chosen_move(&self) -> Value { self.0.chosen_move().wrap() }
#[rune::function] #[rune::function]
fn use_move(&self) -> Shared<AnyObj> { self.0.use_move().wrap() } fn use_move(&self) -> Value { self.0.use_move().wrap() }
#[rune::function] #[rune::function]
fn script(&self) -> Option<Shared<Object>> { resolve_script_data(self.0.script()) } fn script(&self) -> Option<Value> { resolve_script_data(self.0.script()) }
#[rune::function] #[rune::function]
fn get_hit_data(&self, for_target: RunePokemon, hit: u8) -> anyhow::Result<Shared<AnyObj>> { fn get_hit_data(&self, for_target: RunePokemon, hit: u8) -> anyhow::Result<Value> {
self.0.get_hit_data(&for_target.0, hit).map(|hit_data| hit_data.wrap()) self.0.get_hit_data(&for_target.0, hit).map(|hit_data| hit_data.wrap())
} }
} }

View File

@ -1,6 +1,6 @@
use crate::dynamic_data::{LearnedMove, MoveLearnMethod}; use crate::dynamic_data::{LearnedMove, MoveLearnMethod};
use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneWrapper}; use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneWrapper};
use rune::runtime::{AnyObj, Shared}; use rune::runtime::Value;
use rune::Any; use rune::Any;
use std::sync::Arc; use std::sync::Arc;
@ -24,7 +24,7 @@ impl_rune_wrapper!(&Arc<LearnedMove>, RuneLearnedMove);
impl RuneLearnedMove { impl RuneLearnedMove {
#[rune::function] #[rune::function]
fn move_data(&self) -> Shared<AnyObj> { self.0.move_data().wrap() } fn move_data(&self) -> Value { self.0.move_data().wrap() }
#[rune::function] #[rune::function]
fn max_pp(&self) -> u8 { self.0.max_pp() } fn max_pp(&self) -> u8 { self.0.max_pp() }

View File

@ -1,6 +1,5 @@
use crate::dynamic_data::ScriptContainer; use crate::dynamic_data::ScriptContainer;
use crate::script_implementations::rune::script::RuneScript; use crate::script_implementations::rune::script::RuneScript;
use rune::runtime::{Object, Shared};
mod battle; mod battle;
mod battle_party; mod battle_party;
@ -26,7 +25,7 @@ pub fn register(module: &mut rune::Module) -> anyhow::Result<()> {
Ok(()) Ok(())
} }
fn resolve_script_data(container: &ScriptContainer) -> Option<Shared<Object>> { fn resolve_script_data(container: &ScriptContainer) -> Option<rune::Value> {
container container
.get() .get()
.map(|v| { .map(|v| {

View File

@ -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::static_data::item::RuneItem;
use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper}; use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper};
use crate::static_data::{Gender, Statistic}; use crate::static_data::{Gender, Statistic};
use rune::runtime::{AnyObj, Object, Shared}; use rune::runtime::Value;
use rune::Any; use rune::Any;
pub fn register(module: &mut rune::Module) -> anyhow::Result<()> { pub fn register(module: &mut rune::Module) -> anyhow::Result<()> {
@ -69,25 +69,25 @@ pub struct RunePokemon(pub Pokemon);
impl RunePokemon { impl RunePokemon {
#[rune::function] #[rune::function]
fn library(&self) -> Shared<AnyObj> { self.0.library().wrap() } fn library(&self) -> Value { self.0.library().wrap() }
#[rune::function] #[rune::function]
fn species(&self) -> Shared<AnyObj> { self.0.species().wrap() } fn species(&self) -> Value { self.0.species().wrap() }
#[rune::function] #[rune::function]
fn form(&self) -> Shared<AnyObj> { self.0.form().wrap() } fn form(&self) -> Value { self.0.form().wrap() }
#[rune::function] #[rune::function]
fn has_different_display_species(&self) -> bool { self.0.has_different_display_species() } fn has_different_display_species(&self) -> bool { self.0.has_different_display_species() }
#[rune::function] #[rune::function]
fn display_species(&self) -> Shared<AnyObj> { self.0.display_species().wrap() } fn display_species(&self) -> Value { self.0.display_species().wrap() }
#[rune::function] #[rune::function]
fn has_different_display_form(&self) -> bool { self.0.has_different_display_form() } fn has_different_display_form(&self) -> bool { self.0.has_different_display_form() }
#[rune::function] #[rune::function]
fn display_form(&self) -> Shared<AnyObj> { self.0.display_form().wrap() } fn display_form(&self) -> Value { self.0.display_form().wrap() }
#[rune::function] #[rune::function]
fn level(&self) -> LevelInt { self.0.level() } fn level(&self) -> LevelInt { self.0.level() }
@ -105,18 +105,16 @@ impl RunePokemon {
fn coloring(&self) -> u8 { self.0.coloring() } fn coloring(&self) -> u8 { self.0.coloring() }
#[rune::function] #[rune::function]
fn held_item(&self) -> Option<Shared<AnyObj>> { self.0.held_item().map(|v| v.wrap()) } fn held_item(&self) -> Option<Value> { self.0.held_item().map(|v| v.wrap()) }
#[rune::function] #[rune::function]
fn has_held_item(&self, key: RuneStringKey) -> bool { self.0.has_held_item(&key.0) } fn has_held_item(&self, key: RuneStringKey) -> bool { self.0.has_held_item(&key.0) }
#[rune::function] #[rune::function]
fn set_held_item(&mut self, key: RuneItem) -> Option<Shared<AnyObj>> { fn set_held_item(&mut self, key: RuneItem) -> Option<Value> { self.0.set_held_item(&key.0).map(|v| v.wrap()) }
self.0.set_held_item(&key.0).map(|v| v.wrap())
}
#[rune::function] #[rune::function]
fn remove_held_item(&mut self) -> Option<Shared<AnyObj>> { self.0.remove_held_item().map(|v| v.wrap()) } fn remove_held_item(&mut self) -> Option<Value> { self.0.remove_held_item().map(|v| v.wrap()) }
#[rune::function] #[rune::function]
fn consume_held_item(&mut self) -> anyhow::Result<bool> { self.0.consume_held_item() } fn consume_held_item(&mut self) -> anyhow::Result<bool> { self.0.consume_held_item() }
@ -149,19 +147,19 @@ impl RunePokemon {
fn types(&self) -> Vec<u8> { self.0.types().iter().map(|v| u8::from(*v)).collect() } fn types(&self) -> Vec<u8> { self.0.types().iter().map(|v| u8::from(*v)).collect() }
#[rune::function] #[rune::function]
fn learned_moves(&self) -> Vec<Option<Shared<AnyObj>>> { fn learned_moves(&self) -> Vec<Option<Value>> {
let l = self.0.learned_moves().read(); let l = self.0.learned_moves().read();
l.iter().map(|v| v.as_ref().map(|l| l.wrap())).collect() l.iter().map(|v| v.as_ref().map(|l| l.wrap())).collect()
} }
#[rune::function] #[rune::function]
fn flat_stats(&self) -> Shared<AnyObj> { self.0.flat_stats().wrap() } fn flat_stats(&self) -> Value { self.0.flat_stats().wrap() }
#[rune::function] #[rune::function]
fn is_egg(&self) -> bool { self.0.is_egg() } fn is_egg(&self) -> bool { self.0.is_egg() }
#[rune::function] #[rune::function]
fn boosted_stats(&self) -> Shared<AnyObj> { self.0.boosted_stats().wrap() } fn boosted_stats(&self) -> Value { self.0.boosted_stats().wrap() }
#[rune::function] #[rune::function]
fn stat_boost(&self, stat: Statistic) -> i8 { self.0.stat_boost(stat) } 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) } fn get_effort_value(&self, stat: Statistic) -> u8 { self.0.effort_values().get_stat(stat) }
#[rune::function] #[rune::function]
fn get_battle(&self) -> Option<Shared<AnyObj>> { self.0.get_battle().map(|v| v.wrap()) } fn get_battle(&self) -> Option<Value> { self.0.get_battle().map(|v| v.wrap()) }
#[rune::function] #[rune::function]
fn get_battle_side_index(&self) -> Option<u8> { self.0.get_battle_side_index() } fn get_battle_side_index(&self) -> Option<u8> { self.0.get_battle_side_index() }
@ -190,13 +188,13 @@ impl RunePokemon {
fn is_ability_overridden(&self) -> bool { self.0.is_ability_overridden() } fn is_ability_overridden(&self) -> bool { self.0.is_ability_overridden() }
#[rune::function] #[rune::function]
fn active_ability(&self) -> anyhow::Result<Shared<AnyObj>> { self.0.active_ability().map(|v| v.wrap()) } fn active_ability(&self) -> anyhow::Result<Value> { self.0.active_ability().map(|v| v.wrap()) }
#[rune::function] #[rune::function]
fn allowed_experience_gain(&self) -> bool { self.0.allowed_experience_gain() } fn allowed_experience_gain(&self) -> bool { self.0.allowed_experience_gain() }
#[rune::function] #[rune::function]
fn nature(&self) -> Shared<AnyObj> { self.0.nature().wrap() } fn nature(&self) -> Value { self.0.nature().wrap() }
#[rune::function] #[rune::function]
fn change_form(&self, form: RuneForm) -> anyhow::Result<()> { self.0.change_form(&form.0) } 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() } fn clear_status(&self) { self.0.clear_status() }
#[rune::function] #[rune::function]
fn status_script(&self) -> Option<Shared<Object>> { resolve_script_data(&self.0.status()) } fn status_script(&self) -> Option<Value> { resolve_script_data(&self.0.status()) }
#[rune::function] #[rune::function]
fn ability_script(&self) -> Option<Shared<Object>> { resolve_script_data(&self.0.ability_script()) } fn ability_script(&self) -> Option<Value> { resolve_script_data(&self.0.ability_script()) }
} }
impl_rune_wrapper!(&Pokemon, RunePokemon); impl_rune_wrapper!(&Pokemon, RunePokemon);

View File

@ -1,6 +1,6 @@
use crate::dynamic_data::TurnChoice; use crate::dynamic_data::TurnChoice;
use crate::script_implementations::rune::wrappers::RuneWrapper; use crate::script_implementations::rune::wrappers::RuneWrapper;
use rune::runtime::{AnyObj, Shared}; use rune::runtime::Value;
use rune::Any; use rune::Any;
use std::sync::Arc; use std::sync::Arc;
@ -62,7 +62,7 @@ impl RuneTurnChoice {
} }
#[rune::function] #[rune::function]
fn user(&self) -> Shared<AnyObj> { self.get_turn_choice().user().wrap() } fn user(&self) -> Value { self.get_turn_choice().user().wrap() }
#[rune::function] #[rune::function]
fn speed(&self) -> u32 { self.get_turn_choice().speed() } fn speed(&self) -> u32 { self.get_turn_choice().speed() }
@ -75,7 +75,7 @@ impl RuneTurnChoice {
} }
impl RuneWrapper for &Arc<TurnChoice> { impl RuneWrapper for &Arc<TurnChoice> {
fn wrap(self) -> Shared<AnyObj> { fn wrap(self) -> Value {
let o = match self.as_ref() { let o = match self.as_ref() {
TurnChoice::Move(_) => RuneTurnChoice::Move(RuneMoveChoice(self.clone())), TurnChoice::Move(_) => RuneTurnChoice::Move(RuneMoveChoice(self.clone())),
TurnChoice::Item(_) => RuneTurnChoice::Item(RuneItemChoice(self.clone())), TurnChoice::Item(_) => RuneTurnChoice::Item(RuneItemChoice(self.clone())),
@ -83,7 +83,7 @@ impl RuneWrapper for &Arc<TurnChoice> {
TurnChoice::Flee(_) => RuneTurnChoice::Flee(RuneFleeChoice(self.clone())), TurnChoice::Flee(_) => RuneTurnChoice::Flee(RuneFleeChoice(self.clone())),
TurnChoice::Pass(_) => RuneTurnChoice::Pass(RunePassChoice(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] #[rune::function]
fn used_move(&self) -> Shared<AnyObj> { self.move_choice().used_move().wrap() } fn used_move(&self) -> Value { self.move_choice().used_move().wrap() }
#[rune::function] #[rune::function]
fn target_side(&self) -> u8 { self.move_choice().target_side() } fn target_side(&self) -> u8 { self.move_choice().target_side() }
@ -108,5 +108,5 @@ impl RuneMoveChoice {
fn priority(&self) -> i8 { self.move_choice().priority() } fn priority(&self) -> i8 { self.move_choice().priority() }
#[rune::function] #[rune::function]
fn user(&self) -> Shared<AnyObj> { self.move_choice().user().wrap() } fn user(&self) -> Value { self.move_choice().user().wrap() }
} }

View File

@ -1,5 +1,5 @@
use rune::alloc::fmt::TryWrite; use rune::alloc::fmt::TryWrite;
use rune::runtime::{AnyObj, Protocol, Shared, VmResult}; use rune::runtime::{Protocol, VmResult};
use rune::{Any, Value}; use rune::{Any, Value};
use std::num::Saturating; use std::num::Saturating;
@ -8,7 +8,7 @@ mod parameters;
mod static_data; mod static_data;
pub trait RuneWrapper { pub trait RuneWrapper {
fn wrap(self) -> Shared<AnyObj>; fn wrap(self) -> Value;
} }
pub fn module() -> anyhow::Result<rune::Module> { pub fn module() -> anyhow::Result<rune::Module> {
@ -33,6 +33,8 @@ pub fn module() -> anyhow::Result<rune::Module> {
module.ty::<RuneStringKey>()?; module.ty::<RuneStringKey>()?;
module.function_meta(RuneStringKey::string_display)?; 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)?; parameters::register(&mut module)?;
dynamic_data::register(&mut module)?; dynamic_data::register(&mut module)?;
@ -40,30 +42,24 @@ pub fn module() -> anyhow::Result<rune::Module> {
Ok(module) Ok(module)
} }
pub fn wrap_int_reference(value: i64) -> anyhow::Result<Value> { pub fn wrap_int_reference(value: i64) -> anyhow::Result<Value> { Ok(rune::to_value(RuneValueIntWrapper::new(value))?) }
Ok(Value::Any(Shared::new(AnyObj::new(RuneValueIntWrapper::new(value))?)?))
}
pub fn wrap_bool_reference(value: bool) -> anyhow::Result<Value> { pub fn wrap_bool_reference(value: bool) -> anyhow::Result<Value> {
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<i64> { pub fn get_int_reference_value(value: Value) -> anyhow::Result<i64> {
let obj = value.into_any().into_result()?; let obj = match value.into_any::<RuneValueIntWrapper>() {
let obj = obj.take()?; Ok(obj) => obj,
let obj = match obj.downcast_borrow_ref::<RuneValueIntWrapper>() { Err(_) => return Err(anyhow::anyhow!("Value is not a RuneValueIntWrapper")),
Some(obj) => obj,
None => return Err(anyhow::anyhow!("Value is not a RuneValueIntWrapper")),
}; };
Ok(obj.as_int()) Ok(obj.as_int())
} }
pub fn get_bool_reference_value(value: Value) -> anyhow::Result<bool> { pub fn get_bool_reference_value(value: Value) -> anyhow::Result<bool> {
let obj = value.into_any().into_result()?; let obj = match value.into_any::<RuneValueBoolWrapper>() {
let obj = obj.take()?; Ok(obj) => obj,
let obj = match obj.downcast_borrow_ref::<RuneValueBoolWrapper>() { Err(_) => return Err(anyhow::anyhow!("Value is not a RuneValueBoolWrapper")),
Some(obj) => obj,
None => return Err(anyhow::anyhow!("Value is not a RuneValueBoolWrapper")),
}; };
Ok(obj.as_bool()) Ok(obj.as_bool())
} }
@ -71,9 +67,7 @@ pub fn get_bool_reference_value(value: Value) -> anyhow::Result<bool> {
macro_rules! impl_rune_wrapper { macro_rules! impl_rune_wrapper {
($t:ty, $wrapped_type:ident) => { ($t:ty, $wrapped_type:ident) => {
impl crate::script_implementations::rune::wrappers::RuneWrapper for $t { impl crate::script_implementations::rune::wrappers::RuneWrapper for $t {
fn wrap(self) -> rune::runtime::Shared<rune::runtime::AnyObj> { fn wrap(self) -> rune::runtime::Value { rune::to_value($wrapped_type(self.clone())).unwrap() }
rune::runtime::Shared::new(rune::runtime::AnyObj::new($wrapped_type(self.clone())).unwrap()).unwrap()
}
} }
}; };
} }
@ -82,6 +76,7 @@ use crate::StringKey;
use impl_rune_wrapper; use impl_rune_wrapper;
#[derive(Any, Clone)] #[derive(Any, Clone)]
#[rune(name = RefInt)]
struct RuneValueIntWrapper { struct RuneValueIntWrapper {
value: Saturating<i64>, value: Saturating<i64>,
} }
@ -106,10 +101,12 @@ impl RuneValueIntWrapper {
fn sub_assign(&mut self, other: i64) { self.value -= other; } fn sub_assign(&mut self, other: i64) { self.value -= other; }
fn div_assign(&mut self, other: Value) { fn div_assign(&mut self, other: Value) {
match other { match other.as_integer() {
Value::Integer(other) => self.value /= other, Ok(other) => self.value /= other,
Value::Float(other) => self.div_assign_f64(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) { fn mul_assign(&mut self, other: Value) {
match other { match other.as_integer() {
Value::Integer(other) => self.value *= other, Ok(other) => self.value *= other,
Value::Float(other) => self.mul_assign_f64(other), Err(_) => match other.as_float() {
_ => (), Ok(other) => self.mul_assign_f64(other),
Err(_) => (),
},
} }
} }
@ -155,6 +154,7 @@ impl RuneValueIntWrapper {
} }
#[derive(Any, Clone)] #[derive(Any, Clone)]
#[rune(name = RefBool)]
struct RuneValueBoolWrapper(bool); struct RuneValueBoolWrapper(bool);
impl RuneValueBoolWrapper { impl RuneValueBoolWrapper {
@ -178,6 +178,7 @@ impl RuneValueBoolWrapper {
} }
#[derive(Any, Clone, Debug)] #[derive(Any, Clone, Debug)]
#[rune(name = StringKey)]
pub(super) struct RuneStringKey(pub StringKey); pub(super) struct RuneStringKey(pub StringKey);
impl RuneStringKey { impl RuneStringKey {
@ -188,24 +189,39 @@ impl RuneStringKey {
rune::vm_write!(f, "{}", self.0); rune::vm_write!(f, "{}", self.0);
VmResult::Ok(()) VmResult::Ok(())
} }
fn eq(&self, b: Value) -> VmResult<bool> {
match b.borrow_string_ref() {
Ok(s) => VmResult::Ok(self.0 == StringKey::new(&s)),
Err(_) => {
let b = b.borrow_any_ref::<RuneStringKey>();
match b {
Ok(b) => VmResult::Ok(self.0 == b.0),
_ => VmResult::Ok(false),
}
}
}
}
} }
impl RuneWrapper for &StringKey { impl RuneWrapper for &StringKey {
fn wrap(self) -> Shared<AnyObj> { Shared::new(AnyObj::new(RuneStringKey(self.clone())).unwrap()).unwrap() } fn wrap(self) -> Value { rune::to_value(RuneStringKey(self.clone())).unwrap() }
} }
#[cfg(test)] #[cfg(test)]
mod test { mod tests {
use super::*; use super::*;
use anyhow::Result;
use rune::diagnostics::Diagnostic;
use rune::{Context, Diagnostics, Options, Source, Vm}; use rune::{Context, Diagnostics, Options, Source, Vm};
use std::sync::Arc; use std::sync::Arc;
pub fn setup_script(script: &str) -> Vm { pub fn setup_script(script: &str) -> Result<Vm> {
let mut context = Context::with_default_modules().unwrap(); let mut context = Context::with_default_modules()?;
context.install(module().unwrap()).unwrap(); context.install(module()?)?;
let mut sources = rune::Sources::new(); 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 diagnostics = Diagnostics::new();
let mut options = Options::default(); let mut options = Options::default();
@ -218,381 +234,431 @@ mod test {
.with_context(&context) .with_context(&context)
.with_diagnostics(&mut diagnostics) .with_diagnostics(&mut diagnostics)
.with_options(&options) .with_options(&options)
.build() .build();
.unwrap(); if !diagnostics.is_empty() && diagnostics.has_error() {
if !diagnostics.is_empty() { let error_message = diagnostics
panic!("Diagnostics: {:?}", diagnostics); .diagnostics()
.iter()
.filter_map(|d| match d {
Diagnostic::Fatal(f) => Some(f.to_string()),
_ => None,
})
.collect::<Vec<String>>()
.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 { macro_rules! execute_vm {
($vm:expr, $func:expr, $val:expr) => {{ ($vm:expr, $func:expr, $val:expr) => {{
let args = vec![$val.clone()]; 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] #[test]
fn test_int_wrapper_set_value() { fn test_int_wrapper_set_value() -> Result<()> {
let mut vm = setup_script( let mut vm = setup_script(
r#" r#"
pub fn test_int(a) { pub fn test_int(a) {
a.set_value(5); a.set_value(5);
} }
"#, "#,
); )?;
let val = wrap_int_reference(10).unwrap(); let val = wrap_int_reference(10)?;
execute_vm!(vm, "test_int", val); 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); assert_eq!(v, 5);
Ok(())
} }
#[test] #[test]
fn test_int_wrapper_as_int() { fn test_int_wrapper_as_int() -> Result<()> {
let mut vm = setup_script( let mut vm = setup_script(
r#" r#"
pub fn test_int(a) { pub fn test_int(a) {
a.as_int() a.as_int()
} }
"#, "#,
); )?;
let val = wrap_int_reference(10).unwrap(); let val = wrap_int_reference(10)?;
let res = execute_vm!(vm, "test_int", val); let res = execute_vm!(vm, "test_int", val);
let res = res.as_integer().unwrap(); let res = res.as_integer()?;
assert_eq!(res, 10); assert_eq!(res, 10);
Ok(())
} }
#[test] #[test]
fn test_int_wrapper_add() { fn test_int_wrapper_add() -> Result<()> {
let mut vm = setup_script( let mut vm = setup_script(
r#" r#"
pub fn test_int(a) { pub fn test_int(a) {
a += 5; a += 5;
} }
"#, "#,
); )?;
let val = wrap_int_reference(10).unwrap(); let val = wrap_int_reference(10)?;
execute_vm!(vm, "test_int", val); 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); assert_eq!(v, 15);
Ok(())
} }
#[test] #[test]
fn test_int_wrapper_add_overflow() { fn test_int_wrapper_add_overflow() -> Result<()> {
let mut vm = setup_script( let mut vm = setup_script(
r#" r#"
pub fn test_int(a) { pub fn test_int(a) {
a += 5; a += 5;
} }
"#, "#,
); )?;
let val = wrap_int_reference(i64::MAX).unwrap(); let val = wrap_int_reference(i64::MAX)?;
execute_vm!(vm, "test_int", val); 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); assert_eq!(v, i64::MAX);
Ok(())
} }
#[test] #[test]
fn test_int_wrapper_sub() { fn test_int_wrapper_sub() -> Result<()> {
let mut vm = setup_script( let mut vm = setup_script(
r#" r#"
pub fn test_int(a) { pub fn test_int(a) {
a -= 5; a -= 5;
} }
"#, "#,
); )?;
let val = wrap_int_reference(10).unwrap(); let val = wrap_int_reference(10)?;
execute_vm!(vm, "test_int", val); 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); assert_eq!(v, 5);
Ok(())
} }
#[test] #[test]
fn test_int_wrapper_underflow() { fn test_int_wrapper_underflow() -> Result<()> {
let mut vm = setup_script( let mut vm = setup_script(
r#" r#"
pub fn test_int(a) { pub fn test_int(a) {
a -= 5; a -= 5;
} }
"#, "#,
); )?;
let val = wrap_int_reference(i64::MIN).unwrap(); let val = wrap_int_reference(i64::MIN)?;
execute_vm!(vm, "test_int", val); 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); assert_eq!(v, i64::MIN);
Ok(())
} }
#[test] #[test]
fn test_int_wrapper_mul() { fn test_int_wrapper_mul() -> Result<()> {
let mut vm = setup_script( let mut vm = setup_script(
r#" r#"
pub fn test_int(a) { pub fn test_int(a) {
a *= 5; a *= 5;
} }
"#, "#,
); )?;
let val = wrap_int_reference(10).unwrap(); let val = wrap_int_reference(10)?;
execute_vm!(vm, "test_int", val); 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); assert_eq!(v, 50);
Ok(())
} }
#[test] #[test]
fn test_int_wrapper_mul_float() { fn test_int_wrapper_mul_float() -> Result<()> {
let mut vm = setup_script( let mut vm = setup_script(
r#" r#"
pub fn test_int(a) { pub fn test_int(a) {
a *= 0.5; a *= 0.5;
} }
"#, "#,
); )?;
let val = wrap_int_reference(10).unwrap(); let val = wrap_int_reference(10)?;
execute_vm!(vm, "test_int", val); 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); assert_eq!(v, 5);
Ok(())
} }
#[test] #[test]
fn test_int_wrapper_mul_overflow() { fn test_int_wrapper_mul_overflow() -> Result<()> {
let mut vm = setup_script( let mut vm = setup_script(
r#" r#"
pub fn test_int(a) { pub fn test_int(a) {
a *= 5; a *= 5;
} }
"#, "#,
); )?;
let val = wrap_int_reference(i64::MAX).unwrap(); let val = wrap_int_reference(i64::MAX)?;
execute_vm!(vm, "test_int", val); 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); assert_eq!(v, i64::MAX);
Ok(())
} }
#[test] #[test]
fn test_int_wrapper_mul_float_overflow() { fn test_int_wrapper_mul_float_overflow() -> Result<()> {
let mut vm = setup_script( let mut vm = setup_script(
r#" r#"
pub fn test_int(a) { pub fn test_int(a) {
a *= 10.0; a *= 10.0;
} }
"#, "#,
); )?;
let val = wrap_int_reference(i64::MAX).unwrap(); let val = wrap_int_reference(i64::MAX)?;
execute_vm!(vm, "test_int", val); 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); assert_eq!(v, i64::MAX);
Ok(())
} }
#[test] #[test]
fn test_int_wrapper_mul_float_underflow() { fn test_int_wrapper_mul_float_underflow() -> Result<()> {
let mut vm = setup_script( let mut vm = setup_script(
r#" r#"
pub fn test_int(a) { pub fn test_int(a) {
a *= 10.0; a *= 10.0;
} }
"#, "#,
); )?;
let val = wrap_int_reference(i64::MIN).unwrap(); let val = wrap_int_reference(i64::MIN)?;
execute_vm!(vm, "test_int", val); 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); assert_eq!(v, i64::MIN);
Ok(())
} }
#[test] #[test]
fn test_int_wrapper_div() { fn test_int_wrapper_div() -> Result<()> {
let mut vm = setup_script( let mut vm = setup_script(
r#" r#"
pub fn test_int(a) { pub fn test_int(a) {
a /= 5; a /= 5;
} }
"#, "#,
); )?;
let val = wrap_int_reference(10).unwrap(); let val = wrap_int_reference(10)?;
execute_vm!(vm, "test_int", val); 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); assert_eq!(v, 2);
Ok(())
} }
#[test] #[test]
fn test_int_wrapper_div_float() { fn test_int_wrapper_div_float() -> Result<()> {
let mut vm = setup_script( let mut vm = setup_script(
r#" r#"
pub fn test_int(a) { pub fn test_int(a) {
a /= 0.5; a /= 0.5;
} }
"#, "#,
); )?;
let val = wrap_int_reference(10).unwrap(); let val = wrap_int_reference(10)?;
execute_vm!(vm, "test_int", val); 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); assert_eq!(v, 20);
Ok(())
} }
#[test] #[test]
fn test_int_wrapper_div_float_overflow() { fn test_int_wrapper_div_float_overflow() -> Result<()> {
let mut vm = setup_script( let mut vm = setup_script(
r#" r#"
pub fn test_int(a) { pub fn test_int(a) {
a /= 0.0001; a /= 0.0001;
} }
"#, "#,
); )?;
let val = wrap_int_reference(i64::MAX).unwrap(); let val = wrap_int_reference(i64::MAX)?;
execute_vm!(vm, "test_int", val); 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); assert_eq!(v, i64::MAX);
Ok(())
} }
#[test] #[test]
fn test_int_wrapper_div_float_underflow() { fn test_int_wrapper_div_float_underflow() -> Result<()> {
let mut vm = setup_script( let mut vm = setup_script(
r#" r#"
pub fn test_int(a) { pub fn test_int(a) {
a /= 0.0001; a /= 0.0001;
} }
"#, "#,
); )?;
let val = wrap_int_reference(i64::MIN).unwrap(); let val = wrap_int_reference(i64::MIN)?;
execute_vm!(vm, "test_int", val); 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); assert_eq!(v, i64::MIN);
Ok(())
} }
#[test] #[test]
fn test_int_wrapper_eq() { fn test_int_wrapper_eq() -> Result<()> {
let mut vm = setup_script( let mut vm = setup_script(
r#" r#"
pub fn test_int(a) { pub fn test_int(a) {
a == 5 a == 5
} }
"#, "#,
); )?;
let val = wrap_int_reference(5).unwrap(); let val = wrap_int_reference(5)?;
let res = execute_vm!(vm, "test_int", val); let res = execute_vm!(vm, "test_int", val);
let res = res.as_bool().unwrap(); let res = res.as_bool()?;
assert_eq!(res, true); assert_eq!(res, true);
Ok(())
} }
#[test] #[test]
fn test_int_wrapper_ineq() { fn test_int_wrapper_ineq() -> Result<()> {
let mut vm = setup_script( let mut vm = setup_script(
r#" r#"
pub fn test_int(a) { pub fn test_int(a) {
a == 5 a == 5
} }
"#, "#,
); )?;
let val = wrap_int_reference(6).unwrap(); let val = wrap_int_reference(6)?;
let res = execute_vm!(vm, "test_int", val); let res = execute_vm!(vm, "test_int", val);
let res = res.as_bool().unwrap(); let res = res.as_bool()?;
assert_eq!(res, false); assert_eq!(res, false);
Ok(())
} }
#[test] #[test]
fn test_int_wrapper_string_display() { fn test_int_wrapper_string_display() -> Result<()> {
let mut vm = setup_script( let mut vm = setup_script(
r#" r#"
pub fn test_int(a) { pub fn test_int(a) {
`${a}` `${a}`
} }
"#, "#,
); )?;
let val = wrap_int_reference(5).unwrap(); let val = wrap_int_reference(5)?;
let res = execute_vm!(vm, "test_int", val); 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"); assert_eq!(res, "5");
Ok(())
} }
#[test] #[test]
fn test_bool_wrapper_set_value() { fn test_bool_wrapper_set_value() -> Result<()> {
let mut vm = setup_script( let mut vm = setup_script(
r#" r#"
pub fn test_bool(a) { pub fn test_bool(a) {
a.set_value(true); a.set_value(true);
} }
"#, "#,
); )?;
let val = wrap_bool_reference(false).unwrap(); let val = wrap_bool_reference(false)?;
execute_vm!(vm, "test_bool", val); 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); assert_eq!(v, true);
Ok(())
} }
#[test] #[test]
fn test_bool_wrapper_as_bool() { fn test_bool_wrapper_as_bool() -> Result<()> {
let mut vm = setup_script( let mut vm = setup_script(
r#" r#"
pub fn test_bool(a) { pub fn test_bool(a) {
a.as_bool() 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 = execute_vm!(vm, "test_bool", val);
let res = res.as_bool().unwrap(); let res = res.as_bool()?;
assert_eq!(res, true); assert_eq!(res, true);
Ok(())
} }
#[test] #[test]
fn test_bool_wrapper_eq() { fn test_bool_wrapper_eq() -> Result<()> {
let mut vm = setup_script( let mut vm = setup_script(
r#" r#"
pub fn test_bool(a) { pub fn test_bool(a) {
a == true 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 = execute_vm!(vm, "test_bool", val);
let res = res.as_bool().unwrap(); let res = res.as_bool()?;
assert_eq!(res, true); assert_eq!(res, true);
Ok(())
} }
#[test] #[test]
fn test_bool_wrapper_ineq() { fn test_bool_wrapper_ineq() -> Result<()> {
let mut vm = setup_script( let mut vm = setup_script(
r#" r#"
pub fn test_bool(a) { pub fn test_bool(a) {
a == true 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 = execute_vm!(vm, "test_bool", val);
let res = res.as_bool().unwrap(); let res = res.as_bool()?;
assert_eq!(res, false); assert_eq!(res, false);
Ok(())
} }
#[test] #[test]
fn test_bool_wrapper_string_display() { fn test_bool_wrapper_string_display() -> Result<()> {
let mut vm = setup_script( let mut vm = setup_script(
r#" r#"
pub fn test_bool(a) { pub fn test_bool(a) {
`${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 = 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"); assert_eq!(res, "true");
Ok(())
} }
#[test] #[test]
fn test_string_key_wrapper_string_display() { fn test_string_key_wrapper_string_display() -> Result<()> {
let mut vm = setup_script( let mut vm = setup_script(
r#" r#"
pub fn test_string_key(a) { pub fn test_string_key(a) {
`${a}` `${a}`
} }
"#, "#,
); )?;
let val = RuneStringKey::new(StringKey::from("test")); let val = StringKey::from("test");
let val = Shared::new(AnyObj::new(val).unwrap()).unwrap(); let arg = val.wrap();
let arg = Value::Any(val);
let res = execute_vm!(vm, "test_string_key", arg); 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"); 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(())
} }
} }

View File

@ -1,6 +1,6 @@
use crate::script_implementations::rune::wrappers::{RuneStringKey, RuneWrapper}; use crate::script_implementations::rune::wrappers::{RuneStringKey, RuneWrapper};
use crate::static_data::Parameter; use crate::static_data::Parameter;
use rune::runtime::{AnyObj, Shared}; use rune::runtime::Value;
use rune::Any; use rune::Any;
use std::ops::Deref; use std::ops::Deref;
use std::sync::Arc; use std::sync::Arc;
@ -11,6 +11,7 @@ pub fn register(module: &mut rune::Module) -> anyhow::Result<()> {
} }
#[derive(Debug, Any)] #[derive(Debug, Any)]
#[rune(name = Parameter)]
pub(super) enum RuneParameter { pub(super) enum RuneParameter {
Int(#[rune(get)] i32), Int(#[rune(get)] i32),
Float(#[rune(get)] f32), Float(#[rune(get)] f32),
@ -19,13 +20,13 @@ pub(super) enum RuneParameter {
} }
impl RuneWrapper for &Arc<Parameter> { impl RuneWrapper for &Arc<Parameter> {
fn wrap(self) -> Shared<AnyObj> { fn wrap(self) -> Value {
let p = match self.deref() { let p = match self.deref() {
Parameter::Bool(b) => RuneParameter::Bool(*b), Parameter::Bool(b) => RuneParameter::Bool(*b),
Parameter::Int(i) => RuneParameter::Int(*i as i32), Parameter::Int(i) => RuneParameter::Int(*i as i32),
Parameter::Float(f) => RuneParameter::Float(*f), Parameter::Float(f) => RuneParameter::Float(*f),
Parameter::String(s) => RuneParameter::String(RuneStringKey::new(s.clone())), Parameter::String(s) => RuneParameter::String(RuneStringKey::new(s.clone())),
}; };
Shared::new(AnyObj::new(p).unwrap()).unwrap() rune::to_value(p).unwrap()
} }
} }

View File

@ -1,6 +1,7 @@
use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper}; use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper};
use crate::static_data::Ability; use crate::static_data::Ability;
use rune::runtime::{AnyObj, Shared}; use crate::StringKey;
use rune::runtime::Value;
use rune::Any; use rune::Any;
use std::sync::Arc; use std::sync::Arc;
@ -19,16 +20,101 @@ impl_rune_wrapper!(&Arc<dyn Ability>, RuneAbility);
impl RuneAbility { impl RuneAbility {
#[rune::function] #[rune::function]
fn name(&self) -> Shared<AnyObj> { self.0.name().wrap() } fn name(&self) -> Value { self.0.name().wrap() }
#[rune::function] #[rune::function]
fn effect(&self) -> Shared<AnyObj> { self.0.effect().wrap() } fn effect(&self) -> Value { self.0.effect().wrap() }
#[rune::function(vm_result)] #[rune::function]
fn get_parameter(&self, key: RuneStringKey) -> Option<Shared<AnyObj>> { fn get_parameter(&self, key: Value) -> Option<Value> {
match self.0.parameters().get(&key.0) { if let Ok(s) = key.borrow_string_ref() {
None => None, return self.0.parameters().get(&StringKey::new(&s)).map(|v| v.wrap());
Some(p) => Some(p.wrap()), }
if let Ok(v) = key.into_any::<RuneStringKey>() {
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<dyn Ability> = 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<dyn Ability> = 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<dyn Ability> = Arc::new(ability);
let wrapped = a.wrap();
execute_vm!(&mut vm, "test_ability", wrapped);
Ok(())
}
}

View File

@ -1,6 +1,7 @@
use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper}; use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper};
use crate::static_data::{AbilityIndex, Form, Statistic}; use crate::static_data::{AbilityIndex, Form, Statistic};
use rune::runtime::{AnyObj, Shared}; use crate::StringKey;
use rune::runtime::Value;
use rune::Any; use rune::Any;
use std::sync::Arc; use std::sync::Arc;
@ -22,13 +23,14 @@ pub fn register(module: &mut rune::Module) -> anyhow::Result<()> {
} }
#[derive(Debug, Any)] #[derive(Debug, Any)]
#[rune(name = Form)]
pub struct RuneForm(pub Arc<dyn Form>); pub struct RuneForm(pub Arc<dyn Form>);
impl_rune_wrapper!(&Arc<dyn Form>, RuneForm); impl_rune_wrapper!(&Arc<dyn Form>, RuneForm);
impl RuneForm { impl RuneForm {
#[rune::function] #[rune::function]
fn name(&self) -> Shared<AnyObj> { self.0.name().wrap() } fn name(&self) -> Value { self.0.name().wrap() }
#[rune::function] #[rune::function]
fn height(&self) -> f32 { self.0.height() } fn height(&self) -> f32 { self.0.height() }
@ -40,28 +42,286 @@ impl RuneForm {
fn base_experience(&self) -> u32 { self.0.base_experience() } fn base_experience(&self) -> u32 { self.0.base_experience() }
#[rune::function] #[rune::function]
fn types(&self) -> Vec<u8> { self.0.types().iter().map(|t| u8::from(*t)).collect() } fn types(&self) -> Vec<i64> { self.0.types().iter().map(|t| u8::from(*t) as i64).collect() }
#[rune::function] #[rune::function]
fn base_stats(&self) -> Shared<AnyObj> { self.0.base_stats().wrap() } fn base_stats(&self) -> Value { self.0.base_stats().wrap() }
#[rune::function] #[rune::function]
fn abilities(&self) -> Vec<Shared<AnyObj>> { self.0.abilities().iter().map(|a| a.wrap()).collect() } fn abilities(&self) -> Vec<Value> { self.0.abilities().iter().map(|a| a.wrap()).collect() }
#[rune::function] #[rune::function]
fn hidden_abilities(&self) -> Vec<Shared<AnyObj>> { self.0.hidden_abilities().iter().map(|a| a.wrap()).collect() } fn hidden_abilities(&self) -> Vec<Value> { self.0.hidden_abilities().iter().map(|a| a.wrap()).collect() }
#[rune::function] #[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::<RuneStringKey>() {
return self.0.has_flag(&v.0);
}
false
}
#[rune::function] #[rune::function]
fn get_type(&self, index: usize) -> anyhow::Result<u8> { self.0.get_type(index).map(|t| u8::from(t)) } fn get_type(&self, index: usize) -> anyhow::Result<i64> { self.0.get_type(index).map(|t| u8::from(t) as i64) }
#[rune::function] #[rune::function]
fn get_base_stat(&self, statistic: Statistic) -> u16 { self.0.get_base_stat(statistic) } fn get_base_stat(&self, statistic: Statistic) -> u16 { self.0.get_base_stat(statistic) }
#[rune::function] #[rune::function]
fn get_ability(&self, hidden: bool, index: u8) -> anyhow::Result<Shared<AnyObj>> { fn get_ability(&self, hidden: bool, index: i64) -> anyhow::Result<Value> {
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()) 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<dyn Form> = 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<dyn Form> = 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<dyn Form> = 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<dyn Form> = 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<dyn Form> = 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::<u16>::new(1, 2, 3, 4, 5, 6)));
let form: Arc<dyn Form> = 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<dyn Form> = 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<dyn Form> = 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<dyn Form> = 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<dyn Form> = 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::<u16>::new(1, 2, 3, 4, 5, 6).hp());
let form: Arc<dyn Form> = 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<dyn Form> = Arc::new(form);
let wrapped = form.wrap();
execute_vm!(&mut vm, "test_form", wrapped);
Ok(())
}
}

View File

@ -21,7 +21,59 @@ impl RuneGrowthRate {
fn calculate_level(&self, experience: u32) -> i32 { self.0.calculate_level(experience) as i32 } fn calculate_level(&self, experience: u32) -> i32 { self.0.calculate_level(experience) as i32 }
#[rune::function] #[rune::function]
fn calculate_experience(&self, level: LevelInt) -> Result<u32, String> { fn calculate_experience(&self, level: i64) -> Result<u32, String> {
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()) 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<dyn GrowthRate> = 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<dyn GrowthRate> = Arc::new(growth_rate);
let wrapped = growth_rate.wrap();
execute_vm!(&mut vm, "test_growth_rate", wrapped);
Ok(())
}
}

View File

@ -1,6 +1,6 @@
use std::sync::Arc; use std::sync::Arc;
use rune::runtime::{AnyObj, Shared}; use rune::runtime::Value;
use rune::Any; use rune::Any;
use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper}; use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper};
@ -28,7 +28,7 @@ impl_rune_wrapper!(&Arc<dyn Item>, RuneItem);
impl RuneItem { impl RuneItem {
#[rune::function] #[rune::function]
fn name(&self) -> Shared<AnyObj> { self.0.name().clone().wrap() } fn name(&self) -> Value { self.0.name().clone().wrap() }
#[rune::function] #[rune::function]
fn category(&self) -> ItemCategory { self.0.category() } fn category(&self) -> ItemCategory { self.0.category() }
@ -40,8 +40,34 @@ impl RuneItem {
fn price(&self) -> i32 { self.0.price() } fn price(&self) -> i32 { self.0.price() }
#[rune::function] #[rune::function]
fn flags(&self) -> Vec<Shared<AnyObj>> { self.0.flags().iter().map(|s| s.clone().wrap()).collect() } fn flags(&self) -> Vec<Value> { self.0.flags().iter().map(|s| s.clone().wrap()).collect() }
#[rune::function] #[rune::function]
fn has_flag(&self, key: &RuneStringKey) -> bool { self.0.has_flag(&key.0) } 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<dyn Item> = Arc::new(item);
let wrapped = item.wrap();
execute_vm!(&mut vm, "test_item", wrapped);
Ok(())
}
}

View File

@ -1,7 +1,7 @@
use crate::defines::LevelInt; use crate::defines::LevelInt;
use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper}; use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper};
use crate::static_data::LearnableMoves; use crate::static_data::LearnableMoves;
use rune::runtime::{AnyObj, Shared}; use rune::runtime::Value;
use rune::Any; use rune::Any;
use std::sync::Arc; use std::sync::Arc;
@ -20,14 +20,14 @@ impl_rune_wrapper!(&Arc<dyn LearnableMoves>, RuneLearnableMoves);
impl RuneLearnableMoves { impl RuneLearnableMoves {
#[rune::function] #[rune::function]
fn get_learned_by_level(&self, level: LevelInt) -> Option<Vec<Shared<AnyObj>>> { fn get_learned_by_level(&self, level: LevelInt) -> Option<Vec<Value>> {
self.0 self.0
.get_learned_by_level(level) .get_learned_by_level(level)
.map(|v| v.into_iter().map(|s| s.wrap()).collect()) .map(|v| v.into_iter().map(|s| s.wrap()).collect())
} }
#[rune::function] #[rune::function]
fn get_distinct_level_moves(&self) -> Vec<Shared<AnyObj>> { fn get_distinct_level_moves(&self) -> Vec<Value> {
self.0 self.0
.get_distinct_level_moves() .get_distinct_level_moves()
.into_iter() .into_iter()

View File

@ -6,7 +6,7 @@ mod type_library;
use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper}; use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper};
use crate::static_data::{AbilityLibrary, ItemLibrary, MoveLibrary, SpeciesLibrary}; use crate::static_data::{AbilityLibrary, ItemLibrary, MoveLibrary, SpeciesLibrary};
use rune::runtime::{AnyObj, Shared}; use rune::runtime::Value;
use std::sync::Arc; use std::sync::Arc;
pub fn register(module: &mut rune::Module) -> anyhow::Result<()> { pub fn register(module: &mut rune::Module) -> anyhow::Result<()> {
@ -49,13 +49,13 @@ macro_rules! impl_rune_data_library_wrapper {
impl $t { impl $t {
#[rune::function] #[rune::function]
fn get(&self, key: &RuneStringKey) -> Option<Shared<AnyObj>> { self.0.get(&key.0).map(|v| v.wrap()) } fn get(&self, key: &RuneStringKey) -> Option<Value> { self.0.get(&key.0).map(|v| v.wrap()) }
#[rune::function] #[rune::function]
fn len(&self) -> usize { self.0.len() } fn len(&self) -> usize { self.0.len() }
#[rune::function] #[rune::function]
fn get_key_by_index(&self, index: usize) -> Option<Shared<AnyObj>> { fn get_key_by_index(&self, index: usize) -> Option<Value> {
self.0.get_key_by_index(index).map(|v| v.wrap()) self.0.get_key_by_index(index).map(|v| v.wrap())
} }
} }

View File

@ -1,7 +1,7 @@
use crate::script_implementations::rune::wrappers::static_data::nature::RuneNature; use crate::script_implementations::rune::wrappers::static_data::nature::RuneNature;
use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper}; use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper};
use crate::static_data::NatureLibrary; use crate::static_data::NatureLibrary;
use rune::runtime::{AnyObj, Shared}; use rune::runtime::Value;
use std::sync::Arc; use std::sync::Arc;
pub fn register(module: &mut rune::Module) -> anyhow::Result<()> { pub fn register(module: &mut rune::Module) -> anyhow::Result<()> {
@ -18,7 +18,7 @@ impl_rune_wrapper!(&Arc<dyn NatureLibrary>, RuneNatureLibrary);
impl RuneNatureLibrary { impl RuneNatureLibrary {
#[rune::function] #[rune::function]
fn get_nature(&self, key: RuneStringKey) -> Option<Shared<AnyObj>> { self.0.get_nature(&key.0).map(|v| v.wrap()) } fn get_nature(&self, key: RuneStringKey) -> Option<Value> { self.0.get_nature(&key.0).map(|v| v.wrap()) }
#[rune::function] #[rune::function]
fn get_nature_name(&self, nature: &RuneNature) -> RuneStringKey { fn get_nature_name(&self, nature: &RuneNature) -> RuneStringKey {

View File

@ -1,6 +1,6 @@
use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneWrapper}; use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneWrapper};
use crate::static_data::StaticData; use crate::static_data::StaticData;
use rune::runtime::{AnyObj, Shared}; use rune::runtime::Value;
use std::sync::Arc; use std::sync::Arc;
pub fn register(module: &mut rune::Module) -> anyhow::Result<()> { pub fn register(module: &mut rune::Module) -> anyhow::Result<()> {
@ -23,26 +23,26 @@ impl_rune_wrapper!(&Arc<dyn StaticData>, RuneStaticData);
impl RuneStaticData { impl RuneStaticData {
#[rune::function] #[rune::function]
fn settings(&self) -> Shared<AnyObj> { self.0.settings().wrap() } fn settings(&self) -> Value { self.0.settings().wrap() }
#[rune::function] #[rune::function]
fn species(&self) -> Shared<AnyObj> { self.0.species().wrap() } fn species(&self) -> Value { self.0.species().wrap() }
#[rune::function] #[rune::function]
fn moves(&self) -> Shared<AnyObj> { self.0.moves().wrap() } fn moves(&self) -> Value { self.0.moves().wrap() }
#[rune::function] #[rune::function]
fn items(&self) -> Shared<AnyObj> { self.0.items().wrap() } fn items(&self) -> Value { self.0.items().wrap() }
#[rune::function] #[rune::function]
fn growth_rates(&self) -> Shared<AnyObj> { self.0.growth_rates().wrap() } fn growth_rates(&self) -> Value { self.0.growth_rates().wrap() }
#[rune::function] #[rune::function]
fn types(&self) -> Shared<AnyObj> { self.0.types().wrap() } fn types(&self) -> Value { self.0.types().wrap() }
#[rune::function] #[rune::function]
fn natures(&self) -> Shared<AnyObj> { self.0.natures().wrap() } fn natures(&self) -> Value { self.0.natures().wrap() }
#[rune::function] #[rune::function]
fn abilities(&self) -> Shared<AnyObj> { self.0.abilities().wrap() } fn abilities(&self) -> Value { self.0.abilities().wrap() }
} }

View File

@ -1,6 +1,6 @@
use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper}; use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper};
use crate::static_data::TypeLibrary; use crate::static_data::TypeLibrary;
use rune::runtime::{AnyObj, Shared}; use rune::runtime::Value;
use std::sync::Arc; use std::sync::Arc;
pub fn register(module: &mut rune::Module) -> anyhow::Result<()> { pub fn register(module: &mut rune::Module) -> anyhow::Result<()> {
@ -22,7 +22,7 @@ impl RuneTypeLibrary {
fn get_type_id(&self, key: &RuneStringKey) -> Option<u8> { self.0.get_type_id(&key.0).map(|v| v.into()) } fn get_type_id(&self, key: &RuneStringKey) -> Option<u8> { self.0.get_type_id(&key.0).map(|v| v.into()) }
#[rune::function] #[rune::function]
fn get_type_name(&self, t: u8) -> Option<Shared<AnyObj>> { self.0.get_type_name(t.into()).map(|v| v.wrap()) } fn get_type_name(&self, t: u8) -> Option<Value> { self.0.get_type_name(t.into()).map(|v| v.wrap()) }
#[rune::function] #[rune::function]
fn get_single_effectiveness(&self, attacking: u8, defending: u8) -> anyhow::Result<f32> { fn get_single_effectiveness(&self, attacking: u8, defending: u8) -> anyhow::Result<f32> {

View File

@ -1,7 +1,7 @@
use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper}; use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper};
use crate::static_data::{MoveCategory, MoveData, MoveTarget, SecondaryEffect}; use crate::static_data::{MoveCategory, MoveData, MoveTarget, SecondaryEffect};
use rune::runtime::{AnyObj, Object, Shared}; use rune::runtime::{Object, Value};
use rune::{Any, Value}; use rune::Any;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::sync::Arc; use std::sync::Arc;
@ -35,7 +35,7 @@ impl_rune_wrapper!(&Arc<dyn MoveData>, RuneMoveData);
impl RuneMoveData { impl RuneMoveData {
#[rune::function] #[rune::function]
fn name(&self) -> Shared<AnyObj> { self.0.name().wrap() } fn name(&self) -> Value { self.0.name().wrap() }
#[rune::function] #[rune::function]
fn move_type(&self) -> u8 { u8::from(self.0.move_type()) } fn move_type(&self) -> u8 { u8::from(self.0.move_type()) }
@ -59,7 +59,7 @@ impl RuneMoveData {
fn priority(&self) -> i8 { self.0.priority() } fn priority(&self) -> i8 { self.0.priority() }
#[rune::function] #[rune::function]
fn secondary_effect(&self) -> Option<Shared<AnyObj>> { self.0.secondary_effect().as_ref().map(|x| x.wrap()) } fn secondary_effect(&self) -> Option<Value> { self.0.secondary_effect().as_ref().map(|x| x.wrap()) }
#[rune::function] #[rune::function]
fn has_flag(&self, flag: RuneStringKey) -> bool { self.0.has_flag(&flag.0) } 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() } fn chance(&self) -> f32 { self.0.chance() }
#[rune::function] #[rune::function]
fn effect_name(&self) -> Shared<AnyObj> { self.0.effect_name().wrap() } fn effect_name(&self) -> Value { self.0.effect_name().wrap() }
#[rune::function] #[rune::function]
fn parameters(&self) -> anyhow::Result<Object> { fn parameters(&self) -> anyhow::Result<Object> {

View File

@ -1,6 +1,6 @@
use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper}; use crate::script_implementations::rune::wrappers::{impl_rune_wrapper, RuneStringKey, RuneWrapper};
use crate::static_data::Species; use crate::static_data::Species;
use rune::runtime::{AnyObj, Shared}; use rune::runtime::Value;
use rune::Any; use rune::Any;
use std::sync::Arc; use std::sync::Arc;
@ -29,13 +29,13 @@ impl RuneSpecies {
fn id(&self) -> u16 { self.0.id() } fn id(&self) -> u16 { self.0.id() }
#[rune::function] #[rune::function]
fn name(&self) -> Shared<AnyObj> { self.0.name().wrap() } fn name(&self) -> Value { self.0.name().wrap() }
#[rune::function] #[rune::function]
fn gender_rate(&self) -> f32 { self.0.gender_rate() } fn gender_rate(&self) -> f32 { self.0.gender_rate() }
#[rune::function] #[rune::function]
fn growth_rate(&self) -> Shared<AnyObj> { self.0.growth_rate().wrap() } fn growth_rate(&self) -> Value { self.0.growth_rate().wrap() }
#[rune::function] #[rune::function]
fn capture_rate(&self) -> u8 { self.0.capture_rate() } fn capture_rate(&self) -> u8 { self.0.capture_rate() }
@ -44,12 +44,10 @@ impl RuneSpecies {
fn base_happiness(&self) -> u8 { self.0.base_happiness() } fn base_happiness(&self) -> u8 { self.0.base_happiness() }
#[rune::function] #[rune::function]
fn get_form(&self, name: &RuneStringKey) -> Option<Shared<AnyObj>> { fn get_form(&self, name: &RuneStringKey) -> Option<Value> { self.0.get_form(&name.0).map(|form| form.wrap()) }
self.0.get_form(&name.0).map(|form| form.wrap())
}
#[rune::function] #[rune::function]
fn get_default_form(&self) -> anyhow::Result<Shared<AnyObj>> { self.0.get_default_form().map(|v| v.wrap()) } fn get_default_form(&self) -> anyhow::Result<Value> { self.0.get_default_form().map(|v| v.wrap()) }
#[rune::function] #[rune::function]
fn has_flag(&self, key: &RuneStringKey) -> bool { self.0.has_flag(&key.0) } fn has_flag(&self, key: &RuneStringKey) -> bool { self.0.has_flag(&key.0) }

View File

@ -12,20 +12,28 @@ use crate::StringKey;
#[repr(u8)] #[repr(u8)]
pub enum ItemCategory { pub enum ItemCategory {
/// This is where most items should go. /// This is where most items should go.
#[cfg_attr(feature = "rune", rune(constructor))]
MiscItem, MiscItem,
/// Pokeballs are used for capturing Pokemons. /// Pokeballs are used for capturing Pokemons.
#[cfg_attr(feature = "rune", rune(constructor))]
Pokeball, Pokeball,
/// Medicine is used for healing HP, PP, and status effects /// Medicine is used for healing HP, PP, and status effects
#[cfg_attr(feature = "rune", rune(constructor))]
Medicine, Medicine,
/// Berry is used for all berries. /// Berry is used for all berries.
#[cfg_attr(feature = "rune", rune(constructor))]
Berry, Berry,
/// TMHM is used for Technical and Hidden Machines. /// TMHM is used for Technical and Hidden Machines.
#[cfg_attr(feature = "rune", rune(constructor))]
TMHM, TMHM,
/// Form Changer is used for items that change forms, such as mega stones. /// Form Changer is used for items that change forms, such as mega stones.
#[cfg_attr(feature = "rune", rune(constructor))]
FormChanger, FormChanger,
/// Key Items are single stored items, generally used for story progression. /// Key Items are single stored items, generally used for story progression.
#[cfg_attr(feature = "rune", rune(constructor))]
KeyItem, KeyItem,
/// Mail is used for mail items. /// Mail is used for mail items.
#[cfg_attr(feature = "rune", rune(constructor))]
Mail, Mail,
} }
@ -36,14 +44,19 @@ pub enum ItemCategory {
#[repr(u8)] #[repr(u8)]
pub enum BattleItemCategory { pub enum BattleItemCategory {
/// This item can't be used in battle. /// This item can't be used in battle.
#[cfg_attr(feature = "rune", rune(constructor))]
None, None,
/// This item is used for healing Pokemon. /// This item is used for healing Pokemon.
#[cfg_attr(feature = "rune", rune(constructor))]
Healing, Healing,
/// This item is used for healing Pokemon from a status. /// This item is used for healing Pokemon from a status.
#[cfg_attr(feature = "rune", rune(constructor))]
StatusHealing, StatusHealing,
/// This item is used for capturing Pokemon. /// This item is used for capturing Pokemon.
#[cfg_attr(feature = "rune", rune(constructor))]
Pokeball, Pokeball,
/// This item does not belong in above categories, but is still a battle item. /// This item does not belong in above categories, but is still a battle item.
#[cfg_attr(feature = "rune", rune(constructor))]
MiscBattleItem, MiscBattleItem,
} }

View File

@ -14,6 +14,8 @@ use std::fmt::{Display, Formatter};
#[cfg(test)] #[cfg(test)]
pub(crate) mod tests { pub(crate) mod tests {
use super::*; 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 moves::tests::*;
#[doc(inline)] pub use natures::tests::*; #[doc(inline)] pub use natures::tests::*;
#[doc(inline)] pub use species_data::tests::*; #[doc(inline)] pub use species_data::tests::*;

View File

@ -44,12 +44,12 @@ pub trait Form: Debug {
fn find_ability_index(&self, ability: &dyn Ability) -> Option<AbilityIndex>; fn find_ability_index(&self, ability: &dyn Ability) -> Option<AbilityIndex>;
/// Gets an ability from the form. /// Gets an ability from the form.
fn get_ability(&self, index: AbilityIndex) -> Result<&StringKey>; fn get_ability(&self, index: AbilityIndex) -> Result<StringKey>;
/// Gets a random ability from the form. /// 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<StringKey>;
/// Gets a random hidden ability from the form. /// 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<StringKey>;
/// Check if the form has a specific flag set. /// Check if the form has a specific flag set.
fn has_flag(&self, key: &StringKey) -> bool; fn has_flag(&self, key: &StringKey) -> bool;
@ -118,56 +118,32 @@ impl FormImpl {
impl Form for FormImpl { impl Form for FormImpl {
/// The name of the form. /// The name of the form.
fn name(&self) -> &StringKey { fn name(&self) -> &StringKey { &self.name }
&self.name
}
/// The height of the form in meters. /// The height of the form in meters.
fn height(&self) -> f32 { fn height(&self) -> f32 { self.height }
self.height
}
/// The weight of the form in kilograms. /// The weight of the form in kilograms.
fn weight(&self) -> f32 { fn weight(&self) -> f32 { self.weight }
self.weight
}
/// The base amount of experience that is gained when beating a Pokemon with this form. /// The base amount of experience that is gained when beating a Pokemon with this form.
fn base_experience(&self) -> u32 { fn base_experience(&self) -> u32 { self.base_experience }
self.base_experience
}
/// The normal types a Pokemon with this form has. /// The normal types a Pokemon with this form has.
fn types(&self) -> &Vec<TypeIdentifier> { fn types(&self) -> &Vec<TypeIdentifier> { &self.types }
&self.types
}
/// The inherent values of a form of species that are used for the stats of a Pokemon. /// The inherent values of a form of species that are used for the stats of a Pokemon.
fn base_stats(&self) -> &Arc<StaticStatisticSet<u16>> { fn base_stats(&self) -> &Arc<StaticStatisticSet<u16>> { &self.base_stats }
&self.base_stats
}
/// The possible abilities a Pokemon with this form can have. /// The possible abilities a Pokemon with this form can have.
fn abilities(&self) -> &Vec<StringKey> { fn abilities(&self) -> &Vec<StringKey> { &self.abilities }
&self.abilities
}
/// The possible hidden abilities a Pokemon with this form can have. /// The possible hidden abilities a Pokemon with this form can have.
fn hidden_abilities(&self) -> &Vec<StringKey> { fn hidden_abilities(&self) -> &Vec<StringKey> { &self.hidden_abilities }
&self.hidden_abilities
}
/// The moves a Pokemon with this form can learn. /// The moves a Pokemon with this form can learn.
fn moves(&self) -> &Arc<dyn LearnableMoves> { fn moves(&self) -> &Arc<dyn LearnableMoves> { &self.moves }
&self.moves
}
/// Arbitrary flags can be set on a form for scripting use. /// Arbitrary flags can be set on a form for scripting use.
fn flags(&self) -> &HashSet<StringKey> { fn flags(&self) -> &HashSet<StringKey> { &self.flags }
&self.flags
}
/// Get a type of the move at a certain index. /// Get a type of the move at a certain index.
fn get_type(&self, index: usize) -> Result<TypeIdentifier> { fn get_type(&self, index: usize) -> Result<TypeIdentifier> { Ok(*self.types.get_res(index)?) }
Ok(*self.types.get_res(index)?)
}
/// Gets a single base stat value. /// Gets a single base stat value.
fn get_base_stat(&self, stat: Statistic) -> u16 { fn get_base_stat(&self, stat: Statistic) -> u16 { self.base_stats.get_stat(stat) }
self.base_stats.get_stat(stat)
}
/// Find the index of an ability that can be on this form. /// Find the index of an ability that can be on this form.
fn find_ability_index(&self, ability: &dyn Ability) -> Option<AbilityIndex> { fn find_ability_index(&self, ability: &dyn Ability) -> Option<AbilityIndex> {
@ -191,39 +167,35 @@ impl Form for FormImpl {
} }
/// Gets an ability from the form. /// Gets an ability from the form.
fn get_ability(&self, index: AbilityIndex) -> Result<&StringKey> { fn get_ability(&self, index: AbilityIndex) -> Result<StringKey> {
if index.hidden { 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 { } 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. /// 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<StringKey> {
ensure!(!self.abilities.is_empty(), "No abilities on form"); ensure!(!self.abilities.is_empty(), "No abilities on form");
self.abilities self.abilities
.get_res(rand.get_between_unsigned(0, self.abilities.len() as u32) as usize) .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. /// 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<StringKey> {
ensure!(!self.hidden_abilities.is_empty(), "No hidden abilities on form"); ensure!(!self.hidden_abilities.is_empty(), "No hidden abilities on form");
self.hidden_abilities self.hidden_abilities
.get_res(rand.get_between_unsigned(0, self.hidden_abilities.len() as u32) as usize) .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. /// Check if the form has a specific flag set.
fn has_flag(&self, key: &StringKey) -> bool { fn has_flag(&self, key: &StringKey) -> bool { self.flags.contains(key) }
self.flags.contains(key)
}
fn has_flag_by_hash(&self, key_hash: u32) -> bool { fn has_flag_by_hash(&self, key_hash: u32) -> bool { self.flags.contains::<u32>(&key_hash) }
self.flags.contains::<u32>(&key_hash)
}
fn eq(&self, other: &dyn Form) -> bool { fn eq(&self, other: &dyn Form) -> bool { std::ptr::eq(self, other as *const dyn Form as *const Self) }
std::ptr::eq(self, other as *const dyn Form as *const Self)
}
} }
#[cfg(test)] #[cfg(test)]
@ -249,9 +221,9 @@ pub(crate) mod tests {
fn get_type(&self, index: usize) -> Result<TypeIdentifier>; fn get_type(&self, index: usize) -> Result<TypeIdentifier>;
fn get_base_stat(&self, stat: Statistic) -> u16; fn get_base_stat(&self, stat: Statistic) -> u16;
fn find_ability_index(&self, ability: &dyn Ability) -> Option<AbilityIndex>; fn find_ability_index(&self, ability: &dyn Ability) -> Option<AbilityIndex>;
fn get_ability<'a>(&'a self, index: AbilityIndex) -> Result<&'a StringKey>; fn get_ability(&self, index: AbilityIndex) -> Result<StringKey>;
fn get_random_ability<'a>(&'a self, rand: &mut Random) -> Result<&'a StringKey>; fn get_random_ability(&self, rand: &mut Random) -> Result<StringKey>;
fn get_random_hidden_ability<'a>(&'a self, rand: &mut Random) -> Result<&'a StringKey>; fn get_random_hidden_ability(&self, rand: &mut Random) -> Result<StringKey>;
fn has_flag(&self, key: &StringKey) -> bool; fn has_flag(&self, key: &StringKey) -> bool;
fn has_flag_by_hash(&self, key_hash: u32) -> bool; fn has_flag_by_hash(&self, key_hash: u32) -> bool;
fn eq(&self, other: &dyn Form) -> bool; fn eq(&self, other: &dyn Form) -> bool;

View File

@ -9,6 +9,7 @@
pub(crate) mod tests { pub(crate) mod tests {
pub use super::form::tests::*; pub use super::form::tests::*;
pub use super::species::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. /// An ability is a passive effect in battle that is attached to a Pokemon.

View File

@ -7,15 +7,21 @@
#[repr(u8)] #[repr(u8)]
pub enum Statistic { pub enum Statistic {
/// Health Points determine how much damage a Pokemon can receive before fainting. /// Health Points determine how much damage a Pokemon can receive before fainting.
#[cfg_attr(feature = "rune", rune(constructor))]
HP, HP,
/// Attack determines how much damage a Pokemon deals when using a physical attack. /// Attack determines how much damage a Pokemon deals when using a physical attack.
#[cfg_attr(feature = "rune", rune(constructor))]
Attack, Attack,
/// Defense determines how much damage a Pokemon receives when it is hit by a physical attack. /// Defense determines how much damage a Pokemon receives when it is hit by a physical attack.
#[cfg_attr(feature = "rune", rune(constructor))]
Defense, Defense,
/// Special Attack determines how much damage a Pokemon deals when using a special attack. /// Special Attack determines how much damage a Pokemon deals when using a special attack.
#[cfg_attr(feature = "rune", rune(constructor))]
SpecialAttack, SpecialAttack,
/// Special Defense determines how much damage a Pokemon receives when it is hit by a special attack. /// Special Defense determines how much damage a Pokemon receives when it is hit by a special attack.
#[cfg_attr(feature = "rune", rune(constructor))]
SpecialDefense, SpecialDefense,
/// Speed determines the order that a Pokemon can act in battle. /// Speed determines the order that a Pokemon can act in battle.
#[cfg_attr(feature = "rune", rune(constructor))]
Speed, Speed,
} }

View File

@ -10,12 +10,10 @@ fn integration_tests(input: &Path) {
let mut str: String = "".to_string(); let mut str: String = "".to_string();
let mut file = File::open(input).unwrap(); let mut file = File::open(input).unwrap();
file.read_to_string(&mut str).unwrap(); file.read_to_string(&mut str).unwrap();
let test_case = serde_yaml::from_str::<TestCase>(&str).unwrap(); let test_case = serde_yml::from_str::<TestCase>(&str).unwrap();
println!(" Running integration test {}", test_case.name); println!(" Running integration test {}", test_case.name);
test_case.run_test(get_library()); test_case.run_test(get_library());
} }
#[test] #[test]
fn basic_single_turn() { fn basic_single_turn() { integration_tests(Path::new("tests/test_cases/basic_single_turn.yaml")); }
integration_tests(Path::new("tests/test_cases/basic_single_turn.yaml"));
}