diff --git a/NHSE.Injection/PocketInjector.cs b/NHSE.Injection/PocketInjector.cs index 8693470..09f295c 100644 --- a/NHSE.Injection/PocketInjector.cs +++ b/NHSE.Injection/PocketInjector.cs @@ -21,7 +21,7 @@ public PocketInjector(IReadOnlyList items, IRAMReadWriter bot) } private const int pocket = Item.SIZE * 20; - private const int size = (pocket * 2) + 0x18; + private const int size = (pocket + 0x18) * 2; private const int shift = -0x18 - (Item.SIZE * 20); private uint DataOffset => (uint)(WriteOffset + shift); @@ -90,23 +90,44 @@ public bool Validate(byte[] data) if (!ValidateEnabled) return true; + return ValidateItemBinary(data); + } + + public static bool ValidateItemBinary(byte[] data) + { // Check the unlocked slot count -- expect 0,10,20 var bagCount = BitConverter.ToUInt32(data, pocket); if (bagCount > 20 || bagCount % 10 != 0) // pouch21-39 count return false; + var pocketCount = BitConverter.ToUInt32(data, pocket + 0x18 + pocket); + if (pocketCount != 20) // pouch0-19 count should be 20. + return false; + // Check the item wheel binding -- expect -1 or [0,7] // Disallow duplicate binds! + // Don't bother checking that bind[i] (when ! -1) is not NONE at items[i]. We don't need to check everything! var bound = new List(); + if (!ValidateBindList(data, pocket + 4, bound)) + return false; + if (!ValidateBindList(data, pocket + 4 + (pocket + 0x18), bound)) + return false; + + return true; + } + + private static bool ValidateBindList(byte[] data, int bindStart, ICollection bound) + { for (int i = 0; i < 20; i++) { - var bind = data[pocket + 4 + i]; + var bind = data[bindStart + i]; if (bind == 0xFF) continue; if (bind > 7) return false; if (bound.Contains(bind)) return false; + bound.Add(bind); } diff --git a/NHSE.Tests/InjectionTests.cs b/NHSE.Tests/InjectionTests.cs new file mode 100644 index 0000000..1499715 --- /dev/null +++ b/NHSE.Tests/InjectionTests.cs @@ -0,0 +1,17 @@ +using FluentAssertions; +using NHSE.Injection; +using Xunit; + +namespace NHSE.Tests +{ + public static class InjectionTests + { + [Fact] + public static void VerifyItemBinary() + { + var data = Properties.Resources.itempacket; + bool result = PocketInjector.ValidateItemBinary(data); + result.Should().BeTrue(); + } + } +} diff --git a/NHSE.Tests/NHSE.Tests.csproj b/NHSE.Tests/NHSE.Tests.csproj index 9902e99..64f887d 100644 --- a/NHSE.Tests/NHSE.Tests.csproj +++ b/NHSE.Tests/NHSE.Tests.csproj @@ -18,6 +18,7 @@ + diff --git a/NHSE.Tests/Properties/Resources.Designer.cs b/NHSE.Tests/Properties/Resources.Designer.cs index ca053d8..599a499 100644 --- a/NHSE.Tests/Properties/Resources.Designer.cs +++ b/NHSE.Tests/Properties/Resources.Designer.cs @@ -60,6 +60,16 @@ internal class Resources { } } + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] itempacket { + get { + object obj = ResourceManager.GetObject("itempacket", resourceCulture); + return ((byte[])(obj)); + } + } + /// /// Looks up a localized resource of type System.Byte[]. /// diff --git a/NHSE.Tests/Properties/Resources.resx b/NHSE.Tests/Properties/Resources.resx index 43b649f..3fa027a 100644 --- a/NHSE.Tests/Properties/Resources.resx +++ b/NHSE.Tests/Properties/Resources.resx @@ -118,6 +118,9 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + ..\Resources\itempacket.bin;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + ..\Resources\STR_ItemName_41_Turnip.msbt;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 diff --git a/NHSE.Tests/Resources/itempacket.bin b/NHSE.Tests/Resources/itempacket.bin new file mode 100644 index 0000000..759750f Binary files /dev/null and b/NHSE.Tests/Resources/itempacket.bin differ