2023-06-24 12:44:23 +00:00
|
|
|
use crate::static_data::{
|
2023-07-29 10:57:52 +00:00
|
|
|
Ability, Form, GrowthRate, Item, LearnableMoves, MoveData, Nature, Parameter, SecondaryEffect, Species,
|
2023-06-24 12:44:23 +00:00
|
|
|
StaticStatisticSet, StatisticSet,
|
|
|
|
};
|
|
|
|
use anyhow::anyhow;
|
|
|
|
use hashbrown::HashMap;
|
|
|
|
use parking_lot::RwLock;
|
|
|
|
use std::hash::Hash;
|
|
|
|
use std::sync::atomic::AtomicUsize;
|
|
|
|
use std::sync::{Arc, LazyLock};
|
|
|
|
|
2023-06-24 13:22:49 +00:00
|
|
|
/// This function can be called from the FFI to release a handle when it is no longer needed. This
|
|
|
|
/// does not drop the object per se, but will reduce the reference count of the object. If the object
|
|
|
|
/// is then no longer referenced, it will be dropped.
|
|
|
|
#[no_mangle]
|
|
|
|
extern "C" fn ffi_release_handle(handle: usize) {
|
|
|
|
let mut write_lock = FFI_OBJECTS.write();
|
|
|
|
let mut write_lock_inverse = FFI_OBJECTS_INVERSE.write();
|
|
|
|
|
|
|
|
let obj = write_lock.remove(&handle);
|
|
|
|
if let Some(obj) = obj {
|
|
|
|
write_lock_inverse.remove(&obj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-24 13:05:58 +00:00
|
|
|
/// A handle of an object that can be passed over FFI. We use this to avoid passing pointers over the
|
|
|
|
/// FFI boundary. This allows us to be able to move the data around in memory without having to worry
|
|
|
|
/// about the pointers being invalidated. It also allows us to have a type-safe interface.
|
2023-06-24 12:44:23 +00:00
|
|
|
#[repr(C)]
|
|
|
|
pub(super) struct FFIHandle<T> {
|
2023-06-24 13:05:58 +00:00
|
|
|
/// An incrementing handle that is unique for each object.
|
2023-06-24 12:44:23 +00:00
|
|
|
handle: usize,
|
2023-06-24 13:05:58 +00:00
|
|
|
/// The type of the object.
|
2023-06-24 12:44:23 +00:00
|
|
|
_marker: std::marker::PhantomData<T>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Clone for FFIHandle<T> {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
Self {
|
|
|
|
handle: self.handle,
|
|
|
|
_marker: std::marker::PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Copy for FFIHandle<T> {}
|
|
|
|
|
2023-06-25 14:28:51 +00:00
|
|
|
impl<T> Default for FFIHandle<T> {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
handle: 0,
|
|
|
|
_marker: std::marker::PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-24 13:05:58 +00:00
|
|
|
/// An FFIObject we can fetch from the FFIHandle. We store this in a hashmap to be able to fetch
|
|
|
|
/// the object from the handle, and to be able to drop the object when the FFI is done with the handle
|
2023-06-24 12:44:23 +00:00
|
|
|
#[derive(Clone)]
|
2023-06-24 13:05:58 +00:00
|
|
|
#[allow(clippy::missing_docs_in_private_items)] // I'm not documenting these items.
|
2023-06-24 12:44:23 +00:00
|
|
|
pub(super) enum FFIObject {
|
|
|
|
Ability(Arc<dyn Ability>),
|
2023-07-29 10:57:52 +00:00
|
|
|
EffectParameter(Arc<Parameter>),
|
2023-06-24 12:44:23 +00:00
|
|
|
StatisticSetU8(Arc<StatisticSet<u8>>),
|
|
|
|
StatisticSetI8(Arc<StatisticSet<i8>>),
|
|
|
|
StatisticSetU32(Arc<StatisticSet<u32>>),
|
|
|
|
StaticStatisticSetU16(Arc<StaticStatisticSet<u16>>),
|
|
|
|
Form(Arc<dyn Form>),
|
|
|
|
LearnableMoves(Arc<dyn LearnableMoves>),
|
|
|
|
GrowthRate(Arc<dyn GrowthRate>),
|
|
|
|
Item(Arc<dyn Item>),
|
|
|
|
SecondaryEffect(Arc<dyn SecondaryEffect>),
|
|
|
|
MoveData(Arc<dyn MoveData>),
|
|
|
|
Nature(Arc<dyn Nature>),
|
|
|
|
Species(Arc<dyn Species>),
|
|
|
|
|
|
|
|
SpeciesLibrary(Arc<dyn crate::static_data::SpeciesLibrary>),
|
|
|
|
MoveLibrary(Arc<dyn crate::static_data::MoveLibrary>),
|
|
|
|
AbilityLibrary(Arc<dyn crate::static_data::AbilityLibrary>),
|
|
|
|
ItemLibrary(Arc<dyn crate::static_data::ItemLibrary>),
|
|
|
|
GrowthRateLibrary(Arc<dyn crate::static_data::GrowthRateLibrary>),
|
|
|
|
LibrarySettings(Arc<dyn crate::static_data::LibrarySettings>),
|
|
|
|
NatureLibrary(Arc<dyn crate::static_data::NatureLibrary>),
|
|
|
|
TypeLibrary(Arc<dyn crate::static_data::TypeLibrary>),
|
|
|
|
StaticData(Arc<dyn crate::static_data::StaticData>),
|
|
|
|
|
|
|
|
// DynamicData
|
|
|
|
TurnChoice(Arc<crate::dynamic_data::TurnChoice>),
|
|
|
|
Pokemon(crate::dynamic_data::Pokemon),
|
|
|
|
LearnedMove(Arc<crate::dynamic_data::LearnedMove>),
|
|
|
|
PokemonParty(Arc<crate::dynamic_data::PokemonParty>),
|
|
|
|
BattleParty(Arc<crate::dynamic_data::BattleParty>),
|
|
|
|
Battle(crate::dynamic_data::Battle),
|
|
|
|
BattleSide(crate::dynamic_data::BattleSide),
|
|
|
|
BattleRandom(Arc<crate::dynamic_data::BattleRandom>),
|
|
|
|
|
|
|
|
// DynamicLibrary
|
|
|
|
BattleStatCalculator(Arc<dyn crate::dynamic_data::BattleStatCalculator>),
|
|
|
|
DamageLibrary(Arc<dyn crate::dynamic_data::DamageLibrary>),
|
|
|
|
MiscLibrary(Arc<dyn crate::dynamic_data::MiscLibrary>),
|
|
|
|
ScriptResolver(Arc<dyn crate::dynamic_data::ScriptResolver>),
|
|
|
|
DynamicLibrary(Arc<dyn crate::dynamic_data::DynamicLibrary>),
|
2023-06-30 09:32:00 +00:00
|
|
|
|
|
|
|
// Events
|
|
|
|
Event(Arc<crate::dynamic_data::EventData>),
|
2023-06-24 12:44:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
unsafe impl Send for FFIObject {}
|
|
|
|
|
|
|
|
unsafe impl Sync for FFIObject {}
|
|
|
|
|
2023-06-24 13:05:58 +00:00
|
|
|
/// The next handle to be used.
|
2023-06-25 14:28:51 +00:00
|
|
|
static NEXT_HANDLE: AtomicUsize = AtomicUsize::new(1);
|
2023-06-24 13:05:58 +00:00
|
|
|
/// A lookup to get an actual object from a handle.
|
2023-06-24 12:44:23 +00:00
|
|
|
static FFI_OBJECTS: LazyLock<RwLock<HashMap<usize, FFIObject>>> = LazyLock::new(|| RwLock::new(HashMap::new()));
|
2023-06-24 13:05:58 +00:00
|
|
|
/// A lookup to get a handle from an object.
|
2023-06-24 12:44:23 +00:00
|
|
|
static FFI_OBJECTS_INVERSE: LazyLock<RwLock<HashMap<FFIObject, usize>>> = LazyLock::new(|| RwLock::new(HashMap::new()));
|
|
|
|
|
|
|
|
impl<T> FFIHandle<T> {
|
2023-06-24 13:05:58 +00:00
|
|
|
/// Get a handle from an object.
|
2023-06-24 12:44:23 +00:00
|
|
|
pub fn get_handle(o: FFIObject) -> Self {
|
|
|
|
if let Some(handle) = FFI_OBJECTS_INVERSE.read().get(&o) {
|
|
|
|
return Self {
|
|
|
|
handle: *handle,
|
|
|
|
_marker: std::marker::PhantomData,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
let handle = NEXT_HANDLE.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
|
|
|
|
FFI_OBJECTS.write().insert(handle, o.clone());
|
|
|
|
FFI_OBJECTS_INVERSE.write().insert(o, handle);
|
|
|
|
Self {
|
|
|
|
handle,
|
|
|
|
_marker: std::marker::PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-24 13:05:58 +00:00
|
|
|
/// An empty handle. This is used when no value is returned. Represented as handle 0
|
2023-06-24 12:44:23 +00:00
|
|
|
pub fn none() -> Self {
|
|
|
|
Self {
|
|
|
|
handle: 0,
|
|
|
|
_marker: std::marker::PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-24 13:05:58 +00:00
|
|
|
/// Get the object from the handle.
|
2023-06-24 12:44:23 +00:00
|
|
|
#[allow(clippy::unwrap_used)] // Unwrap used, as it is a potential security bug if this fails
|
|
|
|
pub fn resolve(&self) -> FFIObject {
|
|
|
|
FFI_OBJECTS
|
|
|
|
.read()
|
|
|
|
.get(&self.handle)
|
2023-06-25 14:28:51 +00:00
|
|
|
.ok_or(anyhow!("Unable to get handle {} from FFI_OBJECTS", self.handle))
|
2023-06-24 12:44:23 +00:00
|
|
|
.unwrap()
|
|
|
|
.clone()
|
|
|
|
}
|
|
|
|
|
2023-06-24 13:05:58 +00:00
|
|
|
/// Check if the handle is empty.
|
2023-06-24 12:44:23 +00:00
|
|
|
pub fn is_none(&self) -> bool {
|
|
|
|
self.handle == 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[allow(clippy::from_over_into)]
|
|
|
|
impl<T> Into<anyhow_ext::Result<FFIObject>> for FFIHandle<T> {
|
|
|
|
fn into(self) -> anyhow_ext::Result<FFIObject> {
|
|
|
|
Ok(FFI_OBJECTS
|
|
|
|
.read()
|
|
|
|
.get(&self.handle)
|
|
|
|
.ok_or(anyhow!("Unable to get handle"))?
|
|
|
|
.clone())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Eq for FFIObject {}
|
|
|
|
|
2023-06-24 13:05:58 +00:00
|
|
|
/// A trait to convert a handle into an object.
|
2023-06-24 12:44:23 +00:00
|
|
|
#[allow(clippy::wrong_self_convention)]
|
|
|
|
pub(super) trait FromFFIHandle<T> {
|
2023-06-24 13:05:58 +00:00
|
|
|
/// Convert a handle into an object.
|
2023-06-24 12:44:23 +00:00
|
|
|
fn from_ffi_handle(&self) -> T;
|
2023-06-24 13:05:58 +00:00
|
|
|
/// Convert a handle into an object, returning `None` if the handle is empty.
|
2023-06-24 12:44:23 +00:00
|
|
|
fn from_ffi_handle_opt(&self) -> Option<T>;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Hash for FFIObject {
|
|
|
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
|
|
|
match self {
|
|
|
|
Self::Ability(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::EffectParameter(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::StatisticSetU8(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::StatisticSetI8(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::StatisticSetU32(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::StaticStatisticSetU16(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::Form(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::LearnableMoves(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::GrowthRate(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::Item(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::SecondaryEffect(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::MoveData(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::Nature(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::Species(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::SpeciesLibrary(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::MoveLibrary(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::AbilityLibrary(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::ItemLibrary(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::GrowthRateLibrary(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::LibrarySettings(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::NatureLibrary(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::TypeLibrary(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::StaticData(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::TurnChoice(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::Pokemon(a) => a.as_ptr().hash(state),
|
|
|
|
Self::LearnedMove(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::PokemonParty(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::BattleParty(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::Battle(a) => a.as_ptr().hash(state),
|
|
|
|
Self::BattleSide(a) => a.as_ptr().hash(state),
|
|
|
|
Self::BattleRandom(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::BattleStatCalculator(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::DamageLibrary(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::MiscLibrary(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::ScriptResolver(a) => Arc::as_ptr(a).hash(state),
|
|
|
|
Self::DynamicLibrary(a) => Arc::as_ptr(a).hash(state),
|
2023-06-30 09:32:00 +00:00
|
|
|
FFIObject::Event(a) => Arc::as_ptr(a).hash(state),
|
2023-06-24 12:44:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialEq for FFIObject {
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
|
|
|
match (self, other) {
|
|
|
|
(Self::Ability(a), Self::Ability(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::EffectParameter(a), Self::EffectParameter(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::StatisticSetU8(a), Self::StatisticSetU8(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::StatisticSetI8(a), Self::StatisticSetI8(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::StatisticSetU32(a), Self::StatisticSetU32(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::StaticStatisticSetU16(a), Self::StaticStatisticSetU16(b)) => {
|
|
|
|
Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr()
|
|
|
|
}
|
|
|
|
(Self::Form(a), Self::Form(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::LearnableMoves(a), Self::LearnableMoves(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::GrowthRate(a), Self::GrowthRate(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::Item(a), Self::Item(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::SecondaryEffect(a), Self::SecondaryEffect(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::MoveData(a), Self::MoveData(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::Nature(a), Self::Nature(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::Species(a), Self::Species(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::SpeciesLibrary(a), Self::SpeciesLibrary(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::MoveLibrary(a), Self::MoveLibrary(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::AbilityLibrary(a), Self::AbilityLibrary(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::ItemLibrary(a), Self::ItemLibrary(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::GrowthRateLibrary(a), Self::GrowthRateLibrary(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::LibrarySettings(a), Self::LibrarySettings(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::NatureLibrary(a), Self::NatureLibrary(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::TypeLibrary(a), Self::TypeLibrary(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::StaticData(a), Self::StaticData(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::TurnChoice(a), Self::TurnChoice(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::Pokemon(a), Self::Pokemon(b)) => a.eq(b),
|
|
|
|
(Self::LearnedMove(a), Self::LearnedMove(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::PokemonParty(a), Self::PokemonParty(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::BattleParty(a), Self::BattleParty(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::Battle(a), Self::Battle(b)) => a.eq(b),
|
|
|
|
(Self::BattleSide(a), Self::BattleSide(b)) => a.eq(b),
|
|
|
|
(Self::BattleRandom(a), Self::BattleRandom(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::BattleStatCalculator(a), Self::BattleStatCalculator(b)) => {
|
|
|
|
Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr()
|
|
|
|
}
|
|
|
|
(Self::DamageLibrary(a), Self::DamageLibrary(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::MiscLibrary(a), Self::MiscLibrary(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::ScriptResolver(a), Self::ScriptResolver(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
|
|
|
(Self::DynamicLibrary(a), Self::DynamicLibrary(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
2023-06-30 09:32:00 +00:00
|
|
|
(Self::Event(a), Self::Event(b)) => Arc::as_ptr(a).addr() == Arc::as_ptr(b).addr(),
|
2023-06-24 12:44:23 +00:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-24 13:05:58 +00:00
|
|
|
/// Helper macro to implement the `From` trait for a `FFIObject` enum variant, and the `FromFFIHandle`
|
|
|
|
/// trait for a `FFIHandle` enum variant.
|
2023-06-24 12:44:23 +00:00
|
|
|
macro_rules! ffi_obj_conversions {
|
|
|
|
($res_type:ty, $ffi_obj_name:ident) => {
|
|
|
|
impl From<$res_type> for FFIObject {
|
|
|
|
fn from(a: $res_type) -> Self {
|
|
|
|
Self::$ffi_obj_name(a)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FromFFIHandle<$res_type> for FFIHandle<$res_type> {
|
|
|
|
fn from_ffi_handle(&self) -> $res_type {
|
|
|
|
match self.resolve() {
|
|
|
|
FFIObject::$ffi_obj_name(a) => a.clone(),
|
|
|
|
_ => panic!("Invalid handle"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn from_ffi_handle_opt(&self) -> Option<$res_type> {
|
|
|
|
if (self.is_none()) {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
match self.resolve() {
|
|
|
|
FFIObject::$ffi_obj_name(a) => Some(a.clone()),
|
|
|
|
_ => panic!("Invalid handle"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
ffi_obj_conversions!(Arc<dyn Ability>, Ability);
|
2023-07-29 10:57:52 +00:00
|
|
|
ffi_obj_conversions!(Arc<Parameter>, EffectParameter);
|
2023-06-24 12:44:23 +00:00
|
|
|
ffi_obj_conversions!(Arc<StatisticSet<i8>>, StatisticSetI8);
|
|
|
|
ffi_obj_conversions!(Arc<StatisticSet<u8>>, StatisticSetU8);
|
|
|
|
ffi_obj_conversions!(Arc<StatisticSet<u32>>, StatisticSetU32);
|
|
|
|
ffi_obj_conversions!(Arc<StaticStatisticSet<u16>>, StaticStatisticSetU16);
|
|
|
|
ffi_obj_conversions!(Arc<dyn Form>, Form);
|
|
|
|
ffi_obj_conversions!(Arc<dyn LearnableMoves>, LearnableMoves);
|
|
|
|
ffi_obj_conversions!(Arc<dyn GrowthRate>, GrowthRate);
|
|
|
|
ffi_obj_conversions!(Arc<dyn Item>, Item);
|
|
|
|
ffi_obj_conversions!(Arc<dyn SecondaryEffect>, SecondaryEffect);
|
|
|
|
ffi_obj_conversions!(Arc<dyn MoveData>, MoveData);
|
|
|
|
ffi_obj_conversions!(Arc<dyn Nature>, Nature);
|
|
|
|
ffi_obj_conversions!(Arc<dyn Species>, Species);
|
|
|
|
ffi_obj_conversions!(Arc<dyn crate::static_data::SpeciesLibrary>, SpeciesLibrary);
|
|
|
|
ffi_obj_conversions!(Arc<dyn crate::static_data::MoveLibrary>, MoveLibrary);
|
|
|
|
ffi_obj_conversions!(Arc<dyn crate::static_data::AbilityLibrary>, AbilityLibrary);
|
|
|
|
ffi_obj_conversions!(Arc<dyn crate::static_data::ItemLibrary>, ItemLibrary);
|
|
|
|
ffi_obj_conversions!(Arc<dyn crate::static_data::GrowthRateLibrary>, GrowthRateLibrary);
|
|
|
|
ffi_obj_conversions!(Arc<dyn crate::static_data::LibrarySettings>, LibrarySettings);
|
|
|
|
ffi_obj_conversions!(Arc<dyn crate::static_data::NatureLibrary>, NatureLibrary);
|
|
|
|
ffi_obj_conversions!(Arc<dyn crate::static_data::TypeLibrary>, TypeLibrary);
|
|
|
|
ffi_obj_conversions!(Arc<dyn crate::static_data::StaticData>, StaticData);
|
|
|
|
ffi_obj_conversions!(Arc<crate::dynamic_data::TurnChoice>, TurnChoice);
|
|
|
|
ffi_obj_conversions!(crate::dynamic_data::Pokemon, Pokemon);
|
|
|
|
ffi_obj_conversions!(Arc<crate::dynamic_data::LearnedMove>, LearnedMove);
|
|
|
|
ffi_obj_conversions!(Arc<crate::dynamic_data::PokemonParty>, PokemonParty);
|
|
|
|
ffi_obj_conversions!(Arc<crate::dynamic_data::BattleParty>, BattleParty);
|
|
|
|
ffi_obj_conversions!(crate::dynamic_data::Battle, Battle);
|
|
|
|
ffi_obj_conversions!(crate::dynamic_data::BattleSide, BattleSide);
|
|
|
|
ffi_obj_conversions!(Arc<crate::dynamic_data::BattleRandom>, BattleRandom);
|
|
|
|
ffi_obj_conversions!(Arc<dyn crate::dynamic_data::BattleStatCalculator>, BattleStatCalculator);
|
|
|
|
ffi_obj_conversions!(Arc<dyn crate::dynamic_data::DamageLibrary>, DamageLibrary);
|
|
|
|
ffi_obj_conversions!(Arc<dyn crate::dynamic_data::MiscLibrary>, MiscLibrary);
|
|
|
|
ffi_obj_conversions!(Arc<dyn crate::dynamic_data::ScriptResolver>, ScriptResolver);
|
|
|
|
ffi_obj_conversions!(Arc<dyn crate::dynamic_data::DynamicLibrary>, DynamicLibrary);
|
2023-06-30 09:32:00 +00:00
|
|
|
ffi_obj_conversions!(Arc<crate::dynamic_data::EventData>, Event);
|