Implements every script function
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Deukhoofd 2022-08-27 18:04:56 +02:00
parent bd62c1ac62
commit ba5992e925
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
19 changed files with 919 additions and 158 deletions

View File

@ -92,8 +92,8 @@ impl Battle {
/// Executes a move choice. /// Executes a move choice.
fn execute_move_choice<'func>(&'func self, choice: &'func TurnChoice) -> PkmnResult<()> { fn execute_move_choice<'func>(&'func self, choice: &'func TurnChoice) -> PkmnResult<()> {
let choice = choice.get_move_turn_data(); let move_choice = choice.get_move_turn_data();
let used_move = choice.used_move(); let used_move = move_choice.used_move();
let move_data = { let move_data = {
let move_data_lock = used_move; let move_data_lock = used_move;
let move_data = move_data_lock.move_data(); let move_data = move_data_lock.move_data();
@ -103,7 +103,7 @@ impl Battle {
}; };
// FIXME: also change the script on the choice if changed; // FIXME: also change the script on the choice if changed;
let target_type = move_data.target(); let target_type = move_data.target();
let targets = resolve_targets(choice.target_side(), choice.target_index(), target_type, self); let targets = resolve_targets(move_choice.target_side(), move_choice.target_index(), target_type, self);
let mut number_of_hits: u8 = 1; let mut number_of_hits: u8 = 1;
script_hook!(change_number_of_hits, choice, choice, &mut number_of_hits); script_hook!(change_number_of_hits, choice, choice, &mut number_of_hits);
@ -116,7 +116,7 @@ impl Battle {
choice.user().clone(), choice.user().clone(),
used_move.clone(), used_move.clone(),
move_data.clone(), move_data.clone(),
choice.script().clone(), move_choice.script().clone(),
); );
let mut prevented = false; let mut prevented = false;
script_hook!(prevent_move, executing_move, &executing_move, &mut prevented); script_hook!(prevent_move, executing_move, &executing_move, &mut prevented);

View File

@ -22,6 +22,7 @@ use crate::{script_hook, PkmnResult, StringKey};
/// A pokemon battle, with any amount of sides and pokemon per side. /// A pokemon battle, with any amount of sides and pokemon per side.
#[derive(Debug)] #[derive(Debug)]
#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))]
pub struct Battle { pub struct Battle {
/// The library the battle uses for handling. /// The library the battle uses for handling.
library: Arc<DynamicLibrary>, library: Arc<DynamicLibrary>,

View File

@ -84,6 +84,7 @@ impl HitData {
/// An executing move is the data of the move for while it is executing. /// An executing move is the data of the move for while it is executing.
#[derive(Debug)] #[derive(Debug)]
#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))]
pub struct ExecutingMove { pub struct ExecutingMove {
/// The number of hits this move has. /// The number of hits this move has.
number_of_hits: u8, number_of_hits: u8,

View File

@ -7,7 +7,7 @@ use std::thread::JoinHandle;
use parking_lot::{MappedRwLockReadGuard, RwLock, RwLockReadGuard}; use parking_lot::{MappedRwLockReadGuard, RwLock, RwLockReadGuard};
use crate::dynamic_data::choices::{MoveChoice, TurnChoice}; use crate::dynamic_data::choices::TurnChoice;
use crate::dynamic_data::DamageSource; use crate::dynamic_data::DamageSource;
use crate::dynamic_data::ExecutingMove; use crate::dynamic_data::ExecutingMove;
use crate::dynamic_data::Pokemon; use crate::dynamic_data::Pokemon;
@ -79,11 +79,11 @@ pub trait Script: Send + Sync {
/// This function allows you to change the move that is used during execution. This is useful for /// This function allows you to change the move that is used during execution. This is useful for
/// moves such as metronome, where the move chosen actually differs from the move used. /// moves such as metronome, where the move chosen actually differs from the move used.
fn change_move(&self, _choice: &MoveChoice, _move_name: &mut StringKey) {} fn change_move(&self, _choice: &TurnChoice, _move_name: &mut StringKey) {}
/// This function allows you to change a move into a multi-hit move. The number of hits set here /// This function allows you to change a move into a multi-hit move. The number of hits set here
/// gets used as the number of hits. If set to 0, this will behave as if the move missed on its /// gets used as the number of hits. If set to 0, this will behave as if the move missed on its
/// first hit. /// first hit.
fn change_number_of_hits(&self, _choice: &MoveChoice, _number_of_hits: &mut u8) {} fn change_number_of_hits(&self, _choice: &TurnChoice, _number_of_hits: &mut u8) {}
/// This function allows you to prevent a move from running. If this gets set to true, the move /// This function allows you to prevent a move from running. If this gets set to true, the move
/// ends execution here. No PP will be decreased in this case. /// ends execution here. No PP will be decreased in this case.

View File

@ -13,7 +13,7 @@ register! {
turn_choice: ExternRef<LearnedMove>, turn_choice: ExternRef<LearnedMove>,
) -> u8 { ) -> u8 {
unsafe { unsafe {
transmute(turn_choice.value(&env).unwrap().learn_method()) transmute(turn_choice.value_func(&env).unwrap().learn_method())
} }
} }
@ -21,6 +21,6 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
turn_choice: ExternRef<LearnedMove>, turn_choice: ExternRef<LearnedMove>,
) -> ExternRef<MoveData> { ) -> ExternRef<MoveData> {
ExternRef::func_new(&env, turn_choice.value(&env).unwrap().move_data()) ExternRef::func_new(&env, turn_choice.value_func(&env).unwrap().move_data())
} }
} }

View File

@ -18,7 +18,7 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
dynamic_lib: ExternRef<DynamicLibrary>, dynamic_lib: ExternRef<DynamicLibrary>,
) -> ExternRef<StaticData> { ) -> ExternRef<StaticData> {
ExternRef::func_new(&env, dynamic_lib.value(&env).unwrap().static_data()) ExternRef::func_new(&env, dynamic_lib.value_func(&env).unwrap().static_data())
} }
manual manual_register manual manual_register
} }

View File

@ -13,7 +13,7 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> ExternRef<DynamicLibrary> { ) -> ExternRef<DynamicLibrary> {
let lib = pokemon.value(&env).unwrap().library(); let lib = pokemon.value_func(&env).unwrap().library();
ExternRef::func_new(&env, lib) ExternRef::func_new(&env, lib)
} }
@ -21,7 +21,7 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> ExternRef<StatisticSet<u32>> { ) -> ExternRef<StatisticSet<u32>> {
let statistic_set = pokemon.value(&env).unwrap().boosted_stats(); let statistic_set = pokemon.value_func(&env).unwrap().boosted_stats();
ExternRef::func_new(&env, statistic_set) ExternRef::func_new(&env, statistic_set)
} }
@ -29,7 +29,7 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> ExternRef<StatisticSet<u32>> { ) -> ExternRef<StatisticSet<u32>> {
let statistic_set = pokemon.value(&env).unwrap().flat_stats(); let statistic_set = pokemon.value_func(&env).unwrap().flat_stats();
ExternRef::func_new(&env, statistic_set) ExternRef::func_new(&env, statistic_set)
} }
@ -37,7 +37,7 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> ExternRef<ClampedStatisticSet<i8, -6, 6>> { ) -> ExternRef<ClampedStatisticSet<i8, -6, 6>> {
let statistic_set = pokemon.value(&env).unwrap().stat_boosts(); let statistic_set = pokemon.value_func(&env).unwrap().stat_boosts();
ExternRef::func_new(&env, statistic_set) ExternRef::func_new(&env, statistic_set)
} }
@ -45,7 +45,7 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> ExternRef<ClampedStatisticSet<u8, 0, 31>> { ) -> ExternRef<ClampedStatisticSet<u8, 0, 31>> {
let statistic_set = pokemon.value(&env).unwrap().individual_values(); let statistic_set = pokemon.value_func(&env).unwrap().individual_values();
ExternRef::func_new(&env, statistic_set) ExternRef::func_new(&env, statistic_set)
} }
@ -53,7 +53,7 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> ExternRef<ClampedStatisticSet<u8, 0, 252>> { ) -> ExternRef<ClampedStatisticSet<u8, 0, 252>> {
let statistic_set = pokemon.value(&env).unwrap().effort_values(); let statistic_set = pokemon.value_func(&env).unwrap().effort_values();
ExternRef::func_new(&env, statistic_set) ExternRef::func_new(&env, statistic_set)
} }
@ -61,7 +61,7 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> ExternRef<Species> { ) -> ExternRef<Species> {
let species = pokemon.value(&env).unwrap().species(); let species = pokemon.value_func(&env).unwrap().species();
ExternRef::func_new(&env, species) ExternRef::func_new(&env, species)
} }
@ -72,7 +72,7 @@ register! {
source: u8 source: u8
) { ) {
unsafe{ unsafe{
pokemon.value(&env).unwrap().damage(damage, transmute(source)); pokemon.value_func(&env).unwrap().damage(damage, transmute(source));
} }
} }
} }

View File

@ -12,7 +12,7 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
turn_choice: ExternRef<TurnChoice>, turn_choice: ExternRef<TurnChoice>,
) -> ExternRef<Pokemon> { ) -> ExternRef<Pokemon> {
let turn_choice = turn_choice.value(&env).unwrap(); let turn_choice = turn_choice.value_func(&env).unwrap();
ExternRef::func_new(&env, turn_choice.user().as_ref().deref()) ExternRef::func_new(&env, turn_choice.user().as_ref().deref())
} }
@ -20,7 +20,7 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
turn_choice: ExternRef<TurnChoice>, turn_choice: ExternRef<TurnChoice>,
) -> u8 { ) -> u8 {
match turn_choice.value(&env).unwrap() { match turn_choice.value_func(&env).unwrap() {
TurnChoice::Move(_) => 0, TurnChoice::Move(_) => 0,
TurnChoice::Item(_) => 1, TurnChoice::Item(_) => 1,
TurnChoice::Switch(_) => 2, TurnChoice::Switch(_) => 2,
@ -33,7 +33,7 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
turn_choice: ExternRef<TurnChoice>, turn_choice: ExternRef<TurnChoice>,
) -> ExternRef<LearnedMove> { ) -> ExternRef<LearnedMove> {
if let TurnChoice::Move(d) = turn_choice.value(&env).unwrap() { if let TurnChoice::Move(d) = turn_choice.value_func(&env).unwrap() {
return ExternRef::func_new(&env, d.used_move().as_ref()); return ExternRef::func_new(&env, d.used_move().as_ref());
} }
panic!("Invalid turn choice"); panic!("Invalid turn choice");
@ -43,7 +43,7 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
turn_choice: ExternRef<TurnChoice>, turn_choice: ExternRef<TurnChoice>,
) -> u8 { ) -> u8 {
if let TurnChoice::Move(d) = turn_choice.value(&env).unwrap() { if let TurnChoice::Move(d) = turn_choice.value_func(&env).unwrap() {
return d.target_side(); return d.target_side();
} }
panic!("Invalid turn choice"); panic!("Invalid turn choice");
@ -53,7 +53,7 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
turn_choice: ExternRef<TurnChoice>, turn_choice: ExternRef<TurnChoice>,
) -> u8 { ) -> u8 {
if let TurnChoice::Move(d) = turn_choice.value(&env).unwrap() { if let TurnChoice::Move(d) = turn_choice.value_func(&env).unwrap() {
return d.target_index(); return d.target_index();
} }
panic!("Invalid turn choice"); panic!("Invalid turn choice");

View File

@ -119,13 +119,13 @@ fn _vec_extern_ref_get_value(env: FunctionEnvMut<WebAssemblyEnv>, reference: u32
/// Gets the hash value of a StringKey. /// Gets the hash value of a StringKey.
fn string_key_get_hash(env: FunctionEnvMut<WebAssemblyEnv>, string_key: ExternRef<StringKey>) -> u32 { fn string_key_get_hash(env: FunctionEnvMut<WebAssemblyEnv>, string_key: ExternRef<StringKey>) -> u32 {
string_key.value(&env).unwrap().hash() string_key.value_func(&env).unwrap().hash()
} }
/// Get a null-terminated C string from a StringKey. Note that this involves a copy into WASM /// Get a null-terminated C string from a StringKey. Note that this involves a copy into WASM
/// memory, so this is relatively heavy. /// memory, so this is relatively heavy.
fn string_key_get_str(env: FunctionEnvMut<WebAssemblyEnv>, string_key: ExternRef<StringKey>) -> u32 { fn string_key_get_str(env: FunctionEnvMut<WebAssemblyEnv>, string_key: ExternRef<StringKey>) -> u32 {
let string_key = string_key.value(&env).unwrap().str(); let string_key = string_key.value_func(&env).unwrap().str();
let wasm_string_ptr = env let wasm_string_ptr = env
.data() .data()
.data() .data()
@ -141,7 +141,7 @@ fn string_key_get_str(env: FunctionEnvMut<WebAssemblyEnv>, string_key: ExternRef
/// Gets the type of an EffectParameter /// Gets the type of an EffectParameter
fn effect_parameter_get_type(env: FunctionEnvMut<WebAssemblyEnv>, parameter: ExternRef<EffectParameter>) -> u8 { fn effect_parameter_get_type(env: FunctionEnvMut<WebAssemblyEnv>, parameter: ExternRef<EffectParameter>) -> u8 {
let v = parameter.value(&env).unwrap(); let v = parameter.value_func(&env).unwrap();
match v { match v {
EffectParameter::Bool(_) => 1, EffectParameter::Bool(_) => 1,
EffectParameter::Int(_) => 2, EffectParameter::Int(_) => 2,
@ -152,7 +152,7 @@ fn effect_parameter_get_type(env: FunctionEnvMut<WebAssemblyEnv>, parameter: Ext
/// Gets the inner bool data of an EffectParameter. Panics if it's not a bool. /// Gets the inner bool data of an EffectParameter. Panics if it's not a bool.
fn effect_parameter_as_bool(env: FunctionEnvMut<WebAssemblyEnv>, parameter: ExternRef<EffectParameter>) -> u8 { fn effect_parameter_as_bool(env: FunctionEnvMut<WebAssemblyEnv>, parameter: ExternRef<EffectParameter>) -> u8 {
let v = parameter.value(&env).unwrap(); let v = parameter.value_func(&env).unwrap();
match v { match v {
EffectParameter::Bool(b) => { EffectParameter::Bool(b) => {
if *b { if *b {
@ -167,7 +167,7 @@ fn effect_parameter_as_bool(env: FunctionEnvMut<WebAssemblyEnv>, parameter: Exte
/// Gets the inner int data of an EffectParameter. Panics if it's not an int. /// Gets the inner int data of an EffectParameter. Panics if it's not an int.
fn effect_parameter_as_int(env: FunctionEnvMut<WebAssemblyEnv>, parameter: ExternRef<EffectParameter>) -> i64 { fn effect_parameter_as_int(env: FunctionEnvMut<WebAssemblyEnv>, parameter: ExternRef<EffectParameter>) -> i64 {
let v = parameter.value(&env).unwrap(); let v = parameter.value_func(&env).unwrap();
match v { match v {
EffectParameter::Int(i) => *i, EffectParameter::Int(i) => *i,
_ => panic!("Unexpected parameter type!"), _ => panic!("Unexpected parameter type!"),
@ -176,7 +176,7 @@ fn effect_parameter_as_int(env: FunctionEnvMut<WebAssemblyEnv>, parameter: Exter
/// Gets the inner float data of an EffectParameter. Panics if it's not a float. /// Gets the inner float data of an EffectParameter. Panics if it's not a float.
fn effect_parameter_as_float(env: FunctionEnvMut<WebAssemblyEnv>, parameter: ExternRef<EffectParameter>) -> f32 { fn effect_parameter_as_float(env: FunctionEnvMut<WebAssemblyEnv>, parameter: ExternRef<EffectParameter>) -> f32 {
let v = parameter.value(&env).unwrap(); let v = parameter.value_func(&env).unwrap();
match v { match v {
EffectParameter::Float(f) => *f, EffectParameter::Float(f) => *f,
_ => panic!("Unexpected parameter type!"), _ => panic!("Unexpected parameter type!"),
@ -188,7 +188,7 @@ fn effect_parameter_as_string(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
parameter: ExternRef<EffectParameter>, parameter: ExternRef<EffectParameter>,
) -> ExternRef<StringKey> { ) -> ExternRef<StringKey> {
let v = parameter.value(&env).unwrap(); let v = parameter.value_func(&env).unwrap();
match v { match v {
EffectParameter::String(s) => ExternRef::func_new(&env, s), EffectParameter::String(s) => ExternRef::func_new(&env, s),
_ => panic!("Unexpected parameter type!"), _ => panic!("Unexpected parameter type!"),

View File

@ -13,33 +13,33 @@ mod species;
register! { register! {
fn static_data_get_move_library(env: FunctionEnvMut<WebAssemblyEnv>, data_library: ExternRef<StaticData>) -> ExternRef<MoveLibrary> { fn static_data_get_move_library(env: FunctionEnvMut<WebAssemblyEnv>, data_library: ExternRef<StaticData>) -> ExternRef<MoveLibrary> {
ExternRef::func_new(&env, data_library.value(&env).unwrap().moves()) ExternRef::func_new(&env, data_library.value_func(&env).unwrap().moves())
} }
fn static_data_get_species_library( fn static_data_get_species_library(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
data_library: ExternRef<StaticData>, data_library: ExternRef<StaticData>,
) -> ExternRef<SpeciesLibrary> { ) -> ExternRef<SpeciesLibrary> {
ExternRef::func_new(&env, data_library.value(&env).unwrap().species()) ExternRef::func_new(&env, data_library.value_func(&env).unwrap().species())
} }
fn static_data_get_item_library(env: FunctionEnvMut<WebAssemblyEnv>, data_library: ExternRef<StaticData>) -> ExternRef<ItemLibrary> { fn static_data_get_item_library(env: FunctionEnvMut<WebAssemblyEnv>, data_library: ExternRef<StaticData>) -> ExternRef<ItemLibrary> {
ExternRef::func_new(&env, data_library.value(&env).unwrap().items()) ExternRef::func_new(&env, data_library.value_func(&env).unwrap().items())
} }
fn static_data_get_type_library(env: FunctionEnvMut<WebAssemblyEnv>, data_library: ExternRef<StaticData>) -> ExternRef<TypeLibrary> { fn static_data_get_type_library(env: FunctionEnvMut<WebAssemblyEnv>, data_library: ExternRef<StaticData>) -> ExternRef<TypeLibrary> {
ExternRef::func_new(&env, data_library.value(&env).unwrap().types()) ExternRef::func_new(&env, data_library.value_func(&env).unwrap().types())
} }
fn static_data_get_library_settings( fn static_data_get_library_settings(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
data_library: ExternRef<StaticData>, data_library: ExternRef<StaticData>,
) -> ExternRef<LibrarySettings> { ) -> ExternRef<LibrarySettings> {
ExternRef::func_new(&env, data_library.value(&env).unwrap().settings()) ExternRef::func_new(&env, data_library.value_func(&env).unwrap().settings())
} }
fn library_settings_get_maximum_level(env: FunctionEnvMut<WebAssemblyEnv>, data_library: ExternRef<LibrarySettings>) -> LevelInt { fn library_settings_get_maximum_level(env: FunctionEnvMut<WebAssemblyEnv>, data_library: ExternRef<LibrarySettings>) -> LevelInt {
data_library.value(&env).unwrap().maximum_level() data_library.value_func(&env).unwrap().maximum_level()
} }
manual manual_registration manual manual_registration

View File

@ -11,8 +11,8 @@ fn move_library_get_move(
lib: ExternRef<MoveLibrary>, lib: ExternRef<MoveLibrary>,
string_key: ExternRef<StringKey>, string_key: ExternRef<StringKey>,
) -> ExternRef<MoveData> { ) -> ExternRef<MoveData> {
let lib = lib.value(&env).unwrap(); let lib = lib.value_func(&env).unwrap();
let m = lib.get(string_key.value(&env).unwrap()); let m = lib.get(string_key.value_func(&env).unwrap());
if let Some(v) = m { if let Some(v) = m {
ExternRef::func_new(&env, v) ExternRef::func_new(&env, v)
} else { } else {
@ -21,7 +21,7 @@ fn move_library_get_move(
} }
fn move_library_get_move_by_hash(env: FunctionEnvMut<WebAssemblyEnv>, lib: ExternRef<MoveLibrary>, hash: u32) -> ExternRef<MoveData> { fn move_library_get_move_by_hash(env: FunctionEnvMut<WebAssemblyEnv>, lib: ExternRef<MoveLibrary>, hash: u32) -> ExternRef<MoveData> {
let lib = lib.value(&env).unwrap(); let lib = lib.value_func(&env).unwrap();
let m = lib.get_by_hash(hash); let m = lib.get_by_hash(hash);
if let Some(v) = m { if let Some(v) = m {
ExternRef::func_new(&env, v) ExternRef::func_new(&env, v)
@ -31,39 +31,39 @@ fn move_library_get_move_by_hash(env: FunctionEnvMut<WebAssemblyEnv>, lib: Exter
} }
fn move_data_get_name(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>) -> ExternRef<StringKey> { fn move_data_get_name(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>) -> ExternRef<StringKey> {
ExternRef::func_new(&env, move_data.value(&env).unwrap().name()) ExternRef::func_new(&env, move_data.value_func(&env).unwrap().name())
} }
fn move_data_get_type(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>) -> u8 { fn move_data_get_type(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>) -> u8 {
move_data.value(&env).unwrap().move_type().into() move_data.value_func(&env).unwrap().move_type().into()
} }
fn move_data_get_category(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>) -> u8 { fn move_data_get_category(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>) -> u8 {
move_data.value(&env).unwrap().category() as u8 move_data.value_func(&env).unwrap().category() as u8
} }
fn move_data_get_base_power(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>) -> u8 { fn move_data_get_base_power(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>) -> u8 {
move_data.value(&env).unwrap().base_power() move_data.value_func(&env).unwrap().base_power()
} }
fn move_data_get_accuracy(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>) -> u8 { fn move_data_get_accuracy(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>) -> u8 {
move_data.value(&env).unwrap().accuracy() move_data.value_func(&env).unwrap().accuracy()
} }
fn move_data_get_base_usages(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>) -> u8 { fn move_data_get_base_usages(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>) -> u8 {
move_data.value(&env).unwrap().base_usages() move_data.value_func(&env).unwrap().base_usages()
} }
fn move_data_get_target(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>) -> u8 { fn move_data_get_target(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>) -> u8 {
move_data.value(&env).unwrap().target() as u8 move_data.value_func(&env).unwrap().target() as u8
} }
fn move_data_get_priority(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>) -> i8 { fn move_data_get_priority(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>) -> i8 {
move_data.value(&env).unwrap().priority() move_data.value_func(&env).unwrap().priority()
} }
fn move_data_has_flag(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>, flag: ExternRef<StringKey>) -> u8 { fn move_data_has_flag(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>, flag: ExternRef<StringKey>) -> u8 {
if move_data.value(&env).unwrap().has_flag(flag.value(&env).unwrap()) { if move_data.value_func(&env).unwrap().has_flag(flag.value_func(&env).unwrap()) {
1 1
} else { } else {
0 0
} }
} }
fn move_data_has_flag_by_hash(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>, flag_hash: u32) -> u8 { fn move_data_has_flag_by_hash(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>, flag_hash: u32) -> u8 {
if move_data.value(&env).unwrap().has_flag_by_hash(flag_hash) { if move_data.value_func(&env).unwrap().has_flag_by_hash(flag_hash) {
1 1
} else { } else {
0 0

View File

@ -12,8 +12,8 @@ fn species_library_get_species(
lib: ExternRef<SpeciesLibrary>, lib: ExternRef<SpeciesLibrary>,
string_key: ExternRef<StringKey>, string_key: ExternRef<StringKey>,
) -> ExternRef<Species> { ) -> ExternRef<Species> {
let lib = lib.value(&env).unwrap(); let lib = lib.value_func(&env).unwrap();
let m = lib.get(string_key.value(&env).unwrap()); let m = lib.get(string_key.value_func(&env).unwrap());
if let Some(v) = m { if let Some(v) = m {
ExternRef::func_new(&env, v) ExternRef::func_new(&env, v)
} else { } else {
@ -25,14 +25,14 @@ fn species_get_capture_rate(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
species: ExternRef<Species>, species: ExternRef<Species>,
) -> u8 { ) -> u8 {
species.value(&env).unwrap().capture_rate() species.value_func(&env).unwrap().capture_rate()
} }
fn species_get_growth_rate( fn species_get_growth_rate(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
species: ExternRef<Species>, species: ExternRef<Species>,
) -> ExternRef<StringKey> { ) -> ExternRef<StringKey> {
let species = species.value(&env).unwrap(); let species = species.value_func(&env).unwrap();
ExternRef::func_new(&env, species.growth_rate()) ExternRef::func_new(&env, species.growth_rate())
} }
@ -40,14 +40,14 @@ fn species_get_gender_rate(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
species: ExternRef<Species>, species: ExternRef<Species>,
) -> f32 { ) -> f32 {
species.value(&env).unwrap().gender_rate() species.value_func(&env).unwrap().gender_rate()
} }
fn species_get_name( fn species_get_name(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
species: ExternRef<Species>, species: ExternRef<Species>,
) -> ExternRef<StringKey> { ) -> ExternRef<StringKey> {
let species = species.value(&env).unwrap(); let species = species.value_func(&env).unwrap();
ExternRef::func_new(&env, species.name()) ExternRef::func_new(&env, species.name())
} }
@ -55,7 +55,7 @@ fn species_get_id(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
species: ExternRef<Species>, species: ExternRef<Species>,
) -> u16 { ) -> u16 {
species.value(&env).unwrap().id() species.value_func(&env).unwrap().id()
} }

View File

@ -1,5 +1,6 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem::transmute; use std::mem::transmute;
use std::sync::Arc;
use crate::script_implementations::wasm::script_resolver::{ use crate::script_implementations::wasm::script_resolver::{
WebAssemblyEnv, WebAssemblyEnvironmentData, WebAssemblyScriptResolver, WebAssemblyEnv, WebAssemblyEnvironmentData, WebAssemblyScriptResolver,
@ -11,6 +12,7 @@ use wasmer::FunctionEnvMut;
/// An Extern Ref allows us to pass objects to WASM without actually passing raw memory, or /// An Extern Ref allows us to pass objects to WASM without actually passing raw memory, or
/// requiring us to make copies. Instead, we pass a simple increment index, that we can then use /// requiring us to make copies. Instead, we pass a simple increment index, that we can then use
/// to find the relevant data. /// to find the relevant data.
#[derive(Copy, Clone)]
pub(crate) struct ExternRef<T: UniqueTypeId<u64>> { pub(crate) struct ExternRef<T: UniqueTypeId<u64>> {
/// The lookup index we can use to find the data. /// The lookup index we can use to find the data.
index: u32, index: u32,
@ -55,8 +57,14 @@ impl<T: UniqueTypeId<u64>> ExternRef<T> {
/// Returns the real value for a given ExternRef. Note that the requested type must be the same as the type of the /// Returns the real value for a given ExternRef. Note that the requested type must be the same as the type of the
/// value when it was passed before. If these types do not match, this will panic. /// value when it was passed before. If these types do not match, this will panic.
pub fn value<'a, 'b>(&'a self, env: &'b FunctionEnvMut<WebAssemblyEnv>) -> Option<&'b T> { pub fn value_func<'a, 'b>(&'a self, env: &'b FunctionEnvMut<WebAssemblyEnv>) -> Option<&'b T> {
let ptr = env.data().data().get_extern_ref_value(self.index) as *const T; self.value(&env.data().data())
}
/// Returns the real value for a given ExternRef. Note that the requested type must be the same as the type of the
/// value when it was passed before. If these types do not match, this will panic.
pub fn value<'a, 'b, 'c>(&'a self, env: &'b Arc<WebAssemblyEnvironmentData>) -> Option<&'c T> {
let ptr = env.get_extern_ref_value(self.index) as *const T;
unsafe { ptr.as_ref() } unsafe { ptr.as_ref() }
} }
} }

View File

@ -16,61 +16,64 @@ mod temp_wasm_allocator;
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] #[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
#[allow(missing_docs)] #[allow(missing_docs)]
#[allow(clippy::missing_docs_in_private_items)] #[allow(clippy::missing_docs_in_private_items)]
#[repr(u8)]
pub enum WebAssemblyScriptCapabilities { pub enum WebAssemblyScriptCapabilities {
None = 0, None = 0,
Initialize = 1, Initialize = 1,
OnStack, OnStack,
OnRemove, OnRemove,
OnBeforeTurn, OnBeforeTurn,
ChangeAttack, ChangeMove,
ModifyNumberOfHits, ChangeNumberOfHits,
PreventAttack, PreventMove,
FailAttack, FailMove,
StopBeforeAttack, StopBeforeMove,
OnBeforeAttack, OnBeforeMove,
FailIncomingAttack, FailIncomingMove,
IsInvulnerable, IsInvulnerable,
OnAttackMiss, OnMoveMiss,
ChangeAttackType, ChangeMoveType,
ChangeEffectiveness, ChangeEffectiveness,
BlockCritical, BlockCritical,
OnIncomingHit, OnIncomingHit,
OnFaintingOpponent, OnFaintingOpponent,
PreventStatBoostChange, PreventStatBoostChange,
ModifyStatBoostChange, ChangeStatBoostChange,
PreventSecondaryEffects, PreventSecondaryEffects,
OnSecondaryEffect, OnSecondaryEffect,
OnAfterHits, OnAfterHits,
PreventSelfSwitch, PreventSelfSwitch,
ModifyEffectChance, ChangeEffectChance,
ModifyIncomingEffectChance, ChangeIncomingEffectChance,
OverrideBasePower, ChangeBasePower,
ChangeDamageStatsUser, ChangeDamageStatsUser,
BypassDefensiveStat, BypassDefensiveStat,
BypassOffensiveStat, BypassOffensiveStat,
ModifyStatModifier, ChangeStatModifier,
ModifyDamageModifier, ChangeDamageModifier,
OverrideDamage, ChangeDamage,
OverrideIncomingDamage, ChangeIncomingDamage,
ChangeSpeed, ChangeSpeed,
ChangePriority, ChangePriority,
OnFail, OnFail,
OnOpponentFail, OnOpponentFail,
PreventRunAway, PreventSelfRunAway,
PreventOpponentRunAway, PreventOpponentRunAway,
PreventOpponentSwitch, PreventOpponentSwitch,
OnEndTurn, OnEndTurn,
OnDamage, OnDamage,
OnFaint, OnFaint,
OnAfterHeldItemConsume, OnAfterHeldItemConsume,
PreventIncomingCritical, BlockIncomingCritical,
ModifyCriticalStage, ChangeAccuracy,
OverrideCriticalModifier, ChangeCriticalStage,
OverrideSTABModifier, ChangeCriticalModifier,
ModifyExperienceGain, ChangeSTABModifier,
ChangeExperienceGain,
DoesShareExperience, DoesShareExperience,
BlockWeather, BlockWeather,
OnSwitchIn, OnSwitchIn,
ModifyOffensiveStatValue, ChangeOffensiveStatValue,
ModifyDefensiveStatValue, ChangeDefensiveStatValue,
ChangeCaptureRate,
} }

View File

@ -1,14 +1,14 @@
use std::any::Any; use std::any::Any;
use std::sync::atomic::{AtomicBool, AtomicPtr, AtomicUsize}; use std::sync::atomic::{AtomicBool, AtomicPtr, AtomicUsize};
use std::sync::{Arc, Weak}; use std::sync::Arc;
use hashbrown::HashSet; use hashbrown::HashSet;
use crate::dynamic_data::{DynamicLibrary, Script, TurnChoice}; use crate::dynamic_data::{Battle, DamageSource, DynamicLibrary, ExecutingMove, Pokemon, Script, TurnChoice};
use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef}; use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef};
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnvironmentData; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnvironmentData;
use crate::script_implementations::wasm::WebAssemblyScriptCapabilities; use crate::script_implementations::wasm::WebAssemblyScriptCapabilities;
use crate::static_data::EffectParameter; use crate::static_data::{EffectParameter, Item, Statistic, TypeIdentifier};
use crate::StringKey; use crate::StringKey;
/// A WebAssemblyScript is there to implement the Script trait within WebAssemblyScript. /// A WebAssemblyScript is there to implement the Script trait within WebAssemblyScript.
@ -29,7 +29,7 @@ pub struct WebAssemblyScript {
/// Capabilities define which functions we actually implement. /// Capabilities define which functions we actually implement.
capabilities: Arc<HashSet<WebAssemblyScriptCapabilities>>, capabilities: Arc<HashSet<WebAssemblyScriptCapabilities>>,
/// The global runtime environment data. /// The global runtime environment data.
environment: Weak<WebAssemblyEnvironmentData>, environment: Arc<WebAssemblyEnvironmentData>,
} }
impl WebAssemblyScript { impl WebAssemblyScript {
@ -38,7 +38,7 @@ impl WebAssemblyScript {
owner_ptr: *mut u8, owner_ptr: *mut u8,
self_ptr: u32, self_ptr: u32,
capabilities: Arc<HashSet<WebAssemblyScriptCapabilities>>, capabilities: Arc<HashSet<WebAssemblyScriptCapabilities>>,
environment: Weak<WebAssemblyEnvironmentData>, environment: Arc<WebAssemblyEnvironmentData>,
name: StringKey, name: StringKey,
) -> Self { ) -> Self {
Self { Self {
@ -51,6 +51,33 @@ impl WebAssemblyScript {
environment, environment,
} }
} }
/// Check if this script implements a certain capability.
#[inline(always)]
fn has_capability(&self, cap: &WebAssemblyScriptCapabilities) -> bool {
self.capabilities.contains(cap)
}
}
/// Util macro to reduce function call verbosity.
macro_rules! call_func {
($func:ident, $env:ident, $self:ident $(, $par_name:expr)*) => {
$func.call(&mut $env.store_mut(), $self.self_ptr $(, $par_name)*).unwrap();
}
}
/// Util macro to reduce extern ref instantiation verbosity.
macro_rules! ex_ref {
($env:ident, $value:expr) => {
ExternRef::new($env.as_ref(), $value)
};
}
/// Util macro to reduce vec extern ref instantiation verbosity.
macro_rules! vec_ex_ref {
($env:ident, $value:expr) => {
VecExternRef::new($env.as_ref(), $value)
};
} }
impl Script for WebAssemblyScript { impl Script for WebAssemblyScript {
@ -67,104 +94,721 @@ impl Script for WebAssemblyScript {
} }
fn stack(&self) { fn stack(&self) {
if !self.capabilities.contains(&WebAssemblyScriptCapabilities::OnStack) { if !self.has_capability(&WebAssemblyScriptCapabilities::OnStack) {
return; return;
} }
let env = self.environment.upgrade().unwrap(); let env = &self.environment;
let func = env.script_function_cache().stack(&env); if let Some(func) = env.script_function_cache().stack(env) {
if let Some(func) = func { call_func!(func, env, self);
func.call(&mut env.store_mut(), self.self_ptr).unwrap();
} }
} }
fn on_remove(&self) { fn on_remove(&self) {
if !self.capabilities.contains(&WebAssemblyScriptCapabilities::OnRemove) { if !self.has_capability(&WebAssemblyScriptCapabilities::OnRemove) {
return; return;
} }
let env = self.environment.upgrade().unwrap(); let env = &self.environment;
let func = env.script_function_cache().on_remove(&env); if let Some(func) = env.script_function_cache().on_remove(env) {
if let Some(func) = func { call_func!(func, env, self);
func.call(&mut env.store_mut(), self.self_ptr).unwrap();
} }
} }
fn on_initialize(&self, library: &DynamicLibrary, pars: &[EffectParameter]) { fn on_initialize(&self, library: &DynamicLibrary, pars: &[EffectParameter]) {
if !self.capabilities.contains(&WebAssemblyScriptCapabilities::Initialize) { if !self.has_capability(&WebAssemblyScriptCapabilities::Initialize) {
return; return;
} }
let env = self.environment.upgrade().unwrap(); let env = &self.environment;
let func = env.script_function_cache().on_initialize(&env); if let Some(func) = env.script_function_cache().on_initialize(env) {
if let Some(func) = func { call_func!(func, env, self, ex_ref!(env, library), vec_ex_ref!(env, pars));
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) { fn on_before_turn(&self, choice: &TurnChoice) {
if !self.capabilities.contains(&WebAssemblyScriptCapabilities::OnBeforeTurn) { if !self.has_capability(&WebAssemblyScriptCapabilities::OnBeforeTurn) {
return; return;
} }
let env = self.environment.upgrade().unwrap(); let env = &self.environment;
let func = env.script_function_cache().on_before_turn(&env); if let Some(func) = env.script_function_cache().on_before_turn(env) {
if let Some(func) = func { call_func!(func, env, self, ex_ref!(env, choice));
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) { fn change_speed(&self, choice: &TurnChoice, speed: &mut u32) {
if !self.capabilities.contains(&WebAssemblyScriptCapabilities::ChangeSpeed) { if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeSpeed) {
return; return;
} }
let env = self.environment.upgrade().unwrap(); let env = &self.environment;
let func = env.script_function_cache().change_speed(&env); if let Some(func) = env.script_function_cache().change_speed(env) {
if let Some(func) = func { let ptr = env.allocate_temp::<u32>(*speed);
let ptr = env.temp_allocate_mem_typed::<u32>(*speed); call_func!(func, env, self, ex_ref!(env, choice), ptr.wasm_ptr);
func.call(
&mut env.store_mut(),
self.self_ptr,
ExternRef::new(env.as_ref(), choice),
ptr.wasm_pointer,
)
.unwrap();
*speed = *ptr.value(); *speed = *ptr.value();
} }
} }
fn change_priority(&self, choice: &TurnChoice, priority: &mut i8) { fn change_priority(&self, choice: &TurnChoice, priority: &mut i8) {
if !self if !self.has_capability(&WebAssemblyScriptCapabilities::ChangePriority) {
.capabilities
.contains(&WebAssemblyScriptCapabilities::ChangePriority)
{
return; return;
} }
let env = self.environment.upgrade().unwrap(); let env = &self.environment;
let func = env.script_function_cache().change_priority(&env); if let Some(func) = env.script_function_cache().change_priority(env) {
if let Some(func) = func { let ptr = env.allocate_temp::<i8>(*priority);
let ptr = env.temp_allocate_mem_typed::<i8>(*priority); call_func!(func, env, self, ex_ref!(env, choice), ptr.wasm_ptr);
func.call(
&mut env.store_mut(),
self.self_ptr,
ExternRef::new(env.as_ref(), choice),
ptr.wasm_pointer,
)
.unwrap();
*priority = *ptr.value(); *priority = *ptr.value();
} }
} }
fn change_move(&self, choice: &TurnChoice, move_name: &mut StringKey) {
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeMove) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().change_move(env) {
let move_ref = ex_ref!(env, move_name);
let ptr = env.allocate_temp::<ExternRef<StringKey>>(move_ref);
call_func!(func, env, self, ex_ref!(env, choice), ptr.wasm_ptr);
*move_name = ptr.value().value(env).unwrap().clone();
}
}
fn change_number_of_hits(&self, choice: &TurnChoice, number_of_hits: &mut u8) {
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeNumberOfHits) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().change_number_of_hits(env) {
let ptr = env.allocate_temp::<u8>(*number_of_hits);
call_func!(func, env, self, ex_ref!(env, choice), ptr.wasm_ptr);
*number_of_hits = *ptr.value();
}
}
fn prevent_move(&self, mv: &ExecutingMove, prevent: &mut bool) {
if !self.has_capability(&WebAssemblyScriptCapabilities::PreventMove) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().prevent_move(env) {
let ptr = env.allocate_temp::<bool>(*prevent);
call_func!(func, env, self, ex_ref!(env, mv), ptr.wasm_ptr);
*prevent = *ptr.value();
}
}
fn fail_move(&self, mv: &ExecutingMove, fail: &mut bool) {
if !self.has_capability(&WebAssemblyScriptCapabilities::FailMove) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().fail_move(env) {
let ptr = env.allocate_temp::<bool>(*fail);
call_func!(func, env, self, ex_ref!(env, mv), ptr.wasm_ptr);
*fail = *ptr.value();
}
}
fn stop_before_move(&self, mv: &ExecutingMove, stop: &mut bool) {
if !self.has_capability(&WebAssemblyScriptCapabilities::StopBeforeMove) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().stop_before_move(env) {
let ptr = env.allocate_temp::<bool>(*stop);
call_func!(func, env, self, ex_ref!(env, mv), ptr.wasm_ptr);
*stop = *ptr.value();
}
}
fn on_before_move(&self, mv: &ExecutingMove) {
if !self.has_capability(&WebAssemblyScriptCapabilities::OnBeforeMove) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().on_before_move(env) {
call_func!(func, env, self, ex_ref!(env, mv));
}
}
fn fail_incoming_move(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, fail: &mut bool) {
if !self.has_capability(&WebAssemblyScriptCapabilities::FailIncomingMove) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().fail_incoming_move(env) {
let ptr = env.allocate_temp::<bool>(*fail);
call_func!(
func,
env,
self,
ex_ref!(env, mv),
ex_ref!(env, target.as_ref()),
ptr.wasm_ptr
);
*fail = *ptr.value();
}
}
fn is_invulnerable(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, invulnerable: &mut bool) {
if !self.has_capability(&WebAssemblyScriptCapabilities::IsInvulnerable) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().is_invulnerable(env) {
let ptr = env.allocate_temp::<bool>(*invulnerable);
call_func!(
func,
env,
self,
ex_ref!(env, mv),
ex_ref!(env, target.as_ref()),
ptr.wasm_ptr
);
*invulnerable = *ptr.value();
}
}
fn on_move_miss(&self, mv: &ExecutingMove, target: &Arc<Pokemon>) {
if !self.has_capability(&WebAssemblyScriptCapabilities::OnMoveMiss) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().on_move_miss(env) {
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target.as_ref()));
}
}
fn change_move_type(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, move_type: &mut TypeIdentifier) {
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeMoveType) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().change_move_type(env) {
let ptr = env.allocate_temp::<TypeIdentifier>(*move_type);
let target = target.as_ref();
let w_ptr = ptr.wasm_ptr;
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
*move_type = *ptr.value();
}
}
fn change_effectiveness(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, effectiveness: &mut f32) {
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeEffectiveness) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().change_effectiveness(env) {
let ptr = env.allocate_temp(*effectiveness);
let target = target.as_ref();
let w_ptr = ptr.wasm_ptr;
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
*effectiveness = *ptr.value();
}
}
fn block_critical(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, block_critical: &mut bool) {
if !self.has_capability(&WebAssemblyScriptCapabilities::BlockCritical) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().block_critical(env) {
let ptr = env.allocate_temp(*block_critical);
let target = target.as_ref();
let w_ptr = ptr.wasm_ptr;
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
*block_critical = *ptr.value();
}
}
fn block_incoming_critical(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, block_critical: &mut bool) {
if !self.has_capability(&WebAssemblyScriptCapabilities::BlockIncomingCritical) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().block_incoming_critical(env) {
let ptr = env.allocate_temp(*block_critical);
let target = target.as_ref();
let w_ptr = ptr.wasm_ptr;
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
*block_critical = *ptr.value();
}
}
fn change_accuracy(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, accuracy: &mut u8) {
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeAccuracy) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().change_accuracy(env) {
let ptr = env.allocate_temp(*accuracy);
let target = target.as_ref();
let w_ptr = ptr.wasm_ptr;
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
*accuracy = *ptr.value();
}
}
fn change_critical_stage(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, stage: &mut u8) {
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeCriticalStage) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().change_critical_stage(env) {
let ptr = env.allocate_temp(*stage);
let target = target.as_ref();
let w_ptr = ptr.wasm_ptr;
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
*stage = *ptr.value();
}
}
fn change_critical_modifier(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, modifier: &mut f32) {
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeCriticalModifier) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().change_critical_modifier(env) {
let ptr = env.allocate_temp(*modifier);
let target = target.as_ref();
let w_ptr = ptr.wasm_ptr;
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
*modifier = *ptr.value();
}
}
fn change_stab_modifier(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, modifier: &mut f32) {
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeSTABModifier) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().change_stab_modifier(env) {
let ptr = env.allocate_temp(*modifier);
let target = target.as_ref();
let w_ptr = ptr.wasm_ptr;
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
*modifier = *ptr.value();
}
}
fn change_base_power(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, base_power: &mut u8) {
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeBasePower) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().change_base_power(env) {
let ptr = env.allocate_temp(*base_power);
let target = target.as_ref();
let w_ptr = ptr.wasm_ptr;
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
*base_power = *ptr.value();
}
}
fn bypass_defensive_stat_boost(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, bypass: &mut bool) {
if !self.has_capability(&WebAssemblyScriptCapabilities::BypassDefensiveStat) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().bypass_defensive_stat_boost(env) {
let ptr = env.allocate_temp(*bypass);
let target = target.as_ref();
let w_ptr = ptr.wasm_ptr;
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
*bypass = *ptr.value();
}
}
fn bypass_offensive_stat_boost(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, bypass: &mut bool) {
if !self.has_capability(&WebAssemblyScriptCapabilities::BypassOffensiveStat) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().bypass_offensive_stat_boost(env) {
let ptr = env.allocate_temp(*bypass);
let target = target.as_ref();
let w_ptr = ptr.wasm_ptr;
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
*bypass = *ptr.value();
}
}
fn change_offensive_stat_value(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, amount: &mut u32) {
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeOffensiveStatValue) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().change_offensive_stat_value(env) {
let ptr = env.allocate_temp(*amount);
let target = target.as_ref();
let w_ptr = ptr.wasm_ptr;
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
*amount = *ptr.value();
}
}
fn change_defensive_stat_value(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, amount: &mut u32) {
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeOffensiveStatValue) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().change_defensive_stat_value(env) {
let ptr = env.allocate_temp(*amount);
let target = target.as_ref();
let w_ptr = ptr.wasm_ptr;
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
*amount = *ptr.value();
}
}
fn change_damage_stat_modifier(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, modifier: &mut f32) {
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeStatModifier) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().change_damage_stat_modifier(env) {
let ptr = env.allocate_temp(*modifier);
let target = target.as_ref();
let w_ptr = ptr.wasm_ptr;
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
*modifier = *ptr.value();
}
}
fn change_damage_modifier(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, modifier: &mut f32) {
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeDamageModifier) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().change_damage_modifier(env) {
let ptr = env.allocate_temp(*modifier);
let target = target.as_ref();
let w_ptr = ptr.wasm_ptr;
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
*modifier = *ptr.value();
}
}
fn change_damage(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, damage: &mut u32) {
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeDamage) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().change_damage(env) {
let ptr = env.allocate_temp(*damage);
let target = target.as_ref();
let w_ptr = ptr.wasm_ptr;
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
*damage = *ptr.value();
}
}
fn change_incoming_damage(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, damage: &mut u32) {
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeIncomingDamage) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().change_incoming_damage(env) {
let ptr = env.allocate_temp(*damage);
let target = target.as_ref();
let w_ptr = ptr.wasm_ptr;
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
*damage = *ptr.value();
}
}
fn on_incoming_hit(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8) {
if !self.has_capability(&WebAssemblyScriptCapabilities::OnIncomingHit) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().on_incoming_hit(env) {
let target = target.as_ref();
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit);
}
}
fn on_opponent_faints(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8) {
if !self.has_capability(&WebAssemblyScriptCapabilities::OnFaintingOpponent) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().on_opponent_faints(env) {
let target = target.as_ref();
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit);
}
}
fn prevent_stat_boost_change(
&self,
target: &Pokemon,
stat: Statistic,
amount: i8,
self_inflicted: bool,
prevent: &mut bool,
) {
if !self.has_capability(&WebAssemblyScriptCapabilities::PreventStatBoostChange) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().prevent_stat_boost_change(env) {
let ptr = env.allocate_temp(*prevent);
let self_inflicted = if self_inflicted { 1_u8 } else { 0_u8 };
call_func!(
func,
env,
self,
ex_ref!(env, target),
stat as u8,
amount,
self_inflicted,
ptr.wasm_ptr
);
*prevent = *ptr.value();
}
}
fn prevent_secondary_effect(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, prevent: &mut bool) {
if !self.has_capability(&WebAssemblyScriptCapabilities::PreventSecondaryEffects) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().prevent_secondary_effect(env) {
let ptr = env.allocate_temp(*prevent);
let target = target.as_ref();
let w_ptr = ptr.wasm_ptr;
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
*prevent = *ptr.value();
}
}
fn change_effect_chance(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, chance: &mut f32) {
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeEffectChance) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().change_effect_chance(env) {
let ptr = env.allocate_temp(*chance);
let target = target.as_ref();
let w_ptr = ptr.wasm_ptr;
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
*chance = *ptr.value();
}
}
fn change_incoming_effect_chance(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, chance: &mut f32) {
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeIncomingEffectChance) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().change_incoming_effect_chance(env) {
let ptr = env.allocate_temp(*chance);
let target = target.as_ref();
let w_ptr = ptr.wasm_ptr;
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
*chance = *ptr.value();
}
}
fn on_secondary_effect(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8) {
if !self.has_capability(&WebAssemblyScriptCapabilities::OnFaintingOpponent) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().on_secondary_effect(env) {
let target = target.as_ref();
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit);
}
}
fn on_after_hits(&self, mv: &ExecutingMove, target: &Arc<Pokemon>) {
if !self.has_capability(&WebAssemblyScriptCapabilities::OnAfterHits) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().on_after_hits(env) {
let target = target.as_ref();
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target));
}
}
fn prevent_self_switch(&self, choice: &TurnChoice, prevent: &mut bool) {
if !self.has_capability(&WebAssemblyScriptCapabilities::PreventSelfSwitch) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().prevent_self_switch(env) {
let ptr = env.allocate_temp(*prevent);
call_func!(func, env, self, ex_ref!(env, choice), ptr.wasm_ptr);
*prevent = *ptr.value();
}
}
fn prevent_opponent_switch(&self, choice: &TurnChoice, prevent: &mut bool) {
if !self.has_capability(&WebAssemblyScriptCapabilities::PreventSelfSwitch) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().prevent_opponent_switch(env) {
let ptr = env.allocate_temp(*prevent);
call_func!(func, env, self, ex_ref!(env, choice), ptr.wasm_ptr);
*prevent = *ptr.value();
}
}
fn on_fail(&self, pokemon: &Pokemon) {
if !self.has_capability(&WebAssemblyScriptCapabilities::OnFail) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().on_fail(env) {
call_func!(func, env, self, ex_ref!(env, pokemon));
}
}
fn on_opponent_fail(&self, pokemon: &Pokemon) {
if !self.has_capability(&WebAssemblyScriptCapabilities::OnFail) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().on_opponent_fail(env) {
call_func!(func, env, self, ex_ref!(env, pokemon));
}
}
fn prevent_self_run_away(&self, choice: &TurnChoice, prevent: &mut bool) {
if !self.has_capability(&WebAssemblyScriptCapabilities::PreventSelfRunAway) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().prevent_self_run_away(env) {
let ptr = env.allocate_temp(*prevent);
call_func!(func, env, self, ex_ref!(env, choice), ptr.wasm_ptr);
*prevent = *ptr.value();
}
}
fn prevent_opponent_run_away(&self, choice: &TurnChoice, prevent: &mut bool) {
if !self.has_capability(&WebAssemblyScriptCapabilities::PreventOpponentRunAway) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().prevent_opponent_run_away(env) {
let ptr = env.allocate_temp(*prevent);
call_func!(func, env, self, ex_ref!(env, choice), ptr.wasm_ptr);
*prevent = *ptr.value();
}
}
fn on_end_turn(&self) {
if !self.has_capability(&WebAssemblyScriptCapabilities::OnEndTurn) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().on_end_turn(env) {
call_func!(func, env, self);
}
}
fn on_damage(&self, pokemon: &Pokemon, source: DamageSource, old_health: u32, new_health: u32) {
if !self.has_capability(&WebAssemblyScriptCapabilities::OnDamage) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().on_damage(env) {
let r = ex_ref!(env, pokemon);
call_func!(func, env, self, r, source as u8, old_health, new_health);
}
}
fn on_faint(&self, pokemon: &Pokemon, source: DamageSource) {
if !self.has_capability(&WebAssemblyScriptCapabilities::OnFaint) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().on_faint(env) {
call_func!(func, env, self, ex_ref!(env, pokemon), source as u8);
}
}
fn on_switch_in(&self, pokemon: &Pokemon) {
if !self.has_capability(&WebAssemblyScriptCapabilities::OnSwitchIn) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().on_switch_in(env) {
call_func!(func, env, self, ex_ref!(env, pokemon));
}
}
fn on_after_held_item_consume(&self, pokemon: &Pokemon, item: &Item) {
if !self.has_capability(&WebAssemblyScriptCapabilities::OnAfterHeldItemConsume) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().on_after_held_item_consume(env) {
call_func!(func, env, self, ex_ref!(env, pokemon), ex_ref!(env, item));
}
}
fn change_experience_gained(&self, fainted_mon: &Pokemon, winning_mon: &Pokemon, amount: &mut u32) {
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeExperienceGain) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().change_experience_gained(env) {
let ptr = env.allocate_temp(*amount);
let fainted_mon = ex_ref!(env, fainted_mon);
let winning_mon = ex_ref!(env, winning_mon);
call_func!(func, env, self, fainted_mon, winning_mon, ptr.wasm_ptr);
*amount = *ptr.value();
}
}
fn share_experience(&self, fainted_mon: &Pokemon, winning_mon: &Pokemon, shares: &mut bool) {
if !self.has_capability(&WebAssemblyScriptCapabilities::DoesShareExperience) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().share_experience(env) {
let ptr = env.allocate_temp(*shares);
let fainted_mon = ex_ref!(env, fainted_mon);
let winning_mon = ex_ref!(env, winning_mon);
call_func!(func, env, self, fainted_mon, winning_mon, ptr.wasm_ptr);
*shares = *ptr.value();
}
}
fn block_weather(&self, battle: &Battle, blocked: &mut bool) {
if !self.has_capability(&WebAssemblyScriptCapabilities::BlockWeather) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().block_weather(env) {
let ptr = env.allocate_temp(*blocked);
call_func!(func, env, self, ex_ref!(env, battle), ptr.wasm_ptr);
*blocked = *ptr.value();
}
}
fn change_capture_rate_bonus(&self, target: &Pokemon, pokeball: &Item, modifier: &mut u8) {
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeCaptureRate) {
return;
}
let env = &self.environment;
if let Some(func) = env.script_function_cache().change_capture_rate_bonus(env) {
let ptr = env.allocate_temp(*modifier);
let target = ex_ref!(env, target);
let pokeball = ex_ref!(env, pokeball);
call_func!(func, env, self, target, pokeball, ptr.wasm_ptr);
*modifier = *ptr.value();
}
}
fn as_any(&self) -> &dyn Any { fn as_any(&self) -> &dyn Any {
self self
} }

View File

@ -1,14 +1,15 @@
use std::marker::PhantomData;
use std::sync::Arc; use std::sync::Arc;
use parking_lot::RwLock; use parking_lot::RwLock;
use paste::paste; use paste::paste;
use crate::dynamic_data::{DynamicLibrary, TurnChoice}; use crate::dynamic_data::{Battle, DynamicLibrary, ExecutingMove, Pokemon, TurnChoice};
use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef}; use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef};
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnvironmentData; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnvironmentData;
use crate::static_data::EffectParameter; use crate::static_data::{EffectParameter, Item, TypeIdentifier};
use crate::StringKey; use crate::StringKey;
use wasmer::TypedFunction; use wasmer::{FromToNativeWasmType, TypedFunction};
/// A macro to generate the script function cache a bit easier. /// A macro to generate the script function cache a bit easier.
macro_rules! script_function_cache { macro_rules! script_function_cache {
@ -19,7 +20,7 @@ macro_rules! script_function_cache {
) => { ) => {
#[derive(Default)] #[derive(Default)]
#[allow(unused_parens)] #[allow(unused_parens)]
pub struct ScriptFunctionCache { pub(super) struct ScriptFunctionCache {
$( $(
$name: RwLock<Option<TypedFunction<(u32$(, $par_type)*), ()>>>, $name: RwLock<Option<TypedFunction<(u32$(, $par_type)*), ()>>>,
)* )*
@ -60,11 +61,112 @@ macro_rules! script_function_cache {
} }
} }
/// Helper struct to indicate WASM client pointer type. This makes it harder to pass the wrong type
/// to a function by accident.
#[derive(Ord, PartialOrd, Eq, PartialEq)]
pub(super) struct WasmPtr<T> {
/// The memory size
v: u32,
/// Phantom data to store type.
_phantom: PhantomData<T>,
}
impl<T> Clone for WasmPtr<T> {
fn clone(&self) -> Self {
Self {
v: self.v,
_phantom: Default::default(),
}
}
}
impl<T> Copy for WasmPtr<T> {}
impl<T> From<u32> for WasmPtr<T> {
fn from(v: u32) -> Self {
Self {
v,
_phantom: Default::default(),
}
}
}
impl<T> From<WasmPtr<T>> for u32 {
fn from(v: WasmPtr<T>) -> Self {
v.v
}
}
unsafe impl<T> FromToNativeWasmType for WasmPtr<T> {
type Native = i32;
fn from_native(native: Self::Native) -> Self {
Self {
v: native as u32,
_phantom: Default::default(),
}
}
fn to_native(self) -> Self::Native {
self.v as i32
}
}
script_function_cache! { script_function_cache! {
stack() stack()
on_remove() on_remove()
on_initialize(ExternRef<DynamicLibrary>, VecExternRef<EffectParameter>) on_initialize(ExternRef<DynamicLibrary>, VecExternRef<EffectParameter>)
on_before_turn(ExternRef<TurnChoice>) on_before_turn(ExternRef<TurnChoice>)
change_speed(ExternRef<TurnChoice>, u32) change_speed(ExternRef<TurnChoice>, WasmPtr<u32>)
change_priority(ExternRef<TurnChoice>, 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<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<Item>, WasmPtr<u8>)
} }

View File

@ -223,7 +223,7 @@ impl ScriptResolver for WebAssemblyScriptResolver {
owner as *mut u8, owner as *mut u8,
script, script,
capabilities.clone(), capabilities.clone(),
Arc::downgrade(&self.environment_data), self.environment_data.clone(),
script_key.clone(), script_key.clone(),
)))) ))))
} }
@ -324,7 +324,7 @@ impl WebAssemblyEnvironmentData {
} }
/// ///
pub fn script_function_cache(&self) -> &ScriptFunctionCache { pub(super) fn script_function_cache(&self) -> &ScriptFunctionCache {
&self.script_function_cache &self.script_function_cache
} }
@ -361,7 +361,7 @@ impl WebAssemblyEnvironmentData {
/// Allocate a piece of memory inside WASM with a very short lifespan. This is mainly used for /// Allocate a piece of memory inside WASM with a very short lifespan. This is mainly used for
/// rapid allocation of script function parameters, where WASM needs to write to a specific /// rapid allocation of script function parameters, where WASM needs to write to a specific
/// pointer. /// pointer.
pub fn temp_allocate_mem_typed<T>(&self, value: T) -> AllocatedObject<T> { pub(super) fn allocate_temp<T>(&self, value: T) -> AllocatedObject<T> {
self.temp_allocator.read().as_ref().unwrap().alloc::<T>(value) self.temp_allocator.read().as_ref().unwrap().alloc::<T>(value)
} }

View File

@ -1,3 +1,4 @@
use crate::script_implementations::wasm::script_function_cache::WasmPtr;
use std::mem::size_of; use std::mem::size_of;
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
@ -40,7 +41,7 @@ impl TempWasmAllocator {
} }
AllocatedObject::<T> { AllocatedObject::<T> {
ptr, ptr,
wasm_pointer: self.wasm_pointer + ptr_offset as u32, wasm_ptr: (self.wasm_pointer + ptr_offset as u32).into(),
allocator: self as *const TempWasmAllocator, allocator: self as *const TempWasmAllocator,
} }
} }
@ -56,11 +57,11 @@ impl TempWasmAllocator {
} }
/// A value allocated within WASM memory. Once this goes out of scope, it gets deallocated, /// A value allocated within WASM memory. Once this goes out of scope, it gets deallocated,
pub struct AllocatedObject<T> { pub(super) struct AllocatedObject<T> {
/// The pointer in host memory to where the object lives. /// The pointer in host memory to where the object lives.
pub ptr: *mut T, pub ptr: *mut T,
/// The pointer in client memory to where the object lives. /// The pointer in client memory to where the object lives.
pub wasm_pointer: u32, pub wasm_ptr: WasmPtr<T>,
/// A raw pointer to the allocator we use, so we know where to deallocate to. /// A raw pointer to the allocator we use, so we know where to deallocate to.
allocator: *const TempWasmAllocator, allocator: *const TempWasmAllocator,
} }

View File

@ -46,6 +46,7 @@ pub enum BattleItemCategory {
/// An item is an object which the player can pick up, keep in their Bag, and use in some manner /// An item is an object which the player can pick up, keep in their Bag, and use in some manner
#[derive(Debug)] #[derive(Debug)]
#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))]
pub struct Item { pub struct Item {
/// The name of the item. /// The name of the item.
name: StringKey, name: StringKey,