Support for new error handling.
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
@@ -2,7 +2,7 @@ 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, OwnedPtr};
|
||||
use crate::ffi::{ExternPointer, IdentifiablePointer, NativeResult, OwnedPtr};
|
||||
use std::ffi::{c_char, CStr, CString};
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -191,20 +191,20 @@ extern "C" fn battle_try_set_choice(ptr: ExternPointer<Arc<Battle>>, choice: Own
|
||||
|
||||
/// 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) {
|
||||
extern "C" fn battle_set_weather(ptr: ExternPointer<Arc<Battle>>, weather: *const c_char) -> NativeResult<()> {
|
||||
if weather.is_null() {
|
||||
ptr.as_ref().set_weather(None)
|
||||
ptr.as_ref().set_weather(None).into()
|
||||
} else {
|
||||
unsafe { ptr.as_ref().set_weather(Some(CStr::from_ptr(weather).into())) }
|
||||
unsafe { ptr.as_ref().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>>) -> *mut c_char {
|
||||
if let Some(w) = ptr.as_ref().weather_name() {
|
||||
CString::new(w.str()).unwrap().into_raw()
|
||||
} else {
|
||||
std::ptr::null_mut()
|
||||
extern "C" fn battle_weather_name(ptr: ExternPointer<Arc<Battle>>) -> NativeResult<*mut c_char> {
|
||||
match ptr.as_ref().weather_name() {
|
||||
Ok(Some(w)) => CString::new(w.str()).unwrap().into_raw().into(),
|
||||
Ok(None) => std::ptr::null_mut::<c_char>().into(),
|
||||
Err(e) => NativeResult::err(e),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
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, OwnedPtr};
|
||||
use crate::ffi::{ffi_arc_getter, ffi_vec_value_getters, ExternPointer, IdentifiablePointer, NativeResult, OwnedPtr};
|
||||
use crate::static_data::{
|
||||
Ability, AbilityIndex, Form, Gender, Item, Nature, Species, Statistic, StatisticSet, TypeIdentifier,
|
||||
};
|
||||
@@ -21,9 +21,9 @@ extern "C" fn pokemon_new(
|
||||
gender: Gender,
|
||||
coloring: u8,
|
||||
nature: *const c_char,
|
||||
) -> IdentifiablePointer<Arc<Pokemon>> {
|
||||
) -> NativeResult<IdentifiablePointer<Arc<Pokemon>>> {
|
||||
let nature = unsafe { CStr::from_ptr(nature) }.into();
|
||||
Arc::new(Pokemon::new(
|
||||
let pokemon = Pokemon::new(
|
||||
library.as_ref().clone(),
|
||||
species.as_ref().clone(),
|
||||
form.as_ref(),
|
||||
@@ -36,8 +36,11 @@ extern "C" fn pokemon_new(
|
||||
gender,
|
||||
coloring,
|
||||
&nature,
|
||||
))
|
||||
.into()
|
||||
);
|
||||
match pokemon {
|
||||
Ok(pokemon) => NativeResult::ok(Arc::new(pokemon).into()),
|
||||
Err(err) => NativeResult::err(err),
|
||||
}
|
||||
}
|
||||
|
||||
/// Drops an Arc reference held by the FFI.
|
||||
@@ -327,8 +330,8 @@ extern "C" fn pokemon_is_on_battlefield(ptr: ExternPointer<Arc<Pokemon>>) -> u8
|
||||
|
||||
/// Damages the Pokemon by a certain amount of damage, from a damage source.
|
||||
#[no_mangle]
|
||||
extern "C" fn pokemon_damage(ptr: ExternPointer<Arc<Pokemon>>, damage: u32, source: DamageSource) {
|
||||
ptr.as_ref().damage(damage, source)
|
||||
extern "C" fn pokemon_damage(ptr: ExternPointer<Arc<Pokemon>>, damage: u32, source: DamageSource) -> NativeResult<()> {
|
||||
ptr.as_ref().damage(damage, source).into()
|
||||
}
|
||||
|
||||
/// Heals the Pokemon by a specific amount. Unless allow_revive is set to true, this will not
|
||||
|
||||
@@ -93,6 +93,7 @@ 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;
|
||||
use std::ffi::{c_char, CString};
|
||||
use std::mem::transmute;
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -131,6 +132,17 @@ pub(self) struct IdentifiablePointer<T> {
|
||||
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 {
|
||||
@@ -244,3 +256,55 @@ impl<T> IdentifiablePointer<T> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper utility class to give either the data or an error to a FFI.
|
||||
#[repr(C)]
|
||||
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>,
|
||||
}
|
||||
|
||||
/// The result of a FFI call that can either be an error or a value.
|
||||
#[repr(C)]
|
||||
pub struct NativeResult<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> {
|
||||
/// Creates a new NativeResult with the given value.
|
||||
pub fn ok(value: T) -> Self {
|
||||
Self {
|
||||
ok: 1,
|
||||
value: ResultUnion { ok: value },
|
||||
}
|
||||
}
|
||||
/// Creates a new NativeResult with the given error.
|
||||
pub fn err(err: anyhow::Error) -> Self {
|
||||
Self {
|
||||
ok: 0,
|
||||
value: ResultUnion {
|
||||
err: CString::new(err.to_string()).unwrap().into_raw(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> From<anyhow::Result<T>> for NativeResult<T> {
|
||||
fn from(value: anyhow::Result<T>) -> Self {
|
||||
match value {
|
||||
Ok(v) => Self::ok(v),
|
||||
Err(e) => Self::err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> From<T> for NativeResult<T> {
|
||||
fn from(value: T) -> Self {
|
||||
Self::ok(value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::defines::LevelInt;
|
||||
use crate::ffi::{ExternPointer, OwnedPtr};
|
||||
use crate::ffi::{ExternPointer, NativeResult, OwnedPtr};
|
||||
use crate::static_data::{GrowthRate, LookupGrowthRate};
|
||||
use std::ptr::drop_in_place;
|
||||
|
||||
@@ -25,6 +25,9 @@ extern "C" fn growth_rate_calculate_level(ptr: ExternPointer<Box<dyn GrowthRate>
|
||||
|
||||
/// 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) -> u32 {
|
||||
ptr.as_ref().calculate_experience(level)
|
||||
extern "C" fn growth_rate_calculate_experience(
|
||||
ptr: ExternPointer<Box<dyn GrowthRate>>,
|
||||
level: LevelInt,
|
||||
) -> NativeResult<u32> {
|
||||
ptr.as_ref().calculate_experience(level).into()
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::defines::LevelInt;
|
||||
use crate::ffi::{BorrowedPtr, ExternPointer, IdentifiablePointer, OwnedPtr};
|
||||
use crate::ffi::{BorrowedPtr, ExternPointer, IdentifiablePointer, NativeResult, OwnedPtr};
|
||||
use crate::static_data::{GrowthRate, GrowthRateLibrary, GrowthRateLibraryImpl};
|
||||
use std::ffi::{c_char, CStr};
|
||||
use std::ptr::drop_in_place;
|
||||
@@ -34,9 +34,10 @@ unsafe extern "C" fn growth_rate_library_calculate_experience(
|
||||
ptr: ExternPointer<Box<dyn GrowthRateLibrary>>,
|
||||
growth_rate: BorrowedPtr<c_char>,
|
||||
level: LevelInt,
|
||||
) -> u32 {
|
||||
) -> NativeResult<u32> {
|
||||
ptr.as_ref()
|
||||
.calculate_experience(&CStr::from_ptr(growth_rate).into(), level)
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Adds a new growth rate with a name and value.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::defines::LevelInt;
|
||||
use crate::ffi::{ExternPointer, IdentifiablePointer, OwnedPtr};
|
||||
use crate::ffi::{ExternPointer, IdentifiablePointer, NativeResult, OwnedPtr};
|
||||
use crate::static_data::{LibrarySettings, LibrarySettingsImpl};
|
||||
use std::ptr::drop_in_place;
|
||||
|
||||
@@ -12,9 +12,15 @@ use std::ptr::drop_in_place;
|
||||
extern "C" fn library_settings_new(
|
||||
max_level: LevelInt,
|
||||
shiny_rate: u32,
|
||||
) -> IdentifiablePointer<Box<dyn LibrarySettings>> {
|
||||
let b: Box<dyn LibrarySettings> = Box::new(LibrarySettingsImpl::new(max_level, shiny_rate));
|
||||
b.into()
|
||||
) -> NativeResult<IdentifiablePointer<Box<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()
|
||||
}
|
||||
Err(e) => NativeResult::err(e),
|
||||
}
|
||||
}
|
||||
|
||||
/// Drop a library settings object.
|
||||
|
||||
Reference in New Issue
Block a user