PkmnLib_rs/src/script_implementations/wasm/export_registry/dynamic_data/pokemon.rs

512 lines
17 KiB
Rust
Executable File

use std::mem::transmute;
use crate::defines::LevelInt;
use crate::dynamic_data::{Battle, DynamicLibrary, LearnedMove, Pokemon, VolatileScriptsOwner};
use crate::script_implementations::wasm::export_registry::{register, WasmResult};
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::{Ability, ClampedStatisticSet, Form, Nature, Species};
use crate::static_data::{Item, StatisticSet};
use crate::{ScriptCategory, VecExt};
use anyhow::anyhow;
use std::ffi::{c_char, CStr, CString};
use wasmer::FunctionEnvMut;
register! {
fn pokemon_get_library(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<ExternRef<dyn DynamicLibrary>> {
let lib = pokemon.value_func(&env)?.library().clone();
Ok(ExternRef::func_new(&env, &lib)).into()
}
fn pokemon_get_boosted_stats(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<ExternRef<StatisticSet<u32>>> {
let statistic_set = pokemon.value_func(&env)?.boosted_stats();
Ok(ExternRef::func_new(&env, statistic_set)).into()
}
fn pokemon_get_flat_stats(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<ExternRef<StatisticSet<u32>>> {
let statistic_set = pokemon.value_func(&env)?.flat_stats();
Ok(ExternRef::func_new(&env, statistic_set)).into()
}
fn pokemon_get_stat_boosts(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<ExternRef<ClampedStatisticSet<i8, -6, 6>>> {
let statistic_set = pokemon.value_func(&env)?.stat_boosts();
Ok(ExternRef::func_new(&env, statistic_set)).into()
}
fn pokemon_get_individual_values(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<ExternRef<ClampedStatisticSet<u8, 0, 31>>> {
let statistic_set = pokemon.value_func(&env)?.individual_values();
Ok(ExternRef::func_new(&env, statistic_set)).into()
}
fn pokemon_get_effort_values(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<ExternRef<ClampedStatisticSet<u8, 0, 252>>> {
let statistic_set = pokemon.value_func(&env)?.effort_values();
Ok(ExternRef::func_new(&env, statistic_set)).into()
}
fn pokemon_get_species(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<ExternRef<dyn Species>> {
let species = pokemon.value_func(&env)?.species();
Ok(ExternRef::func_new(&env, &species)).into()
}
fn pokemon_get_weight(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<f32> {
Ok(pokemon.value_func(&env)?.weight()).into()
}
fn pokemon_set_weight(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
weight: f32,
) -> WasmResult<()> {
pokemon.value_func(&env)?.set_weight(weight);
Ok(()).into()
}
fn pokemon_get_height(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<f32> {
Ok(pokemon.value_func(&env)?.height()).into()
}
fn pokemon_get_gender(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<u8> {
unsafe {
Ok(transmute(pokemon.value_func(&env)?.gender())).into()
}
}
fn pokemon_damage(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
damage: u32,
source: u8
) -> WasmResult<()> {
unsafe{
pokemon.value_func(&env)?.damage(damage, transmute(source))?;
WasmResult::ok(())
}
}
fn pokemon_get_learned_move(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
index: u32
) -> WasmResult<ExternRef<LearnedMove>> {
let read_lock = pokemon.value_func(&env)?.learned_moves().read();
let mv = read_lock.get(index as usize);
Ok(if let Some(Some(mv)) = mv {
ExternRef::func_new(&env, mv)
}
else{
ExternRef::null()
}).into()
}
fn pokemon_change_stat_boost(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
stat: u8,
amount: i8,
self_inflicted: u8
) -> WasmResult<u8> {
unsafe{
Ok(u8::from(pokemon.value_func(&env)?.change_stat_boost(transmute(stat), amount, self_inflicted == 1)?)).into()
}
}
fn pokemon_get_battle(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<ExternRef<Battle>> {
Ok(if let Some(battle) = pokemon.value_func(&env)?.get_battle() {
ExternRef::func_new(&env, battle)
} else {
ExternRef::null()
}).into()
}
fn pokemon_get_battle_index(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<u8> {
Ok(if let Some(i) = pokemon.value_func(&env)?.get_battle_index() {
i
} else {
255
}).into()
}
fn pokemon_get_battle_side_index(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<u8> {
Ok(if let Some(i) = pokemon.value_func(&env)?.get_battle_side_index() {
i
} else {
255
}).into()
}
fn pokemon_get_held_item(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<ExternRef<dyn Item>> {
let read_lock = pokemon.value_func(&env)?.held_item().read();
Ok(if let Some(item) = read_lock.as_ref() {
ExternRef::func_new(&env, item.as_ref())
} else {
ExternRef::null()
}).into()
}
fn pokemon_has_held_item(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
name: u32
) -> WasmResult<u8> {
let name : *mut c_char = env.data().data().get_raw_pointer(name);
let name = unsafe { CStr::from_ptr(name) };
Ok(u8::from(pokemon.value_func(&env)?.has_held_item(&name.into()))).into()
}
fn pokemon_heal(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
amount: u32,
allow_revive: u8
) -> WasmResult<u8> {
Ok(u8::from(pokemon.value_func(&env)?.heal(amount, allow_revive == 1))).into()
}
fn pokemon_clear_status(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<()> {
pokemon.value_func(&env)?.clear_status();
WasmResult::ok(())
}
fn pokemon_get_active_ability(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<ExternRef<dyn Ability>> {
Ok(ExternRef::func_new(&env, &pokemon.value_func(&env)?.active_ability())).into()
}
fn pokemon_get_real_ability(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<(u8, u8)> {
let index = &pokemon.value_func(&env)?.real_ability();
WasmResult::ok((if index.hidden { 1 } else { 0 }, index.index))
}
fn pokemon_get_is_ability_overriden(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<u8> {
Ok(if pokemon.value_func(&env)?.is_ability_overriden() { 1 } else { 0 }).into()
}
fn pokemon_get_allowed_experience_gain(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<u8> {
Ok(if pokemon.value_func(&env)?.allowed_experience_gain() { 1 } else { 0 }).into()
}
fn pokemon_get_is_usable(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<u8> {
Ok(if pokemon.value_func(&env)?.is_usable() { 1 } else { 0 }).into()
}
fn pokemon_set_held_item(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
item: ExternRef<dyn Item>
) -> WasmResult<ExternRef<dyn Item>> {
let item = item.value_func_arc(&env)?;
let old_item = pokemon.value_func(&env)?.set_held_item(&item);
Ok(if let Some(old_item) = old_item {
ExternRef::func_new(&env, &old_item)
} else {
ExternRef::null()
}).into()
}
fn pokemon_remove_held_item(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<ExternRef<dyn Item>> {
let old_item = pokemon.value_func(&env)?.remove_held_item();
Ok(if let Some(old_item) = old_item {
ExternRef::func_new(&env, &old_item)
} else {
ExternRef::null()
}).into()
}
fn pokemon_consume_held_item(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<u8> {
Ok(if pokemon.value_func(&env)?.consume_held_item()? { 1 } else { 0 }).into()
}
fn pokemon_get_types_length(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>
) -> WasmResult<u32> {
Ok(pokemon.value_func(&env)?.types().len() as u32).into()
}
fn pokemon_get_type(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
index: u32
) -> WasmResult<u8> {
Ok((*pokemon.value_func(&env)?.types().get_res(index as usize)?).into()).into()
}
fn pokemon_has_type(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
t: u8
) -> WasmResult<u8> {
Ok(if pokemon.value_func(&env)?.types().contains(&t.into()) { 1 } else { 0 }).into()
}
fn pokemon_change_species(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
species: ExternRef<dyn Species>,
form: ExternRef<dyn Form>,
) -> WasmResult<()> {
pokemon.value_func(&env)?.change_species(
species.value_func_arc(&env)?,
form.value_func_arc(&env)?,
)?;
WasmResult::ok(())
}
fn pokemon_change_form(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
form: ExternRef<dyn Form>,
) -> WasmResult<()> {
pokemon.value_func(&env)?.change_form(
&form.value_func_arc(&env)?,
)?;
WasmResult::ok(())
}
fn pokemon_get_current_health(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<u32> {
Ok(pokemon.value_func(&env)?.current_health()).into()
}
fn pokemon_get_nature(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<ExternRef<dyn Nature>> {
Ok(ExternRef::func_new(&env, pokemon.value_func(&env)?.nature())).into()
}
fn pokemon_get_form(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<ExternRef<dyn Form>> {
Ok(ExternRef::func_new(&env, &pokemon.value_func(&env)?.form())).into()
}
fn pokemon_get_display_species(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<ExternRef<dyn Species>> {
Ok(ExternRef::func_new(&env, &pokemon.value_func(&env)?.display_species())).into()
}
fn pokemon_get_display_form(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<ExternRef<dyn Form>> {
Ok(ExternRef::func_new(&env, &pokemon.value_func(&env)?.display_form())).into()
}
fn pokemon_get_level(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<LevelInt> {
Ok(pokemon.value_func(&env)?.level()).into()
}
fn pokemon_get_experience(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<u32> {
Ok(pokemon.value_func(&env)?.experience()).into()
}
fn pokemon_get_unique_identifier(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<u32> {
Ok(pokemon.value_func(&env)?.unique_identifier()).into()
}
fn pokemon_get_coloring(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<u8> {
Ok(pokemon.value_func(&env)?.coloring()).into()
}
fn pokemon_get_nickname(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<u32> {
let pokemon = pokemon.value_func(&env)?;
let nickname = pokemon.nickname();
if let Some(nickname) = nickname {
let nickname: CString = match CString::new(nickname.as_str()) {
Ok(nickname) => nickname,
Err(e) => return WasmResult::err(e.into()),
};
env.data().data().copy_value_vec_to_wasm(nickname.as_bytes()).into()
} else {
Ok(0).into()
}
}
fn pokemon_add_volatile_by_name(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
name_ptr: u32
) -> WasmResult<u32> {
unsafe {
let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr));
let script = pokemon.value_func(&env)?.add_volatile_script(&c_name.as_ref().into())?;
if let Some(script) = script {
let script = script.get_as::<WebAssemblyScript>()?;
Ok(script.get_wasm_pointer()).into()
} else {
Ok(0).into()
}
}
}
fn pokemon_add_volatile(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
script_ptr: u32
) -> WasmResult<u32> {
let pokemon : &Pokemon = pokemon.value_func(&env)?;
unsafe{
let env = env.data().data();
let name_ptr = match env.script_function_cache().script_get_name(&env)?.call(&mut env.store_mut(), script_ptr){
Ok(name_ptr) => name_ptr,
Err(e) => return WasmResult::err(e.into())
};
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())?;
env.script_function_cache().dealloc_cstring(&env, name_ptr)?;
if let Some(script) = script {
let script = pokemon.add_volatile_script_with_script(script)?;
let s = script.as_ref().ok_or(anyhow!("Unable to get script"))?.get_as::<WebAssemblyScript>()?;
WasmResult::ok(s.get_wasm_pointer())
} else {
WasmResult::ok(0)
}
}
}
fn pokemon_has_volatile(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
name_ptr: u32
) -> WasmResult<u8> {
unsafe {
let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr));
Ok(u8::from(pokemon.value_func(&env)?.has_volatile_script(&c_name.as_ref().into()))).into()
}
}
fn pokemon_get_volatile(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
name_ptr: u32
) -> WasmResult<u32> {
unsafe {
let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr));
let script = pokemon.value_func(&env)?.get_volatile_script(&c_name.as_ref().into());
Ok(if let Some(script) = script {
let script = script.get_as::<WebAssemblyScript>()?;
script.get_wasm_pointer()
} else {
0
}).into()
}
}
fn pokemon_remove_volatile(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
name_ptr: u32
) -> WasmResult<()> {
unsafe {
let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr));
pokemon.value_func(&env)?.remove_volatile_script(&c_name.as_ref().into())?;
WasmResult::ok(())
}
}
fn pokemon_get_ability_script(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> WasmResult<u32> {
let pokemon = pokemon.value_func(&env)?;
let script = pokemon.ability_script();
if script.is_any() {
return Ok(script.get_as::<WebAssemblyScript>()?.get_wasm_pointer()).into();
}
WasmResult::ok(0)
}
}