Registration fixes and improvements.
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
2022-09-16 11:01:37 +02:00
parent b1890681a1
commit 7bcfd92d45
20 changed files with 397 additions and 52 deletions

View File

@@ -4,9 +4,17 @@ use crate::dynamic_data::{
use crate::script_implementations::wasm::export_registry::register;
use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef};
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
use crate::StringKey;
use wasmer::FunctionEnvMut;
register! {
fn battle_get_pokemon_per_side(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
) -> u8 {
battle.value_func(&env).unwrap().pokemon_per_side()
}
fn battle_get_parties(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
@@ -47,6 +55,18 @@ register! {
ExternRef::func_new(&env, battle.value_func(&env).unwrap().random())
}
fn battle_get_weather_name(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
) -> ExternRef<StringKey> {
let weather = battle.value_func(&env).unwrap().weather_name();
if let Some(weather) = weather {
ExternRef::func_new(&env, &weather)
} else {
ExternRef::null()
}
}
fn battle_find_party_for_pokemon(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,

View File

@@ -3,9 +3,9 @@ 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::{ScriptCategory, StringKey};
use std::ffi::CString;
use wasmer::{FunctionEnvMut, Value};
use crate::ScriptCategory;
use std::ffi::CStr;
use wasmer::FunctionEnvMut;
register! {
fn battleside_has_fled_battle(
@@ -61,8 +61,8 @@ register! {
name_ptr: u32
) -> u32 {
unsafe {
let c_name = CString::from_raw(env.data().data().get_raw_pointer(name_ptr));
let script = side.value_func(&env).unwrap().add_volatile_script(&c_name.into()).unwrap();
let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr));
let script = side.value_func(&env).unwrap().add_volatile_script(&c_name.as_ref().into()).unwrap();
if let Some(script) = script {
let script = script.get_as::<WebAssemblyScript>();
script.get_wasm_pointer()
@@ -78,19 +78,33 @@ register! {
script_ptr: u32
) -> u32 {
let side = side.value_func(&env).unwrap();
let name_ptr = env.data().data().exported_functions().get(&StringKey::new("script_get_name")).unwrap().call(&mut env.data().data().store_mut(), &[Value::I32(script_ptr as i32)]).unwrap().get(0).unwrap().i32().unwrap() as u32;
unsafe{
let name_ptr: CString = CString::from_raw(env.data().data().get_raw_pointer(name_ptr));
let script = env.data().data().setup_script(script_ptr, ScriptCategory::Side, &name_ptr.into(), side.into()).unwrap();
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::Side, &c_name.as_ref().into(), side.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 = side.add_volatile_script_with_script(script);
script.unwrap().unwrap().get_as::<WebAssemblyScript>().get_wasm_pointer()
let s = script.as_ref().unwrap().as_ref().unwrap().get_as::<WebAssemblyScript>();
s.get_wasm_pointer()
} else {
0
}
}
}
fn battleside_has_volatile(
env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>,
name_ptr: u32
) -> u8 {
unsafe {
let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr));
if side.value_func(&env).unwrap().has_volatile_script(&c_name.as_ref().into()) { 1 } else { 0 }
}
}
fn battleside_get_volatile(
env: FunctionEnvMut<WebAssemblyEnv>,
@@ -98,8 +112,8 @@ register! {
name_ptr: u32
) -> u32 {
unsafe {
let c_name = CString::from_raw(env.data().data().get_raw_pointer(name_ptr));
let script = side.value_func(&env).unwrap().get_volatile_script(&c_name.into());
let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr));
let script = side.value_func(&env).unwrap().get_volatile_script(&c_name.as_ref().into());
if let Some(script) = script {
let script = script.get_as::<WebAssemblyScript>();
script.get_wasm_pointer()
@@ -115,8 +129,8 @@ register! {
name_ptr: u32
) {
unsafe {
let c_name = CString::from_raw(env.data().data().get_raw_pointer(name_ptr));
side.value_func(&env).unwrap().remove_volatile_script(&c_name.into());
let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr));
side.value_func(&env).unwrap().remove_volatile_script(&c_name.as_ref().into());
}
}

View File

@@ -5,6 +5,20 @@ use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
use wasmer::FunctionEnvMut;
register! {
fn hit_data_get_damage(
env: FunctionEnvMut<WebAssemblyEnv>,
hit: ExternRef<HitData>,
) -> u32 {
hit.value_func(&env).unwrap().damage()
}
fn hit_data_is_critical(
env: FunctionEnvMut<WebAssemblyEnv>,
hit: ExternRef<HitData>,
) -> u8 {
if hit.value_func(&env).unwrap().is_critical() { 1 } else { 0 }
}
fn hit_data_fail(
env: FunctionEnvMut<WebAssemblyEnv>,
hit: ExternRef<HitData>,

View File

View File

@@ -1,11 +1,14 @@
use std::mem::transmute;
use crate::dynamic_data::{Battle, DynamicLibrary, LearnedMove, Pokemon};
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! {
@@ -65,6 +68,38 @@ register! {
ExternRef::func_new(&env, species)
}
fn pokemon_get_weight(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> f32 {
pokemon.value_func(&env).unwrap().weight()
}
fn pokemon_set_weight(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
weight: f32,
) {
pokemon.value_func(&env).unwrap().set_weight(weight)
}
fn pokemon_get_height(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> f32 {
pokemon.value_func(&env).unwrap().height()
}
fn pokemon_get_gender(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> u8 {
unsafe {
transmute(pokemon.value_func(&env).unwrap().gender())
}
}
fn pokemon_damage(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
@@ -118,14 +153,25 @@ register! {
}
}
fn pokemon_get_battle_side_index(
fn pokemon_get_battle_index(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> u8 {
if let Some(i) = pokemon.value_func(&env).unwrap().get_battle_index() {
i
} else {
0
255
}
}
fn pokemon_get_battle_side_index(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> u8 {
if let Some(i) = pokemon.value_func(&env).unwrap().get_battle_side_index() {
i
} else {
255
}
}
@@ -141,4 +187,110 @@ register! {
}
}
fn pokemon_has_held_item(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
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().clone());
if pokemon.value_func(&env).unwrap().has_held_item(&key) { 1 } else { 0 }
}
fn pokemon_heal(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
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<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) {
pokemon.value_func(&env).unwrap().clear_status()
}
fn pokemon_add_volatile_by_name(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
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::<WebAssemblyScript>();
script.get_wasm_pointer()
} else {
0
}
}
}
fn pokemon_add_volatile(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
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::<WebAssemblyScript>();
s.get_wasm_pointer()
} else {
0
}
}
}
fn pokemon_has_volatile(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
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<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
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::<WebAssemblyScript>();
script.get_wasm_pointer()
} else {
0
}
}
}
fn pokemon_remove_volatile(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
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());
}
}
}

View File

@@ -1,4 +1,4 @@
use std::ffi::CString;
use std::ffi::{c_char, CStr, CString};
use std::mem::{align_of, forget};
use wasmer::{FunctionEnv, FunctionEnvMut, Imports, StoreMut};
@@ -80,34 +80,29 @@ pub(crate) fn register_webassembly_funcs(
}
/// Logging function for WASM.
fn _print(env: FunctionEnvMut<WebAssemblyEnv>, p: u32, len: u32) {
fn _print(env: FunctionEnvMut<WebAssemblyEnv>, p: u32) {
unsafe {
let mem: *mut u8 = env.data().data().memory().offset(p as isize);
let s = String::from_raw_parts(mem, len as usize, len as usize);
println!("{}", s);
forget(s);
let mem: *mut c_char = env.data().data().get_raw_pointer(p);
let s = CStr::from_ptr(mem);
println!("{}", s.to_str().unwrap());
}
}
/// Triggers when WASM panics.
#[track_caller]
fn _error(
env: FunctionEnvMut<WebAssemblyEnv>,
message: u32,
message_len: u32,
file: u32,
file_len: u32,
line: u32,
position: u32,
) {
fn _error(env: FunctionEnvMut<WebAssemblyEnv>, message: u32, file: u32, line: u32, position: u32) {
unsafe {
let mem: *mut u8 = env.data().data().memory().offset(message as isize);
let message_str = String::from_raw_parts(mem, message_len as usize, message_len as usize);
let mem: *mut u8 = env.data().data().memory().offset(file as isize);
let file_str = String::from_raw_parts(mem, file_len as usize, file_len as usize);
let mem: *const c_char = env.data().data().get_raw_pointer(message);
let message_str = CStr::from_ptr(mem);
let mem: *const c_char = env.data().data().get_raw_pointer(file);
let file_str = CStr::from_ptr(mem);
panic!(
"Error: {} in file {}, line: {}:{}",
message_str, file_str, line, position
"WASM Error: {} in file {}, line: {}:{}",
message_str.to_str().unwrap(),
file_str.to_str().unwrap(),
line,
position
);
}
}

View File

View File

@@ -1,10 +1,13 @@
use std::mem::transmute;
use wasmer::{FunctionEnv, FunctionEnvMut, Imports, StoreMut};
use crate::defines::LevelInt;
use crate::script_implementations::wasm::export_registry::register;
use crate::script_implementations::wasm::extern_ref::ExternRef;
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
use crate::static_data::{ItemLibrary, LibrarySettings, MoveLibrary, SpeciesLibrary, StaticData, TypeLibrary};
use crate::static_data::{
ItemLibrary, LibrarySettings, MoveLibrary, SpeciesLibrary, StaticData, StatisticSet, TypeLibrary,
};
mod item;
/// Moves data registration
@@ -43,6 +46,12 @@ register! {
data_library.value_func(&env).unwrap().maximum_level()
}
fn statistic_set_get(env: FunctionEnvMut<WebAssemblyEnv>, statistics_set: ExternRef<StatisticSet<u32>>, stat: u8) -> i64 {
unsafe {
statistics_set.value_func(&env).unwrap().get_stat(transmute(stat)) as i64
}
}
manual manual_registration
}

View File

@@ -21,6 +21,8 @@ macro_rules! script_function_cache {
#[derive(Default)]
#[allow(unused_parens)]
pub(super) struct ScriptFunctionCache {
script_get_name: RwLock<Option<TypedFunction<(u32), u32>>>,
dealloc_cstring: RwLock<Option<TypedFunction<(u32), ()>>>,
$(
$name: RwLock<Option<TypedFunction<(u32$(, $par_type)*), ()>>>,
)*
@@ -168,5 +170,42 @@ script_function_cache! {
share_experience(ExternRef<Pokemon>, ExternRef<Pokemon>, WasmPtr<bool>)
block_weather(ExternRef<Battle>, WasmPtr<bool>)
change_capture_rate_bonus(ExternRef<Pokemon>, ExternRef<Item>, WasmPtr<u8>)
}
impl ScriptFunctionCache {
pub(crate) fn script_get_name(&self, env: &Arc<WebAssemblyEnvironmentData>) -> Option<TypedFunction<u32, u32>> {
{
let read_lock = self.script_get_name.read();
if let Some(f) = read_lock.as_ref() {
return Some(f.clone());
}
}
{
let exported = env.exported_functions();
let f = exported.get::<StringKey>(&"script_get_name".into());
if let Some(f) = f {
let func: TypedFunction<u32, u32> = f.typed(&env.store_ref()).unwrap();
let _ = self.script_get_name.write().insert(func);
}
}
self.script_get_name.read().as_ref().cloned()
}
pub(crate) fn dealloc_cstring(&self, env: &Arc<WebAssemblyEnvironmentData>) -> Option<TypedFunction<u32, ()>> {
{
let read_lock = self.dealloc_cstring.read();
if let Some(f) = read_lock.as_ref() {
return Some(f.clone());
}
}
{
let exported = env.exported_functions();
let f = exported.get::<StringKey>(&"dealloc_cstring".into());
if let Some(f) = f {
let func: TypedFunction<u32, ()> = f.typed(&env.store_ref()).unwrap();
let _ = self.dealloc_cstring.write().insert(func);
}
}
self.dealloc_cstring.read().as_ref().cloned()
}
}