Adds new NativePtrArray class to deal with native arrays easier.

This commit is contained in:
Deukhoofd 2020-07-25 12:52:18 +02:00
parent 4d74dcc263
commit 34c64d6b68
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
9 changed files with 178 additions and 13 deletions

View File

@ -10,9 +10,9 @@ Global
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4CB6DA3C-017B-4AE0-B889-3DFE6B969CD0}.Debug|Any CPU.ActiveCfg = Release|x86_64 {4CB6DA3C-017B-4AE0-B889-3DFE6B969CD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4CB6DA3C-017B-4AE0-B889-3DFE6B969CD0}.Debug|Any CPU.Build.0 = Release|x86_64 {4CB6DA3C-017B-4AE0-B889-3DFE6B969CD0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0D15FD33-1AEA-44F4-8211-AA8AF97EA534}.Debug|Any CPU.ActiveCfg = Debug|x86_64 {0D15FD33-1AEA-44F4-8211-AA8AF97EA534}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0D15FD33-1AEA-44F4-8211-AA8AF97EA534}.Debug|Any CPU.Build.0 = Debug|x86_64 {0D15FD33-1AEA-44F4-8211-AA8AF97EA534}.Debug|Any CPU.Build.0 = Debug|Any CPU
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@ -8,6 +8,7 @@ namespace PkmnLibSharp.Battling
{ {
public class LearnedMove : PointerWrapper public class LearnedMove : PointerWrapper
{ {
public LearnedMove(){}
internal LearnedMove(IntPtr ptr) : base(ptr){} internal LearnedMove(IntPtr ptr) : base(ptr){}
public static LearnedMove Create(MoveData move, byte maxUses, MoveLearnMethod learnMethod) public static LearnedMove Create(MoveData move, byte maxUses, MoveLearnMethod learnMethod)
@ -16,6 +17,26 @@ namespace PkmnLibSharp.Battling
LearnedAttack.Construct(ref ptr, move.Ptr, maxUses, (AttackLearnMethod) learnMethod).Assert(); LearnedAttack.Construct(ref ptr, move.Ptr, maxUses, (AttackLearnMethod) learnMethod).Assert();
return new LearnedMove(ptr); return new LearnedMove(ptr);
} }
public MoveData Move
{
get
{
if (_move != null) return _move;
var ptr = LearnedAttack.GetAttack(Ptr);
if (TryResolvePointer(ptr, out _move))
return _move;
_move = new MoveData(ptr);
return _move;
}
}
public byte MaxUses => Creaturelibbattling.Generated.LearnedAttack.GetMaxUses(Ptr);
public byte RemainingUses => Creaturelibbattling.Generated.LearnedAttack.GetRemainingUses(Ptr);
public MoveLearnMethod LearnMethod =>
(MoveLearnMethod) Creaturelibbattling.Generated.LearnedAttack.GetLearnMethod(Ptr);
private MoveData _move;
protected override void DeletePtr() protected override void DeletePtr()
{ {

View File

@ -187,15 +187,20 @@ namespace PkmnLibSharp.Battling
{ {
return Creaturelibbattling.Generated.Creature.HasVolatileScript(Ptr, scriptName.ToPtr()) == 1; return Creaturelibbattling.Generated.Creature.HasVolatileScript(Ptr, scriptName.ToPtr()) == 1;
} }
public NativePtrArray<LearnedMove> GetMoves()
{
if (_moves != null) return _moves;
var movesLength = Creaturelibbattling.Generated.Creature.GetAttacksCount(Ptr);
var movesPtr = Creaturelibbattling.Generated.Creature.GetAttacks(Ptr);
_moves = new NativePtrArray<LearnedMove>(movesPtr, (int) movesLength);
return _moves;
}
private Species _species; private Species _species;
private Forme _forme; private Forme _forme;
private string _nickname; private string _nickname;
private NativePtrArray<LearnedMove> _moves;
protected override void DeletePtr() protected override void DeletePtr()
{ {

View File

@ -2,8 +2,12 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework> <TargetFramework>netstandard2.1</TargetFramework>
<Configurations>Release;Debug</Configurations> <Configurations>Debug</Configurations>
<Platforms>x86_64</Platforms> <Platforms>AnyCPU</Platforms>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Content Include="Native/*.so.*" CopyToOutputDirectory="Always" CopyToPublishDirectory="Always" Link="%(Filename)%(Extension)"></Content> <Content Include="Native/*.so.*" CopyToOutputDirectory="Always" CopyToPublishDirectory="Always" Link="%(Filename)%(Extension)"></Content>

View File

@ -0,0 +1,111 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace PkmnLibSharp.Utilities
{
public class NativePtrArray<T> : IList<T> where T : PointerWrapper, new()
{
private readonly IntPtr _ptr;
internal NativePtrArray(IntPtr ptr, int length)
{
_ptr = ptr;
Count = length;
}
public IEnumerator<T> GetEnumerator()
{
for (var i = 0; i < Count; i++)
{
yield return this[i];
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(T item)
{
throw new NotImplementedException();
}
public void Clear()
{
throw new NotImplementedException();
}
public bool Contains(T item)
{
foreach (var v in this)
{
if (item == null)
{
if (v.Ptr == IntPtr.Zero)
return true;
continue;
}
if (item.Ptr == v.Ptr)
return true;
}
return false;
}
public void CopyTo(T[] array, int arrayIndex)
{
throw new NotImplementedException();
}
public bool Remove(T item)
{
throw new NotImplementedException();
}
public int Count { get; }
public bool IsReadOnly => true;
public int IndexOf(T item)
{
for (var i = 0; i < Count; i++)
{
var p = _ptr + (i * IntPtr.Size);
if (item == null)
return i;
if (p == item.Ptr)
return i;
}
return -1;
}
public void Insert(int index, T item)
{
throw new NotImplementedException();
}
public void RemoveAt(int index)
{
throw new NotImplementedException();
}
public T this[int index]
{
get
{
unsafe
{
// Where's your god now?
// (We add the offset of the index to the pointer, then dereference the pointer pointer to get the actual pointer.)
var p = new IntPtr(*(void**)IntPtr.Add(_ptr, index * IntPtr.Size).ToPointer());
if (PointerWrapper.TryResolvePointer(p, out T t))
return t;
t = new T();
t.Initialize(p);
return t;
}
}
set => throw new NotImplementedException();
}
}
}

View File

@ -5,7 +5,7 @@ namespace PkmnLibSharp.Utilities
{ {
public abstract class PointerWrapper : IDisposable public abstract class PointerWrapper : IDisposable
{ {
private readonly IntPtr _ptr; private IntPtr _ptr;
internal IntPtr Ptr internal IntPtr Ptr
{ {
@ -31,6 +31,11 @@ namespace PkmnLibSharp.Utilities
} }
protected PointerWrapper(IntPtr ptr) protected PointerWrapper(IntPtr ptr)
{
Initialize(ptr);
}
protected internal void Initialize(IntPtr ptr)
{ {
_ptr = ptr; _ptr = ptr;
var weakRef = new WeakReference<object>(this); var weakRef = new WeakReference<object>(this);

View File

@ -32,6 +32,13 @@ namespace PkmnLibSharpTests.Battling
20, 100)); 20, 100));
var moves = MoveLibrary.Create(10); var moves = MoveLibrary.Create(10);
moves.Insert("testMove", MoveData.Create("testMove", 0, MoveCategory.Physical, 100,
100, 20, MoveTarget.Any, 0, 0f, "",
new EffectParameter[0], new string[0]));
moves.Insert("testMove2", MoveData.Create("testMove2", 0, MoveCategory.Physical, 100,
100, 20, MoveTarget.Any, 0, 0f, "",
new EffectParameter[0], new string[0]));
var items = new ItemLibrary(10); var items = new ItemLibrary(10);
items.Insert("testItem", Item.Create("testItem", ItemCategory.MiscItem, BattleItemCategory.None, items.Insert("testItem", Item.Create("testItem", ItemCategory.MiscItem, BattleItemCategory.None,
500, new string[] { }, 20)); 500, new string[] { }, 20));

View File

@ -36,5 +36,17 @@ namespace PkmnLibSharpTests.Battling
Assert.AreEqual(Gender.Female, pokemon.Gender); Assert.AreEqual(Gender.Female, pokemon.Gender);
} }
[Test]
public void BuildPokemonWithMoves()
{
var lib = BattleLibraryHelper.GetLibrary();
var pokemon = new PokemonBuilder(lib, "testSpecies", 50)
.LearnMove("testMove", MoveLearnMethod.Unknown)
.LearnMove("testMove2", MoveLearnMethod.Level)
.Build();
Assert.AreEqual("testMove", pokemon.GetMoves()[0].Move.Name);
Assert.AreEqual("testMove2", pokemon.GetMoves()[1].Move.Name);
}
} }
} }

View File

@ -5,9 +5,9 @@
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
<Configurations>Debug;Release</Configurations> <Configurations>Debug</Configurations>
<Platforms>x86_64</Platforms> <Platforms>AnyCPU</Platforms>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>