send scores to big display
This commit is contained in:
parent
a89392beb8
commit
7f00160780
1 changed files with 305 additions and 126 deletions
103
TanksServer/ServicePointDisplay/SendToServicePointDisplay.cs
Normal file
103
TanksServer/ServicePointDisplay/SendToServicePointDisplay.cs
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using TanksServer.Servers;
|
||||
using TanksServer.Services;
|
||||
using TanksServer.TickSteps;
|
||||
|
||||
namespace TanksServer.ServicePointDisplay;
|
||||
|
||||
internal sealed class SendToServicePointDisplay : ITickStep, IDisposable
|
||||
{
|
||||
private readonly UdpClient? _udpClient;
|
||||
private readonly LastFinishedFrameProvider _lastFinishedFrameProvider;
|
||||
private readonly TextDisplayBuffer _scoresBuffer;
|
||||
private readonly PlayerServer _players;
|
||||
private readonly ILogger<SendToServicePointDisplay> _logger;
|
||||
|
||||
private const int ScoresWidth = 12;
|
||||
private const int ScoresHeight = 20;
|
||||
private const int ScoresPlayerRows = ScoresHeight - 5;
|
||||
|
||||
public SendToServicePointDisplay(
|
||||
IOptions<ServicePointDisplayConfiguration> options,
|
||||
LastFinishedFrameProvider lastFinishedFrameProvider,
|
||||
PlayerServer players,
|
||||
ILogger<SendToServicePointDisplay> logger
|
||||
)
|
||||
{
|
||||
_lastFinishedFrameProvider = lastFinishedFrameProvider;
|
||||
_players = players;
|
||||
_logger = logger;
|
||||
_udpClient = options.Value.Enable
|
||||
? new UdpClient(options.Value.Hostname, options.Value.Port)
|
||||
: null;
|
||||
|
||||
_scoresBuffer = new(new(MapService.TilesPerRow, 0), 12, 20);
|
||||
_scoresBuffer.Rows[0] = "== TANKS! ==";
|
||||
_scoresBuffer.Rows[1] = "-- scores --";
|
||||
|
||||
_scoresBuffer.Rows[17] = "-- join --";
|
||||
|
||||
var localIp = GetLocalIp(options.Value.Hostname, options.Value.Port).Split('.');
|
||||
Debug.Assert(localIp.Length == 4); // were talking legacy ip
|
||||
_scoresBuffer.Rows[18] = string.Join('.', localIp[..2]);
|
||||
_scoresBuffer.Rows[19] = string.Join('.', localIp[2..]);
|
||||
}
|
||||
|
||||
private static string GetLocalIp(string host, int port)
|
||||
{
|
||||
using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0);
|
||||
socket.Connect(host, port);
|
||||
var endPoint = socket.LocalEndPoint as IPEndPoint ?? throw new NotSupportedException();
|
||||
return endPoint.Address.ToString();
|
||||
}
|
||||
|
||||
public Task TickAsync()
|
||||
{
|
||||
return _udpClient == null ? Task.CompletedTask : Core();
|
||||
|
||||
async Task Core()
|
||||
{
|
||||
RefreshScores();
|
||||
try
|
||||
{
|
||||
await _udpClient.SendAsync(_scoresBuffer.Data);
|
||||
await _udpClient.SendAsync(_lastFinishedFrameProvider.LastFrame.Data);
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "could not send data to service point display");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshScores()
|
||||
{
|
||||
var playersToDisplay = _players.GetAll()
|
||||
.OrderByDescending(p => p.Kills)
|
||||
.Take(ScoresPlayerRows);
|
||||
|
||||
var row = 2;
|
||||
foreach (var p in playersToDisplay)
|
||||
{
|
||||
var score = p.Kills.ToString();
|
||||
var nameLength = ScoresWidth - score.Length;
|
||||
|
||||
var name = p.Name[..nameLength];
|
||||
var spaces = new string(' ', nameLength - name.Length + 1);
|
||||
|
||||
_scoresBuffer.Rows[row] = name + spaces + score;
|
||||
row++;
|
||||
}
|
||||
|
||||
for (; row < 17; row++)
|
||||
_scoresBuffer.Rows[row] = string.Empty;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_udpClient?.Dispose();
|
||||
}
|
||||
}
|
||||
Reference in a new issue