262 lines
9.5 KiB
Rust
Executable File
262 lines
9.5 KiB
Rust
Executable File
use crate::app_interface::list::ImmutableList;
|
|
use crate::app_interface::{ImmutableStatisticSet, StringKey};
|
|
use alloc::rc::Rc;
|
|
use alloc::vec::Vec;
|
|
use core::any::Any;
|
|
|
|
#[repr(u8)]
|
|
#[derive(Eq, PartialEq, Debug)]
|
|
pub enum Gender {
|
|
Male = 0,
|
|
Female = 1,
|
|
Genderless = 2,
|
|
}
|
|
|
|
pub trait FormTrait {
|
|
fn name(&self) -> StringKey;
|
|
fn height(&self) -> f32;
|
|
fn weight(&self) -> f32;
|
|
fn base_experience(&self) -> u32;
|
|
fn base_stats(&self) -> ImmutableStatisticSet;
|
|
fn abilities(&self) -> ImmutableList<Rc<StringKey>>;
|
|
fn hidden_abilities(&self) -> ImmutableList<Rc<StringKey>>;
|
|
fn types(&self) -> &Vec<u8>;
|
|
fn has_flag(&self, flag: &str) -> bool;
|
|
|
|
fn as_any(&self) -> &dyn Any;
|
|
}
|
|
|
|
pub trait SpeciesTrait {
|
|
/// The national dex identifier of the Pokemon.
|
|
fn id(&self) -> u16;
|
|
/// The name of the Pokemon species.
|
|
fn name(&self) -> StringKey;
|
|
/// The chance between 0.0 and 1.0 that a Pokemon is female.
|
|
fn gender_rate(&self) -> f32;
|
|
/// How much experience is required for a level.
|
|
fn growth_rate(&self) -> StringKey;
|
|
/// How hard it is to capture a Pokemon. 255 means this will be always caught, 0 means this is
|
|
/// uncatchable.
|
|
fn capture_rate(&self) -> u8;
|
|
fn get_form(&self, form_name: &str) -> Option<Form>;
|
|
fn has_flag(&self, flag: &str) -> bool;
|
|
|
|
fn as_any(&self) -> &dyn Any;
|
|
}
|
|
|
|
pub type Form = Rc<dyn FormTrait>;
|
|
pub type Species = Rc<dyn SpeciesTrait>;
|
|
|
|
#[cfg(not(feature = "mock_data"))]
|
|
mod implementation {
|
|
use super::*;
|
|
use crate::app_interface::list::ImmutableListWasm;
|
|
use crate::app_interface::{get_hash, ImmutableStatisticSetImpl};
|
|
use crate::handling::cached_value::CachedValue;
|
|
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType, VecExternRef};
|
|
use crate::handling::ffi_array::FFIArray;
|
|
use crate::handling::Cacheable;
|
|
use crate::{cached_value, cached_value_getters};
|
|
use spin::RwLock;
|
|
|
|
struct FormInner {
|
|
reference: ExternRef<FormImpl>,
|
|
name: CachedValue<StringKey>,
|
|
height: CachedValue<f32>,
|
|
weight: CachedValue<f32>,
|
|
types: CachedValue<Vec<u8>>,
|
|
base_experience: CachedValue<u32>,
|
|
base_stats: CachedValue<ImmutableStatisticSet>,
|
|
abilities: CachedValue<ImmutableList<Rc<StringKey>>>,
|
|
hidden_abilities: CachedValue<ImmutableList<Rc<StringKey>>>,
|
|
// moves: CachedValue<LearnableMoves>,
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct FormImpl {
|
|
inner: Rc<FormInner>,
|
|
}
|
|
|
|
impl FormImpl {
|
|
pub(crate) fn new(reference: ExternRef<Self>) -> Self {
|
|
Self::from_ref(reference, &|reference| Self {
|
|
inner: Rc::new(FormInner {
|
|
reference,
|
|
name: cached_value!({ form_get_name(reference).get_value().unwrap() }),
|
|
height: cached_value!({ form_get_height(reference) }),
|
|
weight: cached_value!({ form_get_weight(reference) }),
|
|
types: cached_value!({
|
|
let raw = form_get_types(reference);
|
|
Vec::from_raw_parts(raw.ptr(), raw.len(), raw.len())
|
|
}),
|
|
base_experience: cached_value!({ form_get_base_experience(reference) }),
|
|
base_stats: cached_value!({
|
|
Rc::new(form_get_base_stats(reference).get_value().unwrap())
|
|
}),
|
|
abilities: cached_value!({
|
|
Rc::new(
|
|
crate::app_interface::list::StringKeyImmutableList::from_ref(
|
|
form_get_abilities(reference),
|
|
),
|
|
)
|
|
}),
|
|
hidden_abilities: cached_value!({
|
|
Rc::new(
|
|
crate::app_interface::list::StringKeyImmutableList::from_ref(
|
|
form_get_hidden_abilities(reference),
|
|
),
|
|
)
|
|
}),
|
|
}),
|
|
})
|
|
}
|
|
|
|
pub(crate) fn reference(&self) -> ExternRef<Self> {
|
|
self.inner.reference
|
|
}
|
|
}
|
|
|
|
impl FormTrait for FormImpl {
|
|
cached_value_getters! {
|
|
fn name(&self) -> StringKey;
|
|
fn height(&self) -> f32;
|
|
fn weight(&self) -> f32;
|
|
fn base_experience(&self) -> u32;
|
|
fn base_stats(&self) -> ImmutableStatisticSet;
|
|
fn abilities(&self) -> ImmutableList<Rc<StringKey>>;
|
|
fn hidden_abilities(&self) -> ImmutableList<Rc<StringKey>>;
|
|
}
|
|
fn types(&self) -> &Vec<u8> {
|
|
self.inner.types.value_ref()
|
|
}
|
|
|
|
fn has_flag(&self, flag: &str) -> bool {
|
|
let hash = get_hash(flag);
|
|
unsafe { form_has_flag_by_hash(self.inner.reference, hash) }
|
|
}
|
|
|
|
fn as_any(&self) -> &dyn Any {
|
|
self
|
|
}
|
|
}
|
|
|
|
pub struct SpeciesInner {
|
|
reference: ExternRef<SpeciesImpl>,
|
|
id: CachedValue<u16>,
|
|
name: CachedValue<StringKey>,
|
|
gender_rate: CachedValue<f32>,
|
|
growth_rate: CachedValue<StringKey>,
|
|
capture_rate: CachedValue<u8>,
|
|
forms: RwLock<hashbrown::HashMap<u32, Option<Form>>>,
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct SpeciesImpl {
|
|
inner: Rc<SpeciesInner>,
|
|
}
|
|
|
|
impl SpeciesImpl {
|
|
pub(crate) fn new(reference: ExternRef<SpeciesImpl>) -> Self {
|
|
Self {
|
|
inner: Rc::new(SpeciesInner {
|
|
reference,
|
|
id: cached_value!({ species_get_id(reference) }),
|
|
name: cached_value!({ species_get_name(reference).get_value().unwrap() }),
|
|
gender_rate: cached_value!({ species_get_gender_rate(reference) }),
|
|
growth_rate: cached_value!({
|
|
species_get_growth_rate(reference).get_value().unwrap()
|
|
}),
|
|
capture_rate: cached_value!({ species_get_capture_rate(reference) }),
|
|
forms: Default::default(),
|
|
}),
|
|
}
|
|
}
|
|
|
|
pub(crate) fn reference(&self) -> ExternRef<Self> {
|
|
self.inner.reference
|
|
}
|
|
}
|
|
|
|
impl SpeciesTrait for SpeciesImpl {
|
|
cached_value_getters! {
|
|
/// The national dex identifier of the Pokemon.
|
|
fn id(&self) -> u16;
|
|
/// The name of the Pokemon species.
|
|
fn name(&self) -> StringKey;
|
|
/// The chance between 0.0 and 1.0 that a Pokemon is female.
|
|
fn gender_rate(&self) -> f32;
|
|
/// How much experience is required for a level.
|
|
fn growth_rate(&self) -> StringKey;
|
|
/// How hard it is to capture a Pokemon. 255 means this will be always caught, 0 means this is
|
|
/// uncatchable.
|
|
fn capture_rate(&self) -> u8;
|
|
}
|
|
|
|
fn get_form(&self, form_name: &str) -> Option<Form> {
|
|
let hash = get_hash(form_name);
|
|
unsafe {
|
|
if let Some(v) = self.inner.forms.read().get(&hash) {
|
|
v.clone()
|
|
} else {
|
|
let r = species_get_form_by_hash(self.inner.reference, hash);
|
|
let value = r.get_value();
|
|
let value: Option<Form> = if let Some(value) = value {
|
|
Some(Rc::new(value))
|
|
} else {
|
|
None
|
|
};
|
|
self.inner.forms.write().insert(hash, value.clone());
|
|
value
|
|
}
|
|
}
|
|
}
|
|
|
|
fn has_flag(&self, flag: &str) -> bool {
|
|
let hash = get_hash(flag);
|
|
unsafe { species_has_flag_by_hash(self.inner.reference, hash) }
|
|
}
|
|
|
|
fn as_any(&self) -> &dyn Any {
|
|
self
|
|
}
|
|
}
|
|
|
|
impl ExternalReferenceType for FormImpl {
|
|
fn from_extern_value(reference: ExternRef<Self>) -> Self {
|
|
Self::new(reference)
|
|
}
|
|
}
|
|
|
|
impl ExternalReferenceType for SpeciesImpl {
|
|
fn from_extern_value(reference: ExternRef<Self>) -> Self {
|
|
Self::new(reference)
|
|
}
|
|
}
|
|
|
|
crate::handling::cacheable::cacheable!(FormImpl);
|
|
crate::handling::cacheable::cacheable!(SpeciesImpl);
|
|
|
|
extern "wasm" {
|
|
fn form_get_name(r: ExternRef<FormImpl>) -> ExternRef<StringKey>;
|
|
fn form_get_height(r: ExternRef<FormImpl>) -> f32;
|
|
fn form_get_weight(r: ExternRef<FormImpl>) -> f32;
|
|
fn form_get_types(r: ExternRef<FormImpl>) -> FFIArray<u8>;
|
|
fn form_get_base_experience(r: ExternRef<FormImpl>) -> u32;
|
|
fn form_get_base_stats(r: ExternRef<FormImpl>) -> ExternRef<ImmutableStatisticSetImpl>;
|
|
fn form_get_abilities(r: ExternRef<FormImpl>) -> VecExternRef<StringKey>;
|
|
fn form_get_hidden_abilities(r: ExternRef<FormImpl>) -> VecExternRef<StringKey>;
|
|
fn form_has_flag_by_hash(r: ExternRef<FormImpl>, hash: u32) -> bool;
|
|
|
|
fn species_get_id(r: ExternRef<SpeciesImpl>) -> u16;
|
|
fn species_get_name(r: ExternRef<SpeciesImpl>) -> ExternRef<StringKey>;
|
|
fn species_get_gender_rate(r: ExternRef<SpeciesImpl>) -> f32;
|
|
fn species_get_growth_rate(r: ExternRef<SpeciesImpl>) -> ExternRef<StringKey>;
|
|
fn species_get_capture_rate(r: ExternRef<SpeciesImpl>) -> u8;
|
|
fn species_get_form_by_hash(r: ExternRef<SpeciesImpl>, hash: u32) -> ExternRef<FormImpl>;
|
|
fn species_has_flag_by_hash(r: ExternRef<SpeciesImpl>, flag_hash: u32) -> bool;
|
|
}
|
|
}
|
|
|
|
#[cfg(not(feature = "mock_data"))]
|
|
pub use implementation::*;
|