servicepoint-tanks/tanks-backend/TanksServer/Interactivity/ClientScreenServerConnection.cs
2024-04-28 15:34:32 +02:00

74 lines
2.1 KiB
C#

using System.Net.WebSockets;
using DisplayCommands;
using TanksServer.Graphics;
namespace TanksServer.Interactivity;
internal sealed class ClientScreenServerConnection(
WebSocket webSocket,
ILogger<ClientScreenServerConnection> logger,
string? playerName = null
) : WebsocketServerConnection(logger, new ByteChannelWebSocket(webSocket, logger, 0))
{
private bool _wantsFrameOnTick = true;
private PixelGrid? _lastSentPixels;
private PixelGrid? _nextPixels;
private readonly PlayerScreenData? _nextPlayerData = playerName != null ? new PlayerScreenData(logger) : null;
protected override async ValueTask HandleMessageLockedAsync(Memory<byte> _)
{
if (_nextPixels == null)
{
_wantsFrameOnTick = true;
return;
}
await SendNowAsync();
}
public ValueTask OnGameTickAsync(PixelGrid pixels, GamePixelGrid gamePixelGrid) => LockedAsync(async () =>
{
if (pixels == _lastSentPixels)
return;
if (_nextPlayerData != null)
{
_nextPlayerData.Clear();
foreach (var gamePixel in gamePixelGrid)
{
if (!gamePixel.EntityType.HasValue)
continue;
_nextPlayerData.Add(gamePixel.EntityType.Value, gamePixel.BelongsTo?.Name == playerName);
}
}
_nextPixels = pixels;
if (_wantsFrameOnTick)
_ = await SendNowAsync();
});
private async ValueTask<bool> SendNowAsync()
{
var pixels = _nextPixels
?? throw new InvalidOperationException("next pixels not set");
try
{
await Socket.SendBinaryAsync(pixels.Data, _nextPlayerData == null);
if (_nextPlayerData != null)
await Socket.SendBinaryAsync(_nextPlayerData.GetPacket());
_lastSentPixels = _nextPixels;
_nextPixels = null;
_wantsFrameOnTick = false;
return true;
}
catch (WebSocketException ex)
{
Logger.LogWarning(ex, "send failed");
return false;
}
}
}