From 097b2111aa2605d33a9607b3adc7e66487184185 Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Sun, 18 Sep 2022 18:02:27 +0200 Subject: [PATCH] Initial work --- .gitattributes | 1 + .gitignore | 6 + PkmnLibRSharp.sln | 22 +++ PkmnLibRSharp.sln.DotSettings | 4 + PkmnLibRSharp/FFI/Data.cs | 7 + PkmnLibRSharp/FFI/StaticData/Ability.cs | 26 ++++ .../FFI/StaticData/EffectParameter.cs | 39 ++++++ PkmnLibRSharp/FFI/StaticData/MoveData.cs | 67 +++++++++ PkmnLibRSharp/FFI/StaticData/Nature.cs | 25 ++++ .../FFI/StaticData/StaticStatisticSet.cs | 69 ++++++++++ PkmnLibRSharp/FFI/StaticData/StatisticSet.cs | 125 +++++++++++++++++ PkmnLibRSharp/PkmnLibRSharp.csproj | 20 +++ PkmnLibRSharp/StaticData/Ability.cs | 59 ++++++++ PkmnLibRSharp/StaticData/EffectParameter.cs | 93 +++++++++++++ PkmnLibRSharp/StaticData/MoveData.cs | 129 ++++++++++++++++++ PkmnLibRSharp/StaticData/Nature.cs | 51 +++++++ PkmnLibRSharp/StaticData/SecondaryEffect.cs | 60 ++++++++ .../StaticData/StaticStatisticSet.cs | 129 ++++++++++++++++++ PkmnLibRSharp/StaticData/Statistic.cs | 12 ++ PkmnLibRSharp/StaticData/StatisticSet.cs | 127 +++++++++++++++++ PkmnLibRSharp/StaticData/TypeIdentifier.cs | 41 ++++++ PkmnLibRSharp/Utils/CacheHandler.cs | 25 ++++ PkmnLibRSharp/Utils/ExternPointer.cs | 96 +++++++++++++ PkmnLibRSharp/Utils/FFIExtensions.cs | 33 +++++ PkmnLibRSharp/libpkmn_lib.so | 3 + PkmnLibRSharpTests/PkmnLibRSharpTests.csproj | 21 +++ PkmnLibRSharpTests/StaticData/AbilityTests.cs | 35 +++++ .../StaticData/EffectParameterTests.cs | 40 ++++++ .../StaticData/MoveDataTests.cs | 24 ++++ PkmnLibRSharpTests/StaticData/NatureTests.cs | 29 ++++ .../StaticData/SecondaryEffectTests.cs | 20 +++ .../StaticData/StaticStatisticSetTests.cs | 86 ++++++++++++ .../StaticData/StatisticSetTests.cs | 105 ++++++++++++++ 33 files changed, 1629 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 PkmnLibRSharp.sln create mode 100644 PkmnLibRSharp.sln.DotSettings create mode 100644 PkmnLibRSharp/FFI/Data.cs create mode 100644 PkmnLibRSharp/FFI/StaticData/Ability.cs create mode 100644 PkmnLibRSharp/FFI/StaticData/EffectParameter.cs create mode 100644 PkmnLibRSharp/FFI/StaticData/MoveData.cs create mode 100644 PkmnLibRSharp/FFI/StaticData/Nature.cs create mode 100644 PkmnLibRSharp/FFI/StaticData/StaticStatisticSet.cs create mode 100644 PkmnLibRSharp/FFI/StaticData/StatisticSet.cs create mode 100644 PkmnLibRSharp/PkmnLibRSharp.csproj create mode 100644 PkmnLibRSharp/StaticData/Ability.cs create mode 100644 PkmnLibRSharp/StaticData/EffectParameter.cs create mode 100644 PkmnLibRSharp/StaticData/MoveData.cs create mode 100644 PkmnLibRSharp/StaticData/Nature.cs create mode 100644 PkmnLibRSharp/StaticData/SecondaryEffect.cs create mode 100644 PkmnLibRSharp/StaticData/StaticStatisticSet.cs create mode 100644 PkmnLibRSharp/StaticData/Statistic.cs create mode 100644 PkmnLibRSharp/StaticData/StatisticSet.cs create mode 100644 PkmnLibRSharp/StaticData/TypeIdentifier.cs create mode 100644 PkmnLibRSharp/Utils/CacheHandler.cs create mode 100644 PkmnLibRSharp/Utils/ExternPointer.cs create mode 100644 PkmnLibRSharp/Utils/FFIExtensions.cs create mode 100755 PkmnLibRSharp/libpkmn_lib.so create mode 100644 PkmnLibRSharpTests/PkmnLibRSharpTests.csproj create mode 100644 PkmnLibRSharpTests/StaticData/AbilityTests.cs create mode 100644 PkmnLibRSharpTests/StaticData/EffectParameterTests.cs create mode 100644 PkmnLibRSharpTests/StaticData/MoveDataTests.cs create mode 100644 PkmnLibRSharpTests/StaticData/NatureTests.cs create mode 100644 PkmnLibRSharpTests/StaticData/SecondaryEffectTests.cs create mode 100644 PkmnLibRSharpTests/StaticData/StaticStatisticSetTests.cs create mode 100644 PkmnLibRSharpTests/StaticData/StatisticSetTests.cs diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..c3ad15c --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.so filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..91953df --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +bin/ +obj/ +/packages/ +riderModule.iml +/_ReSharper.Caches/ +.idea \ No newline at end of file diff --git a/PkmnLibRSharp.sln b/PkmnLibRSharp.sln new file mode 100644 index 0000000..7772ca3 --- /dev/null +++ b/PkmnLibRSharp.sln @@ -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 diff --git a/PkmnLibRSharp.sln.DotSettings b/PkmnLibRSharp.sln.DotSettings new file mode 100644 index 0000000..32021a7 --- /dev/null +++ b/PkmnLibRSharp.sln.DotSettings @@ -0,0 +1,4 @@ + + FFI + HP + True \ No newline at end of file diff --git a/PkmnLibRSharp/FFI/Data.cs b/PkmnLibRSharp/FFI/Data.cs new file mode 100644 index 0000000..a3f2584 --- /dev/null +++ b/PkmnLibRSharp/FFI/Data.cs @@ -0,0 +1,7 @@ +namespace PkmnLibSharp.FFI +{ + internal static class Data + { + internal const string DllName = "pkmn_lib.so"; + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/FFI/StaticData/Ability.cs b/PkmnLibRSharp/FFI/StaticData/Ability.cs new file mode 100644 index 0000000..9113d63 --- /dev/null +++ b/PkmnLibRSharp/FFI/StaticData/Ability.cs @@ -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); + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/FFI/StaticData/EffectParameter.cs b/PkmnLibRSharp/FFI/StaticData/EffectParameter.cs new file mode 100644 index 0000000..98089ad --- /dev/null +++ b/PkmnLibRSharp/FFI/StaticData/EffectParameter.cs @@ -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); + + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/FFI/StaticData/MoveData.cs b/PkmnLibRSharp/FFI/StaticData/MoveData.cs new file mode 100644 index 0000000..109ad26 --- /dev/null +++ b/PkmnLibRSharp/FFI/StaticData/MoveData.cs @@ -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); + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/FFI/StaticData/Nature.cs b/PkmnLibRSharp/FFI/StaticData/Nature.cs new file mode 100644 index 0000000..1ab4af5 --- /dev/null +++ b/PkmnLibRSharp/FFI/StaticData/Nature.cs @@ -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); + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/FFI/StaticData/StaticStatisticSet.cs b/PkmnLibRSharp/FFI/StaticData/StaticStatisticSet.cs new file mode 100644 index 0000000..e3c0eb6 --- /dev/null +++ b/PkmnLibRSharp/FFI/StaticData/StaticStatisticSet.cs @@ -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); + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/FFI/StaticData/StatisticSet.cs b/PkmnLibRSharp/FFI/StaticData/StatisticSet.cs new file mode 100644 index 0000000..0a9a260 --- /dev/null +++ b/PkmnLibRSharp/FFI/StaticData/StatisticSet.cs @@ -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); + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/PkmnLibRSharp.csproj b/PkmnLibRSharp/PkmnLibRSharp.csproj new file mode 100644 index 0000000..67b5255 --- /dev/null +++ b/PkmnLibRSharp/PkmnLibRSharp.csproj @@ -0,0 +1,20 @@ + + + + netstandard2.1 + PkmnLibSharp + 8 + enable + + + + + PreserveNewest + + + + + + + + diff --git a/PkmnLibRSharp/StaticData/Ability.cs b/PkmnLibRSharp/StaticData/Ability.cs new file mode 100644 index 0000000..d1ef3cb --- /dev/null +++ b/PkmnLibRSharp/StaticData/Ability.cs @@ -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 + { + [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 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); + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/StaticData/EffectParameter.cs b/PkmnLibRSharp/StaticData/EffectParameter.cs new file mode 100644 index 0000000..f26f0af --- /dev/null +++ b/PkmnLibRSharp/StaticData/EffectParameter.cs @@ -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 + { + [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})"; + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/StaticData/MoveData.cs b/PkmnLibRSharp/StaticData/MoveData.cs new file mode 100644 index 0000000..bd117a7 --- /dev/null +++ b/PkmnLibRSharp/StaticData/MoveData.cs @@ -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 + { + 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 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); + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/StaticData/Nature.cs b/PkmnLibRSharp/StaticData/Nature.cs new file mode 100644 index 0000000..e477e57 --- /dev/null +++ b/PkmnLibRSharp/StaticData/Nature.cs @@ -0,0 +1,51 @@ +using PkmnLibSharp.Utils; +using Interface = PkmnLibSharp.FFI.StaticData.Nature; + +namespace PkmnLibSharp.StaticData +{ + public class Nature : ExternPointer + { + 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); + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/StaticData/SecondaryEffect.cs b/PkmnLibRSharp/StaticData/SecondaryEffect.cs new file mode 100644 index 0000000..9bb0199 --- /dev/null +++ b/PkmnLibRSharp/StaticData/SecondaryEffect.cs @@ -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 + { + 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 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); + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/StaticData/StaticStatisticSet.cs b/PkmnLibRSharp/StaticData/StaticStatisticSet.cs new file mode 100644 index 0000000..5abaea8 --- /dev/null +++ b/PkmnLibRSharp/StaticData/StaticStatisticSet.cs @@ -0,0 +1,129 @@ +using System; +using JetBrains.Annotations; +using PkmnLibSharp.Utils; +using Interface = PkmnLibSharp.FFI.StaticData.StaticStatisticSet; + +namespace PkmnLibSharp.StaticData +{ + public class StaticStatisticSet : ExternPointer.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); + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/StaticData/Statistic.cs b/PkmnLibRSharp/StaticData/Statistic.cs new file mode 100644 index 0000000..da549a6 --- /dev/null +++ b/PkmnLibRSharp/StaticData/Statistic.cs @@ -0,0 +1,12 @@ +namespace PkmnLibSharp.StaticData +{ + public enum Statistic : byte + { + HP = 0, + Attack = 1, + Defense = 2, + SpecialAttack = 3, + SpecialDefense = 4, + Speed = 5 + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/StaticData/StatisticSet.cs b/PkmnLibRSharp/StaticData/StatisticSet.cs new file mode 100644 index 0000000..9cdbc01 --- /dev/null +++ b/PkmnLibRSharp/StaticData/StatisticSet.cs @@ -0,0 +1,127 @@ +using System; +using JetBrains.Annotations; +using PkmnLibSharp.Utils; +using Interface = PkmnLibSharp.FFI.StaticData.StatisticSet; + +namespace PkmnLibSharp.StaticData +{ + public class StatisticSet : ExternPointer.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); + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/StaticData/TypeIdentifier.cs b/PkmnLibRSharp/StaticData/TypeIdentifier.cs new file mode 100644 index 0000000..efd384b --- /dev/null +++ b/PkmnLibRSharp/StaticData/TypeIdentifier.cs @@ -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); + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/Utils/CacheHandler.cs b/PkmnLibRSharp/Utils/CacheHandler.cs new file mode 100644 index 0000000..b0d4941 --- /dev/null +++ b/PkmnLibRSharp/Utils/CacheHandler.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Concurrent; + +namespace PkmnLibSharp.Utils +{ + internal static class CacheHandler + { + private static readonly ConcurrentDictionary Caches = new ConcurrentDictionary(); + + internal static T GetCache(IntPtr ptr, Func 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 _); + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/Utils/ExternPointer.cs b/PkmnLibRSharp/Utils/ExternPointer.cs new file mode 100644 index 0000000..e4532aa --- /dev/null +++ b/PkmnLibRSharp/Utils/ExternPointer.cs @@ -0,0 +1,96 @@ +using System; +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("PkmnLibRSharp")] +namespace PkmnLibSharp.Utils +{ + public abstract class ExternPointer : 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(_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; + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/Utils/FFIExtensions.cs b/PkmnLibRSharp/Utils/FFIExtensions.cs new file mode 100644 index 0000000..3679693 --- /dev/null +++ b/PkmnLibRSharp/Utils/FFIExtensions.cs @@ -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(this T[] a) where T : struct, IConvertible + { + return Marshal.UnsafeAddrOfPinnedArrayElement(a, 0); + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/libpkmn_lib.so b/PkmnLibRSharp/libpkmn_lib.so new file mode 100755 index 0000000..9683056 --- /dev/null +++ b/PkmnLibRSharp/libpkmn_lib.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ebf27a2fcae1c04d58e5c7cde6b58479f47084ceeae09863a6cfcba5f132687f +size 155499256 diff --git a/PkmnLibRSharpTests/PkmnLibRSharpTests.csproj b/PkmnLibRSharpTests/PkmnLibRSharpTests.csproj new file mode 100644 index 0000000..5f9dcb8 --- /dev/null +++ b/PkmnLibRSharpTests/PkmnLibRSharpTests.csproj @@ -0,0 +1,21 @@ + + + + net6.0 + enable + + false + + + + + + + + + + + + + + diff --git a/PkmnLibRSharpTests/StaticData/AbilityTests.cs b/PkmnLibRSharpTests/StaticData/AbilityTests.cs new file mode 100644 index 0000000..e30bae3 --- /dev/null +++ b/PkmnLibRSharpTests/StaticData/AbilityTests.cs @@ -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()); + Assert.AreEqual(name, ability.Name); + } + + [Test] + public void AbilityGetEffect([Values("foo", "bar", "", "zet", "xy")] string effect) + { + using var ability = new Ability("", effect, Array.Empty()); + 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); + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharpTests/StaticData/EffectParameterTests.cs b/PkmnLibRSharpTests/StaticData/EffectParameterTests.cs new file mode 100644 index 0000000..0a3a094 --- /dev/null +++ b/PkmnLibRSharpTests/StaticData/EffectParameterTests.cs @@ -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); + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharpTests/StaticData/MoveDataTests.cs b/PkmnLibRSharpTests/StaticData/MoveDataTests.cs new file mode 100644 index 0000000..4d4c63f --- /dev/null +++ b/PkmnLibRSharpTests/StaticData/MoveDataTests.cs @@ -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()); + 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); + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharpTests/StaticData/NatureTests.cs b/PkmnLibRSharpTests/StaticData/NatureTests.cs new file mode 100644 index 0000000..39e7ea8 --- /dev/null +++ b/PkmnLibRSharpTests/StaticData/NatureTests.cs @@ -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); + } + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharpTests/StaticData/SecondaryEffectTests.cs b/PkmnLibRSharpTests/StaticData/SecondaryEffectTests.cs new file mode 100644 index 0000000..3b60d70 --- /dev/null +++ b/PkmnLibRSharpTests/StaticData/SecondaryEffectTests.cs @@ -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()); + Assert.AreEqual(effectName, effect.Name); + Assert.AreEqual(chance, effect.Chance); + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharpTests/StaticData/StaticStatisticSetTests.cs b/PkmnLibRSharpTests/StaticData/StaticStatisticSetTests.cs new file mode 100644 index 0000000..f99db2d --- /dev/null +++ b/PkmnLibRSharpTests/StaticData/StaticStatisticSetTests.cs @@ -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(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(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(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(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(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(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); + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharpTests/StaticData/StatisticSetTests.cs b/PkmnLibRSharpTests/StaticData/StatisticSetTests.cs new file mode 100644 index 0000000..52d2050 --- /dev/null +++ b/PkmnLibRSharpTests/StaticData/StatisticSetTests.cs @@ -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(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(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(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(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(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(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(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); + } + } +} \ No newline at end of file