mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 18:27:23 +01:00
Add UIGlow and UIForeground SeString payloads; refactor some handling of integer markers in payloads, to make encoding a bit simpler
This commit is contained in:
parent
1e00a33577
commit
4c12b1dfb0
6 changed files with 186 additions and 32 deletions
|
|
@ -2,8 +2,6 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Dalamud.Game.Chat.SeStringHandling.Payloads;
|
||||
using Serilog;
|
||||
|
||||
|
|
@ -74,6 +72,15 @@ namespace Dalamud.Game.Chat.SeStringHandling
|
|||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SeStringChunkType.UIForeground:
|
||||
payload = new UIForegroundPayload();
|
||||
break;
|
||||
|
||||
case SeStringChunkType.UIGlow:
|
||||
payload = new UIGlowPayload();
|
||||
break;
|
||||
|
||||
default:
|
||||
Log.Verbose("Unhandled SeStringChunkType: {0}", chunkType);
|
||||
payload = new RawPayload((byte)chunkType);
|
||||
|
|
@ -104,7 +111,9 @@ namespace Dalamud.Game.Chat.SeStringHandling
|
|||
|
||||
protected enum SeStringChunkType
|
||||
{
|
||||
Interactable = 0x27
|
||||
Interactable = 0x27,
|
||||
UIForeground = 0x48,
|
||||
UIGlow = 0x49
|
||||
}
|
||||
|
||||
protected enum EmbeddedInfoType
|
||||
|
|
@ -118,6 +127,9 @@ namespace Dalamud.Game.Chat.SeStringHandling
|
|||
|
||||
protected enum IntegerType
|
||||
{
|
||||
// Custom value indicating no marker at all
|
||||
None = 0x0,
|
||||
|
||||
Byte = 0xF0,
|
||||
ByteTimes256 = 0xF1,
|
||||
Int16 = 0xF2,
|
||||
|
|
@ -188,37 +200,49 @@ namespace Dalamud.Game.Chat.SeStringHandling
|
|||
}
|
||||
}
|
||||
|
||||
protected static byte[] MakeInteger(int value)
|
||||
protected virtual byte[] MakeInteger(int value)
|
||||
{
|
||||
// clearly the epitome of efficiency
|
||||
// single-byte values below the marker values have no marker and have 1 added
|
||||
if (value + 1 < (int)IntegerType.Byte)
|
||||
{
|
||||
value++;
|
||||
return new byte[] { (byte)value };
|
||||
}
|
||||
|
||||
var bytesPadded = BitConverter.GetBytes(value);
|
||||
Array.Reverse(bytesPadded);
|
||||
return bytesPadded.SkipWhile(b => b == 0x00).ToArray();
|
||||
var shrunkValue = bytesPadded.SkipWhile(b => b == 0x00).ToArray();
|
||||
|
||||
var encodedNum = new List<byte>();
|
||||
|
||||
var marker = GetMarkerForIntegerBytes(shrunkValue);
|
||||
if (marker != 0)
|
||||
{
|
||||
encodedNum.Add(marker);
|
||||
}
|
||||
|
||||
encodedNum.AddRange(shrunkValue);
|
||||
|
||||
return encodedNum.ToArray();
|
||||
}
|
||||
|
||||
protected static IntegerType GetTypeForIntegerBytes(byte[] bytes)
|
||||
// This is only accurate in a very general sense
|
||||
// Different payloads seem to use different default values for things
|
||||
// So this should be overridden where necessary
|
||||
protected virtual byte GetMarkerForIntegerBytes(byte[] bytes)
|
||||
{
|
||||
// not the most scientific, exists mainly for laziness
|
||||
|
||||
if (bytes.Length == 1)
|
||||
var marker = bytes.Length switch
|
||||
{
|
||||
return IntegerType.Byte;
|
||||
}
|
||||
else if (bytes.Length == 2)
|
||||
{
|
||||
return IntegerType.Int16;
|
||||
}
|
||||
else if (bytes.Length == 3)
|
||||
{
|
||||
return IntegerType.Int24;
|
||||
}
|
||||
else if (bytes.Length == 4)
|
||||
{
|
||||
return IntegerType.Int32;
|
||||
}
|
||||
1 => IntegerType.Byte,
|
||||
2 => IntegerType.Int16,
|
||||
3 => IntegerType.Int24,
|
||||
4 => IntegerType.Int32,
|
||||
_ => throw new NotSupportedException()
|
||||
};
|
||||
|
||||
throw new NotSupportedException();
|
||||
return (byte)marker;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,14 @@ namespace Dalamud.Game.Chat.SeStringHandling
|
|||
/// </summary>
|
||||
RawText,
|
||||
/// <summary>
|
||||
/// An SeString payload representing a text foreground color.
|
||||
/// </summary>
|
||||
UIForeground,
|
||||
/// <summary>
|
||||
/// An SeString payload representing a text glow color.
|
||||
/// </summary>
|
||||
UIGlow,
|
||||
/// <summary>
|
||||
/// An SeString payload representing any data we don't handle.
|
||||
/// </summary>
|
||||
Unknown
|
||||
|
|
|
|||
|
|
@ -38,9 +38,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
|||
var idBytes = MakeInteger(actualItemId);
|
||||
bool hasName = !string.IsNullOrEmpty(ItemName);
|
||||
|
||||
var itemIdFlag = IsHQ ? IntegerType.Int16Plus1Million : IntegerType.Int16;
|
||||
|
||||
var chunkLen = idBytes.Length + 5;
|
||||
var chunkLen = idBytes.Length + 4;
|
||||
if (hasName)
|
||||
{
|
||||
// 1 additional unknown byte compared to the nameless version, 1 byte for the name length, and then the name itself
|
||||
|
|
@ -54,8 +52,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
|||
var bytes = new List<byte>()
|
||||
{
|
||||
START_BYTE,
|
||||
(byte)SeStringChunkType.Interactable, (byte)chunkLen, (byte)EmbeddedInfoType.ItemLink,
|
||||
(byte)itemIdFlag
|
||||
(byte)SeStringChunkType.Interactable, (byte)chunkLen, (byte)EmbeddedInfoType.ItemLink
|
||||
};
|
||||
bytes.AddRange(idBytes);
|
||||
// unk
|
||||
|
|
@ -122,5 +119,16 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
|||
ItemName = Encoding.UTF8.GetString(itemNameBytes);
|
||||
}
|
||||
}
|
||||
|
||||
protected override byte GetMarkerForIntegerBytes(byte[] bytes)
|
||||
{
|
||||
// custom marker just for hq items?
|
||||
if (bytes.Length == 3 && IsHQ)
|
||||
{
|
||||
return (byte)IntegerType.Int16Plus1Million;
|
||||
}
|
||||
|
||||
return base.GetMarkerForIntegerBytes(bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,13 +35,11 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
|||
public override byte[] Encode()
|
||||
{
|
||||
var idBytes = MakeInteger(StatusId);
|
||||
var idPrefix = GetTypeForIntegerBytes(idBytes);
|
||||
|
||||
var chunkLen = idBytes.Length + 8;
|
||||
var chunkLen = idBytes.Length + 7;
|
||||
var bytes = new List<byte>()
|
||||
{
|
||||
START_BYTE, (byte)SeStringChunkType.Interactable, (byte)chunkLen, (byte)EmbeddedInfoType.Status,
|
||||
(byte)idPrefix
|
||||
START_BYTE, (byte)SeStringChunkType.Interactable, (byte)chunkLen, (byte)EmbeddedInfoType.Status
|
||||
};
|
||||
|
||||
bytes.AddRange(idBytes);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||
{
|
||||
public class UIForegroundPayload : Payload
|
||||
{
|
||||
public override PayloadType Type => PayloadType.UIForeground;
|
||||
|
||||
public ushort RawColor { get; private set; }
|
||||
|
||||
//public int Red { get; private set; }
|
||||
//public int Green { get; private set; }
|
||||
//public int Blue { get; private set; }
|
||||
|
||||
public override byte[] Encode()
|
||||
{
|
||||
var colorBytes = MakeInteger(RawColor);
|
||||
var chunkLen = colorBytes.Length + 1;
|
||||
|
||||
var bytes = new List<byte>(new byte[]
|
||||
{
|
||||
START_BYTE, (byte)SeStringChunkType.UIForeground, (byte)chunkLen
|
||||
});
|
||||
|
||||
bytes.AddRange(colorBytes);
|
||||
bytes.Add(END_BYTE);
|
||||
|
||||
return bytes.ToArray();
|
||||
}
|
||||
|
||||
public override void Resolve()
|
||||
{
|
||||
// TODO: resolve color keys to hex colors via UIColor table
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Type} - RawColor: {RawColor}";
|
||||
}
|
||||
|
||||
protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream)
|
||||
{
|
||||
RawColor = (ushort)GetInteger(reader);
|
||||
}
|
||||
|
||||
protected override byte GetMarkerForIntegerBytes(byte[] bytes)
|
||||
{
|
||||
return bytes.Length switch
|
||||
{
|
||||
// a single byte of 0x01 is used to 'disable' color, and has no marker
|
||||
1 => (byte)IntegerType.None,
|
||||
_ => base.GetMarkerForIntegerBytes(bytes)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
58
Dalamud/Game/Chat/SeStringHandling/Payloads/UIGlowPayload.cs
Normal file
58
Dalamud/Game/Chat/SeStringHandling/Payloads/UIGlowPayload.cs
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||
{
|
||||
public class UIGlowPayload : Payload
|
||||
{
|
||||
public override PayloadType Type => PayloadType.UIGlow;
|
||||
|
||||
public ushort RawColor { get; private set; }
|
||||
|
||||
//public int Red { get; private set; }
|
||||
//public int Green { get; private set; }
|
||||
//public int Blue { get; private set; }
|
||||
|
||||
public override byte[] Encode()
|
||||
{
|
||||
var colorBytes = MakeInteger(RawColor);
|
||||
var chunkLen = colorBytes.Length + 1;
|
||||
|
||||
var bytes = new List<byte>(new byte[]
|
||||
{
|
||||
START_BYTE, (byte)SeStringChunkType.UIGlow, (byte)chunkLen
|
||||
});
|
||||
|
||||
bytes.AddRange(colorBytes);
|
||||
bytes.Add(END_BYTE);
|
||||
|
||||
return bytes.ToArray();
|
||||
}
|
||||
|
||||
public override void Resolve()
|
||||
{
|
||||
// TODO: resolve color keys to hex colors via UIColor table
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Type} - RawColor: {RawColor}";
|
||||
}
|
||||
|
||||
protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream)
|
||||
{
|
||||
RawColor = (ushort)GetInteger(reader);
|
||||
}
|
||||
|
||||
protected override byte GetMarkerForIntegerBytes(byte[] bytes)
|
||||
{
|
||||
return bytes.Length switch
|
||||
{
|
||||
// a single byte of 0x01 is used to 'disable' color, and has no marker
|
||||
1 => (byte)IntegerType.None,
|
||||
_ => base.GetMarkerForIntegerBytes(bytes)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue