servicepoint-tanks/tanks-backend/TanksServer/Interactivity/PlayerInfoConnection.cs
2024-05-06 00:38:18 +02:00

88 lines
2.6 KiB
C#

using System.Buffers;
using System.IO;
using System.Net.WebSockets;
using System.Text.Json;
using TanksServer.GameLogic;
namespace TanksServer.Interactivity;
internal sealed class PlayerInfoConnection
: DroppablePackageRequestConnection<IMemoryOwner<byte>>
{
private readonly Player _player;
private readonly MapEntityManager _entityManager;
private readonly BufferPool _bufferPool;
private readonly MemoryStream _tempStream = new();
private IMemoryOwner<byte>? _lastMessage = null;
public PlayerInfoConnection(
Player player,
ILogger logger,
WebSocket rawSocket,
MapEntityManager entityManager,
BufferPool bufferPool
) : base(logger, new ByteChannelWebSocket(rawSocket, logger, 0))
{
_player = player;
_entityManager = entityManager;
_bufferPool = bufferPool;
_player.IncrementConnectionCount();
}
public async Task OnGameTickAsync()
{
await Task.Yield();
var response = await GenerateMessageAsync();
if (response != null)
SetNextPackage(response);
}
public override void Dispose()
{
base.Dispose();
_player.DecrementConnectionCount();
}
private async ValueTask<IMemoryOwner<byte>?> GenerateMessageAsync()
{
var tank = _entityManager.GetCurrentTankOfPlayer(_player);
TankInfo? tankInfo = null;
if (tank != null)
{
var magazine = tank.ReloadingUntil > DateTime.Now ? "[ RELOADING ]" : tank.Magazine.ToDisplayString();
tankInfo = new TankInfo(tank.Orientation, magazine, tank.Position.ToPixelPosition(), tank.Moving);
}
var info = new PlayerInfo(
_player.Name,
_player.Scores,
_player.Controls.ToDisplayString(),
tankInfo,
_player.OpenConnections);
_tempStream.Position = 0;
await JsonSerializer.SerializeAsync(_tempStream, info, AppSerializerContext.Default.PlayerInfo);
var messageLength = (int)_tempStream.Position;
var owner = _bufferPool.Rent(messageLength);
_tempStream.Position = 0;
await _tempStream.ReadExactlyAsync(owner.Memory);
if (_lastMessage == null || !owner.Memory.Span.SequenceEqual(_lastMessage.Memory.Span))
return owner;
owner.Dispose();
return null;
}
protected override async ValueTask SendPackageAsync(IMemoryOwner<byte> data)
{
await Socket.SendTextAsync(data.Memory);
Interlocked.Exchange(ref _lastMessage, data)?.Dispose();
}
}