Registration fixes and improvements.
continuous-integration/drone/push Build is failing
Details
continuous-integration/drone/push Build is failing
Details
This commit is contained in:
parent
b1890681a1
commit
7bcfd92d45
|
@ -47,8 +47,10 @@ pub enum ScriptCategory {
|
||||||
Side = 4,
|
Side = 4,
|
||||||
/// A script that can be attached to the entire battle.
|
/// A script that can be attached to the entire battle.
|
||||||
Battle = 5,
|
Battle = 5,
|
||||||
|
/// A special script for weather, for use on battles.
|
||||||
|
Weather = 6,
|
||||||
/// A special script for held items. As they're part of a held item, they're attached to a Pokemon.
|
/// A special script for held items. As they're part of a held item, they're attached to a Pokemon.
|
||||||
ItemBattleTrigger = 6,
|
ItemBattleTrigger = 7,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A basic empty script resolver, that always returns None.
|
/// A basic empty script resolver, that always returns None.
|
||||||
|
|
|
@ -11,12 +11,12 @@ use crate::dynamic_data::models::battle_party::BattleParty;
|
||||||
use crate::dynamic_data::models::battle_random::BattleRandom;
|
use crate::dynamic_data::models::battle_random::BattleRandom;
|
||||||
use crate::dynamic_data::models::battle_side::BattleSide;
|
use crate::dynamic_data::models::battle_side::BattleSide;
|
||||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
use crate::dynamic_data::models::pokemon::Pokemon;
|
||||||
use crate::dynamic_data::ChoiceQueue;
|
|
||||||
use crate::dynamic_data::DynamicLibrary;
|
use crate::dynamic_data::DynamicLibrary;
|
||||||
use crate::dynamic_data::Script;
|
use crate::dynamic_data::Script;
|
||||||
use crate::dynamic_data::ScriptSet;
|
use crate::dynamic_data::ScriptSet;
|
||||||
use crate::dynamic_data::VolatileScriptsOwner;
|
use crate::dynamic_data::VolatileScriptsOwner;
|
||||||
use crate::dynamic_data::{is_valid_target, ScriptWrapper};
|
use crate::dynamic_data::{is_valid_target, ScriptWrapper};
|
||||||
|
use crate::dynamic_data::{ChoiceQueue, ScriptContainer};
|
||||||
use crate::dynamic_data::{ScriptCategory, ScriptSource, ScriptSourceData};
|
use crate::dynamic_data::{ScriptCategory, ScriptSource, ScriptSourceData};
|
||||||
use crate::{script_hook, PkmnResult, StringKey};
|
use crate::{script_hook, PkmnResult, StringKey};
|
||||||
|
|
||||||
|
@ -48,6 +48,8 @@ pub struct Battle {
|
||||||
event_hook: EventHook,
|
event_hook: EventHook,
|
||||||
/// The index of the current turn. 0 until all choices
|
/// The index of the current turn. 0 until all choices
|
||||||
current_turn: AtomicU32,
|
current_turn: AtomicU32,
|
||||||
|
/// The current weather of the battle.
|
||||||
|
weather: ScriptContainer,
|
||||||
/// All the volatile scripts attached to a Pokemon
|
/// All the volatile scripts attached to a Pokemon
|
||||||
volatile_scripts: Arc<ScriptSet>,
|
volatile_scripts: Arc<ScriptSet>,
|
||||||
/// The time the last turn took to run. Defaults to 0.
|
/// The time the last turn took to run. Defaults to 0.
|
||||||
|
@ -91,6 +93,7 @@ impl Battle {
|
||||||
result: RwLock::new(BattleResult::Inconclusive),
|
result: RwLock::new(BattleResult::Inconclusive),
|
||||||
event_hook: Default::default(),
|
event_hook: Default::default(),
|
||||||
current_turn: AtomicU32::new(0),
|
current_turn: AtomicU32::new(0),
|
||||||
|
weather: Default::default(),
|
||||||
volatile_scripts: Default::default(),
|
volatile_scripts: Default::default(),
|
||||||
last_turn_time: Default::default(),
|
last_turn_time: Default::default(),
|
||||||
script_source_data: Default::default(),
|
script_source_data: Default::default(),
|
||||||
|
@ -331,6 +334,30 @@ impl Battle {
|
||||||
.store(time.num_nanoseconds().unwrap() as u64, Ordering::SeqCst);
|
.store(time.num_nanoseconds().unwrap() as u64, Ordering::SeqCst);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the current weather for the battle. If None is passed, this clears the weather.
|
||||||
|
pub fn set_weather(&self, weather: Option<StringKey>) {
|
||||||
|
if let Some(weather) = weather {
|
||||||
|
let script = self
|
||||||
|
.library()
|
||||||
|
.load_script(self.into(), ScriptCategory::Weather, &weather)
|
||||||
|
.unwrap()
|
||||||
|
.expect(format!("Couldn't find weather script by name {}", weather).as_str());
|
||||||
|
self.weather.set(script);
|
||||||
|
} else {
|
||||||
|
self.weather.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the current weather of the battle. If no weather is present, this returns None.
|
||||||
|
pub fn weather_name(&self) -> Option<StringKey> {
|
||||||
|
if let Some(script) = self.weather.get() {
|
||||||
|
let lock = script.read();
|
||||||
|
Some(lock.as_ref().unwrap().name().clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VolatileScriptsOwner for Battle {
|
impl VolatileScriptsOwner for Battle {
|
||||||
|
@ -353,6 +380,7 @@ impl ScriptSource for Battle {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_own_scripts(&self, scripts: &mut Vec<ScriptWrapper>) {
|
fn get_own_scripts(&self, scripts: &mut Vec<ScriptWrapper>) {
|
||||||
|
scripts.push((&self.weather).into());
|
||||||
scripts.push((&self.volatile_scripts).into());
|
scripts.push((&self.volatile_scripts).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -282,6 +282,11 @@ impl Pokemon {
|
||||||
pub fn weight(&self) -> f32 {
|
pub fn weight(&self) -> f32 {
|
||||||
self.weight.load(Ordering::Relaxed)
|
self.weight.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
/// Sets the weight of the Pokemon in kilograms.
|
||||||
|
pub fn set_weight(&self, weight: f32) {
|
||||||
|
self.weight.store(weight, Ordering::Relaxed)
|
||||||
|
}
|
||||||
|
|
||||||
/// The height of the Pokemon in meters.
|
/// The height of the Pokemon in meters.
|
||||||
pub fn height(&self) -> f32 {
|
pub fn height(&self) -> f32 {
|
||||||
self.height.load(Ordering::Relaxed)
|
self.height.load(Ordering::Relaxed)
|
||||||
|
@ -685,6 +690,11 @@ impl Pokemon {
|
||||||
let move_data = self.library.static_data().moves().get(move_name).unwrap();
|
let move_data = self.library.static_data().moves().get(move_name).unwrap();
|
||||||
learned_moves[move_pos.unwrap()] = Some(Arc::new(LearnedMove::new(move_data, learn_method)));
|
learned_moves[move_pos.unwrap()] = Some(Arc::new(LearnedMove::new(move_data, learn_method)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Removes the current non-volatile status from the Pokemon.
|
||||||
|
pub fn clear_status(&self) {
|
||||||
|
self.status_script.clear()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The data of the Pokemon related to being in a battle.
|
/// The data of the Pokemon related to being in a battle.
|
||||||
|
@ -780,6 +790,8 @@ pub enum DamageSource {
|
||||||
MoveDamage = 0,
|
MoveDamage = 0,
|
||||||
/// The damage is done by something else.
|
/// The damage is done by something else.
|
||||||
Misc = 1,
|
Misc = 1,
|
||||||
|
/// The damage is done because of struggling.
|
||||||
|
Struggle = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
20
src/script_implementations/wasm/export_registry/dynamic_data/battle.rs
Normal file → Executable file
20
src/script_implementations/wasm/export_registry/dynamic_data/battle.rs
Normal file → Executable file
|
@ -4,9 +4,17 @@ use crate::dynamic_data::{
|
||||||
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};
|
||||||
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
|
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
|
||||||
|
use crate::StringKey;
|
||||||
use wasmer::FunctionEnvMut;
|
use wasmer::FunctionEnvMut;
|
||||||
|
|
||||||
register! {
|
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(
|
fn battle_get_parties(
|
||||||
env: FunctionEnvMut<WebAssemblyEnv>,
|
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||||
battle: ExternRef<Battle>,
|
battle: ExternRef<Battle>,
|
||||||
|
@ -47,6 +55,18 @@ register! {
|
||||||
ExternRef::func_new(&env, battle.value_func(&env).unwrap().random())
|
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(
|
fn battle_find_party_for_pokemon(
|
||||||
env: FunctionEnvMut<WebAssemblyEnv>,
|
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||||
battle: ExternRef<Battle>,
|
battle: ExternRef<Battle>,
|
||||||
|
|
0
src/script_implementations/wasm/export_registry/dynamic_data/battle_random.rs
Normal file → Executable file
0
src/script_implementations/wasm/export_registry/dynamic_data/battle_random.rs
Normal file → Executable 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::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::{ScriptCategory, StringKey};
|
use crate::ScriptCategory;
|
||||||
use std::ffi::CString;
|
use std::ffi::CStr;
|
||||||
use wasmer::{FunctionEnvMut, Value};
|
use wasmer::FunctionEnvMut;
|
||||||
|
|
||||||
register! {
|
register! {
|
||||||
fn battleside_has_fled_battle(
|
fn battleside_has_fled_battle(
|
||||||
|
@ -61,8 +61,8 @@ register! {
|
||||||
name_ptr: u32
|
name_ptr: u32
|
||||||
) -> u32 {
|
) -> u32 {
|
||||||
unsafe {
|
unsafe {
|
||||||
let c_name = CString::from_raw(env.data().data().get_raw_pointer(name_ptr));
|
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.into()).unwrap();
|
let script = side.value_func(&env).unwrap().add_volatile_script(&c_name.as_ref().into()).unwrap();
|
||||||
if let Some(script) = script {
|
if let Some(script) = script {
|
||||||
let script = script.get_as::<WebAssemblyScript>();
|
let script = script.get_as::<WebAssemblyScript>();
|
||||||
script.get_wasm_pointer()
|
script.get_wasm_pointer()
|
||||||
|
@ -78,19 +78,33 @@ register! {
|
||||||
script_ptr: u32
|
script_ptr: u32
|
||||||
) -> u32 {
|
) -> u32 {
|
||||||
let side = side.value_func(&env).unwrap();
|
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{
|
unsafe{
|
||||||
let name_ptr: CString = CString::from_raw(env.data().data().get_raw_pointer(name_ptr));
|
let env = env.data().data();
|
||||||
let script = env.data().data().setup_script(script_ptr, ScriptCategory::Side, &name_ptr.into(), side.into()).unwrap();
|
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 {
|
if let Some(script) = script {
|
||||||
let script = side.add_volatile_script_with_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 {
|
} else {
|
||||||
0
|
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(
|
fn battleside_get_volatile(
|
||||||
env: FunctionEnvMut<WebAssemblyEnv>,
|
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||||
|
@ -98,8 +112,8 @@ register! {
|
||||||
name_ptr: u32
|
name_ptr: u32
|
||||||
) -> u32 {
|
) -> u32 {
|
||||||
unsafe {
|
unsafe {
|
||||||
let c_name = CString::from_raw(env.data().data().get_raw_pointer(name_ptr));
|
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.into());
|
let script = side.value_func(&env).unwrap().get_volatile_script(&c_name.as_ref().into());
|
||||||
if let Some(script) = script {
|
if let Some(script) = script {
|
||||||
let script = script.get_as::<WebAssemblyScript>();
|
let script = script.get_as::<WebAssemblyScript>();
|
||||||
script.get_wasm_pointer()
|
script.get_wasm_pointer()
|
||||||
|
@ -115,8 +129,8 @@ register! {
|
||||||
name_ptr: u32
|
name_ptr: u32
|
||||||
) {
|
) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let c_name = CString::from_raw(env.data().data().get_raw_pointer(name_ptr));
|
let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr));
|
||||||
side.value_func(&env).unwrap().remove_volatile_script(&c_name.into());
|
side.value_func(&env).unwrap().remove_volatile_script(&c_name.as_ref().into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
0
src/script_implementations/wasm/export_registry/dynamic_data/choice_queue.rs
Normal file → Executable file
0
src/script_implementations/wasm/export_registry/dynamic_data/choice_queue.rs
Normal file → Executable file
0
src/script_implementations/wasm/export_registry/dynamic_data/executing_move.rs
Normal file → Executable file
0
src/script_implementations/wasm/export_registry/dynamic_data/executing_move.rs
Normal file → Executable file
14
src/script_implementations/wasm/export_registry/dynamic_data/hit_data.rs
Normal file → Executable file
14
src/script_implementations/wasm/export_registry/dynamic_data/hit_data.rs
Normal file → Executable file
|
@ -5,6 +5,20 @@ use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
|
||||||
use wasmer::FunctionEnvMut;
|
use wasmer::FunctionEnvMut;
|
||||||
|
|
||||||
register! {
|
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(
|
fn hit_data_fail(
|
||||||
env: FunctionEnvMut<WebAssemblyEnv>,
|
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||||
hit: ExternRef<HitData>,
|
hit: ExternRef<HitData>,
|
||||||
|
|
0
src/script_implementations/wasm/export_registry/dynamic_data/party.rs
Normal file → Executable file
0
src/script_implementations/wasm/export_registry/dynamic_data/party.rs
Normal file → Executable file
|
@ -1,11 +1,14 @@
|
||||||
use std::mem::transmute;
|
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::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::{ClampedStatisticSet, Species};
|
use crate::static_data::{ClampedStatisticSet, Species};
|
||||||
use crate::static_data::{Item, StatisticSet};
|
use crate::static_data::{Item, StatisticSet};
|
||||||
|
use crate::{ScriptCategory, StringKey};
|
||||||
|
use std::ffi::{c_char, CStr};
|
||||||
use wasmer::FunctionEnvMut;
|
use wasmer::FunctionEnvMut;
|
||||||
|
|
||||||
register! {
|
register! {
|
||||||
|
@ -65,6 +68,38 @@ register! {
|
||||||
ExternRef::func_new(&env, species)
|
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(
|
fn pokemon_damage(
|
||||||
env: FunctionEnvMut<WebAssemblyEnv>,
|
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||||
pokemon: ExternRef<Pokemon>,
|
pokemon: ExternRef<Pokemon>,
|
||||||
|
@ -118,14 +153,25 @@ register! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pokemon_get_battle_side_index(
|
fn pokemon_get_battle_index(
|
||||||
env: FunctionEnvMut<WebAssemblyEnv>,
|
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||||
pokemon: ExternRef<Pokemon>,
|
pokemon: ExternRef<Pokemon>,
|
||||||
) -> u8 {
|
) -> u8 {
|
||||||
if let Some(i) = pokemon.value_func(&env).unwrap().get_battle_index() {
|
if let Some(i) = pokemon.value_func(&env).unwrap().get_battle_index() {
|
||||||
i
|
i
|
||||||
} else {
|
} 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::ffi::CString;
|
use std::ffi::{c_char, CStr, CString};
|
||||||
use std::mem::{align_of, forget};
|
use std::mem::{align_of, forget};
|
||||||
|
|
||||||
use wasmer::{FunctionEnv, FunctionEnvMut, Imports, StoreMut};
|
use wasmer::{FunctionEnv, FunctionEnvMut, Imports, StoreMut};
|
||||||
|
@ -80,34 +80,29 @@ pub(crate) fn register_webassembly_funcs(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Logging function for WASM.
|
/// Logging function for WASM.
|
||||||
fn _print(env: FunctionEnvMut<WebAssemblyEnv>, p: u32, len: u32) {
|
fn _print(env: FunctionEnvMut<WebAssemblyEnv>, p: u32) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mem: *mut u8 = env.data().data().memory().offset(p as isize);
|
let mem: *mut c_char = env.data().data().get_raw_pointer(p);
|
||||||
let s = String::from_raw_parts(mem, len as usize, len as usize);
|
let s = CStr::from_ptr(mem);
|
||||||
println!("{}", s);
|
println!("{}", s.to_str().unwrap());
|
||||||
forget(s);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Triggers when WASM panics.
|
/// Triggers when WASM panics.
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn _error(
|
fn _error(env: FunctionEnvMut<WebAssemblyEnv>, message: u32, file: u32, line: u32, position: u32) {
|
||||||
env: FunctionEnvMut<WebAssemblyEnv>,
|
|
||||||
message: u32,
|
|
||||||
message_len: u32,
|
|
||||||
file: u32,
|
|
||||||
file_len: u32,
|
|
||||||
line: u32,
|
|
||||||
position: u32,
|
|
||||||
) {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let mem: *mut u8 = env.data().data().memory().offset(message as isize);
|
let mem: *const c_char = env.data().data().get_raw_pointer(message);
|
||||||
let message_str = String::from_raw_parts(mem, message_len as usize, message_len as usize);
|
let message_str = CStr::from_ptr(mem);
|
||||||
let mem: *mut u8 = env.data().data().memory().offset(file as isize);
|
let mem: *const c_char = env.data().data().get_raw_pointer(file);
|
||||||
let file_str = String::from_raw_parts(mem, file_len as usize, file_len as usize);
|
let file_str = CStr::from_ptr(mem);
|
||||||
|
|
||||||
panic!(
|
panic!(
|
||||||
"Error: {} in file {}, line: {}:{}",
|
"WASM Error: {} in file {}, line: {}:{}",
|
||||||
message_str, file_str, line, position
|
message_str.to_str().unwrap(),
|
||||||
|
file_str.to_str().unwrap(),
|
||||||
|
line,
|
||||||
|
position
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
|
use std::mem::transmute;
|
||||||
use wasmer::{FunctionEnv, FunctionEnvMut, Imports, StoreMut};
|
use wasmer::{FunctionEnv, FunctionEnvMut, Imports, StoreMut};
|
||||||
|
|
||||||
use crate::defines::LevelInt;
|
use crate::defines::LevelInt;
|
||||||
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::{ItemLibrary, LibrarySettings, MoveLibrary, SpeciesLibrary, StaticData, TypeLibrary};
|
use crate::static_data::{
|
||||||
|
ItemLibrary, LibrarySettings, MoveLibrary, SpeciesLibrary, StaticData, StatisticSet, TypeLibrary,
|
||||||
|
};
|
||||||
|
|
||||||
mod item;
|
mod item;
|
||||||
/// Moves data registration
|
/// Moves data registration
|
||||||
|
@ -43,6 +46,12 @@ register! {
|
||||||
data_library.value_func(&env).unwrap().maximum_level()
|
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
|
manual manual_registration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,8 @@ macro_rules! script_function_cache {
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
#[allow(unused_parens)]
|
#[allow(unused_parens)]
|
||||||
pub(super) struct ScriptFunctionCache {
|
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)*), ()>>>,
|
$name: RwLock<Option<TypedFunction<(u32$(, $par_type)*), ()>>>,
|
||||||
)*
|
)*
|
||||||
|
@ -168,5 +170,42 @@ script_function_cache! {
|
||||||
share_experience(ExternRef<Pokemon>, ExternRef<Pokemon>, WasmPtr<bool>)
|
share_experience(ExternRef<Pokemon>, ExternRef<Pokemon>, WasmPtr<bool>)
|
||||||
block_weather(ExternRef<Battle>, WasmPtr<bool>)
|
block_weather(ExternRef<Battle>, WasmPtr<bool>)
|
||||||
change_capture_rate_bonus(ExternRef<Pokemon>, ExternRef<Item>, WasmPtr<u8>)
|
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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
/// Required for standard pokemon functions, but somewhat controversial nowadays. Consider adding a feature
|
/// Required for standard pokemon functions, but somewhat controversial nowadays. Consider adding a feature
|
||||||
/// that allows for a more progressive gender system for those that want it?
|
/// that allows for a more progressive gender system for those that want it?
|
||||||
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
|
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
|
||||||
|
#[repr(u8)]
|
||||||
pub enum Gender {
|
pub enum Gender {
|
||||||
/// The Pokemon has no gender.
|
/// The Pokemon has no gender.
|
||||||
Genderless = 0,
|
Genderless = 0,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::ffi::CString;
|
use std::ffi::CStr;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
@ -106,18 +106,11 @@ impl Display for StringKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Into<StringKey> for CString {
|
impl Into<StringKey> for &CStr {
|
||||||
fn into(self) -> StringKey {
|
fn into(self) -> StringKey {
|
||||||
StringKey::new(self.to_str().unwrap())
|
StringKey::new(self.to_str().unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Into<StringKey> for &CString {
|
|
||||||
fn into(self) -> StringKey {
|
|
||||||
StringKey::new(self.to_str().unwrap())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Converts a character to lowercased in a const safe way.
|
/// Converts a character to lowercased in a const safe way.
|
||||||
const fn to_lower(c: u8) -> u8 {
|
const fn to_lower(c: u8) -> u8 {
|
||||||
if c >= b'A' && c <= b'Z' {
|
if c >= b'A' && c <= b'Z' {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub mod data_getter;
|
mod data_getter;
|
||||||
pub mod library_loader;
|
pub mod library_loader;
|
||||||
pub mod test_case;
|
pub mod test_case;
|
||||||
pub mod test_step;
|
pub mod test_step;
|
||||||
|
|
Binary file not shown.
|
@ -9,7 +9,11 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use conquer_once::OnceCell;
|
use conquer_once::OnceCell;
|
||||||
|
|
||||||
use pkmn_lib::dynamic_data::DynamicLibrary;
|
use pkmn_lib::dynamic_data::{
|
||||||
|
Battle, BattleParty, DamageSource, DynamicLibrary, ExecutingMove, MoveChoice, PokemonBuilder, PokemonParty, Script,
|
||||||
|
ScriptCategory, ScriptContainer, ScriptOwnerData, TurnChoice, VolatileScriptsOwner,
|
||||||
|
};
|
||||||
|
use pkmn_lib::script_implementations::wasm::script::WebAssemblyScript;
|
||||||
|
|
||||||
use crate::common::{library_loader, TestCase};
|
use crate::common::{library_loader, TestCase};
|
||||||
|
|
||||||
|
@ -50,3 +54,65 @@ fn integration_tests(input: &Path) {
|
||||||
println!("\tRunning integration test {}", test_case.name);
|
println!("\tRunning integration test {}", test_case.name);
|
||||||
test_case.run_test(get_library());
|
test_case.run_test(get_library());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Assurance has the interesting properties that it creates a special data script internally, and
|
||||||
|
/// deletes that data script through the get_owner functionality.
|
||||||
|
#[test]
|
||||||
|
#[cfg_attr(miri, ignore)]
|
||||||
|
fn validate_assurance() {
|
||||||
|
let lib = get_library();
|
||||||
|
let p1 = Arc::new(
|
||||||
|
PokemonBuilder::new(lib.clone(), "charizard".into(), 100)
|
||||||
|
.learn_move("assurance".into())
|
||||||
|
.build(),
|
||||||
|
);
|
||||||
|
let p2 = Arc::new(PokemonBuilder::new(lib.clone(), "venusaur".into(), 100).build());
|
||||||
|
|
||||||
|
let party1 = BattleParty::new(
|
||||||
|
Arc::new(PokemonParty::new_from_vec(vec![Some(p1.clone())])),
|
||||||
|
vec![(0, 0)],
|
||||||
|
);
|
||||||
|
let party2 = BattleParty::new(
|
||||||
|
Arc::new(PokemonParty::new_from_vec(vec![Some(p2.clone())])),
|
||||||
|
vec![(1, 0)],
|
||||||
|
);
|
||||||
|
|
||||||
|
let battle = Battle::new(lib.clone(), vec![party1, party2], false, 2, 1, None);
|
||||||
|
|
||||||
|
battle.sides()[0].set_pokemon(0, Some(p1.clone()));
|
||||||
|
battle.sides()[1].set_pokemon(0, Some(p2.clone()));
|
||||||
|
|
||||||
|
let script = lib
|
||||||
|
.load_script(ScriptOwnerData::None, ScriptCategory::Move, &"assurance".into())
|
||||||
|
.unwrap()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mv = p1.learned_moves().read()[0].as_ref().unwrap().clone();
|
||||||
|
let choice = TurnChoice::Move(MoveChoice::new(p1.clone(), mv.clone(), 1, 0));
|
||||||
|
script.on_before_turn(&choice);
|
||||||
|
assert!(battle.sides()[1].has_volatile_script(&"assurance_data".into()));
|
||||||
|
|
||||||
|
let executing_move = ExecutingMove::new(
|
||||||
|
vec![],
|
||||||
|
1,
|
||||||
|
p1.clone(),
|
||||||
|
mv.clone(),
|
||||||
|
mv.move_data().clone(),
|
||||||
|
ScriptContainer::default(),
|
||||||
|
);
|
||||||
|
let mut v = 20_u8;
|
||||||
|
script.change_base_power(&executing_move, &p2, 0, &mut v);
|
||||||
|
assert_eq!(v, 20_u8);
|
||||||
|
|
||||||
|
let s = battle.sides()[1].get_volatile_script(&"assurance_data".into());
|
||||||
|
let data_script = s.as_ref().unwrap().get_as::<WebAssemblyScript>();
|
||||||
|
|
||||||
|
data_script.on_damage(&p2, DamageSource::Misc, 100, 50);
|
||||||
|
|
||||||
|
let mut v = 20_u8;
|
||||||
|
script.change_base_power(&executing_move, &p2, 0, &mut v);
|
||||||
|
assert_eq!(v, 40_u8);
|
||||||
|
|
||||||
|
data_script.on_end_turn();
|
||||||
|
assert!(!battle.sides()[1].has_volatile_script(&"assurance_data".into()));
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue