Skip to content

Commit

Permalink
Merge branch 'main' into cn
Browse files Browse the repository at this point in the history
  • Loading branch information
wozaiha committed Apr 9, 2024
2 parents 90d08c8 + 98c1de8 commit b8b8dd0
Show file tree
Hide file tree
Showing 63 changed files with 44,627 additions and 25,107 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
using System.Collections.Immutable;
using FFXIVClientStructs.InteropGenerator;
using FFXIVClientStructs.InteropSourceGenerators.Extensions;
using FFXIVClientStructs.InteropSourceGenerators.Models;
using LanguageExt;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace FFXIVClientStructs.InteropSourceGenerators;

[Generator]
public class InfoProxyInstanceGenerator : IIncrementalGenerator {
private const string InfoProxyAttributeName = "FFXIVClientStructs.Attributes.InfoProxyAttribute";

public void Initialize(IncrementalGeneratorInitializationContext context) {
IncrementalValuesProvider<(Validation<DiagnosticInfo, StructInfo> StructInfo,
Validation<DiagnosticInfo, InfoProxyInfo> InfoProxyInfo)> structAndInfoProxyInfos =
context.SyntaxProvider
.ForAttributeWithMetadataName(
InfoProxyAttributeName,
static (node, _) => node is StructDeclarationSyntax {
AttributeLists.Count: > 0
},
static (context, _) => {
StructDeclarationSyntax structSyntax = (StructDeclarationSyntax)context.TargetNode;
INamedTypeSymbol symbol = (INamedTypeSymbol)context.TargetSymbol;
return (Struct: StructInfo.GetFromSyntax(structSyntax),
Info: InfoProxyInfo.GetFromRoslyn(structSyntax, symbol));
});

// make sure caching is working
IncrementalValuesProvider<Validation<DiagnosticInfo, StructWithInfoProxyInfos>> structsWithInfoProxyInfos =
structAndInfoProxyInfos.Select(static (item, _) =>
(item.StructInfo, item.InfoProxyInfo).Apply(static (si, ai) =>
new StructWithInfoProxyInfos(si, ai))
);

context.RegisterSourceOutput(structsWithInfoProxyInfos, (sourceContext, item) => {
item.Match(
Fail: diagnosticInfos => {
diagnosticInfos.Iter(dInfo => sourceContext.ReportDiagnostic(dInfo.ToDiagnostic()));
},
Succ: structWithInfoProxyInfos => {
sourceContext.AddSource(structWithInfoProxyInfos.GetFileName(), structWithInfoProxyInfos.RenderSource());
});
});

IncrementalValueProvider<ImmutableArray<Validation<DiagnosticInfo, StructWithInfoProxyInfos>>>
collectedStructs = structsWithInfoProxyInfos.Collect();

context.RegisterSourceOutput(collectedStructs,
(sourceContext, structs) => {
sourceContext.AddSource("InfoModule.InfoProxyGetter.g.cs", BuildInfoProxyGettersSource(structs));
});
}
private static string BuildInfoProxyGettersSource(
ImmutableArray<Validation<DiagnosticInfo, StructWithInfoProxyInfos>> structInfos) {
IndentedStringBuilder builder = new();

builder.AppendLine("// <auto-generated/>");
builder.AppendLine();

builder.AppendLine("namespace FFXIVClientStructs.FFXIV.Client.UI.Info;");
builder.AppendLine();

builder.AppendLine("public unsafe partial struct InfoModule");
builder.AppendLine("{");
builder.Indent();

structInfos.Iter(siv =>
siv.IfSuccess(structWithInfoProxyInfos => structWithInfoProxyInfos.RenderInfoProxyGetter(builder)));

builder.DecrementIndent();
builder.AppendLine("}");

return builder.ToString();
}

internal sealed record InfoProxyInfo(StructInfo StructInfo, uint InfoProxyId) {
public static Validation<DiagnosticInfo, InfoProxyInfo> GetFromRoslyn(
StructDeclarationSyntax structSyntax, INamedTypeSymbol namedTypeSymbol) {
Validation<DiagnosticInfo, StructInfo> validStructInfo =
StructInfo.GetFromSyntax(structSyntax);

Option<AttributeData> infoProxyAttribute = namedTypeSymbol.GetFirstAttributeDataByTypeName(InfoProxyAttributeName);

Validation<DiagnosticInfo, uint> validInfoProxyId =
infoProxyAttribute.GetValidAttributeArgument<uint>("ID", 0, InfoProxyAttributeName, namedTypeSymbol);

return (validStructInfo, validInfoProxyId: validInfoProxyId).Apply((structInfo, infoProxyId) =>
new InfoProxyInfo(structInfo, infoProxyId));
}
}

private sealed record StructWithInfoProxyInfos
(StructInfo StructInfo, InfoProxyInfo InfoProxyInfo) {
public string RenderSource() {
IndentedStringBuilder builder = new();

StructInfo.RenderStart(builder);

builder.AppendLine();
builder.AppendLine($"public static {StructInfo.Name}* Instance() => ({StructInfo.Name}*)InfoModule.Instance()->GetInfoProxyById((uint){InfoProxyInfo.InfoProxyId});");
builder.AppendLine();

StructInfo.RenderEnd(builder);

return builder.ToString();
}

public string GetFileName() {
return $"{StructInfo.Name}.InstanceGetter.g.cs";
}

public void RenderInfoProxyGetter(IndentedStringBuilder builder) {
builder.AppendLine($"public {StructInfo.Name}* Get{StructInfo.Name}() => ({StructInfo.Name}*)GetInfoProxyById((uint){InfoProxyInfo.InfoProxyId});");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public bool IsGPoseWet {
[MemberFunction("E8 ?? ?? ?? ?? 48 85 C0 48 0F 45 F8")]
public partial Character* GetParentCharacter();

/// <summary> Uses TransformationId, Clan, BodyType, Gender and Height as well as RSP scaling values to calculate current height. </summary>
/// <summary> Uses TransformationId, Tribe, BodyType, Sex and Height as well as RSP scaling values to calculate current height. </summary>
[MemberFunction("E8 ?? ?? ?? ?? F3 0F 59 C7 48 8B CE")]
public partial float CalculateHeight();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,21 +123,62 @@ public unsafe partial struct CustomizeData {
private const int Count = 0x1A;

[FieldOffset(0x00)] public fixed byte Data[Count];

[FieldOffset(0x00)] public byte Race;
[FieldOffset(0x01)] public byte Sex;
[FieldOffset(0x02)] public byte BodyType;
[FieldOffset(0x03)] public byte Height;
[FieldOffset(0x04)] public byte Tribe;
[Obsolete("Renamed to Tribe")]
[FieldOffset(0x04)] public byte Clan;
[FieldOffset(0x05)] public byte Face;
[FieldOffset(0x06)] public byte Hairstyle;
// 0x07: Highlights
[FieldOffset(0x08)] public byte SkinColor;
[FieldOffset(0x09)] public byte EyeColorRight;
[FieldOffset(0x0A)] public byte HairColor;
[FieldOffset(0x0B)] public byte HighlightsColor;
// 0x0C: FacialFeature1-7, LegacyTattoo
[FieldOffset(0x0D)] public byte TattooColor;
[FieldOffset(0x0E)] public byte Eyebrows;
[FieldOffset(0x0F)] public byte EyeColorLeft;
// 0x10: EyeShape, SmallIris
[FieldOffset(0x11)] public byte Nose;
[FieldOffset(0x12)] public byte Jaw;
// 0x13: Mouth, Lipstick
[FieldOffset(0x14)] public byte LipColorFurPattern;
[FieldOffset(0x15)] public byte MuscleMass;
[FieldOffset(0x16)] public byte TailShape;
[FieldOffset(0x17)] public byte BustSize;
// 0x18: FacePaint, FacePaintReversed
[FieldOffset(0x19)] public byte FacePaintColor;

public bool Highlights => (byte)(Data[0x07] & 0b_1000_0000) != 0;

public bool FacialFeature1 => (byte)(Data[0x0C] & 0b_0000_0001) != 0;
public bool FacialFeature2 => (byte)(Data[0x0C] & 0b_0000_0010) != 0;
public bool FacialFeature3 => (byte)(Data[0x0C] & 0b_0000_0100) != 0;
public bool FacialFeature4 => (byte)(Data[0x0C] & 0b_0000_1000) != 0;
public bool FacialFeature5 => (byte)(Data[0x0C] & 0b_0001_0000) != 0;
public bool FacialFeature6 => (byte)(Data[0x0C] & 0b_0010_0000) != 0;
public bool FacialFeature7 => (byte)(Data[0x0C] & 0b_0100_0000) != 0;
public bool LegacyTattoo => (byte)(Data[0x0C] & 0b_1000_0000) != 0;

public byte EyeShape => (byte)(Data[0x10] & 0b_0111_1111);
public bool SmallIris => (byte)(Data[0x10] & 0b_1000_0000) != 0;

public byte this[int idx]
=> Data[idx];
public byte Mouth => (byte)(Data[0x13] & 0b_0111_1111);
public bool Lipstick => (byte)(Data[0x13] & 0b_1000_0000) != 0;

public byte FacePaint => (byte)(Data[0x18] & 0b_0111_1111);
public bool FacePaintReversed => (byte)(Data[0x18] & 0b_1000_0000) != 0;

public byte this[int idx] => Data[idx];

[MemberFunction("E8 ?? ?? ?? ?? 33 DB 48 8D 75")]
public partial bool NormalizeCustomizeData(CustomizeData* source);
}



[StructLayout(LayoutKind.Explicit, Size = 8)]
public struct WeaponModelId {
[FieldOffset(0)] public ushort Id;
Expand Down
3 changes: 3 additions & 0 deletions FFXIVClientStructs/FFXIV/Client/Game/Control/Control.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,7 @@ public unsafe partial struct Control {

[StaticAddress("4C 8D 35 ?? ?? ?? ?? 85 D2", 3)]
public static partial Control* Instance();

[StaticAddress("48 89 05 ?? ?? ?? ?? 48 8B 49 08", 3, true)]
public static partial BattleChara* GetLocalPlayer(); // g_Client::Game::Control::Control_LocalPlayer
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using FFXIVClientStructs.FFXIV.Client.Game.UI;
using FFXIVClientStructs.FFXIV.Client.System.String;

namespace FFXIVClientStructs.FFXIV.Client.Game.InstanceContent;

// Client::Game::InstanceContent::PublicContentBozja
// Client::Game::InstanceContent::PublicContentDirector
// Client::Game::InstanceContent::ContentDirector
// Client::Game::Event::Director
// Client::Game::Event::LuaEventHandler
// Client::Game::Event::EventHandler
[StructLayout(LayoutKind.Explicit, Size = 0x2CB8)]
public struct PublicContentBozja {
[FieldOffset(0x00)] public PublicContentDirector PublicContentDirector;

[FieldOffset(0x1098)] public DynamicEventContainer DynamicEventContainer;

[FieldOffset(0x2BC0)] public uint CurrentExperience; // Mettle
[FieldOffset(0x2BC4)] public uint NeededExperience;
}

// Client::Game::InstanceContent::DynamicEventContainer
// Client::Game::InstanceContent::ContentSheetWaiterInterface
[StructLayout(LayoutKind.Explicit, Size = 0x1B28)]
public unsafe partial struct DynamicEventContainer {
[FixedSizeArray<DynamicEvent>(16)]
[FieldOffset(0x08)] public fixed byte Events[0x1B0 * 16];
}

// Client::Game::InstanceContent::DynamicEvent
// Common::Component::Excel::ExcelSheetWaiter
[StructLayout(LayoutKind.Explicit, Size = 0x1B0)]
public unsafe partial struct DynamicEvent {
// [FieldOffset(0)] public ExcelSheetWaiter ExcelSheetWaiter;
[FieldOffset(0x38)] public uint LGBEventObject;
[FieldOffset(0x3C)] public uint LGBMapRange;
[FieldOffset(0x40)] public uint Quest; // RowId of Quest Sheet
[FieldOffset(0x44)] public uint Announce; // RowId of LogMessage Sheet
[FieldOffset(0x48)] public ushort Unknown0;
[FieldOffset(0x4A)] public ushort Unknown1;
[FieldOffset(0x4C)] public ushort Unknown2;
[FieldOffset(0x4E)] public byte EventType; // RowId of DynamicEventType Sheet
[FieldOffset(0x4F)] public byte EnemyType; // RowId of DynamicEventEnemyType Sheet
[FieldOffset(0x50)] public byte MaxParticipants;
[FieldOffset(0x51)] public byte Unknown4;
[FieldOffset(0x52)] public byte Unknown5;
[FieldOffset(0x54)] public uint StartTimestamp;
[FieldOffset(0x58)] public uint SecondsLeft;
[FieldOffset(0x5C)] public uint SecondsDuration;

[FieldOffset(0x63)] public DynamicEventState State;

[FieldOffset(0x65)] public byte Participants;
[FieldOffset(0x66)] public byte Progress;

[FieldOffset(0x53)] public byte SingleBattle; // RowId of DynamicEventSingleBattle Sheet
[FieldOffset(0x68)] public Utf8String Name;
[FieldOffset(0xD0)] public Utf8String Description;
[FieldOffset(0x138)] public uint IconObjective0;
[FieldOffset(0x13C)] public byte MaxParticipants2;
[FieldOffset(0x158)] public MapMarkerData MapMarker;
}

public enum DynamicEventState : byte {
Inactive = 0,
Register = 1,
Warmup = 2,
Battle = 3
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using FFXIVClientStructs.FFXIV.Client.System.String;

namespace FFXIVClientStructs.FFXIV.Client.Game.InstanceContent;

// Client::Game::InstanceContent::PublicContentEureka
// Client::Game::InstanceContent::PublicContentDirector
// Client::Game::InstanceContent::ContentDirector
// Client::Game::Event::Director
// Client::Game::Event::LuaEventHandler
// Client::Game::Event::EventHandler
[StructLayout(LayoutKind.Explicit, Size = 0x12C8)]
public unsafe partial struct PublicContentEureka {
[FieldOffset(0x00)] public PublicContentDirector PublicContentDirector;
[FieldOffset(0x1090)] public ushort Unk1090; // if set, prints log message 9068 in chat ("Character progression enhancement will be applied to all participants in this duty.")
[FieldOffset(0x1092)] public ushort Unk1092; // if set, prints log message 4217 in chat ("To facilitate the successful completion of this duty, you have been granted the power of the Echo.")
[FieldOffset(0x1094)] public byte MaxElementalLevel; // if set, prints log message 9067 in chat ("If your elemental level is above <value>, it will be synced.")

[FieldOffset(0x1098)] public uint CurrentExperience;
[FieldOffset(0x109C)] public uint NeededExperience;
[FieldOffset(0x10A0)] public ushort MagiaAetherCharge;
[FieldOffset(0x10A2)] public byte Fire;
[FieldOffset(0x10A3)] public byte Ice;
[FieldOffset(0x10A4)] public byte Wind;
[FieldOffset(0x10A5)] public byte Earth;
[FieldOffset(0x10A6)] public byte Lightning;
[FieldOffset(0x10A7)] public byte Water;
[FieldOffset(0x10A8)] public byte Magicite;
[FieldOffset(0x10A9)] public byte MagiaAether;

[FixedSizeArray<Utf8String>(4)]
[FieldOffset(0x10B0)] public fixed byte PublicContentTextDataStrings[0x68 * 4]; // starting at row 2000
[FieldOffset(0x1250)] public Utf8String Unk1250;
}
2 changes: 2 additions & 0 deletions FFXIVClientStructs/FFXIV/Client/Game/Object/GameObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ public unsafe partial struct GameObject {
[FieldOffset(0x88)] public ushort ObjectIndex; // index in object table
[FieldOffset(0x8C)] public byte ObjectKind;
[FieldOffset(0x8D)] public byte SubKind;
[FieldOffset(0x8E)] public byte Sex;
[Obsolete("Renamed to Sex")]
[FieldOffset(0x8E)] public byte Gender;
[FieldOffset(0x90)] public byte YalmDistanceFromPlayerX;
[FieldOffset(0x91)] public byte TargetStatus; // Goes from 6 to 2 when selecting a target and flashing a highlight
Expand Down
8 changes: 4 additions & 4 deletions FFXIVClientStructs/FFXIV/Client/Game/UI/Buddy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ public bool IsBuddyEquipUnlocked(uint buddyEquipId)
public unsafe partial struct CompanionInfo {
[FieldOffset(0)] public Buddy.BuddyMember* Companion;
[FieldOffset(0x8)] public float TimeLeft;
[FieldOffset(0xC)] private fixed byte BuddyEquipUnlockBitmask[96 >> 3]; // number of BuddyEquip rows >> 3
[FieldOffset(0x18)] private byte BardingHead;
[FieldOffset(0x19)] private byte BardingChest;
[FieldOffset(0x1A)] private byte BardingFeet;
[FieldOffset(0xC)] public fixed byte BuddyEquipUnlockBitmask[96 >> 3]; // number of BuddyEquip rows >> 3
[FieldOffset(0x18)] public byte BardingHead;
[FieldOffset(0x19)] public byte BardingChest;
[FieldOffset(0x1A)] public byte BardingFeet;
[FieldOffset(0x1B), FixedString("Name")] public fixed byte NameBytes[21];
[FieldOffset(0x30)] public uint CurrentXP;
[FieldOffset(0x34)] public byte Rank;
Expand Down
7 changes: 7 additions & 0 deletions FFXIVClientStructs/FFXIV/Client/Game/UI/CharaCard.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace FFXIVClientStructs.FFXIV.Client.Game.UI;

// Client::Game::UI::CharaCard
[StructLayout(LayoutKind.Explicit, Size = 0x1C8)]
public struct CharaCard {

}
7 changes: 7 additions & 0 deletions FFXIVClientStructs/FFXIV/Client/Game/UI/CollectablesShop.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace FFXIVClientStructs.FFXIV.Client.Game.UI;

// Client::Game::UI::CollectablesShop
[StructLayout(LayoutKind.Explicit, Size = 0x2B8)]
public struct CollectablesShop {
// Contains Yo-kai data at the end?
}
10 changes: 10 additions & 0 deletions FFXIVClientStructs/FFXIV/Client/Game/UI/DailyQuestSupply.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using FFXIVClientStructs.FFXIV.Component.GUI;

namespace FFXIVClientStructs.FFXIV.Client.Game.UI;

// Client::Game::UI::DailyQuestSupply
// Component::GUI::AtkModuleInterface::AtkEventInterface
[StructLayout(LayoutKind.Explicit, Size = 0x3E8)]
public unsafe struct DailyQuestSupply {
[FieldOffset(0)] public AtkEventInterface AtkEventInterface;
}
7 changes: 7 additions & 0 deletions FFXIVClientStructs/FFXIV/Client/Game/UI/Emj.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace FFXIVClientStructs.FFXIV.Client.Game.UI;

// Client::Game::UI::Emj
[StructLayout(LayoutKind.Explicit, Size = 0x38)]
public struct Emj {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace FFXIVClientStructs.FFXIV.Client.Game.UI;

// Client::Game::UI::EurekaElementalEdit
[StructLayout(LayoutKind.Explicit, Size = 0x18)]
public struct EurekaElementalEdit {

}
7 changes: 7 additions & 0 deletions FFXIVClientStructs/FFXIV/Client/Game/UI/FishRecord.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace FFXIVClientStructs.FFXIV.Client.Game.UI;

// Client::Game::UI::FishRecord
[StructLayout(LayoutKind.Explicit, Size = 0x2E0)] // presumably shorter
public struct FishRecord {

}
7 changes: 7 additions & 0 deletions FFXIVClientStructs/FFXIV/Client/Game/UI/FishingNote.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace FFXIVClientStructs.FFXIV.Client.Game.UI;

// Client::Game::UI::FishingNote
[StructLayout(LayoutKind.Explicit, Size = 0x50)]
public struct FishingNote {

}
7 changes: 7 additions & 0 deletions FFXIVClientStructs/FFXIV/Client/Game/UI/GCSupply.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace FFXIVClientStructs.FFXIV.Client.Game.UI;

// Client::Game::UI::GCSupply
[StructLayout(LayoutKind.Explicit, Size = 0x2C28)]
public struct GCSupply {

}
Loading

0 comments on commit b8b8dd0

Please sign in to comment.