diff --git a/Penumbra.GameData/Structs/CharacterEquipment.cs b/Penumbra.GameData/Structs/CharacterEquipment.cs index 11be31ed..357ce36b 100644 --- a/Penumbra.GameData/Structs/CharacterEquipment.cs +++ b/Penumbra.GameData/Structs/CharacterEquipment.cs @@ -4,146 +4,145 @@ using Dalamud.Game.ClientState.Objects.Types; // Read the customization data regarding weapons and displayable equipment from an actor struct. // Stores the data in a 56 bytes, i.e. 7 longs for easier comparison. -namespace Penumbra.GameData.Structs +namespace Penumbra.GameData.Structs; + +[StructLayout( LayoutKind.Sequential, Pack = 1 )] +public class CharacterEquipment { - [StructLayout( LayoutKind.Sequential, Pack = 1 )] - public class CharacterEquipment + public const int MainWeaponOffset = 0x6D0; + public const int OffWeaponOffset = 0x738; + public const int EquipmentOffset = 0x808; + public const int EquipmentSlots = 10; + public const int WeaponSlots = 2; + + public CharacterWeapon MainHand; + public CharacterWeapon OffHand; + public CharacterArmor Head; + public CharacterArmor Body; + public CharacterArmor Hands; + public CharacterArmor Legs; + public CharacterArmor Feet; + public CharacterArmor Ears; + public CharacterArmor Neck; + public CharacterArmor Wrists; + public CharacterArmor RFinger; + public CharacterArmor LFinger; + public ushort IsSet; // Also fills struct size to 56, a multiple of 8. + + public CharacterEquipment() + => Clear(); + + public CharacterEquipment( Character actor ) + : this( actor.Address ) + { } + + public override string ToString() + => IsSet == 0 + ? "(Not Set)" + : $"({MainHand}) | ({OffHand}) | ({Head}) | ({Body}) | ({Hands}) | ({Legs}) | " + + $"({Feet}) | ({Ears}) | ({Neck}) | ({Wrists}) | ({LFinger}) | ({RFinger})"; + + public bool Equal( Character rhs ) + => CompareData( new CharacterEquipment( rhs ) ); + + public bool Equal( CharacterEquipment rhs ) + => CompareData( rhs ); + + public bool CompareAndUpdate( Character rhs ) + => CompareAndOverwrite( new CharacterEquipment( rhs ) ); + + public bool CompareAndUpdate( CharacterEquipment rhs ) + => CompareAndOverwrite( rhs ); + + private unsafe CharacterEquipment( IntPtr actorAddress ) { - public const int MainWeaponOffset = 0x0C78; - public const int OffWeaponOffset = 0x0CE0; - public const int EquipmentOffset = 0xDB0; - public const int EquipmentSlots = 10; - public const int WeaponSlots = 2; - - public CharacterWeapon MainHand; - public CharacterWeapon OffHand; - public CharacterArmor Head; - public CharacterArmor Body; - public CharacterArmor Hands; - public CharacterArmor Legs; - public CharacterArmor Feet; - public CharacterArmor Ears; - public CharacterArmor Neck; - public CharacterArmor Wrists; - public CharacterArmor RFinger; - public CharacterArmor LFinger; - public ushort IsSet; // Also fills struct size to 56, a multiple of 8. - - public CharacterEquipment() - => Clear(); - - public CharacterEquipment( Character actor ) - : this( actor.Address ) - { } - - public override string ToString() - => IsSet == 0 - ? "(Not Set)" - : $"({MainHand}) | ({OffHand}) | ({Head}) | ({Body}) | ({Hands}) | ({Legs}) | " - + $"({Feet}) | ({Ears}) | ({Neck}) | ({Wrists}) | ({LFinger}) | ({RFinger})"; - - public bool Equal( Character rhs ) - => CompareData( new CharacterEquipment( rhs ) ); - - public bool Equal( CharacterEquipment rhs ) - => CompareData( rhs ); - - public bool CompareAndUpdate( Character rhs ) - => CompareAndOverwrite( new CharacterEquipment( rhs ) ); - - public bool CompareAndUpdate( CharacterEquipment rhs ) - => CompareAndOverwrite( rhs ); - - private unsafe CharacterEquipment( IntPtr actorAddress ) + IsSet = 1; + var actorPtr = ( byte* )actorAddress.ToPointer(); + fixed( CharacterWeapon* main = &MainHand, off = &OffHand ) { - IsSet = 1; - var actorPtr = ( byte* )actorAddress.ToPointer(); - fixed( CharacterWeapon* main = &MainHand, off = &OffHand ) - { - Buffer.MemoryCopy( actorPtr + MainWeaponOffset, main, sizeof( CharacterWeapon ), sizeof( CharacterWeapon ) ); - Buffer.MemoryCopy( actorPtr + OffWeaponOffset, off, sizeof( CharacterWeapon ), sizeof( CharacterWeapon ) ); - } - - fixed( CharacterArmor* equipment = &Head ) - { - Buffer.MemoryCopy( actorPtr + EquipmentOffset, equipment, EquipmentSlots * sizeof( CharacterArmor ), - EquipmentSlots * sizeof( CharacterArmor ) ); - } + Buffer.MemoryCopy( actorPtr + MainWeaponOffset, main, sizeof( CharacterWeapon ), sizeof( CharacterWeapon ) ); + Buffer.MemoryCopy( actorPtr + OffWeaponOffset, off, sizeof( CharacterWeapon ), sizeof( CharacterWeapon ) ); } - public unsafe void Clear() + fixed( CharacterArmor* equipment = &Head ) { - fixed( CharacterWeapon* main = &MainHand ) - { - var structSizeEights = ( 2 + EquipmentSlots * sizeof( CharacterArmor ) + WeaponSlots * sizeof( CharacterWeapon ) ) / 8; - for( ulong* ptr = ( ulong* )main, end = ptr + structSizeEights; ptr != end; ++ptr ) - { - *ptr = 0; - } - } + Buffer.MemoryCopy( actorPtr + EquipmentOffset, equipment, EquipmentSlots * sizeof( CharacterArmor ), + EquipmentSlots * sizeof( CharacterArmor ) ); } + } - private unsafe bool CompareAndOverwrite( CharacterEquipment rhs ) + public unsafe void Clear() + { + fixed( CharacterWeapon* main = &MainHand ) { var structSizeEights = ( 2 + EquipmentSlots * sizeof( CharacterArmor ) + WeaponSlots * sizeof( CharacterWeapon ) ) / 8; - var ret = true; - fixed( CharacterWeapon* data1 = &MainHand, data2 = &rhs.MainHand ) + for( ulong* ptr = ( ulong* )main, end = ptr + structSizeEights; ptr != end; ++ptr ) { - var ptr1 = ( ulong* )data1; - var ptr2 = ( ulong* )data2; - for( var end = ptr1 + structSizeEights; ptr1 != end; ++ptr1, ++ptr2 ) - { - if( *ptr1 != *ptr2 ) - { - *ptr1 = *ptr2; - ret = false; - } - } - } - - return ret; - } - - private unsafe bool CompareData( CharacterEquipment rhs ) - { - var structSizeEights = ( 2 + EquipmentSlots * sizeof( CharacterArmor ) + WeaponSlots * sizeof( CharacterWeapon ) ) / 8; - fixed( CharacterWeapon* data1 = &MainHand, data2 = &rhs.MainHand ) - { - var ptr1 = ( ulong* )data1; - var ptr2 = ( ulong* )data2; - for( var end = ptr1 + structSizeEights; ptr1 != end; ++ptr1, ++ptr2 ) - { - if( *ptr1 != *ptr2 ) - { - return false; - } - } - } - - return true; - } - - public unsafe void WriteBytes( byte[] array, int offset = 0 ) - { - fixed( CharacterWeapon* data = &MainHand ) - { - Marshal.Copy( new IntPtr( data ), array, offset, 56 ); - } - } - - public byte[] ToBytes() - { - var ret = new byte[56]; - WriteBytes( ret ); - return ret; - } - - public unsafe void FromBytes( byte[] array, int offset = 0 ) - { - fixed( CharacterWeapon* data = &MainHand ) - { - Marshal.Copy( array, offset, new IntPtr( data ), 56 ); + *ptr = 0; } } } + + private unsafe bool CompareAndOverwrite( CharacterEquipment rhs ) + { + var structSizeEights = ( 2 + EquipmentSlots * sizeof( CharacterArmor ) + WeaponSlots * sizeof( CharacterWeapon ) ) / 8; + var ret = true; + fixed( CharacterWeapon* data1 = &MainHand, data2 = &rhs.MainHand ) + { + var ptr1 = ( ulong* )data1; + var ptr2 = ( ulong* )data2; + for( var end = ptr1 + structSizeEights; ptr1 != end; ++ptr1, ++ptr2 ) + { + if( *ptr1 != *ptr2 ) + { + *ptr1 = *ptr2; + ret = false; + } + } + } + + return ret; + } + + private unsafe bool CompareData( CharacterEquipment rhs ) + { + var structSizeEights = ( 2 + EquipmentSlots * sizeof( CharacterArmor ) + WeaponSlots * sizeof( CharacterWeapon ) ) / 8; + fixed( CharacterWeapon* data1 = &MainHand, data2 = &rhs.MainHand ) + { + var ptr1 = ( ulong* )data1; + var ptr2 = ( ulong* )data2; + for( var end = ptr1 + structSizeEights; ptr1 != end; ++ptr1, ++ptr2 ) + { + if( *ptr1 != *ptr2 ) + { + return false; + } + } + } + + return true; + } + + public unsafe void WriteBytes( byte[] array, int offset = 0 ) + { + fixed( CharacterWeapon* data = &MainHand ) + { + Marshal.Copy( new IntPtr( data ), array, offset, 56 ); + } + } + + public byte[] ToBytes() + { + var ret = new byte[56]; + WriteBytes( ret ); + return ret; + } + + public unsafe void FromBytes( byte[] array, int offset = 0 ) + { + fixed( CharacterWeapon* data = &MainHand ) + { + Marshal.Copy( array, offset, new IntPtr( data ), 56 ); + } + } } \ No newline at end of file diff --git a/Penumbra.PlayerWatch/PlayerWatchBase.cs b/Penumbra.PlayerWatch/PlayerWatchBase.cs index 41cb9fdb..dd777043 100644 --- a/Penumbra.PlayerWatch/PlayerWatchBase.cs +++ b/Penumbra.PlayerWatch/PlayerWatchBase.cs @@ -26,7 +26,7 @@ internal readonly struct WatchedPlayer internal class PlayerWatchBase : IDisposable { public const int GPosePlayerIdx = 201; - public const int GPoseTableEnd = GPosePlayerIdx + 48; + public const int GPoseTableEnd = GPosePlayerIdx + 40; private const int ObjectsPerFrame = 32; private readonly Framework _framework; @@ -301,7 +301,7 @@ internal class PlayerWatchBase : IDisposable var id = GetId( character ); SeenActors.Add( id ); - PluginLog.Verbose( "Comparing Gear for {PlayerName} ({Id}) at {Address}...", character.Name, id, character.Address ); + PluginLog.Verbose( "Comparing Gear for {PlayerName:l} ({Id}) at 0x{Address:X}...", character.Name, id, character.Address.ToInt64() ); if( !watch.FoundActors.TryGetValue( id, out var equip ) ) { equip = new CharacterEquipment( character ); diff --git a/Penumbra/Penumbra.json b/Penumbra/Penumbra.json index 85b613eb..0e05326e 100644 --- a/Penumbra/Penumbra.json +++ b/Penumbra/Penumbra.json @@ -7,7 +7,7 @@ "RepoUrl": "https://github.com/xivdev/Penumbra", "ApplicableVersion": "any", "Tags": [ "modding" ], - "DalamudApiLevel": 5, + "DalamudApiLevel": 6, "LoadPriority": 69420, "IconUrl": "https://raw.githubusercontent.com/xivdev/Penumbra/master/images/icon.png" } \ No newline at end of file diff --git a/base_repo.json b/base_repo.json index 2a3a2145..71b15948 100644 --- a/base_repo.json +++ b/base_repo.json @@ -8,7 +8,7 @@ "TestingAssemblyVersion": "1.0.0.0", "RepoUrl": "https://github.com/xivdev/Penumbra", "ApplicableVersion": "any", - "DalamudApiLevel": 5, + "DalamudApiLevel": 6, "IsHide": "False", "IsTestingExclusive": "False", "DownloadCount": 0,