Adds a large amount of the WASM interface
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Deukhoofd 2023-01-14 13:25:21 +01:00
parent 7511f56b1a
commit ca54820483
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
21 changed files with 777 additions and 9 deletions

View File

@ -405,3 +405,10 @@ pub enum BattleResult {
/// The battle has a winner, with the inner value being the index of the side that has won. /// The battle has a winner, with the inner value being the index of the side that has won.
Conclusive(u8), Conclusive(u8),
} }
impl BattleResult {
/// Whether or not the battle has a winner.
pub fn is_conclusive(&self) -> bool {
matches!(self, Self::Conclusive(_))
}
}

View File

@ -1,5 +1,5 @@
use crate::dynamic_data::{ use crate::dynamic_data::{
Battle, BattleParty, BattleRandom, BattleSide, ChoiceQueue, DynamicLibrary, Pokemon, PokemonParty, Battle, BattleParty, BattleRandom, BattleResult, BattleSide, ChoiceQueue, DynamicLibrary, Pokemon, PokemonParty,
}; };
use crate::script_implementations::wasm::export_registry::register; use crate::script_implementations::wasm::export_registry::register;
use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef}; use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef};
@ -82,6 +82,66 @@ register! {
ExternRef::null() ExternRef::null()
} }
fn battle_get_pokemon(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
side: u8, index: u8
) -> ExternRef<Pokemon> {
let battle = battle.value_func(&env).unwrap();
let pokemon = battle.get_pokemon(side, index);
if let Some(pokemon) = pokemon {
ExternRef::func_new(&env, &pokemon)
} else {
ExternRef::null()
}
}
fn battle_get_can_flee(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
) -> u8 {
if battle.value_func(&env).unwrap().can_flee() { 1 } else { 0 }
}
fn battle_get_number_of_sides(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
) -> u8 {
battle.value_func(&env).unwrap().number_of_sides()
}
fn battle_get_has_ended(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
) -> u8 {
if battle.value_func(&env).unwrap().has_ended() { 1 } else { 0 }
}
fn battle_get_has_ended_conclusively(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
) -> u8 {
if battle.value_func(&env).unwrap().result().is_conclusive() { 1 } else { 0 }
}
fn battle_get_winning_side(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
) -> u8 {
if let BattleResult::Conclusive(result) = battle.value_func(&env).unwrap().result() {
result
} else {
0
}
}
fn battle_get_current_turn(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
) -> u32 {
battle.value_func(&env).unwrap().current_turn()
}
fn battle_party_get_party( fn battle_party_get_party(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
battle_party: ExternRef<BattleParty>, battle_party: ExternRef<BattleParty>,

View File

@ -55,6 +55,20 @@ register! {
} }
} }
fn battle_side_get_has_fled_battle(
env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>,
) -> u8 {
if side.value_func(&env).unwrap().has_fled_battle() { 1 } else { 0 }
}
fn battle_side_get_is_defeated(
env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>,
) -> u8 {
if side.value_func(&env).unwrap().is_defeated() { 1 } else { 0 }
}
fn battleside_add_volatile_by_name( fn battleside_add_volatile_by_name(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>, side: ExternRef<BattleSide>,

View File

@ -1,6 +1,7 @@
use crate::dynamic_data::{ExecutingMove, HitData, LearnedMove, Pokemon}; use crate::dynamic_data::{ExecutingMove, HitData, LearnedMove, Pokemon};
use crate::script_implementations::wasm::export_registry::register; use crate::script_implementations::wasm::export_registry::register;
use crate::script_implementations::wasm::extern_ref::ExternRef; 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::script_implementations::wasm::script_resolver::WebAssemblyEnv;
use crate::static_data::MoveData; use crate::static_data::MoveData;
use wasmer::FunctionEnvMut; use wasmer::FunctionEnvMut;
@ -42,4 +43,38 @@ register! {
) -> ExternRef<HitData> { ) -> ExternRef<HitData> {
ExternRef::func_new(&env, executing_move.value_func(&env).unwrap().get_hit_data(target.value_func(&env).unwrap(), hit).unwrap()) ExternRef::func_new(&env, executing_move.value_func(&env).unwrap().get_hit_data(target.value_func(&env).unwrap(), hit).unwrap())
} }
fn executing_move_get_number_of_targets(
env: FunctionEnvMut<WebAssemblyEnv>,
executing_move: ExternRef<ExecutingMove>,
) -> u32 {
executing_move.value_func(&env).unwrap().target_count() as u32
}
fn executing_move_is_pokemon_target(
env: FunctionEnvMut<WebAssemblyEnv>,
executing_move: ExternRef<ExecutingMove>,
pokemon: ExternRef<Pokemon>
) -> u8 {
let pokemon = pokemon.value_func_arc(&env).unwrap();
if executing_move.value_func(&env).unwrap().is_pokemon_target(&pokemon) { 1 } else { 0 }
}
fn executing_move_get_script(
env: FunctionEnvMut<WebAssemblyEnv>,
executing_move: ExternRef<ExecutingMove>,
) -> (u32 , u32) {
let executing_move = executing_move.value_func(&env).unwrap();
if let Some(script) = executing_move.script().get() {
let read_lock = script.read();
if let Some(script) = read_lock.as_ref() {
let s = script.as_any().downcast_ref::<WebAssemblyScript>().unwrap().get_wasm_pointer();
return (s, s + 4)
}
}
(0, 0)
}
} }

View File

@ -25,4 +25,58 @@ register! {
) { ) {
hit.value_func(&env).unwrap().fail() hit.value_func(&env).unwrap().fail()
} }
fn hit_data_get_base_power(
env: FunctionEnvMut<WebAssemblyEnv>,
hit: ExternRef<HitData>,
) -> u8 {
hit.value_func(&env).unwrap().base_power()
}
fn hit_data_get_effectiveness(
env: FunctionEnvMut<WebAssemblyEnv>,
hit: ExternRef<HitData>,
) -> f32 {
hit.value_func(&env).unwrap().effectiveness()
}
fn hit_data_get_move_type(
env: FunctionEnvMut<WebAssemblyEnv>,
hit: ExternRef<HitData>,
) -> u8 {
hit.value_func(&env).unwrap().move_type().into()
}
fn hit_data_set_critical(
env: FunctionEnvMut<WebAssemblyEnv>,
hit: ExternRef<HitData>,
value: u8
) {
hit.value_func(&env).unwrap().set_critical(value == 1)
}
fn hit_data_set_effectiveness(
env: FunctionEnvMut<WebAssemblyEnv>,
hit: ExternRef<HitData>,
effectiveness: f32
) {
hit.value_func(&env).unwrap().set_effectiveness(effectiveness)
}
fn hit_data_set_damage(
env: FunctionEnvMut<WebAssemblyEnv>,
hit: ExternRef<HitData>,
damage: u32
) {
hit.value_func(&env).unwrap().set_damage(damage)
}
fn hit_data_set_move_type(
env: FunctionEnvMut<WebAssemblyEnv>,
hit: ExternRef<HitData>,
move_type: u8
) {
hit.value_func(&env).unwrap().set_move_type(move_type.into())
}
} }

View File

@ -23,4 +23,20 @@ register! {
) -> ExternRef<dyn MoveData> { ) -> ExternRef<dyn MoveData> {
ExternRef::func_new(&env, turn_choice.value_func(&env).unwrap().move_data()) ExternRef::func_new(&env, turn_choice.value_func(&env).unwrap().move_data())
} }
fn learned_move_restore_all_uses(
env: FunctionEnvMut<WebAssemblyEnv>,
turn_choice: ExternRef<LearnedMove>,
) {
turn_choice.value_func(&env).unwrap().restore_all_uses();
}
fn learned_move_restore_uses(
env: FunctionEnvMut<WebAssemblyEnv>,
turn_choice: ExternRef<LearnedMove>,
amount: u8,
) {
turn_choice.value_func(&env).unwrap().restore_uses(amount);
}
} }

View File

@ -55,6 +55,24 @@ register! {
} }
} }
fn script_get_owner_kind(
env: FunctionEnvMut<WebAssemblyEnv>,
script: u32,
) -> u8 {
let script = env.data().data().get_loaded_script(script);
if let Some(script) = script {
match script.get_owner() {
ScriptOwnerData::Pokemon(_) => 0,
ScriptOwnerData::BattleSide(_) => 1,
ScriptOwnerData::Battle(_) => 2,
ScriptOwnerData::None => 3,
}
} else {
0
}
}
manual manual_register manual manual_register
} }

View File

@ -1,14 +1,15 @@
use std::mem::transmute; use std::mem::transmute;
use crate::defines::LevelInt;
use crate::dynamic_data::{Battle, DynamicLibrary, LearnedMove, Pokemon, VolatileScriptsOwner}; use crate::dynamic_data::{Battle, DynamicLibrary, LearnedMove, Pokemon, VolatileScriptsOwner};
use crate::script_implementations::wasm::export_registry::register; use crate::script_implementations::wasm::export_registry::register;
use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::extern_ref::ExternRef;
use crate::script_implementations::wasm::script::WebAssemblyScript; use crate::script_implementations::wasm::script::WebAssemblyScript;
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
use crate::static_data::{ClampedStatisticSet, Species}; use crate::static_data::{Ability, ClampedStatisticSet, Form, Nature, Species};
use crate::static_data::{Item, StatisticSet}; use crate::static_data::{Item, StatisticSet};
use crate::ScriptCategory; use crate::ScriptCategory;
use std::ffi::{c_char, CStr}; use std::ffi::{c_char, CStr, CString};
use wasmer::FunctionEnvMut; use wasmer::FunctionEnvMut;
register! { register! {
@ -209,6 +210,200 @@ register! {
pokemon.value_func(&env).unwrap().clear_status() pokemon.value_func(&env).unwrap().clear_status()
} }
fn pokemon_get_active_ability(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> ExternRef<dyn Ability> {
ExternRef::func_new(&env, &pokemon.value_func(&env).unwrap().active_ability())
}
fn pokemon_get_real_ability(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> (u8, u8) {
let index = &pokemon.value_func(&env).unwrap().real_ability();
(if index.hidden { 1 } else { 0 }, index.index)
}
fn pokemon_get_is_ability_overriden(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> u8 {
if pokemon.value_func(&env).unwrap().is_ability_overriden() { 1 } else { 0 }
}
fn pokemon_get_allowed_experience_gain(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> u8 {
if pokemon.value_func(&env).unwrap().allowed_experience_gain() { 1 } else { 0 }
}
fn pokemon_get_is_usable(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> u8 {
if pokemon.value_func(&env).unwrap().is_usable() { 1 } else { 0 }
}
fn pokemon_set_held_item(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
item: ExternRef<dyn Item>
) -> ExternRef<dyn Item> {
let item = item.value_func_arc(&env).unwrap();
let old_item = pokemon.value_func(&env).unwrap().set_held_item(&item);
if let Some(old_item) = old_item {
ExternRef::func_new(&env, &old_item)
} else {
ExternRef::null()
}
}
fn pokemon_remove_held_item(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> ExternRef<dyn Item> {
let old_item = pokemon.value_func(&env).unwrap().remove_held_item();
if let Some(old_item) = old_item {
ExternRef::func_new(&env, &old_item)
} else {
ExternRef::null()
}
}
fn pokemon_consume_held_item(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> u8 {
if pokemon.value_func(&env).unwrap().consume_held_item() { 1 } else { 0 }
}
fn pokemon_get_types_length(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>
) -> u32 {
pokemon.value_func(&env).unwrap().types().len() as u32
}
fn pokemon_get_type(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
index: u32
) -> u8 {
(*pokemon.value_func(&env).unwrap().types().get(index as usize).unwrap()).into()
}
fn pokemon_has_type(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
t: u8
) -> u8 {
if pokemon.value_func(&env).unwrap().types().contains(&t.into()) { 1 } else { 0 }
}
fn pokemon_change_species(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
species: ExternRef<dyn Species>,
form: ExternRef<dyn Form>,
) {
pokemon.value_func(&env).unwrap().change_species(
species.value_func_arc(&env).unwrap(),
form.value_func_arc(&env).unwrap(),
);
}
fn pokemon_change_form(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
form: ExternRef<dyn Form>,
) {
pokemon.value_func(&env).unwrap().change_form(
&form.value_func_arc(&env).unwrap(),
);
}
fn pokemon_get_current_health(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> u32 {
pokemon.value_func(&env).unwrap().current_health()
}
fn pokemon_get_nature(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> ExternRef<dyn Nature> {
ExternRef::func_new(&env, pokemon.value_func(&env).unwrap().nature())
}
fn pokemon_get_form(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> ExternRef<dyn Form> {
ExternRef::func_new(&env, &pokemon.value_func(&env).unwrap().form())
}
fn pokemon_get_display_species(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> ExternRef<dyn Species> {
ExternRef::func_new(&env, &pokemon.value_func(&env).unwrap().display_species())
}
fn pokemon_get_display_form(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> ExternRef<dyn Form> {
ExternRef::func_new(&env, &pokemon.value_func(&env).unwrap().display_form())
}
fn pokemon_get_level(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> LevelInt {
pokemon.value_func(&env).unwrap().level()
}
fn pokemon_get_experience(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> u32 {
pokemon.value_func(&env).unwrap().experience()
}
fn pokemon_get_unique_identifier(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> u32 {
pokemon.value_func(&env).unwrap().unique_identifier()
}
fn pokemon_get_coloring(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> u8 {
pokemon.value_func(&env).unwrap().coloring()
}
fn pokemon_get_nickname(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> u32 {
let pokemon = pokemon.value_func(&env).unwrap();
let nickname = pokemon.nickname();
if let Some(nickname) = nickname {
let nickname: CString = CString::new(nickname.as_str()).unwrap();
env.data().data().copy_value_vec_to_wasm(nickname.as_bytes())
} else {
0
}
}
fn pokemon_add_volatile_by_name( fn pokemon_add_volatile_by_name(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
@ -288,4 +483,18 @@ register! {
} }
} }
fn pokemon_get_ability_script(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> u32 {
let pokemon = pokemon.value_func(&env).unwrap();
if let Some(script) = pokemon.ability_script().get() {
let read_lock = script.read();
if let Some(script) = read_lock.as_ref() {
return script.as_any().downcast_ref::<WebAssemblyScript>().unwrap().get_wasm_pointer()
}
}
0
}
} }

View File

@ -3,6 +3,7 @@ use std::ops::Deref;
use crate::dynamic_data::{LearnedMove, Pokemon, TurnChoice}; use crate::dynamic_data::{LearnedMove, Pokemon, TurnChoice};
use crate::script_implementations::wasm::export_registry::register; use crate::script_implementations::wasm::export_registry::register;
use crate::script_implementations::wasm::extern_ref::ExternRef; 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::script_implementations::wasm::script_resolver::WebAssemblyEnv;
use wasmer::FunctionEnvMut; use wasmer::FunctionEnvMut;
@ -29,6 +30,38 @@ register! {
} }
} }
fn turn_choice_get_speed(
env: FunctionEnvMut<WebAssemblyEnv>,
turn_choice: ExternRef<TurnChoice>,
) -> u32 {
turn_choice.value_func(&env).unwrap().speed()
}
fn turn_choice_has_failed(
env: FunctionEnvMut<WebAssemblyEnv>,
turn_choice: ExternRef<TurnChoice>,
) -> u8 {
if turn_choice.value_func(&env).unwrap().has_failed() { 1 } else { 0 }
}
fn turn_choice_fail(
env: FunctionEnvMut<WebAssemblyEnv>,
turn_choice: ExternRef<TurnChoice>,
) {
turn_choice.value_func(&env).unwrap().fail();
}
fn turn_choice_move_priority(
env: FunctionEnvMut<WebAssemblyEnv>,
turn_choice: ExternRef<TurnChoice>,
) -> i8 {
if let TurnChoice::Move(d) = turn_choice.value_func(&env).unwrap() {
return d.priority()
}
panic!("Invalid turn choice");
}
fn turn_choice_move_used_move( fn turn_choice_move_used_move(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
turn_choice: ExternRef<TurnChoice>, turn_choice: ExternRef<TurnChoice>,
@ -59,11 +92,21 @@ register! {
panic!("Invalid turn choice"); panic!("Invalid turn choice");
} }
fn turn_choice_fail( fn turn_choice_move_script(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
turn_choice: ExternRef<TurnChoice>, turn_choice: ExternRef<TurnChoice>,
) { ) -> u32 {
turn_choice.value_func(&env).unwrap().fail(); if let TurnChoice::Move(d) = turn_choice.value_func(&env).unwrap() {
if let Some(script) = d.script().get() {
let read_lock = script.read();
if let Some(script) = read_lock.as_ref() {
return script.as_any().downcast_ref::<WebAssemblyScript>().unwrap().get_wasm_pointer()
}
}
return 0;
}
panic!("Invalid turn choice");
} }
} }

View File

@ -0,0 +1,34 @@
use crate::script_implementations::wasm::export_registry::register;
use crate::script_implementations::wasm::export_registry::FunctionEnvMut;
use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef};
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
use crate::static_data::{Ability, EffectParameter};
use crate::StringKey;
register! {
fn ability_get_name(
env: FunctionEnvMut<WebAssemblyEnv>,
ability: ExternRef<dyn Ability>
) -> ExternRef<StringKey> {
let ability = ability.value_func_arc(&env).unwrap();
ExternRef::func_new(&env, ability.name())
}
fn ability_get_effect(
env: FunctionEnvMut<WebAssemblyEnv>,
ability: ExternRef<dyn Ability>
) -> ExternRef<StringKey> {
let ability = ability.value_func_arc(&env).unwrap();
ExternRef::func_new(&env, ability.effect())
}
fn ability_get_parameters(
env: FunctionEnvMut<WebAssemblyEnv>,
ability: ExternRef<dyn Ability>
) -> VecExternRef<EffectParameter> {
let ability = ability.value_func_arc(&env).unwrap();
VecExternRef::new(env.data().data().as_ref(), ability.parameters())
}
}

View File

@ -0,0 +1,82 @@
use crate::script_implementations::wasm::export_registry::register;
use crate::script_implementations::wasm::export_registry::FunctionEnvMut;
use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef};
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
use crate::static_data::{Form, StatisticSet};
use crate::StringKey;
register! {
fn form_get_name(
env: FunctionEnvMut<WebAssemblyEnv>,
form: ExternRef<dyn Form>
) -> ExternRef<StringKey> {
let form = form.value_func_arc(&env).unwrap();
ExternRef::func_new(&env, form.name())
}
fn form_get_types(
env: FunctionEnvMut<WebAssemblyEnv>,
form: ExternRef<dyn Form>
) -> (u32, u32) {
let form = form.value_func_arc(&env).unwrap();
let vec = form.types();
let wasm_ptr = env.data().data().copy_value_vec_to_wasm(vec);
(wasm_ptr, vec.len() as u32)
}
fn form_get_height(
env: FunctionEnvMut<WebAssemblyEnv>,
form: ExternRef<dyn Form>
) -> f32 {
form.value_func_arc(&env).unwrap().height()
}
fn form_get_weight(
env: FunctionEnvMut<WebAssemblyEnv>,
form: ExternRef<dyn Form>
) -> f32 {
form.value_func_arc(&env).unwrap().weight()
}
fn form_get_base_experience(
env: FunctionEnvMut<WebAssemblyEnv>,
form: ExternRef<dyn Form>
) -> u32 {
form.value_func_arc(&env).unwrap().base_experience()
}
fn form_get_base_stats(
env: FunctionEnvMut<WebAssemblyEnv>,
form: ExternRef<dyn Form>
) -> ExternRef<StatisticSet<u16>> {
let form = form.value_func_arc(&env).unwrap();
ExternRef::func_new(&env, form.base_stats())
}
fn form_get_abilities(
env: FunctionEnvMut<WebAssemblyEnv>,
form: ExternRef<dyn Form>
) -> VecExternRef<StringKey> {
let form = form.value_func_arc(&env).unwrap();
VecExternRef::new(env.data().data().as_ref(), form.abilities())
}
fn form_get_hidden_abilities(
env: FunctionEnvMut<WebAssemblyEnv>,
form: ExternRef<dyn Form>
) -> VecExternRef<StringKey> {
let form = form.value_func_arc(&env).unwrap();
VecExternRef::new(env.data().data().as_ref(), form.hidden_abilities())
}
fn form_has_flag_by_hash(
env: FunctionEnvMut<WebAssemblyEnv>,
form: ExternRef<dyn Form>,
flag_hash: u32,
) -> u8 {
if form.value_func_arc(&env).unwrap().has_flag_by_hash(flag_hash) { 1 } else { 0 }
}
}

View File

@ -32,7 +32,6 @@ register! {
} }
} }
fn item_get_price( fn item_get_price(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
item: ExternRef<dyn Item>, item: ExternRef<dyn Item>,
@ -60,4 +59,13 @@ register! {
) -> u8 { ) -> u8 {
unsafe { transmute(item.value_func_arc(&env).unwrap().battle_category()) } unsafe { transmute(item.value_func_arc(&env).unwrap().battle_category()) }
} }
fn item_has_flag(
env: FunctionEnvMut<WebAssemblyEnv>,
item: ExternRef<dyn Item>,
key: ExternRef<StringKey>
) -> u8 {
if item.value_func_arc(&env).unwrap().has_flag(key.value_func(&env).unwrap()) { 1 } else { 0 }
}
} }

View File

@ -6,15 +6,24 @@ use crate::script_implementations::wasm::export_registry::register;
use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::extern_ref::ExternRef;
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
use crate::static_data::{ use crate::static_data::{
ItemLibrary, LibrarySettings, MoveLibrary, SpeciesLibrary, StaticData, StatisticSet, TypeLibrary, ItemLibrary, LibrarySettings, MoveLibrary, SpeciesLibrary, StaticData, StaticStatisticSet, StatisticSet,
TypeLibrary,
}; };
/// Ability data registration
mod ability;
/// Form data registration
mod form;
/// Item registration. /// Item registration.
mod item; mod item;
/// Moves data registration /// Moves data registration
mod moves; mod moves;
/// Nature data registration
mod nature;
/// Species data registration /// Species data registration
mod species; mod species;
/// Types data registration
mod types;
register! { register! {
fn static_data_get_move_library(env: FunctionEnvMut<WebAssemblyEnv>, data_library: ExternRef<dyn StaticData>) -> ExternRef<dyn MoveLibrary> { fn static_data_get_move_library(env: FunctionEnvMut<WebAssemblyEnv>, data_library: ExternRef<dyn StaticData>) -> ExternRef<dyn MoveLibrary> {
@ -47,12 +56,38 @@ register! {
data_library.value_func_box(&env).unwrap().maximum_level() data_library.value_func_box(&env).unwrap().maximum_level()
} }
fn static_statistics_set_get_stat(env: FunctionEnvMut<WebAssemblyEnv>, statistics_set: ExternRef<StaticStatisticSet<u16>>, stat: u8) -> u32 {
unsafe {
statistics_set.value_func(&env).unwrap().get_stat(transmute(stat)) as u32
}
}
fn statistic_set_get(env: FunctionEnvMut<WebAssemblyEnv>, statistics_set: ExternRef<StatisticSet<u32>>, stat: u8) -> i64 { fn statistic_set_get(env: FunctionEnvMut<WebAssemblyEnv>, statistics_set: ExternRef<StatisticSet<u32>>, stat: u8) -> i64 {
unsafe { unsafe {
statistics_set.value_func(&env).unwrap().get_stat(transmute(stat)) as i64 statistics_set.value_func(&env).unwrap().get_stat(transmute(stat)) as i64
} }
} }
fn statistic_set_set(env: FunctionEnvMut<WebAssemblyEnv>, statistics_set: ExternRef<StatisticSet<u32>>, stat: u8, value: u64) {
unsafe {
statistics_set.value_func(&env).unwrap().set_stat(transmute(stat), value as u32)
}
}
fn statistic_set_increase_stat(env: FunctionEnvMut<WebAssemblyEnv>, statistics_set: ExternRef<StatisticSet<u32>>, stat: u8, value: u64) {
unsafe {
statistics_set.value_func(&env).unwrap().increase_stat(transmute(stat), value as u32)
}
}
fn statistic_set_decrease_stat(env: FunctionEnvMut<WebAssemblyEnv>, statistics_set: ExternRef<StatisticSet<u32>>, stat: u8, value: u64) {
unsafe {
statistics_set.value_func(&env).unwrap().decrease_stat(transmute(stat), value as u32)
}
}
manual manual_registration manual manual_registration
} }
@ -61,4 +96,8 @@ fn manual_registration(imports: &mut Imports, store: &mut StoreMut, env: &Functi
moves::register(imports, store, env); moves::register(imports, store, env);
species::register(imports, store, env); species::register(imports, store, env);
item::register(imports, store, env); item::register(imports, store, env);
nature::register(imports, store, env);
form::register(imports, store, env);
ability::register(imports, store, env);
types::register(imports, store, env);
} }

View File

@ -0,0 +1,33 @@
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::Nature;
use std::mem::transmute;
use wasmer::FunctionEnvMut;
register! {
fn nature_get_increase_stat(
env: FunctionEnvMut<WebAssemblyEnv>,
nature: ExternRef<dyn Nature>
) -> u8 {
unsafe { transmute(nature.value_func_box(&env).unwrap().increased_stat()) }
}
fn nature_get_decrease_stat(
env: FunctionEnvMut<WebAssemblyEnv>,
nature: ExternRef<dyn Nature>
) -> u8 {
unsafe { transmute(nature.value_func_box(&env).unwrap().decreased_stat()) }
}
fn nature_get_increase_modifier(
env: FunctionEnvMut<WebAssemblyEnv>,
nature: ExternRef<dyn Nature>
) -> f32 {
nature.value_func_box(&env).unwrap().increased_modifier()
}
fn nature_get_decrease_modifier(
env: FunctionEnvMut<WebAssemblyEnv>,
nature: ExternRef<dyn Nature>
) -> f32 {
nature.value_func_box(&env).unwrap().decreased_modifier()
}
}

View File

@ -1,8 +1,8 @@
use crate::script_implementations::wasm::export_registry::register; use crate::script_implementations::wasm::export_registry::register;
use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::extern_ref::ExternRef;
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
use crate::static_data::Species;
use crate::static_data::SpeciesLibrary; use crate::static_data::SpeciesLibrary;
use crate::static_data::{Form, Species};
use crate::StringKey; use crate::StringKey;
use wasmer::FunctionEnvMut; use wasmer::FunctionEnvMut;
@ -59,5 +59,27 @@ fn species_get_id(
species.value_func_arc(&env).unwrap().id() species.value_func_arc(&env).unwrap().id()
} }
fn species_get_form_by_hash(
env: FunctionEnvMut<WebAssemblyEnv>,
species: ExternRef<dyn Species>,
form_hash: u32
) -> ExternRef<dyn Form> {
let species = species.value_func_arc(&env).unwrap();
let form = species.get_form_by_hash(form_hash);
if let Some(form) = form {
ExternRef::func_new(&env, &form)
} else {
ExternRef::null()
}
}
fn species_has_flag_by_hash(
env: FunctionEnvMut<WebAssemblyEnv>,
species: ExternRef<dyn Species>,
flag_hash: u32
) -> u8 {
if species.value_func_arc(&env).unwrap().has_flag_by_hash(flag_hash) { 1 } else { 0 }
}
} }

View File

@ -0,0 +1,35 @@
use crate::script_implementations::wasm::export_registry::register;
use crate::script_implementations::wasm::export_registry::FunctionEnvMut;
use crate::script_implementations::wasm::extern_ref::ExternRef;
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
use crate::static_data::TypeLibrary;
use crate::StringKey;
register! {
fn type_library_get_type_by_name(
env: FunctionEnvMut<WebAssemblyEnv>,
lib: ExternRef<dyn TypeLibrary>,
name: ExternRef<StringKey>
) -> u8 {
let lib = lib.value_func_arc(&env).unwrap();
let name = name.value_func(&env).unwrap();
let type_id = lib.get_type_id(name);
if let Some(type_id) = type_id {
type_id.into()
} else {
0
}
}
fn type_library_get_single_effectiveness(
env: FunctionEnvMut<WebAssemblyEnv>,
lib: ExternRef<dyn TypeLibrary>,
attacking: u8,
defending: u8
) -> f32 {
let lib = lib.value_func_arc(&env).unwrap();
lib.get_single_effectiveness(attacking.into(), defending.into())
}
}

View File

@ -344,6 +344,27 @@ impl WebAssemblyEnvironmentData {
unsafe { (self.memory().offset(wasm_ptr as isize), wasm_ptr) } unsafe { (self.memory().offset(wasm_ptr as isize), wasm_ptr) }
} }
/// Allocates a raw array in wasm, and copy the values from a given slice to it. Returns the
/// pointer in wasm memory.
pub fn copy_value_vec_to_wasm<T>(&self, v: &[T]) -> u32 {
let wasm_ptr = self
.allocate_mem_fn
.read()
.as_ref()
.unwrap()
.call(
&mut self.store_mut(),
(size_of::<T>() * v.len()) as u32,
align_of::<T>() as u32,
)
.unwrap();
unsafe {
let raw = self.memory().offset(wasm_ptr as isize) as *mut T;
v.as_ptr().copy_to(raw, v.len());
}
wasm_ptr
}
/// 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.

View File

@ -12,6 +12,12 @@ pub trait Nature: ValueIdentifiable + Debug {
/// The stat that should receive the decreased modifier. /// The stat that should receive the decreased modifier.
fn decreased_stat(&self) -> Statistic; fn decreased_stat(&self) -> Statistic;
/// The amount that the increased stat gets modified by.
fn increased_modifier(&self) -> f32;
/// The amount that the decreased stat gets modified by.
fn decreased_modifier(&self) -> f32;
/// Calculates the modifier for a given stat. If it's the increased stat, returns the increased /// Calculates the modifier for a given stat. If it's the increased stat, returns the increased
/// modifier, if it's the decreased stat, returns the decreased modifier. Otherwise returns 1.0 /// modifier, if it's the decreased stat, returns the decreased modifier. Otherwise returns 1.0
fn get_stat_modifier(&self, stat: Statistic) -> f32; fn get_stat_modifier(&self, stat: Statistic) -> f32;
@ -62,6 +68,14 @@ impl Nature for NatureImpl {
self.decrease_stat self.decrease_stat
} }
fn increased_modifier(&self) -> f32 {
self.increase_modifier
}
fn decreased_modifier(&self) -> f32 {
self.decrease_modifier
}
/// Calculates the modifier for a given stat. If it's the increased stat, returns the increased /// Calculates the modifier for a given stat. If it's the increased stat, returns the increased
/// modifier, if it's the decreased stat, returns the decreased modifier. Otherwise returns 1.0 /// modifier, if it's the decreased stat, returns the decreased modifier. Otherwise returns 1.0
fn get_stat_modifier(&self, stat: Statistic) -> f32 { fn get_stat_modifier(&self, stat: Statistic) -> f32 {
@ -91,6 +105,8 @@ pub(crate) mod tests {
impl Nature for Nature { impl Nature for Nature {
fn increased_stat(&self) -> Statistic; fn increased_stat(&self) -> Statistic;
fn decreased_stat(&self) -> Statistic; fn decreased_stat(&self) -> Statistic;
fn increased_modifier(&self) -> f32;
fn decreased_modifier(&self) -> f32;
fn get_stat_modifier(&self, stat: Statistic) -> f32; fn get_stat_modifier(&self, stat: Statistic) -> f32;
} }
impl ValueIdentifiable for Nature { impl ValueIdentifiable for Nature {

View File

@ -51,6 +51,9 @@ pub trait Form: ValueIdentifiable + Debug {
/// Check if the form has a specific flag set. /// Check if the form has a specific flag set.
fn has_flag(&self, key: &StringKey) -> bool; fn has_flag(&self, key: &StringKey) -> bool;
/// Arbitrary flags that can be applied to the move.
fn has_flag_by_hash(&self, key_hash: u32) -> bool;
} }
/// A form is a variant of a specific species. A species always has at least one form, but can have /// A form is a variant of a specific species. A species always has at least one form, but can have
@ -207,6 +210,10 @@ impl Form for FormImpl {
fn has_flag(&self, key: &StringKey) -> bool { fn has_flag(&self, key: &StringKey) -> bool {
self.flags.contains(key) self.flags.contains(key)
} }
fn has_flag_by_hash(&self, key_hash: u32) -> bool {
self.flags.contains::<u32>(&key_hash)
}
} }
impl ValueIdentifiable for FormImpl { impl ValueIdentifiable for FormImpl {
@ -240,6 +247,7 @@ pub(crate) mod tests {
fn get_random_ability(&self, rand: &mut Random) -> &StringKey; fn get_random_ability(&self, rand: &mut Random) -> &StringKey;
fn get_random_hidden_ability(&self, rand: &mut Random) -> &StringKey; fn get_random_hidden_ability(&self, rand: &mut Random) -> &StringKey;
fn has_flag(&self, key: &StringKey) -> bool; fn has_flag(&self, key: &StringKey) -> bool;
fn has_flag_by_hash(&self, key_hash: u32) -> bool;
} }
impl ValueIdentifiable for Form { impl ValueIdentifiable for Form {
fn value_identifier(&self) -> ValueIdentifier { fn value_identifier(&self) -> ValueIdentifier {

View File

@ -31,12 +31,16 @@ pub trait Species: ValueIdentifiable + Debug {
fn add_form(&self, id: StringKey, form: Arc<dyn Form>); fn add_form(&self, id: StringKey, form: Arc<dyn Form>);
/// Gets a form by name. /// Gets a form by name.
fn get_form(&self, id: &StringKey) -> Option<Arc<dyn Form>>; fn get_form(&self, id: &StringKey) -> Option<Arc<dyn Form>>;
/// Gets a form by the hash of its name.
fn get_form_by_hash(&self, name_hash: u32) -> Option<Arc<dyn Form>>;
/// Gets the form the Pokemon will have by default, if no other form is specified. /// Gets the form the Pokemon will have by default, if no other form is specified.
fn get_default_form(&self) -> Arc<dyn Form>; fn get_default_form(&self) -> Arc<dyn Form>;
/// Gets a random gender. /// Gets a random gender.
fn get_random_gender(&self, rand: &mut Random) -> Gender; fn get_random_gender(&self, rand: &mut Random) -> Gender;
/// Check whether the Pokemon has a specific flag set. /// Check whether the Pokemon has a specific flag set.
fn has_flag(&self, key: &StringKey) -> bool; fn has_flag(&self, key: &StringKey) -> bool;
/// Check whether the Pokemon has a specific flag set.
fn has_flag_by_hash(&self, key_hash: u32) -> bool;
} }
/// The data belonging to a Pokemon with certain characteristics. /// The data belonging to a Pokemon with certain characteristics.
@ -136,6 +140,10 @@ impl Species for SpeciesImpl {
self.forms.read().get(id).cloned() self.forms.read().get(id).cloned()
} }
fn get_form_by_hash(&self, name_hash: u32) -> Option<Arc<dyn Form>> {
self.forms.read().get::<u32>(&name_hash).cloned()
}
/// Gets the form the Pokemon will have by default, if no other form is specified. /// Gets the form the Pokemon will have by default, if no other form is specified.
fn get_default_form(&self) -> Arc<dyn Form> { fn get_default_form(&self) -> Arc<dyn Form> {
self.forms.read().get(&get_default_key()).unwrap().clone() self.forms.read().get(&get_default_key()).unwrap().clone()
@ -156,6 +164,10 @@ impl Species for SpeciesImpl {
fn has_flag(&self, key: &StringKey) -> bool { fn has_flag(&self, key: &StringKey) -> bool {
self.flags.contains(key) self.flags.contains(key)
} }
fn has_flag_by_hash(&self, key_hash: u32) -> bool {
self.flags.contains::<u32>(&key_hash)
}
} }
impl ValueIdentifiable for SpeciesImpl { impl ValueIdentifiable for SpeciesImpl {
@ -181,9 +193,11 @@ pub(crate) mod tests {
fn flags(&self) -> &HashSet<StringKey>; fn flags(&self) -> &HashSet<StringKey>;
fn add_form(&self, id: StringKey, form: Arc<dyn Form>); fn add_form(&self, id: StringKey, form: Arc<dyn Form>);
fn get_form(&self, id: &StringKey) -> Option<Arc<dyn Form>>; fn get_form(&self, id: &StringKey) -> Option<Arc<dyn Form>>;
fn get_form_by_hash(&self, name_hash: u32) -> Option<Arc<dyn Form>>;
fn get_default_form(&self) -> Arc<dyn Form>; fn get_default_form(&self) -> Arc<dyn Form>;
fn get_random_gender(&self, rand: &mut Random) -> Gender; fn get_random_gender(&self, rand: &mut Random) -> Gender;
fn has_flag(&self, key: &StringKey) -> bool; fn has_flag(&self, key: &StringKey) -> bool;
fn has_flag_by_hash(&self, key_hash: u32) -> bool;
} }
impl ValueIdentifiable for Species { impl ValueIdentifiable for Species {
fn value_identifier(&self) -> ValueIdentifier { fn value_identifier(&self) -> ValueIdentifier {

Binary file not shown.