Merge branch 'master' into feature/sestring-to-texture

This commit is contained in:
goat 2025-12-04 00:57:07 +01:00 committed by GitHub
commit 3fbc24904a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
490 changed files with 8689 additions and 3741 deletions

View file

@ -1,3 +1,4 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
@ -117,9 +118,11 @@ public class AddonLifecycleWidget : IDataWindowWidget
{
ImGui.Columns(2);
var functionAddress = receiveEventListener.FunctionAddress;
ImGui.Text("Hook Address"u8);
ImGui.NextColumn();
ImGui.Text(receiveEventListener.FunctionAddress.ToString("X"));
ImGui.Text($"0x{functionAddress:X} (ffxiv_dx11.exe+{functionAddress - Process.GetCurrentProcess().MainModule!.BaseAddress:X})");
ImGui.NextColumn();
ImGui.Text("Hook Status"u8);

View file

@ -81,11 +81,10 @@ internal unsafe class AtkArrayDataBrowserWidget : IDataWindowWidget
var stringArrayData = (StringArrayData*)arrays[arrayIndex];
for (var rowIndex = 0; rowIndex < arrays[arrayIndex]->Size; rowIndex++)
{
var isNull = (nint)stringArrayData->StringArray[rowIndex] == 0;
if (isNull)
if (!stringArrayData->StringArray[rowIndex].HasValue)
continue;
if (new ReadOnlySeStringSpan(stringArrayData->StringArray[rowIndex]).ExtractText().Contains(this.searchTerm, StringComparison.InvariantCultureIgnoreCase))
if (new ReadOnlySeStringSpan(stringArrayData->StringArray[rowIndex].Value).ExtractText().Contains(this.searchTerm, StringComparison.InvariantCultureIgnoreCase))
rowsFound++;
}
@ -289,7 +288,7 @@ internal unsafe class AtkArrayDataBrowserWidget : IDataWindowWidget
for (var i = 0; i < array->Size; i++)
{
var isNull = (nint)array->StringArray[i] == 0;
var isNull = !array->StringArray[i].HasValue;
if (isNull && this.hideUnsetStringArrayEntries)
continue;
@ -298,7 +297,7 @@ internal unsafe class AtkArrayDataBrowserWidget : IDataWindowWidget
if (isNull)
continue;
if (!new ReadOnlySeStringSpan(array->StringArray[i]).ExtractText().Contains(this.searchTerm, StringComparison.InvariantCultureIgnoreCase))
if (!new ReadOnlySeStringSpan(array->StringArray[i].Value).ExtractText().Contains(this.searchTerm, StringComparison.InvariantCultureIgnoreCase))
continue;
}
@ -312,7 +311,7 @@ internal unsafe class AtkArrayDataBrowserWidget : IDataWindowWidget
if (this.showTextAddress)
{
if (!isNull)
WidgetUtil.DrawCopyableText($"0x{(nint)array->StringArray[i]:X}", "Copy text address");
WidgetUtil.DrawCopyableText($"0x{(nint)array->StringArray[i].Value:X}", "Copy text address");
}
else
{
@ -322,7 +321,7 @@ internal unsafe class AtkArrayDataBrowserWidget : IDataWindowWidget
ImGui.TableNextColumn(); // Managed
if (!isNull)
{
ImGui.Text(((nint)array->StringArray[i] != 0 && array->ManagedStringArray[i] == array->StringArray[i]).ToString());
ImGui.Text((array->StringArray[i].HasValue && array->ManagedStringArray[i].Value == array->StringArray[i]).ToString());
}
ImGui.TableNextColumn(); // Text
@ -330,11 +329,11 @@ internal unsafe class AtkArrayDataBrowserWidget : IDataWindowWidget
{
if (this.showMacroString)
{
WidgetUtil.DrawCopyableText(new ReadOnlySeStringSpan(array->StringArray[i]).ToString(), "Copy text");
WidgetUtil.DrawCopyableText(new ReadOnlySeStringSpan(array->StringArray[i].Value).ToString(), "Copy text");
}
else
{
ImGuiHelpers.SeStringWrapped(new ReadOnlySeStringSpan(array->StringArray[i]));
ImGuiHelpers.SeStringWrapped(new ReadOnlySeStringSpan(array->StringArray[i].Value));
}
}
}

View file

@ -40,7 +40,7 @@ internal class BuddyListWidget : IDataWindowWidget
}
else
{
ImGui.Text($"[Companion] {member.Address.ToInt64():X} - {member.ObjectId} - {member.DataID}");
ImGui.Text($"[Companion] {member.Address.ToInt64():X} - {member.EntityId} - {member.DataID}");
if (this.resolveGameData)
{
var gameObject = member.GameObject;
@ -64,7 +64,7 @@ internal class BuddyListWidget : IDataWindowWidget
}
else
{
ImGui.Text($"[Pet] {member.Address.ToInt64():X} - {member.ObjectId} - {member.DataID}");
ImGui.Text($"[Pet] {member.Address.ToInt64():X} - {member.EntityId} - {member.DataID}");
if (this.resolveGameData)
{
var gameObject = member.GameObject;
@ -91,7 +91,7 @@ internal class BuddyListWidget : IDataWindowWidget
for (var i = 0; i < count; i++)
{
var member = buddyList[i];
ImGui.Text($"[BattleBuddy] [{i}] {member?.Address.ToInt64():X} - {member?.ObjectId} - {member?.DataID}");
ImGui.Text($"[BattleBuddy] [{i}] {member?.Address.ToInt64():X} - {member?.EntityId} - {member?.DataID}");
if (this.resolveGameData)
{
var gameObject = member?.GameObject;

View file

@ -1,7 +1,7 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Game.ClientState;
using Dalamud.Game.ClientState.JobGauge;
using Dalamud.Game.ClientState.JobGauge.Types;
using Dalamud.Game.ClientState.Objects;
using Dalamud.Utility;
namespace Dalamud.Interface.Internal.Windows.Data.Widgets;
@ -29,10 +29,10 @@ internal class GaugeWidget : IDataWindowWidget
/// <inheritdoc/>
public void Draw()
{
var clientState = Service<ClientState>.Get();
var objectTable = Service<ObjectTable>.Get();
var jobGauges = Service<JobGauges>.Get();
var player = clientState.LocalPlayer;
var player = objectTable.LocalPlayer;
if (player == null)
{
ImGui.Text("Player is not present"u8);

View file

@ -4,6 +4,7 @@ using Dalamud.Bindings.ImGui;
using Dalamud.Game.ClientState;
using Dalamud.Game.ClientState.Objects;
using Dalamud.Game.Gui;
using Dalamud.Game.Player;
using Dalamud.Utility;
namespace Dalamud.Interface.Internal.Windows.Data.Widgets;
@ -39,12 +40,13 @@ internal class ObjectTableWidget : IDataWindowWidget
var chatGui = Service<ChatGui>.Get();
var clientState = Service<ClientState>.Get();
var playerState = Service<PlayerState>.Get();
var gameGui = Service<GameGui>.Get();
var objectTable = Service<ObjectTable>.Get();
var stateString = string.Empty;
if (clientState.LocalPlayer == null)
if (objectTable.LocalPlayer == null)
{
ImGui.Text("LocalPlayer null."u8);
}
@ -55,10 +57,10 @@ internal class ObjectTableWidget : IDataWindowWidget
else
{
stateString += $"ObjectTableLen: {objectTable.Length}\n";
stateString += $"LocalPlayerName: {clientState.LocalPlayer.Name}\n";
stateString += $"CurrentWorldName: {(this.resolveGameData ? clientState.LocalPlayer.CurrentWorld.ValueNullable?.Name : clientState.LocalPlayer.CurrentWorld.RowId.ToString())}\n";
stateString += $"HomeWorldName: {(this.resolveGameData ? clientState.LocalPlayer.HomeWorld.ValueNullable?.Name : clientState.LocalPlayer.HomeWorld.RowId.ToString())}\n";
stateString += $"LocalCID: {clientState.LocalContentId:X}\n";
stateString += $"LocalPlayerName: {playerState.CharacterName}\n";
stateString += $"CurrentWorldName: {(this.resolveGameData ? playerState.CurrentWorld.ValueNullable?.Name : playerState.CurrentWorld.RowId.ToString())}\n";
stateString += $"HomeWorldName: {(this.resolveGameData ? playerState.HomeWorld.ValueNullable?.Name : playerState.HomeWorld.RowId.ToString())}\n";
stateString += $"LocalCID: {playerState.ContentId:X}\n";
stateString += $"LastLinkedItem: {chatGui.LastLinkedItemId}\n";
stateString += $"TerritoryType: {clientState.TerritoryType}\n\n";

View file

@ -1,10 +1,10 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Game.ClientState;
using Dalamud.Bindings.ImGui;
using Dalamud.Game.ClientState.Objects;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Plugin.Ipc;
using Dalamud.Plugin.Ipc.Internal;
using Dalamud.Utility;
using Serilog;
namespace Dalamud.Interface.Internal.Windows.Data.Widgets;
@ -111,12 +111,12 @@ internal class PluginIpcWidget : IDataWindowWidget
if (ImGui.Button("Action GO"u8))
{
this.ipcSubGo.InvokeAction(Service<ClientState>.Get().LocalPlayer);
this.ipcSubGo.InvokeAction(Service<ObjectTable>.Get().LocalPlayer);
}
if (ImGui.Button("Func GO"u8))
{
this.callGateResponse = this.ipcSubGo.InvokeFunc(Service<ClientState>.Get().LocalPlayer);
this.callGateResponse = this.ipcSubGo.InvokeFunc(Service<ObjectTable>.Get().LocalPlayer);
}
if (!this.callGateResponse.IsNullOrEmpty())

View file

@ -2,9 +2,9 @@ using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using Dalamud.Bindings.ImGui;
using Dalamud.Configuration.Internal;
using Dalamud.Data;
using Dalamud.Game;
using Dalamud.Game.ClientState;
@ -13,12 +13,13 @@ using Dalamud.Game.Text.Noun.Enums;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
using Dalamud.Memory;
using Dalamud.Utility;
using FFXIVClientStructs.FFXIV.Client.System.String;
using FFXIVClientStructs.FFXIV.Client.UI;
using FFXIVClientStructs.FFXIV.Client.UI.Misc;
using FFXIVClientStructs.FFXIV.Component.Text;
using Lumina.Data;
using Lumina.Data.Files.Excel;
using Lumina.Data.Structs.Excel;
@ -89,6 +90,7 @@ internal class SeStringCreatorWidget : IDataWindowWidget
{ MacroCode.FrNoun, ["SheetName", "ArticleType", "RowId", "Amount", "Case", "UnkInt5"] },
{ MacroCode.ChNoun, ["SheetName", "ArticleType", "RowId", "Amount", "Case", "UnkInt5"] },
{ MacroCode.LowerHead, ["String"] },
{ MacroCode.SheetSub, ["SheetName", "RowId", "SubrowId", "ColumnIndex", "SecondarySheetName", "SecondarySheetColumnIndex"] },
{ MacroCode.ColorType, ["ColorType"] },
{ MacroCode.EdgeColorType, ["ColorType"] },
{ MacroCode.Ruby, ["StandardText", "RubyText"] },
@ -103,13 +105,16 @@ internal class SeStringCreatorWidget : IDataWindowWidget
{ LinkMacroPayloadType.Character, ["Flags", "WorldId"] },
{ LinkMacroPayloadType.Item, ["ItemId", "Rarity"] },
{ LinkMacroPayloadType.MapPosition, ["TerritoryType/MapId", "RawX", "RawY"] },
{ LinkMacroPayloadType.Quest, ["QuestId"] },
{ LinkMacroPayloadType.Achievement, ["AchievementId"] },
{ LinkMacroPayloadType.HowTo, ["HowToId"] },
{ LinkMacroPayloadType.Quest, ["RowId"] },
{ LinkMacroPayloadType.Achievement, ["RowId"] },
{ LinkMacroPayloadType.HowTo, ["RowId"] },
// PartyFinderNotification
{ LinkMacroPayloadType.Status, ["StatusId"] },
{ LinkMacroPayloadType.PartyFinder, ["ListingId", string.Empty, "WorldId"] },
{ LinkMacroPayloadType.AkatsukiNote, ["AkatsukiNoteId"] },
{ LinkMacroPayloadType.AkatsukiNote, ["RowId"] },
{ LinkMacroPayloadType.Description, ["RowId"] },
{ LinkMacroPayloadType.WKSPioneeringTrail, ["RowId", "SubrowId"] },
{ LinkMacroPayloadType.MKDLore, ["RowId"] },
{ DalamudLinkType, ["CommandId", "Extra1", "Extra2", "ExtraString"] },
};
@ -142,6 +147,7 @@ internal class SeStringCreatorWidget : IDataWindowWidget
private SeStringParameter[]? localParameters = [Util.GetScmVersion()];
private ReadOnlySeString input;
private ClientLanguage? language;
private Task? validImportSheetNamesTask;
private int importSelectedSheetName;
private int importRowId;
private string[]? validImportSheetNames;
@ -309,13 +315,13 @@ internal class SeStringCreatorWidget : IDataWindowWidget
ImGui.Text(i switch
{
0 => "Player Name",
1 => "Temp Player 1 Name",
2 => "Temp Player 2 Name",
1 => "Temp Entity 1: Name",
2 => "Temp Entity 2: Name",
3 => "Player Sex",
4 => "Temp Player 1 Sex",
5 => "Temp Player 2 Sex",
6 => "Temp Player 1 Unk 1",
7 => "Temp Player 2 Unk 1",
4 => "Temp Entity 1: Sex",
5 => "Temp Entity 2: Sex",
6 => "Temp Entity 1: ObjStrId",
7 => "Temp Entity 2: ObjStrId",
10 => "Eorzea Time Hours",
11 => "Eorzea Time Minutes",
12 => "ColorSay",
@ -364,14 +370,19 @@ internal class SeStringCreatorWidget : IDataWindowWidget
62 => "ColorLoot",
63 => "ColorCraft",
64 => "ColorGathering",
65 => "Temp Player 1 Unk 2",
66 => "Temp Player 2 Unk 2",
65 => "Temp Entity 1: Name starts with Vowel",
66 => "Temp Entity 2: Name starts with Vowel",
67 => "Player ClassJobId",
68 => "Player Level",
69 => "Player StartTown",
70 => "Player Race",
71 => "Player Synced Level",
77 => "Client/Plattform?",
73 => "Quest#66047: Has met Alphinaud and Alisaie",
74 => "PlayStation Generation",
75 => "Is Legacy Player",
77 => "Client/Platform?",
78 => "Player BirthMonth",
79 => "PadMode",
82 => "Datacenter Region",
83 => "ColorCWLS2",
84 => "ColorCWLS3",
@ -392,6 +403,11 @@ internal class SeStringCreatorWidget : IDataWindowWidget
100 => "LogSetRoleColor 1: LogColorOtherClass",
101 => "LogSetRoleColor 2: LogColorOtherClass",
102 => "Has Login Security Token",
103 => "Is subscribed to PlayStation Plus",
104 => "PadMouseMode",
106 => "Preferred World Bonus Max Level",
107 => "Occult Crescent Support Job Level",
108 => "Deep Dungeon Id",
_ => string.Empty,
});
}
@ -506,7 +522,7 @@ internal class SeStringCreatorWidget : IDataWindowWidget
}
}
ImGui.SetClipboardText(sb.ToReadOnlySeString().ToString());
ImGui.SetClipboardText(sb.ToReadOnlySeString().ToMacroString());
}
ImGui.SameLine();
@ -551,22 +567,31 @@ internal class SeStringCreatorWidget : IDataWindowWidget
var dataManager = Service<DataManager>.Get();
this.validImportSheetNames ??= dataManager.Excel.SheetNames.Where(sheetName =>
this.validImportSheetNamesTask ??= Task.Run(() =>
{
try
this.validImportSheetNames = dataManager.Excel.SheetNames.Where(sheetName =>
{
var headerFile = dataManager.GameData.GetFile<ExcelHeaderFile>($"exd/{sheetName}.exh");
if (headerFile.Header.Variant != ExcelVariant.Default)
return false;
try
{
var headerFile = dataManager.GameData.GetFile<ExcelHeaderFile>($"exd/{sheetName}.exh");
if (headerFile.Header.Variant != ExcelVariant.Default)
return false;
var sheet = dataManager.Excel.GetSheet<RawRow>(Language.English, sheetName);
return sheet.Columns.Any(col => col.Type == ExcelColumnDataType.String);
}
catch
{
return false;
}
}).OrderBy(sheetName => sheetName, StringComparer.InvariantCulture).ToArray();
var sheet = dataManager.Excel.GetSheet<RawRow>(Language.English, sheetName);
return sheet.Columns.Any(col => col.Type == ExcelColumnDataType.String);
}
catch
{
return false;
}
}).OrderBy(sheetName => sheetName, StringComparer.InvariantCulture).ToArray();
});
if (this.validImportSheetNames == null)
{
ImGui.Text("Loading sheets..."u8);
return;
}
var sheetChanged = ImGui.Combo("Sheet Name", ref this.importSelectedSheetName, this.validImportSheetNames);
@ -621,7 +646,7 @@ internal class SeStringCreatorWidget : IDataWindowWidget
ImGui.Text(i.ToString());
ImGui.TableNextColumn();
if (ImGui.Selectable($"{value.ToString().Truncate(100)}###Column{i}"))
if (ImGui.Selectable($"{value.ToMacroString().Truncate(100)}###Column{i}"))
{
foreach (var payload in value)
{
@ -692,7 +717,7 @@ internal class SeStringCreatorWidget : IDataWindowWidget
ImGui.TableNextColumn(); // Text
var message = entry.Message;
ImGui.SetNextItemWidth(-1);
if (ImGui.InputText($"##{i}_Message", ref message, 255))
if (ImGui.InputText($"##{i}_Message", ref message, 2048))
{
entry.Message = message;
updateString |= true;
@ -1065,10 +1090,10 @@ internal class SeStringCreatorWidget : IDataWindowWidget
break;
case LinkMacroPayloadType.AkatsukiNote when
dataManager.GetSubrowExcelSheet<AkatsukiNote>(this.language).TryGetRow(u32, out var akatsukiNoteRow) &&
dataManager.GetExcelSheet<AkatsukiNoteString>(this.language).TryGetRow((uint)akatsukiNoteRow[0].Unknown2, out var akatsukiNoteStringRow):
dataManager.GetSubrowExcelSheet<AkatsukiNote>(this.language).TryGetSubrow(u32, 0, out var akatsukiNoteRow) &&
akatsukiNoteRow.ListName.ValueNullable is { } akatsukiNoteStringRow:
ImGui.SameLine();
ImGui.Text(akatsukiNoteStringRow.Unknown0.ExtractText());
ImGui.Text(akatsukiNoteStringRow.Text.ExtractText());
break;
}
}

View file

@ -1,4 +1,4 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Bindings.ImGui;
using Dalamud.Game.ClientState;
using Dalamud.Game.ClientState.Objects;
using Dalamud.Interface.Utility;
@ -33,7 +33,7 @@ internal class TargetWidget : IDataWindowWidget
{
ImGui.Checkbox("Resolve GameData"u8, ref this.resolveGameData);
var clientState = Service<ClientState>.Get();
var objectTable = Service<ObjectTable>.Get();
var targetMgr = Service<TargetManager>.Get();
if (targetMgr.Target != null)
@ -80,7 +80,7 @@ internal class TargetWidget : IDataWindowWidget
if (ImGui.Button("Clear FT"u8))
targetMgr.FocusTarget = null;
var localPlayer = clientState.LocalPlayer;
var localPlayer = objectTable.LocalPlayer;
if (localPlayer != null)
{

View file

@ -27,7 +27,7 @@ internal class UldWidget : IDataWindowWidget
{
// ULD styles can be hardcoded for now as they don't add new ones regularly. Can later try and find where to load these from in the game EXE.
private static readonly string[] ThemeDisplayNames = ["Dark", "Light", "Classic FF", "Clear Blue"];
private static readonly string[] ThemeBasePaths = ["ui/uld/", "ui/uld/light/", "ui/uld/third/", "ui/uld/fourth/"];
private static readonly string[] ThemeBasePaths = ["ui/uld/", "ui/uld/img01/", "ui/uld/img02/", "ui/uld/img03/"];
// 48 8D 15 ?? ?? ?? ?? is the part of the signatures that contain the string location offset
// 48 = 64 bit register prefix

View file

@ -52,7 +52,7 @@ internal class VfsWidget : IDataWindowWidget
for (var i = 0; i < this.reps; i++)
{
stopwatch.Restart();
service.WriteAllBytes(path, data);
service.WriteAllBytesAsync(path, data).GetAwaiter().GetResult();
stopwatch.Stop();
acc += stopwatch.ElapsedMilliseconds;
Log.Information("Turn {Turn} took {Ms}ms", i, stopwatch.ElapsedMilliseconds);
@ -70,7 +70,7 @@ internal class VfsWidget : IDataWindowWidget
for (var i = 0; i < this.reps; i++)
{
stopwatch.Restart();
service.ReadAllBytes(path);
service.ReadAllBytesAsync(path).GetAwaiter().GetResult();
stopwatch.Stop();
acc += stopwatch.ElapsedMilliseconds;
Log.Information("Turn {Turn} took {Ms}ms", i, stopwatch.ElapsedMilliseconds);