Files
Daybreak/Daybreak.API/Services/ChatService.cs
T
amacocian 97fed608d2 Update GWCA (#1484)
* Improve GWCA bindings generator based on headers

* Move all structs to gwca

* Progress

* Complete parser work

* More generator adjustments

* GWCA fixes

* GWCA improvements

* GWCA fixes

* GWCA fixes

* GWCA fixes

* GWCA fixes

* Fix API usage of GWCA

* Update GWCA

---------

Co-authored-by: Alexandru Macocian <amacocian@microsoft.com>
2026-02-26 14:13:40 -08:00

84 lines
3.1 KiB
C#

using Daybreak.API.Interop;
using Daybreak.API.Interop.GuildWars;
using Daybreak.API.Services.Interop;
using System.Core.Extensions;
using System.Extensions;
namespace Daybreak.API.Services;
public sealed class ChatService(
InstanceContextService instanceContextService,
GameThreadService gameThreadService,
UIContextService uiContextService)
{
private readonly SemaphoreSlim semaphoreSlim = new(1);
private readonly InstanceContextService instanceContextService = instanceContextService.ThrowIfNull();
private readonly GameThreadService gameThreadService = gameThreadService.ThrowIfNull();
private readonly UIContextService uiContextService = uiContextService.ThrowIfNull();
/// <summary>
/// Adds a message to the chat. It does not send the message, it only shows it to the player.
/// </summary>
public async ValueTask AddMessageAsync(string message, string? sender, Channel channel, CancellationToken cancellationToken)
{
using var ctx = await this.semaphoreSlim.Acquire(cancellationToken);
await this.gameThreadService.QueueOnGameThread(() =>
{
if (this.instanceContextService.GetInstanceType() is InstanceType.Loading)
{
return;
}
var encodedMessage = string.Create(
3 + message.Length,
message,
static (span, msg) =>
{
span[0] = '\u0108';
span[1] = '\u0107';
msg.AsSpan().CopyTo(span[2..]);
span[^1] = '\u0001';
});
var encodedSender = sender is not null
? string.Create(
3 + sender.Length,
sender,
static (span, msg) =>
{
span[0] = '\u0108';
span[1] = '\u0107';
msg.AsSpan().CopyTo(span[2..]);
span[^1] = '\u0001';
})
: default;
var encoded = encodedSender is null
? encodedMessage
: string.Create(
encodedMessage.Length + encodedSender.Length + 6,
(encodedMessage, encodedSender),
static (span, state) =>
{
span[0] = '\u076b';
span[1] = '\u010a';
state.encodedSender.AsSpan().CopyTo(span[2..]);
span[2 + state.encodedSender.Length] = '\u0001';
span[3 + state.encodedSender.Length] = '\u010b';
state.encodedMessage.AsSpan().CopyTo(span[(4 + state.encodedSender.Length)..]);
span[^2] = '\u0001';
});
unsafe
{
fixed (char* encodedPtr = encoded)
{
using var packet = new UnmanagedStruct<kPrintChatMessage>(new kPrintChatMessage { Channel = (GWCA.GW.Chat.Channel)channel, Message = (nint)encodedPtr });
this.uiContextService.SendMessage(UIMessage.kWriteToChatLog, (nuint)packet.Address, 0x0);
}
}
}, cancellationToken);
}
}