diff --git a/PkmnLibRSharp/FFI/StaticData/GrowthRate.cs b/PkmnLibRSharp/FFI/StaticData/GrowthRate.cs index d81bd4b..0ba6793 100644 --- a/PkmnLibRSharp/FFI/StaticData/GrowthRate.cs +++ b/PkmnLibRSharp/FFI/StaticData/GrowthRate.cs @@ -1,7 +1,6 @@ using System; using System.Runtime.InteropServices; - -using LevelInt = System.Byte; +using PkmnLibSharp.StaticData; namespace PkmnLibSharp.FFI.StaticData { diff --git a/PkmnLibRSharp/FFI/StaticData/LearnableMoves.cs b/PkmnLibRSharp/FFI/StaticData/LearnableMoves.cs index fbcd070..fcf11d2 100644 --- a/PkmnLibRSharp/FFI/StaticData/LearnableMoves.cs +++ b/PkmnLibRSharp/FFI/StaticData/LearnableMoves.cs @@ -2,8 +2,6 @@ using System; using System.Runtime.InteropServices; using PkmnLibSharp.StaticData; -using LevelInt = System.Byte; - namespace PkmnLibSharp.FFI.StaticData { internal static class LearnableMoves diff --git a/PkmnLibRSharp/FFI/StaticData/Libraries/AbilityLibrary.cs b/PkmnLibRSharp/FFI/StaticData/Libraries/AbilityLibrary.cs new file mode 100644 index 0000000..bf8a90d --- /dev/null +++ b/PkmnLibRSharp/FFI/StaticData/Libraries/AbilityLibrary.cs @@ -0,0 +1,26 @@ +using System; +using System.Runtime.InteropServices; + +namespace PkmnLibSharp.FFI.StaticData.Libraries +{ + internal static class AbilityLibrary + { + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr ability_library_new(ulong capacity); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern void ability_library_drop(IntPtr ptr); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr ability_library_get(IntPtr ptr, IntPtr key); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr ability_library_get_key_by_index(IntPtr ptr, ulong index); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern void ability_library_add(IntPtr ptr, IntPtr key, IntPtr value); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern ulong ability_library_len(IntPtr ptr); + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/FFI/StaticData/Libraries/GrowthRateLibrary.cs b/PkmnLibRSharp/FFI/StaticData/Libraries/GrowthRateLibrary.cs new file mode 100644 index 0000000..43732e6 --- /dev/null +++ b/PkmnLibRSharp/FFI/StaticData/Libraries/GrowthRateLibrary.cs @@ -0,0 +1,24 @@ +using System; +using System.Runtime.InteropServices; +using PkmnLibSharp.StaticData; + +namespace PkmnLibSharp.FFI.StaticData.Libraries +{ + internal static class GrowthRateLibrary + { + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr growth_rate_library_new(ulong capacity); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern void growth_rate_library_drop(IntPtr ptr); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern LevelInt growth_rate_library_calculate_level(IntPtr ptr, IntPtr growthRate, uint experience); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern uint growth_rate_library_calculate_experience(IntPtr ptr, IntPtr growthRate, LevelInt level); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern uint growth_rate_library_add_growth_rate(IntPtr ptr, IntPtr name, IntPtr growthRate); + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/FFI/StaticData/Libraries/ItemLibrary.cs b/PkmnLibRSharp/FFI/StaticData/Libraries/ItemLibrary.cs new file mode 100644 index 0000000..51b0dc4 --- /dev/null +++ b/PkmnLibRSharp/FFI/StaticData/Libraries/ItemLibrary.cs @@ -0,0 +1,26 @@ +using System; +using System.Runtime.InteropServices; + +namespace PkmnLibSharp.FFI.StaticData.Libraries +{ + internal static class ItemLibrary + { + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr item_library_new(ulong capacity); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern void item_library_drop(IntPtr ptr); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr item_library_get(IntPtr ptr, IntPtr key); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr item_library_get_key_by_index(IntPtr ptr, ulong index); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern void item_library_add(IntPtr ptr, IntPtr key, IntPtr value); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern ulong item_library_len(IntPtr ptr); + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/FFI/StaticData/Libraries/LibrarySettings.cs b/PkmnLibRSharp/FFI/StaticData/Libraries/LibrarySettings.cs new file mode 100644 index 0000000..e5259f2 --- /dev/null +++ b/PkmnLibRSharp/FFI/StaticData/Libraries/LibrarySettings.cs @@ -0,0 +1,18 @@ +using System; +using System.Runtime.InteropServices; +using PkmnLibSharp.StaticData; + +namespace PkmnLibSharp.FFI.StaticData.Libraries +{ + internal static class LibrarySettings + { + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr library_settings_new(LevelInt maxLevel); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern void library_settings_drop(IntPtr ptr); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern LevelInt library_settings_maximum_level(IntPtr ptr); + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/FFI/StaticData/Libraries/MoveLibrary.cs b/PkmnLibRSharp/FFI/StaticData/Libraries/MoveLibrary.cs new file mode 100644 index 0000000..68274f9 --- /dev/null +++ b/PkmnLibRSharp/FFI/StaticData/Libraries/MoveLibrary.cs @@ -0,0 +1,26 @@ +using System; +using System.Runtime.InteropServices; + +namespace PkmnLibSharp.FFI.StaticData.Libraries +{ + internal static class MoveLibrary + { + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr move_library_new(ulong capacity); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern void move_library_drop(IntPtr ptr); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr move_library_get(IntPtr ptr, IntPtr key); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr move_library_get_key_by_index(IntPtr ptr, ulong index); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern void move_library_add(IntPtr ptr, IntPtr key, IntPtr value); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern ulong move_library_len(IntPtr ptr); + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/FFI/StaticData/Libraries/NatureLibrary.cs b/PkmnLibRSharp/FFI/StaticData/Libraries/NatureLibrary.cs new file mode 100644 index 0000000..83eb31d --- /dev/null +++ b/PkmnLibRSharp/FFI/StaticData/Libraries/NatureLibrary.cs @@ -0,0 +1,23 @@ +using System; +using System.Runtime.InteropServices; + +namespace PkmnLibSharp.FFI.StaticData.Libraries +{ + internal static class NatureLibrary + { + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr nature_library_new(ulong capacity); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern void nature_library_drop(IntPtr ptr); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern void nature_library_load_nature(IntPtr ptr, IntPtr name, IntPtr nature); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr nature_library_get_nature(IntPtr ptr, IntPtr name); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr nature_library_get_nature_name(IntPtr ptr, IntPtr nature); + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/FFI/StaticData/Libraries/SpeciesLibrary.cs b/PkmnLibRSharp/FFI/StaticData/Libraries/SpeciesLibrary.cs index 1813ea8..5ac5844 100644 --- a/PkmnLibRSharp/FFI/StaticData/Libraries/SpeciesLibrary.cs +++ b/PkmnLibRSharp/FFI/StaticData/Libraries/SpeciesLibrary.cs @@ -14,6 +14,9 @@ namespace PkmnLibSharp.FFI.StaticData.Libraries [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] internal static extern IntPtr species_library_get(IntPtr ptr, IntPtr key); + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr species_library_get_key_by_index(IntPtr ptr, ulong index); + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] internal static extern void species_library_add(IntPtr ptr, IntPtr key, IntPtr value); diff --git a/PkmnLibRSharp/FFI/StaticData/Libraries/StaticData.cs b/PkmnLibRSharp/FFI/StaticData/Libraries/StaticData.cs new file mode 100644 index 0000000..2b5e955 --- /dev/null +++ b/PkmnLibRSharp/FFI/StaticData/Libraries/StaticData.cs @@ -0,0 +1,38 @@ +using System; +using System.Runtime.InteropServices; + +namespace PkmnLibSharp.FFI.StaticData.Libraries +{ + internal static class StaticData + { + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr static_data_new(IntPtr settings); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern void static_data_drop(IntPtr ptr); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr static_data_settings(IntPtr ptr); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr static_data_species(IntPtr ptr); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr static_data_moves(IntPtr ptr); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr static_data_items(IntPtr ptr); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr static_data_growth_rates(IntPtr ptr); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr static_data_types(IntPtr ptr); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr static_data_natures(IntPtr ptr); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr static_data_abilities(IntPtr ptr); + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/FFI/StaticData/Libraries/TypeLibrary.cs b/PkmnLibRSharp/FFI/StaticData/Libraries/TypeLibrary.cs new file mode 100644 index 0000000..be6a126 --- /dev/null +++ b/PkmnLibRSharp/FFI/StaticData/Libraries/TypeLibrary.cs @@ -0,0 +1,37 @@ +using System; +using System.Runtime.InteropServices; +using PkmnLibSharp.StaticData; + +namespace PkmnLibSharp.FFI.StaticData.Libraries +{ + internal static class TypeLibrary + { + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr type_library_new(ulong capacity); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern void type_library_drop(IntPtr ptr); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern TypeIdentifier type_library_get_type_id(IntPtr ptr, IntPtr name, IntPtr success); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr type_library_get_type_name(IntPtr ptr, TypeIdentifier typeIdentifier, + IntPtr success); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern float type_library_get_single_effectiveness(IntPtr ptr, TypeIdentifier attacking, + TypeIdentifier defending); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern float type_library_get_effectiveness(IntPtr ptr, TypeIdentifier attacking, + IntPtr defending, ulong defendingLength); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern TypeIdentifier type_library_register_type(IntPtr ptr, IntPtr name); + + [DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern void type_library_set_effectiveness(IntPtr ptr, TypeIdentifier attacking, + TypeIdentifier defending, float effectiveness); + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/PkmnLibRSharp.csproj b/PkmnLibRSharp/PkmnLibRSharp.csproj index 62138a8..31ec70f 100644 --- a/PkmnLibRSharp/PkmnLibRSharp.csproj +++ b/PkmnLibRSharp/PkmnLibRSharp.csproj @@ -11,6 +11,11 @@ 6 true ;NU1605;CA2000 + true + + + + true diff --git a/PkmnLibRSharp/StaticData/Ability.cs b/PkmnLibRSharp/StaticData/Ability.cs index d1ef3cb..a1ba946 100644 --- a/PkmnLibRSharp/StaticData/Ability.cs +++ b/PkmnLibRSharp/StaticData/Ability.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; @@ -27,6 +28,10 @@ namespace PkmnLibSharp.StaticData true); } + internal Ability(IntPtr ptr, bool isOwner) : base(ptr, isOwner) + { + } + public string Name => Cache.Name ?? (Cache.Name = Interface.ability_name(Ptr)); public string Effect => Cache.Effect ?? (Cache.Effect = Interface.ability_effect(Ptr)); @@ -55,5 +60,14 @@ namespace PkmnLibSharp.StaticData { Interface.ability_drop(Ptr); } + + public override void InvalidateChildren() + { + if (Cache.Parameters == null) return; + foreach (var cacheParameter in Cache.Parameters) + { + cacheParameter?.Invalidate(); + } + } } } \ No newline at end of file diff --git a/PkmnLibRSharp/StaticData/Form.cs b/PkmnLibRSharp/StaticData/Form.cs index 23bd549..0ab474e 100644 --- a/PkmnLibRSharp/StaticData/Form.cs +++ b/PkmnLibRSharp/StaticData/Form.cs @@ -72,5 +72,10 @@ namespace PkmnLibSharp.StaticData protected override CacheData CreateCache() => new CacheData(); protected override void Destructor() => Interface.form_drop(Ptr); + + public override void InvalidateChildren() + { + Cache.LearnableMoves?.Invalidate(); + } } } \ No newline at end of file diff --git a/PkmnLibRSharp/StaticData/GrowthRate.cs b/PkmnLibRSharp/StaticData/GrowthRate.cs index 9e23e84..93c6b02 100644 --- a/PkmnLibRSharp/StaticData/GrowthRate.cs +++ b/PkmnLibRSharp/StaticData/GrowthRate.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using PkmnLibSharp.Utils; using Interface = PkmnLibSharp.FFI.StaticData.GrowthRate; -using LevelInt = System.Byte; namespace PkmnLibSharp.StaticData { diff --git a/PkmnLibRSharp/StaticData/Item.cs b/PkmnLibRSharp/StaticData/Item.cs index 42d8e8a..c328e0a 100644 --- a/PkmnLibRSharp/StaticData/Item.cs +++ b/PkmnLibRSharp/StaticData/Item.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; using PkmnLibSharp.Utils; @@ -102,6 +103,10 @@ namespace PkmnLibSharp.StaticData InitializePointer(ptr, true); } + internal Item(IntPtr ptr, bool isOwner) : base(ptr, isOwner) + { + } + public string Name => Cache.Name ??= Interface.item_name(Ptr).PtrString()!; public ItemCategory Category => Cache.Category ??= Interface.item_category(Ptr); public BattleItemCategory BattleCategory => Cache.BattleCategory ??= Interface.item_battle_category(Ptr); diff --git a/PkmnLibRSharp/StaticData/LearnableMoves.cs b/PkmnLibRSharp/StaticData/LearnableMoves.cs index 954d0b6..9baed7f 100644 --- a/PkmnLibRSharp/StaticData/LearnableMoves.cs +++ b/PkmnLibRSharp/StaticData/LearnableMoves.cs @@ -1,7 +1,6 @@ using System; using PkmnLibSharp.Utils; using Interface = PkmnLibSharp.FFI.StaticData.LearnableMoves; -using LevelInt = System.Byte; namespace PkmnLibSharp.StaticData { diff --git a/PkmnLibRSharp/StaticData/LevelInt.cs b/PkmnLibRSharp/StaticData/LevelInt.cs new file mode 100644 index 0000000..ff239ef --- /dev/null +++ b/PkmnLibRSharp/StaticData/LevelInt.cs @@ -0,0 +1,119 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using BackingLevelInt = System.Byte; + +namespace PkmnLibSharp.StaticData +{ + [StructLayout(LayoutKind.Explicit)] + public struct LevelInt : IComparable, IComparable, IComparable, IConvertible, + IEquatable, IEquatable, IEquatable, IFormattable + { + [FieldOffset(0)] private BackingLevelInt _value; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator BackingLevelInt(LevelInt l) + { + return l._value; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator LevelInt(BackingLevelInt b) + { + return new LevelInt { _value = b }; + } + + public int CompareTo(object obj) + { + if (obj is LevelInt l) + return _value.CompareTo(l._value); + return _value.CompareTo(obj); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int CompareTo(BackingLevelInt other) => _value.CompareTo(other); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int CompareTo(LevelInt other) => _value.CompareTo(other._value); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TypeCode GetTypeCode() => Type.GetTypeCode(typeof(BackingLevelInt)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool ToBoolean(IFormatProvider provider) => ((IConvertible)_value).ToBoolean(provider); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public byte ToByte(IFormatProvider provider) => ((IConvertible)_value).ToByte(provider); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public char ToChar(IFormatProvider provider) => ((IConvertible)_value).ToChar(provider); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public DateTime ToDateTime(IFormatProvider provider) => ((IConvertible)_value).ToDateTime(provider); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public decimal ToDecimal(IFormatProvider provider) => ((IConvertible)_value).ToDecimal(provider); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public double ToDouble(IFormatProvider provider) => ((IConvertible)_value).ToDouble(provider); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public short ToInt16(IFormatProvider provider) => ((IConvertible)_value).ToInt16(provider); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int ToInt32(IFormatProvider provider) => ((IConvertible)_value).ToInt32(provider); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public long ToInt64(IFormatProvider provider) => ((IConvertible)_value).ToInt64(provider); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public sbyte ToSByte(IFormatProvider provider) => ((IConvertible)_value).ToSByte(provider); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float ToSingle(IFormatProvider provider) => ((IConvertible)_value).ToSingle(provider); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public string ToString(IFormatProvider provider) => _value.ToString(provider); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public object ToType(Type conversionType, IFormatProvider provider) => + ((IConvertible)_value).ToType(conversionType, provider); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ushort ToUInt16(IFormatProvider provider) => ((IConvertible)_value).ToUInt16(provider); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public uint ToUInt32(IFormatProvider provider) => ((IConvertible)_value).ToUInt32(provider); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ulong ToUInt64(IFormatProvider provider) => ((IConvertible)_value).ToUInt64(provider); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(BackingLevelInt other) => _value == other; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public string ToString(string format, IFormatProvider formatProvider) => + _value.ToString(format, formatProvider); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(LevelInt other) => _value == other._value; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(int other) => _value == other; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override bool Equals(object? obj) => obj is LevelInt other && Equals(other); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override int GetHashCode() + { + return _value.GetHashCode(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator ==(LevelInt left, LevelInt right) => left.Equals(right); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator !=(LevelInt left, LevelInt right) => !left.Equals(right); + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/StaticData/Libraries/AbilityLibrary.cs b/PkmnLibRSharp/StaticData/Libraries/AbilityLibrary.cs new file mode 100644 index 0000000..535ad8c --- /dev/null +++ b/PkmnLibRSharp/StaticData/Libraries/AbilityLibrary.cs @@ -0,0 +1,41 @@ +using System; +using PkmnLibSharp.Utils; +using Interface = PkmnLibSharp.FFI.StaticData.Libraries.ItemLibrary; + +namespace PkmnLibSharp.StaticData.Libraries +{ + public class AbilityLibrary : DataLibrary + { + public AbilityLibrary(ulong capacity) : base(Interface.item_library_new(capacity), true) + { + } + + internal AbilityLibrary(IntPtr ptr, bool isOwner) : base(ptr, isOwner) + { + } + + protected override void Destructor() => Interface.item_library_drop(Ptr); + + public override void Add(string key, Ability value) => + Interface.item_library_add(Ptr, key.ToPtr(), value.TakeOwnershipAndInvalidate()); + + public override int Count => (int)Interface.item_library_len(Ptr); + + protected override Ability? GetValueByKey(string key) + { + var ptr = Interface.item_library_get(Ptr, key.ToPtr()); + return ptr == IntPtr.Zero ? null : new Ability(ptr, false); + } + + public override string? GetKeyByIndex(ulong index) => + Interface.item_library_get_key_by_index(Ptr, index).PtrString(); + + public override void InvalidateChildren() + { + foreach (var value in Cache.ValueCache.Values) + { + value.Invalidate(); + } + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/StaticData/Libraries/DataLibrary.cs b/PkmnLibRSharp/StaticData/Libraries/DataLibrary.cs index 22fe855..9447300 100644 --- a/PkmnLibRSharp/StaticData/Libraries/DataLibrary.cs +++ b/PkmnLibRSharp/StaticData/Libraries/DataLibrary.cs @@ -1,10 +1,12 @@ using System; +using System.Collections; using System.Collections.Generic; +using System.Linq; using PkmnLibSharp.Utils; namespace PkmnLibSharp.StaticData.Libraries { - public abstract class DataLibrary : ExternPointer.CacheData> + public abstract class DataLibrary : ExternPointer.CacheData>, IReadOnlyDictionary { protected DataLibrary(IntPtr ptr, bool isOwner) : base(ptr, isOwner) { @@ -12,25 +14,32 @@ namespace PkmnLibSharp.StaticData.Libraries public class CacheData { + public List? KeyCache { get; internal set; } public Dictionary ValueCache { get; } = new(); } public abstract void Add(string key, T value); - public abstract ulong Length { get; } + public abstract int Count { get; } protected abstract T? GetValueByKey(string key); - public bool TryGetValue(string key, out T? value) + public bool ContainsKey(string key) + { + return GetValueByKey(key) != null; + } + + public bool TryGetValue(string key, out T value) { if (Cache.ValueCache.TryGetValue(key, out value) && value != null) return true; - value = GetValueByKey(key); - if (value != null) + var v = GetValueByKey(key); + if (v != null) { - Cache.ValueCache.Add(key, value); + Cache.ValueCache.Add(key, v); + value = v; } - return value != null; + return v != null; } public T this[string key] @@ -43,6 +52,43 @@ namespace PkmnLibSharp.StaticData.Libraries } } + public abstract string? GetKeyByIndex(ulong index); + + public IEnumerable Keys + { + get + { + if (Cache.KeyCache == null) + { + Cache.KeyCache = new List(Count); + for (ulong i = 0; i < (ulong)Count; i++) + { + var key = GetKeyByIndex(i); + if (key == null) + break; + Cache.KeyCache.Add(key); + } + } + + return Cache.KeyCache; + } + } + + public IEnumerable Values + { + get { return Keys.Select(key => this[key]); } + } + protected override CacheData CreateCache() => new(); + + public IEnumerator> GetEnumerator() + { + return Keys.Select(key => new KeyValuePair(key, this[key])).GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } } } \ No newline at end of file diff --git a/PkmnLibRSharp/StaticData/Libraries/GrowthRateLibrary.cs b/PkmnLibRSharp/StaticData/Libraries/GrowthRateLibrary.cs new file mode 100644 index 0000000..238e13f --- /dev/null +++ b/PkmnLibRSharp/StaticData/Libraries/GrowthRateLibrary.cs @@ -0,0 +1,33 @@ +using System; +using JetBrains.Annotations; +using PkmnLibSharp.Utils; +using Interface = PkmnLibSharp.FFI.StaticData.Libraries.GrowthRateLibrary; + +namespace PkmnLibSharp.StaticData.Libraries +{ + public class GrowthRateLibrary : ExternPointer + { + public GrowthRateLibrary(ulong capacity) : base(Interface.growth_rate_library_new(capacity), true) + { + } + + internal GrowthRateLibrary(IntPtr ptr, bool isOwner) : base(ptr, isOwner) + { + } + + [MustUseReturnValue] + public LevelInt CalculateLevel(string growthRate, uint experience) => + Interface.growth_rate_library_calculate_level(Ptr, growthRate.ToPtr(), experience); + + [MustUseReturnValue] + public uint CalculateExperience(string growthRate, LevelInt level) => + Interface.growth_rate_library_calculate_experience(Ptr, growthRate.ToPtr(), level); + + public void AddGrowthRate(string name, GrowthRate growthRate) => + Interface.growth_rate_library_add_growth_rate(Ptr, name.ToPtr(), growthRate.TakeOwnershipAndInvalidate()); + + protected override object CreateCache() => new(); + + protected override void Destructor() => Interface.growth_rate_library_drop(Ptr); + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/StaticData/Libraries/ItemLibrary.cs b/PkmnLibRSharp/StaticData/Libraries/ItemLibrary.cs new file mode 100644 index 0000000..b4549e1 --- /dev/null +++ b/PkmnLibRSharp/StaticData/Libraries/ItemLibrary.cs @@ -0,0 +1,41 @@ +using System; +using PkmnLibSharp.Utils; +using Interface = PkmnLibSharp.FFI.StaticData.Libraries.ItemLibrary; + +namespace PkmnLibSharp.StaticData.Libraries +{ + public class ItemLibrary : DataLibrary + { + public ItemLibrary(ulong capacity) : base(Interface.item_library_new(capacity), true) + { + } + + internal ItemLibrary(IntPtr ptr, bool isOwner) : base(ptr, isOwner) + { + } + + protected override void Destructor() => Interface.item_library_drop(Ptr); + + public override void Add(string key, Item value) => + Interface.item_library_add(Ptr, key.ToPtr(), value.TakeOwnershipAndInvalidate()); + + public override int Count => (int)Interface.item_library_len(Ptr); + + protected override Item? GetValueByKey(string key) + { + var ptr = Interface.item_library_get(Ptr, key.ToPtr()); + return ptr == IntPtr.Zero ? null : new Item(ptr, false); + } + + public override string? GetKeyByIndex(ulong index) => + Interface.item_library_get_key_by_index(Ptr, index).PtrString(); + + public override void InvalidateChildren() + { + foreach (var value in Cache.ValueCache.Values) + { + value.Invalidate(); + } + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/StaticData/Libraries/LibrarySettings.cs b/PkmnLibRSharp/StaticData/Libraries/LibrarySettings.cs new file mode 100644 index 0000000..9834600 --- /dev/null +++ b/PkmnLibRSharp/StaticData/Libraries/LibrarySettings.cs @@ -0,0 +1,28 @@ +using System; +using PkmnLibSharp.Utils; +using Interface = PkmnLibSharp.FFI.StaticData.Libraries.LibrarySettings; + +namespace PkmnLibSharp.StaticData.Libraries +{ + public class LibrarySettings : ExternPointer + { + public class CacheData + { + public LevelInt? MaxLevel { get; internal set; } + } + + public LibrarySettings(LevelInt maxLevel) : base(Interface.library_settings_new(maxLevel), true) + { + } + + internal LibrarySettings(IntPtr ptr, bool isOwner) : base(ptr, isOwner) + { + } + + public LevelInt MaxLevel => Cache.MaxLevel ??= Interface.library_settings_maximum_level(Ptr); + + protected override CacheData CreateCache() => new(); + + protected override void Destructor() => Interface.library_settings_drop(Ptr); + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/StaticData/Libraries/MoveLibrary.cs b/PkmnLibRSharp/StaticData/Libraries/MoveLibrary.cs new file mode 100644 index 0000000..e0a623a --- /dev/null +++ b/PkmnLibRSharp/StaticData/Libraries/MoveLibrary.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using PkmnLibSharp.Utils; +using Interface = PkmnLibSharp.FFI.StaticData.Libraries.MoveLibrary; + +namespace PkmnLibSharp.StaticData.Libraries +{ + public class MoveLibrary : DataLibrary + { + public MoveLibrary(ulong capacity) : base(Interface.move_library_new(capacity), true) + { + } + + internal MoveLibrary(IntPtr ptr, bool isOwner) : base(ptr, isOwner) + { + } + + protected override void Destructor() + { + Interface.move_library_drop(Ptr); + } + + public override void Add(string key, MoveData value) => + Interface.move_library_add(Ptr, key.ToPtr(), value.TakeOwnershipAndInvalidate()); + + public override int Count => (int)Interface.move_library_len(Ptr); + + protected override MoveData? GetValueByKey(string key) + { + var ptr = Interface.move_library_get(Ptr, key.ToPtr()); + return ptr == IntPtr.Zero ? null : new MoveData(ptr, false); + } + + public override string? GetKeyByIndex(ulong index) => + Interface.move_library_get_key_by_index(Ptr, index).PtrString(); + + public override void InvalidateChildren() + { + foreach (var value in Cache.ValueCache.Values) + { + value.Invalidate(); + } + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/StaticData/Libraries/NatureLibrary.cs b/PkmnLibRSharp/StaticData/Libraries/NatureLibrary.cs new file mode 100644 index 0000000..8728a50 --- /dev/null +++ b/PkmnLibRSharp/StaticData/Libraries/NatureLibrary.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using PkmnLibSharp.Utils; +using Interface = PkmnLibSharp.FFI.StaticData.Libraries.NatureLibrary; + +namespace PkmnLibSharp.StaticData.Libraries +{ + public class NatureLibrary : ExternPointer + { + public class CacheData + { + public Dictionary Natures { get; } = new(StringComparer.InvariantCultureIgnoreCase); + } + + public NatureLibrary(ulong capacity) : base(Interface.nature_library_new(capacity), true) + { + } + + internal NatureLibrary(IntPtr ptr, bool isOwner) : base(ptr, isOwner) + { + } + + public bool TryGetNature(string name, out Nature nature) + { + if (Cache.Natures.TryGetValue(name, out nature)) + return true; + var naturePtr = Interface.nature_library_get_nature(Ptr, name.ToPtr()); + if (naturePtr == IntPtr.Zero) + return false; + nature = new Nature(naturePtr, false); + Cache.Natures.Add(name, nature); + return true; + } + + public string GetNatureName(Nature nature) + { + var fd = Cache.Natures.FirstOrDefault(x => x.Value == nature); + return fd.Key ?? Interface.nature_library_get_nature_name(Ptr, nature.Ptr).PtrString()!; + } + + public void LoadNature(string name, Nature nature) => + Interface.nature_library_load_nature(Ptr, name.ToPtr(), nature.TakeOwnershipAndInvalidate()); + + + protected override CacheData CreateCache() => new(); + + protected override void Destructor() => Interface.nature_library_drop(Ptr); + + public override void InvalidateChildren() + { + base.InvalidateChildren(); + foreach (var nature in Cache.Natures.Values) + { + nature.Invalidate(); + } + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/StaticData/Libraries/SpeciesLibrary.cs b/PkmnLibRSharp/StaticData/Libraries/SpeciesLibrary.cs index b02b328..5222b69 100644 --- a/PkmnLibRSharp/StaticData/Libraries/SpeciesLibrary.cs +++ b/PkmnLibRSharp/StaticData/Libraries/SpeciesLibrary.cs @@ -10,17 +10,32 @@ namespace PkmnLibSharp.StaticData.Libraries { } + internal SpeciesLibrary(IntPtr ptr, bool isOwner) : base(ptr, isOwner) + { + } + protected override void Destructor() => Interface.species_library_drop(Ptr); public override void Add(string key, Species value) => Interface.species_library_add(Ptr, key.ToPtr(), value.TakeOwnershipAndInvalidate()); - public override ulong Length => Interface.species_library_len(Ptr); + public override int Count => (int)Interface.species_library_len(Ptr); protected override Species? GetValueByKey(string key) { var ptr = Interface.species_library_get(Ptr, key.ToPtr()); return ptr == IntPtr.Zero ? null : new Species(ptr, false); } + + public override string? GetKeyByIndex(ulong index) => + Interface.species_library_get_key_by_index(Ptr, index).PtrString(); + + public override void InvalidateChildren() + { + foreach (var value in Cache.ValueCache.Values) + { + value.Invalidate(); + } + } } } \ No newline at end of file diff --git a/PkmnLibRSharp/StaticData/Libraries/StaticData.cs b/PkmnLibRSharp/StaticData/Libraries/StaticData.cs new file mode 100644 index 0000000..ce1cd86 --- /dev/null +++ b/PkmnLibRSharp/StaticData/Libraries/StaticData.cs @@ -0,0 +1,68 @@ +using JetBrains.Annotations; +using PkmnLibSharp.Utils; +using Interface = PkmnLibSharp.FFI.StaticData.Libraries.StaticData; + +namespace PkmnLibSharp.StaticData.Libraries +{ + public class StaticData : ExternPointer + { + public class CacheData + { + public LibrarySettings? Settings { get; internal set; } + public SpeciesLibrary? SpeciesLibrary { get; internal set; } + public MoveLibrary? MoveLibrary { get; internal set; } + public ItemLibrary? ItemLibrary { get; internal set; } + public GrowthRateLibrary? GrowthRateLibrary { get; internal set; } + public TypeLibrary? TypeLibrary { get; internal set; } + public NatureLibrary? NatureLibrary { get; internal set; } + public AbilityLibrary? AbilityLibrary { get; internal set; } + } + + public StaticData(LibrarySettings settings) : base( + Interface.static_data_new(settings.TakeOwnershipAndInvalidate()), true) + { + } + + public LibrarySettings LibrarySettings => + Cache.Settings ??= new LibrarySettings(Interface.static_data_settings(Ptr), false); + + public SpeciesLibrary SpeciesLibrary => + Cache.SpeciesLibrary ??= new SpeciesLibrary(Interface.static_data_species(Ptr), false); + + public MoveLibrary MoveLibrary => + Cache.MoveLibrary ??= new MoveLibrary(Interface.static_data_moves(Ptr), false); + + public ItemLibrary ItemLibrary => + Cache.ItemLibrary ??= new ItemLibrary(Interface.static_data_items(Ptr), false); + + public GrowthRateLibrary GrowthRateLibrary => + Cache.GrowthRateLibrary ??= new GrowthRateLibrary(Interface.static_data_items(Ptr), false); + + public TypeLibrary TypeLibrary => + Cache.TypeLibrary ??= new TypeLibrary(Interface.static_data_items(Ptr), false); + + public NatureLibrary NatureLibrary => + Cache.NatureLibrary ??= new NatureLibrary(Interface.static_data_items(Ptr), false); + + public AbilityLibrary AbilityLibrary => + Cache.AbilityLibrary ??= new AbilityLibrary(Interface.static_data_items(Ptr), false); + + protected override CacheData CreateCache() => new(); + + protected override void Destructor() => Interface.static_data_drop(Ptr); + + public override void InvalidateChildren() + { + if (!HasCache) + return; + Cache.Settings?.Invalidate(); + Cache.SpeciesLibrary?.Invalidate(); + Cache.MoveLibrary?.Invalidate(); + Cache.ItemLibrary?.Invalidate(); + Cache.GrowthRateLibrary?.Invalidate(); + Cache.TypeLibrary?.Invalidate(); + Cache.NatureLibrary?.Invalidate(); + Cache.AbilityLibrary?.Invalidate(); + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/StaticData/Libraries/TypeLibrary.cs b/PkmnLibRSharp/StaticData/Libraries/TypeLibrary.cs new file mode 100644 index 0000000..4859289 --- /dev/null +++ b/PkmnLibRSharp/StaticData/Libraries/TypeLibrary.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using PkmnLibSharp.Utils; +using Interface = PkmnLibSharp.FFI.StaticData.Libraries.TypeLibrary; + +namespace PkmnLibSharp.StaticData.Libraries +{ + public class TypeLibrary : ExternPointer + { + public class CacheData + { + public Dictionary TypeCache { get; } = + new(StringComparer.InvariantCultureIgnoreCase); + } + + public TypeLibrary(ulong capacity) : base(Interface.type_library_new(capacity), true) + { + } + + internal TypeLibrary(IntPtr ptr, bool isOwner) : base(ptr, isOwner) + { + } + + public TypeIdentifier GetTypeId(string name) + { + if (Cache.TypeCache.TryGetValue(name, out var typeIdentifier)) + return typeIdentifier; + throw new KeyNotFoundException($"No type found with name `{name}`"); + } + + public string GetTypeName(TypeIdentifier typeIdentifier) + { + var fd = Cache.TypeCache.FirstOrDefault(x => x.Value == typeIdentifier); + if (fd.Key != null) + return fd.Key; + throw new KeyNotFoundException($"No type found for given identifier"); + } + + + public float GetSingleEffectiveness(TypeIdentifier attacking, TypeIdentifier defending) => + Interface.type_library_get_single_effectiveness(Ptr, attacking, defending); + + public float GetEffectiveness(TypeIdentifier attacking, TypeIdentifier[] defending) + { + var arrayPtr = defending.ArrayPtr(); + return Interface.type_library_get_effectiveness(Ptr, attacking, arrayPtr, (ulong)defending.Length); + } + + public TypeIdentifier RegisterType(string name) + { + var typeId = Interface.type_library_register_type(Ptr, name.ToPtr()); + Cache.TypeCache.Add(name, typeId); + return typeId; + } + + public void SetEffectiveness(TypeIdentifier attacking, TypeIdentifier defending, float effectiveness) => + Interface.type_library_set_effectiveness(Ptr, attacking, defending, effectiveness); + + + protected override CacheData CreateCache() => new(); + + protected override void Destructor() => Interface.type_library_drop(Ptr); + } +} \ No newline at end of file diff --git a/PkmnLibRSharp/StaticData/MoveData.cs b/PkmnLibRSharp/StaticData/MoveData.cs index bd117a7..b42767a 100644 --- a/PkmnLibRSharp/StaticData/MoveData.cs +++ b/PkmnLibRSharp/StaticData/MoveData.cs @@ -76,6 +76,10 @@ namespace PkmnLibSharp.StaticData public SecondaryEffect? SecondaryEffect { get; internal set; } } + internal MoveData(IntPtr ptr, bool isOwner) : base(ptr, isOwner) + { + } + public MoveData(string name, TypeIdentifier moveType, MoveCategory category, byte basePower, byte accuracy, byte baseUsages, MoveTarget target, sbyte priority, SecondaryEffect? secondaryEffect, IEnumerable flags) @@ -125,5 +129,11 @@ namespace PkmnLibSharp.StaticData { Interface.move_data_drop(Ptr); } + + public override void InvalidateChildren() + { + base.InvalidateChildren(); + Cache.SecondaryEffect?.Invalidate(); + } } } \ No newline at end of file diff --git a/PkmnLibRSharp/StaticData/Nature.cs b/PkmnLibRSharp/StaticData/Nature.cs index e477e57..d8effe3 100644 --- a/PkmnLibRSharp/StaticData/Nature.cs +++ b/PkmnLibRSharp/StaticData/Nature.cs @@ -1,3 +1,4 @@ +using System; using PkmnLibSharp.Utils; using Interface = PkmnLibSharp.FFI.StaticData.Nature; @@ -17,6 +18,10 @@ namespace PkmnLibSharp.StaticData { } + internal Nature(IntPtr ptr, bool isOwner) : base(ptr, isOwner) + { + } + public static Nature NeutralNature() { return new Nature(Statistic.HP, Statistic.HP, 1f, 1f); diff --git a/PkmnLibRSharp/StaticData/SecondaryEffect.cs b/PkmnLibRSharp/StaticData/SecondaryEffect.cs index baf6d3c..d651f96 100644 --- a/PkmnLibRSharp/StaticData/SecondaryEffect.cs +++ b/PkmnLibRSharp/StaticData/SecondaryEffect.cs @@ -45,5 +45,17 @@ namespace PkmnLibSharp.StaticData { Interface.secondary_effect_drop(Ptr); } + + public override void InvalidateChildren() + { + base.InvalidateChildren(); + if (Cache.Parameters != null) + { + for (var index = 0; index < Cache.Parameters.Count; index++) + { + Cache.Parameters.GetCachedValue(index)?.Invalidate(); + } + } + } } } \ No newline at end of file diff --git a/PkmnLibRSharp/StaticData/Species.cs b/PkmnLibRSharp/StaticData/Species.cs index 05b1552..72cc9d4 100644 --- a/PkmnLibRSharp/StaticData/Species.cs +++ b/PkmnLibRSharp/StaticData/Species.cs @@ -57,5 +57,14 @@ namespace PkmnLibSharp.StaticData protected override CacheData CreateCache() => new CacheData(); protected override void Destructor() => Interface.species_drop(Ptr); + + public override void InvalidateChildren() + { + base.InvalidateChildren(); + foreach (var form in Cache.Forms) + { + form.Value.Invalidate(); + } + } } } \ No newline at end of file diff --git a/PkmnLibRSharp/Utils/CacheHandler.cs b/PkmnLibRSharp/Utils/CacheHandler.cs index b0d4941..59b1984 100644 --- a/PkmnLibRSharp/Utils/CacheHandler.cs +++ b/PkmnLibRSharp/Utils/CacheHandler.cs @@ -5,7 +5,7 @@ namespace PkmnLibSharp.Utils { internal static class CacheHandler { - private static readonly ConcurrentDictionary Caches = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary Caches = new(); internal static T GetCache(IntPtr ptr, Func ctor) { @@ -14,6 +14,12 @@ namespace PkmnLibSharp.Utils cache = ctor(); Caches.TryAdd(ptr, cache); } + + if (cache.GetType() != typeof(T)) + { + throw new InvalidCastException( + $"Can't cast from cache data `{cache.GetType().FullName}` to cache data `{typeof(T).FullName}`"); + } return (T)cache; } diff --git a/PkmnLibRSharp/Utils/CachedExternArray.cs b/PkmnLibRSharp/Utils/CachedExternArray.cs index 9476abc..fa7fba0 100644 --- a/PkmnLibRSharp/Utils/CachedExternArray.cs +++ b/PkmnLibRSharp/Utils/CachedExternArray.cs @@ -42,6 +42,11 @@ namespace PkmnLibSharp.Utils return _array[index] ??= _getItem((ulong)index); } } + + internal T? GetCachedValue(int i) + { + return _array[i]; + } } public class CachedExternValueArray : IReadOnlyList diff --git a/PkmnLibRSharp/Utils/ExternPointer.cs b/PkmnLibRSharp/Utils/ExternPointer.cs index 7986086..dc607fc 100644 --- a/PkmnLibRSharp/Utils/ExternPointer.cs +++ b/PkmnLibRSharp/Utils/ExternPointer.cs @@ -20,6 +20,8 @@ namespace PkmnLibSharp.Utils get { return _cache ??= CacheHandler.GetCache(_ptr, CreateCache); } } + protected bool HasCache => _cache != null; + protected ExternPointer() { @@ -67,11 +69,14 @@ namespace PkmnLibSharp.Utils return ptr; } - private void Invalidate() + internal void Invalidate() { _isInvalidated = true; CacheHandler.RemoveCache(_ptr); + InvalidateChildren(); } + + public virtual void InvalidateChildren(){} public void Dispose() { @@ -79,6 +84,7 @@ namespace PkmnLibSharp.Utils return; if (_isOwner) { + InvalidateChildren(); if (!_isInvalidated) Destructor(); _isOwner = false; diff --git a/PkmnLibRSharp/libpkmn_lib.so b/PkmnLibRSharp/libpkmn_lib.so index 5909c29..7895da4 100755 --- a/PkmnLibRSharp/libpkmn_lib.so +++ b/PkmnLibRSharp/libpkmn_lib.so @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2c4b99a230268b91e0384e18367eaba6720d0c708aa4fbbac195115ab0e34e39 -size 156040640 +oid sha256:6d0a4633592e95f36dcfb44a74f2dac1fcf2a422ce7bd104940b084bc6e31bf6 +size 167803104 diff --git a/PkmnLibRSharpTests/StaticData/Libraries/AbilityLibraryTests.cs b/PkmnLibRSharpTests/StaticData/Libraries/AbilityLibraryTests.cs new file mode 100644 index 0000000..0940782 --- /dev/null +++ b/PkmnLibRSharpTests/StaticData/Libraries/AbilityLibraryTests.cs @@ -0,0 +1,51 @@ +using System; +using NUnit.Framework; +using PkmnLibSharp.StaticData; +using PkmnLibSharp.StaticData.Libraries; + +namespace PkmnLibRSharpTests.StaticData.Libraries +{ + public class AbilityLibraryTests + { + [Test] + public void Create() + { + using var lib = new AbilityLibrary(0); + Assert.AreEqual(0, lib.Count); + } + + [Test] + public void CreateAndAdd() + { + using var lib = new AbilityLibrary(1); + Assert.AreEqual(0, lib.Count); + using var ability = new Ability("testAbility", "effect", Array.Empty()); + lib.Add("foobar", ability); + Assert.AreEqual(1, lib.Count); + Assert.AreEqual("testAbility", lib["foobar"].Name); + } + + [Test] + public void CreateAddIterate() + { + using var lib = new AbilityLibrary(10); + Assert.AreEqual(0, lib.Count); + for (ushort i = 0; i < 10; i++) + { + using var item = new Ability(i.ToString(), "effect", Array.Empty()); + lib.Add(i + "_key", item); + } + + Assert.AreEqual(10, lib.Count); + var index = 0; + foreach (var kv in lib) + { + Assert.AreEqual(kv.Key, index + "_key"); + Assert.AreEqual(kv.Value.Name, index.ToString()); + index++; + } + + Assert.AreEqual(10, index); + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharpTests/StaticData/Libraries/GrowthRateLibraryTests.cs b/PkmnLibRSharpTests/StaticData/Libraries/GrowthRateLibraryTests.cs new file mode 100644 index 0000000..8d891f7 --- /dev/null +++ b/PkmnLibRSharpTests/StaticData/Libraries/GrowthRateLibraryTests.cs @@ -0,0 +1,43 @@ +using NUnit.Framework; +using PkmnLibSharp.StaticData; +using PkmnLibSharp.StaticData.Libraries; + +namespace PkmnLibRSharpTests.StaticData.Libraries +{ + public class GrowthRateLibraryTests + { + [Test] + public void CreateGrowthRateLibrary() + { + using var library = new GrowthRateLibrary(0); + } + + [Test] + public void AddGrowthRateToLibrary() + { + using var library = new GrowthRateLibrary(0); + using var growthRate = new LookupGrowthRate(new uint[] { 0, 1, 5, 10, 20, 100, 200, 500 }); + library.AddGrowthRate("foobar", growthRate); + } + + [Test] + public void CalculateLevel() + { + using var library = new GrowthRateLibrary(0); + using var growthRate = new LookupGrowthRate(new uint[] { 0, 1, 5, 10, 20, 100, 200, 500 }); + library.AddGrowthRate("foobar", growthRate); + var level = library.CalculateLevel("foobar", 20); + Assert.AreEqual(5, level); + } + + [Test] + public void CalculateExperience() + { + using var library = new GrowthRateLibrary(0); + using var growthRate = new LookupGrowthRate(new uint[] { 0, 1, 5, 10, 20, 100, 200, 500 }); + library.AddGrowthRate("foobar", growthRate); + var experience = library.CalculateExperience("foobar", 5); + Assert.AreEqual(20, experience); + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharpTests/StaticData/Libraries/ItemLibraryTests.cs b/PkmnLibRSharpTests/StaticData/Libraries/ItemLibraryTests.cs new file mode 100644 index 0000000..cffdf5f --- /dev/null +++ b/PkmnLibRSharpTests/StaticData/Libraries/ItemLibraryTests.cs @@ -0,0 +1,52 @@ +using System; +using NUnit.Framework; +using PkmnLibSharp.StaticData; +using PkmnLibSharp.StaticData.Libraries; + +namespace PkmnLibRSharpTests.StaticData.Libraries +{ + public class ItemLibraryTests + { + [Test] + public void Create() + { + using var lib = new ItemLibrary(0); + Assert.AreEqual(0, lib.Count); + } + + [Test] + public void CreateAndAdd() + { + using var lib = new ItemLibrary(1); + Assert.AreEqual(0, lib.Count); + using var item = new Item("testItem", ItemCategory.Mail, BattleItemCategory.None, 100, Array.Empty()); + lib.Add("foobar", item); + Assert.AreEqual(1, lib.Count); + Assert.AreEqual("testItem", lib["foobar"].Name); + } + + [Test] + public void CreateAddIterate() + { + using var lib = new ItemLibrary(10); + Assert.AreEqual(0, lib.Count); + for (ushort i = 0; i < 10; i++) + { + using var item = new Item(i.ToString(), ItemCategory.Mail, BattleItemCategory.None, 100, + Array.Empty()); + lib.Add(i + "_key", item); + } + + Assert.AreEqual(10, lib.Count); + var index = 0; + foreach (var kv in lib) + { + Assert.AreEqual(kv.Key, index + "_key"); + Assert.AreEqual(kv.Value.Name, index.ToString()); + index++; + } + + Assert.AreEqual(10, index); + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharpTests/StaticData/Libraries/LibrarySettingsTests.cs b/PkmnLibRSharpTests/StaticData/Libraries/LibrarySettingsTests.cs new file mode 100644 index 0000000..e6c0e06 --- /dev/null +++ b/PkmnLibRSharpTests/StaticData/Libraries/LibrarySettingsTests.cs @@ -0,0 +1,21 @@ +using NUnit.Framework; +using PkmnLibSharp.StaticData.Libraries; + +namespace PkmnLibRSharpTests.StaticData.Libraries +{ + public class LibrarySettingsTests + { + [Test] + public void CreateLibrarySettings() + { + using var settings = new LibrarySettings(100); + } + + [Test] + public void GetMaxLevel() + { + using var settings = new LibrarySettings(100); + Assert.AreEqual(100, settings.MaxLevel); + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharpTests/StaticData/Libraries/MoveLibraryTests.cs b/PkmnLibRSharpTests/StaticData/Libraries/MoveLibraryTests.cs new file mode 100644 index 0000000..2a1934b --- /dev/null +++ b/PkmnLibRSharpTests/StaticData/Libraries/MoveLibraryTests.cs @@ -0,0 +1,53 @@ +using System; +using NUnit.Framework; +using PkmnLibSharp.StaticData; +using PkmnLibSharp.StaticData.Libraries; + +namespace PkmnLibRSharpTests.StaticData.Libraries +{ + public class MoveLibraryTests + { + [Test] + public void Create() + { + using var lib = new MoveLibrary(0); + Assert.AreEqual(0, lib.Count); + } + + [Test] + public void CreateAndAdd() + { + using var lib = new MoveLibrary(1); + Assert.AreEqual(0, lib.Count); + using var move = new MoveData("testMove", new TypeIdentifier(0), MoveCategory.Physical, 100, 100, 1, + MoveTarget.All, 0, null, Array.Empty()); + lib.Add("foobar", move); + Assert.AreEqual(1, lib.Count); + Assert.AreEqual("testMove", lib["foobar"].Name); + } + + [Test] + public void CreateAddIterate() + { + using var lib = new MoveLibrary(10); + Assert.AreEqual(0, lib.Count); + for (ushort i = 0; i < 10; i++) + { + using var move = new MoveData(i.ToString(), new TypeIdentifier(0), MoveCategory.Physical, 100, 100, 1, + MoveTarget.All, 0, null, Array.Empty()); + lib.Add(i + "_key", move); + } + + Assert.AreEqual(10, lib.Count); + var index = 0; + foreach (var kv in lib) + { + Assert.AreEqual(kv.Key, index + "_key"); + Assert.AreEqual(kv.Value.Name, index.ToString()); + index++; + } + + Assert.AreEqual(10, index); + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharpTests/StaticData/Libraries/NatureLibraryTests.cs b/PkmnLibRSharpTests/StaticData/Libraries/NatureLibraryTests.cs new file mode 100644 index 0000000..27c31ef --- /dev/null +++ b/PkmnLibRSharpTests/StaticData/Libraries/NatureLibraryTests.cs @@ -0,0 +1,71 @@ +using NUnit.Framework; +using PkmnLibSharp.StaticData; +using PkmnLibSharp.StaticData.Libraries; + +namespace PkmnLibRSharpTests.StaticData.Libraries +{ + public class NatureLibraryTests + { + [Test] + public void CreateNatureLibrary() + { + using var library = new NatureLibrary(0); + } + + [Test] + public void LoadNatures() + { + using var library = new NatureLibrary(0); + using var nature1 = Nature.NeutralNature(); + using var nature2 = new Nature(Statistic.Attack, Statistic.Defense); + library.LoadNature("foo", nature1); + library.LoadNature("bar", nature2); + } + + [Test] + public void LoadAndGetNature() + { + using var library = new NatureLibrary(0); + using var nature1 = new Nature(Statistic.Attack, Statistic.Defense); + library.LoadNature("foo", nature1); + + Assert.That(library.TryGetNature("foo", out var n)); + Assert.AreEqual(Statistic.Attack, n.IncreasedStat); + } + + [Test] + public void LoadAndGetNatureTwice() + { + using var library = new NatureLibrary(0); + using var nature1 = new Nature(Statistic.Attack, Statistic.Defense); + library.LoadNature("foo", nature1); + + Assert.That(library.TryGetNature("foo", out var n)); + Assert.AreEqual(Statistic.Attack, n.IncreasedStat); + + Assert.That(library.TryGetNature("foo", out n)); + Assert.AreEqual(Statistic.Attack, n.IncreasedStat); + } + + [Test] + public void GetUnknownNature() + { + using var library = new NatureLibrary(0); + using var nature1 = new Nature(Statistic.Attack, Statistic.Defense); + + Assert.False(library.TryGetNature("foo", out _)); + } + + [Test] + public void GetNatureName() + { + using var library = new NatureLibrary(0); + using var nature1 = new Nature(Statistic.Attack, Statistic.Defense); + library.LoadNature("foo", nature1); + + Assert.That(library.TryGetNature("foo", out var n)); + Assert.AreEqual("foo", library.GetNatureName(n)); + } + + } +} \ No newline at end of file diff --git a/PkmnLibRSharpTests/StaticData/Libraries/SpeciesLibraryTests.cs b/PkmnLibRSharpTests/StaticData/Libraries/SpeciesLibraryTests.cs index f780661..ccd68ff 100644 --- a/PkmnLibRSharpTests/StaticData/Libraries/SpeciesLibraryTests.cs +++ b/PkmnLibRSharpTests/StaticData/Libraries/SpeciesLibraryTests.cs @@ -11,22 +11,47 @@ namespace PkmnLibRSharpTests.StaticData.Libraries public void Create() { using var lib = new SpeciesLibrary(0); - Assert.AreEqual(0, lib.Length); + Assert.AreEqual(0, lib.Count); } [Test] public void CreateAndAdd() { - using var lib = new SpeciesLibrary(0); - Assert.AreEqual(0, lib.Length); + using var lib = new SpeciesLibrary(1); + Assert.AreEqual(0, lib.Count); using var stats = new StaticStatisticSet(5, 10, 30, 20, 2, 0); using var moves = new LearnableMoves(); using var form = new Form("foobar", 0.2f, 5.8f, 300, new TypeIdentifier[] { new(1), new(2) }, stats, new[] { "foo", "bar" }, new[] { "set" }, moves, Array.Empty()); using var species = new Species(10, "testSpecies", 0.2f, "growth", 120, form, Array.Empty()); lib.Add("foobar", species); - Assert.AreEqual(1, lib.Length); + Assert.AreEqual(1, lib.Count); Assert.AreEqual("testSpecies", lib["foobar"].Name); } + + [Test] + public void CreateAddIterate() + { + using var lib = new SpeciesLibrary(1); + Assert.AreEqual(0, lib.Count); + for (ushort i = 0; i < 10; i++) + { + using var stats = new StaticStatisticSet(5, 10, 30, 20, 2, 0); + using var moves = new LearnableMoves(); + using var form = new Form("foobar", 0.2f, 5.8f, 300, new TypeIdentifier[] { new(1), new(2) }, stats, + new[] { "foo", "bar" }, new[] { "set" }, moves, Array.Empty()); + using var species = new Species(i, i.ToString(), 0.2f, "growth", 120, form, Array.Empty()); + lib.Add(i + "_key", species); + } + Assert.AreEqual(10, lib.Count); + var index = 0; + foreach (var kv in lib) + { + Assert.AreEqual(kv.Key, index + "_key"); + Assert.AreEqual(kv.Value.Id, index); + index++; + } + Assert.AreEqual(10, index); + } } } \ No newline at end of file diff --git a/PkmnLibRSharpTests/StaticData/Libraries/StaticDataTests.cs b/PkmnLibRSharpTests/StaticData/Libraries/StaticDataTests.cs new file mode 100644 index 0000000..290e62c --- /dev/null +++ b/PkmnLibRSharpTests/StaticData/Libraries/StaticDataTests.cs @@ -0,0 +1,79 @@ +using NUnit.Framework; +using PkmnLibSharp.StaticData.Libraries; + +namespace PkmnLibRSharpTests.StaticData.Libraries +{ + public class StaticDataTests + { + [Test] + public void CreateNewStaticData() + { + using var settings = new LibrarySettings(100); + using var library = new PkmnLibSharp.StaticData.Libraries.StaticData(settings); + } + + [Test] + public void GetSettings() + { + using var settings = new LibrarySettings(100); + using var library = new PkmnLibSharp.StaticData.Libraries.StaticData(settings); + var _ = library.LibrarySettings; + } + + [Test] + public void GetSpecies() + { + using var settings = new LibrarySettings(100); + using var library = new PkmnLibSharp.StaticData.Libraries.StaticData(settings); + var _ = library.SpeciesLibrary; + } + + [Test] + public void GetMoves() + { + using var settings = new LibrarySettings(100); + using var library = new PkmnLibSharp.StaticData.Libraries.StaticData(settings); + var _ = library.MoveLibrary; + } + + [Test] + public void GetItems() + { + using var settings = new LibrarySettings(100); + using var library = new PkmnLibSharp.StaticData.Libraries.StaticData(settings); + var _ = library.ItemLibrary; + } + + [Test] + public void GetGrowthRates() + { + using var settings = new LibrarySettings(100); + using var library = new PkmnLibSharp.StaticData.Libraries.StaticData(settings); + var _ = library.GrowthRateLibrary; + } + + [Test] + public void GetTypeLibrary() + { + using var settings = new LibrarySettings(100); + using var library = new PkmnLibSharp.StaticData.Libraries.StaticData(settings); + var _ = library.TypeLibrary; + } + + [Test] + public void GetNatureLibrary() + { + using var settings = new LibrarySettings(100); + using var library = new PkmnLibSharp.StaticData.Libraries.StaticData(settings); + var _ = library.NatureLibrary; + } + + [Test] + public void GetAbilityLibrary() + { + using var settings = new LibrarySettings(100); + using var library = new PkmnLibSharp.StaticData.Libraries.StaticData(settings); + var _ = library.AbilityLibrary; + } + } +} \ No newline at end of file diff --git a/PkmnLibRSharpTests/StaticData/Libraries/TypeLibraryTests.cs b/PkmnLibRSharpTests/StaticData/Libraries/TypeLibraryTests.cs new file mode 100644 index 0000000..35885d9 --- /dev/null +++ b/PkmnLibRSharpTests/StaticData/Libraries/TypeLibraryTests.cs @@ -0,0 +1,95 @@ +using System.Collections.Generic; +using NUnit.Framework; +using PkmnLibSharp.StaticData; +using PkmnLibSharp.StaticData.Libraries; + +namespace PkmnLibRSharpTests.StaticData.Libraries +{ + public class TypeLibraryTests + { + [Test] + public void CreateTypeLibrary() + { + using var typeLibrary = new TypeLibrary(0); + } + + [Test] + public void RegisterType() + { + using var typeLibrary = new TypeLibrary(0); + typeLibrary.RegisterType("foobar"); + } + + [Test] + public void RegisterTypeRetrieve() + { + using var typeLibrary = new TypeLibrary(0); + var typeIdentifier1 = typeLibrary.RegisterType("foo"); + Assert.AreEqual(typeIdentifier1, new TypeIdentifier(1)); + var typeIdentifier2 = typeLibrary.RegisterType("bar"); + Assert.AreEqual(typeIdentifier2, new TypeIdentifier(2)); + Assert.AreEqual(typeIdentifier1, typeLibrary.GetTypeId("foo")); + Assert.AreEqual(typeIdentifier2, typeLibrary.GetTypeId("bar")); + } + + [Test] + public void GetUnknownTypeErrors() + { + using var typeLibrary = new TypeLibrary(0); + typeLibrary.RegisterType("foo"); + Assert.Throws(() => + { + typeLibrary.GetTypeId("bar"); + }); + } + + [Test] + public void GetTypeName() + { + using var typeLibrary = new TypeLibrary(0); + var typeIdentifier1 = typeLibrary.RegisterType("foo"); + Assert.AreEqual("foo", typeLibrary.GetTypeName(typeIdentifier1)); + } + + [Test] + public void GetUnknownTypeNameErrors() + { + using var typeLibrary = new TypeLibrary(0); + typeLibrary.RegisterType("foo"); + Assert.Throws(() => + { + typeLibrary.GetTypeName(new TypeIdentifier(100)); + }); + } + + [Test] + public void SetEffectiveness() + { + using var typeLibrary = new TypeLibrary(0); + var typeIdentifier1 = typeLibrary.RegisterType("foo"); + var typeIdentifier2 = typeLibrary.RegisterType("bar"); + typeLibrary.SetEffectiveness(typeIdentifier1, typeIdentifier2, 0.5f); + } + + [Test] + public void GetEffectiveness() + { + using var typeLibrary = new TypeLibrary(0); + var typeIdentifier1 = typeLibrary.RegisterType("foo"); + var typeIdentifier2 = typeLibrary.RegisterType("bar"); + typeLibrary.SetEffectiveness(typeIdentifier1, typeIdentifier2, 0.5f); + Assert.AreEqual(0.5f, typeLibrary.GetSingleEffectiveness(typeIdentifier1, typeIdentifier2)); + } + + [Test] + public void GetMultipleEffectiveness() + { + using var typeLibrary = new TypeLibrary(0); + var typeIdentifier1 = typeLibrary.RegisterType("foo"); + var typeIdentifier2 = typeLibrary.RegisterType("bar"); + typeLibrary.SetEffectiveness(typeIdentifier1, typeIdentifier2, 0.5f); + Assert.AreEqual(0.25f, + typeLibrary.GetEffectiveness(typeIdentifier1, new[] { typeIdentifier2, typeIdentifier2 })); + } + } +} \ No newline at end of file