From b5f34c3199943b42a9fc31a35a9ff8b2a09c8591 Mon Sep 17 00:00:00 2001
From: goat <16760685+goaaats@users.noreply.github.com>
Date: Wed, 17 Nov 2021 19:42:32 +0100
Subject: [PATCH] refactor(Dalamud): switch to file-scoped namespaces
---
Dalamud/ClientLanguage.cs | 41 +-
Dalamud/ClientLanguageExtensions.cs | 35 +-
Dalamud/Configuration/IPluginConfiguration.cs | 17 +-
.../Internal/DalamudConfiguration.cs | 513 +-
.../Internal/DevPluginLocationSettings.cs | 35 +-
.../Internal/DevPluginSettings.cs | 25 +-
.../Internal/EnvironmentConfiguration.cs | 53 +-
.../Internal/ThirdPartyRepoSettings.cs | 43 +-
Dalamud/Configuration/PluginConfigurations.cs | 227 +-
Dalamud/Dalamud.cs | 607 +-
Dalamud/DalamudStartInfo.cs | 85 +-
Dalamud/Data/DataManager.cs | 591 +-
Dalamud/EntryPoint.cs | 425 +-
Dalamud/Game/BaseAddressResolver.cs | 179 +-
Dalamud/Game/ChatHandlers.cs | 495 +-
Dalamud/Game/ClientState/Buddy/BuddyList.cs | 311 +-
Dalamud/Game/ClientState/Buddy/BuddyMember.cs | 121 +-
Dalamud/Game/ClientState/ClientState.cs | 297 +-
.../ClientState/ClientStateAddressResolver.cs | 191 +-
.../Game/ClientState/Conditions/Condition.cs | 243 +-
.../ClientState/Conditions/ConditionFlag.cs | 897 +-
Dalamud/Game/ClientState/Fates/Fate.cs | 231 +-
Dalamud/Game/ClientState/Fates/FateState.cs | 49 +-
Dalamud/Game/ClientState/Fates/FateTable.cs | 237 +-
.../ClientState/GamePad/GamepadButtons.cs | 147 +-
.../Game/ClientState/GamePad/GamepadInput.cs | 125 +-
.../Game/ClientState/GamePad/GamepadState.cs | 477 +-
.../ClientState/JobGauge/Enums/BOTDState.cs | 33 +-
.../ClientState/JobGauge/Enums/CardType.cs | 81 +-
.../JobGauge/Enums/DismissedFairy.cs | 25 +-
.../Game/ClientState/JobGauge/Enums/Mudras.cs | 33 +-
.../ClientState/JobGauge/Enums/PetGlam.cs | 41 +-
.../ClientState/JobGauge/Enums/SealType.cs | 41 +-
.../Game/ClientState/JobGauge/Enums/Sen.cs | 43 +-
.../Game/ClientState/JobGauge/Enums/Song.cs | 41 +-
.../ClientState/JobGauge/Enums/SummonPet.cs | 41 +-
.../Game/ClientState/JobGauge/JobGauges.cs | 69 +-
.../ClientState/JobGauge/Types/ASTGauge.cs | 55 +-
.../ClientState/JobGauge/Types/BLMGauge.cs | 117 +-
.../ClientState/JobGauge/Types/BRDGauge.cs | 61 +-
.../ClientState/JobGauge/Types/DNCGauge.cs | 103 +-
.../ClientState/JobGauge/Types/DRGGauge.cs | 51 +-
.../ClientState/JobGauge/Types/DRKGauge.cs | 63 +-
.../ClientState/JobGauge/Types/GNBGauge.cs | 51 +-
.../JobGauge/Types/JobGaugeBase.cs | 31 +-
.../JobGauge/Types/JobGaugeBase{T}.cs | 33 +-
.../ClientState/JobGauge/Types/MCHGauge.cs | 95 +-
.../ClientState/JobGauge/Types/MNKGauge.cs | 31 +-
.../ClientState/JobGauge/Types/NINGauge.cs | 51 +-
.../ClientState/JobGauge/Types/PLDGauge.cs | 31 +-
.../ClientState/JobGauge/Types/RDMGauge.cs | 41 +-
.../ClientState/JobGauge/Types/SAMGauge.cs | 87 +-
.../ClientState/JobGauge/Types/SCHGauge.cs | 61 +-
.../ClientState/JobGauge/Types/SMNGauge.cs | 99 +-
.../ClientState/JobGauge/Types/WARGauge.cs | 31 +-
.../ClientState/JobGauge/Types/WHMGauge.cs | 51 +-
Dalamud/Game/ClientState/Keys/KeyState.cs | 285 +-
Dalamud/Game/ClientState/Keys/VirtualKey.cs | 2075 ++-
.../Objects/Enums/BattleNpcSubKind.cs | 41 +-
.../Objects/Enums/CustomizeIndex.cs | 219 +-
.../ClientState/Objects/Enums/ObjectKind.cs | 129 +-
.../ClientState/Objects/Enums/StatusFlags.cs | 83 +-
.../Game/ClientState/Objects/ObjectTable.cs | 233 +-
.../ClientState/Objects/SubKinds/BattleNpc.cs | 39 +-
.../ClientState/Objects/SubKinds/EventObj.cs | 23 +-
.../Game/ClientState/Objects/SubKinds/Npc.cs | 23 +-
.../Objects/SubKinds/PlayerCharacter.cs | 53 +-
.../Game/ClientState/Objects/TargetManager.cs | 303 +-
.../ClientState/Objects/Types/BattleChara.cs | 113 +-
.../ClientState/Objects/Types/Character.cs | 185 +-
.../ClientState/Objects/Types/GameObject.cs | 311 +-
Dalamud/Game/ClientState/Party/PartyList.cs | 313 +-
Dalamud/Game/ClientState/Party/PartyMember.cs | 191 +-
.../ClientState/Resolvers/ExcelResolver{T}.cs | 43 +-
Dalamud/Game/ClientState/Statuses/Status.cs | 111 +-
.../Game/ClientState/Statuses/StatusList.cs | 255 +-
.../Game/ClientState/Structs/StatusEffect.cs | 51 +-
Dalamud/Game/Command/CommandInfo.cs | 79 +-
Dalamud/Game/Command/CommandManager.cs | 257 +-
Dalamud/Game/Framework.cs | 511 +-
Dalamud/Game/FrameworkAddressResolver.cs | 83 +-
Dalamud/Game/GameVersion.cs | 767 +-
Dalamud/Game/GameVersionConverter.cs | 127 +-
Dalamud/Game/Gui/ChatGui.cs | 845 +-
Dalamud/Game/Gui/ChatGuiAddressResolver.cs | 199 +-
Dalamud/Game/Gui/FlyText/FlyTextGui.cs | 573 +-
.../Gui/FlyText/FlyTextGuiAddressResolver.cs | 47 +-
Dalamud/Game/Gui/FlyText/FlyTextKind.cs | 455 +-
Dalamud/Game/Gui/GameGui.cs | 1015 +-
Dalamud/Game/Gui/GameGuiAddressResolver.cs | 159 +-
Dalamud/Game/Gui/HoverActionKind.cs | 75 +-
Dalamud/Game/Gui/HoveredAction.cs | 33 +-
Dalamud/Game/Gui/Internal/DalamudIME.cs | 443 +-
.../PartyFinder/Internal/PartyFinderPacket.cs | 35 +-
.../Internal/PartyFinderPacketListing.cs | 181 +-
.../PartyFinder/PartyFinderAddressResolver.cs | 25 +-
.../Game/Gui/PartyFinder/PartyFinderGui.cs | 213 +-
.../Gui/PartyFinder/Types/ConditionFlags.cs | 35 +-
.../Gui/PartyFinder/Types/DutyCategory.cs | 73 +-
.../Types/DutyFinderSettingsFlags.cs | 43 +-
.../Game/Gui/PartyFinder/Types/DutyType.cs | 33 +-
.../Game/Gui/PartyFinder/Types/JobFlags.cs | 227 +-
.../PartyFinder/Types/JobFlagsExtensions.cs | 89 +-
.../Gui/PartyFinder/Types/LootRuleFlags.cs | 35 +-
.../Gui/PartyFinder/Types/ObjectiveFlags.cs | 43 +-
.../PartyFinder/Types/PartyFinderListing.cs | 433 +-
.../Types/PartyFinderListingEventArgs.cs | 41 +-
.../Gui/PartyFinder/Types/PartyFinderSlot.cs | 69 +-
.../Gui/PartyFinder/Types/SearchAreaFlags.cs | 51 +-
Dalamud/Game/Gui/Toast/QuestToastOptions.cs | 49 +-
Dalamud/Game/Gui/Toast/QuestToastPosition.cs | 33 +-
Dalamud/Game/Gui/Toast/ToastGui.cs | 783 +-
.../Game/Gui/Toast/ToastGuiAddressResolver.cs | 49 +-
Dalamud/Game/Gui/Toast/ToastOptions.cs | 25 +-
Dalamud/Game/Gui/Toast/ToastPosition.cs | 25 +-
Dalamud/Game/Gui/Toast/ToastSpeed.cs | 25 +-
Dalamud/Game/Internal/AntiDebug.cs | 191 +-
.../DXGI/Definitions/ID3D11DeviceVtbl.cs | 359 +-
.../DXGI/Definitions/IDXGISwapChainVtbl.cs | 165 +-
.../DXGI/ISwapChainAddressResolver.cs | 25 +-
.../Internal/DXGI/SwapChainSigResolver.cs | 43 +-
.../Internal/DXGI/SwapChainVtableResolver.cs | 111 +-
Dalamud/Game/Internal/DalamudAtkTweaks.cs | 373 +-
Dalamud/Game/Libc/LibcFunction.cs | 111 +-
.../Game/Libc/LibcFunctionAddressResolver.cs | 41 +-
Dalamud/Game/Libc/OwnedStdString.cs | 159 +-
Dalamud/Game/Libc/StdString.cs | 109 +-
Dalamud/Game/Network/GameNetwork.cs | 335 +-
.../Network/GameNetworkAddressResolver.cs | 41 +-
.../IMarketBoardUploader.cs | 45 +-
.../MarketBoardItemRequest.cs | 93 +-
.../Types/UniversalisHistoryEntry.cs | 89 +-
.../Types/UniversalisHistoryUploadRequest.cs | 49 +-
.../UniversalisItemListingDeleteRequest.cs | 59 +-
.../Types/UniversalisItemListingsEntry.cs | 149 +-
.../UniversalisItemListingsUploadRequest.cs | 49 +-
.../Types/UniversalisItemMateria.cs | 29 +-
.../Universalis/Types/UniversalisTaxData.cs | 69 +-
.../Types/UniversalisTaxUploadRequest.cs | 39 +-
.../UniversalisMarketBoardUploader.cs | 305 +-
.../Game/Network/Internal/NetworkHandlers.cs | 487 +-
.../Game/Network/Internal/WinSockHandlers.cs | 85 +-
.../Game/Network/NetworkMessageDirection.cs | 25 +-
.../Structures/MarketBoardCurrentOfferings.cs | 371 +-
.../Network/Structures/MarketBoardHistory.cs | 181 +-
.../Network/Structures/MarketBoardPurchase.cs | 63 +-
.../Structures/MarketBoardPurchaseHandler.cs | 91 +-
.../Game/Network/Structures/MarketTaxRates.cs | 101 +-
Dalamud/Game/SigScanner.cs | 921 +-
Dalamud/Game/Text/Sanitizer/ISanitizer.cs | 61 +-
Dalamud/Game/Text/Sanitizer/Sanitizer.cs | 191 +-
Dalamud/Game/Text/SeIconChar.cs | 1477 +-
.../Text/SeStringHandling/BitmapFontIcon.cs | 867 +-
.../Text/SeStringHandling/ITextProvider.cs | 17 +-
Dalamud/Game/Text/SeStringHandling/Payload.cs | 735 +-
.../Game/Text/SeStringHandling/PayloadType.cs | 129 +-
.../Payloads/AutoTranslatePayload.cs | 259 +-
.../Payloads/DalamudLinkPayload.cs | 83 +-
.../Payloads/EmphasisItalicPayload.cs | 117 +-
.../SeStringHandling/Payloads/IconPayload.cs | 101 +-
.../SeStringHandling/Payloads/ItemPayload.cs | 281 +-
.../Payloads/MapLinkPayload.cs | 407 +-
.../Payloads/NewLinePayload.cs | 49 +-
.../Payloads/PlayerPayload.cs | 179 +-
.../SeStringHandling/Payloads/QuestPayload.cs | 109 +-
.../SeStringHandling/Payloads/RawPayload.cs | 179 +-
.../Payloads/SeHyphenPayload.cs | 49 +-
.../Payloads/StatusPayload.cs | 109 +-
.../SeStringHandling/Payloads/TextPayload.cs | 145 +-
.../Payloads/UIForegroundPayload.cs | 189 +-
.../Payloads/UIGlowPayload.cs | 189 +-
.../Game/Text/SeStringHandling/SeString.cs | 583 +-
.../Text/SeStringHandling/SeStringManager.cs | 199 +-
Dalamud/Game/Text/XivChatEntry.cs | 49 +-
Dalamud/Game/Text/XivChatType.cs | 389 +-
Dalamud/Game/Text/XivChatTypeExtensions.cs | 23 +-
Dalamud/Game/Text/XivChatTypeInfoAttribute.cs | 61 +-
Dalamud/Hooking/AsmHook.cs | 293 +-
Dalamud/Hooking/AsmHookBehaviour.cs | 35 +-
Dalamud/Hooking/Hook.cs | 459 +-
Dalamud/Hooking/IDalamudHook.cs | 41 +-
Dalamud/Hooking/Internal/HookInfo.cs | 115 +-
Dalamud/Hooking/Internal/HookManager.cs | 233 +-
Dalamud/Interface/Animation/AnimUtil.cs | 55 +-
Dalamud/Interface/Animation/Easing.cs | 215 +-
.../Animation/EasingFunctions/InCirc.cs | 37 +-
.../Animation/EasingFunctions/InCubic.cs | 37 +-
.../Animation/EasingFunctions/InElastic.cs | 49 +-
.../Animation/EasingFunctions/InOutCirc.cs | 41 +-
.../Animation/EasingFunctions/InOutCubic.cs | 37 +-
.../Animation/EasingFunctions/InOutElastic.cs | 53 +-
.../Animation/EasingFunctions/InOutQuint.cs | 37 +-
.../Animation/EasingFunctions/InOutSine.cs | 37 +-
.../Animation/EasingFunctions/InQuint.cs | 37 +-
.../Animation/EasingFunctions/InSine.cs | 37 +-
.../Animation/EasingFunctions/OutCirc.cs | 37 +-
.../Animation/EasingFunctions/OutCubic.cs | 37 +-
.../Animation/EasingFunctions/OutElastic.cs | 49 +-
.../Animation/EasingFunctions/OutQuint.cs | 37 +-
.../Animation/EasingFunctions/OutSine.cs | 37 +-
Dalamud/Interface/Colors/ImGuiColors.cs | 161 +-
.../ImGuiComponents.ColorPickerWithPalette.cs | 89 +-
.../ImGuiComponents.DisabledButton.cs | 103 +-
.../Components/ImGuiComponents.HelpMarker.cs | 39 +-
.../Components/ImGuiComponents.IconButton.cs | 177 +-
.../Components/ImGuiComponents.Test.cs | 19 +-
.../ImGuiComponents.TextWithLabel.cs | 41 +-
.../Interface/Components/ImGuiComponents.cs | 13 +-
Dalamud/Interface/FontAwesomeExtensions.cs | 43 +-
Dalamud/Interface/FontAwesomeIcon.cs | 14087 ++++++++--------
Dalamud/Interface/GlyphRangesJapanese.cs | 19 +-
.../ImGuiFileDialog/FileDialog.Files.cs | 729 +-
.../ImGuiFileDialog/FileDialog.Filters.cs | 149 +-
.../ImGuiFileDialog/FileDialog.Helpers.cs | 41 +-
.../ImGuiFileDialog/FileDialog.Structs.cs | 83 +-
.../ImGuiFileDialog/FileDialog.UI.cs | 1509 +-
.../Interface/ImGuiFileDialog/FileDialog.cs | 383 +-
.../ImGuiFileDialog/FileDialogManager.cs | 171 +-
.../ImGuiFileDialog/ImGuiFileDialogFlags.cs | 83 +-
Dalamud/Interface/ImGuiHelpers.cs | 215 +-
Dalamud/Interface/Internal/DalamudCommands.cs | 583 +-
.../Interface/Internal/DalamudInterface.cs | 1233 +-
.../Interface/Internal/InterfaceManager.cs | 1137 +-
.../ManagedAsserts/ImGuiContextOffsets.cs | 31 +-
.../ManagedAsserts/ImGuiManagedAsserts.cs | 217 +-
.../Notifications/NotificationManager.cs | 539 +-
.../Notifications/NotificationType.cs | 49 +-
.../Internal/PluginCategoryManager.cs | 745 +-
Dalamud/Interface/Internal/UiDebug.cs | 1341 +-
.../Internal/Windows/ChangelogWindow.cs | 183 +-
.../Internal/Windows/ColorDemoWindow.cs | 51 +-
.../Internal/Windows/ComponentDemoWindow.cs | 255 +-
.../Internal/Windows/ConsoleWindow.cs | 887 +-
.../Internal/Windows/CreditsWindow.cs | 223 +-
.../Interface/Internal/Windows/DataWindow.cs | 3199 ++--
.../Windows/GamepadModeNotifierWindow.cs | 69 +-
.../Interface/Internal/Windows/IMEWindow.cs | 93 +-
.../Internal/Windows/PluginImageCache.cs | 763 +-
.../Internal/Windows/PluginInstallerWindow.cs | 4291 +++--
.../Internal/Windows/PluginStatWindow.cs | 437 +-
.../AgingSteps/ActorTableAgingStep.cs | 63 +-
.../SelfTest/AgingSteps/ChatAgingStep.cs | 101 +-
.../SelfTest/AgingSteps/ConditionAgingStep.cs | 49 +-
.../AgingSteps/EnterTerritoryAgingStep.cs | 99 +-
.../SelfTest/AgingSteps/FateTableAgingStep.cs | 63 +-
.../AgingSteps/GamepadStateAgingStep.cs | 51 +-
.../AgingSteps/HandledExceptionAgingStep.cs | 49 +-
.../SelfTest/AgingSteps/HoverAgingStep.cs | 83 +-
.../Windows/SelfTest/AgingSteps/IAgingStep.cs | 35 +-
.../SelfTest/AgingSteps/KeyStateAgingStep.cs | 55 +-
.../AgingSteps/LoginEventAgingStep.cs | 79 +-
.../AgingSteps/LogoutEventAgingStep.cs | 79 +-
.../SelfTest/AgingSteps/LuminaAgingStep.cs | 53 +-
.../AgingSteps/PartyFinderAgingStep.cs | 81 +-
.../SelfTest/AgingSteps/TargetAgingStep.cs | 105 +-
.../SelfTest/AgingSteps/ToastAgingStep.cs | 41 +-
.../AgingSteps/WaitFramesAgingStep.cs | 55 +-
.../Windows/SelfTest/SelfTestStepResult.cs | 41 +-
.../Windows/SelfTest/SelfTestWindow.cs | 411 +-
.../Internal/Windows/SettingsWindow.cs | 1214 +-
.../Windows/StyleEditor/StyleEditorWindow.cs | 727 +-
Dalamud/Interface/Style/DalamudColors.cs | 170 +-
Dalamud/Interface/Style/StyleModel.cs | 225 +-
Dalamud/Interface/Style/StyleModelV1.cs | 561 +-
Dalamud/Interface/UiBuilder.cs | 557 +-
Dalamud/Interface/Windowing/Window.cs | 545 +-
Dalamud/Interface/Windowing/WindowSystem.cs | 231 +-
.../IoC/Internal/InterfaceVersionAttribute.cs | 33 +-
Dalamud/IoC/Internal/ObjectInstance.cs | 43 +-
Dalamud/IoC/Internal/ServiceContainer.cs | 365 +-
Dalamud/IoC/PluginInterfaceAttribute.cs | 15 +-
Dalamud/IoC/PluginServiceAttribute.cs | 17 +-
Dalamud/IoC/RequiredVersionAttribute.cs | 33 +-
Dalamud/Localization.cs | 245 +-
Dalamud/Logging/Internal/ModuleLog.cs | 231 +-
Dalamud/Logging/Internal/SerilogEventSink.cs | 71 +-
Dalamud/Logging/Internal/TaskTracker.cs | 387 +-
Dalamud/Logging/PluginLog.cs | 409 +-
.../Exceptions/MemoryAllocationException.cs | 69 +-
Dalamud/Memory/Exceptions/MemoryException.cs | 69 +-
.../Exceptions/MemoryPermissionException.cs | 69 +-
.../Memory/Exceptions/MemoryReadException.cs | 69 +-
.../Memory/Exceptions/MemoryWriteException.cs | 69 +-
Dalamud/Memory/MemoryHelper.cs | 1247 +-
Dalamud/Memory/MemoryProtection.cs | 193 +-
Dalamud/NativeFunctions.cs | 3543 ++--
Dalamud/Plugin/DalamudPluginInterface.cs | 613 +-
Dalamud/Plugin/IDalamudPlugin.cs | 17 +-
.../Exceptions/BannedPluginException.cs | 31 +-
.../Exceptions/DuplicatePluginException.cs | 39 +-
.../Exceptions/InvalidPluginException.cs | 31 +-
.../InvalidPluginOperationException.cs | 31 +-
.../Internal/Exceptions/PluginException.cs | 13 +-
Dalamud/Plugin/Internal/LocalDevPlugin.cs | 275 +-
Dalamud/Plugin/Internal/LocalPlugin.cs | 845 +-
Dalamud/Plugin/Internal/PluginManager.cs | 2141 ++-
Dalamud/Plugin/Internal/PluginRepository.cs | 175 +-
.../Internal/Types/AvailablePluginUpdate.cs | 59 +-
.../Internal/Types/LocalPluginManifest.cs | 125 +-
.../Plugin/Internal/Types/PluginManifest.cs | 261 +-
.../Internal/Types/PluginRepositoryState.cs | 41 +-
Dalamud/Plugin/Internal/Types/PluginState.cs | 49 +-
.../Internal/Types/PluginUpdateStatus.cs | 41 +-
.../Internal/Types/RemotePluginManifest.cs | 23 +-
Dalamud/Plugin/Ipc/Exceptions/IpcError.cs | 51 +-
.../Ipc/Exceptions/IpcLengthMismatchError.cs | 25 +-
.../Plugin/Ipc/Exceptions/IpcNotReadyError.cs | 21 +-
.../Ipc/Exceptions/IpcTypeMismatchError.cs | 27 +-
Dalamud/Plugin/Ipc/ICallGateProvider.cs | 253 +-
Dalamud/Plugin/Ipc/ICallGateSubscriber.cs | 217 +-
Dalamud/Plugin/Ipc/Internal/CallGate.cs | 43 +-
.../Plugin/Ipc/Internal/CallGateChannel.cs | 315 +-
Dalamud/Plugin/Ipc/Internal/CallGatePubSub.cs | 631 +-
.../Plugin/Ipc/Internal/CallGatePubSubBase.cs | 161 +-
Dalamud/Plugin/PluginLoadReason.cs | 49 +-
Dalamud/SafeMemory.cs | 481 +-
Dalamud/Service{T}.cs | 203 +-
Dalamud/Support/BugBait.cs | 95 +-
Dalamud/Support/Troubleshooting.cs | 188 +-
Dalamud/Utility/EnumExtensions.cs | 37 +-
Dalamud/Utility/SeStringExtensions.cs | 25 +-
Dalamud/Utility/StringExtensions.cs | 47 +-
Dalamud/Utility/TexFileExtensions.cs | 41 +-
Dalamud/Utility/Util.cs | 531 +-
Dalamud/Utility/VectorExtensions.cs | 81 +-
325 files changed, 45878 insertions(+), 46218 deletions(-)
diff --git a/Dalamud/ClientLanguage.cs b/Dalamud/ClientLanguage.cs
index ddd69576d..4e04d4a54 100644
--- a/Dalamud/ClientLanguage.cs
+++ b/Dalamud/ClientLanguage.cs
@@ -1,28 +1,27 @@
-namespace Dalamud
+namespace Dalamud;
+
+///
+/// Enum describing the language the game loads in.
+///
+public enum ClientLanguage
{
///
- /// Enum describing the language the game loads in.
+ /// Indicating a Japanese game client.
///
- public enum ClientLanguage
- {
- ///
- /// Indicating a Japanese game client.
- ///
- Japanese,
+ Japanese,
- ///
- /// Indicating an English game client.
- ///
- English,
+ ///
+ /// Indicating an English game client.
+ ///
+ English,
- ///
- /// Indicating a German game client.
- ///
- German,
+ ///
+ /// Indicating a German game client.
+ ///
+ German,
- ///
- /// Indicating a French game client.
- ///
- French,
- }
+ ///
+ /// Indicating a French game client.
+ ///
+ French,
}
diff --git a/Dalamud/ClientLanguageExtensions.cs b/Dalamud/ClientLanguageExtensions.cs
index dccefb93f..b7e021f61 100644
--- a/Dalamud/ClientLanguageExtensions.cs
+++ b/Dalamud/ClientLanguageExtensions.cs
@@ -1,27 +1,26 @@
using System;
-namespace Dalamud
+namespace Dalamud;
+
+///
+/// Extension methods for the class.
+///
+public static class ClientLanguageExtensions
{
///
- /// Extension methods for the class.
+ /// Converts a Dalamud ClientLanguage to the corresponding Lumina variant.
///
- public static class ClientLanguageExtensions
+ /// Langauge to convert.
+ /// Converted langauge.
+ public static Lumina.Data.Language ToLumina(this ClientLanguage language)
{
- ///
- /// Converts a Dalamud ClientLanguage to the corresponding Lumina variant.
- ///
- /// Langauge to convert.
- /// Converted langauge.
- public static Lumina.Data.Language ToLumina(this ClientLanguage language)
+ return language switch
{
- return language switch
- {
- ClientLanguage.Japanese => Lumina.Data.Language.Japanese,
- ClientLanguage.English => Lumina.Data.Language.English,
- ClientLanguage.German => Lumina.Data.Language.German,
- ClientLanguage.French => Lumina.Data.Language.French,
- _ => throw new ArgumentOutOfRangeException(nameof(language)),
- };
- }
+ ClientLanguage.Japanese => Lumina.Data.Language.Japanese,
+ ClientLanguage.English => Lumina.Data.Language.English,
+ ClientLanguage.German => Lumina.Data.Language.German,
+ ClientLanguage.French => Lumina.Data.Language.French,
+ _ => throw new ArgumentOutOfRangeException(nameof(language)),
+ };
}
}
diff --git a/Dalamud/Configuration/IPluginConfiguration.cs b/Dalamud/Configuration/IPluginConfiguration.cs
index 884e38871..dcc93d8d7 100644
--- a/Dalamud/Configuration/IPluginConfiguration.cs
+++ b/Dalamud/Configuration/IPluginConfiguration.cs
@@ -1,13 +1,12 @@
-namespace Dalamud.Configuration
+namespace Dalamud.Configuration;
+
+///
+/// Configuration to store settings for a dalamud plugin.
+///
+public interface IPluginConfiguration
{
///
- /// Configuration to store settings for a dalamud plugin.
+ /// Gets or sets configuration version.
///
- public interface IPluginConfiguration
- {
- ///
- /// Gets or sets configuration version.
- ///
- int Version { get; set; }
- }
+ int Version { get; set; }
}
diff --git a/Dalamud/Configuration/Internal/DalamudConfiguration.cs b/Dalamud/Configuration/Internal/DalamudConfiguration.cs
index b4263679e..7e9718f2d 100644
--- a/Dalamud/Configuration/Internal/DalamudConfiguration.cs
+++ b/Dalamud/Configuration/Internal/DalamudConfiguration.cs
@@ -8,268 +8,267 @@ using Newtonsoft.Json;
using Serilog;
using Serilog.Events;
-namespace Dalamud.Configuration.Internal
+namespace Dalamud.Configuration.Internal;
+
+///
+/// Class containing Dalamud settings.
+///
+[Serializable]
+internal sealed class DalamudConfiguration
{
- ///
- /// Class containing Dalamud settings.
- ///
- [Serializable]
- internal sealed class DalamudConfiguration
+ private static readonly JsonSerializerSettings SerializerSettings = new()
{
- private static readonly JsonSerializerSettings SerializerSettings = new()
+ TypeNameHandling = TypeNameHandling.All,
+ TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
+ Formatting = Formatting.Indented,
+ };
+
+ [JsonIgnore]
+ private string configPath;
+
+ ///
+ /// Delegate for the event that occurs when the dalamud configuration is saved.
+ ///
+ /// The current dalamud configuration.
+ public delegate void DalamudConfigurationSavedDelegate(DalamudConfiguration dalamudConfiguration);
+
+ ///
+ /// Event that occurs when dalamud configuration is saved.
+ ///
+ public event DalamudConfigurationSavedDelegate DalamudConfigurationSaved;
+
+ ///
+ /// Gets or sets a list of muted works.
+ ///
+ public List BadWords { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether or not the taskbar should flash once a duty is found.
+ ///
+ public bool DutyFinderTaskbarFlash { get; set; } = true;
+
+ ///
+ /// Gets or sets a value indicating whether or not a message should be sent in chat once a duty is found.
+ ///
+ public bool DutyFinderChatMessage { get; set; } = true;
+
+ ///
+ /// Gets or sets the language code to load Dalamud localization with.
+ ///
+ public string LanguageOverride { get; set; } = null;
+
+ ///
+ /// Gets or sets the last loaded Dalamud version.
+ ///
+ public string LastVersion { get; set; } = null;
+
+ ///
+ /// Gets or sets the last loaded Dalamud version.
+ ///
+ public string LastChangelogMajorMinor { get; set; } = null;
+
+ ///
+ /// Gets or sets the chat type used by default for plugin messages.
+ ///
+ public XivChatType GeneralChatType { get; set; } = XivChatType.Debug;
+
+ ///
+ /// Gets or sets a value indicating whether or not plugin testing builds should be shown.
+ ///
+ public bool DoPluginTest { get; set; } = false;
+
+ ///
+ /// Gets or sets a value indicating whether or not Dalamud testing builds should be used.
+ ///
+ public bool DoDalamudTest { get; set; } = false;
+
+ ///
+ /// Gets or sets a value indicating whether or not XL should download the Dalamud .NET runtime.
+ ///
+ public bool DoDalamudRuntime { get; set; } = false;
+
+ ///
+ /// Gets or sets a list of custom repos.
+ ///
+ public List ThirdRepoList { get; set; } = new();
+
+ ///
+ /// Gets or sets a list of hidden plugins.
+ ///
+ public List HiddenPluginInternalName { get; set; } = new();
+
+ ///
+ /// Gets or sets a list of seen plugins.
+ ///
+ public List SeenPluginInternalName { get; set; } = new();
+
+ ///
+ /// Gets or sets a list of additional settings for devPlugins. The key is the absolute path
+ /// to the plugin DLL. This is automatically generated for any plugins in the devPlugins folder.
+ /// However by specifiying this value manually, you can add arbitrary files outside the normal
+ /// file paths.
+ ///
+ public Dictionary DevPluginSettings { get; set; } = new();
+
+ ///
+ /// Gets or sets a list of additional locations that dev plugins should be loaded from. This can
+ /// be either a DLL or folder, but should be the absolute path, or a path relative to the currently
+ /// injected Dalamud instance.
+ ///
+ public List DevPluginLoadLocations { get; set; } = new();
+
+ ///
+ /// Gets or sets the global UI scale.
+ ///
+ public float GlobalUiScale { get; set; } = 1.0f;
+
+ ///
+ /// Gets or sets a value indicating whether or not plugin UI should be hidden.
+ ///
+ public bool ToggleUiHide { get; set; } = true;
+
+ ///
+ /// Gets or sets a value indicating whether or not plugin UI should be hidden during cutscenes.
+ ///
+ public bool ToggleUiHideDuringCutscenes { get; set; } = true;
+
+ ///
+ /// Gets or sets a value indicating whether or not plugin UI should be hidden during GPose.
+ ///
+ public bool ToggleUiHideDuringGpose { get; set; } = true;
+
+ ///
+ /// Gets or sets a value indicating whether or not a message containing detailed plugin information should be sent at login.
+ ///
+ public bool PrintPluginsWelcomeMsg { get; set; } = true;
+
+ ///
+ /// Gets or sets a value indicating whether or not plugins should be auto-updated.
+ ///
+ public bool AutoUpdatePlugins { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether or not Dalamud should add buttons to the system menu.
+ ///
+ public bool DoButtonsSystemMenu { get; set; } = true;
+
+ ///
+ /// Gets or sets the default Dalamud debug log level on startup.
+ ///
+ public LogEventLevel LogLevel { get; set; } = LogEventLevel.Information;
+
+ ///
+ /// Gets or sets a value indicating whether or not the debug log should scroll automatically.
+ ///
+ public bool LogAutoScroll { get; set; } = true;
+
+ ///
+ /// Gets or sets a value indicating whether or not the debug log should open at startup.
+ ///
+ public bool LogOpenAtStartup { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether or not ImGui asserts should be enabled at startup.
+ ///
+ public bool AssertsEnabledAtStartup { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether or not docking should be globally enabled in ImGui.
+ ///
+ public bool IsDocking { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether viewports should always be disabled.
+ ///
+ public bool IsDisableViewport { get; set; } = true;
+
+ ///
+ /// Gets or sets a value indicating whether or not navigation via a gamepad should be globally enabled in ImGui.
+ ///
+ public bool IsGamepadNavigationEnabled { get; set; } = true;
+
+ ///
+ /// Gets or sets a value indicating whether or not focus management is enabled.
+ ///
+ public bool IsFocusManagementEnabled { get; set; } = true;
+
+ ///
+ /// Gets or sets a value indicating whether or not the anti-anti-debug check is enabled on startup.
+ ///
+ public bool IsAntiAntiDebugEnabled { get; set; } = false;
+
+ ///
+ /// Gets or sets the kind of beta to download when is set to true.
+ ///
+ public string DalamudBetaKind { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether or not all plugins, regardless of API level, should be loaded.
+ ///
+ public bool LoadAllApiLevels { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether or not banned plugins should be loaded.
+ ///
+ public bool LoadBannedPlugins { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether or not any plugin should be loaded when the game is started.
+ /// It is reset immediately when read.
+ ///
+ public bool PluginSafeMode { get; set; }
+
+ ///
+ /// Gets or sets a list of saved styles.
+ ///
+ [JsonProperty("SavedStyles")]
+ public List? SavedStylesOld { get; set; }
+
+ ///
+ /// Gets or sets a list of saved styles.
+ ///
+ [JsonProperty("SavedStylesVersioned")]
+ public List? SavedStyles { get; set; }
+
+ ///
+ /// Gets or sets the name of the currently chosen style.
+ ///
+ public string ChosenStyle { get; set; } = "Dalamud Standard";
+
+ ///
+ /// Gets or sets a value indicating whether or not Dalamud RMT filtering should be disabled.
+ ///
+ public bool DisableRmtFiltering { get; set; }
+
+ ///
+ /// Load a configuration from the provided path.
+ ///
+ /// The path to load the configuration file from.
+ /// The deserialized configuration file.
+ public static DalamudConfiguration Load(string path)
+ {
+ DalamudConfiguration deserialized;
+ try
{
- TypeNameHandling = TypeNameHandling.All,
- TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
- Formatting = Formatting.Indented,
- };
-
- [JsonIgnore]
- private string configPath;
-
- ///
- /// Delegate for the event that occurs when the dalamud configuration is saved.
- ///
- /// The current dalamud configuration.
- public delegate void DalamudConfigurationSavedDelegate(DalamudConfiguration dalamudConfiguration);
-
- ///
- /// Event that occurs when dalamud configuration is saved.
- ///
- public event DalamudConfigurationSavedDelegate DalamudConfigurationSaved;
-
- ///
- /// Gets or sets a list of muted works.
- ///
- public List BadWords { get; set; }
-
- ///
- /// Gets or sets a value indicating whether or not the taskbar should flash once a duty is found.
- ///
- public bool DutyFinderTaskbarFlash { get; set; } = true;
-
- ///
- /// Gets or sets a value indicating whether or not a message should be sent in chat once a duty is found.
- ///
- public bool DutyFinderChatMessage { get; set; } = true;
-
- ///
- /// Gets or sets the language code to load Dalamud localization with.
- ///
- public string LanguageOverride { get; set; } = null;
-
- ///
- /// Gets or sets the last loaded Dalamud version.
- ///
- public string LastVersion { get; set; } = null;
-
- ///
- /// Gets or sets the last loaded Dalamud version.
- ///
- public string LastChangelogMajorMinor { get; set; } = null;
-
- ///
- /// Gets or sets the chat type used by default for plugin messages.
- ///
- public XivChatType GeneralChatType { get; set; } = XivChatType.Debug;
-
- ///
- /// Gets or sets a value indicating whether or not plugin testing builds should be shown.
- ///
- public bool DoPluginTest { get; set; } = false;
-
- ///
- /// Gets or sets a value indicating whether or not Dalamud testing builds should be used.
- ///
- public bool DoDalamudTest { get; set; } = false;
-
- ///
- /// Gets or sets a value indicating whether or not XL should download the Dalamud .NET runtime.
- ///
- public bool DoDalamudRuntime { get; set; } = false;
-
- ///
- /// Gets or sets a list of custom repos.
- ///
- public List ThirdRepoList { get; set; } = new();
-
- ///
- /// Gets or sets a list of hidden plugins.
- ///
- public List HiddenPluginInternalName { get; set; } = new();
-
- ///
- /// Gets or sets a list of seen plugins.
- ///
- public List SeenPluginInternalName { get; set; } = new();
-
- ///
- /// Gets or sets a list of additional settings for devPlugins. The key is the absolute path
- /// to the plugin DLL. This is automatically generated for any plugins in the devPlugins folder.
- /// However by specifiying this value manually, you can add arbitrary files outside the normal
- /// file paths.
- ///
- public Dictionary DevPluginSettings { get; set; } = new();
-
- ///
- /// Gets or sets a list of additional locations that dev plugins should be loaded from. This can
- /// be either a DLL or folder, but should be the absolute path, or a path relative to the currently
- /// injected Dalamud instance.
- ///
- public List DevPluginLoadLocations { get; set; } = new();
-
- ///
- /// Gets or sets the global UI scale.
- ///
- public float GlobalUiScale { get; set; } = 1.0f;
-
- ///
- /// Gets or sets a value indicating whether or not plugin UI should be hidden.
- ///
- public bool ToggleUiHide { get; set; } = true;
-
- ///
- /// Gets or sets a value indicating whether or not plugin UI should be hidden during cutscenes.
- ///
- public bool ToggleUiHideDuringCutscenes { get; set; } = true;
-
- ///
- /// Gets or sets a value indicating whether or not plugin UI should be hidden during GPose.
- ///
- public bool ToggleUiHideDuringGpose { get; set; } = true;
-
- ///
- /// Gets or sets a value indicating whether or not a message containing detailed plugin information should be sent at login.
- ///
- public bool PrintPluginsWelcomeMsg { get; set; } = true;
-
- ///
- /// Gets or sets a value indicating whether or not plugins should be auto-updated.
- ///
- public bool AutoUpdatePlugins { get; set; }
-
- ///
- /// Gets or sets a value indicating whether or not Dalamud should add buttons to the system menu.
- ///
- public bool DoButtonsSystemMenu { get; set; } = true;
-
- ///
- /// Gets or sets the default Dalamud debug log level on startup.
- ///
- public LogEventLevel LogLevel { get; set; } = LogEventLevel.Information;
-
- ///
- /// Gets or sets a value indicating whether or not the debug log should scroll automatically.
- ///
- public bool LogAutoScroll { get; set; } = true;
-
- ///
- /// Gets or sets a value indicating whether or not the debug log should open at startup.
- ///
- public bool LogOpenAtStartup { get; set; }
-
- ///
- /// Gets or sets a value indicating whether or not ImGui asserts should be enabled at startup.
- ///
- public bool AssertsEnabledAtStartup { get; set; }
-
- ///
- /// Gets or sets a value indicating whether or not docking should be globally enabled in ImGui.
- ///
- public bool IsDocking { get; set; }
-
- ///
- /// Gets or sets a value indicating whether viewports should always be disabled.
- ///
- public bool IsDisableViewport { get; set; } = true;
-
- ///
- /// Gets or sets a value indicating whether or not navigation via a gamepad should be globally enabled in ImGui.
- ///
- public bool IsGamepadNavigationEnabled { get; set; } = true;
-
- ///
- /// Gets or sets a value indicating whether or not focus management is enabled.
- ///
- public bool IsFocusManagementEnabled { get; set; } = true;
-
- ///
- /// Gets or sets a value indicating whether or not the anti-anti-debug check is enabled on startup.
- ///
- public bool IsAntiAntiDebugEnabled { get; set; } = false;
-
- ///
- /// Gets or sets the kind of beta to download when is set to true.
- ///
- public string DalamudBetaKind { get; set; }
-
- ///
- /// Gets or sets a value indicating whether or not all plugins, regardless of API level, should be loaded.
- ///
- public bool LoadAllApiLevels { get; set; }
-
- ///
- /// Gets or sets a value indicating whether or not banned plugins should be loaded.
- ///
- public bool LoadBannedPlugins { get; set; }
-
- ///
- /// Gets or sets a value indicating whether or not any plugin should be loaded when the game is started.
- /// It is reset immediately when read.
- ///
- public bool PluginSafeMode { get; set; }
-
- ///
- /// Gets or sets a list of saved styles.
- ///
- [JsonProperty("SavedStyles")]
- public List? SavedStylesOld { get; set; }
-
- ///
- /// Gets or sets a list of saved styles.
- ///
- [JsonProperty("SavedStylesVersioned")]
- public List? SavedStyles { get; set; }
-
- ///
- /// Gets or sets the name of the currently chosen style.
- ///
- public string ChosenStyle { get; set; } = "Dalamud Standard";
-
- ///
- /// Gets or sets a value indicating whether or not Dalamud RMT filtering should be disabled.
- ///
- public bool DisableRmtFiltering { get; set; }
-
- ///
- /// Load a configuration from the provided path.
- ///
- /// The path to load the configuration file from.
- /// The deserialized configuration file.
- public static DalamudConfiguration Load(string path)
+ deserialized = JsonConvert.DeserializeObject(File.ReadAllText(path), SerializerSettings);
+ }
+ catch (Exception ex)
{
- DalamudConfiguration deserialized;
- try
- {
- deserialized = JsonConvert.DeserializeObject(File.ReadAllText(path), SerializerSettings);
- }
- catch (Exception ex)
- {
- Log.Warning(ex, "Failed to load DalamudConfiguration at {0}", path);
- deserialized = new DalamudConfiguration();
- }
-
- deserialized.configPath = path;
-
- return deserialized;
+ Log.Warning(ex, "Failed to load DalamudConfiguration at {0}", path);
+ deserialized = new DalamudConfiguration();
}
- ///
- /// Save the configuration at the path it was loaded from.
- ///
- public void Save()
- {
- File.WriteAllText(this.configPath, JsonConvert.SerializeObject(this, SerializerSettings));
- this.DalamudConfigurationSaved?.Invoke(this);
- }
+ deserialized.configPath = path;
+
+ return deserialized;
+ }
+
+ ///
+ /// Save the configuration at the path it was loaded from.
+ ///
+ public void Save()
+ {
+ File.WriteAllText(this.configPath, JsonConvert.SerializeObject(this, SerializerSettings));
+ this.DalamudConfigurationSaved?.Invoke(this);
}
}
diff --git a/Dalamud/Configuration/Internal/DevPluginLocationSettings.cs b/Dalamud/Configuration/Internal/DevPluginLocationSettings.cs
index 995fb1a23..2bf34c4fa 100644
--- a/Dalamud/Configuration/Internal/DevPluginLocationSettings.cs
+++ b/Dalamud/Configuration/Internal/DevPluginLocationSettings.cs
@@ -1,24 +1,23 @@
-namespace Dalamud.Configuration
+namespace Dalamud.Configuration.Internal;
+
+///
+/// Additional locations to load dev plugins from.
+///
+internal sealed class DevPluginLocationSettings
{
///
- /// Additional locations to load dev plugins from.
+ /// Gets or sets the dev pluign path.
///
- internal sealed class DevPluginLocationSettings
- {
- ///
- /// Gets or sets the dev pluign path.
- ///
- public string Path { get; set; }
+ public string Path { get; set; }
- ///
- /// Gets or sets a value indicating whether the third party repo is enabled.
- ///
- public bool IsEnabled { get; set; }
+ ///
+ /// Gets or sets a value indicating whether the third party repo is enabled.
+ ///
+ public bool IsEnabled { get; set; }
- ///
- /// Clone this object.
- ///
- /// A shallow copy of this object.
- public DevPluginLocationSettings Clone() => this.MemberwiseClone() as DevPluginLocationSettings;
- }
+ ///
+ /// Clone this object.
+ ///
+ /// A shallow copy of this object.
+ public DevPluginLocationSettings Clone() => this.MemberwiseClone() as DevPluginLocationSettings;
}
diff --git a/Dalamud/Configuration/Internal/DevPluginSettings.cs b/Dalamud/Configuration/Internal/DevPluginSettings.cs
index 17350cba0..939b03eca 100644
--- a/Dalamud/Configuration/Internal/DevPluginSettings.cs
+++ b/Dalamud/Configuration/Internal/DevPluginSettings.cs
@@ -1,18 +1,17 @@
-namespace Dalamud.Configuration.Internal
+namespace Dalamud.Configuration.Internal;
+
+///
+/// Settings for DevPlugins.
+///
+internal sealed class DevPluginSettings
{
///
- /// Settings for DevPlugins.
+ /// Gets or sets a value indicating whether this plugin should automatically start when Dalamud boots up.
///
- internal sealed class DevPluginSettings
- {
- ///
- /// Gets or sets a value indicating whether this plugin should automatically start when Dalamud boots up.
- ///
- public bool StartOnBoot { get; set; } = true;
+ public bool StartOnBoot { get; set; } = true;
- ///
- /// Gets or sets a value indicating whether this plugin should automatically reload on file change.
- ///
- public bool AutomaticReloading { get; set; } = false;
- }
+ ///
+ /// Gets or sets a value indicating whether this plugin should automatically reload on file change.
+ ///
+ public bool AutomaticReloading { get; set; } = false;
}
diff --git a/Dalamud/Configuration/Internal/EnvironmentConfiguration.cs b/Dalamud/Configuration/Internal/EnvironmentConfiguration.cs
index 2cb89915c..42885e8e0 100644
--- a/Dalamud/Configuration/Internal/EnvironmentConfiguration.cs
+++ b/Dalamud/Configuration/Internal/EnvironmentConfiguration.cs
@@ -1,38 +1,37 @@
using System;
-namespace Dalamud.Configuration.Internal
+namespace Dalamud.Configuration.Internal;
+
+///
+/// Environmental configuration settings.
+///
+internal class EnvironmentConfiguration
{
///
- /// Environmental configuration settings.
+ /// Gets a value indicating whether the XL_WINEONLINUX setting has been enabled.
///
- internal class EnvironmentConfiguration
- {
- ///
- /// Gets a value indicating whether the XL_WINEONLINUX setting has been enabled.
- ///
- public static bool XlWineOnLinux { get; } = GetEnvironmentVariable("XL_WINEONLINUX");
+ public static bool XlWineOnLinux { get; } = GetEnvironmentVariable("XL_WINEONLINUX");
- ///
- /// Gets a value indicating whether the DALAMUD_NOT_HAVE_PLUGINS setting has been enabled.
- ///
- public static bool DalamudNoPlugins { get; } = GetEnvironmentVariable("DALAMUD_NOT_HAVE_PLUGINS");
+ ///
+ /// Gets a value indicating whether the DALAMUD_NOT_HAVE_PLUGINS setting has been enabled.
+ ///
+ public static bool DalamudNoPlugins { get; } = GetEnvironmentVariable("DALAMUD_NOT_HAVE_PLUGINS");
- ///
- /// Gets a value indicating whether the DalamudForceReloaded setting has been enabled.
- ///
- public static bool DalamudForceReloaded { get; } = GetEnvironmentVariable("DALAMUD_FORCE_RELOADED");
+ ///
+ /// Gets a value indicating whether the DalamudForceReloaded setting has been enabled.
+ ///
+ public static bool DalamudForceReloaded { get; } = GetEnvironmentVariable("DALAMUD_FORCE_RELOADED");
- ///
- /// Gets a value indicating whether the DalamudForceMinHook setting has been enabled.
- ///
- public static bool DalamudForceMinHook { get; } = GetEnvironmentVariable("DALAMUD_FORCE_MINHOOK");
+ ///
+ /// Gets a value indicating whether the DalamudForceMinHook setting has been enabled.
+ ///
+ public static bool DalamudForceMinHook { get; } = GetEnvironmentVariable("DALAMUD_FORCE_MINHOOK");
- ///
- /// Gets a value indicating whether or not Dalamud should wait for a debugger to be attached when initializing.
- ///
- public static bool DalamudWaitForDebugger { get; } = GetEnvironmentVariable("DALAMUD_WAIT_DEBUGGER");
+ ///
+ /// Gets a value indicating whether or not Dalamud should wait for a debugger to be attached when initializing.
+ ///
+ public static bool DalamudWaitForDebugger { get; } = GetEnvironmentVariable("DALAMUD_WAIT_DEBUGGER");
- private static bool GetEnvironmentVariable(string name)
- => bool.Parse(Environment.GetEnvironmentVariable(name) ?? "false");
- }
+ private static bool GetEnvironmentVariable(string name)
+ => bool.Parse(Environment.GetEnvironmentVariable(name) ?? "false");
}
diff --git a/Dalamud/Configuration/Internal/ThirdPartyRepoSettings.cs b/Dalamud/Configuration/Internal/ThirdPartyRepoSettings.cs
index cafb96a47..94bfc96e7 100644
--- a/Dalamud/Configuration/Internal/ThirdPartyRepoSettings.cs
+++ b/Dalamud/Configuration/Internal/ThirdPartyRepoSettings.cs
@@ -1,29 +1,28 @@
-namespace Dalamud.Configuration
+namespace Dalamud.Configuration.Internal;
+
+///
+/// Third party repository for dalamud plugins.
+///
+internal sealed class ThirdPartyRepoSettings
{
///
- /// Third party repository for dalamud plugins.
+ /// Gets or sets the third party repo url.
///
- internal sealed class ThirdPartyRepoSettings
- {
- ///
- /// Gets or sets the third party repo url.
- ///
- public string Url { get; set; }
+ public string Url { get; set; }
- ///
- /// Gets or sets a value indicating whether the third party repo is enabled.
- ///
- public bool IsEnabled { get; set; }
+ ///
+ /// Gets or sets a value indicating whether the third party repo is enabled.
+ ///
+ public bool IsEnabled { get; set; }
- ///
- /// Gets or sets a short name for the repo url.
- ///
- public string Name { get; set; }
+ ///
+ /// Gets or sets a short name for the repo url.
+ ///
+ public string Name { get; set; }
- ///
- /// Clone this object.
- ///
- /// A shallow copy of this object.
- public ThirdPartyRepoSettings Clone() => this.MemberwiseClone() as ThirdPartyRepoSettings;
- }
+ ///
+ /// Clone this object.
+ ///
+ /// A shallow copy of this object.
+ public ThirdPartyRepoSettings Clone() => this.MemberwiseClone() as ThirdPartyRepoSettings;
}
diff --git a/Dalamud/Configuration/PluginConfigurations.cs b/Dalamud/Configuration/PluginConfigurations.cs
index faa01af99..349d51e57 100644
--- a/Dalamud/Configuration/PluginConfigurations.cs
+++ b/Dalamud/Configuration/PluginConfigurations.cs
@@ -2,129 +2,128 @@ using System.IO;
using Newtonsoft.Json;
-namespace Dalamud.Configuration
+namespace Dalamud.Configuration;
+
+///
+/// Configuration to store settings for a dalamud plugin.
+///
+public sealed class PluginConfigurations
{
+ private readonly DirectoryInfo configDirectory;
+
///
- /// Configuration to store settings for a dalamud plugin.
+ /// Initializes a new instance of the class.
///
- public sealed class PluginConfigurations
+ /// Directory for storage of plugin configuration files.
+ public PluginConfigurations(string storageFolder)
{
- private readonly DirectoryInfo configDirectory;
+ this.configDirectory = new DirectoryInfo(storageFolder);
+ this.configDirectory.Create();
+ }
- ///
- /// Initializes a new instance of the class.
- ///
- /// Directory for storage of plugin configuration files.
- public PluginConfigurations(string storageFolder)
+ ///
+ /// Save/Load plugin configuration.
+ /// NOTE: Save/Load are still using Type information for now,
+ /// despite LoadForType superseding Load and not requiring or using it.
+ /// It might be worth removing the Type info from Save, to strip it from all future saved configs,
+ /// and then Load() can probably be removed entirely.
+ ///
+ /// Plugin configuration.
+ /// Plugin name.
+ public void Save(IPluginConfiguration config, string pluginName)
+ {
+ File.WriteAllText(this.GetConfigFile(pluginName).FullName, JsonConvert.SerializeObject(config, Formatting.Indented, new JsonSerializerSettings
{
- this.configDirectory = new DirectoryInfo(storageFolder);
- this.configDirectory.Create();
- }
+ TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
+ TypeNameHandling = TypeNameHandling.Objects,
+ }));
+ }
- ///
- /// Save/Load plugin configuration.
- /// NOTE: Save/Load are still using Type information for now,
- /// despite LoadForType superseding Load and not requiring or using it.
- /// It might be worth removing the Type info from Save, to strip it from all future saved configs,
- /// and then Load() can probably be removed entirely.
- ///
- /// Plugin configuration.
- /// Plugin name.
- public void Save(IPluginConfiguration config, string pluginName)
- {
- File.WriteAllText(this.GetConfigFile(pluginName).FullName, JsonConvert.SerializeObject(config, Formatting.Indented, new JsonSerializerSettings
+ ///
+ /// Load plugin configuration.
+ ///
+ /// Plugin name.
+ /// Plugin configuration.
+ public IPluginConfiguration? Load(string pluginName)
+ {
+ var path = this.GetConfigFile(pluginName);
+
+ if (!path.Exists)
+ return null;
+
+ return JsonConvert.DeserializeObject(
+ File.ReadAllText(path.FullName),
+ new JsonSerializerSettings
{
TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
TypeNameHandling = TypeNameHandling.Objects,
- }));
- }
-
- ///
- /// Load plugin configuration.
- ///
- /// Plugin name.
- /// Plugin configuration.
- public IPluginConfiguration? Load(string pluginName)
- {
- var path = this.GetConfigFile(pluginName);
-
- if (!path.Exists)
- return null;
-
- return JsonConvert.DeserializeObject(
- File.ReadAllText(path.FullName),
- new JsonSerializerSettings
- {
- TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
- TypeNameHandling = TypeNameHandling.Objects,
- });
- }
-
- ///
- /// Delete the configuration file and folder for the specified plugin.
- /// This will throw an if the plugin did not correctly close its handles.
- ///
- /// The name of the plugin.
- public void Delete(string pluginName)
- {
- var directory = this.GetDirectoryPath(pluginName);
- if (directory.Exists)
- directory.Delete(true);
-
- var file = this.GetConfigFile(pluginName);
- if (file.Exists)
- file.Delete();
- }
-
- ///
- /// Get plugin directory.
- ///
- /// Plugin name.
- /// Plugin directory path.
- public string GetDirectory(string pluginName)
- {
- try
- {
- var path = this.GetDirectoryPath(pluginName);
- if (!path.Exists)
- {
- path.Create();
- }
-
- return path.FullName;
- }
- catch
- {
- return string.Empty;
- }
- }
-
- ///
- /// Load Plugin configuration. Parameterized deserialization.
- /// Currently this is called via reflection from DalamudPluginInterface.GetPluginConfig().
- /// Eventually there may be an additional pluginInterface method that can call this directly
- /// without reflection - for now this is in support of the existing plugin api.
- ///
- /// Plugin Name.
- /// Configuration Type.
- /// Plugin Configuration.
- public T LoadForType(string pluginName) where T : IPluginConfiguration
- {
- var path = this.GetConfigFile(pluginName);
-
- return !path.Exists ? default : JsonConvert.DeserializeObject(File.ReadAllText(path.FullName));
-
- // intentionally no type handling - it will break when updating a plugin at runtime
- // and turns out to be unnecessary when we fully qualify the object type
- }
-
- ///
- /// Get FileInfo to plugin config file.
- ///
- /// InternalName of the plugin.
- /// FileInfo of the config file.
- public FileInfo GetConfigFile(string pluginName) => new(Path.Combine(this.configDirectory.FullName, $"{pluginName}.json"));
-
- private DirectoryInfo GetDirectoryPath(string pluginName) => new(Path.Combine(this.configDirectory.FullName, pluginName));
+ });
}
+
+ ///
+ /// Delete the configuration file and folder for the specified plugin.
+ /// This will throw an if the plugin did not correctly close its handles.
+ ///
+ /// The name of the plugin.
+ public void Delete(string pluginName)
+ {
+ var directory = this.GetDirectoryPath(pluginName);
+ if (directory.Exists)
+ directory.Delete(true);
+
+ var file = this.GetConfigFile(pluginName);
+ if (file.Exists)
+ file.Delete();
+ }
+
+ ///
+ /// Get plugin directory.
+ ///
+ /// Plugin name.
+ /// Plugin directory path.
+ public string GetDirectory(string pluginName)
+ {
+ try
+ {
+ var path = this.GetDirectoryPath(pluginName);
+ if (!path.Exists)
+ {
+ path.Create();
+ }
+
+ return path.FullName;
+ }
+ catch
+ {
+ return string.Empty;
+ }
+ }
+
+ ///
+ /// Load Plugin configuration. Parameterized deserialization.
+ /// Currently this is called via reflection from DalamudPluginInterface.GetPluginConfig().
+ /// Eventually there may be an additional pluginInterface method that can call this directly
+ /// without reflection - for now this is in support of the existing plugin api.
+ ///
+ /// Plugin Name.
+ /// Configuration Type.
+ /// Plugin Configuration.
+ public T LoadForType(string pluginName) where T : IPluginConfiguration
+ {
+ var path = this.GetConfigFile(pluginName);
+
+ return !path.Exists ? default : JsonConvert.DeserializeObject(File.ReadAllText(path.FullName));
+
+ // intentionally no type handling - it will break when updating a plugin at runtime
+ // and turns out to be unnecessary when we fully qualify the object type
+ }
+
+ ///
+ /// Get FileInfo to plugin config file.
+ ///
+ /// InternalName of the plugin.
+ /// FileInfo of the config file.
+ public FileInfo GetConfigFile(string pluginName) => new(Path.Combine(this.configDirectory.FullName, $"{pluginName}.json"));
+
+ private DirectoryInfo GetDirectoryPath(string pluginName) => new(Path.Combine(this.configDirectory.FullName, pluginName));
}
diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs
index f5460af2f..eaf325ebf 100644
--- a/Dalamud/Dalamud.cs
+++ b/Dalamud/Dalamud.cs
@@ -33,379 +33,378 @@ using Serilog.Events;
[assembly: InternalsVisibleTo("Dalamud.Test")]
-namespace Dalamud
+namespace Dalamud;
+
+///
+/// The main Dalamud class containing all subsystems.
+///
+internal sealed class Dalamud : IDisposable
{
+ #region Internals
+
+ private readonly ManualResetEvent unloadSignal;
+ private readonly ManualResetEvent finishUnloadSignal;
+ private MonoMod.RuntimeDetour.Hook processMonoHook;
+ private bool hasDisposedPlugins = false;
+
+ #endregion
+
///
- /// The main Dalamud class containing all subsystems.
+ /// Initializes a new instance of the class.
///
- internal sealed class Dalamud : IDisposable
+ /// DalamudStartInfo instance.
+ /// LoggingLevelSwitch to control Serilog level.
+ /// Signal signalling shutdown.
+ /// The Dalamud configuration.
+ public Dalamud(DalamudStartInfo info, LoggingLevelSwitch loggingLevelSwitch, ManualResetEvent finishSignal, DalamudConfiguration configuration)
{
- #region Internals
+ this.ApplyProcessPatch();
- private readonly ManualResetEvent unloadSignal;
- private readonly ManualResetEvent finishUnloadSignal;
- private MonoMod.RuntimeDetour.Hook processMonoHook;
- private bool hasDisposedPlugins = false;
+ Service.Set(this);
+ Service.Set(info);
+ Service.Set(configuration);
- #endregion
+ this.LogLevelSwitch = loggingLevelSwitch;
- ///
- /// Initializes a new instance of the class.
- ///
- /// DalamudStartInfo instance.
- /// LoggingLevelSwitch to control Serilog level.
- /// Signal signalling shutdown.
- /// The Dalamud configuration.
- public Dalamud(DalamudStartInfo info, LoggingLevelSwitch loggingLevelSwitch, ManualResetEvent finishSignal, DalamudConfiguration configuration)
+ this.unloadSignal = new ManualResetEvent(false);
+ this.unloadSignal.Reset();
+
+ this.finishUnloadSignal = finishSignal;
+ this.finishUnloadSignal.Reset();
+ }
+
+ ///
+ /// Gets LoggingLevelSwitch for Dalamud and Plugin logs.
+ ///
+ internal LoggingLevelSwitch LogLevelSwitch { get; private set; }
+
+ ///
+ /// Gets location of stored assets.
+ ///
+ internal DirectoryInfo AssetDirectory => new(Service.Get().AssetDirectory);
+
+ ///
+ /// Runs tier 1 of the Dalamud initialization process.
+ ///
+ public void LoadTier1()
+ {
+ try
{
- this.ApplyProcessPatch();
+ SerilogEventSink.Instance.LogLine += SerilogOnLogLine;
- Service.Set(this);
- Service.Set(info);
- Service.Set(configuration);
+ Service.Set();
- this.LogLevelSwitch = loggingLevelSwitch;
+ // Initialize the process information.
+ Service.Set(new SigScanner(true));
+ Service.Set();
- this.unloadSignal = new ManualResetEvent(false);
- this.unloadSignal.Reset();
+ // Initialize FFXIVClientStructs function resolver
+ FFXIVClientStructs.Resolver.Initialize();
+ Log.Information("[T1] FFXIVClientStructs initialized!");
- this.finishUnloadSignal = finishSignal;
- this.finishUnloadSignal.Reset();
- }
-
- ///
- /// Gets LoggingLevelSwitch for Dalamud and Plugin logs.
- ///
- internal LoggingLevelSwitch LogLevelSwitch { get; private set; }
-
- ///
- /// Gets location of stored assets.
- ///
- internal DirectoryInfo AssetDirectory => new(Service.Get().AssetDirectory);
-
- ///
- /// Runs tier 1 of the Dalamud initialization process.
- ///
- public void LoadTier1()
- {
- try
- {
- SerilogEventSink.Instance.LogLine += SerilogOnLogLine;
-
- Service.Set();
-
- // Initialize the process information.
- Service.Set(new SigScanner(true));
- Service.Set();
-
- // Initialize FFXIVClientStructs function resolver
- FFXIVClientStructs.Resolver.Initialize();
- Log.Information("[T1] FFXIVClientStructs initialized!");
-
- // Initialize game subsystem
- var framework = Service.Set();
- Log.Information("[T1] Framework OK!");
+ // Initialize game subsystem
+ var framework = Service.Set();
+ Log.Information("[T1] Framework OK!");
#if DEBUG
- Service.Set();
- Log.Information("[T1] TaskTracker OK!");
+ Service.Set();
+ Log.Information("[T1] TaskTracker OK!");
#endif
- Service.Set();
- Service.Set();
+ Service.Set();
+ Service.Set();
- framework.Enable();
+ framework.Enable();
- Log.Information("[T1] Load complete!");
- }
- catch (Exception ex)
- {
- Log.Error(ex, "Tier 1 load failed.");
- this.Unload();
- }
+ Log.Information("[T1] Load complete!");
}
-
- ///
- /// Runs tier 2 of the Dalamud initialization process.
- ///
- /// Whether or not the load succeeded.
- public bool LoadTier2()
+ catch (Exception ex)
{
- try
- {
- var configuration = Service.Get();
+ Log.Error(ex, "Tier 1 load failed.");
+ this.Unload();
+ }
+ }
- var antiDebug = Service.Set();
- if (!antiDebug.IsEnabled)
- {
+ ///
+ /// Runs tier 2 of the Dalamud initialization process.
+ ///
+ /// Whether or not the load succeeded.
+ public bool LoadTier2()
+ {
+ try
+ {
+ var configuration = Service.Get();
+
+ var antiDebug = Service.Set();
+ if (!antiDebug.IsEnabled)
+ {
#if DEBUG
- antiDebug.Enable();
+ antiDebug.Enable();
#else
if (configuration.IsAntiAntiDebugEnabled)
antiDebug.Enable();
#endif
- }
+ }
- Log.Information("[T2] AntiDebug OK!");
+ Log.Information("[T2] AntiDebug OK!");
- Service.Set();
- Log.Information("[T2] WinSock OK!");
+ Service.Set();
+ Log.Information("[T2] WinSock OK!");
- Service.Set();
- Log.Information("[T2] NH OK!");
+ Service.Set();
+ Log.Information("[T2] NH OK!");
- try
- {
- Service.Set().Initialize(this.AssetDirectory.FullName);
- }
- catch (Exception e)
- {
- Log.Error(e, "Could not initialize DataManager.");
- this.Unload();
- return false;
- }
+ try
+ {
+ Service.Set().Initialize(this.AssetDirectory.FullName);
+ }
+ catch (Exception e)
+ {
+ Log.Error(e, "Could not initialize DataManager.");
+ this.Unload();
+ return false;
+ }
- Log.Information("[T2] Data OK!");
+ Log.Information("[T2] Data OK!");
- var clientState = Service.Set();
- Log.Information("[T2] CS OK!");
+ var clientState = Service.Set();
+ Log.Information("[T2] CS OK!");
- var localization = Service.Set(new Localization(Path.Combine(this.AssetDirectory.FullName, "UIRes", "loc", "dalamud"), "dalamud_"));
- if (!string.IsNullOrEmpty(configuration.LanguageOverride))
- {
- localization.SetupWithLangCode(configuration.LanguageOverride);
- }
- else
- {
- localization.SetupWithUiCulture();
- }
+ var localization = Service.Set(new Localization(Path.Combine(this.AssetDirectory.FullName, "UIRes", "loc", "dalamud"), "dalamud_"));
+ if (!string.IsNullOrEmpty(configuration.LanguageOverride))
+ {
+ localization.SetupWithLangCode(configuration.LanguageOverride);
+ }
+ else
+ {
+ localization.SetupWithUiCulture();
+ }
- Log.Information("[T2] LOC OK!");
+ Log.Information("[T2] LOC OK!");
- // This is enabled in ImGuiScene setup
- Service.Set();
- Log.Information("[T2] IME OK!");
+ // This is enabled in ImGuiScene setup
+ Service.Set();
+ Log.Information("[T2] IME OK!");
- Service.Set().Enable();
- Log.Information("[T2] IM OK!");
+ Service.Set().Enable();
+ Log.Information("[T2] IM OK!");
#pragma warning disable CS0618 // Type or member is obsolete
- Service.Set();
+ Service.Set();
#pragma warning restore CS0618 // Type or member is obsolete
- Log.Information("[T2] SeString OK!");
+ Log.Information("[T2] SeString OK!");
- // Initialize managers. Basically handlers for the logic
- Service.Set();
+ // Initialize managers. Basically handlers for the logic
+ Service.Set();
- Service.Set().SetupCommands();
+ Service.Set().SetupCommands();
- Log.Information("[T2] CM OK!");
+ Log.Information("[T2] CM OK!");
- Service.Set();
+ Service.Set();
- Log.Information("[T2] CH OK!");
+ Log.Information("[T2] CH OK!");
- clientState.Enable();
- Log.Information("[T2] CS ENABLE!");
+ clientState.Enable();
+ Log.Information("[T2] CS ENABLE!");
- Service.Set().Enable();
+ Service.Set().Enable();
- Log.Information("[T2] Load complete!");
- }
- catch (Exception ex)
- {
- Log.Error(ex, "Tier 2 load failed.");
- this.Unload();
- return false;
- }
-
- return true;
+ Log.Information("[T2] Load complete!");
+ }
+ catch (Exception ex)
+ {
+ Log.Error(ex, "Tier 2 load failed.");
+ this.Unload();
+ return false;
}
- ///
- /// Runs tier 3 of the Dalamud initialization process.
- ///
- /// Whether or not the load succeeded.
- public bool LoadTier3()
+ return true;
+ }
+
+ ///
+ /// Runs tier 3 of the Dalamud initialization process.
+ ///
+ /// Whether or not the load succeeded.
+ public bool LoadTier3()
+ {
+ try
{
+ Log.Information("[T3] START!");
+
+ var pluginManager = Service.Set();
+ Service.Set();
+
try
{
- Log.Information("[T3] START!");
+ _ = pluginManager.SetPluginReposFromConfigAsync(false);
- var pluginManager = Service.Set();
- Service.Set();
+ pluginManager.OnInstalledPluginsChanged += Troubleshooting.LogTroubleshooting;
- try
- {
- _ = pluginManager.SetPluginReposFromConfigAsync(false);
+ Log.Information("[T3] PM OK!");
- pluginManager.OnInstalledPluginsChanged += Troubleshooting.LogTroubleshooting;
+ pluginManager.CleanupPlugins();
+ Log.Information("[T3] PMC OK!");
- Log.Information("[T3] PM OK!");
-
- pluginManager.CleanupPlugins();
- Log.Information("[T3] PMC OK!");
-
- pluginManager.LoadAllPlugins();
- Log.Information("[T3] PML OK!");
- }
- catch (Exception ex)
- {
- Log.Error(ex, "Plugin load failed.");
- }
-
- Service.Set();
- Log.Information("[T3] DUI OK!");
-
- Troubleshooting.LogTroubleshooting();
-
- Log.Information("Dalamud is ready.");
+ pluginManager.LoadAllPlugins();
+ Log.Information("[T3] PML OK!");
}
catch (Exception ex)
{
- Log.Error(ex, "Tier 3 load failed.");
- this.Unload();
-
- return false;
+ Log.Error(ex, "Plugin load failed.");
}
- return true;
+ Service.Set();
+ Log.Information("[T3] DUI OK!");
+
+ Troubleshooting.LogTroubleshooting();
+
+ Log.Information("Dalamud is ready.");
+ }
+ catch (Exception ex)
+ {
+ Log.Error(ex, "Tier 3 load failed.");
+ this.Unload();
+
+ return false;
}
- ///
- /// Queue an unload of Dalamud when it gets the chance.
- ///
- public void Unload()
+ return true;
+ }
+
+ ///
+ /// Queue an unload of Dalamud when it gets the chance.
+ ///
+ public void Unload()
+ {
+ Log.Information("Trigger unload");
+ this.unloadSignal.Set();
+ }
+
+ ///
+ /// Wait for an unload request to start.
+ ///
+ public void WaitForUnload()
+ {
+ this.unloadSignal.WaitOne();
+ }
+
+ ///
+ /// Wait for a queued unload to be finalized.
+ ///
+ public void WaitForUnloadFinish()
+ {
+ this.finishUnloadSignal?.WaitOne();
+ }
+
+ ///
+ /// Dispose subsystems related to plugin handling.
+ ///
+ public void DisposePlugins()
+ {
+ this.hasDisposedPlugins = true;
+
+ // this must be done before unloading interface manager, in order to do rebuild
+ // the correct cascaded WndProc (IME -> RawDX11Scene -> Game). Otherwise the game
+ // will not receive any windows messages
+ Service.GetNullable()?.Dispose();
+
+ // this must be done before unloading plugins, or it can cause a race condition
+ // due to rendering happening on another thread, where a plugin might receive
+ // a render call after it has been disposed, which can crash if it attempts to
+ // use any resources that it freed in its own Dispose method
+ Service.GetNullable()?.Dispose();
+
+ Service.GetNullable()?.Dispose();
+
+ Service.GetNullable()?.Dispose();
+ }
+
+ ///
+ /// Dispose Dalamud subsystems.
+ ///
+ public void Dispose()
+ {
+ try
{
- Log.Information("Trigger unload");
- this.unloadSignal.Set();
- }
-
- ///
- /// Wait for an unload request to start.
- ///
- public void WaitForUnload()
- {
- this.unloadSignal.WaitOne();
- }
-
- ///
- /// Wait for a queued unload to be finalized.
- ///
- public void WaitForUnloadFinish()
- {
- this.finishUnloadSignal?.WaitOne();
- }
-
- ///
- /// Dispose subsystems related to plugin handling.
- ///
- public void DisposePlugins()
- {
- this.hasDisposedPlugins = true;
-
- // this must be done before unloading interface manager, in order to do rebuild
- // the correct cascaded WndProc (IME -> RawDX11Scene -> Game). Otherwise the game
- // will not receive any windows messages
- Service.GetNullable()?.Dispose();
-
- // this must be done before unloading plugins, or it can cause a race condition
- // due to rendering happening on another thread, where a plugin might receive
- // a render call after it has been disposed, which can crash if it attempts to
- // use any resources that it freed in its own Dispose method
- Service.GetNullable()?.Dispose();
-
- Service.GetNullable()?.Dispose();
-
- Service.GetNullable()?.Dispose();
- }
-
- ///
- /// Dispose Dalamud subsystems.
- ///
- public void Dispose()
- {
- try
+ if (!this.hasDisposedPlugins)
{
- if (!this.hasDisposedPlugins)
- {
- this.DisposePlugins();
- Thread.Sleep(100);
- }
-
- Service.GetNullable()?.Dispose();
- Service.GetNullable()?.Dispose();
-
- this.unloadSignal?.Dispose();
-
- Service.GetNullable()?.Dispose();
- Service.GetNullable()?.Dispose();
- Service.GetNullable()?.Dispose();
- Service.GetNullable()?.Dispose();
- Service.GetNullable()?.Dispose();
- Service.GetNullable()?.Dispose();
-
- SerilogEventSink.Instance.LogLine -= SerilogOnLogLine;
-
- this.processMonoHook?.Dispose();
-
- Log.Debug("Dalamud::Dispose() OK!");
- }
- catch (Exception ex)
- {
- Log.Error(ex, "Dalamud::Dispose() failed.");
- }
- }
-
- ///
- /// Replace the built-in exception handler with a debug one.
- ///
- internal void ReplaceExceptionHandler()
- {
- var releaseSig = "40 55 53 56 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 85 ?? ?? ?? ?? 48 83 3D ?? ?? ?? ?? ??";
- var releaseFilter = Service.Get().ScanText(releaseSig);
- Log.Debug($"SE debug filter at {releaseFilter.ToInt64():X}");
-
- var oldFilter = NativeFunctions.SetUnhandledExceptionFilter(releaseFilter);
- Log.Debug("Reset ExceptionFilter, old: {0}", oldFilter);
- }
-
- private static void SerilogOnLogLine(object? sender, (string Line, LogEventLevel Level, DateTimeOffset TimeStamp, Exception? Exception) e)
- {
- if (e.Exception == null)
- return;
-
- Troubleshooting.LogException(e.Exception, e.Line);
- }
-
- ///
- /// Patch method for the class Process.Handle. This patch facilitates fixing Reloaded so that it
- /// uses pseudo-handles to access memory, to prevent permission errors.
- /// It should never be called manually.
- ///
- /// A delegate that acts as the original method.
- /// The equivalent of `this`.
- /// A pseudo-handle for the current process, or the result from the original method.
- private static IntPtr ProcessHandlePatch(Func orig, Process self)
- {
- var result = orig(self);
-
- if (self.Id == Environment.ProcessId)
- {
- result = (IntPtr)0xFFFFFFFF;
+ this.DisposePlugins();
+ Thread.Sleep(100);
}
- // Log.Verbose($"Process.Handle // {self.ProcessName} // {result:X}");
- return result;
+ Service.GetNullable()?.Dispose();
+ Service.GetNullable()?.Dispose();
+
+ this.unloadSignal?.Dispose();
+
+ Service.GetNullable()?.Dispose();
+ Service.GetNullable()?.Dispose();
+ Service.GetNullable()?.Dispose();
+ Service.GetNullable()?.Dispose();
+ Service.GetNullable()?.Dispose();
+ Service.GetNullable()?.Dispose();
+
+ SerilogEventSink.Instance.LogLine -= SerilogOnLogLine;
+
+ this.processMonoHook?.Dispose();
+
+ Log.Debug("Dalamud::Dispose() OK!");
}
-
- private void ApplyProcessPatch()
+ catch (Exception ex)
{
- var targetType = typeof(Process);
-
- var handleTarget = targetType.GetProperty(nameof(Process.Handle)).GetGetMethod();
- var handlePatch = typeof(Dalamud).GetMethod(nameof(Dalamud.ProcessHandlePatch), BindingFlags.NonPublic | BindingFlags.Static);
- this.processMonoHook = new MonoMod.RuntimeDetour.Hook(handleTarget, handlePatch);
+ Log.Error(ex, "Dalamud::Dispose() failed.");
}
}
+
+ ///
+ /// Replace the built-in exception handler with a debug one.
+ ///
+ internal void ReplaceExceptionHandler()
+ {
+ var releaseSig = "40 55 53 56 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 85 ?? ?? ?? ?? 48 83 3D ?? ?? ?? ?? ??";
+ var releaseFilter = Service.Get().ScanText(releaseSig);
+ Log.Debug($"SE debug filter at {releaseFilter.ToInt64():X}");
+
+ var oldFilter = NativeFunctions.SetUnhandledExceptionFilter(releaseFilter);
+ Log.Debug("Reset ExceptionFilter, old: {0}", oldFilter);
+ }
+
+ private static void SerilogOnLogLine(object? sender, (string Line, LogEventLevel Level, DateTimeOffset TimeStamp, Exception? Exception) e)
+ {
+ if (e.Exception == null)
+ return;
+
+ Troubleshooting.LogException(e.Exception, e.Line);
+ }
+
+ ///
+ /// Patch method for the class Process.Handle. This patch facilitates fixing Reloaded so that it
+ /// uses pseudo-handles to access memory, to prevent permission errors.
+ /// It should never be called manually.
+ ///
+ /// A delegate that acts as the original method.
+ /// The equivalent of `this`.
+ /// A pseudo-handle for the current process, or the result from the original method.
+ private static IntPtr ProcessHandlePatch(Func orig, Process self)
+ {
+ var result = orig(self);
+
+ if (self.Id == Environment.ProcessId)
+ {
+ result = (IntPtr)0xFFFFFFFF;
+ }
+
+ // Log.Verbose($"Process.Handle // {self.ProcessName} // {result:X}");
+ return result;
+ }
+
+ private void ApplyProcessPatch()
+ {
+ var targetType = typeof(Process);
+
+ var handleTarget = targetType.GetProperty(nameof(Process.Handle)).GetGetMethod();
+ var handlePatch = typeof(Dalamud).GetMethod(nameof(Dalamud.ProcessHandlePatch), BindingFlags.NonPublic | BindingFlags.Static);
+ this.processMonoHook = new MonoMod.RuntimeDetour.Hook(handleTarget, handlePatch);
+ }
}
diff --git a/Dalamud/DalamudStartInfo.cs b/Dalamud/DalamudStartInfo.cs
index 891a57dca..fbdcd3588 100644
--- a/Dalamud/DalamudStartInfo.cs
+++ b/Dalamud/DalamudStartInfo.cs
@@ -3,58 +3,57 @@ using System;
using Dalamud.Game;
using Newtonsoft.Json;
-namespace Dalamud
+namespace Dalamud;
+
+///
+/// Struct containing information needed to initialize Dalamud.
+///
+[Serializable]
+public record DalamudStartInfo
{
///
- /// Struct containing information needed to initialize Dalamud.
+ /// Gets or sets the working directory of the XIVLauncher installations.
///
- [Serializable]
- public record DalamudStartInfo
- {
- ///
- /// Gets or sets the working directory of the XIVLauncher installations.
- ///
- public string WorkingDirectory { get; set; }
+ public string WorkingDirectory { get; set; }
- ///
- /// Gets the path to the configuration file.
- ///
- public string ConfigurationPath { get; init; }
+ ///
+ /// Gets the path to the configuration file.
+ ///
+ public string ConfigurationPath { get; init; }
- ///
- /// Gets the path to the directory for installed plugins.
- ///
- public string PluginDirectory { get; init; }
+ ///
+ /// Gets the path to the directory for installed plugins.
+ ///
+ public string PluginDirectory { get; init; }
- ///
- /// Gets the path to the directory for developer plugins.
- ///
- public string DefaultPluginDirectory { get; init; }
+ ///
+ /// Gets the path to the directory for developer plugins.
+ ///
+ public string DefaultPluginDirectory { get; init; }
- ///
- /// Gets the path to core Dalamud assets.
- ///
- public string AssetDirectory { get; init; }
+ ///
+ /// Gets the path to core Dalamud assets.
+ ///
+ public string AssetDirectory { get; init; }
- ///
- /// Gets the language of the game client.
- ///
- public ClientLanguage Language { get; init; }
+ ///
+ /// Gets the language of the game client.
+ ///
+ public ClientLanguage Language { get; init; }
- ///
- /// Gets the current game version code.
- ///
- [JsonConverter(typeof(GameVersionConverter))]
- public GameVersion GameVersion { get; init; }
+ ///
+ /// Gets the current game version code.
+ ///
+ [JsonConverter(typeof(GameVersionConverter))]
+ public GameVersion GameVersion { get; init; }
- ///
- /// Gets a value indicating whether or not market board information should be uploaded by default.
- ///
- public bool OptOutMbCollection { get; init; }
+ ///
+ /// Gets a value indicating whether or not market board information should be uploaded by default.
+ ///
+ public bool OptOutMbCollection { get; init; }
- ///
- /// Gets a value that specifies how much to wait before a new Dalamud session.
- ///
- public int DelayInitializeMs { get; init; } = 0;
- }
+ ///
+ /// Gets a value that specifies how much to wait before a new Dalamud session.
+ ///
+ public int DelayInitializeMs { get; init; } = 0;
}
diff --git a/Dalamud/Data/DataManager.cs b/Dalamud/Data/DataManager.cs
index a78f0eec3..61f701055 100644
--- a/Dalamud/Data/DataManager.cs
+++ b/Dalamud/Data/DataManager.cs
@@ -18,330 +18,329 @@ using Lumina.Excel;
using Newtonsoft.Json;
using Serilog;
-namespace Dalamud.Data
+namespace Dalamud.Data;
+
+///
+/// This class provides data for Dalamud-internal features, but can also be used by plugins if needed.
+///
+[PluginInterface]
+[InterfaceVersion("1.0")]
+public sealed class DataManager : IDisposable
{
+ private const string IconFileFormat = "ui/icon/{0:D3}000/{1}{2:D6}.tex";
+
+ private Thread luminaResourceThread;
+ private CancellationTokenSource luminaCancellationTokenSource;
+
///
- /// This class provides data for Dalamud-internal features, but can also be used by plugins if needed.
+ /// Initializes a new instance of the class.
///
- [PluginInterface]
- [InterfaceVersion("1.0")]
- public sealed class DataManager : IDisposable
+ internal DataManager()
{
- private const string IconFileFormat = "ui/icon/{0:D3}000/{1}{2:D6}.tex";
+ this.Language = Service.Get().Language;
- private Thread luminaResourceThread;
- private CancellationTokenSource luminaCancellationTokenSource;
+ // Set up default values so plugins do not null-reference when data is being loaded.
+ this.ClientOpCodes = this.ServerOpCodes = new ReadOnlyDictionary(new Dictionary());
+ }
- ///
- /// Initializes a new instance of the class.
- ///
- internal DataManager()
+ ///
+ /// Gets the current game client language.
+ ///
+ public ClientLanguage Language { get; private set; }
+
+ ///
+ /// Gets the OpCodes sent by the server to the client.
+ ///
+ public ReadOnlyDictionary ServerOpCodes { get; private set; }
+
+ ///
+ /// Gets the OpCodes sent by the client to the server.
+ ///
+ [UsedImplicitly]
+ public ReadOnlyDictionary ClientOpCodes { get; private set; }
+
+ ///
+ /// Gets a object which gives access to any excel/game data.
+ ///
+ public GameData GameData { get; private set; }
+
+ ///
+ /// Gets an object which gives access to any of the game's sheet data.
+ ///
+ public ExcelModule Excel => this.GameData?.Excel;
+
+ ///
+ /// Gets a value indicating whether Game Data is ready to be read.
+ ///
+ public bool IsDataReady { get; private set; }
+
+ #region Lumina Wrappers
+
+ ///
+ /// Get an with the given Excel sheet row type.
+ ///
+ /// The excel sheet type to get.
+ /// The , giving access to game rows.
+ public ExcelSheet? GetExcelSheet() where T : ExcelRow
+ {
+ return this.Excel.GetSheet();
+ }
+
+ ///
+ /// Get an with the given Excel sheet row type with a specified language.
+ ///
+ /// Language of the sheet to get.
+ /// The excel sheet type to get.
+ /// The , giving access to game rows.
+ public ExcelSheet? GetExcelSheet(ClientLanguage language) where T : ExcelRow
+ {
+ return this.Excel.GetSheet(language.ToLumina());
+ }
+
+ ///
+ /// Get a with the given path.
+ ///
+ /// The path inside of the game files.
+ /// The of the file.
+ public FileResource? GetFile(string path)
+ {
+ return this.GetFile(path);
+ }
+
+ ///
+ /// Get a with the given path, of the given type.
+ ///
+ /// The type of resource.
+ /// The path inside of the game files.
+ /// The of the file.
+ public T? GetFile(string path) where T : FileResource
+ {
+ var filePath = GameData.ParseFilePath(path);
+ if (filePath == null)
+ return default;
+ return this.GameData.Repositories.TryGetValue(filePath.Repository, out var repository) ? repository.GetFile(filePath.Category, filePath) : default;
+ }
+
+ ///
+ /// Check if the file with the given path exists within the game's index files.
+ ///
+ /// The path inside of the game files.
+ /// True if the file exists.
+ public bool FileExists(string path)
+ {
+ return this.GameData.FileExists(path);
+ }
+
+ ///
+ /// Get a containing the icon with the given ID.
+ ///
+ /// The icon ID.
+ /// The containing the icon.
+ public TexFile? GetIcon(uint iconId)
+ {
+ return this.GetIcon(this.Language, iconId);
+ }
+
+ ///
+ /// Get a containing the icon with the given ID, of the given quality.
+ ///
+ /// A value indicating whether the icon should be HQ.
+ /// The icon ID.
+ /// The containing the icon.
+ public TexFile? GetIcon(bool isHq, uint iconId)
+ {
+ var type = isHq ? "hq/" : string.Empty;
+ return this.GetIcon(type, iconId);
+ }
+
+ ///
+ /// Get a containing the icon with the given ID, of the given language.
+ ///
+ /// The requested language.
+ /// The icon ID.
+ /// The containing the icon.
+ public TexFile? GetIcon(ClientLanguage iconLanguage, uint iconId)
+ {
+ var type = iconLanguage switch
{
- this.Language = Service.Get().Language;
+ ClientLanguage.Japanese => "ja/",
+ ClientLanguage.English => "en/",
+ ClientLanguage.German => "de/",
+ ClientLanguage.French => "fr/",
+ _ => throw new ArgumentOutOfRangeException(nameof(iconLanguage), $"Unknown Language: {iconLanguage}"),
+ };
- // Set up default values so plugins do not null-reference when data is being loaded.
- this.ClientOpCodes = this.ServerOpCodes = new ReadOnlyDictionary(new Dictionary());
- }
+ return this.GetIcon(type, iconId);
+ }
- ///
- /// Gets the current game client language.
- ///
- public ClientLanguage Language { get; private set; }
+ ///
+ /// Get a containing the icon with the given ID, of the given type.
+ ///
+ /// The type of the icon (e.g. 'hq' to get the HQ variant of an item icon).
+ /// The icon ID.
+ /// The containing the icon.
+ public TexFile? GetIcon(string type, uint iconId)
+ {
+ type ??= string.Empty;
+ if (type.Length > 0 && !type.EndsWith("/"))
+ type += "/";
- ///
- /// Gets the OpCodes sent by the server to the client.
- ///
- public ReadOnlyDictionary ServerOpCodes { get; private set; }
+ var filePath = string.Format(IconFileFormat, iconId / 1000, type, iconId);
+ var file = this.GetFile(filePath);
- ///
- /// Gets the OpCodes sent by the client to the server.
- ///
- [UsedImplicitly]
- public ReadOnlyDictionary ClientOpCodes { get; private set; }
-
- ///
- /// Gets a object which gives access to any excel/game data.
- ///
- public GameData GameData { get; private set; }
-
- ///
- /// Gets an object which gives access to any of the game's sheet data.
- ///
- public ExcelModule Excel => this.GameData?.Excel;
-
- ///
- /// Gets a value indicating whether Game Data is ready to be read.
- ///
- public bool IsDataReady { get; private set; }
-
- #region Lumina Wrappers
-
- ///
- /// Get an with the given Excel sheet row type.
- ///
- /// The excel sheet type to get.
- /// The , giving access to game rows.
- public ExcelSheet? GetExcelSheet() where T : ExcelRow
- {
- return this.Excel.GetSheet();
- }
-
- ///
- /// Get an with the given Excel sheet row type with a specified language.
- ///
- /// Language of the sheet to get.
- /// The excel sheet type to get.
- /// The , giving access to game rows.
- public ExcelSheet? GetExcelSheet(ClientLanguage language) where T : ExcelRow
- {
- return this.Excel.GetSheet(language.ToLumina());
- }
-
- ///
- /// Get a with the given path.
- ///
- /// The path inside of the game files.
- /// The of the file.
- public FileResource? GetFile(string path)
- {
- return this.GetFile(path);
- }
-
- ///
- /// Get a with the given path, of the given type.
- ///
- /// The type of resource.
- /// The path inside of the game files.
- /// The of the file.
- public T? GetFile(string path) where T : FileResource
- {
- var filePath = GameData.ParseFilePath(path);
- if (filePath == null)
- return default;
- return this.GameData.Repositories.TryGetValue(filePath.Repository, out var repository) ? repository.GetFile(filePath.Category, filePath) : default;
- }
-
- ///
- /// Check if the file with the given path exists within the game's index files.
- ///
- /// The path inside of the game files.
- /// True if the file exists.
- public bool FileExists(string path)
- {
- return this.GameData.FileExists(path);
- }
-
- ///
- /// Get a containing the icon with the given ID.
- ///
- /// The icon ID.
- /// The containing the icon.
- public TexFile? GetIcon(uint iconId)
- {
- return this.GetIcon(this.Language, iconId);
- }
-
- ///
- /// Get a containing the icon with the given ID, of the given quality.
- ///
- /// A value indicating whether the icon should be HQ.
- /// The icon ID.
- /// The containing the icon.
- public TexFile? GetIcon(bool isHq, uint iconId)
- {
- var type = isHq ? "hq/" : string.Empty;
- return this.GetIcon(type, iconId);
- }
-
- ///
- /// Get a containing the icon with the given ID, of the given language.
- ///
- /// The requested language.
- /// The icon ID.
- /// The containing the icon.
- public TexFile? GetIcon(ClientLanguage iconLanguage, uint iconId)
- {
- var type = iconLanguage switch
- {
- ClientLanguage.Japanese => "ja/",
- ClientLanguage.English => "en/",
- ClientLanguage.German => "de/",
- ClientLanguage.French => "fr/",
- _ => throw new ArgumentOutOfRangeException(nameof(iconLanguage), $"Unknown Language: {iconLanguage}"),
- };
-
- return this.GetIcon(type, iconId);
- }
-
- ///
- /// Get a containing the icon with the given ID, of the given type.
- ///
- /// The type of the icon (e.g. 'hq' to get the HQ variant of an item icon).
- /// The icon ID.
- /// The containing the icon.
- public TexFile? GetIcon(string type, uint iconId)
- {
- type ??= string.Empty;
- if (type.Length > 0 && !type.EndsWith("/"))
- type += "/";
-
- var filePath = string.Format(IconFileFormat, iconId / 1000, type, iconId);
- var file = this.GetFile(filePath);
-
- if (type == string.Empty || file != default)
- return file;
-
- // Couldn't get specific type, try for generic version.
- filePath = string.Format(IconFileFormat, iconId / 1000, string.Empty, iconId);
- file = this.GetFile(filePath);
+ if (type == string.Empty || file != default)
return file;
- }
- ///
- /// Get a containing the HQ icon with the given ID.
- ///
- /// The icon ID.
- /// The containing the icon.
- public TexFile? GetHqIcon(uint iconId)
- => this.GetIcon(true, iconId);
+ // Couldn't get specific type, try for generic version.
+ filePath = string.Format(IconFileFormat, iconId / 1000, string.Empty, iconId);
+ file = this.GetFile(filePath);
+ return file;
+ }
- ///
- /// Get the passed as a drawable ImGui TextureWrap.
- ///
- /// The Lumina .
- /// A that can be used to draw the texture.
- public TextureWrap? GetImGuiTexture(TexFile? tex)
+ ///
+ /// Get a containing the HQ icon with the given ID.
+ ///
+ /// The icon ID.
+ /// The containing the icon.
+ public TexFile? GetHqIcon(uint iconId)
+ => this.GetIcon(true, iconId);
+
+ ///
+ /// Get the passed as a drawable ImGui TextureWrap.
+ ///
+ /// The Lumina .
+ /// A that can be used to draw the texture.
+ public TextureWrap? GetImGuiTexture(TexFile? tex)
+ {
+ return tex == null ? null : Service.Get().LoadImageRaw(tex.GetRgbaImageData(), tex.Header.Width, tex.Header.Height, 4);
+ }
+
+ ///
+ /// Get the passed texture path as a drawable ImGui TextureWrap.
+ ///
+ /// The internal path to the texture.
+ /// A that can be used to draw the texture.
+ public TextureWrap? GetImGuiTexture(string path)
+ => this.GetImGuiTexture(this.GetFile(path));
+
+ ///
+ /// Get a containing the icon with the given ID.
+ ///
+ /// The icon ID.
+ /// The containing the icon.
+ public TextureWrap? GetImGuiTextureIcon(uint iconId)
+ => this.GetImGuiTexture(this.GetIcon(iconId));
+
+ ///
+ /// Get a containing the icon with the given ID, of the given quality.
+ ///
+ /// A value indicating whether the icon should be HQ.
+ /// The icon ID.
+ /// The containing the icon.
+ public TextureWrap? GetImGuiTextureIcon(bool isHq, uint iconId)
+ => this.GetImGuiTexture(this.GetIcon(isHq, iconId));
+
+ ///
+ /// Get a containing the icon with the given ID, of the given language.
+ ///
+ /// The requested language.
+ /// The icon ID.
+ /// The containing the icon.
+ public TextureWrap? GetImGuiTextureIcon(ClientLanguage iconLanguage, uint iconId)
+ => this.GetImGuiTexture(this.GetIcon(iconLanguage, iconId));
+
+ ///
+ /// Get a containing the icon with the given ID, of the given type.
+ ///
+ /// The type of the icon (e.g. 'hq' to get the HQ variant of an item icon).
+ /// The icon ID.
+ /// The containing the icon.
+ public TextureWrap? GetImGuiTextureIcon(string type, uint iconId)
+ => this.GetImGuiTexture(this.GetIcon(type, iconId));
+
+ ///
+ /// Get a containing the HQ icon with the given ID.
+ ///
+ /// The icon ID.
+ /// The containing the icon.
+ public TextureWrap? GetImGuiTextureHqIcon(uint iconId)
+ => this.GetImGuiTexture(this.GetHqIcon(iconId));
+
+ #endregion
+
+ ///
+ /// Dispose this DataManager.
+ ///
+ public void Dispose()
+ {
+ this.luminaCancellationTokenSource.Cancel();
+ }
+
+ ///
+ /// Initialize this data manager.
+ ///
+ /// The directory to load data from.
+ internal void Initialize(string baseDir)
+ {
+ try
{
- return tex == null ? null : Service.Get().LoadImageRaw(tex.GetRgbaImageData(), tex.Header.Width, tex.Header.Height, 4);
- }
+ Log.Verbose("Starting data load...");
- ///
- /// Get the passed texture path as a drawable ImGui TextureWrap.
- ///
- /// The internal path to the texture.
- /// A that can be used to draw the texture.
- public TextureWrap? GetImGuiTexture(string path)
- => this.GetImGuiTexture(this.GetFile(path));
+ var zoneOpCodeDict = JsonConvert.DeserializeObject>(
+ File.ReadAllText(Path.Combine(baseDir, "UIRes", "serveropcode.json")));
+ this.ServerOpCodes = new ReadOnlyDictionary(zoneOpCodeDict);
- ///
- /// Get a containing the icon with the given ID.
- ///
- /// The icon ID.
- /// The containing the icon.
- public TextureWrap? GetImGuiTextureIcon(uint iconId)
- => this.GetImGuiTexture(this.GetIcon(iconId));
+ Log.Verbose("Loaded {0} ServerOpCodes.", zoneOpCodeDict.Count);
- ///
- /// Get a containing the icon with the given ID, of the given quality.
- ///
- /// A value indicating whether the icon should be HQ.
- /// The icon ID.
- /// The containing the icon.
- public TextureWrap? GetImGuiTextureIcon(bool isHq, uint iconId)
- => this.GetImGuiTexture(this.GetIcon(isHq, iconId));
+ var clientOpCodeDict = JsonConvert.DeserializeObject>(
+ File.ReadAllText(Path.Combine(baseDir, "UIRes", "clientopcode.json")));
+ this.ClientOpCodes = new ReadOnlyDictionary(clientOpCodeDict);
- ///
- /// Get a containing the icon with the given ID, of the given language.
- ///
- /// The requested language.
- /// The icon ID.
- /// The containing the icon.
- public TextureWrap? GetImGuiTextureIcon(ClientLanguage iconLanguage, uint iconId)
- => this.GetImGuiTexture(this.GetIcon(iconLanguage, iconId));
+ Log.Verbose("Loaded {0} ClientOpCodes.", clientOpCodeDict.Count);
- ///
- /// Get a containing the icon with the given ID, of the given type.
- ///
- /// The type of the icon (e.g. 'hq' to get the HQ variant of an item icon).
- /// The icon ID.
- /// The containing the icon.
- public TextureWrap? GetImGuiTextureIcon(string type, uint iconId)
- => this.GetImGuiTexture(this.GetIcon(type, iconId));
-
- ///
- /// Get a containing the HQ icon with the given ID.
- ///
- /// The icon ID.
- /// The containing the icon.
- public TextureWrap? GetImGuiTextureHqIcon(uint iconId)
- => this.GetImGuiTexture(this.GetHqIcon(iconId));
-
- #endregion
-
- ///
- /// Dispose this DataManager.
- ///
- public void Dispose()
- {
- this.luminaCancellationTokenSource.Cancel();
- }
-
- ///
- /// Initialize this data manager.
- ///
- /// The directory to load data from.
- internal void Initialize(string baseDir)
- {
- try
+ var luminaOptions = new LuminaOptions
{
- Log.Verbose("Starting data load...");
-
- var zoneOpCodeDict = JsonConvert.DeserializeObject>(
- File.ReadAllText(Path.Combine(baseDir, "UIRes", "serveropcode.json")));
- this.ServerOpCodes = new ReadOnlyDictionary(zoneOpCodeDict);
-
- Log.Verbose("Loaded {0} ServerOpCodes.", zoneOpCodeDict.Count);
-
- var clientOpCodeDict = JsonConvert.DeserializeObject>(
- File.ReadAllText(Path.Combine(baseDir, "UIRes", "clientopcode.json")));
- this.ClientOpCodes = new ReadOnlyDictionary(clientOpCodeDict);
-
- Log.Verbose("Loaded {0} ClientOpCodes.", clientOpCodeDict.Count);
-
- var luminaOptions = new LuminaOptions
- {
- CacheFileResources = true,
+ CacheFileResources = true,
#if DEBUG
- PanicOnSheetChecksumMismatch = true,
+ PanicOnSheetChecksumMismatch = true,
#else
PanicOnSheetChecksumMismatch = false,
#endif
- DefaultExcelLanguage = this.Language.ToLumina(),
- };
+ DefaultExcelLanguage = this.Language.ToLumina(),
+ };
- var processModule = Process.GetCurrentProcess().MainModule;
- if (processModule != null)
- {
- this.GameData = new GameData(Path.Combine(Path.GetDirectoryName(processModule.FileName), "sqpack"), luminaOptions);
- }
-
- Log.Information("Lumina is ready: {0}", this.GameData.DataPath);
-
- this.IsDataReady = true;
-
- this.luminaCancellationTokenSource = new();
-
- var luminaCancellationToken = this.luminaCancellationTokenSource.Token;
- this.luminaResourceThread = new(() =>
- {
- while (!luminaCancellationToken.IsCancellationRequested)
- {
- if (this.GameData.FileHandleManager.HasPendingFileLoads)
- {
- this.GameData.ProcessFileHandleQueue();
- }
- else
- {
- Thread.Sleep(5);
- }
- }
- });
- this.luminaResourceThread.Start();
- }
- catch (Exception ex)
+ var processModule = Process.GetCurrentProcess().MainModule;
+ if (processModule != null)
{
- Log.Error(ex, "Could not download data.");
+ this.GameData = new GameData(Path.Combine(Path.GetDirectoryName(processModule.FileName), "sqpack"), luminaOptions);
}
+
+ Log.Information("Lumina is ready: {0}", this.GameData.DataPath);
+
+ this.IsDataReady = true;
+
+ this.luminaCancellationTokenSource = new();
+
+ var luminaCancellationToken = this.luminaCancellationTokenSource.Token;
+ this.luminaResourceThread = new(() =>
+ {
+ while (!luminaCancellationToken.IsCancellationRequested)
+ {
+ if (this.GameData.FileHandleManager.HasPendingFileLoads)
+ {
+ this.GameData.ProcessFileHandleQueue();
+ }
+ else
+ {
+ Thread.Sleep(5);
+ }
+ }
+ });
+ this.luminaResourceThread.Start();
+ }
+ catch (Exception ex)
+ {
+ Log.Error(ex, "Could not download data.");
}
}
}
diff --git a/Dalamud/EntryPoint.cs b/Dalamud/EntryPoint.cs
index e9df6be92..e630d3ee5 100644
--- a/Dalamud/EntryPoint.cs
+++ b/Dalamud/EntryPoint.cs
@@ -21,262 +21,261 @@ using Serilog.Events;
using static Dalamud.NativeFunctions;
-namespace Dalamud
+namespace Dalamud;
+
+///
+/// The main entrypoint for the Dalamud system.
+///
+public sealed class EntryPoint
{
///
- /// The main entrypoint for the Dalamud system.
+ /// A delegate used during initialization of the CLR from Dalamud.Boot.
///
- public sealed class EntryPoint
+ /// Pointer to a serialized data.
+ public delegate void InitDelegate(IntPtr infoPtr);
+
+ ///
+ /// Initialize Dalamud.
+ ///
+ /// Pointer to a serialized data.
+ public static void Initialize(IntPtr infoPtr)
{
- ///
- /// A delegate used during initialization of the CLR from Dalamud.Boot.
- ///
- /// Pointer to a serialized data.
- public delegate void InitDelegate(IntPtr infoPtr);
+ var infoStr = Marshal.PtrToStringUTF8(infoPtr);
+ var info = JsonConvert.DeserializeObject(infoStr);
- ///
- /// Initialize Dalamud.
- ///
- /// Pointer to a serialized data.
- public static void Initialize(IntPtr infoPtr)
+ new Thread(() => RunThread(info)).Start();
+ }
+
+ ///
+ /// Initialize all Dalamud subsystems and start running on the main thread.
+ ///
+ /// The containing information needed to initialize Dalamud.
+ private static void RunThread(DalamudStartInfo info)
+ {
+ if (EnvironmentConfiguration.DalamudWaitForDebugger)
{
- var infoStr = Marshal.PtrToStringUTF8(infoPtr);
- var info = JsonConvert.DeserializeObject(infoStr);
-
- new Thread(() => RunThread(info)).Start();
+ while (!Debugger.IsAttached)
+ {
+ Thread.Sleep(100);
+ }
}
- ///
- /// Initialize all Dalamud subsystems and start running on the main thread.
- ///
- /// The containing information needed to initialize Dalamud.
- private static void RunThread(DalamudStartInfo info)
- {
- if (EnvironmentConfiguration.DalamudWaitForDebugger)
- {
- while (!Debugger.IsAttached)
- {
- Thread.Sleep(100);
- }
- }
+ // Setup logger
+ var levelSwitch = InitLogging(info.WorkingDirectory);
- // Setup logger
- var levelSwitch = InitLogging(info.WorkingDirectory);
+ // Load configuration first to get some early persistent state, like log level
+ var configuration = DalamudConfiguration.Load(info.ConfigurationPath);
- // Load configuration first to get some early persistent state, like log level
- var configuration = DalamudConfiguration.Load(info.ConfigurationPath);
-
- // Set the appropriate logging level from the configuration
+ // Set the appropriate logging level from the configuration
#if !DEBUG
levelSwitch.MinimumLevel = configuration.LogLevel;
#endif
- // Log any unhandled exception.
- AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
- TaskScheduler.UnobservedTaskException += OnUnobservedTaskException;
+ // Log any unhandled exception.
+ AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
+ TaskScheduler.UnobservedTaskException += OnUnobservedTaskException;
- var finishSignal = new ManualResetEvent(false);
+ var finishSignal = new ManualResetEvent(false);
- try
- {
- if (info.DelayInitializeMs > 0)
- {
- Log.Information(string.Format("Waiting for {0}ms before starting a session.", info.DelayInitializeMs));
- Thread.Sleep(info.DelayInitializeMs);
- }
-
- Log.Information(new string('-', 80));
- Log.Information("Initializing a session..");
-
- // This is due to GitHub not supporting TLS 1.0, so we enable all TLS versions globally
- ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls;
-
- if (!Util.IsLinux())
- InitSymbolHandler(info);
-
- var dalamud = new Dalamud(info, levelSwitch, finishSignal, configuration);
- Log.Information("Starting a session..");
-
- // Run session
- dalamud.LoadTier1();
- dalamud.WaitForUnload();
-
- dalamud.Dispose();
- }
- catch (Exception ex)
- {
- Log.Fatal(ex, "Unhandled exception on main thread.");
- }
- finally
- {
- TaskScheduler.UnobservedTaskException -= OnUnobservedTaskException;
- AppDomain.CurrentDomain.UnhandledException -= OnUnhandledException;
-
- Log.Information("Session has ended.");
- Log.CloseAndFlush();
-
- finishSignal.Set();
- }
- }
-
- private static void InitSymbolHandler(DalamudStartInfo info)
+ try
{
- try
+ if (info.DelayInitializeMs > 0)
{
- if (string.IsNullOrEmpty(info.AssetDirectory))
- return;
-
- var symbolPath = Path.Combine(info.AssetDirectory, "UIRes", "pdb");
- var searchPath = $".;{symbolPath}";
-
- // Remove any existing Symbol Handler and Init a new one with our search path added
- SymCleanup(GetCurrentProcess());
-
- if (!SymInitialize(GetCurrentProcess(), searchPath, true))
- throw new Win32Exception();
- }
- catch (Exception ex)
- {
- Log.Error(ex, "SymbolHandler Initialize Failed.");
+ Log.Information(string.Format("Waiting for {0}ms before starting a session.", info.DelayInitializeMs));
+ Thread.Sleep(info.DelayInitializeMs);
}
+
+ Log.Information(new string('-', 80));
+ Log.Information("Initializing a session..");
+
+ // This is due to GitHub not supporting TLS 1.0, so we enable all TLS versions globally
+ ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls;
+
+ if (!Util.IsLinux())
+ InitSymbolHandler(info);
+
+ var dalamud = new Dalamud(info, levelSwitch, finishSignal, configuration);
+ Log.Information("Starting a session..");
+
+ // Run session
+ dalamud.LoadTier1();
+ dalamud.WaitForUnload();
+
+ dalamud.Dispose();
}
-
- private static LoggingLevelSwitch InitLogging(string baseDirectory)
+ catch (Exception ex)
{
+ Log.Fatal(ex, "Unhandled exception on main thread.");
+ }
+ finally
+ {
+ TaskScheduler.UnobservedTaskException -= OnUnobservedTaskException;
+ AppDomain.CurrentDomain.UnhandledException -= OnUnhandledException;
+
+ Log.Information("Session has ended.");
+ Log.CloseAndFlush();
+
+ finishSignal.Set();
+ }
+ }
+
+ private static void InitSymbolHandler(DalamudStartInfo info)
+ {
+ try
+ {
+ if (string.IsNullOrEmpty(info.AssetDirectory))
+ return;
+
+ var symbolPath = Path.Combine(info.AssetDirectory, "UIRes", "pdb");
+ var searchPath = $".;{symbolPath}";
+
+ // Remove any existing Symbol Handler and Init a new one with our search path added
+ SymCleanup(GetCurrentProcess());
+
+ if (!SymInitialize(GetCurrentProcess(), searchPath, true))
+ throw new Win32Exception();
+ }
+ catch (Exception ex)
+ {
+ Log.Error(ex, "SymbolHandler Initialize Failed.");
+ }
+ }
+
+ private static LoggingLevelSwitch InitLogging(string baseDirectory)
+ {
#if DEBUG
- var logPath = Path.Combine(baseDirectory, "dalamud.log");
- var oldPath = Path.Combine(baseDirectory, "dalamud.log.old");
+ var logPath = Path.Combine(baseDirectory, "dalamud.log");
+ var oldPath = Path.Combine(baseDirectory, "dalamud.log.old");
#else
var logPath = Path.Combine(baseDirectory, "..", "..", "..", "dalamud.log");
var oldPath = Path.Combine(baseDirectory, "..", "..", "..", "dalamud.log.old");
#endif
- CullLogFile(logPath, oldPath, 1 * 1024 * 1024);
- CullLogFile(oldPath, null, 10 * 1024 * 1024);
+ CullLogFile(logPath, oldPath, 1 * 1024 * 1024);
+ CullLogFile(oldPath, null, 10 * 1024 * 1024);
- var levelSwitch = new LoggingLevelSwitch(LogEventLevel.Verbose);
- Log.Logger = new LoggerConfiguration()
- .WriteTo.Async(a => a.File(logPath))
- .WriteTo.Sink(SerilogEventSink.Instance)
- .MinimumLevel.ControlledBy(levelSwitch)
- .CreateLogger();
+ var levelSwitch = new LoggingLevelSwitch(LogEventLevel.Verbose);
+ Log.Logger = new LoggerConfiguration()
+ .WriteTo.Async(a => a.File(logPath))
+ .WriteTo.Sink(SerilogEventSink.Instance)
+ .MinimumLevel.ControlledBy(levelSwitch)
+ .CreateLogger();
- return levelSwitch;
- }
+ return levelSwitch;
+ }
- private static void CullLogFile(string logPath, string? oldPath, int cullingFileSize)
+ private static void CullLogFile(string logPath, string? oldPath, int cullingFileSize)
+ {
+ try
{
- try
+ var bufferSize = 4096;
+
+ var logFile = new FileInfo(logPath);
+
+ if (!logFile.Exists)
+ logFile.Create();
+
+ if (logFile.Length <= cullingFileSize)
+ return;
+
+ var amountToCull = logFile.Length - cullingFileSize;
+
+ if (amountToCull < bufferSize)
+ return;
+
+ if (oldPath != null)
{
- var bufferSize = 4096;
+ var oldFile = new FileInfo(oldPath);
- var logFile = new FileInfo(logPath);
+ if (!oldFile.Exists)
+ oldFile.Create().Close();
- if (!logFile.Exists)
- logFile.Create();
+ using var reader = new BinaryReader(logFile.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
+ using var writer = new BinaryWriter(oldFile.Open(FileMode.Append, FileAccess.Write, FileShare.ReadWrite));
- if (logFile.Length <= cullingFileSize)
- return;
-
- var amountToCull = logFile.Length - cullingFileSize;
-
- if (amountToCull < bufferSize)
- return;
-
- if (oldPath != null)
+ var read = -1;
+ var total = 0;
+ var buffer = new byte[bufferSize];
+ while (read != 0 && total < amountToCull)
{
- var oldFile = new FileInfo(oldPath);
-
- if (!oldFile.Exists)
- oldFile.Create().Close();
-
- using var reader = new BinaryReader(logFile.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
- using var writer = new BinaryWriter(oldFile.Open(FileMode.Append, FileAccess.Write, FileShare.ReadWrite));
-
- var read = -1;
- var total = 0;
- var buffer = new byte[bufferSize];
- while (read != 0 && total < amountToCull)
- {
- read = reader.Read(buffer, 0, buffer.Length);
- writer.Write(buffer, 0, read);
- total += read;
- }
- }
-
- {
- using var reader = new BinaryReader(logFile.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
- using var writer = new BinaryWriter(logFile.Open(FileMode.Open, FileAccess.Write, FileShare.ReadWrite));
-
- reader.BaseStream.Seek(amountToCull, SeekOrigin.Begin);
-
- var read = -1;
- var total = 0;
- var buffer = new byte[bufferSize];
- while (read != 0)
- {
- read = reader.Read(buffer, 0, buffer.Length);
- writer.Write(buffer, 0, read);
- total += read;
- }
-
- writer.BaseStream.SetLength(total);
+ read = reader.Read(buffer, 0, buffer.Length);
+ writer.Write(buffer, 0, read);
+ total += read;
}
}
- catch (Exception ex)
- {
- Log.Error(ex, "Log cull failed");
- /*
- var caption = "XIVLauncher Error";
- var message = $"Log cull threw an exception: {ex.Message}\n{ex.StackTrace ?? string.Empty}";
- _ = MessageBoxW(IntPtr.Zero, message, caption, MessageBoxType.IconError | MessageBoxType.Ok);
- */
+ {
+ using var reader = new BinaryReader(logFile.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
+ using var writer = new BinaryWriter(logFile.Open(FileMode.Open, FileAccess.Write, FileShare.ReadWrite));
+
+ reader.BaseStream.Seek(amountToCull, SeekOrigin.Begin);
+
+ var read = -1;
+ var total = 0;
+ var buffer = new byte[bufferSize];
+ while (read != 0)
+ {
+ read = reader.Read(buffer, 0, buffer.Length);
+ writer.Write(buffer, 0, read);
+ total += read;
+ }
+
+ writer.BaseStream.SetLength(total);
}
}
-
- private static void OnUnhandledException(object sender, UnhandledExceptionEventArgs args)
+ catch (Exception ex)
{
- switch (args.ExceptionObject)
- {
- case Exception ex:
- Log.Fatal(ex, "Unhandled exception on AppDomain");
- Troubleshooting.LogException(ex, "DalamudUnhandled");
+ Log.Error(ex, "Log cull failed");
- var info = "Further information could not be obtained";
- if (ex.TargetSite != null && ex.TargetSite.DeclaringType != null)
- {
- info = $"{ex.TargetSite.DeclaringType.Assembly.GetName().Name}, {ex.TargetSite.DeclaringType.FullName}::{ex.TargetSite.Name}";
- }
-
- const MessageBoxType flags = NativeFunctions.MessageBoxType.YesNo | NativeFunctions.MessageBoxType.IconError | NativeFunctions.MessageBoxType.SystemModal;
- var result = MessageBoxW(
- Process.GetCurrentProcess().MainWindowHandle,
- $"An internal error in a Dalamud plugin occurred.\nThe game must close.\n\nType: {ex.GetType().Name}\n{info}\n\nMore information has been recorded separately, please contact us in our Discord or on GitHub.\n\nDo you want to disable all plugins the next time you start the game?",
- "Dalamud",
- flags);
-
- if (result == (int)User32.MessageBoxResult.IDYES)
- {
- Log.Information("User chose to disable plugins on next launch...");
- var config = Service.Get();
- config.PluginSafeMode = true;
- config.Save();
- }
-
- Environment.Exit(-1);
-
- break;
- default:
- Log.Fatal("Unhandled SEH object on AppDomain: {Object}", args.ExceptionObject);
- break;
- }
- }
-
- private static void OnUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs args)
- {
- if (!args.Observed)
- Log.Error(args.Exception, "Unobserved exception in Task.");
+ /*
+ var caption = "XIVLauncher Error";
+ var message = $"Log cull threw an exception: {ex.Message}\n{ex.StackTrace ?? string.Empty}";
+ _ = MessageBoxW(IntPtr.Zero, message, caption, MessageBoxType.IconError | MessageBoxType.Ok);
+ */
}
}
+
+ private static void OnUnhandledException(object sender, UnhandledExceptionEventArgs args)
+ {
+ switch (args.ExceptionObject)
+ {
+ case Exception ex:
+ Log.Fatal(ex, "Unhandled exception on AppDomain");
+ Troubleshooting.LogException(ex, "DalamudUnhandled");
+
+ var info = "Further information could not be obtained";
+ if (ex.TargetSite != null && ex.TargetSite.DeclaringType != null)
+ {
+ info = $"{ex.TargetSite.DeclaringType.Assembly.GetName().Name}, {ex.TargetSite.DeclaringType.FullName}::{ex.TargetSite.Name}";
+ }
+
+ const MessageBoxType flags = NativeFunctions.MessageBoxType.YesNo | NativeFunctions.MessageBoxType.IconError | NativeFunctions.MessageBoxType.SystemModal;
+ var result = MessageBoxW(
+ Process.GetCurrentProcess().MainWindowHandle,
+ $"An internal error in a Dalamud plugin occurred.\nThe game must close.\n\nType: {ex.GetType().Name}\n{info}\n\nMore information has been recorded separately, please contact us in our Discord or on GitHub.\n\nDo you want to disable all plugins the next time you start the game?",
+ "Dalamud",
+ flags);
+
+ if (result == (int)User32.MessageBoxResult.IDYES)
+ {
+ Log.Information("User chose to disable plugins on next launch...");
+ var config = Service.Get();
+ config.PluginSafeMode = true;
+ config.Save();
+ }
+
+ Environment.Exit(-1);
+
+ break;
+ default:
+ Log.Fatal("Unhandled SEH object on AppDomain: {Object}", args.ExceptionObject);
+ break;
+ }
+ }
+
+ private static void OnUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs args)
+ {
+ if (!args.Observed)
+ Log.Error(args.Exception, "Unobserved exception in Task.");
+ }
}
diff --git a/Dalamud/Game/BaseAddressResolver.cs b/Dalamud/Game/BaseAddressResolver.cs
index 4528b138e..ab1502376 100644
--- a/Dalamud/Game/BaseAddressResolver.cs
+++ b/Dalamud/Game/BaseAddressResolver.cs
@@ -3,112 +3,111 @@ using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
-namespace Dalamud.Game
+namespace Dalamud.Game;
+
+///
+/// Base memory address resolver.
+///
+public abstract class BaseAddressResolver
{
///
- /// Base memory address resolver.
+ /// Gets a list of memory addresses that were found, to list in /xldata.
///
- public abstract class BaseAddressResolver
+ public static Dictionary> DebugScannedValues { get; } = new();
+
+ ///
+ /// Gets or sets a value indicating whether the resolver has successfully run or .
+ ///
+ protected bool IsResolved { get; set; }
+
+ ///
+ /// Setup the resolver, calling the appopriate method based on the process architecture.
+ ///
+ public void Setup()
{
- ///
- /// Gets a list of memory addresses that were found, to list in /xldata.
- ///
- public static Dictionary> DebugScannedValues { get; } = new();
+ var scanner = Service.Get();
+ this.Setup(scanner);
+ }
- ///
- /// Gets or sets a value indicating whether the resolver has successfully run or .
- ///
- protected bool IsResolved { get; set; }
+ ///
+ /// Setup the resolver, calling the appopriate method based on the process architecture.
+ ///
+ /// The SigScanner instance.
+ public void Setup(SigScanner scanner)
+ {
+ // Because C# don't allow to call virtual function while in ctor
+ // we have to do this shit :\
- ///
- /// Setup the resolver, calling the appopriate method based on the process architecture.
- ///
- public void Setup()
+ if (this.IsResolved)
{
- var scanner = Service.Get();
- this.Setup(scanner);
+ return;
}
- ///
- /// Setup the resolver, calling the appopriate method based on the process architecture.
- ///
- /// The SigScanner instance.
- public void Setup(SigScanner scanner)
+ if (scanner.Is32BitProcess)
{
- // Because C# don't allow to call virtual function while in ctor
- // we have to do this shit :\
-
- if (this.IsResolved)
- {
- return;
- }
-
- if (scanner.Is32BitProcess)
- {
- this.Setup32Bit(scanner);
- }
- else
- {
- this.Setup64Bit(scanner);
- }
-
- this.SetupInternal(scanner);
-
- var className = this.GetType().Name;
- DebugScannedValues[className] = new List<(string, IntPtr)>();
-
- foreach (var property in this.GetType().GetProperties().Where(x => x.PropertyType == typeof(IntPtr)))
- {
- DebugScannedValues[className].Add((property.Name, (IntPtr)property.GetValue(this)));
- }
-
- this.IsResolved = true;
+ this.Setup32Bit(scanner);
+ }
+ else
+ {
+ this.Setup64Bit(scanner);
}
- ///
- /// Fetch vfunc N from a pointer to the vtable and return a delegate function pointer.
- ///
- /// The delegate to marshal the function pointer to.
- /// The address of the virtual table.
- /// The offset from address to the vtable pointer.
- /// The vfunc index.
- /// A delegate function pointer that can be invoked.
- public T GetVirtualFunction(IntPtr address, int vtableOffset, int count) where T : class
+ this.SetupInternal(scanner);
+
+ var className = this.GetType().Name;
+ DebugScannedValues[className] = new List<(string, IntPtr)>();
+
+ foreach (var property in this.GetType().GetProperties().Where(x => x.PropertyType == typeof(IntPtr)))
{
- // Get vtable
- var vtable = Marshal.ReadIntPtr(address, vtableOffset);
-
- // Get an address to the function
- var functionAddress = Marshal.ReadIntPtr(vtable, IntPtr.Size * count);
-
- return Marshal.GetDelegateForFunctionPointer(functionAddress);
+ DebugScannedValues[className].Add((property.Name, (IntPtr)property.GetValue(this)));
}
- ///
- /// Setup the resolver by finding any necessary memory addresses.
- ///
- /// The SigScanner instance.
- protected virtual void Setup32Bit(SigScanner scanner)
- {
- throw new NotSupportedException("32 bit version is not supported.");
- }
+ this.IsResolved = true;
+ }
- ///
- /// Setup the resolver by finding any necessary memory addresses.
- ///
- /// The SigScanner instance.
- protected virtual void Setup64Bit(SigScanner scanner)
- {
- throw new NotSupportedException("64 bit version is not supported.");
- }
+ ///
+ /// Fetch vfunc N from a pointer to the vtable and return a delegate function pointer.
+ ///
+ /// The delegate to marshal the function pointer to.
+ /// The address of the virtual table.
+ /// The offset from address to the vtable pointer.
+ /// The vfunc index.
+ /// A delegate function pointer that can be invoked.
+ public T GetVirtualFunction(IntPtr address, int vtableOffset, int count) where T : class
+ {
+ // Get vtable
+ var vtable = Marshal.ReadIntPtr(address, vtableOffset);
- ///
- /// Setup the resolver by finding any necessary memory addresses.
- ///
- /// The SigScanner instance.
- protected virtual void SetupInternal(SigScanner scanner)
- {
- // Do nothing
- }
+ // Get an address to the function
+ var functionAddress = Marshal.ReadIntPtr(vtable, IntPtr.Size * count);
+
+ return Marshal.GetDelegateForFunctionPointer(functionAddress);
+ }
+
+ ///
+ /// Setup the resolver by finding any necessary memory addresses.
+ ///
+ /// The SigScanner instance.
+ protected virtual void Setup32Bit(SigScanner scanner)
+ {
+ throw new NotSupportedException("32 bit version is not supported.");
+ }
+
+ ///
+ /// Setup the resolver by finding any necessary memory addresses.
+ ///
+ /// The SigScanner instance.
+ protected virtual void Setup64Bit(SigScanner scanner)
+ {
+ throw new NotSupportedException("64 bit version is not supported.");
+ }
+
+ ///
+ /// Setup the resolver by finding any necessary memory addresses.
+ ///
+ /// The SigScanner instance.
+ protected virtual void SetupInternal(SigScanner scanner)
+ {
+ // Do nothing
}
}
diff --git a/Dalamud/Game/ChatHandlers.cs b/Dalamud/Game/ChatHandlers.cs
index 5465fef97..0da9f6dcf 100644
--- a/Dalamud/Game/ChatHandlers.cs
+++ b/Dalamud/Game/ChatHandlers.cs
@@ -21,298 +21,298 @@ using Dalamud.Plugin.Internal;
using Dalamud.Utility;
using Serilog;
-namespace Dalamud.Game
+namespace Dalamud.Game;
+
+///
+/// Chat events and public helper functions.
+///
+[PluginInterface]
+[InterfaceVersion("1.0")]
+public class ChatHandlers
{
- ///
- /// Chat events and public helper functions.
- ///
- [PluginInterface]
- [InterfaceVersion("1.0")]
- public class ChatHandlers
+ // private static readonly Dictionary UnicodeToDiscordEmojiDict = new()
+ // {
+ // { "", "<:ffxive071:585847382210642069>" },
+ // { "", "<:ffxive083:585848592699490329>" },
+ // };
+
+ // private readonly Dictionary handledChatTypeColors = new()
+ // {
+ // { XivChatType.CrossParty, Color.DodgerBlue },
+ // { XivChatType.Party, Color.DodgerBlue },
+ // { XivChatType.FreeCompany, Color.DeepSkyBlue },
+ // { XivChatType.CrossLinkShell1, Color.ForestGreen },
+ // { XivChatType.CrossLinkShell2, Color.ForestGreen },
+ // { XivChatType.CrossLinkShell3, Color.ForestGreen },
+ // { XivChatType.CrossLinkShell4, Color.ForestGreen },
+ // { XivChatType.CrossLinkShell5, Color.ForestGreen },
+ // { XivChatType.CrossLinkShell6, Color.ForestGreen },
+ // { XivChatType.CrossLinkShell7, Color.ForestGreen },
+ // { XivChatType.CrossLinkShell8, Color.ForestGreen },
+ // { XivChatType.Ls1, Color.ForestGreen },
+ // { XivChatType.Ls2, Color.ForestGreen },
+ // { XivChatType.Ls3, Color.ForestGreen },
+ // { XivChatType.Ls4, Color.ForestGreen },
+ // { XivChatType.Ls5, Color.ForestGreen },
+ // { XivChatType.Ls6, Color.ForestGreen },
+ // { XivChatType.Ls7, Color.ForestGreen },
+ // { XivChatType.Ls8, Color.ForestGreen },
+ // { XivChatType.TellIncoming, Color.HotPink },
+ // { XivChatType.PvPTeam, Color.SandyBrown },
+ // { XivChatType.Urgent, Color.DarkViolet },
+ // { XivChatType.NoviceNetwork, Color.SaddleBrown },
+ // { XivChatType.Echo, Color.Gray },
+ // };
+
+ private readonly Regex rmtRegex = new(
+ @"4KGOLD|We have sufficient stock|VPK\.OM|Gil for free|www\.so9\.com|Fast & Convenient|Cheap & Safety Guarantee|【Code|A O A U E|igfans|4KGOLD\.COM|Cheapest Gil with|pvp and bank on google|Selling Cheap GIL|ff14mogstation\.com|Cheap Gil 1000k|gilsforyou|server 1000K =|gils_selling|E A S Y\.C O M|bonus code|mins delivery guarantee|Sell cheap|Salegm\.com|cheap Mog|Off Code:|FF14Mog.com|使用する5%オ|Off Code( *):|offers Fantasia",
+ RegexOptions.Compiled);
+
+ private readonly Dictionary retainerSaleRegexes = new()
{
- // private static readonly Dictionary UnicodeToDiscordEmojiDict = new()
- // {
- // { "", "<:ffxive071:585847382210642069>" },
- // { "", "<:ffxive083:585848592699490329>" },
- // };
-
- // private readonly Dictionary handledChatTypeColors = new()
- // {
- // { XivChatType.CrossParty, Color.DodgerBlue },
- // { XivChatType.Party, Color.DodgerBlue },
- // { XivChatType.FreeCompany, Color.DeepSkyBlue },
- // { XivChatType.CrossLinkShell1, Color.ForestGreen },
- // { XivChatType.CrossLinkShell2, Color.ForestGreen },
- // { XivChatType.CrossLinkShell3, Color.ForestGreen },
- // { XivChatType.CrossLinkShell4, Color.ForestGreen },
- // { XivChatType.CrossLinkShell5, Color.ForestGreen },
- // { XivChatType.CrossLinkShell6, Color.ForestGreen },
- // { XivChatType.CrossLinkShell7, Color.ForestGreen },
- // { XivChatType.CrossLinkShell8, Color.ForestGreen },
- // { XivChatType.Ls1, Color.ForestGreen },
- // { XivChatType.Ls2, Color.ForestGreen },
- // { XivChatType.Ls3, Color.ForestGreen },
- // { XivChatType.Ls4, Color.ForestGreen },
- // { XivChatType.Ls5, Color.ForestGreen },
- // { XivChatType.Ls6, Color.ForestGreen },
- // { XivChatType.Ls7, Color.ForestGreen },
- // { XivChatType.Ls8, Color.ForestGreen },
- // { XivChatType.TellIncoming, Color.HotPink },
- // { XivChatType.PvPTeam, Color.SandyBrown },
- // { XivChatType.Urgent, Color.DarkViolet },
- // { XivChatType.NoviceNetwork, Color.SaddleBrown },
- // { XivChatType.Echo, Color.Gray },
- // };
-
- private readonly Regex rmtRegex = new(
- @"4KGOLD|We have sufficient stock|VPK\.OM|Gil for free|www\.so9\.com|Fast & Convenient|Cheap & Safety Guarantee|【Code|A O A U E|igfans|4KGOLD\.COM|Cheapest Gil with|pvp and bank on google|Selling Cheap GIL|ff14mogstation\.com|Cheap Gil 1000k|gilsforyou|server 1000K =|gils_selling|E A S Y\.C O M|bonus code|mins delivery guarantee|Sell cheap|Salegm\.com|cheap Mog|Off Code:|FF14Mog.com|使用する5%オ|Off Code( *):|offers Fantasia",
- RegexOptions.Compiled);
-
- private readonly Dictionary retainerSaleRegexes = new()
{
+ ClientLanguage.Japanese,
+ new Regex[]
{
- ClientLanguage.Japanese,
- new Regex[]
- {
new Regex(@"^(?:.+)マーケットに(?[\d,.]+)ギルで出品した(?- .*)×(?[\d,.]+)が売れ、(?[\d,.]+)ギルを入手しました。$", RegexOptions.Compiled),
new Regex(@"^(?:.+)マーケットに(?[\d,.]+)ギルで出品した(?
- .*)が売れ、(?[\d,.]+)ギルを入手しました。$", RegexOptions.Compiled),
- }
- },
+ }
+ },
+ {
+ ClientLanguage.English,
+ new Regex[]
{
- ClientLanguage.English,
- new Regex[]
- {
new Regex(@"^(?
- .+) you put up for sale in the (?:.+) markets (?:have|has) sold for (?[\d,.]+) gil \(after fees\)\.$", RegexOptions.Compiled),
- }
- },
+ }
+ },
+ {
+ ClientLanguage.German,
+ new Regex[]
{
- ClientLanguage.German,
- new Regex[]
- {
new Regex(@"^Dein Gehilfe hat (?
- .+) auf dem Markt von (?:.+) für (?[\d,.]+) Gil verkauft\.$", RegexOptions.Compiled),
new Regex(@"^Dein Gehilfe hat (?
- .+) auf dem Markt von (?:.+) verkauft und (?[\d,.]+) Gil erhalten\.$", RegexOptions.Compiled),
- }
- },
- {
- ClientLanguage.French,
- new Regex[]
- {
- new Regex(@"^Un servant a vendu (?
- .+) pour (?[\d,.]+) gil à (?:.+)\.$", RegexOptions.Compiled),
- }
- },
- };
-
- private readonly Regex urlRegex = new(@"(http|ftp|https)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?", RegexOptions.Compiled);
-
- private readonly DalamudLinkPayload openInstallerWindowLink;
-
- private bool hasSeenLoadingMsg;
- private bool hasAutoUpdatedPlugins;
-
- ///
- /// Initializes a new instance of the class.
- ///
- internal ChatHandlers()
- {
- var chatGui = Service.Get();
-
- chatGui.CheckMessageHandled += this.OnCheckMessageHandled;
- chatGui.ChatMessage += this.OnChatMessage;
-
- this.openInstallerWindowLink = chatGui.AddChatLinkHandler("Dalamud", 1001, (i, m) =>
- {
- Service.Get().OpenPluginInstaller();
- });
- }
-
- ///
- /// Gets the last URL seen in chat.
- ///
- public string? LastLink { get; private set; }
-
- ///
- /// Convert a TextPayload to SeString and wrap in italics payloads.
- ///
- /// Text to convert.
- /// SeString payload of italicized text.
- public static SeString MakeItalics(string text)
- => MakeItalics(new TextPayload(text));
-
- ///
- /// Convert a TextPayload to SeString and wrap in italics payloads.
- ///
- /// Text to convert.
- /// SeString payload of italicized text.
- public static SeString MakeItalics(TextPayload text)
- => new(EmphasisItalicPayload.ItalicsOn, text, EmphasisItalicPayload.ItalicsOff);
-
- private void OnCheckMessageHandled(XivChatType type, uint senderid, ref SeString sender, ref SeString message, ref bool isHandled)
- {
- var configuration = Service.Get();
-
- var textVal = message.TextValue;
-
- if (!configuration.DisableRmtFiltering)
- {
- var matched = this.rmtRegex.IsMatch(textVal);
- if (matched)
- {
- // This seems to be a RMT ad - let's not show it
- Log.Debug("Handled RMT ad: " + message.TextValue);
- isHandled = true;
- return;
- }
}
-
- if (configuration.BadWords != null &&
- configuration.BadWords.Any(x => !string.IsNullOrEmpty(x) && textVal.Contains(x)))
+ },
+ {
+ ClientLanguage.French,
+ new Regex[]
{
- // This seems to be in the user block list - let's not show it
- Log.Debug("Blocklist triggered");
+ new Regex(@"^Un servant a vendu (?
- .+) pour (?[\d,.]+) gil à (?:.+)\.$", RegexOptions.Compiled),
+ }
+ },
+ };
+
+ private readonly Regex urlRegex = new(@"(http|ftp|https)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?", RegexOptions.Compiled);
+
+ private readonly DalamudLinkPayload openInstallerWindowLink;
+
+ private bool hasSeenLoadingMsg;
+ private bool hasAutoUpdatedPlugins;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ internal ChatHandlers()
+ {
+ var chatGui = Service.Get();
+
+ chatGui.CheckMessageHandled += this.OnCheckMessageHandled;
+ chatGui.ChatMessage += this.OnChatMessage;
+
+ this.openInstallerWindowLink = chatGui.AddChatLinkHandler("Dalamud", 1001, (i, m) =>
+ {
+ Service.Get().OpenPluginInstaller();
+ });
+ }
+
+ ///
+ /// Gets the last URL seen in chat.
+ ///
+ public string? LastLink { get; private set; }
+
+ ///
+ /// Convert a TextPayload to SeString and wrap in italics payloads.
+ ///
+ /// Text to convert.
+ /// SeString payload of italicized text.
+ public static SeString MakeItalics(string text)
+ => MakeItalics(new TextPayload(text));
+
+ ///
+ /// Convert a TextPayload to SeString and wrap in italics payloads.
+ ///
+ /// Text to convert.
+ /// SeString payload of italicized text.
+ public static SeString MakeItalics(TextPayload text)
+ => new(EmphasisItalicPayload.ItalicsOn, text, EmphasisItalicPayload.ItalicsOff);
+
+ private void OnCheckMessageHandled(XivChatType type, uint senderid, ref SeString sender, ref SeString message, ref bool isHandled)
+ {
+ var configuration = Service.Get();
+
+ var textVal = message.TextValue;
+
+ if (!configuration.DisableRmtFiltering)
+ {
+ var matched = this.rmtRegex.IsMatch(textVal);
+ if (matched)
+ {
+ // This seems to be a RMT ad - let's not show it
+ Log.Debug("Handled RMT ad: " + message.TextValue);
isHandled = true;
return;
}
}
- private void OnChatMessage(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled)
+ if (configuration.BadWords != null &&
+ configuration.BadWords.Any(x => !string.IsNullOrEmpty(x) && textVal.Contains(x)))
{
- var startInfo = Service.Get();
- var clientState = Service.Get();
+ // This seems to be in the user block list - let's not show it
+ Log.Debug("Blocklist triggered");
+ isHandled = true;
+ return;
+ }
+ }
- if (type == XivChatType.Notice && !this.hasSeenLoadingMsg)
- this.PrintWelcomeMessage();
+ private void OnChatMessage(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled)
+ {
+ var startInfo = Service.Get();
+ var clientState = Service.Get();
- // For injections while logged in
- if (clientState.LocalPlayer != null && clientState.TerritoryType == 0 && !this.hasSeenLoadingMsg)
- this.PrintWelcomeMessage();
+ if (type == XivChatType.Notice && !this.hasSeenLoadingMsg)
+ this.PrintWelcomeMessage();
- if (!this.hasAutoUpdatedPlugins)
- this.AutoUpdatePlugins();
+ // For injections while logged in
+ if (clientState.LocalPlayer != null && clientState.TerritoryType == 0 && !this.hasSeenLoadingMsg)
+ this.PrintWelcomeMessage();
+
+ if (!this.hasAutoUpdatedPlugins)
+ this.AutoUpdatePlugins();
#if !DEBUG && false
if (!this.hasSeenLoadingMsg)
return;
#endif
- if (type == XivChatType.RetainerSale)
+ if (type == XivChatType.RetainerSale)
+ {
+ foreach (var regex in this.retainerSaleRegexes[startInfo.Language])
{
- foreach (var regex in this.retainerSaleRegexes[startInfo.Language])
+ var matchInfo = regex.Match(message.TextValue);
+
+ // we no longer really need to do/validate the item matching since we read the id from the byte array
+ // but we'd be checking the main match anyway
+ var itemInfo = matchInfo.Groups["item"];
+ if (!itemInfo.Success)
+ continue;
+
+ var itemLink = message.Payloads.FirstOrDefault(x => x.Type == PayloadType.Item) as ItemPayload;
+ if (itemLink == default)
{
- var matchInfo = regex.Match(message.TextValue);
-
- // we no longer really need to do/validate the item matching since we read the id from the byte array
- // but we'd be checking the main match anyway
- var itemInfo = matchInfo.Groups["item"];
- if (!itemInfo.Success)
- continue;
-
- var itemLink = message.Payloads.FirstOrDefault(x => x.Type == PayloadType.Item) as ItemPayload;
- if (itemLink == default)
- {
- Log.Error("itemLink was null. Msg: {0}", BitConverter.ToString(message.Encode()));
- break;
- }
-
- Log.Debug($"Probable retainer sale: {message}, decoded item {itemLink.Item.RowId}, HQ {itemLink.IsHQ}");
-
- var valueInfo = matchInfo.Groups["value"];
- // not sure if using a culture here would work correctly, so just strip symbols instead
- if (!valueInfo.Success || !int.TryParse(valueInfo.Value.Replace(",", string.Empty).Replace(".", string.Empty), out var itemValue))
- continue;
-
- // Task.Run(() => this.dalamud.BotManager.ProcessRetainerSale(itemLink.Item.RowId, itemValue, itemLink.IsHQ));
+ Log.Error("itemLink was null. Msg: {0}", BitConverter.ToString(message.Encode()));
break;
}
+
+ Log.Debug($"Probable retainer sale: {message}, decoded item {itemLink.Item.RowId}, HQ {itemLink.IsHQ}");
+
+ var valueInfo = matchInfo.Groups["value"];
+ // not sure if using a culture here would work correctly, so just strip symbols instead
+ if (!valueInfo.Success || !int.TryParse(valueInfo.Value.Replace(",", string.Empty).Replace(".", string.Empty), out var itemValue))
+ continue;
+
+ // Task.Run(() => this.dalamud.BotManager.ProcessRetainerSale(itemLink.Item.RowId, itemValue, itemLink.IsHQ));
+ break;
}
-
- var messageCopy = message;
- var senderCopy = sender;
-
- var linkMatch = this.urlRegex.Match(message.TextValue);
- if (linkMatch.Value.Length > 0)
- this.LastLink = linkMatch.Value;
}
- private void PrintWelcomeMessage()
+ var messageCopy = message;
+ var senderCopy = sender;
+
+ var linkMatch = this.urlRegex.Match(message.TextValue);
+ if (linkMatch.Value.Length > 0)
+ this.LastLink = linkMatch.Value;
+ }
+
+ private void PrintWelcomeMessage()
+ {
+ var chatGui = Service.Get();
+ var configuration = Service.Get();
+ var pluginManager = Service.Get();
+ var dalamudInterface = Service.Get();
+
+ var assemblyVersion = Assembly.GetAssembly(typeof(ChatHandlers)).GetName().Version.ToString();
+
+ chatGui.Print(string.Format(Loc.Localize("DalamudWelcome", "Dalamud vD{0} loaded."), assemblyVersion)
+ + string.Format(Loc.Localize("PluginsWelcome", " {0} plugin(s) loaded."), pluginManager.InstalledPlugins.Count));
+
+ if (configuration.PrintPluginsWelcomeMsg)
{
- var chatGui = Service.Get();
- var configuration = Service.Get();
- var pluginManager = Service.Get();
- var dalamudInterface = Service.Get();
-
- var assemblyVersion = Assembly.GetAssembly(typeof(ChatHandlers)).GetName().Version.ToString();
-
- chatGui.Print(string.Format(Loc.Localize("DalamudWelcome", "Dalamud vD{0} loaded."), assemblyVersion)
- + string.Format(Loc.Localize("PluginsWelcome", " {0} plugin(s) loaded."), pluginManager.InstalledPlugins.Count));
-
- if (configuration.PrintPluginsWelcomeMsg)
+ foreach (var plugin in pluginManager.InstalledPlugins.OrderBy(plugin => plugin.Name))
{
- foreach (var plugin in pluginManager.InstalledPlugins.OrderBy(plugin => plugin.Name))
- {
- chatGui.Print(string.Format(Loc.Localize("DalamudPluginLoaded", " 》 {0} v{1} loaded."), plugin.Name, plugin.Manifest.AssemblyVersion));
- }
+ chatGui.Print(string.Format(Loc.Localize("DalamudPluginLoaded", " 》 {0} v{1} loaded."), plugin.Name, plugin.Manifest.AssemblyVersion));
}
-
- if (string.IsNullOrEmpty(configuration.LastVersion) || !assemblyVersion.StartsWith(configuration.LastVersion))
- {
- chatGui.PrintChat(new XivChatEntry
- {
- Message = Loc.Localize("DalamudUpdated", "The In-Game addon has been updated or was reinstalled successfully! Please check the discord for a full changelog."),
- Type = XivChatType.Notice,
- });
-
- if (string.IsNullOrEmpty(configuration.LastChangelogMajorMinor) || (!ChangelogWindow.WarrantsChangelogForMajorMinor.StartsWith(configuration.LastChangelogMajorMinor) && assemblyVersion.StartsWith(ChangelogWindow.WarrantsChangelogForMajorMinor)))
- {
- dalamudInterface.OpenChangelogWindow();
- configuration.LastChangelogMajorMinor = ChangelogWindow.WarrantsChangelogForMajorMinor;
- }
-
- configuration.LastVersion = assemblyVersion;
- configuration.Save();
- }
-
- this.hasSeenLoadingMsg = true;
}
- private void AutoUpdatePlugins()
+ if (string.IsNullOrEmpty(configuration.LastVersion) || !assemblyVersion.StartsWith(configuration.LastVersion))
{
- var chatGui = Service.Get();
- var configuration = Service.Get();
- var pluginManager = Service.Get();
- var notifications = Service.Get();
-
- if (!pluginManager.ReposReady || pluginManager.InstalledPlugins.Count == 0 || pluginManager.AvailablePlugins.Count == 0)
+ chatGui.PrintChat(new XivChatEntry
{
- // Plugins aren't ready yet.
+ Message = Loc.Localize("DalamudUpdated", "The In-Game addon has been updated or was reinstalled successfully! Please check the discord for a full changelog."),
+ Type = XivChatType.Notice,
+ });
+
+ if (string.IsNullOrEmpty(configuration.LastChangelogMajorMinor) || (!ChangelogWindow.WarrantsChangelogForMajorMinor.StartsWith(configuration.LastChangelogMajorMinor) && assemblyVersion.StartsWith(ChangelogWindow.WarrantsChangelogForMajorMinor)))
+ {
+ dalamudInterface.OpenChangelogWindow();
+ configuration.LastChangelogMajorMinor = ChangelogWindow.WarrantsChangelogForMajorMinor;
+ }
+
+ configuration.LastVersion = assemblyVersion;
+ configuration.Save();
+ }
+
+ this.hasSeenLoadingMsg = true;
+ }
+
+ private void AutoUpdatePlugins()
+ {
+ var chatGui = Service.Get();
+ var configuration = Service.Get();
+ var pluginManager = Service.Get();
+ var notifications = Service.Get();
+
+ if (!pluginManager.ReposReady || pluginManager.InstalledPlugins.Count == 0 || pluginManager.AvailablePlugins.Count == 0)
+ {
+ // Plugins aren't ready yet.
+ return;
+ }
+
+ this.hasAutoUpdatedPlugins = true;
+
+ Task.Run(() => pluginManager.UpdatePluginsAsync(!configuration.AutoUpdatePlugins)).ContinueWith(task =>
+ {
+ if (task.IsFaulted)
+ {
+ Log.Error(task.Exception, Loc.Localize("DalamudPluginUpdateCheckFail", "Could not check for plugin updates."));
return;
}
- this.hasAutoUpdatedPlugins = true;
-
- Task.Run(() => pluginManager.UpdatePluginsAsync(!configuration.AutoUpdatePlugins)).ContinueWith(task =>
+ var updatedPlugins = task.Result;
+ if (updatedPlugins != null && updatedPlugins.Any())
{
- if (task.IsFaulted)
+ if (configuration.AutoUpdatePlugins)
{
- Log.Error(task.Exception, Loc.Localize("DalamudPluginUpdateCheckFail", "Could not check for plugin updates."));
- return;
+ pluginManager.PrintUpdatedPlugins(updatedPlugins, Loc.Localize("DalamudPluginAutoUpdate", "Auto-update:"));
+ notifications.AddNotification(Loc.Localize("NotificationUpdatedPlugins", "{0} of your plugins were updated.").Format(updatedPlugins.Count), Loc.Localize("NotificationAutoUpdate", "Auto-Update"), NotificationType.Info);
}
-
- var updatedPlugins = task.Result;
- if (updatedPlugins != null && updatedPlugins.Any())
+ else
{
- if (configuration.AutoUpdatePlugins)
- {
- pluginManager.PrintUpdatedPlugins(updatedPlugins, Loc.Localize("DalamudPluginAutoUpdate", "Auto-update:"));
- notifications.AddNotification(Loc.Localize("NotificationUpdatedPlugins", "{0} of your plugins were updated.").Format(updatedPlugins.Count), Loc.Localize("NotificationAutoUpdate", "Auto-Update"), NotificationType.Info);
- }
- else
- {
- var data = Service.Get();
+ var data = Service.Get();
- chatGui.PrintChat(new XivChatEntry
- {
- Message = new SeString(new List()
- {
+ chatGui.PrintChat(new XivChatEntry
+ {
+ Message = new SeString(new List()
+ {
new TextPayload(Loc.Localize("DalamudPluginUpdateRequired", "One or more of your plugins needs to be updated. Please use the /xlplugins command in-game to update them!")),
new TextPayload(" ["),
new UIForegroundPayload(500),
@@ -321,12 +321,11 @@ namespace Dalamud.Game
RawPayload.LinkTerminator,
new UIForegroundPayload(0),
new TextPayload("]"),
- }),
- Type = XivChatType.Urgent,
- });
- }
+ }),
+ Type = XivChatType.Urgent,
+ });
}
- });
- }
+ }
+ });
}
}
diff --git a/Dalamud/Game/ClientState/Buddy/BuddyList.cs b/Dalamud/Game/ClientState/Buddy/BuddyList.cs
index 21a31d868..9af104e80 100644
--- a/Dalamud/Game/ClientState/Buddy/BuddyList.cs
+++ b/Dalamud/Game/ClientState/Buddy/BuddyList.cs
@@ -7,180 +7,179 @@ using Dalamud.IoC;
using Dalamud.IoC.Internal;
using Serilog;
-namespace Dalamud.Game.ClientState.Buddy
+namespace Dalamud.Game.ClientState.Buddy;
+
+///
+/// This collection represents the buddies present in your squadron or trust party.
+/// It does not include the local player.
+///
+[PluginInterface]
+[InterfaceVersion("1.0")]
+public sealed partial class BuddyList
{
+ private const uint InvalidObjectID = 0xE0000000;
+
+ private readonly ClientStateAddressResolver address;
+
///
- /// This collection represents the buddies present in your squadron or trust party.
- /// It does not include the local player.
+ /// Initializes a new instance of the class.
///
- [PluginInterface]
- [InterfaceVersion("1.0")]
- public sealed partial class BuddyList
+ /// Client state address resolver.
+ internal BuddyList(ClientStateAddressResolver addressResolver)
{
- private const uint InvalidObjectID = 0xE0000000;
+ this.address = addressResolver;
- private readonly ClientStateAddressResolver address;
+ Log.Verbose($"Buddy list address 0x{this.address.BuddyList.ToInt64():X}");
+ }
- ///
- /// Initializes a new instance of the class.
- ///
- /// Client state address resolver.
- internal BuddyList(ClientStateAddressResolver addressResolver)
+ ///
+ /// Gets the amount of battle buddies the local player has.
+ ///
+ public int Length
+ {
+ get
{
- this.address = addressResolver;
-
- Log.Verbose($"Buddy list address 0x{this.address.BuddyList.ToInt64():X}");
- }
-
- ///
- /// Gets the amount of battle buddies the local player has.
- ///
- public int Length
- {
- get
+ var i = 0;
+ for (; i < 3; i++)
{
- var i = 0;
- for (; i < 3; i++)
- {
- var addr = this.GetBattleBuddyMemberAddress(i);
- var member = this.CreateBuddyMemberReference(addr);
- if (member == null)
- break;
- }
-
- return i;
+ var addr = this.GetBattleBuddyMemberAddress(i);
+ var member = this.CreateBuddyMemberReference(addr);
+ if (member == null)
+ break;
}
- }
- ///
- /// Gets a value indicating whether the local player's companion is present.
- ///
- public bool CompanionBuddyPresent => this.CompanionBuddy != null;
-
- ///
- /// Gets a value indicating whether the local player's pet is present.
- ///
- public bool PetBuddyPresent => this.PetBuddy != null;
-
- ///
- /// Gets the active companion buddy.
- ///
- public BuddyMember? CompanionBuddy
- {
- get
- {
- var addr = this.GetCompanionBuddyMemberAddress();
- return this.CreateBuddyMemberReference(addr);
- }
- }
-
- ///
- /// Gets the active pet buddy.
- ///
- public BuddyMember? PetBuddy
- {
- get
- {
- var addr = this.GetPetBuddyMemberAddress();
- return this.CreateBuddyMemberReference(addr);
- }
- }
-
- ///
- /// Gets the address of the buddy list.
- ///
- internal IntPtr BuddyListAddress => this.address.BuddyList;
-
- private static int BuddyMemberSize { get; } = Marshal.SizeOf();
-
- private unsafe FFXIVClientStructs.FFXIV.Client.Game.UI.Buddy* BuddyListStruct => (FFXIVClientStructs.FFXIV.Client.Game.UI.Buddy*)this.BuddyListAddress;
-
- ///
- /// Gets a battle buddy at the specified spawn index.
- ///
- /// Spawn index.
- /// A at the specified spawn index.
- public BuddyMember? this[int index]
- {
- get
- {
- var address = this.GetBattleBuddyMemberAddress(index);
- return this.CreateBuddyMemberReference(address);
- }
- }
-
- ///
- /// Gets the address of the companion buddy.
- ///
- /// The memory address of the companion buddy.
- public unsafe IntPtr GetCompanionBuddyMemberAddress()
- {
- return (IntPtr)(&this.BuddyListStruct->Companion);
- }
-
- ///
- /// Gets the address of the pet buddy.
- ///
- /// The memory address of the pet buddy.
- public unsafe IntPtr GetPetBuddyMemberAddress()
- {
- return (IntPtr)(&this.BuddyListStruct->Pet);
- }
-
- ///
- /// Gets the address of the battle buddy at the specified index of the buddy list.
- ///
- /// The index of the battle buddy.
- /// The memory address of the battle buddy.
- public unsafe IntPtr GetBattleBuddyMemberAddress(int index)
- {
- if (index < 0 || index >= 3)
- return IntPtr.Zero;
-
- return (IntPtr)(this.BuddyListStruct->BattleBuddies + (index * BuddyMemberSize));
- }
-
- ///
- /// Create a reference to a buddy.
- ///
- /// The address of the buddy in memory.
- /// object containing the requested data.
- public BuddyMember? CreateBuddyMemberReference(IntPtr address)
- {
- var clientState = Service.Get();
-
- if (clientState.LocalContentId == 0)
- return null;
-
- if (address == IntPtr.Zero)
- return null;
-
- var buddy = new BuddyMember(address);
- if (buddy.ObjectId == InvalidObjectID)
- return null;
-
- return buddy;
+ return i;
}
}
///
- /// This collection represents the buddies present in your squadron or trust party.
+ /// Gets a value indicating whether the local player's companion is present.
///
- public sealed partial class BuddyList : IReadOnlyCollection
+ public bool CompanionBuddyPresent => this.CompanionBuddy != null;
+
+ ///
+ /// Gets a value indicating whether the local player's pet is present.
+ ///
+ public bool PetBuddyPresent => this.PetBuddy != null;
+
+ ///
+ /// Gets the active companion buddy.
+ ///
+ public BuddyMember? CompanionBuddy
{
- ///
- int IReadOnlyCollection.Count => this.Length;
-
- ///
- public IEnumerator GetEnumerator()
+ get
{
- for (var i = 0; i < this.Length; i++)
- {
- yield return this[i];
- }
+ var addr = this.GetCompanionBuddyMemberAddress();
+ return this.CreateBuddyMemberReference(addr);
}
+ }
- ///
- IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
+ ///
+ /// Gets the active pet buddy.
+ ///
+ public BuddyMember? PetBuddy
+ {
+ get
+ {
+ var addr = this.GetPetBuddyMemberAddress();
+ return this.CreateBuddyMemberReference(addr);
+ }
+ }
+
+ ///
+ /// Gets the address of the buddy list.
+ ///
+ internal IntPtr BuddyListAddress => this.address.BuddyList;
+
+ private static int BuddyMemberSize { get; } = Marshal.SizeOf();
+
+ private unsafe FFXIVClientStructs.FFXIV.Client.Game.UI.Buddy* BuddyListStruct => (FFXIVClientStructs.FFXIV.Client.Game.UI.Buddy*)this.BuddyListAddress;
+
+ ///
+ /// Gets a battle buddy at the specified spawn index.
+ ///
+ /// Spawn index.
+ /// A at the specified spawn index.
+ public BuddyMember? this[int index]
+ {
+ get
+ {
+ var address = this.GetBattleBuddyMemberAddress(index);
+ return this.CreateBuddyMemberReference(address);
+ }
+ }
+
+ ///
+ /// Gets the address of the companion buddy.
+ ///
+ /// The memory address of the companion buddy.
+ public unsafe IntPtr GetCompanionBuddyMemberAddress()
+ {
+ return (IntPtr)(&this.BuddyListStruct->Companion);
+ }
+
+ ///
+ /// Gets the address of the pet buddy.
+ ///
+ /// The memory address of the pet buddy.
+ public unsafe IntPtr GetPetBuddyMemberAddress()
+ {
+ return (IntPtr)(&this.BuddyListStruct->Pet);
+ }
+
+ ///
+ /// Gets the address of the battle buddy at the specified index of the buddy list.
+ ///
+ /// The index of the battle buddy.
+ /// The memory address of the battle buddy.
+ public unsafe IntPtr GetBattleBuddyMemberAddress(int index)
+ {
+ if (index < 0 || index >= 3)
+ return IntPtr.Zero;
+
+ return (IntPtr)(this.BuddyListStruct->BattleBuddies + (index * BuddyMemberSize));
+ }
+
+ ///
+ /// Create a reference to a buddy.
+ ///
+ /// The address of the buddy in memory.
+ /// object containing the requested data.
+ public BuddyMember? CreateBuddyMemberReference(IntPtr address)
+ {
+ var clientState = Service.Get();
+
+ if (clientState.LocalContentId == 0)
+ return null;
+
+ if (address == IntPtr.Zero)
+ return null;
+
+ var buddy = new BuddyMember(address);
+ if (buddy.ObjectId == InvalidObjectID)
+ return null;
+
+ return buddy;
}
}
+
+///
+/// This collection represents the buddies present in your squadron or trust party.
+///
+public sealed partial class BuddyList : IReadOnlyCollection
+{
+ ///
+ int IReadOnlyCollection.Count => this.Length;
+
+ ///
+ public IEnumerator GetEnumerator()
+ {
+ for (var i = 0; i < this.Length; i++)
+ {
+ yield return this[i];
+ }
+ }
+
+ ///
+ IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
+}
diff --git a/Dalamud/Game/ClientState/Buddy/BuddyMember.cs b/Dalamud/Game/ClientState/Buddy/BuddyMember.cs
index 0029d20db..4d16a69d1 100644
--- a/Dalamud/Game/ClientState/Buddy/BuddyMember.cs
+++ b/Dalamud/Game/ClientState/Buddy/BuddyMember.cs
@@ -4,70 +4,69 @@ using Dalamud.Game.ClientState.Objects;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Game.ClientState.Resolvers;
-namespace Dalamud.Game.ClientState.Buddy
+namespace Dalamud.Game.ClientState.Buddy;
+
+///
+/// This class represents a buddy such as the chocobo companion, summoned pets, squadron groups and trust parties.
+///
+public unsafe class BuddyMember
{
///
- /// This class represents a buddy such as the chocobo companion, summoned pets, squadron groups and trust parties.
+ /// Initializes a new instance of the class.
///
- public unsafe class BuddyMember
+ /// Buddy address.
+ internal BuddyMember(IntPtr address)
{
- ///
- /// Initializes a new instance of the class.
- ///
- /// Buddy address.
- internal BuddyMember(IntPtr address)
- {
- this.Address = address;
- }
-
- ///
- /// Gets the address of the buddy in memory.
- ///
- public IntPtr Address { get; }
-
- ///
- /// Gets the object ID of this buddy.
- ///
- public uint ObjectId => this.Struct->ObjectID;
-
- ///
- /// Gets the actor associated with this buddy.
- ///
- ///
- /// This iterates the actor table, it should be used with care.
- ///
- public GameObject? GameObject => Service.Get().SearchById(this.ObjectId);
-
- ///
- /// Gets the current health of this buddy.
- ///
- public uint CurrentHP => this.Struct->CurrentHealth;
-
- ///
- /// Gets the maximum health of this buddy.
- ///
- public uint MaxHP => this.Struct->MaxHealth;
-
- ///
- /// Gets the data ID of this buddy.
- ///
- public uint DataID => this.Struct->DataID;
-
- ///
- /// Gets the Mount data related to this buddy. It should only be used with companion buddies.
- ///
- public ExcelResolver MountData => new(this.DataID);
-
- ///
- /// Gets the Pet data related to this buddy. It should only be used with pet buddies.
- ///
- public ExcelResolver PetData => new(this.DataID);
-
- ///
- /// Gets the Trust data related to this buddy. It should only be used with battle buddies.
- ///
- public ExcelResolver TrustData => new(this.DataID);
-
- private FFXIVClientStructs.FFXIV.Client.Game.UI.Buddy.BuddyMember* Struct => (FFXIVClientStructs.FFXIV.Client.Game.UI.Buddy.BuddyMember*)this.Address;
+ this.Address = address;
}
+
+ ///
+ /// Gets the address of the buddy in memory.
+ ///
+ public IntPtr Address { get; }
+
+ ///
+ /// Gets the object ID of this buddy.
+ ///
+ public uint ObjectId => this.Struct->ObjectID;
+
+ ///
+ /// Gets the actor associated with this buddy.
+ ///
+ ///
+ /// This iterates the actor table, it should be used with care.
+ ///
+ public GameObject? GameObject => Service.Get().SearchById(this.ObjectId);
+
+ ///
+ /// Gets the current health of this buddy.
+ ///
+ public uint CurrentHP => this.Struct->CurrentHealth;
+
+ ///
+ /// Gets the maximum health of this buddy.
+ ///
+ public uint MaxHP => this.Struct->MaxHealth;
+
+ ///
+ /// Gets the data ID of this buddy.
+ ///
+ public uint DataID => this.Struct->DataID;
+
+ ///
+ /// Gets the Mount data related to this buddy. It should only be used with companion buddies.
+ ///
+ public ExcelResolver MountData => new(this.DataID);
+
+ ///
+ /// Gets the Pet data related to this buddy. It should only be used with pet buddies.
+ ///
+ public ExcelResolver PetData => new(this.DataID);
+
+ ///
+ /// Gets the Trust data related to this buddy. It should only be used with battle buddies.
+ ///
+ public ExcelResolver TrustData => new(this.DataID);
+
+ private FFXIVClientStructs.FFXIV.Client.Game.UI.Buddy.BuddyMember* Struct => (FFXIVClientStructs.FFXIV.Client.Game.UI.Buddy.BuddyMember*)this.Address;
}
diff --git a/Dalamud/Game/ClientState/ClientState.cs b/Dalamud/Game/ClientState/ClientState.cs
index 52b63ed9e..6f7fdb6f3 100644
--- a/Dalamud/Game/ClientState/ClientState.cs
+++ b/Dalamud/Game/ClientState/ClientState.cs
@@ -16,165 +16,164 @@ using Dalamud.IoC;
using Dalamud.IoC.Internal;
using Serilog;
-namespace Dalamud.Game.ClientState
+namespace Dalamud.Game.ClientState;
+
+///
+/// This class represents the state of the game client at the time of access.
+///
+[PluginInterface]
+[InterfaceVersion("1.0")]
+public sealed class ClientState : IDisposable
{
+ private readonly ClientStateAddressResolver address;
+ private readonly Hook setupTerritoryTypeHook;
+
+ private bool lastConditionNone = true;
+
///
- /// This class represents the state of the game client at the time of access.
+ /// Initializes a new instance of the class.
+ /// Set up client state access.
///
- [PluginInterface]
- [InterfaceVersion("1.0")]
- public sealed class ClientState : IDisposable
+ internal ClientState()
{
- private readonly ClientStateAddressResolver address;
- private readonly Hook setupTerritoryTypeHook;
+ this.address = new ClientStateAddressResolver();
+ this.address.Setup();
- private bool lastConditionNone = true;
+ Log.Verbose("===== C L I E N T S T A T E =====");
- ///
- /// Initializes a new instance of the class.
- /// Set up client state access.
- ///
- internal ClientState()
+ this.ClientLanguage = Service.Get().Language;
+
+ Service.Set(this.address);
+
+ Service.Set(this.address);
+
+ Service.Set(this.address);
+
+ Service.Set(this.address);
+
+ Service.Set(this.address);
+
+ Service.Set(this.address);
+
+ Service.Set(this.address);
+
+ Service.Set(this.address);
+
+ Service.Set(this.address);
+
+ Log.Verbose($"SetupTerritoryType address 0x{this.address.SetupTerritoryType.ToInt64():X}");
+
+ this.setupTerritoryTypeHook = new Hook(this.address.SetupTerritoryType, this.SetupTerritoryTypeDetour);
+
+ var framework = Service.Get();
+ framework.Update += this.FrameworkOnOnUpdateEvent;
+
+ var networkHandlers = Service.Get();
+ networkHandlers.CfPop += this.NetworkHandlersOnCfPop;
+ }
+
+ [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
+ private delegate IntPtr SetupTerritoryTypeDelegate(IntPtr manager, ushort terriType);
+
+ ///
+ /// Event that gets fired when the current Territory changes.
+ ///
+ public event EventHandler TerritoryChanged;
+
+ ///
+ /// Event that fires when a character is logging in.
+ ///
+ public event EventHandler Login;
+
+ ///
+ /// Event that fires when a character is logging out.
+ ///
+ public event EventHandler Logout;
+
+ ///
+ /// Event that gets fired when a duty is ready.
+ ///
+ public event EventHandler CfPop;
+
+ ///
+ /// Gets the language of the client.
+ ///
+ public ClientLanguage ClientLanguage { get; }
+
+ ///
+ /// Gets the current Territory the player resides in.
+ ///
+ public ushort TerritoryType { get; private set; }
+
+ ///
+ /// Gets the local player character, if one is present.
+ ///
+ public PlayerCharacter? LocalPlayer => Service.Get()[0] as PlayerCharacter;
+
+ ///
+ /// Gets the content ID of the local character.
+ ///
+ public ulong LocalContentId => (ulong)Marshal.ReadInt64(this.address.LocalContentId);
+
+ ///
+ /// Gets a value indicating whether a character is logged in.
+ ///
+ public bool IsLoggedIn { get; private set; }
+
+ ///
+ /// Enable this module.
+ ///
+ public void Enable()
+ {
+ Service.Get().Enable();
+ Service