diff --git a/ChatTwo/Chunk.cs b/ChatTwo/Chunk.cs index fd14a56..cab50ec 100755 --- a/ChatTwo/Chunk.cs +++ b/ChatTwo/Chunk.cs @@ -4,9 +4,11 @@ using Dalamud.Game.Text.SeStringHandling; namespace ChatTwo; internal abstract class Chunk { + internal SeString? Source { get; set; } internal Payload? Link { get; set; } - protected Chunk(Payload? link) { + protected Chunk(SeString? source, Payload? link) { + this.Source = source; this.Link = link; } } @@ -18,11 +20,11 @@ internal class TextChunk : Chunk { internal bool Italic { get; set; } internal string Content { get; set; } - internal TextChunk(Payload? link, string content) : base(link) { + internal TextChunk(SeString? source, Payload? link, string content) : base(source, link) { this.Content = content; } - internal TextChunk(Payload? link, ChatType? fallbackColour, uint? foreground, uint? glow, bool italic, string content) : base(link) { + internal TextChunk(SeString? source, Payload? link, ChatType? fallbackColour, uint? foreground, uint? glow, bool italic, string content) : base(source, link) { this.FallbackColour = fallbackColour; this.Foreground = foreground; this.Glow = glow; @@ -34,7 +36,7 @@ internal class TextChunk : Chunk { internal class IconChunk : Chunk { internal BitmapFontIcon Icon { get; set; } - public IconChunk(Payload? link, BitmapFontIcon icon) : base(link) { + public IconChunk(SeString? source, Payload? link, BitmapFontIcon icon) : base(source, link) { this.Icon = icon; } } diff --git a/ChatTwo/PayloadHandler.cs b/ChatTwo/PayloadHandler.cs index 1230c63..0ccf9be 100755 --- a/ChatTwo/PayloadHandler.cs +++ b/ChatTwo/PayloadHandler.cs @@ -1,4 +1,5 @@ using System.Numerics; +using System.Reflection; using ChatTwo.Ui; using ChatTwo.Util; using Dalamud.Game.ClientState.Objects.SubKinds; @@ -54,12 +55,12 @@ internal sealed class PayloadHandler { } } - internal void Click(Payload payload, ImGuiMouseButton button) { + internal void Click(Chunk chunk, Payload payload, ImGuiMouseButton button) { PluginLog.Log($"clicked {payload} with {button}"); switch (button) { case ImGuiMouseButton.Left: - this.LeftClickPayload(payload); + this.LeftClickPayload(chunk, payload); break; case ImGuiMouseButton.Right: this.RightClickPayload(payload); @@ -145,7 +146,7 @@ internal sealed class PayloadHandler { this.Log.DrawChunks(desc.ToList()); } - private void LeftClickPayload(Payload payload) { + private void LeftClickPayload(Chunk chunk, Payload payload) { switch (payload) { case MapLinkPayload map: { this.Ui.Plugin.GameGui.OpenMapWithMapLink(map); @@ -156,11 +157,38 @@ internal sealed class PayloadHandler { break; } case DalamudLinkPayload link: { + this.ClickLinkPayload(chunk, payload, link); break; } } } + private void ClickLinkPayload(Chunk chunk, Payload payload, DalamudLinkPayload link) { + if (chunk.Source is not { } source) { + return; + } + + var start = source.Payloads.IndexOf(payload); + var end = source.Payloads.IndexOf(RawPayload.LinkTerminator); + if (start == -1 || end == -1) { + return; + } + + var payloads = source.Payloads.Skip(start).Take(end - start + 1).ToList(); + + var chatGui = this.Ui.Plugin.ChatGui; + var field = chatGui.GetType().GetField("dalamudLinkHandlers", BindingFlags.Instance | BindingFlags.NonPublic); + if (field == null || field.GetValue(chatGui) is not Dictionary<(string PluginName, uint CommandId), Action> dict || !dict.TryGetValue((link.Plugin, link.CommandId), out var action)) { + return; + } + + try { + action(link.CommandId, new SeString(payloads)); + } catch (Exception ex) { + PluginLog.LogError(ex, "Error executing DalamudLinkPayload handler"); + } + } + private void RightClickPayload(Payload payload) { switch (payload) { case PlayerPayload player: { diff --git a/ChatTwo/Store.cs b/ChatTwo/Store.cs index 5b21e23..5c6008e 100755 --- a/ChatTwo/Store.cs +++ b/ChatTwo/Store.cs @@ -86,11 +86,11 @@ internal class Store : IDisposable { var senderChunks = new List(); if (formatting is { IsPresent: true }) { - senderChunks.Add(new TextChunk(null, formatting.Before) { + senderChunks.Add(new TextChunk(null, null, formatting.Before) { FallbackColour = chatCode.Type, }); senderChunks.AddRange(ChunkUtil.ToChunks(sender, chatCode.Type)); - senderChunks.Add(new TextChunk(null, formatting.After) { + senderChunks.Add(new TextChunk(null, null, formatting.After) { FallbackColour = chatCode.Type, }); } diff --git a/ChatTwo/Ui/ChatLog.cs b/ChatTwo/Ui/ChatLog.cs index 6ea3054..8b03a69 100755 --- a/ChatTwo/Ui/ChatLog.cs +++ b/ChatTwo/Ui/ChatLog.cs @@ -94,7 +94,7 @@ internal sealed class ChatLog : IUiComponent { if (tab.DisplayTimestamp) { var timestamp = message.Date.ToLocalTime().ToString("t"); - this.DrawChunk(new TextChunk(null, $"[{timestamp}]") { + this.DrawChunk(new TextChunk(null, null, $"[{timestamp}]") { Foreground = 0xFFFFFFFF, }); ImGui.SameLine(); @@ -298,7 +298,7 @@ internal sealed class ChatLog : IUiComponent { var uv0 = new Vector2(bounds.Value.X, bounds.Value.Y - 2) / texSize; var uv1 = new Vector2(bounds.Value.X + bounds.Value.Z, bounds.Value.Y - 2 + bounds.Value.W) / texSize; ImGui.Image(this._fontIcon.ImGuiHandle, size, uv0, uv1); - ImGuiUtil.PostPayload(chunk.Link, handler); + ImGuiUtil.PostPayload(chunk, handler); } return; @@ -325,7 +325,7 @@ internal sealed class ChatLog : IUiComponent { ImGui.PushFont(this.Ui.ItalicFont.Value); } - ImGuiUtil.WrapText(text.Content, chunk.Link, handler); + ImGuiUtil.WrapText(text.Content, chunk, handler); if (text.Italic && this.Ui.ItalicFont.HasValue) { ImGui.PopFont(); diff --git a/ChatTwo/Util/ChunkUtil.cs b/ChatTwo/Util/ChunkUtil.cs index 7c40c23..57ec3e3 100755 --- a/ChatTwo/Util/ChunkUtil.cs +++ b/ChatTwo/Util/ChunkUtil.cs @@ -14,7 +14,7 @@ internal static class ChunkUtil { Payload? link = null; void Append(string text) { - chunks.Add(new TextChunk(link, text) { + chunks.Add(new TextChunk(msg, link, text) { FallbackColour = defaultColour, Foreground = foreground.Count > 0 ? foreground.Peek() : null, Glow = glow.Count > 0 ? glow.Peek() : null, @@ -47,13 +47,13 @@ internal static class ChunkUtil { break; case PayloadType.AutoTranslateText: - chunks.Add(new IconChunk(link, BitmapFontIcon.AutoTranslateBegin)); + chunks.Add(new IconChunk(msg, link, BitmapFontIcon.AutoTranslateBegin)); var autoText = ((AutoTranslatePayload) payload).Text; Append(autoText.Substring(2, autoText.Length - 4)); - chunks.Add(new IconChunk(link, BitmapFontIcon.AutoTranslateEnd)); + chunks.Add(new IconChunk(msg, link, BitmapFontIcon.AutoTranslateEnd)); break; case PayloadType.Icon: - chunks.Add(new IconChunk(link, ((IconPayload) payload).Icon)); + chunks.Add(new IconChunk(msg, link, ((IconPayload) payload).Icon)); break; case PayloadType.MapLink: case PayloadType.Quest: diff --git a/ChatTwo/Util/ImGuiUtil.cs b/ChatTwo/Util/ImGuiUtil.cs index 0b1ea39..6619847 100755 --- a/ChatTwo/Util/ImGuiUtil.cs +++ b/ChatTwo/Util/ImGuiUtil.cs @@ -1,5 +1,4 @@ using System.Text; -using Dalamud.Game.Text.SeStringHandling; using Dalamud.Interface; using ImGuiNET; @@ -12,7 +11,8 @@ internal static class ImGuiUtil { ImGuiMouseButton.Right, }; - internal static void PostPayload(Payload? payload, PayloadHandler? handler) { + internal static void PostPayload(Chunk chunk, PayloadHandler? handler) { + var payload = chunk.Link; if (payload != null && ImGui.IsItemHovered()) { ImGui.SetMouseCursor(ImGuiMouseCursor.Hand); handler?.Hover(payload); @@ -24,15 +24,15 @@ internal static class ImGuiUtil { foreach (var button in Buttons) { if (ImGui.IsItemClicked(button)) { - handler.Click(payload, button); + handler.Click(chunk, payload, button); } } } - internal static unsafe void WrapText(string csText, Payload? payload, PayloadHandler? handler) { + internal static unsafe void WrapText(string csText, Chunk chunk, PayloadHandler? handler) { void Text(byte* text, byte* textEnd) { ImGuiNative.igTextUnformatted(text, textEnd); - PostPayload(payload, handler); + PostPayload(chunk, handler); } if (csText.Length == 0) {