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: case EmbeddedInfoType.Status:
payload = new StatusPayload(); payload = new StatusPayload();
break; break;
case EmbeddedInfoType.LinkTerminator: case EmbeddedInfoType.LinkTerminator:
// Does not need to be handled // this has no custom handling and so needs to fallthrough to ensure it is captured
break;
default: default:
Log.Verbose("Unhandled EmbeddedInfoType: {0}", subType); 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;
} }
} }
break; break;
default: default:
Log.Verbose("Unhandled SeStringChunkType: {0}", chunkType); Log.Verbose("Unhandled SeStringChunkType: {0}", chunkType);
payload = new RawPayload((byte)chunkType);
break; break;
} }

View file

@ -26,6 +26,10 @@ namespace Dalamud.Game.Chat.SeStringHandling
/// <summary> /// <summary>
/// An SeString payload representing raw, typed text. /// An SeString payload representing raw, typed text.
/// </summary> /// </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 actualItemId = IsHQ ? ItemId + 1000000 : ItemId;
var idBytes = MakeInteger(actualItemId); var idBytes = MakeInteger(actualItemId);
bool hasName = !string.IsNullOrEmpty(ItemName);
var itemIdFlag = IsHQ ? IntegerType.Int16Plus1Million : IntegerType.Int16; var itemIdFlag = IsHQ ? IntegerType.Int16Plus1Million : IntegerType.Int16;
var chunkLen = idBytes.Length + 5; 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>() var bytes = new List<byte>()
{ {
START_BYTE, START_BYTE,
@ -48,7 +59,32 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
}; };
bytes.AddRange(idBytes); bytes.AddRange(idBytes);
// unk // 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(); return bytes.ToArray();
} }
@ -74,7 +110,16 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
reader.ReadBytes(3); reader.ReadBytes(3);
var itemNameLen = GetInteger(reader); 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));
}
}
}