mirror of
https://github.com/goatcorp/Dalamud.git
synced 2026-01-03 06:13:40 +01:00
PartyFinder namespaces, break out
This commit is contained in:
parent
9199adb261
commit
bab8eb4182
18 changed files with 570 additions and 571 deletions
28
Dalamud/Game/Gui/PartyFinder/Internal/PartyFinderPacket.cs
Normal file
28
Dalamud/Game/Gui/PartyFinder/Internal/PartyFinderPacket.cs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Dalamud.Game.Gui.PartyFinder.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// The structure of the PartyFinder packet.
|
||||
/// </summary>
|
||||
[SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1201:Elements should appear in the correct order", Justification = "Sequential struct marshaling.")]
|
||||
[SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1202:Elements should be ordered by access", Justification = "Sequential struct marshaling.")]
|
||||
[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "Document the field usage.")]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal readonly struct PartyFinderPacket
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the size of this packet.
|
||||
/// </summary>
|
||||
internal static int PacketSize { get; } = Marshal.SizeOf<PartyFinderPacket>();
|
||||
|
||||
internal readonly int BatchNumber;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
|
||||
private readonly byte[] padding1;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
||||
internal readonly PartyFinderPacketListing[] Listings;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Dalamud.Game.Gui.PartyFinder.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// The structure of an individual listing within a packet.
|
||||
/// </summary>
|
||||
[SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1202:Elements should be ordered by access", Justification = "Sequential struct marshaling.")]
|
||||
[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "Document the field usage.")]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal readonly struct PartyFinderPacketListing
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
||||
private readonly byte[] header1;
|
||||
internal readonly uint Id;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
||||
private readonly byte[] header2;
|
||||
|
||||
internal readonly uint ContentIdLower;
|
||||
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)]
|
||||
internal readonly byte[] Name;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 192)]
|
||||
internal readonly byte[] Description;
|
||||
|
||||
internal bool IsNull()
|
||||
{
|
||||
// a valid party finder must have at least one slot set
|
||||
return this.Slots.All(slot => slot == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
21
Dalamud/Game/Gui/PartyFinder/PartyFinderAddressResolver.cs
Normal file
21
Dalamud/Game/Gui/PartyFinder/PartyFinderAddressResolver.cs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
using System;
|
||||
|
||||
namespace Dalamud.Game.Gui.PartyFinder
|
||||
{
|
||||
/// <summary>
|
||||
/// The address resolver for the <see cref="PartyFinderGui"/> class.
|
||||
/// </summary>
|
||||
public class PartyFinderAddressResolver : BaseAddressResolver
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the address of the native ReceiveListing method.
|
||||
/// </summary>
|
||||
public IntPtr ReceiveListing { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Setup64Bit(SigScanner sig)
|
||||
{
|
||||
this.ReceiveListing = sig.ScanText("40 53 41 57 48 83 EC 28 48 8B D9");
|
||||
}
|
||||
}
|
||||
}
|
||||
133
Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs
Normal file
133
Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using Dalamud.Game.Gui.PartyFinder.Internal;
|
||||
using Dalamud.Game.Gui.PartyFinder.Types;
|
||||
using Dalamud.Hooking;
|
||||
using Serilog;
|
||||
|
||||
namespace Dalamud.Game.Gui.PartyFinder
|
||||
{
|
||||
/// <summary>
|
||||
/// This class handles interacting with the native PartyFinder window.
|
||||
/// </summary>
|
||||
public sealed class PartyFinderGui : IDisposable
|
||||
{
|
||||
private readonly Dalamud dalamud;
|
||||
private readonly PartyFinderAddressResolver address;
|
||||
private readonly IntPtr memory;
|
||||
|
||||
private readonly Hook<ReceiveListingDelegate> receiveListingHook;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PartyFinderGui"/> class.
|
||||
/// </summary>
|
||||
/// <param name="scanner">The SigScanner instance.</param>
|
||||
/// <param name="dalamud">The Dalamud instance.</param>
|
||||
internal PartyFinderGui(SigScanner scanner, Dalamud dalamud)
|
||||
{
|
||||
this.dalamud = dalamud;
|
||||
|
||||
this.address = new PartyFinderAddressResolver();
|
||||
this.address.Setup(scanner);
|
||||
|
||||
this.memory = Marshal.AllocHGlobal(PartyFinderPacket.PacketSize);
|
||||
|
||||
this.receiveListingHook = new Hook<ReceiveListingDelegate>(this.address.ReceiveListing, new ReceiveListingDelegate(this.HandleReceiveListingDetour));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event type fired each time the game receives an individual Party Finder listing.
|
||||
/// Cannot modify listings but can hide them.
|
||||
/// </summary>
|
||||
/// <param name="listing">The listings received.</param>
|
||||
/// <param name="args">Additional arguments passed by the game.</param>
|
||||
public delegate void PartyFinderListingEventDelegate(PartyFinderListing listing, PartyFinderListingEventArgs args);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
|
||||
private delegate void ReceiveListingDelegate(IntPtr managerPtr, IntPtr data);
|
||||
|
||||
/// <summary>
|
||||
/// Event fired each time the game receives an individual Party Finder listing.
|
||||
/// Cannot modify listings but can hide them.
|
||||
/// </summary>
|
||||
public event PartyFinderListingEventDelegate ReceiveListing;
|
||||
|
||||
/// <summary>
|
||||
/// Enables this module.
|
||||
/// </summary>
|
||||
public void Enable()
|
||||
{
|
||||
this.receiveListingHook.Enable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of m anaged and unmanaged resources.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
this.receiveListingHook.Dispose();
|
||||
Marshal.FreeHGlobal(this.memory);
|
||||
}
|
||||
|
||||
private void HandleReceiveListingDetour(IntPtr managerPtr, IntPtr data)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.HandleListingEvents(data);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Exception on ReceiveListing hook.");
|
||||
}
|
||||
|
||||
this.receiveListingHook.Original(managerPtr, data);
|
||||
}
|
||||
|
||||
private void HandleListingEvents(IntPtr data)
|
||||
{
|
||||
var dataPtr = data + 0x10;
|
||||
|
||||
var packet = Marshal.PtrToStructure<PartyFinderPacket>(dataPtr);
|
||||
|
||||
// rewriting is an expensive operation, so only do it if necessary
|
||||
var needToRewrite = false;
|
||||
|
||||
for (var i = 0; i < packet.Listings.Length; i++)
|
||||
{
|
||||
// these are empty slots that are not shown to the player
|
||||
if (packet.Listings[i].IsNull())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var listing = new PartyFinderListing(packet.Listings[i], this.dalamud.Data, this.dalamud.SeStringManager);
|
||||
var args = new PartyFinderListingEventArgs(packet.BatchNumber);
|
||||
this.ReceiveListing?.Invoke(listing, args);
|
||||
|
||||
if (args.Visible)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// hide the listing from the player by setting it to a null listing
|
||||
packet.Listings[i] = default;
|
||||
needToRewrite = true;
|
||||
}
|
||||
|
||||
if (!needToRewrite)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// write our struct into the memory (doing this directly crashes the game)
|
||||
Marshal.StructureToPtr(packet, this.memory, false);
|
||||
|
||||
// copy our new memory over the game's
|
||||
unsafe
|
||||
{
|
||||
Buffer.MemoryCopy((void*)this.memory, (void*)dataPtr, PartyFinderPacket.PacketSize, PartyFinderPacket.PacketSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
48
Dalamud/Game/Gui/PartyFinder/Types/DutyFinderCategory.cs
Normal file
48
Dalamud/Game/Gui/PartyFinder/Types/DutyFinderCategory.cs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
namespace Dalamud.Game.Gui.PartyFinder.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// Category flags for the <see cref="PartyFinder"/> class.
|
||||
/// </summary>
|
||||
public enum DutyFinderCategory
|
||||
{
|
||||
/// <summary>
|
||||
/// The duty category.
|
||||
/// </summary>
|
||||
Duty = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The quest battle category.
|
||||
/// </summary>
|
||||
QuestBattles = 1 << 0,
|
||||
|
||||
/// <summary>
|
||||
/// The fate category.
|
||||
/// </summary>
|
||||
Fates = 1 << 1,
|
||||
|
||||
/// <summary>
|
||||
/// The treasure hunt category.
|
||||
/// </summary>
|
||||
TreasureHunt = 1 << 2,
|
||||
|
||||
/// <summary>
|
||||
/// The hunt category.
|
||||
/// </summary>
|
||||
TheHunt = 1 << 3,
|
||||
|
||||
/// <summary>
|
||||
/// The gathering forays category.
|
||||
/// </summary>
|
||||
GatheringForays = 1 << 4,
|
||||
|
||||
/// <summary>
|
||||
/// The deep dungeons category.
|
||||
/// </summary>
|
||||
DeepDungeons = 1 << 5,
|
||||
|
||||
/// <summary>
|
||||
/// The adventuring forays category.
|
||||
/// </summary>
|
||||
AdventuringForays = 1 << 6,
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
using System;
|
||||
|
||||
namespace Dalamud.Game.Gui.PartyFinder.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// Condition flags for the <see cref="PartyFinder"/> class.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum DutyFinderConditionFlags : uint
|
||||
{
|
||||
/// <summary>
|
||||
/// No duty condition.
|
||||
/// </summary>
|
||||
None = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The duty complete condition.
|
||||
/// </summary>
|
||||
DutyComplete = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The duty incomplete condition.
|
||||
/// </summary>
|
||||
DutyIncomplete = 4,
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
using System;
|
||||
|
||||
namespace Dalamud.Game.Gui.PartyFinder.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// Loot rule flags for the <see cref="PartyFinder"/> class.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum DutyFinderLootRuleFlags : uint
|
||||
{
|
||||
/// <summary>
|
||||
/// No loot rules.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The greed only rule.
|
||||
/// </summary>
|
||||
GreedOnly = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The lootmaster rule.
|
||||
/// </summary>
|
||||
Lootmaster = 2,
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
|
||||
namespace Dalamud.Game.Gui.PartyFinder.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// Objective flags for the <see cref="PartyFinder"/> class.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum DutyFinderObjectiveFlags : uint
|
||||
{
|
||||
/// <summary>
|
||||
/// No objective.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The duty completion objective.
|
||||
/// </summary>
|
||||
DutyCompletion = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The practice objective.
|
||||
/// </summary>
|
||||
Practice = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The loot objective.
|
||||
/// </summary>
|
||||
Loot = 4,
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
using System;
|
||||
|
||||
namespace Dalamud.Game.Gui.PartyFinder.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// Search area flags for the <see cref="PartyFinder"/> class.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum DutyFinderSearchAreaFlags : uint
|
||||
{
|
||||
/// <summary>
|
||||
/// Datacenter.
|
||||
/// </summary>
|
||||
DataCentre = 1 << 0,
|
||||
|
||||
/// <summary>
|
||||
/// Private.
|
||||
/// </summary>
|
||||
Private = 1 << 1,
|
||||
|
||||
/// <summary>
|
||||
/// Alliance raid.
|
||||
/// </summary>
|
||||
AllianceRaid = 1 << 2,
|
||||
|
||||
/// <summary>
|
||||
/// World.
|
||||
/// </summary>
|
||||
World = 1 << 3,
|
||||
|
||||
/// <summary>
|
||||
/// One player per job.
|
||||
/// </summary>
|
||||
OnePlayerPerJob = 1 << 5,
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
|
||||
namespace Dalamud.Game.Gui.PartyFinder.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// Duty finder settings flags for the <see cref="PartyFinder"/> class.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum DutyFinderSettingsFlags : uint
|
||||
{
|
||||
/// <summary>
|
||||
/// No duty finder settings.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The undersized party setting.
|
||||
/// </summary>
|
||||
UndersizedParty = 1 << 0,
|
||||
|
||||
/// <summary>
|
||||
/// The minimum item level setting.
|
||||
/// </summary>
|
||||
MinimumItemLevel = 1 << 1,
|
||||
|
||||
/// <summary>
|
||||
/// The silence echo setting.
|
||||
/// </summary>
|
||||
SilenceEcho = 1 << 2,
|
||||
}
|
||||
}
|
||||
23
Dalamud/Game/Gui/PartyFinder/Types/DutyType.cs
Normal file
23
Dalamud/Game/Gui/PartyFinder/Types/DutyType.cs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
namespace Dalamud.Game.Gui.PartyFinder.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// Duty type flags for the <see cref="PartyFinder"/> class.
|
||||
/// </summary>
|
||||
public enum DutyType
|
||||
{
|
||||
/// <summary>
|
||||
/// No duty type.
|
||||
/// </summary>
|
||||
Other = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The roulette duty type.
|
||||
/// </summary>
|
||||
Roulette = 1 << 0,
|
||||
|
||||
/// <summary>
|
||||
/// The normal duty type.
|
||||
/// </summary>
|
||||
Normal = 1 << 1,
|
||||
}
|
||||
}
|
||||
146
Dalamud/Game/Gui/PartyFinder/Types/JobFlags.cs
Normal file
146
Dalamud/Game/Gui/PartyFinder/Types/JobFlags.cs
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
using System;
|
||||
|
||||
namespace Dalamud.Game.Gui.PartyFinder.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// Job flags for the <see cref="PartyFinder"/> class.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum JobFlags
|
||||
{
|
||||
/// <summary>
|
||||
/// Gladiator (GLD).
|
||||
/// </summary>
|
||||
Gladiator = 1 << 1,
|
||||
|
||||
/// <summary>
|
||||
/// Pugilist (PGL).
|
||||
/// </summary>
|
||||
Pugilist = 1 << 2,
|
||||
|
||||
/// <summary>
|
||||
/// Marauder (MRD).
|
||||
/// </summary>
|
||||
Marauder = 1 << 3,
|
||||
|
||||
/// <summary>
|
||||
/// Lancer (LNC).
|
||||
/// </summary>
|
||||
Lancer = 1 << 4,
|
||||
|
||||
/// <summary>
|
||||
/// Archer (ARC).
|
||||
/// </summary>
|
||||
Archer = 1 << 5,
|
||||
|
||||
/// <summary>
|
||||
/// Conjurer (CNJ).
|
||||
/// </summary>
|
||||
Conjurer = 1 << 6,
|
||||
|
||||
/// <summary>
|
||||
/// Thaumaturge (THM).
|
||||
/// </summary>
|
||||
Thaumaturge = 1 << 7,
|
||||
|
||||
/// <summary>
|
||||
/// Paladin (PLD).
|
||||
/// </summary>
|
||||
Paladin = 1 << 8,
|
||||
|
||||
/// <summary>
|
||||
/// Monk (MNK).
|
||||
/// </summary>
|
||||
Monk = 1 << 9,
|
||||
|
||||
/// <summary>
|
||||
/// Warrior (WAR).
|
||||
/// </summary>
|
||||
Warrior = 1 << 10,
|
||||
|
||||
/// <summary>
|
||||
/// Dragoon (DRG).
|
||||
/// </summary>
|
||||
Dragoon = 1 << 11,
|
||||
|
||||
/// <summary>
|
||||
/// Bard (BRD).
|
||||
/// </summary>
|
||||
Bard = 1 << 12,
|
||||
|
||||
/// <summary>
|
||||
/// White mage (WHM).
|
||||
/// </summary>
|
||||
WhiteMage = 1 << 13,
|
||||
|
||||
/// <summary>
|
||||
/// Black mage (BLM).
|
||||
/// </summary>
|
||||
BlackMage = 1 << 14,
|
||||
|
||||
/// <summary>
|
||||
/// Arcanist (ACN).
|
||||
/// </summary>
|
||||
Arcanist = 1 << 15,
|
||||
|
||||
/// <summary>
|
||||
/// Summoner (SMN).
|
||||
/// </summary>
|
||||
Summoner = 1 << 16,
|
||||
|
||||
/// <summary>
|
||||
/// Scholar (SCH).
|
||||
/// </summary>
|
||||
Scholar = 1 << 17,
|
||||
|
||||
/// <summary>
|
||||
/// Rogue (ROG).
|
||||
/// </summary>
|
||||
Rogue = 1 << 18,
|
||||
|
||||
/// <summary>
|
||||
/// Ninja (NIN).
|
||||
/// </summary>
|
||||
Ninja = 1 << 19,
|
||||
|
||||
/// <summary>
|
||||
/// Machinist (MCH).
|
||||
/// </summary>
|
||||
Machinist = 1 << 20,
|
||||
|
||||
/// <summary>
|
||||
/// Dark Knight (DRK).
|
||||
/// </summary>
|
||||
DarkKnight = 1 << 21,
|
||||
|
||||
/// <summary>
|
||||
/// Astrologian (AST).
|
||||
/// </summary>
|
||||
Astrologian = 1 << 22,
|
||||
|
||||
/// <summary>
|
||||
/// Samurai (SAM).
|
||||
/// </summary>
|
||||
Samurai = 1 << 23,
|
||||
|
||||
/// <summary>
|
||||
/// Red mage (RDM).
|
||||
/// </summary>
|
||||
RedMage = 1 << 24,
|
||||
|
||||
/// <summary>
|
||||
/// Blue mage (BLM).
|
||||
/// </summary>
|
||||
BlueMage = 1 << 25,
|
||||
|
||||
/// <summary>
|
||||
/// Gunbreaker (GNB).
|
||||
/// </summary>
|
||||
Gunbreaker = 1 << 26,
|
||||
|
||||
/// <summary>
|
||||
/// Dancer (DNC).
|
||||
/// </summary>
|
||||
Dancer = 1 << 27,
|
||||
}
|
||||
}
|
||||
27
Dalamud/Game/Gui/PartyFinder/Types/JobFlagsExtensions.cs
Normal file
27
Dalamud/Game/Gui/PartyFinder/Types/JobFlagsExtensions.cs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
using System;
|
||||
|
||||
using Dalamud.Data;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
|
||||
namespace Dalamud.Game.Gui.PartyFinder.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// Extensions for the <see cref="JobFlags"/> enum.
|
||||
/// </summary>
|
||||
public static class JobFlagsExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the actual ClassJob from the in-game sheets for this JobFlags.
|
||||
/// </summary>
|
||||
/// <param name="job">A JobFlags enum member.</param>
|
||||
/// <param name="data">A DataManager to get the ClassJob from.</param>
|
||||
/// <returns>A ClassJob if found or null if not.</returns>
|
||||
public static ClassJob ClassJob(this JobFlags job, DataManager data)
|
||||
{
|
||||
var result = Math.Log2((double)job);
|
||||
return result % 1 == 0
|
||||
? data.GetExcelSheet<ClassJob>().GetRow((uint)result)
|
||||
: null;
|
||||
}
|
||||
}
|
||||
}
|
||||
231
Dalamud/Game/Gui/PartyFinder/Types/PartyFinderListing.cs
Normal file
231
Dalamud/Game/Gui/PartyFinder/Types/PartyFinderListing.cs
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using Dalamud.Data;
|
||||
using Dalamud.Game.Gui.PartyFinder.Internal;
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
|
||||
namespace Dalamud.Game.Gui.PartyFinder.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// A single listing in party finder.
|
||||
/// </summary>
|
||||
public class PartyFinderListing
|
||||
{
|
||||
#region Backing fields
|
||||
|
||||
private readonly byte objective;
|
||||
private readonly byte conditions;
|
||||
private readonly byte dutyFinderSettings;
|
||||
private readonly byte lootRules;
|
||||
private readonly byte searchArea;
|
||||
private readonly PartyFinderSlot[] slots;
|
||||
private readonly byte[] jobsPresent;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PartyFinderListing"/> class.
|
||||
/// </summary>
|
||||
/// <param name="listing">The interop listing data.</param>
|
||||
/// <param name="dataManager">The DataManager instance.</param>
|
||||
/// <param name="seStringManager">The SeStringManager instance.</param>
|
||||
internal PartyFinderListing(PartyFinderPacketListing listing, DataManager dataManager, SeStringManager seStringManager)
|
||||
{
|
||||
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.Id = listing.Id;
|
||||
this.ContentIdLower = listing.ContentIdLower;
|
||||
this.Name = seStringManager.Parse(listing.Name.TakeWhile(b => b != 0).ToArray());
|
||||
this.Description = seStringManager.Parse(listing.Description.TakeWhile(b => b != 0).ToArray());
|
||||
this.World = new Lazy<World>(() => dataManager.GetExcelSheet<World>().GetRow(listing.World));
|
||||
this.HomeWorld = new Lazy<World>(() => dataManager.GetExcelSheet<World>().GetRow(listing.HomeWorld));
|
||||
this.CurrentWorld = new Lazy<World>(() => dataManager.GetExcelSheet<World>().GetRow(listing.CurrentWorld));
|
||||
this.Category = (DutyFinderCategory)listing.Category;
|
||||
this.RawDuty = listing.Duty;
|
||||
this.Duty = new Lazy<ContentFinderCondition>(() => dataManager.GetExcelSheet<ContentFinderCondition>().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.JobsPresent = listing.JobsPresent
|
||||
.Select(id => new Lazy<ClassJob>(
|
||||
() => id == 0
|
||||
? null
|
||||
: dataManager.GetExcelSheet<ClassJob>().GetRow(id)))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ID assigned to this listing by the game's server.
|
||||
/// </summary>
|
||||
public uint Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the lower bits of the player's content ID.
|
||||
/// </summary>
|
||||
public uint ContentIdLower { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the player hosting this listing.
|
||||
/// </summary>
|
||||
public SeString Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the description of this listing as set by the host. May be multiple lines.
|
||||
/// </summary>
|
||||
public SeString Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the world that this listing was created on.
|
||||
/// </summary>
|
||||
public Lazy<World> World { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the home world of the listing's host.
|
||||
/// </summary>
|
||||
public Lazy<World> HomeWorld { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current world of the listing's host.
|
||||
/// </summary>
|
||||
public Lazy<World> CurrentWorld { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Party Finder category this listing is listed under.
|
||||
/// </summary>
|
||||
public DutyFinderCategory Category { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the row ID of the duty this listing is for. May be 0 for non-duty listings.
|
||||
/// </summary>
|
||||
public ushort RawDuty { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the duty this listing is for. May be null for non-duty listings.
|
||||
/// </summary>
|
||||
public Lazy<ContentFinderCondition> Duty { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of duty this listing is for.
|
||||
/// </summary>
|
||||
public DutyType DutyType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether if this listing is beginner-friendly. Shown with a sprout icon in-game.
|
||||
/// </summary>
|
||||
public bool BeginnersWelcome { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets how many seconds this listing will continue to be available for. It may end before this time if the party
|
||||
/// fills or the host ends it early.
|
||||
/// </summary>
|
||||
public ushort SecondsRemaining { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the minimum item level required to join this listing.
|
||||
/// </summary>
|
||||
public ushort MinimumItemLevel { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of parties this listing is recruiting for.
|
||||
/// </summary>
|
||||
public byte Parties { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of player slots this listing is recruiting for.
|
||||
/// </summary>
|
||||
public byte SlotsAvailable { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of player slots that the Party Finder is accepting.
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<PartyFinderSlot> Slots => this.slots;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the objective of this listing.
|
||||
/// </summary>
|
||||
public DutyFinderObjectiveFlags Objective => (DutyFinderObjectiveFlags)this.objective;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the conditions of this listing.
|
||||
/// </summary>
|
||||
public DutyFinderConditionFlags Conditions => (DutyFinderConditionFlags)this.conditions;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Duty Finder settings that will be used for this listing.
|
||||
/// </summary>
|
||||
public DutyFinderSettingsFlags DutyFinderSettings => (DutyFinderSettingsFlags)this.dutyFinderSettings;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the loot rules that will be used for this listing.
|
||||
/// </summary>
|
||||
public DutyFinderLootRuleFlags LootRules => (DutyFinderLootRuleFlags)this.lootRules;
|
||||
|
||||
/// <summary>
|
||||
/// Gets where this listing is searching. Note that this is also used for denoting alliance raid listings and one
|
||||
/// player per job.
|
||||
/// </summary>
|
||||
public DutyFinderSearchAreaFlags SearchArea => (DutyFinderSearchAreaFlags)this.searchArea;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of the class/job IDs that are currently present in the party.
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<byte> RawJobsPresent => this.jobsPresent;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of the classes/jobs that are currently present in the party.
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<Lazy<ClassJob>> JobsPresent { get; }
|
||||
|
||||
#region Indexers
|
||||
|
||||
/// <summary>
|
||||
/// Check if the given flag is present.
|
||||
/// </summary>
|
||||
/// <param name="flag">The flag to check for.</param>
|
||||
/// <returns>A value indicating whether the flag is present.</returns>
|
||||
public bool this[DutyFinderObjectiveFlags flag] => this.objective == 0 || (this.objective & (uint)flag) > 0;
|
||||
|
||||
/// <summary>
|
||||
/// Check if the given flag is present.
|
||||
/// </summary>
|
||||
/// <param name="flag">The flag to check for.</param>
|
||||
/// <returns>A value indicating whether the flag is present.</returns>
|
||||
public bool this[DutyFinderConditionFlags flag] => this.conditions == 0 || (this.conditions & (uint)flag) > 0;
|
||||
|
||||
/// <summary>
|
||||
/// Check if the given flag is present.
|
||||
/// </summary>
|
||||
/// <param name="flag">The flag to check for.</param>
|
||||
/// <returns>A value indicating whether the flag is present.</returns>
|
||||
public bool this[DutyFinderSettingsFlags flag] => this.dutyFinderSettings == 0 || (this.dutyFinderSettings & (uint)flag) > 0;
|
||||
|
||||
/// <summary>
|
||||
/// Check if the given flag is present.
|
||||
/// </summary>
|
||||
/// <param name="flag">The flag to check for.</param>
|
||||
/// <returns>A value indicating whether the flag is present.</returns>
|
||||
public bool this[DutyFinderLootRuleFlags flag] => this.lootRules == 0 || (this.lootRules & (uint)flag) > 0;
|
||||
|
||||
/// <summary>
|
||||
/// Check if the given flag is present.
|
||||
/// </summary>
|
||||
/// <param name="flag">The flag to check for.</param>
|
||||
/// <returns>A value indicating whether the flag is present.</returns>
|
||||
public bool this[DutyFinderSearchAreaFlags flag] => this.searchArea == 0 || (this.searchArea & (uint)flag) > 0;
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
namespace Dalamud.Game.Gui.PartyFinder.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// This class represents additional arguments passed by the game.
|
||||
/// </summary>
|
||||
public class PartyFinderListingEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PartyFinderListingEventArgs"/> class.
|
||||
/// </summary>
|
||||
/// <param name="batchNumber">The batch number.</param>
|
||||
internal PartyFinderListingEventArgs(int batchNumber)
|
||||
{
|
||||
this.BatchNumber = batchNumber;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the batch number.
|
||||
/// </summary>
|
||||
public int BatchNumber { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the listing is visible.
|
||||
/// </summary>
|
||||
public bool Visible { get; set; } = true;
|
||||
}
|
||||
}
|
||||
51
Dalamud/Game/Gui/PartyFinder/Types/PartyFinderSlot.cs
Normal file
51
Dalamud/Game/Gui/PartyFinder/Types/PartyFinderSlot.cs
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Dalamud.Game.Gui.PartyFinder.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// A player slot in a Party Finder listing.
|
||||
/// </summary>
|
||||
public class PartyFinderSlot
|
||||
{
|
||||
private readonly uint accepting;
|
||||
private JobFlags[] listAccepting;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PartyFinderSlot"/> class.
|
||||
/// </summary>
|
||||
/// <param name="accepting">The flag value of accepted jobs.</param>
|
||||
internal PartyFinderSlot(uint accepting)
|
||||
{
|
||||
this.accepting = accepting;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of jobs that this slot is accepting.
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<JobFlags> Accepting
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.listAccepting != null)
|
||||
{
|
||||
return this.listAccepting;
|
||||
}
|
||||
|
||||
this.listAccepting = Enum.GetValues(typeof(JobFlags))
|
||||
.Cast<JobFlags>()
|
||||
.Where(flag => this[flag])
|
||||
.ToArray();
|
||||
|
||||
return this.listAccepting;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests if this slot is accepting a job.
|
||||
/// </summary>
|
||||
/// <param name="flag">Job to test.</param>
|
||||
public bool this[JobFlags flag] => (this.accepting & (uint)flag) > 0;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue