Files
PkmnLib_rs/src/script_implementations/wasm/script.rs
Deukhoofd bd62c1ac62
All checks were successful
continuous-integration/drone/push Build is passing
Update to Wasmer 3.0 beta
2022-08-27 14:14:58 +02:00

175 lines
5.7 KiB
Rust

use std::any::Any;
use std::sync::atomic::{AtomicBool, AtomicPtr, AtomicUsize};
use std::sync::{Arc, Weak};
use hashbrown::HashSet;
use crate::dynamic_data::{DynamicLibrary, Script, TurnChoice};
use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef};
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnvironmentData;
use crate::script_implementations::wasm::WebAssemblyScriptCapabilities;
use crate::static_data::EffectParameter;
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)
_owner_ptr: AtomicPtr<u8>,
/// Pointer inside WebAssembly memory where the data is for this script.
self_ptr: u32,
/// Capabilities define which functions we actually implement.
capabilities: Arc<HashSet<WebAssemblyScriptCapabilities>>,
/// The global runtime environment data.
environment: Weak<WebAssemblyEnvironmentData>,
}
impl WebAssemblyScript {
/// Instantiates a new WebAssemblyScript.
pub fn new(
owner_ptr: *mut u8,
self_ptr: u32,
capabilities: Arc<HashSet<WebAssemblyScriptCapabilities>>,
environment: Weak<WebAssemblyEnvironmentData>,
name: StringKey,
) -> Self {
Self {
name,
marked_for_deletion: Default::default(),
suppressed_count: Default::default(),
_owner_ptr: AtomicPtr::new(owner_ptr),
self_ptr,
capabilities,
environment,
}
}
}
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
}
fn stack(&self) {
if !self.capabilities.contains(&WebAssemblyScriptCapabilities::OnStack) {
return;
}
let env = self.environment.upgrade().unwrap();
let func = env.script_function_cache().stack(&env);
if let Some(func) = func {
func.call(&mut env.store_mut(), self.self_ptr).unwrap();
}
}
fn on_remove(&self) {
if !self.capabilities.contains(&WebAssemblyScriptCapabilities::OnRemove) {
return;
}
let env = self.environment.upgrade().unwrap();
let func = env.script_function_cache().on_remove(&env);
if let Some(func) = func {
func.call(&mut env.store_mut(), self.self_ptr).unwrap();
}
}
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(
&mut env.store_mut(),
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 {
func.call(
&mut env.store_mut(),
self.self_ptr,
ExternRef::new(env.as_ref(), choice),
)
.unwrap();
}
}
fn change_speed(&self, choice: &TurnChoice, speed: &mut u32) {
if !self.capabilities.contains(&WebAssemblyScriptCapabilities::ChangeSpeed) {
return;
}
let env = self.environment.upgrade().unwrap();
let func = env.script_function_cache().change_speed(&env);
if let Some(func) = func {
let ptr = env.temp_allocate_mem_typed::<u32>(*speed);
func.call(
&mut env.store_mut(),
self.self_ptr,
ExternRef::new(env.as_ref(), choice),
ptr.wasm_pointer,
)
.unwrap();
*speed = *ptr.value();
}
}
fn change_priority(&self, choice: &TurnChoice, priority: &mut i8) {
if !self
.capabilities
.contains(&WebAssemblyScriptCapabilities::ChangePriority)
{
return;
}
let env = self.environment.upgrade().unwrap();
let func = env.script_function_cache().change_priority(&env);
if let Some(func) = func {
let ptr = env.temp_allocate_mem_typed::<i8>(*priority);
func.call(
&mut env.store_mut(),
self.self_ptr,
ExternRef::new(env.as_ref(), choice),
ptr.wasm_pointer,
)
.unwrap();
*priority = *ptr.value();
}
}
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
}