From a3ce973dda92b152759d24940c1ec2552a1a31fe Mon Sep 17 00:00:00 2001 From: Anna Date: Wed, 31 Mar 2021 09:47:17 -0400 Subject: [PATCH] refactor: use new Dalamud PF event --- BetterPartyFinder/BetterPartyFinder.csproj | 4 +- BetterPartyFinder/Configuration.cs | 1 + BetterPartyFinder/Filter.cs | 14 +- BetterPartyFinder/GameFunctions.cs | 84 ------- BetterPartyFinder/PartyFinder.cs | 242 --------------------- BetterPartyFinder/PfPacket.cs | 125 ----------- BetterPartyFinder/PluginUi.cs | 2 + 7 files changed, 13 insertions(+), 459 deletions(-) delete mode 100755 BetterPartyFinder/PartyFinder.cs delete mode 100755 BetterPartyFinder/PfPacket.cs diff --git a/BetterPartyFinder/BetterPartyFinder.csproj b/BetterPartyFinder/BetterPartyFinder.csproj index 0fe2f9d..23ad5d5 100755 --- a/BetterPartyFinder/BetterPartyFinder.csproj +++ b/BetterPartyFinder/BetterPartyFinder.csproj @@ -8,7 +8,7 @@ - + $(AppData)\XIVLauncher\addon\Hooks\dev\Dalamud.dll False @@ -35,7 +35,7 @@ - + diff --git a/BetterPartyFinder/Configuration.cs b/BetterPartyFinder/Configuration.cs index f97e178..0b8fbde 100755 --- a/BetterPartyFinder/Configuration.cs +++ b/BetterPartyFinder/Configuration.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using Dalamud.Configuration; +using Dalamud.Game.Internal.Gui.Structs; namespace BetterPartyFinder { public class Configuration : IPluginConfiguration { diff --git a/BetterPartyFinder/Filter.cs b/BetterPartyFinder/Filter.cs index ab13c56..84e564d 100755 --- a/BetterPartyFinder/Filter.cs +++ b/BetterPartyFinder/Filter.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; +using Dalamud.Game.Internal.Gui; +using Dalamud.Game.Internal.Gui.Structs; namespace BetterPartyFinder { public class Filter : IDisposable { @@ -9,7 +11,11 @@ namespace BetterPartyFinder { internal Filter(Plugin plugin) { this.Plugin = plugin; - this.Plugin.Functions.ReceivePartyFinderListing += this.ReceiveListing; + this.Plugin.Interface.Framework.Gui.PartyFinder.ReceiveListing += this.ReceiveListing; + } + + public void Dispose() { + this.Plugin.Interface.Framework.Gui.PartyFinder.ReceiveListing -= this.ReceiveListing; } private void ReceiveListing(PartyFinderListing listing, PartyFinderListingEventArgs args) { @@ -142,16 +148,12 @@ namespace BetterPartyFinder { // filter based on player if (filter.Players.Count > 0) { - if (filter.Players.Any(info => info.Name == listing.Name && info.World == listing.HomeWorld.Value.RowId)) { + if (filter.Players.Any(info => info.Name == listing.Name.TextValue && info.World == listing.HomeWorld.Value.RowId)) { return false; } } return true; } - - public void Dispose() { - this.Plugin.Functions.ReceivePartyFinderListing -= this.ReceiveListing; - } } } diff --git a/BetterPartyFinder/GameFunctions.cs b/BetterPartyFinder/GameFunctions.cs index 36e19e5..c05a971 100755 --- a/BetterPartyFinder/GameFunctions.cs +++ b/BetterPartyFinder/GameFunctions.cs @@ -1,7 +1,6 @@ using System; using System.Runtime.InteropServices; using Dalamud.Hooking; -using Dalamud.Plugin; namespace BetterPartyFinder { public class GameFunctions : IDisposable { @@ -14,18 +13,6 @@ namespace BetterPartyFinder { #endregion - #region PF Listings events - - internal delegate void PartyFinderListingEventDelegate(PartyFinderListing listing, PartyFinderListingEventArgs args); - - internal event PartyFinderListingEventDelegate? ReceivePartyFinderListing; - - private delegate void HandlePfPacketDelegate(IntPtr param1, IntPtr data); - - private readonly Hook _handlePacketHook; - - #endregion - private Plugin Plugin { get; } private IntPtr PartyFinderAgent { get; set; } = IntPtr.Zero; @@ -33,19 +20,14 @@ namespace BetterPartyFinder { this.Plugin = plugin; var requestPfPtr = this.Plugin.Interface.TargetModuleScanner.ScanText("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 40 0F 10 81 ?? ?? ?? ??"); - var listingPtr = this.Plugin.Interface.TargetModuleScanner.ScanText("40 53 41 57 48 83 EC 28 48 8B D9"); this._requestPartyFinderListings = Marshal.GetDelegateForFunctionPointer(requestPfPtr); this._requestPfListingsHook = new Hook(requestPfPtr, new RequestPartyFinderListingsDelegate(this.OnRequestPartyFinderListings)); this._requestPfListingsHook.Enable(); - - this._handlePacketHook = new Hook(listingPtr, new HandlePfPacketDelegate(this.PacketDetour)); - this._handlePacketHook.Enable(); } public void Dispose() { this._requestPfListingsHook.Dispose(); - this._handlePacketHook.Dispose(); } private byte OnRequestPartyFinderListings(IntPtr agent, byte categoryIdx) { @@ -69,71 +51,5 @@ namespace BetterPartyFinder { var categoryIdx = Marshal.ReadByte(this.PartyFinderAgent + categoryOffset); this._requestPartyFinderListings(this.PartyFinderAgent, categoryIdx); } - - - private void PacketDetour(IntPtr param1, IntPtr data) { - if (data == IntPtr.Zero) { - goto Return; - } - - try { - this.OnPacket(data); - } catch (Exception ex) { - PluginLog.Error(ex, "Unhandled exception in PF packet detour"); - } - - Return: - this._handlePacketHook!.Original(param1, data); - } - - private void OnPacket(IntPtr data) { - var dataPtr = data + 0x10; - - // parse the packet into a struct - var packet = Marshal.PtrToStructure(dataPtr); - - var needToRewrite = false; - - for (var i = 0; i < packet.listings.Length; i++) { - if (packet.listings[i].IsNull()) { - continue; - } - - // invoke event for each non-null listing - var listing = new PartyFinderListing(packet.listings[i], this.Plugin.Interface.Data); - var args = new PartyFinderListingEventArgs(); - this.ReceivePartyFinderListing?.Invoke(listing, args); - - if (args.Visible) { - continue; - } - - // zero the listing if it shouldn't be visible - packet.listings[i] = new PfListing(); - needToRewrite = true; - } - - if (!needToRewrite) { - return; - } - - // get some memory for writing to - var newPacket = new byte[PacketInfo.PacketSize]; - var pinnedArray = GCHandle.Alloc(newPacket, GCHandleType.Pinned); - var pointer = pinnedArray.AddrOfPinnedObject(); - - // write our struct into the memory (doing this directly crashes the game) - Marshal.StructureToPtr(packet, pointer, false); - - // copy our new memory over the game's - Marshal.Copy(newPacket, 0, dataPtr, PacketInfo.PacketSize); - - // free memory - pinnedArray.Free(); - } - } - - internal class PartyFinderListingEventArgs { - public bool Visible { get; set; } = true; } } diff --git a/BetterPartyFinder/PartyFinder.cs b/BetterPartyFinder/PartyFinder.cs deleted file mode 100755 index d768c6e..0000000 --- a/BetterPartyFinder/PartyFinder.cs +++ /dev/null @@ -1,242 +0,0 @@ -using Dalamud.Data; -using Lumina.Excel.GeneratedSheets; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace BetterPartyFinder { - public class PartyFinderListing { - public uint Id { get; } - public string Name { get; } - public string Description { get; } - public Lazy World { get; } - public Lazy HomeWorld { get; } - public Lazy CurrentWorld { get; } - public Category Category { get; } - public ushort RawDuty { get; } - public Lazy Duty { get; } - public DutyType DutyType { get; } - public bool BeginnersWelcome { get; } - public ushort SecondsRemaining { get; } - public ushort MinimumItemLevel { get; } - public byte Parties { get; } - public byte SlotsAvailable { get; } - public IEnumerable Slots => this._slots; - - private readonly byte _objective; - public ObjectiveFlags Objective => (ObjectiveFlags) this._objective; - - private readonly byte _conditions; - public ConditionFlags Conditions => (ConditionFlags) this._conditions; - - private readonly byte _dutyFinderSettings; - public DutyFinderSettingsFlags DutyFinderSettings => (DutyFinderSettingsFlags) this._dutyFinderSettings; - - private readonly byte _lootRules; - public LootRuleFlags LootRules => (LootRuleFlags) this._lootRules; - - private readonly byte _searchArea; - public SearchAreaFlags SearchArea => (SearchAreaFlags) this._searchArea; - - private readonly PartyFinderSlot[] _slots; - - private readonly byte[] _jobsPresent; - internal IEnumerable RawJobsPresent => this._jobsPresent; - internal IReadOnlyCollection> JobsPresent { get; } - - public bool this[ObjectiveFlags flag] => this._objective == 0 || (this._objective & (uint) flag) > 0; - - - public bool this[ConditionFlags flag] => this._conditions == 0 || (this._conditions & (uint) flag) > 0; - - public bool this[DutyFinderSettingsFlags flag] => this._dutyFinderSettings == 0 || (this._dutyFinderSettings & (uint) flag) > 0; - - public bool this[LootRuleFlags flag] => this._lootRules == 0 || (this._lootRules & (uint) flag) > 0; - - public bool this[SearchAreaFlags flag] => this._searchArea == 0 || (this._searchArea & (uint) flag) > 0; - - internal PartyFinderListing(PfListing listing, DataManager dataManager) { - this.Id = listing.id; - this.Name = listing.Name(); - this.Description = listing.Description(); - this.World = new Lazy(() => dataManager.GetExcelSheet().GetRow(listing.world)); - this.HomeWorld = new Lazy(() => dataManager.GetExcelSheet().GetRow(listing.homeWorld)); - this.CurrentWorld = new Lazy(() => dataManager.GetExcelSheet().GetRow(listing.currentWorld)); - this.Category = (Category) listing.category; - this.RawDuty = listing.duty; - this.Duty = new Lazy(() => dataManager.GetExcelSheet().GetRow(listing.duty)); - this.DutyType = (DutyType) listing.dutyType; - this.BeginnersWelcome = listing.beginnersWelcome == 1; - this.SecondsRemaining = listing.secondsRemaining; - this.MinimumItemLevel = listing.minimumItemLevel; - this.Parties = listing.numParties; - this.SlotsAvailable = listing.numSlots; - - this._objective = listing.objective; - this._conditions = listing.conditions; - this._dutyFinderSettings = listing.dutyFinderSettings; - this._lootRules = listing.lootRules; - this._searchArea = listing.searchArea; - - this._slots = listing.slots.Select(accepting => new PartyFinderSlot(accepting)).ToArray(); - this._jobsPresent = listing.jobsPresent; - this.JobsPresent = this._jobsPresent - .Select(id => new Lazy(() => id == 0 - ? null - : dataManager.GetExcelSheet().GetRow(id))) - .ToArray(); - } - } - - public class PartyFinderSlot { - private readonly uint _accepting; - private JobFlags[]? _listAccepting; - - public IReadOnlyCollection Accepting { - get { - if (this._listAccepting != null) { - return this._listAccepting; - } - - this._listAccepting = Enum.GetValues(typeof(JobFlags)) - .Cast() - .Where(flag => this[flag]) - .ToArray(); - - return this._listAccepting; - } - } - - public bool this[JobFlags flag] => (this._accepting & (uint) flag) > 0; - - internal PartyFinderSlot(uint accepting) { - this._accepting = accepting; - } - } - - [Flags] - public enum SearchAreaFlags : uint { - DataCentre = 1 << 0, - Private = 1 << 1, - AllianceRaid = 1 << 2, - World = 1 << 3, - OnePlayerPerJob = 1 << 5, - } - - [Flags] - public enum JobFlags { - Gladiator = 1 << 1, - Pugilist = 1 << 2, - Marauder = 1 << 3, - Lancer = 1 << 4, - Archer = 1 << 5, - Conjurer = 1 << 6, - Thaumaturge = 1 << 7, - Paladin = 1 << 8, - Monk = 1 << 9, - Warrior = 1 << 10, - Dragoon = 1 << 11, - Bard = 1 << 12, - WhiteMage = 1 << 13, - BlackMage = 1 << 14, - Arcanist = 1 << 15, - Summoner = 1 << 16, - Scholar = 1 << 17, - Rogue = 1 << 18, - Ninja = 1 << 19, - Machinist = 1 << 20, - DarkKnight = 1 << 21, - Astrologian = 1 << 22, - Samurai = 1 << 23, - RedMage = 1 << 24, - BlueMage = 1 << 25, - Gunbreaker = 1 << 26, - Dancer = 1 << 27, - } - - internal static class JobFlagsExt { - internal static ClassJob? ClassJob(this JobFlags job, DataManager data) { - var jobs = data.GetExcelSheet(); - - uint? row = job switch { - JobFlags.Gladiator => 1, - JobFlags.Pugilist => 2, - JobFlags.Marauder => 3, - JobFlags.Lancer => 4, - JobFlags.Archer => 5, - JobFlags.Conjurer => 6, - JobFlags.Thaumaturge => 7, - JobFlags.Paladin => 19, - JobFlags.Monk => 20, - JobFlags.Warrior => 21, - JobFlags.Dragoon => 22, - JobFlags.Bard => 23, - JobFlags.WhiteMage => 24, - JobFlags.BlackMage => 25, - JobFlags.Arcanist => 26, - JobFlags.Summoner => 27, - JobFlags.Scholar => 28, - JobFlags.Rogue => 29, - JobFlags.Ninja => 30, - JobFlags.Machinist => 31, - JobFlags.DarkKnight => 32, - JobFlags.Astrologian => 33, - JobFlags.Samurai => 34, - JobFlags.RedMage => 35, - JobFlags.BlueMage => 36, - JobFlags.Gunbreaker => 37, - JobFlags.Dancer => 38, - _ => null, - }; - - return row == null ? null : jobs.GetRow((uint) row); - } - } - - [Flags] - public enum ObjectiveFlags : uint { - None = 0, - DutyCompletion = 1, - Practice = 2, - Loot = 4, - } - - [Flags] - public enum ConditionFlags : uint { - None = 1, - DutyComplete = 2, - DutyIncomplete = 4, - } - - [Flags] - public enum DutyFinderSettingsFlags : uint { - None = 0, - UndersizedParty = 1 << 0, - MinimumItemLevel = 1 << 1, - SilenceEcho = 1 << 2, - } - - [Flags] - public enum LootRuleFlags : uint { - None = 0, - GreedOnly = 1, - Lootmaster = 2, - } - - public enum Category { - Duty = 0, - QuestBattles = 1 << 0, - Fates = 1 << 1, - TreasureHunt = 1 << 2, - TheHunt = 1 << 3, - GatheringForays = 1 << 4, - DeepDungeons = 1 << 5, - AdventuringForays = 1 << 6, - } - - public enum DutyType { - Other = 0, - Roulette = 1 << 0, - Normal = 1 << 1, - } -} diff --git a/BetterPartyFinder/PfPacket.cs b/BetterPartyFinder/PfPacket.cs deleted file mode 100755 index 5f2df9c..0000000 --- a/BetterPartyFinder/PfPacket.cs +++ /dev/null @@ -1,125 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; - -namespace BetterPartyFinder { - public static class PacketInfo { - public static readonly int PacketSize = Marshal.SizeOf(); - } - - [StructLayout(LayoutKind.Sequential)] - public readonly struct PfPacket { - private readonly int unk0; - - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] - private readonly byte[] padding1; - - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] - public readonly PfListing[] listings; - } - - [StructLayout(LayoutKind.Sequential)] - public readonly struct PfListing { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] - private readonly byte[] header1; - - internal readonly uint id; - - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] - private readonly byte[] header2; - - private readonly uint unknownInt1; - private readonly ushort unknownShort1; - private readonly ushort unknownShort2; - - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] - private readonly byte[] header3; - - internal readonly byte category; - - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] - private readonly byte[] header4; - - internal readonly ushort duty; - internal readonly byte dutyType; - - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] - private readonly byte[] header5; - - internal readonly ushort world; - - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] - private readonly byte[] header6; - - internal readonly byte objective; - internal readonly byte beginnersWelcome; - internal readonly byte conditions; - internal readonly byte dutyFinderSettings; - internal readonly byte lootRules; - - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] - private readonly byte[] header7; // all zero in every pf I've examined - - private 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 - - internal readonly ushort minimumItemLevel; - internal readonly ushort homeWorld; - internal readonly ushort currentWorld; - - private readonly byte header9; - - internal readonly byte numSlots; - - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] - private readonly byte[] header10; - - internal readonly byte searchArea; - - private readonly byte header11; - - 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 = 8)] - internal readonly uint[] slots; - - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] - internal readonly byte[] jobsPresent; - - // Note that ByValTStr will not work here because the strings are UTF-8 and there's only a CharSet for UTF-16 in C#. - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] - private readonly byte[] name; - - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 192)] - private readonly byte[] description; - - // 128 (0x80) before name and desc - // 160 (0xA0) with name (32 bytes/0x20) - // 352 (0x160) with both (192 bytes/0xC0) - - private static string HandleString(IEnumerable bytes) { - var nonNull = bytes.TakeWhile(b => b != 0).ToArray(); - return Encoding.UTF8.GetString(nonNull); - } - - internal string Name() { - return HandleString(this.name); - } - - internal string Description() { - return HandleString(this.description); - } - - internal bool IsNull() { - // a valid party finder must have at least one slot set - return this.slots.All(slot => slot == 0); - } - } -} diff --git a/BetterPartyFinder/PluginUi.cs b/BetterPartyFinder/PluginUi.cs index dedae7b..33a018a 100755 --- a/BetterPartyFinder/PluginUi.cs +++ b/BetterPartyFinder/PluginUi.cs @@ -3,9 +3,11 @@ using System.Collections.Generic; using System.Linq; using System.Numerics; using Dalamud.Data; +using Dalamud.Game.Internal.Gui.Structs; using Dalamud.Interface; using ImGuiNET; using Lumina.Excel.GeneratedSheets; +using Addon = Lumina.Excel.GeneratedSheets.Addon; using GameAddon = Dalamud.Game.Internal.Gui.Addon.Addon; namespace BetterPartyFinder {