A lot more work on WASM script execution
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2022-09-07 18:01:26 +02:00
parent f9761f61da
commit b1890681a1
102 changed files with 748 additions and 202 deletions

View File

@@ -0,0 +1,71 @@
use crate::dynamic_data::{
Battle, BattleParty, BattleRandom, BattleSide, ChoiceQueue, DynamicLibrary, Pokemon, PokemonParty,
};
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 wasmer::FunctionEnvMut;
register! {
fn battle_get_parties(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
) -> VecExternRef<BattleParty> {
VecExternRef::new(env.data().data().as_ref(), battle.value_func(&env).unwrap().parties())
}
fn battle_get_choice_queue(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
) -> ExternRef<ChoiceQueue> {
let queue = battle.value_func(&env).unwrap().current_turn_queue().read();
if let Some(queue) = queue.as_ref() {
ExternRef::func_new(&env, queue)
} else {
ExternRef::null()
}
}
fn battle_get_library(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
) -> ExternRef<DynamicLibrary> {
ExternRef::func_new(&env, battle.value_func(&env).unwrap().library().as_ref())
}
fn battle_get_sides(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
) -> VecExternRef<BattleSide> {
VecExternRef::new(env.data().data().as_ref(), battle.value_func(&env).unwrap().sides())
}
fn battle_get_random(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
) -> ExternRef<BattleRandom> {
ExternRef::func_new(&env, battle.value_func(&env).unwrap().random())
}
fn battle_find_party_for_pokemon(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
pokemon: ExternRef<Pokemon>
) -> ExternRef<BattleParty> {
let battle = battle.value_func(&env).unwrap();
let pokemon = pokemon.value_func(&env).unwrap();
for party in battle.parties() {
if party.party().has_pokemon(pokemon) {
return ExternRef::func_new(&env, party);
}
}
ExternRef::null()
}
fn battle_party_get_party(
env: FunctionEnvMut<WebAssemblyEnv>,
battle_party: ExternRef<BattleParty>,
) -> ExternRef<PokemonParty> {
ExternRef::func_new(&env, battle_party.value_func(&env).unwrap().party().as_ref())
}
}

View File

@@ -0,0 +1,30 @@
use crate::dynamic_data::BattleRandom;
use crate::script_implementations::wasm::export_registry::register;
use crate::script_implementations::wasm::extern_ref::ExternRef;
use wasmer::FunctionEnvMut;
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
register! {
fn battle_random_get(
env: FunctionEnvMut<WebAssemblyEnv>,
battle_random: ExternRef<BattleRandom>,
) -> i32 {
battle_random.value_func(&env).unwrap().get()
}
fn battle_random_get_max(
env: FunctionEnvMut<WebAssemblyEnv>,
battle_random: ExternRef<BattleRandom>,
max: i32
) -> i32 {
battle_random.value_func(&env).unwrap().get_max(max)
}
fn battle_random_get_between(
env: FunctionEnvMut<WebAssemblyEnv>,
battle_random: ExternRef<BattleRandom>,
min: i32,
max: i32
) -> i32 {
battle_random.value_func(&env).unwrap().get_between(min, max)
}
}

View File

@@ -0,0 +1,123 @@
use crate::dynamic_data::{Battle, BattleSide, 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::{ScriptCategory, StringKey};
use std::ffi::CString;
use wasmer::{FunctionEnvMut, Value};
register! {
fn battleside_has_fled_battle(
env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>,
) -> u8 {
if side.value_func(&env).unwrap().has_fled_battle() { 1 } else { 0 }
}
fn battleside_is_defeated(
env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>,
) -> u8 {
if side.value_func(&env).unwrap().is_defeated() { 1 } else { 0 }
}
fn battleside_get_side_index(
env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>,
) -> u8 {
side.value_func(&env).unwrap().index()
}
fn battleside_get_pokemon_per_side(
env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>,
) -> u8 {
side.value_func(&env).unwrap().pokemon_per_side()
}
fn battleside_get_battle(
env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>,
) -> ExternRef<Battle> {
ExternRef::func_new(&env, side.value_func(&env).unwrap().battle())
}
fn battleside_get_pokemon(
env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>,
index: u32
) -> ExternRef<Pokemon> {
if let Some(Some(p)) = side.value_func(&env).unwrap().pokemon().get(index as usize) {
ExternRef::func_new(&env, p.as_ref())
} else {
ExternRef::null()
}
}
fn battleside_add_volatile_by_name(
env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>,
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();
if let Some(script) = script {
let script = script.get_as::<WebAssemblyScript>();
script.get_wasm_pointer()
} else {
0
}
}
}
fn battleside_add_volatile(
env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>,
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();
if let Some(script) = script {
let script = side.add_volatile_script_with_script(script);
script.unwrap().unwrap().get_as::<WebAssemblyScript>().get_wasm_pointer()
} else {
0
}
}
}
fn battleside_get_volatile(
env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>,
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());
if let Some(script) = script {
let script = script.get_as::<WebAssemblyScript>();
script.get_wasm_pointer()
} else {
0
}
}
}
fn battleside_remove_volatile(
env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>,
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());
}
}
}

View File

@@ -0,0 +1,19 @@
use crate::dynamic_data::{ChoiceQueue, Pokemon};
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 wasmer::FunctionEnvMut;
register! {
fn choice_queue_move_pokemon_choice_next(
env: FunctionEnvMut<WebAssemblyEnv>,
battle_random: ExternRef<ChoiceQueue>,
pokemon: ExternRef<Pokemon>
) -> u8 {
if battle_random.value_func(&env).unwrap().move_pokemon_choice_next(pokemon.value_func(&env).unwrap()) {
1
} else {
0
}
}
}

View File

@@ -0,0 +1,45 @@
use crate::dynamic_data::{ExecutingMove, HitData, LearnedMove, Pokemon};
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::MoveData;
use wasmer::FunctionEnvMut;
register! {
fn executing_move_get_user(
env: FunctionEnvMut<WebAssemblyEnv>,
executing_move: ExternRef<ExecutingMove>,
) -> ExternRef<Pokemon> {
ExternRef::func_new(&env, executing_move.value_func(&env).unwrap().user().as_ref())
}
fn executing_move_get_use_move(
env: FunctionEnvMut<WebAssemblyEnv>,
executing_move: ExternRef<ExecutingMove>,
) -> ExternRef<MoveData> {
ExternRef::func_new(&env, executing_move.value_func(&env).unwrap().use_move().as_ref())
}
fn executing_move_get_chosen_move(
env: FunctionEnvMut<WebAssemblyEnv>,
executing_move: ExternRef<ExecutingMove>,
) -> ExternRef<LearnedMove> {
ExternRef::func_new(&env, executing_move.value_func(&env).unwrap().chosen_move().as_ref())
}
fn executing_move_get_number_of_hits(
env: FunctionEnvMut<WebAssemblyEnv>,
executing_move: ExternRef<ExecutingMove>,
) -> u8 {
executing_move.value_func(&env).unwrap().number_of_hits()
}
fn executing_move_get_hit_data(
env: FunctionEnvMut<WebAssemblyEnv>,
executing_move: ExternRef<ExecutingMove>,
target: ExternRef<Pokemon>,
hit: u8
) -> ExternRef<HitData> {
ExternRef::func_new(&env, executing_move.value_func(&env).unwrap().get_hit_data(target.value_func(&env).unwrap(), hit).unwrap())
}
}

View File

@@ -0,0 +1,14 @@
use crate::dynamic_data::HitData;
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 wasmer::FunctionEnvMut;
register! {
fn hit_data_fail(
env: FunctionEnvMut<WebAssemblyEnv>,
hit: ExternRef<HitData>,
) {
hit.value_func(&env).unwrap().fail()
}
}

View File

@@ -1,31 +1,67 @@
use crate::dynamic_data::DynamicLibrary;
use crate::dynamic_data::{DynamicLibrary, ScriptOwnerData};
use crate::script_implementations::wasm::export_registry::register;
use crate::script_implementations::wasm::extern_ref::ExternRef;
use std::sync::atomic::Ordering;
use wasmer::{FunctionEnv, FunctionEnvMut, Imports, StoreMut};
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
use crate::static_data::StaticData;
mod battle_random;
/// Battle side registration
mod battle_side;
mod choice_queue;
mod executing_move;
/// Learned move registration
mod learned_move;
mod party;
/// Pokemon registration
mod pokemon;
/// Turn choice registration
mod turn_choice;
mod hit_data;
mod battle;
register! {
fn dynamic_library_get_static_data(
env: FunctionEnvMut<WebAssemblyEnv>,
dynamic_lib: ExternRef<DynamicLibrary>,
) -> ExternRef<StaticData> {
ExternRef::func_new(&env, dynamic_lib.value_func(&env).unwrap().static_data())
}
env: FunctionEnvMut<WebAssemblyEnv>,
dynamic_lib: ExternRef<DynamicLibrary>,
) -> ExternRef<StaticData> {
ExternRef::func_new(&env, dynamic_lib.value_func(&env).unwrap().static_data())
}
fn script_get_owner(
env: FunctionEnvMut<WebAssemblyEnv>,
script: u32,
) -> u32 {
unsafe {
let script = env.data().data().get_loaded_script(script);
if let Some(script) = script {
match script.get_owner() {
ScriptOwnerData::Pokemon(p) => env.data().data().get_extern_ref_index(p.load(Ordering::Relaxed).as_ref().unwrap()),
ScriptOwnerData::BattleSide(p) => env.data().data().get_extern_ref_index(p.load(Ordering::Relaxed).as_ref().unwrap()),
ScriptOwnerData::Battle(p) => env.data().data().get_extern_ref_index(p.load(Ordering::Relaxed).as_ref().unwrap()),
ScriptOwnerData::None => 0,
}
} else {
0
}
}
}
manual manual_register
}
/// Additional required manual registration
fn manual_register(imports: &mut Imports, store: &mut StoreMut, env: &FunctionEnv<WebAssemblyEnv>) {
battle::register(imports, store, env);
turn_choice::register(imports, store, env);
pokemon::register(imports, store, env);
learned_move::register(imports, store, env);
battle_side::register(imports, store, env);
battle_random::register(imports, store, env);
choice_queue::register(imports, store, env);
party::register(imports, store, env);
executing_move::register(imports, store, env);
hit_data::register(imports, store, env);
}

View File

@@ -0,0 +1,26 @@
use crate::dynamic_data::{Pokemon, PokemonParty};
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 wasmer::FunctionEnvMut;
register! {
fn party_get_pokemon(
env: FunctionEnvMut<WebAssemblyEnv>,
party: ExternRef<PokemonParty>,
index: u32
) -> ExternRef<Pokemon> {
if let Some(v) = &party.value_func(&env).unwrap().pokemon()[index as usize] {
ExternRef::func_new(&env, v.as_ref())
} else {
ExternRef::null()
}
}
fn party_get_length(
env: FunctionEnvMut<WebAssemblyEnv>,
party: ExternRef<PokemonParty>,
) -> u32 {
party.value_func(&env).unwrap().length() as u32
}
}

View File

@@ -1,11 +1,11 @@
use std::mem::transmute;
use crate::dynamic_data::{DynamicLibrary, Pokemon};
use crate::dynamic_data::{Battle, DynamicLibrary, LearnedMove, Pokemon};
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::StatisticSet;
use crate::static_data::{ClampedStatisticSet, Species};
use crate::static_data::{Item, StatisticSet};
use wasmer::FunctionEnvMut;
register! {
@@ -75,4 +75,70 @@ register! {
pokemon.value_func(&env).unwrap().damage(damage, transmute(source));
}
}
fn pokemon_get_learned_move(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
index: u32
) -> ExternRef<LearnedMove> {
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<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
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<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> ExternRef<Battle> {
if let Some(battle) = pokemon.value_func(&env).unwrap().get_battle() {
ExternRef::func_new(&env, battle)
} else {
ExternRef::null()
}
}
fn pokemon_get_battle_side_index(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> u8 {
if let Some(i) = pokemon.value_func(&env).unwrap().get_battle_index() {
i
} else {
0
}
}
fn pokemon_get_held_item(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> ExternRef<Item> {
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()
}
}
}

View File

@@ -59,4 +59,11 @@ register! {
panic!("Invalid turn choice");
}
fn turn_choice_fail(
env: FunctionEnvMut<WebAssemblyEnv>,
turn_choice: ExternRef<TurnChoice>,
) {
turn_choice.value_func(&env).unwrap().fail();
}
}