diff --git a/Core/Chat/ChatReader.cs b/Core/Chat/ChatReader.cs new file mode 100644 index 000000000..970bd5a14 --- /dev/null +++ b/Core/Chat/ChatReader.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.ObjectModel; +using System.Text; + +namespace Core; + +public enum ChatMessageType +{ + Whisper, + Say, + Yell, + Emote, + Party +} + +public readonly record struct ChatMessageEntry(DateTime Time, ChatMessageType Type, string Author, string Message); + +public sealed class ChatReader : IReader +{ + private const int cMsg = 98; + private const int cMeta = 99; + + public ObservableCollection Messages { get; } = new(); + + // 12 character name + // 1 space + // 256 maximum message length + private readonly StringBuilder sb = new(12 + 1 + 256); + + private int _head; + + public void Update(IAddonDataProvider reader) + { + int meta = reader.GetInt(cMeta); + if (meta == 0) + { + _head = 0; + return; + } + + ChatMessageType type = (ChatMessageType)(meta / 1000000); + int length = meta % 1000000 / 1000; + int head = meta % 1000; + + if (_head != head) + _head = head; + else if (_head == head) + return; + + string part = reader.GetString(cMsg).Replace('@', ' '); + + sb.Append(part); + + if (head + 2 < length) + return; + + string text = sb.ToString().ToLowerInvariant(); + sb.Clear(); + + int firstSpaceIdx = text.IndexOf(" "); + string author = text.AsSpan(0, firstSpaceIdx).ToString(); + text = text.AsSpan(firstSpaceIdx).ToString(); + + Messages.Add(new(DateTime.Now, type, author, text)); + } +} diff --git a/Core/DependencyInjection.cs b/Core/DependencyInjection.cs index a890812d2..3a573047f 100644 --- a/Core/DependencyInjection.cs +++ b/Core/DependencyInjection.cs @@ -47,6 +47,7 @@ public static IServiceCollection AddAddonComponents( s.ForwardSingleton(); s.ForwardSingleton(); s.ForwardSingleton(); + s.ForwardSingleton(); s.ForwardSingleton(); s.ForwardSingleton(); @@ -123,6 +124,7 @@ public static IServiceCollection AddStartupIoC( s.ForwardSingleton(sp); s.ForwardSingleton(sp); s.ForwardSingleton(sp); + s.ForwardSingleton(sp); s.ForwardSingleton(sp); s.ForwardSingleton(sp); diff --git a/Frontend/Pages/Chat.razor b/Frontend/Pages/Chat.razor new file mode 100644 index 000000000..ffbcd0276 --- /dev/null +++ b/Frontend/Pages/Chat.razor @@ -0,0 +1,2 @@ +@page "/Chat" + \ No newline at end of file diff --git a/Frontend/Pages/ChatComponent.razor b/Frontend/Pages/ChatComponent.razor new file mode 100644 index 000000000..fd0b87fb7 --- /dev/null +++ b/Frontend/Pages/ChatComponent.razor @@ -0,0 +1,55 @@ +@using System.Collections.Specialized + +@implements IDisposable + +@inject ChatReader reader + + + +
+ + @foreach (var cme in reader.Messages.Reverse()) + { + + + + + + } +
@cme.Time.ToString("HH:mm:ss")@cme.Author:@cme.Message
+
+ +@code { + [Parameter] + public int MaxHeight { get; set; } = 400; + + private static readonly string[] typeColor = { + "pink", // ChatMessageType.Whisper + "white", // ChatMessageType.Say + "red", // ChatMessageType.Yell + "orange", // ChatMessageType.Emote + "cyan", // ChatMessageType.Party + }; + + protected override void OnInitialized() + { + reader.Messages.CollectionChanged += Changed; + } + + public void Dispose() + { + reader.Messages.CollectionChanged -= Changed; + } + + private void Changed(object? s, NotifyCollectionChangedEventArgs e) + { + base.InvokeAsync(StateHasChanged); + } +} \ No newline at end of file diff --git a/Frontend/Pages/Index.razor b/Frontend/Pages/Index.razor index 5ec3a3801..06aa35b07 100644 --- a/Frontend/Pages/Index.razor +++ b/Frontend/Pages/Index.razor @@ -24,6 +24,11 @@ + + + + + diff --git a/Frontend/Shared/NavMenu.razor b/Frontend/Shared/NavMenu.razor index 95bde0bd8..4dc266833 100644 --- a/Frontend/Shared/NavMenu.razor +++ b/Frontend/Shared/NavMenu.razor @@ -90,6 +90,12 @@ Frame Config +