diff --git a/PkmnLibSharp/Battling/Battle/Battle.cs b/PkmnLibSharp/Battling/Battle/Battle.cs index 8255cbe..ece5226 100644 --- a/PkmnLibSharp/Battling/Battle/Battle.cs +++ b/PkmnLibSharp/Battling/Battle/Battle.cs @@ -10,11 +10,6 @@ namespace PkmnLibSharp.Battling { public class Battle : PointerWrapper { - internal Battle(IntPtr ptr) : base(ptr) - { - Initialize(ptr); - } - public Battle(BattleLibrary library, BattleParty[] parties, bool canFlee, byte numberOfSides, byte pokemonPerSide, ulong randomSeed) { @@ -133,7 +128,7 @@ namespace PkmnLibSharp.Battling { var ptr = IntPtr.Zero; Creaturelib.Generated.Battle.GetCreature(ref ptr, Ptr, side, index).Assert(); - return TryResolvePointer(ptr, out Pokemon? pokemon) ? pokemon! : new Pokemon(ptr); + return TryResolvePointer(ptr, out Pokemon? pokemon) ? pokemon! : Constructor.Active.ConstructPokemon(ptr)!; } public void ForceRecall(byte side, byte index) diff --git a/PkmnLibSharp/Battling/Battle/BattleSide.cs b/PkmnLibSharp/Battling/Battle/BattleSide.cs index 4727d15..a09bde4 100644 --- a/PkmnLibSharp/Battling/Battle/BattleSide.cs +++ b/PkmnLibSharp/Battling/Battle/BattleSide.cs @@ -50,7 +50,7 @@ namespace PkmnLibSharp.Battling Creaturelib.Generated.BattleSide.GetCreature(ref ptr, Ptr, index); if (TryResolvePointer(ptr, out Pokemon? pokemon)) return pokemon!; - return new Pokemon(ptr); + return Constructor.Active.ConstructPokemon(ptr)!; } protected override void DeletePtr() diff --git a/PkmnLibSharp/Battling/Battle/ExecutingMove.cs b/PkmnLibSharp/Battling/Battle/ExecutingMove.cs index 262a233..cce2877 100644 --- a/PkmnLibSharp/Battling/Battle/ExecutingMove.cs +++ b/PkmnLibSharp/Battling/Battle/ExecutingMove.cs @@ -27,7 +27,7 @@ namespace PkmnLibSharp.Battling var ptr = Creaturelib.Generated.ExecutingAttack.GetUser(Ptr); if (TryResolvePointer(ptr, out _user)) return _user!; - _user = new Pokemon(ptr); + _user = Constructor.Active.ConstructPokemon(ptr)!; return _user; } } diff --git a/PkmnLibSharp/Battling/Battle/HitData.cs b/PkmnLibSharp/Battling/Battle/HitData.cs index fd87a23..68d670c 100644 --- a/PkmnLibSharp/Battling/Battle/HitData.cs +++ b/PkmnLibSharp/Battling/Battle/HitData.cs @@ -3,7 +3,7 @@ using PkmnLibSharp.Utilities; namespace PkmnLibSharp.Battling { - public class HitData : PointerWrapper + public sealed class HitData : PointerWrapper { internal HitData(IntPtr ptr) : base(ptr){} diff --git a/PkmnLibSharp/Battling/ChoiceTurn/BaseTurnChoice.cs b/PkmnLibSharp/Battling/ChoiceTurn/BaseTurnChoice.cs index 604add9..89ff90f 100644 --- a/PkmnLibSharp/Battling/ChoiceTurn/BaseTurnChoice.cs +++ b/PkmnLibSharp/Battling/ChoiceTurn/BaseTurnChoice.cs @@ -17,7 +17,7 @@ namespace PkmnLibSharp.Battling.ChoiceTurn var ptr = Creaturelib.Generated.BaseTurnChoice.GetUser(Ptr); if (TryResolvePointer(ptr, out _user)) return _user!; - _user = new Pokemon(ptr); + _user = Constructor.Active.ConstructPokemon(ptr)!; return _user; } } diff --git a/PkmnLibSharp/Battling/Events/EventData/DamageEvent.cs b/PkmnLibSharp/Battling/Events/EventData/DamageEvent.cs index 12ea86d..2b1b263 100644 --- a/PkmnLibSharp/Battling/Events/EventData/DamageEvent.cs +++ b/PkmnLibSharp/Battling/Events/EventData/DamageEvent.cs @@ -1,4 +1,5 @@ using System; +using PkmnLibSharp.Utilities; namespace PkmnLibSharp.Battling.Events { @@ -16,7 +17,7 @@ namespace PkmnLibSharp.Battling.Events var ptr = Creaturelib.Generated.DamageEvent.GetCreature(Ptr); if (TryResolvePointer(ptr, out _pokemon)) return _pokemon!; - _pokemon = new Pokemon(ptr); + _pokemon = Constructor.Active.ConstructPokemon(ptr)!; return _pokemon; } } diff --git a/PkmnLibSharp/Battling/Events/EventData/ExperienceGainEvent.cs b/PkmnLibSharp/Battling/Events/EventData/ExperienceGainEvent.cs index 7cf61ea..d0a7274 100644 --- a/PkmnLibSharp/Battling/Events/EventData/ExperienceGainEvent.cs +++ b/PkmnLibSharp/Battling/Events/EventData/ExperienceGainEvent.cs @@ -1,4 +1,5 @@ using System; +using PkmnLibSharp.Utilities; namespace PkmnLibSharp.Battling.Events { @@ -16,7 +17,7 @@ namespace PkmnLibSharp.Battling.Events var ptr = Creaturelib.Generated.ExperienceGainEvent.GetCreature(Ptr); if (TryResolvePointer(ptr, out _pokemon)) return _pokemon!; - _pokemon = new Pokemon(ptr); + _pokemon = Constructor.Active.ConstructPokemon(ptr)!; return _pokemon; } } diff --git a/PkmnLibSharp/Battling/Events/EventData/FaintEvent.cs b/PkmnLibSharp/Battling/Events/EventData/FaintEvent.cs index 0f16219..4516d5b 100644 --- a/PkmnLibSharp/Battling/Events/EventData/FaintEvent.cs +++ b/PkmnLibSharp/Battling/Events/EventData/FaintEvent.cs @@ -1,4 +1,5 @@ using System; +using PkmnLibSharp.Utilities; namespace PkmnLibSharp.Battling.Events { @@ -16,7 +17,7 @@ namespace PkmnLibSharp.Battling.Events var ptr = Creaturelib.Generated.DamageEvent.GetCreature(Ptr); if (TryResolvePointer(ptr, out _pokemon)) return _pokemon!; - _pokemon = new Pokemon(ptr); + _pokemon = Constructor.Active.ConstructPokemon(ptr)!; return _pokemon; } diff --git a/PkmnLibSharp/Battling/Events/EventData/HealEvent.cs b/PkmnLibSharp/Battling/Events/EventData/HealEvent.cs index d8d1f05..132f21f 100644 --- a/PkmnLibSharp/Battling/Events/EventData/HealEvent.cs +++ b/PkmnLibSharp/Battling/Events/EventData/HealEvent.cs @@ -1,4 +1,5 @@ using System; +using PkmnLibSharp.Utilities; namespace PkmnLibSharp.Battling.Events { @@ -16,7 +17,7 @@ namespace PkmnLibSharp.Battling.Events var ptr = Creaturelib.Generated.HealEvent.GetCreature(Ptr); if (TryResolvePointer(ptr, out _pokemon)) return _pokemon!; - _pokemon = new Pokemon(ptr); + _pokemon = Constructor.Active.ConstructPokemon(ptr)!; return _pokemon; } } diff --git a/PkmnLibSharp/Battling/Events/EventData/SwitchEvent.cs b/PkmnLibSharp/Battling/Events/EventData/SwitchEvent.cs index a13b84f..7d82eb0 100644 --- a/PkmnLibSharp/Battling/Events/EventData/SwitchEvent.cs +++ b/PkmnLibSharp/Battling/Events/EventData/SwitchEvent.cs @@ -1,4 +1,5 @@ using System; +using PkmnLibSharp.Utilities; namespace PkmnLibSharp.Battling.Events { @@ -16,7 +17,7 @@ namespace PkmnLibSharp.Battling.Events var ptr = Creaturelib.Generated.SwitchEvent.GetNewCreature(Ptr); if (TryResolvePointer(ptr, out _newPokemon)) return _newPokemon!; - _newPokemon = new Pokemon(ptr); + _newPokemon = Constructor.Active.ConstructPokemon(ptr)!; return _newPokemon; } } diff --git a/PkmnLibSharp/Battling/History/HistoryHandler.cs b/PkmnLibSharp/Battling/History/HistoryHandler.cs index dbe243f..5fe761d 100644 --- a/PkmnLibSharp/Battling/History/HistoryHandler.cs +++ b/PkmnLibSharp/Battling/History/HistoryHandler.cs @@ -5,7 +5,7 @@ using PkmnLibSharp.Utilities; namespace PkmnLibSharp.Battling.History { - public class HistoryHandler : PointerWrapper + public sealed class HistoryHandler : PointerWrapper { internal HistoryHandler(IntPtr ptr) : base(ptr){} diff --git a/PkmnLibSharp/Battling/Pokemon.cs b/PkmnLibSharp/Battling/Pokemon.cs index 5c5e0d8..b203b66 100644 --- a/PkmnLibSharp/Battling/Pokemon.cs +++ b/PkmnLibSharp/Battling/Pokemon.cs @@ -10,9 +10,11 @@ namespace PkmnLibSharp.Battling { public class Pokemon : PointerWrapper { - internal Pokemon(IntPtr ptr) : base(ptr) + protected internal override void Initialize(IntPtr ptr) { - Library = new BattleLibrary(Creaturelib.Generated.Creature.GetLibrary(ptr)); + base.Initialize(ptr); + if (Library == null) + Library = new BattleLibrary(Creaturelib.Generated.Creature.GetLibrary(ptr)); } public Pokemon(BattleLibrary library, Species species, Forme forme, @@ -45,7 +47,7 @@ namespace PkmnLibSharp.Battling var ptr = Creaturelib.Generated.Creature.GetSpecies(Ptr); if (TryResolvePointer(ptr, out _species)) return _species!; - _species = new Species(ptr); + _species = Constructor.Active.ConstructSpecies(ptr)!; return _species; } } @@ -58,7 +60,7 @@ namespace PkmnLibSharp.Battling var ptr = Creaturelib.Generated.Creature.GetVariant(Ptr); if (TryResolvePointer(ptr, out _forme)) return _forme!; - _forme = new Forme(ptr); + _forme = Constructor.Active.ConstructForme(ptr)!; return _forme; } } @@ -71,7 +73,7 @@ namespace PkmnLibSharp.Battling var ptr = Creaturelib.Generated.Creature.GetDisplaySpecies(Ptr); if (TryResolvePointer(ptr, out _displaySpecies)) return _displaySpecies; - _displaySpecies = new Species(ptr); + _displaySpecies = Constructor.Active.ConstructSpecies(ptr); return _displaySpecies; } set => Creaturelib.Generated.Creature.SetDisplaySpecies(Ptr, value?.Ptr ?? IntPtr.Zero); @@ -85,7 +87,7 @@ namespace PkmnLibSharp.Battling var ptr = Creaturelib.Generated.Creature.GetDisplayVariant(Ptr); if (TryResolvePointer(ptr, out _displayForme)) return _displayForme; - _displayForme = new Forme(ptr); + _displayForme = Constructor.Active.ConstructForme(ptr)!; return _displayForme; } set => Creaturelib.Generated.Creature.SetDisplayVariant(Ptr, value?.Ptr ?? IntPtr.Zero); @@ -122,7 +124,7 @@ namespace PkmnLibSharp.Battling if (_battle != null && _battle.Ptr == ptr) return _battle; if (TryResolvePointer(ptr, out _battle)) return _battle; - _battle = new Battle(ptr); + _battle = Constructor.Active.ConstructBattle(ptr); return _battle; } } diff --git a/PkmnLibSharp/Battling/PokemonParty.cs b/PkmnLibSharp/Battling/PokemonParty.cs index 85c8e42..fe49f84 100644 --- a/PkmnLibSharp/Battling/PokemonParty.cs +++ b/PkmnLibSharp/Battling/PokemonParty.cs @@ -24,7 +24,7 @@ namespace PkmnLibSharp.Battling { var ptr = IntPtr.Zero; Creaturelib.Generated.CreatureParty.GetAtIndex(ref ptr, Ptr, index).Assert(); - return TryResolvePointer(ptr, out Pokemon? pkmn) ? pkmn! : new Pokemon(ptr); + return TryResolvePointer(ptr, out Pokemon? pkmn) ? pkmn! : Constructor.Active.ConstructPokemon(ptr)!; } public void Switch(ulong indexA, ulong indexB) @@ -38,7 +38,7 @@ namespace PkmnLibSharp.Battling Creaturelib.Generated.CreatureParty.SwapInto(ref ptr, Ptr, indexA, pokemon.Ptr).Assert(); if (TryResolvePointer(ptr, out Pokemon? newPokemon)) return newPokemon!; - return new Pokemon(ptr); + return Constructor.Active.ConstructPokemon(ptr)!; } public bool HasAvailablePokemon() diff --git a/PkmnLibSharp/Library/Species/Evolution/EvolutionData.cs b/PkmnLibSharp/Library/Species/Evolution/EvolutionData.cs index 0111f85..820e606 100644 --- a/PkmnLibSharp/Library/Species/Evolution/EvolutionData.cs +++ b/PkmnLibSharp/Library/Species/Evolution/EvolutionData.cs @@ -8,7 +8,7 @@ using PkmnLibSharp.Utilities; namespace PkmnLibSharp.Library.Evolution { - public class EvolutionData : PointerWrapper + public sealed class EvolutionData : PointerWrapper { private EvolutionData(IntPtr ptr) : base(ptr) { @@ -89,7 +89,7 @@ namespace PkmnLibSharp.Library.Evolution var ptr = Pkmnlib.Generated.EvolutionData.GetNewSpecies(Ptr); if (TryResolvePointer(ptr, out _species)) return _species!; - _species = new Species(ptr); + _species = Constructor.Active.ConstructSpecies(ptr)!; return _species; } } diff --git a/PkmnLibSharp/Library/Species/Forme.cs b/PkmnLibSharp/Library/Species/Forme.cs index b5f88de..7804918 100644 --- a/PkmnLibSharp/Library/Species/Forme.cs +++ b/PkmnLibSharp/Library/Species/Forme.cs @@ -39,11 +39,7 @@ namespace PkmnLibSharp.Library Marshal.FreeHGlobal(intPtr); Initialize(ptr); } - - internal Forme(IntPtr parent) : base(parent) - { - } - + public string Name => _name ??= SpeciesVariant.GetName(Ptr).PtrString()!; public float Height => SpeciesVariant.GetHeight(Ptr); public float Weight => SpeciesVariant.GetWeight(Ptr); @@ -126,7 +122,7 @@ namespace PkmnLibSharp.Library if (_moves != null) return _moves; var movesPtr = SpeciesVariant.GetLearnableAttacks(Ptr); if (!TryResolvePointer(movesPtr, out _moves)) - _moves = new LearnableMoves(movesPtr); + _moves = Constructor.Active.ConstructLearnableMoves(movesPtr); return _moves!; } diff --git a/PkmnLibSharp/Library/Species/Species.cs b/PkmnLibSharp/Library/Species/Species.cs index 754d659..f0159ff 100644 --- a/PkmnLibSharp/Library/Species/Species.cs +++ b/PkmnLibSharp/Library/Species/Species.cs @@ -11,10 +11,6 @@ namespace PkmnLibSharp.Library { public class Species : PointerWrapper { - internal Species(IntPtr ptr) : base(ptr) - { - } - public Species(ushort id, string name, Forme defaultForme, float genderRatio, string growthRate, byte captureRate, byte baseHappiness, IReadOnlyCollection eggGroups, IReadOnlyCollection tags) { @@ -95,7 +91,7 @@ namespace PkmnLibSharp.Library return true; } - forme = new Forme(ptr); + forme = Constructor.Active.ConstructForme(ptr)!; _formeCache.Add(s, forme); return true; } @@ -114,7 +110,7 @@ namespace PkmnLibSharp.Library _formeCache.Add(s, f!); return f!; } - forme = new Forme(ptr); + forme = Constructor.Active.ConstructForme(ptr)!; _formeCache.Add(s, forme); return forme; } diff --git a/PkmnLibSharp/Library/SpeciesLibrary.cs b/PkmnLibSharp/Library/SpeciesLibrary.cs index 2756e9a..adc0d9a 100644 --- a/PkmnLibSharp/Library/SpeciesLibrary.cs +++ b/PkmnLibSharp/Library/SpeciesLibrary.cs @@ -33,7 +33,7 @@ namespace PkmnLibSharp.Library _cache.Add(key, species!); return true; } - species = new Species(ptr); + species = Constructor.Active.ConstructSpecies(ptr)!; _cache.Add(key, species); return true; } @@ -49,7 +49,7 @@ namespace PkmnLibSharp.Library _cache.Add(key, s!); return s!; } - species = new Species(ptr); + species = Constructor.Active.ConstructSpecies(ptr)!; _cache.Add(key, species); return species; } @@ -61,7 +61,7 @@ namespace PkmnLibSharp.Library { return s!; } - s = new Species(ptr); + s = Constructor.Active.ConstructSpecies(ptr)!; return s; } @@ -69,7 +69,9 @@ namespace PkmnLibSharp.Library { var ptr = Pkmnlib.Generated.SpeciesLibrary.FindPreEvolution(Ptr, species.Ptr); if (ptr == IntPtr.Zero) return null; - return TryResolvePointer(ptr, out Species? prevoSpecies) ? prevoSpecies : new Species(ptr); + return TryResolvePointer(ptr, out Species? prevoSpecies) + ? prevoSpecies + : Constructor.Active.ConstructSpecies(ptr); } public IEnumerable GetEnumerator() @@ -81,7 +83,7 @@ namespace PkmnLibSharp.Library Creaturelib.Generated.SpeciesLibrary.GetAtIndex(Ptr, i, ref ptr).Assert(); if (TryResolvePointer(ptr, out Species? species)) yield return species!; - yield return new Species(ptr); + yield return Constructor.Active.ConstructSpecies(ptr)!; } } diff --git a/PkmnLibSharp/Utilities/Constructor.cs b/PkmnLibSharp/Utilities/Constructor.cs new file mode 100644 index 0000000..673b3d3 --- /dev/null +++ b/PkmnLibSharp/Utilities/Constructor.cs @@ -0,0 +1,71 @@ +using System; +using System.Runtime.Serialization; +using PkmnLibSharp.Battling; +using PkmnLibSharp.Library; + +namespace PkmnLibSharp.Utilities +{ + public abstract class Constructor + { + public static Constructor Active { get; set; } = + new Constructor(); + + internal abstract Species? ConstructSpecies(IntPtr ptr); + internal abstract Forme? ConstructForme(IntPtr ptr); + internal abstract LearnableMoves? ConstructLearnableMoves(IntPtr ptr); + internal abstract Pokemon? ConstructPokemon(IntPtr ptr); + internal abstract Battle? ConstructBattle(IntPtr ptr); + } + + public class Constructor< + TSpecies, TForme, TLearnableMoves, + TPokemon, TBattle> + : Constructor + where TSpecies : Species + where TForme : Forme + where TLearnableMoves : LearnableMoves + + where TPokemon : Pokemon + where TBattle : Battle + { + private readonly Type _speciesType = typeof(TSpecies); + private readonly Type _formeType = typeof(TForme); + private readonly Type _learnableMovesType = typeof(TLearnableMoves); + + private readonly Type _pokemonType = typeof(TPokemon); + private readonly Type _battleType = typeof(TBattle); + + private static T? Create(IntPtr ptr, Type t) where T : PointerWrapper + { + if (ptr == IntPtr.Zero) return null; + var o = (T) FormatterServices.GetUninitializedObject(t); + o.Initialize(ptr); + return o; + } + + internal override Species? ConstructSpecies(IntPtr ptr) + { + return Create(ptr, _speciesType); + } + + internal override Forme? ConstructForme(IntPtr ptr) + { + return Create(ptr, _formeType); + } + + internal override LearnableMoves? ConstructLearnableMoves(IntPtr ptr) + { + return Create(ptr, _learnableMovesType); + } + + internal override Pokemon? ConstructPokemon(IntPtr ptr) + { + return Create(ptr, _pokemonType); + } + + internal override Battle? ConstructBattle(IntPtr ptr) + { + return Create(ptr, _battleType); + } + } +} \ No newline at end of file