diff --git a/ChatTwo/ChatTwoConflictDetector.cs b/ChatTwo/ChatTwoConflictDetector.cs new file mode 100644 index 0000000..64ef39d --- /dev/null +++ b/ChatTwo/ChatTwoConflictDetector.cs @@ -0,0 +1,27 @@ +using System.Linq; +using ChatTwo.Resources; +using Dalamud.Plugin; + +namespace ChatTwo; + +internal static class ChatTwoConflictDetector +{ + private const string UpstreamInternalName = "ChatTwo"; + + public static void ThrowIfChatTwoIsLoaded(IDalamudPluginInterface pluginInterface) + { + var conflict = pluginInterface.InstalledPlugins + .FirstOrDefault(p => + p.InternalName == UpstreamInternalName && + p.IsLoaded); + + if (conflict is null) + return; + + var message = HellionStrings.ChatTwoConflictTitle + "\n\n" + + HellionStrings.ChatTwoConflictBody + "\n\n" + + HellionStrings.ChatTwoConflictAction; + + throw new System.InvalidOperationException(message); + } +} diff --git a/ChatTwo/Plugin.cs b/ChatTwo/Plugin.cs index 161f48b..608475a 100755 --- a/ChatTwo/Plugin.cs +++ b/ChatTwo/Plugin.cs @@ -94,6 +94,12 @@ public sealed class Plugin : IDalamudPlugin public Plugin() { + // Refuse to start if upstream Chat 2 is loaded — prevents IPC + // channel collisions and double-replacement of the in-game chat + // window. Throwing here makes Dalamud abort the load cleanly with + // our localized message instead of crashing FFXIV mid-frame. + ChatTwoConflictDetector.ThrowIfChatTwoIsLoaded(Interface); + try { GameStarted = Process.GetCurrentProcess().StartTime.ToUniversalTime(); diff --git a/ChatTwo/Resources/HellionStrings.Designer.cs b/ChatTwo/Resources/HellionStrings.Designer.cs index 18de8e1..6b360ed 100644 --- a/ChatTwo/Resources/HellionStrings.Designer.cs +++ b/ChatTwo/Resources/HellionStrings.Designer.cs @@ -270,4 +270,9 @@ internal class HellionStrings internal static string Hint_v061_PopOutHeader_Body => Get(nameof(Hint_v061_PopOutHeader_Body)); internal static string Hint_v061_PopOutHeader_Ack => Get(nameof(Hint_v061_PopOutHeader_Ack)); internal static string Hint_v061_PopOutHeader_OpenSettings => Get(nameof(Hint_v061_PopOutHeader_OpenSettings)); + + // Hellion Chat — v1.0.0 Chat 2 parallel-load conflict detection + internal static string ChatTwoConflictTitle => Get(nameof(ChatTwoConflictTitle)); + internal static string ChatTwoConflictBody => Get(nameof(ChatTwoConflictBody)); + internal static string ChatTwoConflictAction => Get(nameof(ChatTwoConflictAction)); } diff --git a/ChatTwo/Resources/HellionStrings.de.resx b/ChatTwo/Resources/HellionStrings.de.resx index 5002f28..9111ebb 100644 --- a/ChatTwo/Resources/HellionStrings.de.resx +++ b/ChatTwo/Resources/HellionStrings.de.resx @@ -609,4 +609,13 @@ Einstellungen öffnen + + Hellion Chat kann nicht starten, solange Chat 2 geladen ist. + + + Hellion Chat ist ein eigenständiger Fork von Chat 2. Beide Plugins ersetzen dasselbe Chat-Fenster im Spiel und würden zur Laufzeit kollidieren. + + + Chat 2 in /xlplugins deaktivieren, danach Hellion Chat erneut aktivieren. + diff --git a/ChatTwo/Resources/HellionStrings.resx b/ChatTwo/Resources/HellionStrings.resx index 8006988..deae647 100644 --- a/ChatTwo/Resources/HellionStrings.resx +++ b/ChatTwo/Resources/HellionStrings.resx @@ -609,4 +609,13 @@ Open Settings + + Hellion Chat cannot start while Chat 2 is loaded. + + + Hellion Chat is a standalone fork of Chat 2. Both plugins replace the same in-game chat window and would conflict at runtime if loaded together. + + + Disable Chat 2 in /xlplugins, then re-enable Hellion Chat. +