154 lines
5.0 KiB
Rust
154 lines
5.0 KiB
Rust
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()),
|
|
}
|
|
}
|