diff --git a/Dalamud/Game/Chat/SeStringHandling/Payload.cs b/Dalamud/Game/Chat/SeStringHandling/Payload.cs
index 2320a8dfb..07baef08e 100644
--- a/Dalamud/Game/Chat/SeStringHandling/Payload.cs
+++ b/Dalamud/Game/Chat/SeStringHandling/Payload.cs
@@ -8,7 +8,6 @@ using Serilog;
// TODOs:
// - refactor integer handling now that we have multiple packed types
-// - wrapper class(es) for handling of composite links in chat (item, map etc) and formatting operations
// Maybes:
// - convert parsing to custom structs for each payload? would make some code prettier and easier to work with
// but also wouldn't work out as well for things that are dynamically-sized
@@ -22,18 +21,41 @@ namespace Dalamud.Game.Chat.SeStringHandling
///
public abstract class Payload
{
+ ///
+ /// The type of this payload.
+ ///
public abstract PayloadType Type { get; }
+ ///
+ /// Whether this payload has been modified since the last Encode().
+ ///
public bool Dirty { get; protected set; } = true;
+ ///
+ /// Encodes the internal state of this payload into a byte[] suitable for sending to in-game
+ /// handlers such as the chat log.
+ ///
+ /// Encoded binary payload data suitable for use with in-game handlers.
protected abstract byte[] EncodeImpl();
+ // TODO: endOfStream is somewhat legacy now that payload length is always handled correctly.
+ // This could be changed to just take a straight byte[], but that would complicate reading
+ // but we could probably at least remove the end param
+ ///
+ /// Decodes a byte stream from the game into a payload object.
+ ///
+ /// A BinaryReader containing at least all the data for this payload.
+ /// The location holding the end of the data for this payload.
protected abstract void DecodeImpl(BinaryReader reader, long endOfStream);
- // :(
+ ///
+ /// The Lumina instance to use for any necessary data lookups.
+ ///
protected DataManager dataResolver;
- protected byte[] encodedData;
+ // private for now, since subclasses shouldn't interact with this
+ // To force-invalidate it, Dirty can be set to true
+ private byte[] encodedData;
protected Payload()
{
@@ -45,6 +67,11 @@ namespace Dalamud.Game.Chat.SeStringHandling
this.dataResolver = SeString.Dalamud.Data;
}
+ ///
+ /// Encode this payload object into a byte[] useable in-game for things like the chat log.
+ ///
+ /// If true, ignores any cached value and forcibly reencodes the payload from its internal representation.
+ /// A byte[] suitable for use with in-game handlers such as the chat log.
public byte[] Encode(bool force = false)
{
if (Dirty || force)
@@ -56,6 +83,11 @@ namespace Dalamud.Game.Chat.SeStringHandling
return this.encodedData;
}
+ ///
+ /// Decodes a binary representation of a payload into its corresponding nice object payload.
+ ///
+ /// A reader positioned at the start of the payload, and containing at least one entire payload.
+ /// The constructed Payload-derived object that was decoded from the binary data.
public static Payload Decode(BinaryReader reader)
{
var payloadStartPos = reader.BaseStream.Position;
@@ -96,6 +128,7 @@ namespace Dalamud.Game.Chat.SeStringHandling
var packetStart = reader.BaseStream.Position;
+ // any unhandled payload types will be turned into a RawPayload with the exact same binary data
switch (chunkType)
{
case SeStringChunkType.EmphasisItalic:
@@ -197,6 +230,10 @@ namespace Dalamud.Game.Chat.SeStringHandling
LinkTerminator = 0xCF // not clear but seems to always follow a link
}
+
+ // TODO - everything below needs to be completely refactored, now that we have run into
+ // a lot more cases than were originally handled.
+
protected enum IntegerType
{
// used as an internal marker; sometimes single bytes are bare with no marker at all
@@ -205,7 +242,6 @@ namespace Dalamud.Game.Chat.SeStringHandling
Byte = 0xF0,
ByteTimes256 = 0xF1,
Int16 = 0xF2,
- // ByteTimes65536 = 0xF3, // from RE but never seen
Int16Packed = 0xF4, // seen in map links, seemingly 2 8-bit values packed into 2 bytes with only one marker
Int24Special = 0xF6, // unsure how different form Int24 - used for hq items that add 1 million, also used for normal 24-bit values in map links
Int24 = 0xFA,
diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/AutoTranslatePayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/AutoTranslatePayload.cs
index 31f2a9243..3c022d8ec 100644
--- a/Dalamud/Game/Chat/SeStringHandling/Payloads/AutoTranslatePayload.cs
+++ b/Dalamud/Game/Chat/SeStringHandling/Payloads/AutoTranslatePayload.cs
@@ -8,11 +8,20 @@ using System.Linq;
namespace Dalamud.Game.Chat.SeStringHandling.Payloads
{
+ ///
+ /// An SeString Payload containing an auto-translation/completion chat message.
+ ///
public class AutoTranslatePayload : Payload, ITextProvider
{
public override PayloadType Type => PayloadType.AutoTranslateText;
private string text;
+ ///
+ /// The actual text displayed in-game for this payload.
+ ///
+ ///
+ /// Value is evaluated lazily and cached.
+ ///
public string Text
{
get
@@ -29,6 +38,15 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
internal AutoTranslatePayload() { }
+ ///
+ /// Creates a new auto-translate payload.
+ ///
+ /// The group id for this message.
+ /// The key/row id for this message. Which table this is in depends on the group id and details the Completion table.
+ ///
+ /// This table is somewhat complicated in structure, and so using this constructor may not be very nice.
+ /// There is probably little use to create one of these, however.
+ ///
public AutoTranslatePayload(uint group, uint key)
{
this.group = group;
@@ -39,7 +57,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
public override string ToString()
{
- return $"{Type} - Group: {group}, Key: {key}";
+ return $"{Type} - Group: {group}, Key: {key}, Text: {Text}";
}
protected override byte[] EncodeImpl()
diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/EmphasisItalicPayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/EmphasisItalicPayload.cs
index 19909f516..341439edb 100644
--- a/Dalamud/Game/Chat/SeStringHandling/Payloads/EmphasisItalicPayload.cs
+++ b/Dalamud/Game/Chat/SeStringHandling/Payloads/EmphasisItalicPayload.cs
@@ -4,17 +4,37 @@ using System.IO;
namespace Dalamud.Game.Chat.SeStringHandling.Payloads
{
- class EmphasisItalicPayload : Payload
+ ///
+ /// An SeString Payload containing information about enabling or disabling italics formatting on following text.
+ ///
+ ///
+ /// As with other formatting payloads, this is only useful in a payload block, where it affects any subsequent
+ /// text payloads.
+ ///
+ public class EmphasisItalicPayload : Payload
{
+ ///
+ /// Payload representing enabling italics on following text.
+ ///
public static EmphasisItalicPayload ItalicsOn => new EmphasisItalicPayload(true);
+ ///
+ /// Payload representing disabling italics on following text.
+ ///
public static EmphasisItalicPayload ItalicsOff => new EmphasisItalicPayload(false);
public override PayloadType Type => PayloadType.EmphasisItalic;
+ ///
+ /// Whether this payload enables italics formatting for following text.
+ ///
public bool IsEnabled { get; private set; }
internal EmphasisItalicPayload() { }
+ ///
+ /// Creates an EmphasisItalicPayload.
+ ///
+ /// Whether italics formatting should be enabled or disabled for following text.
public EmphasisItalicPayload(bool enabled)
{
IsEnabled = enabled;
diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/ItemPayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/ItemPayload.cs
index da09fc5d0..87b3ab87d 100644
--- a/Dalamud/Game/Chat/SeStringHandling/Payloads/ItemPayload.cs
+++ b/Dalamud/Game/Chat/SeStringHandling/Payloads/ItemPayload.cs
@@ -7,11 +7,20 @@ using System.Text;
namespace Dalamud.Game.Chat.SeStringHandling.Payloads
{
+ ///
+ /// An SeString Payload representing an interactable item link.
+ ///
public class ItemPayload : Payload
{
public override PayloadType Type => PayloadType.Item;
private Item item;
+ ///
+ /// The underlying Lumina Item represented by this payload.
+ ///
+ ///
+ /// Value is evaluated lazily and cached.
+ ///
public Item Item
{
get
@@ -22,7 +31,14 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
}
// mainly to allow overriding the name (for things like owo)
- private string displayName;
+ // TODO: even though this is present in some item links, it may not really have a use at all
+ // For things like owo, changing the text payload is probably correct, whereas changing the
+ // actual embedded name might not work properly.
+ private string displayName = null;
+ ///
+ /// The displayed name for this item link. Note that incoming links only sometimes have names embedded,
+ /// often the name is only present in a following text payload.
+ ///
public string DisplayName
{
get
@@ -37,12 +53,23 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
}
}
+ ///
+ /// Whether or not this item link is for a high-quality version of the item.
+ ///
public bool IsHQ { get; private set; } = false;
private uint itemId;
internal ItemPayload() { }
+ ///
+ /// Creates a payload representing an interactable item link for the specified item.
+ ///
+ /// The id of the item.
+ /// Whether or not the link should be for the high-quality variant of the item.
+ /// An optional name to include in the item link. Typically this should
+ /// be left as null, or set to the normal item name. Actual overrides are better done with the subsequent
+ /// TextPayload that is a part of a full item link in chat.
public ItemPayload(uint itemId, bool isHQ, string displayNameOverride = null)
{
this.itemId = itemId;
@@ -52,7 +79,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
public override string ToString()
{
- return $"{Type} - ItemId: {itemId}, IsHQ: {IsHQ}";
+ return $"{Type} - ItemId: {itemId}, IsHQ: {IsHQ}, Name: {this.displayName ?? Item.Name}";
}
protected override byte[] EncodeImpl()
diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/MapLinkPayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/MapLinkPayload.cs
index 30d11e5fe..e73eb8393 100644
--- a/Dalamud/Game/Chat/SeStringHandling/Payloads/MapLinkPayload.cs
+++ b/Dalamud/Game/Chat/SeStringHandling/Payloads/MapLinkPayload.cs
@@ -5,11 +5,20 @@ using System.IO;
namespace Dalamud.Game.Chat.SeStringHandling.Payloads
{
+ ///
+ /// An SeString Payload representing an interactable map position link.
+ ///
public class MapLinkPayload : Payload
{
public override PayloadType Type => PayloadType.MapLink;
private Map map;
+ ///
+ /// The Map specified for this map link.
+ ///
+ ///
+ /// Value is evaluated lazily and cached.
+ ///
public Map Map
{
get
@@ -20,6 +29,12 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
}
private TerritoryType territoryType;
+ ///
+ /// The TerritoryType specified for this map link.
+ ///
+ ///
+ /// Value is evaluated lazily and cached.
+ ///
public TerritoryType TerritoryType
{
get
@@ -29,23 +44,43 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
}
}
+ ///
+ /// The internal x-coordinate for this map position.
+ ///
+ public int RawX { get; private set; }
+
+ ///
+ /// The internal y-coordinate for this map position.
+ ///
+ public int RawY { get; private set; }
+
// these could be cached, but this isn't really too egregious
+ ///
+ /// The readable x-coordinate position for this map link. This value is approximate and unrounded.
+ ///
public float XCoord
{
get
{
- return ConvertRawPositionToMapCoordinate(this.rawX, Map.SizeFactor);
+ return ConvertRawPositionToMapCoordinate(RawX, Map.SizeFactor);
}
}
+ ///
+ /// The readable y-coordinate position for this map link. This value is approximate and unrounded.
+ ///
public float YCoord
{
get
{
- return ConvertRawPositionToMapCoordinate(this.rawY, Map.SizeFactor);
+ return ConvertRawPositionToMapCoordinate(RawY, Map.SizeFactor);
}
}
+ ///
+ /// The printable map coordinates for this link. This value tries to match the in-game printable text as closely as possible
+ /// but is an approximation and may be slightly off for some positions.
+ ///
public string CoordinateString
{
get
@@ -57,11 +92,15 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
var x = Math.Truncate((XCoord+fudge) * 10.0f) / 10.0f;
var y = Math.Truncate((YCoord+fudge) * 10.0f) / 10.0f;
+ // the formatting and spacing the game uses
return $"( {x.ToString("0.0")} , {y.ToString("0.0")} )";
}
}
private string placeNameRegion;
+ ///
+ /// The region name for this map link. This corresponds to the upper zone name found in the actual in-game map UI. eg, "La Noscea"
+ ///
public string PlaceNameRegion
{
get
@@ -72,6 +111,9 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
}
private string placeName;
+ ///
+ /// The place name for this map link. This corresponds to the lower zone name found in the actual in-game map UI. eg, "Limsa Lominsa Upper Decks"
+ ///
public string PlaceName
{
get
@@ -81,16 +123,25 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
}
}
- public string DataString => $"m:{TerritoryType.RowId},{Map.RowId},{rawX},{rawY}";
+ ///
+ /// The data string for this map link, for use by internal game functions that take a string variant and not a binary payload.
+ ///
+ public string DataString => $"m:{TerritoryType.RowId},{Map.RowId},{RawX},{RawY}";
private uint territoryTypeId;
private uint mapId;
- private int rawX;
- private int rawY;
// there is no Z; it's purely in the text payload where applicable
internal MapLinkPayload() { }
+ ///
+ /// Creates an interactable MapLinkPayload from a human-readable position.
+ ///
+ /// The id of the TerritoryType entry for this link.
+ /// The id of the Map entry for this link.
+ /// The human-readable x-coordinate for this link.
+ /// The human-readable y-coordinate for this link.
+ /// An optional offset to account for rounding and truncation errors; it is best to leave this untouched in most cases.
public MapLinkPayload(uint territoryTypeId, uint mapId, float niceXCoord, float niceYCoord, float fudgeFactor = 0.05f)
{
this.territoryTypeId = territoryTypeId;
@@ -98,28 +149,35 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
// this fudge is necessary basically to ensure we don't shift down a full tenth
// because essentially values are truncated instead of rounded, so 3.09999f will become
// 3.0f and not 3.1f
- this.rawX = this.ConvertMapCoordinateToRawPosition(niceXCoord + fudgeFactor, Map.SizeFactor);
- this.rawY = this.ConvertMapCoordinateToRawPosition(niceYCoord + fudgeFactor, Map.SizeFactor);
+ RawX = this.ConvertMapCoordinateToRawPosition(niceXCoord + fudgeFactor, Map.SizeFactor);
+ RawY = this.ConvertMapCoordinateToRawPosition(niceYCoord + fudgeFactor, Map.SizeFactor);
}
+ ///
+ /// Creates an interactable MapLinkPayload from a raw position.
+ ///
+ /// The id of the TerritoryType entry for this link.
+ /// The id of the Map entry for this link.
+ /// The internal raw x-coordinate for this link.
+ /// The internal raw y-coordinate for this link.
public MapLinkPayload(uint territoryTypeId, uint mapId, int rawX, int rawY)
{
this.territoryTypeId = territoryTypeId;
this.mapId = mapId;
- this.rawX = rawX;
- this.rawY = rawY;
+ RawX = rawX;
+ RawY = rawY;
}
public override string ToString()
{
- return $"{Type} - TerritoryTypeId: {territoryTypeId}, MapId: {mapId}, RawX: {rawX}, RawY: {rawY}";
+ return $"{Type} - TerritoryTypeId: {territoryTypeId}, MapId: {mapId}, RawX: {RawX}, RawY: {RawY}, display: {PlaceName} {CoordinateString}";
}
protected override byte[] EncodeImpl()
{
var packedTerritoryAndMapBytes = MakePackedInteger(this.territoryTypeId, this.mapId);
- var xBytes = MakeInteger(unchecked((uint)this.rawX));
- var yBytes = MakeInteger(unchecked((uint)this.rawY));
+ var xBytes = MakeInteger(unchecked((uint)RawX));
+ var yBytes = MakeInteger(unchecked((uint)RawY));
var chunkLen = 4 + packedTerritoryAndMapBytes.Length + xBytes.Length + yBytes.Length;
@@ -149,8 +207,8 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
try
{
(this.territoryTypeId, this.mapId) = GetPackedIntegers(reader);
- this.rawX = unchecked((int)GetInteger(reader));
- this.rawY = unchecked((int)GetInteger(reader));
+ RawX = unchecked((int)GetInteger(reader));
+ RawY = unchecked((int)GetInteger(reader));
// the Z coordinate is never in this chunk, just the text (if applicable)
// seems to always be FF 01
diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/PlayerPayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/PlayerPayload.cs
index 6a05f1a74..d2c0cbfb8 100644
--- a/Dalamud/Game/Chat/SeStringHandling/Payloads/PlayerPayload.cs
+++ b/Dalamud/Game/Chat/SeStringHandling/Payloads/PlayerPayload.cs
@@ -6,11 +6,17 @@ using System.Text;
namespace Dalamud.Game.Chat.SeStringHandling.Payloads
{
+ ///
+ /// An SeString Payload representing a player link.
+ ///
public class PlayerPayload : Payload
{
public override PayloadType Type => PayloadType.Player;
private string playerName;
+ ///
+ /// The player's displayed name. This does not contain the server name.
+ ///
public string PlayerName
{
get { return this.playerName; }
@@ -22,6 +28,12 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
}
private World world;
+ ///
+ /// The Lumina object representing the player's home server.
+ ///
+ ///
+ /// Value is evaluated lazily and cached.
+ ///
public World World
{
get
@@ -31,10 +43,21 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
}
}
+ ///
+ /// A text representation of this player link matching how it might appear in-game.
+ /// The world name will always be present.
+ ///
+ public string DisplayedName => $"{PlayerName}{(char)SeIconChar.CrossWorld}{World.Name}";
+
private uint serverId;
internal PlayerPayload() { }
+ ///
+ /// Create a PlayerPayload link for the specified player.
+ ///
+ /// The player's displayed name.
+ /// The player's home server id.
public PlayerPayload(string playerName, uint serverId)
{
this.playerName = playerName;
@@ -43,7 +66,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
public override string ToString()
{
- return $"{Type} - PlayerName: {PlayerName}, ServerId: {serverId}";
+ return $"{Type} - PlayerName: {PlayerName}, ServerId: {serverId}, ServerName: {World.Name}";
}
protected override byte[] EncodeImpl()
diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/RawPayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/RawPayload.cs
index 2a1d04b55..301bde07e 100644
--- a/Dalamud/Game/Chat/SeStringHandling/Payloads/RawPayload.cs
+++ b/Dalamud/Game/Chat/SeStringHandling/Payloads/RawPayload.cs
@@ -5,21 +5,36 @@ using System.Linq;
namespace Dalamud.Game.Chat.SeStringHandling.Payloads
{
+ ///
+ /// An SeString Payload representing unhandled raw payload data.
+ /// Mainly useful for constructing unhandled hardcoded payloads, or forwarding any unknown
+ /// payloads without modification.
+ ///
public class RawPayload : Payload
{
// this and others could be an actual static member somewhere and avoid construction costs, but that probably isn't a real concern
+ ///
+ /// A fixed Payload representing a common link-termination sequence, found in many payload chains.
+ ///
public static RawPayload LinkTerminator => new RawPayload(new byte[] { 0x02, 0x27, 0x07, 0xCF, 0x01, 0x01, 0x01, 0xFF, 0x01, 0x03 });
public override PayloadType Type => PayloadType.Unknown;
private byte[] data;
+ // this is a bit different from the underlying data
+ // We need to store just the chunk data for decode to behave nicely, but when reading data out
+ // it makes more sense to get the entire payload
+ ///
+ /// The entire payload byte sequence for this payload.
+ /// The returned data is a clone and modifications will not be persisted.
+ ///
public byte[] Data
{
get
{
// for now don't allow modifying the contents
// because we don't really have a way to track Dirty
- return (byte[])data.Clone();
+ return (byte[])Encode().Clone();
}
}
@@ -34,13 +49,14 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
{
// this payload is 'special' in that we require the entire chunk to be passed in
// and not just the data after the header
+ // This sets data to hold the chunk data fter the header, excluding the END_BYTE
this.chunkType = data[1];
this.data = data.Skip(3).Take(data.Length-4).ToArray();
}
public override string ToString()
{
- return $"{Type} - Chunk type: {chunkType:X}, Data: {BitConverter.ToString(data).Replace("-", " ")}";
+ return $"{Type} - Data: {BitConverter.ToString(Data).Replace("-", " ")}";
}
protected override byte[] EncodeImpl()
diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/StatusPayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/StatusPayload.cs
index 3b822c239..d5753e40c 100644
--- a/Dalamud/Game/Chat/SeStringHandling/Payloads/StatusPayload.cs
+++ b/Dalamud/Game/Chat/SeStringHandling/Payloads/StatusPayload.cs
@@ -5,11 +5,20 @@ using System.IO;
namespace Dalamud.Game.Chat.SeStringHandling.Payloads
{
+ ///
+ /// An SeString Payload representing an interactable status link.
+ ///
public class StatusPayload : Payload
{
public override PayloadType Type => PayloadType.Status;
private Status status;
+ ///
+ /// The Lumina Status object represented by this payload.
+ ///
+ ///
+ /// Value is evaluated lazily and cached.
+ ///
public Status Status
{
get
@@ -23,6 +32,10 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
internal StatusPayload() { }
+ ///
+ /// Creates a new StatusPayload for the given status id.
+ ///
+ /// The id of the Status for this link.
public StatusPayload(uint statusId)
{
this.statusId = statusId;
@@ -30,7 +43,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
public override string ToString()
{
- return $"{Type} - StatusId: {statusId}";
+ return $"{Type} - StatusId: {statusId}, Name: {Status.Name}";
}
protected override byte[] EncodeImpl()
diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/TextPayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/TextPayload.cs
index 5b3fc9882..ae7bcb23b 100644
--- a/Dalamud/Game/Chat/SeStringHandling/Payloads/TextPayload.cs
+++ b/Dalamud/Game/Chat/SeStringHandling/Payloads/TextPayload.cs
@@ -5,12 +5,19 @@ using System.Text;
namespace Dalamud.Game.Chat.SeStringHandling.Payloads
{
+ ///
+ /// An SeString Payload representing a plain text string.
+ ///
public class TextPayload : Payload, ITextProvider
{
public override PayloadType Type => PayloadType.RawText;
// allow modifying the text of existing payloads on the fly
private string text;
+ ///
+ /// The text contained in this payload.
+ /// This may contain SE's special unicode characters.
+ ///
public string Text
{
get { return this.text; }
@@ -28,6 +35,10 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
internal TextPayload() { }
+ ///
+ /// Creates a new TextPayload for the given text.
+ ///
+ /// The text to include for this payload.
public TextPayload(string text)
{
this.text = text;
diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/UIForegroundPayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/UIForegroundPayload.cs
index 8d7290058..9a8e5780c 100644
--- a/Dalamud/Game/Chat/SeStringHandling/Payloads/UIForegroundPayload.cs
+++ b/Dalamud/Game/Chat/SeStringHandling/Payloads/UIForegroundPayload.cs
@@ -5,15 +5,30 @@ using System.IO;
namespace Dalamud.Game.Chat.SeStringHandling.Payloads
{
+ ///
+ /// An SeString Payload representing a UI foreground color applied to following text payloads.
+ ///
public class UIForegroundPayload : Payload
{
+ ///
+ /// Payload representing disabling foreground color on following text.
+ ///
public static UIForegroundPayload UIForegroundOff => new UIForegroundPayload(0);
public override PayloadType Type => PayloadType.UIForeground;
+ ///
+ /// Whether or not this payload represents applying a foreground color, or disabling one.
+ ///
public bool IsEnabled => ColorKey != 0;
private UIColor color;
+ ///
+ /// A Lumina UIColor object representing this payload. The actual color data is at UIColor.UIForeground
+ ///
+ ///
+ /// Value is evaluated lazily and cached.
+ ///
public UIColor UIColor
{
get
@@ -23,6 +38,9 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
}
}
+ ///
+ /// The color key used as a lookup in the UIColor table for this foreground color.
+ ///
public ushort ColorKey
{
get { return this.colorKey; }
@@ -34,6 +52,9 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
}
}
+ ///
+ /// The Red/Green/Blue values for this foreground color, encoded as a typical hex color.
+ ///
public uint RGB
{
get
@@ -46,6 +67,10 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
internal UIForegroundPayload() { }
+ ///
+ /// Creates a new UIForegroundPayload for the given UIColor key.
+ ///
+ ///
public UIForegroundPayload(ushort colorKey)
{
this.colorKey = colorKey;
@@ -53,7 +78,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
public override string ToString()
{
- return $"{Type} - UIColor: {colorKey}";
+ return $"{Type} - UIColor: {colorKey} color: {(IsEnabled ? RGB : 0)}";
}
protected override byte[] EncodeImpl()
diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/UIGlowPayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/UIGlowPayload.cs
index fcabfe742..7731b431a 100644
--- a/Dalamud/Game/Chat/SeStringHandling/Payloads/UIGlowPayload.cs
+++ b/Dalamud/Game/Chat/SeStringHandling/Payloads/UIGlowPayload.cs
@@ -5,15 +5,30 @@ using System.IO;
namespace Dalamud.Game.Chat.SeStringHandling.Payloads
{
+ ///
+ /// An SeString Payload representing a UI glow color applied to following text payloads.
+ ///
public class UIGlowPayload : Payload
{
+ ///
+ /// Payload representing disabling glow color on following text.
+ ///
public static UIGlowPayload UIGlowOff => new UIGlowPayload(0);
public override PayloadType Type => PayloadType.UIGlow;
+ ///
+ /// Whether or not this payload represents applying a glow color, or disabling one.
+ ///
public bool IsEnabled => ColorKey != 0;
private UIColor color;
+ ///
+ /// A Lumina UIColor object representing this payload. The actual color data is at UIColor.UIGlow
+ ///
+ ///
+ /// Value is evaluated lazily and cached.
+ ///
public UIColor UIColor
{
get
@@ -23,6 +38,9 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
}
}
+ ///
+ /// The color key used as a lookup in the UIColor table for this glow color.
+ ///
public ushort ColorKey
{
get { return this.colorKey; }
@@ -34,6 +52,9 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
}
}
+ ///
+ /// The Red/Green/Blue values for this glow color, encoded as a typical hex color.
+ ///
public uint RGB
{
get
@@ -46,6 +67,10 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
internal UIGlowPayload() { }
+ ///
+ /// Creates a new UIForegroundPayload for the given UIColor key.
+ ///
+ ///
public UIGlowPayload(ushort colorKey)
{
this.colorKey = colorKey;
@@ -53,7 +78,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
public override string ToString()
{
- return $"{Type} - UIColor: {colorKey}";
+ return $"{Type} - UIColor: {colorKey} color: {(IsEnabled ? RGB : 0)}";
}
protected override byte[] EncodeImpl()
diff --git a/Dalamud/Game/Chat/SeStringHandling/SeString.cs b/Dalamud/Game/Chat/SeStringHandling/SeString.cs
index 01f01d593..26e7e7342 100644
--- a/Dalamud/Game/Chat/SeStringHandling/SeString.cs
+++ b/Dalamud/Game/Chat/SeStringHandling/SeString.cs
@@ -14,6 +14,9 @@ namespace Dalamud.Game.Chat.SeStringHandling
// TODO: probably change how this is done/where it comes from
internal static Dalamud Dalamud { get; set; }
+ ///
+ /// The ordered list of payloads included in this SeString.
+ ///
public List Payloads { get; }
///
@@ -56,30 +59,54 @@ namespace Dalamud.Game.Chat.SeStringHandling
return new SeString(payloads);
}
+ ///
+ /// Creates a new SeString from an ordered list of payloads.
+ ///
+ /// The Payload objects to make up this string.
public SeString(List payloads)
{
Payloads = payloads;
}
+ ///
+ /// Appends the contents of one SeString to this one.
+ ///
+ /// The SeString to append to this one.
+ /// This object.
public SeString Append(SeString other)
{
Payloads.AddRange(other.Payloads);
return this;
}
+ ///
+ /// Appends a list of payloads to this SeString.
+ ///
+ /// The Payloads to append.
+ /// This object.
public SeString Append(List payloads)
{
Payloads.AddRange(payloads);
return this;
}
+ ///
+ /// Appends a single payload to this SeString.
+ ///
+ /// The payload to append.
+ /// This object.
public SeString Append(Payload payload)
{
Payloads.Add(payload);
return this;
}
- internal byte[] Encode()
+ ///
+ /// Encodes the Payloads in this SeString into a binary representation
+ /// suitable for use by in-game handlers, such as the chat log.
+ ///
+ /// The binary encoded payload data.
+ public byte[] Encode()
{
var messageBytes = new List();
foreach (var p in Payloads)
diff --git a/Dalamud/Game/Chat/SeStringHandling/SeStringUtils.cs b/Dalamud/Game/Chat/SeStringHandling/SeStringUtils.cs
index 4a5dbfc9f..e7b4cc43f 100644
--- a/Dalamud/Game/Chat/SeStringHandling/SeStringUtils.cs
+++ b/Dalamud/Game/Chat/SeStringHandling/SeStringUtils.cs
@@ -8,8 +8,18 @@ using DalamudItem = Dalamud.Data.TransientSheet.Item;
namespace Dalamud.Game.Chat.SeStringHandling
{
- public class SeStringUtils
+ ///
+ /// A utility class for working with common SeString variants.
+ ///
+ public static class SeStringUtils
{
+ ///
+ /// Creates an SeString representing an entire Payload chain that can be used to link an item in the chat log.
+ ///
+ /// The id of the item to link.
+ /// Whether to link the high-quality variant of the item.
+ /// An optional name override to display, instead of the actual item name.
+ /// An SeString containing all the payloads necessary to display an item link in the chat log.
public static SeString CreateItemLink(uint itemId, bool isHQ, string displayNameOverride = null)
{
string displayName = displayNameOverride ?? SeString.Dalamud.Data.GetExcelSheet().GetRow((int)itemId).Name;
@@ -35,11 +45,44 @@ namespace Dalamud.Game.Chat.SeStringHandling
return new SeString(payloads);
}
+ ///
+ /// Creates an SeString representing an entire Payload chain that can be used to link an item in the chat log.
+ ///
+ /// The Lumina Item to link.
+ /// Whether to link the high-quality variant of the item.
+ /// An optional name override to display, instead of the actual item name.
+ /// An SeString containing all the payloads necessary to display an item link in the chat log.
public static SeString CreateItemLink(DalamudItem item, bool isHQ, string displayNameOverride = null)
{
return CreateItemLink((uint)item.RowId, isHQ, displayNameOverride ?? item.Name);
}
+ public static SeString CreateMapLink(uint territoryId, uint mapId, int rawX, int rawY)
+ {
+ var mapPayload = new MapLinkPayload(territoryId, mapId, rawX, rawY);
+ var nameString = $"{mapPayload.PlaceName} {mapPayload.CoordinateString}";
+
+ var payloads = new List(new Payload[]
+ {
+ mapPayload,
+ // arrow goes here
+ new TextPayload(nameString),
+ RawPayload.LinkTerminator
+ });
+ payloads.InsertRange(1, TextArrowPayloads());
+
+ return new SeString(payloads);
+ }
+
+ ///
+ /// Creates an SeString representing an entire Payload chain that can be used to link a map position in the chat log.
+ ///
+ /// The id of the TerritoryType for this map link.
+ /// The id of the Map for this map link.
+ /// The human-readable x-coordinate for this link.
+ /// The human-readable y-coordinate for this link.
+ /// An optional offset to account for rounding and truncation errors; it is best to leave this untouched in most cases.
+ /// An SeString containing all of the payloads necessary to display a map link in the chat log.
public static SeString CreateMapLink(uint territoryId, uint mapId, float xCoord, float yCoord, float fudgeFactor = 0.05f)
{
var mapPayload = new MapLinkPayload(territoryId, mapId, xCoord, yCoord, fudgeFactor);
@@ -57,6 +100,14 @@ namespace Dalamud.Game.Chat.SeStringHandling
return new SeString(payloads);
}
+ ///
+ /// Creates an SeString representing an entire Payload chain that can be used to link a map position in the chat log, matching a specified zone name.
+ ///
+ /// The name of the location for this link. This should be exactly the name as seen in a displayed map link in-game for the same zone.
+ /// The human-readable x-coordinate for this link.
+ /// The human-readable y-coordinate for this link.
+ /// An optional offset to account for rounding and truncation errors; it is best to leave this untouched in most cases.
+ /// An SeString containing all of the payloads necessary to display a map link in the chat log.
public static SeString CreateMapLink(string placeName, float xCoord, float yCoord, float fudgeFactor = 0.05f)
{
var mapSheet = SeString.Dalamud.Data.GetExcelSheet