From 39296124b10811172ef57c8df09babdd388ede2b Mon Sep 17 00:00:00 2001 From: Infi Date: Tue, 2 Jul 2024 18:39:18 +0200 Subject: [PATCH] Fix party finder packet layout (#1875) Co-authored-by: goat <16760685+goaaats@users.noreply.github.com> --- .../Internal/PartyFinderPacketListing.cs | 45 ++++++++++--------- .../Game/Gui/PartyFinder/PartyFinderGui.cs | 8 ++-- .../Game/Gui/PartyFinder/Types/JobFlags.cs | 10 +++++ .../PartyFinder/Types/JobFlagsExtensions.cs | 2 + .../PartyFinder/Types/PartyFinderListing.cs | 17 +++++-- .../Gui/PartyFinder/Types/PartyFinderSlot.cs | 4 +- 6 files changed, 56 insertions(+), 30 deletions(-) diff --git a/Dalamud/Game/Gui/PartyFinder/Internal/PartyFinderPacketListing.cs b/Dalamud/Game/Gui/PartyFinder/Internal/PartyFinderPacketListing.cs index 53d2831ef..8cf9acf08 100644 --- a/Dalamud/Game/Gui/PartyFinder/Internal/PartyFinderPacketListing.cs +++ b/Dalamud/Game/Gui/PartyFinder/Internal/PartyFinderPacketListing.cs @@ -13,34 +13,36 @@ namespace Dalamud.Game.Gui.PartyFinder.Internal; internal readonly struct PartyFinderPacketListing { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] - private readonly byte[] header1; + private readonly byte[] padding1; internal readonly uint Id; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] - private readonly byte[] header2; + private readonly byte[] padding2; - internal readonly uint ContentIdLower; - private readonly ushort unknownShort1; - private readonly ushort unknownShort2; + internal readonly uint PaddingId; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + private readonly byte[] padding3; + + internal readonly ulong ContentId; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] - private readonly byte[] header3; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + private readonly byte[] padding4; internal readonly byte Category; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] - private readonly byte[] header4; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + private readonly byte[] padding5; internal readonly ushort Duty; internal readonly byte DutyType; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] - private readonly byte[] header5; + private readonly byte[] padding6; internal readonly ushort World; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] - private readonly byte[] header6; + private readonly byte[] padding7; internal readonly byte Objective; internal readonly byte BeginnersWelcome; @@ -49,36 +51,36 @@ internal readonly struct PartyFinderPacketListing internal readonly byte LootRules; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] - private readonly byte[] header7; // all zero in every pf I've examined + private readonly byte[] padding8; // all zero in every pf I've examined internal readonly uint LastPatchHotfixTimestamp; // last time the servers were restarted? internal readonly ushort SecondsRemaining; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] - private readonly byte[] header8; // 00 00 01 00 00 00 in every pf I've examined + private readonly byte[] padding9; // 00 00 01 00 00 00 in every pf I've examined internal readonly ushort MinimumItemLevel; internal readonly ushort HomeWorld; internal readonly ushort CurrentWorld; - private readonly byte header9; + private readonly byte padding10; internal readonly byte NumSlots; + internal readonly byte NumSlotsFilled; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] - private readonly byte[] header10; + private readonly byte padding11; internal readonly byte SearchArea; - private readonly byte header11; + private readonly byte padding12; internal readonly byte NumParties; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] - private readonly byte[] header12; // 00 00 00 always. maybe numParties is a u32? + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)] + private readonly byte[] padding13; // 00 00 00 always. maybe numParties is a u32? [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] - internal readonly uint[] Slots; + internal readonly ulong[] Slots; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] internal readonly byte[] JobsPresent; @@ -90,6 +92,9 @@ internal readonly struct PartyFinderPacketListing [MarshalAs(UnmanagedType.ByValArray, SizeConst = 192)] internal readonly byte[] Description; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + private readonly byte[] padding14; + internal bool IsNull() { // a valid party finder must have at least one slot set diff --git a/Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs b/Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs index 19b4cecd0..ef4055b29 100644 --- a/Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs +++ b/Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs @@ -18,7 +18,7 @@ namespace Dalamud.Game.Gui.PartyFinder; internal sealed class PartyFinderGui : IInternalDisposableService, IPartyFinderGui { private readonly PartyFinderAddressResolver address; - private readonly IntPtr memory; + private readonly nint memory; private readonly Hook receiveListingHook; @@ -39,7 +39,7 @@ private PartyFinderGui(TargetSigScanner sigScanner) } [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - private delegate void ReceiveListingDelegate(IntPtr managerPtr, IntPtr data); + private delegate void ReceiveListingDelegate(nint managerPtr, nint data); /// public event IPartyFinderGui.PartyFinderListingEventDelegate? ReceiveListing; @@ -61,7 +61,7 @@ void IInternalDisposableService.DisposeService() } } - private void HandleReceiveListingDetour(IntPtr managerPtr, IntPtr data) + private void HandleReceiveListingDetour(nint managerPtr, nint data) { try { @@ -75,7 +75,7 @@ private void HandleReceiveListingDetour(IntPtr managerPtr, IntPtr data) this.receiveListingHook.Original(managerPtr, data); } - private void HandleListingEvents(IntPtr data) + private void HandleListingEvents(nint data) { var dataPtr = data + 0x10; diff --git a/Dalamud/Game/Gui/PartyFinder/Types/JobFlags.cs b/Dalamud/Game/Gui/PartyFinder/Types/JobFlags.cs index 419a4a138..ff2a3ce2a 100644 --- a/Dalamud/Game/Gui/PartyFinder/Types/JobFlags.cs +++ b/Dalamud/Game/Gui/PartyFinder/Types/JobFlags.cs @@ -150,4 +150,14 @@ public enum JobFlags /// Sage (SGE). /// Sage = 1 << 29, + + /// + /// Viper (VPR). + /// + Viper = 1 << 30, + + /// + /// Pictomancer (PCT). + /// + Pictomancer = 1 << 31, } diff --git a/Dalamud/Game/Gui/PartyFinder/Types/JobFlagsExtensions.cs b/Dalamud/Game/Gui/PartyFinder/Types/JobFlagsExtensions.cs index 46e83b972..ba72021ba 100644 --- a/Dalamud/Game/Gui/PartyFinder/Types/JobFlagsExtensions.cs +++ b/Dalamud/Game/Gui/PartyFinder/Types/JobFlagsExtensions.cs @@ -49,6 +49,8 @@ public static class JobFlagsExtensions JobFlags.Dancer => 38, JobFlags.Reaper => 39, JobFlags.Sage => 40, + JobFlags.Viper => 41, + JobFlags.Pictomancer => 42, _ => null, }; diff --git a/Dalamud/Game/Gui/PartyFinder/Types/PartyFinderListing.cs b/Dalamud/Game/Gui/PartyFinder/Types/PartyFinderListing.cs index fb8d4b900..3275537a7 100644 --- a/Dalamud/Game/Gui/PartyFinder/Types/PartyFinderListing.cs +++ b/Dalamud/Game/Gui/PartyFinder/Types/PartyFinderListing.cs @@ -58,7 +58,7 @@ public interface IPartyFinderListing /// /// Gets the lower bits of the player's content ID. /// - uint ContentIdLower { get; } + ulong ContentId { get; } /// /// Gets the name of the player hosting this listing. @@ -131,6 +131,11 @@ public interface IPartyFinderListing /// byte SlotsAvailable { get; } + /// + /// Gets the number of player slots filled. + /// + byte SlotsFilled { get; } + /// /// Gets the time at which the server this listings is on last restarted for a patch/hotfix. /// Probably. @@ -208,7 +213,7 @@ internal PartyFinderListing(PartyFinderPacketListing listing) this.jobsPresent = listing.JobsPresent; this.Id = listing.Id; - this.ContentIdLower = listing.ContentIdLower; + this.ContentId = listing.ContentId; this.Name = SeString.Parse(listing.Name.TakeWhile(b => b != 0).ToArray()); this.Description = SeString.Parse(listing.Description.TakeWhile(b => b != 0).ToArray()); this.World = new Lazy(() => dataManager.GetExcelSheet().GetRow(listing.World)); @@ -223,6 +228,7 @@ internal PartyFinderListing(PartyFinderPacketListing listing) this.MinimumItemLevel = listing.MinimumItemLevel; this.Parties = listing.NumParties; this.SlotsAvailable = listing.NumSlots; + this.SlotsFilled = listing.NumSlotsFilled; this.LastPatchHotfixTimestamp = listing.LastPatchHotfixTimestamp; this.JobsPresent = listing.JobsPresent .Select(id => new Lazy( @@ -236,7 +242,7 @@ internal PartyFinderListing(PartyFinderPacketListing listing) public uint Id { get; } /// - public uint ContentIdLower { get; } + public ulong ContentId { get; } /// public SeString Name { get; } @@ -280,6 +286,9 @@ internal PartyFinderListing(PartyFinderPacketListing listing) /// public byte SlotsAvailable { get; } + /// + public byte SlotsFilled { get; } + /// public uint LastPatchHotfixTimestamp { get; } @@ -325,5 +334,5 @@ internal PartyFinderListing(PartyFinderPacketListing listing) public bool this[SearchAreaFlags flag] => this.searchArea == 0 || (this.searchArea & (uint)flag) > 0; #endregion - } + diff --git a/Dalamud/Game/Gui/PartyFinder/Types/PartyFinderSlot.cs b/Dalamud/Game/Gui/PartyFinder/Types/PartyFinderSlot.cs index 631a89a41..3d1e496fc 100644 --- a/Dalamud/Game/Gui/PartyFinder/Types/PartyFinderSlot.cs +++ b/Dalamud/Game/Gui/PartyFinder/Types/PartyFinderSlot.cs @@ -8,14 +8,14 @@ namespace Dalamud.Game.Gui.PartyFinder.Types; /// public class PartyFinderSlot { - private readonly uint accepting; + private readonly ulong accepting; private JobFlags[] listAccepting; /// /// Initializes a new instance of the class. /// /// The flag value of accepted jobs. - internal PartyFinderSlot(uint accepting) + internal PartyFinderSlot(ulong accepting) { this.accepting = accepting; }