feat(safety): refuse to load when Chat 2 is also active
When the user has both Hellion Chat and upstream Chat 2 installed and loaded, the parallel chat-window replacement and Hook collisions can crash FFXIV at frame boundaries. The new detector inspects IDalamudPluginInterface.InstalledPlugins and throws an InvalidOperationException with a localized message if Chat 2 is loaded, which Dalamud surfaces cleanly instead of letting the load proceed into a runtime crash. Bilingual messages (EN/DE) follow the existing HellionStrings pattern.
This commit is contained in:
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -94,6 +94,12 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
|
|
||||||
public Plugin()
|
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
|
try
|
||||||
{
|
{
|
||||||
GameStarted = Process.GetCurrentProcess().StartTime.ToUniversalTime();
|
GameStarted = Process.GetCurrentProcess().StartTime.ToUniversalTime();
|
||||||
|
|||||||
+5
@@ -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_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_Ack => Get(nameof(Hint_v061_PopOutHeader_Ack));
|
||||||
internal static string Hint_v061_PopOutHeader_OpenSettings => Get(nameof(Hint_v061_PopOutHeader_OpenSettings));
|
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));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -609,4 +609,13 @@
|
|||||||
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
|
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
|
||||||
<value>Einstellungen öffnen</value>
|
<value>Einstellungen öffnen</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ChatTwoConflictTitle" xml:space="preserve">
|
||||||
|
<value>Hellion Chat kann nicht starten, solange Chat 2 geladen ist.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ChatTwoConflictBody" xml:space="preserve">
|
||||||
|
<value>Hellion Chat ist ein eigenständiger Fork von Chat 2. Beide Plugins ersetzen dasselbe Chat-Fenster im Spiel und würden zur Laufzeit kollidieren.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ChatTwoConflictAction" xml:space="preserve">
|
||||||
|
<value>Chat 2 in /xlplugins deaktivieren, danach Hellion Chat erneut aktivieren.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -609,4 +609,13 @@
|
|||||||
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
|
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
|
||||||
<value>Open Settings</value>
|
<value>Open Settings</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ChatTwoConflictTitle" xml:space="preserve">
|
||||||
|
<value>Hellion Chat cannot start while Chat 2 is loaded.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ChatTwoConflictBody" xml:space="preserve">
|
||||||
|
<value>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.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ChatTwoConflictAction" xml:space="preserve">
|
||||||
|
<value>Disable Chat 2 in /xlplugins, then re-enable Hellion Chat.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
Reference in New Issue
Block a user