Initial work

This commit is contained in:
Deukhoofd 2022-09-18 18:02:27 +02:00
commit 097b2111aa
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
33 changed files with 1629 additions and 0 deletions

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
*.so filter=lfs diff=lfs merge=lfs -text

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
bin/
obj/
/packages/
riderModule.iml
/_ReSharper.Caches/
.idea

22
PkmnLibRSharp.sln Normal file
View File

@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PkmnLibRSharp", "PkmnLibRSharp\PkmnLibRSharp.csproj", "{3291855A-7704-4FA1-BEF0-60F00ECF44B0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PkmnLibRSharpTests", "PkmnLibRSharpTests\PkmnLibRSharpTests.csproj", "{8D006ABF-9F4D-4995-9101-504ED67BFDD2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{3291855A-7704-4FA1-BEF0-60F00ECF44B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3291855A-7704-4FA1-BEF0-60F00ECF44B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3291855A-7704-4FA1-BEF0-60F00ECF44B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3291855A-7704-4FA1-BEF0-60F00ECF44B0}.Release|Any CPU.Build.0 = Release|Any CPU
{8D006ABF-9F4D-4995-9101-504ED67BFDD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8D006ABF-9F4D-4995-9101-504ED67BFDD2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8D006ABF-9F4D-4995-9101-504ED67BFDD2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8D006ABF-9F4D-4995-9101-504ED67BFDD2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,4 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=FFI/@EntryIndexedValue">FFI</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HP/@EntryIndexedValue">HP</s:String>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Pkmn/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@ -0,0 +1,7 @@
namespace PkmnLibSharp.FFI
{
internal static class Data
{
internal const string DllName = "pkmn_lib.so";
}
}

View File

@ -0,0 +1,26 @@
using System;
using System.Runtime.InteropServices;
namespace PkmnLibSharp.FFI.StaticData
{
internal static class Ability
{
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern IntPtr ability_new(IntPtr name, IntPtr effect, IntPtr parameters, ulong size);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void ability_drop(IntPtr value);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern string ability_name(IntPtr value);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern string ability_effect(IntPtr value);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern ulong ability_parameter_length(IntPtr value);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern IntPtr ability_parameter_get(IntPtr value, ulong index);
}
}

View File

@ -0,0 +1,39 @@
using System;
using System.Runtime.InteropServices;
namespace PkmnLibSharp.FFI.StaticData
{
internal static class EffectParameter
{
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr effect_parameter_new_bool(byte value);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr effect_parameter_new_int(long value);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr effect_parameter_new_float(float value);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern IntPtr effect_parameter_new_string(IntPtr value);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern void effect_parameter_drop(IntPtr value);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern byte effect_parameter_get_type(IntPtr value);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern byte effect_parameter_get_as_bool(IntPtr value);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern long effect_parameter_get_as_int(IntPtr value);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern float effect_parameter_get_as_float(IntPtr value);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr effect_parameter_get_as_string(IntPtr value);
}
}

View File

@ -0,0 +1,67 @@
using System;
using System.Runtime.InteropServices;
using PkmnLibSharp.StaticData;
namespace PkmnLibSharp.FFI.StaticData
{
internal static class MoveData
{
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr move_data_new(IntPtr name, TypeIdentifier moveType, MoveCategory category,
byte basePower, byte accuracy, byte baseUsages, MoveTarget target, sbyte priority, IntPtr secondaryEffect,
IntPtr flags, ulong flagsLength);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern void move_data_drop(IntPtr p);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr move_data_name(IntPtr p);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern TypeIdentifier move_data_move_type(IntPtr p);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern MoveCategory move_data_category(IntPtr p);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern byte move_data_base_power(IntPtr p);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern byte move_data_accuracy(IntPtr p);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern byte move_data_base_usages(IntPtr p);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern MoveTarget move_data_target(IntPtr p);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern sbyte move_data_priority(IntPtr p);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr move_data_secondary_effect(IntPtr p);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern byte move_data_has_flag(IntPtr p, IntPtr flag);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr secondary_effect_new(float chance, IntPtr effectName, IntPtr parameters,
ulong parametersLength);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern void secondary_effect_drop(IntPtr p);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern float secondary_effect_chance(IntPtr p);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr secondary_effect_effect_name(IntPtr p);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern ulong secondary_effect_parameter_length(IntPtr p);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr secondary_effect_parameter_get(IntPtr p, ulong index);
}
}

View File

@ -0,0 +1,25 @@
using System;
using System.Runtime.InteropServices;
using PkmnLibSharp.StaticData;
namespace PkmnLibSharp.FFI.StaticData
{
internal static class Nature
{
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr nature_new(Statistic increaseStat, Statistic decreaseStat, float increaseModifier,
float decreaseModifier);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern void nature_drop(IntPtr p);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern Statistic nature_increased_stat(IntPtr p);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern Statistic nature_decreased_stat(IntPtr p);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern float nature_get_stat_modifier(IntPtr p, Statistic statistic);
}
}

View File

@ -0,0 +1,69 @@
using System;
using System.Runtime.InteropServices;
using PkmnLibSharp.StaticData;
namespace PkmnLibSharp.FFI.StaticData
{
internal static class StaticStatisticSet
{
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern IntPtr static_statistic_set_u8_new(byte hp, byte attack, byte defense,
byte specialAttack, byte specialDefense, byte speed);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern IntPtr static_statistic_set_u16_new(ushort hp, ushort attack, ushort defense,
ushort specialAttack, ushort specialDefense, ushort speed);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern IntPtr static_statistic_set_u32_new(uint hp, uint attack, uint defense,
uint specialAttack, uint specialDefense, uint speed);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern IntPtr static_statistic_set_i8_new(sbyte hp, sbyte attack, sbyte defense,
sbyte specialAttack, sbyte specialDefense, sbyte speed);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern IntPtr static_statistic_set_i16_new(short hp, short attack, short defense,
short specialAttack, short specialDefense, short speed);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern IntPtr static_statistic_set_i32_new(int hp, int attack, int defense, int specialAttack,
int specialDefense, int speed);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void static_statistic_set_u8_drop(IntPtr value);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void static_statistic_set_u16_drop(IntPtr value);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void static_statistic_set_u32_drop(IntPtr value);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void static_statistic_set_i8_drop(IntPtr value);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void static_statistic_set_i16_drop(IntPtr value);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void static_statistic_set_i32_drop(IntPtr value);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern byte static_statistic_set_u8_get_stat(IntPtr value, Statistic statistic);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern ushort static_statistic_set_u16_get_stat(IntPtr value, Statistic statistic);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern uint static_statistic_set_u32_get_stat(IntPtr value, Statistic statistic);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern sbyte static_statistic_set_i8_get_stat(IntPtr value, Statistic statistic);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern short static_statistic_set_i16_get_stat(IntPtr value, Statistic statistic);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern int static_statistic_set_i32_get_stat(IntPtr value, Statistic statistic);
}
}

View File

@ -0,0 +1,125 @@
using System;
using System.Runtime.InteropServices;
using PkmnLibSharp.StaticData;
namespace PkmnLibSharp.FFI.StaticData
{
internal static class StatisticSet
{
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern IntPtr statistic_set_u8_new(byte hp, byte attack, byte defense, byte specialAttack,
byte specialDefense, byte speed);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern IntPtr statistic_set_u16_new(ushort hp, ushort attack, ushort defense,
ushort specialAttack, ushort specialDefense, ushort speed);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern IntPtr statistic_set_u32_new(uint hp, uint attack, uint defense, uint specialAttack,
uint specialDefense, uint speed);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern IntPtr statistic_set_i8_new(sbyte hp, sbyte attack, sbyte defense, sbyte specialAttack,
sbyte specialDefense, sbyte speed);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern IntPtr statistic_set_i16_new(short hp, short attack, short defense, short specialAttack,
short specialDefense, short speed);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern IntPtr statistic_set_i32_new(int hp, int attack, int defense, int specialAttack,
int specialDefense, int speed);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void statistic_set_u8_drop(IntPtr value);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void statistic_set_u16_drop(IntPtr value);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void statistic_set_u32_drop(IntPtr value);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void statistic_set_i8_drop(IntPtr value);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void statistic_set_i16_drop(IntPtr value);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void statistic_set_i32_drop(IntPtr value);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern byte statistic_set_u8_get_stat(IntPtr value, Statistic statistic);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern ushort statistic_set_u16_get_stat(IntPtr value, Statistic statistic);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern uint statistic_set_u32_get_stat(IntPtr value, Statistic statistic);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern sbyte statistic_set_i8_get_stat(IntPtr value, Statistic statistic);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern short statistic_set_i16_get_stat(IntPtr value, Statistic statistic);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern int statistic_set_i32_get_stat(IntPtr value, Statistic statistic);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void statistic_set_u8_set_stat(IntPtr value, Statistic statistic, byte v);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void statistic_set_u16_set_stat(IntPtr value, Statistic statistic, ushort v);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void statistic_set_u32_set_stat(IntPtr value, Statistic statistic, uint v);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void statistic_set_i8_set_stat(IntPtr value, Statistic statistic, sbyte v);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void statistic_set_i16_set_stat(IntPtr value, Statistic statistic, short v);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void statistic_set_i32_set_stat(IntPtr value, Statistic statistic, int v);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void statistic_set_u8_increase_stat(IntPtr value, Statistic statistic, byte v);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void statistic_set_u16_increase_stat(IntPtr value, Statistic statistic, ushort v);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void statistic_set_u32_increase_stat(IntPtr value, Statistic statistic, uint v);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void statistic_set_i8_increase_stat(IntPtr value, Statistic statistic, sbyte v);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void statistic_set_i16_increase_stat(IntPtr value, Statistic statistic, short v);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void statistic_set_i32_increase_stat(IntPtr value, Statistic statistic, int v);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void statistic_set_u8_decrease_stat(IntPtr value, Statistic statistic, byte v);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void statistic_set_u16_decrease_stat(IntPtr value, Statistic statistic, ushort v);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void statistic_set_u32_decrease_stat(IntPtr value, Statistic statistic, uint v);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void statistic_set_i8_decrease_stat(IntPtr value, Statistic statistic, sbyte v);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void statistic_set_i16_decrease_stat(IntPtr value, Statistic statistic, short v);
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
internal static extern void statistic_set_i32_decrease_stat(IntPtr value, Statistic statistic, int v);
}
}

View File

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<RootNamespace>PkmnLibSharp</RootNamespace>
<LangVersion>8</LangVersion>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<None Update="libpkmn_lib.so">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2022.1.0" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,59 @@
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using PkmnLibSharp.Utils;
using Interface = PkmnLibSharp.FFI.StaticData.Ability;
namespace PkmnLibSharp.StaticData
{
public class Ability : ExternPointer<Ability.CacheData>
{
[UsedImplicitly]
public class CacheData
{
public string? Name { get; internal set; }
public string? Effect { get; internal set; }
public ulong? ParameterLength { get; internal set; }
public EffectParameter?[]? Parameters { get; internal set; }
}
public Ability(string name, string effect, IReadOnlyCollection<EffectParameter> parameters)
{
// Passing effect parameters to Rust gives Rust full control over them, and means it can move it. As such
// we remove ownership and invalidate the passed parameters.
var parameterArray = parameters.Select(x => x.TakeOwnershipAndInvalidate()).ToArray();
var arrayPtr = parameterArray.ArrayPtr();
InitializePointer(Interface.ability_new(name.ToPtr(), effect.ToPtr(), arrayPtr, (ulong)parameters.Count),
true);
}
public string Name => Cache.Name ?? (Cache.Name = Interface.ability_name(Ptr));
public string Effect => Cache.Effect ?? (Cache.Effect = Interface.ability_effect(Ptr));
public ulong ParameterLength =>
Cache.ParameterLength ?? (Cache.ParameterLength = Interface.ability_parameter_length(Ptr)).Value;
public EffectParameter GetParameter(int index)
{
Cache.Parameters ??= new EffectParameter[ParameterLength];
if (Cache.Parameters[index] == null)
{
var ptr = Interface.ability_parameter_get(Ptr, (ulong)index);
Cache.Parameters[index] = new EffectParameter(ptr, false);
}
return Cache.Parameters[index]!;
}
protected override CacheData CreateCache()
{
return new CacheData();
}
protected override void Destructor()
{
Interface.ability_drop(Ptr);
}
}
}

View File

@ -0,0 +1,93 @@
using System;
using JetBrains.Annotations;
using PkmnLibSharp.Utils;
using Interface = PkmnLibSharp.FFI.StaticData.EffectParameter;
namespace PkmnLibSharp.StaticData
{
public class EffectParameter : ExternPointer<EffectParameter.CacheData>
{
[UsedImplicitly]
public class CacheData
{
public ParameterType? Type { get; internal set; }
public object? Data { get; internal set; }
}
internal EffectParameter(IntPtr ptr, bool isOwner) : base(ptr, isOwner)
{
}
public EffectParameter(bool b) : base(Interface.effect_parameter_new_bool(b.ForeignBool()), true)
{
}
public EffectParameter(long l) : base(Interface.effect_parameter_new_int(l), true)
{
}
public EffectParameter(float f) : base(Interface.effect_parameter_new_float(f), true)
{
}
public EffectParameter(string s) : base(Interface.effect_parameter_new_string(s.ToPtr()), true)
{
}
public enum ParameterType : byte
{
Bool = 0,
Int = 1,
Float = 2,
String = 3
}
public ParameterType Type
{
get
{
var cache = Cache.Type;
if (cache.HasValue)
return cache.Value;
Cache.Type = (ParameterType)Interface.effect_parameter_get_type(Ptr);
return Cache.Type.Value;
}
}
public object Data
{
get
{
var cache = Cache.Data;
if (cache != null)
return cache;
var type = Type;
Cache.Data = type switch
{
ParameterType.Bool => Interface.effect_parameter_get_as_bool(Ptr) == 1,
ParameterType.Int => Interface.effect_parameter_get_as_int(Ptr),
ParameterType.Float => Interface.effect_parameter_get_as_float(Ptr),
ParameterType.String => Interface.effect_parameter_get_as_string(Ptr).PtrString(),
_ => throw new ArgumentOutOfRangeException()
};
return Cache.Data!;
}
}
protected override CacheData CreateCache()
{
return new CacheData();
}
protected override void Destructor()
{
Interface.effect_parameter_drop(Ptr);
}
public override string ToString()
{
var data = Data;
return data is string ? $"{Type}(\"{data}\")" : $"{Type}({data})";
}
}
}

View File

@ -0,0 +1,129 @@
using System;
using System.Collections.Generic;
using System.Linq;
using PkmnLibSharp.Utils;
using Interface = PkmnLibSharp.FFI.StaticData.MoveData;
namespace PkmnLibSharp.StaticData
{
public enum MoveCategory : byte
{
/// A physical move uses the physical attack stats and physical defense stats to calculate damage.
Physical = 0,
/// A special move uses the special attack stats and special defense stats to calculate damage.
Special = 1,
/// A status move does not do damage, and only runs a secondary effect.
Status = 2,
}
public enum MoveTarget : byte
{
/// Adjacent allows a move to target any Pokemon that is either directly to the left or right of
/// the user, opposed to the user, or left or right of the slot that is opposing the user.
Adjacent = 0,
/// AdjacentAlly allows a move to target any Pokemon that is directly to the left or right of
/// the user.
AdjacentAlly,
/// AdjacentAllySelf allows a move to target any Pokemon that is either directly to the left or
/// right of the user, or the user itself.
AdjacentAllySelf,
/// AdjacentOpponent allows a move to target any Pokemon that is either the opponent, or directly
/// to the left or right of it.
AdjacentOpponent,
/// All makes the move target everything on the field.
All,
/// AllAdjacent makes the move target everything adjacent on the field.
AllAdjacent,
/// AllAdjacentOpponent makes the move target everything adjacent to the opponent, and the opponent.
AllAdjacentOpponent,
/// AllAlly targets all Pokemon on the same side as the user.
AllAlly,
/// AllOpponent targets all Pokemon on an opposing side from the user.
AllOpponent,
/// Any allows a move to target a single Pokemon, in any position.
Any,
/// RandomOpponent allows a move to target a single Pokemon, in a random position.
RandomOpponent,
/// SelfUse makes the move target the user itself.
SelfUse,
}
public class MoveData : ExternPointer<MoveData.CacheData>
{
public class CacheData
{
public string? Name { get; internal set; }
public TypeIdentifier? Type { get; internal set; }
public MoveCategory? Category { get; internal set; }
public byte? BasePower { get; internal set; }
public byte? Accuracy { get; internal set; }
public byte? BaseUsages { get; internal set; }
public MoveTarget? Target { get; internal set; }
public sbyte? Priority { get; internal set; }
public SecondaryEffect? SecondaryEffect { get; internal set; }
}
public MoveData(string name, TypeIdentifier moveType, MoveCategory category, byte basePower, byte accuracy,
byte baseUsages, MoveTarget target, sbyte priority, SecondaryEffect? secondaryEffect,
IEnumerable<string> flags)
{
var ptrArray = flags.Select(x => x.ToPtr()).ToArray();
var ptrToPtrArray = ptrArray.ArrayPtr();
var ptr = Interface.move_data_new(name.ToPtr(), moveType, category, basePower, accuracy, baseUsages, target,
priority, secondaryEffect?.TakeOwnershipAndInvalidate() ?? IntPtr.Zero, ptrToPtrArray,
(ulong)ptrArray.Length);
InitializePointer(ptr, true);
}
public string Name => Cache.Name ??= Interface.move_data_name(Ptr).PtrString()!;
public TypeIdentifier Type => Cache.Type ??= Interface.move_data_move_type(Ptr);
public byte BasePower => Cache.BasePower ??= Interface.move_data_base_power(Ptr);
public MoveCategory Category => Cache.Category ??= Interface.move_data_category(Ptr);
public byte Accuracy => Cache.Accuracy ??= Interface.move_data_accuracy(Ptr);
public byte BaseUsages => Cache.BaseUsages ??= Interface.move_data_base_usages(Ptr);
public MoveTarget Target => Cache.Target ??= Interface.move_data_target(Ptr);
public sbyte Priority => Cache.Priority ??= Interface.move_data_priority(Ptr);
public SecondaryEffect? SecondaryEffect
{
get
{
if (Cache.SecondaryEffect != null)
return Cache.SecondaryEffect;
var effect = Interface.move_data_secondary_effect(Ptr);
if (effect == IntPtr.Zero)
return null;
Cache.SecondaryEffect = new SecondaryEffect(effect, false);
return Cache.SecondaryEffect;
}
}
public bool HasFlag(string flag)
{
return Interface.move_data_has_flag(Ptr, flag.ToPtr()) == 1;
}
protected override CacheData CreateCache()
{
return new CacheData();
}
protected override void Destructor()
{
Interface.move_data_drop(Ptr);
}
}
}

View File

@ -0,0 +1,51 @@
using PkmnLibSharp.Utils;
using Interface = PkmnLibSharp.FFI.StaticData.Nature;
namespace PkmnLibSharp.StaticData
{
public class Nature : ExternPointer<Nature.CacheData>
{
public class CacheData
{
public Statistic? IncreasedStat { get; internal set; }
public Statistic? DecreasedStat { get; internal set; }
}
public Nature(Statistic increasedStat, Statistic decreasedStat, float increaseModifier = 1.1f,
float decreaseModifier = 0.9f) : base(
Interface.nature_new(increasedStat, decreasedStat, increaseModifier, decreaseModifier), true)
{
}
public static Nature NeutralNature()
{
return new Nature(Statistic.HP, Statistic.HP, 1f, 1f);
}
public Statistic IncreasedStat
{
get { return Cache.IncreasedStat ??= Interface.nature_increased_stat(Ptr); }
}
public Statistic DecreasedStat
{
get { return Cache.DecreasedStat ??= Interface.nature_decreased_stat(Ptr); }
}
public float GetStatModifier(Statistic statistic)
{
return Interface.nature_get_stat_modifier(Ptr, statistic);
}
protected override CacheData CreateCache()
{
return new CacheData();
}
protected override void Destructor()
{
Interface.nature_drop(Ptr);
}
}
}

View File

@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Linq;
using PkmnLibSharp.Utils;
using Interface = PkmnLibSharp.FFI.StaticData.MoveData;
namespace PkmnLibSharp.StaticData
{
public class SecondaryEffect : ExternPointer<SecondaryEffect.CacheData>
{
public class CacheData
{
public float? Chance { get; internal set; }
public string? Name { get; internal set; }
public ulong? ParameterLength { get; internal set; }
public EffectParameter?[]? Parameters { get; internal set; }
}
internal SecondaryEffect(IntPtr ptr, bool isOwner) : base(ptr, isOwner)
{
}
public SecondaryEffect(float chance, string effectName, IReadOnlyCollection<EffectParameter> parameters)
{
var parameterPtrs = parameters.Select(x => x.TakeOwnershipAndInvalidate()).ToArray();
var parameterArrayPtr = parameterPtrs.ArrayPtr();
InitializePointer(
Interface.secondary_effect_new(chance, effectName.ToPtr(), parameterArrayPtr, (ulong)parameters.Count),
true);
}
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]!;
}
protected override CacheData CreateCache()
{
return new CacheData();
}
protected override void Destructor()
{
Interface.secondary_effect_drop(Ptr);
}
}
}

View File

@ -0,0 +1,129 @@
using System;
using JetBrains.Annotations;
using PkmnLibSharp.Utils;
using Interface = PkmnLibSharp.FFI.StaticData.StaticStatisticSet;
namespace PkmnLibSharp.StaticData
{
public class StaticStatisticSet<T> : ExternPointer<StaticStatisticSet<T>.CacheData> where T : struct, IConvertible
{
public class CacheData
{
public T? HP { get; internal set; }
public T? Attack { get; internal set; }
public T? Defense { get; internal set; }
public T? SpecialAttack { get; internal set; }
public T? SpecialDefense { get; internal set; }
public T? Speed { get; internal set; }
}
public StaticStatisticSet(T hp, T attack, T defense, T specialAttack, T specialDefense, T speed)
{
var p = typeof(T) switch
{
{ } t when t == typeof(byte) => Interface.static_statistic_set_u8_new(Convert.ToByte(hp),
Convert.ToByte(attack), Convert.ToByte(defense), Convert.ToByte(specialAttack),
Convert.ToByte(specialDefense), Convert.ToByte(speed)),
{ } t when t == typeof(ushort) => Interface.static_statistic_set_u16_new(Convert.ToUInt16(hp),
Convert.ToUInt16(attack), Convert.ToUInt16(defense), Convert.ToUInt16(specialAttack),
Convert.ToUInt16(specialDefense), Convert.ToUInt16(speed)),
{ } t when t == typeof(uint) => Interface.static_statistic_set_u32_new(Convert.ToUInt32(hp),
Convert.ToUInt32(attack), Convert.ToUInt32(defense), Convert.ToUInt32(specialAttack),
Convert.ToUInt32(specialDefense), Convert.ToUInt32(speed)),
{ } t when t == typeof(sbyte) => Interface.static_statistic_set_i8_new(Convert.ToSByte(hp),
Convert.ToSByte(attack), Convert.ToSByte(defense), Convert.ToSByte(specialAttack),
Convert.ToSByte(specialDefense), Convert.ToSByte(speed)),
{ } t when t == typeof(short) => Interface.static_statistic_set_i16_new(Convert.ToInt16(hp),
Convert.ToInt16(attack), Convert.ToInt16(defense), Convert.ToInt16(specialAttack),
Convert.ToInt16(specialDefense), Convert.ToInt16(speed)),
{ } t when t == typeof(int) => Interface.static_statistic_set_i32_new(Convert.ToInt32(hp),
Convert.ToInt32(attack), Convert.ToInt32(defense), Convert.ToInt32(specialAttack),
Convert.ToInt32(specialDefense), Convert.ToInt32(speed)),
_ => throw new ArgumentOutOfRangeException()
};
InitializePointer(p, true);
}
[PublicAPI]
public T GetStatistic(Statistic statistic)
{
switch (statistic)
{
case Statistic.HP when Cache.HP.HasValue:
return Cache.HP.Value;
case Statistic.Attack when Cache.Attack.HasValue:
return Cache.Attack.Value;
case Statistic.Defense when Cache.Defense.HasValue:
return Cache.Defense.Value;
case Statistic.SpecialAttack when Cache.SpecialAttack.HasValue:
return Cache.SpecialAttack.Value;
case Statistic.SpecialDefense when Cache.SpecialDefense.HasValue:
return Cache.SpecialDefense.Value;
case Statistic.Speed when Cache.Speed.HasValue:
return Cache.Speed.Value;
}
object p = typeof(T) switch
{
{ } t when t == typeof(byte) => Interface.static_statistic_set_u8_get_stat(Ptr, statistic),
{ } t when t == typeof(ushort) => Interface.static_statistic_set_u16_get_stat(Ptr, statistic),
{ } t when t == typeof(uint) => Interface.static_statistic_set_u32_get_stat(Ptr, statistic),
{ } t when t == typeof(sbyte) => Interface.static_statistic_set_i8_get_stat(Ptr, statistic),
{ } t when t == typeof(short) => Interface.static_statistic_set_i16_get_stat(Ptr, statistic),
{ } t when t == typeof(int) => Interface.static_statistic_set_i32_get_stat(Ptr, statistic),
_ => throw new ArgumentOutOfRangeException()
};
switch (statistic)
{
case Statistic.HP:
Cache.HP = (T)p;
break;
case Statistic.Attack:
Cache.Attack = (T)p;
break;
case Statistic.Defense:
Cache.Defense = (T)p;
break;
case Statistic.SpecialAttack:
Cache.SpecialAttack = (T)p;
break;
case Statistic.SpecialDefense:
Cache.SpecialDefense = (T)p;
break;
case Statistic.Speed:
Cache.Speed = (T)p;
break;
}
return (T)p;
}
public T HP => GetStatistic(Statistic.HP);
public T Attack => GetStatistic(Statistic.Attack);
public T Defense => GetStatistic(Statistic.Defense);
public T SpecialAttack => GetStatistic(Statistic.SpecialAttack);
public T SpecialDefense => GetStatistic(Statistic.SpecialDefense);
public T Speed => GetStatistic(Statistic.Speed);
protected override CacheData CreateCache()
{
return new CacheData();
}
protected override void Destructor()
{
if (typeof(T) == typeof(byte)) Interface.static_statistic_set_u8_drop(Ptr);
else if (typeof(T) == typeof(ushort)) Interface.static_statistic_set_u16_drop(Ptr);
else if (typeof(T) == typeof(uint)) Interface.static_statistic_set_u32_drop(Ptr);
else if (typeof(T) == typeof(sbyte)) Interface.static_statistic_set_i8_drop(Ptr);
else if (typeof(T) == typeof(short)) Interface.static_statistic_set_i16_drop(Ptr);
else if (typeof(T) == typeof(int)) Interface.static_statistic_set_i32_drop(Ptr);
}
}
}

View File

@ -0,0 +1,12 @@
namespace PkmnLibSharp.StaticData
{
public enum Statistic : byte
{
HP = 0,
Attack = 1,
Defense = 2,
SpecialAttack = 3,
SpecialDefense = 4,
Speed = 5
}
}

View File

@ -0,0 +1,127 @@
using System;
using JetBrains.Annotations;
using PkmnLibSharp.Utils;
using Interface = PkmnLibSharp.FFI.StaticData.StatisticSet;
namespace PkmnLibSharp.StaticData
{
public class StatisticSet<T> : ExternPointer<StatisticSet<T>.CacheData> where T : struct, IConvertible
{
public class CacheData
{
// While we require cache types for all pointer data, we can't make caching assumptions for this type.
// As such, this is empty (and never instantiated).
}
public StatisticSet(T hp, T attack, T defense, T specialAttack, T specialDefense, T speed)
{
var p = typeof(T) switch
{
{ } t when t == typeof(byte) => Interface.statistic_set_u8_new(Convert.ToByte(hp),
Convert.ToByte(attack), Convert.ToByte(defense), Convert.ToByte(specialAttack),
Convert.ToByte(specialDefense), Convert.ToByte(speed)),
{ } t when t == typeof(ushort) => Interface.statistic_set_u16_new(Convert.ToUInt16(hp),
Convert.ToUInt16(attack), Convert.ToUInt16(defense), Convert.ToUInt16(specialAttack),
Convert.ToUInt16(specialDefense), Convert.ToUInt16(speed)),
{ } t when t == typeof(uint) => Interface.statistic_set_u32_new(Convert.ToUInt32(hp),
Convert.ToUInt32(attack), Convert.ToUInt32(defense), Convert.ToUInt32(specialAttack),
Convert.ToUInt32(specialDefense), Convert.ToUInt32(speed)),
{ } t when t == typeof(sbyte) => Interface.statistic_set_i8_new(Convert.ToSByte(hp),
Convert.ToSByte(attack), Convert.ToSByte(defense), Convert.ToSByte(specialAttack),
Convert.ToSByte(specialDefense), Convert.ToSByte(speed)),
{ } t when t == typeof(short) => Interface.statistic_set_i16_new(Convert.ToInt16(hp),
Convert.ToInt16(attack), Convert.ToInt16(defense), Convert.ToInt16(specialAttack),
Convert.ToInt16(specialDefense), Convert.ToInt16(speed)),
{ } t when t == typeof(int) => Interface.statistic_set_i32_new(Convert.ToInt32(hp),
Convert.ToInt32(attack), Convert.ToInt32(defense), Convert.ToInt32(specialAttack),
Convert.ToInt32(specialDefense), Convert.ToInt32(speed)),
_ => throw new ArgumentOutOfRangeException()
};
InitializePointer(p, true);
}
[PublicAPI]
public T GetStatistic(Statistic statistic)
{
object p = typeof(T) switch
{
{ } t when t == typeof(byte) => Interface.statistic_set_u8_get_stat(Ptr, statistic),
{ } t when t == typeof(ushort) => Interface.statistic_set_u16_get_stat(Ptr, statistic),
{ } t when t == typeof(uint) => Interface.statistic_set_u32_get_stat(Ptr, statistic),
{ } t when t == typeof(sbyte) => Interface.statistic_set_i8_get_stat(Ptr, statistic),
{ } t when t == typeof(short) => Interface.statistic_set_i16_get_stat(Ptr, statistic),
{ } t when t == typeof(int) => Interface.statistic_set_i32_get_stat(Ptr, statistic),
_ => throw new ArgumentOutOfRangeException()
};
return (T)p;
}
[PublicAPI]
public void SetStatistic(Statistic statistic, T value)
{
if (typeof(T) == typeof(byte)) Interface.statistic_set_u8_set_stat(Ptr, statistic, Convert.ToByte(value));
else if (typeof(T) == typeof(ushort))
Interface.statistic_set_u16_set_stat(Ptr, statistic, Convert.ToUInt16(value));
else if (typeof(T) == typeof(uint))
Interface.statistic_set_u32_set_stat(Ptr, statistic, Convert.ToUInt32(value));
else if (typeof(T) == typeof(sbyte))
Interface.statistic_set_i8_set_stat(Ptr, statistic, Convert.ToSByte(value));
else if (typeof(T) == typeof(short))
Interface.statistic_set_i16_set_stat(Ptr, statistic, Convert.ToInt16(value));
else if (typeof(T) == typeof(int))
Interface.statistic_set_i32_set_stat(Ptr, statistic, Convert.ToInt32(value));
}
public T HP
{
get => GetStatistic(Statistic.HP);
set => SetStatistic(Statistic.HP, value);
}
public T Attack
{
get => GetStatistic(Statistic.Attack);
set => SetStatistic(Statistic.Attack, value);
}
public T Defense
{
get => GetStatistic(Statistic.Defense);
set => SetStatistic(Statistic.Defense, value);
}
public T SpecialAttack
{
get => GetStatistic(Statistic.SpecialAttack);
set => SetStatistic(Statistic.SpecialAttack, value);
}
public T SpecialDefense
{
get => GetStatistic(Statistic.SpecialDefense);
set => SetStatistic(Statistic.SpecialDefense, value);
}
public T Speed
{
get => GetStatistic(Statistic.Speed);
set => SetStatistic(Statistic.Speed, value);
}
protected override CacheData CreateCache()
{
return new CacheData();
}
protected override void Destructor()
{
if (typeof(T) == typeof(byte)) Interface.statistic_set_u8_drop(Ptr);
else if (typeof(T) == typeof(ushort)) Interface.statistic_set_u16_drop(Ptr);
else if (typeof(T) == typeof(uint)) Interface.statistic_set_u32_drop(Ptr);
else if (typeof(T) == typeof(sbyte)) Interface.statistic_set_i8_drop(Ptr);
else if (typeof(T) == typeof(short)) Interface.statistic_set_i16_drop(Ptr);
else if (typeof(T) == typeof(int)) Interface.statistic_set_i32_drop(Ptr);
}
}
}

View File

@ -0,0 +1,41 @@
using System.Runtime.InteropServices;
namespace PkmnLibSharp.StaticData
{
[StructLayout(LayoutKind.Explicit)]
public readonly struct TypeIdentifier
{
// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
[FieldOffset(0)] private readonly byte _identifier;
internal TypeIdentifier(byte b)
{
_identifier = b;
}
public bool Equals(TypeIdentifier other)
{
return _identifier == other._identifier;
}
public override bool Equals(object? obj)
{
return obj is TypeIdentifier other && Equals(other);
}
public override int GetHashCode()
{
return _identifier.GetHashCode();
}
public static bool operator ==(TypeIdentifier left, TypeIdentifier right)
{
return left.Equals(right);
}
public static bool operator !=(TypeIdentifier left, TypeIdentifier right)
{
return !left.Equals(right);
}
}
}

View File

@ -0,0 +1,25 @@
using System;
using System.Collections.Concurrent;
namespace PkmnLibSharp.Utils
{
internal static class CacheHandler
{
private static readonly ConcurrentDictionary<IntPtr, object> Caches = new ConcurrentDictionary<IntPtr, object>();
internal static T GetCache<T>(IntPtr ptr, Func<object> ctor)
{
if (!Caches.TryGetValue(ptr, out var cache))
{
cache = ctor();
Caches.TryAdd(ptr, cache);
}
return (T)cache;
}
internal static void RemoveCache(IntPtr ptr)
{
Caches.TryRemove(ptr, out _);
}
}
}

View File

@ -0,0 +1,96 @@
using System;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("PkmnLibRSharp")]
namespace PkmnLibSharp.Utils
{
public abstract class ExternPointer<TCache> : IDisposable
where TCache : class
{
private IntPtr _ptr;
private bool _isOwner;
private bool _isInvalidated;
private bool _isDisposed;
private TCache? _cache;
protected abstract TCache CreateCache();
internal TCache Cache
{
get { return _cache ??= CacheHandler.GetCache<TCache>(_ptr, CreateCache); }
}
protected ExternPointer()
{
}
protected ExternPointer(IntPtr ptr, bool isOwner)
{
InitializePointer(ptr, isOwner);
}
protected void InitializePointer(IntPtr ptr, bool isOwner)
{
_ptr = ptr;
_isOwner = isOwner;
}
protected abstract void Destructor();
internal IntPtr Ptr
{
get
{
if (_isInvalidated)
{
throw new Exception("Pointer was used after invalidate");
}
return _ptr;
}
}
internal IntPtr TakeOwnership()
{
if (!_isOwner)
{
throw new Exception("Tried to take ownership of a non-owned object");
}
_isOwner = false;
return Ptr;
}
internal IntPtr TakeOwnershipAndInvalidate()
{
var ptr = TakeOwnership();
Invalidate();
return ptr;
}
internal void Invalidate()
{
_isInvalidated = true;
CacheHandler.RemoveCache(_ptr);
}
~ExternPointer()
{
Dispose();
}
public void Dispose()
{
if (_isDisposed)
return;
if (_isOwner)
{
if (!_isInvalidated)
Destructor();
_isOwner = false;
CacheHandler.RemoveCache(_ptr);
}
_isDisposed = true;
_isInvalidated = true;
}
}
}

View File

@ -0,0 +1,33 @@
using System;
using System.Runtime.InteropServices;
namespace PkmnLibSharp.Utils
{
internal static class FFIExtensions
{
internal static byte ForeignBool(this bool b)
{
return b ? (byte)1 : (byte)0;
}
internal static IntPtr ToPtr(this string? s)
{
if (s == null) return IntPtr.Zero;
return Marshal.StringToHGlobalAnsi(s);
}
internal static string? PtrString(this IntPtr i)
{
return i == IntPtr.Zero ? null : Marshal.PtrToStringAnsi(i);
}
internal static IntPtr ArrayPtr(this IntPtr[] a)
{
return Marshal.UnsafeAddrOfPinnedArrayElement(a, 0);
}
internal static IntPtr ArrayPtr<T>(this T[] a) where T : struct, IConvertible
{
return Marshal.UnsafeAddrOfPinnedArrayElement(a, 0);
}
}
}

BIN
PkmnLibRSharp/libpkmn_lib.so (Stored with Git LFS) Executable file

Binary file not shown.

View File

@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="NUnit" Version="3.13.2" />
<PackageReference Include="NUnit3TestAdapter" Version="4.0.0" />
<PackageReference Include="coverlet.collector" Version="3.1.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PkmnLibRSharp\PkmnLibRSharp.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,35 @@
using System;
using NUnit.Framework;
using PkmnLibSharp.StaticData;
namespace PkmnLibRSharpTests.StaticData
{
public class AbilityTests
{
[Test]
public void AbilityGetName([Values("foo", "bar", "", "zet", "xy")] string name)
{
using var ability = new Ability(name, "", Array.Empty<EffectParameter>());
Assert.AreEqual(name, ability.Name);
}
[Test]
public void AbilityGetEffect([Values("foo", "bar", "", "zet", "xy")] string effect)
{
using var ability = new Ability("", effect, Array.Empty<EffectParameter>());
Assert.AreEqual(effect, ability.Effect);
}
[Test]
public void AbilityGetParameters()
{
using var ability = new Ability("", "",
new EffectParameter[] { new(100), new(false), new("foobar"), new(true) });
Assert.AreEqual(4, ability.ParameterLength);
Assert.AreEqual(100, ability.GetParameter(0).Data);
Assert.AreEqual(false, ability.GetParameter(1).Data);
Assert.AreEqual("foobar", ability.GetParameter(2).Data);
Assert.AreEqual(true, ability.GetParameter(3).Data);
}
}
}

View File

@ -0,0 +1,40 @@
using NUnit.Framework;
using PkmnLibSharp.StaticData;
namespace PkmnLibRSharpTests.StaticData
{
public class EffectParameterTests
{
[Test]
public void BoolParameter([Values(true, false)] bool value)
{
using var parameter = new EffectParameter(value);
Assert.AreEqual(EffectParameter.ParameterType.Bool, parameter.Type);
Assert.AreEqual(value, parameter.Data);
}
[Test]
public void IntParameter([Random(long.MinValue, long.MaxValue, 10)] long value)
{
using var parameter = new EffectParameter(value);
Assert.AreEqual(EffectParameter.ParameterType.Int, parameter.Type);
Assert.AreEqual(value, parameter.Data);
}
[Test]
public void FloatParameter([Random(float.MinValue, float.MaxValue, 10)] float value)
{
using var parameter = new EffectParameter(value);
Assert.AreEqual(EffectParameter.ParameterType.Float, parameter.Type);
Assert.AreEqual(value, parameter.Data);
}
[Test]
public void StringParameter([Values("foo", "bar", "zet", "x", "")] string value)
{
using var parameter = new EffectParameter(value);
Assert.AreEqual(EffectParameter.ParameterType.String, parameter.Type);
Assert.AreEqual(value, parameter.Data);
}
}
}

View File

@ -0,0 +1,24 @@
using System;
using NUnit.Framework;
using PkmnLibSharp.StaticData;
namespace PkmnLibRSharpTests.StaticData
{
public class MoveDataTests
{
[Test]
public void BasicTests()
{
using var move = new MoveData("foobar", new TypeIdentifier(), MoveCategory.Physical, 68, 23, 56,
MoveTarget.Any, -3, null, Array.Empty<string>());
Assert.AreEqual("foobar", move.Name);
Assert.AreEqual(MoveCategory.Physical, move.Category);
Assert.AreEqual(68, move.BasePower);
Assert.AreEqual(23, move.Accuracy);
Assert.AreEqual(56, move.BaseUsages);
Assert.AreEqual(MoveTarget.Any, move.Target);
Assert.AreEqual(-3, move.Priority);
Assert.AreEqual(null, move.SecondaryEffect);
}
}
}

View File

@ -0,0 +1,29 @@
using NUnit.Framework;
using PkmnLibSharp.StaticData;
namespace PkmnLibRSharpTests.StaticData
{
public class NatureTests
{
[Test]
public void InstantiateNatures(
[Values] Statistic increasedStat,
[Values] Statistic decreasedStat
)
{
var nature = new Nature(increasedStat, decreasedStat);
Assert.AreEqual(increasedStat, nature.IncreasedStat);
Assert.AreEqual(decreasedStat, nature.DecreasedStat);
if (increasedStat == decreasedStat)
{
Assert.AreEqual(1.0f, nature.GetStatModifier(increasedStat), 0.001f);
Assert.AreEqual(1.0f, nature.GetStatModifier(decreasedStat), 0.001f);
}
else
{
Assert.AreEqual(1.1f, nature.GetStatModifier(increasedStat), 0.001f);
Assert.AreEqual(0.9f, nature.GetStatModifier(decreasedStat), 0.001f);
}
}
}
}

View File

@ -0,0 +1,20 @@
using System;
using NUnit.Framework;
using PkmnLibSharp.StaticData;
namespace PkmnLibRSharpTests.StaticData
{
public class SecondaryEffectTests
{
[Test]
public void BasicTests(
[Values(0, 100, 50, 22.5f)] float chance,
[Values("foo", "bar", "", "ssdsdsdsdsd")] string effectName
)
{
using var effect = new SecondaryEffect(chance, effectName, Array.Empty<EffectParameter>());
Assert.AreEqual(effectName, effect.Name);
Assert.AreEqual(chance, effect.Chance);
}
}
}

View File

@ -0,0 +1,86 @@
using NUnit.Framework;
using PkmnLibSharp.StaticData;
namespace PkmnLibRSharpTests.StaticData
{
public class StaticStaticStatisticSetTests
{
[Test]
public void ByteStaticStatisticSet([Random(1)] byte hp, [Random(1)] byte attack, [Random(1)] byte defense,
[Random(1)] byte specialAttack, [Random(1)] byte specialDefense, [Random(1)] byte speed)
{
using var set = new StaticStatisticSet<byte>(hp, attack, defense, specialAttack, specialDefense, speed);
Assert.AreEqual(set.HP, hp);
Assert.AreEqual(set.Attack, attack);
Assert.AreEqual(set.Defense, defense);
Assert.AreEqual(set.SpecialAttack, specialAttack);
Assert.AreEqual(set.SpecialDefense, specialDefense);
Assert.AreEqual(set.Speed, speed);
}
[Test]
public void UShortStaticStatisticSet([Random(1)] ushort hp, [Random(1)] ushort attack, [Random(1)] ushort defense,
[Random(1)] ushort specialAttack, [Random(1)] ushort specialDefense, [Random(1)] ushort speed)
{
using var set = new StaticStatisticSet<ushort>(hp, attack, defense, specialAttack, specialDefense, speed);
Assert.AreEqual(set.HP, hp);
Assert.AreEqual(set.Attack, attack);
Assert.AreEqual(set.Defense, defense);
Assert.AreEqual(set.SpecialAttack, specialAttack);
Assert.AreEqual(set.SpecialDefense, specialDefense);
Assert.AreEqual(set.Speed, speed);
}
[Test]
public void UintStaticStatisticSet([Random(1)] uint hp, [Random(1)] uint attack, [Random(1)] uint defense,
[Random(1)] uint specialAttack, [Random(1)] uint specialDefense, [Random(1)] uint speed)
{
using var set = new StaticStatisticSet<uint>(hp, attack, defense, specialAttack, specialDefense, speed);
Assert.AreEqual(set.HP, hp);
Assert.AreEqual(set.Attack, attack);
Assert.AreEqual(set.Defense, defense);
Assert.AreEqual(set.SpecialAttack, specialAttack);
Assert.AreEqual(set.SpecialDefense, specialDefense);
Assert.AreEqual(set.Speed, speed);
}
[Test]
public void SbyteStaticStatisticSet([Random(1)] sbyte hp, [Random(1)] sbyte attack, [Random(1)] sbyte defense,
[Random(1)] sbyte specialAttack, [Random(1)] sbyte specialDefense, [Random(1)] sbyte speed)
{
using var set = new StaticStatisticSet<sbyte>(hp, attack, defense, specialAttack, specialDefense, speed);
Assert.AreEqual(set.HP, hp);
Assert.AreEqual(set.Attack, attack);
Assert.AreEqual(set.Defense, defense);
Assert.AreEqual(set.SpecialAttack, specialAttack);
Assert.AreEqual(set.SpecialDefense, specialDefense);
Assert.AreEqual(set.Speed, speed);
}
[Test]
public void ShortStaticStatisticSet([Random(1)] short hp, [Random(1)] short attack, [Random(1)] short defense,
[Random(1)] short specialAttack, [Random(1)] short specialDefense, [Random(1)] short speed)
{
using var set = new StaticStatisticSet<short>(hp, attack, defense, specialAttack, specialDefense, speed);
Assert.AreEqual(set.HP, hp);
Assert.AreEqual(set.Attack, attack);
Assert.AreEqual(set.Defense, defense);
Assert.AreEqual(set.SpecialAttack, specialAttack);
Assert.AreEqual(set.SpecialDefense, specialDefense);
Assert.AreEqual(set.Speed, speed);
}
[Test]
public void IntStaticStatisticSet([Random(1)] int hp, [Random(1)] int attack, [Random(1)] int defense,
[Random(1)] int specialAttack, [Random(1)] int specialDefense, [Random(1)] int speed)
{
using var set = new StaticStatisticSet<int>(hp, attack, defense, specialAttack, specialDefense, speed);
Assert.AreEqual(set.HP, hp);
Assert.AreEqual(set.Attack, attack);
Assert.AreEqual(set.Defense, defense);
Assert.AreEqual(set.SpecialAttack, specialAttack);
Assert.AreEqual(set.SpecialDefense, specialDefense);
Assert.AreEqual(set.Speed, speed);
}
}
}

View File

@ -0,0 +1,105 @@
using NUnit.Framework;
using PkmnLibSharp.StaticData;
namespace PkmnLibRSharpTests.StaticData
{
public class StatisticSetTests
{
[Test]
public void ByteStatisticSet([Random(1)] byte hp, [Random(1)] byte attack, [Random(1)] byte defense,
[Random(1)] byte specialAttack, [Random(1)] byte specialDefense, [Random(1)] byte speed)
{
using var set = new StatisticSet<byte>(hp, attack, defense, specialAttack, specialDefense, speed);
Assert.AreEqual(set.HP, hp);
Assert.AreEqual(set.Attack, attack);
Assert.AreEqual(set.Defense, defense);
Assert.AreEqual(set.SpecialAttack, specialAttack);
Assert.AreEqual(set.SpecialDefense, specialDefense);
Assert.AreEqual(set.Speed, speed);
}
[Test]
public void ByteStatisticSetModifying([Random(1)] byte hp, [Random(1)] byte attack, [Random(1)] byte defense,
[Random(1)] byte specialAttack, [Random(1)] byte specialDefense, [Random(1)] byte speed)
{
using var set = new StatisticSet<byte>(0,0,0,0,0,0);
set.HP = hp;
Assert.AreEqual(set.HP, hp);
set.Attack = attack;
Assert.AreEqual(set.Attack, attack);
set.Defense = defense;
Assert.AreEqual(set.Defense, defense);
set.SpecialAttack = specialAttack;
Assert.AreEqual(set.SpecialAttack, specialAttack);
set.SpecialDefense = specialDefense;
Assert.AreEqual(set.SpecialDefense, specialDefense);
set.Speed = speed;
Assert.AreEqual(set.Speed, speed);
}
[Test]
public void UShortStatisticSet([Random(1)] ushort hp, [Random(1)] ushort attack, [Random(1)] ushort defense,
[Random(1)] ushort specialAttack, [Random(1)] ushort specialDefense, [Random(1)] ushort speed)
{
using var set = new StatisticSet<ushort>(hp, attack, defense, specialAttack, specialDefense, speed);
Assert.AreEqual(set.HP, hp);
Assert.AreEqual(set.Attack, attack);
Assert.AreEqual(set.Defense, defense);
Assert.AreEqual(set.SpecialAttack, specialAttack);
Assert.AreEqual(set.SpecialDefense, specialDefense);
Assert.AreEqual(set.Speed, speed);
}
[Test]
public void UintStatisticSet([Random(1)] uint hp, [Random(1)] uint attack, [Random(1)] uint defense,
[Random(1)] uint specialAttack, [Random(1)] uint specialDefense, [Random(1)] uint speed)
{
using var set = new StatisticSet<uint>(hp, attack, defense, specialAttack, specialDefense, speed);
Assert.AreEqual(set.HP, hp);
Assert.AreEqual(set.Attack, attack);
Assert.AreEqual(set.Defense, defense);
Assert.AreEqual(set.SpecialAttack, specialAttack);
Assert.AreEqual(set.SpecialDefense, specialDefense);
Assert.AreEqual(set.Speed, speed);
}
[Test]
public void SbyteStatisticSet([Random(1)] sbyte hp, [Random(1)] sbyte attack, [Random(1)] sbyte defense,
[Random(1)] sbyte specialAttack, [Random(1)] sbyte specialDefense, [Random(1)] sbyte speed)
{
using var set = new StatisticSet<sbyte>(hp, attack, defense, specialAttack, specialDefense, speed);
Assert.AreEqual(set.HP, hp);
Assert.AreEqual(set.Attack, attack);
Assert.AreEqual(set.Defense, defense);
Assert.AreEqual(set.SpecialAttack, specialAttack);
Assert.AreEqual(set.SpecialDefense, specialDefense);
Assert.AreEqual(set.Speed, speed);
}
[Test]
public void ShortStatisticSet([Random(1)] short hp, [Random(1)] short attack, [Random(1)] short defense,
[Random(1)] short specialAttack, [Random(1)] short specialDefense, [Random(1)] short speed)
{
using var set = new StatisticSet<short>(hp, attack, defense, specialAttack, specialDefense, speed);
Assert.AreEqual(set.HP, hp);
Assert.AreEqual(set.Attack, attack);
Assert.AreEqual(set.Defense, defense);
Assert.AreEqual(set.SpecialAttack, specialAttack);
Assert.AreEqual(set.SpecialDefense, specialDefense);
Assert.AreEqual(set.Speed, speed);
}
[Test]
public void IntStatisticSet([Random(1)] int hp, [Random(1)] int attack, [Random(1)] int defense,
[Random(1)] int specialAttack, [Random(1)] int specialDefense, [Random(1)] int speed)
{
using var set = new StatisticSet<int>(hp, attack, defense, specialAttack, specialDefense, speed);
Assert.AreEqual(set.HP, hp);
Assert.AreEqual(set.Attack, attack);
Assert.AreEqual(set.Defense, defense);
Assert.AreEqual(set.SpecialAttack, specialAttack);
Assert.AreEqual(set.SpecialDefense, specialDefense);
Assert.AreEqual(set.Speed, speed);
}
}
}