Complete refactor of the FFI to use handles instead of pointers.
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:
@@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
|
||||
use std::any::Any;
|
||||
use std::fmt::Debug;
|
||||
|
||||
use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
|
||||
use crate::StringKey;
|
||||
|
||||
/// An item category defines which bag slot items are stored in.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
@@ -47,7 +47,7 @@ pub enum BattleItemCategory {
|
||||
}
|
||||
|
||||
/// An item is an object which the player can pick up, keep in their Bag, and use in some manner
|
||||
pub trait Item: ValueIdentifiable + Debug + Any {
|
||||
pub trait Item: Debug + Any {
|
||||
/// The name of the item.
|
||||
fn name(&self) -> &StringKey;
|
||||
/// Which bag slot items are stored in.
|
||||
@@ -66,8 +66,6 @@ pub trait Item: ValueIdentifiable + Debug + Any {
|
||||
/// An item is an object which the player can pick up, keep in their Bag, and use in some manner
|
||||
#[derive(Debug)]
|
||||
pub struct ItemImpl {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The name of the item.
|
||||
name: StringKey,
|
||||
/// Which bag slot items are stored in.
|
||||
@@ -90,7 +88,6 @@ impl ItemImpl {
|
||||
flags: HashSet<StringKey>,
|
||||
) -> ItemImpl {
|
||||
ItemImpl {
|
||||
identifier: Default::default(),
|
||||
name: name.clone(),
|
||||
category,
|
||||
battle_category,
|
||||
@@ -128,12 +125,6 @@ impl Item for ItemImpl {
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for ItemImpl {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::indexing_slicing)]
|
||||
pub(crate) mod tests {
|
||||
@@ -150,10 +141,5 @@ pub(crate) mod tests {
|
||||
fn flags(&self) -> &HashSet<StringKey>;
|
||||
fn has_flag(&self, key: &StringKey) -> bool;
|
||||
}
|
||||
impl ValueIdentifiable for Item {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
ValueIdentifier::new(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,16 +5,14 @@ use indexmap::IndexMap;
|
||||
|
||||
use crate::static_data::Ability;
|
||||
use crate::static_data::DataLibrary;
|
||||
use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
|
||||
use crate::StringKey;
|
||||
|
||||
/// A storage for all abilities that can be used in this data library.
|
||||
pub trait AbilityLibrary: DataLibrary<dyn Ability> + ValueIdentifiable + Debug {}
|
||||
pub trait AbilityLibrary: DataLibrary<dyn Ability> + Debug {}
|
||||
|
||||
/// A storage for all abilities that can be used in this data library.
|
||||
#[derive(Debug)]
|
||||
pub struct AbilityLibraryImpl {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The underlying map for the library.
|
||||
map: IndexMap<StringKey, Arc<dyn Ability>>,
|
||||
}
|
||||
@@ -23,7 +21,6 @@ impl AbilityLibraryImpl {
|
||||
/// Instantiates a new ability library.
|
||||
pub fn new(capacity: usize) -> Self {
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
map: IndexMap::with_capacity(capacity),
|
||||
}
|
||||
}
|
||||
@@ -40,12 +37,6 @@ impl DataLibrary<dyn Ability> for AbilityLibraryImpl {
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for AbilityLibraryImpl {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::indexing_slicing)]
|
||||
#[allow(clippy::unwrap_used)]
|
||||
@@ -57,7 +48,7 @@ pub mod tests {
|
||||
use std::sync::Arc;
|
||||
|
||||
pub fn build() -> AbilityLibraryImpl {
|
||||
let mut lib = AbilityLibraryImpl::new(1);
|
||||
let lib = AbilityLibraryImpl::new(1);
|
||||
lib.add(
|
||||
&StringKey::new("test_ability"),
|
||||
Arc::new(AbilityImpl::new(
|
||||
|
||||
@@ -15,13 +15,17 @@ pub trait DataLibrary<T: ?Sized> {
|
||||
fn get_modify(&mut self) -> &mut IndexMap<StringKey, Arc<T>>;
|
||||
|
||||
/// Adds a new value to the library.
|
||||
fn add(&mut self, key: &StringKey, value: Arc<T>) {
|
||||
self.get_modify().insert(key.clone(), value);
|
||||
fn add(&self, key: &StringKey, value: Arc<T>) {
|
||||
#[allow(clippy::unwrap_used)] // We know this cant fail.
|
||||
let self_mut = unsafe { (self as *const Self as *mut Self).as_mut() }.unwrap();
|
||||
self_mut.get_modify().insert(key.clone(), value);
|
||||
}
|
||||
|
||||
/// Removes a value from the library.
|
||||
fn remove(&mut self, key: &StringKey) {
|
||||
self.get_modify().remove(key);
|
||||
fn remove(&self, key: &StringKey) {
|
||||
#[allow(clippy::unwrap_used)] // We know this cant fail.
|
||||
let self_mut = unsafe { (self as *const Self as *mut Self).as_mut() }.unwrap();
|
||||
self_mut.get_modify().remove(key);
|
||||
}
|
||||
|
||||
/// Gets a value from the library.
|
||||
|
||||
@@ -1,37 +1,36 @@
|
||||
use anyhow::Result;
|
||||
use std::fmt;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::sync::Arc;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use parking_lot::RwLock;
|
||||
|
||||
use crate::defines::LevelInt;
|
||||
use crate::static_data::GrowthRate;
|
||||
use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
|
||||
use crate::StringKey;
|
||||
|
||||
/// A library to store all growth rates.
|
||||
pub trait GrowthRateLibrary: Debug + ValueIdentifiable {
|
||||
pub trait GrowthRateLibrary: Debug {
|
||||
/// Calculates the level for a given growth key name and a certain experience.
|
||||
fn calculate_level(&self, growth_rate: &StringKey, experience: u32) -> Result<LevelInt>;
|
||||
/// Calculates the experience for a given growth key name and a certain level.
|
||||
fn calculate_experience(&self, growth_rate: &StringKey, level: LevelInt) -> Result<u32>;
|
||||
/// Adds a new growth rate with a name and value.
|
||||
fn add_growth_rate(&mut self, key: &StringKey, value: Box<dyn GrowthRate>);
|
||||
fn add_growth_rate(&self, key: &StringKey, value: Arc<dyn GrowthRate>);
|
||||
}
|
||||
|
||||
/// A library to store all growth rates.
|
||||
pub struct GrowthRateLibraryImpl {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The underlying data structure.
|
||||
growth_rates: HashMap<StringKey, Box<dyn GrowthRate>>,
|
||||
growth_rates: RwLock<HashMap<StringKey, Arc<dyn GrowthRate>>>,
|
||||
}
|
||||
|
||||
impl GrowthRateLibraryImpl {
|
||||
/// Instantiates a new growth rate library with a capacity.
|
||||
pub fn new(capacity: usize) -> Self {
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
growth_rates: HashMap::with_capacity(capacity),
|
||||
growth_rates: RwLock::new(HashMap::with_capacity(capacity)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,6 +40,7 @@ impl GrowthRateLibrary for GrowthRateLibraryImpl {
|
||||
fn calculate_level(&self, growth_rate: &StringKey, experience: u32) -> Result<LevelInt> {
|
||||
Ok(self
|
||||
.growth_rates
|
||||
.read()
|
||||
.get(growth_rate)
|
||||
.ok_or_else(|| anyhow::anyhow!("No growth rate found with key {}", growth_rate.to_string()))?
|
||||
.calculate_level(experience))
|
||||
@@ -48,20 +48,15 @@ impl GrowthRateLibrary for GrowthRateLibraryImpl {
|
||||
/// Calculates the experience for a given growth key name and a certain level.
|
||||
fn calculate_experience(&self, growth_rate: &StringKey, level: LevelInt) -> Result<u32> {
|
||||
self.growth_rates
|
||||
.read()
|
||||
.get(growth_rate)
|
||||
.ok_or_else(|| anyhow::anyhow!("No growth rate found with key {}", growth_rate.to_string()))?
|
||||
.calculate_experience(level)
|
||||
}
|
||||
|
||||
/// Adds a new growth rate with a name and value.
|
||||
fn add_growth_rate(&mut self, key: &StringKey, value: Box<dyn GrowthRate>) {
|
||||
self.growth_rates.insert(key.clone(), value);
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for GrowthRateLibraryImpl {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
fn add_growth_rate(&self, key: &StringKey, value: Arc<dyn GrowthRate>) {
|
||||
self.growth_rates.write().insert(key.clone(), value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +82,7 @@ pub mod tests {
|
||||
let w = &mut lib;
|
||||
w.add_growth_rate(
|
||||
&"test_growthrate".into(),
|
||||
Box::new(LookupGrowthRate::new(vec![0, 5, 10, 100])),
|
||||
Arc::new(LookupGrowthRate::new(vec![0, 5, 10, 100])),
|
||||
);
|
||||
// Drops borrow as mut
|
||||
|
||||
@@ -100,12 +95,7 @@ pub mod tests {
|
||||
impl GrowthRateLibrary for GrowthRateLibrary {
|
||||
fn calculate_level(&self, growth_rate: &StringKey, experience: u32) -> Result<LevelInt>;
|
||||
fn calculate_experience(&self, growth_rate: &StringKey, level: LevelInt) -> Result<u32>;
|
||||
fn add_growth_rate(&mut self, key: &StringKey, value: Box<dyn GrowthRate>);
|
||||
}
|
||||
impl ValueIdentifiable for GrowthRateLibrary {
|
||||
fn value_identifier(&self) -> ValueIdentifier{
|
||||
ValueIdentifier::new(0)
|
||||
}
|
||||
fn add_growth_rate(&self, key: &StringKey, value: Arc<dyn GrowthRate>);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,16 +5,14 @@ use indexmap::IndexMap;
|
||||
|
||||
use crate::static_data::DataLibrary;
|
||||
use crate::static_data::Item;
|
||||
use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
|
||||
use crate::StringKey;
|
||||
|
||||
/// A library to store all items.
|
||||
pub trait ItemLibrary: DataLibrary<dyn Item> + ValueIdentifiable + Debug {}
|
||||
pub trait ItemLibrary: DataLibrary<dyn Item> + Debug {}
|
||||
|
||||
/// A library to store all items.
|
||||
#[derive(Debug)]
|
||||
pub struct ItemLibraryImpl {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The underlying data structure.
|
||||
map: IndexMap<StringKey, Arc<dyn Item>>,
|
||||
}
|
||||
@@ -23,7 +21,6 @@ impl ItemLibraryImpl {
|
||||
/// Instantiates a new Item Library.
|
||||
pub fn new(capacity: usize) -> Self {
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
map: IndexMap::with_capacity(capacity),
|
||||
}
|
||||
}
|
||||
@@ -41,12 +38,6 @@ impl DataLibrary<dyn Item> for ItemLibraryImpl {
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for ItemLibraryImpl {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use hashbrown::HashSet;
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
use crate::defines::LevelInt;
|
||||
use crate::{ValueIdentifiable, ValueIdentifier};
|
||||
use anyhow::Result;
|
||||
use anyhow_ext::ensure;
|
||||
use std::fmt::Debug;
|
||||
|
||||
/// This library holds several misc settings for the library.
|
||||
pub trait LibrarySettings: Debug + ValueIdentifiable {
|
||||
pub trait LibrarySettings: Debug {
|
||||
/// The highest level a Pokemon can be.
|
||||
fn maximum_level(&self) -> LevelInt;
|
||||
|
||||
@@ -17,8 +16,6 @@ pub trait LibrarySettings: Debug + ValueIdentifiable {
|
||||
/// This library holds several misc settings for the library.
|
||||
#[derive(Debug)]
|
||||
pub struct LibrarySettingsImpl {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The highest level a Pokemon can be.
|
||||
maximum_level: LevelInt,
|
||||
/// The chance of a Pokemon being shiny, as the denominator of a fraction, where the nominator
|
||||
@@ -36,7 +33,6 @@ impl LibrarySettingsImpl {
|
||||
ensure!(shiny_rate >= 1);
|
||||
ensure!(maximum_level >= 1);
|
||||
Ok(Self {
|
||||
identifier: Default::default(),
|
||||
maximum_level,
|
||||
shiny_rate,
|
||||
})
|
||||
@@ -51,9 +47,3 @@ impl LibrarySettings for LibrarySettingsImpl {
|
||||
self.shiny_rate
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for LibrarySettingsImpl {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,16 +5,14 @@ use indexmap::IndexMap;
|
||||
|
||||
use crate::static_data::DataLibrary;
|
||||
use crate::static_data::MoveData;
|
||||
use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
|
||||
use crate::StringKey;
|
||||
|
||||
/// A library to store all data for moves.
|
||||
pub trait MoveLibrary: DataLibrary<dyn MoveData> + ValueIdentifiable + Debug {}
|
||||
pub trait MoveLibrary: DataLibrary<dyn MoveData> + Debug {}
|
||||
|
||||
/// A library to store all data for moves.
|
||||
#[derive(Debug)]
|
||||
pub struct MoveLibraryImpl {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The underlying map.
|
||||
map: IndexMap<StringKey, Arc<dyn MoveData>>,
|
||||
}
|
||||
@@ -23,7 +21,6 @@ impl MoveLibraryImpl {
|
||||
/// Instantiates a new Move Library.
|
||||
pub fn new(capacity: usize) -> Self {
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
map: IndexMap::with_capacity(capacity),
|
||||
}
|
||||
}
|
||||
@@ -40,12 +37,6 @@ impl DataLibrary<dyn MoveData> for MoveLibraryImpl {
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for MoveLibraryImpl {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use hashbrown::HashSet;
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
use crate::static_data::Nature;
|
||||
use crate::{Random, StringKey, ValueIdentifiable, ValueIdentifier};
|
||||
use crate::{Random, StringKey};
|
||||
use anyhow::bail;
|
||||
use anyhow_ext::{ensure, Result};
|
||||
use indexmap::IndexMap;
|
||||
use parking_lot::RwLock;
|
||||
use std::fmt::Debug;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// A library of all natures that can be used, stored by their names.
|
||||
pub trait NatureLibrary: Debug + ValueIdentifiable {
|
||||
pub trait NatureLibrary: Debug {
|
||||
/// Adds a new nature with name to the library.
|
||||
fn load_nature(&mut self, name: StringKey, nature: Arc<dyn Nature>);
|
||||
fn load_nature(&self, name: StringKey, nature: Arc<dyn Nature>);
|
||||
/// Gets a nature by name.
|
||||
fn get_nature(&self, key: &StringKey) -> Option<Arc<dyn Nature>>;
|
||||
/// Gets a random nature.
|
||||
@@ -21,38 +22,35 @@ pub trait NatureLibrary: Debug + ValueIdentifiable {
|
||||
/// A library of all natures that can be used, stored by their names.
|
||||
#[derive(Debug)]
|
||||
pub struct NatureLibraryImpl {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The underlying data structure.
|
||||
map: IndexMap<StringKey, Arc<dyn Nature>>,
|
||||
map: RwLock<IndexMap<StringKey, Arc<dyn Nature>>>,
|
||||
}
|
||||
|
||||
impl NatureLibraryImpl {
|
||||
/// Creates a new nature library with a given capacity.
|
||||
pub fn new(capacity: usize) -> Self {
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
map: IndexMap::with_capacity(capacity),
|
||||
map: RwLock::new(IndexMap::with_capacity(capacity)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NatureLibrary for NatureLibraryImpl {
|
||||
/// Adds a new nature with name to the library.
|
||||
fn load_nature(&mut self, name: StringKey, nature: Arc<dyn Nature>) {
|
||||
self.map.insert(name, nature);
|
||||
fn load_nature(&self, name: StringKey, nature: Arc<dyn Nature>) {
|
||||
self.map.write().insert(name, nature);
|
||||
}
|
||||
|
||||
/// Gets a nature by name.
|
||||
fn get_nature(&self, key: &StringKey) -> Option<Arc<dyn Nature>> {
|
||||
self.map.get(key).cloned()
|
||||
self.map.read().get(key).cloned()
|
||||
}
|
||||
|
||||
fn get_random_nature(&self, rand: &mut Random) -> Result<Arc<dyn Nature>> {
|
||||
ensure!(!self.map.is_empty(), "No natures were loaded into the library.");
|
||||
let i = rand.get_between(0, self.map.len() as i32);
|
||||
Ok(self
|
||||
.map
|
||||
let map = self.map.read();
|
||||
ensure!(!map.is_empty(), "No natures were loaded into the library.");
|
||||
let i = rand.get_between(0, map.len() as i32);
|
||||
Ok(map
|
||||
.get_index(i as usize)
|
||||
// this should never happen, but we'll check anyway.
|
||||
.ok_or(anyhow_ext::anyhow!("Failed to get a random nature from the library."))?
|
||||
@@ -62,10 +60,11 @@ impl NatureLibrary for NatureLibraryImpl {
|
||||
|
||||
/// Finds a nature name by nature.
|
||||
fn get_nature_name(&self, nature: &Arc<dyn Nature>) -> Result<StringKey> {
|
||||
for kv in &self.map {
|
||||
let read_lock = self.map.read();
|
||||
for kv in read_lock.iter() {
|
||||
// As natures can't be copied, and should always be the same reference as the value
|
||||
// in the map, we just compare by reference.
|
||||
if kv.1.value_identifier() == nature.value_identifier() {
|
||||
if Arc::ptr_eq(&kv.1, nature) {
|
||||
return Ok(kv.0.clone());
|
||||
}
|
||||
}
|
||||
@@ -73,12 +72,6 @@ impl NatureLibrary for NatureLibraryImpl {
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for NatureLibraryImpl {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::indexing_slicing)]
|
||||
#[allow(clippy::unwrap_used)]
|
||||
@@ -89,7 +82,7 @@ pub mod tests {
|
||||
use crate::static_data::{NatureImpl, NatureLibrary, NatureLibraryImpl};
|
||||
|
||||
pub fn build() -> NatureLibraryImpl {
|
||||
let mut lib = NatureLibraryImpl::new(2);
|
||||
let lib = NatureLibraryImpl::new(2);
|
||||
|
||||
lib.load_nature(
|
||||
"test_nature".into(),
|
||||
@@ -103,21 +96,16 @@ pub mod tests {
|
||||
#[derive(Debug)]
|
||||
pub NatureLibrary{}
|
||||
impl NatureLibrary for NatureLibrary {
|
||||
fn load_nature(&mut self, name: StringKey, nature: Arc<dyn Nature>);
|
||||
fn load_nature(&self, name: StringKey, nature: Arc<dyn Nature>);
|
||||
fn get_nature(&self, key: &StringKey) -> Option<Arc<dyn Nature>>;
|
||||
fn get_nature_name(&self, nature: &Arc<dyn Nature>) -> Result<StringKey>;
|
||||
fn get_random_nature(&self, rand: &mut Random) -> Result<Arc<dyn Nature>>;
|
||||
}
|
||||
impl ValueIdentifiable for NatureLibrary {
|
||||
fn value_identifier(&self) -> ValueIdentifier{
|
||||
ValueIdentifier::new(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_nature_library_insert_and_retrieve() {
|
||||
let mut lib = NatureLibraryImpl::new(2);
|
||||
let lib = NatureLibraryImpl::new(2);
|
||||
lib.load_nature(
|
||||
"foo".into(),
|
||||
NatureImpl::new(Statistic::HP, Statistic::Attack, 1.1, 0.9),
|
||||
@@ -135,7 +123,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn create_nature_library_insert_and_get_name() {
|
||||
let mut lib = NatureLibraryImpl::new(2);
|
||||
let lib = NatureLibraryImpl::new(2);
|
||||
lib.load_nature(
|
||||
"foo".into(),
|
||||
NatureImpl::new(Statistic::HP, Statistic::Attack, 1.1, 0.9),
|
||||
@@ -155,7 +143,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn create_nature_library_insert_single_and_retrieve_random() {
|
||||
let mut lib = NatureLibraryImpl::new(2);
|
||||
let lib = NatureLibraryImpl::new(2);
|
||||
lib.load_nature(
|
||||
"foo".into(),
|
||||
NatureImpl::new(Statistic::HP, Statistic::Attack, 1.1, 0.9),
|
||||
|
||||
@@ -5,16 +5,14 @@ use indexmap::IndexMap;
|
||||
|
||||
use crate::static_data::DataLibrary;
|
||||
use crate::static_data::Species;
|
||||
use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
|
||||
use crate::StringKey;
|
||||
|
||||
/// A library to store all data for Pokemon species.
|
||||
pub trait SpeciesLibrary: DataLibrary<dyn Species> + ValueIdentifiable + Debug {}
|
||||
pub trait SpeciesLibrary: DataLibrary<dyn Species> + Debug {}
|
||||
|
||||
/// A library to store all data for Pokemon species.
|
||||
#[derive(Debug)]
|
||||
pub struct SpeciesLibraryImpl {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The underlying map.
|
||||
map: IndexMap<StringKey, Arc<dyn Species>>,
|
||||
}
|
||||
@@ -23,7 +21,6 @@ impl SpeciesLibraryImpl {
|
||||
/// Instantiates a new Species Library.
|
||||
pub fn new(capacity: usize) -> Self {
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
map: IndexMap::with_capacity(capacity),
|
||||
}
|
||||
}
|
||||
@@ -40,12 +37,6 @@ impl DataLibrary<dyn Species> for SpeciesLibraryImpl {
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for SpeciesLibraryImpl {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::indexing_slicing)]
|
||||
#[allow(clippy::unwrap_used)]
|
||||
@@ -65,11 +56,6 @@ pub mod tests {
|
||||
fn map(&self) -> &IndexMap<StringKey, Arc<dyn Species>>;
|
||||
fn get_modify(&mut self) -> &mut IndexMap<StringKey, Arc<dyn Species>>;
|
||||
}
|
||||
impl ValueIdentifiable for SpeciesLibrary {
|
||||
fn value_identifier(&self) -> ValueIdentifier{
|
||||
ValueIdentifier::new(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn build_species() -> Arc<dyn Species> {
|
||||
@@ -85,10 +71,10 @@ pub mod tests {
|
||||
0.0,
|
||||
0,
|
||||
Vec::new(),
|
||||
StaticStatisticSet::new(10, 10, 10, 10, 10, 10),
|
||||
Arc::new(StaticStatisticSet::new(10, 10, 10, 10, 10, 10)),
|
||||
Vec::new(),
|
||||
Vec::new(),
|
||||
Box::new(LearnableMovesImpl::new(100)),
|
||||
Arc::new(LearnableMovesImpl::new(100)),
|
||||
HashSet::new(),
|
||||
)),
|
||||
HashSet::new(),
|
||||
|
||||
@@ -6,12 +6,11 @@ use crate::static_data::MoveLibrary;
|
||||
use crate::static_data::NatureLibrary;
|
||||
use crate::static_data::SpeciesLibrary;
|
||||
use crate::static_data::TypeLibrary;
|
||||
use crate::{ValueIdentifiable, ValueIdentifier};
|
||||
use std::fmt::Debug;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// The storage for all different libraries.
|
||||
pub trait StaticData: Debug + ValueIdentifiable {
|
||||
pub trait StaticData: Debug {
|
||||
/// Several misc settings for the library.
|
||||
fn settings(&self) -> &Arc<dyn LibrarySettings>;
|
||||
/// All data for Pokemon species.
|
||||
@@ -34,8 +33,6 @@ pub trait StaticData: Debug + ValueIdentifiable {
|
||||
/// The storage for all different libraries.
|
||||
#[derive(Debug)]
|
||||
pub struct StaticDataImpl {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// Several misc settings for the library.
|
||||
settings: Arc<dyn LibrarySettings>,
|
||||
/// All data for Pokemon species.
|
||||
@@ -67,7 +64,6 @@ impl StaticDataImpl {
|
||||
abilities: Arc<dyn AbilityLibrary>,
|
||||
) -> Self {
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
settings,
|
||||
species,
|
||||
moves,
|
||||
@@ -116,12 +112,6 @@ impl StaticData for StaticDataImpl {
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for StaticDataImpl {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::indexing_slicing)]
|
||||
#[allow(clippy::unwrap_used)]
|
||||
@@ -143,16 +133,10 @@ pub mod test {
|
||||
fn natures(&self) -> &Arc<dyn NatureLibrary>;
|
||||
fn abilities(&self) -> &Arc<dyn AbilityLibrary>;
|
||||
}
|
||||
impl ValueIdentifiable for StaticData {
|
||||
fn value_identifier(&self) -> ValueIdentifier{
|
||||
ValueIdentifier::new(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build() -> StaticDataImpl {
|
||||
StaticDataImpl {
|
||||
identifier: Default::default(),
|
||||
settings: Arc::new(LibrarySettingsImpl::new(100, 100).unwrap()),
|
||||
species: crate::static_data::libraries::species_library::tests::build(),
|
||||
moves: crate::static_data::libraries::move_library::tests::build(),
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use anyhow_ext::Result;
|
||||
use atomig::Atom;
|
||||
use hashbrown::HashMap;
|
||||
use parking_lot::{RwLock, RwLockReadGuard};
|
||||
use std::fmt::{Debug, Display};
|
||||
|
||||
use crate::{PkmnError, StringKey, ValueIdentifiable, ValueIdentifier};
|
||||
use crate::{PkmnError, StringKey};
|
||||
|
||||
/// A unique key that can be used to store a reference to a type. Opaque reference to a byte
|
||||
/// internally.
|
||||
@@ -33,7 +34,7 @@ impl Display for TypeIdentifier {
|
||||
}
|
||||
|
||||
/// All data related to types and effectiveness.
|
||||
pub trait TypeLibrary: Debug + ValueIdentifiable {
|
||||
pub trait TypeLibrary: Debug {
|
||||
/// Gets the type identifier for a type with a name.
|
||||
fn get_type_id(&self, key: &StringKey) -> Option<TypeIdentifier>;
|
||||
|
||||
@@ -49,48 +50,56 @@ pub trait TypeLibrary: Debug + ValueIdentifiable {
|
||||
fn get_effectiveness(&self, attacking: TypeIdentifier, defending: &[TypeIdentifier]) -> Result<f32>;
|
||||
|
||||
/// Registers a new type in the library.
|
||||
fn register_type(&mut self, name: &StringKey) -> TypeIdentifier;
|
||||
fn register_type(&self, name: &StringKey) -> TypeIdentifier;
|
||||
|
||||
/// Sets the effectiveness for an attacking type against a defending type.
|
||||
fn set_effectiveness(
|
||||
&mut self,
|
||||
attacking: TypeIdentifier,
|
||||
defending: TypeIdentifier,
|
||||
effectiveness: f32,
|
||||
) -> Result<()>;
|
||||
fn set_effectiveness(&self, attacking: TypeIdentifier, defending: TypeIdentifier, effectiveness: f32)
|
||||
-> Result<()>;
|
||||
}
|
||||
|
||||
/// All data related to types and effectiveness.
|
||||
#[derive(Debug)]
|
||||
pub struct TypeLibraryImpl {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// A list of types
|
||||
types: HashMap<StringKey, TypeIdentifier>,
|
||||
types: RwLock<HashMap<StringKey, TypeIdentifier>>,
|
||||
/// The effectiveness of the different types against each other.
|
||||
effectiveness: Vec<Vec<f32>>,
|
||||
effectiveness: RwLock<Vec<Vec<f32>>>,
|
||||
}
|
||||
|
||||
impl TypeLibraryImpl {
|
||||
/// Instantiates a new type library with a specific capacity.
|
||||
pub fn new(capacity: usize) -> Self {
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
types: HashMap::with_capacity(capacity),
|
||||
effectiveness: vec![],
|
||||
types: RwLock::new(HashMap::with_capacity(capacity)),
|
||||
effectiveness: RwLock::new(vec![]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeLibraryImpl {
|
||||
fn get_single_effectiveness_with_lock(
|
||||
lock: &RwLockReadGuard<Vec<Vec<f32>>>,
|
||||
attacking: TypeIdentifier,
|
||||
defending: TypeIdentifier,
|
||||
) -> Result<f32> {
|
||||
Ok(*lock
|
||||
.get((attacking.val - 1) as usize)
|
||||
.ok_or(PkmnError::InvalidTypeIdentifier { type_id: attacking })?
|
||||
.get((defending.val - 1) as usize)
|
||||
.ok_or(PkmnError::InvalidTypeIdentifier { type_id: defending })?)
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeLibrary for TypeLibraryImpl {
|
||||
/// Gets the type identifier for a type with a name.
|
||||
fn get_type_id(&self, key: &StringKey) -> Option<TypeIdentifier> {
|
||||
self.types.get(key).cloned()
|
||||
self.types.read().get(key).cloned()
|
||||
}
|
||||
|
||||
/// Gets the type name from the type identifier.
|
||||
fn get_type_name(&self, t: TypeIdentifier) -> Option<StringKey> {
|
||||
for kv in &self.types {
|
||||
let types = self.types.read();
|
||||
for kv in types.iter() {
|
||||
if *kv.1 == t {
|
||||
return Some(kv.0.clone());
|
||||
}
|
||||
@@ -100,12 +109,7 @@ impl TypeLibrary for TypeLibraryImpl {
|
||||
|
||||
/// Gets the effectiveness for a single attacking type against a single defending type.
|
||||
fn get_single_effectiveness(&self, attacking: TypeIdentifier, defending: TypeIdentifier) -> Result<f32> {
|
||||
Ok(*self
|
||||
.effectiveness
|
||||
.get((attacking.val - 1) as usize)
|
||||
.ok_or(PkmnError::InvalidTypeIdentifier { type_id: attacking })?
|
||||
.get((defending.val - 1) as usize)
|
||||
.ok_or(PkmnError::InvalidTypeIdentifier { type_id: defending })?)
|
||||
Self::get_single_effectiveness_with_lock(&self.effectiveness.read(), attacking, defending)
|
||||
}
|
||||
|
||||
/// Gets the effectiveness for a single attacking type against an amount of defending types.
|
||||
@@ -113,20 +117,24 @@ impl TypeLibrary for TypeLibraryImpl {
|
||||
/// multiplying the results with each other.
|
||||
fn get_effectiveness(&self, attacking: TypeIdentifier, defending: &[TypeIdentifier]) -> Result<f32> {
|
||||
let mut e = 1.0;
|
||||
let lock = self.effectiveness.read();
|
||||
for def in defending {
|
||||
e *= self.get_single_effectiveness(attacking, *def)?;
|
||||
e *= Self::get_single_effectiveness_with_lock(&lock, attacking, *def)?;
|
||||
}
|
||||
Ok(e)
|
||||
}
|
||||
|
||||
/// Registers a new type in the library.
|
||||
fn register_type(&mut self, name: &StringKey) -> TypeIdentifier {
|
||||
fn register_type(&self, name: &StringKey) -> TypeIdentifier {
|
||||
let mut types_write_lock = self.types.write();
|
||||
let mut effectiveness_write_lock = self.effectiveness.write();
|
||||
|
||||
let id = TypeIdentifier {
|
||||
val: (self.types.len() + 1) as u8,
|
||||
val: (types_write_lock.len() + 1) as u8,
|
||||
};
|
||||
self.types.insert(name.clone(), id);
|
||||
self.effectiveness.resize((id.val) as usize, vec![]);
|
||||
for effectiveness in &mut self.effectiveness {
|
||||
types_write_lock.insert(name.clone(), id);
|
||||
effectiveness_write_lock.resize((id.val) as usize, vec![]);
|
||||
for effectiveness in &mut effectiveness_write_lock.iter_mut() {
|
||||
effectiveness.resize((id.val) as usize, 1.0)
|
||||
}
|
||||
id
|
||||
@@ -134,13 +142,14 @@ impl TypeLibrary for TypeLibraryImpl {
|
||||
|
||||
/// Sets the effectiveness for an attacking type against a defending type.
|
||||
fn set_effectiveness(
|
||||
&mut self,
|
||||
&self,
|
||||
attacking: TypeIdentifier,
|
||||
defending: TypeIdentifier,
|
||||
effectiveness: f32,
|
||||
) -> Result<()> {
|
||||
*self
|
||||
.effectiveness
|
||||
.write()
|
||||
.get_mut((attacking.val - 1) as usize)
|
||||
.ok_or(PkmnError::InvalidTypeIdentifier { type_id: attacking })?
|
||||
.get_mut((defending.val - 1) as usize)
|
||||
@@ -149,12 +158,6 @@ impl TypeLibrary for TypeLibraryImpl {
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for TypeLibraryImpl {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::indexing_slicing)]
|
||||
#[allow(clippy::unwrap_used)]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
|
||||
use crate::StringKey;
|
||||
#[doc(inline)]
|
||||
pub use growth_rates::*;
|
||||
#[doc(inline)]
|
||||
@@ -56,57 +56,46 @@ mod statistics;
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
pub enum EffectParameter {
|
||||
/// A boolean value.
|
||||
Bool(ValueIdentifier, bool),
|
||||
Bool(bool),
|
||||
/// An integer value. Stored as a 64 bit int to deal with potentially large numbers.
|
||||
Int(ValueIdentifier, i64),
|
||||
Int(i64),
|
||||
/// A float value. Stored as a 32 bit float.
|
||||
Float(ValueIdentifier, f32),
|
||||
Float(f32),
|
||||
/// A string value.
|
||||
String(ValueIdentifier, StringKey),
|
||||
String(StringKey),
|
||||
}
|
||||
|
||||
impl From<bool> for EffectParameter {
|
||||
fn from(b: bool) -> Self {
|
||||
EffectParameter::Bool(Default::default(), b)
|
||||
EffectParameter::Bool(b)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i64> for EffectParameter {
|
||||
fn from(i: i64) -> Self {
|
||||
EffectParameter::Int(Default::default(), i)
|
||||
EffectParameter::Int(i)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f32> for EffectParameter {
|
||||
fn from(f: f32) -> Self {
|
||||
EffectParameter::Float(Default::default(), f)
|
||||
EffectParameter::Float(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StringKey> for EffectParameter {
|
||||
fn from(s: StringKey) -> Self {
|
||||
EffectParameter::String(Default::default(), s)
|
||||
EffectParameter::String(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for EffectParameter {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
EffectParameter::Bool(_, v) => f.write_fmt(format_args!("EffectParameter::Bool({v})")),
|
||||
EffectParameter::Int(_, v) => f.write_fmt(format_args!("EffectParameter::Int({v})")),
|
||||
EffectParameter::Float(_, v) => f.write_fmt(format_args!("EffectParameter::Float({v})")),
|
||||
EffectParameter::String(_, v) => f.write_fmt(format_args!("EffectParameter::String({v})")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for EffectParameter {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
match self {
|
||||
EffectParameter::Bool(i, _) => *i,
|
||||
EffectParameter::Int(i, _) => *i,
|
||||
EffectParameter::Float(i, _) => *i,
|
||||
EffectParameter::String(i, _) => *i,
|
||||
EffectParameter::Bool(v) => f.write_fmt(format_args!("EffectParameter::Bool({v})")),
|
||||
EffectParameter::Int(v) => f.write_fmt(format_args!("EffectParameter::Int({v})")),
|
||||
EffectParameter::Float(v) => f.write_fmt(format_args!("EffectParameter::Float({v})")),
|
||||
EffectParameter::String(v) => f.write_fmt(format_args!("EffectParameter::String({v})")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,10 @@ use hashbrown::HashSet;
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::Debug;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::static_data::{SecondaryEffect, TypeIdentifier};
|
||||
use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
|
||||
use crate::StringKey;
|
||||
|
||||
/// The move category defines what global kind of move this move is.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
@@ -61,7 +62,7 @@ pub enum MoveTarget {
|
||||
}
|
||||
|
||||
/// A move is the skill Pokémon primarily use in battle. This is the data related to that.
|
||||
pub trait MoveData: Debug + ValueIdentifiable {
|
||||
pub trait MoveData: Debug {
|
||||
/// The name of the move.
|
||||
fn name(&self) -> &StringKey;
|
||||
/// The attacking type of the move.
|
||||
@@ -82,7 +83,7 @@ pub trait MoveData: Debug + ValueIdentifiable {
|
||||
fn priority(&self) -> i8;
|
||||
|
||||
/// The optional secondary effect the move has.
|
||||
fn secondary_effect(&self) -> &Option<Box<dyn SecondaryEffect>>;
|
||||
fn secondary_effect(&self) -> &Option<Arc<dyn SecondaryEffect>>;
|
||||
|
||||
/// Arbitrary flags that can be applied to the move.
|
||||
fn has_flag(&self, key: &StringKey) -> bool;
|
||||
@@ -94,8 +95,6 @@ pub trait MoveData: Debug + ValueIdentifiable {
|
||||
/// A move is the skill Pokémon primarily use in battle. This is the data related to that.
|
||||
#[derive(Debug)]
|
||||
pub struct MoveDataImpl {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The name of the move.
|
||||
name: StringKey,
|
||||
/// The attacking type of the move.
|
||||
@@ -114,7 +113,7 @@ pub struct MoveDataImpl {
|
||||
/// The priority of the move. A higher priority means the move should go before other moves.
|
||||
priority: i8,
|
||||
/// The optional secondary effect the move has.
|
||||
secondary_effect: Option<Box<dyn SecondaryEffect>>,
|
||||
secondary_effect: Option<Arc<dyn SecondaryEffect>>,
|
||||
/// Arbitrary flags that can be applied to the move.
|
||||
flags: HashSet<StringKey>,
|
||||
}
|
||||
@@ -130,11 +129,10 @@ impl MoveDataImpl {
|
||||
base_usages: u8,
|
||||
target: MoveTarget,
|
||||
priority: i8,
|
||||
secondary_effect: Option<Box<dyn SecondaryEffect>>,
|
||||
secondary_effect: Option<Arc<dyn SecondaryEffect>>,
|
||||
flags: HashSet<StringKey>,
|
||||
) -> Self {
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
name: name.clone(),
|
||||
move_type,
|
||||
category,
|
||||
@@ -186,7 +184,7 @@ impl MoveData for MoveDataImpl {
|
||||
}
|
||||
|
||||
/// The optional secondary effect the move has.
|
||||
fn secondary_effect(&self) -> &Option<Box<dyn SecondaryEffect>> {
|
||||
fn secondary_effect(&self) -> &Option<Arc<dyn SecondaryEffect>> {
|
||||
&self.secondary_effect
|
||||
}
|
||||
|
||||
@@ -201,12 +199,6 @@ impl MoveData for MoveDataImpl {
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for MoveDataImpl {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::indexing_slicing)]
|
||||
#[allow(clippy::unwrap_used)]
|
||||
@@ -225,14 +217,9 @@ pub(crate) mod tests {
|
||||
fn base_usages(&self) -> u8;
|
||||
fn target(&self) -> MoveTarget;
|
||||
fn priority(&self) -> i8;
|
||||
fn secondary_effect(&self) -> &Option<Box<dyn SecondaryEffect>>;
|
||||
fn secondary_effect(&self) -> &Option<Arc<dyn SecondaryEffect>>;
|
||||
fn has_flag(&self, key: &StringKey) -> bool;
|
||||
fn has_flag_by_hash(&self, key_hash: u32) -> bool;
|
||||
}
|
||||
impl ValueIdentifiable for MoveData{
|
||||
fn value_identifier(&self) -> ValueIdentifier{
|
||||
ValueIdentifier::new(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use crate::static_data::EffectParameter;
|
||||
use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
|
||||
use crate::StringKey;
|
||||
use std::fmt::Debug;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// A secondary effect is an effect on a move that happens after it hits.
|
||||
pub trait SecondaryEffect: Debug + ValueIdentifiable {
|
||||
pub trait SecondaryEffect: Debug {
|
||||
/// The chance in percentages that the effect triggers. -1 to make it always trigger.
|
||||
fn chance(&self) -> f32;
|
||||
/// The name of the effect.
|
||||
@@ -16,8 +16,6 @@ pub trait SecondaryEffect: Debug + ValueIdentifiable {
|
||||
/// A secondary effect is an effect on a move that happens after it hits.
|
||||
#[derive(Debug)]
|
||||
pub struct SecondaryEffectImpl {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The chance in percentages that the effect triggers. -1 to make it always trigger.
|
||||
chance: f32,
|
||||
/// The name of the effect.
|
||||
@@ -30,7 +28,6 @@ impl SecondaryEffectImpl {
|
||||
/// Instantiates a new Secondary Effect.
|
||||
pub fn new(chance: f32, effect_name: StringKey, parameters: Vec<Arc<EffectParameter>>) -> Self {
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
chance,
|
||||
effect_name,
|
||||
parameters,
|
||||
@@ -53,12 +50,6 @@ impl SecondaryEffect for SecondaryEffectImpl {
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for SecondaryEffectImpl {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::indexing_slicing)]
|
||||
#[allow(clippy::unwrap_used)]
|
||||
@@ -77,11 +68,6 @@ pub(crate) mod tests {
|
||||
fn effect_name(&self) -> &StringKey;
|
||||
fn parameters(&self) -> &Vec<Arc<EffectParameter>>;
|
||||
}
|
||||
impl ValueIdentifiable for SecondaryEffect{
|
||||
fn value_identifier(&self) -> ValueIdentifier{
|
||||
ValueIdentifier::new(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
use crate::static_data::Statistic;
|
||||
use crate::{ValueIdentifiable, ValueIdentifier};
|
||||
use std::fmt::Debug;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// A nature is an attribute on a Pokemon that modifies the effective base stats on a Pokemon. They
|
||||
/// can have an increased statistic and a decreased statistic, or be neutral.
|
||||
pub trait Nature: ValueIdentifiable + Debug {
|
||||
pub trait Nature: Debug {
|
||||
/// The stat that should receive the increased modifier.
|
||||
fn increased_stat(&self) -> Statistic;
|
||||
|
||||
@@ -27,8 +26,6 @@ pub trait Nature: ValueIdentifiable + Debug {
|
||||
/// can have an increased statistic and a decreased statistic, or be neutral.
|
||||
#[derive(Debug)]
|
||||
pub struct NatureImpl {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The stat that should receive the increased modifier.
|
||||
increase_stat: Statistic,
|
||||
/// The stat that should receive the decreased modifier.
|
||||
@@ -48,7 +45,6 @@ impl NatureImpl {
|
||||
decrease_modifier: f32,
|
||||
) -> Arc<Self> {
|
||||
Arc::new(Self {
|
||||
identifier: Default::default(),
|
||||
increase_stat,
|
||||
decrease_stat,
|
||||
increase_modifier,
|
||||
@@ -89,12 +85,6 @@ impl Nature for NatureImpl {
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for NatureImpl {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::indexing_slicing)]
|
||||
#[allow(clippy::unwrap_used)]
|
||||
@@ -111,10 +101,5 @@ pub(crate) mod tests {
|
||||
fn decreased_modifier(&self) -> f32;
|
||||
fn get_stat_modifier(&self, stat: Statistic) -> f32;
|
||||
}
|
||||
impl ValueIdentifiable for Nature {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
ValueIdentifier::new(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use crate::static_data::EffectParameter;
|
||||
use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
|
||||
use crate::StringKey;
|
||||
use std::fmt::Debug;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// An ability is a passive effect in battle that is attached to a Pokemon.
|
||||
pub trait Ability: Debug + ValueIdentifiable {
|
||||
pub trait Ability: Debug {
|
||||
/// The name of the ability.
|
||||
fn name(&self) -> &StringKey;
|
||||
/// The name of the script effect of the ability.
|
||||
@@ -16,8 +16,6 @@ pub trait Ability: Debug + ValueIdentifiable {
|
||||
/// An ability is a passive effect in battle that is attached to a Pokemon.
|
||||
#[derive(Debug)]
|
||||
pub struct AbilityImpl {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The name of the ability.
|
||||
name: StringKey,
|
||||
/// The name of the script effect of the ability.
|
||||
@@ -30,7 +28,6 @@ impl AbilityImpl {
|
||||
/// Instantiates a new ability.
|
||||
pub fn new(name: &StringKey, effect: &StringKey, parameters: Vec<Arc<EffectParameter>>) -> Self {
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
name: name.clone(),
|
||||
effect: effect.clone(),
|
||||
parameters,
|
||||
@@ -53,12 +50,6 @@ impl Ability for AbilityImpl {
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for AbilityImpl {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
/// An ability index allows us to find an ability on a form. It combines a bool for whether the
|
||||
/// ability is hidden or not, and then an index of the ability.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
@@ -84,10 +75,5 @@ pub(crate) mod tests {
|
||||
fn effect(&self) -> &StringKey;
|
||||
fn parameters(&self) -> &Vec<Arc<EffectParameter>>;
|
||||
}
|
||||
impl ValueIdentifiable for Ability {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
ValueIdentifier::new(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,12 @@ use crate::static_data::Statistic;
|
||||
use crate::static_data::TypeIdentifier;
|
||||
use crate::static_data::{Ability, StaticStatisticSet};
|
||||
use crate::static_data::{AbilityIndex, LearnableMoves};
|
||||
use crate::{Random, ValueIdentifiable, ValueIdentifier};
|
||||
use crate::Random;
|
||||
use crate::{StringKey, VecExt};
|
||||
|
||||
/// A form is a variant of a specific species. A species always has at least one form, but can have
|
||||
/// many more.
|
||||
pub trait Form: ValueIdentifiable + Debug {
|
||||
pub trait Form: Debug {
|
||||
/// The name of the form.
|
||||
fn name(&self) -> &StringKey;
|
||||
/// The height of the form in meters.
|
||||
@@ -31,7 +31,7 @@ pub trait Form: ValueIdentifiable + Debug {
|
||||
fn hidden_abilities(&self) -> &Vec<StringKey>;
|
||||
|
||||
/// The moves a Pokemon with this form can learn.
|
||||
fn moves(&self) -> &Box<dyn LearnableMoves>;
|
||||
fn moves(&self) -> &Arc<dyn LearnableMoves>;
|
||||
/// Arbitrary flags can be set on a form for scripting use.
|
||||
fn flags(&self) -> &HashSet<StringKey>;
|
||||
|
||||
@@ -62,8 +62,6 @@ pub trait Form: ValueIdentifiable + Debug {
|
||||
/// many more.
|
||||
#[derive(Debug)]
|
||||
pub struct FormImpl {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The name of the form.
|
||||
name: StringKey,
|
||||
/// The height of the form in meters.
|
||||
@@ -81,7 +79,7 @@ pub struct FormImpl {
|
||||
/// The possible hidden abilities a Pokemon with this form can have.
|
||||
hidden_abilities: Vec<StringKey>,
|
||||
/// The moves a Pokemon with this form can learn.
|
||||
moves: Box<dyn LearnableMoves>,
|
||||
moves: Arc<dyn LearnableMoves>,
|
||||
/// Arbitrary flags can be set on a form for scripting use.
|
||||
flags: HashSet<StringKey>,
|
||||
}
|
||||
@@ -94,20 +92,19 @@ impl FormImpl {
|
||||
weight: f32,
|
||||
base_experience: u32,
|
||||
types: Vec<TypeIdentifier>,
|
||||
base_stats: StaticStatisticSet<u16>,
|
||||
base_stats: Arc<StaticStatisticSet<u16>>,
|
||||
abilities: Vec<StringKey>,
|
||||
hidden_abilities: Vec<StringKey>,
|
||||
moves: Box<dyn LearnableMoves>,
|
||||
moves: Arc<dyn LearnableMoves>,
|
||||
flags: HashSet<StringKey>,
|
||||
) -> Self {
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
name: name.clone(),
|
||||
height,
|
||||
weight,
|
||||
base_experience,
|
||||
types,
|
||||
base_stats: Arc::new(base_stats),
|
||||
base_stats,
|
||||
abilities,
|
||||
hidden_abilities,
|
||||
moves,
|
||||
@@ -151,7 +148,7 @@ impl Form for FormImpl {
|
||||
}
|
||||
|
||||
/// The moves a Pokemon with this form can learn.
|
||||
fn moves(&self) -> &Box<dyn LearnableMoves> {
|
||||
fn moves(&self) -> &Arc<dyn LearnableMoves> {
|
||||
&self.moves
|
||||
}
|
||||
/// Arbitrary flags can be set on a form for scripting use.
|
||||
@@ -222,12 +219,6 @@ impl Form for FormImpl {
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for FormImpl {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::indexing_slicing)]
|
||||
#[allow(clippy::unwrap_used)]
|
||||
@@ -246,7 +237,7 @@ pub(crate) mod tests {
|
||||
fn base_stats(&self) -> &Arc<StaticStatisticSet<u16>>;
|
||||
fn abilities(&self) -> &Vec<StringKey>;
|
||||
fn hidden_abilities(&self) -> &Vec<StringKey>;
|
||||
fn moves(&self) -> &Box<dyn LearnableMoves>;
|
||||
fn moves(&self) -> &Arc<dyn LearnableMoves>;
|
||||
fn flags(&self) -> &HashSet<StringKey>;
|
||||
fn get_type(&self, index: usize) -> Result<TypeIdentifier>;
|
||||
fn get_base_stat(&self, stat: Statistic) -> u16;
|
||||
@@ -257,10 +248,5 @@ pub(crate) mod tests {
|
||||
fn has_flag(&self, key: &StringKey) -> bool;
|
||||
fn has_flag_by_hash(&self, key_hash: u32) -> bool;
|
||||
}
|
||||
impl ValueIdentifiable for Form {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
ValueIdentifier::new(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use anyhow_ext::Result;
|
||||
use indexmap::IndexSet;
|
||||
use parking_lot::RwLock;
|
||||
use std::fmt::Debug;
|
||||
|
||||
use crate::defines::LevelInt;
|
||||
@@ -8,27 +9,27 @@ use crate::{StringKey, VecExt};
|
||||
/// The storage of the moves a Pokemon can learn.
|
||||
pub trait LearnableMoves: Debug {
|
||||
/// Adds a new level move the Pokemon can learn.
|
||||
fn add_level_move(&mut self, level: LevelInt, m: &StringKey) -> Result<()>;
|
||||
fn add_level_move(&self, level: LevelInt, m: &StringKey) -> Result<()>;
|
||||
/// Gets all moves a Pokemon can learn when leveling up to a specific level.
|
||||
fn get_learned_by_level(&self, level: LevelInt) -> Option<&Vec<StringKey>>;
|
||||
fn get_learned_by_level(&self, level: LevelInt) -> Option<Vec<StringKey>>;
|
||||
/// Gets the distinct moves a Pokemon can learn through leveling up.
|
||||
fn get_distinct_level_moves(&self) -> &IndexSet<StringKey>;
|
||||
fn get_distinct_level_moves(&self) -> IndexSet<StringKey>;
|
||||
}
|
||||
|
||||
/// The storage of the moves a Pokemon can learn.
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub struct LearnableMovesImpl {
|
||||
/// A map of the moves a Pokemon can learn per level.
|
||||
learned_by_level: Vec<Vec<StringKey>>,
|
||||
learned_by_level: RwLock<Vec<Vec<StringKey>>>,
|
||||
/// A list of the distinct moves a Pokemon can learn through leveling up.
|
||||
distinct_level_moves: IndexSet<StringKey>,
|
||||
distinct_level_moves: RwLock<IndexSet<StringKey>>,
|
||||
}
|
||||
|
||||
impl LearnableMovesImpl {
|
||||
/// Instantiates a new Learnable Moves.
|
||||
pub fn new(max_level: LevelInt) -> Self {
|
||||
Self {
|
||||
learned_by_level: vec![Vec::new(); (max_level + 1) as usize],
|
||||
learned_by_level: RwLock::new(vec![Vec::new(); (max_level + 1) as usize]),
|
||||
distinct_level_moves: Default::default(),
|
||||
}
|
||||
}
|
||||
@@ -36,20 +37,23 @@ impl LearnableMovesImpl {
|
||||
|
||||
impl LearnableMoves for LearnableMovesImpl {
|
||||
/// Adds a new level move the Pokemon can learn.
|
||||
fn add_level_move(&mut self, level: LevelInt, m: &StringKey) -> Result<()> {
|
||||
self.learned_by_level.get_mut_res(level as usize)?.push(m.clone());
|
||||
self.distinct_level_moves.insert(m.clone());
|
||||
fn add_level_move(&self, level: LevelInt, m: &StringKey) -> Result<()> {
|
||||
self.learned_by_level
|
||||
.write()
|
||||
.get_mut_res(level as usize)?
|
||||
.push(m.clone());
|
||||
self.distinct_level_moves.write().insert(m.clone());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Gets all moves a Pokemon can learn when leveling up to a specific level.
|
||||
fn get_learned_by_level(&self, level: LevelInt) -> Option<&Vec<StringKey>> {
|
||||
self.learned_by_level.get(level as usize)
|
||||
fn get_learned_by_level(&self, level: LevelInt) -> Option<Vec<StringKey>> {
|
||||
self.learned_by_level.read().get(level as usize).cloned()
|
||||
}
|
||||
|
||||
/// Gets the distinct moves a Pokemon can learn through leveling up.
|
||||
fn get_distinct_level_moves(&self) -> &IndexSet<StringKey> {
|
||||
&self.distinct_level_moves
|
||||
fn get_distinct_level_moves(&self) -> IndexSet<StringKey> {
|
||||
self.distinct_level_moves.read().clone()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +65,7 @@ pub(crate) mod tests {
|
||||
|
||||
#[test]
|
||||
fn adds_level_moves() {
|
||||
let mut moves = LearnableMovesImpl::new(100);
|
||||
let moves = LearnableMovesImpl::new(100);
|
||||
moves.add_level_move(1, &"foo".into()).unwrap();
|
||||
moves.add_level_move(1, &"bar".into()).unwrap();
|
||||
|
||||
@@ -73,7 +77,7 @@ pub(crate) mod tests {
|
||||
|
||||
#[test]
|
||||
fn adds_two_same_moves_at_different_level() {
|
||||
let mut moves = LearnableMovesImpl::new(100);
|
||||
let moves = LearnableMovesImpl::new(100);
|
||||
|
||||
moves.add_level_move(1, &"foo".into()).unwrap();
|
||||
moves.add_level_move(5, &"foo".into()).unwrap();
|
||||
|
||||
@@ -8,11 +8,11 @@ use parking_lot::{RawRwLock, RwLock};
|
||||
|
||||
use crate::static_data::Form;
|
||||
use crate::static_data::Gender;
|
||||
use crate::Random;
|
||||
use crate::StringKey;
|
||||
use crate::{Random, ValueIdentifiable, ValueIdentifier};
|
||||
|
||||
/// The data belonging to a Pokemon with certain characteristics.
|
||||
pub trait Species: ValueIdentifiable + Debug {
|
||||
pub trait Species: Debug {
|
||||
/// The national dex identifier of the Pokemon.
|
||||
fn id(&self) -> u16;
|
||||
/// The name of the Pokemon.
|
||||
@@ -47,8 +47,6 @@ pub trait Species: ValueIdentifiable + Debug {
|
||||
/// The data belonging to a Pokemon with certain characteristics.
|
||||
#[derive(Debug)]
|
||||
pub struct SpeciesImpl {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The national dex identifier of the Pokemon.
|
||||
id: u16,
|
||||
/// The name of the Pokemon.
|
||||
@@ -88,7 +86,6 @@ impl SpeciesImpl {
|
||||
let mut forms = HashMap::with_capacity(1);
|
||||
forms.insert_unique_unchecked(get_default_key(), default_form);
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
id,
|
||||
name: name.clone(),
|
||||
gender_rate,
|
||||
@@ -176,12 +173,6 @@ impl Species for SpeciesImpl {
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for SpeciesImpl {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::indexing_slicing)]
|
||||
#[allow(clippy::unwrap_used)]
|
||||
@@ -207,10 +198,5 @@ pub(crate) mod tests {
|
||||
fn has_flag(&self, key: &StringKey) -> bool;
|
||||
fn has_flag_by_hash(&self, key_hash: u32) -> bool;
|
||||
}
|
||||
impl ValueIdentifiable for Species {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
ValueIdentifier::new(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use crate::{ValueIdentifiable, ValueIdentifier};
|
||||
use atomig::impls::{PrimitiveAtom, PrimitiveAtomInteger};
|
||||
use atomig::{Atom, AtomInteger, Atomic};
|
||||
use num_traits::{clamp, NumCast, PrimInt};
|
||||
@@ -20,8 +19,6 @@ where
|
||||
<T as Atom>::Repr: PrimitiveAtomInteger,
|
||||
T: AtomInteger,
|
||||
{
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The health point stat value.
|
||||
hp: Atomic<T>,
|
||||
/// The physical attack stat value.
|
||||
@@ -47,7 +44,6 @@ where
|
||||
/// Creates a new statistic set with given stats.
|
||||
pub fn new(hp: T, attack: T, defense: T, special_attack: T, special_defense: T, speed: T) -> Self {
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
hp: Atomic::<T>::new(hp),
|
||||
attack: Atomic::<T>::new(attack),
|
||||
defense: Atomic::<T>::new(defense),
|
||||
@@ -131,19 +127,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ValueIdentifiable for StatisticSet<T>
|
||||
where
|
||||
T: PrimitiveAtom,
|
||||
T: Atom,
|
||||
T: PrimitiveAtomInteger,
|
||||
<T as Atom>::Repr: PrimitiveAtomInteger,
|
||||
T: AtomInteger,
|
||||
{
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
/// A collection of statistics that can not be modified after creation.
|
||||
///
|
||||
/// As no modifications happen, this struct does not use atomics.
|
||||
@@ -152,8 +135,6 @@ pub struct StaticStatisticSet<T>
|
||||
where
|
||||
T: PrimInt,
|
||||
{
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The health point stat value.
|
||||
hp: T,
|
||||
/// The physical attack stat value.
|
||||
@@ -175,7 +156,6 @@ where
|
||||
/// Create a new static statistic set.
|
||||
pub fn new(hp: T, attack: T, defense: T, special_attack: T, special_defense: T, speed: T) -> Self {
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
hp,
|
||||
attack,
|
||||
defense,
|
||||
@@ -223,15 +203,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ValueIdentifiable for StaticStatisticSet<T>
|
||||
where
|
||||
T: PrimInt,
|
||||
{
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
/// A clamped statistic set holds the 6 normal stats for a Pokemon, but ensures it always remains
|
||||
/// between two values (inclusive on the two values).
|
||||
#[derive(Default, Debug)]
|
||||
@@ -245,8 +216,6 @@ where
|
||||
T: NumCast,
|
||||
T: PrimInt,
|
||||
{
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The health point stat value.
|
||||
hp: Atomic<T>,
|
||||
/// The physical attack stat value.
|
||||
@@ -295,7 +264,6 @@ where
|
||||
/// Instantiates a new clamped statistic set.
|
||||
pub fn new(hp: T, attack: T, defense: T, special_attack: T, special_defense: T, speed: T) -> Self {
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
hp: Self::clamped_cast(hp),
|
||||
attack: Self::clamped_cast(attack),
|
||||
defense: Self::clamped_cast(defense),
|
||||
@@ -409,21 +377,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const MIN: i64, const MAX: i64> ValueIdentifiable for ClampedStatisticSet<T, MIN, MAX>
|
||||
where
|
||||
T: PrimitiveAtom,
|
||||
T: Atom,
|
||||
T: PrimitiveAtomInteger,
|
||||
<T as Atom>::Repr: PrimitiveAtomInteger,
|
||||
T: AtomInteger,
|
||||
T: NumCast,
|
||||
T: PrimInt,
|
||||
{
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user