Use Constructor class in PointerArray

This commit is contained in:
Deukhoofd 2020-08-24 18:33:04 +02:00
parent f74f29daef
commit 2c5f35c640
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
9 changed files with 103 additions and 34 deletions

View File

@ -64,7 +64,7 @@ namespace PkmnLibSharp.Battling
{ {
if (_sides != null) return _sides; if (_sides != null) return _sides;
var ptr = Creaturelib.Generated.Battle.GetSides(Ptr); var ptr = Creaturelib.Generated.Battle.GetSides(Ptr);
_sides = new ReadOnlyNativePtrArray<BattleSide>(ptr, (int) SidesCount); _sides = new ReadOnlyNativePtrArray<BattleSide>(ptr, (int) SidesCount, Constructor.GenericType.BattleSide);
return _sides; return _sides;
} }
} }
@ -77,7 +77,7 @@ namespace PkmnLibSharp.Battling
{ {
if (_parties != null) return _parties; if (_parties != null) return _parties;
var ptr = Creaturelib.Generated.Battle.GetParties(Ptr); var ptr = Creaturelib.Generated.Battle.GetParties(Ptr);
_parties = new ReadOnlyNativePtrArray<BattleParty>(ptr, (int) PartiesCount); _parties = new ReadOnlyNativePtrArray<BattleParty>(ptr, (int) PartiesCount, Constructor.GenericType.BattleParty);
return _parties; return _parties;
} }
} }

View File

@ -35,7 +35,7 @@ namespace PkmnLibSharp.Battling
/// <summary> /// <summary>
/// Get the first hit for the first target. Honestly just here so I can quickly read hit info from my debugger. /// Get the first hit for the first target. Honestly just here so I can quickly read hit info from my debugger.
/// </summary> /// </summary>
public HitData FirstHit => GetHitData(Targets[0], 0); public HitData FirstHit => GetHitData(Targets[0]!, 0);
public byte NumberOfHits => Creaturelib.Generated.ExecutingAttack.GetNumberOfHits(Ptr); public byte NumberOfHits => Creaturelib.Generated.ExecutingAttack.GetNumberOfHits(Ptr);
@ -46,7 +46,7 @@ namespace PkmnLibSharp.Battling
if (_targets != null) return _targets; if (_targets != null) return _targets;
var size = Creaturelib.Generated.ExecutingAttack.GetTargetCount(Ptr); var size = Creaturelib.Generated.ExecutingAttack.GetTargetCount(Ptr);
var ptr = Creaturelib.Generated.ExecutingAttack.GetTargets(Ptr); var ptr = Creaturelib.Generated.ExecutingAttack.GetTargets(Ptr);
_targets = new ReadOnlyNativePtrArray<Pokemon>(ptr, size); _targets = new ReadOnlyNativePtrArray<Pokemon>(ptr, size, Constructor.GenericType.Pokemon);
return _targets; return _targets;
} }
} }

View File

@ -173,7 +173,7 @@ namespace PkmnLibSharp.Battling
if (_moves != null) return _moves; if (_moves != null) return _moves;
var movesLength = Creaturelib.Generated.Creature.GetAttacksCount(Ptr); var movesLength = Creaturelib.Generated.Creature.GetAttacksCount(Ptr);
var movesPtr = Creaturelib.Generated.Creature.GetAttacks(Ptr); var movesPtr = Creaturelib.Generated.Creature.GetAttacks(Ptr);
_moves = new ReadOnlyNativePtrArray<LearnedMove>(movesPtr, (int) movesLength); _moves = new ReadOnlyNativePtrArray<LearnedMove>(movesPtr, (int) movesLength, Constructor.GenericType.LearnedMove);
return _moves; return _moves;
} }
} }

View File

@ -7,7 +7,7 @@ namespace PkmnLibSharp.Battling
{ {
public class PokemonParty : PointerWrapper, IEnumerable<Pokemon> public class PokemonParty : PointerWrapper, IEnumerable<Pokemon>
{ {
private ReadOnlyNativePtrArray<Pokemon?>? _party; private ReadOnlyNativePtrArray<Pokemon>? _party;
internal PokemonParty(IntPtr ptr) : base(ptr){} internal PokemonParty(IntPtr ptr) : base(ptr){}
@ -46,13 +46,13 @@ namespace PkmnLibSharp.Battling
return Creaturelib.Generated.CreatureParty.HasAvailableCreatures(Ptr) == 1; return Creaturelib.Generated.CreatureParty.HasAvailableCreatures(Ptr) == 1;
} }
public ReadOnlyNativePtrArray<Pokemon?> Party public ReadOnlyNativePtrArray<Pokemon> Party
{ {
get get
{ {
if (_party != null) return _party; if (_party != null) return _party;
var ptr = Creaturelib.Generated.CreatureParty.GetParty(Ptr); var ptr = Creaturelib.Generated.CreatureParty.GetParty(Ptr);
_party = new ReadOnlyNativePtrArray<Pokemon?>(ptr, (int) Length); _party = new ReadOnlyNativePtrArray<Pokemon>(ptr, (int) Length, Constructor.GenericType.Pokemon);
return _party; return _party;
} }
} }

View File

@ -10,7 +10,7 @@ namespace PkmnLibSharp.Library.Evolution
{ {
public sealed class EvolutionData : PointerWrapper public sealed class EvolutionData : PointerWrapper
{ {
private EvolutionData(IntPtr ptr) : base(ptr) internal EvolutionData(IntPtr ptr) : base(ptr)
{ {
} }

View File

@ -25,7 +25,8 @@ namespace PkmnLibSharp.Library
if (_distinctLevelMoves != null) return _distinctLevelMoves; if (_distinctLevelMoves != null) return _distinctLevelMoves;
var count = LearnableAttacks.GetDistinctLevelAttacksCount(Ptr); var count = LearnableAttacks.GetDistinctLevelAttacksCount(Ptr);
var ptr = LearnableAttacks.GetDistinctLevelAttacks(Ptr); var ptr = LearnableAttacks.GetDistinctLevelAttacks(Ptr);
_distinctLevelMoves = new ReadOnlyNativePtrArray<MoveData>(ptr, (int) count); _distinctLevelMoves =
new ReadOnlyNativePtrArray<MoveData>(ptr, (int) count, Constructor.GenericType.LearnableMoves);
return _distinctLevelMoves; return _distinctLevelMoves;
} }
} }
@ -37,7 +38,7 @@ namespace PkmnLibSharp.Library
if (_eggMoves != null) return _eggMoves; if (_eggMoves != null) return _eggMoves;
var count = Pkmnlib.Generated.LearnableMoves.GetEggMovesCount(Ptr); var count = Pkmnlib.Generated.LearnableMoves.GetEggMovesCount(Ptr);
var ptr = Pkmnlib.Generated.LearnableMoves.GetEggMoves(Ptr); var ptr = Pkmnlib.Generated.LearnableMoves.GetEggMoves(Ptr);
_eggMoves = new ReadOnlyNativePtrArray<MoveData>(ptr, (int) count); _eggMoves = new ReadOnlyNativePtrArray<MoveData>(ptr, (int) count, Constructor.GenericType.MoveData);
return _eggMoves; return _eggMoves;
} }
} }
@ -47,11 +48,11 @@ namespace PkmnLibSharp.Library
{ {
if (LearnableAttacks.HasAttacksForLevel(Ptr, level) != 1) if (LearnableAttacks.HasAttacksForLevel(Ptr, level) != 1)
{ {
return new ReadOnlyNativePtrArray<MoveData>(); return new ReadOnlyNativePtrArray<MoveData>(Constructor.GenericType.MoveData);
} }
var count = LearnableAttacks.GetAttacksForLevelCount(Ptr, level); var count = LearnableAttacks.GetAttacksForLevelCount(Ptr, level);
var ptr = LearnableAttacks.GetAttacksForLevel(Ptr, level); var ptr = LearnableAttacks.GetAttacksForLevel(Ptr, level);
return new ReadOnlyNativePtrArray<MoveData>(ptr, (int) count); return new ReadOnlyNativePtrArray<MoveData>(ptr, (int) count, Constructor.GenericType.MoveData);
} }
public void AddLevelMove(byte level, MoveData move) public void AddLevelMove(byte level, MoveData move)

View File

@ -55,7 +55,7 @@ namespace PkmnLibSharp.Library
if (_formes != null) return _formes; if (_formes != null) return _formes;
var startPtr = CreatureSpecies.GetVariants(Ptr); var startPtr = CreatureSpecies.GetVariants(Ptr);
var size = CreatureSpecies.GetVariantsCount(Ptr); var size = CreatureSpecies.GetVariantsCount(Ptr);
_formes = new ReadOnlyNativePtrArray<Forme>(startPtr, (int) size); _formes = new ReadOnlyNativePtrArray<Forme>(startPtr, (int) size, Constructor.GenericType.Forme);
return _formes; return _formes;
} }
} }
@ -68,7 +68,7 @@ namespace PkmnLibSharp.Library
var ptr = IntPtr.Zero; var ptr = IntPtr.Zero;
PokemonSpecies.GetEvolutions(Ptr, ref ptr); PokemonSpecies.GetEvolutions(Ptr, ref ptr);
var length = PokemonSpecies.GetEvolutionCount(Ptr); var length = PokemonSpecies.GetEvolutionCount(Ptr);
_evolutions = new ReadOnlyNativePtrArray<EvolutionData>(ptr, (int) length); _evolutions = new ReadOnlyNativePtrArray<EvolutionData>(ptr, (int) length, Constructor.GenericType.EvolutionData);
return _evolutions; return _evolutions;
} }
} }

View File

@ -2,16 +2,32 @@ using System;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using PkmnLibSharp.Battling; using PkmnLibSharp.Battling;
using PkmnLibSharp.Library; using PkmnLibSharp.Library;
using PkmnLibSharp.Library.Items;
using PkmnLibSharp.Library.Moves; 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 namespace PkmnLibSharp.Utilities
{ {
public abstract class Constructor public abstract class Constructor
{ {
public static Constructor Active { get; set; } = public static Constructor Active { get; set; } =
new Constructor<Species, Forme, MoveData, Item, LearnableMoves, Pokemon, Battle>(); 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 Species? ConstructSpecies(IntPtr ptr);
internal abstract Forme? ConstructForme(IntPtr ptr); internal abstract Forme? ConstructForme(IntPtr ptr);
internal abstract MoveData? ConstructMove(IntPtr ptr); internal abstract MoveData? ConstructMove(IntPtr ptr);
@ -19,11 +35,39 @@ namespace PkmnLibSharp.Utilities
internal abstract LearnableMoves? ConstructLearnableMoves(IntPtr ptr); internal abstract LearnableMoves? ConstructLearnableMoves(IntPtr ptr);
internal abstract Pokemon? ConstructPokemon(IntPtr ptr); internal abstract Pokemon? ConstructPokemon(IntPtr ptr);
internal abstract Battle? ConstructBattle(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< public class Constructor<
TSpecies, TForme, TMoveData, TItem, TLearnableMoves, TSpecies, TForme, TMoveData, TItem, TLearnableMoves,
TPokemon, TBattle> TPokemon, TBattle, TBattleParty, TBattleSide, TLearnedMove>
: Constructor : Constructor
where TSpecies : Species where TSpecies : Species
where TForme : Forme where TForme : Forme
@ -33,6 +77,9 @@ namespace PkmnLibSharp.Utilities
where TPokemon : Pokemon where TPokemon : Pokemon
where TBattle : Battle where TBattle : Battle
where TBattleParty : BattleParty
where TBattleSide : BattleSide
where TLearnedMove : LearnedMove
{ {
private readonly Type _speciesType = typeof(TSpecies); private readonly Type _speciesType = typeof(TSpecies);
private readonly Type _formeType = typeof(TForme); private readonly Type _formeType = typeof(TForme);
@ -42,7 +89,10 @@ namespace PkmnLibSharp.Utilities
private readonly Type _pokemonType = typeof(TPokemon); private readonly Type _pokemonType = typeof(TPokemon);
private readonly Type _battleType = typeof(TBattle); 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<T>(IntPtr ptr, Type t) where T : PointerWrapper private static T? Create<T>(IntPtr ptr, Type t) where T : PointerWrapper
{ {
if (ptr == IntPtr.Zero) return null; if (ptr == IntPtr.Zero) return null;
@ -85,5 +135,20 @@ namespace PkmnLibSharp.Utilities
{ {
return Create<TBattle>(ptr, _battleType); return Create<TBattle>(ptr, _battleType);
} }
internal override BattleParty? ConstructBattleParty(IntPtr ptr)
{
return Create<TBattleParty>(ptr, _battlePartyType);
}
internal override BattleSide? ConstructBattleSide(IntPtr ptr)
{
return Create<TBattleSide>(ptr, _battleSideType);
}
internal override LearnedMove? ConstructLearnedMove(IntPtr ptr)
{
return Create<TLearnedMove>(ptr, _learnedMoveType);
}
} }
} }

View File

@ -8,24 +8,27 @@ namespace PkmnLibSharp.Utilities
public class ReadOnlyNativePtrArray<T> : IReadOnlyList<T> where T : PointerWrapper public class ReadOnlyNativePtrArray<T> : IReadOnlyList<T> where T : PointerWrapper
{ {
private readonly IntPtr _ptr; private readonly IntPtr _ptr;
private T?[] _cache; private readonly T?[] _cache;
private Type _type = typeof(T); private readonly Type _type = typeof(T);
private Constructor.GenericType _constructorType;
internal ReadOnlyNativePtrArray() internal ReadOnlyNativePtrArray(Constructor.GenericType type)
{ {
_ptr = IntPtr.Zero; _ptr = IntPtr.Zero;
Count = 0; Count = 0;
_cache = new T[Count]; _cache = new T[Count];
_constructorType = type;
} }
internal ReadOnlyNativePtrArray(IntPtr ptr, int length) internal ReadOnlyNativePtrArray(IntPtr ptr, int length, Constructor.GenericType type)
{ {
_ptr = ptr; _ptr = ptr;
Count = length; Count = length;
_cache = new T[Count]; _cache = new T[Count];
_constructorType = type;
} }
public IEnumerator<T> GetEnumerator() public IEnumerator<T?> GetEnumerator()
{ {
for (var i = 0; i < Count; i++) for (var i = 0; i < Count; i++)
{ {
@ -42,14 +45,15 @@ namespace PkmnLibSharp.Utilities
{ {
foreach (var v in this) 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; return true;
}
if (v != null && item != null)
{
if (item.Ptr == v.Ptr)
return true;
}
} }
return false; return false;
} }
@ -69,7 +73,7 @@ namespace PkmnLibSharp.Utilities
return -1; return -1;
} }
public T this[int index] public T? this[int index]
{ {
get get
{ {
@ -84,8 +88,7 @@ namespace PkmnLibSharp.Utilities
return _cache[index]!; return _cache[index]!;
if (PointerWrapper.TryResolvePointer(p, out T? t)) if (PointerWrapper.TryResolvePointer(p, out T? t))
return t!; return t!;
t = (T) FormatterServices.GetUninitializedObject(_type); t = (T?) Constructor.Active.InstantiateGeneric(_constructorType, p);
t.Initialize(p);
_cache[index] = t; _cache[index] = t;
return t; return t;
} }