diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index cf708326b..ddc03558b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,9 +10,10 @@ jobs: runs-on: windows-2022 steps: - name: Checkout Dalamud - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: submodules: recursive + fetch-depth: 0 - name: Setup MSBuild uses: microsoft/setup-msbuild@v1.0.2 - name: Define VERSION diff --git a/Dalamud.Injector/EntryPoint.cs b/Dalamud.Injector/EntryPoint.cs index a7dca9392..f05b1ac08 100644 --- a/Dalamud.Injector/EntryPoint.cs +++ b/Dalamud.Injector/EntryPoint.cs @@ -260,7 +260,6 @@ namespace Dalamud.Injector for (var i = 2; i < args.Count; i++) { - Log.Information(args[i]); if (args[i].StartsWith(key = "--dalamud-working-directory=")) workingDirectory = args[i][key.Length..]; else if (args[i].StartsWith(key = "--dalamud-configuration-path=")) diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index addcdfc57..9cf3129d0 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -8,7 +8,7 @@ - 7.4.1.0 + 7.4.3.0 XIV Launcher addon framework $(DalamudVersion) $(DalamudVersion) diff --git a/Dalamud/Data/DataManager.cs b/Dalamud/Data/DataManager.cs index dce3e98c3..b6570a2ea 100644 --- a/Dalamud/Data/DataManager.cs +++ b/Dalamud/Data/DataManager.cs @@ -65,7 +65,7 @@ public sealed class DataManager : IDisposable, IServiceType { LoadMultithreaded = true, CacheFileResources = true, -#if DEBUG +#if NEVER // Lumina bug PanicOnSheetChecksumMismatch = true, #else PanicOnSheetChecksumMismatch = false, diff --git a/Dalamud/EntryPoint.cs b/Dalamud/EntryPoint.cs index 702d46d0a..11f270b63 100644 --- a/Dalamud/EntryPoint.cs +++ b/Dalamud/EntryPoint.cs @@ -177,7 +177,7 @@ public sealed class EntryPoint InitSymbolHandler(info); var dalamud = new Dalamud(info, configuration, mainThreadContinueEvent); - Log.Information("This is Dalamud - Core: {GitHash}, CS: {CsGitHash}", Util.GetGitHash(), Util.GetGitHashClientStructs()); + Log.Information("This is Dalamud - Core: {GitHash}, CS: {CsGitHash} [{CsVersion}]", Util.GetGitHash(), Util.GetGitHashClientStructs(), FFXIVClientStructs.Interop.Resolver.Version); dalamud.WaitForUnload(); diff --git a/Dalamud/Game/ClientState/Objects/Enums/ObjectKind.cs b/Dalamud/Game/ClientState/Objects/Enums/ObjectKind.cs index 6bfb80863..e60ecaff5 100644 --- a/Dalamud/Game/ClientState/Objects/Enums/ObjectKind.cs +++ b/Dalamud/Game/ClientState/Objects/Enums/ObjectKind.cs @@ -79,4 +79,9 @@ public enum ObjectKind : byte /// Objects representing card stand objects. /// CardStand = 0x0E, + + /// + /// Objects representing ornament (Fashion Accessories) objects. + /// + Ornament = 0x0F, } diff --git a/Dalamud/Game/ClientState/Objects/ObjectTable.cs b/Dalamud/Game/ClientState/Objects/ObjectTable.cs index 80db0f200..70c17fd83 100644 --- a/Dalamud/Game/ClientState/Objects/ObjectTable.cs +++ b/Dalamud/Game/ClientState/Objects/ObjectTable.cs @@ -111,8 +111,12 @@ public sealed partial class ObjectTable : IServiceType { ObjectKind.Player => new PlayerCharacter(address), ObjectKind.BattleNpc => new BattleNpc(address), + ObjectKind.EventNpc => new Npc(address), + ObjectKind.Retainer => new Npc(address), ObjectKind.EventObj => new EventObj(address), ObjectKind.Companion => new Npc(address), + ObjectKind.MountType => new Npc(address), + ObjectKind.Ornament => new Npc(address), _ => new GameObject(address), }; } diff --git a/Dalamud/Game/ClientState/Objects/Types/GameObject.cs b/Dalamud/Game/ClientState/Objects/Types/GameObject.cs index 4335f053a..62b69dcec 100644 --- a/Dalamud/Game/ClientState/Objects/Types/GameObject.cs +++ b/Dalamud/Game/ClientState/Objects/Types/GameObject.cs @@ -113,6 +113,11 @@ public unsafe partial class GameObject /// public uint OwnerId => this.Struct->OwnerID; + /// + /// Gets the index of this object in the object table. + /// + public ushort ObjectIndex => this.Struct->ObjectIndex; + /// /// Gets the entity kind of this . /// See the ObjectKind enum for possible values. diff --git a/Dalamud/Game/Gui/GameGui.cs b/Dalamud/Game/Gui/GameGui.cs index 301f7a634..d3b479642 100644 --- a/Dalamud/Game/Gui/GameGui.cs +++ b/Dalamud/Game/Gui/GameGui.cs @@ -184,8 +184,18 @@ public sealed unsafe class GameGui : IDisposable, IServiceType /// /// Coordinates in the world. /// Converted coordinates. - /// True if worldPos corresponds to a position in front of the camera. + /// True if worldPos corresponds to a position in front of the camera and screenPos is in the viewport. public bool WorldToScreen(Vector3 worldPos, out Vector2 screenPos) + => this.WorldToScreen(worldPos, out screenPos, out var inView) && inView; + + /// + /// Converts in-world coordinates to screen coordinates (upper left corner origin). + /// + /// Coordinates in the world. + /// Converted coordinates. + /// True if screenPos corresponds to a position inside the camera viewport. + /// True if worldPos corresponds to a position in front of the camera. + public bool WorldToScreen(Vector3 worldPos, out Vector2 screenPos, out bool inView) { // Get base object with matrices var matrixSingleton = this.getMatrixSingleton(); @@ -203,9 +213,12 @@ public sealed unsafe class GameGui : IDisposable, IServiceType screenPos.X = (0.5f * width * (screenPos.X + 1f)) + windowPos.X; screenPos.Y = (0.5f * height * (1f - screenPos.Y)) + windowPos.Y; - return pCoords.Z > 0 && - screenPos.X > windowPos.X && screenPos.X < windowPos.X + width && - screenPos.Y > windowPos.Y && screenPos.Y < windowPos.Y + height; + var inFront = pCoords.Z > 0; + inView = inFront && + screenPos.X > windowPos.X && screenPos.X < windowPos.X + width && + screenPos.Y > windowPos.Y && screenPos.Y < windowPos.Y + height; + + return inFront; } /// diff --git a/Dalamud/Game/SigScanner.cs b/Dalamud/Game/SigScanner.cs index 4d3a78830..b19024098 100644 --- a/Dalamud/Game/SigScanner.cs +++ b/Dalamud/Game/SigScanner.cs @@ -395,26 +395,6 @@ public class SigScanner : IDisposable, IServiceType } } - private unsafe class UnsafeCodeReader : CodeReader - { - private readonly int length; - private readonly byte* address; - private int pos; - public UnsafeCodeReader(byte* address, int length) - { - this.length = length; - this.address = address; - } - - public bool CanReadByte => this.pos < this.length; - - public override int ReadByte() - { - if (this.pos >= this.length) return -1; - return *(this.address + this.pos++); - } - } - /// /// Helper for ScanText to get the correct address for IDA sigs that mark the first JMP or CALL location. /// @@ -578,4 +558,25 @@ public class SigScanner : IDisposable, IServiceType Log.Error(ex, "Couldn't load cached sigs"); } } + + private unsafe class UnsafeCodeReader : CodeReader + { + private readonly int length; + private readonly byte* address; + private int pos; + + public UnsafeCodeReader(byte* address, int length) + { + this.length = length; + this.address = address; + } + + public bool CanReadByte => this.pos < this.length; + + public override int ReadByte() + { + if (this.pos >= this.length) return -1; + return *(this.address + this.pos++); + } + } } diff --git a/Dalamud/Game/Text/SeStringHandling/SeString.cs b/Dalamud/Game/Text/SeStringHandling/SeString.cs index 412a78c3f..8413bf610 100644 --- a/Dalamud/Game/Text/SeStringHandling/SeString.cs +++ b/Dalamud/Game/Text/SeStringHandling/SeString.cs @@ -304,7 +304,7 @@ public class SeString foreach (var place in matches) { var map = mapSheet.FirstOrDefault(row => row.PlaceName.Row == place.RowId); - if (map != null) + if (map != null && map.TerritoryType.Row != 0) { return CreateMapLink(map.TerritoryType.Row, map.RowId, xCoord, yCoord, fudgeFactor); } diff --git a/Dalamud/Hooking/Hook.cs b/Dalamud/Hooking/Hook.cs index 6e1fa24f2..74b9e6384 100644 --- a/Dalamud/Hooking/Hook.cs +++ b/Dalamud/Hooking/Hook.cs @@ -67,7 +67,7 @@ public class Hook : IDisposable, IDalamudHook where T : Delegate if (EnvironmentConfiguration.DalamudForceMinHook) useMinHook = true; - address = HookManager.FollowJmp(address); + this.address = address = HookManager.FollowJmp(address); if (useMinHook) this.compatHookImpl = new MinHookHook(address, detour, callingAssembly); else diff --git a/Dalamud/Interface/Internal/DalamudInterface.cs b/Dalamud/Interface/Internal/DalamudInterface.cs index 97313730f..a32db0036 100644 --- a/Dalamud/Interface/Internal/DalamudInterface.cs +++ b/Dalamud/Interface/Internal/DalamudInterface.cs @@ -697,7 +697,7 @@ internal class DalamudInterface : IDisposable, IServiceType ImGui.MenuItem(Util.AssemblyVersion, false); ImGui.MenuItem(startInfo.GameVersion?.ToString() ?? "Unknown version", false); - ImGui.MenuItem($"D: {Util.GetGitHash()} CS: {Util.GetGitHashClientStructs()}", false); + ImGui.MenuItem($"D: {Util.GetGitHash()} CS: {Util.GetGitHashClientStructs()} [{FFXIVClientStructs.Interop.Resolver.Version}]", false); ImGui.MenuItem($"CLR: {Environment.Version}", false); ImGui.EndMenu(); diff --git a/Dalamud/Interface/Internal/InterfaceManager.cs b/Dalamud/Interface/Internal/InterfaceManager.cs index 650b1e00b..9d6a23d34 100644 --- a/Dalamud/Interface/Internal/InterfaceManager.cs +++ b/Dalamud/Interface/Internal/InterfaceManager.cs @@ -417,8 +417,8 @@ internal class InterfaceManager : IDisposable, IServiceType if (this.Device == null) return null; - var dxgiDev = this.Device.QueryInterface(); - var dxgiAdapter = dxgiDev.Adapter.QueryInterfaceOrNull(); + var dxgiDev = this.Device.QueryInterfaceOrNull(); + var dxgiAdapter = dxgiDev?.Adapter.QueryInterfaceOrNull(); if (dxgiAdapter == null) return null; diff --git a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs index f305a722d..2dcd16c4b 100644 --- a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs +++ b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs @@ -46,6 +46,8 @@ internal class PluginInstallerWindow : Window, IDisposable private readonly DateTime timeLoaded; + private readonly object listLock = new(); + #region Image Tester State private string[] testerImagePaths = new string[5]; @@ -214,14 +216,17 @@ internal class PluginInstallerWindow : Window, IDisposable /// public override void Draw() { - this.DrawHeader(); - this.DrawPluginCategories(); - this.DrawFooter(); - this.DrawErrorModal(); - this.DrawUpdateModal(); - this.DrawTestingWarningModal(); - this.DrawFeedbackModal(); - this.DrawProgressOverlay(); + lock (this.listLock) + { + this.DrawHeader(); + this.DrawPluginCategories(); + this.DrawFooter(); + this.DrawErrorModal(); + this.DrawUpdateModal(); + this.DrawTestingWarningModal(); + this.DrawFeedbackModal(); + this.DrawProgressOverlay(); + } } /// @@ -431,7 +436,8 @@ internal class PluginInstallerWindow : Window, IDisposable this.sortKind = selectable.SortKind; this.filterText = selectable.Localization; - this.ResortPlugins(); + lock (this.listLock) + this.ResortPlugins(); } } @@ -1091,7 +1097,7 @@ internal class PluginInstallerWindow : Window, IDisposable private void DrawPluginCategoryContent() { - var ready = this.DrawPluginListLoading() && !this.AnyOperationInProgress; + var ready = this.DrawPluginListLoading(); if (!this.categoryManager.IsSelectionValid || !ready) { return; @@ -2684,11 +2690,14 @@ internal class PluginInstallerWindow : Window, IDisposable { var pluginManager = Service.Get(); - // By removing installed plugins only when the available plugin list changes (basically when the window is - // opened), plugins that have been newly installed remain in the available plugin list as installed. - this.pluginListAvailable = pluginManager.AvailablePlugins.ToList(); - this.pluginListUpdatable = pluginManager.UpdatablePlugins.ToList(); - this.ResortPlugins(); + lock (this.listLock) + { + // By removing installed plugins only when the available plugin list changes (basically when the window is + // opened), plugins that have been newly installed remain in the available plugin list as installed. + this.pluginListAvailable = pluginManager.AvailablePlugins.ToList(); + this.pluginListUpdatable = pluginManager.UpdatablePlugins.ToList(); + this.ResortPlugins(); + } this.UpdateCategoriesOnPluginsChange(); } @@ -2697,10 +2706,13 @@ internal class PluginInstallerWindow : Window, IDisposable { var pluginManager = Service.Get(); - this.pluginListInstalled = pluginManager.InstalledPlugins.ToList(); - this.pluginListUpdatable = pluginManager.UpdatablePlugins.ToList(); - this.hasDevPlugins = this.pluginListInstalled.Any(plugin => plugin.IsDev); - this.ResortPlugins(); + lock (this.listLock) + { + this.pluginListInstalled = pluginManager.InstalledPlugins.ToList(); + this.pluginListUpdatable = pluginManager.UpdatablePlugins.ToList(); + this.hasDevPlugins = this.pluginListInstalled.Any(plugin => plugin.IsDev); + this.ResortPlugins(); + } this.UpdateCategoriesOnPluginsChange(); } diff --git a/Dalamud/Interface/Internal/Windows/PluginStatWindow.cs b/Dalamud/Interface/Internal/Windows/PluginStatWindow.cs index e5e8b90e7..21b32a68a 100644 --- a/Dalamud/Interface/Internal/Windows/PluginStatWindow.cs +++ b/Dalamud/Interface/Internal/Windows/PluginStatWindow.cs @@ -6,6 +6,7 @@ using System.Reflection; using Dalamud.Game; using Dalamud.Hooking.Internal; +using Dalamud.Interface.Components; using Dalamud.Interface.Internal.Notifications; using Dalamud.Interface.Windowing; using Dalamud.Plugin.Internal; @@ -68,6 +69,16 @@ internal class PluginStatWindow : Window } } + var loadedPlugins = pluginManager.InstalledPlugins.Where(plugin => plugin.State == PluginState.Loaded); + var totalLast = loadedPlugins.Sum(plugin => plugin.DalamudInterface?.UiBuilder.LastDrawTime ?? 0); + var totalAverage = loadedPlugins.Sum(plugin => plugin.DalamudInterface?.UiBuilder.DrawTimeHistory.DefaultIfEmpty().Average() ?? 0); + + ImGuiComponents.TextWithLabel("Total Last", $"{totalLast / 10000f:F4}ms", "All last draw times added together"); + ImGui.SameLine(); + ImGuiComponents.TextWithLabel("Total Average", $"{totalAverage / 10000f:F4}ms", "All average draw times added together"); + ImGui.SameLine(); + ImGuiComponents.TextWithLabel("Collective Average", $"{(loadedPlugins.Any() ? totalAverage / loadedPlugins.Count() / 10000f : 0):F4}ms", "Average of all average draw times"); + if (ImGui.BeginTable( "##PluginStatsDrawTimes", 4, @@ -86,8 +97,6 @@ internal class PluginStatWindow : Window ImGui.TableSetupColumn("Average"); ImGui.TableHeadersRow(); - var loadedPlugins = pluginManager.InstalledPlugins.Where(plugin => plugin.State == PluginState.Loaded); - var sortSpecs = ImGui.TableGetSortSpecs(); loadedPlugins = sortSpecs.Specs.ColumnIndex switch { @@ -149,6 +158,16 @@ internal class PluginStatWindow : Window Framework.StatsHistory.Clear(); } + var statsHistory = Framework.StatsHistory.ToArray(); + var totalLast = statsHistory.Sum(stats => stats.Value.LastOrDefault()); + var totalAverage = statsHistory.Sum(stats => stats.Value.Average()); + + ImGuiComponents.TextWithLabel("Total Last", $"{totalLast:F4}ms", "All last update times added together"); + ImGui.SameLine(); + ImGuiComponents.TextWithLabel("Total Average", $"{totalAverage:F4}ms", "All average update times added together"); + ImGui.SameLine(); + ImGuiComponents.TextWithLabel("Collective Average", $"{(statsHistory.Any() ? totalAverage / statsHistory.Length : 0):F4}ms", "Average of all average update times"); + if (ImGui.BeginTable( "##PluginStatsFrameworkTimes", 4, @@ -167,8 +186,6 @@ internal class PluginStatWindow : Window ImGui.TableSetupColumn("Average", ImGuiTableColumnFlags.None, 50); ImGui.TableHeadersRow(); - var statsHistory = Framework.StatsHistory.ToArray(); - var sortSpecs = ImGui.TableGetSortSpecs(); statsHistory = sortSpecs.Specs.ColumnIndex switch { diff --git a/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabExperimental.cs b/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabExperimental.cs index a1c2c3336..ec22ef8d7 100644 --- a/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabExperimental.cs +++ b/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabExperimental.cs @@ -55,5 +55,6 @@ public class SettingsTabExperimental : SettingsTab base.Draw(); ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, "Total memory used by Dalamud & Plugins: " + Util.FormatBytes(GC.GetTotalMemory(false))); + ImGuiHelpers.ScaledDummy(15); } } diff --git a/Dalamud/Plugin/Internal/Types/LocalPlugin.cs b/Dalamud/Plugin/Internal/Types/LocalPlugin.cs index 9d36a1644..2c77ff528 100644 --- a/Dalamud/Plugin/Internal/Types/LocalPlugin.cs +++ b/Dalamud/Plugin/Internal/Types/LocalPlugin.cs @@ -147,7 +147,7 @@ internal class LocalPlugin : IDisposable } var pluginManager = Service.Get(); - this.IsBanned = pluginManager.IsManifestBanned(this.Manifest); + this.IsBanned = pluginManager.IsManifestBanned(this.Manifest) && !this.IsDev; this.BanReason = pluginManager.GetBanReason(this.Manifest); this.SaveManifest(); @@ -320,7 +320,7 @@ internal class LocalPlugin : IDisposable throw new ArgumentOutOfRangeException(this.State.ToString()); } - if (pluginManager.IsManifestBanned(this.Manifest)) + if (pluginManager.IsManifestBanned(this.Manifest) && !this.IsDev) throw new BannedPluginException($"Unable to load {this.Name}, banned"); if (this.Manifest.ApplicableVersion < startInfo.GameVersion) diff --git a/lib/FFXIVClientStructs b/lib/FFXIVClientStructs index 08e6c7ed7..47ffffaa0 160000 --- a/lib/FFXIVClientStructs +++ b/lib/FFXIVClientStructs @@ -1 +1 @@ -Subproject commit 08e6c7ed7747ad68a38e5762863b5874fe04b8b8 +Subproject commit 47ffffaa05ee72d286772cef9ab2f62ab1422e45