servicepoint-tanks/TanksServer/ServicePointDisplay/SendToServicePointDisplay.cs

110 lines
3.5 KiB
C#
Raw Normal View History

2024-04-09 22:38:56 +02:00
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
2024-04-10 19:25:45 +02:00
using TanksServer.GameLogic;
using TanksServer.Graphics;
using TanksServer.Interactivity;
2024-04-09 22:38:56 +02:00
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;
2024-04-10 22:03:36 +02:00
private DateTime _nextFailLog = DateTime.Now;
2024-04-09 22:38:56 +02:00
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;
var localIp = GetLocalIp(options.Value.Hostname, options.Value.Port).Split('.');
Debug.Assert(localIp.Length == 4); // were talking legacy ip
2024-04-10 19:25:45 +02:00
_scoresBuffer = new TextDisplayBuffer(new TilePosition(MapService.TilesPerRow, 0), 12, 20)
{
Rows =
{
[0] = "== TANKS! ==",
[1] = "-- scores --",
[17] = "-- join --",
[18] = string.Join('.', localIp[..2]),
[19] = string.Join('.', localIp[2..])
}
};
2024-04-09 22:38:56 +02:00
}
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)
{
2024-04-10 22:03:36 +02:00
if (DateTime.Now > _nextFailLog)
{
_logger.LogWarning("could not send data to service point display: {}", ex.Message);
_nextFailLog = DateTime.Now + TimeSpan.FromSeconds(5);
}
2024-04-09 22:38:56 +02:00
}
}
}
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();
}
}