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

This commit is contained in:
2023-06-22 15:43:41 +02:00
parent 6a2353df4c
commit 46195d3042
71 changed files with 2142 additions and 1488 deletions

View File

@@ -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;
}