more commands, change display communication to new lib

This commit is contained in:
Vinzenz Schroeter 2024-04-12 16:05:24 +02:00
parent 38463ac109
commit 7213318838
31 changed files with 240 additions and 417 deletions

View file

@ -7,15 +7,15 @@ namespace TanksServer.Interactivity;
/// <summary>
/// Hacky class for easier semantics
/// </summary>
internal sealed class ByteChannelWebSocket : Channel<byte[]>
internal sealed class ByteChannelWebSocket : Channel<Memory<byte>>
{
private readonly ILogger _logger;
private readonly WebSocket _socket;
private readonly Task _backgroundDone;
private readonly byte[] _buffer;
private readonly Channel<byte[]> _outgoing = Channel.CreateUnbounded<byte[]>();
private readonly Channel<byte[]> _incoming = Channel.CreateUnbounded<byte[]>();
private readonly Channel<Memory<byte>> _outgoing = Channel.CreateUnbounded<Memory<byte>>();
private readonly Channel<Memory<byte>> _incoming = Channel.CreateUnbounded<Memory<byte>>();
public ByteChannelWebSocket(WebSocket socket, ILogger logger, int messageSize)
{

View file

@ -1,8 +1,8 @@
using System.Diagnostics;
using System.Net.WebSockets;
using System.Threading.Channels;
using DisplayCommands;
using Microsoft.Extensions.Hosting;
using TanksServer.ServicePointDisplay;
namespace TanksServer.Interactivity;
@ -44,10 +44,10 @@ internal sealed class ClientScreenServer(
public Task StoppedAsync(CancellationToken cancellationToken) => Task.CompletedTask;
private void Remove(ClientScreenServerConnection connection) => _connections.TryRemove(connection, out _);
public IEnumerable<ClientScreenServerConnection> GetConnections() => _connections.Keys;
internal sealed class ClientScreenServerConnection: IDisposable
internal sealed class ClientScreenServerConnection : IDisposable
{
private readonly ByteChannelWebSocket _channel;
private readonly SemaphoreSlim _wantedFrames = new(1);
@ -64,7 +64,7 @@ internal sealed class ClientScreenServer(
Done = ReceiveAsync();
}
public async Task SendAsync(PixelDisplayBufferView buf)
public async Task SendAsync(PixelGrid buf)
{
if (!await _wantedFrames.WaitAsync(TimeSpan.Zero))
{
@ -85,9 +85,9 @@ internal sealed class ClientScreenServer(
private async Task ReceiveAsync()
{
await foreach (var _ in _channel.Reader.ReadAllAsync())
await foreach (var _ in _channel.Reader.ReadAllAsync())
_wantedFrames.Release();
_logger.LogTrace("done receiving");
_server.Remove(this);
}
@ -106,4 +106,4 @@ internal sealed class ClientScreenServer(
Done.Dispose();
}
}
}
}

View file

@ -71,8 +71,8 @@ internal sealed class ControlsServer(ILogger<ControlsServer> logger, ILoggerFact
{
await foreach (var buffer in _binaryWebSocket.Reader.ReadAllAsync())
{
var type = (MessageType)buffer[0];
var control = (InputType)buffer[1];
var type = (MessageType)buffer.Span[0];
var control = (InputType)buffer.Span[1];
_logger.LogTrace("player input {} {} {}", _player.Id, type, control);

View file

@ -0,0 +1,87 @@
using System.Diagnostics;
using System.Net.Sockets;
using DisplayCommands;
using TanksServer.GameLogic;
using TanksServer.Graphics;
namespace TanksServer.Interactivity;
internal sealed class SendToServicePointDisplay : ITickStep
{
private readonly LastFinishedFrameProvider _lastFinishedFrameProvider;
private readonly Cp437Grid _scoresBuffer;
private readonly PlayerServer _players;
private readonly ILogger<SendToServicePointDisplay> _logger;
private readonly IDisplayConnection _displayConnection;
private DateTime _nextFailLog = DateTime.Now;
private const int ScoresWidth = 12;
private const int ScoresHeight = 20;
private const int ScoresPlayerRows = ScoresHeight - 5;
public SendToServicePointDisplay(
LastFinishedFrameProvider lastFinishedFrameProvider,
PlayerServer players,
ILogger<SendToServicePointDisplay> logger,
IDisplayConnection displayConnection
)
{
_lastFinishedFrameProvider = lastFinishedFrameProvider;
_players = players;
_logger = logger;
_displayConnection = displayConnection;
var localIp = _displayConnection.GetLocalIPv4().Split('.');
Debug.Assert(localIp.Length == 4);
_scoresBuffer = new Cp437Grid(12, 20)
{
[00] = "== TANKS! ==",
[01] = "-- scores --",
[17] = "-- join --",
[18] = string.Join('.', localIp[..2]),
[19] = string.Join('.', localIp[2..])
};
}
public async Task TickAsync()
{
RefreshScores();
try
{
await _displayConnection.SendCp437DataAsync(MapService.TilesPerRow, 0, _scoresBuffer);
await _displayConnection.SendBitmapLinearWindowAsync(0, 0, _lastFinishedFrameProvider.LastFrame);
}
catch (SocketException ex)
{
if (DateTime.Now > _nextFailLog)
{
_logger.LogWarning("could not send data to service point display: {}", ex.Message);
_nextFailLog = DateTime.Now + TimeSpan.FromSeconds(5);
}
}
}
private void RefreshScores()
{
var playersToDisplay = _players.GetAll()
.OrderByDescending(p => p.Kills)
.Take(ScoresPlayerRows);
ushort row = 2;
foreach (var p in playersToDisplay)
{
var score = p.Kills.ToString();
var nameLength = Math.Min(p.Name.Length, ScoresWidth - score.Length - 1);
var name = p.Name[..nameLength];
var spaces = new string(' ', ScoresWidth - score.Length - nameLength);
_scoresBuffer[row] = name + spaces + score;
row++;
}
for (; row < 17; row++)
_scoresBuffer[row] = string.Empty;
}
}