Adds support for item use scripts
continuous-integration/drone/push Build was killed
Details
continuous-integration/drone/push Build was killed
Details
This commit is contained in:
parent
0c6a0cadfe
commit
3f91f80982
|
@ -1,2 +1,46 @@
|
|||
use crate::dynamic_data::Pokemon;
|
||||
use crate::static_data::EffectParameter;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// The script functions that are relevant to item use.
|
||||
pub trait ItemScript {}
|
||||
pub trait ItemScript {
|
||||
/// Initializes the script with the given parameters for a specific item
|
||||
fn on_initialize(&self, _pars: Vec<Arc<EffectParameter>>) -> anyhow_ext::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns whether the item is usable in the current context.
|
||||
fn is_item_usable(&self) -> anyhow_ext::Result<bool> {
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
/// Returns whether the item requires a target to be used.
|
||||
fn requires_target(&self) -> anyhow_ext::Result<bool> {
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
/// Returns whether the item is usable on the given target.
|
||||
fn is_target_valid(&self, _target: &Pokemon) -> anyhow_ext::Result<bool> {
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
/// Returns whether the item can be held by the given target.
|
||||
fn is_holdable(&self) -> anyhow_ext::Result<bool> {
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
/// Returns whether the item can be held by the given target.
|
||||
fn can_target_hold(&self, _target: &Pokemon) -> anyhow_ext::Result<bool> {
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
/// Handles the use of the item.
|
||||
fn on_use(&self) -> anyhow_ext::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Handles the use of the item on the given target.
|
||||
fn on_use_with_target(&self, _target: &Pokemon) -> anyhow_ext::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,167 @@
|
|||
use crate::dynamic_data::{ItemScript, Pokemon};
|
||||
use crate::script_implementations::wasm::export_registry::WasmVoidResultExtension;
|
||||
use crate::script_implementations::wasm::extern_ref::ExternRef;
|
||||
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnvironmentData;
|
||||
use crate::static_data::EffectParameter;
|
||||
use crate::StringKey;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// A web assembly implementation of the item script.
|
||||
pub struct WebAssemblyItemScript {
|
||||
/// The unique identifier of the script.
|
||||
name: StringKey,
|
||||
|
||||
/// Pointer inside WebAssembly memory where the data is for this script.
|
||||
self_ptr: u32,
|
||||
|
||||
/// Cached value for the is_usable function.
|
||||
is_usable: Option<bool>,
|
||||
|
||||
/// Cached value for the requires_target function.
|
||||
requires_target: Option<bool>,
|
||||
|
||||
/// Cached value for the is_holdable function.
|
||||
is_holdable: Option<bool>,
|
||||
|
||||
/// The global runtime environment data.
|
||||
environment: Arc<WebAssemblyEnvironmentData>,
|
||||
}
|
||||
|
||||
impl WebAssemblyItemScript {
|
||||
/// Create a new instance of the script.
|
||||
pub fn new(name: StringKey, self_ptr: u32, environment: Arc<WebAssemblyEnvironmentData>) -> Self {
|
||||
Self {
|
||||
name,
|
||||
self_ptr,
|
||||
is_usable: None,
|
||||
requires_target: None,
|
||||
is_holdable: None,
|
||||
environment,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the name of the script.
|
||||
pub fn name(&self) -> &StringKey {
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
|
||||
/// Util macro to reduce function call verbosity.
|
||||
macro_rules! call_func {
|
||||
($func:ident, $env:ident, $self:ident $(, $par_name:expr)*) => {
|
||||
match $func.call(&mut $env.store_mut(), $self.self_ptr $(, $par_name)*) {
|
||||
Ok(res) => res.into_result_env($env)?,
|
||||
Err(e) => return Err(e.into()),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// Util macro to reduce extern ref instantiation verbosity.
|
||||
macro_rules! ex_ref {
|
||||
($env:ident, $value:expr) => {
|
||||
ExternRef::new($env.as_ref(), $value.into())
|
||||
};
|
||||
}
|
||||
|
||||
impl ItemScript for WebAssemblyItemScript {
|
||||
fn on_initialize(&self, pars: Vec<Arc<EffectParameter>>) -> anyhow_ext::Result<()> {
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().item_on_initialize(env) {
|
||||
let pars = pars
|
||||
.into_iter()
|
||||
.map(|p| ExternRef::<EffectParameter>::new(env, (&p).into()).index() as u32)
|
||||
.collect::<Vec<_>>();
|
||||
let wasm_ptr = env.copy_value_vec_to_wasm(&pars)?;
|
||||
let r: u64 = unsafe { std::mem::transmute((wasm_ptr, pars.len() as u32)) };
|
||||
call_func!(func, env, self, r);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn is_item_usable(&self) -> anyhow_ext::Result<bool> {
|
||||
if let Some(is_usable) = self.is_usable {
|
||||
return Ok(is_usable);
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().item_is_usable(env) {
|
||||
let res_ptr = env.allocate_temp::<bool>(false);
|
||||
call_func!(func, env, self, res_ptr.wasm_ptr);
|
||||
let res = *res_ptr.value();
|
||||
let self_mut = unsafe { (self as *const Self as *mut Self).as_mut().unwrap_unchecked() };
|
||||
self_mut.is_usable = Some(res);
|
||||
return Ok(res);
|
||||
}
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn requires_target(&self) -> anyhow_ext::Result<bool> {
|
||||
if let Some(requires_target) = self.requires_target {
|
||||
return Ok(requires_target);
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().item_requires_target(env) {
|
||||
let res_ptr = env.allocate_temp::<bool>(false);
|
||||
call_func!(func, env, self, res_ptr.wasm_ptr);
|
||||
let res = *res_ptr.value();
|
||||
let self_mut = unsafe { (self as *const Self as *mut Self).as_mut().unwrap_unchecked() };
|
||||
self_mut.requires_target = Some(res);
|
||||
return Ok(res);
|
||||
}
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
fn is_target_valid(&self, target: &Pokemon) -> anyhow::Result<bool> {
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().item_is_target_valid(env) {
|
||||
let target = ex_ref!(env, target);
|
||||
let res_ptr = env.allocate_temp::<bool>(false);
|
||||
call_func!(func, env, self, target, res_ptr.wasm_ptr);
|
||||
return Ok(*res_ptr.value());
|
||||
}
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
fn is_holdable(&self) -> anyhow::Result<bool> {
|
||||
if let Some(is_holdable) = self.is_holdable {
|
||||
return Ok(is_holdable);
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().item_is_holdable(env) {
|
||||
let res_ptr = env.allocate_temp::<bool>(false);
|
||||
call_func!(func, env, self, res_ptr.wasm_ptr);
|
||||
let res = *res_ptr.value();
|
||||
let self_mut = unsafe { (self as *const Self as *mut Self).as_mut().unwrap_unchecked() };
|
||||
self_mut.is_holdable = Some(res);
|
||||
return Ok(res);
|
||||
}
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
fn can_target_hold(&self, target: &Pokemon) -> anyhow::Result<bool> {
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().item_can_target_hold(env) {
|
||||
let target = ex_ref!(env, target);
|
||||
let res_ptr = env.allocate_temp::<bool>(false);
|
||||
call_func!(func, env, self, target, res_ptr.wasm_ptr);
|
||||
return Ok(*res_ptr.value());
|
||||
}
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
fn on_use(&self) -> anyhow::Result<()> {
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().item_on_use(env) {
|
||||
call_func!(func, env, self);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn on_use_with_target(&self, target: &Pokemon) -> anyhow::Result<()> {
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().item_on_use_with_target(env) {
|
||||
let target = ex_ref!(env, target);
|
||||
call_func!(func, env, self, target);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
/// The export registry module deals with registering all functions we require in WebAssembly.
|
||||
mod export_registry;
|
||||
/// A hacky extern ref implementation to ensure the client does not do things it is not allowed to do.
|
||||
/// A extern ref implementation to ensure the client does not do things it is not allowed to do.
|
||||
pub(crate) mod extern_ref;
|
||||
/// The item script module deals with the actual running of WASM functions.
|
||||
pub mod item_script;
|
||||
/// The script module deals with the actual running of WASM functions.
|
||||
pub mod script;
|
||||
/// A cache of all script functions for easy calls
|
||||
|
|
|
@ -18,7 +18,7 @@ use wasmer::{FromToNativeWasmType, TypedFunction};
|
|||
macro_rules! script_function_cache {
|
||||
(
|
||||
$(
|
||||
$name:ident($($par_type:ty),*$(,)?)
|
||||
$prefix:ident, $name:ident($($par_type:ty),*$(,)?)
|
||||
)*
|
||||
) => {
|
||||
#[derive(Default)]
|
||||
|
@ -38,7 +38,7 @@ macro_rules! script_function_cache {
|
|||
#[allow(unused_parens)]
|
||||
fn [<initialize_ $name>](&self, env: &Arc<WebAssemblyEnvironmentData>) {
|
||||
let exported = env.exported_functions();
|
||||
let f = exported.get::<StringKey>(&stringify!([< script_ $name >]).into());
|
||||
let f = exported.get::<StringKey>(&stringify!([< $prefix $name >]).into());
|
||||
if let Some(f) = f {
|
||||
let func: TypedFunction<(u32 $(,$par_type)*), WasmVoidResult> = f.typed(&env.store_ref()).unwrap();
|
||||
let _ = self.$name.write().insert(func);
|
||||
|
@ -121,61 +121,71 @@ unsafe impl<T> FromToNativeWasmType for WasmPtr<T> {
|
|||
}
|
||||
|
||||
script_function_cache! {
|
||||
stack()
|
||||
on_remove()
|
||||
on_initialize(ExternRef<dyn DynamicLibrary>, u64)
|
||||
on_before_turn(ExternRef<TurnChoice>)
|
||||
change_speed(ExternRef<TurnChoice>, WasmPtr<u32>)
|
||||
change_priority(ExternRef<TurnChoice>, WasmPtr<i8>)
|
||||
change_move(ExternRef<TurnChoice>, WasmPtr<ExternRef<StringKey>>)
|
||||
change_number_of_hits(ExternRef<TurnChoice>, WasmPtr<u8>)
|
||||
prevent_move(ExternRef<ExecutingMove>, WasmPtr<bool>)
|
||||
fail_move(ExternRef<ExecutingMove>, WasmPtr<bool>)
|
||||
stop_before_move(ExternRef<ExecutingMove>, WasmPtr<bool>)
|
||||
on_before_move(ExternRef<ExecutingMove>)
|
||||
fail_incoming_move(ExternRef<ExecutingMove>, ExternRef<Pokemon>, WasmPtr<bool>)
|
||||
is_invulnerable(ExternRef<ExecutingMove>, ExternRef<Pokemon>, WasmPtr<bool>)
|
||||
on_move_miss(ExternRef<ExecutingMove>, ExternRef<Pokemon>)
|
||||
change_move_type(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<TypeIdentifier>)
|
||||
change_effectiveness(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||
block_critical(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<bool>)
|
||||
block_incoming_critical(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<bool>)
|
||||
change_accuracy(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u8>)
|
||||
change_critical_stage(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u8>)
|
||||
change_critical_modifier(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||
change_stab_modifier(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||
change_base_power(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u8>)
|
||||
bypass_defensive_stat_boost(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<bool>)
|
||||
bypass_offensive_stat_boost(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<bool>)
|
||||
change_offensive_stat_value(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u32>)
|
||||
change_defensive_stat_value(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u32>)
|
||||
change_damage_stat_modifier(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||
change_damage_modifier(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||
change_damage(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u32>)
|
||||
change_incoming_damage(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u32>)
|
||||
on_incoming_hit(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8)
|
||||
on_opponent_faints(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8)
|
||||
prevent_stat_boost_change(ExternRef<Pokemon>, u8, i8, u8, WasmPtr<bool>)
|
||||
prevent_secondary_effect(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<bool>)
|
||||
change_effect_chance(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||
change_incoming_effect_chance(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||
on_secondary_effect(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8)
|
||||
on_after_hits(ExternRef<ExecutingMove>, ExternRef<Pokemon>)
|
||||
prevent_self_switch(ExternRef<TurnChoice>, WasmPtr<bool>)
|
||||
prevent_opponent_switch(ExternRef<TurnChoice>, WasmPtr<bool>)
|
||||
on_fail(ExternRef<Pokemon>)
|
||||
on_opponent_fail(ExternRef<Pokemon>)
|
||||
prevent_self_run_away(ExternRef<TurnChoice>, WasmPtr<bool>)
|
||||
prevent_opponent_run_away(ExternRef<TurnChoice>, WasmPtr<bool>)
|
||||
on_end_turn()
|
||||
on_damage(ExternRef<Pokemon>, u8, u32, u32)
|
||||
on_faint(ExternRef<Pokemon>, u8)
|
||||
on_switch_in(ExternRef<Pokemon>)
|
||||
on_after_held_item_consume(ExternRef<Pokemon>, ExternRef<dyn Item>)
|
||||
change_experience_gained(ExternRef<Pokemon>, ExternRef<Pokemon>, WasmPtr<u32>)
|
||||
share_experience(ExternRef<Pokemon>, ExternRef<Pokemon>, WasmPtr<bool>)
|
||||
block_weather(ExternRef<Battle>, WasmPtr<bool>)
|
||||
change_capture_rate_bonus(ExternRef<Pokemon>, ExternRef<dyn Item>, WasmPtr<u8>)
|
||||
script_, stack()
|
||||
script_, on_remove()
|
||||
script_, on_initialize(ExternRef<dyn DynamicLibrary>, u64)
|
||||
script_, on_before_turn(ExternRef<TurnChoice>)
|
||||
script_, change_speed(ExternRef<TurnChoice>, WasmPtr<u32>)
|
||||
script_, change_priority(ExternRef<TurnChoice>, WasmPtr<i8>)
|
||||
script_, change_move(ExternRef<TurnChoice>, WasmPtr<ExternRef<StringKey>>)
|
||||
script_, change_number_of_hits(ExternRef<TurnChoice>, WasmPtr<u8>)
|
||||
script_, prevent_move(ExternRef<ExecutingMove>, WasmPtr<bool>)
|
||||
script_, fail_move(ExternRef<ExecutingMove>, WasmPtr<bool>)
|
||||
script_, stop_before_move(ExternRef<ExecutingMove>, WasmPtr<bool>)
|
||||
script_, on_before_move(ExternRef<ExecutingMove>)
|
||||
script_, fail_incoming_move(ExternRef<ExecutingMove>, ExternRef<Pokemon>, WasmPtr<bool>)
|
||||
script_, is_invulnerable(ExternRef<ExecutingMove>, ExternRef<Pokemon>, WasmPtr<bool>)
|
||||
script_, on_move_miss(ExternRef<ExecutingMove>, ExternRef<Pokemon>)
|
||||
script_, change_move_type(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<TypeIdentifier>)
|
||||
script_, change_effectiveness(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||
script_, block_critical(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<bool>)
|
||||
script_, block_incoming_critical(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<bool>)
|
||||
script_, change_accuracy(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u8>)
|
||||
script_, change_critical_stage(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u8>)
|
||||
script_, change_critical_modifier(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||
script_, change_stab_modifier(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||
script_, change_base_power(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u8>)
|
||||
script_, bypass_defensive_stat_boost(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<bool>)
|
||||
script_, bypass_offensive_stat_boost(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<bool>)
|
||||
script_, change_offensive_stat_value(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u32>)
|
||||
script_, change_defensive_stat_value(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u32>)
|
||||
script_, change_damage_stat_modifier(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||
script_, change_damage_modifier(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||
script_, change_damage(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u32>)
|
||||
script_, change_incoming_damage(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u32>)
|
||||
script_, on_incoming_hit(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8)
|
||||
script_, on_opponent_faints(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8)
|
||||
script_, prevent_stat_boost_change(ExternRef<Pokemon>, u8, i8, u8, WasmPtr<bool>)
|
||||
script_, prevent_secondary_effect(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<bool>)
|
||||
script_, change_effect_chance(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||
script_, change_incoming_effect_chance(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||
script_, on_secondary_effect(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8)
|
||||
script_, on_after_hits(ExternRef<ExecutingMove>, ExternRef<Pokemon>)
|
||||
script_, prevent_self_switch(ExternRef<TurnChoice>, WasmPtr<bool>)
|
||||
script_, prevent_opponent_switch(ExternRef<TurnChoice>, WasmPtr<bool>)
|
||||
script_, on_fail(ExternRef<Pokemon>)
|
||||
script_, on_opponent_fail(ExternRef<Pokemon>)
|
||||
script_, prevent_self_run_away(ExternRef<TurnChoice>, WasmPtr<bool>)
|
||||
script_, prevent_opponent_run_away(ExternRef<TurnChoice>, WasmPtr<bool>)
|
||||
script_, on_end_turn()
|
||||
script_, on_damage(ExternRef<Pokemon>, u8, u32, u32)
|
||||
script_, on_faint(ExternRef<Pokemon>, u8)
|
||||
script_, on_switch_in(ExternRef<Pokemon>)
|
||||
script_, on_after_held_item_consume(ExternRef<Pokemon>, ExternRef<dyn Item>)
|
||||
script_, change_experience_gained(ExternRef<Pokemon>, ExternRef<Pokemon>, WasmPtr<u32>)
|
||||
script_, share_experience(ExternRef<Pokemon>, ExternRef<Pokemon>, WasmPtr<bool>)
|
||||
script_, block_weather(ExternRef<Battle>, WasmPtr<bool>)
|
||||
script_, change_capture_rate_bonus(ExternRef<Pokemon>, ExternRef<dyn Item>, WasmPtr<u8>)
|
||||
|
||||
// Item script functions
|
||||
item_script_, item_on_initialize(u64)
|
||||
item_script_, item_is_usable(WasmPtr<bool>)
|
||||
item_script_, item_requires_target(WasmPtr<bool>)
|
||||
item_script_, item_is_target_valid(ExternRef<Pokemon>, WasmPtr<bool>)
|
||||
item_script_, item_is_holdable(WasmPtr<bool>)
|
||||
item_script_, item_can_target_hold(ExternRef<Pokemon>, WasmPtr<bool>)
|
||||
item_script_, item_on_use()
|
||||
item_script_, item_on_use_with_target(ExternRef<Pokemon>)
|
||||
}
|
||||
|
||||
impl ScriptFunctionCache {
|
||||
|
|
|
@ -15,6 +15,7 @@ use wasmer::{
|
|||
use crate::dynamic_data::{ItemScript, Script, ScriptOwnerData, ScriptResolver};
|
||||
use crate::script_implementations::wasm::export_registry::{register_webassembly_funcs, WasmObject};
|
||||
use crate::script_implementations::wasm::extern_ref::ExternRef;
|
||||
use crate::script_implementations::wasm::item_script::WebAssemblyItemScript;
|
||||
use crate::script_implementations::wasm::script::WebAssemblyScript;
|
||||
use crate::script_implementations::wasm::script_function_cache::ScriptFunctionCache;
|
||||
use crate::script_implementations::wasm::temp_wasm_allocator::{AllocatedObject, TempWasmAllocator};
|
||||
|
@ -35,8 +36,14 @@ pub struct WebAssemblyScriptResolver {
|
|||
/// This is the WASM function to load a script.
|
||||
load_script_fn: Option<TypedFunction<(u8, ExternRef<StringKey>), u32>>,
|
||||
|
||||
/// This is the WASM function to load an item script.
|
||||
load_item_script_fn: Option<TypedFunction<ExternRef<StringKey>, u32>>,
|
||||
|
||||
/// The data for use in the scripting function calls.
|
||||
environment_data: Arc<WebAssemblyEnvironmentData>,
|
||||
|
||||
/// A cache of all item scripts for faster calls.
|
||||
item_scripts: RwLock<HashMap<StringKey, Arc<dyn ItemScript>>>,
|
||||
}
|
||||
|
||||
/// This struct allows us to index a hashmap with both a category and name of a script.
|
||||
|
@ -68,7 +75,9 @@ impl WebAssemblyScriptResolver {
|
|||
modules: Default::default(),
|
||||
instances: Default::default(),
|
||||
load_script_fn: None,
|
||||
load_item_script_fn: None,
|
||||
environment_data: environment,
|
||||
item_scripts: Default::default(),
|
||||
};
|
||||
|
||||
Arc::new(s)
|
||||
|
@ -148,6 +157,11 @@ impl WebAssemblyScriptResolver {
|
|||
let self_mut = (self as *const Self as *mut Self).as_mut().unwrap();
|
||||
self_mut.load_script_fn = Some(f.typed(&self.store_ref())?)
|
||||
}
|
||||
#[allow(clippy::unwrap_used)] // We know this is valid.
|
||||
if let Some(f) = exported_functions.get::<StringKey>(&"load_item_script".into()) {
|
||||
let self_mut = (self as *const Self as *mut Self).as_mut().unwrap();
|
||||
self_mut.load_item_script_fn = Some(f.typed(&self.store_ref())?)
|
||||
}
|
||||
}
|
||||
if let Some(f) = exported_functions.get::<StringKey>(&"allocate_mem".into()) {
|
||||
let _ = self
|
||||
|
@ -194,7 +208,30 @@ impl ScriptResolver for WebAssemblyScriptResolver {
|
|||
}
|
||||
|
||||
fn load_item_script(&self, _key: &dyn Item) -> Result<Option<Arc<dyn ItemScript>>> {
|
||||
todo!()
|
||||
if self.load_item_script_fn.is_none() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
if let Some(script) = self.item_scripts.read().get(_key.name()) {
|
||||
return Ok(Some(script.clone()));
|
||||
}
|
||||
let mut item_scripts_write_lock = self.item_scripts.write();
|
||||
let script_ptr = self
|
||||
.load_item_script_fn
|
||||
.as_ref()
|
||||
// should never happen, as we check for this above.
|
||||
.ok_or(anyhow!("Load item script function was not found"))?
|
||||
.call(
|
||||
&mut self.store_mut(),
|
||||
ExternRef::new_with_resolver(self, WasmObject::StringKey(_key.name().clone())),
|
||||
)?;
|
||||
let script = Arc::new(WebAssemblyItemScript::new(
|
||||
_key.name().clone(),
|
||||
script_ptr,
|
||||
self.environment_data.clone(),
|
||||
));
|
||||
item_scripts_write_lock.insert(_key.name().clone(), script.clone());
|
||||
Ok(Some(script))
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue