Initial work on rune as scripting library
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
153
src/script_implementations/rune/script.rs
Normal file
153
src/script_implementations/rune/script.rs
Normal file
@@ -0,0 +1,153 @@
|
||||
use crate::dynamic_data::{DynamicLibrary, ExecutingMove, Pokemon, Script, ScriptOwnerData, TurnChoice};
|
||||
use crate::script_implementations::rune::wrappers::*;
|
||||
use crate::script_implementations::rune::RuneScriptType;
|
||||
use crate::static_data::Parameter;
|
||||
use crate::StringKey;
|
||||
use hashbrown::HashMap;
|
||||
use parking_lot::RwLock;
|
||||
use rune::runtime::{Object, RuntimeContext, Shared, VmError, VmResult};
|
||||
use rune::{Any, Unit, Value};
|
||||
use std::convert::TryFrom;
|
||||
use std::error::Error;
|
||||
use std::ops::Deref;
|
||||
use std::sync::atomic::{AtomicBool, AtomicUsize};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct RuneScript {
|
||||
name: StringKey,
|
||||
state: RwLock<Shared<Object>>,
|
||||
/// 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).
|
||||
marked_for_deletion: AtomicBool,
|
||||
/// A script can be suppressed by other scripts. If a script is suppressed by at least one script
|
||||
/// we will not execute its methods. This holds the number of suppressions on the script.
|
||||
suppressed_count: AtomicUsize,
|
||||
/// The owner of this script (where the script is attached to)
|
||||
owner: ScriptOwnerData,
|
||||
|
||||
script_type: Arc<RuneScriptType>,
|
||||
|
||||
runtime: Arc<RuntimeContext>,
|
||||
unit: Arc<Unit>,
|
||||
}
|
||||
|
||||
unsafe impl Send for RuneScript {}
|
||||
|
||||
unsafe impl Sync for RuneScript {}
|
||||
|
||||
impl RuneScript {
|
||||
pub fn new(
|
||||
name: StringKey,
|
||||
object: Shared<Object>,
|
||||
owner: ScriptOwnerData,
|
||||
script_type: Arc<RuneScriptType>,
|
||||
runtime: Arc<RuntimeContext>,
|
||||
unit: Arc<Unit>,
|
||||
) -> Self {
|
||||
Self {
|
||||
name,
|
||||
state: RwLock::new(object),
|
||||
marked_for_deletion: Default::default(),
|
||||
suppressed_count: Default::default(),
|
||||
owner,
|
||||
script_type,
|
||||
runtime,
|
||||
unit,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Script for RuneScript {
|
||||
fn name(&self) -> anyhow::Result<&StringKey> { Ok(&self.name) }
|
||||
|
||||
fn get_marked_for_deletion(&self) -> &AtomicBool { &self.marked_for_deletion }
|
||||
|
||||
fn get_suppressed_count(&self) -> &AtomicUsize { &self.suppressed_count }
|
||||
|
||||
fn on_initialize(
|
||||
&self,
|
||||
_: &Arc<dyn DynamicLibrary>,
|
||||
pars: &HashMap<StringKey, Arc<Parameter>>,
|
||||
) -> anyhow::Result<()> {
|
||||
if pars.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
let mut write_lock = self.state.write();
|
||||
for par in pars {
|
||||
let key = rune::alloc::string::String::try_from(par.0.str())?;
|
||||
write_lock
|
||||
.borrow_mut()?
|
||||
.insert(key, parameter_to_rune_value(par.1.as_ref())?)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn block_critical(
|
||||
&self,
|
||||
move_data: &Arc<ExecutingMove>,
|
||||
target: &Pokemon,
|
||||
hit: u8,
|
||||
block_critical: &mut bool,
|
||||
) -> anyhow::Result<()> {
|
||||
if let Some(hash) = self.script_type.fn_block_critical {
|
||||
let mut vm = rune::runtime::Vm::new(self.runtime.clone(), self.unit.clone());
|
||||
todo!()
|
||||
// let block_critical_handle = RuneValueWrapper::new_mut(block_critical);
|
||||
// let read_lock = self.state.read();
|
||||
// let state = read_lock.deref();
|
||||
//
|
||||
// vm.execute(
|
||||
// hash,
|
||||
// vec![
|
||||
// Value::Object(state.clone()),
|
||||
// Value::from(move_data.wrap()?),
|
||||
// Value::from(target.wrap()?),
|
||||
// Value::from(hit),
|
||||
// Value::from(block_critical_handle.clone().wrap()?),
|
||||
// ],
|
||||
// )?;
|
||||
// *block_critical = block_critical_handle.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn change_speed(&self, choice: &Arc<TurnChoice>, speed: &mut u32) -> anyhow::Result<()> {
|
||||
if let Some(hash) = self.script_type.fn_change_speed {
|
||||
let mut vm = rune::runtime::Vm::new(self.runtime.clone(), self.unit.clone());
|
||||
let speed_handle = wrap_value_reference(*speed as i64)?;
|
||||
let read_lock = self.state.read();
|
||||
let state = read_lock.deref();
|
||||
|
||||
let res = vm
|
||||
.execute(
|
||||
hash,
|
||||
vec![
|
||||
Value::Object(state.clone()),
|
||||
Value::from(choice.wrap()),
|
||||
speed_handle.clone(),
|
||||
],
|
||||
)?
|
||||
.complete();
|
||||
if let VmResult::Err(e) = res {
|
||||
return Err(anyhow::anyhow!("Error executing script: {}", e));
|
||||
}
|
||||
|
||||
*speed = get_value_reference(speed_handle)? as u32;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any { self }
|
||||
|
||||
fn as_any_mut(&mut self) -> &mut dyn std::any::Any { self }
|
||||
}
|
||||
|
||||
fn parameter_to_rune_value(parameter: &Parameter) -> Result<Value, VmError> {
|
||||
match parameter {
|
||||
Parameter::Bool(b) => rune::to_value(*b),
|
||||
Parameter::Int(i) => rune::to_value(*i),
|
||||
Parameter::Float(f) => rune::to_value(*f),
|
||||
Parameter::String(s) => rune::to_value(s.str()),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user