2022-07-18 08:16:47 +00:00
|
|
|
use std::any::Any;
|
|
|
|
use std::sync::atomic::{AtomicBool, AtomicPtr, AtomicUsize};
|
2022-08-20 10:22:12 +00:00
|
|
|
use std::sync::{Arc, Weak};
|
2022-07-18 08:16:47 +00:00
|
|
|
|
|
|
|
use hashbrown::HashSet;
|
2022-07-18 13:36:03 +00:00
|
|
|
use wasmer::NativeFunc;
|
2022-07-18 08:16:47 +00:00
|
|
|
|
2022-08-20 11:17:20 +00:00
|
|
|
use crate::dynamic_data::{DynamicLibrary, Script, TurnChoice};
|
2022-08-20 10:22:12 +00:00
|
|
|
use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef};
|
2022-07-18 13:36:03 +00:00
|
|
|
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnvironmentData;
|
2022-07-18 08:16:47 +00:00
|
|
|
use crate::script_implementations::wasm::WebAssemblyScriptCapabilities;
|
2022-07-18 13:36:03 +00:00
|
|
|
use crate::static_data::EffectParameter;
|
2022-07-18 08:16:47 +00:00
|
|
|
use crate::StringKey;
|
|
|
|
|
|
|
|
/// A WebAssemblyScript is there to implement the Script trait within WebAssemblyScript.
|
|
|
|
pub struct WebAssemblyScript {
|
|
|
|
/// The unique identifier of the script.
|
|
|
|
name: StringKey,
|
|
|
|
/// 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)
|
2022-08-20 10:22:12 +00:00
|
|
|
_owner_ptr: AtomicPtr<u8>,
|
2022-07-18 08:16:47 +00:00
|
|
|
/// Pointer inside WebAssembly memory where the data is for this script.
|
|
|
|
self_ptr: u32,
|
|
|
|
/// Capabilities define which functions we actually implement.
|
2022-08-20 10:22:12 +00:00
|
|
|
capabilities: Arc<HashSet<WebAssemblyScriptCapabilities>>,
|
2022-07-18 13:36:03 +00:00
|
|
|
/// The global runtime environment data.
|
|
|
|
environment: Weak<WebAssemblyEnvironmentData>,
|
2022-07-18 08:16:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl WebAssemblyScript {
|
|
|
|
/// Instantiates a new WebAssemblyScript.
|
|
|
|
pub fn new(
|
|
|
|
owner_ptr: *mut u8,
|
|
|
|
self_ptr: u32,
|
2022-08-20 10:22:12 +00:00
|
|
|
capabilities: Arc<HashSet<WebAssemblyScriptCapabilities>>,
|
2022-07-18 13:36:03 +00:00
|
|
|
environment: Weak<WebAssemblyEnvironmentData>,
|
2022-07-18 08:16:47 +00:00
|
|
|
name: StringKey,
|
|
|
|
) -> Self {
|
|
|
|
Self {
|
|
|
|
name,
|
|
|
|
marked_for_deletion: Default::default(),
|
|
|
|
suppressed_count: Default::default(),
|
2022-08-20 10:22:12 +00:00
|
|
|
_owner_ptr: AtomicPtr::new(owner_ptr),
|
2022-07-18 08:16:47 +00:00
|
|
|
self_ptr,
|
2022-08-20 10:22:12 +00:00
|
|
|
capabilities,
|
2022-07-18 13:36:03 +00:00
|
|
|
environment,
|
2022-07-18 08:16:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Script for WebAssemblyScript {
|
|
|
|
fn name(&self) -> &StringKey {
|
|
|
|
&self.name
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_marked_for_deletion(&self) -> &AtomicBool {
|
|
|
|
&self.marked_for_deletion
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_suppressed_count(&self) -> &AtomicUsize {
|
|
|
|
&self.suppressed_count
|
|
|
|
}
|
|
|
|
|
2022-08-20 10:22:12 +00:00
|
|
|
fn on_initialize(&self, library: &DynamicLibrary, pars: &[EffectParameter]) {
|
|
|
|
if !self.capabilities.contains(&WebAssemblyScriptCapabilities::Initialize) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let env = self.environment.upgrade().unwrap();
|
|
|
|
let func = env.script_function_cache().on_initialize(&env);
|
|
|
|
if let Some(func) = func {
|
|
|
|
func.call(
|
|
|
|
self.self_ptr,
|
|
|
|
ExternRef::new(env.as_ref(), library),
|
|
|
|
VecExternRef::new(env.as_ref(), pars),
|
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn on_before_turn(&self, choice: &TurnChoice) {
|
|
|
|
if !self.capabilities.contains(&WebAssemblyScriptCapabilities::OnBeforeTurn) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
let env = self.environment.upgrade().unwrap();
|
|
|
|
let func = env.script_function_cache().on_before_turn(&env);
|
|
|
|
if let Some(func) = func {
|
2022-08-20 11:17:20 +00:00
|
|
|
func.call(self.self_ptr, ExternRef::new(env.as_ref(), choice)).unwrap();
|
2022-08-20 10:22:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn change_speed(&self, choice: &TurnChoice, speed: &mut u32) {
|
|
|
|
if !self.capabilities.contains(&WebAssemblyScriptCapabilities::ChangeSpeed) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-07-18 13:36:03 +00:00
|
|
|
let env = self.environment.upgrade().unwrap();
|
|
|
|
let exported = env.exported_functions();
|
2022-08-20 10:22:12 +00:00
|
|
|
if let Some(f) = exported.get::<StringKey>(&"script_change_speed".into()) {
|
|
|
|
let func: NativeFunc<(u32, ExternRef<TurnChoice>, u32), ()> = f.native().unwrap();
|
|
|
|
let ptr = env.temp_allocate_mem_typed::<u32>();
|
|
|
|
func.call(self.self_ptr, ExternRef::new(env.as_ref(), choice), ptr.wasm_pointer)
|
2022-07-18 13:36:03 +00:00
|
|
|
.unwrap();
|
2022-08-20 10:22:12 +00:00
|
|
|
unsafe {
|
|
|
|
*speed = *ptr.ptr;
|
|
|
|
}
|
2022-07-18 13:36:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-18 08:16:47 +00:00
|
|
|
fn as_any(&self) -> &dyn Any {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
fn as_any_mut(&mut self) -> &mut dyn Any {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|