Display emote name if loading failed
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Version>1.24.3</Version>
|
<Version>1.24.4</Version>
|
||||||
<TargetFramework>net8.0-windows</TargetFramework>
|
<TargetFramework>net8.0-windows</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|||||||
+12
-10
@@ -11,6 +11,13 @@ namespace ChatTwo;
|
|||||||
|
|
||||||
public static class EmoteCache
|
public static class EmoteCache
|
||||||
{
|
{
|
||||||
|
private static readonly HttpClient Client = new();
|
||||||
|
|
||||||
|
private const string BetterTTV = "https://api.betterttv.net/3";
|
||||||
|
private const string GlobalEmotes = $"{BetterTTV}/cached/emotes/global";
|
||||||
|
private const string Top100Emotes = "{0}/emotes/shared/top?before={1}&limit=100";
|
||||||
|
private const string EmotePath = "https://cdn.betterttv.net/emote/{0}/1x";
|
||||||
|
|
||||||
private struct Top100
|
private struct Top100
|
||||||
{
|
{
|
||||||
[JsonPropertyName("emote")]
|
[JsonPropertyName("emote")]
|
||||||
@@ -37,18 +44,11 @@ public static class EmoteCache
|
|||||||
Done
|
Done
|
||||||
}
|
}
|
||||||
|
|
||||||
private const string BetterTTV = "https://api.betterttv.net/3";
|
|
||||||
private const string GlobalEmotes = $"{BetterTTV}/cached/emotes/global";
|
|
||||||
private const string Top100Emotes = "{0}/emotes/shared/top?before={1}&limit=100";
|
|
||||||
private const string EmotePath = "https://cdn.betterttv.net/emote/{0}/1x";
|
|
||||||
|
|
||||||
private static readonly HttpClient Client = new();
|
|
||||||
|
|
||||||
// All of this data is uninitalized while State is not `LoadingState.Done`
|
// All of this data is uninitalized while State is not `LoadingState.Done`
|
||||||
public static LoadingState State = LoadingState.Unloaded;
|
public static LoadingState State = LoadingState.Unloaded;
|
||||||
private static Dictionary<string, IEmote> EmoteImages = new();
|
|
||||||
|
|
||||||
private static Dictionary<string, Emote> Cache = new();
|
private static readonly Dictionary<string, Emote> Cache = new();
|
||||||
|
private static readonly Dictionary<string, IEmote> EmoteImages = new();
|
||||||
|
|
||||||
public static string[] SortedCodeArray = [];
|
public static string[] SortedCodeArray = [];
|
||||||
|
|
||||||
@@ -127,9 +127,9 @@ public static class EmoteCache
|
|||||||
|
|
||||||
public class IEmote
|
public class IEmote
|
||||||
{
|
{
|
||||||
|
public bool Failed;
|
||||||
public bool IsLoaded;
|
public bool IsLoaded;
|
||||||
|
|
||||||
public bool IsAnimated = false;
|
|
||||||
public IDalamudTextureWrap Texture;
|
public IDalamudTextureWrap Texture;
|
||||||
|
|
||||||
public virtual void Draw(Vector2 size)
|
public virtual void Draw(Vector2 size)
|
||||||
@@ -182,6 +182,7 @@ public static class EmoteCache
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
Failed = true;
|
||||||
Plugin.Log.Error(ex, $"Unable to load {emote.Code} with id {emote.Id}");
|
Plugin.Log.Error(ex, $"Unable to load {emote.Code} with id {emote.Id}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -271,6 +272,7 @@ public static class EmoteCache
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
Failed = true;
|
||||||
Plugin.Log.Error(ex, $"Unable to load {emote.Code} with id {emote.Id}");
|
Plugin.Log.Error(ex, $"Unable to load {emote.Code} with id {emote.Id}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1513,8 +1513,11 @@ public sealed class ChatLogWindow : Window
|
|||||||
DrawChunk(chunks[i], wrap, handler, lineWidth);
|
DrawChunk(chunks[i], wrap, handler, lineWidth);
|
||||||
|
|
||||||
if (i < chunks.Count - 1)
|
if (i < chunks.Count - 1)
|
||||||
|
{
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
else if (chunks[i].Link is EmotePayload && Plugin.Config.ShowEmotes) {
|
}
|
||||||
|
else if (chunks[i].Link is EmotePayload && Plugin.Config.ShowEmotes)
|
||||||
|
{
|
||||||
// Emote payloads seem to not automatically put newlines, which
|
// Emote payloads seem to not automatically put newlines, which
|
||||||
// is an issue when modern mode is disabled.
|
// is an issue when modern mode is disabled.
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
@@ -1554,16 +1557,20 @@ public sealed class ChatLogWindow : Window
|
|||||||
var emoteSize = ImGui.CalcTextSize("W");
|
var emoteSize = ImGui.CalcTextSize("W");
|
||||||
emoteSize = emoteSize with { Y = emoteSize.X } * 1.5f;
|
emoteSize = emoteSize with { Y = emoteSize.X } * 1.5f;
|
||||||
|
|
||||||
|
// We only draw a dummy if it is still loading, in the case it failed we draw the actual name
|
||||||
var image = EmoteCache.GetEmote(emotePayload.Code);
|
var image = EmoteCache.GetEmote(emotePayload.Code);
|
||||||
if (image is { IsLoaded: true })
|
if (image is { Failed: false })
|
||||||
image.Draw(emoteSize);
|
{
|
||||||
else
|
if (image.IsLoaded)
|
||||||
ImGui.Dummy(emoteSize);
|
image.Draw(emoteSize);
|
||||||
|
else
|
||||||
|
ImGui.Dummy(emoteSize);
|
||||||
|
|
||||||
if (ImGui.IsItemHovered())
|
if (ImGui.IsItemHovered())
|
||||||
ImGui.SetTooltip(emotePayload.Code);
|
ImGui.SetTooltip(emotePayload.Code);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var colour = text.Foreground;
|
var colour = text.Foreground;
|
||||||
|
|||||||
+35
-31
@@ -5,8 +5,10 @@ using System.Text;
|
|||||||
|
|
||||||
namespace ChatTwo.Util;
|
namespace ChatTwo.Util;
|
||||||
|
|
||||||
internal static class ChunkUtil {
|
internal static class ChunkUtil
|
||||||
internal static IEnumerable<Chunk> ToChunks(SeString msg, ChunkSource source, ChatType? defaultColour) {
|
{
|
||||||
|
internal static IEnumerable<Chunk> ToChunks(SeString msg, ChunkSource source, ChatType? defaultColour)
|
||||||
|
{
|
||||||
var chunks = new List<Chunk>();
|
var chunks = new List<Chunk>();
|
||||||
|
|
||||||
var italic = false;
|
var italic = false;
|
||||||
@@ -14,8 +16,10 @@ internal static class ChunkUtil {
|
|||||||
var glow = new Stack<uint>();
|
var glow = new Stack<uint>();
|
||||||
Payload? link = null;
|
Payload? link = null;
|
||||||
|
|
||||||
void Append(string text) {
|
void Append(string text)
|
||||||
chunks.Add(new TextChunk(source, link, text) {
|
{
|
||||||
|
chunks.Add(new TextChunk(source, link, text)
|
||||||
|
{
|
||||||
FallbackColour = defaultColour,
|
FallbackColour = defaultColour,
|
||||||
Foreground = foreground.Count > 0 ? foreground.Peek() : null,
|
Foreground = foreground.Count > 0 ? foreground.Peek() : null,
|
||||||
Glow = glow.Count > 0 ? glow.Peek() : null,
|
Glow = glow.Count > 0 ? glow.Peek() : null,
|
||||||
@@ -23,29 +27,27 @@ internal static class ChunkUtil {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var payload in msg.Payloads) {
|
foreach (var payload in msg.Payloads)
|
||||||
switch (payload.Type) {
|
{
|
||||||
|
switch (payload.Type)
|
||||||
|
{
|
||||||
case PayloadType.EmphasisItalic:
|
case PayloadType.EmphasisItalic:
|
||||||
var newStatus = ((EmphasisItalicPayload) payload).IsEnabled;
|
var newStatus = ((EmphasisItalicPayload) payload).IsEnabled;
|
||||||
italic = newStatus;
|
italic = newStatus;
|
||||||
break;
|
break;
|
||||||
case PayloadType.UIForeground:
|
case PayloadType.UIForeground:
|
||||||
var foregroundPayload = (UIForegroundPayload) payload;
|
var foregroundPayload = (UIForegroundPayload) payload;
|
||||||
if (foregroundPayload.IsEnabled) {
|
if (foregroundPayload.IsEnabled)
|
||||||
foreground.Push(foregroundPayload.UIColor.UIForeground);
|
foreground.Push(foregroundPayload.UIColor.UIForeground);
|
||||||
} else if (foreground.Count > 0) {
|
else if (foreground.Count > 0)
|
||||||
foreground.Pop();
|
foreground.Pop();
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case PayloadType.UIGlow:
|
case PayloadType.UIGlow:
|
||||||
var glowPayload = (UIGlowPayload) payload;
|
var glowPayload = (UIGlowPayload) payload;
|
||||||
if (glowPayload.IsEnabled) {
|
if (glowPayload.IsEnabled)
|
||||||
glow.Push(glowPayload.UIColor.UIGlow);
|
glow.Push(glowPayload.UIColor.UIGlow);
|
||||||
} else if (glow.Count > 0) {
|
else if (glow.Count > 0)
|
||||||
glow.Pop();
|
glow.Pop();
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case PayloadType.AutoTranslateText:
|
case PayloadType.AutoTranslateText:
|
||||||
chunks.Add(new IconChunk(source, link, BitmapFontIcon.AutoTranslateBegin));
|
chunks.Add(new IconChunk(source, link, BitmapFontIcon.AutoTranslateBegin));
|
||||||
@@ -86,7 +88,8 @@ internal static class ChunkUtil {
|
|||||||
}
|
}
|
||||||
else if (rawPayload.Data.Length > 1 && rawPayload.Data[1] == 0x14)
|
else if (rawPayload.Data.Length > 1 && rawPayload.Data[1] == 0x14)
|
||||||
{
|
{
|
||||||
if (glow.Count > 0) {
|
if (glow.Count > 0)
|
||||||
|
{
|
||||||
glow.Pop();
|
glow.Pop();
|
||||||
}
|
}
|
||||||
else if (rawPayload.Data.Length > 6 && rawPayload.Data[2] == 0x05 && rawPayload.Data[3] == 0xF6)
|
else if (rawPayload.Data.Length > 6 && rawPayload.Data[2] == 0x05 && rawPayload.Data[3] == 0xF6)
|
||||||
@@ -95,30 +98,34 @@ internal static class ChunkUtil {
|
|||||||
glow.Push(ColourUtil.ComponentsToRgba(r, g, b));
|
glow.Push(ColourUtil.ComponentsToRgba(r, g, b));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (rawPayload.Data.Length > 7 && rawPayload.Data[1] == 0x27 && rawPayload.Data[3] == 0x0A) {
|
else if (rawPayload.Data.Length > 7 && rawPayload.Data[1] == 0x27 && rawPayload.Data[3] == 0x0A)
|
||||||
|
{
|
||||||
// pf payload
|
// pf payload
|
||||||
var reader = new BinaryReader(new MemoryStream(rawPayload.Data[4..]));
|
var reader = new BinaryReader(new MemoryStream(rawPayload.Data[4..]));
|
||||||
var id = GetInteger(reader);
|
var id = GetInteger(reader);
|
||||||
link = new PartyFinderPayload(id);
|
link = new PartyFinderPayload(id);
|
||||||
} else if (rawPayload.Data.Length > 5 && rawPayload.Data[1] == 0x27 && rawPayload.Data[3] == 0x06) {
|
}
|
||||||
|
else if (rawPayload.Data.Length > 5 && rawPayload.Data[1] == 0x27 && rawPayload.Data[3] == 0x06)
|
||||||
|
{
|
||||||
// achievement payload
|
// achievement payload
|
||||||
var reader = new BinaryReader(new MemoryStream(rawPayload.Data[4..]));
|
var reader = new BinaryReader(new MemoryStream(rawPayload.Data[4..]));
|
||||||
var id = GetInteger(reader);
|
var id = GetInteger(reader);
|
||||||
link = new AchievementPayload(id);
|
link = new AchievementPayload(id);
|
||||||
} else if (rawPayload.Data.Length > 5 && rawPayload.Data[1] == 0x27 && rawPayload.Data[3] == 0x07) {
|
}
|
||||||
|
else if (rawPayload.Data.Length > 5 && rawPayload.Data[1] == 0x27 && rawPayload.Data[3] == 0x07)
|
||||||
|
{
|
||||||
// uri payload
|
// uri payload
|
||||||
var uri = new Uri(Encoding.UTF8.GetString(rawPayload.Data[4..]));
|
var uri = new Uri(Encoding.UTF8.GetString(rawPayload.Data[4..]));
|
||||||
link = new UriPayload(uri);
|
link = new UriPayload(uri);
|
||||||
} else if (Equals(rawPayload, RawPayload.LinkTerminator)) {
|
}
|
||||||
|
else if (Equals(rawPayload, RawPayload.LinkTerminator))
|
||||||
|
{
|
||||||
link = null;
|
link = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (payload is ITextProvider textProvider) {
|
if (payload is ITextProvider textProvider)
|
||||||
Append(textProvider.Text);
|
Append(textProvider.Text);
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,21 +133,18 @@ internal static class ChunkUtil {
|
|||||||
return chunks;
|
return chunks;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static readonly RawPayload PeriodicRecruitmentLink = new(new byte[] {
|
internal static readonly RawPayload PeriodicRecruitmentLink = new([0x02, 0x27, 0x07, 0x08, 0x01, 0x01, 0x01, 0xFF, 0x01, 0x03]);
|
||||||
0x02, 0x27, 0x07, 0x08, 0x01, 0x01, 0x01, 0xFF, 0x01, 0x03,
|
|
||||||
});
|
|
||||||
|
|
||||||
private static uint GetInteger(BinaryReader input) {
|
private static uint GetInteger(BinaryReader input)
|
||||||
|
{
|
||||||
var num1 = (uint) input.ReadByte();
|
var num1 = (uint) input.ReadByte();
|
||||||
if (num1 < 208U) {
|
if (num1 < 208U)
|
||||||
return num1 - 1U;
|
return num1 - 1U;
|
||||||
}
|
|
||||||
|
|
||||||
var num2 = (uint) ((int) num1 + 1 & 15);
|
var num2 = (uint) ((int) num1 + 1 & 15);
|
||||||
var numArray = new byte[4];
|
var numArray = new byte[4];
|
||||||
for (var index = 3; index >= 0; --index) {
|
for (var index = 3; index >= 0; --index)
|
||||||
numArray[index] = (num2 & 1 << index) == 0L ? (byte) 0 : input.ReadByte();
|
numArray[index] = (num2 & 1 << index) == 0L ? (byte) 0 : input.ReadByte();
|
||||||
}
|
|
||||||
|
|
||||||
return BitConverter.ToUInt32(numArray, 0);
|
return BitConverter.ToUInt32(numArray, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user