use std::mem::transmute; use crate::dynamic_data::{Battle, DynamicLibrary, LearnedMove, Pokemon, VolatileScriptsOwner}; use crate::script_implementations::wasm::export_registry::register; use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::script::WebAssemblyScript; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; use crate::static_data::{ClampedStatisticSet, Species}; use crate::static_data::{Item, StatisticSet}; use crate::{ScriptCategory, StringKey}; use std::ffi::{c_char, CStr}; use wasmer::FunctionEnvMut; register! { fn pokemon_get_library( env: FunctionEnvMut, pokemon: ExternRef, ) -> ExternRef { let lib = pokemon.value_func(&env).unwrap().library(); ExternRef::func_new(&env, lib) } fn pokemon_get_boosted_stats( env: FunctionEnvMut, pokemon: ExternRef, ) -> ExternRef> { let statistic_set = pokemon.value_func(&env).unwrap().boosted_stats(); ExternRef::func_new(&env, statistic_set) } fn pokemon_get_flat_stats( env: FunctionEnvMut, pokemon: ExternRef, ) -> ExternRef> { let statistic_set = pokemon.value_func(&env).unwrap().flat_stats(); ExternRef::func_new(&env, statistic_set) } fn pokemon_get_stat_boosts( env: FunctionEnvMut, pokemon: ExternRef, ) -> ExternRef> { let statistic_set = pokemon.value_func(&env).unwrap().stat_boosts(); ExternRef::func_new(&env, statistic_set) } fn pokemon_get_individual_values( env: FunctionEnvMut, pokemon: ExternRef, ) -> ExternRef> { let statistic_set = pokemon.value_func(&env).unwrap().individual_values(); ExternRef::func_new(&env, statistic_set) } fn pokemon_get_effort_values( env: FunctionEnvMut, pokemon: ExternRef, ) -> ExternRef> { let statistic_set = pokemon.value_func(&env).unwrap().effort_values(); ExternRef::func_new(&env, statistic_set) } fn pokemon_get_species( env: FunctionEnvMut, pokemon: ExternRef, ) -> ExternRef { let species = pokemon.value_func(&env).unwrap().species(); ExternRef::func_new(&env, species) } fn pokemon_get_weight( env: FunctionEnvMut, pokemon: ExternRef, ) -> f32 { pokemon.value_func(&env).unwrap().weight() } fn pokemon_set_weight( env: FunctionEnvMut, pokemon: ExternRef, weight: f32, ) { pokemon.value_func(&env).unwrap().set_weight(weight) } fn pokemon_get_height( env: FunctionEnvMut, pokemon: ExternRef, ) -> f32 { pokemon.value_func(&env).unwrap().height() } fn pokemon_get_gender( env: FunctionEnvMut, pokemon: ExternRef, ) -> u8 { unsafe { transmute(pokemon.value_func(&env).unwrap().gender()) } } fn pokemon_damage( env: FunctionEnvMut, pokemon: ExternRef, damage: u32, source: u8 ) { unsafe{ pokemon.value_func(&env).unwrap().damage(damage, transmute(source)); } } fn pokemon_get_learned_move( env: FunctionEnvMut, pokemon: ExternRef, index: u32 ) -> ExternRef { let read_lock = pokemon.value_func(&env).unwrap().learned_moves().read(); let mv = read_lock.get(index as usize); if let Some(Some(mv)) = mv { ExternRef::func_new(&env, mv) } else{ ExternRef::null() } } fn pokemon_change_stat_boost( env: FunctionEnvMut, pokemon: ExternRef, stat: u8, amount: i8, self_inflicted: u8 ) -> u8 { unsafe{ if pokemon.value_func(&env).unwrap().change_stat_boost(transmute(stat), amount, self_inflicted == 1) { 1 } else { 0 } } } fn pokemon_get_battle( env: FunctionEnvMut, pokemon: ExternRef, ) -> ExternRef { if let Some(battle) = pokemon.value_func(&env).unwrap().get_battle() { ExternRef::func_new(&env, battle) } else { ExternRef::null() } } fn pokemon_get_battle_index( env: FunctionEnvMut, pokemon: ExternRef, ) -> u8 { if let Some(i) = pokemon.value_func(&env).unwrap().get_battle_index() { i } else { 255 } } fn pokemon_get_battle_side_index( env: FunctionEnvMut, pokemon: ExternRef, ) -> u8 { if let Some(i) = pokemon.value_func(&env).unwrap().get_battle_side_index() { i } else { 255 } } fn pokemon_get_held_item( env: FunctionEnvMut, pokemon: ExternRef, ) -> ExternRef { let read_lock = pokemon.value_func(&env).unwrap().held_item().read(); if let Some(item) = read_lock.as_ref() { ExternRef::func_new(&env, item.as_ref()) } else { ExternRef::null() } } fn pokemon_has_held_item( env: FunctionEnvMut, pokemon: ExternRef, name: u32 ) -> u8 { let name : *mut c_char = env.data().data().get_raw_pointer(name); let name = unsafe { CStr::from_ptr(name) }; let key = StringKey::new(name.to_str().unwrap().into()); if pokemon.value_func(&env).unwrap().has_held_item(&key) { 1 } else { 0 } } fn pokemon_heal( env: FunctionEnvMut, pokemon: ExternRef, amount: u32, allow_revive: u8 ) -> u8 { if pokemon.value_func(&env).unwrap().heal(amount, allow_revive == 1) { 1 } else { 0 } } fn pokemon_clear_status( env: FunctionEnvMut, pokemon: ExternRef, ) { pokemon.value_func(&env).unwrap().clear_status() } fn pokemon_add_volatile_by_name( env: FunctionEnvMut, pokemon: ExternRef, name_ptr: u32 ) -> u32 { unsafe { let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr)); let script = pokemon.value_func(&env).unwrap().add_volatile_script(&c_name.as_ref().into()).unwrap(); if let Some(script) = script { let script = script.get_as::(); script.get_wasm_pointer() } else { 0 } } } fn pokemon_add_volatile( env: FunctionEnvMut, pokemon: ExternRef, script_ptr: u32 ) -> u32 { let pokemon = pokemon.value_func(&env).unwrap(); unsafe{ let env = env.data().data(); let name_ptr = env.script_function_cache().script_get_name(&env).unwrap().call(&mut env.store_mut(), script_ptr).unwrap(); let c_name: &CStr = CStr::from_ptr(env.get_raw_pointer(name_ptr)); let script = env.setup_script(script_ptr, ScriptCategory::Pokemon, &c_name.as_ref().into(), pokemon.into()).unwrap(); env.script_function_cache().dealloc_cstring(&env).unwrap().call(&mut env.store_mut(), name_ptr).unwrap(); if let Some(script) = script { let script = pokemon.add_volatile_script_with_script(script); let s = script.as_ref().unwrap().as_ref().unwrap().get_as::(); s.get_wasm_pointer() } else { 0 } } } fn pokemon_has_volatile( env: FunctionEnvMut, pokemon: ExternRef, name_ptr: u32 ) -> u8 { unsafe { let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr)); if pokemon.value_func(&env).unwrap().has_volatile_script(&c_name.as_ref().into()) { 1 } else { 0 } } } fn pokemon_get_volatile( env: FunctionEnvMut, pokemon: ExternRef, name_ptr: u32 ) -> u32 { unsafe { let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr)); let script = pokemon.value_func(&env).unwrap().get_volatile_script(&c_name.as_ref().into()); if let Some(script) = script { let script = script.get_as::(); script.get_wasm_pointer() } else { 0 } } } fn pokemon_remove_volatile( env: FunctionEnvMut, pokemon: ExternRef, name_ptr: u32 ) { unsafe { let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr)); pokemon.value_func(&env).unwrap().remove_volatile_script(&c_name.as_ref().into()); } } }