126 lines
4.1 KiB
C#
Executable File
126 lines
4.1 KiB
C#
Executable File
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<PfPacket>();
|
|
}
|
|
|
|
[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<byte> 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);
|
|
}
|
|
}
|
|
}
|