Major rework of extern ref system for WASM, fixes most possible panics in WASM handling
All checks were successful
continuous-integration/drone Build is passing
All checks were successful
continuous-integration/drone Build is passing
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use anyhow::{bail, Result};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::atomic::{AtomicBool, AtomicI8, AtomicU32, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
use parking_lot::RwLock;
|
||||
@@ -16,12 +16,12 @@ struct CommonChoiceData {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The user of the turn choice
|
||||
user: Arc<Pokemon>,
|
||||
user: Pokemon,
|
||||
/// The speed of the user at the beginning of the turn.
|
||||
speed: u32,
|
||||
speed: AtomicU32,
|
||||
/// This random value is set at the beginning of the turn. It is used for tie breaking of the
|
||||
/// turn order in a predictable way, regardless of implementation and hardware.
|
||||
random_value: u32,
|
||||
random_value: AtomicU32,
|
||||
/// Whether or not the choice has failed. A failed choice will stop running, and execute special
|
||||
/// fail handling during turn execution.
|
||||
has_failed: AtomicBool,
|
||||
@@ -57,32 +57,22 @@ impl TurnChoice {
|
||||
TurnChoice::Pass(data) => &data.choice_data,
|
||||
}
|
||||
}
|
||||
/// The shared choice data between each of the different turn choices.
|
||||
fn choice_data_mut(&mut self) -> &mut Box<CommonChoiceData> {
|
||||
match self {
|
||||
TurnChoice::Move(data) => &mut data.choice_data,
|
||||
TurnChoice::Item(data) => &mut data.choice_data,
|
||||
TurnChoice::Switch(data) => &mut data.choice_data,
|
||||
TurnChoice::Flee(data) => &mut data.choice_data,
|
||||
TurnChoice::Pass(data) => &mut data.choice_data,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the user of the given choice.
|
||||
pub fn user(&self) -> &Arc<Pokemon> {
|
||||
pub fn user(&self) -> &Pokemon {
|
||||
&self.choice_data().user
|
||||
}
|
||||
|
||||
/// Get the speed of the user for the choice. Note that this speed is the speed of the Pokemon
|
||||
/// at the start of the turn!
|
||||
pub fn speed(&self) -> u32 {
|
||||
self.choice_data().speed
|
||||
self.choice_data().speed.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
/// Get the mutable speed of the user for the choice. Note that this speed is the speed of the Pokemon
|
||||
/// at the start of the turn!
|
||||
pub fn speed_mut(&mut self) -> &mut u32 {
|
||||
&mut self.choice_data_mut().speed
|
||||
/// Sets the speed of user for the choice. Note that this speed is the speed of the Pokemon at
|
||||
/// the start of the turn!
|
||||
pub fn set_speed(&self, value: u32) {
|
||||
self.choice_data().speed.store(value, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
/// Gets whether or not the choice has failed. If we notice this when we execute the choice, we
|
||||
@@ -101,12 +91,12 @@ impl TurnChoice {
|
||||
/// breaking of turn executions. This means that choices get executed with a predictable order,
|
||||
/// regardless of implementation details.
|
||||
pub(crate) fn random_value(&self) -> u32 {
|
||||
self.choice_data().random_value
|
||||
self.choice_data().random_value.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
/// This sets the above random value.
|
||||
pub(crate) fn set_random_value(&mut self, val: u32) {
|
||||
self.choice_data_mut().random_value = val;
|
||||
pub(crate) fn set_random_value(&self, val: u32) {
|
||||
self.choice_data().random_value.store(val, Ordering::Relaxed)
|
||||
}
|
||||
|
||||
/// Helper function to get the move choice data from a turn. Note that this will panic if not
|
||||
@@ -174,26 +164,26 @@ pub struct MoveChoice {
|
||||
/// The move script.
|
||||
script: ScriptContainer,
|
||||
/// The priority of the move choice at the beginning of the turn.
|
||||
priority: i8,
|
||||
priority: AtomicI8,
|
||||
/// The common turn choice data.
|
||||
choice_data: Box<CommonChoiceData>,
|
||||
}
|
||||
|
||||
impl MoveChoice {
|
||||
/// Initializes the data for a new move choice.
|
||||
pub fn new(user: Arc<Pokemon>, used_move: Arc<LearnedMove>, target_side: u8, target_index: u8) -> Self {
|
||||
pub fn new(user: Pokemon, used_move: Arc<LearnedMove>, target_side: u8, target_index: u8) -> Self {
|
||||
let speed = user.boosted_stats().speed();
|
||||
Self {
|
||||
used_move,
|
||||
target_side,
|
||||
target_index,
|
||||
script: Default::default(),
|
||||
priority: 0,
|
||||
priority: AtomicI8::new(0),
|
||||
choice_data: Box::new(CommonChoiceData {
|
||||
identifier: Default::default(),
|
||||
user,
|
||||
speed,
|
||||
random_value: 0,
|
||||
speed: AtomicU32::new(speed),
|
||||
random_value: AtomicU32::new(0),
|
||||
has_failed: Default::default(),
|
||||
script_source_data: Default::default(),
|
||||
}),
|
||||
@@ -215,14 +205,14 @@ impl MoveChoice {
|
||||
}
|
||||
/// The priority of the move choice at the beginning of the turn.
|
||||
pub fn priority(&self) -> i8 {
|
||||
self.priority
|
||||
self.priority.load(Ordering::Relaxed)
|
||||
}
|
||||
/// The priority of the move choice at the beginning of the turn.
|
||||
pub fn priority_mut(&mut self) -> &mut i8 {
|
||||
&mut self.priority
|
||||
pub fn set_priority(&self, value: i8) {
|
||||
self.priority.store(value, Ordering::Relaxed)
|
||||
}
|
||||
/// The user of the choice.
|
||||
pub fn user(&self) -> &Arc<Pokemon> {
|
||||
pub fn user(&self) -> &Pokemon {
|
||||
&self.choice_data.user
|
||||
}
|
||||
/// The move script of the choice.
|
||||
@@ -259,14 +249,14 @@ pub struct ItemChoice {
|
||||
|
||||
impl ItemChoice {
|
||||
/// Initialised a new item choice.
|
||||
pub fn new(user: Arc<Pokemon>) -> Self {
|
||||
pub fn new(user: Pokemon) -> Self {
|
||||
let speed = user.boosted_stats().speed();
|
||||
Self {
|
||||
choice_data: Box::new(CommonChoiceData {
|
||||
identifier: Default::default(),
|
||||
user,
|
||||
speed,
|
||||
random_value: 0,
|
||||
speed: AtomicU32::new(speed),
|
||||
random_value: AtomicU32::new(0),
|
||||
has_failed: Default::default(),
|
||||
script_source_data: Default::default(),
|
||||
}),
|
||||
@@ -299,14 +289,14 @@ pub struct SwitchChoice {
|
||||
|
||||
impl SwitchChoice {
|
||||
/// Initialise the turn choice data.
|
||||
pub fn new(user: Arc<Pokemon>) -> Self {
|
||||
pub fn new(user: Pokemon) -> Self {
|
||||
let speed = user.boosted_stats().speed();
|
||||
Self {
|
||||
choice_data: Box::new(CommonChoiceData {
|
||||
identifier: Default::default(),
|
||||
user,
|
||||
speed,
|
||||
random_value: 0,
|
||||
speed: AtomicU32::new(speed),
|
||||
random_value: AtomicU32::new(0),
|
||||
has_failed: Default::default(),
|
||||
script_source_data: Default::default(),
|
||||
}),
|
||||
@@ -339,13 +329,13 @@ pub struct FleeChoice {
|
||||
|
||||
impl FleeChoice {
|
||||
/// Initialises a new flee choice.
|
||||
pub fn new(user: Arc<Pokemon>) -> Self {
|
||||
pub fn new(user: Pokemon) -> Self {
|
||||
Self {
|
||||
choice_data: Box::new(CommonChoiceData {
|
||||
identifier: Default::default(),
|
||||
user,
|
||||
speed: 0,
|
||||
random_value: 0,
|
||||
speed: AtomicU32::new(0),
|
||||
random_value: AtomicU32::new(0),
|
||||
has_failed: Default::default(),
|
||||
script_source_data: Default::default(),
|
||||
}),
|
||||
@@ -378,14 +368,14 @@ pub struct PassChoice {
|
||||
|
||||
impl PassChoice {
|
||||
/// Initialised a new pass choice.
|
||||
pub fn new(user: Arc<Pokemon>) -> Self {
|
||||
pub fn new(user: Pokemon) -> Self {
|
||||
let speed = user.boosted_stats().speed();
|
||||
Self {
|
||||
choice_data: Box::new(CommonChoiceData {
|
||||
identifier: Default::default(),
|
||||
user,
|
||||
speed,
|
||||
random_value: 0,
|
||||
speed: AtomicU32::new(speed),
|
||||
random_value: AtomicU32::new(0),
|
||||
has_failed: Default::default(),
|
||||
script_source_data: Default::default(),
|
||||
}),
|
||||
@@ -428,7 +418,10 @@ impl Ord for TurnChoice {
|
||||
match self {
|
||||
TurnChoice::Move(data) => {
|
||||
if let TurnChoice::Move(other_data) = other {
|
||||
let priority_compare = data.priority.cmp(&other_data.priority);
|
||||
let priority_compare = data
|
||||
.priority
|
||||
.load(Ordering::Relaxed)
|
||||
.cmp(&other_data.priority.load(Ordering::Relaxed));
|
||||
if priority_compare != std::cmp::Ordering::Equal {
|
||||
return priority_compare;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user