WIP switch to ServicePoint2 library
This commit is contained in:
parent
eb999b0d1a
commit
e1cfd714c1
31 changed files with 66 additions and 791 deletions
|
@ -1,13 +1,13 @@
|
|||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using DisplayCommands;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.HttpResults;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using ServicePoint2;
|
||||
using TanksServer.GameLogic;
|
||||
using TanksServer.Interactivity;
|
||||
|
||||
|
@ -19,7 +19,7 @@ internal sealed class Endpoints(
|
|||
ControlsServer controlsServer,
|
||||
MapService mapService,
|
||||
ChangeToRequestedMap changeToRequestedMap,
|
||||
IDisplayConnection displayConnection
|
||||
Connection displayConnection
|
||||
)
|
||||
{
|
||||
public void Map(WebApplication app)
|
||||
|
@ -31,7 +31,7 @@ internal sealed class Endpoints(
|
|||
app.Map("/controls", ConnectControlsAsync);
|
||||
app.MapGet("/map", () => mapService.MapNames);
|
||||
app.MapPost("/map", PostMap);
|
||||
app.MapPost("/resetDisplay", displayConnection.SendHardResetAsync);
|
||||
app.MapPost("/resetDisplay", () => displayConnection.Send(Command.HardReset()));
|
||||
app.MapGet("/map/{name}", GetMapByName);
|
||||
|
||||
app.MapHealthChecks("/health", new HealthCheckOptions
|
||||
|
@ -117,7 +117,7 @@ internal sealed class Endpoints(
|
|||
if (!mapService.TryGetPreview(name, out var preview))
|
||||
return TypedResults.NotFound();
|
||||
|
||||
var mapInfo = new MapInfo(prototype.Name, prototype.GetType().Name, preview.Data);
|
||||
var mapInfo = new MapInfo(prototype.Name, prototype.GetType().Name, preview.Data.ToArray());
|
||||
return TypedResults.Ok(mapInfo);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using DisplayCommands;
|
||||
using ServicePoint2;
|
||||
using TanksServer.Graphics;
|
||||
|
||||
namespace TanksServer.GameLogic;
|
||||
|
@ -42,7 +42,7 @@ internal sealed class MapService
|
|||
if (!_mapPrototypes.TryGetValue(name, out var prototype))
|
||||
return false; // name not found
|
||||
|
||||
pixelGrid = new PixelGrid(PixelsPerRow, PixelsPerColumn);
|
||||
pixelGrid = PixelGrid.New(PixelsPerRow, PixelsPerColumn);
|
||||
DrawMapStep.Draw(pixelGrid, prototype.CreateInstance());
|
||||
|
||||
_mapPreviews.TryAdd(name, pixelGrid); // another thread may have added the map already
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
using System.Diagnostics;
|
||||
|
||||
namespace TanksServer.GameLogic;
|
||||
|
||||
internal sealed class SpawnPowerUp(
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using DisplayCommands;
|
||||
using ServicePoint2;
|
||||
using TanksServer.GameLogic;
|
||||
|
||||
namespace TanksServer.Graphics;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using DisplayCommands;
|
||||
using ServicePoint2;
|
||||
using TanksServer.GameLogic;
|
||||
using TanksServer.Interactivity;
|
||||
|
||||
|
@ -10,9 +10,9 @@ internal sealed class GeneratePixelsTickStep(
|
|||
) : ITickStep
|
||||
{
|
||||
private GamePixelGrid _lastGamePixelGrid = new(MapService.PixelsPerRow, MapService.PixelsPerColumn);
|
||||
private PixelGrid _lastObserverPixelGrid = new(MapService.PixelsPerRow, MapService.PixelsPerColumn);
|
||||
private PixelGrid _lastObserverPixelGrid = PixelGrid.New(MapService.PixelsPerRow, MapService.PixelsPerColumn);
|
||||
private GamePixelGrid _gamePixelGrid = new(MapService.PixelsPerRow, MapService.PixelsPerColumn);
|
||||
private PixelGrid _observerPixelGrid = new(MapService.PixelsPerRow, MapService.PixelsPerColumn);
|
||||
private PixelGrid _observerPixelGrid = PixelGrid.New(MapService.PixelsPerRow, MapService.PixelsPerColumn);
|
||||
|
||||
private readonly List<IDrawStep> _drawSteps = drawSteps.ToList();
|
||||
private readonly List<IFrameConsumer> _consumers = consumers.ToList();
|
||||
|
@ -20,7 +20,7 @@ internal sealed class GeneratePixelsTickStep(
|
|||
public async ValueTask TickAsync(TimeSpan _)
|
||||
{
|
||||
Draw(_gamePixelGrid, _observerPixelGrid);
|
||||
if (_observerPixelGrid.Data.Span.SequenceEqual(_lastObserverPixelGrid.Data.Span))
|
||||
if (_observerPixelGrid.Data.SequenceEqual(_lastObserverPixelGrid.Data))
|
||||
return;
|
||||
|
||||
await _consumers.Select(c => c.OnFrameDoneAsync(_gamePixelGrid, _observerPixelGrid))
|
||||
|
@ -36,7 +36,7 @@ internal sealed class GeneratePixelsTickStep(
|
|||
foreach (var step in _drawSteps)
|
||||
step.Draw(gamePixelGrid);
|
||||
|
||||
observerPixelGrid.Clear();
|
||||
observerPixelGrid.Fill(false);
|
||||
for (var y = 0; y < MapService.PixelsPerColumn; y++)
|
||||
for (var x = 0; x < MapService.PixelsPerRow; x++)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using DisplayCommands;
|
||||
using ServicePoint2;
|
||||
|
||||
namespace TanksServer.Graphics;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
using System.Net.WebSockets;
|
||||
using DisplayCommands;
|
||||
using ServicePoint2;
|
||||
using TanksServer.Graphics;
|
||||
|
||||
namespace TanksServer.Interactivity;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
using System.Buffers;
|
||||
using System.Net.WebSockets;
|
||||
using DisplayCommands;
|
||||
using ServicePoint2;
|
||||
using TanksServer.Graphics;
|
||||
|
||||
namespace TanksServer.Interactivity;
|
||||
|
@ -36,8 +36,9 @@ internal sealed class ClientScreenServerConnection
|
|||
|
||||
private Package BuildNextPackage(PixelGrid pixels, GamePixelGrid gamePixelGrid)
|
||||
{
|
||||
var nextPixels = _bufferPool.Rent(pixels.Data.Length);
|
||||
pixels.Data.CopyTo(nextPixels.Memory);
|
||||
var pixelsData = pixels.Data;
|
||||
var nextPixels = _bufferPool.Rent(pixelsData.Length);
|
||||
pixelsData.CopyTo(nextPixels.Memory.Span);
|
||||
|
||||
if (_playerDataBuilder == null)
|
||||
return new Package(nextPixels, null);
|
||||
|
|
|
@ -13,7 +13,7 @@ internal sealed class PlayerInfoConnection
|
|||
private readonly MapEntityManager _entityManager;
|
||||
private readonly BufferPool _bufferPool;
|
||||
private readonly MemoryStream _tempStream = new();
|
||||
private IMemoryOwner<byte>? _lastMessage = null;
|
||||
private IMemoryOwner<byte>? _lastMessage;
|
||||
|
||||
public PlayerInfoConnection(
|
||||
Player player,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using DisplayCommands;
|
||||
using ServicePoint2;
|
||||
using TanksServer.GameLogic;
|
||||
using TanksServer.Graphics;
|
||||
|
||||
|
@ -12,11 +13,11 @@ internal sealed class SendToServicePointDisplay : IFrameConsumer
|
|||
private const int ScoresHeight = 20;
|
||||
private const int ScoresPlayerRows = ScoresHeight - 6;
|
||||
|
||||
private readonly IDisplayConnection _displayConnection;
|
||||
private readonly Connection _displayConnection;
|
||||
private readonly MapService _mapService;
|
||||
private readonly ILogger<SendToServicePointDisplay> _logger;
|
||||
private readonly PlayerServer _players;
|
||||
private readonly Cp437Grid _scoresBuffer;
|
||||
private readonly ByteGrid _scoresBuffer;
|
||||
private readonly TimeSpan _minFrameTime;
|
||||
private readonly IOptionsMonitor<HostConfiguration> _options;
|
||||
|
||||
|
@ -26,11 +27,11 @@ internal sealed class SendToServicePointDisplay : IFrameConsumer
|
|||
public SendToServicePointDisplay(
|
||||
PlayerServer players,
|
||||
ILogger<SendToServicePointDisplay> logger,
|
||||
IDisplayConnection displayConnection,
|
||||
Connection displayConnection,
|
||||
IOptions<HostConfiguration> hostOptions,
|
||||
MapService mapService,
|
||||
IOptionsMonitor<HostConfiguration> options
|
||||
)
|
||||
IOptionsMonitor<HostConfiguration> options,
|
||||
IOptions<DisplayConfiguration> displayConfig)
|
||||
{
|
||||
_players = players;
|
||||
_logger = logger;
|
||||
|
@ -39,16 +40,15 @@ internal sealed class SendToServicePointDisplay : IFrameConsumer
|
|||
_minFrameTime = TimeSpan.FromMilliseconds(hostOptions.Value.ServicePointDisplayMinFrameTimeMs);
|
||||
_options = options;
|
||||
|
||||
var localIp = _displayConnection.GetLocalIPv4().Split('.');
|
||||
var localIp = GetLocalIPv4(displayConfig.Value).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..])
|
||||
};
|
||||
_scoresBuffer = ByteGrid.New(12, 20);
|
||||
|
||||
_scoresBuffer[00] = "== TANKS! ==";
|
||||
_scoresBuffer[01] = "-- scores --";
|
||||
_scoresBuffer[17] = "-- join --";
|
||||
_scoresBuffer[18] = string.Join('.', localIp[..2]);
|
||||
_scoresBuffer[19] = string.Join('.', localIp[2..]);
|
||||
}
|
||||
|
||||
public async Task OnFrameDoneAsync(GamePixelGrid gamePixelGrid, PixelGrid observerPixels)
|
||||
|
@ -66,8 +66,8 @@ internal sealed class SendToServicePointDisplay : IFrameConsumer
|
|||
|
||||
try
|
||||
{
|
||||
await _displayConnection.SendBitmapLinearWindowAsync(0, 0, observerPixels);
|
||||
await _displayConnection.SendCp437DataAsync(MapService.TilesPerRow, 0, _scoresBuffer);
|
||||
_displayConnection.Send(Command.BitmapLinearWin(0, 0, observerPixels.Clone()));
|
||||
_displayConnection.Send(Command.Cp437Data(MapService.TilesPerRow, 0, _scoresBuffer.Clone()));
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
|
@ -103,4 +103,12 @@ internal sealed class SendToServicePointDisplay : IFrameConsumer
|
|||
|
||||
_scoresBuffer[16] = _mapService.Current.Name[..(Math.Min(ScoresWidth, _mapService.Current.Name.Length) - 1)];
|
||||
}
|
||||
|
||||
private static string GetLocalIPv4(DisplayConfiguration configuration)
|
||||
{
|
||||
using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0);
|
||||
socket.Connect(configuration.Hostname, configuration.Port);
|
||||
var endPoint = socket.LocalEndPoint as IPEndPoint ?? throw new NotSupportedException();
|
||||
return endPoint.Address.ToString();
|
||||
}
|
||||
}
|
||||
|
|
8
tanks-backend/TanksServer/Models/DisplayConfiguration.cs
Normal file
8
tanks-backend/TanksServer/Models/DisplayConfiguration.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
namespace TanksServer.Models;
|
||||
|
||||
public class DisplayConfiguration
|
||||
{
|
||||
public string Hostname { get; set; } = "172.23.42.29";
|
||||
|
||||
public int Port { get; set; } = 2342;
|
||||
}
|
|
@ -1,8 +1,9 @@
|
|||
using System.IO;
|
||||
using DisplayCommands;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using ServicePoint2;
|
||||
using SixLabors.ImageSharp;
|
||||
using TanksServer.GameLogic;
|
||||
using TanksServer.Graphics;
|
||||
using TanksServer.Interactivity;
|
||||
|
@ -94,9 +95,14 @@ public static class Program
|
|||
|
||||
builder.Services.Configure<GameRules>(builder.Configuration.GetSection("GameRules"));
|
||||
builder.Services.Configure<HostConfiguration>(builder.Configuration.GetSection("Host"));
|
||||
builder.Services.Configure<DisplayConfiguration>(builder.Configuration.GetSection("ServicePointDisplay"));
|
||||
|
||||
builder.Services.AddSingleton<IFrameConsumer, SendToServicePointDisplay>();
|
||||
builder.Services.AddDisplay(builder.Configuration.GetSection("ServicePointDisplay"));
|
||||
builder.Services.AddSingleton<Connection>(sp =>
|
||||
{
|
||||
var config = sp.GetRequiredService<IOptions<DisplayConfiguration>>().Value;
|
||||
return Connection.Open($"{config.Hostname}:{config.Port}");
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
|
|
|
@ -10,11 +10,14 @@
|
|||
<PackageReference Include="DotNext.Threading" Version="5.3.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.4" />
|
||||
<ProjectReference Include="../DisplayCommands/DisplayCommands.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="./assets/**" CopyToOutputDirectory="PreserveNewest" CopyToPublishDirectory="Always"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\servicepoint2\servicepoint2-binding-cs\ServicePoint2\ServicePoint2.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
}
|
||||
},
|
||||
"ServicePointDisplay": {
|
||||
"Hostname": "172.23.42.29",
|
||||
//"Hostname": "172.23.42.29",
|
||||
"Hostname": "127.0.0.1",
|
||||
"Port": 2342
|
||||
},
|
||||
"GameRules": {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue