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.
#[derive(Debug)]
struct CommonChoiceData<'user, 'library> {
struct CommonChoiceData {
/// 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.
speed: u32,
/// 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.
#[derive(Debug)]
#[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.
Move(MoveChoice<'user, 'library>),
Move(MoveChoice),
/// 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.
Switch(SwitchChoice<'user, 'library>),
Switch(SwitchChoice),
/// 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.
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.
fn choice_data(&self) -> &CommonChoiceData<'user, 'library> {
fn choice_data(&self) -> &CommonChoiceData {
match self {
TurnChoice::Move(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.
fn choice_data_mut(&mut self) -> &mut Box<CommonChoiceData<'user, 'library>> {
fn choice_data_mut(&mut self) -> &mut Box<CommonChoiceData> {
match self {
TurnChoice::Move(data) => &mut data.choice_data,
TurnChoice::Item(data) => &mut data.choice_data,
@ -66,7 +66,7 @@ impl<'user, 'library> TurnChoice<'user, 'library> {
}
/// 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
}
@ -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
/// 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 {
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 {
match self {
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.
#[derive(Debug)]
pub struct MoveChoice<'user, 'library> {
pub struct MoveChoice {
/// The move that is used for this choice.
used_move: Arc<LearnedMove<'library>>,
used_move: Arc<LearnedMove>,
/// The side this move is aimed at.
target_side: u8,
/// 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.
priority: i8,
/// 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.
pub fn new(
user: Arc<Pokemon<'user, 'library>>,
used_move: Arc<LearnedMove<'library>>,
target_side: u8,
target_index: u8,
) -> Self {
pub fn new(user: Arc<Pokemon>, used_move: Arc<LearnedMove>, target_side: u8, target_index: u8) -> Self {
Self {
used_move,
target_side,
@ -200,7 +195,7 @@ impl<'user, 'library> MoveChoice<'user, 'library> {
}
/// 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
}
@ -221,7 +216,7 @@ impl<'user, 'library> MoveChoice<'user, 'library> {
&mut self.priority
}
/// The user of the choice.
pub fn user(&self) -> &Arc<Pokemon<'user, 'library>> {
pub fn user(&self) -> &Arc<Pokemon> {
&self.choice_data.user
}
/// 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 {
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.
#[derive(Debug)]
pub struct ItemChoice<'user, 'library> {
pub struct ItemChoice {
/// 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.
pub fn new(user: Arc<Pokemon<'user, 'library>>) -> Self {
pub fn new(user: Arc<Pokemon>) -> Self {
Self {
choice_data: Box::new(CommonChoiceData {
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 {
0
}
@ -289,14 +284,14 @@ impl<'user, 'library> ScriptSource<'user> for ItemChoice<'user, 'library> {
/// The data given when we select a switch choice.
#[derive(Debug)]
pub struct SwitchChoice<'user, 'library> {
pub struct SwitchChoice {
/// 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.
pub fn new(user: Arc<Pokemon<'user, 'library>>) -> Self {
pub fn new(user: Arc<Pokemon>) -> Self {
Self {
choice_data: Box::new(CommonChoiceData {
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 {
0
}
@ -327,14 +322,14 @@ impl<'user, 'library> ScriptSource<'user> for SwitchChoice<'user, 'library> {
/// The data given when we select a flee choice.
#[derive(Debug)]
pub struct FleeChoice<'user, 'library> {
pub struct FleeChoice {
/// 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.
pub fn new(user: Arc<Pokemon<'user, 'library>>) -> Self {
pub fn new(user: Arc<Pokemon>) -> Self {
Self {
choice_data: Box::new(CommonChoiceData {
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 {
0
}
@ -365,14 +360,14 @@ impl<'user, 'library> ScriptSource<'user> for FleeChoice<'user, 'library> {
/// The data given when we select a pass choice.
#[derive(Debug)]
pub struct PassChoice<'user, 'library> {
pub struct PassChoice {
/// 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.
pub fn new(user: Arc<Pokemon<'user, 'library>>) -> Self {
pub fn new(user: Arc<Pokemon>) -> Self {
Self {
choice_data: Box::new(CommonChoiceData {
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 {
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 {
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> {
Some(self.cmp(other))
}
}
impl<'user, 'library> Ord for TurnChoice<'user, 'library> {
impl Ord for TurnChoice {
fn cmp(&self, other: &Self) -> Ordering {
match self {
TurnChoice::Move(data) => {

View File

@ -1,4 +1,5 @@
use std::fmt::{Debug, Formatter};
use std::sync::Arc;
use crate::dynamic_data::DamageSource;
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
/// 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);
for f in &self.evt_hook_function {
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.
#[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.
Switch {
/// 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
index: u8,
/// 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.
Swap {
@ -67,23 +68,23 @@ pub enum Event<'own, 'battle, 'library> {
/// enjoy.
SpeciesChange {
/// The pokemon that changed species.
pokemon: &'own Pokemon<'battle, 'library>,
pokemon: &'own Pokemon,
/// The new species of the Pokemon.
species: &'own Species,
species: Arc<Species>,
/// 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.
FormChange {
/// The pokemon that changed forms.
pokemon: &'own Pokemon<'battle, 'library>,
pokemon: &'own Pokemon,
/// The new form of the Pokemon.
form: &'own Form,
},
/// This event happens when a Pokemon takes damage.
Damage {
/// The Pokemon that takes damage.
pokemon: &'own Pokemon<'battle, 'library>,
pokemon: &'own Pokemon,
/// The source of damage.
source: DamageSource,
/// 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
Heal {
/// The Pokemon that gets healed.
pokemon: &'own Pokemon<'battle, 'library>,
pokemon: &'own Pokemon,
/// The health of the Pokemon before the heal.
original_health: u32,
/// 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.
Faint {
/// 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.
MoveUse {
/// The data of the move used.
executing_move: &'own ExecutingMove<'own, 'battle, 'library>,
executing_move: &'own ExecutingMove,
},
/// This event happens when a Pokemon missed.
Miss {
/// The pokemon that missed.
user: &'own Pokemon<'battle, 'library>,
user: &'own Pokemon,
},
/// The turn is finished running, waiting for new input.
EndTurn,
/// A pokemon had its stat boost changed
StatBoostChange {
/// The pokemon that had its stat boosts changed.
user: &'own Pokemon<'battle, 'library>,
user: &'own Pokemon,
/// The statistic that changed.
stat: Statistic,
/// 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
/// moves in Pokemon actively mess with this order.
#[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
/// executed.
queue: Vec<Option<TurnChoice<'battle, 'library>>>,
queue: Vec<Option<TurnChoice>>,
/// The current index of the turn we need to execute next.
current: usize,
}
impl<'battle, 'library> ChoiceQueue<'battle, 'library> {
impl ChoiceQueue {
/// 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 }
}
/// 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
/// 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();
self.current += 1;
c.unwrap()
}
/// 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()
}
@ -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.
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()]
}
}

View File

@ -8,10 +8,10 @@ use crate::dynamic_data::Pokemon;
use crate::static_data::MoveTarget;
/// 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.
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);
for side in battle.sides() {
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,
/// the Pokemon left of it, the Pokemon right of it, and the Pokemon opposite of it.
fn get_all_adjacent_opponent<'b, 'library>(
side: u8,
index: u8,
battle: &Battle<'b, 'library>,
) -> TargetList<'b, 'library> {
fn get_all_adjacent_opponent<'b, 'library>(side: u8, index: u8, battle: &Battle) -> TargetList {
let left = index as i32 - 1;
let right = index + 1;
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
/// 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 right = index + 1;
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.
pub fn resolve_targets<'b, 'library>(
side: u8,
index: u8,
target: MoveTarget,
battle: &Battle<'b, 'library>,
) -> TargetList<'b, 'library> {
pub fn resolve_targets<'b, 'library>(side: u8, index: u8, target: MoveTarget, battle: &Battle) -> TargetList {
match target {
// 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.

View File

@ -12,7 +12,7 @@ use crate::dynamic_data::Pokemon;
use crate::static_data::{DataLibrary, MoveCategory};
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.
pub(crate) fn run_turn(&self) -> PkmnResult<()> {
let choice_queue = self.current_turn_queue();
@ -62,7 +62,7 @@ impl<'own, 'library> Battle<'own, 'library> {
}
/// 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.
if let TurnChoice::Pass(..) = choice {
return Ok(());
@ -91,7 +91,7 @@ impl<'own, 'library> Battle<'own, 'library> {
}
/// 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 used_move = choice.used_move();
let move_data = {
@ -111,11 +111,11 @@ impl<'own, 'library> Battle<'own, 'library> {
return Ok(());
}
let mut executing_move = ExecutingMove::new(
&targets,
targets.clone(),
number_of_hits,
choice.user().clone(),
used_move.clone(),
move_data,
move_data.clone(),
choice.script().clone(),
);
let mut prevented = false;
@ -148,11 +148,7 @@ impl<'own, 'library> Battle<'own, 'library> {
}
/// Executes a move turn choice on a single target.
fn handle_move_for_target(
&self,
executing_move: &mut ExecutingMove<'_, 'own, 'library>,
target: &Arc<Pokemon<'own, 'library>>,
) -> PkmnResult<()> {
fn handle_move_for_target(&self, executing_move: &mut ExecutingMove, target: &Arc<Pokemon>) -> PkmnResult<()> {
{
let mut fail = false;
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>,
/// The Misc Library holds minor functions that do not fall in any of the other libraries and
/// 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.
script_resolver: Box<dyn ScriptResolver>,
@ -40,7 +40,7 @@ impl DynamicLibrary {
static_data: StaticData,
stat_calculator: Box<dyn BattleStatCalculator>,
damage_calculator: Box<dyn DamageLibrary>,
misc_library: Box<dyn MiscLibrary<'static>>,
misc_library: Box<dyn MiscLibrary>,
script_resolver: Box<dyn ScriptResolver>,
) -> 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
/// calculators.
pub fn misc_library(&self) -> &dyn MiscLibrary<'static> {
pub fn misc_library(&self) -> &dyn MiscLibrary {
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
/// combinations, returns None. Note that ItemScripts are immutable, as their script should be
/// 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!()
}
}

View File

@ -10,35 +10,26 @@ use crate::static_data::{MoveCategory, MoveData, MoveTarget, SecondaryEffect};
use crate::StringKey;
/// 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.
fn can_flee(&self, choice: &TurnChoice) -> bool;
/// Returns the move we need to use if we can't use another move. Typically Struggle.
fn replacement_move<'func>(
&'func self,
user: &Arc<Pokemon<'func, 'library>>,
target_side: u8,
target_index: u8,
) -> TurnChoice<'func, 'library>;
fn replacement_move<'func>(&'func self, user: &Arc<Pokemon>, target_side: u8, target_index: u8) -> TurnChoice;
// TODO: can evolve from level up?
// TODO: get time
}
/// A gen 7 implementation for the MiscLibrary.
#[derive(Debug)]
pub struct Gen7MiscLibrary<'library> {
/// 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,
pub struct Gen7MiscLibrary {
/// 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.
pub fn new() -> Self {
let struggle_data = Box::new(MoveData::new(
let struggle_data = Arc::new(MoveData::new(
&StringKey::new("struggle"),
0.into(),
MoveCategory::Physical,
@ -50,40 +41,23 @@ impl<'library> Gen7MiscLibrary<'library> {
Some(SecondaryEffect::new(-1.0, StringKey::new("struggle"), vec![])),
HashSet::new(),
));
let struggle_ptr = Box::into_raw(struggle_data);
let struggle_learned_move = Arc::new(LearnedMove::new(unsafe { &*struggle_ptr }, MoveLearnMethod::Unknown));
Self {
struggle_data: struggle_ptr,
struggle_learned_move,
}
let struggle_learned_move = Arc::new(LearnedMove::new(&struggle_data.clone(), MoveLearnMethod::Unknown));
Self { struggle_learned_move }
}
}
impl<'library> Default for Gen7MiscLibrary<'library> {
impl Default for Gen7MiscLibrary {
fn default() -> Self {
Self::new()
}
}
impl<'library> Drop for Gen7MiscLibrary<'library> {
fn drop(&mut self) {
unsafe {
let _ = Box::from_raw(self.struggle_data as *mut MoveData);
}
}
}
impl<'library> MiscLibrary<'library> for Gen7MiscLibrary<'library> {
impl MiscLibrary for Gen7MiscLibrary {
fn can_flee(&self, _choice: &TurnChoice) -> bool {
todo!()
}
fn replacement_move<'func>(
&'func self,
user: &Arc<Pokemon<'func, 'library>>,
target_side: u8,
target_index: u8,
) -> TurnChoice<'func, 'library> {
fn replacement_move<'func>(&'func self, user: &Arc<Pokemon>, target_side: u8, target_index: u8) -> TurnChoice {
self.struggle_learned_move.restore_all_uses();
TurnChoice::Move(MoveChoice::new(
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.
#[derive(Debug)]
pub struct Battle<'own, 'library> {
pub struct Battle {
/// The library the battle uses for handling.
library: &'own DynamicLibrary,
library: Arc<DynamicLibrary>,
/// 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.
can_flee: bool,
/// 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.
pokemon_per_side: u8,
/// A list of all sides in the battle.
sides: Vec<BattleSide<'own, 'library>>,
sides: Vec<BattleSide>,
/// The RNG used for the battle.
random: BattleRandom,
/// 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.
has_ended: AtomicBool,
/// 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>,
}
impl<'own, 'library> Battle<'own, 'library> {
impl<'own, 'library> Battle {
/// Initializes a new battle.
pub fn new(
library: &'own DynamicLibrary,
parties: Vec<BattleParty<'own, 'library>>,
library: Arc<DynamicLibrary>,
parties: Vec<BattleParty>,
can_flee: bool,
number_of_sides: u8,
pokemon_per_side: u8,
@ -104,11 +104,11 @@ impl<'own, 'library> Battle<'own, 'library> {
}
/// The library the battle uses for handling.
pub fn library(&self) -> &'own DynamicLibrary {
self.library
pub fn library(&self) -> &Arc<DynamicLibrary> {
&self.library
}
/// 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
}
/// Whether or not Pokemon can flee from the battle.
@ -124,11 +124,11 @@ impl<'own, 'library> Battle<'own, 'library> {
self.pokemon_per_side
}
/// A list of all sides in the battle.
pub fn sides(&self) -> &Vec<BattleSide<'own, 'library>> {
pub fn sides(&self) -> &Vec<BattleSide> {
&self.sides
}
/// A mutable list of all sides in the battle.
pub fn sides_mut(&mut self) -> &mut Vec<BattleSide<'own, 'library>> {
pub fn sides_mut(&mut self) -> &mut Vec<BattleSide> {
&mut self.sides
}
/// The RNG used for the battle.
@ -156,12 +156,12 @@ impl<'own, 'library> Battle<'own, 'library> {
self.last_turn_time.load(Ordering::Relaxed)
}
/// 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
}
/// 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);
side?;
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.
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) {
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> {
&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 {
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
/// on the field attached.
#[derive(Debug)]
pub struct BattleParty<'own, 'library> {
pub struct BattleParty {
/// 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)
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
/// 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 {
party,
responsible_indices,
@ -44,7 +44,7 @@ impl<'own, 'library> BattleParty<'own, 'library> {
}
/// 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)
}
}

View File

@ -18,22 +18,22 @@ use crate::{script_hook, PkmnResult, StringKey};
/// A side on a battle.
#[derive(Debug)]
pub struct BattleSide<'own, 'library> {
pub struct BattleSide {
/// The index of the side on the battle.
index: u8,
/// The number of Pokemon that can be on the side.
pokemon_per_side: u8,
/// 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.
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
/// has lost the battle.
fillable_slots: Vec<AtomicBool>,
/// The number of choices that are set.
choices_set: AtomicU8,
/// A reference to the battle we're part of.
battle: *mut Battle<'own, 'library>,
battle: *mut Battle,
/// Whether or not this side has fled.
has_fled_battle: bool,
/// The volatile scripts that are attached to the side.
@ -43,7 +43,7 @@ pub struct BattleSide<'own, 'library> {
script_source_data: RwLock<ScriptSourceData>,
}
impl<'own, 'library> BattleSide<'own, 'library> {
impl<'own, 'library> BattleSide {
/// Instantiates a battle side.
pub fn new(index: u8, pokemon_per_side: u8) -> Self {
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.
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;
}
@ -86,11 +86,11 @@ impl<'own, 'library> BattleSide<'own, 'library> {
self.pokemon_per_side
}
/// 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()
}
/// 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
}
/// 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)
}
/// 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() }
}
/// 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.
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() {
if let Some(pokemon) = pokemon_slot {
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.
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];
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.
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() {
if std::ptr::eq(p.deref().deref(), pokemon.deref()) {
return true;
@ -218,7 +218,7 @@ impl<'own, 'library> BattleSide<'own, 'library> {
}
/// 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() {
if let Some(p) = slot {
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> {
&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 {
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.
#[derive(Debug)]
pub struct ExecutingMove<'own, 'battle, 'library> {
pub struct ExecutingMove {
/// The number of hits this move has.
number_of_hits: u8,
/// 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.
hits: Vec<HitData>,
/// The user of the move.
user: Arc<Pokemon<'battle, 'library>>,
user: Arc<Pokemon>,
/// 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.
use_move: &'own MoveData,
use_move: Arc<MoveData>,
/// The script of the move.
script: ScriptContainer,
/// The targets for this move.
targets: &'own TargetList<'battle, 'library>,
targets: TargetList,
/// Data required for this to be a script source.
script_source_data: RwLock<ScriptSourceData>,
}
impl<'own, 'battle, 'library> ExecutingMove<'own, 'battle, 'library> {
impl ExecutingMove {
/// Instantiates an executing move.
pub fn new(
targets: &'own TargetList<'battle, 'library>,
targets: TargetList,
number_of_hits: u8,
user: Arc<Pokemon<'battle, 'library>>,
chosen_move: Arc<LearnedMove<'library>>,
use_move: &'own MoveData,
user: Arc<Pokemon>,
chosen_move: Arc<LearnedMove>,
use_move: Arc<MoveData>,
script: ScriptContainer,
) -> Self {
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
}
/// The user of the move.
pub fn user(&self) -> &Arc<Pokemon<'battle, 'library>> {
pub fn user(&self) -> &Arc<Pokemon> {
&self.user
}
/// 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
}
/// The move that the user is actually going to do.
pub fn use_move(&self) -> &'own MoveData {
self.use_move
pub fn use_move(&self) -> &Arc<MoveData> {
&self.use_move
}
/// The script of the move.
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.
pub fn get_hit_data<'func>(
&'func self,
for_target: &'func Arc<Pokemon<'battle, 'library>>,
hit: u8,
) -> PkmnResult<&'func HitData> {
pub fn get_hit_data<'func>(&'func self, for_target: &'func Arc<Pokemon>, hit: u8) -> PkmnResult<&'func HitData> {
for (index, target) in self.targets.iter().enumerate() {
if let Some(target) = target {
if std::ptr::eq(target.deref().deref(), for_target.deref().deref()) {
@ -174,7 +170,7 @@ impl<'own, 'battle, 'library> ExecutingMove<'own, 'battle, 'library> {
}
/// 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() {
if std::ptr::eq(target.deref().deref(), pokemon.deref().deref()) {
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.
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() {
if let Some(target) = target {
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 {
1
}

View File

@ -1,4 +1,5 @@
use std::sync::atomic::{AtomicU8, Ordering};
use std::sync::Arc;
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.
#[derive(Debug)]
#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))]
pub struct LearnedMove<'library> {
pub struct LearnedMove {
/// The immutable move information of the move.
move_data: &'library MoveData,
move_data: Arc<MoveData>,
/// The maximal power points for this move.
max_pp: u8,
/// 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,
}
impl<'a> LearnedMove<'a> {
impl LearnedMove {
/// 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 {
move_data,
move_data: move_data.clone(),
max_pp: move_data.base_usages(),
remaining_pp: AtomicU8::new(move_data.base_usages()),
learn_method,
@ -40,8 +41,8 @@ impl<'a> LearnedMove<'a> {
}
/// The immutable move information of the move.
pub fn move_data(&self) -> &MoveData {
self.move_data
pub fn move_data(&self) -> &Arc<MoveData> {
&self.move_data
}
/// The maximal power points for this move.
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.
#[derive(Debug)]
#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))]
pub struct Pokemon<'own, 'library>
where
'own: 'library,
{
pub struct Pokemon {
/// The library data of the Pokemon.
library: &'own DynamicLibrary,
library: Arc<DynamicLibrary>,
/// The species of the Pokemon.
species: &'own Species,
species: Arc<Species>,
/// 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
/// 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
// 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.
level: LevelInt,
@ -57,7 +54,7 @@ where
/// currently not used, and can be used for other implementations.
coloring: u8,
/// 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.
current_health: AtomicU32,
@ -78,7 +75,7 @@ where
/// The [effort values](https://bulbapedia.bulbagarden.net/wiki/Effort_values) of the Pokemon.
effort_values: ClampedStatisticSet<u8, 0, 252>,
/// The [nature](https://bulbapedia.bulbagarden.net/wiki/Nature) of the Pokemon.
nature: &'own Nature,
nature: Arc<Nature>,
/// An optional nickname of the Pokemon.
nickname: Option<String>,
@ -90,11 +87,11 @@ where
override_ability: Option<Ability>,
/// 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
/// 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.
allowed_experience: bool,
@ -118,12 +115,12 @@ where
script_source_data: RwLock<ScriptSourceData>,
}
impl<'own, 'library> Pokemon<'own, 'library> {
impl Pokemon {
/// Instantiates a new Pokemon.
pub fn new(
library: &'own DynamicLibrary,
species: &'own Species,
form: &'own Form,
library: Arc<DynamicLibrary>,
species: Arc<Species>,
form: &Arc<Form>,
ability: AbilityIndex,
level: LevelInt,
unique_identifier: u32,
@ -142,11 +139,12 @@ impl<'own, 'library> Pokemon<'own, 'library> {
.static_data()
.natures()
.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 {
library,
species,
form,
form: form.clone(),
display_species: None,
display_form: None,
level,
@ -187,31 +185,31 @@ impl<'own, 'library> Pokemon<'own, 'library> {
}
/// The library data of the Pokemon.
pub fn library(&self) -> &'own DynamicLibrary {
self.library
pub fn library(&self) -> &Arc<DynamicLibrary> {
&self.library
}
/// The species of the Pokemon.
pub fn species(&self) -> &'own Species {
self.species
pub fn species(&self) -> &Arc<Species> {
&self.species
}
/// The form of the Pokemon.
pub fn form(&self) -> &'own Form {
self.form
pub fn form(&self) -> &Arc<Form> {
&self.form
}
/// The species that should be displayed to the user. This handles stuff like the Illusion ability.
pub fn display_species(&self) -> &'own Species {
if let Some(v) = self.display_species {
pub fn display_species(&self) -> &Arc<Species> {
if let Some(v) = &self.display_species {
v
} else {
self.species
&self.species
}
}
/// The form that should be displayed to the user. This handles stuff like the Illusion ability.
pub fn display_form(&self) -> &'own Form {
if let Some(v) = self.display_form {
pub fn display_form(&self) -> &Arc<Form> {
if let Some(v) = &self.display_form {
v
} else {
self.form
&self.form
}
}
/// The current level of the Pokemon.
@ -235,8 +233,8 @@ impl<'own, 'library> Pokemon<'own, 'library> {
pub fn coloring(&self) -> u8 {
self.coloring
}
/// Checks whether the Pokemon is holding an item,
pub fn held_item(&self) -> &RwLock<Option<&'own Item>> {
/// Gets the held item of a Pokemon
pub fn held_item(&self) -> &RwLock<Option<Arc<Item>>> {
&self.held_item
}
/// Checks whether the Pokemon is holding a specific item.
@ -248,11 +246,11 @@ impl<'own, 'library> Pokemon<'own, 'library> {
false
}
/// Changes the held item of the Pokemon/
pub fn set_held_item(&self, item: &'own Item) -> Option<&'own Item> {
self.held_item.write().replace(item)
pub fn set_held_item(&self, item: &Arc<Item>) -> Option<Arc<Item>> {
self.held_item.write().replace(item.clone())
}
/// 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()
}
/// Makes the Pokemon uses its held item.
@ -260,7 +258,10 @@ impl<'own, 'library> Pokemon<'own, 'library> {
if self.held_item.read().is_none() {
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() {
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
/// 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
}
@ -384,7 +385,7 @@ impl<'own, 'library> Pokemon<'own, 'library> {
}
/// 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();
if let Some(data) = &r.deref() {
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.
pub fn nature(&self) -> &'own Nature {
self.nature
pub fn nature(&self) -> &Arc<Nature> {
&self.nature
}
/// Calculates the flat stats on the Pokemon.
@ -453,9 +454,9 @@ impl<'own, 'library> Pokemon<'own, 'library> {
}
/// Change the species of the Pokemon.
pub fn change_species(&mut self, species: &'own Species, form: &'own Form) {
self.species = species;
self.form = form;
pub fn change_species(&mut self, species: Arc<Species>, form: Arc<Form>) {
self.species = species.clone();
self.form = form.clone();
// 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 {
@ -486,11 +487,11 @@ impl<'own, 'library> Pokemon<'own, 'library> {
}
/// Change the form of the Pokemon.
pub fn change_form(&mut self, form: &'own Form) {
if std::ptr::eq(self.form, form) {
pub fn change_form(&mut self, form: &Arc<Form>) {
if Arc::ptr_eq(&self.form, form) {
return;
}
self.form = form;
self.form = form.clone();
self.types.clear();
for t in form.types() {
@ -512,7 +513,7 @@ impl<'own, 'library> Pokemon<'own, 'library> {
.set(ability_script)
.as_ref()
// 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 {
self.ability_script.clear();
}
@ -547,7 +548,7 @@ impl<'own, 'library> Pokemon<'own, 'library> {
}
/// 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();
if let Some(battle_data) = w.deref_mut() {
battle_data.battle = battle;
@ -590,7 +591,7 @@ impl<'own, 'library> Pokemon<'own, 'library> {
}
/// 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();
if let Some(battle_data) = &r.deref() {
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.
#[derive(Debug)]
pub struct PokemonBattleData<'pokemon, 'library> {
pub struct PokemonBattleData {
/// The battle data of the Pokemon
battle: *mut Battle<'pokemon, 'library>,
battle: *mut Battle,
/// The index of the side of the Pokemon
battle_side_index: AtomicU8,
/// 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.
on_battle_field: AtomicBool,
/// 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
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() }
}
/// 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() }
}
@ -728,12 +729,12 @@ impl<'pokemon, 'library> PokemonBattleData<'pokemon, 'library> {
self.on_battle_field.load(Ordering::Relaxed)
}
/// 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
}
}
impl<'own, 'library> ScriptSource<'own> for Pokemon<'own, 'library> {
impl ScriptSource for Pokemon {
fn get_script_count(&self) -> usize {
let mut c = 3;
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> {
&self.volatile
}
@ -794,7 +795,7 @@ pub mod test {
#[test]
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 form = species.get_form(&"default".into()).unwrap();

View File

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

View File

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

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.
pub trait ScriptSource<'a> {
pub trait ScriptSource {
/// 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.
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};
/// 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.
fn volatile_scripts(&self) -> &Arc<ScriptSet>;
/// Loads a volatile script by name.

View File

@ -1,13 +1,13 @@
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::extern_ref::ExternRef;
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
use crate::static_data::MoveData;
register! {
fn learned_move_get_learn_method<'a>(
fn learned_move_get_learn_method(
env: &WebAssemblyEnv,
turn_choice: ExternRef<LearnedMove>,
) -> u8 {
@ -16,7 +16,7 @@ register! {
}
}
fn learned_move_get_move_data<'a>(
fn learned_move_get_move_data(
env: &WebAssemblyEnv,
turn_choice: ExternRef<LearnedMove>,
) -> ExternRef<MoveData> {

View File

@ -1,6 +1,6 @@
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::extern_ref::ExternRef;
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;

View File

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

View File

@ -1,12 +1,8 @@
use std::ffi::CString;
use std::mem::{align_of, forget};
use std::process::exit;
use wasmer::{Exports, Store};
pub(crate) use register;
pub(crate) use register_func_with_env;
use crate::dynamic_data::DynamicLibrary;
use crate::script_implementations::wasm::extern_ref::ExternRef;
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
@ -35,7 +31,7 @@ macro_rules! register_func_with_env {
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,
@ -43,7 +39,7 @@ macro_rules! register {
env: crate::script_implementations::wasm::script_resolver::WebAssemblyEnv) {
$(
fn $name<$($($lt)*)*>(
fn $name(
$(
$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) {
register_func_with_env!(exports, store, _print, 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.
pub(crate) fn new_with_resolver(resolver: &WebAssemblyScriptResolver, value: &T) -> Self {
Self {

View File

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

View File

@ -58,5 +58,5 @@ macro_rules! script_function_cache {
script_function_cache! {
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 crate::static_data::Ability;
@ -8,7 +10,7 @@ use crate::StringKey;
#[derive(Debug)]
pub struct AbilityLibrary {
/// The underlying map for the library.
map: IndexMap<StringKey, Box<Ability>>,
map: IndexMap<StringKey, Arc<Ability>>,
}
impl AbilityLibrary {
@ -20,11 +22,11 @@ impl AbilityLibrary {
}
}
impl DataLibrary<'_, Box<Ability>> for AbilityLibrary {
fn map(&self) -> &IndexMap<StringKey, Box<Ability>> {
impl DataLibrary<'_, Ability> for AbilityLibrary {
fn map(&self) -> &IndexMap<StringKey, Arc<Ability>> {
&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
}
}

View File

@ -1,3 +1,5 @@
use std::sync::Arc;
use indexmap::IndexMap;
use crate::Random;
@ -7,13 +9,13 @@ use crate::StringKey;
/// by both key, while keeping their insertion order.
pub trait DataLibrary<'a, T: 'a> {
/// Returns the underlying map.
fn map(&self) -> &IndexMap<StringKey, T>;
fn map(&self) -> &IndexMap<StringKey, Arc<T>>;
/// 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.
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.
@ -22,20 +24,15 @@ pub trait DataLibrary<'a, T: 'a> {
}
/// 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)
}
/// 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)
}
/// 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.
fn len(&self) -> usize {
self.map().len()
@ -46,7 +43,7 @@ pub trait DataLibrary<'a, T: 'a> {
}
/// 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);
return self.map().get_index(i as usize).unwrap().1;
}

View File

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

View File

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

View File

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

View File

@ -1,3 +1,5 @@
use std::sync::Arc;
use hashbrown::HashMap;
use crate::static_data::Statistic;
@ -60,7 +62,7 @@ impl Nature {
#[derive(Debug)]
pub struct NatureLibrary {
/// The underlying data structure.
map: HashMap<StringKey, Nature>,
map: HashMap<StringKey, Arc<Nature>>,
}
impl NatureLibrary {
@ -73,20 +75,20 @@ impl NatureLibrary {
/// Adds a new nature with name to the library.
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.
pub fn get_nature(&self, key: &StringKey) -> Option<&Nature> {
pub fn get_nature(&self, key: &StringKey) -> Option<&Arc<Nature>> {
self.map.get(key)
}
/// 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 {
// As natures can't be copied, and should always be the same reference as the value
// 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();
}
}

View File

@ -1,3 +1,5 @@
use std::sync::Arc;
use hashbrown::{HashMap, HashSet};
use crate::static_data::Form;
@ -21,7 +23,7 @@ pub struct Species {
/// uncatchable.
capture_rate: u8,
/// 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.
flags: HashSet<StringKey>,
}
@ -46,7 +48,7 @@ impl Species {
flags: HashSet<StringKey>,
) -> Species {
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 {
id,
name: name.clone(),
@ -80,7 +82,7 @@ impl Species {
self.capture_rate
}
/// The forms that belong to this Pokemon.
pub fn forms(&self) -> &HashMap<StringKey, Form> {
pub fn forms(&self) -> &HashMap<StringKey, Arc<Form>> {
&self.forms
}
/// 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.
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.
pub fn get_form(&self, id: &StringKey) -> Option<&Form> {
pub fn get_form(&self, id: &StringKey) -> Option<&Arc<Form>> {
self.forms.get(id)
}
/// 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()
}

View File

@ -115,10 +115,7 @@ pub fn load_items(path: &String, lib: &mut ItemLibrary) {
}
}
lib.add(
&name,
Box::new(Item::new(&name, category, battle_category, price as i32, flags)),
);
lib.add(&name, 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 = parse_form("default".into(), default_form_value, library);
let species = Box::new(Species::new(
let species = Species::new(
id as u16,
&name,
gender_rate as f32,
@ -270,7 +267,7 @@ pub fn load_species(path: &String, library: &mut StaticData) {
catch_rate as u8,
default_form,
Default::default(),
));
);
library.species_mut().add(&name, species);
}
}

View File

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

View File

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