Major work on WASM results
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
use parking_lot::RwLock;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::sync::Arc;
|
||||
use std::sync::RwLock;
|
||||
|
||||
use crate::dynamic_data::DamageSource;
|
||||
use crate::dynamic_data::ExecutingMove;
|
||||
@@ -29,14 +29,15 @@ impl EventHook {
|
||||
/// listeners can exist at the same time. Note that for these functions the event will be disposed
|
||||
/// of after the event is finished being sent.
|
||||
pub fn register_listener(&self, func: EvtHookFn) {
|
||||
self.evt_hook_function.write().push(func);
|
||||
self.evt_hook_function.write().unwrap().push(func);
|
||||
}
|
||||
|
||||
/// Run a new event. This will send the event to all externally defined event listeners. It will
|
||||
/// dispose of the event afterwards.
|
||||
pub fn trigger(&self, evt: Event) {
|
||||
let b = Box::new(&evt);
|
||||
for f in self.evt_hook_function.read().iter() {
|
||||
let read_lock = self.evt_hook_function.read().unwrap();
|
||||
for f in read_lock.iter() {
|
||||
f(&b);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ impl Battle {
|
||||
number_of_sides: u8,
|
||||
pokemon_per_side: u8,
|
||||
random_seed: Option<u128>,
|
||||
) -> Self {
|
||||
) -> Arc<Self> {
|
||||
// If no seed was passed, we use the current time as seed for the RNG, otherwise we use the
|
||||
// seed.
|
||||
let random = if let Some(seed) = random_seed {
|
||||
@@ -83,7 +83,7 @@ impl Battle {
|
||||
sides.push(BattleSide::new(i, pokemon_per_side));
|
||||
}
|
||||
|
||||
let mut battle = Self {
|
||||
let battle = Self {
|
||||
identifier: Default::default(),
|
||||
library,
|
||||
parties,
|
||||
@@ -103,12 +103,16 @@ impl Battle {
|
||||
script_source_data: Default::default(),
|
||||
};
|
||||
|
||||
let ptr: *mut Battle = &mut battle;
|
||||
for side in &mut battle.sides {
|
||||
side.set_battle(ptr);
|
||||
let battle_arc = Arc::new(battle);
|
||||
|
||||
let battle_ptr = Arc::as_ptr(&battle_arc) as *mut Battle;
|
||||
unsafe {
|
||||
for side in &mut battle_ptr.as_mut().unwrap().sides {
|
||||
side.set_battle(Arc::downgrade(&battle_arc));
|
||||
}
|
||||
}
|
||||
|
||||
battle
|
||||
battle_arc
|
||||
}
|
||||
|
||||
/// The library the battle uses for handling.
|
||||
@@ -135,10 +139,6 @@ impl Battle {
|
||||
pub fn sides(&self) -> &Vec<BattleSide> {
|
||||
&self.sides
|
||||
}
|
||||
/// A mutable list of all sides in the battle.
|
||||
pub fn sides_mut(&mut self) -> &mut Vec<BattleSide> {
|
||||
&mut self.sides
|
||||
}
|
||||
/// The RNG used for the battle.
|
||||
pub fn random(&self) -> &BattleRandom {
|
||||
&self.random
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::ops::Deref;
|
||||
use std::sync::atomic::{AtomicBool, AtomicU8, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::sync::{Arc, Weak};
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use parking_lot::lock_api::RwLockReadGuard;
|
||||
@@ -35,7 +35,7 @@ pub struct BattleSide {
|
||||
/// The number of choices that are set.
|
||||
choices_set: AtomicU8,
|
||||
/// A reference to the battle we're part of.
|
||||
battle: *mut Battle,
|
||||
battle: Weak<Battle>,
|
||||
/// Whether or not this side has fled.
|
||||
has_fled_battle: bool,
|
||||
/// The volatile scripts that are attached to the side.
|
||||
@@ -68,7 +68,7 @@ impl BattleSide {
|
||||
choices,
|
||||
fillable_slots,
|
||||
choices_set: AtomicU8::new(0),
|
||||
battle: std::ptr::null_mut::<Battle>(),
|
||||
battle: Weak::new(),
|
||||
has_fled_battle: false,
|
||||
volatile_scripts: Default::default(),
|
||||
script_source_data: Default::default(),
|
||||
@@ -76,7 +76,7 @@ impl BattleSide {
|
||||
}
|
||||
|
||||
/// Set the battle this side belongs to.
|
||||
pub(crate) fn set_battle(&mut self, battle: *mut Battle) {
|
||||
pub(crate) fn set_battle(&mut self, battle: Weak<Battle>) {
|
||||
self.battle = battle;
|
||||
}
|
||||
|
||||
@@ -106,8 +106,10 @@ impl BattleSide {
|
||||
self.choices_set.load(Ordering::SeqCst)
|
||||
}
|
||||
/// A reference to the battle we're part of.
|
||||
pub fn battle(&self) -> Result<&Battle> {
|
||||
unsafe { self.battle.as_ref().ok_or(anyhow!("Battle was not set, but requested")) }
|
||||
pub fn battle(&self) -> Result<Arc<Battle>> {
|
||||
self.battle
|
||||
.upgrade()
|
||||
.ok_or(anyhow!("Battle was not set, but requested"))
|
||||
}
|
||||
/// Whether or not this side has fled.
|
||||
pub fn has_fled_battle(&self) -> bool {
|
||||
@@ -194,7 +196,7 @@ impl BattleSide {
|
||||
&read_lock.get_res(index as usize)?.clone()
|
||||
};
|
||||
if let Some(pokemon) = pokemon {
|
||||
pokemon.set_battle_data(self.battle, self.index);
|
||||
pokemon.set_battle_data(self.battle.clone(), self.index);
|
||||
pokemon.set_on_battlefield(true)?;
|
||||
pokemon.set_battle_index(index);
|
||||
|
||||
@@ -227,7 +229,7 @@ impl BattleSide {
|
||||
/// Checks whether a Pokemon is on the field in this side.
|
||||
pub fn is_pokemon_on_side(&self, pokemon: Arc<Pokemon>) -> bool {
|
||||
for p in self.pokemon.read().iter().flatten() {
|
||||
if std::ptr::eq(p.deref().deref(), pokemon.deref()) {
|
||||
if Arc::ptr_eq(p, &pokemon) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -247,7 +249,7 @@ impl BattleSide {
|
||||
pub fn is_slot_unfillable(&self, pokemon: Arc<Pokemon>) -> Result<bool> {
|
||||
for (i, slot) in self.pokemon.read().iter().enumerate() {
|
||||
if let Some(p) = slot {
|
||||
if std::ptr::eq(p.deref().deref(), pokemon.deref()) {
|
||||
if Arc::ptr_eq(p, &pokemon) {
|
||||
return Ok(self.fillable_slots.get_res(i)?.load(Ordering::Relaxed));
|
||||
}
|
||||
}
|
||||
@@ -290,7 +292,8 @@ impl BattleSide {
|
||||
// Fetch parties for the two indices.
|
||||
let mut party_a = None;
|
||||
let mut party_b = None;
|
||||
for party in self.battle()?.parties() {
|
||||
let battle = self.battle()?;
|
||||
for party in battle.parties() {
|
||||
if party.is_responsible_for_index(self.index, a) {
|
||||
party_a = Some(party);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use std::ops::Deref;
|
||||
use std::sync::atomic::{AtomicBool, AtomicU32, AtomicU8, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -166,10 +165,10 @@ impl ExecutingMove {
|
||||
}
|
||||
|
||||
/// Gets a hit data for a target, with a specific index.
|
||||
pub fn get_hit_data(&self, for_target: &Pokemon, hit: u8) -> Result<&HitData> {
|
||||
pub fn get_hit_data(&self, for_target: &Arc<Pokemon>, hit: u8) -> Result<&HitData> {
|
||||
for (index, target) in self.targets.iter().enumerate() {
|
||||
if let Some(target) = target {
|
||||
if std::ptr::eq(target.deref().deref(), for_target.deref().deref()) {
|
||||
if Arc::ptr_eq(target, for_target) {
|
||||
let i = index * self.number_of_hits as usize + hit as usize;
|
||||
return match self.hits.get(i) {
|
||||
Some(hit) => Ok(hit),
|
||||
@@ -188,7 +187,7 @@ impl ExecutingMove {
|
||||
/// Checks whether a Pokemon is a target for this move.
|
||||
pub fn is_pokemon_target(&self, pokemon: &Arc<Pokemon>) -> bool {
|
||||
for target in self.targets.iter().flatten() {
|
||||
if std::ptr::eq(target.deref().deref(), pokemon.deref().deref()) {
|
||||
if Arc::ptr_eq(target, pokemon) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -199,7 +198,7 @@ impl ExecutingMove {
|
||||
pub(crate) fn get_index_of_target(&self, for_target: &Arc<Pokemon>) -> Result<usize> {
|
||||
for (index, target) in self.targets.iter().enumerate() {
|
||||
if let Some(target) = target {
|
||||
if std::ptr::eq(target.deref().deref(), for_target.deref().deref()) {
|
||||
if Arc::ptr_eq(target, for_target) {
|
||||
let i = index * self.number_of_hits as usize;
|
||||
return Ok(i);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use anyhow::Result;
|
||||
use std::sync::atomic::{AtomicU8, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -81,7 +80,7 @@ impl LearnedMove {
|
||||
}
|
||||
|
||||
/// Restore the remaining PP by a certain amount. Will prevent it from going above max PP.
|
||||
pub fn restore_uses(&self, mut uses: u8) -> Result<()> {
|
||||
pub fn restore_uses(&self, mut uses: u8) {
|
||||
self.remaining_pp
|
||||
.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| {
|
||||
if x + uses > self.max_pp {
|
||||
@@ -90,7 +89,6 @@ impl LearnedMove {
|
||||
Some(x + uses)
|
||||
})
|
||||
.ok();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +111,7 @@ mod tests {
|
||||
let data: Arc<dyn MoveData> = Arc::new(mock);
|
||||
let learned_move = LearnedMove::new(data, MoveLearnMethod::Level);
|
||||
assert!(learned_move.try_use(15));
|
||||
learned_move.restore_uses(5).unwrap();
|
||||
learned_move.restore_uses(5);
|
||||
assert_eq!(20, learned_move.remaining_pp());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::sync::atomic::{AtomicBool, AtomicU32, AtomicU8, Ordering};
|
||||
use std::sync::{Arc, Weak};
|
||||
@@ -26,7 +27,6 @@ use crate::{script_hook, PkmnError, StringKey, ValueIdentifiable, ValueIdentifie
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
|
||||
/// An individual Pokemon as we know and love them.
|
||||
#[derive(Debug)]
|
||||
pub struct Pokemon {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
@@ -392,10 +392,10 @@ impl Pokemon {
|
||||
}
|
||||
|
||||
/// Gets the battle the battle is currently in.
|
||||
pub fn get_battle(&self) -> Option<&Battle> {
|
||||
pub fn get_battle(&self) -> Option<Arc<Battle>> {
|
||||
let r = self.battle_data.read();
|
||||
if let Some(data) = &r.deref() {
|
||||
unsafe { data.battle.as_ref() }
|
||||
data.battle.upgrade()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -480,13 +480,8 @@ impl Pokemon {
|
||||
// If we're in battle, use the battle random for predictability
|
||||
let r = self.battle_data.read();
|
||||
if let Some(data) = r.deref() {
|
||||
let mut random = match data
|
||||
.battle()
|
||||
.ok_or(anyhow!("Battle not set"))?
|
||||
.random()
|
||||
.get_rng()
|
||||
.lock()
|
||||
{
|
||||
let battle = data.battle().ok_or(anyhow!("Battle not set"))?;
|
||||
let mut random = match battle.random().get_rng().lock() {
|
||||
Ok(v) => v,
|
||||
Err(_) => return Err(PkmnError::UnableToAcquireLock.into()),
|
||||
};
|
||||
@@ -585,7 +580,7 @@ impl Pokemon {
|
||||
}
|
||||
|
||||
/// Sets the current battle the Pokemon is in.
|
||||
pub fn set_battle_data(&self, battle: *mut Battle, battle_side_index: u8) {
|
||||
pub fn set_battle_data(&self, battle: Weak<Battle>, battle_side_index: u8) {
|
||||
let mut w = self.battle_data.write();
|
||||
if let Some(battle_data) = w.deref_mut() {
|
||||
battle_data.battle = battle;
|
||||
@@ -770,7 +765,7 @@ impl Pokemon {
|
||||
#[derive(Debug)]
|
||||
pub struct PokemonBattleData {
|
||||
/// The battle data of the Pokemon
|
||||
battle: *mut Battle,
|
||||
battle: Weak<Battle>,
|
||||
/// The index of the side of the Pokemon
|
||||
battle_side_index: AtomicU8,
|
||||
/// The index of the slot on the side of the Pokemon.
|
||||
@@ -783,12 +778,12 @@ pub struct PokemonBattleData {
|
||||
|
||||
impl PokemonBattleData {
|
||||
/// The battle data of the Pokemon
|
||||
pub fn battle_mut(&mut self) -> Option<&mut Battle> {
|
||||
unsafe { self.battle.as_mut() }
|
||||
pub fn battle_mut(&mut self) -> Option<Arc<Battle>> {
|
||||
self.battle.upgrade()
|
||||
}
|
||||
/// The battle data of the Pokemon
|
||||
pub fn battle(&self) -> Option<&Battle> {
|
||||
unsafe { self.battle.as_ref() }
|
||||
pub fn battle(&self) -> Option<Arc<Battle>> {
|
||||
self.battle.upgrade()
|
||||
}
|
||||
|
||||
/// The index of the side of the Pokemon
|
||||
@@ -876,6 +871,18 @@ pub enum DamageSource {
|
||||
Struggle = 2,
|
||||
}
|
||||
|
||||
impl Debug for Pokemon {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str("Pokemon(")?;
|
||||
write!(f, "Species: {}, ", self.species().name())?;
|
||||
write!(f, "Form: {}, ", self.form().name())?;
|
||||
write!(f, "Level: {}, ", self.level())?;
|
||||
|
||||
f.write_str(")")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::unwrap_used)]
|
||||
pub mod test {
|
||||
|
||||
Reference in New Issue
Block a user