Support for serializing and deserializing a Pokemon
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2023-07-22 12:23:33 +02:00
parent f23fc43405
commit 12802ce542
15 changed files with 473 additions and 12 deletions

View File

@@ -188,7 +188,7 @@ impl Pokemon {
ability_index: ability,
override_ability: None,
battle_data: RwLock::new(None),
moves: RwLock::new([None, None, None, None]),
moves: RwLock::new(Default::default()),
allowed_experience: false,
types: RwLock::new(form.types().to_vec()),
is_egg: false,
@@ -222,6 +222,10 @@ impl Pokemon {
pub fn form(&self) -> Arc<dyn Form> {
self.data.form.read().clone()
}
/// Whether or not the Pokemon is showing as a different species than it actually is.
pub fn has_different_display_species(&self) -> bool {
self.data.display_species.is_some()
}
/// The species that should be displayed to the user. This handles stuff like the Illusion ability.
pub fn display_species(&self) -> Arc<dyn Species> {
if let Some(v) = &self.data.display_species {
@@ -230,6 +234,10 @@ impl Pokemon {
self.species()
}
}
/// Whether or not the Pokemon is showing as a different form than it actually is.
pub fn has_different_display_form(&self) -> bool {
self.data.display_form.is_some()
}
/// The form that should be displayed to the user. This handles stuff like the Illusion ability.
pub fn display_form(&self) -> Arc<dyn Form> {
if let Some(v) = &self.data.display_form {
@@ -351,6 +359,11 @@ impl Pokemon {
&self.data.stat_boost
}
/// Whether or not this Pokemon is still an egg, and therefore cannot battle.
pub fn is_egg(&self) -> bool {
self.data.is_egg
}
/// The stats of the Pokemon including the stat boosts
pub fn boosted_stats(&self) -> &Arc<StatisticSet<u32>> {
&self.data.boosted_stats
@@ -833,6 +846,136 @@ impl Pokemon {
self.recalculate_flat_stats()
}
/// Converts the Pokemon into a serializable form.
#[cfg(feature = "serde")]
pub fn serialize(&self) -> Result<super::serialization::SerializedPokemon> {
self.into()
}
/// Deserializes a Pokemon from a serializable form.
#[cfg(feature = "serde")]
pub fn deserialize(
library: &Arc<dyn DynamicLibrary>,
value: &super::serialization::SerializedPokemon,
) -> Result<Self> {
let species = library
.static_data()
.species()
.get(&value.species)
.ok_or(PkmnError::InvalidSpeciesName {
species: value.species.clone(),
})?;
let form = species.get_form(&value.form).ok_or(PkmnError::InvalidFormName {
species: value.species.clone(),
form: value.form.clone(),
})?;
let display_species = if let Some(v) = &value.display_species {
Some(
library
.static_data()
.species()
.get(v)
.ok_or(PkmnError::InvalidSpeciesName { species: v.clone() })?,
)
} else {
None
};
let display_form = if let Some(v) = &value.display_form {
if let Some(display_species) = &display_species {
Some(display_species.get_form(v).ok_or(PkmnError::InvalidFormName {
species: display_species.name().clone(),
form: v.clone(),
})?)
} else {
None
}
} else {
None
};
Ok(Self {
data: Arc::new(PokemonData {
library: library.clone(),
species: RwLock::new(species),
form: RwLock::new(form),
display_species,
display_form,
level: Atomic::new(value.level),
experience: AtomicU32::new(value.experience),
personality_value: value.personality_value,
gender: RwLock::new(value.gender),
coloring: value.coloring,
held_item: RwLock::new({
if let Some(v) = &value.held_item {
Some(
library
.static_data()
.items()
.get(v)
.ok_or(PkmnError::InvalidItemName { item: v.clone() })?,
)
} else {
None
}
}),
current_health: AtomicU32::new(value.current_health),
weight: Atomic::new(value.weight),
height: Atomic::new(value.height),
flat_stats: Arc::new(Default::default()),
stat_boost: Arc::new(value.stat_boosts.clone()),
boosted_stats: Arc::new(Default::default()),
individual_values: Arc::new(value.individual_values.clone()),
effort_values: Arc::new(value.effort_values.clone()),
nature: {
library
.static_data()
.natures()
.get_nature(&value.nature)
.ok_or(PkmnError::InvalidNatureName {
nature: value.nature.clone(),
})?
},
nickname: value.nickname.clone(),
ability_index: value.ability_index,
override_ability: {
if let Some(v) = &value.override_ability {
Some(
library
.static_data()
.abilities()
.get(v)
.ok_or(PkmnError::InvalidAbilityName { ability: v.clone() })?,
)
} else {
None
}
},
battle_data: Default::default(),
moves: {
let mut moves: [Option<Arc<LearnedMove>>; MAX_MOVES] = Default::default();
for (i, v) in value.moves.iter().enumerate() {
if i >= MAX_MOVES {
break;
}
moves
.get_mut(i)
.replace(&mut Some(Arc::new(LearnedMove::deserialize(library, v)?)));
}
RwLock::new(moves)
},
allowed_experience: value.allowed_experience,
types: RwLock::new(value.types.clone()),
is_egg: value.is_egg,
is_caught: false,
held_item_trigger_script: Default::default(),
ability_script: Default::default(),
status_script: Default::default(),
volatile: Arc::new(Default::default()),
script_source_data: Default::default(),
}),
})
}
/// Take a weak reference to the Pokemon.
pub fn weak(&self) -> WeakPokemonReference {
WeakPokemonReference {