using System; using System.Runtime.Serialization; using PkmnLibSharp.Battling; using PkmnLibSharp.Library; 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(); internal enum GenericType { Species, Forme, MoveData, Item, LearnableMoves, EvolutionData, Pokemon, Battle, BattleParty, BattleSide, LearnedMove, Ability } internal abstract Species? ConstructSpecies(IntPtr ptr); internal abstract Ability? ConstructAbility(IntPtr ptr); internal abstract Forme? ConstructForme(IntPtr ptr); internal abstract MoveData? ConstructMove(IntPtr ptr); internal abstract Item? ConstructItem(IntPtr ptr); 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, TBattleParty, TBattleSide, TLearnedMove, TAbility> : Constructor where TSpecies : Species where TForme : Forme where TMoveData : MoveData where TItem : Item where TLearnableMoves : LearnableMoves where TPokemon : Pokemon where TBattle : Battle where TBattleParty : BattleParty where TBattleSide : BattleSide where TLearnedMove : LearnedMove where TAbility : Ability { private readonly Type _speciesType = typeof(TSpecies); private readonly Type _formeType = typeof(TForme); private readonly Type _moveDataType = typeof(TMoveData); private readonly Type _itemType = typeof(TItem); private readonly Type _learnableMovesType = typeof(TLearnableMoves); private readonly Type _abilityType = typeof(TAbility); 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; var o = (T)FormatterServices.GetUninitializedObject(t); o.Initialize(ptr); return o; } internal override Species? ConstructSpecies(IntPtr ptr) { return Create(ptr, _speciesType); } internal override Ability? ConstructAbility(IntPtr ptr) { return Create(ptr, _abilityType); } internal override Forme? ConstructForme(IntPtr ptr) { return Create(ptr, _formeType); } internal override MoveData? ConstructMove(IntPtr ptr) { return Create(ptr, _moveDataType); } internal override Item? ConstructItem(IntPtr ptr) { return Create(ptr, _itemType); } 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); } 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); } } }