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.
|
/// 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.
|
/// The export registry module deals with registering all functions we require in WebAssembly.
|
||||||
mod export_registry;
|
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;
|
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.
|
/// The script module deals with the actual running of WASM functions.
|
||||||
pub mod script;
|
pub mod script;
|
||||||
/// A cache of all script functions for easy calls
|
/// A cache of all script functions for easy calls
|
||||||
|
|
|
@ -18,7 +18,7 @@ use wasmer::{FromToNativeWasmType, TypedFunction};
|
||||||
macro_rules! script_function_cache {
|
macro_rules! script_function_cache {
|
||||||
(
|
(
|
||||||
$(
|
$(
|
||||||
$name:ident($($par_type:ty),*$(,)?)
|
$prefix:ident, $name:ident($($par_type:ty),*$(,)?)
|
||||||
)*
|
)*
|
||||||
) => {
|
) => {
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -38,7 +38,7 @@ macro_rules! script_function_cache {
|
||||||
#[allow(unused_parens)]
|
#[allow(unused_parens)]
|
||||||
fn [<initialize_ $name>](&self, env: &Arc<WebAssemblyEnvironmentData>) {
|
fn [<initialize_ $name>](&self, env: &Arc<WebAssemblyEnvironmentData>) {
|
||||||
let exported = env.exported_functions();
|
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 {
|
if let Some(f) = f {
|
||||||
let func: TypedFunction<(u32 $(,$par_type)*), WasmVoidResult> = f.typed(&env.store_ref()).unwrap();
|
let func: TypedFunction<(u32 $(,$par_type)*), WasmVoidResult> = f.typed(&env.store_ref()).unwrap();
|
||||||
let _ = self.$name.write().insert(func);
|
let _ = self.$name.write().insert(func);
|
||||||
|
@ -121,61 +121,71 @@ unsafe impl<T> FromToNativeWasmType for WasmPtr<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
script_function_cache! {
|
script_function_cache! {
|
||||||
stack()
|
script_, stack()
|
||||||
on_remove()
|
script_, on_remove()
|
||||||
on_initialize(ExternRef<dyn DynamicLibrary>, u64)
|
script_, on_initialize(ExternRef<dyn DynamicLibrary>, u64)
|
||||||
on_before_turn(ExternRef<TurnChoice>)
|
script_, on_before_turn(ExternRef<TurnChoice>)
|
||||||
change_speed(ExternRef<TurnChoice>, WasmPtr<u32>)
|
script_, change_speed(ExternRef<TurnChoice>, WasmPtr<u32>)
|
||||||
change_priority(ExternRef<TurnChoice>, WasmPtr<i8>)
|
script_, change_priority(ExternRef<TurnChoice>, WasmPtr<i8>)
|
||||||
change_move(ExternRef<TurnChoice>, WasmPtr<ExternRef<StringKey>>)
|
script_, change_move(ExternRef<TurnChoice>, WasmPtr<ExternRef<StringKey>>)
|
||||||
change_number_of_hits(ExternRef<TurnChoice>, WasmPtr<u8>)
|
script_, change_number_of_hits(ExternRef<TurnChoice>, WasmPtr<u8>)
|
||||||
prevent_move(ExternRef<ExecutingMove>, WasmPtr<bool>)
|
script_, prevent_move(ExternRef<ExecutingMove>, WasmPtr<bool>)
|
||||||
fail_move(ExternRef<ExecutingMove>, WasmPtr<bool>)
|
script_, fail_move(ExternRef<ExecutingMove>, WasmPtr<bool>)
|
||||||
stop_before_move(ExternRef<ExecutingMove>, WasmPtr<bool>)
|
script_, stop_before_move(ExternRef<ExecutingMove>, WasmPtr<bool>)
|
||||||
on_before_move(ExternRef<ExecutingMove>)
|
script_, on_before_move(ExternRef<ExecutingMove>)
|
||||||
fail_incoming_move(ExternRef<ExecutingMove>, ExternRef<Pokemon>, WasmPtr<bool>)
|
script_, fail_incoming_move(ExternRef<ExecutingMove>, ExternRef<Pokemon>, WasmPtr<bool>)
|
||||||
is_invulnerable(ExternRef<ExecutingMove>, ExternRef<Pokemon>, WasmPtr<bool>)
|
script_, is_invulnerable(ExternRef<ExecutingMove>, ExternRef<Pokemon>, WasmPtr<bool>)
|
||||||
on_move_miss(ExternRef<ExecutingMove>, ExternRef<Pokemon>)
|
script_, on_move_miss(ExternRef<ExecutingMove>, ExternRef<Pokemon>)
|
||||||
change_move_type(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<TypeIdentifier>)
|
script_, change_move_type(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<TypeIdentifier>)
|
||||||
change_effectiveness(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
script_, change_effectiveness(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||||
block_critical(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<bool>)
|
script_, block_critical(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<bool>)
|
||||||
block_incoming_critical(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<bool>)
|
script_, block_incoming_critical(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<bool>)
|
||||||
change_accuracy(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u8>)
|
script_, change_accuracy(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u8>)
|
||||||
change_critical_stage(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u8>)
|
script_, change_critical_stage(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u8>)
|
||||||
change_critical_modifier(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
script_, change_critical_modifier(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||||
change_stab_modifier(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
script_, change_stab_modifier(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||||
change_base_power(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u8>)
|
script_, change_base_power(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u8>)
|
||||||
bypass_defensive_stat_boost(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<bool>)
|
script_, bypass_defensive_stat_boost(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<bool>)
|
||||||
bypass_offensive_stat_boost(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<bool>)
|
script_, bypass_offensive_stat_boost(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<bool>)
|
||||||
change_offensive_stat_value(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u32>)
|
script_, change_offensive_stat_value(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u32>)
|
||||||
change_defensive_stat_value(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u32>)
|
script_, change_defensive_stat_value(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u32>)
|
||||||
change_damage_stat_modifier(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
script_, change_damage_stat_modifier(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||||
change_damage_modifier(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
script_, change_damage_modifier(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||||
change_damage(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u32>)
|
script_, change_damage(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u32>)
|
||||||
change_incoming_damage(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u32>)
|
script_, change_incoming_damage(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u32>)
|
||||||
on_incoming_hit(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8)
|
script_, on_incoming_hit(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8)
|
||||||
on_opponent_faints(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8)
|
script_, on_opponent_faints(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8)
|
||||||
prevent_stat_boost_change(ExternRef<Pokemon>, u8, i8, u8, WasmPtr<bool>)
|
script_, prevent_stat_boost_change(ExternRef<Pokemon>, u8, i8, u8, WasmPtr<bool>)
|
||||||
prevent_secondary_effect(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<bool>)
|
script_, prevent_secondary_effect(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<bool>)
|
||||||
change_effect_chance(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
script_, change_effect_chance(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||||
change_incoming_effect_chance(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
script_, change_incoming_effect_chance(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||||
on_secondary_effect(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8)
|
script_, on_secondary_effect(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8)
|
||||||
on_after_hits(ExternRef<ExecutingMove>, ExternRef<Pokemon>)
|
script_, on_after_hits(ExternRef<ExecutingMove>, ExternRef<Pokemon>)
|
||||||
prevent_self_switch(ExternRef<TurnChoice>, WasmPtr<bool>)
|
script_, prevent_self_switch(ExternRef<TurnChoice>, WasmPtr<bool>)
|
||||||
prevent_opponent_switch(ExternRef<TurnChoice>, WasmPtr<bool>)
|
script_, prevent_opponent_switch(ExternRef<TurnChoice>, WasmPtr<bool>)
|
||||||
on_fail(ExternRef<Pokemon>)
|
script_, on_fail(ExternRef<Pokemon>)
|
||||||
on_opponent_fail(ExternRef<Pokemon>)
|
script_, on_opponent_fail(ExternRef<Pokemon>)
|
||||||
prevent_self_run_away(ExternRef<TurnChoice>, WasmPtr<bool>)
|
script_, prevent_self_run_away(ExternRef<TurnChoice>, WasmPtr<bool>)
|
||||||
prevent_opponent_run_away(ExternRef<TurnChoice>, WasmPtr<bool>)
|
script_, prevent_opponent_run_away(ExternRef<TurnChoice>, WasmPtr<bool>)
|
||||||
on_end_turn()
|
script_, on_end_turn()
|
||||||
on_damage(ExternRef<Pokemon>, u8, u32, u32)
|
script_, on_damage(ExternRef<Pokemon>, u8, u32, u32)
|
||||||
on_faint(ExternRef<Pokemon>, u8)
|
script_, on_faint(ExternRef<Pokemon>, u8)
|
||||||
on_switch_in(ExternRef<Pokemon>)
|
script_, on_switch_in(ExternRef<Pokemon>)
|
||||||
on_after_held_item_consume(ExternRef<Pokemon>, ExternRef<dyn Item>)
|
script_, on_after_held_item_consume(ExternRef<Pokemon>, ExternRef<dyn Item>)
|
||||||
change_experience_gained(ExternRef<Pokemon>, ExternRef<Pokemon>, WasmPtr<u32>)
|
script_, change_experience_gained(ExternRef<Pokemon>, ExternRef<Pokemon>, WasmPtr<u32>)
|
||||||
share_experience(ExternRef<Pokemon>, ExternRef<Pokemon>, WasmPtr<bool>)
|
script_, share_experience(ExternRef<Pokemon>, ExternRef<Pokemon>, WasmPtr<bool>)
|
||||||
block_weather(ExternRef<Battle>, WasmPtr<bool>)
|
script_, block_weather(ExternRef<Battle>, WasmPtr<bool>)
|
||||||
change_capture_rate_bonus(ExternRef<Pokemon>, ExternRef<dyn Item>, WasmPtr<u8>)
|
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 {
|
impl ScriptFunctionCache {
|
||||||
|
|
|
@ -15,6 +15,7 @@ use wasmer::{
|
||||||
use crate::dynamic_data::{ItemScript, Script, ScriptOwnerData, ScriptResolver};
|
use crate::dynamic_data::{ItemScript, Script, ScriptOwnerData, ScriptResolver};
|
||||||
use crate::script_implementations::wasm::export_registry::{register_webassembly_funcs, WasmObject};
|
use crate::script_implementations::wasm::export_registry::{register_webassembly_funcs, WasmObject};
|
||||||
use crate::script_implementations::wasm::extern_ref::ExternRef;
|
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::WebAssemblyScript;
|
||||||
use crate::script_implementations::wasm::script_function_cache::ScriptFunctionCache;
|
use crate::script_implementations::wasm::script_function_cache::ScriptFunctionCache;
|
||||||
use crate::script_implementations::wasm::temp_wasm_allocator::{AllocatedObject, TempWasmAllocator};
|
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.
|
/// This is the WASM function to load a script.
|
||||||
load_script_fn: Option<TypedFunction<(u8, ExternRef<StringKey>), u32>>,
|
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.
|
/// The data for use in the scripting function calls.
|
||||||
environment_data: Arc<WebAssemblyEnvironmentData>,
|
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.
|
/// 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(),
|
modules: Default::default(),
|
||||||
instances: Default::default(),
|
instances: Default::default(),
|
||||||
load_script_fn: None,
|
load_script_fn: None,
|
||||||
|
load_item_script_fn: None,
|
||||||
environment_data: environment,
|
environment_data: environment,
|
||||||
|
item_scripts: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Arc::new(s)
|
Arc::new(s)
|
||||||
|
@ -148,6 +157,11 @@ impl WebAssemblyScriptResolver {
|
||||||
let self_mut = (self as *const Self as *mut Self).as_mut().unwrap();
|
let self_mut = (self as *const Self as *mut Self).as_mut().unwrap();
|
||||||
self_mut.load_script_fn = Some(f.typed(&self.store_ref())?)
|
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()) {
|
if let Some(f) = exported_functions.get::<StringKey>(&"allocate_mem".into()) {
|
||||||
let _ = self
|
let _ = self
|
||||||
|
@ -194,7 +208,30 @@ impl ScriptResolver for WebAssemblyScriptResolver {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_item_script(&self, _key: &dyn Item) -> Result<Option<Arc<dyn ItemScript>>> {
|
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 {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue