diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index 6165dd89a..43591ea4f 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -558,23 +558,11 @@ namespace Dalamud { private void OnItemLinkCommand(string command, string arguments) { this.itemSearchCommandWindow = new ItemSearchWindow(this.Data, new UiBuilder(this.InterfaceManager, "ItemSearcher"), false); - this.itemSearchCommandWindow.OnItemChosen += (sender, item) => { - var hexData = new byte[] { - 0x02, 0x13, 0x06, 0xFE, 0xFF, 0xF3, 0xF3, 0xF3, 0x03, 0x02, 0x27, 0x07, 0x03, 0xF2, 0x3A, 0x2F, - 0x02, 0x01, 0x03, 0x02, 0x13, 0x06, 0xFE, 0xFF, 0xFF, 0x7B, 0x1A, 0x03, 0xEE, 0x82, 0xBB, 0x02, - 0x13, 0x02, 0xEC, 0x03 - }; - - var endTag = new byte[] { - 0x02, 0x27, 0x07, 0xCF, 0x01, 0x01, 0x01, 0xFF, 0x01, 0x03, 0x02, 0x13, 0x02, 0xEC, 0x03 - }; - - BitConverter.GetBytes((short) item.RowId).Reverse().ToArray().CopyTo(hexData, 14); - - hexData = hexData.Concat(Encoding.UTF8.GetBytes(item.Name)).Concat(endTag).ToArray(); - - this.Framework.Gui.Chat.PrintChat(new XivChatEntry { - MessageBytes = hexData + this.itemSearchCommandWindow.OnItemChosen += (sender, item) => + { + this.Framework.Gui.Chat.PrintChat(new XivChatEntry + { + MessageBytes = SeStringUtils.CreateItemLink((uint)item.RowId, false).Encode() }); }; this.isImguiDrawItemSearchWindow = true; diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/RawPayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/RawPayload.cs index a71060cfb..4bde12652 100644 --- a/Dalamud/Game/Chat/SeStringHandling/Payloads/RawPayload.cs +++ b/Dalamud/Game/Chat/SeStringHandling/Payloads/RawPayload.cs @@ -29,8 +29,10 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads public RawPayload(byte[] data) { - this.chunkType = data[0]; - this.data = data.Skip(1).ToArray(); + // this payload is 'special' in that we require the entire chunk to be passed in + // and not just the data after the header + this.chunkType = data[1]; + this.data = data.Skip(3).Take(data.Length-4).ToArray(); } public override string ToString() diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/TextPayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/TextPayload.cs index 8bb5eff1e..5b3fc9882 100644 --- a/Dalamud/Game/Chat/SeStringHandling/Payloads/TextPayload.cs +++ b/Dalamud/Game/Chat/SeStringHandling/Payloads/TextPayload.cs @@ -35,7 +35,14 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads protected override byte[] EncodeImpl() { - return Encoding.UTF8.GetBytes(Text); + // special case to allow for empty text payloads, so users don't have to check + // this may change or go away + if (string.IsNullOrEmpty(this.text)) + { + return new byte[] { }; + } + + return Encoding.UTF8.GetBytes(this.text); } protected override void DecodeImpl(BinaryReader reader, long endOfStream) diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/UIForegroundPayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/UIForegroundPayload.cs index 78150f08d..1f06d7dce 100644 --- a/Dalamud/Game/Chat/SeStringHandling/Payloads/UIForegroundPayload.cs +++ b/Dalamud/Game/Chat/SeStringHandling/Payloads/UIForegroundPayload.cs @@ -9,6 +9,8 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads { public override PayloadType Type => PayloadType.UIForeground; + public bool IsEnabled => ColorKey != 0; + private UIColor color; public UIColor UIColor { diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/UIGlowPayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/UIGlowPayload.cs index 19fd8365a..3c9664073 100644 --- a/Dalamud/Game/Chat/SeStringHandling/Payloads/UIGlowPayload.cs +++ b/Dalamud/Game/Chat/SeStringHandling/Payloads/UIGlowPayload.cs @@ -9,6 +9,8 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads { public override PayloadType Type => PayloadType.UIGlow; + public bool IsEnabled => ColorKey != 0; + private UIColor color; public UIColor UIColor { diff --git a/Dalamud/Game/Chat/SeStringHandling/SeString.cs b/Dalamud/Game/Chat/SeStringHandling/SeString.cs index 222d00ec1..01f01d593 100644 --- a/Dalamud/Game/Chat/SeStringHandling/SeString.cs +++ b/Dalamud/Game/Chat/SeStringHandling/SeString.cs @@ -12,15 +12,10 @@ namespace Dalamud.Game.Chat.SeStringHandling public class SeString { // TODO: probably change how this is done/where it comes from - public static Dalamud Dalamud { get; internal set; } + internal static Dalamud Dalamud { get; set; } public List Payloads { get; } - public SeString(List payloads) - { - Payloads = payloads; - } - /// /// Helper function to get all raw text from a message as a single joined string /// @@ -39,10 +34,10 @@ namespace Dalamud.Game.Chat.SeStringHandling } /// - /// Parse an array of bytes to a SeString. + /// Parse a binary game message into an SeString. /// - /// - /// + /// Binary message payload data in SE's internal format. + /// An SeString containing parsed Payload objects for each payload in the data. public static SeString Parse(byte[] bytes) { var payloads = new List(); @@ -61,12 +56,30 @@ namespace Dalamud.Game.Chat.SeStringHandling return new SeString(payloads); } - /// - /// Encode a parsed/created SeString to an array of bytes, to be used for injection. - /// - /// - /// The bytes of the message. - public byte[] Encode() + public SeString(List payloads) + { + Payloads = payloads; + } + + public SeString Append(SeString other) + { + Payloads.AddRange(other.Payloads); + return this; + } + + public SeString Append(List payloads) + { + Payloads.AddRange(payloads); + return this; + } + + public SeString Append(Payload payload) + { + Payloads.Add(payload); + return this; + } + + internal byte[] Encode() { var messageBytes = new List(); foreach (var p in Payloads) diff --git a/Dalamud/Game/Chat/SeStringHandling/SeStringUtils.cs b/Dalamud/Game/Chat/SeStringHandling/SeStringUtils.cs new file mode 100644 index 000000000..cf30a296b --- /dev/null +++ b/Dalamud/Game/Chat/SeStringHandling/SeStringUtils.cs @@ -0,0 +1,37 @@ +using Dalamud.Data.TransientSheet; +using Dalamud.Game.Chat.SeStringHandling.Payloads; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Dalamud.Game.Chat.SeStringHandling +{ + public class SeStringUtils + { + public static SeString CreateItemLink(uint itemId, bool isHQ, string displayNameOverride = null) + { + string displayName = displayNameOverride ?? SeString.Dalamud.Data.GetExcelSheet().GetRow((int)itemId).Name; + if (isHQ) + { + displayName += " \uE03C"; + } + + var payloads = new List(new Payload[] + { + new UIForegroundPayload(0x0225), + new UIGlowPayload(0x0226), + new ItemPayload(itemId, isHQ), + new UIForegroundPayload(0x01F4), + new UIGlowPayload(0x01F5), + new TextPayload("\uE0BB"), + new UIGlowPayload(0), + new UIForegroundPayload(0), + new TextPayload(displayName), + new RawPayload(new byte[] { 0x02, 0x27, 0x07, 0xCF, 0x01, 0x01, 0x01, 0xFF, 0x01, 0x03 }) + }); + + return new SeString(payloads); + } + } +}