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:
@@ -1,105 +1,102 @@
|
||||
use crate::dynamic_data::{FleeChoice, LearnedMove, MoveChoice, PassChoice, Pokemon, TurnChoice};
|
||||
use crate::ffi::{ExternPointer, IdentifiablePointer, NativeResult, OwnedPtr};
|
||||
use crate::ffi::ffi_handle::{FFIHandle, FromFFIHandle};
|
||||
use crate::ffi::FFIResult;
|
||||
use anyhow::anyhow;
|
||||
use std::ptr::drop_in_place;
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Disposes a turn choice.
|
||||
#[no_mangle]
|
||||
extern "C" fn turn_choice_drop(choice: OwnedPtr<TurnChoice>) {
|
||||
unsafe { drop_in_place(choice) }
|
||||
}
|
||||
|
||||
/// Get the user of the given choice.
|
||||
#[no_mangle]
|
||||
extern "C" fn turn_choice_user(choice: ExternPointer<TurnChoice>) -> IdentifiablePointer<Pokemon> {
|
||||
choice.as_ref().user().clone().into()
|
||||
extern "C" fn turn_choice_user(choice: FFIHandle<Arc<TurnChoice>>) -> FFIHandle<Pokemon> {
|
||||
FFIHandle::get_handle(choice.from_ffi_handle().user().clone().into())
|
||||
}
|
||||
|
||||
/// Get the speed of the user for the choice. Note that this speed is the speed of the Pokemon
|
||||
/// at the start of the turn!
|
||||
#[no_mangle]
|
||||
extern "C" fn turn_choice_speed(choice: ExternPointer<TurnChoice>) -> u32 {
|
||||
choice.as_ref().speed()
|
||||
extern "C" fn turn_choice_speed(choice: FFIHandle<Arc<TurnChoice>>) -> u32 {
|
||||
choice.from_ffi_handle().speed()
|
||||
}
|
||||
|
||||
/// Gets whether or not the choice has failed. If we notice this when we execute the choice, we
|
||||
/// will not execute it.
|
||||
#[no_mangle]
|
||||
extern "C" fn turn_choice_has_failed(choice: ExternPointer<TurnChoice>) -> u8 {
|
||||
u8::from(choice.as_ref().has_failed())
|
||||
extern "C" fn turn_choice_has_failed(choice: FFIHandle<Arc<TurnChoice>>) -> u8 {
|
||||
u8::from(choice.from_ffi_handle().has_failed())
|
||||
}
|
||||
|
||||
/// Fails the choice. This will prevent it from executing and run a specific fail handling during
|
||||
/// execution. Note that this can not be undone.
|
||||
#[no_mangle]
|
||||
extern "C" fn turn_choice_fail(choice: ExternPointer<TurnChoice>) {
|
||||
choice.as_ref().fail()
|
||||
extern "C" fn turn_choice_fail(choice: FFIHandle<Arc<TurnChoice>>) {
|
||||
choice.from_ffi_handle().fail()
|
||||
}
|
||||
|
||||
/// Creates a new Turn Choice with a move to use.
|
||||
#[no_mangle]
|
||||
extern "C" fn turn_choice_move_new(
|
||||
user: ExternPointer<Pokemon>,
|
||||
learned_move: ExternPointer<Arc<LearnedMove>>,
|
||||
user: FFIHandle<Pokemon>,
|
||||
learned_move: FFIHandle<Arc<LearnedMove>>,
|
||||
target_side: u8,
|
||||
target_index: u8,
|
||||
) -> IdentifiablePointer<TurnChoice> {
|
||||
Box::new(TurnChoice::Move(MoveChoice::new(
|
||||
user.as_ref().clone(),
|
||||
learned_move.as_ref().clone(),
|
||||
target_side,
|
||||
target_index,
|
||||
)))
|
||||
.into()
|
||||
) -> FFIHandle<Arc<TurnChoice>> {
|
||||
FFIHandle::get_handle(
|
||||
Arc::new(TurnChoice::Move(MoveChoice::new(
|
||||
user.from_ffi_handle(),
|
||||
learned_move.from_ffi_handle(),
|
||||
target_side,
|
||||
target_index,
|
||||
)))
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
/// The actual learned move on the Pokemon we use for this choice.
|
||||
#[no_mangle]
|
||||
extern "C" fn turn_choice_move_learned_move(
|
||||
choice: ExternPointer<TurnChoice>,
|
||||
) -> NativeResult<IdentifiablePointer<Arc<LearnedMove>>> {
|
||||
if let TurnChoice::Move(c) = choice.as_ref() {
|
||||
return NativeResult::ok(c.used_move().clone().into());
|
||||
choice: FFIHandle<Arc<TurnChoice>>,
|
||||
) -> FFIResult<FFIHandle<Arc<LearnedMove>>> {
|
||||
if let TurnChoice::Move(c) = choice.from_ffi_handle().deref() {
|
||||
return FFIResult::ok(FFIHandle::get_handle(c.used_move().clone().into()));
|
||||
}
|
||||
NativeResult::err(anyhow!("Turn choice was not a learned move"))
|
||||
FFIResult::err(anyhow!("Turn choice was not a learned move"))
|
||||
}
|
||||
|
||||
/// The target side the move is aimed at.
|
||||
#[no_mangle]
|
||||
extern "C" fn turn_choice_move_target_side(choice: ExternPointer<TurnChoice>) -> NativeResult<u8> {
|
||||
if let TurnChoice::Move(c) = choice.as_ref() {
|
||||
return NativeResult::ok(c.target_side());
|
||||
extern "C" fn turn_choice_move_target_side(choice: FFIHandle<Arc<TurnChoice>>) -> FFIResult<u8> {
|
||||
if let TurnChoice::Move(c) = choice.from_ffi_handle().deref() {
|
||||
return FFIResult::ok(c.target_side());
|
||||
}
|
||||
NativeResult::err(anyhow!("Turn choice was not a learned move"))
|
||||
FFIResult::err(anyhow!("Turn choice was not a learned move"))
|
||||
}
|
||||
|
||||
/// The Pokemon index on the side we're aiming at.
|
||||
#[no_mangle]
|
||||
extern "C" fn turn_choice_move_target_index(choice: ExternPointer<TurnChoice>) -> NativeResult<u8> {
|
||||
if let TurnChoice::Move(c) = choice.as_ref() {
|
||||
return NativeResult::ok(c.target_index());
|
||||
extern "C" fn turn_choice_move_target_index(choice: FFIHandle<Arc<TurnChoice>>) -> FFIResult<u8> {
|
||||
if let TurnChoice::Move(c) = choice.from_ffi_handle().deref() {
|
||||
return FFIResult::ok(c.target_index());
|
||||
}
|
||||
NativeResult::err(anyhow!("Turn choice was not a learned move"))
|
||||
FFIResult::err(anyhow!("Turn choice was not a learned move"))
|
||||
}
|
||||
|
||||
/// The priority of the move choice at the beginning of the turn.
|
||||
#[no_mangle]
|
||||
extern "C" fn turn_choice_move_priority(choice: ExternPointer<TurnChoice>) -> NativeResult<i8> {
|
||||
if let TurnChoice::Move(c) = choice.as_ref() {
|
||||
return NativeResult::ok(c.priority());
|
||||
extern "C" fn turn_choice_move_priority(choice: FFIHandle<Arc<TurnChoice>>) -> FFIResult<i8> {
|
||||
if let TurnChoice::Move(c) = choice.from_ffi_handle().deref() {
|
||||
return FFIResult::ok(c.priority());
|
||||
}
|
||||
NativeResult::err(anyhow!("Turn choice was not a learned move"))
|
||||
FFIResult::err(anyhow!("Turn choice was not a learned move"))
|
||||
}
|
||||
|
||||
/// Creates a new Turn Choice for the user to flee.
|
||||
#[no_mangle]
|
||||
extern "C" fn turn_choice_flee_new(user: ExternPointer<Pokemon>) -> IdentifiablePointer<TurnChoice> {
|
||||
Box::new(TurnChoice::Flee(FleeChoice::new(user.as_ref().clone()))).into()
|
||||
extern "C" fn turn_choice_flee_new(user: FFIHandle<Pokemon>) -> FFIHandle<Arc<TurnChoice>> {
|
||||
FFIHandle::get_handle(Arc::new(TurnChoice::Flee(FleeChoice::new(user.from_ffi_handle()))).into())
|
||||
}
|
||||
|
||||
/// Creates a new Turn Choice for the user to pass the turn.
|
||||
#[no_mangle]
|
||||
extern "C" fn turn_choice_pass_new(user: ExternPointer<Pokemon>) -> IdentifiablePointer<TurnChoice> {
|
||||
Box::new(TurnChoice::Pass(PassChoice::new(user.as_ref().clone()))).into()
|
||||
extern "C" fn turn_choice_pass_new(user: FFIHandle<Pokemon>) -> FFIHandle<Arc<TurnChoice>> {
|
||||
FFIHandle::get_handle(Arc::new(TurnChoice::Pass(PassChoice::new(user.from_ffi_handle()))).into())
|
||||
}
|
||||
|
||||
@@ -1,63 +1,61 @@
|
||||
use crate::dynamic_data::{BattleStatCalculator, Gen7BattleStatCalculator, Pokemon};
|
||||
use crate::ffi::{ExternPointer, IdentifiablePointer, NativeResult, OwnedPtr};
|
||||
use crate::ffi::ffi_handle::{FFIHandle, FromFFIHandle};
|
||||
use crate::ffi::{ExternPointer, FFIResult};
|
||||
use crate::static_data::{Statistic, StatisticSet};
|
||||
use std::ptr::drop_in_place;
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Creates a new Gen 7 battle stat calculator
|
||||
#[no_mangle]
|
||||
extern "C" fn gen_7_battle_stat_calculator_new() -> IdentifiablePointer<Box<dyn BattleStatCalculator>> {
|
||||
let v: Box<dyn BattleStatCalculator> = Box::new(Gen7BattleStatCalculator::new());
|
||||
let id = v.value_identifier();
|
||||
let ptr = Box::into_raw(Box::new(v));
|
||||
IdentifiablePointer::new(ptr, id)
|
||||
}
|
||||
|
||||
/// Drops a battle stat calculator.
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_stat_calculator_drop(ptr: OwnedPtr<Box<dyn BattleStatCalculator>>) {
|
||||
unsafe { drop_in_place(ptr) };
|
||||
extern "C" fn gen_7_battle_stat_calculator_new() -> FFIHandle<Arc<dyn BattleStatCalculator>> {
|
||||
let v: Arc<dyn BattleStatCalculator> = Arc::new(Gen7BattleStatCalculator::new());
|
||||
FFIHandle::get_handle(v.into())
|
||||
}
|
||||
|
||||
/// Calculate all the flat stats of a Pokemon, disregarding stat boosts.
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_stat_calculator_calculate_flat_stats(
|
||||
ptr: ExternPointer<Box<dyn BattleStatCalculator>>,
|
||||
ptr: FFIHandle<Arc<dyn BattleStatCalculator>>,
|
||||
pokemon: ExternPointer<Pokemon>,
|
||||
mut stats: ExternPointer<Box<StatisticSet<u32>>>,
|
||||
) -> NativeResult<()> {
|
||||
ptr.as_ref()
|
||||
.calculate_flat_stats(pokemon.as_ref(), stats.as_mut())
|
||||
stats: FFIHandle<Arc<StatisticSet<u32>>>,
|
||||
) -> FFIResult<()> {
|
||||
ptr.from_ffi_handle()
|
||||
.calculate_flat_stats(pokemon.as_ref(), stats.from_ffi_handle().deref())
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Calculate a single flat stat of a Pokemon, disregarding stat boost
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_stat_calculator_calculate_flat_stat(
|
||||
ptr: ExternPointer<Box<dyn BattleStatCalculator>>,
|
||||
pokemon: ExternPointer<Pokemon>,
|
||||
ptr: FFIHandle<Arc<dyn BattleStatCalculator>>,
|
||||
pokemon: FFIHandle<Pokemon>,
|
||||
stat: Statistic,
|
||||
) -> NativeResult<u32> {
|
||||
ptr.as_ref().calculate_flat_stat(pokemon.as_ref(), stat).into()
|
||||
) -> FFIResult<u32> {
|
||||
ptr.from_ffi_handle()
|
||||
.calculate_flat_stat(&pokemon.from_ffi_handle(), stat)
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Calculate all the boosted stats of a Pokemon, including stat boosts.
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_stat_calculator_calculate_boosted_stats(
|
||||
ptr: ExternPointer<Box<dyn BattleStatCalculator>>,
|
||||
pokemon: ExternPointer<Pokemon>,
|
||||
mut stats: ExternPointer<Box<StatisticSet<u32>>>,
|
||||
) -> NativeResult<()> {
|
||||
ptr.as_ref()
|
||||
.calculate_boosted_stats(pokemon.as_ref(), stats.as_mut())
|
||||
ptr: FFIHandle<Arc<dyn BattleStatCalculator>>,
|
||||
pokemon: FFIHandle<Pokemon>,
|
||||
stats: FFIHandle<Arc<StatisticSet<u32>>>,
|
||||
) -> FFIResult<()> {
|
||||
ptr.from_ffi_handle()
|
||||
.calculate_boosted_stats(&pokemon.from_ffi_handle(), stats.from_ffi_handle().deref())
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Calculate a single boosted stat of a Pokemon, including stat boosts.
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_stat_calculator_calculate_boosted_stat(
|
||||
ptr: ExternPointer<Box<dyn BattleStatCalculator>>,
|
||||
pokemon: ExternPointer<Pokemon>,
|
||||
ptr: FFIHandle<Arc<dyn BattleStatCalculator>>,
|
||||
pokemon: FFIHandle<Pokemon>,
|
||||
stat: Statistic,
|
||||
) -> NativeResult<u32> {
|
||||
ptr.as_ref().calculate_boosted_stat(pokemon.as_ref(), stat).into()
|
||||
) -> FFIResult<u32> {
|
||||
ptr.from_ffi_handle()
|
||||
.calculate_boosted_stat(&pokemon.from_ffi_handle(), stat)
|
||||
.into()
|
||||
}
|
||||
|
||||
@@ -1,19 +1,11 @@
|
||||
use crate::dynamic_data::{DamageLibrary, Gen7DamageLibrary};
|
||||
use crate::ffi::{IdentifiablePointer, OwnedPtr};
|
||||
use std::ptr::drop_in_place;
|
||||
use crate::ffi::ffi_handle::FFIHandle;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Creates a new generation 7 damage library. `has_randomness` defines whether a random damage
|
||||
/// modifier (0.85x - 1.00x) is applied to the calculated damage.
|
||||
#[no_mangle]
|
||||
extern "C" fn gen_7_damage_library_new(has_randomness: u8) -> IdentifiablePointer<Box<dyn DamageLibrary>> {
|
||||
let v: Box<dyn DamageLibrary> = Box::new(Gen7DamageLibrary::new(has_randomness == 1));
|
||||
let id = v.value_identifier();
|
||||
let ptr = Box::into_raw(Box::new(v));
|
||||
IdentifiablePointer::new(ptr, id)
|
||||
}
|
||||
|
||||
/// Drops a DamageLibrary.
|
||||
#[no_mangle]
|
||||
extern "C" fn damage_library_drop(ptr: OwnedPtr<Box<dyn DamageLibrary>>) {
|
||||
unsafe { drop_in_place(ptr) };
|
||||
extern "C" fn gen_7_damage_library_new(has_randomness: u8) -> FFIHandle<Arc<dyn DamageLibrary>> {
|
||||
let v: Arc<dyn DamageLibrary> = Arc::new(Gen7DamageLibrary::new(has_randomness == 1));
|
||||
FFIHandle::get_handle(v.into())
|
||||
}
|
||||
|
||||
@@ -1,68 +1,59 @@
|
||||
use crate::dynamic_data::{
|
||||
BattleStatCalculator, DamageLibrary, DynamicLibrary, DynamicLibraryImpl, MiscLibrary, ScriptResolver,
|
||||
};
|
||||
use crate::ffi::{ExternPointer, IdentifiablePointer, OwnedPtr};
|
||||
use crate::ffi::ffi_handle::{FFIHandle, FromFFIHandle};
|
||||
use crate::static_data::StaticData;
|
||||
use std::ptr::drop_in_place;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Instantiates a new DynamicLibrary with given parameters.
|
||||
#[no_mangle]
|
||||
extern "C" fn dynamic_library_new(
|
||||
static_data: OwnedPtr<Arc<dyn StaticData>>,
|
||||
stat_calculator: OwnedPtr<Arc<dyn BattleStatCalculator>>,
|
||||
damage_library: OwnedPtr<Arc<dyn DamageLibrary>>,
|
||||
misc_library: OwnedPtr<Arc<dyn MiscLibrary>>,
|
||||
script_resolver: OwnedPtr<Box<dyn ScriptResolver>>,
|
||||
) -> IdentifiablePointer<Arc<dyn DynamicLibrary>> {
|
||||
unsafe {
|
||||
let a: Arc<dyn DynamicLibrary> = Arc::new(DynamicLibraryImpl::new(
|
||||
static_data.read(),
|
||||
stat_calculator.read(),
|
||||
damage_library.read(),
|
||||
misc_library.read(),
|
||||
*Box::from_raw(script_resolver),
|
||||
));
|
||||
a.into()
|
||||
}
|
||||
}
|
||||
|
||||
/// Drops a dynamic library.
|
||||
#[no_mangle]
|
||||
extern "C" fn dynamic_library_drop(ptr: OwnedPtr<Arc<dyn DynamicLibrary>>) {
|
||||
unsafe { drop_in_place(ptr) };
|
||||
static_data: FFIHandle<Arc<dyn StaticData>>,
|
||||
stat_calculator: FFIHandle<Arc<dyn BattleStatCalculator>>,
|
||||
damage_library: FFIHandle<Arc<dyn DamageLibrary>>,
|
||||
misc_library: FFIHandle<Arc<dyn MiscLibrary>>,
|
||||
script_resolver: FFIHandle<Arc<dyn ScriptResolver>>,
|
||||
) -> FFIHandle<Arc<dyn DynamicLibrary>> {
|
||||
let a: Arc<dyn DynamicLibrary> = Arc::new(DynamicLibraryImpl::new(
|
||||
static_data.from_ffi_handle(),
|
||||
stat_calculator.from_ffi_handle(),
|
||||
damage_library.from_ffi_handle(),
|
||||
misc_library.from_ffi_handle(),
|
||||
script_resolver.from_ffi_handle(),
|
||||
));
|
||||
FFIHandle::get_handle(a.into())
|
||||
}
|
||||
|
||||
/// The static data is the immutable storage data for this library.
|
||||
#[no_mangle]
|
||||
extern "C" fn dynamic_library_get_static_data(
|
||||
ptr: ExternPointer<Arc<dyn DynamicLibrary>>,
|
||||
) -> IdentifiablePointer<Arc<dyn StaticData>> {
|
||||
ptr.as_ref().static_data().clone().into()
|
||||
ptr: FFIHandle<Arc<dyn DynamicLibrary>>,
|
||||
) -> FFIHandle<Arc<dyn StaticData>> {
|
||||
FFIHandle::get_handle(ptr.from_ffi_handle().static_data().clone().into())
|
||||
}
|
||||
|
||||
/// The stat calculator deals with the calculation of flat and boosted stats, based on the
|
||||
/// Pokemons attributes.
|
||||
#[no_mangle]
|
||||
extern "C" fn dynamic_library_get_stat_calculator(
|
||||
ptr: ExternPointer<Arc<dyn DynamicLibrary>>,
|
||||
) -> IdentifiablePointer<Arc<dyn BattleStatCalculator>> {
|
||||
ptr.as_ref().stat_calculator().clone().into()
|
||||
ptr: FFIHandle<Arc<dyn DynamicLibrary>>,
|
||||
) -> FFIHandle<Arc<dyn BattleStatCalculator>> {
|
||||
FFIHandle::get_handle(ptr.from_ffi_handle().stat_calculator().clone().into())
|
||||
}
|
||||
|
||||
/// The damage calculator deals with the calculation of things relating to damage.
|
||||
#[no_mangle]
|
||||
extern "C" fn dynamic_library_get_damage_calculator(
|
||||
ptr: ExternPointer<Arc<dyn DynamicLibrary>>,
|
||||
) -> IdentifiablePointer<Arc<dyn DamageLibrary>> {
|
||||
ptr.as_ref().damage_calculator().clone().into()
|
||||
ptr: FFIHandle<Arc<dyn DynamicLibrary>>,
|
||||
) -> FFIHandle<Arc<dyn DamageLibrary>> {
|
||||
FFIHandle::get_handle(ptr.from_ffi_handle().damage_calculator().clone().into())
|
||||
}
|
||||
|
||||
/// The Misc Library holds minor functions that do not fall in any of the other libraries and
|
||||
/// calculators.
|
||||
#[no_mangle]
|
||||
extern "C" fn dynamic_library_get_misc_library(
|
||||
ptr: ExternPointer<Arc<dyn DynamicLibrary>>,
|
||||
) -> IdentifiablePointer<Arc<dyn MiscLibrary>> {
|
||||
ptr.as_ref().misc_library().clone().into()
|
||||
ptr: FFIHandle<Arc<dyn DynamicLibrary>>,
|
||||
) -> FFIHandle<Arc<dyn MiscLibrary>> {
|
||||
FFIHandle::get_handle(ptr.from_ffi_handle().misc_library().clone().into())
|
||||
}
|
||||
|
||||
@@ -1,18 +1,10 @@
|
||||
use crate::dynamic_data::{Gen7MiscLibrary, MiscLibrary};
|
||||
use crate::ffi::{IdentifiablePointer, OwnedPtr};
|
||||
use std::ptr::drop_in_place;
|
||||
use crate::ffi::ffi_handle::FFIHandle;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Instantiates a new MiscLibrary.
|
||||
#[no_mangle]
|
||||
extern "C" fn gen_7_misc_library_new() -> IdentifiablePointer<Box<dyn MiscLibrary>> {
|
||||
let v: Box<dyn MiscLibrary> = Box::new(Gen7MiscLibrary::new());
|
||||
let id = v.value_identifier();
|
||||
let ptr = Box::into_raw(Box::new(v));
|
||||
IdentifiablePointer::new(ptr, id)
|
||||
}
|
||||
|
||||
/// Drops a MiscLibrary.
|
||||
#[no_mangle]
|
||||
extern "C" fn misc_library_drop(ptr: OwnedPtr<Box<dyn MiscLibrary>>) {
|
||||
unsafe { drop_in_place(ptr) };
|
||||
extern "C" fn gen_7_misc_library_new() -> FFIHandle<Arc<dyn MiscLibrary>> {
|
||||
let v: Arc<dyn MiscLibrary> = Arc::new(Gen7MiscLibrary::new());
|
||||
FFIHandle::get_handle(v.into())
|
||||
}
|
||||
|
||||
@@ -1,49 +1,45 @@
|
||||
use crate::dynamic_data::{EmptyScriptResolver, ScriptResolver};
|
||||
use crate::ffi::{IdentifiablePointer, OwnedPtr};
|
||||
use std::ptr::drop_in_place;
|
||||
use crate::ffi::ffi_handle::FFIHandle;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Instantiates a basic empty script resolver, that always returns None.
|
||||
#[no_mangle]
|
||||
extern "C" fn empty_script_resolver_new() -> IdentifiablePointer<Box<dyn ScriptResolver>> {
|
||||
let v: Box<dyn ScriptResolver> = Box::new(EmptyScriptResolver {
|
||||
identifier: Default::default(),
|
||||
});
|
||||
let id = v.value_identifier();
|
||||
let ptr = Box::into_raw(Box::new(v));
|
||||
IdentifiablePointer::new(ptr, id)
|
||||
}
|
||||
|
||||
/// Drops a script resolver.
|
||||
#[no_mangle]
|
||||
extern "C" fn script_resolver_drop(ptr: OwnedPtr<Box<dyn ScriptResolver>>) {
|
||||
unsafe { drop_in_place(ptr) };
|
||||
extern "C" fn empty_script_resolver_new() -> FFIHandle<Arc<dyn ScriptResolver>> {
|
||||
let v: Arc<dyn ScriptResolver> = Arc::new(EmptyScriptResolver {});
|
||||
FFIHandle::get_handle(v.into())
|
||||
}
|
||||
|
||||
/// Foreign function interfaces for the Webassembly script resolver.
|
||||
#[cfg(feature = "wasm")]
|
||||
mod web_assembly_script_resolver {
|
||||
use crate::dynamic_data::ScriptResolver;
|
||||
use crate::ffi::{ExternPointer, IdentifiablePointer, NativeResult};
|
||||
use crate::ffi::ffi_handle::{FFIHandle, FromFFIHandle};
|
||||
use crate::ffi::FFIResult;
|
||||
use crate::script_implementations::wasm::script_resolver::WebAssemblyScriptResolver;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Instantiates a new WebAssemblyScriptResolver.
|
||||
#[no_mangle]
|
||||
extern "C" fn webassembly_script_resolver_new() -> IdentifiablePointer<Box<dyn ScriptResolver>> {
|
||||
let v: Box<dyn ScriptResolver> = WebAssemblyScriptResolver::new();
|
||||
let id = v.value_identifier();
|
||||
let ptr = Box::into_raw(Box::new(v));
|
||||
IdentifiablePointer::new(ptr, id)
|
||||
extern "C" fn webassembly_script_resolver_new() -> FFIHandle<Arc<dyn ScriptResolver>> {
|
||||
let v: Arc<dyn ScriptResolver> = WebAssemblyScriptResolver::new();
|
||||
FFIHandle::get_handle(v.into())
|
||||
}
|
||||
|
||||
/// Load a compiled WASM module.
|
||||
#[no_mangle]
|
||||
extern "C" fn webassembly_script_resolver_load_wasm_from_bytes(
|
||||
mut ptr: ExternPointer<Box<WebAssemblyScriptResolver>>,
|
||||
ptr: FFIHandle<Arc<dyn ScriptResolver>>,
|
||||
arr: *const u8,
|
||||
len: usize,
|
||||
) -> NativeResult<()> {
|
||||
) -> FFIResult<()> {
|
||||
#[allow(clippy::unwrap_used)] // Unwrap used, but we know it cannot fail.
|
||||
unsafe {
|
||||
ptr.as_mut()
|
||||
let script_resolver = ptr.from_ffi_handle();
|
||||
let wasm_script_resolver = script_resolver
|
||||
.as_any()
|
||||
.downcast_ref::<WebAssemblyScriptResolver>()
|
||||
.unwrap();
|
||||
wasm_script_resolver
|
||||
.load_wasm_from_bytes(std::slice::from_raw_parts(arr, len))
|
||||
.into()
|
||||
}
|
||||
@@ -51,9 +47,13 @@ mod web_assembly_script_resolver {
|
||||
|
||||
/// Tells the script resolver we're done loading wasm modules, and to finalize the resolver.
|
||||
#[no_mangle]
|
||||
extern "C" fn webassembly_script_resolver_finalize(
|
||||
mut ptr: ExternPointer<Box<WebAssemblyScriptResolver>>,
|
||||
) -> NativeResult<()> {
|
||||
ptr.as_mut().finalize().into()
|
||||
#[allow(clippy::unwrap_used)] // Unwrap used, but we know it cannot fail.
|
||||
extern "C" fn webassembly_script_resolver_finalize(ptr: FFIHandle<Arc<dyn ScriptResolver>>) -> FFIResult<()> {
|
||||
let script_resolver = ptr.from_ffi_handle();
|
||||
let wasm_script_resolver = script_resolver
|
||||
.as_any()
|
||||
.downcast_ref::<WebAssemblyScriptResolver>()
|
||||
.unwrap();
|
||||
wasm_script_resolver.finalize().into()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,16 +2,18 @@ use crate::dynamic_data::{
|
||||
Battle, BattleParty, BattleRandom, BattleResult, BattleSide, DynamicLibrary, Pokemon, TurnChoice,
|
||||
};
|
||||
use crate::ffi::dynamic_data::models::native_event_hook::NativeEventHook;
|
||||
use crate::ffi::{ExternPointer, IdentifiablePointer, NativeResult, OwnedPtr};
|
||||
use crate::ffi::ffi_handle::{FFIHandle, FromFFIHandle};
|
||||
use crate::ffi::FFIResult;
|
||||
use anyhow::anyhow;
|
||||
use std::ffi::{c_char, CStr, CString};
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Initializes a new battle.
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_new(
|
||||
library: ExternPointer<Arc<dyn DynamicLibrary>>,
|
||||
parties: *const OwnedPtr<Arc<BattleParty>>,
|
||||
library: FFIHandle<Arc<dyn DynamicLibrary>>,
|
||||
parties: *const FFIHandle<Arc<BattleParty>>,
|
||||
parties_length: usize,
|
||||
can_flee: u8,
|
||||
number_of_sides: u8,
|
||||
@@ -19,11 +21,11 @@ extern "C" fn battle_new(
|
||||
// NOTE: Split into two due to u128 not being ABI safe: https://github.com/rust-lang/rust/issues/54341
|
||||
random_seed_1: u64,
|
||||
random_seed_2: u64,
|
||||
) -> IdentifiablePointer<Battle> {
|
||||
) -> FFIHandle<Battle> {
|
||||
let parties = unsafe {
|
||||
std::slice::from_raw_parts(parties, parties_length)
|
||||
.iter()
|
||||
.map(|x| *Box::from_raw(*x))
|
||||
.map(|x| x.from_ffi_handle())
|
||||
.collect()
|
||||
};
|
||||
|
||||
@@ -34,99 +36,98 @@ extern "C" fn battle_new(
|
||||
};
|
||||
let random_seed = if random_seed == 0 { None } else { Some(random_seed) };
|
||||
|
||||
Battle::new(
|
||||
library.as_ref().clone(),
|
||||
parties,
|
||||
can_flee == 1,
|
||||
number_of_sides,
|
||||
pokemon_per_side,
|
||||
random_seed,
|
||||
FFIHandle::get_handle(
|
||||
Battle::new(
|
||||
library.from_ffi_handle(),
|
||||
parties,
|
||||
can_flee == 1,
|
||||
number_of_sides,
|
||||
pokemon_per_side,
|
||||
random_seed,
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.into()
|
||||
}
|
||||
|
||||
/// The library the battle uses for handling.
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_library(ptr: ExternPointer<Arc<Battle>>) -> IdentifiablePointer<Arc<dyn DynamicLibrary>> {
|
||||
ptr.as_ref().library().clone().into()
|
||||
extern "C" fn battle_library(ptr: FFIHandle<Battle>) -> FFIHandle<Arc<dyn DynamicLibrary>> {
|
||||
FFIHandle::get_handle(ptr.from_ffi_handle().library().clone().into())
|
||||
}
|
||||
|
||||
/// The length of the list of all different parties in the battle.
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_parties_length(ptr: ExternPointer<Arc<Battle>>) -> usize {
|
||||
ptr.as_ref().parties().len()
|
||||
extern "C" fn battle_parties_length(ptr: FFIHandle<Battle>) -> usize {
|
||||
ptr.from_ffi_handle().parties().len()
|
||||
}
|
||||
|
||||
/// Get a party in the battle.
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_parties_get(
|
||||
ptr: ExternPointer<Arc<Battle>>,
|
||||
index: usize,
|
||||
) -> IdentifiablePointer<Arc<BattleParty>> {
|
||||
if let Some(v) = ptr.as_ref().parties().get(index) {
|
||||
v.clone().into()
|
||||
extern "C" fn battle_parties_get(ptr: FFIHandle<Battle>, index: usize) -> FFIHandle<Arc<BattleParty>> {
|
||||
if let Some(v) = ptr.from_ffi_handle().parties().get(index) {
|
||||
FFIHandle::get_handle(v.clone().into())
|
||||
} else {
|
||||
IdentifiablePointer::none()
|
||||
FFIHandle::none()
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether or not Pokemon can flee from the battle.
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_can_flee(ptr: ExternPointer<Arc<Battle>>) -> u8 {
|
||||
u8::from(ptr.as_ref().can_flee())
|
||||
extern "C" fn battle_can_flee(ptr: FFIHandle<Battle>) -> u8 {
|
||||
u8::from(ptr.from_ffi_handle().can_flee())
|
||||
}
|
||||
|
||||
/// The number of sides in the battle. Typically 2.
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_number_of_sides(ptr: ExternPointer<Arc<Battle>>) -> u8 {
|
||||
ptr.as_ref().number_of_sides()
|
||||
extern "C" fn battle_number_of_sides(ptr: FFIHandle<Battle>) -> u8 {
|
||||
ptr.from_ffi_handle().number_of_sides()
|
||||
}
|
||||
|
||||
/// The number of Pokemon that can be on each side.
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_pokemon_per_side(ptr: ExternPointer<Arc<Battle>>) -> u8 {
|
||||
ptr.as_ref().pokemon_per_side()
|
||||
extern "C" fn battle_pokemon_per_side(ptr: FFIHandle<Battle>) -> u8 {
|
||||
ptr.from_ffi_handle().pokemon_per_side()
|
||||
}
|
||||
|
||||
/// The length of the list of all different sides in the battle.
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_sides_length(ptr: ExternPointer<Arc<Battle>>) -> usize {
|
||||
ptr.as_ref().sides().len()
|
||||
extern "C" fn battle_sides_length(ptr: FFIHandle<Battle>) -> usize {
|
||||
ptr.from_ffi_handle().sides().len()
|
||||
}
|
||||
|
||||
/// Get a side in the battle.
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_sides_get(ptr: ExternPointer<Arc<Battle>>, index: usize) -> IdentifiablePointer<BattleSide> {
|
||||
if let Some(v) = ptr.as_ref().sides().get(index) {
|
||||
(v as *const BattleSide).into()
|
||||
extern "C" fn battle_sides_get(ptr: FFIHandle<Battle>, index: usize) -> FFIHandle<BattleSide> {
|
||||
if let Some(v) = ptr.from_ffi_handle().sides().get(index) {
|
||||
FFIHandle::get_handle(v.clone().into())
|
||||
} else {
|
||||
IdentifiablePointer::none()
|
||||
FFIHandle::none()
|
||||
}
|
||||
}
|
||||
|
||||
/// The RNG used for the battle.
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_random(ptr: ExternPointer<Arc<Battle>>) -> IdentifiablePointer<Arc<BattleRandom>> {
|
||||
ptr.as_ref().random().clone().into()
|
||||
extern "C" fn battle_random(ptr: FFIHandle<Battle>) -> FFIHandle<Arc<BattleRandom>> {
|
||||
FFIHandle::get_handle(ptr.from_ffi_handle().random().clone().into())
|
||||
}
|
||||
|
||||
/// Whether or not the battle has ended.
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_has_ended(ptr: ExternPointer<Arc<Battle>>) -> u8 {
|
||||
u8::from(ptr.as_ref().has_ended())
|
||||
extern "C" fn battle_has_ended(ptr: FFIHandle<Battle>) -> u8 {
|
||||
u8::from(ptr.from_ffi_handle().has_ended())
|
||||
}
|
||||
|
||||
/// Whether or not we have a conclusive winner
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_has_conclusive_result(ptr: ExternPointer<Arc<Battle>>) -> u8 {
|
||||
u8::from(ptr.as_ref().result() != BattleResult::Inconclusive)
|
||||
extern "C" fn battle_has_conclusive_result(ptr: FFIHandle<Battle>) -> u8 {
|
||||
u8::from(ptr.from_ffi_handle().result() != BattleResult::Inconclusive)
|
||||
}
|
||||
|
||||
/// If we have a conclusive winner, the side that has won. If we don't have a conclusive winner, this
|
||||
/// always returns 0.
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_winning_side(ptr: ExternPointer<Arc<Battle>>) -> u8 {
|
||||
if let BattleResult::Conclusive(winner) = ptr.as_ref().result() {
|
||||
extern "C" fn battle_winning_side(ptr: FFIHandle<Battle>) -> u8 {
|
||||
if let BattleResult::Conclusive(winner) = ptr.from_ffi_handle().result() {
|
||||
winner
|
||||
} else {
|
||||
0
|
||||
@@ -135,29 +136,29 @@ extern "C" fn battle_winning_side(ptr: ExternPointer<Arc<Battle>>) -> u8 {
|
||||
|
||||
/// Register a function to be triggered when an event in a battle occurs.
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_register_event_hook(ptr: ExternPointer<Arc<Battle>>, f: NativeEventHook) {
|
||||
ptr.as_ref().event_hook().register_listener(Box::new(f))
|
||||
extern "C" fn battle_register_event_hook(ptr: FFIHandle<Battle>, f: NativeEventHook) {
|
||||
ptr.from_ffi_handle().event_hook().register_listener(Box::new(f))
|
||||
}
|
||||
|
||||
/// The index of the current turn. 0 until all choices
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_current_turn(ptr: ExternPointer<Arc<Battle>>) -> u32 {
|
||||
ptr.as_ref().current_turn()
|
||||
extern "C" fn battle_current_turn(ptr: FFIHandle<Battle>) -> u32 {
|
||||
ptr.from_ffi_handle().current_turn()
|
||||
}
|
||||
|
||||
/// The time in nanoseconds the last turn took to run. Defaults to 0.
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_last_turn_time(ptr: ExternPointer<Arc<Battle>>) -> u64 {
|
||||
ptr.as_ref().last_turn_time()
|
||||
extern "C" fn battle_last_turn_time(ptr: FFIHandle<Battle>) -> u64 {
|
||||
ptr.from_ffi_handle().last_turn_time()
|
||||
}
|
||||
|
||||
/// Get a Pokemon on the battlefield, on a specific side and an index on that side.
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_get_pokemon(ptr: ExternPointer<Arc<Battle>>, side: u8, index: u8) -> IdentifiablePointer<Pokemon> {
|
||||
if let Some(v) = ptr.as_ref().get_pokemon(side, index) {
|
||||
v.into()
|
||||
extern "C" fn battle_get_pokemon(ptr: FFIHandle<Battle>, side: u8, index: u8) -> FFIHandle<Pokemon> {
|
||||
if let Some(v) = ptr.from_ffi_handle().get_pokemon(side, index) {
|
||||
FFIHandle::get_handle(v.into())
|
||||
} else {
|
||||
IdentifiablePointer::none()
|
||||
FFIHandle::none()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,47 +166,51 @@ extern "C" fn battle_get_pokemon(ptr: ExternPointer<Arc<Battle>>, side: u8, inde
|
||||
/// for that slot, or a party is responsible, but has no remaining Pokemon to throw out anymore,
|
||||
/// this returns false.
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_can_slot_be_filled(ptr: ExternPointer<Arc<Battle>>, side: u8, index: u8) -> u8 {
|
||||
u8::from(ptr.as_ref().can_slot_be_filled(side, index))
|
||||
extern "C" fn battle_can_slot_be_filled(ptr: FFIHandle<Battle>, side: u8, index: u8) -> u8 {
|
||||
u8::from(ptr.from_ffi_handle().can_slot_be_filled(side, index))
|
||||
}
|
||||
|
||||
/// Checks whether a choice is actually possible.
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_can_use(ptr: ExternPointer<Arc<Battle>>, choice: ExternPointer<TurnChoice>) -> u8 {
|
||||
u8::from(ptr.as_ref().can_use(choice.as_ref()))
|
||||
extern "C" fn battle_can_use(ptr: FFIHandle<Battle>, choice: FFIHandle<Arc<TurnChoice>>) -> u8 {
|
||||
u8::from(ptr.from_ffi_handle().can_use(choice.from_ffi_handle().deref()))
|
||||
}
|
||||
|
||||
/// Checks to see whether all Pokemon on the field have set their choices. If so, we then run
|
||||
/// the turn.
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_try_set_choice(ptr: ExternPointer<Arc<Battle>>, choice: OwnedPtr<TurnChoice>) -> NativeResult<u8> {
|
||||
let choice = unsafe { choice.read() };
|
||||
let result = ptr.as_ref().try_set_choice(choice);
|
||||
extern "C" fn battle_try_set_choice(ptr: FFIHandle<Battle>, choice: FFIHandle<Arc<TurnChoice>>) -> FFIResult<u8> {
|
||||
let choice = choice.from_ffi_handle();
|
||||
let result = ptr.from_ffi_handle().try_set_choice(choice);
|
||||
match result {
|
||||
Ok(b) => NativeResult::ok(u8::from(b)),
|
||||
Err(e) => NativeResult::err(e),
|
||||
Ok(b) => FFIResult::ok(u8::from(b)),
|
||||
Err(e) => FFIResult::err(e),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the current weather for the battle. If nullptr is passed, this clears the weather.
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_set_weather(ptr: ExternPointer<Arc<Battle>>, weather: *const c_char) -> NativeResult<()> {
|
||||
extern "C" fn battle_set_weather(ptr: FFIHandle<Battle>, weather: *const c_char) -> FFIResult<()> {
|
||||
if weather.is_null() {
|
||||
ptr.as_ref().set_weather(None).into()
|
||||
ptr.from_ffi_handle().set_weather(None).into()
|
||||
} else {
|
||||
unsafe { ptr.as_ref().set_weather(Some(CStr::from_ptr(weather).into())).into() }
|
||||
unsafe {
|
||||
ptr.from_ffi_handle()
|
||||
.set_weather(Some(CStr::from_ptr(weather).into()))
|
||||
.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the current weather of the battle. If no weather is present, this returns nullptr.
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_weather_name(ptr: ExternPointer<Arc<Battle>>) -> NativeResult<*mut c_char> {
|
||||
match ptr.as_ref().weather_name() {
|
||||
extern "C" fn battle_weather_name(ptr: FFIHandle<Battle>) -> FFIResult<*mut c_char> {
|
||||
match ptr.from_ffi_handle().weather_name() {
|
||||
Ok(Some(w)) => match CString::new(w.str()) {
|
||||
Ok(s) => s.into_raw().into(),
|
||||
Err(e) => NativeResult::err(anyhow!("Failed to convert weather name to CString: {}", e)),
|
||||
Err(e) => FFIResult::err(anyhow!("Failed to convert weather name to CString: {}", e)),
|
||||
},
|
||||
Ok(None) => std::ptr::null_mut::<c_char>().into(),
|
||||
Err(e) => NativeResult::err(e),
|
||||
Err(e) => FFIResult::err(e),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::dynamic_data::{BattleParty, Pokemon, PokemonParty};
|
||||
use crate::ffi::{ExternPointer, IdentifiablePointer, NativeResult};
|
||||
use crate::ffi::ffi_handle::{FFIHandle, FromFFIHandle};
|
||||
use crate::ffi::FFIResult;
|
||||
use crate::VecExt;
|
||||
use anyhow::{anyhow, Result};
|
||||
use std::sync::Arc;
|
||||
@@ -8,12 +9,12 @@ use std::sync::Arc;
|
||||
/// on the field attached. The indices are stored
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_party_new(
|
||||
party: ExternPointer<Arc<PokemonParty>>,
|
||||
party: FFIHandle<Arc<PokemonParty>>,
|
||||
responsible_indices_ptr: *const u8,
|
||||
responsible_indices_length: usize,
|
||||
) -> NativeResult<IdentifiablePointer<Arc<BattleParty>>> {
|
||||
) -> FFIResult<FFIHandle<Arc<BattleParty>>> {
|
||||
if responsible_indices_length % 2 != 0 {
|
||||
return NativeResult::err(anyhow!("The length of responsible indices should be dividable by two"));
|
||||
return FFIResult::err(anyhow!("The length of responsible indices should be dividable by two"));
|
||||
}
|
||||
|
||||
let responsible_indices_slice =
|
||||
@@ -31,43 +32,40 @@ extern "C" fn battle_party_new(
|
||||
for i in 0..responsible_indices_length / 2 {
|
||||
match split(i) {
|
||||
Ok(_) => (),
|
||||
Err(e) => return NativeResult::err(e),
|
||||
Err(e) => return FFIResult::err(e),
|
||||
}
|
||||
}
|
||||
|
||||
match BattleParty::new(party.as_ref().clone(), responsible_indices) {
|
||||
Ok(v) => NativeResult::ok(Arc::new(v).into()),
|
||||
Err(e) => NativeResult::err(e),
|
||||
match BattleParty::new(party.from_ffi_handle(), responsible_indices) {
|
||||
Ok(v) => FFIResult::ok(FFIHandle::get_handle(Arc::new(v).into())),
|
||||
Err(e) => FFIResult::err(e),
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks whether the party is responsible for the given index.
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_party_is_responsible_for_index(ptr: ExternPointer<Arc<BattleParty>>, side: u8, index: u8) -> u8 {
|
||||
u8::from(ptr.as_ref().is_responsible_for_index(side, index))
|
||||
extern "C" fn battle_party_is_responsible_for_index(ptr: FFIHandle<Arc<BattleParty>>, side: u8, index: u8) -> u8 {
|
||||
u8::from(ptr.from_ffi_handle().is_responsible_for_index(side, index))
|
||||
}
|
||||
|
||||
/// Whether or not the party has non fainted Pokemon that could be thrown out into the field.
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_party_has_pokemon_not_in_field(ptr: ExternPointer<Arc<BattleParty>>) -> u8 {
|
||||
u8::from(ptr.as_ref().has_pokemon_not_in_field())
|
||||
extern "C" fn battle_party_has_pokemon_not_in_field(ptr: FFIHandle<Arc<BattleParty>>) -> u8 {
|
||||
u8::from(ptr.from_ffi_handle().has_pokemon_not_in_field())
|
||||
}
|
||||
|
||||
/// Gets a Pokemon at an index.
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_party_get_pokemon(
|
||||
ptr: ExternPointer<Arc<BattleParty>>,
|
||||
index: usize,
|
||||
) -> IdentifiablePointer<Pokemon> {
|
||||
if let Some(v) = ptr.as_ref().get_pokemon(index) {
|
||||
v.into()
|
||||
extern "C" fn battle_party_get_pokemon(ptr: FFIHandle<Arc<BattleParty>>, index: usize) -> FFIHandle<Pokemon> {
|
||||
if let Some(v) = ptr.from_ffi_handle().get_pokemon(index) {
|
||||
FFIHandle::get_handle(v.into())
|
||||
} else {
|
||||
IdentifiablePointer::none()
|
||||
FFIHandle::none()
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the underlying Pokemon Party
|
||||
#[no_mangle]
|
||||
extern "C" fn battle_party_party(ptr: ExternPointer<Arc<BattleParty>>) -> IdentifiablePointer<Arc<PokemonParty>> {
|
||||
ptr.as_ref().party().clone().into()
|
||||
extern "C" fn battle_party_party(ptr: FFIHandle<Arc<BattleParty>>) -> FFIHandle<Arc<PokemonParty>> {
|
||||
FFIHandle::get_handle(ptr.from_ffi_handle().party().clone().into())
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::dynamic_data::{Event, Pokemon};
|
||||
use crate::ffi::{ExternPointer, IdentifiablePointer};
|
||||
use crate::ffi::ExternPointer;
|
||||
use crate::ffi::FFIHandle;
|
||||
|
||||
/// The kind of the event.
|
||||
#[no_mangle]
|
||||
@@ -66,13 +67,18 @@ event_ffi!(
|
||||
/// The index of the Pokemon that got switched in/out on its side
|
||||
index: u8,
|
||||
/// The new Pokemon that will be on the spot. If none, the spot will be null.
|
||||
pokemon: IdentifiablePointer<Pokemon>,
|
||||
pokemon: FFIHandle<Pokemon>,
|
||||
},
|
||||
{
|
||||
let pokemon_handle = match pokemon {
|
||||
Some(pokemon) => FFIHandle::get_handle(pokemon.clone().into()),
|
||||
None => FFIHandle::none(),
|
||||
};
|
||||
|
||||
return SwitchData{
|
||||
side_index: *side_index,
|
||||
index: *index,
|
||||
pokemon: pokemon.clone().into(),
|
||||
pokemon: pokemon_handle,
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,66 +1,58 @@
|
||||
use crate::dynamic_data::{LearnedMove, MoveLearnMethod};
|
||||
use crate::ffi::{ExternPointer, IdentifiablePointer, NativeResult, OwnedPtr};
|
||||
use crate::ffi::ffi_handle::{FFIHandle, FromFFIHandle};
|
||||
use crate::ffi::FFIResult;
|
||||
use crate::static_data::MoveData;
|
||||
use std::ptr::drop_in_place;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Instantiate a new learned move.
|
||||
#[no_mangle]
|
||||
extern "C" fn learned_move_new(
|
||||
move_data: ExternPointer<Arc<dyn MoveData>>,
|
||||
move_data: FFIHandle<Arc<dyn MoveData>>,
|
||||
learn_method: MoveLearnMethod,
|
||||
) -> IdentifiablePointer<Arc<LearnedMove>> {
|
||||
Arc::new(LearnedMove::new(move_data.as_ref().clone(), learn_method)).into()
|
||||
}
|
||||
|
||||
/// Drops a learned move.
|
||||
#[no_mangle]
|
||||
extern "C" fn learned_move_drop(learned_move: OwnedPtr<Arc<LearnedMove>>) {
|
||||
unsafe { drop_in_place(learned_move) }
|
||||
) -> FFIHandle<Arc<LearnedMove>> {
|
||||
FFIHandle::get_handle(Arc::new(LearnedMove::new(move_data.from_ffi_handle().clone(), learn_method)).into())
|
||||
}
|
||||
|
||||
/// The immutable move information of the move.
|
||||
#[no_mangle]
|
||||
extern "C" fn learned_move_move_data(
|
||||
learned_move: ExternPointer<Arc<LearnedMove>>,
|
||||
) -> IdentifiablePointer<Arc<dyn MoveData>> {
|
||||
learned_move.as_ref().move_data().clone().into()
|
||||
extern "C" fn learned_move_move_data(learned_move: FFIHandle<Arc<LearnedMove>>) -> FFIHandle<Arc<dyn MoveData>> {
|
||||
FFIHandle::get_handle(learned_move.from_ffi_handle().move_data().clone().into())
|
||||
}
|
||||
|
||||
/// The maximal power points for this move.
|
||||
#[no_mangle]
|
||||
extern "C" fn learned_move_max_pp(learned_move: ExternPointer<Arc<LearnedMove>>) -> u8 {
|
||||
learned_move.as_ref().max_pp()
|
||||
extern "C" fn learned_move_max_pp(learned_move: FFIHandle<Arc<LearnedMove>>) -> u8 {
|
||||
learned_move.from_ffi_handle().max_pp()
|
||||
}
|
||||
|
||||
/// The amount of remaining power points. If this is 0, we can not use the move anymore.
|
||||
#[no_mangle]
|
||||
extern "C" fn learned_move_remaining_pp(learned_move: ExternPointer<Arc<LearnedMove>>) -> u8 {
|
||||
learned_move.as_ref().remaining_pp()
|
||||
extern "C" fn learned_move_remaining_pp(learned_move: FFIHandle<Arc<LearnedMove>>) -> u8 {
|
||||
learned_move.from_ffi_handle().remaining_pp()
|
||||
}
|
||||
|
||||
/// The way the move was learned.
|
||||
#[no_mangle]
|
||||
extern "C" fn learned_move_learn_method(learned_move: ExternPointer<Arc<LearnedMove>>) -> MoveLearnMethod {
|
||||
learned_move.as_ref().learn_method()
|
||||
extern "C" fn learned_move_learn_method(learned_move: FFIHandle<Arc<LearnedMove>>) -> MoveLearnMethod {
|
||||
learned_move.from_ffi_handle().learn_method()
|
||||
}
|
||||
|
||||
/// Try and reduce the PP by a certain amount. If the amount is higher than the current uses,
|
||||
/// return 0. Otherwise, reduce the PP, and return 1.
|
||||
#[no_mangle]
|
||||
extern "C" fn learned_move_try_use(learned_move: ExternPointer<Arc<LearnedMove>>, amount: u8) -> u8 {
|
||||
u8::from(learned_move.as_ref().try_use(amount))
|
||||
extern "C" fn learned_move_try_use(learned_move: FFIHandle<Arc<LearnedMove>>, amount: u8) -> u8 {
|
||||
u8::from(learned_move.from_ffi_handle().try_use(amount))
|
||||
}
|
||||
|
||||
/// Set the remaining PP to the max amount of PP.
|
||||
#[no_mangle]
|
||||
extern "C" fn learned_move_restore_all_uses(learned_move: ExternPointer<Arc<LearnedMove>>) {
|
||||
learned_move.as_ref().restore_all_uses();
|
||||
extern "C" fn learned_move_restore_all_uses(learned_move: FFIHandle<Arc<LearnedMove>>) {
|
||||
learned_move.from_ffi_handle().restore_all_uses();
|
||||
}
|
||||
|
||||
/// Restore the remaining PP by a certain amount. Will prevent it from going above max PP.
|
||||
#[no_mangle]
|
||||
extern "C" fn learned_move_restore_uses(learned_move: ExternPointer<Arc<LearnedMove>>, amount: u8) -> NativeResult<()> {
|
||||
learned_move.as_ref().restore_uses(amount);
|
||||
NativeResult::ok(())
|
||||
extern "C" fn learned_move_restore_uses(learned_move: FFIHandle<Arc<LearnedMove>>, amount: u8) -> FFIResult<()> {
|
||||
learned_move.from_ffi_handle().restore_uses(amount);
|
||||
FFIResult::ok(())
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
use crate::dynamic_data::Event;
|
||||
use crate::ffi::BorrowedPtr;
|
||||
|
||||
/// Wrapper class for easier use of an external function pointer.
|
||||
#[repr(C)]
|
||||
pub(super) struct NativeEventHook {
|
||||
/// The actual C function to be called.
|
||||
f: extern "C" fn(BorrowedPtr<Event>),
|
||||
f: extern "C" fn(*const Event<'_>),
|
||||
}
|
||||
|
||||
impl NativeEventHook {
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
use crate::defines::LevelInt;
|
||||
use crate::dynamic_data::{Battle, DamageSource, DynamicLibrary, LearnedMove, MoveLearnMethod, Pokemon};
|
||||
use crate::ffi::{ffi_arc_getter, ffi_vec_value_getters, ExternPointer, IdentifiablePointer, NativeResult, OwnedPtr};
|
||||
use crate::ffi::ffi_handle::{FFIHandle, FromFFIHandle};
|
||||
use crate::ffi::FFIResult;
|
||||
use crate::static_data::{
|
||||
Ability, AbilityIndex, Form, Gender, Item, Nature, Species, Statistic, StatisticSet, TypeIdentifier,
|
||||
};
|
||||
use crate::VecExt;
|
||||
use anyhow::anyhow;
|
||||
use std::ffi::{c_char, CStr, CString};
|
||||
use std::ptr::drop_in_place;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Instantiates a new Pokemon.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_new(
|
||||
library: ExternPointer<Arc<dyn DynamicLibrary>>,
|
||||
species: ExternPointer<Arc<dyn Species>>,
|
||||
form: ExternPointer<Arc<dyn Form>>,
|
||||
library: FFIHandle<Arc<dyn DynamicLibrary>>,
|
||||
species: FFIHandle<Arc<dyn Species>>,
|
||||
form: FFIHandle<Arc<dyn Form>>,
|
||||
hidden_ability: u8,
|
||||
ability_index: u8,
|
||||
level: LevelInt,
|
||||
@@ -22,12 +23,12 @@ extern "C" fn pokemon_new(
|
||||
gender: Gender,
|
||||
coloring: u8,
|
||||
nature: *const c_char,
|
||||
) -> NativeResult<IdentifiablePointer<Pokemon>> {
|
||||
) -> FFIResult<FFIHandle<Pokemon>> {
|
||||
let nature = unsafe { CStr::from_ptr(nature) }.into();
|
||||
let pokemon = Pokemon::new(
|
||||
library.as_ref().clone(),
|
||||
species.as_ref().clone(),
|
||||
form.as_ref(),
|
||||
library.from_ffi_handle(),
|
||||
species.from_ffi_handle(),
|
||||
&form.from_ffi_handle(),
|
||||
AbilityIndex {
|
||||
hidden: hidden_ability == 1,
|
||||
index: ability_index,
|
||||
@@ -39,337 +40,373 @@ extern "C" fn pokemon_new(
|
||||
&nature,
|
||||
);
|
||||
match pokemon {
|
||||
Ok(pokemon) => NativeResult::ok(pokemon.into()),
|
||||
Err(err) => NativeResult::err(err),
|
||||
Ok(pokemon) => FFIResult::ok(FFIHandle::get_handle(pokemon.into())),
|
||||
Err(err) => FFIResult::err(err),
|
||||
}
|
||||
}
|
||||
|
||||
/// Drops an Arc reference held by the FFI.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn pokemon_drop(ptr: OwnedPtr<Pokemon>) {
|
||||
drop_in_place(ptr);
|
||||
}
|
||||
|
||||
/// The library data of the Pokemon.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_library(ptr: ExternPointer<Pokemon>) -> IdentifiablePointer<Arc<dyn DynamicLibrary>> {
|
||||
ptr.as_ref().library().clone().into()
|
||||
extern "C" fn pokemon_library(handle: FFIHandle<Pokemon>) -> FFIHandle<Arc<dyn DynamicLibrary>> {
|
||||
FFIHandle::get_handle(handle.from_ffi_handle().library().clone().into())
|
||||
}
|
||||
|
||||
/// The species of the Pokemon.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_species(ptr: ExternPointer<Pokemon>) -> IdentifiablePointer<Arc<dyn Species>> {
|
||||
ptr.as_ref().species().into()
|
||||
extern "C" fn pokemon_species(handle: FFIHandle<Pokemon>) -> FFIHandle<Arc<dyn Species>> {
|
||||
FFIHandle::get_handle(handle.from_ffi_handle().species().into())
|
||||
}
|
||||
|
||||
/// The form of the Pokemon.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_form(ptr: ExternPointer<Pokemon>) -> IdentifiablePointer<Arc<dyn Form>> {
|
||||
ptr.as_ref().form().into()
|
||||
extern "C" fn pokemon_form(handle: FFIHandle<Pokemon>) -> FFIHandle<Arc<dyn Form>> {
|
||||
FFIHandle::get_handle(handle.from_ffi_handle().form().into())
|
||||
}
|
||||
|
||||
/// The species that should be displayed to the user. This handles stuff like the Illusion ability.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_display_species(ptr: ExternPointer<Pokemon>) -> IdentifiablePointer<Arc<dyn Species>> {
|
||||
ptr.as_ref().display_species().into()
|
||||
extern "C" fn pokemon_display_species(handle: FFIHandle<Pokemon>) -> FFIHandle<Arc<dyn Species>> {
|
||||
FFIHandle::get_handle(handle.from_ffi_handle().display_species().into())
|
||||
}
|
||||
|
||||
/// The form that should be displayed to the user. This handles stuff like the Illusion ability.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_display_form(ptr: ExternPointer<Pokemon>) -> IdentifiablePointer<Arc<dyn Form>> {
|
||||
ptr.as_ref().display_form().into()
|
||||
extern "C" fn pokemon_display_form(handle: FFIHandle<Pokemon>) -> FFIHandle<Arc<dyn Form>> {
|
||||
FFIHandle::get_handle(handle.from_ffi_handle().display_form().into())
|
||||
}
|
||||
|
||||
ffi_arc_getter!(Pokemon, level, LevelInt);
|
||||
ffi_arc_getter!(Pokemon, experience, u32);
|
||||
ffi_arc_getter!(Pokemon, unique_identifier, u32);
|
||||
ffi_arc_getter!(Pokemon, gender, Gender);
|
||||
ffi_arc_getter!(Pokemon, coloring, u8);
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_level(handle: FFIHandle<Pokemon>) -> LevelInt {
|
||||
handle.from_ffi_handle().level()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_experience(handle: FFIHandle<Pokemon>) -> u32 {
|
||||
handle.from_ffi_handle().experience()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_unique_identifier(handle: FFIHandle<Pokemon>) -> u32 {
|
||||
handle.from_ffi_handle().unique_identifier()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_gender(handle: FFIHandle<Pokemon>) -> Gender {
|
||||
handle.from_ffi_handle().gender()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_coloring(handle: FFIHandle<Pokemon>) -> u8 {
|
||||
handle.from_ffi_handle().coloring()
|
||||
}
|
||||
|
||||
/// Gets the held item of a Pokemon
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_held_item(ptr: ExternPointer<Pokemon>) -> IdentifiablePointer<Arc<dyn Item>> {
|
||||
if let Some(v) = ptr.as_ref().held_item().read().as_ref() {
|
||||
v.clone().into()
|
||||
extern "C" fn pokemon_held_item(handle: FFIHandle<Pokemon>) -> FFIHandle<Arc<dyn Item>> {
|
||||
if let Some(v) = handle.from_ffi_handle().held_item().read().as_ref() {
|
||||
FFIHandle::get_handle(v.clone().into())
|
||||
} else {
|
||||
IdentifiablePointer::none()
|
||||
FFIHandle::none()
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks whether the Pokemon is holding a specific item.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_has_held_item(ptr: ExternPointer<Pokemon>, name: *const c_char) -> u8 {
|
||||
extern "C" fn pokemon_has_held_item(handle: FFIHandle<Pokemon>, name: *const c_char) -> u8 {
|
||||
let name = unsafe { CStr::from_ptr(name) }.into();
|
||||
u8::from(ptr.as_ref().has_held_item(&name))
|
||||
u8::from(handle.from_ffi_handle().has_held_item(&name))
|
||||
}
|
||||
|
||||
/// Changes the held item of the Pokemon. Returns the previously held item.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_set_held_item(
|
||||
ptr: ExternPointer<Pokemon>,
|
||||
item: ExternPointer<Arc<dyn Item>>,
|
||||
) -> IdentifiablePointer<Arc<dyn Item>> {
|
||||
if let Some(v) = ptr.as_ref().set_held_item(item.as_ref()) {
|
||||
v.into()
|
||||
handle: FFIHandle<Pokemon>,
|
||||
item: FFIHandle<Arc<dyn Item>>,
|
||||
) -> FFIHandle<Arc<dyn Item>> {
|
||||
if let Some(v) = handle.from_ffi_handle().set_held_item(&item.from_ffi_handle()) {
|
||||
FFIHandle::get_handle(v.into())
|
||||
} else {
|
||||
IdentifiablePointer::none()
|
||||
FFIHandle::none()
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes the held item from the Pokemon. Returns the previously held item.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_remove_held_item(ptr: ExternPointer<Pokemon>) -> IdentifiablePointer<Arc<dyn Item>> {
|
||||
if let Some(v) = ptr.as_ref().remove_held_item() {
|
||||
v.into()
|
||||
extern "C" fn pokemon_remove_held_item(handle: FFIHandle<Pokemon>) -> FFIHandle<Arc<dyn Item>> {
|
||||
if let Some(v) = handle.from_ffi_handle().remove_held_item() {
|
||||
FFIHandle::get_handle(v.into())
|
||||
} else {
|
||||
IdentifiablePointer::none()
|
||||
FFIHandle::none()
|
||||
}
|
||||
}
|
||||
|
||||
/// Makes the Pokemon uses its held item.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_consume_held_item(ptr: ExternPointer<Pokemon>) -> NativeResult<u8> {
|
||||
match ptr.as_ref().consume_held_item() {
|
||||
Ok(v) => NativeResult::ok(u8::from(v)),
|
||||
Err(err) => NativeResult::err(err),
|
||||
extern "C" fn pokemon_consume_held_item(handle: FFIHandle<Pokemon>) -> FFIResult<u8> {
|
||||
match handle.from_ffi_handle().consume_held_item() {
|
||||
Ok(v) => FFIResult::ok(u8::from(v)),
|
||||
Err(err) => FFIResult::err(err),
|
||||
}
|
||||
}
|
||||
|
||||
ffi_arc_getter!(Pokemon, current_health, u32);
|
||||
ffi_arc_getter!(Pokemon, max_health, u32);
|
||||
ffi_arc_getter!(Pokemon, weight, f32);
|
||||
ffi_arc_getter!(Pokemon, height, f32);
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_current_health(handle: FFIHandle<Pokemon>) -> u32 {
|
||||
handle.from_ffi_handle().current_health()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_max_health(handle: FFIHandle<Pokemon>) -> u32 {
|
||||
handle.from_ffi_handle().max_health()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_weight(handle: FFIHandle<Pokemon>) -> f32 {
|
||||
handle.from_ffi_handle().weight()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_height(handle: FFIHandle<Pokemon>) -> f32 {
|
||||
handle.from_ffi_handle().height()
|
||||
}
|
||||
|
||||
/// An optional nickname of the Pokemon.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_nickname(ptr: ExternPointer<Pokemon>) -> NativeResult<*mut c_char> {
|
||||
let name = ptr.as_ref().nickname();
|
||||
extern "C" fn pokemon_nickname(handle: FFIHandle<Pokemon>) -> FFIResult<*mut c_char> {
|
||||
let form = handle.from_ffi_handle();
|
||||
let name = form.nickname();
|
||||
if let Some(v) = name {
|
||||
match CString::new(v.as_str()) {
|
||||
Ok(v) => NativeResult::ok(v.into_raw()),
|
||||
Err(err) => NativeResult::err(anyhow!("Could not convert nickname to CString: {}", err)),
|
||||
Ok(v) => FFIResult::ok(v.into_raw()),
|
||||
Err(err) => FFIResult::err(anyhow!("Could not convert nickname to CString: {}", err)),
|
||||
}
|
||||
} else {
|
||||
NativeResult::ok(std::ptr::null_mut())
|
||||
FFIResult::ok(std::ptr::null_mut())
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether the actual ability on the form is a hidden ability.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_real_ability_is_hidden(ptr: ExternPointer<Pokemon>) -> u8 {
|
||||
u8::from(ptr.as_ref().real_ability().hidden)
|
||||
extern "C" fn pokemon_real_ability_is_hidden(handle: FFIHandle<Pokemon>) -> u8 {
|
||||
u8::from(handle.from_ffi_handle().real_ability().hidden)
|
||||
}
|
||||
|
||||
/// The index of the actual ability on the form.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_real_ability_index(ptr: ExternPointer<Pokemon>) -> u8 {
|
||||
ptr.as_ref().real_ability().index
|
||||
extern "C" fn pokemon_real_ability_index(handle: FFIHandle<Pokemon>) -> u8 {
|
||||
handle.from_ffi_handle().real_ability().index
|
||||
}
|
||||
|
||||
ffi_vec_value_getters!(Pokemon, Pokemon, types, TypeIdentifier);
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_types_length(ptr: FFIHandle<Pokemon>) -> usize {
|
||||
ptr.from_ffi_handle().types().len()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_types_get(ptr: FFIHandle<Pokemon>, index: usize) -> FFIResult<TypeIdentifier> {
|
||||
match ptr.from_ffi_handle().types().get_res(index) {
|
||||
Ok(v) => FFIResult::ok(*v),
|
||||
Err(err) => FFIResult::err(err),
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a learned move of the Pokemon. Index should generally be below [`MAX_MOVES`], you will get
|
||||
/// a null pointer otherwise.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_learned_move_get(
|
||||
ptr: ExternPointer<Pokemon>,
|
||||
index: usize,
|
||||
) -> IdentifiablePointer<Arc<LearnedMove>> {
|
||||
if let Some(Some(v)) = ptr.as_ref().learned_moves().read().get(index) {
|
||||
v.clone().into()
|
||||
extern "C" fn pokemon_learned_move_get(handle: FFIHandle<Pokemon>, index: usize) -> FFIHandle<Arc<LearnedMove>> {
|
||||
if let Some(Some(v)) = handle.from_ffi_handle().learned_moves().read().get(index) {
|
||||
FFIHandle::get_handle(v.clone().into())
|
||||
} else {
|
||||
IdentifiablePointer::none()
|
||||
FFIHandle::none()
|
||||
}
|
||||
}
|
||||
|
||||
/// The stats of the Pokemon when disregarding any stat boosts.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_flat_stats(ptr: ExternPointer<Pokemon>) -> IdentifiablePointer<Arc<StatisticSet<u32>>> {
|
||||
ptr.as_ref().flat_stats().clone().into()
|
||||
extern "C" fn pokemon_flat_stats(handle: FFIHandle<Pokemon>) -> FFIHandle<Arc<StatisticSet<u32>>> {
|
||||
FFIHandle::get_handle(handle.from_ffi_handle().flat_stats().clone().into())
|
||||
}
|
||||
|
||||
/// The stats of the Pokemon including the stat boosts.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_boosted_stats(ptr: ExternPointer<Pokemon>) -> IdentifiablePointer<Arc<StatisticSet<u32>>> {
|
||||
ptr.as_ref().boosted_stats().clone().into()
|
||||
extern "C" fn pokemon_boosted_stats(handle: FFIHandle<Pokemon>) -> FFIHandle<Arc<StatisticSet<u32>>> {
|
||||
FFIHandle::get_handle(handle.from_ffi_handle().boosted_stats().clone().into())
|
||||
}
|
||||
|
||||
/// Get the stat boosts for a specific stat.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_get_stat_boost(ptr: ExternPointer<Pokemon>, statistic: Statistic) -> i8 {
|
||||
ptr.as_ref().stat_boost(statistic)
|
||||
extern "C" fn pokemon_get_stat_boost(handle: FFIHandle<Pokemon>, statistic: Statistic) -> i8 {
|
||||
handle.from_ffi_handle().stat_boost(statistic)
|
||||
}
|
||||
|
||||
/// Change a boosted stat by a certain amount.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_change_stat_boost(
|
||||
ptr: ExternPointer<Pokemon>,
|
||||
handle: FFIHandle<Pokemon>,
|
||||
stat: Statistic,
|
||||
diff_amount: i8,
|
||||
self_inflicted: u8,
|
||||
) -> NativeResult<u8> {
|
||||
match ptr.as_ref().change_stat_boost(stat, diff_amount, self_inflicted == 1) {
|
||||
Ok(v) => NativeResult::ok(u8::from(v)),
|
||||
Err(e) => NativeResult::err(e),
|
||||
) -> FFIResult<u8> {
|
||||
match handle
|
||||
.from_ffi_handle()
|
||||
.change_stat_boost(stat, diff_amount, self_inflicted == 1)
|
||||
{
|
||||
Ok(v) => FFIResult::ok(u8::from(v)),
|
||||
Err(e) => FFIResult::err(e),
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a [individual value](https://bulbapedia.bulbagarden.net/wiki/Individual_values) of the Pokemon.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_get_individual_value(ptr: ExternPointer<Pokemon>, stat: Statistic) -> u8 {
|
||||
ptr.as_ref().individual_values().get_stat(stat)
|
||||
extern "C" fn pokemon_get_individual_value(handle: FFIHandle<Pokemon>, stat: Statistic) -> u8 {
|
||||
handle.from_ffi_handle().individual_values().get_stat(stat)
|
||||
}
|
||||
|
||||
/// Modifies a [individual value](https://bulbapedia.bulbagarden.net/wiki/Individual_values) of the Pokemon.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_set_individual_value(
|
||||
ptr: ExternPointer<Pokemon>,
|
||||
stat: Statistic,
|
||||
value: u8,
|
||||
) -> NativeResult<()> {
|
||||
ptr.as_ref().individual_values().set_stat(stat, value);
|
||||
ptr.as_ref().recalculate_flat_stats().into()
|
||||
extern "C" fn pokemon_set_individual_value(handle: FFIHandle<Pokemon>, stat: Statistic, value: u8) -> FFIResult<()> {
|
||||
handle.from_ffi_handle().individual_values().set_stat(stat, value);
|
||||
handle.from_ffi_handle().recalculate_flat_stats().into()
|
||||
}
|
||||
|
||||
/// Gets a [effort value](https://bulbapedia.bulbagarden.net/wiki/Effort_values) of the Pokemon.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_get_effort_value(ptr: ExternPointer<Pokemon>, stat: Statistic) -> u8 {
|
||||
ptr.as_ref().effort_values().get_stat(stat)
|
||||
extern "C" fn pokemon_get_effort_value(handle: FFIHandle<Pokemon>, stat: Statistic) -> u8 {
|
||||
handle.from_ffi_handle().effort_values().get_stat(stat)
|
||||
}
|
||||
|
||||
/// Modifies a [effort value](https://bulbapedia.bulbagarden.net/wiki/Effort_values) of the Pokemon.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_set_effort_value(ptr: ExternPointer<Pokemon>, stat: Statistic, value: u8) -> NativeResult<()> {
|
||||
ptr.as_ref().effort_values().set_stat(stat, value);
|
||||
ptr.as_ref().recalculate_flat_stats().into()
|
||||
extern "C" fn pokemon_set_effort_value(handle: FFIHandle<Pokemon>, stat: Statistic, value: u8) -> FFIResult<()> {
|
||||
handle.from_ffi_handle().effort_values().set_stat(stat, value);
|
||||
handle.from_ffi_handle().recalculate_flat_stats().into()
|
||||
}
|
||||
|
||||
/// Gets the data for the battle the Pokemon is currently in. If the Pokemon is not in a battle, this
|
||||
/// returns null.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_get_battle(ptr: ExternPointer<Pokemon>) -> IdentifiablePointer<Battle> {
|
||||
if let Some(v) = ptr.as_ref().get_battle() {
|
||||
v.into()
|
||||
extern "C" fn pokemon_get_battle(handle: FFIHandle<Pokemon>) -> FFIHandle<Battle> {
|
||||
if let Some(v) = handle.from_ffi_handle().get_battle() {
|
||||
FFIHandle::get_handle(v.into())
|
||||
} else {
|
||||
IdentifiablePointer::none()
|
||||
FFIHandle::none()
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the index of the side of the battle the Pokemon is in. If the Pokemon
|
||||
/// is not on the battlefield, this always returns 0.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_get_battle_side_index(ptr: ExternPointer<Pokemon>) -> u8 {
|
||||
ptr.as_ref().get_battle_side_index().unwrap_or_default()
|
||||
extern "C" fn pokemon_get_battle_side_index(handle: FFIHandle<Pokemon>) -> u8 {
|
||||
handle.from_ffi_handle().get_battle_side_index().unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Get the index of the slot on the side of the battle the Pokemon is in. If the Pokemon
|
||||
/// is not on the battlefield, this always returns 0.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_get_battle_index(ptr: ExternPointer<Pokemon>) -> u8 {
|
||||
ptr.as_ref().get_battle_index().unwrap_or_default()
|
||||
extern "C" fn pokemon_get_battle_index(handle: FFIHandle<Pokemon>) -> u8 {
|
||||
handle.from_ffi_handle().get_battle_index().unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Returns whether something overrides the ability.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_is_ability_overriden(ptr: ExternPointer<Pokemon>) -> u8 {
|
||||
u8::from(ptr.as_ref().is_ability_overriden())
|
||||
extern "C" fn pokemon_is_ability_overriden(handle: FFIHandle<Pokemon>) -> u8 {
|
||||
u8::from(handle.from_ffi_handle().is_ability_overriden())
|
||||
}
|
||||
|
||||
/// Returns the currently active ability.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_active_ability(
|
||||
ptr: ExternPointer<Pokemon>,
|
||||
) -> NativeResult<IdentifiablePointer<Arc<dyn Ability>>> {
|
||||
match ptr.as_ref().active_ability() {
|
||||
Ok(v) => NativeResult::ok(v.clone().into()),
|
||||
Err(e) => NativeResult::err(e),
|
||||
extern "C" fn pokemon_active_ability(handle: FFIHandle<Pokemon>) -> FFIResult<FFIHandle<Arc<dyn Ability>>> {
|
||||
match handle.from_ffi_handle().active_ability() {
|
||||
Ok(v) => FFIResult::ok(FFIHandle::get_handle(v.clone().into())),
|
||||
Err(e) => FFIResult::err(e),
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether or not the Pokemon is allowed to gain experience.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_allowed_experience_gain(ptr: ExternPointer<Pokemon>) -> u8 {
|
||||
u8::from(ptr.as_ref().allowed_experience_gain())
|
||||
extern "C" fn pokemon_allowed_experience_gain(handle: FFIHandle<Pokemon>) -> u8 {
|
||||
u8::from(handle.from_ffi_handle().allowed_experience_gain())
|
||||
}
|
||||
|
||||
/// The [nature](https://bulbapedia.bulbagarden.net/wiki/Nature) of the Pokemon.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_nature(ptr: ExternPointer<Pokemon>) -> IdentifiablePointer<Arc<dyn Nature>> {
|
||||
ptr.as_ref().nature().clone().into()
|
||||
extern "C" fn pokemon_nature(handle: FFIHandle<Pokemon>) -> FFIHandle<Arc<dyn Nature>> {
|
||||
FFIHandle::get_handle(handle.from_ffi_handle().nature().clone().into())
|
||||
}
|
||||
|
||||
/// Calculates the flat stats on the Pokemon. This should be called when for example the base
|
||||
/// stats, level, nature, IV, or EV changes. This has a side effect of recalculating the boosted
|
||||
/// stats, as those depend on the flat stats.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_recalculate_flat_stats(ptr: ExternPointer<Pokemon>) -> NativeResult<()> {
|
||||
ptr.as_ref().recalculate_flat_stats().into()
|
||||
extern "C" fn pokemon_recalculate_flat_stats(handle: FFIHandle<Pokemon>) -> FFIResult<()> {
|
||||
handle.from_ffi_handle().recalculate_flat_stats().into()
|
||||
}
|
||||
|
||||
/// Calculates the boosted stats on the Pokemon. This should be called when a stat boost changes.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_recalculate_boosted_stats(ptr: ExternPointer<Pokemon>) -> NativeResult<()> {
|
||||
ptr.as_ref().recalculate_boosted_stats().into()
|
||||
extern "C" fn pokemon_recalculate_boosted_stats(handle: FFIHandle<Pokemon>) -> FFIResult<()> {
|
||||
handle.from_ffi_handle().recalculate_boosted_stats().into()
|
||||
}
|
||||
|
||||
/// Change the species of the Pokemon.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_change_species(
|
||||
ptr: ExternPointer<Pokemon>,
|
||||
species: ExternPointer<Arc<dyn Species>>,
|
||||
form: ExternPointer<Arc<dyn Form>>,
|
||||
) -> NativeResult<()> {
|
||||
ptr.as_ref()
|
||||
.change_species(species.as_ref().clone(), form.as_ref().clone())
|
||||
handle: FFIHandle<Pokemon>,
|
||||
species: FFIHandle<Arc<dyn Species>>,
|
||||
form: FFIHandle<Arc<dyn Form>>,
|
||||
) -> FFIResult<()> {
|
||||
handle
|
||||
.from_ffi_handle()
|
||||
.change_species(species.from_ffi_handle().clone(), form.from_ffi_handle().clone())
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Change the form of the Pokemon.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_change_form(ptr: ExternPointer<Pokemon>, form: ExternPointer<Arc<dyn Form>>) -> NativeResult<()> {
|
||||
ptr.as_ref().change_form(form.as_ref()).into()
|
||||
extern "C" fn pokemon_change_form(handle: FFIHandle<Pokemon>, form: FFIHandle<Arc<dyn Form>>) -> FFIResult<()> {
|
||||
handle.from_ffi_handle().change_form(&form.from_ffi_handle()).into()
|
||||
}
|
||||
|
||||
/// Whether or not the Pokemon is useable in a battle.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_is_usable(ptr: ExternPointer<Pokemon>) -> u8 {
|
||||
u8::from(ptr.as_ref().is_usable())
|
||||
extern "C" fn pokemon_is_usable(handle: FFIHandle<Pokemon>) -> u8 {
|
||||
u8::from(handle.from_ffi_handle().is_usable())
|
||||
}
|
||||
|
||||
/// Returns whether the Pokemon is fainted.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_is_fainted(ptr: ExternPointer<Pokemon>) -> u8 {
|
||||
u8::from(ptr.as_ref().is_fainted())
|
||||
extern "C" fn pokemon_is_fainted(handle: FFIHandle<Pokemon>) -> u8 {
|
||||
u8::from(handle.from_ffi_handle().is_fainted())
|
||||
}
|
||||
|
||||
/// Whether or not the Pokemon is on the battlefield.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_is_on_battlefield(ptr: ExternPointer<Pokemon>) -> u8 {
|
||||
u8::from(ptr.as_ref().is_on_battlefield())
|
||||
extern "C" fn pokemon_is_on_battlefield(handle: FFIHandle<Pokemon>) -> u8 {
|
||||
u8::from(handle.from_ffi_handle().is_on_battlefield())
|
||||
}
|
||||
|
||||
/// Damages the Pokemon by a certain amount of damage, from a damage source.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_damage(ptr: ExternPointer<Pokemon>, damage: u32, source: DamageSource) -> NativeResult<()> {
|
||||
ptr.as_ref().damage(damage, source).into()
|
||||
extern "C" fn pokemon_damage(handle: FFIHandle<Pokemon>, damage: u32, source: DamageSource) -> FFIResult<()> {
|
||||
handle.from_ffi_handle().damage(damage, source).into()
|
||||
}
|
||||
|
||||
/// Heals the Pokemon by a specific amount. Unless allow_revive is set to true, this will not
|
||||
/// heal if the Pokemon has 0 health. If the amount healed is 0, this will return false.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_heal(ptr: ExternPointer<Pokemon>, amount: u32, allow_revive: u8) -> bool {
|
||||
ptr.as_ref().heal(amount, allow_revive == 1)
|
||||
extern "C" fn pokemon_heal(handle: FFIHandle<Pokemon>, amount: u32, allow_revive: u8) -> bool {
|
||||
handle.from_ffi_handle().heal(amount, allow_revive == 1)
|
||||
}
|
||||
|
||||
/// Learn a move.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_learn_move(
|
||||
ptr: ExternPointer<Pokemon>,
|
||||
handle: FFIHandle<Pokemon>,
|
||||
move_name: *const c_char,
|
||||
learn_method: MoveLearnMethod,
|
||||
) -> NativeResult<()> {
|
||||
) -> FFIResult<()> {
|
||||
unsafe {
|
||||
ptr.as_ref()
|
||||
handle
|
||||
.from_ffi_handle()
|
||||
.learn_move(&CStr::from_ptr(move_name).into(), learn_method)
|
||||
.into()
|
||||
}
|
||||
@@ -377,6 +414,6 @@ extern "C" fn pokemon_learn_move(
|
||||
|
||||
/// Removes the current non-volatile status from the Pokemon.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_clear_status(ptr: ExternPointer<Pokemon>) {
|
||||
ptr.as_ref().clear_status()
|
||||
extern "C" fn pokemon_clear_status(handle: FFIHandle<Pokemon>) {
|
||||
handle.from_ffi_handle().clear_status()
|
||||
}
|
||||
|
||||
@@ -1,68 +1,69 @@
|
||||
use crate::dynamic_data::{Pokemon, PokemonParty};
|
||||
use crate::ffi::{ExternPointer, IdentifiablePointer, NativeResult};
|
||||
use crate::ffi::ffi_handle::{FFIHandle, FromFFIHandle};
|
||||
use crate::ffi::FFIResult;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Instantiates a party with a set size.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_party_new(capacity: usize) -> IdentifiablePointer<Arc<PokemonParty>> {
|
||||
Arc::new(PokemonParty::new(capacity)).into()
|
||||
extern "C" fn pokemon_party_new(capacity: usize) -> FFIHandle<Arc<PokemonParty>> {
|
||||
FFIHandle::get_handle(Arc::new(PokemonParty::new(capacity)).into())
|
||||
}
|
||||
|
||||
/// Gets a Pokemon at an index in the party.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_party_at(ptr: ExternPointer<Arc<PokemonParty>>, index: usize) -> IdentifiablePointer<Pokemon> {
|
||||
if let Some(v) = ptr.as_ref().at(index) {
|
||||
v.into()
|
||||
extern "C" fn pokemon_party_at(ptr: FFIHandle<Arc<PokemonParty>>, index: usize) -> FFIHandle<Pokemon> {
|
||||
if let Some(v) = ptr.from_ffi_handle().at(index) {
|
||||
FFIHandle::get_handle(v.into())
|
||||
} else {
|
||||
IdentifiablePointer::none()
|
||||
FFIHandle::none()
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a Pokemon at an index in the party.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_party_switch(ptr: ExternPointer<Arc<PokemonParty>>, a: usize, b: usize) {
|
||||
ptr.as_ref().switch(a, b);
|
||||
extern "C" fn pokemon_party_switch(ptr: FFIHandle<Arc<PokemonParty>>, a: usize, b: usize) {
|
||||
ptr.from_ffi_handle().switch(a, b);
|
||||
}
|
||||
|
||||
/// Sets the Pokemon at an index to a Pokemon, returning the old Pokemon.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_party_swap_into(
|
||||
ptr: ExternPointer<Arc<PokemonParty>>,
|
||||
ptr: FFIHandle<Arc<PokemonParty>>,
|
||||
index: usize,
|
||||
pokemon: ExternPointer<Pokemon>,
|
||||
) -> NativeResult<IdentifiablePointer<Pokemon>> {
|
||||
let pokemon = if pokemon.ptr.is_null() {
|
||||
pokemon: FFIHandle<Pokemon>,
|
||||
) -> FFIResult<FFIHandle<Pokemon>> {
|
||||
let pokemon = if pokemon.is_none() {
|
||||
None
|
||||
} else {
|
||||
Some(pokemon.as_ref().clone())
|
||||
Some(pokemon.from_ffi_handle())
|
||||
};
|
||||
match ptr.as_ref().swap_into(index, pokemon) {
|
||||
Ok(Some(v)) => NativeResult::ok(v.into()),
|
||||
Ok(None) => NativeResult::ok(IdentifiablePointer::none()),
|
||||
Err(e) => NativeResult::err(e),
|
||||
match ptr.from_ffi_handle().swap_into(index, pokemon) {
|
||||
Ok(Some(v)) => FFIResult::ok(FFIHandle::get_handle(v.into())),
|
||||
Ok(None) => FFIResult::ok(FFIHandle::none()),
|
||||
Err(e) => FFIResult::err(e),
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether or not the party still has Pokemon that can be used in battle.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_party_has_usable_pokemon(ptr: ExternPointer<Arc<PokemonParty>>) -> u8 {
|
||||
u8::from(ptr.as_ref().has_usable_pokemon())
|
||||
extern "C" fn pokemon_party_has_usable_pokemon(ptr: FFIHandle<Arc<PokemonParty>>) -> u8 {
|
||||
u8::from(ptr.from_ffi_handle().has_usable_pokemon())
|
||||
}
|
||||
|
||||
/// Get the length of the underlying list of Pokemon.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_party_length(ptr: ExternPointer<Arc<PokemonParty>>) -> usize {
|
||||
ptr.as_ref().length()
|
||||
extern "C" fn pokemon_party_length(ptr: FFIHandle<Arc<PokemonParty>>) -> usize {
|
||||
ptr.from_ffi_handle().length()
|
||||
}
|
||||
|
||||
/// Makes sure there are no empty spots in the party anymore, leaving the length the same.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_party_pack_party(ptr: ExternPointer<Arc<PokemonParty>>) -> NativeResult<()> {
|
||||
ptr.as_ref().pack_party().into()
|
||||
extern "C" fn pokemon_party_pack_party(ptr: FFIHandle<Arc<PokemonParty>>) -> FFIResult<()> {
|
||||
ptr.from_ffi_handle().pack_party().into()
|
||||
}
|
||||
|
||||
/// Checks if the party contains a given pokemon.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_party_has_pokemon(ptr: ExternPointer<Arc<PokemonParty>>, pokemon: ExternPointer<Pokemon>) -> u8 {
|
||||
u8::from(ptr.as_ref().has_pokemon(pokemon.as_ref()))
|
||||
extern "C" fn pokemon_party_has_pokemon(ptr: FFIHandle<Arc<PokemonParty>>, pokemon: FFIHandle<Pokemon>) -> u8 {
|
||||
u8::from(ptr.from_ffi_handle().has_pokemon(&pokemon.from_ffi_handle()))
|
||||
}
|
||||
|
||||
296
src/ffi/ffi_handle.rs
Normal file
296
src/ffi/ffi_handle.rs
Normal file
@@ -0,0 +1,296 @@
|
||||
use crate::static_data::{
|
||||
Ability, EffectParameter, Form, GrowthRate, Item, LearnableMoves, MoveData, Nature, SecondaryEffect, Species,
|
||||
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};
|
||||
|
||||
#[repr(C)]
|
||||
pub(super) struct FFIHandle<T> {
|
||||
handle: usize,
|
||||
_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> {}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(super) enum FFIObject {
|
||||
Ability(Arc<dyn Ability>),
|
||||
EffectParameter(Arc<EffectParameter>),
|
||||
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>),
|
||||
}
|
||||
|
||||
unsafe impl Send for FFIObject {}
|
||||
|
||||
unsafe impl Sync for FFIObject {}
|
||||
|
||||
static NEXT_HANDLE: AtomicUsize = AtomicUsize::new(0);
|
||||
static FFI_OBJECTS: LazyLock<RwLock<HashMap<usize, FFIObject>>> = LazyLock::new(|| RwLock::new(HashMap::new()));
|
||||
static FFI_OBJECTS_INVERSE: LazyLock<RwLock<HashMap<FFIObject, usize>>> = LazyLock::new(|| RwLock::new(HashMap::new()));
|
||||
|
||||
impl<T> FFIHandle<T> {
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn none() -> Self {
|
||||
Self {
|
||||
handle: 0,
|
||||
_marker: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
#[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)
|
||||
.ok_or(anyhow!("Unable to get handle"))
|
||||
.unwrap()
|
||||
.clone()
|
||||
}
|
||||
|
||||
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 {}
|
||||
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub(super) trait FromFFIHandle<T> {
|
||||
fn from_ffi_handle(&self) -> T;
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
ffi_obj_conversions!(Arc<EffectParameter>, EffectParameter);
|
||||
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);
|
||||
254
src/ffi/mod.rs
254
src/ffi/mod.rs
@@ -1,68 +1,57 @@
|
||||
/// The foreign function interfaces for the dynamic data
|
||||
mod dynamic_data;
|
||||
mod ffi_handle;
|
||||
/// The foreign function interfaces for that static data
|
||||
mod static_data;
|
||||
|
||||
pub(self) use ffi_handle::*;
|
||||
|
||||
/// Helper type for clearer functions.
|
||||
type OwnedPtr<T> = *mut T;
|
||||
type OwnedPtrString = *mut c_char;
|
||||
/// Helper type for clearer functions.
|
||||
type BorrowedPtr<T> = *const T;
|
||||
type NonOwnedPtrString = *const c_char;
|
||||
|
||||
/// Generates a basic getter foreign function interface.
|
||||
macro_rules! ffi_arc_getter {
|
||||
macro_rules! ffi_handle_arc_dyn_getter {
|
||||
(
|
||||
$type:ty, $func:ident, $returns: ty
|
||||
) => {
|
||||
paste::paste! {
|
||||
#[no_mangle]
|
||||
extern "C" fn [< $type:snake _ $func >](ptr: ExternPointer<Arc<$type>>) -> $returns {
|
||||
ptr.as_ref().$func()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Generates a basic getter foreign function interface.
|
||||
macro_rules! ffi_arc_dyn_getter {
|
||||
(
|
||||
$type:ty, $func:ident, $returns: ty
|
||||
) => {
|
||||
paste::paste! {
|
||||
#[no_mangle]
|
||||
extern "C" fn [< $type:snake _ $func >](ptr: ExternPointer<Arc<dyn $type>>) -> $returns {
|
||||
ptr.as_ref().$func()
|
||||
extern "C" fn [< $type:snake _ $func >](ptr: FFIHandle<Arc<dyn $type>>) -> $returns {
|
||||
ptr.from_ffi_handle().$func()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Generates a basic getter foreign function interface where the return type is a [`crate::StringKey`].
|
||||
macro_rules! ffi_arc_stringkey_getter {
|
||||
macro_rules! ffi_handle_arc_stringkey_getter {
|
||||
(
|
||||
$type:ty, $func:ident
|
||||
) => {
|
||||
paste::paste! {
|
||||
#[no_mangle]
|
||||
extern "C" fn [< $type:lower _ $func >](ptr: ExternPointer<Arc<dyn $type>>) -> OwnedPtr<c_char> {
|
||||
std::ffi::CString::new(ptr.as_ref().$func().str()).unwrap().into_raw()
|
||||
extern "C" fn [< $type:lower _ $func >](ptr: FFIHandle<Arc<dyn $type>>) -> NonOwnedPtrString {
|
||||
std::ffi::CString::new(ptr.from_ffi_handle().$func().str()).unwrap().into_raw()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Generates a foreign function interface for a vec. This generates a length function, and a getter.
|
||||
macro_rules! ffi_vec_value_getters {
|
||||
macro_rules! ffi_handle_vec_value_getters {
|
||||
(
|
||||
$name:ident, $type:ty, $func:ident, $returns: ty
|
||||
) => {
|
||||
paste::paste! {
|
||||
#[no_mangle]
|
||||
extern "C" fn [< $name:lower _ $func _length>](ptr: ExternPointer<Arc<$type>>) -> usize {
|
||||
ptr.as_ref().$func().len()
|
||||
extern "C" fn [< $name:lower _ $func _length>](ptr: FFIHandle<Arc<$type>>) -> usize {
|
||||
ptr.from_ffi_handle().$func().len()
|
||||
}
|
||||
#[no_mangle]
|
||||
extern "C" fn [< $name:lower _ $func _get>](ptr: ExternPointer<Arc<$type>>, index: usize) -> $returns {
|
||||
*ptr.as_ref().$func().get(index).unwrap()
|
||||
extern "C" fn [< $name:lower _ $func _get>](ptr: FFIHandle<Arc<$type>>, index: usize) -> $returns {
|
||||
*ptr.from_ffi_handle().$func().get(index).unwrap()
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -70,33 +59,28 @@ macro_rules! ffi_vec_value_getters {
|
||||
|
||||
/// Generates a foreign function interface for a vec of [`crate::StringKey`]. This generates a
|
||||
/// length function, and a getter.
|
||||
macro_rules! ffi_vec_stringkey_getters {
|
||||
macro_rules! ffi_handle_vec_stringkey_getters {
|
||||
(
|
||||
$type:ty, $func:ident
|
||||
) => {
|
||||
paste::paste! {
|
||||
#[no_mangle]
|
||||
extern "C" fn [< $type:lower _ $func _length>](ptr: ExternPointer<Arc<dyn $type>>) -> usize {
|
||||
ptr.as_ref().$func().len()
|
||||
extern "C" fn [< $type:lower _ $func _length>](ptr: FFIHandle<Arc<dyn $type>>) -> usize {
|
||||
ptr.from_ffi_handle().$func().len()
|
||||
}
|
||||
#[no_mangle]
|
||||
extern "C" fn [< $type:lower _ $func _get>](ptr: ExternPointer<Arc<dyn $type>>, index: usize) -> OwnedPtr<c_char> {
|
||||
CString::new(ptr.as_ref().$func().get(index).unwrap().str()).unwrap().into_raw()
|
||||
extern "C" fn [< $type:lower _ $func _get>](ptr: FFIHandle<Arc<dyn $type>>, index: usize) -> OwnedPtrString {
|
||||
CString::new(ptr.from_ffi_handle().$func().get(index).unwrap().str()).unwrap().into_raw()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
use crate::dynamic_data::{Battle, Pokemon};
|
||||
use crate::{ValueIdentifiable, ValueIdentifier};
|
||||
pub(self) use ffi_arc_dyn_getter;
|
||||
pub(self) use ffi_arc_getter;
|
||||
pub(self) use ffi_arc_stringkey_getter;
|
||||
pub(self) use ffi_vec_stringkey_getters;
|
||||
pub(self) use ffi_vec_value_getters;
|
||||
pub(self) use ffi_handle_arc_dyn_getter;
|
||||
pub(self) use ffi_handle_arc_stringkey_getter;
|
||||
pub(self) use ffi_handle_vec_stringkey_getters;
|
||||
pub(self) use ffi_handle_vec_value_getters;
|
||||
use std::ffi::{c_char, CString};
|
||||
use std::mem::transmute;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Helper utility class to wrap a pointer for extern functions.
|
||||
#[repr(C)]
|
||||
@@ -115,184 +99,6 @@ impl<T: ?Sized> ExternPointer<T> {
|
||||
.unwrap_or_else(|| panic!("Given pointer of type '{}' was null", std::any::type_name::<T>()))
|
||||
}
|
||||
}
|
||||
/// Get the internal pointer as mutable reference.
|
||||
#[allow(clippy::panic)] // We currently allow this as these should never be null, but we might want to change this in the future.
|
||||
pub(self) fn as_mut(&mut self) -> &mut T {
|
||||
unsafe {
|
||||
self.ptr
|
||||
.as_mut()
|
||||
.unwrap_or_else(|| panic!("Given pointer of type '{}' was null", std::any::type_name::<T>()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper utility class to give both the pointer and identifier to a FFI.
|
||||
#[repr(C)]
|
||||
pub(self) struct IdentifiablePointer<T> {
|
||||
/// The wrapped pointer.
|
||||
pub ptr: *const T,
|
||||
/// The identifier of the pointer.
|
||||
pub id: usize,
|
||||
}
|
||||
|
||||
impl<T> Clone for IdentifiablePointer<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
id: self.id,
|
||||
ptr: self.ptr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Copy for IdentifiablePointer<T> {}
|
||||
|
||||
impl<T> IdentifiablePointer<T> {
|
||||
/// Creates a new IdentifiablePointer.
|
||||
pub(self) fn new(ptr: *const T, id: ValueIdentifier) -> Self {
|
||||
unsafe { Self { ptr, id: transmute(id) } }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<*mut T> for ExternPointer<T> {
|
||||
fn from(ptr: *mut T) -> Self {
|
||||
ExternPointer { ptr }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ValueIdentifiable + ?Sized> From<Arc<T>> for IdentifiablePointer<Arc<T>> {
|
||||
fn from(v: Arc<T>) -> Self {
|
||||
let id = v.value_identifier().value();
|
||||
Self {
|
||||
ptr: Box::into_raw(Box::new(v)),
|
||||
id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ValueIdentifiable + ?Sized> From<Option<Arc<T>>> for IdentifiablePointer<Arc<T>> {
|
||||
fn from(v: Option<Arc<T>>) -> Self {
|
||||
if let Some(v) = v {
|
||||
let id = unsafe { transmute(v.value_identifier()) };
|
||||
Self {
|
||||
ptr: Box::into_raw(Box::new(v)),
|
||||
id,
|
||||
}
|
||||
} else {
|
||||
IdentifiablePointer::none()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ValueIdentifiable + ?Sized> From<Box<T>> for IdentifiablePointer<Box<T>> {
|
||||
fn from(v: Box<T>) -> Self {
|
||||
let id = unsafe { transmute(v.value_identifier()) };
|
||||
Self {
|
||||
ptr: Box::into_raw(Box::new(v)),
|
||||
id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ValueIdentifiable + ?Sized> From<&Box<T>> for IdentifiablePointer<Box<T>> {
|
||||
fn from(v: &Box<T>) -> Self {
|
||||
let id = unsafe { transmute(v.value_identifier()) };
|
||||
Self {
|
||||
ptr: v as *const Box<T>,
|
||||
id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ValueIdentifiable + ?Sized> From<Option<Box<T>>> for IdentifiablePointer<Box<T>> {
|
||||
fn from(v: Option<Box<T>>) -> Self {
|
||||
if let Some(v) = v {
|
||||
let id = unsafe { transmute(v.value_identifier()) };
|
||||
Self {
|
||||
ptr: Box::into_raw(Box::new(v)),
|
||||
id,
|
||||
}
|
||||
} else {
|
||||
IdentifiablePointer::none()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ValueIdentifiable + ?Sized> From<&Option<Box<T>>> for IdentifiablePointer<Box<T>> {
|
||||
fn from(v: &Option<Box<T>>) -> Self {
|
||||
if let Some(v) = v {
|
||||
let id = unsafe { transmute(v.value_identifier()) };
|
||||
unsafe {
|
||||
Self {
|
||||
ptr: *Box::into_raw(Box::new(v as *const Box<T>)),
|
||||
id,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
IdentifiablePointer::none()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ValueIdentifiable> From<Box<T>> for IdentifiablePointer<T> {
|
||||
fn from(v: Box<T>) -> Self {
|
||||
let id = unsafe { transmute(v.value_identifier()) };
|
||||
Self {
|
||||
ptr: Box::into_raw(v),
|
||||
id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ValueIdentifiable> From<*const T> for IdentifiablePointer<T> {
|
||||
#[allow(clippy::unwrap_used)] // We currently allow this as these should never be null, but we might want to change this in the future.
|
||||
fn from(v: *const T) -> Self {
|
||||
let id = unsafe { transmute(v.as_ref().unwrap().value_identifier()) };
|
||||
Self { ptr: v, id }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Pokemon> for IdentifiablePointer<Pokemon> {
|
||||
fn from(v: Pokemon) -> Self {
|
||||
let id = v.value_identifier().value();
|
||||
Self {
|
||||
ptr: Box::into_raw(Box::new(v)),
|
||||
id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Option<Pokemon>> for IdentifiablePointer<Pokemon> {
|
||||
fn from(v: Option<Pokemon>) -> Self {
|
||||
if let Some(v) = v {
|
||||
let id = unsafe { transmute(v.value_identifier()) };
|
||||
Self {
|
||||
ptr: Box::into_raw(Box::new(v)),
|
||||
id,
|
||||
}
|
||||
} else {
|
||||
IdentifiablePointer::none()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Battle> for IdentifiablePointer<Battle> {
|
||||
fn from(v: Battle) -> Self {
|
||||
let id = v.value_identifier().value();
|
||||
Self {
|
||||
ptr: Box::into_raw(Box::new(v)),
|
||||
id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> IdentifiablePointer<T> {
|
||||
/// Returns an identifiable pointer with null as pointer, and 0 as identifier.
|
||||
pub fn none() -> Self {
|
||||
Self {
|
||||
ptr: std::ptr::null(),
|
||||
id: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper utility class to give either the data or an error to a FFI.
|
||||
@@ -301,19 +107,19 @@ union ResultUnion<T: Copy> {
|
||||
/// If the result is ok, this contains the value.
|
||||
ok: T,
|
||||
/// If the result is an error, this contains the error message.
|
||||
err: OwnedPtr<c_char>,
|
||||
err: NonOwnedPtrString,
|
||||
}
|
||||
|
||||
/// The result of a FFI call that can either be an error or a value.
|
||||
#[repr(C)]
|
||||
pub struct NativeResult<T: Copy> {
|
||||
pub struct FFIResult<T: Copy> {
|
||||
/// If the result is ok, this is 1, otherwise 0.
|
||||
ok: u8,
|
||||
/// The value or error.
|
||||
value: ResultUnion<T>,
|
||||
}
|
||||
|
||||
impl<T: Copy> NativeResult<T> {
|
||||
impl<T: Copy> FFIResult<T> {
|
||||
/// Creates a new NativeResult with the given value.
|
||||
pub fn ok(value: T) -> Self {
|
||||
Self {
|
||||
@@ -344,7 +150,7 @@ impl<T: Copy> NativeResult<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> From<anyhow::Result<T>> for NativeResult<T> {
|
||||
impl<T: Copy> From<anyhow::Result<T>> for FFIResult<T> {
|
||||
fn from(value: anyhow::Result<T>) -> Self {
|
||||
match value {
|
||||
Ok(v) => Self::ok(v),
|
||||
@@ -353,7 +159,7 @@ impl<T: Copy> From<anyhow::Result<T>> for NativeResult<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> From<T> for NativeResult<T> {
|
||||
impl<T: Copy> From<T> for FFIResult<T> {
|
||||
fn from(value: T) -> Self {
|
||||
Self::ok(value)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use crate::ffi::{ExternPointer, IdentifiablePointer, NativeResult, OwnedPtr};
|
||||
use crate::ffi::FFIHandle;
|
||||
use crate::ffi::FromFFIHandle;
|
||||
use crate::ffi::{FFIResult, OwnedPtrString};
|
||||
use crate::static_data::{Ability, AbilityImpl, EffectParameter};
|
||||
use crate::StringKey;
|
||||
use anyhow::anyhow;
|
||||
use std::ffi::{c_char, CStr, CString};
|
||||
use std::ptr::drop_in_place;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Instantiates a new ability.
|
||||
@@ -11,67 +12,61 @@ use std::sync::Arc;
|
||||
unsafe extern "C" fn ability_new(
|
||||
name: *const c_char,
|
||||
effect: *const c_char,
|
||||
parameters: *const OwnedPtr<Arc<EffectParameter>>,
|
||||
parameters: *const FFIHandle<Arc<EffectParameter>>,
|
||||
parameters_length: usize,
|
||||
) -> NativeResult<IdentifiablePointer<Arc<dyn Ability>>> {
|
||||
) -> FFIResult<FFIHandle<Arc<dyn Ability>>> {
|
||||
let parameters = std::slice::from_raw_parts(parameters, parameters_length);
|
||||
let mut parameters_vec: Vec<Arc<EffectParameter>> = Vec::with_capacity(parameters_length);
|
||||
for parameter in parameters {
|
||||
parameters_vec.push(parameter.read());
|
||||
parameters_vec.push(parameter.from_ffi_handle());
|
||||
}
|
||||
|
||||
let name: StringKey = match CStr::from_ptr(name).to_str() {
|
||||
Ok(s) => s.into(),
|
||||
Err(_) => return NativeResult::err(anyhow!("Failed to convert name to CStr")),
|
||||
Err(_) => return FFIResult::err(anyhow!("Failed to convert name to CStr")),
|
||||
};
|
||||
let effect: StringKey = match CStr::from_ptr(effect).to_str() {
|
||||
Ok(s) => s.into(),
|
||||
Err(_) => return NativeResult::err(anyhow!("Failed to convert effect to CStr")),
|
||||
Err(_) => return FFIResult::err(anyhow!("Failed to convert effect to CStr")),
|
||||
};
|
||||
|
||||
let arc: Arc<dyn Ability> = Arc::new(AbilityImpl::new(&name, &effect, parameters_vec));
|
||||
NativeResult::ok(arc.into())
|
||||
}
|
||||
|
||||
/// Drops a reference counted ability.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn ability_drop(ptr: OwnedPtr<Arc<dyn Ability>>) {
|
||||
drop_in_place(ptr)
|
||||
FFIResult::ok(FFIHandle::get_handle(arc.into()))
|
||||
}
|
||||
|
||||
/// The name of the ability.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn ability_name(ptr: ExternPointer<Arc<dyn Ability>>) -> NativeResult<OwnedPtr<c_char>> {
|
||||
match CString::new(ptr.as_ref().name().str()) {
|
||||
Ok(s) => NativeResult::ok(s.into_raw()),
|
||||
Err(_) => NativeResult::err(anyhow!("Failed to convert name to CString")),
|
||||
unsafe extern "C" fn ability_name(handle: FFIHandle<Arc<dyn Ability>>) -> FFIResult<OwnedPtrString> {
|
||||
match CString::new(handle.from_ffi_handle().name().str()) {
|
||||
Ok(s) => FFIResult::ok(s.into_raw()),
|
||||
Err(_) => FFIResult::err(anyhow!("Failed to convert name to CString")),
|
||||
}
|
||||
}
|
||||
|
||||
/// The name of the script effect of the ability.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn ability_effect(ptr: ExternPointer<Arc<dyn Ability>>) -> NativeResult<OwnedPtr<c_char>> {
|
||||
match CString::new(ptr.as_ref().effect().str()) {
|
||||
Ok(s) => NativeResult::ok(s.into_raw()),
|
||||
Err(_) => NativeResult::err(anyhow!("Failed to convert effect to CString")),
|
||||
unsafe extern "C" fn ability_effect(ptr: FFIHandle<Arc<dyn Ability>>) -> FFIResult<OwnedPtrString> {
|
||||
match CString::new(ptr.from_ffi_handle().effect().str()) {
|
||||
Ok(s) => FFIResult::ok(s.into_raw()),
|
||||
Err(_) => FFIResult::err(anyhow!("Failed to convert effect to CString")),
|
||||
}
|
||||
}
|
||||
|
||||
/// The length of the parameters for the script effect of the ability.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn ability_parameter_length(ptr: ExternPointer<Arc<dyn Ability>>) -> usize {
|
||||
ptr.as_ref().parameters().len()
|
||||
unsafe extern "C" fn ability_parameter_length(ptr: FFIHandle<Arc<dyn Ability>>) -> usize {
|
||||
ptr.from_ffi_handle().parameters().len()
|
||||
}
|
||||
|
||||
/// Gets a parameter for the script effect of the ability.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn ability_parameter_get(
|
||||
ptr: ExternPointer<Arc<dyn Ability>>,
|
||||
ptr: FFIHandle<Arc<dyn Ability>>,
|
||||
index: usize,
|
||||
) -> IdentifiablePointer<Arc<EffectParameter>> {
|
||||
if let Some(p) = ptr.as_ref().parameters().get(index) {
|
||||
p.clone().into()
|
||||
) -> FFIHandle<Arc<EffectParameter>> {
|
||||
if let Some(p) = ptr.from_ffi_handle().parameters().get(index) {
|
||||
FFIHandle::get_handle(p.clone().into())
|
||||
} else {
|
||||
IdentifiablePointer::none()
|
||||
FFIHandle::none()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use crate::ffi::ffi_handle::{FFIHandle, FromFFIHandle};
|
||||
use crate::ffi::{
|
||||
ffi_arc_dyn_getter, ffi_vec_stringkey_getters, ffi_vec_value_getters, BorrowedPtr, ExternPointer,
|
||||
IdentifiablePointer, NativeResult, OwnedPtr,
|
||||
ffi_handle_arc_dyn_getter, ffi_handle_vec_stringkey_getters, ffi_handle_vec_value_getters, FFIResult,
|
||||
NonOwnedPtrString, OwnedPtrString,
|
||||
};
|
||||
use crate::static_data::{Form, FormImpl, LearnableMoves, StaticStatisticSet, TypeIdentifier};
|
||||
use crate::StringKey;
|
||||
use anyhow::anyhow;
|
||||
use hashbrown::HashSet;
|
||||
use std::ffi::{c_char, CStr, CString};
|
||||
use std::ptr::drop_in_place;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Instantiates a new form.
|
||||
@@ -19,18 +19,18 @@ unsafe extern "C" fn form_new(
|
||||
base_experience: u32,
|
||||
types: *const TypeIdentifier,
|
||||
types_length: usize,
|
||||
base_stats: OwnedPtr<StaticStatisticSet<u16>>,
|
||||
abilities: *const BorrowedPtr<c_char>,
|
||||
base_stats: FFIHandle<Arc<StaticStatisticSet<u16>>>,
|
||||
abilities: *const NonOwnedPtrString,
|
||||
abilities_length: usize,
|
||||
hidden_abilities: *const BorrowedPtr<c_char>,
|
||||
hidden_abilities: *const NonOwnedPtrString,
|
||||
hidden_abilities_length: usize,
|
||||
moves: OwnedPtr<Box<dyn LearnableMoves>>,
|
||||
moves: FFIHandle<Arc<dyn LearnableMoves>>,
|
||||
flags: *const *const c_char,
|
||||
flags_length: usize,
|
||||
) -> NativeResult<IdentifiablePointer<Arc<dyn Form>>> {
|
||||
) -> FFIResult<FFIHandle<Arc<dyn Form>>> {
|
||||
let name: StringKey = match CStr::from_ptr(name).to_str() {
|
||||
Ok(name) => name.into(),
|
||||
Err(_) => return NativeResult::err(anyhow!("Unable to convert name to string")),
|
||||
Err(_) => return FFIResult::err(anyhow!("Unable to convert name to string")),
|
||||
};
|
||||
|
||||
let abilities = std::slice::from_raw_parts(abilities, abilities_length);
|
||||
@@ -49,7 +49,7 @@ unsafe extern "C" fn form_new(
|
||||
for flag in flags {
|
||||
let flag = match CStr::from_ptr(*flag).to_str() {
|
||||
Ok(flag) => flag,
|
||||
Err(_) => return NativeResult::err(anyhow!("Unable to convert flag to string")),
|
||||
Err(_) => return FFIResult::err(anyhow!("Unable to convert flag to string")),
|
||||
};
|
||||
flags_set.insert(flag.into());
|
||||
}
|
||||
@@ -60,57 +60,50 @@ unsafe extern "C" fn form_new(
|
||||
weight,
|
||||
base_experience,
|
||||
std::slice::from_raw_parts(types, types_length).to_vec(),
|
||||
*Box::from_raw(base_stats),
|
||||
base_stats.from_ffi_handle(),
|
||||
abilities_vec,
|
||||
hidden_abilities_vec,
|
||||
*Box::from_raw(moves),
|
||||
moves.from_ffi_handle(),
|
||||
flags_set,
|
||||
));
|
||||
NativeResult::ok(a.into())
|
||||
}
|
||||
|
||||
/// Drops a reference count for a form.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn form_drop(ptr: OwnedPtr<Arc<dyn Form>>) {
|
||||
drop_in_place(ptr)
|
||||
FFIResult::ok(FFIHandle::get_handle(a.into()))
|
||||
}
|
||||
|
||||
/// The name of the form.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn form_name(ptr: ExternPointer<Arc<dyn Form>>) -> NativeResult<OwnedPtr<c_char>> {
|
||||
let name = ptr.as_ref().name();
|
||||
unsafe extern "C" fn form_name(ptr: FFIHandle<Arc<dyn Form>>) -> FFIResult<OwnedPtrString> {
|
||||
let obj = ptr.from_ffi_handle();
|
||||
let name = obj.name();
|
||||
match CString::new(name.str()) {
|
||||
Ok(name) => NativeResult::ok(name.into_raw()),
|
||||
Err(_) => NativeResult::err(anyhow!("Unable to convert name `{}` to CString", name.str())),
|
||||
Ok(name) => FFIResult::ok(name.into_raw()),
|
||||
Err(_) => FFIResult::err(anyhow!("Unable to convert name `{}` to CString", name.str())),
|
||||
}
|
||||
}
|
||||
|
||||
ffi_arc_dyn_getter!(Form, height, f32);
|
||||
ffi_arc_dyn_getter!(Form, weight, f32);
|
||||
ffi_arc_dyn_getter!(Form, base_experience, u32);
|
||||
ffi_handle_arc_dyn_getter!(Form, height, f32);
|
||||
ffi_handle_arc_dyn_getter!(Form, weight, f32);
|
||||
ffi_handle_arc_dyn_getter!(Form, base_experience, u32);
|
||||
|
||||
ffi_vec_value_getters!(Form, dyn Form, types, TypeIdentifier);
|
||||
ffi_handle_vec_value_getters!(Form, dyn Form, types, TypeIdentifier);
|
||||
|
||||
/// The inherent values of a form of species that are used for the stats of a Pokemon.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn form_base_stats(
|
||||
ptr: ExternPointer<Arc<dyn Form>>,
|
||||
) -> IdentifiablePointer<Arc<StaticStatisticSet<u16>>> {
|
||||
ptr.as_ref().base_stats().clone().into()
|
||||
unsafe extern "C" fn form_base_stats(ptr: FFIHandle<Arc<dyn Form>>) -> FFIHandle<Arc<StaticStatisticSet<u16>>> {
|
||||
FFIHandle::get_handle(ptr.from_ffi_handle().base_stats().clone().into())
|
||||
}
|
||||
|
||||
ffi_vec_stringkey_getters!(Form, abilities);
|
||||
ffi_vec_stringkey_getters!(Form, hidden_abilities);
|
||||
ffi_handle_vec_stringkey_getters!(Form, abilities);
|
||||
ffi_handle_vec_stringkey_getters!(Form, hidden_abilities);
|
||||
|
||||
/// The moves a Pokemon with this form can learn.
|
||||
#[no_mangle]
|
||||
extern "C" fn form_moves(ptr: ExternPointer<Arc<dyn Form>>) -> BorrowedPtr<Box<dyn LearnableMoves>> {
|
||||
ptr.as_ref().moves() as *const Box<dyn LearnableMoves>
|
||||
extern "C" fn form_moves(ptr: FFIHandle<Arc<dyn Form>>) -> FFIHandle<Arc<dyn LearnableMoves>> {
|
||||
FFIHandle::get_handle(ptr.from_ffi_handle().moves().clone().into())
|
||||
}
|
||||
|
||||
/// Check if the form has a specific flag set.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn form_has_flag(ptr: ExternPointer<Arc<dyn Form>>, flag: *const c_char) -> u8 {
|
||||
unsafe extern "C" fn form_has_flag(ptr: FFIHandle<Arc<dyn Form>>, flag: *const c_char) -> u8 {
|
||||
let flag = CStr::from_ptr(flag).into();
|
||||
u8::from(ptr.as_ref().has_flag(&flag))
|
||||
u8::from(ptr.from_ffi_handle().has_flag(&flag))
|
||||
}
|
||||
|
||||
@@ -1,33 +1,26 @@
|
||||
use crate::defines::LevelInt;
|
||||
use crate::ffi::{ExternPointer, NativeResult, OwnedPtr};
|
||||
use crate::ffi::ffi_handle::{FFIHandle, FromFFIHandle};
|
||||
use crate::ffi::FFIResult;
|
||||
use crate::static_data::{GrowthRate, LookupGrowthRate};
|
||||
use std::ptr::drop_in_place;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Instantiates a new lookup growth rate. The experience array should be the amount of experience
|
||||
/// required per level, with the first element being the experience required for level 1 (generally 0).
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn growth_rate_lookup_new(array: *const u32, length: usize) -> OwnedPtr<Box<dyn GrowthRate>> {
|
||||
unsafe extern "C" fn growth_rate_lookup_new(array: *const u32, length: usize) -> FFIHandle<Arc<dyn GrowthRate>> {
|
||||
let array = std::slice::from_raw_parts(array, length);
|
||||
Box::into_raw(Box::new(Box::new(LookupGrowthRate::new(array.to_vec()))))
|
||||
}
|
||||
|
||||
/// Drops the growth rate.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn growth_rate_lookup_drop(ptr: OwnedPtr<Box<dyn GrowthRate>>) {
|
||||
drop_in_place(ptr)
|
||||
let g: Arc<dyn GrowthRate> = Arc::new(LookupGrowthRate::new(array.to_vec()));
|
||||
FFIHandle::get_handle(g.into())
|
||||
}
|
||||
|
||||
/// Calculate the level something with this growth rate would have at a certain experience.
|
||||
#[no_mangle]
|
||||
extern "C" fn growth_rate_calculate_level(ptr: ExternPointer<Box<dyn GrowthRate>>, experience: u32) -> LevelInt {
|
||||
ptr.as_ref().calculate_level(experience)
|
||||
extern "C" fn growth_rate_calculate_level(ptr: FFIHandle<Arc<dyn GrowthRate>>, experience: u32) -> LevelInt {
|
||||
ptr.from_ffi_handle().calculate_level(experience)
|
||||
}
|
||||
|
||||
/// Calculate the experience something with this growth rate would have at a certain level.
|
||||
#[no_mangle]
|
||||
extern "C" fn growth_rate_calculate_experience(
|
||||
ptr: ExternPointer<Box<dyn GrowthRate>>,
|
||||
level: LevelInt,
|
||||
) -> NativeResult<u32> {
|
||||
ptr.as_ref().calculate_experience(level).into()
|
||||
extern "C" fn growth_rate_calculate_experience(ptr: FFIHandle<Arc<dyn GrowthRate>>, level: LevelInt) -> FFIResult<u32> {
|
||||
ptr.from_ffi_handle().calculate_experience(level).into()
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use crate::ffi::{ffi_arc_dyn_getter, ExternPointer, IdentifiablePointer, NativeResult, OwnedPtr};
|
||||
use crate::ffi::ffi_handle::{FFIHandle, FromFFIHandle};
|
||||
use crate::ffi::{ffi_handle_arc_dyn_getter, FFIResult, OwnedPtrString};
|
||||
use crate::static_data::{BattleItemCategory, Item, ItemCategory, ItemImpl};
|
||||
use crate::StringKey;
|
||||
use anyhow::anyhow;
|
||||
use hashbrown::HashSet;
|
||||
use std::ffi::{c_char, CStr, CString};
|
||||
use std::ptr::drop_in_place;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Instantiates an item.
|
||||
@@ -16,48 +16,43 @@ unsafe extern "C" fn item_new(
|
||||
price: i32,
|
||||
flags: *const *const c_char,
|
||||
flags_length: usize,
|
||||
) -> NativeResult<IdentifiablePointer<Arc<dyn Item>>> {
|
||||
) -> FFIResult<FFIHandle<Arc<dyn Item>>> {
|
||||
let flags = std::slice::from_raw_parts(flags, flags_length);
|
||||
let name: StringKey = match CStr::from_ptr(name).to_str() {
|
||||
Ok(name) => name.into(),
|
||||
Err(_) => return NativeResult::err(anyhow!("Unable to convert name to string")),
|
||||
Err(_) => return FFIResult::err(anyhow!("Unable to convert name to string")),
|
||||
};
|
||||
let mut flags_set: HashSet<StringKey> = HashSet::with_capacity(flags_length);
|
||||
for flag in flags {
|
||||
let flag = match CStr::from_ptr(*flag).to_str() {
|
||||
Ok(flag) => flag,
|
||||
Err(_) => return NativeResult::err(anyhow!("Unable to convert flag to string")),
|
||||
Err(_) => return FFIResult::err(anyhow!("Unable to convert flag to string")),
|
||||
};
|
||||
flags_set.insert(flag.into());
|
||||
}
|
||||
|
||||
let item: Arc<dyn Item> = Arc::new(ItemImpl::new(&name, category, battle_category, price, flags_set));
|
||||
NativeResult::ok(item.into())
|
||||
}
|
||||
|
||||
/// Drops a reference counted item.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn item_drop(ptr: OwnedPtr<Arc<dyn Item>>) {
|
||||
drop_in_place(ptr)
|
||||
FFIResult::ok(FFIHandle::get_handle(item.into()))
|
||||
}
|
||||
|
||||
/// The name of the item.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn item_name(ptr: ExternPointer<Arc<dyn Item>>) -> NativeResult<OwnedPtr<c_char>> {
|
||||
let name = ptr.as_ref().name();
|
||||
unsafe extern "C" fn item_name(ptr: FFIHandle<Arc<dyn Item>>) -> FFIResult<OwnedPtrString> {
|
||||
let item = ptr.from_ffi_handle();
|
||||
let name = item.name();
|
||||
match CString::new(name.str()) {
|
||||
Ok(name) => NativeResult::ok(name.into_raw()),
|
||||
Err(_) => NativeResult::err(anyhow!("Unable to convert name `{}` to CString", name.str())),
|
||||
Ok(name) => FFIResult::ok(name.into_raw()),
|
||||
Err(_) => FFIResult::err(anyhow!("Unable to convert name `{}` to CString", name.str())),
|
||||
}
|
||||
}
|
||||
|
||||
ffi_arc_dyn_getter!(Item, category, ItemCategory);
|
||||
ffi_arc_dyn_getter!(Item, battle_category, BattleItemCategory);
|
||||
ffi_arc_dyn_getter!(Item, price, i32);
|
||||
ffi_handle_arc_dyn_getter!(Item, category, ItemCategory);
|
||||
ffi_handle_arc_dyn_getter!(Item, battle_category, BattleItemCategory);
|
||||
ffi_handle_arc_dyn_getter!(Item, price, i32);
|
||||
|
||||
/// Checks whether the item has a specific flag.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn item_has_flag(ptr: ExternPointer<Arc<dyn Item>>, flag: *const c_char) -> u8 {
|
||||
unsafe extern "C" fn item_has_flag(ptr: FFIHandle<Arc<dyn Item>>, flag: *const c_char) -> u8 {
|
||||
let flag = CStr::from_ptr(flag).into();
|
||||
u8::from(ptr.as_ref().has_flag(&flag))
|
||||
u8::from(ptr.from_ffi_handle().has_flag(&flag))
|
||||
}
|
||||
|
||||
@@ -1,29 +1,25 @@
|
||||
use crate::defines::LevelInt;
|
||||
use crate::ffi::{BorrowedPtr, ExternPointer, NativeResult, OwnedPtr};
|
||||
use crate::ffi::ffi_handle::{FFIHandle, FromFFIHandle};
|
||||
use crate::ffi::{FFIResult, NonOwnedPtrString};
|
||||
use crate::static_data::{LearnableMoves, LearnableMovesImpl};
|
||||
use std::ffi::{c_char, CStr};
|
||||
use std::ptr::drop_in_place;
|
||||
use std::ffi::CStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Instantiates a new Learnable Moves.
|
||||
#[no_mangle]
|
||||
extern "C" fn learnable_moves_new(max_level: LevelInt) -> OwnedPtr<Box<dyn LearnableMoves>> {
|
||||
Box::into_raw(Box::new(Box::new(LearnableMovesImpl::new(max_level))))
|
||||
}
|
||||
|
||||
/// drops a learnablemoves struct.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn learnable_moves_drop(ptr: OwnedPtr<Box<dyn LearnableMoves>>) {
|
||||
drop_in_place(ptr)
|
||||
extern "C" fn learnable_moves_new(max_level: LevelInt) -> FFIHandle<Arc<dyn LearnableMoves>> {
|
||||
let p: Arc<dyn LearnableMoves> = Arc::new(LearnableMovesImpl::new(max_level));
|
||||
FFIHandle::get_handle(p.into())
|
||||
}
|
||||
|
||||
/// Adds a new level move the Pokemon can learn.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn learnable_moves_add_level_move(
|
||||
mut ptr: ExternPointer<Box<dyn LearnableMoves>>,
|
||||
ptr: FFIHandle<Arc<dyn LearnableMoves>>,
|
||||
level: LevelInt,
|
||||
move_name: BorrowedPtr<c_char>,
|
||||
) -> NativeResult<()> {
|
||||
ptr.as_mut()
|
||||
move_name: NonOwnedPtrString,
|
||||
) -> FFIResult<()> {
|
||||
ptr.from_ffi_handle()
|
||||
.add_level_move(level, &CStr::from_ptr(move_name).into())
|
||||
.into()
|
||||
}
|
||||
|
||||
@@ -1,30 +1,25 @@
|
||||
use crate::defines::LevelInt;
|
||||
use crate::ffi::{BorrowedPtr, ExternPointer, IdentifiablePointer, NativeResult, OwnedPtr};
|
||||
use crate::ffi::ffi_handle::{FFIHandle, FromFFIHandle};
|
||||
use crate::ffi::{FFIResult, NonOwnedPtrString};
|
||||
use crate::static_data::{GrowthRate, GrowthRateLibrary, GrowthRateLibraryImpl};
|
||||
use std::ffi::{c_char, CStr};
|
||||
use std::ptr::drop_in_place;
|
||||
use std::ffi::CStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Instantiates a new growth rate library with a capacity
|
||||
#[no_mangle]
|
||||
extern "C" fn growth_rate_library_new(capacity: usize) -> IdentifiablePointer<Box<dyn GrowthRateLibrary>> {
|
||||
let b: Box<dyn GrowthRateLibrary> = Box::new(GrowthRateLibraryImpl::new(capacity));
|
||||
b.into()
|
||||
}
|
||||
|
||||
/// Drops the growthrate library.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn growth_rate_library_drop(ptr: OwnedPtr<Box<dyn GrowthRateLibrary>>) {
|
||||
drop_in_place(ptr)
|
||||
extern "C" fn growth_rate_library_new(capacity: usize) -> FFIHandle<Arc<dyn GrowthRateLibrary>> {
|
||||
let b: Arc<dyn GrowthRateLibrary> = Arc::new(GrowthRateLibraryImpl::new(capacity));
|
||||
FFIHandle::get_handle(b.into())
|
||||
}
|
||||
|
||||
/// Calculates the level for a given growth key name and a certain experience.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn growth_rate_library_calculate_level(
|
||||
ptr: ExternPointer<Box<dyn GrowthRateLibrary>>,
|
||||
growth_rate: BorrowedPtr<c_char>,
|
||||
ptr: FFIHandle<Arc<dyn GrowthRateLibrary>>,
|
||||
growth_rate: NonOwnedPtrString,
|
||||
experience: u32,
|
||||
) -> NativeResult<LevelInt> {
|
||||
ptr.as_ref()
|
||||
) -> FFIResult<LevelInt> {
|
||||
ptr.from_ffi_handle()
|
||||
.calculate_level(&CStr::from_ptr(growth_rate).into(), experience)
|
||||
.into()
|
||||
}
|
||||
@@ -32,11 +27,11 @@ unsafe extern "C" fn growth_rate_library_calculate_level(
|
||||
/// Calculates the experience for a given growth key name and a certain level.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn growth_rate_library_calculate_experience(
|
||||
ptr: ExternPointer<Box<dyn GrowthRateLibrary>>,
|
||||
growth_rate: BorrowedPtr<c_char>,
|
||||
ptr: FFIHandle<Arc<dyn GrowthRateLibrary>>,
|
||||
growth_rate: NonOwnedPtrString,
|
||||
level: LevelInt,
|
||||
) -> NativeResult<u32> {
|
||||
ptr.as_ref()
|
||||
) -> FFIResult<u32> {
|
||||
ptr.from_ffi_handle()
|
||||
.calculate_experience(&CStr::from_ptr(growth_rate).into(), level)
|
||||
.into()
|
||||
}
|
||||
@@ -44,10 +39,10 @@ unsafe extern "C" fn growth_rate_library_calculate_experience(
|
||||
/// Adds a new growth rate with a name and value.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn growth_rate_library_add_growth_rate(
|
||||
mut ptr: ExternPointer<Box<dyn GrowthRateLibrary>>,
|
||||
name: BorrowedPtr<c_char>,
|
||||
growth_rate: OwnedPtr<Box<dyn GrowthRate>>,
|
||||
ptr: FFIHandle<Arc<dyn GrowthRateLibrary>>,
|
||||
name: NonOwnedPtrString,
|
||||
growth_rate: FFIHandle<Arc<dyn GrowthRate>>,
|
||||
) {
|
||||
ptr.as_mut()
|
||||
.add_growth_rate(&CStr::from_ptr(name).into(), *Box::from_raw(growth_rate));
|
||||
ptr.from_ffi_handle()
|
||||
.add_growth_rate(&CStr::from_ptr(name).into(), growth_rate.from_ffi_handle());
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use crate::defines::LevelInt;
|
||||
use crate::ffi::{ExternPointer, IdentifiablePointer, NativeResult, OwnedPtr};
|
||||
use crate::ffi::ffi_handle::{FFIHandle, FromFFIHandle};
|
||||
use crate::ffi::FFIResult;
|
||||
use crate::static_data::{LibrarySettings, LibrarySettingsImpl};
|
||||
use std::ptr::drop_in_place;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Creates a new settings library.
|
||||
/// - `maximum_level` is the highest level a Pokemon can be.
|
||||
@@ -12,32 +13,26 @@ use std::ptr::drop_in_place;
|
||||
extern "C" fn library_settings_new(
|
||||
max_level: LevelInt,
|
||||
shiny_rate: u32,
|
||||
) -> NativeResult<IdentifiablePointer<Box<dyn LibrarySettings>>> {
|
||||
) -> FFIResult<FFIHandle<Arc<dyn LibrarySettings>>> {
|
||||
match LibrarySettingsImpl::new(max_level, shiny_rate) {
|
||||
Ok(settings) => {
|
||||
let b: Box<dyn LibrarySettings> = Box::new(settings);
|
||||
let p: IdentifiablePointer<Box<dyn LibrarySettings>> = b.into();
|
||||
p.into()
|
||||
let b: Arc<dyn LibrarySettings> = Arc::new(settings);
|
||||
let p: FFIHandle<Arc<dyn LibrarySettings>> = FFIHandle::get_handle(b.into());
|
||||
FFIResult::ok(p)
|
||||
}
|
||||
Err(e) => NativeResult::err(e),
|
||||
Err(e) => FFIResult::err(e),
|
||||
}
|
||||
}
|
||||
|
||||
/// Drop a library settings object.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn library_settings_drop(ptr: OwnedPtr<Box<dyn LibrarySettings>>) {
|
||||
drop_in_place(ptr)
|
||||
}
|
||||
|
||||
/// The highest level a Pokemon can be.
|
||||
#[no_mangle]
|
||||
extern "C" fn library_settings_maximum_level(ptr: ExternPointer<Box<dyn LibrarySettings>>) -> LevelInt {
|
||||
ptr.as_ref().maximum_level()
|
||||
extern "C" fn library_settings_maximum_level(ptr: FFIHandle<Arc<dyn LibrarySettings>>) -> LevelInt {
|
||||
ptr.from_ffi_handle().maximum_level()
|
||||
}
|
||||
|
||||
/// The chance of a Pokemon being shiny, as the denominator of a fraction, where the nominator
|
||||
/// is 1. For example, if this is 1000, then the chance of a Pokemon being shiny is 1/1000.
|
||||
#[no_mangle]
|
||||
extern "C" fn library_settings_shiny_rate(ptr: ExternPointer<Box<dyn LibrarySettings>>) -> u32 {
|
||||
ptr.as_ref().shiny_rate()
|
||||
extern "C" fn library_settings_shiny_rate(ptr: FFIHandle<Arc<dyn LibrarySettings>>) -> u32 {
|
||||
ptr.from_ffi_handle().shiny_rate()
|
||||
}
|
||||
|
||||
@@ -9,10 +9,10 @@ mod static_data;
|
||||
/// The foreign function interface for the type library.
|
||||
mod type_library;
|
||||
|
||||
use crate::ffi::{BorrowedPtr, IdentifiablePointer, OwnedPtr};
|
||||
use crate::ffi::{FFIHandle, FromFFIHandle};
|
||||
use crate::ffi::{NonOwnedPtrString, OwnedPtrString};
|
||||
use crate::static_data::*;
|
||||
use std::ffi::{c_char, CStr};
|
||||
use std::ptr::drop_in_place;
|
||||
use std::ffi::CStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Generates foreign function interfaces for a DataLibrary trait implementation.
|
||||
@@ -20,42 +20,37 @@ macro_rules! library_interface {
|
||||
($library_type_name:ident, $library_type:ty, $return_type:ty) => {
|
||||
paste::paste! {
|
||||
#[no_mangle]
|
||||
extern "C" fn [< $library_type_name:snake _new >](capacity: usize) -> IdentifiablePointer<$library_type> {
|
||||
let value: $library_type = Box::new([<$library_type_name Impl>]::new(capacity));
|
||||
value.into()
|
||||
extern "C" fn [< $library_type_name:snake _new >](capacity: usize) -> FFIHandle<$library_type> {
|
||||
let value: $library_type = Arc::new([<$library_type_name Impl>]::new(capacity));
|
||||
FFIHandle::get_handle(value.into())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn [< $library_type_name:snake _drop >](ptr: OwnedPtr<$library_type>) {
|
||||
drop_in_place(ptr);
|
||||
unsafe extern "C" fn [< $library_type_name:snake _add >](ptr: FFIHandle<$library_type>, key: NonOwnedPtrString, value: FFIHandle<Arc<$return_type>>) {
|
||||
let lib = ptr.from_ffi_handle();
|
||||
lib.add(&CStr::from_ptr(key).into(), value.from_ffi_handle());
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn [< $library_type_name:snake _add >](ptr: OwnedPtr<$library_type>, key: BorrowedPtr<c_char>, value: OwnedPtr<Arc<$return_type>>) {
|
||||
let lib = ptr.as_mut().unwrap();
|
||||
lib.add(&CStr::from_ptr(key).into(), *Box::from_raw(value));
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn [< $library_type_name:snake _remove >](ptr: OwnedPtr<$library_type>, key: BorrowedPtr<c_char>) {
|
||||
let lib = ptr.as_mut().unwrap();
|
||||
unsafe extern "C" fn [< $library_type_name:snake _remove >](ptr: FFIHandle<$library_type>, key: NonOwnedPtrString) {
|
||||
let lib = ptr.from_ffi_handle();
|
||||
lib.remove(&CStr::from_ptr(key).into());
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn [< $library_type_name:snake _get >](ptr: OwnedPtr<$library_type>, key: BorrowedPtr<c_char>) -> IdentifiablePointer<Arc<$return_type>> {
|
||||
let lib = ptr.as_mut().unwrap();
|
||||
unsafe extern "C" fn [< $library_type_name:snake _get >](ptr: FFIHandle<$library_type>, key: NonOwnedPtrString) -> FFIHandle<Arc<$return_type>> {
|
||||
let lib = ptr.from_ffi_handle();
|
||||
let v = lib.get(&CStr::from_ptr(key).into());
|
||||
if let Some(value) = v {
|
||||
value.clone().into()
|
||||
FFIHandle::get_handle(value.clone().into())
|
||||
} else {
|
||||
IdentifiablePointer::none()
|
||||
FFIHandle::none()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn [< $library_type_name:snake _get_key_by_index >](ptr: OwnedPtr<$library_type>, index: usize) -> OwnedPtr<c_char> {
|
||||
let lib = ptr.as_mut().unwrap();
|
||||
unsafe extern "C" fn [< $library_type_name:snake _get_key_by_index >](ptr: FFIHandle<$library_type>, index: usize) -> OwnedPtrString {
|
||||
let lib = ptr.from_ffi_handle();
|
||||
let v = lib.get_key_by_index(index);
|
||||
if let Some(value) = v {
|
||||
std::ffi::CString::new(value.str()).unwrap().into_raw()
|
||||
@@ -65,15 +60,15 @@ macro_rules! library_interface {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn [< $library_type_name:snake _len >](ptr: OwnedPtr<$library_type>) -> usize {
|
||||
let lib = ptr.as_mut().unwrap();
|
||||
unsafe extern "C" fn [< $library_type_name:snake _len >](ptr: FFIHandle<$library_type>) -> usize {
|
||||
let lib = ptr.from_ffi_handle();
|
||||
lib.len()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
library_interface!(SpeciesLibrary, Box<dyn SpeciesLibrary>, dyn Species);
|
||||
library_interface!(MoveLibrary, Box<dyn MoveLibrary>, dyn MoveData);
|
||||
library_interface!(AbilityLibrary, Box<dyn AbilityLibrary>, dyn Ability);
|
||||
library_interface!(ItemLibrary, Box<dyn ItemLibrary>, dyn Item);
|
||||
library_interface!(SpeciesLibrary, Arc<dyn SpeciesLibrary>, dyn Species);
|
||||
library_interface!(MoveLibrary, Arc<dyn MoveLibrary>, dyn MoveData);
|
||||
library_interface!(AbilityLibrary, Arc<dyn AbilityLibrary>, dyn Ability);
|
||||
library_interface!(ItemLibrary, Arc<dyn ItemLibrary>, dyn Item);
|
||||
|
||||
@@ -1,84 +1,79 @@
|
||||
use crate::ffi::{BorrowedPtr, ExternPointer, IdentifiablePointer, NativeResult, OwnedPtr};
|
||||
use crate::ffi::ffi_handle::{FFIHandle, FromFFIHandle};
|
||||
use crate::ffi::{FFIResult, NonOwnedPtrString, OwnedPtrString};
|
||||
use crate::static_data::{Nature, NatureLibrary, NatureLibraryImpl};
|
||||
use crate::{PkmnError, Random};
|
||||
use anyhow::anyhow;
|
||||
use std::ffi::{c_char, CStr, CString};
|
||||
use std::ptr::drop_in_place;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Creates a new nature library with a given capacity.
|
||||
#[no_mangle]
|
||||
extern "C" fn nature_library_new(capacity: usize) -> IdentifiablePointer<Box<dyn NatureLibrary>> {
|
||||
let b: Box<dyn NatureLibrary> = Box::new(NatureLibraryImpl::new(capacity));
|
||||
b.into()
|
||||
}
|
||||
|
||||
/// Drop a nature library.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn nature_library_drop(ptr: OwnedPtr<Box<dyn NatureLibrary>>) {
|
||||
drop_in_place(ptr);
|
||||
extern "C" fn nature_library_new(capacity: usize) -> FFIHandle<Arc<dyn NatureLibrary>> {
|
||||
let b: Arc<dyn NatureLibrary> = Arc::new(NatureLibraryImpl::new(capacity));
|
||||
FFIHandle::get_handle(b.into())
|
||||
}
|
||||
|
||||
/// Adds a new nature with name to the library.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn nature_library_load_nature(
|
||||
mut ptr: ExternPointer<Box<dyn NatureLibrary>>,
|
||||
name: BorrowedPtr<c_char>,
|
||||
nature: OwnedPtr<Arc<dyn Nature>>,
|
||||
) -> NativeResult<()> {
|
||||
let nature = nature.as_ref().ok_or(PkmnError::NullReference);
|
||||
ptr: FFIHandle<Arc<dyn NatureLibrary>>,
|
||||
name: NonOwnedPtrString,
|
||||
nature: FFIHandle<Arc<dyn Nature>>,
|
||||
) -> FFIResult<()> {
|
||||
let nature = nature.from_ffi_handle_opt().ok_or(PkmnError::NullReference);
|
||||
match nature {
|
||||
Ok(nature) => {
|
||||
ptr.as_mut().load_nature(CStr::from_ptr(name).into(), nature.clone());
|
||||
NativeResult::ok(())
|
||||
ptr.from_ffi_handle()
|
||||
.load_nature(CStr::from_ptr(name).into(), nature.clone());
|
||||
FFIResult::ok(())
|
||||
}
|
||||
Err(e) => NativeResult::err(e.into()),
|
||||
Err(e) => FFIResult::err(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a nature by name.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn nature_library_get_nature(
|
||||
ptr: ExternPointer<Box<dyn NatureLibrary>>,
|
||||
name: BorrowedPtr<c_char>,
|
||||
) -> IdentifiablePointer<Arc<dyn Nature>> {
|
||||
if let Some(nature) = ptr.as_ref().get_nature(&CStr::from_ptr(name).into()) {
|
||||
nature.into()
|
||||
ptr: FFIHandle<Arc<dyn NatureLibrary>>,
|
||||
name: NonOwnedPtrString,
|
||||
) -> FFIHandle<Arc<dyn Nature>> {
|
||||
if let Some(nature) = ptr.from_ffi_handle().get_nature(&CStr::from_ptr(name).into()) {
|
||||
FFIHandle::get_handle(nature.into())
|
||||
} else {
|
||||
IdentifiablePointer::none()
|
||||
FFIHandle::none()
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a random nature.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn nature_library_get_random_nature(
|
||||
ptr: ExternPointer<Box<dyn NatureLibrary>>,
|
||||
ptr: FFIHandle<Arc<dyn NatureLibrary>>,
|
||||
seed: u64,
|
||||
) -> NativeResult<IdentifiablePointer<Arc<dyn Nature>>> {
|
||||
) -> FFIResult<FFIHandle<Arc<dyn Nature>>> {
|
||||
let mut rand = Random::new(seed as u128);
|
||||
match ptr.as_ref().get_random_nature(&mut rand) {
|
||||
Ok(nature) => NativeResult::ok(nature.into()),
|
||||
Err(e) => NativeResult::err(e),
|
||||
match ptr.from_ffi_handle().get_random_nature(&mut rand) {
|
||||
Ok(nature) => FFIResult::ok(FFIHandle::get_handle(nature.into())),
|
||||
Err(e) => FFIResult::err(e),
|
||||
}
|
||||
}
|
||||
|
||||
/// Finds a nature name by nature.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn nature_library_get_nature_name(
|
||||
ptr: ExternPointer<Box<dyn NatureLibrary>>,
|
||||
nature: BorrowedPtr<Arc<dyn Nature>>,
|
||||
) -> NativeResult<OwnedPtr<c_char>> {
|
||||
match nature.as_ref() {
|
||||
ptr: FFIHandle<Arc<dyn NatureLibrary>>,
|
||||
nature: FFIHandle<Arc<dyn Nature>>,
|
||||
) -> FFIResult<OwnedPtrString> {
|
||||
match nature.from_ffi_handle_opt() {
|
||||
Some(nature) => {
|
||||
let name = ptr.as_ref().get_nature_name(nature);
|
||||
let name = ptr.from_ffi_handle().get_nature_name(&nature);
|
||||
match name {
|
||||
Ok(name) => match CString::new(name.str()) {
|
||||
Ok(cstr) => NativeResult::ok(cstr.into_raw()),
|
||||
Err(_) => NativeResult::err(anyhow!("Failed to convert nature name to C string")),
|
||||
Ok(cstr) => FFIResult::ok(cstr.into_raw()),
|
||||
Err(_) => FFIResult::err(anyhow!("Failed to convert nature name to C string")),
|
||||
},
|
||||
Err(e) => NativeResult::err(e),
|
||||
Err(e) => FFIResult::err(e),
|
||||
}
|
||||
}
|
||||
None => NativeResult::err(PkmnError::NullReference.into()),
|
||||
None => FFIResult::err(PkmnError::NullReference.into()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,102 +1,81 @@
|
||||
use crate::ffi::{ExternPointer, IdentifiablePointer, OwnedPtr};
|
||||
use crate::ffi::ffi_handle::{FFIHandle, FromFFIHandle};
|
||||
use crate::static_data::{
|
||||
AbilityLibrary, GrowthRateLibrary, ItemLibrary, LibrarySettings, MoveLibrary, NatureLibrary, SpeciesLibrary,
|
||||
StaticData, StaticDataImpl, TypeLibrary,
|
||||
};
|
||||
use std::ptr::drop_in_place;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Instantiates a new data collection.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn static_data_new(
|
||||
settings: OwnedPtr<Arc<dyn LibrarySettings>>,
|
||||
species: OwnedPtr<Arc<dyn SpeciesLibrary>>,
|
||||
moves: OwnedPtr<Arc<dyn MoveLibrary>>,
|
||||
items: OwnedPtr<Arc<dyn ItemLibrary>>,
|
||||
growth_rates: OwnedPtr<Arc<dyn GrowthRateLibrary>>,
|
||||
types: OwnedPtr<Arc<dyn TypeLibrary>>,
|
||||
natures: OwnedPtr<Arc<dyn NatureLibrary>>,
|
||||
abilities: OwnedPtr<Arc<dyn AbilityLibrary>>,
|
||||
) -> IdentifiablePointer<Arc<dyn StaticData>> {
|
||||
settings: FFIHandle<Arc<dyn LibrarySettings>>,
|
||||
species: FFIHandle<Arc<dyn SpeciesLibrary>>,
|
||||
moves: FFIHandle<Arc<dyn MoveLibrary>>,
|
||||
items: FFIHandle<Arc<dyn ItemLibrary>>,
|
||||
growth_rates: FFIHandle<Arc<dyn GrowthRateLibrary>>,
|
||||
types: FFIHandle<Arc<dyn TypeLibrary>>,
|
||||
natures: FFIHandle<Arc<dyn NatureLibrary>>,
|
||||
abilities: FFIHandle<Arc<dyn AbilityLibrary>>,
|
||||
) -> FFIHandle<Arc<dyn StaticData>> {
|
||||
let b: Arc<dyn StaticData> = Arc::new(StaticDataImpl::new(
|
||||
settings.read(),
|
||||
species.read(),
|
||||
moves.read(),
|
||||
items.read(),
|
||||
growth_rates.read(),
|
||||
types.read(),
|
||||
natures.read(),
|
||||
abilities.read(),
|
||||
settings.from_ffi_handle(),
|
||||
species.from_ffi_handle(),
|
||||
moves.from_ffi_handle(),
|
||||
items.from_ffi_handle(),
|
||||
growth_rates.from_ffi_handle(),
|
||||
types.from_ffi_handle(),
|
||||
natures.from_ffi_handle(),
|
||||
abilities.from_ffi_handle(),
|
||||
));
|
||||
b.into()
|
||||
}
|
||||
|
||||
/// Drop a static data.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn static_data_drop(ptr: OwnedPtr<Box<dyn StaticData>>) {
|
||||
drop_in_place(ptr)
|
||||
FFIHandle::get_handle(b.into())
|
||||
}
|
||||
|
||||
/// Several misc settings for the library.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn static_data_settings(
|
||||
mut data: ExternPointer<Arc<dyn StaticData>>,
|
||||
) -> IdentifiablePointer<Arc<dyn LibrarySettings>> {
|
||||
data.as_mut().settings().clone().into()
|
||||
unsafe extern "C" fn static_data_settings(data: FFIHandle<Arc<dyn StaticData>>) -> FFIHandle<Arc<dyn LibrarySettings>> {
|
||||
FFIHandle::get_handle(data.from_ffi_handle().settings().clone().into())
|
||||
}
|
||||
|
||||
/// All data for Pokemon species.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn static_data_species(
|
||||
mut data: ExternPointer<Arc<dyn StaticData>>,
|
||||
) -> IdentifiablePointer<Arc<dyn SpeciesLibrary>> {
|
||||
data.as_mut().species().clone().into()
|
||||
unsafe extern "C" fn static_data_species(data: FFIHandle<Arc<dyn StaticData>>) -> FFIHandle<Arc<dyn SpeciesLibrary>> {
|
||||
FFIHandle::get_handle(data.from_ffi_handle().species().clone().into())
|
||||
}
|
||||
|
||||
/// All data for the moves.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn static_data_moves(
|
||||
mut data: ExternPointer<Arc<dyn StaticData>>,
|
||||
) -> IdentifiablePointer<Arc<dyn MoveLibrary>> {
|
||||
data.as_mut().moves().clone().into()
|
||||
unsafe extern "C" fn static_data_moves(data: FFIHandle<Arc<dyn StaticData>>) -> FFIHandle<Arc<dyn MoveLibrary>> {
|
||||
FFIHandle::get_handle(data.from_ffi_handle().moves().clone().into())
|
||||
}
|
||||
|
||||
/// All data for the items.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn static_data_items(
|
||||
mut data: ExternPointer<Arc<dyn StaticData>>,
|
||||
) -> IdentifiablePointer<Arc<dyn ItemLibrary>> {
|
||||
(data.as_mut().items()).clone().into()
|
||||
unsafe extern "C" fn static_data_items(data: FFIHandle<Arc<dyn StaticData>>) -> FFIHandle<Arc<dyn ItemLibrary>> {
|
||||
FFIHandle::get_handle((data.from_ffi_handle().items()).clone().into())
|
||||
}
|
||||
|
||||
/// All data for growth rates.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn static_data_growth_rates(
|
||||
mut data: ExternPointer<Arc<dyn StaticData>>,
|
||||
) -> IdentifiablePointer<Arc<dyn GrowthRateLibrary>> {
|
||||
data.as_mut().growth_rates().clone().into()
|
||||
data: FFIHandle<Arc<dyn StaticData>>,
|
||||
) -> FFIHandle<Arc<dyn GrowthRateLibrary>> {
|
||||
FFIHandle::get_handle(data.from_ffi_handle().growth_rates().clone().into())
|
||||
}
|
||||
|
||||
/// All data related to types and type effectiveness.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn static_data_types(
|
||||
mut data: ExternPointer<Arc<dyn StaticData>>,
|
||||
) -> IdentifiablePointer<Arc<dyn TypeLibrary>> {
|
||||
data.as_mut().types().clone().into()
|
||||
unsafe extern "C" fn static_data_types(data: FFIHandle<Arc<dyn StaticData>>) -> FFIHandle<Arc<dyn TypeLibrary>> {
|
||||
FFIHandle::get_handle(data.from_ffi_handle().types().clone().into())
|
||||
}
|
||||
|
||||
/// All data related to natures.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn static_data_natures(
|
||||
data: ExternPointer<Arc<dyn StaticData>>,
|
||||
) -> IdentifiablePointer<Arc<dyn NatureLibrary>> {
|
||||
data.as_ref().natures().clone().into()
|
||||
unsafe extern "C" fn static_data_natures(data: FFIHandle<Arc<dyn StaticData>>) -> FFIHandle<Arc<dyn NatureLibrary>> {
|
||||
FFIHandle::get_handle(data.from_ffi_handle().natures().clone().into())
|
||||
}
|
||||
|
||||
/// All data related to abilities.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn static_data_abilities(
|
||||
mut data: ExternPointer<Arc<dyn StaticData>>,
|
||||
) -> IdentifiablePointer<Arc<dyn AbilityLibrary>> {
|
||||
(data.as_mut().abilities()).clone().into()
|
||||
unsafe extern "C" fn static_data_abilities(data: FFIHandle<Arc<dyn StaticData>>) -> FFIHandle<Arc<dyn AbilityLibrary>> {
|
||||
FFIHandle::get_handle((data.from_ffi_handle().abilities()).clone().into())
|
||||
}
|
||||
|
||||
@@ -1,29 +1,24 @@
|
||||
use crate::ffi::{BorrowedPtr, ExternPointer, IdentifiablePointer, NativeResult, OwnedPtr};
|
||||
use crate::ffi::ffi_handle::{FFIHandle, FromFFIHandle};
|
||||
use crate::ffi::{FFIResult, NonOwnedPtrString};
|
||||
use crate::static_data::{TypeIdentifier, TypeLibrary, TypeLibraryImpl};
|
||||
use std::ffi::{c_char, CStr, CString};
|
||||
use std::ptr::drop_in_place;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Instantiates a new type library with a specific capacity.
|
||||
#[no_mangle]
|
||||
extern "C" fn type_library_new(capacity: usize) -> IdentifiablePointer<Box<dyn TypeLibrary>> {
|
||||
let b: Box<dyn TypeLibrary> = Box::new(TypeLibraryImpl::new(capacity));
|
||||
b.into()
|
||||
}
|
||||
|
||||
/// Drops a type library.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn type_library_drop(ptr: OwnedPtr<Box<dyn TypeLibrary>>) {
|
||||
drop_in_place(ptr);
|
||||
extern "C" fn type_library_new(capacity: usize) -> FFIHandle<Arc<dyn TypeLibrary>> {
|
||||
let b: Arc<dyn TypeLibrary> = Arc::new(TypeLibraryImpl::new(capacity));
|
||||
FFIHandle::get_handle(b.into())
|
||||
}
|
||||
|
||||
/// Gets the type identifier for a type with a name.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn type_library_get_type_id(
|
||||
ptr: ExternPointer<Box<dyn TypeLibrary>>,
|
||||
key: BorrowedPtr<c_char>,
|
||||
ptr: FFIHandle<Arc<dyn TypeLibrary>>,
|
||||
key: NonOwnedPtrString,
|
||||
found: *mut bool,
|
||||
) -> TypeIdentifier {
|
||||
if let Some(v) = ptr.as_ref().get_type_id(&CStr::from_ptr(key).into()) {
|
||||
if let Some(v) = ptr.from_ffi_handle().get_type_id(&CStr::from_ptr(key).into()) {
|
||||
*found = true;
|
||||
v
|
||||
} else {
|
||||
@@ -35,31 +30,33 @@ unsafe extern "C" fn type_library_get_type_id(
|
||||
/// Gets the type name from the type identifier.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn type_library_get_type_name(
|
||||
ptr: ExternPointer<Box<dyn TypeLibrary>>,
|
||||
ptr: FFIHandle<Arc<dyn TypeLibrary>>,
|
||||
type_id: TypeIdentifier,
|
||||
found: *mut bool,
|
||||
) -> NativeResult<*mut c_char> {
|
||||
if let Some(v) = ptr.as_ref().get_type_name(type_id) {
|
||||
) -> FFIResult<*mut c_char> {
|
||||
if let Some(v) = ptr.from_ffi_handle().get_type_name(type_id) {
|
||||
*found = true;
|
||||
|
||||
match CString::new(v.str()) {
|
||||
Ok(v) => NativeResult::ok(v.into_raw()),
|
||||
Err(e) => NativeResult::err(e.into()),
|
||||
Ok(v) => FFIResult::ok(v.into_raw()),
|
||||
Err(e) => FFIResult::err(e.into()),
|
||||
}
|
||||
} else {
|
||||
*found = false;
|
||||
NativeResult::ok(std::ptr::null_mut())
|
||||
FFIResult::ok(std::ptr::null_mut())
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the effectiveness for a single attacking type against a single defending type.
|
||||
#[no_mangle]
|
||||
extern "C" fn type_library_get_single_effectiveness(
|
||||
ptr: ExternPointer<Box<dyn TypeLibrary>>,
|
||||
ptr: FFIHandle<Arc<dyn TypeLibrary>>,
|
||||
attacking: TypeIdentifier,
|
||||
defending: TypeIdentifier,
|
||||
) -> NativeResult<f32> {
|
||||
ptr.as_ref().get_single_effectiveness(attacking, defending).into()
|
||||
) -> FFIResult<f32> {
|
||||
ptr.from_ffi_handle()
|
||||
.get_single_effectiveness(attacking, defending)
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Gets the effectiveness for a single attacking type against an amount of defending types.
|
||||
@@ -67,33 +64,33 @@ extern "C" fn type_library_get_single_effectiveness(
|
||||
/// and multiplying the results with each other.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn type_library_get_effectiveness(
|
||||
ptr: ExternPointer<Box<dyn TypeLibrary>>,
|
||||
ptr: FFIHandle<Arc<dyn TypeLibrary>>,
|
||||
attacking: TypeIdentifier,
|
||||
defending: OwnedPtr<TypeIdentifier>,
|
||||
defending: *const TypeIdentifier,
|
||||
defending_length: usize,
|
||||
) -> NativeResult<f32> {
|
||||
) -> FFIResult<f32> {
|
||||
let v = std::slice::from_raw_parts(defending, defending_length);
|
||||
ptr.as_ref().get_effectiveness(attacking, v).into()
|
||||
ptr.from_ffi_handle().get_effectiveness(attacking, v).into()
|
||||
}
|
||||
|
||||
/// Registers a new type in the library.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn type_library_register_type(
|
||||
mut ptr: ExternPointer<Box<dyn TypeLibrary>>,
|
||||
name: BorrowedPtr<c_char>,
|
||||
ptr: FFIHandle<Arc<dyn TypeLibrary>>,
|
||||
name: NonOwnedPtrString,
|
||||
) -> TypeIdentifier {
|
||||
ptr.as_mut().register_type(&CStr::from_ptr(name).into())
|
||||
ptr.from_ffi_handle().register_type(&CStr::from_ptr(name).into())
|
||||
}
|
||||
|
||||
/// Sets the effectiveness for an attacking type against a defending type.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn type_library_set_effectiveness(
|
||||
mut ptr: ExternPointer<Box<dyn TypeLibrary>>,
|
||||
ptr: FFIHandle<Arc<dyn TypeLibrary>>,
|
||||
attacking: TypeIdentifier,
|
||||
defending: TypeIdentifier,
|
||||
effectiveness: f32,
|
||||
) -> NativeResult<()> {
|
||||
ptr.as_mut()
|
||||
) -> FFIResult<()> {
|
||||
ptr.from_ffi_handle()
|
||||
.set_effectiveness(attacking, defending, effectiveness)
|
||||
.into()
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
use crate::ffi::{ExternPointer, IdentifiablePointer, NativeResult, OwnedPtr};
|
||||
use crate::ffi::ffi_handle::{FFIHandle, FFIObject, FromFFIHandle};
|
||||
use crate::ffi::{FFIResult, OwnedPtrString};
|
||||
use crate::static_data::EffectParameter;
|
||||
use crate::{PkmnError, StringKey};
|
||||
use anyhow::anyhow;
|
||||
use std::ffi::{c_char, CStr, CString};
|
||||
use std::ptr::drop_in_place;
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// The Foreign Function Interface for abilities
|
||||
mod ability;
|
||||
@@ -28,94 +30,88 @@ mod statistic_set;
|
||||
|
||||
/// Instantiates an effect parameter with a boolean.
|
||||
#[no_mangle]
|
||||
extern "C" fn effect_parameter_new_bool(value: u8) -> IdentifiablePointer<EffectParameter> {
|
||||
Box::<EffectParameter>::new((value == 1).into()).into()
|
||||
extern "C" fn effect_parameter_new_bool(value: u8) -> FFIHandle<Arc<EffectParameter>> {
|
||||
FFIHandle::get_handle(FFIObject::EffectParameter(Arc::new(EffectParameter::from(value == 1))))
|
||||
}
|
||||
|
||||
/// Instantiates an effect parameter with an integer.
|
||||
#[no_mangle]
|
||||
extern "C" fn effect_parameter_new_int(value: i64) -> IdentifiablePointer<EffectParameter> {
|
||||
Box::<EffectParameter>::new(value.into()).into()
|
||||
extern "C" fn effect_parameter_new_int(value: i64) -> FFIHandle<Arc<EffectParameter>> {
|
||||
FFIHandle::get_handle(FFIObject::EffectParameter(Arc::new(EffectParameter::from(value))))
|
||||
}
|
||||
|
||||
/// Instantiates an effect parameter with a float.
|
||||
#[no_mangle]
|
||||
extern "C" fn effect_parameter_new_float(value: f32) -> IdentifiablePointer<EffectParameter> {
|
||||
Box::<EffectParameter>::new(value.into()).into()
|
||||
extern "C" fn effect_parameter_new_float(value: f32) -> FFIHandle<Arc<EffectParameter>> {
|
||||
FFIHandle::get_handle(FFIObject::EffectParameter(Arc::new(EffectParameter::from(value))))
|
||||
}
|
||||
|
||||
/// Instantiates an effect parameter with a string.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn effect_parameter_new_string(
|
||||
value: *const c_char,
|
||||
) -> NativeResult<IdentifiablePointer<EffectParameter>> {
|
||||
unsafe extern "C" fn effect_parameter_new_string(value: *const c_char) -> FFIResult<FFIHandle<Arc<EffectParameter>>> {
|
||||
let sk: StringKey = match CStr::from_ptr(value).to_str() {
|
||||
Ok(sk) => sk.into(),
|
||||
Err(_) => return NativeResult::err(PkmnError::InvalidCString.into()),
|
||||
Err(_) => return FFIResult::err(PkmnError::InvalidCString.into()),
|
||||
};
|
||||
NativeResult::ok(Box::<EffectParameter>::new(sk.into()).into())
|
||||
}
|
||||
|
||||
/// Drop an effect parameter.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn effect_parameter_drop(ptr: OwnedPtr<EffectParameter>) {
|
||||
drop_in_place(ptr)
|
||||
FFIResult::ok(FFIHandle::get_handle(FFIObject::EffectParameter(Arc::new(
|
||||
EffectParameter::from(sk),
|
||||
))))
|
||||
}
|
||||
|
||||
/// Get the type of an effect parameter.
|
||||
#[no_mangle]
|
||||
extern "C" fn effect_parameter_get_type(ptr: ExternPointer<EffectParameter>) -> u8 {
|
||||
match ptr.as_ref() {
|
||||
EffectParameter::Bool(_, _) => 0,
|
||||
EffectParameter::Int(_, _) => 1,
|
||||
EffectParameter::Float(_, _) => 2,
|
||||
EffectParameter::String(_, _) => 3,
|
||||
extern "C" fn effect_parameter_get_type(ptr: FFIHandle<Arc<EffectParameter>>) -> u8 {
|
||||
match ptr.from_ffi_handle().deref() {
|
||||
EffectParameter::Bool(_) => 0,
|
||||
EffectParameter::Int(_) => 1,
|
||||
EffectParameter::Float(_) => 2,
|
||||
EffectParameter::String(_) => 3,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the boolean contained in the effect parameter, panics if the effect parameter is not a bool.
|
||||
#[no_mangle]
|
||||
extern "C" fn effect_parameter_get_as_bool(ptr: ExternPointer<EffectParameter>) -> NativeResult<u8> {
|
||||
let p = ptr.as_ref();
|
||||
if let EffectParameter::Bool(_, b) = p {
|
||||
NativeResult::ok(u8::from(*b))
|
||||
extern "C" fn effect_parameter_get_as_bool(ptr: FFIHandle<Arc<EffectParameter>>) -> FFIResult<u8> {
|
||||
let p = ptr.from_ffi_handle();
|
||||
if let EffectParameter::Bool(b) = p.deref() {
|
||||
FFIResult::ok(u8::from(*b))
|
||||
} else {
|
||||
NativeResult::err(anyhow!("Unexpected effect parameter. Expected bool, was: {}", p))
|
||||
FFIResult::err(anyhow!("Unexpected effect parameter. Expected bool, was: {}", p))
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the int contained in the effect parameter, panics if the effect parameter is not a int.
|
||||
#[no_mangle]
|
||||
extern "C" fn effect_parameter_get_as_int(ptr: ExternPointer<EffectParameter>) -> NativeResult<i64> {
|
||||
let p = ptr.as_ref();
|
||||
if let EffectParameter::Int(_, b) = p {
|
||||
NativeResult::ok(*b)
|
||||
extern "C" fn effect_parameter_get_as_int(ptr: FFIHandle<Arc<EffectParameter>>) -> FFIResult<i64> {
|
||||
let p = ptr.from_ffi_handle();
|
||||
if let EffectParameter::Int(b) = p.deref() {
|
||||
FFIResult::ok(*b)
|
||||
} else {
|
||||
NativeResult::err(anyhow!("Unexpected effect parameter. Expected int, was: {}", p))
|
||||
FFIResult::err(anyhow!("Unexpected effect parameter. Expected int, was: {}", p))
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the float contained in the effect parameter, panics if the effect parameter is not a float.
|
||||
#[no_mangle]
|
||||
extern "C" fn effect_parameter_get_as_float(ptr: ExternPointer<EffectParameter>) -> NativeResult<f32> {
|
||||
let p = ptr.as_ref();
|
||||
if let EffectParameter::Float(_, b) = p {
|
||||
NativeResult::ok(*b)
|
||||
extern "C" fn effect_parameter_get_as_float(ptr: FFIHandle<Arc<EffectParameter>>) -> FFIResult<f32> {
|
||||
let p = ptr.from_ffi_handle();
|
||||
if let EffectParameter::Float(b) = p.deref() {
|
||||
FFIResult::ok(*b)
|
||||
} else {
|
||||
NativeResult::err(anyhow!("Unexpected effect parameter. Expected float, was: {}", p))
|
||||
FFIResult::err(anyhow!("Unexpected effect parameter. Expected float, was: {}", p))
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the string contained in the effect parameter, panics if the effect parameter is not a string.
|
||||
#[no_mangle]
|
||||
extern "C" fn effect_parameter_get_as_string(ptr: ExternPointer<EffectParameter>) -> NativeResult<OwnedPtr<c_char>> {
|
||||
let p = ptr.as_ref();
|
||||
if let EffectParameter::String(_, b) = p {
|
||||
extern "C" fn effect_parameter_get_as_string(ptr: FFIHandle<Arc<EffectParameter>>) -> FFIResult<OwnedPtrString> {
|
||||
let p = ptr.from_ffi_handle();
|
||||
if let EffectParameter::String(b) = p.deref() {
|
||||
match CString::new(b.str().to_string()) {
|
||||
Ok(cstr) => NativeResult::ok(cstr.into_raw()),
|
||||
Err(_) => NativeResult::err(PkmnError::InvalidCString.into()),
|
||||
Ok(cstr) => FFIResult::ok(cstr.into_raw()),
|
||||
Err(_) => FFIResult::err(PkmnError::InvalidCString.into()),
|
||||
}
|
||||
} else {
|
||||
NativeResult::err(anyhow!("Unexpected effect parameter. Expected string, was: {}", p))
|
||||
FFIResult::err(anyhow!("Unexpected effect parameter. Expected string, was: {}", p))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::ffi::{ffi_arc_dyn_getter, BorrowedPtr, ExternPointer, IdentifiablePointer, NativeResult, OwnedPtr};
|
||||
use crate::ffi::ffi_handle::{FFIHandle, FromFFIHandle};
|
||||
use crate::ffi::{ffi_handle_arc_dyn_getter, ExternPointer, FFIResult, NonOwnedPtrString, OwnedPtrString};
|
||||
use crate::static_data::{
|
||||
EffectParameter, MoveCategory, MoveData, MoveDataImpl, MoveTarget, SecondaryEffect, SecondaryEffectImpl,
|
||||
TypeIdentifier,
|
||||
@@ -7,7 +8,6 @@ use crate::StringKey;
|
||||
use anyhow::anyhow;
|
||||
use hashbrown::HashSet;
|
||||
use std::ffi::{c_char, CStr, CString};
|
||||
use std::ptr::drop_in_place;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Instantiates a new move.
|
||||
@@ -21,27 +21,27 @@ unsafe extern "C" fn move_data_new(
|
||||
base_usages: u8,
|
||||
target: MoveTarget,
|
||||
priority: i8,
|
||||
secondary_effect: *mut Box<dyn SecondaryEffect>,
|
||||
secondary_effect: FFIHandle<Arc<dyn SecondaryEffect>>,
|
||||
flags: *const *const c_char,
|
||||
flags_length: usize,
|
||||
) -> NativeResult<IdentifiablePointer<Arc<dyn MoveData>>> {
|
||||
) -> FFIResult<FFIHandle<Arc<dyn MoveData>>> {
|
||||
let flags = std::slice::from_raw_parts(flags, flags_length);
|
||||
let name: StringKey = match CStr::from_ptr(name).to_str() {
|
||||
Ok(name) => name.into(),
|
||||
Err(_) => return NativeResult::err_from_str("Unable to convert name to string"),
|
||||
Err(_) => return FFIResult::err_from_str("Unable to convert name to string"),
|
||||
};
|
||||
let mut flags_set: HashSet<StringKey> = HashSet::with_capacity(flags_length);
|
||||
for flag in flags {
|
||||
let flag = match CStr::from_ptr(*flag).to_str() {
|
||||
Ok(flag) => flag,
|
||||
Err(_) => return NativeResult::err_from_str("Unable to convert flag to string"),
|
||||
Err(_) => return FFIResult::err_from_str("Unable to convert flag to string"),
|
||||
};
|
||||
flags_set.insert(flag.into());
|
||||
}
|
||||
let secondary_effect = if secondary_effect.is_null() {
|
||||
let secondary_effect = if secondary_effect.is_none() {
|
||||
None
|
||||
} else {
|
||||
Some(*Box::from_raw(secondary_effect))
|
||||
Some(secondary_effect.from_ffi_handle())
|
||||
};
|
||||
let a: Arc<dyn MoveData> = Arc::new(MoveDataImpl::new(
|
||||
&name,
|
||||
@@ -55,39 +55,37 @@ unsafe extern "C" fn move_data_new(
|
||||
secondary_effect,
|
||||
flags_set,
|
||||
));
|
||||
NativeResult::ok(a.into())
|
||||
}
|
||||
|
||||
/// Drops a reference counted move.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn move_data_drop(ptr: OwnedPtr<Arc<dyn MoveData>>) {
|
||||
drop_in_place(ptr)
|
||||
FFIResult::ok(FFIHandle::get_handle(a.into()))
|
||||
}
|
||||
|
||||
/// The name of the move.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn move_data_name(ptr: ExternPointer<Arc<dyn MoveData>>) -> NativeResult<OwnedPtr<c_char>> {
|
||||
let name = ptr.as_ref().name();
|
||||
unsafe extern "C" fn move_data_name(ptr: FFIHandle<Arc<dyn MoveData>>) -> FFIResult<OwnedPtrString> {
|
||||
let move_data = ptr.from_ffi_handle();
|
||||
let name = move_data.name();
|
||||
match CString::new(name.str()) {
|
||||
Ok(name) => NativeResult::ok(name.into_raw()),
|
||||
Err(_) => NativeResult::err_from_str("Unable to convert name to string"),
|
||||
Ok(name) => FFIResult::ok(name.into_raw()),
|
||||
Err(_) => FFIResult::err_from_str("Unable to convert name to string"),
|
||||
}
|
||||
}
|
||||
|
||||
ffi_arc_dyn_getter!(MoveData, move_type, TypeIdentifier);
|
||||
ffi_arc_dyn_getter!(MoveData, category, MoveCategory);
|
||||
ffi_arc_dyn_getter!(MoveData, base_power, u8);
|
||||
ffi_arc_dyn_getter!(MoveData, accuracy, u8);
|
||||
ffi_arc_dyn_getter!(MoveData, base_usages, u8);
|
||||
ffi_arc_dyn_getter!(MoveData, target, MoveTarget);
|
||||
ffi_arc_dyn_getter!(MoveData, priority, i8);
|
||||
ffi_handle_arc_dyn_getter!(MoveData, move_type, TypeIdentifier);
|
||||
ffi_handle_arc_dyn_getter!(MoveData, category, MoveCategory);
|
||||
ffi_handle_arc_dyn_getter!(MoveData, base_power, u8);
|
||||
ffi_handle_arc_dyn_getter!(MoveData, accuracy, u8);
|
||||
ffi_handle_arc_dyn_getter!(MoveData, base_usages, u8);
|
||||
ffi_handle_arc_dyn_getter!(MoveData, target, MoveTarget);
|
||||
ffi_handle_arc_dyn_getter!(MoveData, priority, i8);
|
||||
|
||||
/// The optional secondary effect the move has.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn move_data_secondary_effect(
|
||||
ptr: ExternPointer<Arc<dyn MoveData>>,
|
||||
) -> IdentifiablePointer<Box<dyn SecondaryEffect>> {
|
||||
ptr.as_ref().secondary_effect().into()
|
||||
ptr: FFIHandle<Arc<dyn MoveData>>,
|
||||
) -> FFIHandle<Arc<dyn SecondaryEffect>> {
|
||||
match ptr.from_ffi_handle().secondary_effect() {
|
||||
Some(secondary_effect) => FFIHandle::get_handle(secondary_effect.clone().into()),
|
||||
None => FFIHandle::none(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Arbitrary flags that can be applied to the move.
|
||||
@@ -101,28 +99,22 @@ unsafe extern "C" fn move_data_has_flag(ptr: ExternPointer<Arc<dyn MoveData>>, f
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn secondary_effect_new(
|
||||
chance: f32,
|
||||
effect_name: BorrowedPtr<c_char>,
|
||||
parameters: *mut OwnedPtr<Arc<EffectParameter>>,
|
||||
effect_name: NonOwnedPtrString,
|
||||
parameters: *mut FFIHandle<Arc<EffectParameter>>,
|
||||
parameters_length: usize,
|
||||
) -> IdentifiablePointer<Box<dyn SecondaryEffect>> {
|
||||
) -> FFIHandle<Box<dyn SecondaryEffect>> {
|
||||
let parameter_slice = std::slice::from_raw_parts(parameters, parameters_length);
|
||||
let mut parameters = Vec::with_capacity(parameters_length);
|
||||
for parameter in parameter_slice {
|
||||
parameters.push(*Box::from_raw(*parameter))
|
||||
parameters.push(parameter.from_ffi_handle())
|
||||
}
|
||||
|
||||
let b: Box<dyn SecondaryEffect> = Box::new(SecondaryEffectImpl::new(
|
||||
let b: Arc<dyn SecondaryEffect> = Arc::new(SecondaryEffectImpl::new(
|
||||
chance,
|
||||
CStr::from_ptr(effect_name).into(),
|
||||
parameters,
|
||||
));
|
||||
b.into()
|
||||
}
|
||||
|
||||
/// Drop a secondary effect.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn secondary_effect_drop(ptr: OwnedPtr<Box<dyn SecondaryEffect>>) {
|
||||
drop_in_place(ptr)
|
||||
FFIHandle::get_handle(b.into())
|
||||
}
|
||||
|
||||
/// The chance the effect triggers.
|
||||
@@ -135,10 +127,10 @@ unsafe extern "C" fn secondary_effect_chance(ptr: ExternPointer<Box<dyn Secondar
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn secondary_effect_effect_name(
|
||||
ptr: ExternPointer<Box<dyn SecondaryEffect>>,
|
||||
) -> NativeResult<OwnedPtr<c_char>> {
|
||||
) -> FFIResult<OwnedPtrString> {
|
||||
match CString::new(ptr.as_ref().effect_name().str()) {
|
||||
Ok(name) => NativeResult::ok(name.into_raw()),
|
||||
Err(_) => NativeResult::err(anyhow!(
|
||||
Ok(name) => FFIResult::ok(name.into_raw()),
|
||||
Err(_) => FFIResult::err(anyhow!(
|
||||
"Unable to convert effect name '{}' to CString",
|
||||
ptr.as_ref().effect_name()
|
||||
)),
|
||||
@@ -156,10 +148,10 @@ unsafe extern "C" fn secondary_effect_parameter_length(ptr: ExternPointer<Box<dy
|
||||
unsafe extern "C" fn secondary_effect_parameter_get(
|
||||
ptr: ExternPointer<Box<dyn SecondaryEffect>>,
|
||||
index: usize,
|
||||
) -> IdentifiablePointer<Arc<EffectParameter>> {
|
||||
) -> FFIHandle<Arc<EffectParameter>> {
|
||||
if let Some(v) = ptr.as_ref().parameters().get(index) {
|
||||
v.clone().into()
|
||||
FFIHandle::get_handle(v.clone().into())
|
||||
} else {
|
||||
IdentifiablePointer::none()
|
||||
FFIHandle::none()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use crate::ffi::{ExternPointer, IdentifiablePointer, OwnedPtr};
|
||||
use crate::ffi::ffi_handle::{FFIHandle, FromFFIHandle};
|
||||
use crate::static_data::{Nature, NatureImpl, Statistic};
|
||||
use std::ptr::drop_in_place;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Instantiates a new statistic.
|
||||
@@ -10,32 +9,26 @@ extern "C" fn nature_new(
|
||||
decrease_stat: Statistic,
|
||||
increase_modifier: f32,
|
||||
decrease_modifier: f32,
|
||||
) -> IdentifiablePointer<Arc<dyn Nature>> {
|
||||
) -> FFIHandle<Arc<dyn Nature>> {
|
||||
let arc: Arc<dyn Nature> = NatureImpl::new(increase_stat, decrease_stat, increase_modifier, decrease_modifier);
|
||||
arc.into()
|
||||
}
|
||||
|
||||
/// Reduce the reference count for a nature.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn nature_drop(ptr: OwnedPtr<Arc<dyn Nature>>) {
|
||||
drop_in_place(ptr)
|
||||
FFIHandle::get_handle(arc.into())
|
||||
}
|
||||
|
||||
/// The stat that should receive the increased modifier.
|
||||
#[no_mangle]
|
||||
extern "C" fn nature_increased_stat(ptr: ExternPointer<Arc<dyn Nature>>) -> Statistic {
|
||||
ptr.as_ref().increased_stat()
|
||||
extern "C" fn nature_increased_stat(ptr: FFIHandle<Arc<dyn Nature>>) -> Statistic {
|
||||
ptr.from_ffi_handle().increased_stat()
|
||||
}
|
||||
|
||||
/// The stat that should receive the decreased modifier.
|
||||
#[no_mangle]
|
||||
extern "C" fn nature_decreased_stat(ptr: ExternPointer<Arc<dyn Nature>>) -> Statistic {
|
||||
ptr.as_ref().decreased_stat()
|
||||
extern "C" fn nature_decreased_stat(ptr: FFIHandle<Arc<dyn Nature>>) -> Statistic {
|
||||
ptr.from_ffi_handle().decreased_stat()
|
||||
}
|
||||
|
||||
/// Calculates the modifier for a given stat. If it's the increased stat, returns the increased
|
||||
/// modifier, if it's the decreased stat, returns the decreased modifier. Otherwise returns 1.0
|
||||
#[no_mangle]
|
||||
extern "C" fn nature_get_stat_modifier(ptr: ExternPointer<Arc<dyn Nature>>, stat: Statistic) -> f32 {
|
||||
ptr.as_ref().get_stat_modifier(stat)
|
||||
extern "C" fn nature_get_stat_modifier(ptr: FFIHandle<Arc<dyn Nature>>, stat: Statistic) -> f32 {
|
||||
ptr.from_ffi_handle().get_stat_modifier(stat)
|
||||
}
|
||||
|
||||
@@ -1,33 +1,32 @@
|
||||
use crate::ffi::ffi_handle::FFIHandle;
|
||||
use crate::ffi::{
|
||||
ffi_arc_dyn_getter, ffi_arc_stringkey_getter, BorrowedPtr, ExternPointer, IdentifiablePointer, NativeResult,
|
||||
OwnedPtr,
|
||||
ffi_handle_arc_dyn_getter, ffi_handle_arc_stringkey_getter, FFIResult, FromFFIHandle, NonOwnedPtrString,
|
||||
};
|
||||
use crate::static_data::{Form, Gender, Species, SpeciesImpl};
|
||||
use crate::{PkmnError, Random, StringKey};
|
||||
use hashbrown::HashSet;
|
||||
use std::ffi::{c_char, CStr};
|
||||
use std::ptr::drop_in_place;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Creates a new species.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn species_new(
|
||||
id: u16,
|
||||
name: BorrowedPtr<c_char>,
|
||||
name: NonOwnedPtrString,
|
||||
gender_rate: f32,
|
||||
growth_rate: BorrowedPtr<c_char>,
|
||||
growth_rate: NonOwnedPtrString,
|
||||
capture_rate: u8,
|
||||
default_form: OwnedPtr<Arc<dyn Form>>,
|
||||
default_form: FFIHandle<Arc<dyn Form>>,
|
||||
flags: *const *const c_char,
|
||||
flags_length: usize,
|
||||
) -> NativeResult<IdentifiablePointer<Arc<dyn Species>>> {
|
||||
) -> FFIResult<FFIHandle<Arc<dyn Species>>> {
|
||||
let name: StringKey = match CStr::from_ptr(name).to_str() {
|
||||
Ok(name) => name.into(),
|
||||
Err(_) => return NativeResult::err(PkmnError::InvalidCString.into()),
|
||||
Err(_) => return FFIResult::err(PkmnError::InvalidCString.into()),
|
||||
};
|
||||
let growth_rate: StringKey = match CStr::from_ptr(growth_rate).to_str() {
|
||||
Ok(growth_rate) => growth_rate.into(),
|
||||
Err(_) => return NativeResult::err(PkmnError::InvalidCString.into()),
|
||||
Err(_) => return FFIResult::err(PkmnError::InvalidCString.into()),
|
||||
};
|
||||
|
||||
let flags = std::slice::from_raw_parts(flags, flags_length);
|
||||
@@ -35,13 +34,14 @@ unsafe extern "C" fn species_new(
|
||||
for flag in flags {
|
||||
let flag = match CStr::from_ptr(*flag).to_str() {
|
||||
Ok(flag) => flag,
|
||||
Err(_) => return NativeResult::err(PkmnError::InvalidCString.into()),
|
||||
Err(_) => return FFIResult::err(PkmnError::InvalidCString.into()),
|
||||
};
|
||||
flags_set.insert(flag.into());
|
||||
}
|
||||
let default_form = match default_form.as_ref() {
|
||||
Some(default_form) => default_form,
|
||||
None => return NativeResult::err(PkmnError::NullReference.into()),
|
||||
let default_form = if default_form.is_none() {
|
||||
return FFIResult::err(PkmnError::NullReference.into());
|
||||
} else {
|
||||
default_form.from_ffi_handle()
|
||||
};
|
||||
|
||||
let a: Arc<dyn Species> = Arc::new(SpeciesImpl::new(
|
||||
@@ -53,53 +53,48 @@ unsafe extern "C" fn species_new(
|
||||
default_form.clone(),
|
||||
flags_set,
|
||||
));
|
||||
NativeResult::ok(a.into())
|
||||
FFIResult::ok(FFIHandle::get_handle(a.into()))
|
||||
}
|
||||
|
||||
/// Drop a reference to the species.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn species_drop(ptr: OwnedPtr<Arc<dyn Species>>) {
|
||||
drop_in_place(ptr);
|
||||
}
|
||||
|
||||
ffi_arc_dyn_getter!(Species, id, u16);
|
||||
ffi_arc_stringkey_getter!(Species, name);
|
||||
ffi_arc_dyn_getter!(Species, gender_rate, f32);
|
||||
ffi_arc_stringkey_getter!(Species, growth_rate);
|
||||
ffi_arc_dyn_getter!(Species, capture_rate, u8);
|
||||
ffi_handle_arc_dyn_getter!(Species, id, u16);
|
||||
ffi_handle_arc_stringkey_getter!(Species, name);
|
||||
ffi_handle_arc_dyn_getter!(Species, gender_rate, f32);
|
||||
ffi_handle_arc_stringkey_getter!(Species, growth_rate);
|
||||
ffi_handle_arc_dyn_getter!(Species, capture_rate, u8);
|
||||
|
||||
/// Adds a new form to the species.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn species_add_form(
|
||||
mut species: ExternPointer<Arc<dyn Species>>,
|
||||
name: BorrowedPtr<c_char>,
|
||||
form: OwnedPtr<Arc<dyn Form>>,
|
||||
) -> NativeResult<()> {
|
||||
let form = match form.as_ref() {
|
||||
Some(form) => form.clone(),
|
||||
None => return NativeResult::err(PkmnError::NullReference.into()),
|
||||
species: FFIHandle<Arc<dyn Species>>,
|
||||
name: NonOwnedPtrString,
|
||||
form: FFIHandle<Arc<dyn Form>>,
|
||||
) -> FFIResult<()> {
|
||||
let form = if form.is_none() {
|
||||
return FFIResult::err(PkmnError::NullReference.into());
|
||||
} else {
|
||||
form.from_ffi_handle()
|
||||
};
|
||||
species.as_mut().add_form(CStr::from_ptr(name).into(), form);
|
||||
NativeResult::ok(())
|
||||
species.from_ffi_handle().add_form(CStr::from_ptr(name).into(), form);
|
||||
FFIResult::ok(())
|
||||
}
|
||||
|
||||
/// Gets a form by name.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn species_get_form(
|
||||
species: ExternPointer<Arc<dyn Species>>,
|
||||
name: BorrowedPtr<c_char>,
|
||||
) -> IdentifiablePointer<Arc<dyn Form>> {
|
||||
let form = species.as_ref().get_form(&CStr::from_ptr(name).into());
|
||||
species: FFIHandle<Arc<dyn Species>>,
|
||||
name: NonOwnedPtrString,
|
||||
) -> FFIHandle<Arc<dyn Form>> {
|
||||
let form = species.from_ffi_handle().get_form(&CStr::from_ptr(name).into());
|
||||
if let Some(form) = form {
|
||||
form.into()
|
||||
FFIHandle::get_handle(form.into())
|
||||
} else {
|
||||
IdentifiablePointer::none()
|
||||
FFIHandle::none()
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a form by name.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn species_get_random_gender(species: ExternPointer<Arc<dyn Species>>, seed: u64) -> Gender {
|
||||
unsafe extern "C" fn species_get_random_gender(species: FFIHandle<Arc<dyn Species>>, seed: u64) -> Gender {
|
||||
let mut rand = Random::new(seed as u128);
|
||||
species.as_ref().get_random_gender(&mut rand)
|
||||
species.from_ffi_handle().get_random_gender(&mut rand)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::ffi::{ExternPointer, IdentifiablePointer, OwnedPtr};
|
||||
use crate::ffi::FFIHandle;
|
||||
use crate::ffi::FromFFIHandle;
|
||||
use crate::static_data::{StaticStatisticSet, Statistic, StatisticSet};
|
||||
use std::ptr::drop_in_place;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Basic foreign function interface for a statistic set.
|
||||
macro_rules! statistic_set {
|
||||
@@ -15,40 +16,35 @@ extern "C" fn [<statistic_set_ $num_type _new>](
|
||||
special_attack: $num_type,
|
||||
special_defense: $num_type,
|
||||
speed: $num_type,
|
||||
) -> IdentifiablePointer<StatisticSet<$num_type>> {
|
||||
Box::new(StatisticSet::new(
|
||||
) -> FFIHandle<Arc<StatisticSet<$num_type>>> {
|
||||
FFIHandle::get_handle(Arc::new(StatisticSet::new(
|
||||
hp,
|
||||
attack,
|
||||
defense,
|
||||
special_attack,
|
||||
special_defense,
|
||||
speed,
|
||||
)).into()
|
||||
)).into())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn [<statistic_set_ $num_type _drop>](ptr: OwnedPtr<StatisticSet<$num_type>>) {
|
||||
drop_in_place(ptr)
|
||||
extern "C" fn [<statistic_set_ $num_type _get_stat>](ptr: FFIHandle<Arc<StatisticSet<$num_type>>>, stat: Statistic) -> $num_type {
|
||||
ptr.from_ffi_handle().get_stat(stat)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn [<statistic_set_ $num_type _get_stat>](ptr: ExternPointer<StatisticSet<$num_type>>, stat: Statistic) -> $num_type {
|
||||
ptr.as_ref().get_stat(stat)
|
||||
extern "C" fn [<statistic_set_ $num_type _set_stat>](ptr: FFIHandle<Arc<StatisticSet<$num_type>>>, stat: Statistic, value: $num_type) {
|
||||
ptr.from_ffi_handle().set_stat(stat, value)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn [<statistic_set_ $num_type _set_stat>](ptr: ExternPointer<StatisticSet<$num_type>>, stat: Statistic, value: $num_type) {
|
||||
ptr.as_ref().set_stat(stat, value)
|
||||
extern "C" fn [<statistic_set_ $num_type _increase_stat>](ptr: FFIHandle<Arc<StatisticSet<$num_type>>>, stat: Statistic, value: $num_type) {
|
||||
ptr.from_ffi_handle().increase_stat(stat, value)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn [<statistic_set_ $num_type _increase_stat>](ptr: ExternPointer<StatisticSet<$num_type>>, stat: Statistic, value: $num_type) {
|
||||
ptr.as_ref().increase_stat(stat, value)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn [<statistic_set_ $num_type _decrease_stat>](ptr: ExternPointer<StatisticSet<$num_type>>, stat: Statistic, value: $num_type) {
|
||||
ptr.as_ref().decrease_stat(stat, value)
|
||||
extern "C" fn [<statistic_set_ $num_type _decrease_stat>](ptr: FFIHandle<Arc<StatisticSet<$num_type>>>, stat: Statistic, value: $num_type) {
|
||||
ptr.from_ffi_handle().decrease_stat(stat, value)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -56,11 +52,11 @@ extern "C" fn [<statistic_set_ $num_type _decrease_stat>](ptr: ExternPointer<Sta
|
||||
}
|
||||
|
||||
statistic_set!(u8);
|
||||
statistic_set!(u16);
|
||||
// statistic_set!(u16);
|
||||
statistic_set!(u32);
|
||||
statistic_set!(i8);
|
||||
statistic_set!(i16);
|
||||
statistic_set!(i32);
|
||||
// statistic_set!(i16);
|
||||
// statistic_set!(i32);
|
||||
|
||||
/// Basic foreign function interface for a static statistic set.
|
||||
macro_rules! static_statistic_set {
|
||||
@@ -75,34 +71,29 @@ extern "C" fn [<static_statistic_set_ $num_type _new>](
|
||||
special_attack: $num_type,
|
||||
special_defense: $num_type,
|
||||
speed: $num_type,
|
||||
) -> IdentifiablePointer<StaticStatisticSet<$num_type>> {
|
||||
Box::new(StaticStatisticSet::new(
|
||||
) -> FFIHandle<Arc<StaticStatisticSet<$num_type>>> {
|
||||
FFIHandle::get_handle(Arc::new(StaticStatisticSet::new(
|
||||
hp,
|
||||
attack,
|
||||
defense,
|
||||
special_attack,
|
||||
special_defense,
|
||||
speed,
|
||||
)).into()
|
||||
)).into())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn [<static_statistic_set_ $num_type _drop>](ptr: OwnedPtr<StaticStatisticSet<$num_type>>) {
|
||||
drop_in_place(ptr)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn [<static_statistic_set_ $num_type _get_stat>](ptr: ExternPointer<StaticStatisticSet<$num_type>>, stat: Statistic) -> $num_type {
|
||||
ptr.as_ref().get_stat(stat)
|
||||
extern "C" fn [<static_statistic_set_ $num_type _get_stat>](ptr: FFIHandle<Arc<StaticStatisticSet<$num_type>>>, stat: Statistic) -> $num_type {
|
||||
ptr.from_ffi_handle().get_stat(stat)
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static_statistic_set!(u8);
|
||||
// static_statistic_set!(u8);
|
||||
static_statistic_set!(u16);
|
||||
static_statistic_set!(u32);
|
||||
static_statistic_set!(i8);
|
||||
static_statistic_set!(i16);
|
||||
static_statistic_set!(i32);
|
||||
// static_statistic_set!(u32);
|
||||
// static_statistic_set!(i8);
|
||||
// static_statistic_set!(i16);
|
||||
// static_statistic_set!(i32);
|
||||
|
||||
Reference in New Issue
Block a user