Remove lifetime mess, replace a lot of code with Arc instead of borrows.
continuous-integration/drone/push Build is failing Details

This cleans up the codebase massively, and allows me to maintain some semblance of sanity.
This commit is contained in:
Deukhoofd 2022-08-20 13:17:20 +02:00
parent 2d4253e155
commit 55cc0906c9
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
34 changed files with 320 additions and 366 deletions

View File

@ -10,9 +10,9 @@ use crate::dynamic_data::{ScriptSource, ScriptSourceData};
/// The data on a turn choice that should be contained in every turn choice, regardless of type. /// The data on a turn choice that should be contained in every turn choice, regardless of type.
#[derive(Debug)] #[derive(Debug)]
struct CommonChoiceData<'user, 'library> { struct CommonChoiceData {
/// The user of the turn choice /// The user of the turn choice
user: Arc<Pokemon<'user, 'library>>, user: Arc<Pokemon>,
/// The speed of the user at the beginning of the turn. /// The speed of the user at the beginning of the turn.
speed: u32, speed: u32,
/// This random value is set at the beginning of the turn. It is used for tie breaking of the /// This random value is set at the beginning of the turn. It is used for tie breaking of the
@ -30,22 +30,22 @@ struct CommonChoiceData<'user, 'library> {
/// This enum defines a single choice for a Pokemon for a battle turn. /// This enum defines a single choice for a Pokemon for a battle turn.
#[derive(Debug)] #[derive(Debug)]
#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] #[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))]
pub enum TurnChoice<'user, 'library> { pub enum TurnChoice {
/// A move choice tells a Pokemon to use a move on a target for this turn. /// A move choice tells a Pokemon to use a move on a target for this turn.
Move(MoveChoice<'user, 'library>), Move(MoveChoice),
/// An item choice tells a Pokemon to use an item. /// An item choice tells a Pokemon to use an item.
Item(ItemChoice<'user, 'library>), Item(ItemChoice),
/// A switch choice tells a Pokemon to switch with another Pokemon from the party. /// A switch choice tells a Pokemon to switch with another Pokemon from the party.
Switch(SwitchChoice<'user, 'library>), Switch(SwitchChoice),
/// A flee choice tells a Pokemon to flee from battle. /// A flee choice tells a Pokemon to flee from battle.
Flee(FleeChoice<'user, 'library>), Flee(FleeChoice),
/// A pass choice tells the user to do nothing that turn. /// A pass choice tells the user to do nothing that turn.
Pass(PassChoice<'user, 'library>), Pass(PassChoice),
} }
impl<'user, 'library> TurnChoice<'user, 'library> { impl TurnChoice {
/// The shared choice data between each of the different turn choices. /// The shared choice data between each of the different turn choices.
fn choice_data(&self) -> &CommonChoiceData<'user, 'library> { fn choice_data(&self) -> &CommonChoiceData {
match self { match self {
TurnChoice::Move(data) => &data.choice_data, TurnChoice::Move(data) => &data.choice_data,
TurnChoice::Item(data) => &data.choice_data, TurnChoice::Item(data) => &data.choice_data,
@ -55,7 +55,7 @@ impl<'user, 'library> TurnChoice<'user, 'library> {
} }
} }
/// The shared choice data between each of the different turn choices. /// The shared choice data between each of the different turn choices.
fn choice_data_mut(&mut self) -> &mut Box<CommonChoiceData<'user, 'library>> { fn choice_data_mut(&mut self) -> &mut Box<CommonChoiceData> {
match self { match self {
TurnChoice::Move(data) => &mut data.choice_data, TurnChoice::Move(data) => &mut data.choice_data,
TurnChoice::Item(data) => &mut data.choice_data, TurnChoice::Item(data) => &mut data.choice_data,
@ -66,7 +66,7 @@ impl<'user, 'library> TurnChoice<'user, 'library> {
} }
/// Get the user of the given choice. /// Get the user of the given choice.
pub fn user(&self) -> &Arc<Pokemon<'user, 'library>> { pub fn user(&self) -> &Arc<Pokemon> {
&self.choice_data().user &self.choice_data().user
} }
@ -108,7 +108,7 @@ impl<'user, 'library> TurnChoice<'user, 'library> {
/// Helper function to get the move choice data from a turn. Note that this will panic if not /// Helper function to get the move choice data from a turn. Note that this will panic if not
/// used on a move choice. /// used on a move choice.
pub(crate) fn get_move_turn_data<'b>(&'b self) -> &'b MoveChoice<'user, 'library> { pub(crate) fn get_move_turn_data(&self) -> &MoveChoice {
if let TurnChoice::Move(data) = self { if let TurnChoice::Move(data) = self {
return data; return data;
} }
@ -116,7 +116,7 @@ impl<'user, 'library> TurnChoice<'user, 'library> {
} }
} }
impl<'user, 'library> ScriptSource<'user> for TurnChoice<'user, 'library> { impl ScriptSource for TurnChoice {
fn get_script_count(&self) -> usize { fn get_script_count(&self) -> usize {
match self { match self {
TurnChoice::Move(data) => data.get_script_count(), TurnChoice::Move(data) => data.get_script_count(),
@ -160,9 +160,9 @@ impl<'user, 'library> ScriptSource<'user> for TurnChoice<'user, 'library> {
/// The data attached to a move choice. /// The data attached to a move choice.
#[derive(Debug)] #[derive(Debug)]
pub struct MoveChoice<'user, 'library> { pub struct MoveChoice {
/// The move that is used for this choice. /// The move that is used for this choice.
used_move: Arc<LearnedMove<'library>>, used_move: Arc<LearnedMove>,
/// The side this move is aimed at. /// The side this move is aimed at.
target_side: u8, target_side: u8,
/// The index of the Pokemon on the side we're aiming at. /// The index of the Pokemon on the side we're aiming at.
@ -172,17 +172,12 @@ pub struct MoveChoice<'user, 'library> {
/// The priority of the move choice at the beginning of the turn. /// The priority of the move choice at the beginning of the turn.
priority: i8, priority: i8,
/// The common turn choice data. /// The common turn choice data.
choice_data: Box<CommonChoiceData<'user, 'library>>, choice_data: Box<CommonChoiceData>,
} }
impl<'user, 'library> MoveChoice<'user, 'library> { impl<'user, 'library> MoveChoice {
/// Initializes the data for a new move choice. /// Initializes the data for a new move choice.
pub fn new( pub fn new(user: Arc<Pokemon>, used_move: Arc<LearnedMove>, target_side: u8, target_index: u8) -> Self {
user: Arc<Pokemon<'user, 'library>>,
used_move: Arc<LearnedMove<'library>>,
target_side: u8,
target_index: u8,
) -> Self {
Self { Self {
used_move, used_move,
target_side, target_side,
@ -200,7 +195,7 @@ impl<'user, 'library> MoveChoice<'user, 'library> {
} }
/// The actual learned move on the Pokemon we use for this choice. /// The actual learned move on the Pokemon we use for this choice.
pub fn used_move(&self) -> &Arc<LearnedMove<'library>> { pub fn used_move(&self) -> &Arc<LearnedMove> {
&self.used_move &self.used_move
} }
@ -221,7 +216,7 @@ impl<'user, 'library> MoveChoice<'user, 'library> {
&mut self.priority &mut self.priority
} }
/// The user of the choice. /// The user of the choice.
pub fn user(&self) -> &Arc<Pokemon<'user, 'library>> { pub fn user(&self) -> &Arc<Pokemon> {
&self.choice_data.user &self.choice_data.user
} }
/// The move script of the choice. /// The move script of the choice.
@ -230,7 +225,7 @@ impl<'user, 'library> MoveChoice<'user, 'library> {
} }
} }
impl<'user, 'library> ScriptSource<'user> for MoveChoice<'user, 'library> { impl ScriptSource for MoveChoice {
fn get_script_count(&self) -> usize { fn get_script_count(&self) -> usize {
1 + self.choice_data.user.get_script_count() 1 + self.choice_data.user.get_script_count()
} }
@ -251,14 +246,14 @@ impl<'user, 'library> ScriptSource<'user> for MoveChoice<'user, 'library> {
/// The data given when we select an item choice. /// The data given when we select an item choice.
#[derive(Debug)] #[derive(Debug)]
pub struct ItemChoice<'user, 'library> { pub struct ItemChoice {
/// The shared data of all turn choices. /// The shared data of all turn choices.
choice_data: Box<CommonChoiceData<'user, 'library>>, choice_data: Box<CommonChoiceData>,
} }
impl<'user, 'library> ItemChoice<'user, 'library> { impl ItemChoice {
/// Initialised a new item choice. /// Initialised a new item choice.
pub fn new(user: Arc<Pokemon<'user, 'library>>) -> Self { pub fn new(user: Arc<Pokemon>) -> Self {
Self { Self {
choice_data: Box::new(CommonChoiceData { choice_data: Box::new(CommonChoiceData {
user, user,
@ -271,7 +266,7 @@ impl<'user, 'library> ItemChoice<'user, 'library> {
} }
} }
impl<'user, 'library> ScriptSource<'user> for ItemChoice<'user, 'library> { impl ScriptSource for ItemChoice {
fn get_script_count(&self) -> usize { fn get_script_count(&self) -> usize {
0 0
} }
@ -289,14 +284,14 @@ impl<'user, 'library> ScriptSource<'user> for ItemChoice<'user, 'library> {
/// The data given when we select a switch choice. /// The data given when we select a switch choice.
#[derive(Debug)] #[derive(Debug)]
pub struct SwitchChoice<'user, 'library> { pub struct SwitchChoice {
/// The shared data of all turn choices. /// The shared data of all turn choices.
choice_data: Box<CommonChoiceData<'user, 'library>>, choice_data: Box<CommonChoiceData>,
} }
impl<'user, 'library> SwitchChoice<'user, 'library> { impl SwitchChoice {
/// Initialise the turn choice data. /// Initialise the turn choice data.
pub fn new(user: Arc<Pokemon<'user, 'library>>) -> Self { pub fn new(user: Arc<Pokemon>) -> Self {
Self { Self {
choice_data: Box::new(CommonChoiceData { choice_data: Box::new(CommonChoiceData {
user, user,
@ -309,7 +304,7 @@ impl<'user, 'library> SwitchChoice<'user, 'library> {
} }
} }
impl<'user, 'library> ScriptSource<'user> for SwitchChoice<'user, 'library> { impl ScriptSource for SwitchChoice {
fn get_script_count(&self) -> usize { fn get_script_count(&self) -> usize {
0 0
} }
@ -327,14 +322,14 @@ impl<'user, 'library> ScriptSource<'user> for SwitchChoice<'user, 'library> {
/// The data given when we select a flee choice. /// The data given when we select a flee choice.
#[derive(Debug)] #[derive(Debug)]
pub struct FleeChoice<'user, 'library> { pub struct FleeChoice {
/// The common data all turn choices share. /// The common data all turn choices share.
choice_data: Box<CommonChoiceData<'user, 'library>>, choice_data: Box<CommonChoiceData>,
} }
impl<'user, 'library> FleeChoice<'user, 'library> { impl FleeChoice {
/// Initialises a new flee choice. /// Initialises a new flee choice.
pub fn new(user: Arc<Pokemon<'user, 'library>>) -> Self { pub fn new(user: Arc<Pokemon>) -> Self {
Self { Self {
choice_data: Box::new(CommonChoiceData { choice_data: Box::new(CommonChoiceData {
user, user,
@ -347,7 +342,7 @@ impl<'user, 'library> FleeChoice<'user, 'library> {
} }
} }
impl<'user, 'library> ScriptSource<'user> for FleeChoice<'user, 'library> { impl ScriptSource for FleeChoice {
fn get_script_count(&self) -> usize { fn get_script_count(&self) -> usize {
0 0
} }
@ -365,14 +360,14 @@ impl<'user, 'library> ScriptSource<'user> for FleeChoice<'user, 'library> {
/// The data given when we select a pass choice. /// The data given when we select a pass choice.
#[derive(Debug)] #[derive(Debug)]
pub struct PassChoice<'user, 'library> { pub struct PassChoice {
/// The common data of all turn choices. /// The common data of all turn choices.
choice_data: Box<CommonChoiceData<'user, 'library>>, choice_data: Box<CommonChoiceData>,
} }
impl<'user, 'library> PassChoice<'user, 'library> { impl PassChoice {
/// Initialised a new pass choice. /// Initialised a new pass choice.
pub fn new(user: Arc<Pokemon<'user, 'library>>) -> Self { pub fn new(user: Arc<Pokemon>) -> Self {
Self { Self {
choice_data: Box::new(CommonChoiceData { choice_data: Box::new(CommonChoiceData {
user, user,
@ -385,7 +380,7 @@ impl<'user, 'library> PassChoice<'user, 'library> {
} }
} }
impl<'user, 'library> ScriptSource<'user> for PassChoice<'user, 'library> { impl ScriptSource for PassChoice {
fn get_script_count(&self) -> usize { fn get_script_count(&self) -> usize {
0 0
} }
@ -401,21 +396,21 @@ impl<'user, 'library> ScriptSource<'user> for PassChoice<'user, 'library> {
} }
} }
impl<'user, 'library> PartialEq<Self> for TurnChoice<'user, 'library> { impl PartialEq<Self> for TurnChoice {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
std::ptr::eq(self, other) std::ptr::eq(self, other)
} }
} }
impl<'user, 'library> Eq for TurnChoice<'user, 'library> {} impl Eq for TurnChoice {}
impl<'user, 'library> PartialOrd for TurnChoice<'user, 'library> { impl PartialOrd for TurnChoice {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other)) Some(self.cmp(other))
} }
} }
impl<'user, 'library> Ord for TurnChoice<'user, 'library> { impl Ord for TurnChoice {
fn cmp(&self, other: &Self) -> Ordering { fn cmp(&self, other: &Self) -> Ordering {
match self { match self {
TurnChoice::Move(data) => { TurnChoice::Move(data) => {

View File

@ -1,4 +1,5 @@
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
use std::sync::Arc;
use crate::dynamic_data::DamageSource; use crate::dynamic_data::DamageSource;
use crate::dynamic_data::ExecutingMove; use crate::dynamic_data::ExecutingMove;
@ -27,7 +28,7 @@ impl<'battle, 'library> EventHook {
/// Run a new event. This will send the event to all externally defined event listeners. It will /// Run a new event. This will send the event to all externally defined event listeners. It will
/// dispose of the event afterwards. /// dispose of the event afterwards.
pub fn trigger<'b>(&self, evt: Event<'b, 'battle, 'library>) { pub fn trigger(&self, evt: Event) {
let b = Box::new(&evt); let b = Box::new(&evt);
for f in &self.evt_hook_function { for f in &self.evt_hook_function {
f(&b); f(&b);
@ -43,7 +44,7 @@ impl Debug for EventHook {
/// The different events that can occur during the battle, for which a GUI should show something. /// The different events that can occur during the battle, for which a GUI should show something.
#[derive(Debug)] #[derive(Debug)]
pub enum Event<'own, 'battle, 'library> { pub enum Event<'own> {
/// A switch event happens when a Pokemon gets switched out for something else. /// A switch event happens when a Pokemon gets switched out for something else.
Switch { Switch {
/// The side the Pokemon got switched from/on /// The side the Pokemon got switched from/on
@ -51,7 +52,7 @@ pub enum Event<'own, 'battle, 'library> {
/// The index of the Pokemon that got switched in/out on its side /// The index of the Pokemon that got switched in/out on its side
index: u8, index: u8,
/// The new Pokemon that will be on the spot. If none, the spot will now be empty. /// The new Pokemon that will be on the spot. If none, the spot will now be empty.
pokemon: Option<&'own Pokemon<'battle, 'library>>, pokemon: Option<&'own Pokemon>,
}, },
/// A swap event happens when two Pokemon on a side swap positions. Note that this is rare. /// A swap event happens when two Pokemon on a side swap positions. Note that this is rare.
Swap { Swap {
@ -67,23 +68,23 @@ pub enum Event<'own, 'battle, 'library> {
/// enjoy. /// enjoy.
SpeciesChange { SpeciesChange {
/// The pokemon that changed species. /// The pokemon that changed species.
pokemon: &'own Pokemon<'battle, 'library>, pokemon: &'own Pokemon,
/// The new species of the Pokemon. /// The new species of the Pokemon.
species: &'own Species, species: Arc<Species>,
/// The form of the species the Pokemon will have. /// The form of the species the Pokemon will have.
form: &'own Form, form: Arc<Form>,
}, },
/// This event happens when a Pokemon changes form during battle. This is rather common. /// This event happens when a Pokemon changes form during battle. This is rather common.
FormChange { FormChange {
/// The pokemon that changed forms. /// The pokemon that changed forms.
pokemon: &'own Pokemon<'battle, 'library>, pokemon: &'own Pokemon,
/// The new form of the Pokemon. /// The new form of the Pokemon.
form: &'own Form, form: &'own Form,
}, },
/// This event happens when a Pokemon takes damage. /// This event happens when a Pokemon takes damage.
Damage { Damage {
/// The Pokemon that takes damage. /// The Pokemon that takes damage.
pokemon: &'own Pokemon<'battle, 'library>, pokemon: &'own Pokemon,
/// The source of damage. /// The source of damage.
source: DamageSource, source: DamageSource,
/// The health of the Pokemon before the damage. /// The health of the Pokemon before the damage.
@ -94,7 +95,7 @@ pub enum Event<'own, 'battle, 'library> {
/// This event happens when a Pokemon gets healed /// This event happens when a Pokemon gets healed
Heal { Heal {
/// The Pokemon that gets healed. /// The Pokemon that gets healed.
pokemon: &'own Pokemon<'battle, 'library>, pokemon: &'own Pokemon,
/// The health of the Pokemon before the heal. /// The health of the Pokemon before the heal.
original_health: u32, original_health: u32,
/// The health of the Pokemon after the heal. /// The health of the Pokemon after the heal.
@ -103,24 +104,24 @@ pub enum Event<'own, 'battle, 'library> {
/// This event happens when a Pokemon faints. /// This event happens when a Pokemon faints.
Faint { Faint {
/// The pokemon that has fainted. /// The pokemon that has fainted.
pokemon: &'own Pokemon<'battle, 'library>, pokemon: &'own Pokemon,
}, },
/// This event happens when a Pokemon uses a move on a target, just before any hits. /// This event happens when a Pokemon uses a move on a target, just before any hits.
MoveUse { MoveUse {
/// The data of the move used. /// The data of the move used.
executing_move: &'own ExecutingMove<'own, 'battle, 'library>, executing_move: &'own ExecutingMove,
}, },
/// This event happens when a Pokemon missed. /// This event happens when a Pokemon missed.
Miss { Miss {
/// The pokemon that missed. /// The pokemon that missed.
user: &'own Pokemon<'battle, 'library>, user: &'own Pokemon,
}, },
/// The turn is finished running, waiting for new input. /// The turn is finished running, waiting for new input.
EndTurn, EndTurn,
/// A pokemon had its stat boost changed /// A pokemon had its stat boost changed
StatBoostChange { StatBoostChange {
/// The pokemon that had its stat boosts changed. /// The pokemon that had its stat boosts changed.
user: &'own Pokemon<'battle, 'library>, user: &'own Pokemon,
/// The statistic that changed. /// The statistic that changed.
stat: Statistic, stat: Statistic,
/// The value of the stat before the change. /// The value of the stat before the change.

View File

@ -8,31 +8,31 @@ use crate::dynamic_data::Pokemon;
/// helper functions to change the turn order while doing the execution. This is needed, as several /// helper functions to change the turn order while doing the execution. This is needed, as several
/// moves in Pokemon actively mess with this order. /// moves in Pokemon actively mess with this order.
#[derive(Debug)] #[derive(Debug)]
pub struct ChoiceQueue<'battle, 'library> { pub struct ChoiceQueue {
/// Our storage of turn choices. Starts out completely filled, then slowly empties as turns get /// Our storage of turn choices. Starts out completely filled, then slowly empties as turns get
/// executed. /// executed.
queue: Vec<Option<TurnChoice<'battle, 'library>>>, queue: Vec<Option<TurnChoice>>,
/// The current index of the turn we need to execute next. /// The current index of the turn we need to execute next.
current: usize, current: usize,
} }
impl<'battle, 'library> ChoiceQueue<'battle, 'library> { impl ChoiceQueue {
/// Initializes a ChoiceQueue. We expect the given queue to already be sorted here. /// Initializes a ChoiceQueue. We expect the given queue to already be sorted here.
pub(crate) fn new(queue: Vec<Option<TurnChoice<'battle, 'library>>>) -> Self { pub(crate) fn new(queue: Vec<Option<TurnChoice>>) -> Self {
Self { queue, current: 0 } Self { queue, current: 0 }
} }
/// Dequeues the next turn choice to be executed. This gives ownership to the callee, and replaces /// Dequeues the next turn choice to be executed. This gives ownership to the callee, and replaces
/// our own reference to the turn choice with an empty spot. It also increments the current position /// our own reference to the turn choice with an empty spot. It also increments the current position
/// by one. /// by one.
pub fn dequeue<'b>(&'b mut self) -> TurnChoice<'battle, 'library> { pub fn dequeue<'b>(&'b mut self) -> TurnChoice {
let c = self.queue[self.current].take(); let c = self.queue[self.current].take();
self.current += 1; self.current += 1;
c.unwrap() c.unwrap()
} }
/// This reads what the next choice to execute will be, without modifying state. /// This reads what the next choice to execute will be, without modifying state.
pub fn peek(&self) -> &'battle TurnChoice { pub fn peek(&self) -> &TurnChoice {
self.queue[self.current].as_ref().unwrap() self.queue[self.current].as_ref().unwrap()
} }
@ -55,7 +55,7 @@ impl<'battle, 'library> ChoiceQueue<'battle, 'library> {
} }
/// Internal helper function to be easily able to iterate over the yet to be executed choices. /// Internal helper function to be easily able to iterate over the yet to be executed choices.
pub(crate) fn get_queue(&self) -> &[Option<TurnChoice<'battle, 'library>>] { pub(crate) fn get_queue(&self) -> &[Option<TurnChoice>] {
&self.queue[self.current..self.queue.len()] &self.queue[self.current..self.queue.len()]
} }
} }

View File

@ -8,10 +8,10 @@ use crate::dynamic_data::Pokemon;
use crate::static_data::MoveTarget; use crate::static_data::MoveTarget;
/// Helper type for the vector of targets we will return. /// Helper type for the vector of targets we will return.
pub type TargetList<'own, 'library> = Vec<Option<Arc<Pokemon<'own, 'library>>>>; pub type TargetList = Vec<Option<Arc<Pokemon>>>;
/// This returns all Pokemon in the battle. /// This returns all Pokemon in the battle.
fn get_all_targets<'b, 'library>(battle: &Battle<'b, 'library>) -> TargetList<'b, 'library> { fn get_all_targets<'b, 'library>(battle: &Battle) -> TargetList {
let mut v = Vec::with_capacity(battle.pokemon_per_side() as usize * battle.number_of_sides() as usize); let mut v = Vec::with_capacity(battle.pokemon_per_side() as usize * battle.number_of_sides() as usize);
for side in battle.sides() { for side in battle.sides() {
for pokemon in side.pokemon().deref() { for pokemon in side.pokemon().deref() {
@ -31,11 +31,7 @@ fn get_opposite_side(side: u8) -> u8 {
/// Gets all Pokemon that are adjacent to of directly opposite of a Pokemon. This means the target, /// Gets all Pokemon that are adjacent to of directly opposite of a Pokemon. This means the target,
/// the Pokemon left of it, the Pokemon right of it, and the Pokemon opposite of it. /// the Pokemon left of it, the Pokemon right of it, and the Pokemon opposite of it.
fn get_all_adjacent_opponent<'b, 'library>( fn get_all_adjacent_opponent<'b, 'library>(side: u8, index: u8, battle: &Battle) -> TargetList {
side: u8,
index: u8,
battle: &Battle<'b, 'library>,
) -> TargetList<'b, 'library> {
let left = index as i32 - 1; let left = index as i32 - 1;
let right = index + 1; let right = index + 1;
if left < 0 && right >= battle.pokemon_per_side() { if left < 0 && right >= battle.pokemon_per_side() {
@ -80,7 +76,7 @@ fn get_all_adjacent_opponent<'b, 'library>(
/// Gets all Pokemon that are adjacent to a Pokemon. This includes the target, the Pokemon to the /// Gets all Pokemon that are adjacent to a Pokemon. This includes the target, the Pokemon to the
/// left of it, and the Pokemon to the right of it. /// left of it, and the Pokemon to the right of it.
fn get_all_adjacent<'b, 'library>(side: u8, index: u8, battle: &Battle<'b, 'library>) -> TargetList<'b, 'library> { fn get_all_adjacent<'b, 'library>(side: u8, index: u8, battle: &Battle) -> TargetList {
let left = index as i32 - 1; let left = index as i32 - 1;
let right = index + 1; let right = index + 1;
if left < 0 && right >= battle.pokemon_per_side() { if left < 0 && right >= battle.pokemon_per_side() {
@ -106,12 +102,7 @@ fn get_all_adjacent<'b, 'library>(side: u8, index: u8, battle: &Battle<'b, 'libr
} }
/// Gets the target for a specific move target type, given the targeted position. /// Gets the target for a specific move target type, given the targeted position.
pub fn resolve_targets<'b, 'library>( pub fn resolve_targets<'b, 'library>(side: u8, index: u8, target: MoveTarget, battle: &Battle) -> TargetList {
side: u8,
index: u8,
target: MoveTarget,
battle: &Battle<'b, 'library>,
) -> TargetList<'b, 'library> {
match target { match target {
// These all resolve to a single position. We let the client deal with where the target is, // These all resolve to a single position. We let the client deal with where the target is,
// and just return the Pokemon at that given target here. // and just return the Pokemon at that given target here.

View File

@ -12,7 +12,7 @@ use crate::dynamic_data::Pokemon;
use crate::static_data::{DataLibrary, MoveCategory}; use crate::static_data::{DataLibrary, MoveCategory};
use crate::{run_scripts, script_hook, PkmnResult}; use crate::{run_scripts, script_hook, PkmnResult};
impl<'own, 'library> Battle<'own, 'library> { impl Battle {
/// Execute the entire turn after the choices are all set. /// Execute the entire turn after the choices are all set.
pub(crate) fn run_turn(&self) -> PkmnResult<()> { pub(crate) fn run_turn(&self) -> PkmnResult<()> {
let choice_queue = self.current_turn_queue(); let choice_queue = self.current_turn_queue();
@ -62,7 +62,7 @@ impl<'own, 'library> Battle<'own, 'library> {
} }
/// Executes a single choice. /// Executes a single choice.
fn execute_choice(&self, choice: &TurnChoice<'own, 'library>) -> PkmnResult<()> { fn execute_choice(&self, choice: &TurnChoice) -> PkmnResult<()> {
// A pass turn choice means the user does not intend to do anything. As such, return. // A pass turn choice means the user does not intend to do anything. As such, return.
if let TurnChoice::Pass(..) = choice { if let TurnChoice::Pass(..) = choice {
return Ok(()); return Ok(());
@ -91,7 +91,7 @@ impl<'own, 'library> Battle<'own, 'library> {
} }
/// Executes a move choice. /// Executes a move choice.
fn execute_move_choice<'func>(&'func self, choice: &'func TurnChoice<'own, 'library>) -> PkmnResult<()> { fn execute_move_choice<'func>(&'func self, choice: &'func TurnChoice) -> PkmnResult<()> {
let choice = choice.get_move_turn_data(); let choice = choice.get_move_turn_data();
let used_move = choice.used_move(); let used_move = choice.used_move();
let move_data = { let move_data = {
@ -111,11 +111,11 @@ impl<'own, 'library> Battle<'own, 'library> {
return Ok(()); return Ok(());
} }
let mut executing_move = ExecutingMove::new( let mut executing_move = ExecutingMove::new(
&targets, targets.clone(),
number_of_hits, number_of_hits,
choice.user().clone(), choice.user().clone(),
used_move.clone(), used_move.clone(),
move_data, move_data.clone(),
choice.script().clone(), choice.script().clone(),
); );
let mut prevented = false; let mut prevented = false;
@ -148,11 +148,7 @@ impl<'own, 'library> Battle<'own, 'library> {
} }
/// Executes a move turn choice on a single target. /// Executes a move turn choice on a single target.
fn handle_move_for_target( fn handle_move_for_target(&self, executing_move: &mut ExecutingMove, target: &Arc<Pokemon>) -> PkmnResult<()> {
&self,
executing_move: &mut ExecutingMove<'_, 'own, 'library>,
target: &Arc<Pokemon<'own, 'library>>,
) -> PkmnResult<()> {
{ {
let mut fail = false; let mut fail = false;
script_hook!(fail_incoming_move, target, executing_move, target, &mut fail); script_hook!(fail_incoming_move, target, executing_move, target, &mut fail);

View File

@ -25,7 +25,7 @@ pub struct DynamicLibrary {
damage_calculator: Box<dyn DamageLibrary>, damage_calculator: Box<dyn DamageLibrary>,
/// The Misc Library holds minor functions that do not fall in any of the other libraries and /// The Misc Library holds minor functions that do not fall in any of the other libraries and
/// calculators. /// calculators.
misc_library: Box<dyn MiscLibrary<'static>>, misc_library: Box<dyn MiscLibrary>,
/// The script resolver deals with how to resolve the scripts from specific unique key combinations. /// The script resolver deals with how to resolve the scripts from specific unique key combinations.
script_resolver: Box<dyn ScriptResolver>, script_resolver: Box<dyn ScriptResolver>,
@ -40,7 +40,7 @@ impl DynamicLibrary {
static_data: StaticData, static_data: StaticData,
stat_calculator: Box<dyn BattleStatCalculator>, stat_calculator: Box<dyn BattleStatCalculator>,
damage_calculator: Box<dyn DamageLibrary>, damage_calculator: Box<dyn DamageLibrary>,
misc_library: Box<dyn MiscLibrary<'static>>, misc_library: Box<dyn MiscLibrary>,
script_resolver: Box<dyn ScriptResolver>, script_resolver: Box<dyn ScriptResolver>,
) -> Self { ) -> Self {
Self { Self {
@ -67,7 +67,7 @@ impl DynamicLibrary {
} }
/// The Misc Library holds minor functions that do not fall in any of the other libraries and /// The Misc Library holds minor functions that do not fall in any of the other libraries and
/// calculators. /// calculators.
pub fn misc_library(&self) -> &dyn MiscLibrary<'static> { pub fn misc_library(&self) -> &dyn MiscLibrary {
self.misc_library.deref() self.misc_library.deref()
} }
@ -84,7 +84,7 @@ impl DynamicLibrary {
/// Loads an item script with the given unique key. If no script can be created with this /// Loads an item script with the given unique key. If no script can be created with this
/// combinations, returns None. Note that ItemScripts are immutable, as their script should be /// combinations, returns None. Note that ItemScripts are immutable, as their script should be
/// shared between all different usages. /// shared between all different usages.
pub fn load_item_script(&self, _key: &Item) -> PkmnResult<Option<Arc<dyn ItemScript>>> { pub fn load_item_script(&self, _key: &Arc<Item>) -> PkmnResult<Option<Arc<dyn ItemScript>>> {
todo!() todo!()
} }
} }

View File

@ -10,35 +10,26 @@ use crate::static_data::{MoveCategory, MoveData, MoveTarget, SecondaryEffect};
use crate::StringKey; use crate::StringKey;
/// The misc library holds several misc functions required for the battle to run. /// The misc library holds several misc functions required for the battle to run.
pub trait MiscLibrary<'library>: Debug { pub trait MiscLibrary: Debug {
/// Returns whether or not a Pokemon is allowed to flee or switch out. /// Returns whether or not a Pokemon is allowed to flee or switch out.
fn can_flee(&self, choice: &TurnChoice) -> bool; fn can_flee(&self, choice: &TurnChoice) -> bool;
/// Returns the move we need to use if we can't use another move. Typically Struggle. /// Returns the move we need to use if we can't use another move. Typically Struggle.
fn replacement_move<'func>( fn replacement_move<'func>(&'func self, user: &Arc<Pokemon>, target_side: u8, target_index: u8) -> TurnChoice;
&'func self,
user: &Arc<Pokemon<'func, 'library>>,
target_side: u8,
target_index: u8,
) -> TurnChoice<'func, 'library>;
// TODO: can evolve from level up? // TODO: can evolve from level up?
// TODO: get time // TODO: get time
} }
/// A gen 7 implementation for the MiscLibrary. /// A gen 7 implementation for the MiscLibrary.
#[derive(Debug)] #[derive(Debug)]
pub struct Gen7MiscLibrary<'library> { pub struct Gen7MiscLibrary {
/// The move data for struggle. This is a pointer due to lifetime issues; we know that the
/// learned move based on this has the same lifetime as the move data, but the compiler does not.
/// If possible in a sane manner, we should get rid of this pointer.
struggle_data: *const MoveData,
/// The learned move data for struggle. /// The learned move data for struggle.
struggle_learned_move: Arc<LearnedMove<'library>>, struggle_learned_move: Arc<LearnedMove>,
} }
impl<'library> Gen7MiscLibrary<'library> { impl Gen7MiscLibrary {
/// Instantiates a new MiscLibrary. /// Instantiates a new MiscLibrary.
pub fn new() -> Self { pub fn new() -> Self {
let struggle_data = Box::new(MoveData::new( let struggle_data = Arc::new(MoveData::new(
&StringKey::new("struggle"), &StringKey::new("struggle"),
0.into(), 0.into(),
MoveCategory::Physical, MoveCategory::Physical,
@ -50,40 +41,23 @@ impl<'library> Gen7MiscLibrary<'library> {
Some(SecondaryEffect::new(-1.0, StringKey::new("struggle"), vec![])), Some(SecondaryEffect::new(-1.0, StringKey::new("struggle"), vec![])),
HashSet::new(), HashSet::new(),
)); ));
let struggle_ptr = Box::into_raw(struggle_data); let struggle_learned_move = Arc::new(LearnedMove::new(&struggle_data.clone(), MoveLearnMethod::Unknown));
let struggle_learned_move = Arc::new(LearnedMove::new(unsafe { &*struggle_ptr }, MoveLearnMethod::Unknown)); Self { struggle_learned_move }
Self {
struggle_data: struggle_ptr,
struggle_learned_move,
}
} }
} }
impl<'library> Default for Gen7MiscLibrary<'library> { impl Default for Gen7MiscLibrary {
fn default() -> Self { fn default() -> Self {
Self::new() Self::new()
} }
} }
impl<'library> Drop for Gen7MiscLibrary<'library> { impl MiscLibrary for Gen7MiscLibrary {
fn drop(&mut self) {
unsafe {
let _ = Box::from_raw(self.struggle_data as *mut MoveData);
}
}
}
impl<'library> MiscLibrary<'library> for Gen7MiscLibrary<'library> {
fn can_flee(&self, _choice: &TurnChoice) -> bool { fn can_flee(&self, _choice: &TurnChoice) -> bool {
todo!() todo!()
} }
fn replacement_move<'func>( fn replacement_move<'func>(&'func self, user: &Arc<Pokemon>, target_side: u8, target_index: u8) -> TurnChoice {
&'func self,
user: &Arc<Pokemon<'func, 'library>>,
target_side: u8,
target_index: u8,
) -> TurnChoice<'func, 'library> {
self.struggle_learned_move.restore_all_uses(); self.struggle_learned_move.restore_all_uses();
TurnChoice::Move(MoveChoice::new( TurnChoice::Move(MoveChoice::new(
user.clone(), user.clone(),

View File

@ -22,11 +22,11 @@ use crate::{script_hook, PkmnResult, StringKey};
/// A pokemon battle, with any amount of sides and pokemon per side. /// A pokemon battle, with any amount of sides and pokemon per side.
#[derive(Debug)] #[derive(Debug)]
pub struct Battle<'own, 'library> { pub struct Battle {
/// The library the battle uses for handling. /// The library the battle uses for handling.
library: &'own DynamicLibrary, library: Arc<DynamicLibrary>,
/// A list of all different parties in the battle. /// A list of all different parties in the battle.
parties: Vec<BattleParty<'own, 'library>>, parties: Vec<BattleParty>,
/// Whether or not Pokemon can flee from the battle. /// Whether or not Pokemon can flee from the battle.
can_flee: bool, can_flee: bool,
/// The number of sides in the battle. Typically 2. /// The number of sides in the battle. Typically 2.
@ -34,11 +34,11 @@ pub struct Battle<'own, 'library> {
/// The number of Pokemon that can be on each side. /// The number of Pokemon that can be on each side.
pokemon_per_side: u8, pokemon_per_side: u8,
/// A list of all sides in the battle. /// A list of all sides in the battle.
sides: Vec<BattleSide<'own, 'library>>, sides: Vec<BattleSide>,
/// The RNG used for the battle. /// The RNG used for the battle.
random: BattleRandom, random: BattleRandom,
/// A queue of the yet to be executed choices in a turn. /// A queue of the yet to be executed choices in a turn.
current_turn_queue: RwLock<Option<ChoiceQueue<'own, 'library>>>, current_turn_queue: RwLock<Option<ChoiceQueue>>,
/// Whether or not the battle has ended. /// Whether or not the battle has ended.
has_ended: AtomicBool, has_ended: AtomicBool,
/// The eventual result of the battle. Inconclusive until the battle is ended. /// The eventual result of the battle. Inconclusive until the battle is ended.
@ -55,11 +55,11 @@ pub struct Battle<'own, 'library> {
script_source_data: RwLock<ScriptSourceData>, script_source_data: RwLock<ScriptSourceData>,
} }
impl<'own, 'library> Battle<'own, 'library> { impl<'own, 'library> Battle {
/// Initializes a new battle. /// Initializes a new battle.
pub fn new( pub fn new(
library: &'own DynamicLibrary, library: Arc<DynamicLibrary>,
parties: Vec<BattleParty<'own, 'library>>, parties: Vec<BattleParty>,
can_flee: bool, can_flee: bool,
number_of_sides: u8, number_of_sides: u8,
pokemon_per_side: u8, pokemon_per_side: u8,
@ -104,11 +104,11 @@ impl<'own, 'library> Battle<'own, 'library> {
} }
/// The library the battle uses for handling. /// The library the battle uses for handling.
pub fn library(&self) -> &'own DynamicLibrary { pub fn library(&self) -> &Arc<DynamicLibrary> {
self.library &self.library
} }
/// A list of all different parties in the battle. /// A list of all different parties in the battle.
pub fn parties(&self) -> &Vec<BattleParty<'own, 'library>> { pub fn parties(&self) -> &Vec<BattleParty> {
&self.parties &self.parties
} }
/// Whether or not Pokemon can flee from the battle. /// Whether or not Pokemon can flee from the battle.
@ -124,11 +124,11 @@ impl<'own, 'library> Battle<'own, 'library> {
self.pokemon_per_side self.pokemon_per_side
} }
/// A list of all sides in the battle. /// A list of all sides in the battle.
pub fn sides(&self) -> &Vec<BattleSide<'own, 'library>> { pub fn sides(&self) -> &Vec<BattleSide> {
&self.sides &self.sides
} }
/// A mutable list of all sides in the battle. /// A mutable list of all sides in the battle.
pub fn sides_mut(&mut self) -> &mut Vec<BattleSide<'own, 'library>> { pub fn sides_mut(&mut self) -> &mut Vec<BattleSide> {
&mut self.sides &mut self.sides
} }
/// The RNG used for the battle. /// The RNG used for the battle.
@ -156,12 +156,12 @@ impl<'own, 'library> Battle<'own, 'library> {
self.last_turn_time.load(Ordering::Relaxed) self.last_turn_time.load(Ordering::Relaxed)
} }
/// A queue of the yet to be executed choices in a turn. /// A queue of the yet to be executed choices in a turn.
pub fn current_turn_queue(&self) -> &RwLock<Option<ChoiceQueue<'own, 'library>>> { pub fn current_turn_queue(&self) -> &RwLock<Option<ChoiceQueue>> {
&self.current_turn_queue &self.current_turn_queue
} }
/// Get a Pokemon on the battlefield, on a specific side and an index on that side. /// Get a Pokemon on the battlefield, on a specific side and an index on that side.
pub fn get_pokemon(&self, side: u8, index: u8) -> Option<Arc<Pokemon<'own, 'library>>> { pub fn get_pokemon(&self, side: u8, index: u8) -> Option<Arc<Pokemon>> {
let side = self.sides.get(side as usize); let side = self.sides.get(side as usize);
side?; side?;
let pokemon_read_lock = side.unwrap().pokemon(); let pokemon_read_lock = side.unwrap().pokemon();
@ -254,7 +254,7 @@ impl<'own, 'library> Battle<'own, 'library> {
} }
/// Try and set the choice for the battle. If the choice is not valid, this returns false. /// Try and set the choice for the battle. If the choice is not valid, this returns false.
pub fn try_set_choice(&mut self, choice: TurnChoice<'own, 'library>) -> PkmnResult<bool> { pub fn try_set_choice(&mut self, choice: TurnChoice) -> PkmnResult<bool> {
if !self.can_use(&choice) { if !self.can_use(&choice) {
return Ok(false); return Ok(false);
} }
@ -332,7 +332,7 @@ impl<'own, 'library> Battle<'own, 'library> {
} }
} }
impl<'own, 'library> VolatileScriptsOwner<'own> for Battle<'own, 'library> { impl VolatileScriptsOwner for Battle {
fn volatile_scripts(&self) -> &Arc<ScriptSet> { fn volatile_scripts(&self) -> &Arc<ScriptSet> {
&self.volatile_scripts &self.volatile_scripts
} }
@ -343,7 +343,7 @@ impl<'own, 'library> VolatileScriptsOwner<'own> for Battle<'own, 'library> {
} }
} }
impl<'own, 'library> ScriptSource<'own> for Battle<'own, 'library> { impl ScriptSource for Battle {
fn get_script_count(&self) -> usize { fn get_script_count(&self) -> usize {
1 1
} }

View File

@ -6,17 +6,17 @@ use crate::dynamic_data::models::pokemon_party::PokemonParty;
/// A battle party is a wrapper around a party, with the indices for which the party is responsible /// A battle party is a wrapper around a party, with the indices for which the party is responsible
/// on the field attached. /// on the field attached.
#[derive(Debug)] #[derive(Debug)]
pub struct BattleParty<'own, 'library> { pub struct BattleParty {
/// The party the BattleParty is holding. /// The party the BattleParty is holding.
party: Arc<PokemonParty<'own, 'library>>, party: Arc<PokemonParty>,
/// The indices for which the party is responsible, in the format (side, index) /// The indices for which the party is responsible, in the format (side, index)
responsible_indices: Vec<(u8, u8)>, responsible_indices: Vec<(u8, u8)>,
} }
impl<'own, 'library> BattleParty<'own, 'library> { impl BattleParty {
/// Initializes a battle party with the underlying party, and the indices the party is responsible /// Initializes a battle party with the underlying party, and the indices the party is responsible
/// for. /// for.
pub fn new(party: Arc<PokemonParty<'own, 'library>>, responsible_indices: Vec<(u8, u8)>) -> Self { pub fn new(party: Arc<PokemonParty>, responsible_indices: Vec<(u8, u8)>) -> Self {
Self { Self {
party, party,
responsible_indices, responsible_indices,
@ -44,7 +44,7 @@ impl<'own, 'library> BattleParty<'own, 'library> {
} }
/// Gets a Pokemon at an index. /// Gets a Pokemon at an index.
pub fn get_pokemon(&self, index: usize) -> &Option<Arc<Pokemon<'own, 'library>>> { pub fn get_pokemon(&self, index: usize) -> &Option<Arc<Pokemon>> {
self.party.at(index) self.party.at(index)
} }
} }

View File

@ -18,22 +18,22 @@ use crate::{script_hook, PkmnResult, StringKey};
/// A side on a battle. /// A side on a battle.
#[derive(Debug)] #[derive(Debug)]
pub struct BattleSide<'own, 'library> { pub struct BattleSide {
/// The index of the side on the battle. /// The index of the side on the battle.
index: u8, index: u8,
/// The number of Pokemon that can be on the side. /// The number of Pokemon that can be on the side.
pokemon_per_side: u8, pokemon_per_side: u8,
/// A list of pokemon currently on the battlefield. /// A list of pokemon currently on the battlefield.
pokemon: RwLock<Vec<Option<Arc<Pokemon<'own, 'library>>>>>, pokemon: RwLock<Vec<Option<Arc<Pokemon>>>>,
/// The currently set choices for all Pokemon on the battlefield. Cleared when the turn starts. /// The currently set choices for all Pokemon on the battlefield. Cleared when the turn starts.
choices: RwLock<Vec<Option<TurnChoice<'own, 'library>>>>, choices: RwLock<Vec<Option<TurnChoice>>>,
/// The slots on the side that can still be filled. Once all slots are set to false, this side /// The slots on the side that can still be filled. Once all slots are set to false, this side
/// has lost the battle. /// has lost the battle.
fillable_slots: Vec<AtomicBool>, fillable_slots: Vec<AtomicBool>,
/// The number of choices that are set. /// The number of choices that are set.
choices_set: AtomicU8, choices_set: AtomicU8,
/// A reference to the battle we're part of. /// A reference to the battle we're part of.
battle: *mut Battle<'own, 'library>, battle: *mut Battle,
/// Whether or not this side has fled. /// Whether or not this side has fled.
has_fled_battle: bool, has_fled_battle: bool,
/// The volatile scripts that are attached to the side. /// The volatile scripts that are attached to the side.
@ -43,7 +43,7 @@ pub struct BattleSide<'own, 'library> {
script_source_data: RwLock<ScriptSourceData>, script_source_data: RwLock<ScriptSourceData>,
} }
impl<'own, 'library> BattleSide<'own, 'library> { impl<'own, 'library> BattleSide {
/// Instantiates a battle side. /// Instantiates a battle side.
pub fn new(index: u8, pokemon_per_side: u8) -> Self { pub fn new(index: u8, pokemon_per_side: u8) -> Self {
let mut pokemon = Vec::with_capacity(pokemon_per_side as usize); let mut pokemon = Vec::with_capacity(pokemon_per_side as usize);
@ -73,7 +73,7 @@ impl<'own, 'library> BattleSide<'own, 'library> {
} }
/// Set the battle this side belongs to. /// Set the battle this side belongs to.
pub(crate) fn set_battle(&mut self, battle: *mut Battle<'own, 'library>) { pub(crate) fn set_battle(&mut self, battle: *mut Battle) {
self.battle = battle; self.battle = battle;
} }
@ -86,11 +86,11 @@ impl<'own, 'library> BattleSide<'own, 'library> {
self.pokemon_per_side self.pokemon_per_side
} }
/// A list of pokemon currently on the battlefield. /// A list of pokemon currently on the battlefield.
pub fn pokemon(&self) -> RwLockReadGuard<'_, RawRwLock, Vec<Option<Arc<Pokemon<'own, 'library>>>>> { pub fn pokemon(&self) -> RwLockReadGuard<'_, RawRwLock, Vec<Option<Arc<Pokemon>>>> {
self.pokemon.read() self.pokemon.read()
} }
/// The currently set choices for all Pokemon on the battlefield. Cleared when the turn starts. /// The currently set choices for all Pokemon on the battlefield. Cleared when the turn starts.
pub fn choices(&self) -> &RwLock<Vec<Option<TurnChoice<'own, 'library>>>> { pub fn choices(&self) -> &RwLock<Vec<Option<TurnChoice>>> {
&self.choices &self.choices
} }
/// The slots on the side that can still be filled. Once all slots are set to false, this side /// The slots on the side that can still be filled. Once all slots are set to false, this side
@ -103,7 +103,7 @@ impl<'own, 'library> BattleSide<'own, 'library> {
self.choices_set.load(Ordering::SeqCst) self.choices_set.load(Ordering::SeqCst)
} }
/// A reference to the battle we're part of. /// A reference to the battle we're part of.
pub fn battle(&self) -> &Battle<'own, 'library> { pub fn battle(&self) -> &Battle {
unsafe { self.battle.as_ref().unwrap() } unsafe { self.battle.as_ref().unwrap() }
} }
/// Whether or not this side has fled. /// Whether or not this side has fled.
@ -135,7 +135,7 @@ impl<'own, 'library> BattleSide<'own, 'library> {
} }
/// Sets a choice for a Pokemon on this side. /// Sets a choice for a Pokemon on this side.
pub(crate) fn set_choice(&self, choice: TurnChoice<'own, 'library>) { pub(crate) fn set_choice(&self, choice: TurnChoice) {
for (index, pokemon_slot) in self.pokemon.read().iter().enumerate() { for (index, pokemon_slot) in self.pokemon.read().iter().enumerate() {
if let Some(pokemon) = pokemon_slot { if let Some(pokemon) = pokemon_slot {
if std::ptr::eq(pokemon.deref(), choice.user().deref()) { if std::ptr::eq(pokemon.deref(), choice.user().deref()) {
@ -161,7 +161,7 @@ impl<'own, 'library> BattleSide<'own, 'library> {
} }
/// Switches out a spot on the field for a different Pokemon. /// Switches out a spot on the field for a different Pokemon.
pub fn set_pokemon(&self, index: u8, pokemon: Option<Arc<Pokemon<'own, 'library>>>) { pub fn set_pokemon(&self, index: u8, pokemon: Option<Arc<Pokemon>>) {
{ {
let old = &self.pokemon.read()[index as usize]; let old = &self.pokemon.read()[index as usize];
if let Some(old_pokemon) = old { if let Some(old_pokemon) = old {
@ -202,7 +202,7 @@ impl<'own, 'library> BattleSide<'own, 'library> {
} }
/// Checks whether a Pokemon is on the field in this side. /// Checks whether a Pokemon is on the field in this side.
pub fn is_pokemon_on_side(&self, pokemon: Arc<Pokemon<'own, 'library>>) -> bool { pub fn is_pokemon_on_side(&self, pokemon: Arc<Pokemon>) -> bool {
for p in self.pokemon.read().iter().flatten() { for p in self.pokemon.read().iter().flatten() {
if std::ptr::eq(p.deref().deref(), pokemon.deref()) { if std::ptr::eq(p.deref().deref(), pokemon.deref()) {
return true; return true;
@ -218,7 +218,7 @@ impl<'own, 'library> BattleSide<'own, 'library> {
} }
/// Checks whether a slot is unfillable or not. /// Checks whether a slot is unfillable or not.
pub fn is_slot_unfillable(&self, pokemon: Arc<Pokemon<'own, 'library>>) -> bool { pub fn is_slot_unfillable(&self, pokemon: Arc<Pokemon>) -> bool {
for (i, slot) in self.pokemon.read().iter().enumerate() { for (i, slot) in self.pokemon.read().iter().enumerate() {
if let Some(p) = slot { if let Some(p) = slot {
if std::ptr::eq(p.deref().deref(), pokemon.deref()) { if std::ptr::eq(p.deref().deref(), pokemon.deref()) {
@ -296,7 +296,7 @@ impl<'own, 'library> BattleSide<'own, 'library> {
} }
} }
impl<'own, 'library> VolatileScriptsOwner<'own> for BattleSide<'own, 'library> { impl VolatileScriptsOwner for BattleSide {
fn volatile_scripts(&self) -> &Arc<ScriptSet> { fn volatile_scripts(&self) -> &Arc<ScriptSet> {
&self.volatile_scripts &self.volatile_scripts
} }
@ -308,7 +308,7 @@ impl<'own, 'library> VolatileScriptsOwner<'own> for BattleSide<'own, 'library> {
} }
} }
impl<'own, 'library> ScriptSource<'own> for BattleSide<'own, 'library> { impl ScriptSource for BattleSide {
fn get_script_count(&self) -> usize { fn get_script_count(&self) -> usize {
self.battle().get_script_count() + 1 self.battle().get_script_count() + 1
} }

View File

@ -84,34 +84,34 @@ impl HitData {
/// An executing move is the data of the move for while it is executing. /// An executing move is the data of the move for while it is executing.
#[derive(Debug)] #[derive(Debug)]
pub struct ExecutingMove<'own, 'battle, 'library> { pub struct ExecutingMove {
/// The number of hits this move has. /// The number of hits this move has.
number_of_hits: u8, number_of_hits: u8,
/// A list of hits for this move. For multi target multi hit moves, this stores the hits linearly, /// A list of hits for this move. For multi target multi hit moves, this stores the hits linearly,
/// for example: (target1, hit1), (target1, hit2), (target2, hit1), (target2, hit2), etc. /// for example: (target1, hit1), (target1, hit2), (target2, hit1), (target2, hit2), etc.
hits: Vec<HitData>, hits: Vec<HitData>,
/// The user of the move. /// The user of the move.
user: Arc<Pokemon<'battle, 'library>>, user: Arc<Pokemon>,
/// The move the user has actually chosen to do. /// The move the user has actually chosen to do.
chosen_move: Arc<LearnedMove<'library>>, chosen_move: Arc<LearnedMove>,
/// The move that the user is actually going to do. /// The move that the user is actually going to do.
use_move: &'own MoveData, use_move: Arc<MoveData>,
/// The script of the move. /// The script of the move.
script: ScriptContainer, script: ScriptContainer,
/// The targets for this move. /// The targets for this move.
targets: &'own TargetList<'battle, 'library>, targets: TargetList,
/// Data required for this to be a script source. /// Data required for this to be a script source.
script_source_data: RwLock<ScriptSourceData>, script_source_data: RwLock<ScriptSourceData>,
} }
impl<'own, 'battle, 'library> ExecutingMove<'own, 'battle, 'library> { impl ExecutingMove {
/// Instantiates an executing move. /// Instantiates an executing move.
pub fn new( pub fn new(
targets: &'own TargetList<'battle, 'library>, targets: TargetList,
number_of_hits: u8, number_of_hits: u8,
user: Arc<Pokemon<'battle, 'library>>, user: Arc<Pokemon>,
chosen_move: Arc<LearnedMove<'library>>, chosen_move: Arc<LearnedMove>,
use_move: &'own MoveData, use_move: Arc<MoveData>,
script: ScriptContainer, script: ScriptContainer,
) -> Self { ) -> Self {
let total_hits = number_of_hits as usize * targets.len(); let total_hits = number_of_hits as usize * targets.len();
@ -140,16 +140,16 @@ impl<'own, 'battle, 'library> ExecutingMove<'own, 'battle, 'library> {
self.number_of_hits self.number_of_hits
} }
/// The user of the move. /// The user of the move.
pub fn user(&self) -> &Arc<Pokemon<'battle, 'library>> { pub fn user(&self) -> &Arc<Pokemon> {
&self.user &self.user
} }
/// The move the user has actually chosen to do. /// The move the user has actually chosen to do.
pub fn chosen_move(&self) -> &Arc<LearnedMove<'library>> { pub fn chosen_move(&self) -> &Arc<LearnedMove> {
&self.chosen_move &self.chosen_move
} }
/// The move that the user is actually going to do. /// The move that the user is actually going to do.
pub fn use_move(&self) -> &'own MoveData { pub fn use_move(&self) -> &Arc<MoveData> {
self.use_move &self.use_move
} }
/// The script of the move. /// The script of the move.
pub fn script(&self) -> &ScriptContainer { pub fn script(&self) -> &ScriptContainer {
@ -157,11 +157,7 @@ impl<'own, 'battle, 'library> ExecutingMove<'own, 'battle, 'library> {
} }
/// Gets a hit data for a target, with a specific index. /// Gets a hit data for a target, with a specific index.
pub fn get_hit_data<'func>( pub fn get_hit_data<'func>(&'func self, for_target: &'func Arc<Pokemon>, hit: u8) -> PkmnResult<&'func HitData> {
&'func self,
for_target: &'func Arc<Pokemon<'battle, 'library>>,
hit: u8,
) -> PkmnResult<&'func HitData> {
for (index, target) in self.targets.iter().enumerate() { for (index, target) in self.targets.iter().enumerate() {
if let Some(target) = target { if let Some(target) = target {
if std::ptr::eq(target.deref().deref(), for_target.deref().deref()) { if std::ptr::eq(target.deref().deref(), for_target.deref().deref()) {
@ -174,7 +170,7 @@ impl<'own, 'battle, 'library> ExecutingMove<'own, 'battle, 'library> {
} }
/// Checks whether a Pokemon is a target for this move. /// Checks whether a Pokemon is a target for this move.
pub fn is_pokemon_target(&self, pokemon: &Arc<Pokemon<'battle, 'library>>) -> bool { pub fn is_pokemon_target(&self, pokemon: &Arc<Pokemon>) -> bool {
for target in self.targets.iter().flatten() { for target in self.targets.iter().flatten() {
if std::ptr::eq(target.deref().deref(), pokemon.deref().deref()) { if std::ptr::eq(target.deref().deref(), pokemon.deref().deref()) {
return true; return true;
@ -184,7 +180,7 @@ impl<'own, 'battle, 'library> ExecutingMove<'own, 'battle, 'library> {
} }
/// Gets the index of the hits in this move where the hits for a specific target start. /// Gets the index of the hits in this move where the hits for a specific target start.
pub(crate) fn get_index_of_target(&self, for_target: &Arc<Pokemon<'battle, 'library>>) -> PkmnResult<usize> { pub(crate) fn get_index_of_target(&self, for_target: &Arc<Pokemon>) -> PkmnResult<usize> {
for (index, target) in self.targets.iter().enumerate() { for (index, target) in self.targets.iter().enumerate() {
if let Some(target) = target { if let Some(target) = target {
if std::ptr::eq(target.deref().deref(), for_target.deref().deref()) { if std::ptr::eq(target.deref().deref(), for_target.deref().deref()) {
@ -202,7 +198,7 @@ impl<'own, 'battle, 'library> ExecutingMove<'own, 'battle, 'library> {
} }
} }
impl<'own, 'battle, 'library> ScriptSource<'own> for ExecutingMove<'own, 'battle, 'library> { impl ScriptSource for ExecutingMove {
fn get_script_count(&self) -> usize { fn get_script_count(&self) -> usize {
1 1
} }

View File

@ -1,4 +1,5 @@
use std::sync::atomic::{AtomicU8, Ordering}; use std::sync::atomic::{AtomicU8, Ordering};
use std::sync::Arc;
use crate::static_data::MoveData; use crate::static_data::MoveData;
@ -6,9 +7,9 @@ use crate::static_data::MoveData;
/// such as the remaining amount of users, how it has been learned, etc. /// such as the remaining amount of users, how it has been learned, etc.
#[derive(Debug)] #[derive(Debug)]
#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] #[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))]
pub struct LearnedMove<'library> { pub struct LearnedMove {
/// The immutable move information of the move. /// The immutable move information of the move.
move_data: &'library MoveData, move_data: Arc<MoveData>,
/// The maximal power points for this move. /// The maximal power points for this move.
max_pp: u8, max_pp: u8,
/// The amount of remaining power points. If this is 0, we can not use the move anymore. /// The amount of remaining power points. If this is 0, we can not use the move anymore.
@ -28,11 +29,11 @@ pub enum MoveLearnMethod {
Level = 1, Level = 1,
} }
impl<'a> LearnedMove<'a> { impl LearnedMove {
/// Instantiate a new learned move. /// Instantiate a new learned move.
pub fn new(move_data: &'a MoveData, learn_method: MoveLearnMethod) -> Self { pub fn new(move_data: &Arc<MoveData>, learn_method: MoveLearnMethod) -> Self {
Self { Self {
move_data, move_data: move_data.clone(),
max_pp: move_data.base_usages(), max_pp: move_data.base_usages(),
remaining_pp: AtomicU8::new(move_data.base_usages()), remaining_pp: AtomicU8::new(move_data.base_usages()),
learn_method, learn_method,
@ -40,8 +41,8 @@ impl<'a> LearnedMove<'a> {
} }
/// The immutable move information of the move. /// The immutable move information of the move.
pub fn move_data(&self) -> &MoveData { pub fn move_data(&self) -> &Arc<MoveData> {
self.move_data &self.move_data
} }
/// The maximal power points for this move. /// The maximal power points for this move.
pub fn max_pp(&self) -> u8 { pub fn max_pp(&self) -> u8 {

View File

@ -26,23 +26,20 @@ use crate::{script_hook, PkmnResult, StringKey};
/// An individual Pokemon as we know and love them. /// An individual Pokemon as we know and love them.
#[derive(Debug)] #[derive(Debug)]
#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] #[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))]
pub struct Pokemon<'own, 'library> pub struct Pokemon {
where
'own: 'library,
{
/// The library data of the Pokemon. /// The library data of the Pokemon.
library: &'own DynamicLibrary, library: Arc<DynamicLibrary>,
/// The species of the Pokemon. /// The species of the Pokemon.
species: &'own Species, species: Arc<Species>,
/// The form of the Pokemon. /// The form of the Pokemon.
form: &'own Form, form: Arc<Form>,
/// An optional display species of the Pokemon. If this is set, the client should display this /// An optional display species of the Pokemon. If this is set, the client should display this
/// species. An example of usage for this is the Illusion ability. /// species. An example of usage for this is the Illusion ability.
display_species: Option<&'own Species>, display_species: Option<Arc<Species>>,
/// An optional display form of the Pokemon. If this is set, the client should display this /// An optional display form of the Pokemon. If this is set, the client should display this
// species. An example of usage for this is the Illusion ability. // species. An example of usage for this is the Illusion ability.
display_form: Option<&'own Form>, display_form: Option<Arc<Form>>,
/// The current level of the Pokemon. /// The current level of the Pokemon.
level: LevelInt, level: LevelInt,
@ -57,7 +54,7 @@ where
/// currently not used, and can be used for other implementations. /// currently not used, and can be used for other implementations.
coloring: u8, coloring: u8,
/// The held item of the Pokemon. /// The held item of the Pokemon.
held_item: RwLock<Option<&'own Item>>, held_item: RwLock<Option<Arc<Item>>>,
/// The remaining health points of the Pokemon. /// The remaining health points of the Pokemon.
current_health: AtomicU32, current_health: AtomicU32,
@ -78,7 +75,7 @@ where
/// The [effort values](https://bulbapedia.bulbagarden.net/wiki/Effort_values) of the Pokemon. /// The [effort values](https://bulbapedia.bulbagarden.net/wiki/Effort_values) of the Pokemon.
effort_values: ClampedStatisticSet<u8, 0, 252>, effort_values: ClampedStatisticSet<u8, 0, 252>,
/// The [nature](https://bulbapedia.bulbagarden.net/wiki/Nature) of the Pokemon. /// The [nature](https://bulbapedia.bulbagarden.net/wiki/Nature) of the Pokemon.
nature: &'own Nature, nature: Arc<Nature>,
/// An optional nickname of the Pokemon. /// An optional nickname of the Pokemon.
nickname: Option<String>, nickname: Option<String>,
@ -90,11 +87,11 @@ where
override_ability: Option<Ability>, override_ability: Option<Ability>,
/// If in battle, we have additional data. /// If in battle, we have additional data.
battle_data: RwLock<Option<PokemonBattleData<'own, 'library>>>, battle_data: RwLock<Option<PokemonBattleData>>,
/// The moves the Pokemon has learned. This is of a set length of [`MAX_MOVES`]. Empty move slots /// The moves the Pokemon has learned. This is of a set length of [`MAX_MOVES`]. Empty move slots
/// are defined by None. /// are defined by None.
moves: RwLock<[Option<Arc<LearnedMove<'library>>>; MAX_MOVES]>, moves: RwLock<[Option<Arc<LearnedMove>>; MAX_MOVES]>,
/// Whether or not the Pokemon is allowed to gain experience. /// Whether or not the Pokemon is allowed to gain experience.
allowed_experience: bool, allowed_experience: bool,
@ -118,12 +115,12 @@ where
script_source_data: RwLock<ScriptSourceData>, script_source_data: RwLock<ScriptSourceData>,
} }
impl<'own, 'library> Pokemon<'own, 'library> { impl Pokemon {
/// Instantiates a new Pokemon. /// Instantiates a new Pokemon.
pub fn new( pub fn new(
library: &'own DynamicLibrary, library: Arc<DynamicLibrary>,
species: &'own Species, species: Arc<Species>,
form: &'own Form, form: &Arc<Form>,
ability: AbilityIndex, ability: AbilityIndex,
level: LevelInt, level: LevelInt,
unique_identifier: u32, unique_identifier: u32,
@ -142,11 +139,12 @@ impl<'own, 'library> Pokemon<'own, 'library> {
.static_data() .static_data()
.natures() .natures()
.get_nature(nature) .get_nature(nature)
.unwrap_or_else(|| panic!("Unknown nature name was given: {}.", &nature)); .unwrap_or_else(|| panic!("Unknown nature name was given: {}.", &nature))
.clone();
let mut pokemon = Self { let mut pokemon = Self {
library, library,
species, species,
form, form: form.clone(),
display_species: None, display_species: None,
display_form: None, display_form: None,
level, level,
@ -187,31 +185,31 @@ impl<'own, 'library> Pokemon<'own, 'library> {
} }
/// The library data of the Pokemon. /// The library data of the Pokemon.
pub fn library(&self) -> &'own DynamicLibrary { pub fn library(&self) -> &Arc<DynamicLibrary> {
self.library &self.library
} }
/// The species of the Pokemon. /// The species of the Pokemon.
pub fn species(&self) -> &'own Species { pub fn species(&self) -> &Arc<Species> {
self.species &self.species
} }
/// The form of the Pokemon. /// The form of the Pokemon.
pub fn form(&self) -> &'own Form { pub fn form(&self) -> &Arc<Form> {
self.form &self.form
} }
/// The species that should be displayed to the user. This handles stuff like the Illusion ability. /// The species that should be displayed to the user. This handles stuff like the Illusion ability.
pub fn display_species(&self) -> &'own Species { pub fn display_species(&self) -> &Arc<Species> {
if let Some(v) = self.display_species { if let Some(v) = &self.display_species {
v v
} else { } else {
self.species &self.species
} }
} }
/// The form that should be displayed to the user. This handles stuff like the Illusion ability. /// The form that should be displayed to the user. This handles stuff like the Illusion ability.
pub fn display_form(&self) -> &'own Form { pub fn display_form(&self) -> &Arc<Form> {
if let Some(v) = self.display_form { if let Some(v) = &self.display_form {
v v
} else { } else {
self.form &self.form
} }
} }
/// The current level of the Pokemon. /// The current level of the Pokemon.
@ -235,8 +233,8 @@ impl<'own, 'library> Pokemon<'own, 'library> {
pub fn coloring(&self) -> u8 { pub fn coloring(&self) -> u8 {
self.coloring self.coloring
} }
/// Checks whether the Pokemon is holding an item, /// Gets the held item of a Pokemon
pub fn held_item(&self) -> &RwLock<Option<&'own Item>> { pub fn held_item(&self) -> &RwLock<Option<Arc<Item>>> {
&self.held_item &self.held_item
} }
/// Checks whether the Pokemon is holding a specific item. /// Checks whether the Pokemon is holding a specific item.
@ -248,11 +246,11 @@ impl<'own, 'library> Pokemon<'own, 'library> {
false false
} }
/// Changes the held item of the Pokemon/ /// Changes the held item of the Pokemon/
pub fn set_held_item(&self, item: &'own Item) -> Option<&'own Item> { pub fn set_held_item(&self, item: &Arc<Item>) -> Option<Arc<Item>> {
self.held_item.write().replace(item) self.held_item.write().replace(item.clone())
} }
/// Removes the held item from the Pokemon. /// Removes the held item from the Pokemon.
pub fn remove_held_item(&self) -> Option<&'own Item> { pub fn remove_held_item(&self) -> Option<Arc<Item>> {
self.held_item.write().take() self.held_item.write().take()
} }
/// Makes the Pokemon uses its held item. /// Makes the Pokemon uses its held item.
@ -260,7 +258,10 @@ impl<'own, 'library> Pokemon<'own, 'library> {
if self.held_item.read().is_none() { if self.held_item.read().is_none() {
return false; return false;
} }
let script = self.library.load_item_script(self.held_item.read().unwrap()).unwrap(); let script = self
.library
.load_item_script(&self.held_item.read().as_ref().unwrap())
.unwrap();
if script.is_none() { if script.is_none() {
return false; return false;
} }
@ -299,7 +300,7 @@ impl<'own, 'library> Pokemon<'own, 'library> {
} }
/// The moves the Pokemon has learned. This is of a set length of [`MAX_MOVES`]. Empty move slots /// The moves the Pokemon has learned. This is of a set length of [`MAX_MOVES`]. Empty move slots
/// are defined by None. /// are defined by None.
pub fn learned_moves(&self) -> &RwLock<[Option<Arc<LearnedMove<'library>>>; MAX_MOVES]> { pub fn learned_moves(&self) -> &RwLock<[Option<Arc<LearnedMove>>; MAX_MOVES]> {
&self.moves &self.moves
} }
@ -384,7 +385,7 @@ impl<'own, 'library> Pokemon<'own, 'library> {
} }
/// Gets the battle the battle is currently in. /// Gets the battle the battle is currently in.
pub fn get_battle(&self) -> Option<&Battle<'own, 'library>> { pub fn get_battle(&self) -> Option<&Battle> {
let r = self.battle_data.read(); let r = self.battle_data.read();
if let Some(data) = &r.deref() { if let Some(data) = &r.deref() {
unsafe { data.battle.as_ref() } unsafe { data.battle.as_ref() }
@ -434,8 +435,8 @@ impl<'own, 'library> Pokemon<'own, 'library> {
} }
/// The [nature](https://bulbapedia.bulbagarden.net/wiki/Nature) of the Pokemon. /// The [nature](https://bulbapedia.bulbagarden.net/wiki/Nature) of the Pokemon.
pub fn nature(&self) -> &'own Nature { pub fn nature(&self) -> &Arc<Nature> {
self.nature &self.nature
} }
/// Calculates the flat stats on the Pokemon. /// Calculates the flat stats on the Pokemon.
@ -453,9 +454,9 @@ impl<'own, 'library> Pokemon<'own, 'library> {
} }
/// Change the species of the Pokemon. /// Change the species of the Pokemon.
pub fn change_species(&mut self, species: &'own Species, form: &'own Form) { pub fn change_species(&mut self, species: Arc<Species>, form: Arc<Form>) {
self.species = species; self.species = species.clone();
self.form = form; self.form = form.clone();
// If the pokemon is genderless, but it's new species is not, we want to set its gender // If the pokemon is genderless, but it's new species is not, we want to set its gender
if self.gender != Gender::Genderless && species.gender_rate() < 0.0 { if self.gender != Gender::Genderless && species.gender_rate() < 0.0 {
@ -486,11 +487,11 @@ impl<'own, 'library> Pokemon<'own, 'library> {
} }
/// Change the form of the Pokemon. /// Change the form of the Pokemon.
pub fn change_form(&mut self, form: &'own Form) { pub fn change_form(&mut self, form: &Arc<Form>) {
if std::ptr::eq(self.form, form) { if Arc::ptr_eq(&self.form, form) {
return; return;
} }
self.form = form; self.form = form.clone();
self.types.clear(); self.types.clear();
for t in form.types() { for t in form.types() {
@ -512,7 +513,7 @@ impl<'own, 'library> Pokemon<'own, 'library> {
.set(ability_script) .set(ability_script)
.as_ref() .as_ref()
// Ensure the ability script gets initialized with the parameters for the ability. // Ensure the ability script gets initialized with the parameters for the ability.
.on_initialize(self.library, self.active_ability().parameters()) .on_initialize(self.library.as_ref(), self.active_ability().parameters())
} else { } else {
self.ability_script.clear(); self.ability_script.clear();
} }
@ -547,7 +548,7 @@ impl<'own, 'library> Pokemon<'own, 'library> {
} }
/// Sets the current battle the Pokemon is in. /// Sets the current battle the Pokemon is in.
pub fn set_battle_data(&self, battle: *mut Battle<'own, 'library>, battle_side_index: u8) { pub fn set_battle_data(&self, battle: *mut Battle, battle_side_index: u8) {
let mut w = self.battle_data.write(); let mut w = self.battle_data.write();
if let Some(battle_data) = w.deref_mut() { if let Some(battle_data) = w.deref_mut() {
battle_data.battle = battle; battle_data.battle = battle;
@ -590,7 +591,7 @@ impl<'own, 'library> Pokemon<'own, 'library> {
} }
/// Marks an opponent as seen, for use in experience gain. /// Marks an opponent as seen, for use in experience gain.
pub fn mark_opponent_as_seen(&self, pokemon: Weak<Pokemon<'own, 'library>>) { pub fn mark_opponent_as_seen(&self, pokemon: Weak<Pokemon>) {
let r = self.battle_data.read(); let r = self.battle_data.read();
if let Some(battle_data) = &r.deref() { if let Some(battle_data) = &r.deref() {
let mut opponents = battle_data.seen_opponents().write(); let mut opponents = battle_data.seen_opponents().write();
@ -692,9 +693,9 @@ impl<'own, 'library> Pokemon<'own, 'library> {
/// The data of the Pokemon related to being in a battle. /// The data of the Pokemon related to being in a battle.
#[derive(Debug)] #[derive(Debug)]
pub struct PokemonBattleData<'pokemon, 'library> { pub struct PokemonBattleData {
/// The battle data of the Pokemon /// The battle data of the Pokemon
battle: *mut Battle<'pokemon, 'library>, battle: *mut Battle,
/// The index of the side of the Pokemon /// The index of the side of the Pokemon
battle_side_index: AtomicU8, battle_side_index: AtomicU8,
/// The index of the slot on the side of the Pokemon. /// The index of the slot on the side of the Pokemon.
@ -702,16 +703,16 @@ pub struct PokemonBattleData<'pokemon, 'library> {
/// Whether or not the Pokemon is on the battlefield. /// Whether or not the Pokemon is on the battlefield.
on_battle_field: AtomicBool, on_battle_field: AtomicBool,
/// A list of opponents the Pokemon has seen this battle. /// A list of opponents the Pokemon has seen this battle.
seen_opponents: RwLock<Vec<Weak<Pokemon<'pokemon, 'library>>>>, seen_opponents: RwLock<Vec<Weak<Pokemon>>>,
} }
impl<'pokemon, 'library> PokemonBattleData<'pokemon, 'library> { impl PokemonBattleData {
/// The battle data of the Pokemon /// The battle data of the Pokemon
pub fn battle_mut(&mut self) -> Option<&mut Battle<'pokemon, 'library>> { pub fn battle_mut(&mut self) -> Option<&mut Battle> {
unsafe { self.battle.as_mut() } unsafe { self.battle.as_mut() }
} }
/// The battle data of the Pokemon /// The battle data of the Pokemon
pub fn battle(&self) -> Option<&Battle<'pokemon, 'library>> { pub fn battle(&self) -> Option<&Battle> {
unsafe { self.battle.as_ref() } unsafe { self.battle.as_ref() }
} }
@ -728,12 +729,12 @@ impl<'pokemon, 'library> PokemonBattleData<'pokemon, 'library> {
self.on_battle_field.load(Ordering::Relaxed) self.on_battle_field.load(Ordering::Relaxed)
} }
/// A list of opponents the Pokemon has seen this battle. /// A list of opponents the Pokemon has seen this battle.
pub fn seen_opponents(&self) -> &RwLock<Vec<Weak<Pokemon<'pokemon, 'library>>>> { pub fn seen_opponents(&self) -> &RwLock<Vec<Weak<Pokemon>>> {
&self.seen_opponents &self.seen_opponents
} }
} }
impl<'own, 'library> ScriptSource<'own> for Pokemon<'own, 'library> { impl ScriptSource for Pokemon {
fn get_script_count(&self) -> usize { fn get_script_count(&self) -> usize {
let mut c = 3; let mut c = 3;
if let Some(battle_data) = &self.battle_data.read().deref() { if let Some(battle_data) = &self.battle_data.read().deref() {
@ -765,7 +766,7 @@ impl<'own, 'library> ScriptSource<'own> for Pokemon<'own, 'library> {
} }
} }
impl<'own, 'library> VolatileScriptsOwner<'own> for Pokemon<'own, 'library> { impl VolatileScriptsOwner for Pokemon {
fn volatile_scripts(&self) -> &Arc<ScriptSet> { fn volatile_scripts(&self) -> &Arc<ScriptSet> {
&self.volatile &self.volatile
} }
@ -794,7 +795,7 @@ pub mod test {
#[test] #[test]
fn construct_pokemon() { fn construct_pokemon() {
let lib = crate::dynamic_data::libraries::dynamic_library::test::build(); let lib = Arc::new(crate::dynamic_data::libraries::dynamic_library::test::build());
let species = lib.static_data().species().get(&"foo".into()).unwrap(); let species = lib.static_data().species().get(&"foo".into()).unwrap();
let form = species.get_form(&"default".into()).unwrap(); let form = species.get_form(&"default".into()).unwrap();

View File

@ -1,3 +1,5 @@
use std::sync::Arc;
use crate::defines::LevelInt; use crate::defines::LevelInt;
use crate::dynamic_data::models::learned_move::MoveLearnMethod; use crate::dynamic_data::models::learned_move::MoveLearnMethod;
use crate::dynamic_data::models::pokemon::Pokemon; use crate::dynamic_data::models::pokemon::Pokemon;
@ -6,9 +8,9 @@ use crate::static_data::{AbilityIndex, DataLibrary, Gender};
use crate::{Random, StringKey}; use crate::{Random, StringKey};
/// This allows for the easy chain building of a Pokemon. /// This allows for the easy chain building of a Pokemon.
pub struct PokemonBuilder<'own> { pub struct PokemonBuilder {
/// The library of the Pokemon. /// The library of the Pokemon.
library: &'own DynamicLibrary, library: Arc<DynamicLibrary>,
/// The name of the species of the Pokemon. /// The name of the species of the Pokemon.
species: StringKey, species: StringKey,
/// The level of the Pokemon. /// The level of the Pokemon.
@ -19,9 +21,9 @@ pub struct PokemonBuilder<'own> {
random_seed: Option<u128>, random_seed: Option<u128>,
} }
impl<'own> PokemonBuilder<'own> { impl PokemonBuilder {
/// Creates a new PokemonBuilder with a library, species, and level. /// Creates a new PokemonBuilder with a library, species, and level.
pub fn new(library: &'own DynamicLibrary, species: StringKey, level: LevelInt) -> Self { pub fn new(library: Arc<DynamicLibrary>, species: StringKey, level: LevelInt) -> Self {
Self { Self {
library, library,
species, species,
@ -37,19 +39,19 @@ impl<'own> PokemonBuilder<'own> {
} }
/// Finally turn the builder into an actual Pokemon. /// Finally turn the builder into an actual Pokemon.
pub fn build(self) -> Pokemon<'own, 'own> { pub fn build(self) -> Pokemon {
let mut random = if let Some(seed) = self.random_seed { let mut random = if let Some(seed) = self.random_seed {
Random::new(seed) Random::new(seed)
} else { } else {
Random::default() Random::default()
}; };
let species = self.library.static_data().species().get(&self.species).unwrap(); let species = self.library.static_data().species().get(&self.species).unwrap().clone();
let form = species.get_default_form(); let form = species.get_default_form().clone();
let p = Pokemon::new( let p = Pokemon::new(
self.library, self.library,
species, species,
form, &form,
AbilityIndex { AbilityIndex {
hidden: false, hidden: false,
index: 0, index: 0,

View File

@ -4,12 +4,12 @@ use crate::dynamic_data::models::pokemon::Pokemon;
/// A list of Pokemon belonging to a trainer. /// A list of Pokemon belonging to a trainer.
#[derive(Debug)] #[derive(Debug)]
pub struct PokemonParty<'pokemon, 'library> { pub struct PokemonParty {
/// The underlying list of Pokemon. /// The underlying list of Pokemon.
pokemon: Vec<Option<Arc<Pokemon<'pokemon, 'library>>>>, pokemon: Vec<Option<Arc<Pokemon>>>,
} }
impl<'own, 'library> PokemonParty<'own, 'library> { impl<'own, 'library> PokemonParty {
/// Instantiates a party with a set size. /// Instantiates a party with a set size.
pub fn new(size: usize) -> Self { pub fn new(size: usize) -> Self {
let mut pokemon = Vec::with_capacity(size); let mut pokemon = Vec::with_capacity(size);
@ -20,12 +20,12 @@ impl<'own, 'library> PokemonParty<'own, 'library> {
} }
/// Instantiates a party with a list. /// Instantiates a party with a list.
pub fn new_from_vec(pokemon: Vec<Option<Arc<Pokemon<'own, 'library>>>>) -> Self { pub fn new_from_vec(pokemon: Vec<Option<Arc<Pokemon>>>) -> Self {
Self { pokemon } Self { pokemon }
} }
/// Gets a Pokemon at an index in the party. /// Gets a Pokemon at an index in the party.
pub fn at(&self, index: usize) -> &Option<Arc<Pokemon<'own, 'library>>> { pub fn at(&self, index: usize) -> &Option<Arc<Pokemon>> {
let opt = self.pokemon.get(index); let opt = self.pokemon.get(index);
if let Some(v) = opt { if let Some(v) = opt {
v v
@ -40,11 +40,7 @@ impl<'own, 'library> PokemonParty<'own, 'library> {
} }
/// Sets the Pokemon at an index to a Pokemon, returning the old Pokemon. /// Sets the Pokemon at an index to a Pokemon, returning the old Pokemon.
pub fn swap_into( pub fn swap_into(&mut self, index: usize, pokemon: Option<Arc<Pokemon>>) -> Option<Arc<Pokemon>> {
&mut self,
index: usize,
pokemon: Option<Arc<Pokemon<'own, 'library>>>,
) -> Option<Arc<Pokemon<'own, 'library>>> {
if index >= self.pokemon.len() { if index >= self.pokemon.len() {
return pokemon; return pokemon;
} }
@ -69,7 +65,7 @@ impl<'own, 'library> PokemonParty<'own, 'library> {
} }
/// Gets the underlying list of Pokemon. /// Gets the underlying list of Pokemon.
pub fn pokemon(&self) -> &Vec<Option<Arc<Pokemon<'own, 'library>>>> { pub fn pokemon(&self) -> &Vec<Option<Arc<Pokemon>>> {
&self.pokemon &self.pokemon
} }

View File

@ -86,7 +86,7 @@ pub struct ScriptSourceData {
} }
/// A script source is a struct on which we can trigger scripts to be run from. /// A script source is a struct on which we can trigger scripts to be run from.
pub trait ScriptSource<'a> { pub trait ScriptSource {
/// Gets an iterator over all the scripts that are relevant to this script source. If the data /// Gets an iterator over all the scripts that are relevant to this script source. If the data
/// has not been initialised, it will do so here. /// has not been initialised, it will do so here.
fn get_script_iterator(&self) -> ScriptIterator { fn get_script_iterator(&self) -> ScriptIterator {

View File

@ -5,7 +5,7 @@ use crate::dynamic_data::script_handling::script_set::ScriptSet;
use crate::{PkmnResult, StringKey}; use crate::{PkmnResult, StringKey};
/// This trait adds a bunch of helper functions to deal with volatile scripts on a struct. /// This trait adds a bunch of helper functions to deal with volatile scripts on a struct.
pub trait VolatileScriptsOwner<'a> { pub trait VolatileScriptsOwner {
/// Return the [`ScriptSet`] that are our volatile scripts. /// Return the [`ScriptSet`] that are our volatile scripts.
fn volatile_scripts(&self) -> &Arc<ScriptSet>; fn volatile_scripts(&self) -> &Arc<ScriptSet>;
/// Loads a volatile script by name. /// Loads a volatile script by name.

View File

@ -1,13 +1,13 @@
use std::intrinsics::transmute; use std::intrinsics::transmute;
use crate::dynamic_data::{LearnedMove, MoveLearnMethod, Pokemon, TurnChoice}; use crate::dynamic_data::LearnedMove;
use crate::script_implementations::wasm::export_registry::register; use crate::script_implementations::wasm::export_registry::register;
use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::extern_ref::ExternRef;
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
use crate::static_data::MoveData; use crate::static_data::MoveData;
register! { register! {
fn learned_move_get_learn_method<'a>( fn learned_move_get_learn_method(
env: &WebAssemblyEnv, env: &WebAssemblyEnv,
turn_choice: ExternRef<LearnedMove>, turn_choice: ExternRef<LearnedMove>,
) -> u8 { ) -> u8 {
@ -16,7 +16,7 @@ register! {
} }
} }
fn learned_move_get_move_data<'a>( fn learned_move_get_move_data(
env: &WebAssemblyEnv, env: &WebAssemblyEnv,
turn_choice: ExternRef<LearnedMove>, turn_choice: ExternRef<LearnedMove>,
) -> ExternRef<MoveData> { ) -> ExternRef<MoveData> {

View File

@ -1,6 +1,6 @@
use std::mem::transmute; use std::mem::transmute;
use crate::dynamic_data::{DamageSource, DynamicLibrary, Pokemon}; use crate::dynamic_data::{DynamicLibrary, Pokemon};
use crate::script_implementations::wasm::export_registry::register; use crate::script_implementations::wasm::export_registry::register;
use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::extern_ref::ExternRef;
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;

View File

@ -7,10 +7,10 @@ use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
register! { register! {
fn turn_choice_get_user<'a>( fn turn_choice_get_user(
env: &WebAssemblyEnv, env: &WebAssemblyEnv,
turn_choice: ExternRef<TurnChoice<'a, 'a>>, turn_choice: ExternRef<TurnChoice>,
) -> ExternRef<Pokemon<'a, 'a>> { ) -> ExternRef<Pokemon> {
let turn_choice = turn_choice.value(env).unwrap(); let turn_choice = turn_choice.value(env).unwrap();
ExternRef::new(env.data().as_ref(), turn_choice.user().as_ref().deref()) ExternRef::new(env.data().as_ref(), turn_choice.user().as_ref().deref())
} }
@ -28,10 +28,10 @@ register! {
} }
} }
fn turn_choice_move_used_move<'a>( fn turn_choice_move_used_move(
env: &WebAssemblyEnv, env: &WebAssemblyEnv,
turn_choice: ExternRef<TurnChoice<'a, 'a>>, turn_choice: ExternRef<TurnChoice>,
) -> ExternRef<LearnedMove<'a>> { ) -> ExternRef<LearnedMove> {
if let TurnChoice::Move(d) = turn_choice.value(env).unwrap() { if let TurnChoice::Move(d) = turn_choice.value(env).unwrap() {
return ExternRef::new(env.data().as_ref(), d.used_move().as_ref()); return ExternRef::new(env.data().as_ref(), d.used_move().as_ref());
} }

View File

@ -1,12 +1,8 @@
use std::ffi::CString; use std::ffi::CString;
use std::mem::{align_of, forget}; use std::mem::{align_of, forget};
use std::process::exit;
use wasmer::{Exports, Store}; use wasmer::{Exports, Store};
pub(crate) use register;
pub(crate) use register_func_with_env;
use crate::dynamic_data::DynamicLibrary; use crate::dynamic_data::DynamicLibrary;
use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::extern_ref::ExternRef;
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
@ -35,7 +31,7 @@ macro_rules! register_func_with_env {
macro_rules! register { macro_rules! register {
( (
$( $(
fn $name:ident$(<$($lt:lifetime)*>)?($($par:ident: $par_type:ty),*$(,)?) $(-> $return:ty)? $block:block fn $name:ident($($par:ident: $par_type:ty),*$(,)?) $(-> $return:ty)? $block:block
)* )*
) => { ) => {
pub(crate) fn register(exports: &mut crate::script_implementations::wasm::export_registry::Exports, pub(crate) fn register(exports: &mut crate::script_implementations::wasm::export_registry::Exports,
@ -43,7 +39,7 @@ macro_rules! register {
env: crate::script_implementations::wasm::script_resolver::WebAssemblyEnv) { env: crate::script_implementations::wasm::script_resolver::WebAssemblyEnv) {
$( $(
fn $name<$($($lt)*)*>( fn $name(
$( $(
$par: $par_type, $par: $par_type,
)* )*
@ -55,6 +51,9 @@ macro_rules! register {
}; };
} }
pub(crate) use register;
pub(crate) use register_func_with_env;
pub(crate) fn register_webassembly_funcs(exports: &mut Exports, store: &Store, env: WebAssemblyEnv) { pub(crate) fn register_webassembly_funcs(exports: &mut Exports, store: &Store, env: WebAssemblyEnv) {
register_func_with_env!(exports, store, _print, env); register_func_with_env!(exports, store, _print, env);
register_func_with_env!(exports, store, _error, env); register_func_with_env!(exports, store, _error, env);

View File

@ -21,10 +21,6 @@ impl<T: UniqueTypeId<u64>> ExternRef<T> {
} }
} }
pub(crate) fn index(&self) -> u32 {
self.index
}
/// Creates an ExternRef with a given resolver. This can be used in cases where we do not have an environment variable. /// Creates an ExternRef with a given resolver. This can be used in cases where we do not have an environment variable.
pub(crate) fn new_with_resolver(resolver: &WebAssemblyScriptResolver, value: &T) -> Self { pub(crate) fn new_with_resolver(resolver: &WebAssemblyScriptResolver, value: &T) -> Self {
Self { Self {

View File

@ -1,12 +1,11 @@
use std::any::Any; use std::any::Any;
use std::mem::{align_of, size_of};
use std::sync::atomic::{AtomicBool, AtomicPtr, AtomicUsize}; use std::sync::atomic::{AtomicBool, AtomicPtr, AtomicUsize};
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use hashbrown::HashSet; use hashbrown::HashSet;
use wasmer::NativeFunc; use wasmer::NativeFunc;
use crate::dynamic_data::{DynamicLibrary, Pokemon, Script, TurnChoice}; use crate::dynamic_data::{DynamicLibrary, Script, TurnChoice};
use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef}; use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef};
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnvironmentData; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnvironmentData;
use crate::script_implementations::wasm::WebAssemblyScriptCapabilities; use crate::script_implementations::wasm::WebAssemblyScriptCapabilities;
@ -92,8 +91,7 @@ impl Script for WebAssemblyScript {
let env = self.environment.upgrade().unwrap(); let env = self.environment.upgrade().unwrap();
let func = env.script_function_cache().on_before_turn(&env); let func = env.script_function_cache().on_before_turn(&env);
if let Some(func) = func { if let Some(func) = func {
func.call(self.self_ptr, ExternRef::new(env.as_ref(), choice).index()) func.call(self.self_ptr, ExternRef::new(env.as_ref(), choice)).unwrap();
.unwrap();
} }
} }

View File

@ -58,5 +58,5 @@ macro_rules! script_function_cache {
script_function_cache! { script_function_cache! {
on_initialize -> NativeFunc<(u32, ExternRef<DynamicLibrary>, VecExternRef<EffectParameter>), ()> on_initialize -> NativeFunc<(u32, ExternRef<DynamicLibrary>, VecExternRef<EffectParameter>), ()>
on_before_turn -> NativeFunc<(u32, u32), ()> on_before_turn -> NativeFunc<(u32, ExternRef<TurnChoice>), ()>
} }

View File

@ -1,3 +1,5 @@
use std::sync::Arc;
use indexmap::IndexMap; use indexmap::IndexMap;
use crate::static_data::Ability; use crate::static_data::Ability;
@ -8,7 +10,7 @@ use crate::StringKey;
#[derive(Debug)] #[derive(Debug)]
pub struct AbilityLibrary { pub struct AbilityLibrary {
/// The underlying map for the library. /// The underlying map for the library.
map: IndexMap<StringKey, Box<Ability>>, map: IndexMap<StringKey, Arc<Ability>>,
} }
impl AbilityLibrary { impl AbilityLibrary {
@ -20,11 +22,11 @@ impl AbilityLibrary {
} }
} }
impl DataLibrary<'_, Box<Ability>> for AbilityLibrary { impl DataLibrary<'_, Ability> for AbilityLibrary {
fn map(&self) -> &IndexMap<StringKey, Box<Ability>> { fn map(&self) -> &IndexMap<StringKey, Arc<Ability>> {
&self.map &self.map
} }
fn get_modify(&mut self) -> &mut IndexMap<StringKey, Box<Ability>> { fn get_modify(&mut self) -> &mut IndexMap<StringKey, Arc<Ability>> {
&mut self.map &mut self.map
} }
} }

View File

@ -1,3 +1,5 @@
use std::sync::Arc;
use indexmap::IndexMap; use indexmap::IndexMap;
use crate::Random; use crate::Random;
@ -7,13 +9,13 @@ use crate::StringKey;
/// by both key, while keeping their insertion order. /// by both key, while keeping their insertion order.
pub trait DataLibrary<'a, T: 'a> { pub trait DataLibrary<'a, T: 'a> {
/// Returns the underlying map. /// Returns the underlying map.
fn map(&self) -> &IndexMap<StringKey, T>; fn map(&self) -> &IndexMap<StringKey, Arc<T>>;
/// Returns the underlying map in mutable manner. /// Returns the underlying map in mutable manner.
fn get_modify(&mut self) -> &mut IndexMap<StringKey, T>; fn get_modify(&mut self) -> &mut IndexMap<StringKey, Arc<T>>;
/// Adds a new value to the library. /// Adds a new value to the library.
fn add(&mut self, key: &StringKey, value: T) { fn add(&mut self, key: &StringKey, value: T) {
self.get_modify().insert(key.clone(), value); self.get_modify().insert(key.clone(), Arc::new(value));
} }
/// Removes a value from the library. /// Removes a value from the library.
@ -22,20 +24,15 @@ pub trait DataLibrary<'a, T: 'a> {
} }
/// Gets a value from the library. /// Gets a value from the library.
fn get(&'a self, key: &StringKey) -> Option<&'a T> { fn get(&'a self, key: &StringKey) -> Option<&Arc<T>> {
self.map().get::<StringKey>(key) self.map().get::<StringKey>(key)
} }
/// Gets a value from the library. /// Gets a value from the library.
fn get_by_hash(&'a self, key: u32) -> Option<&'a T> { fn get_by_hash(&'a self, key: u32) -> Option<&Arc<T>> {
self.map().get::<u32>(&key) self.map().get::<u32>(&key)
} }
/// Gets a mutable value from the library.
fn get_mut(&mut self, key: &StringKey) -> Option<&mut T> {
self.get_modify().get_mut(key)
}
/// Gets the amount of values in the library. /// Gets the amount of values in the library.
fn len(&self) -> usize { fn len(&self) -> usize {
self.map().len() self.map().len()
@ -46,7 +43,7 @@ pub trait DataLibrary<'a, T: 'a> {
} }
/// Gets a random value from the library. /// Gets a random value from the library.
fn random_value(&self, rand: &mut Random) -> &T { fn random_value(&self, rand: &mut Random) -> &Arc<T> {
let i = rand.get_between(0, self.len() as i32); let i = rand.get_between(0, self.len() as i32);
return self.map().get_index(i as usize).unwrap().1; return self.map().get_index(i as usize).unwrap().1;
} }

View File

@ -1,3 +1,5 @@
use std::sync::Arc;
use indexmap::IndexMap; use indexmap::IndexMap;
use crate::static_data::DataLibrary; use crate::static_data::DataLibrary;
@ -9,7 +11,7 @@ use crate::StringKey;
#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] #[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))]
pub struct ItemLibrary { pub struct ItemLibrary {
/// The underlying data structure. /// The underlying data structure.
map: IndexMap<StringKey, Box<Item>>, map: IndexMap<StringKey, Arc<Item>>,
} }
impl ItemLibrary { impl ItemLibrary {
@ -21,12 +23,12 @@ impl ItemLibrary {
} }
} }
impl DataLibrary<'_, Box<Item>> for ItemLibrary { impl DataLibrary<'_, Item> for ItemLibrary {
fn map(&self) -> &IndexMap<StringKey, Box<Item>> { fn map(&self) -> &IndexMap<StringKey, Arc<Item>> {
&self.map &self.map
} }
fn get_modify(&mut self) -> &mut IndexMap<StringKey, Box<Item>> { fn get_modify(&mut self) -> &mut IndexMap<StringKey, Arc<Item>> {
&mut self.map &mut self.map
} }
} }

View File

@ -1,3 +1,5 @@
use std::sync::Arc;
use indexmap::IndexMap; use indexmap::IndexMap;
use crate::static_data::DataLibrary; use crate::static_data::DataLibrary;
@ -9,7 +11,7 @@ use crate::StringKey;
#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] #[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))]
pub struct MoveLibrary { pub struct MoveLibrary {
/// The underlying map. /// The underlying map.
map: IndexMap<StringKey, MoveData>, map: IndexMap<StringKey, Arc<MoveData>>,
} }
impl MoveLibrary { impl MoveLibrary {
@ -22,10 +24,10 @@ impl MoveLibrary {
} }
impl DataLibrary<'_, MoveData> for MoveLibrary { impl DataLibrary<'_, MoveData> for MoveLibrary {
fn map(&self) -> &IndexMap<StringKey, MoveData> { fn map(&self) -> &IndexMap<StringKey, Arc<MoveData>> {
&self.map &self.map
} }
fn get_modify(&mut self) -> &mut IndexMap<StringKey, MoveData> { fn get_modify(&mut self) -> &mut IndexMap<StringKey, Arc<MoveData>> {
&mut self.map &mut self.map
} }
} }

View File

@ -1,3 +1,5 @@
use std::sync::Arc;
use indexmap::IndexMap; use indexmap::IndexMap;
use crate::static_data::DataLibrary; use crate::static_data::DataLibrary;
@ -9,7 +11,7 @@ use crate::StringKey;
#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] #[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))]
pub struct SpeciesLibrary { pub struct SpeciesLibrary {
/// The underlying map. /// The underlying map.
map: IndexMap<StringKey, Box<Species>>, map: IndexMap<StringKey, Arc<Species>>,
} }
impl SpeciesLibrary { impl SpeciesLibrary {
@ -21,11 +23,11 @@ impl SpeciesLibrary {
} }
} }
impl<'a> DataLibrary<'a, Box<Species>> for SpeciesLibrary { impl<'a> DataLibrary<'a, Species> for SpeciesLibrary {
fn map(&self) -> &IndexMap<StringKey, Box<Species>> { fn map(&self) -> &IndexMap<StringKey, Arc<Species>> {
&self.map &self.map
} }
fn get_modify(&mut self) -> &mut IndexMap<StringKey, Box<Species>> { fn get_modify(&mut self) -> &mut IndexMap<StringKey, Arc<Species>> {
&mut self.map &mut self.map
} }
} }

View File

@ -1,3 +1,5 @@
use std::sync::Arc;
use hashbrown::HashMap; use hashbrown::HashMap;
use crate::static_data::Statistic; use crate::static_data::Statistic;
@ -60,7 +62,7 @@ impl Nature {
#[derive(Debug)] #[derive(Debug)]
pub struct NatureLibrary { pub struct NatureLibrary {
/// The underlying data structure. /// The underlying data structure.
map: HashMap<StringKey, Nature>, map: HashMap<StringKey, Arc<Nature>>,
} }
impl NatureLibrary { impl NatureLibrary {
@ -73,20 +75,20 @@ impl NatureLibrary {
/// Adds a new nature with name to the library. /// Adds a new nature with name to the library.
pub fn load_nature(&mut self, name: StringKey, nature: Nature) { pub fn load_nature(&mut self, name: StringKey, nature: Nature) {
self.map.insert(name, nature); self.map.insert(name, Arc::new(nature));
} }
/// Gets a nature by name. /// Gets a nature by name.
pub fn get_nature(&self, key: &StringKey) -> Option<&Nature> { pub fn get_nature(&self, key: &StringKey) -> Option<&Arc<Nature>> {
self.map.get(key) self.map.get(key)
} }
/// Finds a nature name by nature. /// Finds a nature name by nature.
pub fn get_nature_name(&self, nature: &Nature) -> StringKey { pub fn get_nature_name(&self, nature: &Arc<Nature>) -> StringKey {
for kv in &self.map { for kv in &self.map {
// As natures can't be copied, and should always be the same reference as the value // As natures can't be copied, and should always be the same reference as the value
// in the map, we just compare by reference. // in the map, we just compare by reference.
if std::ptr::eq(kv.1, nature) { if Arc::ptr_eq(kv.1, nature) {
return kv.0.clone(); return kv.0.clone();
} }
} }

View File

@ -1,3 +1,5 @@
use std::sync::Arc;
use hashbrown::{HashMap, HashSet}; use hashbrown::{HashMap, HashSet};
use crate::static_data::Form; use crate::static_data::Form;
@ -21,7 +23,7 @@ pub struct Species {
/// uncatchable. /// uncatchable.
capture_rate: u8, capture_rate: u8,
/// The forms that belong to this Pokemon. /// The forms that belong to this Pokemon.
forms: HashMap<StringKey, Form>, forms: HashMap<StringKey, Arc<Form>>,
/// The arbitrary flags that can be set on a Pokemon for script use. /// The arbitrary flags that can be set on a Pokemon for script use.
flags: HashSet<StringKey>, flags: HashSet<StringKey>,
} }
@ -46,7 +48,7 @@ impl Species {
flags: HashSet<StringKey>, flags: HashSet<StringKey>,
) -> Species { ) -> Species {
let mut forms = HashMap::with_capacity(1); let mut forms = HashMap::with_capacity(1);
forms.insert_unique_unchecked(get_default_key(), default_form); forms.insert_unique_unchecked(get_default_key(), Arc::new(default_form));
Species { Species {
id, id,
name: name.clone(), name: name.clone(),
@ -80,7 +82,7 @@ impl Species {
self.capture_rate self.capture_rate
} }
/// The forms that belong to this Pokemon. /// The forms that belong to this Pokemon.
pub fn forms(&self) -> &HashMap<StringKey, Form> { pub fn forms(&self) -> &HashMap<StringKey, Arc<Form>> {
&self.forms &self.forms
} }
/// The arbitrary flags that can be set on a Pokemon for script use. /// The arbitrary flags that can be set on a Pokemon for script use.
@ -90,16 +92,16 @@ impl Species {
/// Adds a new form to the species. /// Adds a new form to the species.
pub fn add_form(&mut self, id: StringKey, form: Form) { pub fn add_form(&mut self, id: StringKey, form: Form) {
self.forms.insert(id, form); self.forms.insert(id, Arc::new(form));
} }
/// Gets a form by name. /// Gets a form by name.
pub fn get_form(&self, id: &StringKey) -> Option<&Form> { pub fn get_form(&self, id: &StringKey) -> Option<&Arc<Form>> {
self.forms.get(id) self.forms.get(id)
} }
/// Gets the form the Pokemon will have by default, if no other form is specified. /// Gets the form the Pokemon will have by default, if no other form is specified.
pub fn get_default_form(&self) -> &Form { pub fn get_default_form(&self) -> &Arc<Form> {
self.forms.get(&get_default_key()).unwrap() self.forms.get(&get_default_key()).unwrap()
} }

View File

@ -115,10 +115,7 @@ pub fn load_items(path: &String, lib: &mut ItemLibrary) {
} }
} }
lib.add( lib.add(&name, Item::new(&name, category, battle_category, price as i32, flags));
&name,
Box::new(Item::new(&name, category, battle_category, price as i32, flags)),
);
} }
} }
@ -161,7 +158,7 @@ pub fn load_abilities(path: &String, ability_library: &mut AbilityLibrary) {
} }
} }
ability_library.add(&name, Box::new(Ability::new(&name, &effect, parameters))); ability_library.add(&name, Ability::new(&name, &effect, parameters));
} }
} }
@ -262,7 +259,7 @@ pub fn load_species(path: &String, library: &mut StaticData) {
let default_form_value = &forms["default"]; let default_form_value = &forms["default"];
let default_form = parse_form("default".into(), default_form_value, library); let default_form = parse_form("default".into(), default_form_value, library);
let species = Box::new(Species::new( let species = Species::new(
id as u16, id as u16,
&name, &name,
gender_rate as f32, gender_rate as f32,
@ -270,7 +267,7 @@ pub fn load_species(path: &String, library: &mut StaticData) {
catch_rate as u8, catch_rate as u8,
default_form, default_form,
Default::default(), Default::default(),
)); );
library.species_mut().add(&name, species); library.species_mut().add(&name, species);
} }
} }

View File

@ -43,13 +43,13 @@ struct TestPokemon {
} }
impl TestCase { impl TestCase {
pub fn run_test(&self, library: &DynamicLibrary) { pub fn run_test(&self, library: Arc<DynamicLibrary>) {
let mut parties = Vec::new(); let mut parties = Vec::new();
for party in &self.battle_setup.parties { for party in &self.battle_setup.parties {
let pokemon = party let pokemon = party
.pokemon .pokemon
.iter() .iter()
.map(|a| Some(Arc::new(a.to_pokemon(library)))) .map(|a| Some(Arc::new(a.to_pokemon(library.clone()))))
.collect(); .collect();
let indices = party.indices.iter().map(|a| (a[0], a[1])).collect(); let indices = party.indices.iter().map(|a| (a[0], a[1])).collect();
parties.push((Arc::new(PokemonParty::new_from_vec(pokemon)), indices)); parties.push((Arc::new(PokemonParty::new_from_vec(pokemon)), indices));
@ -73,7 +73,7 @@ impl TestCase {
} }
impl TestPokemon { impl TestPokemon {
fn to_pokemon<'a>(&'a self, library: &'a DynamicLibrary) -> Pokemon { fn to_pokemon(&self, library: Arc<DynamicLibrary>) -> Pokemon {
let mut builder = PokemonBuilder::new(library, StringKey::new(self.species.as_str()), self.level); let mut builder = PokemonBuilder::new(library, StringKey::new(self.species.as_str()), self.level);
for move_name in &self.moves { for move_name in &self.moves {
builder = builder.learn_move(StringKey::new(move_name)); builder = builder.learn_move(StringKey::new(move_name));

View File

@ -16,16 +16,18 @@ use crate::common::{library_loader, TestCase};
pub mod common; pub mod common;
static LIBRARY: OnceCell<DynamicLibrary> = OnceCell::uninit(); static LIBRARY: OnceCell<Arc<DynamicLibrary>> = OnceCell::uninit();
fn get_library<'a>() -> &'a DynamicLibrary { fn get_library<'a>() -> Arc<DynamicLibrary> {
LIBRARY.get_or_init(|| { LIBRARY
.get_or_init(|| {
let start_time = chrono::Utc::now(); let start_time = chrono::Utc::now();
let lib = library_loader::load_library(); let lib = library_loader::load_library();
let end_time = chrono::Utc::now(); let end_time = chrono::Utc::now();
println!("Built library in {} ms", (end_time - start_time).num_milliseconds()); println!("Built library in {} ms", (end_time - start_time).num_milliseconds());
lib Arc::new(lib)
}) })
.clone()
} }
#[test] #[test]
@ -73,7 +75,7 @@ fn validate_script_2() {
.unwrap() .unwrap()
.unwrap(); .unwrap();
let user = Arc::new( let user = Arc::new(
PokemonBuilder::new(&lib, "charizard".into(), 100) PokemonBuilder::new(lib, "charizard".into(), 100)
.learn_move("fire_blast".into()) .learn_move("fire_blast".into())
.build(), .build(),
); );