Display emote name if loading failed

This commit is contained in:
Infi
2024-05-14 00:44:06 +02:00
parent 26e993be67
commit 0de883ec39
4 changed files with 63 additions and 50 deletions
+1 -1
View File
@@ -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
View File
@@ -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}");
} }
} }
+9 -2
View File
@@ -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,8 +1557,11 @@ 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 })
{
if (image.IsLoaded)
image.Draw(emoteSize); image.Draw(emoteSize);
else else
ImGui.Dummy(emoteSize); ImGui.Dummy(emoteSize);
@@ -1565,6 +1571,7 @@ public sealed class ChatLogWindow : Window
return; return;
} }
}
var colour = text.Foreground; var colour = text.Foreground;
if (colour == null && text.FallbackColour != null) if (colour == null && text.FallbackColour != null)
+35 -31
View File
@@ -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);
} }