Adds ability to get the current time of day
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Deukhoofd 2023-07-22 13:22:47 +02:00
parent c75541720b
commit 0c6a0cadfe
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
10 changed files with 132 additions and 25 deletions

View File

@ -156,7 +156,7 @@ pub mod test {
static_data: Arc::new(crate::static_data::libraries::static_data::test::build()),
stat_calculator: Arc::new(Gen7BattleStatCalculator::new()),
damage_calculator: Arc::new(Gen7DamageLibrary::new(false)),
misc_library: Arc::new(Gen7MiscLibrary::new()),
misc_library: Arc::new(Gen7MiscLibrary::default()),
script_resolver: Arc::new(EmptyScriptResolver {}),
}
}

View File

@ -1,4 +1,5 @@
use std::fmt::Debug;
use chrono::Timelike;
use std::fmt::{Debug, Formatter};
use std::sync::Arc;
use hashbrown::HashSet;
@ -6,7 +7,7 @@ use hashbrown::HashSet;
use crate::dynamic_data::choices::{MoveChoice, TurnChoice};
use crate::dynamic_data::Pokemon;
use crate::dynamic_data::{LearnedMove, MoveLearnMethod};
use crate::static_data::{MoveCategory, MoveData, MoveDataImpl, MoveTarget, SecondaryEffectImpl};
use crate::static_data::{MoveCategory, MoveData, MoveDataImpl, MoveTarget, SecondaryEffectImpl, TimeOfDay};
use crate::StringKey;
/// The misc library holds several misc functions required for the battle to run.
@ -16,19 +17,24 @@ pub trait MiscLibrary: Debug {
/// Returns the move we need to use if we can't use another move. Typically Struggle.
fn replacement_move(&self, user: &Pokemon, target_side: u8, target_index: u8) -> TurnChoice;
// TODO: can evolve from level up?
// TODO: get time
/// Gets the current time of day for the battle.
fn time_of_day(&self) -> TimeOfDay;
}
/// A function pointer to get the time of day.
type GetTimeOfDayFn = Box<dyn Fn() -> TimeOfDay>;
/// A gen 7 implementation for the MiscLibrary.
#[derive(Debug)]
pub struct Gen7MiscLibrary {
/// The learned move data for struggle.
struggle_learned_move: Arc<LearnedMove>,
/// The function to get the time of day.
get_time_fn: GetTimeOfDayFn,
}
impl Gen7MiscLibrary {
/// Instantiates a new MiscLibrary.
pub fn new() -> Self {
pub fn new(get_time_fn: GetTimeOfDayFn) -> Self {
let struggle_data: Arc<dyn MoveData> = Arc::new(MoveDataImpl::new(
&StringKey::new("struggle"),
0.into(),
@ -46,13 +52,28 @@ impl Gen7MiscLibrary {
HashSet::new(),
));
let struggle_learned_move = Arc::new(LearnedMove::new(struggle_data, MoveLearnMethod::Unknown));
Self { struggle_learned_move }
Self {
struggle_learned_move,
get_time_fn,
}
}
}
impl Default for Gen7MiscLibrary {
fn default() -> Self {
Self::new()
Self::new(Box::new(|| {
let time = chrono::Local::now().time();
let hour = time.hour();
// Following the values for Pokemon Sun.
match hour {
0..=5 => TimeOfDay::Night,
6..=9 => TimeOfDay::Morning,
10..=16 => TimeOfDay::Day,
17 => TimeOfDay::Evening,
18..=23 => TimeOfDay::Night,
_ => unreachable!(),
}
}))
}
}
@ -70,4 +91,14 @@ impl MiscLibrary for Gen7MiscLibrary {
target_index,
))
}
fn time_of_day(&self) -> TimeOfDay {
(self.get_time_fn)()
}
}
impl Debug for Gen7MiscLibrary {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str("Gen7MiscLibrary")
}
}

View File

@ -1,10 +1,46 @@
use crate::dynamic_data::{Gen7MiscLibrary, MiscLibrary};
use crate::ffi::ffi_handle::FFIHandle;
use crate::static_data::TimeOfDay;
use std::sync::Arc;
/// Instantiates a new MiscLibrary.
#[no_mangle]
extern "C" fn gen_7_misc_library_new() -> FFIHandle<Arc<dyn MiscLibrary>> {
let v: Arc<dyn MiscLibrary> = Arc::new(Gen7MiscLibrary::new());
extern "C" fn gen_7_misc_library_new(get_time_of_day_fn: FFIGetTimeOfDayFn) -> FFIHandle<Arc<dyn MiscLibrary>> {
let v: Arc<dyn MiscLibrary> = Arc::new(Gen7MiscLibrary::new(Box::new(get_time_of_day_fn)));
FFIHandle::get_handle(v.into())
}
/// Wrapper class for easier use of an external function pointer.
#[repr(C)]
pub(super) struct FFIGetTimeOfDayFn {
/// The actual C function to be called. Note that we pass the batch id as a pair of u64s. This
/// is because u128 does not have a stable ABI yet.
f: extern "C" fn() -> u8,
}
impl FFIGetTimeOfDayFn {
/// Calls the actual wrapped function in the correct format.
fn call_self(&self) -> TimeOfDay {
unsafe { std::mem::transmute((self.f)()) }
}
}
impl FnMut<()> for FFIGetTimeOfDayFn {
extern "rust-call" fn call_mut(&mut self, _: ()) -> Self::Output {
self.call_self()
}
}
impl FnOnce<()> for FFIGetTimeOfDayFn {
type Output = TimeOfDay;
extern "rust-call" fn call_once(self, _: ()) -> Self::Output {
self.call_self()
}
}
impl Fn<()> for FFIGetTimeOfDayFn {
extern "rust-call" fn call(&self, _: ()) -> Self::Output {
self.call_self()
}
}

View File

@ -1,11 +1,11 @@
use crate::dynamic_data::{DynamicLibrary, ScriptOwnerData};
use crate::dynamic_data::{DynamicLibrary, MiscLibrary, ScriptOwnerData};
use crate::script_implementations::wasm::export_registry::register;
use crate::script_implementations::wasm::export_registry::wasm_result::{try_wasm, wasm_ok, WasmResult};
use crate::script_implementations::wasm::extern_ref::ExternRef;
use wasmer::{FunctionEnv, FunctionEnvMut, Imports, StoreMut};
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
use crate::static_data::StaticData;
use crate::static_data::{StaticData, TimeOfDay};
/// The battle registration
mod battle;
@ -38,6 +38,27 @@ register! {
wasm_ok(ExternRef::<dyn StaticData>::func_new(&env, static_data.into()))
}
fn dynamic_library_get_misc_library(
env: FunctionEnvMut<WebAssemblyEnv>,
dynamic_lib: ExternRef<dyn DynamicLibrary>,
) -> WasmResult<ExternRef<dyn MiscLibrary>> {
let dynamic_lib = try_wasm!(dynamic_lib.value_func_arc(&env), env);
let misc_library = dynamic_lib.misc_library();
wasm_ok(ExternRef::<dyn MiscLibrary>::func_new(&env, misc_library.into()))
}
fn misc_library_get_time_of_day(
env: FunctionEnvMut<WebAssemblyEnv>,
dynamic_lib: ExternRef<dyn MiscLibrary>,
) -> WasmResult<u8> {
let misc_library = try_wasm!(dynamic_lib.value_func_arc(&env), env);
unsafe{
let time_of_day = misc_library.time_of_day();
wasm_ok(std::mem::transmute::<TimeOfDay, u8>(time_of_day))
}
}
fn script_get_owner(
env: FunctionEnvMut<WebAssemblyEnv>,
script: u32,

View File

@ -40,6 +40,7 @@ pub(crate) enum WasmObject {
// Dynamic data libraries
DynamicLibrary(Weak<dyn crate::dynamic_data::DynamicLibrary>),
MiscLibrary(Weak<dyn crate::dynamic_data::MiscLibrary>),
// Battle data
Battle(WeakBattleReference),
@ -88,6 +89,7 @@ impl PartialEq for WasmObject {
(WasmObject::PokemonParty(s1), WasmObject::PokemonParty(s2)) => Weak::ptr_eq(s1, s2),
(WasmObject::LearnedMove(s1), WasmObject::LearnedMove(s2)) => Weak::ptr_eq(s1, s2),
(WasmObject::DynamicLibrary(s1), WasmObject::DynamicLibrary(s2)) => Weak::ptr_eq(s1, s2),
(WasmObject::MiscLibrary(s1), WasmObject::MiscLibrary(s2)) => Weak::ptr_eq(s1, s2),
(WasmObject::Battle(s1), WasmObject::Battle(s2)) => WeakBattleReference::eq(s1, s2),
(WasmObject::ChoiceQueue(s1), WasmObject::ChoiceQueue(s2)) => Weak::ptr_eq(s1, s2),
(WasmObject::BattleRandom(s1), WasmObject::BattleRandom(s2)) => Weak::ptr_eq(s1, s2),
@ -131,6 +133,7 @@ impl Hash for WasmObject {
WasmObject::PokemonParty(m) => m.as_ptr().hash(state),
WasmObject::LearnedMove(m) => m.as_ptr().hash(state),
WasmObject::DynamicLibrary(m) => m.as_ptr().hash(state),
WasmObject::MiscLibrary(m) => m.as_ptr().hash(state),
WasmObject::Battle(m) => m.as_ptr().hash(state),
WasmObject::ChoiceQueue(m) => m.as_ptr().hash(state),
WasmObject::BattleRandom(m) => m.as_ptr().hash(state),
@ -394,6 +397,14 @@ impl From<&Arc<dyn crate::dynamic_data::DynamicLibrary>> for WasmObject {
impl_from_wasm_obj!(DynamicLibrary, Arc<dyn crate::dynamic_data::DynamicLibrary>);
impl From<&Arc<dyn crate::dynamic_data::MiscLibrary>> for WasmObject {
fn from(value: &Arc<dyn crate::dynamic_data::MiscLibrary>) -> Self {
Self::MiscLibrary(Arc::downgrade(value))
}
}
impl_from_wasm_obj!(MiscLibrary, Arc<dyn crate::dynamic_data::MiscLibrary>);
impl From<&Arc<crate::dynamic_data::BattleRandom>> for WasmObject {
fn from(value: &Arc<crate::dynamic_data::BattleRandom>) -> Self {
Self::BattleRandom(Arc::downgrade(value))

View File

@ -168,17 +168,6 @@ impl<T> Default for VecExternRef<T> {
}
}
// impl<T: 'static> VecExternRef<T> {
// /// Instantiates a new VecExternRef for a given slice.
// pub fn new(env: &WebAssemblyEnvironmentData, value: &Vec<T>) -> Self {
// Self {
// index: env.get_extern_vec_ref_index(value),
// size: value.len() as u32,
// _phantom: Default::default(),
// }
// }
// }
unsafe impl<T> FromToNativeWasmType for VecExternRef<T> {
type Native = i64;

View File

@ -15,6 +15,9 @@ pub use species_data::*;
pub use statistic_set::*;
#[doc(inline)]
pub use statistics::*;
#[doc(inline)]
pub use time_of_day::*;
use std::fmt::{Display, Formatter};
#[cfg(test)]
@ -50,6 +53,8 @@ mod species_data;
mod statistic_set;
/// Statistics are numerical values on Pokemon that are used in battle.
mod statistics;
/// Time of day defines the time of day for a battle.
mod time_of_day;
/// A parameter for an effect. This is basically a simple way to dynamically store multiple different
/// primitives on data.

View File

@ -0,0 +1,14 @@
/// The time of day. These values are the 4 different groups of time of day in Pokemon games since
/// gen 5. The exact times these correspond to differ between games.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u8)]
pub enum TimeOfDay {
/// The morning.
Morning = 0,
/// The day.
Day = 1,
/// The evening.
Evening = 2,
/// The night.
Night = 3,
}

View File

@ -20,7 +20,7 @@ use pkmn_lib::static_data::{
GrowthRateLibrary, GrowthRateLibraryImpl, ItemImpl, ItemLibrary, ItemLibraryImpl, LearnableMoves,
LearnableMovesImpl, LibrarySettingsImpl, LookupGrowthRate, MoveDataImpl, MoveLibrary, MoveLibraryImpl, NatureImpl,
NatureLibrary, NatureLibraryImpl, SecondaryEffect, SecondaryEffectImpl, SpeciesImpl, SpeciesLibrary,
SpeciesLibraryImpl, StaticDataImpl, StaticStatisticSet, Statistic, TypeLibrary, TypeLibraryImpl,
SpeciesLibraryImpl, StaticDataImpl, StaticStatisticSet, Statistic, TimeOfDay, TypeLibrary, TypeLibraryImpl,
};
use pkmn_lib::StringKey;
@ -84,7 +84,7 @@ pub fn load_library() -> LoadResult {
Arc::new(data),
Arc::new(Gen7BattleStatCalculator::new()),
Arc::new(Gen7DamageLibrary::new(false)),
Arc::new(Gen7MiscLibrary::new()),
Arc::new(Gen7MiscLibrary::new(Box::new(|| TimeOfDay::Day))),
script_resolver,
));

Binary file not shown.