139 lines
2.6 KiB
Plaintext
139 lines
2.6 KiB
Plaintext
@using System;
|
||
@using Sandbox.UI;
|
||
@namespace Sandbox
|
||
@inherits PanelComponent
|
||
@implements Component.INetworkListener
|
||
<root>
|
||
|
||
<div class="output">
|
||
@foreach (var entry in Entries)
|
||
{
|
||
<div class="chat_entry">
|
||
@if (entry.steamid > 0)
|
||
{
|
||
<div class="avatar" style="background-image: url( avatar:@entry.steamid )"></div>
|
||
}
|
||
<div class="author">@entry.author</div>
|
||
<div class="message">@entry.message</div>
|
||
</div>
|
||
}
|
||
</div>
|
||
|
||
<div class="input">
|
||
<TextEntry @ref="InputBox" onsubmit="@ChatFinished"></TextEntry>
|
||
</div>
|
||
|
||
</root>
|
||
|
||
@code
|
||
{
|
||
|
||
public static Chat Instance;
|
||
public Chat() => Instance = this;
|
||
public static bool IsActive => Instance.InputBox.HasFocus;
|
||
|
||
public static void Open()
|
||
{
|
||
Instance.InputBox.Focus();
|
||
}
|
||
|
||
public static void AddText(string text)
|
||
{
|
||
Instance.AddTextInternal(text);
|
||
}
|
||
|
||
public event Action<string> OnChat;
|
||
public TextEntry InputBox;
|
||
|
||
public record Entry(ulong steamid, string author, string message, RealTimeSince timeSinceAdded);
|
||
List<Entry> Entries = new();
|
||
|
||
protected override void OnUpdate()
|
||
{
|
||
if (InputBox is null)
|
||
return;
|
||
|
||
Panel.AcceptsFocus = false;
|
||
|
||
if (Input.Pressed("chat"))
|
||
Open();
|
||
|
||
if (Entries.RemoveAll(x => x.timeSinceAdded > 20.0f) > 0)
|
||
{
|
||
StateHasChanged();
|
||
}
|
||
|
||
if (InputBox.HasFocus && Input.EscapePressed)
|
||
{
|
||
Input.EscapePressed = false;
|
||
ChatClosed();
|
||
}
|
||
|
||
SetClass("open", InputBox.HasFocus);
|
||
}
|
||
|
||
void ChatFinished()
|
||
{
|
||
var text = InputBox.Text;
|
||
Mouse.Visibility = MouseVisibility.Auto;
|
||
|
||
OnChat?.Invoke(text);
|
||
OnChat = null;
|
||
if (string.IsNullOrWhiteSpace(text))
|
||
return;
|
||
|
||
AddTextInternal(InputBox.Text);
|
||
InputBox.Text = "";
|
||
}
|
||
|
||
void ChatClosed()
|
||
{
|
||
var text = InputBox.Text;
|
||
InputBox.Text = "";
|
||
OnChat = null;
|
||
}
|
||
|
||
[Rpc.Broadcast]
|
||
public void AddTextInternal(string message)
|
||
{
|
||
message = message.Truncate(300);
|
||
|
||
if (string.IsNullOrWhiteSpace(message))
|
||
return;
|
||
|
||
var author = Rpc.Caller.DisplayName;
|
||
var steamid = Rpc.Caller.SteamId;
|
||
|
||
Log.Info($"{author}: {message}");
|
||
|
||
Entries.Add(new Entry(steamid, author, message, 0.0f));
|
||
StateHasChanged();
|
||
}
|
||
|
||
[Rpc.Broadcast]
|
||
void AddSystemText(string message)
|
||
{
|
||
message = message.Truncate(300);
|
||
|
||
if (string.IsNullOrWhiteSpace(message))
|
||
return;
|
||
|
||
Entries.Add(new Entry(0, "ℹ️", message, 0.0f));
|
||
StateHasChanged();
|
||
}
|
||
|
||
void Component.INetworkListener.OnConnected(Connection channel)
|
||
{
|
||
if (IsProxy) return;
|
||
|
||
AddSystemText($"{channel.DisplayName} has joined the game");
|
||
}
|
||
|
||
void Component.INetworkListener.OnDisconnected(Connection channel)
|
||
{
|
||
if (IsProxy) return;
|
||
|
||
AddSystemText($"{channel.DisplayName} has left the game");
|
||
}
|
||
}
|