mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 18:27:23 +01:00
Update SeString Payload handling to make explicit payloads for all chunk types, including unknown ones. Also update ItemPayload to properly handle encoding the item name if present. These changes allow an incoming string to be parsed into payloads, and then fully reconstructed into a valid string, with or without changes.
This commit is contained in:
parent
3980929f71
commit
3d67aecc17
4 changed files with 109 additions and 5 deletions
|
|
@ -62,17 +62,21 @@ namespace Dalamud.Game.Chat.SeStringHandling
|
|||
case EmbeddedInfoType.Status:
|
||||
payload = new StatusPayload();
|
||||
break;
|
||||
|
||||
case EmbeddedInfoType.LinkTerminator:
|
||||
// Does not need to be handled
|
||||
break;
|
||||
// this has no custom handling and so needs to fallthrough to ensure it is captured
|
||||
default:
|
||||
Log.Verbose("Unhandled EmbeddedInfoType: {0}", subType);
|
||||
// rewind so we capture the Interactable byte in the raw data
|
||||
reader.BaseStream.Seek(-1, SeekOrigin.Current);
|
||||
payload = new RawPayload((byte)chunkType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Log.Verbose("Unhandled SeStringChunkType: {0}", chunkType);
|
||||
payload = new RawPayload((byte)chunkType);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,10 @@ namespace Dalamud.Game.Chat.SeStringHandling
|
|||
/// <summary>
|
||||
/// An SeString payload representing raw, typed text.
|
||||
/// </summary>
|
||||
RawText
|
||||
RawText,
|
||||
/// <summary>
|
||||
/// An SeString payload representing any data we don't handle.
|
||||
/// </summary>
|
||||
Unknown
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,10 +36,21 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
|||
{
|
||||
var actualItemId = IsHQ ? ItemId + 1000000 : ItemId;
|
||||
var idBytes = MakeInteger(actualItemId);
|
||||
bool hasName = !string.IsNullOrEmpty(ItemName);
|
||||
|
||||
var itemIdFlag = IsHQ ? IntegerType.Int16Plus1Million : IntegerType.Int16;
|
||||
|
||||
var chunkLen = idBytes.Length + 5;
|
||||
if (hasName)
|
||||
{
|
||||
// 1 additional unknown byte compared to the nameless version, 1 byte for the name length, and then the name itself
|
||||
chunkLen += (1 + 1 + ItemName.Length);
|
||||
if (IsHQ)
|
||||
{
|
||||
chunkLen += 4; // unicode representation of the HQ symbol is 3 bytes, preceded by a space
|
||||
}
|
||||
}
|
||||
|
||||
var bytes = new List<byte>()
|
||||
{
|
||||
START_BYTE,
|
||||
|
|
@ -48,7 +59,32 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
|||
};
|
||||
bytes.AddRange(idBytes);
|
||||
// unk
|
||||
bytes.AddRange(new byte[] { 0x02, 0x01, END_BYTE });
|
||||
bytes.AddRange(new byte[] { 0x02, 0x01 });
|
||||
|
||||
// Links don't have to include the name, but if they do, it requires additional work
|
||||
if (hasName)
|
||||
{
|
||||
var nameLen = ItemName.Length + 1;
|
||||
if (IsHQ)
|
||||
{
|
||||
nameLen += 4; // space plus 3 bytes for HQ symbol
|
||||
}
|
||||
|
||||
bytes.AddRange(new byte[]
|
||||
{
|
||||
0xFF, // unk
|
||||
(byte)nameLen
|
||||
});
|
||||
bytes.AddRange(Encoding.UTF8.GetBytes(ItemName));
|
||||
|
||||
if (IsHQ)
|
||||
{
|
||||
// space and HQ symbol
|
||||
bytes.AddRange(new byte[] { 0x20, 0xEE, 0x80, 0xBC });
|
||||
}
|
||||
}
|
||||
|
||||
bytes.Add(END_BYTE);
|
||||
|
||||
return bytes.ToArray();
|
||||
}
|
||||
|
|
@ -74,7 +110,16 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
|||
reader.ReadBytes(3);
|
||||
|
||||
var itemNameLen = GetInteger(reader);
|
||||
ItemName = Encoding.UTF8.GetString(reader.ReadBytes(itemNameLen));
|
||||
var itemNameBytes = reader.ReadBytes(itemNameLen);
|
||||
|
||||
// HQ items have the HQ symbol as part of the name, but since we already recorded
|
||||
// the HQ flag, we want just the bare name
|
||||
if (IsHQ)
|
||||
{
|
||||
itemNameBytes = itemNameBytes.Take(itemNameLen - 4).ToArray();
|
||||
}
|
||||
|
||||
ItemName = Encoding.UTF8.GetString(itemNameBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
51
Dalamud/Game/Chat/SeStringHandling/Payloads/RawPayload.cs
Normal file
51
Dalamud/Game/Chat/SeStringHandling/Payloads/RawPayload.cs
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||
{
|
||||
public class RawPayload : Payload
|
||||
{
|
||||
public override PayloadType Type => PayloadType.Unknown;
|
||||
|
||||
public byte ChunkType { get; private set; }
|
||||
public byte[] Data { get; private set; }
|
||||
|
||||
public RawPayload(byte chunkType)
|
||||
{
|
||||
ChunkType = chunkType;
|
||||
}
|
||||
|
||||
public override void Resolve()
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
public override byte[] Encode()
|
||||
{
|
||||
var chunkLen = Data.Length + 1;
|
||||
|
||||
var bytes = new List<byte>()
|
||||
{
|
||||
START_BYTE,
|
||||
ChunkType,
|
||||
(byte)chunkLen
|
||||
};
|
||||
bytes.AddRange(Data);
|
||||
|
||||
bytes.Add(END_BYTE);
|
||||
|
||||
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)
|
||||
{
|
||||
Data = reader.ReadBytes((int)(endOfStream - reader.BaseStream.Position + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue