More removal of RwLocks and replace it with Atomics, to prevent locks.
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:
@@ -124,7 +124,7 @@ impl<'user, 'library> ScriptSource<'user> for TurnChoice<'user, 'library> {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MoveChoice<'user, 'library> {
|
||||
used_move: Arc<RwLock<LearnedMove<'library>>>,
|
||||
used_move: Arc<LearnedMove<'library>>,
|
||||
target_side: u8,
|
||||
target_index: u8,
|
||||
script: ScriptContainer,
|
||||
@@ -135,7 +135,7 @@ pub struct MoveChoice<'user, 'library> {
|
||||
impl<'user, 'library> MoveChoice<'user, 'library> {
|
||||
pub fn new(
|
||||
user: Arc<RwLock<Pokemon<'user, 'library>>>,
|
||||
used_move: Arc<RwLock<LearnedMove<'library>>>,
|
||||
used_move: Arc<LearnedMove<'library>>,
|
||||
target_side: u8,
|
||||
target_index: u8,
|
||||
) -> Self {
|
||||
@@ -155,7 +155,7 @@ impl<'user, 'library> MoveChoice<'user, 'library> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn used_move(&self) -> &Arc<RwLock<LearnedMove<'library>>> {
|
||||
pub fn used_move(&self) -> &Arc<LearnedMove<'library>> {
|
||||
&self.used_move
|
||||
}
|
||||
|
||||
|
||||
@@ -68,14 +68,15 @@ impl<'own, 'library> Battle<'own, 'library> {
|
||||
if self.has_ended() {
|
||||
return Ok(());
|
||||
}
|
||||
let user = choice.user().read();
|
||||
if !user.is_usable() {
|
||||
return Ok(());
|
||||
{
|
||||
let user = choice.user().read();
|
||||
if !user.is_usable() {
|
||||
return Ok(());
|
||||
}
|
||||
if !user.is_on_battlefield() {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
if !user.is_on_battlefield() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if !self.can_use(&choice) {
|
||||
return Ok(());
|
||||
}
|
||||
@@ -92,12 +93,13 @@ impl<'own, 'library> Battle<'own, 'library> {
|
||||
fn execute_move_choice<'func>(&'func self, choice: &'func TurnChoice<'own, 'library>) -> PkmnResult<()> {
|
||||
let choice = choice.get_move_turn_data();
|
||||
let used_move = choice.used_move();
|
||||
let move_data_lock = used_move.read();
|
||||
let move_data = move_data_lock.move_data();
|
||||
let mut move_name = move_data.name().clone();
|
||||
script_hook!(change_move, choice, choice, &mut move_name);
|
||||
let move_data = self.library().static_data().moves().get(&move_name).unwrap();
|
||||
drop(move_data_lock);
|
||||
let move_data = {
|
||||
let move_data_lock = used_move;
|
||||
let move_data = move_data_lock.move_data();
|
||||
let mut move_name = move_data.name().clone();
|
||||
script_hook!(change_move, choice, choice, &mut move_name);
|
||||
self.library().static_data().moves().get(&move_name).unwrap()
|
||||
};
|
||||
// FIXME: also change the script on the choice if changed;
|
||||
let target_type = move_data.target();
|
||||
let targets = resolve_targets(choice.target_side(), choice.target_index(), target_type, self);
|
||||
@@ -120,7 +122,7 @@ impl<'own, 'library> Battle<'own, 'library> {
|
||||
if prevented {
|
||||
return Ok(());
|
||||
}
|
||||
if !executing_move.chosen_move().write().try_use(1) {
|
||||
if !executing_move.chosen_move().try_use(1) {
|
||||
return Ok(());
|
||||
}
|
||||
self.event_hook().trigger(Event::MoveUse {
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
||||
use crate::static_data::statistic_set::StatisticSet;
|
||||
use crate::static_data::statistics::Statistic;
|
||||
use std::sync::atomic::AtomicU32;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BattleStatCalculator {}
|
||||
|
||||
impl BattleStatCalculator {
|
||||
pub fn calculate_flat_stats(&self, pokemon: &Pokemon) -> StatisticSet<u32> {
|
||||
StatisticSet::<u32>::new(
|
||||
pub fn calculate_flat_stats(&self, pokemon: &Pokemon) -> StatisticSet<AtomicU32> {
|
||||
StatisticSet::<AtomicU32>::new(
|
||||
self.calculate_health_stat(pokemon),
|
||||
self.calculate_other_stat(pokemon, Statistic::Attack),
|
||||
self.calculate_other_stat(pokemon, Statistic::Defense),
|
||||
@@ -25,8 +26,8 @@ impl BattleStatCalculator {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn calculate_boosted_stats(&self, pokemon: &Pokemon) -> StatisticSet<u32> {
|
||||
StatisticSet::<u32>::new(
|
||||
pub fn calculate_boosted_stats(&self, pokemon: &Pokemon) -> StatisticSet<AtomicU32> {
|
||||
StatisticSet::<AtomicU32>::new(
|
||||
self.calculate_boosted_stat(pokemon, Statistic::HP),
|
||||
self.calculate_boosted_stat(pokemon, Statistic::Attack),
|
||||
self.calculate_boosted_stat(pokemon, Statistic::Defense),
|
||||
|
||||
@@ -39,7 +39,7 @@ impl<'library> Debug for dyn MiscLibrary<'library> {
|
||||
#[derive(Debug)]
|
||||
pub struct Gen7MiscLibrary<'library> {
|
||||
struggle_data: *const MoveData,
|
||||
struggle_learned_move: Arc<RwLock<LearnedMove<'library>>>,
|
||||
struggle_learned_move: Arc<LearnedMove<'library>>,
|
||||
}
|
||||
|
||||
impl<'library> Gen7MiscLibrary<'library> {
|
||||
@@ -50,17 +50,14 @@ impl<'library> Gen7MiscLibrary<'library> {
|
||||
MoveCategory::Physical,
|
||||
50,
|
||||
255,
|
||||
10,
|
||||
255,
|
||||
MoveTarget::Any,
|
||||
0,
|
||||
SecondaryEffect::new(-1.0, StringKey::new("struggle"), vec![]),
|
||||
HashSet::new(),
|
||||
));
|
||||
let struggle_ptr = Box::into_raw(struggle_data);
|
||||
let struggle_learned_move = Arc::new(RwLock::new(LearnedMove::new(
|
||||
unsafe { &*struggle_ptr },
|
||||
MoveLearnMethod::Unknown,
|
||||
)));
|
||||
let struggle_learned_move = Arc::new(LearnedMove::new(unsafe { &*struggle_ptr }, MoveLearnMethod::Unknown));
|
||||
Self {
|
||||
struggle_data: struggle_ptr,
|
||||
struggle_learned_move,
|
||||
|
||||
@@ -197,13 +197,13 @@ impl<'own, 'library> Battle<'own, 'library> {
|
||||
}
|
||||
if let TurnChoice::Move(data) = choice {
|
||||
// TODO: Hook to change number of PP needed.
|
||||
if data.used_move().read().remaining_pp() < 1 {
|
||||
if data.used_move().remaining_pp() < 1 {
|
||||
return false;
|
||||
}
|
||||
if !is_valid_target(
|
||||
data.target_side(),
|
||||
data.target_index(),
|
||||
data.used_move().read().move_data().target(),
|
||||
data.used_move().move_data().target(),
|
||||
choice.user().read().deref(),
|
||||
) {
|
||||
return false;
|
||||
|
||||
@@ -63,7 +63,7 @@ pub struct ExecutingMove<'own, 'battle, 'library> {
|
||||
number_of_hits: u8,
|
||||
hits: Vec<HitData>,
|
||||
user: Arc<RwLock<Pokemon<'battle, 'library>>>,
|
||||
chosen_move: Arc<RwLock<LearnedMove<'library>>>,
|
||||
chosen_move: Arc<LearnedMove<'library>>,
|
||||
use_move: &'own MoveData,
|
||||
script: ScriptContainer,
|
||||
targets: &'own TargetList<'battle, 'library>,
|
||||
@@ -75,7 +75,7 @@ impl<'own, 'battle, 'library> ExecutingMove<'own, 'battle, 'library> {
|
||||
targets: &'own TargetList<'battle, 'library>,
|
||||
number_of_hits: u8,
|
||||
user: Arc<RwLock<Pokemon<'battle, 'library>>>,
|
||||
chosen_move: Arc<RwLock<LearnedMove<'library>>>,
|
||||
chosen_move: Arc<LearnedMove<'library>>,
|
||||
use_move: &'own MoveData,
|
||||
script: ScriptContainer,
|
||||
) -> Self {
|
||||
@@ -104,7 +104,7 @@ impl<'own, 'battle, 'library> ExecutingMove<'own, 'battle, 'library> {
|
||||
pub fn user(&self) -> &Arc<RwLock<Pokemon<'battle, 'library>>> {
|
||||
&self.user
|
||||
}
|
||||
pub fn chosen_move(&self) -> &Arc<RwLock<LearnedMove<'library>>> {
|
||||
pub fn chosen_move(&self) -> &Arc<LearnedMove<'library>> {
|
||||
&self.chosen_move
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use crate::static_data::MoveData;
|
||||
use std::sync::atomic::{AtomicU8, Ordering};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LearnedMove<'library> {
|
||||
move_data: &'library MoveData,
|
||||
max_pp: u8,
|
||||
remaining_pp: u8,
|
||||
remaining_pp: AtomicU8,
|
||||
learn_method: MoveLearnMethod,
|
||||
}
|
||||
|
||||
@@ -19,7 +20,7 @@ impl<'a> LearnedMove<'a> {
|
||||
Self {
|
||||
move_data,
|
||||
max_pp: move_data.base_usages(),
|
||||
remaining_pp: move_data.base_usages(),
|
||||
remaining_pp: AtomicU8::new(move_data.base_usages()),
|
||||
learn_method,
|
||||
}
|
||||
}
|
||||
@@ -32,17 +33,17 @@ impl<'a> LearnedMove<'a> {
|
||||
self.max_pp
|
||||
}
|
||||
pub fn remaining_pp(&self) -> u8 {
|
||||
self.remaining_pp
|
||||
self.remaining_pp.load(Ordering::Relaxed)
|
||||
}
|
||||
pub fn learn_method(&self) -> MoveLearnMethod {
|
||||
self.learn_method
|
||||
}
|
||||
|
||||
pub fn try_use(&mut self, amount: u8) -> bool {
|
||||
if amount > self.remaining_pp {
|
||||
pub fn try_use(&self, amount: u8) -> bool {
|
||||
if amount > self.remaining_pp() {
|
||||
return false;
|
||||
}
|
||||
self.remaining_pp -= amount;
|
||||
return true;
|
||||
self.remaining_pp.fetch_sub(amount, Ordering::SeqCst);
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ use crate::static_data::DataLibrary;
|
||||
use crate::utils::random::Random;
|
||||
use crate::{script_hook, PkmnResult, ScriptCategory, StringKey};
|
||||
use parking_lot::RwLock;
|
||||
use std::sync::atomic::{AtomicI8, AtomicU32, AtomicU8, Ordering};
|
||||
use std::sync::{Arc, Weak};
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -63,21 +64,21 @@ where
|
||||
display_form: Option<&'own Form>,
|
||||
|
||||
level: LevelInt,
|
||||
experience: u32,
|
||||
experience: AtomicU32,
|
||||
unique_identifier: u32,
|
||||
gender: Gender,
|
||||
coloring: u8,
|
||||
held_item: Option<&'own Item>,
|
||||
current_health: u32,
|
||||
current_health: AtomicU32,
|
||||
|
||||
weight: f32,
|
||||
height: f32,
|
||||
|
||||
stat_boost: ClampedStatisticSet<i8, -6, 6>,
|
||||
flat_stats: StatisticSet<u32>,
|
||||
boosted_stats: StatisticSet<u32>,
|
||||
individual_values: ClampedStatisticSet<u8, 0, 31>,
|
||||
effort_values: ClampedStatisticSet<u8, 0, 252>,
|
||||
stat_boost: ClampedStatisticSet<AtomicI8, -6, 6>,
|
||||
flat_stats: StatisticSet<AtomicU32>,
|
||||
boosted_stats: StatisticSet<AtomicU32>,
|
||||
individual_values: ClampedStatisticSet<AtomicU8, 0, 31>,
|
||||
effort_values: ClampedStatisticSet<AtomicU8, 0, 252>,
|
||||
nature: &'own Nature,
|
||||
|
||||
nickname: Option<String>,
|
||||
@@ -88,7 +89,7 @@ where
|
||||
|
||||
battle_data: Option<PokemonBattleData<'own, 'library>>,
|
||||
|
||||
moves: [Option<Arc<RwLock<LearnedMove<'library>>>>; MAX_MOVES],
|
||||
moves: [Option<Arc<LearnedMove<'library>>>; MAX_MOVES],
|
||||
allowed_experience: bool,
|
||||
|
||||
types: Vec<u8>,
|
||||
@@ -125,7 +126,7 @@ impl<'own, 'library> Pokemon<'own, 'library> {
|
||||
let nature = library
|
||||
.static_data()
|
||||
.natures()
|
||||
.get_nature(&nature)
|
||||
.get_nature(nature)
|
||||
.unwrap_or_else(|| panic!("Unknown nature name was given: {}.", &nature));
|
||||
let mut pokemon = Self {
|
||||
library,
|
||||
@@ -134,12 +135,12 @@ impl<'own, 'library> Pokemon<'own, 'library> {
|
||||
display_species: None,
|
||||
display_form: None,
|
||||
level,
|
||||
experience,
|
||||
experience: AtomicU32::new(experience),
|
||||
unique_identifier,
|
||||
gender,
|
||||
coloring,
|
||||
held_item: None,
|
||||
current_health: 1,
|
||||
current_health: AtomicU32::new(1),
|
||||
weight,
|
||||
height,
|
||||
stat_boost: Default::default(),
|
||||
@@ -166,7 +167,7 @@ impl<'own, 'library> Pokemon<'own, 'library> {
|
||||
};
|
||||
pokemon.recalculate_flat_stats();
|
||||
let health = pokemon.flat_stats().hp();
|
||||
pokemon.current_health = health;
|
||||
pokemon.current_health = AtomicU32::new(health);
|
||||
|
||||
pokemon
|
||||
}
|
||||
@@ -199,7 +200,7 @@ impl<'own, 'library> Pokemon<'own, 'library> {
|
||||
self.level
|
||||
}
|
||||
pub fn experience(&self) -> u32 {
|
||||
self.experience
|
||||
self.experience.load(Ordering::Relaxed)
|
||||
}
|
||||
pub fn unique_identifier(&self) -> u32 {
|
||||
self.unique_identifier
|
||||
@@ -240,7 +241,7 @@ impl<'own, 'library> Pokemon<'own, 'library> {
|
||||
}
|
||||
|
||||
pub fn current_health(&self) -> u32 {
|
||||
self.current_health
|
||||
self.current_health.load(Ordering::Relaxed)
|
||||
}
|
||||
pub fn max_health(&self) -> u32 {
|
||||
self.boosted_stats.hp()
|
||||
@@ -260,31 +261,31 @@ impl<'own, 'library> Pokemon<'own, 'library> {
|
||||
pub fn types(&self) -> &Vec<u8> {
|
||||
&self.types
|
||||
}
|
||||
pub fn learned_moves(&self) -> &[Option<Arc<RwLock<LearnedMove<'library>>>>; MAX_MOVES] {
|
||||
pub fn learned_moves(&self) -> &[Option<Arc<LearnedMove<'library>>>; MAX_MOVES] {
|
||||
&self.moves
|
||||
}
|
||||
pub fn status(&self) -> &ScriptContainer {
|
||||
&self.status_script
|
||||
}
|
||||
pub fn flat_stats(&self) -> &StatisticSet<u32> {
|
||||
pub fn flat_stats(&self) -> &StatisticSet<AtomicU32> {
|
||||
&self.flat_stats
|
||||
}
|
||||
pub fn boosted_stats(&self) -> &StatisticSet<u32> {
|
||||
pub fn boosted_stats(&self) -> &StatisticSet<AtomicU32> {
|
||||
&self.boosted_stats
|
||||
}
|
||||
pub fn stat_boost(&self) -> &ClampedStatisticSet<i8, -6, 6> {
|
||||
pub fn stat_boost(&self) -> &ClampedStatisticSet<AtomicI8, -6, 6> {
|
||||
&self.stat_boost
|
||||
}
|
||||
pub fn individual_values(&self) -> &ClampedStatisticSet<u8, 0, 31> {
|
||||
pub fn individual_values(&self) -> &ClampedStatisticSet<AtomicU8, 0, 31> {
|
||||
&self.individual_values
|
||||
}
|
||||
pub fn effort_values(&self) -> &ClampedStatisticSet<u8, 0, 252> {
|
||||
pub fn effort_values(&self) -> &ClampedStatisticSet<AtomicU8, 0, 252> {
|
||||
&self.effort_values
|
||||
}
|
||||
|
||||
pub fn get_battle(&self) -> Option<&Battle<'own, 'library>> {
|
||||
if let Some(data) = &self.battle_data {
|
||||
Some(&data.battle().unwrap())
|
||||
Some(data.battle().unwrap())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -401,10 +402,10 @@ impl<'own, 'library> Pokemon<'own, 'library> {
|
||||
let old_health = self.max_health();
|
||||
self.recalculate_flat_stats();
|
||||
let diff_health = (self.max_health() - old_health) as i32;
|
||||
if self.current_health == 0 && (self.current_health as i32) < -diff_health {
|
||||
self.current_health = 0;
|
||||
if self.current_health() == 0 && (self.current_health() as i32) < -diff_health {
|
||||
self.current_health.store(0, Ordering::SeqCst);
|
||||
} else {
|
||||
self.current_health = self.current_health() + diff_health as u32;
|
||||
self.current_health.fetch_add(diff_health as u32, Ordering::Acquire);
|
||||
}
|
||||
// TODO: consider form specific attacks?
|
||||
|
||||
@@ -420,7 +421,7 @@ impl<'own, 'library> Pokemon<'own, 'library> {
|
||||
}
|
||||
|
||||
pub fn is_fainted(&self) -> bool {
|
||||
self.current_health == 0
|
||||
self.current_health() == 0
|
||||
}
|
||||
|
||||
pub fn set_battle_data(&mut self, battle: *mut Battle<'own, 'library>, battle_side_index: u8) {
|
||||
@@ -475,8 +476,8 @@ impl<'own, 'library> Pokemon<'own, 'library> {
|
||||
}
|
||||
|
||||
pub fn damage(&mut self, mut damage: u32, source: DamageSource) {
|
||||
if damage > self.current_health {
|
||||
damage = self.current_health;
|
||||
if damage > self.current_health() {
|
||||
damage = self.current_health();
|
||||
}
|
||||
if damage == 0 {
|
||||
return;
|
||||
@@ -491,10 +492,10 @@ impl<'own, 'library> Pokemon<'own, 'library> {
|
||||
new_health,
|
||||
});
|
||||
// TODO: register history
|
||||
script_hook!(on_damage, self, self, source, self.current_health, new_health);
|
||||
script_hook!(on_damage, self, self, source, self.current_health(), new_health);
|
||||
}
|
||||
}
|
||||
self.current_health = new_health;
|
||||
self.current_health.store(new_health, Ordering::SeqCst);
|
||||
if self.is_fainted() && damage > 0 {
|
||||
self.on_faint(source);
|
||||
}
|
||||
@@ -540,7 +541,7 @@ impl<'own, 'library> Pokemon<'own, 'library> {
|
||||
panic!("No more moves with an empty space found.");
|
||||
}
|
||||
let move_data = self.library.static_data().moves().get(move_name).unwrap();
|
||||
self.moves[move_pos.unwrap()] = Some(Arc::new(RwLock::new(LearnedMove::new(move_data, learn_method))));
|
||||
self.moves[move_pos.unwrap()] = Some(Arc::new(LearnedMove::new(move_data, learn_method)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user