Implements Form foreign interface
This commit is contained in:
parent
8bb62aa260
commit
c8be93f83f
|
@ -0,0 +1,57 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using PkmnLibSharp.StaticData;
|
||||
|
||||
namespace PkmnLibSharp.FFI.StaticData
|
||||
{
|
||||
internal static class Form
|
||||
{
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern IntPtr form_new(IntPtr name, float height, float weight, uint baseExperience,
|
||||
IntPtr types, ulong typesLength, IntPtr baseStats, IntPtr abilities, ulong abilitiesLength,
|
||||
IntPtr hiddenAbilities, ulong hiddenAbilitiesLength, IntPtr learnableMoves, IntPtr flags,
|
||||
ulong flagsLength);
|
||||
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void form_drop(IntPtr ptr);
|
||||
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern IntPtr form_name(IntPtr ptr);
|
||||
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern float form_height(IntPtr ptr);
|
||||
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern float form_weight(IntPtr ptr);
|
||||
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern uint form_base_experience(IntPtr ptr);
|
||||
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern ulong form_types_length(IntPtr ptr);
|
||||
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern TypeIdentifier form_types_get(IntPtr ptr, ulong index);
|
||||
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern IntPtr form_base_stats(IntPtr ptr);
|
||||
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern ulong form_abilities_length(IntPtr ptr);
|
||||
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern IntPtr form_abilities_get(IntPtr ptr, ulong index);
|
||||
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern ulong form_hidden_abilities_length(IntPtr ptr);
|
||||
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern IntPtr form_hidden_abilities_get(IntPtr ptr, ulong index);
|
||||
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern IntPtr form_moves(IntPtr ptr);
|
||||
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern byte form_has_flag(IntPtr ptr, IntPtr flag);
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<RootNamespace>PkmnLibSharp</RootNamespace>
|
||||
<LangVersion>8</LangVersion>
|
||||
<LangVersion>9</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using PkmnLibSharp.Utils;
|
||||
using Interface = PkmnLibSharp.FFI.StaticData.Form;
|
||||
|
||||
namespace PkmnLibSharp.StaticData
|
||||
{
|
||||
public class Form : ExternPointer<Form.CacheData>
|
||||
{
|
||||
public class CacheData
|
||||
{
|
||||
public string? Name { get; internal set; }
|
||||
public float? Height { get; internal set; }
|
||||
public float? Weight { get; internal set; }
|
||||
public uint? BaseExperience { get; internal set; }
|
||||
public ulong? TypesLength { get; internal set; }
|
||||
public CachedExternValueArray<TypeIdentifier>? Types { get; internal set; }
|
||||
public StaticStatisticSet<ushort>? BaseStats { get; internal set; }
|
||||
public CachedExternArray<string>? Abilities { get; internal set; }
|
||||
public CachedExternArray<string>? HiddenAbilities { get; internal set; }
|
||||
public LearnableMoves? LearnableMoves { get; internal set; }
|
||||
}
|
||||
|
||||
public Form(string name, float height, float weight, uint baseExperience, TypeIdentifier[] types,
|
||||
StaticStatisticSet<short> baseStats, IReadOnlyCollection<string> abilities,
|
||||
IReadOnlyCollection<string> hiddenAbilities, LearnableMoves learnableMoves,
|
||||
IReadOnlyCollection<string> flags)
|
||||
{
|
||||
var typesArr = types.ArrayPtr();
|
||||
|
||||
var abilitiesPtrArray = abilities.Select(x => x.ToPtr()).ToArray();
|
||||
var hiddenAbilitiesPtrArray = hiddenAbilities.Select(x => x.ToPtr()).ToArray();
|
||||
var flagsPtrArray = flags.Select(x => x.ToPtr()).ToArray();
|
||||
|
||||
var ptr = Interface.form_new(name.ToPtr(), height, weight, baseExperience, typesArr, (ulong)types.Length,
|
||||
baseStats.TakeOwnershipAndInvalidate(), abilitiesPtrArray.ArrayPtr(), (ulong)abilities.Count,
|
||||
hiddenAbilitiesPtrArray.ArrayPtr(), (ulong)hiddenAbilities.Count,
|
||||
learnableMoves.TakeOwnershipAndInvalidate(), flagsPtrArray.ArrayPtr(), (ulong)flags.Count);
|
||||
InitializePointer(ptr, true);
|
||||
}
|
||||
|
||||
public string Name => Cache.Name ??= Interface.form_name(Ptr).PtrString()!;
|
||||
public float Height => Cache.Height ??= Interface.form_height(Ptr);
|
||||
public float Weight => Cache.Weight ??= Interface.form_weight(Ptr);
|
||||
public uint BaseExperience => Cache.BaseExperience ??= Interface.form_base_experience(Ptr);
|
||||
|
||||
public IReadOnlyList<TypeIdentifier> Types =>
|
||||
Cache.Types ??= new CachedExternValueArray<TypeIdentifier>(Interface.form_types_length(Ptr),
|
||||
arg => Interface.form_types_get(Ptr, arg));
|
||||
|
||||
public StaticStatisticSet<ushort> BaseStats =>
|
||||
Cache.BaseStats ??= new StaticStatisticSet<ushort>(Interface.form_base_stats(Ptr), false);
|
||||
|
||||
public IReadOnlyList<string> Abilities =>
|
||||
Cache.Abilities ??= new CachedExternArray<string>(Interface.form_abilities_length(Ptr),
|
||||
arg => Interface.form_abilities_get(Ptr, arg).PtrString()!);
|
||||
|
||||
public IReadOnlyList<string> HiddenAbilities =>
|
||||
Cache.HiddenAbilities ??= new CachedExternArray<string>(Interface.form_hidden_abilities_length(Ptr),
|
||||
arg => Interface.form_hidden_abilities_get(Ptr, arg).PtrString()!);
|
||||
|
||||
public LearnableMoves LearnableMoves =>
|
||||
Cache.LearnableMoves ??= new LearnableMoves(Interface.form_moves(Ptr), false);
|
||||
|
||||
|
||||
protected override CacheData CreateCache() => new CacheData();
|
||||
|
||||
protected override void Destructor() => Interface.form_drop(Ptr);
|
||||
}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
using System;
|
||||
using PkmnLibSharp.Utils;
|
||||
using Interface = PkmnLibSharp.FFI.StaticData.LearnableMoves;
|
||||
using LevelInt = System.Byte;
|
||||
|
@ -6,6 +7,10 @@ namespace PkmnLibSharp.StaticData
|
|||
{
|
||||
public class LearnableMoves : ExternPointer<object>
|
||||
{
|
||||
internal LearnableMoves(IntPtr ptr, bool isOwner) : base(ptr, isOwner)
|
||||
{
|
||||
}
|
||||
|
||||
public LearnableMoves() : base(Interface.learnable_moves_new(), true)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -12,8 +12,7 @@ namespace PkmnLibSharp.StaticData
|
|||
{
|
||||
public float? Chance { get; internal set; }
|
||||
public string? Name { get; internal set; }
|
||||
public ulong? ParameterLength { get; internal set; }
|
||||
public EffectParameter?[]? Parameters { get; internal set; }
|
||||
public CachedExternArray<EffectParameter>? Parameters { get; internal set; }
|
||||
}
|
||||
|
||||
internal SecondaryEffect(IntPtr ptr, bool isOwner) : base(ptr, isOwner)
|
||||
|
@ -32,20 +31,10 @@ namespace PkmnLibSharp.StaticData
|
|||
public float Chance => Cache.Chance ??= Interface.secondary_effect_chance(Ptr);
|
||||
public string Name => Cache.Name ?? (Cache.Name = Interface.secondary_effect_effect_name(Ptr).PtrString()!);
|
||||
|
||||
public ulong ParameterLength =>
|
||||
Cache.ParameterLength ?? (Cache.ParameterLength = Interface.secondary_effect_parameter_length(Ptr)).Value;
|
||||
|
||||
public EffectParameter GetParameter(int index)
|
||||
{
|
||||
Cache.Parameters ??= new EffectParameter[ParameterLength];
|
||||
if (Cache.Parameters[index] == null)
|
||||
{
|
||||
var ptr = Interface.secondary_effect_parameter_get(Ptr, (ulong)index);
|
||||
Cache.Parameters[index] = new EffectParameter(ptr, false);
|
||||
}
|
||||
|
||||
return Cache.Parameters[index]!;
|
||||
}
|
||||
public IReadOnlyList<EffectParameter> Parameters =>
|
||||
Cache.Parameters ??= new CachedExternArray<EffectParameter>(
|
||||
Interface.secondary_effect_parameter_length(Ptr),
|
||||
arg => new EffectParameter(Interface.secondary_effect_parameter_get(Ptr, arg), false));
|
||||
|
||||
protected override CacheData CreateCache()
|
||||
{
|
||||
|
|
|
@ -17,6 +17,10 @@ namespace PkmnLibSharp.StaticData
|
|||
public T? Speed { get; internal set; }
|
||||
}
|
||||
|
||||
internal StaticStatisticSet(IntPtr ptr, bool isOwner) : base(ptr, isOwner)
|
||||
{
|
||||
}
|
||||
|
||||
public StaticStatisticSet(T hp, T attack, T defense, T specialAttack, T specialDefense, T speed)
|
||||
{
|
||||
var p = typeof(T) switch
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace PkmnLibSharp.StaticData
|
|||
// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
|
||||
[FieldOffset(0)] private readonly byte _identifier;
|
||||
|
||||
internal TypeIdentifier(byte b)
|
||||
public TypeIdentifier(byte b)
|
||||
{
|
||||
_identifier = b;
|
||||
}
|
||||
|
@ -37,5 +37,10 @@ namespace PkmnLibSharp.StaticData
|
|||
{
|
||||
return !left.Equals(right);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Type({_identifier})";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace PkmnLibSharp.Utils
|
||||
{
|
||||
public class CachedExternArray<T> : IReadOnlyList<T>
|
||||
where T: class
|
||||
{
|
||||
private readonly T?[] _array;
|
||||
private readonly Func<ulong, T> _getItem;
|
||||
|
||||
public CachedExternArray(ulong size, Func<ulong, T> getItem)
|
||||
{
|
||||
_array = new T?[(int)size];
|
||||
_getItem = getItem;
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
yield return this[i];
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public int Count => _array.Length;
|
||||
|
||||
public T this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (index >= _array.Length)
|
||||
throw new ArgumentOutOfRangeException(
|
||||
$"Index {index} was outside of the bounds of the external array with length {Count}");
|
||||
return _array[index] ??= _getItem((ulong)index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class CachedExternValueArray<T> : IReadOnlyList<T>
|
||||
where T: struct
|
||||
{
|
||||
private readonly T?[] _array;
|
||||
private readonly Func<ulong, T> _getItem;
|
||||
|
||||
public CachedExternValueArray(ulong size, Func<ulong, T> getItem)
|
||||
{
|
||||
_array = new T?[(int)size];
|
||||
_getItem = getItem;
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
yield return this[i];
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public int Count => _array.Length;
|
||||
|
||||
public T this[int index] => _array[index] ??= _getItem((ulong)index);
|
||||
}
|
||||
|
||||
}
|
|
@ -25,7 +25,7 @@ namespace PkmnLibSharp.Utils
|
|||
{
|
||||
return Marshal.UnsafeAddrOfPinnedArrayElement(a, 0);
|
||||
}
|
||||
internal static IntPtr ArrayPtr<T>(this T[] a) where T : struct, IConvertible
|
||||
internal static IntPtr ArrayPtr<T>(this T[] a) where T : struct
|
||||
{
|
||||
return Marshal.UnsafeAddrOfPinnedArrayElement(a, 0);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
using NUnit.Framework;
|
||||
using PkmnLibSharp.StaticData;
|
||||
|
||||
namespace PkmnLibRSharpTests.StaticData
|
||||
{
|
||||
public class FormTests
|
||||
{
|
||||
[Test]
|
||||
public void BasicTests()
|
||||
{
|
||||
using var form = new Form("foobar", 0.2f, 5.8f, 300, new TypeIdentifier[] { new(1), new(2) },
|
||||
new StaticStatisticSet<short>(5, 10, 30, 20, 2, 0), new[] { "foo", "bar" }, new[] { "set" },
|
||||
new LearnableMoves(), Array.Empty<string>());
|
||||
Assert.AreEqual("foobar", form.Name);
|
||||
Assert.AreEqual(0.2f, form.Height, 0.00001f);
|
||||
Assert.AreEqual(5.8f, form.Weight, 0.00001f);
|
||||
Assert.AreEqual(300, form.BaseExperience);
|
||||
Assert.AreEqual(new TypeIdentifier(1), form.Types[0]);
|
||||
Assert.AreEqual(new TypeIdentifier(2), form.Types[1]);
|
||||
Assert.AreEqual(10, form.BaseStats.Attack);
|
||||
Assert.AreEqual("foo", form.Abilities[0]);
|
||||
Assert.AreEqual("bar", form.Abilities[1]);
|
||||
Assert.AreEqual("set", form.HiddenAbilities[0]);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue