mirror of
https://github.com/gwdevhub/Daybreak.git
synced 2026-07-15 15:19:57 +00:00
97fed608d2
* 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>
84 lines
3.1 KiB
C#
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);
|
|
}
|
|
}
|