Initial work on FFI
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
39497891e9
commit
726e294f11
10
Cargo.toml
10
Cargo.toml
|
@ -8,21 +8,21 @@ edition = "2018"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "pkmn_lib"
|
name = "pkmn_lib"
|
||||||
crate_type = ["rlib"]
|
crate_type = ["cdylib", "rlib"]
|
||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
ffi = []
|
ffi = []
|
||||||
serde = ["dep:serde"]
|
serde = ["dep:serde"]
|
||||||
wasm = ["dep:wasmer", "dep:unique-type-id", "dep:unique-type-id-derive"]
|
wasm = ["dep:wasmer", "dep:unique-type-id", "dep:unique-type-id-derive"]
|
||||||
default = ["serde", "wasm"]
|
default = ["serde", "wasm", "ffi"]
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
opt-level = 0
|
opt-level = 0
|
||||||
debug = true
|
debug = true
|
||||||
debug-assertions = true
|
debug-assertions = true
|
||||||
overflow-checks = true
|
overflow-checks = true
|
||||||
lto = "thin"
|
lto = false
|
||||||
panic = 'unwind'
|
panic = 'unwind'
|
||||||
incremental = true
|
incremental = true
|
||||||
codegen-units = 256
|
codegen-units = 256
|
||||||
|
@ -33,7 +33,7 @@ opt-level = 3
|
||||||
debug = 1
|
debug = 1
|
||||||
debug-assertions = false
|
debug-assertions = false
|
||||||
overflow-checks = true
|
overflow-checks = true
|
||||||
lto = "fat"
|
lto = false
|
||||||
panic = 'unwind'
|
panic = 'unwind'
|
||||||
incremental = false
|
incremental = false
|
||||||
codegen-units = 16
|
codegen-units = 16
|
||||||
|
@ -56,7 +56,7 @@ wasmer = { version = "3.0.0-beta", optional = true, default-features = true }
|
||||||
unique-type-id = { version = "1.0.0", optional = true }
|
unique-type-id = { version = "1.0.0", optional = true }
|
||||||
unique-type-id-derive = { version = "1.0.0", optional = true }
|
unique-type-id-derive = { version = "1.0.0", optional = true }
|
||||||
paste = { version = "1.0.8" }
|
paste = { version = "1.0.8" }
|
||||||
arcstr = "1.1.4"
|
arcstr = { version = "1.1.4", features = ["std"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
csv = "1.1.6"
|
csv = "1.1.6"
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
mod static_data;
|
||||||
|
|
||||||
|
type OwnedPtr<T> = *mut T;
|
||||||
|
type BorrowedPtr<T> = *const T;
|
||||||
|
|
||||||
|
macro_rules! ffi_getter {
|
||||||
|
(
|
||||||
|
$type:ty, $func:ident, $returns: ty
|
||||||
|
) => {
|
||||||
|
paste::paste! {
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn [< $type:snake _ $func >](ptr: ExternPointer<$type>) -> $returns {
|
||||||
|
ptr.as_ref().$func()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! ffi_stringkey_getter {
|
||||||
|
(
|
||||||
|
$type:ty, $func:ident
|
||||||
|
) => {
|
||||||
|
paste::paste! {
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn [< $type:lower _ $func >](ptr: ExternPointer<$type>) -> OwnedPtr<c_char> {
|
||||||
|
std::ffi::CString::new(ptr.as_ref().$func().str()).unwrap().into_raw()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! ffi_vec_value_getters {
|
||||||
|
(
|
||||||
|
$type:ty, $func:ident, $returns: ty
|
||||||
|
) => {
|
||||||
|
paste::paste! {
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn [< $type:lower _ $func _length>](ptr: ExternPointer<$type>) -> usize {
|
||||||
|
ptr.as_ref().$func().len()
|
||||||
|
}
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn [< $type:lower _ $func _get>](ptr: ExternPointer<$type>, index: usize) -> $returns {
|
||||||
|
*ptr.as_ref().$func().get(index).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! ffi_vec_stringkey_getters {
|
||||||
|
(
|
||||||
|
$type:ident, $func:ident
|
||||||
|
) => {
|
||||||
|
paste::paste! {
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn [< $type:lower _ $func _length>](ptr: ExternPointer<$type>) -> usize {
|
||||||
|
ptr.as_ref().$func().len()
|
||||||
|
}
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn [< $type:lower _ $func _get>](ptr: ExternPointer<$type>, index: usize) -> OwnedPtr<c_char> {
|
||||||
|
CString::new(ptr.as_ref().$func().get(index).unwrap().str()).unwrap().into_raw()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(self) use ffi_getter;
|
||||||
|
pub(self) use ffi_stringkey_getter;
|
||||||
|
pub(self) use ffi_vec_stringkey_getters;
|
||||||
|
pub(self) use ffi_vec_value_getters;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub(self) struct ExternPointer<T: ?Sized> {
|
||||||
|
ptr: *mut T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ?Sized> ExternPointer<T> {
|
||||||
|
pub(self) fn as_ref(&self) -> &T {
|
||||||
|
unsafe {
|
||||||
|
self.ptr.as_ref().expect(&format!(
|
||||||
|
"Given pointer of type '{}' was null",
|
||||||
|
std::any::type_name::<T>()
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(self) fn as_mut(&self) -> &mut T {
|
||||||
|
unsafe {
|
||||||
|
self.ptr.as_mut().expect(&format!(
|
||||||
|
"Given pointer of type '{}' was null",
|
||||||
|
std::any::type_name::<T>()
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Into<ExternPointer<T>> for *mut T {
|
||||||
|
fn into(self) -> ExternPointer<T> {
|
||||||
|
ExternPointer { ptr: self }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
use crate::ffi::{BorrowedPtr, ExternPointer, OwnedPtr};
|
||||||
|
use crate::static_data::{Ability, EffectParameter};
|
||||||
|
use crate::StringKey;
|
||||||
|
use std::ffi::{c_char, CStr, CString};
|
||||||
|
use std::ptr::drop_in_place;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn ability_new(
|
||||||
|
name: *const c_char,
|
||||||
|
effect: *const c_char,
|
||||||
|
parameters: *const OwnedPtr<EffectParameter>,
|
||||||
|
parameters_length: usize,
|
||||||
|
) -> OwnedPtr<Ability> {
|
||||||
|
let parameters = std::slice::from_raw_parts(parameters, parameters_length);
|
||||||
|
let mut parameters_vec: Vec<EffectParameter> = Vec::with_capacity(parameters_length);
|
||||||
|
for parameter in parameters {
|
||||||
|
parameters_vec.push(*Box::from_raw(*parameter));
|
||||||
|
}
|
||||||
|
|
||||||
|
let name: StringKey = CStr::from_ptr(name).to_str().unwrap().into();
|
||||||
|
let effect: StringKey = CStr::from_ptr(effect).to_str().unwrap().into();
|
||||||
|
|
||||||
|
Box::into_raw(Box::new(Ability::new(&name, &effect, parameters_vec)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn ability_drop(ptr: OwnedPtr<Ability>) {
|
||||||
|
drop_in_place(ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn ability_name(ptr: ExternPointer<Ability>) -> OwnedPtr<c_char> {
|
||||||
|
CString::new(ptr.as_ref().name().str()).unwrap().into_raw()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn ability_effect(ptr: ExternPointer<Ability>) -> OwnedPtr<c_char> {
|
||||||
|
CString::new(ptr.as_ref().effect().str()).unwrap().into_raw()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn ability_parameter_length(ptr: ExternPointer<Ability>) -> usize {
|
||||||
|
ptr.as_ref().parameters().len()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn ability_parameter_get(ptr: ExternPointer<Ability>, index: usize) -> BorrowedPtr<EffectParameter> {
|
||||||
|
if let Some(p) = ptr.as_ref().parameters().get(index) {
|
||||||
|
p as *const EffectParameter
|
||||||
|
} else {
|
||||||
|
std::ptr::null()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
use crate::ffi::{ffi_getter, ffi_vec_stringkey_getters, ffi_vec_value_getters, BorrowedPtr, ExternPointer, OwnedPtr};
|
||||||
|
use crate::static_data::{Form, LearnableMoves, StaticStatisticSet, TypeIdentifier};
|
||||||
|
use crate::StringKey;
|
||||||
|
use hashbrown::HashSet;
|
||||||
|
use std::ffi::{c_char, CStr, CString};
|
||||||
|
use std::ptr::drop_in_place;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn form_new(
|
||||||
|
name: *const c_char,
|
||||||
|
height: f32,
|
||||||
|
weight: f32,
|
||||||
|
base_experience: u32,
|
||||||
|
types: *const TypeIdentifier,
|
||||||
|
types_length: usize,
|
||||||
|
base_stats: OwnedPtr<StaticStatisticSet<u16>>,
|
||||||
|
abilities: *const BorrowedPtr<c_char>,
|
||||||
|
abilities_length: usize,
|
||||||
|
hidden_abilities: *const BorrowedPtr<c_char>,
|
||||||
|
hidden_abilities_length: usize,
|
||||||
|
moves: OwnedPtr<LearnableMoves>,
|
||||||
|
flags: *const *const c_char,
|
||||||
|
flags_length: usize,
|
||||||
|
) -> OwnedPtr<Form> {
|
||||||
|
let name: StringKey = CStr::from_ptr(name).to_str().unwrap().into();
|
||||||
|
|
||||||
|
let abilities = std::slice::from_raw_parts(abilities, abilities_length);
|
||||||
|
let mut abilities_vec = Vec::with_capacity(abilities_length);
|
||||||
|
for ability in abilities {
|
||||||
|
abilities_vec.push(CStr::from_ptr(*ability).into())
|
||||||
|
}
|
||||||
|
let hidden_abilities = std::slice::from_raw_parts(hidden_abilities, hidden_abilities_length);
|
||||||
|
let mut hidden_abilities_vec = Vec::with_capacity(hidden_abilities_length);
|
||||||
|
for ability in hidden_abilities {
|
||||||
|
hidden_abilities_vec.push(CStr::from_ptr(*ability).into())
|
||||||
|
}
|
||||||
|
|
||||||
|
let flags = std::slice::from_raw_parts(flags, flags_length);
|
||||||
|
let mut flags_set: HashSet<StringKey> = HashSet::with_capacity(flags_length);
|
||||||
|
for flag in flags {
|
||||||
|
flags_set.insert(CStr::from_ptr(*flag).to_str().unwrap().into());
|
||||||
|
}
|
||||||
|
|
||||||
|
Box::into_raw(Box::new(Form::new(
|
||||||
|
&name,
|
||||||
|
height,
|
||||||
|
weight,
|
||||||
|
base_experience,
|
||||||
|
std::slice::from_raw_parts(types, types_length).to_vec(),
|
||||||
|
*Box::from_raw(base_stats),
|
||||||
|
abilities_vec,
|
||||||
|
hidden_abilities_vec,
|
||||||
|
*Box::from_raw(moves),
|
||||||
|
flags_set,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn form_drop(ptr: OwnedPtr<Form>) {
|
||||||
|
drop_in_place(ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn form_name(ptr: ExternPointer<Form>) -> OwnedPtr<c_char> {
|
||||||
|
let name = ptr.as_ref().name();
|
||||||
|
CString::new(name.str()).unwrap().into_raw()
|
||||||
|
}
|
||||||
|
|
||||||
|
ffi_getter!(Form, height, f32);
|
||||||
|
ffi_getter!(Form, weight, f32);
|
||||||
|
ffi_getter!(Form, base_experience, u32);
|
||||||
|
|
||||||
|
ffi_vec_value_getters!(Form, types, TypeIdentifier);
|
||||||
|
|
||||||
|
ffi_getter!(Form, base_stats, BorrowedPtr<StaticStatisticSet<u16>>);
|
||||||
|
|
||||||
|
ffi_vec_stringkey_getters!(Form, abilities);
|
||||||
|
ffi_vec_stringkey_getters!(Form, hidden_abilities);
|
||||||
|
|
||||||
|
ffi_getter!(Form, moves, BorrowedPtr<LearnableMoves>);
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn form_has_flag(ptr: ExternPointer<Form>, flag: *const c_char) -> u8 {
|
||||||
|
let flag = CStr::from_ptr(flag).into();
|
||||||
|
if ptr.as_ref().has_flag(&flag) {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
use crate::defines::LevelInt;
|
||||||
|
use crate::ffi::{ExternPointer, OwnedPtr};
|
||||||
|
use crate::static_data::{GrowthRate, LookupGrowthRate};
|
||||||
|
use std::ptr::drop_in_place;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn growth_rate_lookup_new(array: *const u32, length: usize) -> OwnedPtr<LookupGrowthRate> {
|
||||||
|
let array = std::slice::from_raw_parts(array, length);
|
||||||
|
Box::into_raw(Box::new(LookupGrowthRate::new(array.to_vec())))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn growth_rate_lookup_drop(ptr: OwnedPtr<LookupGrowthRate>) {
|
||||||
|
drop_in_place(ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
#[allow(improper_ctypes_definitions)]
|
||||||
|
extern "C" fn growth_rate_calculate_level(ptr: ExternPointer<dyn GrowthRate>, experience: u32) -> LevelInt {
|
||||||
|
ptr.as_ref().calculate_level(experience)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
#[allow(improper_ctypes_definitions)]
|
||||||
|
extern "C" fn growth_rate_calculate_experience(ptr: ExternPointer<dyn GrowthRate>, level: LevelInt) -> u32 {
|
||||||
|
ptr.as_ref().calculate_experience(level)
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
use crate::ffi::{ffi_getter, ExternPointer, OwnedPtr};
|
||||||
|
use crate::static_data::{BattleItemCategory, Item, ItemCategory};
|
||||||
|
use crate::StringKey;
|
||||||
|
use hashbrown::HashSet;
|
||||||
|
use std::ffi::{c_char, CStr, CString};
|
||||||
|
use std::ptr::drop_in_place;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn item_new(
|
||||||
|
name: *const c_char,
|
||||||
|
category: ItemCategory,
|
||||||
|
battle_category: BattleItemCategory,
|
||||||
|
price: i32,
|
||||||
|
flags: *const *const c_char,
|
||||||
|
flags_length: usize,
|
||||||
|
) -> OwnedPtr<Item> {
|
||||||
|
let flags = std::slice::from_raw_parts(flags, flags_length);
|
||||||
|
let name: StringKey = CStr::from_ptr(name).to_str().unwrap().into();
|
||||||
|
let mut flags_set: HashSet<StringKey> = HashSet::with_capacity(flags_length);
|
||||||
|
for flag in flags {
|
||||||
|
flags_set.insert(CStr::from_ptr(*flag).to_str().unwrap().into());
|
||||||
|
}
|
||||||
|
Box::into_raw(Box::new(Item::new(&name, category, battle_category, price, flags_set)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn item_drop(ptr: OwnedPtr<Item>) {
|
||||||
|
drop_in_place(ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn item_name(ptr: ExternPointer<Item>) -> OwnedPtr<c_char> {
|
||||||
|
let name = ptr.as_ref().name();
|
||||||
|
CString::new(name.str()).unwrap().into_raw()
|
||||||
|
}
|
||||||
|
|
||||||
|
ffi_getter!(Item, category, ItemCategory);
|
||||||
|
ffi_getter!(Item, battle_category, BattleItemCategory);
|
||||||
|
ffi_getter!(Item, price, i32);
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn item_has_flag(ptr: ExternPointer<Item>, flag: *const c_char) -> u8 {
|
||||||
|
let flag = CStr::from_ptr(flag).into();
|
||||||
|
if ptr.as_ref().has_flag(&flag) {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
use crate::defines::LevelInt;
|
||||||
|
use crate::ffi::{BorrowedPtr, ExternPointer, OwnedPtr};
|
||||||
|
use crate::static_data::LearnableMoves;
|
||||||
|
use std::ffi::{c_char, CStr};
|
||||||
|
use std::ptr::drop_in_place;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn learnable_moves_new() -> OwnedPtr<LearnableMoves> {
|
||||||
|
Box::into_raw(Box::new(LearnableMoves::new()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn learnable_moves_drop(ptr: OwnedPtr<LearnableMoves>) {
|
||||||
|
drop_in_place(ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn learnable_moves_add_level_move(
|
||||||
|
ptr: ExternPointer<LearnableMoves>,
|
||||||
|
level: LevelInt,
|
||||||
|
move_name: BorrowedPtr<c_char>,
|
||||||
|
) {
|
||||||
|
ptr.as_mut().add_level_move(level, &CStr::from_ptr(move_name).into())
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
use crate::ffi::{ExternPointer, OwnedPtr};
|
||||||
|
use crate::static_data::EffectParameter;
|
||||||
|
use std::ffi::{c_char, CStr, CString};
|
||||||
|
use std::ptr::drop_in_place;
|
||||||
|
|
||||||
|
mod ability;
|
||||||
|
mod form;
|
||||||
|
mod growth_rate;
|
||||||
|
mod item;
|
||||||
|
mod learnable_moves;
|
||||||
|
mod move_data;
|
||||||
|
mod nature;
|
||||||
|
mod species;
|
||||||
|
mod statistic_set;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn effect_parameter_new_bool(value: u8) -> OwnedPtr<EffectParameter> {
|
||||||
|
Box::into_raw(Box::new(EffectParameter::Bool(value == 1)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn effect_parameter_new_int(value: i64) -> OwnedPtr<EffectParameter> {
|
||||||
|
Box::into_raw(Box::new(EffectParameter::Int(value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn effect_parameter_new_float(value: f32) -> OwnedPtr<EffectParameter> {
|
||||||
|
Box::into_raw(Box::new(EffectParameter::Float(value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn effect_parameter_new_string(value: *const c_char) -> OwnedPtr<EffectParameter> {
|
||||||
|
Box::into_raw(Box::new(EffectParameter::String(
|
||||||
|
CStr::from_ptr(value).to_str().unwrap().into(),
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn effect_parameter_drop(ptr: OwnedPtr<EffectParameter>) {
|
||||||
|
drop_in_place(ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn effect_parameter_get_as_bool(ptr: ExternPointer<EffectParameter>) -> u8 {
|
||||||
|
let p = ptr.as_ref();
|
||||||
|
if let EffectParameter::Bool(b) = p {
|
||||||
|
return if *b { 1 } else { 0 };
|
||||||
|
}
|
||||||
|
panic!("Unexpected effect parameter. Expected bool, was: {}", p);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn effect_parameter_get_as_int(ptr: ExternPointer<EffectParameter>) -> i64 {
|
||||||
|
let p = ptr.as_ref();
|
||||||
|
if let EffectParameter::Int(b) = p {
|
||||||
|
return *b;
|
||||||
|
}
|
||||||
|
panic!("Unexpected effect parameter. Expected int, was: {}", p);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn effect_parameter_get_as_float(ptr: ExternPointer<EffectParameter>) -> f32 {
|
||||||
|
let p = ptr.as_ref();
|
||||||
|
if let EffectParameter::Float(b) = p {
|
||||||
|
return *b;
|
||||||
|
}
|
||||||
|
panic!("Unexpected effect parameter. Expected float, was: {}", p);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn effect_parameter_get_as_string(ptr: ExternPointer<EffectParameter>) -> OwnedPtr<c_char> {
|
||||||
|
let p = ptr.as_ref();
|
||||||
|
if let EffectParameter::String(b) = p {
|
||||||
|
return CString::new(b.str().to_string()).unwrap().into_raw();
|
||||||
|
}
|
||||||
|
panic!("Unexpected effect parameter. Expected string, was: {}", p);
|
||||||
|
}
|
|
@ -0,0 +1,133 @@
|
||||||
|
use crate::ffi::{ffi_getter, BorrowedPtr, ExternPointer, OwnedPtr};
|
||||||
|
use crate::static_data::{EffectParameter, MoveCategory, MoveData, MoveTarget, SecondaryEffect, TypeIdentifier};
|
||||||
|
use crate::StringKey;
|
||||||
|
use hashbrown::HashSet;
|
||||||
|
use std::ffi::{c_char, CStr, CString};
|
||||||
|
use std::ptr::drop_in_place;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn move_data_new(
|
||||||
|
name: *const c_char,
|
||||||
|
move_type: TypeIdentifier,
|
||||||
|
category: MoveCategory,
|
||||||
|
base_power: u8,
|
||||||
|
accuracy: u8,
|
||||||
|
base_usages: u8,
|
||||||
|
target: MoveTarget,
|
||||||
|
priority: i8,
|
||||||
|
secondary_effect: *mut SecondaryEffect,
|
||||||
|
flags: *const *const c_char,
|
||||||
|
flags_length: usize,
|
||||||
|
) -> OwnedPtr<MoveData> {
|
||||||
|
let flags = std::slice::from_raw_parts(flags, flags_length);
|
||||||
|
let name: StringKey = CStr::from_ptr(name).to_str().unwrap().into();
|
||||||
|
let mut flags_set: HashSet<StringKey> = HashSet::with_capacity(flags_length);
|
||||||
|
for flag in flags {
|
||||||
|
flags_set.insert(CStr::from_ptr(*flag).to_str().unwrap().into());
|
||||||
|
}
|
||||||
|
let secondary_effect = if secondary_effect.is_null() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(*Box::from_raw(secondary_effect))
|
||||||
|
};
|
||||||
|
Box::into_raw(Box::new(MoveData::new(
|
||||||
|
&name,
|
||||||
|
move_type,
|
||||||
|
category,
|
||||||
|
base_power,
|
||||||
|
accuracy,
|
||||||
|
base_usages,
|
||||||
|
target,
|
||||||
|
priority,
|
||||||
|
secondary_effect,
|
||||||
|
flags_set,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn move_data_drop(ptr: OwnedPtr<MoveData>) {
|
||||||
|
drop_in_place(ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn move_data_name(ptr: ExternPointer<MoveData>) -> OwnedPtr<c_char> {
|
||||||
|
let name = ptr.as_ref().name();
|
||||||
|
CString::new(name.str()).unwrap().into_raw()
|
||||||
|
}
|
||||||
|
|
||||||
|
ffi_getter!(MoveData, move_type, TypeIdentifier);
|
||||||
|
ffi_getter!(MoveData, category, MoveCategory);
|
||||||
|
ffi_getter!(MoveData, base_power, u8);
|
||||||
|
ffi_getter!(MoveData, accuracy, u8);
|
||||||
|
ffi_getter!(MoveData, base_usages, u8);
|
||||||
|
ffi_getter!(MoveData, target, MoveTarget);
|
||||||
|
ffi_getter!(MoveData, priority, i8);
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn move_data_secondary_effect(ptr: ExternPointer<MoveData>) -> BorrowedPtr<SecondaryEffect> {
|
||||||
|
let effect = ptr.as_ref().secondary_effect();
|
||||||
|
if let Some(v) = effect {
|
||||||
|
v as *const SecondaryEffect
|
||||||
|
} else {
|
||||||
|
std::ptr::null()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn move_data_has_flag(ptr: ExternPointer<MoveData>, flag: *const c_char) -> u8 {
|
||||||
|
let flag = CStr::from_ptr(flag).into();
|
||||||
|
if ptr.as_ref().has_flag(&flag) {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn secondary_effect_new(
|
||||||
|
chance: f32,
|
||||||
|
effect_name: BorrowedPtr<c_char>,
|
||||||
|
parameters: *mut OwnedPtr<EffectParameter>,
|
||||||
|
parameters_length: usize,
|
||||||
|
) -> OwnedPtr<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))
|
||||||
|
}
|
||||||
|
|
||||||
|
Box::into_raw(Box::new(SecondaryEffect::new(
|
||||||
|
chance,
|
||||||
|
CStr::from_ptr(effect_name).into(),
|
||||||
|
parameters,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn secondary_effect_drop(ptr: OwnedPtr<SecondaryEffect>) {
|
||||||
|
drop_in_place(ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
ffi_getter!(SecondaryEffect, chance, f32);
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn secondary_effect_effect_name(ptr: ExternPointer<SecondaryEffect>) -> OwnedPtr<c_char> {
|
||||||
|
CString::new(ptr.as_ref().effect_name().str()).unwrap().into_raw()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn secondary_effect_parameter_length(ptr: ExternPointer<SecondaryEffect>) -> usize {
|
||||||
|
ptr.as_ref().parameters().len()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn secondary_effect_parameter_get(
|
||||||
|
ptr: ExternPointer<SecondaryEffect>,
|
||||||
|
index: usize,
|
||||||
|
) -> BorrowedPtr<EffectParameter> {
|
||||||
|
if let Some(v) = ptr.as_ref().parameters().get(index) {
|
||||||
|
v as *const EffectParameter
|
||||||
|
} else {
|
||||||
|
std::ptr::null()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
use crate::ffi::{ffi_getter, ExternPointer, OwnedPtr};
|
||||||
|
use crate::static_data::{Nature, Statistic};
|
||||||
|
use std::ptr::drop_in_place;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn nature_new(
|
||||||
|
increase_stat: Statistic,
|
||||||
|
decrease_stat: Statistic,
|
||||||
|
increase_modifier: f32,
|
||||||
|
decrease_modifier: f32,
|
||||||
|
) -> OwnedPtr<Nature> {
|
||||||
|
Box::into_raw(Box::new(Nature::new(
|
||||||
|
increase_stat,
|
||||||
|
decrease_stat,
|
||||||
|
increase_modifier,
|
||||||
|
decrease_modifier,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn nature_drop(ptr: OwnedPtr<Nature>) {
|
||||||
|
drop_in_place(ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
ffi_getter!(Nature, increased_stat, Statistic);
|
||||||
|
ffi_getter!(Nature, decreased_stat, Statistic);
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn nature_get_stat_modifier(ptr: ExternPointer<Nature>, stat: Statistic) -> f32 {
|
||||||
|
ptr.as_ref().get_stat_modifier(stat)
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
use crate::ffi::{ffi_getter, ffi_stringkey_getter, BorrowedPtr, ExternPointer, OwnedPtr};
|
||||||
|
use crate::static_data::{Form, Species};
|
||||||
|
use crate::StringKey;
|
||||||
|
use hashbrown::HashSet;
|
||||||
|
use std::ffi::{c_char, CStr};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn species_new(
|
||||||
|
id: u16,
|
||||||
|
name: BorrowedPtr<c_char>,
|
||||||
|
gender_rate: f32,
|
||||||
|
growth_rate: BorrowedPtr<c_char>,
|
||||||
|
capture_rate: u8,
|
||||||
|
default_form: OwnedPtr<Form>,
|
||||||
|
flags: *const *const c_char,
|
||||||
|
flags_length: usize,
|
||||||
|
) -> OwnedPtr<Species> {
|
||||||
|
let name: StringKey = CStr::from_ptr(name).to_str().unwrap().into();
|
||||||
|
let growth_rate: StringKey = CStr::from_ptr(growth_rate).to_str().unwrap().into();
|
||||||
|
|
||||||
|
let flags = std::slice::from_raw_parts(flags, flags_length);
|
||||||
|
let mut flags_set: HashSet<StringKey> = HashSet::with_capacity(flags_length);
|
||||||
|
for flag in flags {
|
||||||
|
flags_set.insert(CStr::from_ptr(*flag).to_str().unwrap().into());
|
||||||
|
}
|
||||||
|
Box::into_raw(Box::new(Species::new(
|
||||||
|
id,
|
||||||
|
&name,
|
||||||
|
gender_rate,
|
||||||
|
&growth_rate,
|
||||||
|
capture_rate,
|
||||||
|
*Box::from_raw(default_form),
|
||||||
|
flags_set,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
ffi_getter!(Species, id, u16);
|
||||||
|
ffi_stringkey_getter!(Species, name);
|
||||||
|
ffi_getter!(Species, gender_rate, f32);
|
||||||
|
ffi_stringkey_getter!(Species, growth_rate);
|
||||||
|
ffi_getter!(Species, capture_rate, u8);
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn species_add_form(
|
||||||
|
species: ExternPointer<Species>,
|
||||||
|
name: BorrowedPtr<c_char>,
|
||||||
|
form: OwnedPtr<Form>,
|
||||||
|
) {
|
||||||
|
let form = *Box::from_raw(form);
|
||||||
|
species.as_mut().add_form(CStr::from_ptr(name).into(), form)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn species_get_form(species: ExternPointer<Species>, name: BorrowedPtr<c_char>) -> BorrowedPtr<Form> {
|
||||||
|
let form = species.as_ref().get_form(&CStr::from_ptr(name).into());
|
||||||
|
if let Some(form) = form {
|
||||||
|
Arc::as_ptr(form)
|
||||||
|
} else {
|
||||||
|
std::ptr::null()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
use crate::ffi::{ExternPointer, OwnedPtr};
|
||||||
|
use crate::static_data::{StaticStatisticSet, Statistic, StatisticSet};
|
||||||
|
use std::ptr::drop_in_place;
|
||||||
|
|
||||||
|
macro_rules! statistic_set {
|
||||||
|
($num_type:ident) => {
|
||||||
|
paste::paste!{
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn [<statistic_set_ $num_type _new>](
|
||||||
|
hp: $num_type,
|
||||||
|
attack: $num_type,
|
||||||
|
defense: $num_type,
|
||||||
|
special_attack: $num_type,
|
||||||
|
special_defense: $num_type,
|
||||||
|
speed: $num_type,
|
||||||
|
) -> OwnedPtr<StatisticSet<$num_type>> {
|
||||||
|
Box::into_raw(Box::new(StatisticSet::new(
|
||||||
|
hp,
|
||||||
|
attack,
|
||||||
|
defense,
|
||||||
|
special_attack,
|
||||||
|
special_defense,
|
||||||
|
speed,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn [<statistic_set_ $num_type _drop>](ptr: OwnedPtr<StatisticSet<$num_type>>) {
|
||||||
|
drop_in_place(ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
statistic_set!(u8);
|
||||||
|
statistic_set!(u16);
|
||||||
|
statistic_set!(u32);
|
||||||
|
statistic_set!(i8);
|
||||||
|
statistic_set!(i16);
|
||||||
|
statistic_set!(i32);
|
||||||
|
|
||||||
|
macro_rules! static_statistic_set {
|
||||||
|
($num_type:ident) => {
|
||||||
|
paste::paste!{
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn [<static_statistic_set_ $num_type _new>](
|
||||||
|
hp: $num_type,
|
||||||
|
attack: $num_type,
|
||||||
|
defense: $num_type,
|
||||||
|
special_attack: $num_type,
|
||||||
|
special_defense: $num_type,
|
||||||
|
speed: $num_type,
|
||||||
|
) -> OwnedPtr<StaticStatisticSet<$num_type>> {
|
||||||
|
Box::into_raw(Box::new(StaticStatisticSet::new(
|
||||||
|
hp,
|
||||||
|
attack,
|
||||||
|
defense,
|
||||||
|
special_attack,
|
||||||
|
special_defense,
|
||||||
|
speed,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static_statistic_set!(u8);
|
||||||
|
static_statistic_set!(u16);
|
||||||
|
static_statistic_set!(u32);
|
||||||
|
static_statistic_set!(i8);
|
||||||
|
static_statistic_set!(i16);
|
||||||
|
static_statistic_set!(i32);
|
|
@ -28,6 +28,9 @@ pub mod defines;
|
||||||
/// The dynamic data module holds data that can change during execution, and things that relate to
|
/// The dynamic data module holds data that can change during execution, and things that relate to
|
||||||
/// this. This includes things as Pokemon themselves, battles, etc.
|
/// this. This includes things as Pokemon themselves, battles, etc.
|
||||||
pub mod dynamic_data;
|
pub mod dynamic_data;
|
||||||
|
/// The Foreign Function Interface allows for non Rust applications to call this library.
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
mod ffi;
|
||||||
/// Script implementations handles the different ways that dynamic scripts get loaded during battle.
|
/// Script implementations handles the different ways that dynamic scripts get loaded during battle.
|
||||||
pub mod script_implementations;
|
pub mod script_implementations;
|
||||||
/// The static data module holds data that can be set once, and then never change. This includes
|
/// The static data module holds data that can be set once, and then never change. This includes
|
||||||
|
|
|
@ -6,6 +6,7 @@ use crate::StringKey;
|
||||||
/// A unique key that can be used to store a reference to a type. Opaque reference to a byte
|
/// A unique key that can be used to store a reference to a type. Opaque reference to a byte
|
||||||
/// internally.
|
/// internally.
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash, Atom)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash, Atom)]
|
||||||
|
#[repr(C)]
|
||||||
pub struct TypeIdentifier {
|
pub struct TypeIdentifier {
|
||||||
/// The unique internal value.
|
/// The unique internal value.
|
||||||
val: u8,
|
val: u8,
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::StringKey;
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use growth_rates::*;
|
pub use growth_rates::*;
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
|
@ -14,6 +15,7 @@ pub use species_data::*;
|
||||||
pub use statistic_set::*;
|
pub use statistic_set::*;
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use statistics::*;
|
pub use statistics::*;
|
||||||
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
/// Growth rates define how fast a Pokemon can level up.
|
/// Growth rates define how fast a Pokemon can level up.
|
||||||
mod growth_rates;
|
mod growth_rates;
|
||||||
|
@ -31,3 +33,29 @@ mod species_data;
|
||||||
mod statistic_set;
|
mod statistic_set;
|
||||||
/// Statistics are numerical values on Pokemon that are used in battle.
|
/// Statistics are numerical values on Pokemon that are used in battle.
|
||||||
mod statistics;
|
mod statistics;
|
||||||
|
|
||||||
|
/// A parameter for an effect. This is basically a simple way to dynamically store multiple different
|
||||||
|
/// primitives on data.
|
||||||
|
#[derive(PartialEq, Debug)]
|
||||||
|
#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))]
|
||||||
|
pub enum EffectParameter {
|
||||||
|
/// A boolean value.
|
||||||
|
Bool(bool),
|
||||||
|
/// An integer value. Stored as a 64 bit int to deal with potentially large numbers.
|
||||||
|
Int(i64),
|
||||||
|
/// A float value. Stored as a 32 bit float.
|
||||||
|
Float(f32),
|
||||||
|
/// A string value.
|
||||||
|
String(StringKey),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for EffectParameter {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
EffectParameter::Bool(v) => f.write_fmt(format_args!("EffectParameter::Bool({})", v)),
|
||||||
|
EffectParameter::Int(v) => f.write_fmt(format_args!("EffectParameter::Int({})", v)),
|
||||||
|
EffectParameter::Float(v) => f.write_fmt(format_args!("EffectParameter::Float({})", v)),
|
||||||
|
EffectParameter::String(v) => f.write_fmt(format_args!("EffectParameter::String({})", v)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ use crate::StringKey;
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
|
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
|
||||||
|
#[repr(u8)]
|
||||||
pub enum MoveCategory {
|
pub enum MoveCategory {
|
||||||
/// A physical move uses the physical attack stats and physical defense stats to calculate damage.
|
/// A physical move uses the physical attack stats and physical defense stats to calculate damage.
|
||||||
Physical = 0,
|
Physical = 0,
|
||||||
|
@ -21,6 +22,7 @@ pub enum MoveCategory {
|
||||||
/// The move target defines what kind of targets the move can touch.
|
/// The move target defines what kind of targets the move can touch.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
#[repr(u8)]
|
||||||
pub enum MoveTarget {
|
pub enum MoveTarget {
|
||||||
/// Adjacent allows a move to target any Pokemon that is either directly to the left or right of
|
/// Adjacent allows a move to target any Pokemon that is either directly to the left or right of
|
||||||
/// the user, opposed to the user, or left or right of the slot that is opposing the user.
|
/// the user, opposed to the user, or left or right of the slot that is opposing the user.
|
||||||
|
|
|
@ -1,20 +1,6 @@
|
||||||
|
use crate::static_data::EffectParameter;
|
||||||
use crate::StringKey;
|
use crate::StringKey;
|
||||||
|
|
||||||
/// A parameter for an effect. This is basically a simple way to dynamically store multiple different
|
|
||||||
/// primitives on data.
|
|
||||||
#[derive(PartialEq, Debug)]
|
|
||||||
#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))]
|
|
||||||
pub enum EffectParameter {
|
|
||||||
/// A boolean value.
|
|
||||||
Bool(bool),
|
|
||||||
/// An integer value. Stored as a 64 bit int to deal with potentially large numbers.
|
|
||||||
Int(i64),
|
|
||||||
/// A float value. Stored as a 32 bit float.
|
|
||||||
Float(f32),
|
|
||||||
/// A string value.
|
|
||||||
String(StringKey),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A secondary effect is an effect on a move that happens after it hits.
|
/// A secondary effect is an effect on a move that happens after it hits.
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug)]
|
||||||
pub struct SecondaryEffect {
|
pub struct SecondaryEffect {
|
||||||
|
|
|
@ -48,9 +48,9 @@ impl Nature {
|
||||||
/// Calculates the modifier for a given stat. If it's the increased stat, returns the increased
|
/// 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
|
/// modifier, if it's the decreased stat, returns the decreased modifier. Otherwise returns 1.0
|
||||||
pub fn get_stat_modifier(&self, stat: Statistic) -> f32 {
|
pub fn get_stat_modifier(&self, stat: Statistic) -> f32 {
|
||||||
if stat == self.increase_stat {
|
if stat == self.increase_stat && stat != self.decrease_stat {
|
||||||
self.increase_modifier
|
self.increase_modifier
|
||||||
} else if stat == self.decrease_stat {
|
} else if stat == self.decrease_stat && stat != self.increase_stat {
|
||||||
self.decrease_modifier
|
self.decrease_modifier
|
||||||
} else {
|
} else {
|
||||||
1.0
|
1.0
|
||||||
|
|
|
@ -42,8 +42,7 @@ impl StringKey {
|
||||||
/// Creates a new StringKey. If we can find a value for this StringKey in the cache, we re-use
|
/// Creates a new StringKey. If we can find a value for this StringKey in the cache, we re-use
|
||||||
/// that value.
|
/// that value.
|
||||||
pub fn new(s: &str) -> Self {
|
pub fn new(s: &str) -> Self {
|
||||||
let s: ArcStr = s.into();
|
let hash = Self::get_hash(s);
|
||||||
let hash = StringKey::get_hash(s.as_str());
|
|
||||||
{
|
{
|
||||||
let cache_read = STRING_CACHE.read();
|
let cache_read = STRING_CACHE.read();
|
||||||
let cached_value = cache_read.get(&hash);
|
let cached_value = cache_read.get(&hash);
|
||||||
|
@ -55,8 +54,15 @@ impl StringKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let v = Self { str: s.clone(), hash };
|
|
||||||
let mut cache_write = STRING_CACHE.write();
|
let mut cache_write = STRING_CACHE.write();
|
||||||
|
if let Some(cached_value) = cache_write.get(&hash) {
|
||||||
|
return Self {
|
||||||
|
str: cached_value.clone(),
|
||||||
|
hash,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
let s: ArcStr = s.into();
|
||||||
|
let v = Self { str: s.clone(), hash };
|
||||||
cache_write.insert(hash, s);
|
cache_write.insert(hash, s);
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
|
@ -112,7 +118,7 @@ impl Display for StringKey {
|
||||||
|
|
||||||
impl Into<StringKey> for &CStr {
|
impl Into<StringKey> for &CStr {
|
||||||
fn into(self) -> StringKey {
|
fn into(self) -> StringKey {
|
||||||
StringKey::new(self.to_str().unwrap().into())
|
StringKey::new(self.to_str().unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Converts a character to lowercased in a const safe way.
|
/// Converts a character to lowercased in a const safe way.
|
||||||
|
|
Loading…
Reference in New Issue