mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-15 13:14:17 +01:00
Initial pieces of payload rework; everything is read-only at the moment, pending next stages. Lumina is now used for on-demand property resolution, properties are only exposed for user-facing values, and mostly expose the lumina object(s) where applicable
This commit is contained in:
parent
22e9eb89b8
commit
f2cee5f5bc
17 changed files with 355 additions and 253 deletions
|
|
@ -12,6 +12,7 @@ using Dalamud.Data;
|
||||||
using Dalamud.DiscordBot;
|
using Dalamud.DiscordBot;
|
||||||
using Dalamud.Game;
|
using Dalamud.Game;
|
||||||
using Dalamud.Game.Chat;
|
using Dalamud.Game.Chat;
|
||||||
|
using Dalamud.Game.Chat.SeStringHandling;
|
||||||
using Dalamud.Game.ClientState;
|
using Dalamud.Game.ClientState;
|
||||||
using Dalamud.Game.ClientState.Actors.Types;
|
using Dalamud.Game.ClientState.Actors.Types;
|
||||||
using Dalamud.Game.ClientState.Actors.Types.NonPlayer;
|
using Dalamud.Game.ClientState.Actors.Types.NonPlayer;
|
||||||
|
|
@ -103,6 +104,9 @@ namespace Dalamud {
|
||||||
this.Data = new DataManager(this.StartInfo.Language);
|
this.Data = new DataManager(this.StartInfo.Language);
|
||||||
this.Data.Initialize();
|
this.Data.Initialize();
|
||||||
|
|
||||||
|
// TODO: better way to do this? basically for lumina injection
|
||||||
|
SeString.Dalamud = this;
|
||||||
|
|
||||||
this.ClientState = new ClientState(this, info, this.SigScanner);
|
this.ClientState = new ClientState(this, info, this.SigScanner);
|
||||||
|
|
||||||
this.BotManager = new DiscordBotManager(this, this.Configuration.DiscordFeatureConfig);
|
this.BotManager = new DiscordBotManager(this, this.Configuration.DiscordFeatureConfig);
|
||||||
|
|
|
||||||
53
Dalamud/Data/TransientSheet/Completion.cs
Normal file
53
Dalamud/Data/TransientSheet/Completion.cs
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
using Lumina.Excel;
|
||||||
|
|
||||||
|
namespace Dalamud.Data.TransientSheet
|
||||||
|
{
|
||||||
|
[Sheet( "Completion", columnHash: 0x2e6c55a3 )]
|
||||||
|
public class Completion : IExcelRow
|
||||||
|
{
|
||||||
|
// column defs from Mon, 02 Mar 2020 11:00:20 GMT
|
||||||
|
|
||||||
|
|
||||||
|
// col: 03 offset: 0000
|
||||||
|
public string Text;
|
||||||
|
|
||||||
|
// col: 04 offset: 0004
|
||||||
|
public string GroupTitle;
|
||||||
|
|
||||||
|
// col: 02 offset: 0008
|
||||||
|
public string LookupTable;
|
||||||
|
|
||||||
|
// col: 00 offset: 000c
|
||||||
|
public ushort Group;
|
||||||
|
|
||||||
|
// col: 01 offset: 000e
|
||||||
|
public ushort Key;
|
||||||
|
|
||||||
|
|
||||||
|
public int RowId { get; set; }
|
||||||
|
public int SubRowId { get; set; }
|
||||||
|
|
||||||
|
public void PopulateData( RowParser parser, Lumina.Lumina lumina )
|
||||||
|
{
|
||||||
|
RowId = parser.Row;
|
||||||
|
SubRowId = parser.SubRow;
|
||||||
|
|
||||||
|
// col: 3 offset: 0000
|
||||||
|
Text = parser.ReadOffset< string >( 0x0 );
|
||||||
|
|
||||||
|
// col: 4 offset: 0004
|
||||||
|
GroupTitle = parser.ReadOffset< string >( 0x4 );
|
||||||
|
|
||||||
|
// col: 2 offset: 0008
|
||||||
|
LookupTable = parser.ReadOffset< string >( 0x8 );
|
||||||
|
|
||||||
|
// col: 0 offset: 000c
|
||||||
|
Group = parser.ReadOffset< ushort >( 0xc );
|
||||||
|
|
||||||
|
// col: 1 offset: 000e
|
||||||
|
Key = parser.ReadOffset< ushort >( 0xe );
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -205,10 +205,8 @@ namespace Dalamud.DiscordBot {
|
||||||
|
|
||||||
senderWorld = this.dalamud.ClientState.LocalPlayer.HomeWorld.GameData.Name;
|
senderWorld = this.dalamud.ClientState.LocalPlayer.HomeWorld.GameData.Name;
|
||||||
} else {
|
} else {
|
||||||
playerLink.Resolve();
|
|
||||||
|
|
||||||
senderName = wasOutgoingTell ? this.dalamud.ClientState.LocalPlayer.Name : playerLink.PlayerName;
|
senderName = wasOutgoingTell ? this.dalamud.ClientState.LocalPlayer.Name : playerLink.PlayerName;
|
||||||
senderWorld = playerLink.ServerName;
|
senderWorld = playerLink.World.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
var rawMessage = SeString.Parse(message.RawData).TextValue;
|
var rawMessage = SeString.Parse(message.RawData).TextValue;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Dalamud.Data;
|
||||||
using Dalamud.Game.Chat.SeStringHandling.Payloads;
|
using Dalamud.Game.Chat.SeStringHandling.Payloads;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
||||||
|
|
@ -11,6 +12,7 @@ using Serilog;
|
||||||
// - lumina DI
|
// - lumina DI
|
||||||
// - design for handling raw values vs resolved values, both for input and output
|
// - design for handling raw values vs resolved values, both for input and output
|
||||||
// - wrapper class(es) for handling of composite links in chat (item, map etc) and formatting operations
|
// - wrapper class(es) for handling of composite links in chat (item, map etc) and formatting operations
|
||||||
|
// - add italics payload
|
||||||
|
|
||||||
namespace Dalamud.Game.Chat.SeStringHandling
|
namespace Dalamud.Game.Chat.SeStringHandling
|
||||||
{
|
{
|
||||||
|
|
@ -21,12 +23,23 @@ namespace Dalamud.Game.Chat.SeStringHandling
|
||||||
{
|
{
|
||||||
public abstract PayloadType Type { get; }
|
public abstract PayloadType Type { get; }
|
||||||
|
|
||||||
public abstract void Resolve();
|
|
||||||
|
|
||||||
public abstract byte[] Encode();
|
public abstract byte[] Encode();
|
||||||
|
|
||||||
protected abstract void ProcessChunkImpl(BinaryReader reader, long endOfStream);
|
protected abstract void ProcessChunkImpl(BinaryReader reader, long endOfStream);
|
||||||
|
|
||||||
|
// :(
|
||||||
|
protected DataManager dataResolver;
|
||||||
|
|
||||||
|
public Payload()
|
||||||
|
{
|
||||||
|
// this is not a good way to do this, but I don't want to have to include a dalamud
|
||||||
|
// reference on multiple methods in every payload class
|
||||||
|
// We could also just directly reference this static where we use it, but this at least
|
||||||
|
// allows for more easily changing how this is injected later, without affecting code
|
||||||
|
// that makes use of it
|
||||||
|
this.dataResolver = SeString.Dalamud.Data;
|
||||||
|
}
|
||||||
|
|
||||||
public static Payload Process(BinaryReader reader)
|
public static Payload Process(BinaryReader reader)
|
||||||
{
|
{
|
||||||
Payload payload = null;
|
Payload payload = null;
|
||||||
|
|
@ -78,10 +91,13 @@ namespace Dalamud.Game.Chat.SeStringHandling
|
||||||
case EmbeddedInfoType.LinkTerminator:
|
case EmbeddedInfoType.LinkTerminator:
|
||||||
// this has no custom handling and so needs to fallthrough to ensure it is captured
|
// this has no custom handling and so needs to fallthrough to ensure it is captured
|
||||||
default:
|
default:
|
||||||
Log.Verbose("Unhandled EmbeddedInfoType: {0}", subType);
|
// but I'm also tired of this log
|
||||||
|
if (subType != EmbeddedInfoType.LinkTerminator)
|
||||||
|
{
|
||||||
|
Log.Verbose("Unhandled EmbeddedInfoType: {0}", subType);
|
||||||
|
}
|
||||||
// rewind so we capture the Interactable byte in the raw data
|
// rewind so we capture the Interactable byte in the raw data
|
||||||
reader.BaseStream.Seek(-1, SeekOrigin.Current);
|
reader.BaseStream.Seek(-1, SeekOrigin.Current);
|
||||||
payload = new RawPayload((byte)chunkType);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -101,11 +117,11 @@ namespace Dalamud.Game.Chat.SeStringHandling
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Log.Verbose("Unhandled SeStringChunkType: {0}", chunkType);
|
Log.Verbose("Unhandled SeStringChunkType: {0}", chunkType);
|
||||||
payload = new RawPayload((byte)chunkType);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
payload?.ProcessChunkImpl(reader, reader.BaseStream.Position + chunkLen - 1);
|
payload ??= new RawPayload((byte)chunkType);
|
||||||
|
payload.ProcessChunkImpl(reader, reader.BaseStream.Position + chunkLen - 1);
|
||||||
|
|
||||||
// read through the rest of the packet
|
// read through the rest of the packet
|
||||||
var readBytes = (uint)(reader.BaseStream.Position - packetStart);
|
var readBytes = (uint)(reader.BaseStream.Position - packetStart);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
|
using Dalamud.Data.TransientSheet;
|
||||||
|
using Lumina.Excel.GeneratedSheets;
|
||||||
|
using Serilog;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
{
|
{
|
||||||
|
|
@ -9,78 +12,29 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
{
|
{
|
||||||
public override PayloadType Type => PayloadType.AutoTranslateText;
|
public override PayloadType Type => PayloadType.AutoTranslateText;
|
||||||
|
|
||||||
public uint Group { get; set; }
|
private string text;
|
||||||
|
public string Text
|
||||||
public uint Key { get; set; }
|
|
||||||
|
|
||||||
public string Text { get; set; }
|
|
||||||
|
|
||||||
public override void Resolve()
|
|
||||||
{
|
{
|
||||||
// TODO: fixup once lumina DI is in
|
get
|
||||||
|
{
|
||||||
//if (string.IsNullOrEmpty(Text))
|
this.text ??= Resolve();
|
||||||
//{
|
return this.text;
|
||||||
// var sheet = dalamud.Data.GetExcelSheet<Completion>();
|
}
|
||||||
|
|
||||||
// Completion row = null;
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// // try to get the row in the Completion table itself, because this is 'easiest'
|
|
||||||
// // The row may not exist at all (if the Key is for another table), or it could be the wrong row
|
|
||||||
// // (again, if it's meant for another table)
|
|
||||||
// row = sheet.GetRow(Key);
|
|
||||||
// }
|
|
||||||
// catch {} // don't care, row will be null
|
|
||||||
|
|
||||||
// if (row?.Group == Group)
|
|
||||||
// {
|
|
||||||
// // if the row exists in this table and the group matches, this is actually the correct data
|
|
||||||
// Text = $"{{ {row.Text} }} ";
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// Log.Verbose("row mismatch");
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// // we need to get the linked table and do the lookup there instead
|
|
||||||
// // in this case, there will only be one entry for this group id
|
|
||||||
// row = sheet.GetRows().First(r => r.Group == Group);
|
|
||||||
// // many of the names contain valid id ranges after the table name, but we don't need those
|
|
||||||
// var actualTableName = row.LookupTable.Split('[')[0];
|
|
||||||
|
|
||||||
// var name = actualTableName switch
|
|
||||||
// {
|
|
||||||
// // TODO: rest of xref'd tables
|
|
||||||
// "Action" => dalamud.Data.GetExcelSheet<Data.TransientSheet.Action>().GetRow(Key).Name,
|
|
||||||
// "ClassJob" => dalamud.Data.GetExcelSheet<ClassJob>().GetRow(Key).Name,
|
|
||||||
// "CraftAction" => dalamud.Data.GetExcelSheet<CraftAction>().GetRow(Key).Name,
|
|
||||||
// "Mount" => dalamud.Data.GetExcelSheet<Mount>().GetRow(Key).Singular,
|
|
||||||
// "PlaceName" => dalamud.Data.GetExcelSheet<PlaceName>().GetRow(Key).Name,
|
|
||||||
// "Race" => dalamud.Data.GetExcelSheet<Race>().GetRow(Key).Masculine,
|
|
||||||
// _ => throw new Exception(actualTableName)
|
|
||||||
// };
|
|
||||||
|
|
||||||
// Text = $"{{ {name} }} ";
|
|
||||||
// }
|
|
||||||
// catch (Exception e)
|
|
||||||
// {
|
|
||||||
// Log.Error(e, $"AutoTranslatePayload - failed to resolve: {this}");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private uint group;
|
||||||
|
private uint key;
|
||||||
|
|
||||||
public override byte[] Encode()
|
public override byte[] Encode()
|
||||||
{
|
{
|
||||||
var keyBytes = MakeInteger(Key);
|
var keyBytes = MakeInteger(this.key);
|
||||||
|
|
||||||
var chunkLen = keyBytes.Length + 2;
|
var chunkLen = keyBytes.Length + 2;
|
||||||
var bytes = new List<byte>()
|
var bytes = new List<byte>()
|
||||||
{
|
{
|
||||||
START_BYTE,
|
START_BYTE,
|
||||||
(byte)SeStringChunkType.AutoTranslateKey, (byte)chunkLen,
|
(byte)SeStringChunkType.AutoTranslateKey, (byte)chunkLen,
|
||||||
(byte)Group
|
(byte)this.group
|
||||||
};
|
};
|
||||||
bytes.AddRange(keyBytes);
|
bytes.AddRange(keyBytes);
|
||||||
bytes.Add(END_BYTE);
|
bytes.Add(END_BYTE);
|
||||||
|
|
@ -90,16 +44,83 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"{Type} - Group: {Group}, Key: {Key}, Text: {Text}";
|
return $"{Type} - Group: {group}, Key: {key}";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream)
|
protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream)
|
||||||
{
|
{
|
||||||
// this seems to always be a bare byte, and not following normal integer encoding
|
// this seems to always be a bare byte, and not following normal integer encoding
|
||||||
// the values in the table are all <70 so this is presumably ok
|
// the values in the table are all <70 so this is presumably ok
|
||||||
Group = reader.ReadByte();
|
this.group = reader.ReadByte();
|
||||||
|
|
||||||
Key = GetInteger(reader);
|
this.key = GetInteger(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Resolve()
|
||||||
|
{
|
||||||
|
string value = null;
|
||||||
|
|
||||||
|
var sheet = this.dataResolver.GetExcelSheet<Completion>();
|
||||||
|
|
||||||
|
Completion row = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// try to get the row in the Completion table itself, because this is 'easiest'
|
||||||
|
// The row may not exist at all (if the Key is for another table), or it could be the wrong row
|
||||||
|
// (again, if it's meant for another table)
|
||||||
|
row = sheet.GetRow((int)this.key);
|
||||||
|
}
|
||||||
|
catch { } // don't care, row will be null
|
||||||
|
|
||||||
|
if (row?.Group == this.group)
|
||||||
|
{
|
||||||
|
// if the row exists in this table and the group matches, this is actually the correct data
|
||||||
|
value = row.Text;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// we need to get the linked table and do the lookup there instead
|
||||||
|
// in this case, there will only be one entry for this group id
|
||||||
|
row = sheet.GetRows().First(r => r.Group == this.group);
|
||||||
|
// many of the names contain valid id ranges after the table name, but we don't need those
|
||||||
|
var actualTableName = row.LookupTable.Split('[')[0];
|
||||||
|
|
||||||
|
var ikey = (int)this.key;
|
||||||
|
|
||||||
|
var name = actualTableName switch
|
||||||
|
{
|
||||||
|
"Action" => this.dataResolver.GetExcelSheet<Lumina.Excel.GeneratedSheets.Action>().GetRow(ikey).Name,
|
||||||
|
"ActionComboRoute" => this.dataResolver.GetExcelSheet<ActionComboRoute>().GetRow(ikey).Name,
|
||||||
|
"BuddyAction" => this.dataResolver.GetExcelSheet<BuddyAction>().GetRow(ikey).Name,
|
||||||
|
"ClassJob" => this.dataResolver.GetExcelSheet<ClassJob>().GetRow(ikey).Name,
|
||||||
|
"Companion" => this.dataResolver.GetExcelSheet<Companion>().GetRow(ikey).Singular,
|
||||||
|
"CraftAction" => this.dataResolver.GetExcelSheet<CraftAction>().GetRow(ikey).Name,
|
||||||
|
"GeneralAction" => this.dataResolver.GetExcelSheet<GeneralAction>().GetRow(ikey).Name,
|
||||||
|
"GuardianDeity" => this.dataResolver.GetExcelSheet<GuardianDeity>().GetRow(ikey).Name,
|
||||||
|
"MainCommand" => this.dataResolver.GetExcelSheet<MainCommand>().GetRow(ikey).Name,
|
||||||
|
"Mount" => this.dataResolver.GetExcelSheet<Mount>().GetRow(ikey).Singular,
|
||||||
|
"Pet" => this.dataResolver.GetExcelSheet<Pet>().GetRow(ikey).Name,
|
||||||
|
"PetAction" => this.dataResolver.GetExcelSheet<PetAction>().GetRow(ikey).Name,
|
||||||
|
// TODO: lumina doesn't have PetMirage
|
||||||
|
"PlaceName" => this.dataResolver.GetExcelSheet<PlaceName>().GetRow(ikey).Name,
|
||||||
|
"Race" => this.dataResolver.GetExcelSheet<Race>().GetRow(ikey).Masculine,
|
||||||
|
"TextCommand" => this.dataResolver.GetExcelSheet<TextCommand>().GetRow(ikey).Command,
|
||||||
|
"Tribe" => this.dataResolver.GetExcelSheet<Tribe>().GetRow(ikey).Masculine,
|
||||||
|
"Weather" => this.dataResolver.GetExcelSheet<Weather>().GetRow(ikey).Name,
|
||||||
|
_ => throw new Exception(actualTableName)
|
||||||
|
};
|
||||||
|
|
||||||
|
value = name;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Error(e, $"AutoTranslatePayload - failed to resolve: {this}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
|
using Dalamud.Data.TransientSheet;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
{
|
{
|
||||||
|
|
@ -11,38 +11,34 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
{
|
{
|
||||||
public override PayloadType Type => PayloadType.Item;
|
public override PayloadType Type => PayloadType.Item;
|
||||||
|
|
||||||
public uint ItemId { get; private set; }
|
private Item item;
|
||||||
public string ItemName { get; private set; } = string.Empty;
|
public Item Item
|
||||||
public bool IsHQ { get; private set; } = false;
|
|
||||||
|
|
||||||
public ItemPayload() { }
|
|
||||||
|
|
||||||
public ItemPayload(uint itemId, bool isHQ)
|
|
||||||
{
|
{
|
||||||
ItemId = itemId;
|
get
|
||||||
IsHQ = isHQ;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Resolve()
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(ItemName))
|
|
||||||
{
|
{
|
||||||
dynamic item = XivApi.GetItem((int)ItemId).GetAwaiter().GetResult();
|
this.item ??= this.dataResolver.GetExcelSheet<Item>().GetRow((int)this.itemId);
|
||||||
ItemName = item.Name;
|
return this.item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsHQ { get; private set; } = false;
|
||||||
|
|
||||||
|
private uint itemId;
|
||||||
|
// mainly to allow overriding the name (for things like owo)
|
||||||
|
private string displayName;
|
||||||
|
|
||||||
|
|
||||||
public override byte[] Encode()
|
public override byte[] Encode()
|
||||||
{
|
{
|
||||||
var actualItemId = IsHQ ? ItemId + 1000000 : ItemId;
|
var actualItemId = IsHQ ? this.itemId + 1000000 : this.itemId;
|
||||||
var idBytes = MakeInteger(actualItemId);
|
var idBytes = MakeInteger(actualItemId);
|
||||||
bool hasName = !string.IsNullOrEmpty(ItemName);
|
bool hasName = !string.IsNullOrEmpty(this.displayName);
|
||||||
|
|
||||||
var chunkLen = idBytes.Length + 4;
|
var chunkLen = idBytes.Length + 4;
|
||||||
if (hasName)
|
if (hasName)
|
||||||
{
|
{
|
||||||
// 1 additional unknown byte compared to the nameless version, 1 byte for the name length, and then the name itself
|
// 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);
|
chunkLen += (1 + 1 + this.displayName.Length);
|
||||||
if (IsHQ)
|
if (IsHQ)
|
||||||
{
|
{
|
||||||
chunkLen += 4; // unicode representation of the HQ symbol is 3 bytes, preceded by a space
|
chunkLen += 4; // unicode representation of the HQ symbol is 3 bytes, preceded by a space
|
||||||
|
|
@ -61,7 +57,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
// Links don't have to include the name, but if they do, it requires additional work
|
// Links don't have to include the name, but if they do, it requires additional work
|
||||||
if (hasName)
|
if (hasName)
|
||||||
{
|
{
|
||||||
var nameLen = ItemName.Length + 1;
|
var nameLen = this.displayName.Length + 1;
|
||||||
if (IsHQ)
|
if (IsHQ)
|
||||||
{
|
{
|
||||||
nameLen += 4; // space plus 3 bytes for HQ symbol
|
nameLen += 4; // space plus 3 bytes for HQ symbol
|
||||||
|
|
@ -72,7 +68,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
0xFF, // unk
|
0xFF, // unk
|
||||||
(byte)nameLen
|
(byte)nameLen
|
||||||
});
|
});
|
||||||
bytes.AddRange(Encoding.UTF8.GetBytes(ItemName));
|
bytes.AddRange(Encoding.UTF8.GetBytes(this.displayName));
|
||||||
|
|
||||||
if (IsHQ)
|
if (IsHQ)
|
||||||
{
|
{
|
||||||
|
|
@ -88,16 +84,16 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"{Type} - ItemId: {ItemId}, ItemName: {ItemName}, IsHQ: {IsHQ}";
|
return $"{Type} - ItemId: {itemId}, IsHQ: {IsHQ}";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream)
|
protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream)
|
||||||
{
|
{
|
||||||
ItemId = GetInteger(reader);
|
this.itemId = GetInteger(reader);
|
||||||
|
|
||||||
if (ItemId > 1000000)
|
if (this.itemId > 1000000)
|
||||||
{
|
{
|
||||||
ItemId -= 1000000;
|
this.itemId -= 1000000;
|
||||||
IsHQ = true;
|
IsHQ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -109,6 +105,11 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
var itemNameLen = (int)GetInteger(reader);
|
var itemNameLen = (int)GetInteger(reader);
|
||||||
var itemNameBytes = reader.ReadBytes(itemNameLen);
|
var itemNameBytes = reader.ReadBytes(itemNameLen);
|
||||||
|
|
||||||
|
// it probably isn't necessary to store this, as we now get the lumina Item
|
||||||
|
// on demand from the id, which will have the name
|
||||||
|
// For incoming links, the name "should?" always match
|
||||||
|
// but we'll store it for use in encode just in case it doesn't
|
||||||
|
|
||||||
// HQ items have the HQ symbol as part of the name, but since we already recorded
|
// 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
|
// the HQ flag, we want just the bare name
|
||||||
if (IsHQ)
|
if (IsHQ)
|
||||||
|
|
@ -116,7 +117,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
itemNameBytes = itemNameBytes.Take(itemNameLen - 4).ToArray();
|
itemNameBytes = itemNameBytes.Take(itemNameLen - 4).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemName = Encoding.UTF8.GetString(itemNameBytes);
|
this.displayName = Encoding.UTF8.GetString(itemNameBytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,18 +9,69 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
{
|
{
|
||||||
public override PayloadType Type => PayloadType.MapLink;
|
public override PayloadType Type => PayloadType.MapLink;
|
||||||
|
|
||||||
// pre-Resolve() values
|
private Map map;
|
||||||
public uint TerritoryTypeId { get; set; }
|
public Map Map
|
||||||
public uint MapId { get; set; }
|
{
|
||||||
public uint RawX { get; set; }
|
get
|
||||||
public uint RawY { get; set; }
|
{
|
||||||
|
this.map ??= this.dataResolver.GetExcelSheet<Map>().GetRow((int)this.mapId);
|
||||||
|
return this.map;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Resolved values
|
private TerritoryType territoryType;
|
||||||
// It might make sense to have Territory be an external type, that has assorted relevant info
|
public TerritoryType TerritoryType
|
||||||
public string Territory { get; private set; }
|
{
|
||||||
public string Zone { get; private set; }
|
get
|
||||||
public float XCoord { get; private set; }
|
{
|
||||||
public float YCoord { get; private set; }
|
this.territoryType ??= this.dataResolver.GetExcelSheet<TerritoryType>().GetRow((int)this.territoryTypeId);
|
||||||
|
return this.territoryType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// these could be cached, but this isn't really too egregious
|
||||||
|
public float XCoord
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ConvertRawPositionToMapCoordinate(this.rawX, Map.SizeFactor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float YCoord
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ConvertRawPositionToMapCoordinate(this.rawY, Map.SizeFactor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string placeNameRegion;
|
||||||
|
public string PlaceNameRegion
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
this.placeNameRegion ??= this.dataResolver.GetExcelSheet<PlaceName>().GetRow(TerritoryType.PlaceNameRegion).Name;
|
||||||
|
return this.placeNameRegion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string placeName;
|
||||||
|
public string PlaceName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
this.placeName ??= this.dataResolver.GetExcelSheet<PlaceName>().GetRow(TerritoryType.PlaceName).Name;
|
||||||
|
return this.placeName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string DataString => $"m:{TerritoryType.RowId},{Map.RowId},{unchecked((int)rawX)},{unchecked((int)rawY)}";
|
||||||
|
|
||||||
|
private uint territoryTypeId;
|
||||||
|
private uint mapId;
|
||||||
|
private uint rawX;
|
||||||
|
private uint rawY;
|
||||||
// there is no Z; it's purely in the text payload where applicable
|
// there is no Z; it's purely in the text payload where applicable
|
||||||
|
|
||||||
public override byte[] Encode()
|
public override byte[] Encode()
|
||||||
|
|
@ -28,9 +79,9 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
// TODO: for now we just encode the raw/internal values
|
// TODO: for now we just encode the raw/internal values
|
||||||
// eventually we should allow creation using 'nice' values that then encode properly
|
// eventually we should allow creation using 'nice' values that then encode properly
|
||||||
|
|
||||||
var packedTerritoryAndMapBytes = MakePackedInteger(TerritoryTypeId, MapId);
|
var packedTerritoryAndMapBytes = MakePackedInteger(this.territoryTypeId, this.mapId);
|
||||||
var xBytes = MakeInteger(RawX);
|
var xBytes = MakeInteger(this.rawX);
|
||||||
var yBytes = MakeInteger(RawY);
|
var yBytes = MakeInteger(this.rawY);
|
||||||
|
|
||||||
var chunkLen = 4 + packedTerritoryAndMapBytes.Length + xBytes.Length + yBytes.Length;
|
var chunkLen = 4 + packedTerritoryAndMapBytes.Length + xBytes.Length + yBytes.Length;
|
||||||
|
|
||||||
|
|
@ -50,24 +101,9 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
return bytes.ToArray();
|
return bytes.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Resolve()
|
|
||||||
{
|
|
||||||
// TODO: add once lumina DI is figured out
|
|
||||||
//if (string.IsNullOrEmpty(Territory))
|
|
||||||
//{
|
|
||||||
// var terrRow = dataResolver.GetExcelSheet<TerritoryType>().GetRow((int)TerritoryTypeId);
|
|
||||||
// Territory = dataResolver.GetExcelSheet<PlaceName>().GetRow(terrRow.PlaceName).Name;
|
|
||||||
// Zone = dataResolver.GetExcelSheet<PlaceName>().GetRow(terrRow.PlaceNameZone).Name;
|
|
||||||
|
|
||||||
// var mapSizeFactor = dataResolver.GetExcelSheet<Map>().GetRow((int)MapId).SizeFactor;
|
|
||||||
// XCoord = ConvertRawPositionToMapCoordinate(RawX, mapSizeFactor);
|
|
||||||
// YCoord = ConvertRawPositionToMapCoordinate(RawY, mapSizeFactor);
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"{Type} - TerritoryTypeId: {TerritoryTypeId}, MapId: {MapId}, RawX: {RawX}, RawY: {RawY}";
|
return $"{Type} - TerritoryTypeId: {territoryTypeId}, MapId: {mapId}, RawX: {rawX}, RawY: {rawY}";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream)
|
protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream)
|
||||||
|
|
@ -79,9 +115,9 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
(TerritoryTypeId, MapId) = GetPackedIntegers(reader);
|
(this.territoryTypeId, this.mapId) = GetPackedIntegers(reader);
|
||||||
RawX = (uint)GetInteger(reader);
|
this.rawX = (uint)GetInteger(reader);
|
||||||
RawY = (uint)GetInteger(reader);
|
this.rawY = (uint)GetInteger(reader);
|
||||||
// the Z coordinate is never in this chunk, just the text (if applicable)
|
// the Z coordinate is never in this chunk, just the text (if applicable)
|
||||||
|
|
||||||
// seems to always be FF 01
|
// seems to always be FF 01
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
|
using Lumina.Excel.GeneratedSheets;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
{
|
{
|
||||||
|
|
@ -12,26 +11,19 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
public override PayloadType Type => PayloadType.Player;
|
public override PayloadType Type => PayloadType.Player;
|
||||||
|
|
||||||
public string PlayerName { get; private set; }
|
public string PlayerName { get; private set; }
|
||||||
public uint ServerId { get; private set; }
|
|
||||||
public string ServerName { get; private set; } = String.Empty;
|
|
||||||
|
|
||||||
public PlayerPayload() { }
|
private World world;
|
||||||
|
public World World
|
||||||
public PlayerPayload(string playerName, uint serverId)
|
|
||||||
{
|
{
|
||||||
PlayerName = playerName;
|
get
|
||||||
ServerId = serverId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Resolve()
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(ServerName))
|
|
||||||
{
|
{
|
||||||
dynamic server = XivApi.Get($"World/{ServerId}").GetAwaiter().GetResult();
|
this.world ??= this.dataResolver.GetExcelSheet<World>().GetRow((int)this.serverId);
|
||||||
ServerName = server.Name;
|
return this.world;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private uint serverId;
|
||||||
|
|
||||||
public override byte[] Encode()
|
public override byte[] Encode()
|
||||||
{
|
{
|
||||||
var chunkLen = PlayerName.Length + 7;
|
var chunkLen = PlayerName.Length + 7;
|
||||||
|
|
@ -40,7 +32,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
START_BYTE,
|
START_BYTE,
|
||||||
(byte)SeStringChunkType.Interactable, (byte)chunkLen, (byte)EmbeddedInfoType.PlayerName,
|
(byte)SeStringChunkType.Interactable, (byte)chunkLen, (byte)EmbeddedInfoType.PlayerName,
|
||||||
/* unk */ 0x01,
|
/* unk */ 0x01,
|
||||||
(byte)(ServerId+1), // I didn't want to deal with single-byte values in MakeInteger, so we have to do the +1 manually
|
(byte)(this.serverId+1), // I didn't want to deal with single-byte values in MakeInteger, so we have to do the +1 manually
|
||||||
/* unk */0x01, /* unk */0xFF, // these sometimes vary but are frequently this
|
/* unk */0x01, /* unk */0xFF, // these sometimes vary but are frequently this
|
||||||
(byte)(PlayerName.Length+1)
|
(byte)(PlayerName.Length+1)
|
||||||
};
|
};
|
||||||
|
|
@ -50,7 +42,10 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
|
|
||||||
// encoded names are followed by the name in plain text again
|
// encoded names are followed by the name in plain text again
|
||||||
// use the payload parsing for consistency, as this is technically a new chunk
|
// use the payload parsing for consistency, as this is technically a new chunk
|
||||||
bytes.AddRange(new TextPayload(PlayerName).Encode());
|
// bytes.AddRange(new TextPayload(PlayerName).Encode());
|
||||||
|
|
||||||
|
// FIXME
|
||||||
|
bytes.AddRange(Encoding.UTF8.GetBytes(PlayerName));
|
||||||
|
|
||||||
// unsure about this entire packet, but it seems to always follow a name
|
// unsure about this entire packet, but it seems to always follow a name
|
||||||
bytes.AddRange(new byte[]
|
bytes.AddRange(new byte[]
|
||||||
|
|
@ -65,7 +60,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"{Type} - PlayerName: {PlayerName}, ServerId: {ServerId}, ServerName: {ServerName}";
|
return $"{Type} - PlayerName: {PlayerName}, ServerId: {serverId}";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream)
|
protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream)
|
||||||
|
|
@ -73,7 +68,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
// unk
|
// unk
|
||||||
reader.ReadByte();
|
reader.ReadByte();
|
||||||
|
|
||||||
ServerId = GetInteger(reader);
|
this.serverId = GetInteger(reader);
|
||||||
|
|
||||||
// unk
|
// unk
|
||||||
reader.ReadBytes(2);
|
reader.ReadBytes(2);
|
||||||
|
|
|
||||||
|
|
@ -8,17 +8,13 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
{
|
{
|
||||||
public override PayloadType Type => PayloadType.Unknown;
|
public override PayloadType Type => PayloadType.Unknown;
|
||||||
|
|
||||||
public byte ChunkType { get; private set; }
|
|
||||||
public byte[] Data { get; private set; }
|
public byte[] Data { get; private set; }
|
||||||
|
|
||||||
|
private byte chunkType;
|
||||||
|
|
||||||
public RawPayload(byte chunkType)
|
public RawPayload(byte chunkType)
|
||||||
{
|
{
|
||||||
ChunkType = chunkType;
|
this.chunkType = chunkType;
|
||||||
}
|
|
||||||
|
|
||||||
public override void Resolve()
|
|
||||||
{
|
|
||||||
// nothing to do
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override byte[] Encode()
|
public override byte[] Encode()
|
||||||
|
|
@ -28,7 +24,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
var bytes = new List<byte>()
|
var bytes = new List<byte>()
|
||||||
{
|
{
|
||||||
START_BYTE,
|
START_BYTE,
|
||||||
ChunkType,
|
this.chunkType,
|
||||||
(byte)chunkLen
|
(byte)chunkLen
|
||||||
};
|
};
|
||||||
bytes.AddRange(Data);
|
bytes.AddRange(Data);
|
||||||
|
|
@ -40,7 +36,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"{Type} - Chunk type: {ChunkType:X}, Data: {BitConverter.ToString(Data).Replace("-", " ")}";
|
return $"{Type} - Chunk type: {chunkType:X}, Data: {BitConverter.ToString(Data).Replace("-", " ")}";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream)
|
protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream)
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
|
using Lumina.Excel.GeneratedSheets;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
{
|
{
|
||||||
|
|
@ -11,30 +9,21 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
{
|
{
|
||||||
public override PayloadType Type => PayloadType.Status;
|
public override PayloadType Type => PayloadType.Status;
|
||||||
|
|
||||||
public uint StatusId { get; private set; }
|
private Status status;
|
||||||
|
public Status Status
|
||||||
public string StatusName { get; private set; } = string.Empty;
|
|
||||||
|
|
||||||
public StatusPayload() { }
|
|
||||||
|
|
||||||
public StatusPayload(uint statusId)
|
|
||||||
{
|
{
|
||||||
StatusId = statusId;
|
get
|
||||||
}
|
|
||||||
|
|
||||||
public override void Resolve()
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(StatusName))
|
|
||||||
{
|
{
|
||||||
dynamic status = XivApi.Get($"Status/{StatusId}").GetAwaiter().GetResult();
|
status ??= this.dataResolver.GetExcelSheet<Status>().GetRow((int)this.statusId);
|
||||||
//Console.WriteLine($"Resolved status {StatusId} to {status.Name}");
|
return status;
|
||||||
StatusName = status.Name;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private uint statusId;
|
||||||
|
|
||||||
public override byte[] Encode()
|
public override byte[] Encode()
|
||||||
{
|
{
|
||||||
var idBytes = MakeInteger(StatusId);
|
var idBytes = MakeInteger(this.statusId);
|
||||||
|
|
||||||
var chunkLen = idBytes.Length + 7;
|
var chunkLen = idBytes.Length + 7;
|
||||||
var bytes = new List<byte>()
|
var bytes = new List<byte>()
|
||||||
|
|
@ -51,12 +40,12 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"{Type} - StatusId: {StatusId}, StatusName: {StatusName}";
|
return $"{Type} - StatusId: {statusId}";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream)
|
protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream)
|
||||||
{
|
{
|
||||||
StatusId = GetInteger(reader);
|
this.statusId = GetInteger(reader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
{
|
{
|
||||||
|
|
@ -11,36 +9,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
{
|
{
|
||||||
public override PayloadType Type => PayloadType.RawText;
|
public override PayloadType Type => PayloadType.RawText;
|
||||||
|
|
||||||
private string textConverted = null;
|
public string Text { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The Text of this text payload as an UTF-8 converted string.
|
|
||||||
/// Don't rely on this for accurate representation of SE payload data, please check RawData instead.
|
|
||||||
/// </summary>
|
|
||||||
public string Text {
|
|
||||||
get { return this.textConverted ??= Encoding.UTF8.GetString(RawData); }
|
|
||||||
set {
|
|
||||||
this.textConverted = value;
|
|
||||||
RawData = Encoding.UTF8.GetBytes(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The raw unconverted data of this text payload.
|
|
||||||
/// </summary>
|
|
||||||
public byte[] RawData { get; set; }
|
|
||||||
|
|
||||||
public TextPayload() { }
|
|
||||||
|
|
||||||
public TextPayload(string text)
|
|
||||||
{
|
|
||||||
Text = text;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Resolve()
|
|
||||||
{
|
|
||||||
// nothing to do
|
|
||||||
}
|
|
||||||
|
|
||||||
public override byte[] Encode()
|
public override byte[] Encode()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
using Lumina.Excel.GeneratedSheets;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
@ -8,15 +9,29 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
{
|
{
|
||||||
public override PayloadType Type => PayloadType.UIForeground;
|
public override PayloadType Type => PayloadType.UIForeground;
|
||||||
|
|
||||||
public ushort RawColor { get; private set; }
|
private UIColor color;
|
||||||
|
public UIColor UIColor
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
this.color ??= this.dataResolver.GetExcelSheet<UIColor>().GetRow(this.colorKey);
|
||||||
|
return this.color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//public int Red { get; private set; }
|
public uint RGB
|
||||||
//public int Green { get; private set; }
|
{
|
||||||
//public int Blue { get; private set; }
|
get
|
||||||
|
{
|
||||||
|
return UIColor.UIForeground;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ushort colorKey;
|
||||||
|
|
||||||
public override byte[] Encode()
|
public override byte[] Encode()
|
||||||
{
|
{
|
||||||
var colorBytes = MakeInteger(RawColor);
|
var colorBytes = MakeInteger(this.colorKey);
|
||||||
var chunkLen = colorBytes.Length + 1;
|
var chunkLen = colorBytes.Length + 1;
|
||||||
|
|
||||||
var bytes = new List<byte>(new byte[]
|
var bytes = new List<byte>(new byte[]
|
||||||
|
|
@ -30,19 +45,14 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
return bytes.ToArray();
|
return bytes.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Resolve()
|
|
||||||
{
|
|
||||||
// TODO: resolve color keys to hex colors via UIColor table
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"{Type} - RawColor: {RawColor}";
|
return $"{Type} - UIColor: {colorKey}";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream)
|
protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream)
|
||||||
{
|
{
|
||||||
RawColor = (ushort)GetInteger(reader);
|
this.colorKey = (ushort)GetInteger(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override byte GetMarkerForIntegerBytes(byte[] bytes)
|
protected override byte GetMarkerForIntegerBytes(byte[] bytes)
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
using Lumina.Excel.GeneratedSheets;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
@ -8,15 +9,29 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
{
|
{
|
||||||
public override PayloadType Type => PayloadType.UIGlow;
|
public override PayloadType Type => PayloadType.UIGlow;
|
||||||
|
|
||||||
public ushort RawColor { get; private set; }
|
private UIColor color;
|
||||||
|
public UIColor UIColor
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
this.color ??= this.dataResolver.GetExcelSheet<UIColor>().GetRow(this.colorKey);
|
||||||
|
return this.color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//public int Red { get; private set; }
|
public uint RGB
|
||||||
//public int Green { get; private set; }
|
{
|
||||||
//public int Blue { get; private set; }
|
get
|
||||||
|
{
|
||||||
|
return UIColor.UIGlow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ushort colorKey;
|
||||||
|
|
||||||
public override byte[] Encode()
|
public override byte[] Encode()
|
||||||
{
|
{
|
||||||
var colorBytes = MakeInteger(RawColor);
|
var colorBytes = MakeInteger(this.colorKey);
|
||||||
var chunkLen = colorBytes.Length + 1;
|
var chunkLen = colorBytes.Length + 1;
|
||||||
|
|
||||||
var bytes = new List<byte>(new byte[]
|
var bytes = new List<byte>(new byte[]
|
||||||
|
|
@ -30,19 +45,14 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
return bytes.ToArray();
|
return bytes.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Resolve()
|
|
||||||
{
|
|
||||||
// TODO: resolve color keys to hex colors via UIColor table
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"{Type} - RawColor: {RawColor}";
|
return $"{Type} - UIColor: {colorKey}";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream)
|
protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream)
|
||||||
{
|
{
|
||||||
RawColor = (ushort)GetInteger(reader);
|
this.colorKey = (ushort)GetInteger(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override byte GetMarkerForIntegerBytes(byte[] bytes)
|
protected override byte GetMarkerForIntegerBytes(byte[] bytes)
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Dalamud.Data;
|
|
||||||
using Dalamud.Game.Chat.SeStringHandling.Payloads;
|
using Dalamud.Game.Chat.SeStringHandling.Payloads;
|
||||||
|
|
||||||
namespace Dalamud.Game.Chat.SeStringHandling
|
namespace Dalamud.Game.Chat.SeStringHandling
|
||||||
|
|
@ -14,6 +11,9 @@ namespace Dalamud.Game.Chat.SeStringHandling
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SeString
|
public class SeString
|
||||||
{
|
{
|
||||||
|
// TODO: probably change how this is done/where it comes from
|
||||||
|
public static Dalamud Dalamud { get; internal set; }
|
||||||
|
|
||||||
public List<Payload> Payloads { get; }
|
public List<Payload> Payloads { get; }
|
||||||
|
|
||||||
public SeString(List<Payload> payloads)
|
public SeString(List<Payload> payloads)
|
||||||
|
|
@ -37,6 +37,11 @@ namespace Dalamud.Game.Chat.SeStringHandling
|
||||||
{
|
{
|
||||||
sb.Append(((TextPayload)p).Text);
|
sb.Append(((TextPayload)p).Text);
|
||||||
}
|
}
|
||||||
|
// TODO: temporary (probably)
|
||||||
|
else if (p.Type == PayloadType.AutoTranslateText)
|
||||||
|
{
|
||||||
|
sb.Append($"{{ {((AutoTranslatePayload)p).Text} }}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
|
|
@ -52,9 +57,9 @@ namespace Dalamud.Game.Chat.SeStringHandling
|
||||||
{
|
{
|
||||||
var payloads = new List<Payload>();
|
var payloads = new List<Payload>();
|
||||||
|
|
||||||
using (var stream = new MemoryStream(bytes)) {
|
using (var stream = new MemoryStream(bytes))
|
||||||
using var reader = new BinaryReader(stream);
|
using (var reader = new BinaryReader(stream))
|
||||||
|
{
|
||||||
while (stream.Position < bytes.Length)
|
while (stream.Position < bytes.Length)
|
||||||
{
|
{
|
||||||
var payload = Payload.Process(reader);
|
var payload = Payload.Process(reader);
|
||||||
|
|
|
||||||
|
|
@ -181,14 +181,14 @@ namespace Dalamud.Game {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Debug($"Probable retainer sale: {message}, decoded item {itemLink.ItemId}, HQ {itemLink.IsHQ}");
|
Log.Debug($"Probable retainer sale: {message}, decoded item {itemLink.Item.RowId}, HQ {itemLink.IsHQ}");
|
||||||
|
|
||||||
var valueInfo = matchInfo.Groups["value"];
|
var valueInfo = matchInfo.Groups["value"];
|
||||||
// not sure if using a culture here would work correctly, so just strip symbols instead
|
// not sure if using a culture here would work correctly, so just strip symbols instead
|
||||||
if (!valueInfo.Success || !int.TryParse(valueInfo.Value.Replace(",", "").Replace(".", ""), out var itemValue))
|
if (!valueInfo.Success || !int.TryParse(valueInfo.Value.Replace(",", "").Replace(".", ""), out var itemValue))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Task.Run(() => this.dalamud.BotManager.ProcessRetainerSale((int)itemLink.ItemId, itemValue, itemLink.IsHQ));
|
Task.Run(() => this.dalamud.BotManager.ProcessRetainerSale((int)itemLink.Item.RowId, itemValue, itemLink.IsHQ));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -112,8 +112,8 @@ namespace Dalamud.Game.Internal.Gui {
|
||||||
if (!FastByteArrayCompare(oldEdited, newEdited)) {
|
if (!FastByteArrayCompare(oldEdited, newEdited)) {
|
||||||
Log.Verbose("SeString was edited, taking precedence over StdString edit.");
|
Log.Verbose("SeString was edited, taking precedence over StdString edit.");
|
||||||
message.RawData = newEdited;
|
message.RawData = newEdited;
|
||||||
}
|
Log.Debug($"\nOLD: {BitConverter.ToString(originalMessageData)}\nNEW: {BitConverter.ToString(newEdited)}");
|
||||||
Log.Debug($"\nOLD: {BitConverter.ToString(originalMessageData)}\nNEW: {BitConverter.ToString(newEdited)}");
|
}
|
||||||
|
|
||||||
var messagePtr = pMessage;
|
var messagePtr = pMessage;
|
||||||
OwnedStdString allocatedString = null;
|
OwnedStdString allocatedString = null;
|
||||||
|
|
|
||||||
|
|
@ -151,8 +151,7 @@ namespace Dalamud.Game.Internal.Gui {
|
||||||
openMapWithFlag =
|
openMapWithFlag =
|
||||||
Address.GetVirtualFunction<OpenMapWithFlagDelegate>(uiMapObjectPtr, 0, 63);
|
Address.GetVirtualFunction<OpenMapWithFlagDelegate>(uiMapObjectPtr, 0, 63);
|
||||||
|
|
||||||
var mapLinkString =
|
var mapLinkString = mapLink.DataString;
|
||||||
$"m:{mapLink.TerritoryTypeId},{mapLink.MapId},{unchecked((int)mapLink.RawX)},{unchecked((int)mapLink.RawY)}";
|
|
||||||
|
|
||||||
Log.Debug($"OpenMapWithMapLink: Opening Map Link: {mapLinkString}");
|
Log.Debug($"OpenMapWithMapLink: Opening Map Link: {mapLinkString}");
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue