A bunch more work on replacing every potential panic with results
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -20,7 +20,7 @@ use crate::dynamic_data::VolatileScriptsOwner;
|
||||
use crate::dynamic_data::{is_valid_target, ScriptWrapper};
|
||||
use crate::dynamic_data::{ChoiceQueue, ScriptContainer};
|
||||
use crate::dynamic_data::{ScriptCategory, ScriptSource, ScriptSourceData};
|
||||
use crate::{script_hook, PkmnError, StringKey, ValueIdentifiable, ValueIdentifier};
|
||||
use crate::{script_hook, PkmnError, StringKey, ValueIdentifiable, ValueIdentifier, VecExt};
|
||||
|
||||
/// A pokemon battle, with any amount of sides and pokemon per side.
|
||||
#[derive(Debug)]
|
||||
@@ -271,13 +271,7 @@ impl Battle {
|
||||
let side = choice.user().get_battle_side_index();
|
||||
match side {
|
||||
Some(side) => {
|
||||
self.sides
|
||||
.get(side as usize)
|
||||
.ok_or(PkmnError::IndexOutOfBounds {
|
||||
index: side as usize,
|
||||
len: self.sides.len(),
|
||||
})?
|
||||
.set_choice(choice)?;
|
||||
self.sides.get_res(side as usize)?.set_choice(choice)?;
|
||||
self.check_choices_set_and_run()?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use anyhow::Result;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
||||
@@ -19,12 +20,12 @@ pub struct BattleParty {
|
||||
impl BattleParty {
|
||||
/// Initializes a battle party with the underlying party, and the indices the party is responsible
|
||||
/// for.
|
||||
pub fn new(party: Arc<PokemonParty>, responsible_indices: Vec<(u8, u8)>) -> Self {
|
||||
Self {
|
||||
pub fn new(party: Arc<PokemonParty>, responsible_indices: Vec<(u8, u8)>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
identifier: Default::default(),
|
||||
party,
|
||||
responsible_indices,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Checks whether the party is responsible for the given index.
|
||||
|
||||
@@ -14,7 +14,7 @@ use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, Scrip
|
||||
use crate::dynamic_data::Script;
|
||||
use crate::dynamic_data::ScriptSet;
|
||||
use crate::dynamic_data::VolatileScriptsOwner;
|
||||
use crate::{script_hook, PkmnError, StringKey, ValueIdentifiable, ValueIdentifier};
|
||||
use crate::{script_hook, StringKey, ValueIdentifiable, ValueIdentifier, VecExt};
|
||||
|
||||
/// A side on a battle.
|
||||
#[derive(Debug)]
|
||||
@@ -149,12 +149,7 @@ impl BattleSide {
|
||||
for (index, pokemon_slot) in self.pokemon.read().iter().enumerate() {
|
||||
if let Some(pokemon) = pokemon_slot {
|
||||
if std::ptr::eq(pokemon.deref(), choice.user().deref()) {
|
||||
let len = self.choices.read().len();
|
||||
self.choices
|
||||
.write()
|
||||
.get_mut(index)
|
||||
.ok_or(PkmnError::IndexOutOfBounds { index, len })?
|
||||
.replace(choice);
|
||||
self.choices.write().get_mut_res(index)?.replace(choice);
|
||||
self.choices_set.fetch_add(1, Ordering::SeqCst);
|
||||
return Ok(());
|
||||
}
|
||||
@@ -180,10 +175,7 @@ impl BattleSide {
|
||||
pub fn set_pokemon(&self, index: u8, pokemon: Option<Arc<Pokemon>>) -> Result<()> {
|
||||
{
|
||||
let mut write_lock = self.pokemon.write();
|
||||
let old = write_lock.get_mut(index as usize).ok_or(PkmnError::IndexOutOfBounds {
|
||||
index: index as usize,
|
||||
len: self.pokemon_per_side as usize,
|
||||
})?;
|
||||
let old = write_lock.get_mut_res(index as usize)?;
|
||||
let old = match pokemon {
|
||||
Some(pokemon) => old.replace(pokemon),
|
||||
None => old.take(),
|
||||
@@ -193,23 +185,17 @@ impl BattleSide {
|
||||
// side again.
|
||||
drop(write_lock);
|
||||
script_hook!(on_remove, old_pokemon,);
|
||||
old_pokemon.set_on_battlefield(false);
|
||||
old_pokemon.set_on_battlefield(false)?;
|
||||
}
|
||||
}
|
||||
|
||||
let pokemon = {
|
||||
let read_lock = self.pokemon.read();
|
||||
&read_lock
|
||||
.get(index as usize)
|
||||
.ok_or(PkmnError::IndexOutOfBounds {
|
||||
index: index as usize,
|
||||
len: read_lock.len(),
|
||||
})?
|
||||
.clone()
|
||||
&read_lock.get_res(index as usize)?.clone()
|
||||
};
|
||||
if let Some(pokemon) = pokemon {
|
||||
pokemon.set_battle_data(self.battle, self.index);
|
||||
pokemon.set_on_battlefield(true);
|
||||
pokemon.set_on_battlefield(true)?;
|
||||
pokemon.set_battle_index(index);
|
||||
|
||||
let battle = self.battle()?;
|
||||
@@ -252,11 +238,7 @@ impl BattleSide {
|
||||
/// If this happens, the slot can not be used again.
|
||||
pub(crate) fn mark_slot_as_unfillable(&self, index: u8) -> Result<()> {
|
||||
self.fillable_slots
|
||||
.get(index as usize)
|
||||
.ok_or(PkmnError::IndexOutOfBounds {
|
||||
index: index as usize,
|
||||
len: self.fillable_slots.len(),
|
||||
})?
|
||||
.get_res(index as usize)?
|
||||
.store(false, Ordering::SeqCst);
|
||||
Ok(())
|
||||
}
|
||||
@@ -266,14 +248,7 @@ impl BattleSide {
|
||||
for (i, slot) in self.pokemon.read().iter().enumerate() {
|
||||
if let Some(p) = slot {
|
||||
if std::ptr::eq(p.deref().deref(), pokemon.deref()) {
|
||||
return Ok(self
|
||||
.fillable_slots
|
||||
.get(i)
|
||||
.ok_or(PkmnError::IndexOutOfBounds {
|
||||
index: i,
|
||||
len: self.fillable_slots.len(),
|
||||
})?
|
||||
.load(Ordering::Relaxed));
|
||||
return Ok(self.fillable_slots.get_res(i)?.load(Ordering::Relaxed));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ use crate::static_data::TypeIdentifier;
|
||||
use crate::static_data::{Ability, Statistic};
|
||||
use crate::static_data::{ClampedStatisticSet, StatisticSet};
|
||||
use crate::utils::Random;
|
||||
use crate::{script_hook, PkmnError, StringKey, ValueIdentifiable, ValueIdentifier};
|
||||
use crate::{script_hook, PkmnError, StringKey, ValueIdentifiable, ValueIdentifier, VecExt};
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
|
||||
/// An individual Pokemon as we know and love them.
|
||||
@@ -595,16 +595,17 @@ impl Pokemon {
|
||||
}
|
||||
|
||||
/// Sets whether or not the Pokemon is on the battlefield.
|
||||
pub fn set_on_battlefield(&self, value: bool) {
|
||||
pub fn set_on_battlefield(&self, value: bool) -> Result<()> {
|
||||
let r = self.battle_data.read();
|
||||
if let Some(data) = &mut r.deref() {
|
||||
data.on_battle_field.store(value, Ordering::SeqCst);
|
||||
if !value {
|
||||
self.volatile.clear();
|
||||
self.volatile.clear()?;
|
||||
self.weight.store(self.form().weight(), Ordering::SeqCst);
|
||||
self.height.store(self.form().height(), Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets the index of the slot of the side the Pokemon is on.
|
||||
@@ -676,11 +677,7 @@ impl Pokemon {
|
||||
if !battle.can_slot_be_filled(battle_data.battle_side_index(), battle_data.index()) {
|
||||
battle
|
||||
.sides()
|
||||
.get(battle_data.battle_side_index() as usize)
|
||||
.ok_or(PkmnError::IndexOutOfBounds {
|
||||
index: battle_data.battle_side_index() as usize,
|
||||
len: battle.sides().len(),
|
||||
})?
|
||||
.get_res(battle_data.battle_side_index() as usize)?
|
||||
.mark_slot_as_unfillable(battle_data.index())?;
|
||||
}
|
||||
|
||||
@@ -721,9 +718,12 @@ impl Pokemon {
|
||||
pub fn learn_move(&self, move_name: &StringKey, learn_method: MoveLearnMethod) -> Result<()> {
|
||||
let mut learned_moves = self.learned_moves().write();
|
||||
let move_pos = learned_moves.iter().position(|a| a.is_none());
|
||||
if move_pos.is_none() {
|
||||
bail!("No more moves with an empty space found.");
|
||||
}
|
||||
let move_pos = match move_pos {
|
||||
Some(a) => a,
|
||||
None => {
|
||||
bail!("No more moves with an empty space found.");
|
||||
}
|
||||
};
|
||||
let move_data = self
|
||||
.library
|
||||
.static_data()
|
||||
@@ -732,7 +732,9 @@ impl Pokemon {
|
||||
.ok_or(PkmnError::InvalidMoveName {
|
||||
move_name: move_name.clone(),
|
||||
})?;
|
||||
learned_moves[move_pos.unwrap()] = Some(Arc::new(LearnedMove::new(move_data, learn_method)));
|
||||
learned_moves
|
||||
.get_mut_res(move_pos)?
|
||||
.replace(Arc::new(LearnedMove::new(move_data, learn_method)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -805,7 +807,10 @@ impl ScriptSource for Pokemon {
|
||||
let mut c = 3;
|
||||
if let Some(battle_data) = &self.battle_data.read().deref() {
|
||||
if let Some(battle) = battle_data.battle() {
|
||||
c += battle.sides()[battle_data.battle_side_index() as usize].get_script_count()?;
|
||||
c += battle
|
||||
.sides()
|
||||
.get_res(battle_data.battle_side_index() as usize)?
|
||||
.get_script_count()?;
|
||||
}
|
||||
}
|
||||
Ok(c)
|
||||
@@ -826,7 +831,10 @@ impl ScriptSource for Pokemon {
|
||||
self.get_own_scripts(scripts);
|
||||
if let Some(battle_data) = &self.battle_data.read().deref() {
|
||||
if let Some(battle) = battle_data.battle() {
|
||||
battle.sides()[battle_data.battle_side_index() as usize].collect_scripts(scripts)?;
|
||||
battle
|
||||
.sides()
|
||||
.get_res(battle_data.battle_side_index() as usize)?
|
||||
.collect_scripts(scripts)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@@ -862,6 +870,7 @@ pub enum DamageSource {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::unwrap_used)]
|
||||
pub mod test {
|
||||
use crate::dynamic_data::libraries::test::MockDynamicLibrary;
|
||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::dynamic_data::models::learned_move::MoveLearnMethod;
|
||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
||||
use crate::dynamic_data::DynamicLibrary;
|
||||
use crate::static_data::{AbilityIndex, Gender};
|
||||
use crate::{Random, StringKey};
|
||||
use crate::{PkmnError, Random, StringKey};
|
||||
use anyhow::Result;
|
||||
|
||||
/// This allows for the easy chain building of a Pokemon.
|
||||
@@ -47,7 +47,12 @@ impl PokemonBuilder {
|
||||
Random::default()
|
||||
};
|
||||
|
||||
let species = self.library.static_data().species().get(&self.species).unwrap();
|
||||
let species = self
|
||||
.library
|
||||
.static_data()
|
||||
.species()
|
||||
.get(&self.species)
|
||||
.ok_or(PkmnError::InvalidSpeciesName { species: self.species })?;
|
||||
let form = species.get_default_form();
|
||||
let p = Pokemon::new(
|
||||
self.library,
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use anyhow::Result;
|
||||
use parking_lot::lock_api::RwLockReadGuard;
|
||||
use parking_lot::{RawRwLock, RwLock};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
||||
use crate::{ValueIdentifiable, ValueIdentifier};
|
||||
use crate::{ValueIdentifiable, ValueIdentifier, VecExt};
|
||||
|
||||
/// A list of Pokemon belonging to a trainer.
|
||||
#[derive(Debug)]
|
||||
@@ -52,14 +53,17 @@ impl PokemonParty {
|
||||
}
|
||||
|
||||
/// Sets the Pokemon at an index to a Pokemon, returning the old Pokemon.
|
||||
pub fn swap_into(&self, index: usize, pokemon: Option<Arc<Pokemon>>) -> Option<Arc<Pokemon>> {
|
||||
pub fn swap_into(&self, index: usize, pokemon: Option<Arc<Pokemon>>) -> Result<Option<Arc<Pokemon>>> {
|
||||
let mut party = self.pokemon.write();
|
||||
if index >= party.len() {
|
||||
return pokemon;
|
||||
return Ok(pokemon);
|
||||
}
|
||||
let old = party[index].as_ref().cloned();
|
||||
party[index] = pokemon;
|
||||
old
|
||||
let value = party.get_mut_res(index)?;
|
||||
let old = match pokemon {
|
||||
Some(p) => value.replace(p),
|
||||
None => value.take(),
|
||||
};
|
||||
Ok(old)
|
||||
}
|
||||
|
||||
/// Whether or not the party still has Pokemon that can be used in battle.
|
||||
@@ -83,18 +87,18 @@ impl PokemonParty {
|
||||
}
|
||||
|
||||
/// Makes sure there are no empty spots in the party anymore, leaving the length the same.
|
||||
pub fn pack_party(&self) {
|
||||
pub fn pack_party(&self) -> Result<()> {
|
||||
let mut first_empty = None;
|
||||
let mut i = 0;
|
||||
let mut party = self.pokemon.write();
|
||||
loop {
|
||||
if party[i].is_none() {
|
||||
if party.get_res(i)?.is_none() {
|
||||
if first_empty.is_none() {
|
||||
first_empty = Some(i)
|
||||
}
|
||||
} else if first_empty.is_some() {
|
||||
party.swap(first_empty.unwrap(), i);
|
||||
i = first_empty.unwrap();
|
||||
} else if let Some(f) = first_empty {
|
||||
party.swap(f, i);
|
||||
i = f;
|
||||
first_empty = None;
|
||||
}
|
||||
i += 1;
|
||||
@@ -102,6 +106,7 @@ impl PokemonParty {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Checks if the party contains a given pokemon.
|
||||
|
||||
Reference in New Issue
Block a user