diff --git a/Dalamud/Game/Chat/SeStringHandling/Payload.cs b/Dalamud/Game/Chat/SeStringHandling/Payload.cs index a69e68b3e..7b001b920 100644 --- a/Dalamud/Game/Chat/SeStringHandling/Payload.cs +++ b/Dalamud/Game/Chat/SeStringHandling/Payload.cs @@ -9,7 +9,6 @@ using Serilog; // TODOs: // - refactor integer handling now that we have multiple packed types // - common construction/property design for subclasses -// - lumina DI // - design for handling raw values vs resolved values, both for input and output // - wrapper class(es) for handling of composite links in chat (item, map etc) and formatting operations // - add italics payload @@ -23,13 +22,17 @@ namespace Dalamud.Game.Chat.SeStringHandling { public abstract PayloadType Type { get; } - public abstract byte[] Encode(); + public bool Dirty { get; protected set; } = true; - protected abstract void ProcessChunkImpl(BinaryReader reader, long endOfStream); + protected abstract byte[] EncodeImpl(); + + protected abstract void DecodeImpl(BinaryReader reader, long endOfStream); // :( protected DataManager dataResolver; + protected byte[] encodedData; + public Payload() { // this is not a good way to do this, but I don't want to have to include a dalamud @@ -40,22 +43,48 @@ namespace Dalamud.Game.Chat.SeStringHandling this.dataResolver = SeString.Dalamud.Data; } - public static Payload Process(BinaryReader reader) + public byte[] Encode(bool force = false) { + if (Dirty || force) + { + this.encodedData = EncodeImpl(); + Dirty = false; + } + + return this.encodedData; + } + + public static Payload Decode(BinaryReader reader) + { + var payloadStartPos = reader.BaseStream.Position; + Payload payload = null; if ((byte)reader.PeekChar() != START_BYTE) { - payload = ProcessText(reader); + payload = DecodeText(reader); } else { - payload = ProcessChunk(reader); + payload = DecodeChunk(reader); } + // for now, cache off the actual binary data for this payload, so we don't have to + // regenerate it if the payload isn't modified + // TODO: probably better ways to handle this + var payloadEndPos = reader.BaseStream.Position; + + reader.BaseStream.Position = payloadStartPos; + payload.encodedData = reader.ReadBytes((int)(payloadEndPos - payloadStartPos)); + payload.Dirty = false; + + // Log.Verbose($"got payload bytes {BitConverter.ToString(payload.encodedData).Replace("-", " ")}"); + + reader.BaseStream.Position = payloadEndPos; + return payload; } - private static Payload ProcessChunk(BinaryReader reader) + private static Payload DecodeChunk(BinaryReader reader) { Payload payload = null; @@ -121,7 +150,7 @@ namespace Dalamud.Game.Chat.SeStringHandling } payload ??= new RawPayload((byte)chunkType); - payload.ProcessChunkImpl(reader, reader.BaseStream.Position + chunkLen - 1); + payload.DecodeImpl(reader, reader.BaseStream.Position + chunkLen - 1); // read through the rest of the packet var readBytes = (uint)(reader.BaseStream.Position - packetStart); @@ -130,10 +159,10 @@ namespace Dalamud.Game.Chat.SeStringHandling return payload; } - private static Payload ProcessText(BinaryReader reader) + private static Payload DecodeText(BinaryReader reader) { var payload = new TextPayload(); - payload.ProcessChunkImpl(reader, reader.BaseStream.Length); + payload.DecodeImpl(reader, reader.BaseStream.Length); return payload; } diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/AutoTranslatePayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/AutoTranslatePayload.cs index 0a6cb8104..4e6fbfb3a 100644 --- a/Dalamud/Game/Chat/SeStringHandling/Payloads/AutoTranslatePayload.cs +++ b/Dalamud/Game/Chat/SeStringHandling/Payloads/AutoTranslatePayload.cs @@ -25,7 +25,12 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads private uint group; private uint key; - public override byte[] Encode() + public override string ToString() + { + return $"{Type} - Group: {group}, Key: {key}"; + } + + protected override byte[] EncodeImpl() { var keyBytes = MakeInteger(this.key); @@ -42,12 +47,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads return bytes.ToArray(); } - public override string ToString() - { - return $"{Type} - Group: {group}, Key: {key}"; - } - - protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream) + protected override void DecodeImpl(BinaryReader reader, long endOfStream) { // this seems to always be a bare byte, and not following normal integer encoding // the values in the table are all <70 so this is presumably ok diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/ItemPayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/ItemPayload.cs index 5f8133953..c1f95aae1 100644 --- a/Dalamud/Game/Chat/SeStringHandling/Payloads/ItemPayload.cs +++ b/Dalamud/Game/Chat/SeStringHandling/Payloads/ItemPayload.cs @@ -27,8 +27,12 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads // mainly to allow overriding the name (for things like owo) private string displayName; + public override string ToString() + { + return $"{Type} - ItemId: {itemId}, IsHQ: {IsHQ}"; + } - public override byte[] Encode() + protected override byte[] EncodeImpl() { var actualItemId = IsHQ ? this.itemId + 1000000 : this.itemId; var idBytes = MakeInteger(actualItemId); @@ -82,12 +86,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads return bytes.ToArray(); } - public override string ToString() - { - return $"{Type} - ItemId: {itemId}, IsHQ: {IsHQ}"; - } - - protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream) + protected override void DecodeImpl(BinaryReader reader, long endOfStream) { this.itemId = GetInteger(reader); diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/MapLinkPayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/MapLinkPayload.cs index 377dc9eef..beaa80e3a 100644 --- a/Dalamud/Game/Chat/SeStringHandling/Payloads/MapLinkPayload.cs +++ b/Dalamud/Game/Chat/SeStringHandling/Payloads/MapLinkPayload.cs @@ -74,7 +74,12 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads private uint rawY; // there is no Z; it's purely in the text payload where applicable - public override byte[] Encode() + public override string ToString() + { + return $"{Type} - TerritoryTypeId: {territoryTypeId}, MapId: {mapId}, RawX: {rawX}, RawY: {rawY}"; + } + + protected override byte[] EncodeImpl() { // TODO: for now we just encode the raw/internal values // eventually we should allow creation using 'nice' values that then encode properly @@ -101,12 +106,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads return bytes.ToArray(); } - public override string ToString() - { - return $"{Type} - TerritoryTypeId: {territoryTypeId}, MapId: {mapId}, RawX: {rawX}, RawY: {rawY}"; - } - - protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream) + protected override void DecodeImpl(BinaryReader reader, long endOfStream) { // for debugging for now var oldPos = reader.BaseStream.Position; diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/PlayerPayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/PlayerPayload.cs index 747ee8c75..a04d75d1c 100644 --- a/Dalamud/Game/Chat/SeStringHandling/Payloads/PlayerPayload.cs +++ b/Dalamud/Game/Chat/SeStringHandling/Payloads/PlayerPayload.cs @@ -24,7 +24,12 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads private uint serverId; - public override byte[] Encode() + public override string ToString() + { + return $"{Type} - PlayerName: {PlayerName}, ServerId: {serverId}"; + } + + protected override byte[] EncodeImpl() { var chunkLen = PlayerName.Length + 7; var bytes = new List() @@ -58,12 +63,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads return bytes.ToArray(); } - public override string ToString() - { - return $"{Type} - PlayerName: {PlayerName}, ServerId: {serverId}"; - } - - protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream) + protected override void DecodeImpl(BinaryReader reader, long endOfStream) { // unk reader.ReadByte(); diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/RawPayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/RawPayload.cs index ac4707af4..4d4788623 100644 --- a/Dalamud/Game/Chat/SeStringHandling/Payloads/RawPayload.cs +++ b/Dalamud/Game/Chat/SeStringHandling/Payloads/RawPayload.cs @@ -17,7 +17,12 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads this.chunkType = chunkType; } - public override byte[] Encode() + public override string ToString() + { + return $"{Type} - Chunk type: {chunkType:X}, Data: {BitConverter.ToString(Data).Replace("-", " ")}"; + } + + protected override byte[] EncodeImpl() { var chunkLen = Data.Length + 1; @@ -34,12 +39,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads return bytes.ToArray(); } - public override string ToString() - { - return $"{Type} - Chunk type: {chunkType:X}, Data: {BitConverter.ToString(Data).Replace("-", " ")}"; - } - - protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream) + protected override void DecodeImpl(BinaryReader reader, long endOfStream) { Data = reader.ReadBytes((int)(endOfStream - reader.BaseStream.Position + 1)); } diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/StatusPayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/StatusPayload.cs index 5dd3de457..0a08c5e5b 100644 --- a/Dalamud/Game/Chat/SeStringHandling/Payloads/StatusPayload.cs +++ b/Dalamud/Game/Chat/SeStringHandling/Payloads/StatusPayload.cs @@ -21,7 +21,12 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads private uint statusId; - public override byte[] Encode() + public override string ToString() + { + return $"{Type} - StatusId: {statusId}"; + } + + protected override byte[] EncodeImpl() { var idBytes = MakeInteger(this.statusId); @@ -38,12 +43,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads return bytes.ToArray(); } - public override string ToString() - { - return $"{Type} - StatusId: {statusId}"; - } - - protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream) + protected override void DecodeImpl(BinaryReader reader, long endOfStream) { this.statusId = GetInteger(reader); } diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/TextPayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/TextPayload.cs index bb189a6f8..8d81a2b5e 100644 --- a/Dalamud/Game/Chat/SeStringHandling/Payloads/TextPayload.cs +++ b/Dalamud/Game/Chat/SeStringHandling/Payloads/TextPayload.cs @@ -11,17 +11,17 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads public string Text { get; private set; } - public override byte[] Encode() - { - return Encoding.UTF8.GetBytes(Text); - } - public override string ToString() { return $"{Type} - Text: {Text}"; } - protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream) + protected override byte[] EncodeImpl() + { + return Encoding.UTF8.GetBytes(Text); + } + + protected override void DecodeImpl(BinaryReader reader, long endOfStream) { var text = new List(); diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/UIForegroundPayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/UIForegroundPayload.cs index 359c0694d..443c57507 100644 --- a/Dalamud/Game/Chat/SeStringHandling/Payloads/UIForegroundPayload.cs +++ b/Dalamud/Game/Chat/SeStringHandling/Payloads/UIForegroundPayload.cs @@ -29,7 +29,12 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads private ushort colorKey; - public override byte[] Encode() + public override string ToString() + { + return $"{Type} - UIColor: {colorKey}"; + } + + protected override byte[] EncodeImpl() { var colorBytes = MakeInteger(this.colorKey); var chunkLen = colorBytes.Length + 1; @@ -45,12 +50,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads return bytes.ToArray(); } - public override string ToString() - { - return $"{Type} - UIColor: {colorKey}"; - } - - protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream) + protected override void DecodeImpl(BinaryReader reader, long endOfStream) { this.colorKey = (ushort)GetInteger(reader); } diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/UIGlowPayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/UIGlowPayload.cs index 297bce2a4..b6332bc5a 100644 --- a/Dalamud/Game/Chat/SeStringHandling/Payloads/UIGlowPayload.cs +++ b/Dalamud/Game/Chat/SeStringHandling/Payloads/UIGlowPayload.cs @@ -29,7 +29,12 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads private ushort colorKey; - public override byte[] Encode() + public override string ToString() + { + return $"{Type} - UIColor: {colorKey}"; + } + + protected override byte[] EncodeImpl() { var colorBytes = MakeInteger(this.colorKey); var chunkLen = colorBytes.Length + 1; @@ -45,12 +50,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads return bytes.ToArray(); } - public override string ToString() - { - return $"{Type} - UIColor: {colorKey}"; - } - - protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream) + protected override void DecodeImpl(BinaryReader reader, long endOfStream) { this.colorKey = (ushort)GetInteger(reader); } diff --git a/Dalamud/Game/Chat/SeStringHandling/SeString.cs b/Dalamud/Game/Chat/SeStringHandling/SeString.cs index d98c5f0c0..248a0692f 100644 --- a/Dalamud/Game/Chat/SeStringHandling/SeString.cs +++ b/Dalamud/Game/Chat/SeStringHandling/SeString.cs @@ -62,7 +62,7 @@ namespace Dalamud.Game.Chat.SeStringHandling { while (stream.Position < bytes.Length) { - var payload = Payload.Process(reader); + var payload = Payload.Decode(reader); if (payload != null) payloads.Add(payload); }