using System.IO; using Lumina.Text.Payloads; using Lumina.Text.ReadOnly; using Newtonsoft.Json; namespace Dalamud.Game.Text.SeStringHandling.Payloads; /// /// This class represents a custom Dalamud clickable chat link. /// public class DalamudLinkPayload : Payload { /// public override PayloadType Type => PayloadType.DalamudLink; /// Gets the plugin command ID to be linked. public uint CommandId { get; internal set; } /// Gets an optional extra integer value 1. public int Extra1 { get; internal set; } /// Gets an optional extra integer value 2. public int Extra2 { get; internal set; } /// Gets the plugin name to be linked. public string Plugin { get; internal set; } = string.Empty; /// Gets an optional extra string. public string ExtraString { get; internal set; } = string.Empty; /// public override string ToString() => $"{this.Type} - {this.Plugin} ({this.CommandId}/{this.Extra1}/{this.Extra2}/{this.ExtraString})"; /// protected override byte[] EncodeImpl() { var ssb = Lumina.Text.SeStringBuilder.SharedPool.Get(); var res = ssb.BeginMacro(MacroCode.Link) .AppendIntExpression((int)EmbeddedInfoType.DalamudLink - 1) .AppendUIntExpression(this.CommandId) .AppendIntExpression(this.Extra1) .AppendIntExpression(this.Extra2) .BeginStringExpression() .Append(JsonConvert.SerializeObject(new[] { this.Plugin, this.ExtraString })) .EndExpression() .EndMacro() .ToArray(); Lumina.Text.SeStringBuilder.SharedPool.Return(ssb); return res; } /// protected override void DecodeImpl(BinaryReader reader, long endOfStream) { // Note: Payload.DecodeChunk already took the first int expr (DalamudLink). var body = reader.ReadBytes((int)(endOfStream - reader.BaseStream.Position)); var rosps = new ReadOnlySePayloadSpan(ReadOnlySePayloadType.Macro, MacroCode.Link, body.AsSpan()); if (!rosps.TryGetExpression( out var commandIdExpression, out var extra1Expression, out var extra2Expression, out var compositeExpression)) { if (!rosps.TryGetExpression(out var pluginExpression, out commandIdExpression)) return; if (!pluginExpression.TryGetString(out var pluginString)) return; if (!commandIdExpression.TryGetUInt(out var commandId)) return; this.Plugin = pluginString.ExtractText(); this.CommandId = commandId; } else { if (!commandIdExpression.TryGetUInt(out var commandId)) return; if (!extra1Expression.TryGetInt(out var extra1)) return; if (!extra2Expression.TryGetInt(out var extra2)) return; if (!compositeExpression.TryGetString(out var compositeString)) return; string[] extraData; try { extraData = JsonConvert.DeserializeObject(compositeString.ExtractText()); } catch { return; } this.CommandId = commandId; this.Extra1 = extra1; this.Extra2 = extra2; this.Plugin = extraData[0]; this.ExtraString = extraData[1]; } } }