diff --git a/Dalamud/Game/ChatHandlers.cs b/Dalamud/Game/ChatHandlers.cs index 2d7d3c83a..d29c89f70 100644 --- a/Dalamud/Game/ChatHandlers.cs +++ b/Dalamud/Game/ChatHandlers.cs @@ -49,7 +49,7 @@ internal partial class ChatHandlers : IServiceType [GeneratedRegex(@"(http|ftp|https)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?", RegexOptions.Compiled)] private static partial Regex CompiledUrlRegex(); - private void OnCheckMessageHandled(XivChatType type, int timestamp, ref SeString sender, ref SeString message, ref bool isHandled) + private void OnCheckMessageHandled(XivChatType type, XivChatRelationKind sourceKind, XivChatRelationKind targetKind, int timestamp, ref SeString sender, ref SeString message, ref bool isHandled) { var textVal = message.TextValue; @@ -63,7 +63,7 @@ internal partial class ChatHandlers : IServiceType } } - private void OnChatMessage(XivChatType type, int timestamp, ref SeString sender, ref SeString message, ref bool isHandled) + private void OnChatMessage(XivChatType type, XivChatRelationKind sourceKind, XivChatRelationKind targetKind, int timestamp, ref SeString sender, ref SeString message, ref bool isHandled) { var clientState = Service.GetNullable(); if (clientState == null) diff --git a/Dalamud/Game/Gui/ChatGui.cs b/Dalamud/Game/Gui/ChatGui.cs index c514752da..314f7f391 100644 --- a/Dalamud/Game/Gui/ChatGui.cs +++ b/Dalamud/Game/Gui/ChatGui.cs @@ -44,7 +44,7 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui private readonly Dictionary<(string PluginName, uint CommandId), Action> dalamudLinkHandlers = []; private readonly List seenLogMessageObjects = []; - private readonly Hook printMessageHook; + private readonly Hook printMessageHook; private readonly Hook inventoryItemCopyHook; private readonly Hook handleLinkClickHook; private readonly Hook handleLogModuleUpdate; @@ -58,7 +58,7 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui [ServiceManager.ServiceConstructor] private ChatGui() { - this.printMessageHook = Hook.FromAddress(RaptureLogModule.Addresses.PrintMessage.Value, this.HandlePrintMessageDetour); + this.printMessageHook = Hook.FromAddress(RaptureLogModule.Addresses.PrintMessage.Value, this.HandlePrintMessageDetour); this.inventoryItemCopyHook = Hook.FromAddress((nint)InventoryItem.StaticVirtualTablePointer->Copy, this.InventoryItemCopyDetour); this.handleLinkClickHook = Hook.FromAddress(LogViewer.Addresses.HandleLinkClick.Value, this.HandleLinkClickDetour); this.handleLogModuleUpdate = Hook.FromAddress(RaptureLogModule.Addresses.Update.Value, this.UpdateDetour); @@ -69,9 +69,6 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui this.handleLogModuleUpdate.Enable(); } - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - private delegate uint PrintMessageDelegate(RaptureLogModule* manager, XivChatType chatType, Utf8String* sender, Utf8String* message, int timestamp, byte silent); - /// public event IChatGui.OnMessageDelegate? ChatMessage; @@ -249,11 +246,11 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui this.HandlePrintMessageDetour( RaptureLogModule.Instance(), - targetChannel, + (ushort)targetChannel, &sender, &message, chat.Timestamp, - (byte)(chat.Silent ? 1 : 0)); + chat.Silent); } } @@ -373,7 +370,7 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui } } - private uint HandlePrintMessageDetour(RaptureLogModule* manager, XivChatType chatType, Utf8String* sender, Utf8String* message, int timestamp, byte silent) + private uint HandlePrintMessageDetour(RaptureLogModule* manager, ushort logInfo, Utf8String* sender, Utf8String* message, int timestamp, bool silent) { var messageId = 0u; @@ -385,6 +382,10 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui var terminatedSender = parsedSender.EncodeWithNullTerminator(); var terminatedMessage = parsedMessage.EncodeWithNullTerminator(); + var logKind = (XivChatType)(logInfo & 0x7F); + var sourceKind = (XivChatRelationKind)((logInfo >> 11) & 0xF); + var targetKind = (XivChatRelationKind)((logInfo >> 7) & 0xF); + // Call events var isHandled = false; @@ -392,7 +393,7 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui { try { - action(chatType, timestamp, ref parsedSender, ref parsedMessage, ref isHandled); + action(logKind, sourceKind, targetKind, timestamp, ref parsedSender, ref parsedMessage, ref isHandled); } catch (Exception e) { @@ -406,7 +407,7 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui { try { - action(chatType, timestamp, ref parsedSender, ref parsedMessage, ref isHandled); + action(logKind, sourceKind, targetKind, timestamp, ref parsedSender, ref parsedMessage, ref isHandled); } catch (Exception e) { @@ -434,19 +435,19 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui if (isHandled) { foreach (var d in Delegate.EnumerateInvocationList(this.ChatMessageHandled)) - d(chatType, timestamp, parsedSender, parsedMessage); + d(logKind, sourceKind, targetKind, timestamp, parsedSender, parsedMessage); } else { - messageId = this.printMessageHook.Original(manager, chatType, sender, message, timestamp, silent); + messageId = this.printMessageHook.Original(manager, logInfo, sender, message, timestamp, silent); foreach (var d in Delegate.EnumerateInvocationList(this.ChatMessageUnhandled)) - d(chatType, timestamp, parsedSender, parsedMessage); + d(logKind, sourceKind, targetKind, timestamp, parsedSender, parsedMessage); } } catch (Exception ex) { Log.Error(ex, "Exception on OnChatMessage hook."); - messageId = this.printMessageHook.Original(manager, chatType, sender, message, timestamp, silent); + messageId = this.printMessageHook.Original(manager, logInfo, sender, message, timestamp, silent); } return messageId; @@ -653,17 +654,17 @@ internal class ChatGuiPluginScoped : IInternalDisposableService, IChatGui public void PrintError(ReadOnlySpan message, string? messageTag = null, ushort? tagColor = null) => this.chatGuiService.PrintError(message, messageTag, tagColor); - private void OnMessageForward(XivChatType type, int timestamp, ref SeString sender, ref SeString message, ref bool isHandled) - => this.ChatMessage?.Invoke(type, timestamp, ref sender, ref message, ref isHandled); + private void OnMessageForward(XivChatType type, XivChatRelationKind sourceKind, XivChatRelationKind targetKind, int timestamp, ref SeString sender, ref SeString message, ref bool isHandled) + => this.ChatMessage?.Invoke(type, sourceKind, targetKind, timestamp, ref sender, ref message, ref isHandled); - private void OnCheckMessageForward(XivChatType type, int timestamp, ref SeString sender, ref SeString message, ref bool isHandled) - => this.CheckMessageHandled?.Invoke(type, timestamp, ref sender, ref message, ref isHandled); + private void OnCheckMessageForward(XivChatType type, XivChatRelationKind sourceKind, XivChatRelationKind targetKind, int timestamp, ref SeString sender, ref SeString message, ref bool isHandled) + => this.CheckMessageHandled?.Invoke(type, sourceKind, targetKind, timestamp, ref sender, ref message, ref isHandled); - private void OnMessageHandledForward(XivChatType type, int timestamp, SeString sender, SeString message) - => this.ChatMessageHandled?.Invoke(type, timestamp, sender, message); + private void OnMessageHandledForward(XivChatType type, XivChatRelationKind sourceKind, XivChatRelationKind targetKind, int timestamp, SeString sender, SeString message) + => this.ChatMessageHandled?.Invoke(type, sourceKind, targetKind, timestamp, sender, message); - private void OnMessageUnhandledForward(XivChatType type, int timestamp, SeString sender, SeString message) - => this.ChatMessageUnhandled?.Invoke(type, timestamp, sender, message); + private void OnMessageUnhandledForward(XivChatType type, XivChatRelationKind sourceKind, XivChatRelationKind targetKind, int timestamp, SeString sender, SeString message) + => this.ChatMessageUnhandled?.Invoke(type, sourceKind, targetKind, timestamp, sender, message); private void OnLogMessageForward(Chat.ILogMessage message) => this.LogMessage?.Invoke(message); diff --git a/Dalamud/Game/Text/XivChatRelationKind.cs b/Dalamud/Game/Text/XivChatRelationKind.cs new file mode 100644 index 000000000..d58548a5f --- /dev/null +++ b/Dalamud/Game/Text/XivChatRelationKind.cs @@ -0,0 +1,44 @@ +namespace Dalamud.Game.Text; + +/// +/// Specifies the relationship for entities involved in a chat log event (e.g., Source or Target).
+/// Used primarily for parsing and coloring chat log messages. +///
+public enum XivChatRelationKind : byte +{ + /// No specific relation or unknown entity. + None = 0, + + /// The player currently controlled by the local client. + LocalPlayer = 1, + + /// A player in the same 4-man or 8-man party as the local player. + PartyMember = 2, + + /// A player in the same alliance raid. + AllianceMember = 3, + + /// A player not in the local player's party or alliance. + OtherPlayer = 4, + + /// An enemy entity that is currently in combat with the player or party. + EngagedEnemy = 5, + + /// An enemy entity that is not yet in combat or claimed. + UnengagedEnemy = 6, + + /// An NPC that is friendly or neutral to the player (e.g., EventNPCs). + FriendlyNpc = 7, + + /// A pet (Summoner/Scholar) or companion (Chocobo) belonging to the local player. + PetOrCompanion = 8, + + /// A pet or companion belonging to a member of the local player's party. + PetOrCompanionParty = 9, + + /// A pet or companion belonging to a member of the alliance. + PetOrCompanionAlliance = 10, + + /// A pet or companion belonging to a player not in the party or alliance. + PetOrCompanionOther = 11, +} diff --git a/Dalamud/Interface/Internal/Windows/SelfTest/Steps/ChatSelfTestStep.cs b/Dalamud/Interface/Internal/Windows/SelfTest/Steps/ChatSelfTestStep.cs index 851957b4b..2f74fedd4 100644 --- a/Dalamud/Interface/Internal/Windows/SelfTest/Steps/ChatSelfTestStep.cs +++ b/Dalamud/Interface/Internal/Windows/SelfTest/Steps/ChatSelfTestStep.cs @@ -105,7 +105,7 @@ internal class ChatSelfTestStep : ISelfTestStep } private void ChatOnOnChatMessage( - XivChatType type, int timestamp, ref SeString sender, ref SeString message, ref bool ishandled) + XivChatType type, XivChatRelationKind sourceKind, XivChatRelationKind targetKind, int timestamp, ref SeString sender, ref SeString message, ref bool ishandled) { if (type == XivChatType.Echo && message.TextValue == "DALAMUD") { diff --git a/Dalamud/Plugin/Services/IChatGui.cs b/Dalamud/Plugin/Services/IChatGui.cs index 2bb7b6913..7244085c5 100644 --- a/Dalamud/Plugin/Services/IChatGui.cs +++ b/Dalamud/Plugin/Services/IChatGui.cs @@ -17,39 +17,47 @@ public interface IChatGui : IDalamudService /// A delegate type used with the event. /// /// The type of chat. + /// The relationship of the entity sending the message or performing the action. + /// The relationship of the entity receiving the message or being targeted by the action. /// The timestamp of when the message was sent. /// The sender name. /// The message sent. /// A value indicating whether the message was handled or should be propagated. - public delegate void OnMessageDelegate(XivChatType type, int timestamp, ref SeString sender, ref SeString message, ref bool isHandled); + public delegate void OnMessageDelegate(XivChatType type, XivChatRelationKind sourceKind, XivChatRelationKind targetKind, int timestamp, ref SeString sender, ref SeString message, ref bool isHandled); /// /// A delegate type used with the event. /// /// The type of chat. + /// The relationship of the entity sending the message or performing the action. + /// The relationship of the entity receiving the message or being targeted by the action. /// The timestamp of when the message was sent. /// The sender name. /// The message sent. /// A value indicating whether the message was handled or should be propagated. - public delegate void OnCheckMessageHandledDelegate(XivChatType type, int timestamp, ref SeString sender, ref SeString message, ref bool isHandled); + public delegate void OnCheckMessageHandledDelegate(XivChatType type, XivChatRelationKind sourceKind, XivChatRelationKind targetKind, int timestamp, ref SeString sender, ref SeString message, ref bool isHandled); /// /// A delegate type used with the event. /// /// The type of chat. + /// The relationship of the entity sending the message or performing the action. + /// The relationship of the entity receiving the message or being targeted by the action. /// The timestamp of when the message was sent. /// The sender name. /// The message sent. - public delegate void OnMessageHandledDelegate(XivChatType type, int timestamp, SeString sender, SeString message); + public delegate void OnMessageHandledDelegate(XivChatType type, XivChatRelationKind sourceKind, XivChatRelationKind targetKind, int timestamp, SeString sender, SeString message); /// /// A delegate type used with the event. /// /// The type of chat. + /// The relationship of the entity sending the message or performing the action. + /// The relationship of the entity receiving the message or being targeted by the action. /// The timestamp of when the message was sent. /// The sender name. /// The message sent. - public delegate void OnMessageUnhandledDelegate(XivChatType type, int timestamp, SeString sender, SeString message); + public delegate void OnMessageUnhandledDelegate(XivChatType type, XivChatRelationKind sourceKind, XivChatRelationKind targetKind, int timestamp, SeString sender, SeString message); /// /// A delegate type used with the event.