Merge pull request #32 from ff-meli/master

Update SeString Payload handling to make explicit payloads for all ch…
This commit is contained in:
goaaats 2020-02-14 10:07:29 +09:00 committed by GitHub
commit b7c9f23d4f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 109 additions and 5 deletions

View file

@ -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;
}

View file

@ -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
}
}

View file

@ -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);
}
}
}

View 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));
}
}
}