Major rework of extern ref system for WASM, fixes most possible panics in WASM handling
All checks were successful
continuous-integration/drone Build is passing

This commit is contained in:
2023-06-22 15:43:41 +02:00
parent 6a2353df4c
commit 46195d3042
71 changed files with 2142 additions and 1488 deletions

View File

@@ -1,5 +1,4 @@
use serde::Deserialize;
use std::sync::Arc;
use pkmn_lib::dynamic_data::Battle;
@@ -10,7 +9,7 @@ pub enum TestDataGetter {
}
impl TestDataGetter {
pub fn get(&self, battle: &Arc<Battle>) -> String {
pub fn get(&self, battle: &Battle) -> String {
match self {
TestDataGetter::PokemonHealth { index } => battle
.get_pokemon(index[0], index[1])

View File

@@ -65,7 +65,7 @@ pub fn load_library() -> LoadResult {
let species_load_time = t2 - t1;
let data = StaticDataImpl::new(
Box::new(LibrarySettingsImpl::new(100, 100).unwrap()),
Arc::new(LibrarySettingsImpl::new(100, 100).unwrap()),
species,
moves,
items,
@@ -81,10 +81,10 @@ pub fn load_library() -> LoadResult {
let wasm_load_time = t2 - t1;
let library = Arc::new(DynamicLibraryImpl::new(
Box::new(data),
Box::new(Gen7BattleStatCalculator::new()),
Box::new(Gen7DamageLibrary::new(false)),
Box::new(Gen7MiscLibrary::new()),
Arc::new(data),
Arc::new(Gen7BattleStatCalculator::new()),
Arc::new(Gen7DamageLibrary::new(false)),
Arc::new(Gen7MiscLibrary::new()),
script_resolver,
));
@@ -101,13 +101,13 @@ pub fn load_library() -> LoadResult {
}
}
pub fn load_types(path: &String) -> Box<dyn TypeLibrary> {
pub fn load_types(path: &String) -> Arc<dyn TypeLibrary> {
let mut reader = csv::ReaderBuilder::new()
.delimiter(b'|')
.from_path(path.to_string() + "Types.csv")
.unwrap();
let mut type_library = Box::new(TypeLibraryImpl::new(20));
let mut type_library = TypeLibraryImpl::new(20);
let headers = reader.headers().unwrap();
for header in headers.iter().skip(1) {
@@ -126,16 +126,16 @@ pub fn load_types(path: &String) -> Box<dyn TypeLibrary> {
.unwrap();
}
}
type_library
Arc::new(type_library)
}
pub fn load_natures(path: &String) -> Box<dyn NatureLibrary> {
pub fn load_natures(path: &String) -> Arc<dyn NatureLibrary> {
let mut reader = csv::ReaderBuilder::new()
.delimiter(b'|')
.from_path(path.to_string() + "Natures.csv")
.unwrap();
let mut nature_library = Box::new(NatureLibraryImpl::new(24));
let mut nature_library = NatureLibraryImpl::new(24);
for record in reader.records() {
let record = record.unwrap();
let nature_name = record.get(0).unwrap().into();
@@ -152,17 +152,17 @@ pub fn load_natures(path: &String) -> Box<dyn NatureLibrary> {
);
}
}
nature_library
Arc::new(nature_library)
}
pub fn load_items(path: &String) -> Box<dyn ItemLibrary> {
pub fn load_items(path: &String) -> Arc<dyn ItemLibrary> {
let mut file = File::open(path.to_string() + "Items.json").unwrap();
let mut data = String::new();
file.read_to_string(&mut data).unwrap();
let json: Value = serde_json::from_str(&data).unwrap();
let json_array = json.as_array().unwrap();
let mut item_library = Box::new(ItemLibraryImpl::new(400));
let mut item_library = ItemLibraryImpl::new(400);
for v in json_array {
let name = v.get("name").unwrap().as_str().unwrap().into();
let category = serde_json::from_value(v.get("itemType").unwrap().clone()).unwrap();
@@ -184,17 +184,17 @@ pub fn load_items(path: &String) -> Box<dyn ItemLibrary> {
Arc::new(ItemImpl::new(&name, category, battle_category, price as i32, flags)),
);
}
item_library
Arc::new(item_library)
}
pub fn load_growth_rates(path: &String) -> Box<dyn GrowthRateLibrary> {
pub fn load_growth_rates(path: &String) -> Arc<dyn GrowthRateLibrary> {
let mut file = File::open(path.to_string() + "GrowthRates.json").unwrap();
let mut data = String::new();
file.read_to_string(&mut data).unwrap();
let json: Value = serde_json::from_str(&data).unwrap();
let o = json.as_object().unwrap();
let mut growth_rate_library = Box::new(GrowthRateLibraryImpl::new(10));
let mut growth_rate_library = GrowthRateLibraryImpl::new(10);
for (key, value) in o {
let name = StringKey::new(key);
let experience_required_json = value.as_array().unwrap();
@@ -205,17 +205,17 @@ pub fn load_growth_rates(path: &String) -> Box<dyn GrowthRateLibrary> {
growth_rate_library.add_growth_rate(&name, Box::new(LookupGrowthRate::new(experience_required)));
}
growth_rate_library
Arc::new(growth_rate_library)
}
pub fn load_abilities(path: &String) -> Box<dyn AbilityLibrary> {
pub fn load_abilities(path: &String) -> Arc<dyn AbilityLibrary> {
let mut file = File::open(path.to_string() + "Abilities.json").unwrap();
let mut data = String::new();
file.read_to_string(&mut data).unwrap();
let json: Value = serde_json::from_str(&data).unwrap();
let o = json.as_object().unwrap();
let mut ability_library = Box::new(AbilityLibraryImpl::new(400));
let mut ability_library = AbilityLibraryImpl::new(400);
for (key, value) in o {
let name = StringKey::new(key);
let mut effect = StringKey::empty();
@@ -231,16 +231,16 @@ pub fn load_abilities(path: &String) -> Box<dyn AbilityLibrary> {
ability_library.add(&name, Arc::new(AbilityImpl::new(&name, &effect, parameters)));
}
ability_library
Arc::new(ability_library)
}
pub fn load_moves(path: &String, types: &Box<dyn TypeLibrary>) -> Box<dyn MoveLibrary> {
pub fn load_moves(path: &String, types: &Arc<dyn TypeLibrary>) -> Arc<dyn MoveLibrary> {
let mut file = File::open(path.to_string() + "Moves.json").unwrap();
let mut data = String::new();
file.read_to_string(&mut data).unwrap();
let json: Value = serde_json::from_str(&data).unwrap();
let data = json.as_object().unwrap().get("data").unwrap().as_array().unwrap();
let mut move_library = Box::new(MoveLibraryImpl::new(600));
let mut move_library = MoveLibraryImpl::new(600);
for move_data in data {
let move_data = move_data.as_object().unwrap();
let move_name = move_data.get("name").unwrap().as_str().unwrap().into();
@@ -298,21 +298,21 @@ pub fn load_moves(path: &String, types: &Box<dyn TypeLibrary>) -> Box<dyn MoveLi
)),
);
}
move_library
Arc::new(move_library)
}
pub fn load_species(
path: &String,
types: &Box<dyn TypeLibrary>,
moves: &Box<dyn MoveLibrary>,
) -> Box<dyn SpeciesLibrary> {
types: &Arc<dyn TypeLibrary>,
moves: &Arc<dyn MoveLibrary>,
) -> Arc<dyn SpeciesLibrary> {
let mut file = File::open(path.to_string() + "Pokemon.json").unwrap();
let mut data = String::new();
file.read_to_string(&mut data).unwrap();
let json: Value = serde_json::from_str(&data).unwrap();
let o = json.as_object().unwrap();
let mut species_library = Box::new(SpeciesLibraryImpl::new(800));
let mut species_library = SpeciesLibraryImpl::new(800);
for (key, value) in o.iter() {
if key.starts_with('$') {
continue;
@@ -349,7 +349,7 @@ pub fn load_species(
);
species_library.add(&name, Arc::new(species));
}
species_library
Arc::new(species_library)
}
#[cfg(not(feature = "wasm"))]
@@ -372,8 +372,8 @@ fn load_script_resolver(path: &String) -> Box<dyn ScriptResolver> {
fn parse_form(
name: StringKey,
value: &Value,
types: &Box<dyn TypeLibrary>,
moves: &Box<dyn MoveLibrary>,
types: &Arc<dyn TypeLibrary>,
moves: &Arc<dyn MoveLibrary>,
) -> Arc<dyn Form> {
let mut abilities = Vec::new();
for a in value.get("abilities").unwrap().as_array().unwrap() {
@@ -457,7 +457,7 @@ where
)
}
fn parse_moves(value: &Value, move_library: &Box<dyn MoveLibrary>) -> Box<dyn LearnableMoves> {
fn parse_moves(value: &Value, move_library: &Arc<dyn MoveLibrary>) -> Box<dyn LearnableMoves> {
let mut moves = LearnableMovesImpl::new(100);
let level_moves = value.get("levelMoves").unwrap().as_array().unwrap();
@@ -471,8 +471,8 @@ fn parse_moves(value: &Value, move_library: &Box<dyn MoveLibrary>) -> Box<dyn Le
Box::new(moves)
}
fn parse_effect_parameter(value: &Value) -> EffectParameter {
match value {
fn parse_effect_parameter(value: &Value) -> Arc<EffectParameter> {
Arc::new(match value {
Value::Null => {
panic!("Unexpected type")
}
@@ -491,7 +491,7 @@ fn parse_effect_parameter(value: &Value) -> EffectParameter {
Value::Object(_) => {
panic!("Unexpected type")
}
}
})
}
#[test]

View File

@@ -49,14 +49,14 @@ impl TestCase {
let pokemon = party
.pokemon
.iter()
.map(|a| Some(Arc::new(a.to_pokemon(library.clone()))))
.map(|a| Some(a.to_pokemon(library.clone())))
.collect();
let indices = party.indices.iter().map(|a| (a[0], a[1])).collect();
parties.push((Arc::new(PokemonParty::new_from_vec(pokemon)), indices));
}
let mut battle_parties = Vec::new();
for party in parties {
battle_parties.push(BattleParty::new(party.0.clone(), party.1).unwrap());
battle_parties.push(Arc::new(BattleParty::new(party.0.clone(), party.1).unwrap()));
}
let battle = Battle::new(
library,

View File

@@ -1,5 +1,4 @@
use serde::Deserialize;
use std::sync::Arc;
use pkmn_lib::dynamic_data::Battle;
use pkmn_lib::dynamic_data::{MoveChoice, PassChoice, TurnChoice};
@@ -32,7 +31,7 @@ pub enum TestStep {
}
impl TestStep {
pub fn execute(&self, battle: &Arc<Battle>) {
pub fn execute(&self, battle: &Battle) {
match self {
TestStep::SetPokemon { place, from_party } => {
let p = battle.parties()[from_party[0] as usize].get_pokemon(from_party[1] as usize);
@@ -73,7 +72,7 @@ impl TestStep {
assert!(battle.try_set_choice(TurnChoice::Pass(PassChoice::new(p))).unwrap());
}
TestStep::Assert { value, expected } => {
let v = value.get(&battle);
let v = value.get(battle);
assert_eq!(&v, expected)
}
}

Binary file not shown.

View File

@@ -84,29 +84,28 @@ fn load_non_existing_wasm_script() {
#[test]
fn validate_assurance() {
let lib = get_library();
let p1 = Arc::new(
PokemonBuilder::new(lib.clone(), "charizard".into(), 100)
.learn_move("assurance".into())
.build()
.unwrap(),
let p1 = PokemonBuilder::new(lib.clone(), "charizard".into(), 100)
.learn_move("assurance".into())
.build()
.unwrap();
let p2 = PokemonBuilder::new(lib.clone(), "venusaur".into(), 100)
.build()
.unwrap();
let party1 = Arc::new(
BattleParty::new(
Arc::new(PokemonParty::new_from_vec(vec![Some(p1.clone())])),
vec![(0, 0)],
)
.unwrap(),
);
let p2 = Arc::new(
PokemonBuilder::new(lib.clone(), "venusaur".into(), 100)
.build()
.unwrap(),
let party2 = Arc::new(
BattleParty::new(
Arc::new(PokemonParty::new_from_vec(vec![Some(p2.clone())])),
vec![(1, 0)],
)
.unwrap(),
);
let party1 = BattleParty::new(
Arc::new(PokemonParty::new_from_vec(vec![Some(p1.clone())])),
vec![(0, 0)],
)
.unwrap();
let party2 = BattleParty::new(
Arc::new(PokemonParty::new_from_vec(vec![Some(p2.clone())])),
vec![(1, 0)],
)
.unwrap();
let battle = Battle::new(lib.clone(), vec![party1, party2], false, 2, 1, None);
battle.sides()[0].set_pokemon(0, Some(p1.clone())).unwrap();
@@ -118,18 +117,18 @@ fn validate_assurance() {
.unwrap();
let mv = p1.learned_moves().read()[0].as_ref().unwrap().clone();
let choice = TurnChoice::Move(MoveChoice::new(p1.clone(), mv.clone(), 1, 0));
let choice = Arc::new(TurnChoice::Move(MoveChoice::new(p1.clone(), mv.clone(), 1, 0)));
script.on_before_turn(&choice).unwrap();
assert!(battle.sides()[1].has_volatile_script(&"assurance_data".into()));
let executing_move = ExecutingMove::new(
let executing_move = Arc::new(ExecutingMove::new(
vec![],
1,
p1,
mv.clone(),
mv.move_data().clone(),
ScriptContainer::default(),
);
));
let mut v = 20_u8;
script.change_base_power(&executing_move, &p2, 0, &mut v).unwrap();
assert_eq!(v, 20_u8);