diff --git a/PkmnLibSharp/Battling/Battle/Battle.cs b/PkmnLibSharp/Battling/Battle/Battle.cs index ece5226..326fc3b 100644 --- a/PkmnLibSharp/Battling/Battle/Battle.cs +++ b/PkmnLibSharp/Battling/Battle/Battle.cs @@ -64,7 +64,7 @@ namespace PkmnLibSharp.Battling { if (_sides != null) return _sides; var ptr = Creaturelib.Generated.Battle.GetSides(Ptr); - _sides = new ReadOnlyNativePtrArray(ptr, (int) SidesCount); + _sides = new ReadOnlyNativePtrArray(ptr, (int) SidesCount, Constructor.GenericType.BattleSide); return _sides; } } @@ -77,7 +77,7 @@ namespace PkmnLibSharp.Battling { if (_parties != null) return _parties; var ptr = Creaturelib.Generated.Battle.GetParties(Ptr); - _parties = new ReadOnlyNativePtrArray(ptr, (int) PartiesCount); + _parties = new ReadOnlyNativePtrArray(ptr, (int) PartiesCount, Constructor.GenericType.BattleParty); return _parties; } } diff --git a/PkmnLibSharp/Battling/Battle/ExecutingMove.cs b/PkmnLibSharp/Battling/Battle/ExecutingMove.cs index cce2877..3dba295 100644 --- a/PkmnLibSharp/Battling/Battle/ExecutingMove.cs +++ b/PkmnLibSharp/Battling/Battle/ExecutingMove.cs @@ -35,7 +35,7 @@ namespace PkmnLibSharp.Battling /// /// Get the first hit for the first target. Honestly just here so I can quickly read hit info from my debugger. /// - public HitData FirstHit => GetHitData(Targets[0], 0); + public HitData FirstHit => GetHitData(Targets[0]!, 0); public byte NumberOfHits => Creaturelib.Generated.ExecutingAttack.GetNumberOfHits(Ptr); @@ -46,7 +46,7 @@ namespace PkmnLibSharp.Battling if (_targets != null) return _targets; var size = Creaturelib.Generated.ExecutingAttack.GetTargetCount(Ptr); var ptr = Creaturelib.Generated.ExecutingAttack.GetTargets(Ptr); - _targets = new ReadOnlyNativePtrArray(ptr, size); + _targets = new ReadOnlyNativePtrArray(ptr, size, Constructor.GenericType.Pokemon); return _targets; } } diff --git a/PkmnLibSharp/Battling/Pokemon.cs b/PkmnLibSharp/Battling/Pokemon.cs index fe735c1..c96be4e 100644 --- a/PkmnLibSharp/Battling/Pokemon.cs +++ b/PkmnLibSharp/Battling/Pokemon.cs @@ -173,7 +173,7 @@ namespace PkmnLibSharp.Battling if (_moves != null) return _moves; var movesLength = Creaturelib.Generated.Creature.GetAttacksCount(Ptr); var movesPtr = Creaturelib.Generated.Creature.GetAttacks(Ptr); - _moves = new ReadOnlyNativePtrArray(movesPtr, (int) movesLength); + _moves = new ReadOnlyNativePtrArray(movesPtr, (int) movesLength, Constructor.GenericType.LearnedMove); return _moves; } } diff --git a/PkmnLibSharp/Battling/PokemonParty.cs b/PkmnLibSharp/Battling/PokemonParty.cs index fe49f84..dbe33b3 100644 --- a/PkmnLibSharp/Battling/PokemonParty.cs +++ b/PkmnLibSharp/Battling/PokemonParty.cs @@ -7,7 +7,7 @@ namespace PkmnLibSharp.Battling { public class PokemonParty : PointerWrapper, IEnumerable { - private ReadOnlyNativePtrArray? _party; + private ReadOnlyNativePtrArray? _party; internal PokemonParty(IntPtr ptr) : base(ptr){} @@ -46,13 +46,13 @@ namespace PkmnLibSharp.Battling return Creaturelib.Generated.CreatureParty.HasAvailableCreatures(Ptr) == 1; } - public ReadOnlyNativePtrArray Party + public ReadOnlyNativePtrArray Party { get { if (_party != null) return _party; var ptr = Creaturelib.Generated.CreatureParty.GetParty(Ptr); - _party = new ReadOnlyNativePtrArray(ptr, (int) Length); + _party = new ReadOnlyNativePtrArray(ptr, (int) Length, Constructor.GenericType.Pokemon); return _party; } } diff --git a/PkmnLibSharp/Library/Species/Evolution/EvolutionData.cs b/PkmnLibSharp/Library/Species/Evolution/EvolutionData.cs index 820e606..d9bf865 100644 --- a/PkmnLibSharp/Library/Species/Evolution/EvolutionData.cs +++ b/PkmnLibSharp/Library/Species/Evolution/EvolutionData.cs @@ -10,7 +10,7 @@ namespace PkmnLibSharp.Library.Evolution { public sealed class EvolutionData : PointerWrapper { - private EvolutionData(IntPtr ptr) : base(ptr) + internal EvolutionData(IntPtr ptr) : base(ptr) { } diff --git a/PkmnLibSharp/Library/Species/LearnableMoves.cs b/PkmnLibSharp/Library/Species/LearnableMoves.cs index bc3e246..1641fdf 100644 --- a/PkmnLibSharp/Library/Species/LearnableMoves.cs +++ b/PkmnLibSharp/Library/Species/LearnableMoves.cs @@ -25,7 +25,8 @@ namespace PkmnLibSharp.Library if (_distinctLevelMoves != null) return _distinctLevelMoves; var count = LearnableAttacks.GetDistinctLevelAttacksCount(Ptr); var ptr = LearnableAttacks.GetDistinctLevelAttacks(Ptr); - _distinctLevelMoves = new ReadOnlyNativePtrArray(ptr, (int) count); + _distinctLevelMoves = + new ReadOnlyNativePtrArray(ptr, (int) count, Constructor.GenericType.LearnableMoves); return _distinctLevelMoves; } } @@ -37,7 +38,7 @@ namespace PkmnLibSharp.Library if (_eggMoves != null) return _eggMoves; var count = Pkmnlib.Generated.LearnableMoves.GetEggMovesCount(Ptr); var ptr = Pkmnlib.Generated.LearnableMoves.GetEggMoves(Ptr); - _eggMoves = new ReadOnlyNativePtrArray(ptr, (int) count); + _eggMoves = new ReadOnlyNativePtrArray(ptr, (int) count, Constructor.GenericType.MoveData); return _eggMoves; } } @@ -47,11 +48,11 @@ namespace PkmnLibSharp.Library { if (LearnableAttacks.HasAttacksForLevel(Ptr, level) != 1) { - return new ReadOnlyNativePtrArray(); + return new ReadOnlyNativePtrArray(Constructor.GenericType.MoveData); } var count = LearnableAttacks.GetAttacksForLevelCount(Ptr, level); var ptr = LearnableAttacks.GetAttacksForLevel(Ptr, level); - return new ReadOnlyNativePtrArray(ptr, (int) count); + return new ReadOnlyNativePtrArray(ptr, (int) count, Constructor.GenericType.MoveData); } public void AddLevelMove(byte level, MoveData move) diff --git a/PkmnLibSharp/Library/Species/Species.cs b/PkmnLibSharp/Library/Species/Species.cs index f0159ff..a3f2343 100644 --- a/PkmnLibSharp/Library/Species/Species.cs +++ b/PkmnLibSharp/Library/Species/Species.cs @@ -55,7 +55,7 @@ namespace PkmnLibSharp.Library if (_formes != null) return _formes; var startPtr = CreatureSpecies.GetVariants(Ptr); var size = CreatureSpecies.GetVariantsCount(Ptr); - _formes = new ReadOnlyNativePtrArray(startPtr, (int) size); + _formes = new ReadOnlyNativePtrArray(startPtr, (int) size, Constructor.GenericType.Forme); return _formes; } } @@ -68,7 +68,7 @@ namespace PkmnLibSharp.Library var ptr = IntPtr.Zero; PokemonSpecies.GetEvolutions(Ptr, ref ptr); var length = PokemonSpecies.GetEvolutionCount(Ptr); - _evolutions = new ReadOnlyNativePtrArray(ptr, (int) length); + _evolutions = new ReadOnlyNativePtrArray(ptr, (int) length, Constructor.GenericType.EvolutionData); return _evolutions; } } diff --git a/PkmnLibSharp/Utilities/Constructor.cs b/PkmnLibSharp/Utilities/Constructor.cs index 01e843a..6649119 100644 --- a/PkmnLibSharp/Utilities/Constructor.cs +++ b/PkmnLibSharp/Utilities/Constructor.cs @@ -2,16 +2,32 @@ using System; using System.Runtime.Serialization; using PkmnLibSharp.Battling; using PkmnLibSharp.Library; -using PkmnLibSharp.Library.Items; using PkmnLibSharp.Library.Moves; +using Battle = PkmnLibSharp.Battling.Battle; +using EvolutionData = PkmnLibSharp.Library.Evolution.EvolutionData; +using Item = PkmnLibSharp.Library.Items.Item; +using LearnableMoves = PkmnLibSharp.Library.LearnableMoves; +using Pokemon = PkmnLibSharp.Battling.Pokemon; namespace PkmnLibSharp.Utilities { public abstract class Constructor { - public static Constructor Active { get; set; } = - new Constructor(); + public static Constructor Active { get; set; } = + new Constructor< + Species, Forme, MoveData, Item, LearnableMoves, + Pokemon, Battle, BattleParty, BattleSide, LearnedMove>(); + internal enum GenericType + { + Species, Forme, MoveData, Item, LearnableMoves, EvolutionData, + Pokemon, Battle, + + BattleParty, + BattleSide, + LearnedMove + } + internal abstract Species? ConstructSpecies(IntPtr ptr); internal abstract Forme? ConstructForme(IntPtr ptr); internal abstract MoveData? ConstructMove(IntPtr ptr); @@ -19,11 +35,39 @@ namespace PkmnLibSharp.Utilities internal abstract LearnableMoves? ConstructLearnableMoves(IntPtr ptr); internal abstract Pokemon? ConstructPokemon(IntPtr ptr); internal abstract Battle? ConstructBattle(IntPtr ptr); + internal abstract BattleParty? ConstructBattleParty(IntPtr ptr); + internal abstract BattleSide? ConstructBattleSide(IntPtr ptr); + internal abstract LearnedMove? ConstructLearnedMove(IntPtr ptr); + + internal EvolutionData? ConstructEvolutionData(IntPtr ptr) + { + return new EvolutionData(ptr); + } + + internal object? InstantiateGeneric(GenericType type, IntPtr ptr) + { + return type switch + { + GenericType.Species => ConstructSpecies(ptr), + GenericType.Forme => ConstructForme(ptr), + GenericType.MoveData => ConstructMove(ptr), + GenericType.Item => ConstructItem(ptr), + GenericType.LearnableMoves => ConstructLearnableMoves(ptr), + GenericType.EvolutionData => ConstructEvolutionData(ptr), + + GenericType.Pokemon => ConstructPokemon(ptr), + GenericType.Battle => ConstructBattle(ptr), + GenericType.BattleParty => ConstructBattleParty(ptr), + GenericType.BattleSide => ConstructBattleSide(ptr), + GenericType.LearnedMove => ConstructLearnedMove(ptr), + _ => throw new ArgumentOutOfRangeException(nameof(type), type, null) + }; + } } public class Constructor< TSpecies, TForme, TMoveData, TItem, TLearnableMoves, - TPokemon, TBattle> + TPokemon, TBattle, TBattleParty, TBattleSide, TLearnedMove> : Constructor where TSpecies : Species where TForme : Forme @@ -33,6 +77,9 @@ namespace PkmnLibSharp.Utilities where TPokemon : Pokemon where TBattle : Battle + where TBattleParty : BattleParty + where TBattleSide : BattleSide + where TLearnedMove : LearnedMove { private readonly Type _speciesType = typeof(TSpecies); private readonly Type _formeType = typeof(TForme); @@ -42,7 +89,10 @@ namespace PkmnLibSharp.Utilities private readonly Type _pokemonType = typeof(TPokemon); private readonly Type _battleType = typeof(TBattle); - + private readonly Type _battlePartyType = typeof(TBattleParty); + private readonly Type _battleSideType = typeof(TBattleSide); + private readonly Type _learnedMoveType = typeof(TLearnedMove); + private static T? Create(IntPtr ptr, Type t) where T : PointerWrapper { if (ptr == IntPtr.Zero) return null; @@ -85,5 +135,20 @@ namespace PkmnLibSharp.Utilities { return Create(ptr, _battleType); } + + internal override BattleParty? ConstructBattleParty(IntPtr ptr) + { + return Create(ptr, _battlePartyType); + } + + internal override BattleSide? ConstructBattleSide(IntPtr ptr) + { + return Create(ptr, _battleSideType); + } + + internal override LearnedMove? ConstructLearnedMove(IntPtr ptr) + { + return Create(ptr, _learnedMoveType); + } } } \ No newline at end of file diff --git a/PkmnLibSharp/Utilities/ReadOnlyNativePtrArray.cs b/PkmnLibSharp/Utilities/ReadOnlyNativePtrArray.cs index 93325c0..e0ac112 100644 --- a/PkmnLibSharp/Utilities/ReadOnlyNativePtrArray.cs +++ b/PkmnLibSharp/Utilities/ReadOnlyNativePtrArray.cs @@ -8,24 +8,27 @@ namespace PkmnLibSharp.Utilities public class ReadOnlyNativePtrArray : IReadOnlyList where T : PointerWrapper { private readonly IntPtr _ptr; - private T?[] _cache; - private Type _type = typeof(T); + private readonly T?[] _cache; + private readonly Type _type = typeof(T); + private Constructor.GenericType _constructorType; - internal ReadOnlyNativePtrArray() + internal ReadOnlyNativePtrArray(Constructor.GenericType type) { _ptr = IntPtr.Zero; Count = 0; _cache = new T[Count]; + _constructorType = type; } - internal ReadOnlyNativePtrArray(IntPtr ptr, int length) + internal ReadOnlyNativePtrArray(IntPtr ptr, int length, Constructor.GenericType type) { _ptr = ptr; Count = length; _cache = new T[Count]; + _constructorType = type; } - public IEnumerator GetEnumerator() + public IEnumerator GetEnumerator() { for (var i = 0; i < Count; i++) { @@ -42,14 +45,15 @@ namespace PkmnLibSharp.Utilities { foreach (var v in this) { - if (item == null) + if (item == null && v == null) { - if (v.Ptr == IntPtr.Zero) - return true; - continue; - } - if (item.Ptr == v.Ptr) return true; + } + if (v != null && item != null) + { + if (item.Ptr == v.Ptr) + return true; + } } return false; } @@ -69,7 +73,7 @@ namespace PkmnLibSharp.Utilities return -1; } - public T this[int index] + public T? this[int index] { get { @@ -84,8 +88,7 @@ namespace PkmnLibSharp.Utilities return _cache[index]!; if (PointerWrapper.TryResolvePointer(p, out T? t)) return t!; - t = (T) FormatterServices.GetUninitializedObject(_type); - t.Initialize(p); + t = (T?) Constructor.Active.InstantiateGeneric(_constructorType, p); _cache[index] = t; return t; }