diff --git a/HellionChat/GameFunctions/GameFunctions.cs b/HellionChat/GameFunctions/GameFunctions.cs index 5e6de44..31b8970 100755 --- a/HellionChat/GameFunctions/GameFunctions.cs +++ b/HellionChat/GameFunctions/GameFunctions.cs @@ -249,9 +249,15 @@ internal unsafe class GameFunctions : IDisposable private nint ResolveTextCommandPlaceholderDetour(nint a1, byte* placeholderText, byte a3, byte a4) { + // The detour is only invoked through the hook, so the hook should + // never be null here, but the nullable field declaration forces us + // to handle the theoretical race during teardown. + if (ResolveTextCommandPlaceholderHook is null) + return nint.Zero; + var placeholder = MemoryHelper.ReadStringNullTerminated((nint) placeholderText); if (ReplacementName == null || placeholder != Placeholder) - return ResolveTextCommandPlaceholderHook!.Original(a1, placeholderText, a3, a4); + return ResolveTextCommandPlaceholderHook.Original(a1, placeholderText, a3, a4); MemoryHelper.WriteString(PlaceholderNamePtr, ReplacementName); ReplacementName = null; diff --git a/HellionChat/GameFunctions/Types/TellTarget.cs b/HellionChat/GameFunctions/Types/TellTarget.cs index e1c9469..b6151c2 100755 --- a/HellionChat/GameFunctions/Types/TellTarget.cs +++ b/HellionChat/GameFunctions/Types/TellTarget.cs @@ -30,6 +30,9 @@ public class TellTarget public unsafe void FromTarget(IPlayerCharacter target) { + if (target.Address == nint.Zero) + return; + Name = target.Name.TextValue; World = target.HomeWorld.RowId; ContentId = ((Character*)target.Address)->ContentId; diff --git a/HellionChat/Ipc/ExtraChat.cs b/HellionChat/Ipc/ExtraChat.cs index 178cb96..b04521e 100644 --- a/HellionChat/Ipc/ExtraChat.cs +++ b/HellionChat/Ipc/ExtraChat.cs @@ -49,6 +49,8 @@ public sealed class ExtraChat : IDisposable public void Dispose() { OverrideChannelGate.Unsubscribe(OnOverrideChannel); + ChannelCommandColoursGate.Unsubscribe(OnChannelCommandColours); + ChannelNamesGate.Unsubscribe(OnChannelNames); } private void OnOverrideChannel(OverrideInfo info)