send scores to big display
This commit is contained in:
parent
a89392beb8
commit
7f00160780
|
@ -1,11 +1,12 @@
|
|||
using TanksServer.Helpers;
|
||||
using TanksServer.ServicePointDisplay;
|
||||
using TanksServer.Services;
|
||||
|
||||
namespace TanksServer.DrawSteps;
|
||||
|
||||
internal sealed class BulletDrawer(BulletManager bullets): IDrawStep
|
||||
{
|
||||
public void Draw(DisplayPixelBuffer buffer)
|
||||
public void Draw(PixelDisplayBufferView buffer)
|
||||
{
|
||||
foreach (var bullet in bullets.GetAll())
|
||||
buffer.Pixels[bullet.Position.ToPixelPosition().ToPixelIndex()] = true;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
using TanksServer.Helpers;
|
||||
using TanksServer.ServicePointDisplay;
|
||||
|
||||
namespace TanksServer.DrawSteps;
|
||||
|
||||
internal interface IDrawStep
|
||||
{
|
||||
void Draw(DisplayPixelBuffer buffer);
|
||||
void Draw(PixelDisplayBufferView buffer);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
using TanksServer.Helpers;
|
||||
using TanksServer.Models;
|
||||
using TanksServer.ServicePointDisplay;
|
||||
using TanksServer.Services;
|
||||
|
||||
namespace TanksServer.DrawSteps;
|
||||
|
||||
internal sealed class MapDrawer(MapService map) : IDrawStep
|
||||
{
|
||||
public void Draw(DisplayPixelBuffer buffer)
|
||||
public void Draw(PixelDisplayBufferView buffer)
|
||||
{
|
||||
for (var tileY = 0; tileY < MapService.TilesPerColumn; tileY++)
|
||||
for (var tileX = 0; tileX < MapService.TilesPerRow; tileX++)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using TanksServer.Helpers;
|
||||
using TanksServer.ServicePointDisplay;
|
||||
using TanksServer.Services;
|
||||
|
||||
namespace TanksServer.DrawSteps;
|
||||
|
@ -29,7 +30,7 @@ internal sealed class TankDrawer : IDrawStep
|
|||
_tankSpriteWidth = tankImage.Width;
|
||||
}
|
||||
|
||||
public void Draw(DisplayPixelBuffer buffer)
|
||||
public void Draw(PixelDisplayBufferView buffer)
|
||||
{
|
||||
foreach (var tank in _tanks)
|
||||
{
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
namespace TanksServer.Helpers;
|
||||
|
||||
internal sealed class DisplayPixelBuffer(byte[] data)
|
||||
{
|
||||
public byte[] Data => data;
|
||||
|
||||
public byte Magic1
|
||||
{
|
||||
get => data[0];
|
||||
set => data[0] = value;
|
||||
}
|
||||
|
||||
public byte Magic2
|
||||
{
|
||||
get => data[1];
|
||||
set => data[1] = value;
|
||||
}
|
||||
|
||||
public ushort X
|
||||
{
|
||||
get => GetTwoBytes(2);
|
||||
set => SetTwoBytes(2, value);
|
||||
}
|
||||
|
||||
public ushort Y
|
||||
{
|
||||
get => GetTwoBytes(4);
|
||||
set => SetTwoBytes(4, value);
|
||||
}
|
||||
|
||||
public ushort WidthInTiles
|
||||
{
|
||||
get => GetTwoBytes(6);
|
||||
set => SetTwoBytes(6, value);
|
||||
}
|
||||
|
||||
public ushort HeightInPixels
|
||||
{
|
||||
get => GetTwoBytes(8);
|
||||
set => SetTwoBytes(8, value);
|
||||
}
|
||||
|
||||
public FixedSizeBitFieldView Pixels { get; } = new(data.AsMemory(10));
|
||||
|
||||
private ushort GetTwoBytes(int index)
|
||||
{
|
||||
return (ushort)(data[index] * byte.MaxValue + data[index + 1]);
|
||||
}
|
||||
|
||||
private void SetTwoBytes(int index, ushort value)
|
||||
{
|
||||
data[index] = (byte)(value / byte.MaxValue);
|
||||
data[index + 1] = (byte)(value % byte.MaxValue);
|
||||
}
|
||||
}
|
|
@ -6,8 +6,8 @@ using Microsoft.Extensions.DependencyInjection;
|
|||
using Microsoft.Extensions.FileProviders;
|
||||
using TanksServer.DrawSteps;
|
||||
using TanksServer.Helpers;
|
||||
using TanksServer.Models;
|
||||
using TanksServer.Servers;
|
||||
using TanksServer.ServicePointDisplay;
|
||||
using TanksServer.Services;
|
||||
using TanksServer.TickSteps;
|
||||
|
||||
|
@ -81,7 +81,6 @@ internal static class Program
|
|||
builder.Services.AddSingleton<MapService>();
|
||||
builder.Services.AddSingleton<BulletManager>();
|
||||
builder.Services.AddSingleton<TankManager>();
|
||||
builder.Services.AddSingleton<SpawnNewTanks>();
|
||||
builder.Services.AddSingleton<ControlsServer>();
|
||||
builder.Services.AddSingleton<PlayerServer>();
|
||||
builder.Services.AddSingleton<ClientScreenServer>();
|
||||
|
@ -98,7 +97,7 @@ internal static class Program
|
|||
builder.Services.AddSingleton<ITickStep, RotateTanks>();
|
||||
builder.Services.AddSingleton<ITickStep, MoveTanks>();
|
||||
builder.Services.AddSingleton<ITickStep, ShootFromTanks>();
|
||||
builder.Services.AddSingleton<ITickStep>(sp => sp.GetRequiredService<SpawnNewTanks>());
|
||||
builder.Services.AddSingleton<ITickStep, SpawnNewTanks>();
|
||||
builder.Services.AddSingleton<ITickStep, DrawStateToFrame>();
|
||||
builder.Services.AddSingleton<ITickStep, SendToServicePointDisplay>();
|
||||
builder.Services.AddSingleton<ITickStep, SendToClientScreen>();
|
||||
|
|
|
@ -4,6 +4,7 @@ using System.Threading.Channels;
|
|||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using TanksServer.Helpers;
|
||||
using TanksServer.ServicePointDisplay;
|
||||
|
||||
namespace TanksServer.Servers;
|
||||
|
||||
|
@ -65,7 +66,7 @@ internal sealed class ClientScreenServer(
|
|||
Done = ReceiveAsync();
|
||||
}
|
||||
|
||||
public async Task SendAsync(DisplayPixelBuffer buf)
|
||||
public async Task SendAsync(PixelDisplayBufferView buf)
|
||||
{
|
||||
if (!await _wantedFrames.WaitAsync(TimeSpan.Zero))
|
||||
{
|
||||
|
|
|
@ -29,6 +29,8 @@ internal sealed class PlayerServer(ILogger<PlayerServer> logger, SpawnQueueProvi
|
|||
foundPlayer = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public IEnumerable<Player> GetAll() => _players.Values;
|
||||
|
||||
private Player AddAndSpawn(string name)
|
||||
{
|
||||
|
|
64
TanksServer/ServicePointDisplay/DisplayBufferView.cs
Normal file
64
TanksServer/ServicePointDisplay/DisplayBufferView.cs
Normal file
|
@ -0,0 +1,64 @@
|
|||
using TanksServer.Models;
|
||||
|
||||
namespace TanksServer.ServicePointDisplay;
|
||||
|
||||
internal class DisplayBufferView(byte[] data)
|
||||
{
|
||||
public byte[] Data => data;
|
||||
|
||||
public ushort Mode
|
||||
{
|
||||
get => GetTwoBytes(0);
|
||||
set => SetTwoBytes(0, value);
|
||||
}
|
||||
|
||||
public ushort TileX
|
||||
{
|
||||
get => GetTwoBytes(2);
|
||||
set => SetTwoBytes(2, value);
|
||||
}
|
||||
|
||||
public ushort TileY
|
||||
{
|
||||
get => GetTwoBytes(4);
|
||||
set => SetTwoBytes(4, value);
|
||||
}
|
||||
|
||||
public ushort WidthInTiles
|
||||
{
|
||||
get => GetTwoBytes(6);
|
||||
set => SetTwoBytes(6, value);
|
||||
}
|
||||
|
||||
public ushort RowCount
|
||||
{
|
||||
get => GetTwoBytes(8);
|
||||
set => SetTwoBytes(8, value);
|
||||
}
|
||||
|
||||
public TilePosition Position
|
||||
{
|
||||
get => new(TileX, TileY);
|
||||
set
|
||||
{
|
||||
ArgumentOutOfRangeException.ThrowIfGreaterThan(value.X, ushort.MaxValue);
|
||||
ArgumentOutOfRangeException.ThrowIfGreaterThan(value.Y, ushort.MaxValue);
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(value.X);
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(value.Y);
|
||||
|
||||
TileX = (ushort)value.X;
|
||||
TileY = (ushort)value.Y;
|
||||
}
|
||||
}
|
||||
|
||||
private ushort GetTwoBytes(int index)
|
||||
{
|
||||
return (ushort)(data[index] * byte.MaxValue + data[index + 1]);
|
||||
}
|
||||
|
||||
private void SetTwoBytes(int index, ushort value)
|
||||
{
|
||||
data[index] = (byte)(value / byte.MaxValue);
|
||||
data[index + 1] = (byte)(value % byte.MaxValue);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
using System.Collections;
|
||||
|
||||
namespace TanksServer.Helpers;
|
||||
namespace TanksServer.ServicePointDisplay;
|
||||
|
||||
internal sealed class FixedSizeBitFieldView(Memory<byte> data) : IList<bool>
|
||||
{
|
||||
|
@ -8,6 +8,7 @@ internal sealed class FixedSizeBitFieldView(Memory<byte> data) : IList<bool>
|
|||
public bool IsReadOnly => false;
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
public IEnumerator<bool> GetEnumerator()
|
||||
{
|
||||
return Enumerable().GetEnumerator();
|
||||
|
@ -32,10 +33,17 @@ internal sealed class FixedSizeBitFieldView(Memory<byte> data) : IList<bool>
|
|||
array[i + arrayIndex] = this[i];
|
||||
}
|
||||
|
||||
private static (int byteIndex, int bitInByteIndex) GetIndexes(int bitIndex)
|
||||
private (int byteIndex, int bitInByteIndex) GetIndexes(int bitIndex)
|
||||
{
|
||||
var byteIndex = bitIndex / 8;
|
||||
var bitInByteIndex = 7 - bitIndex % 8;
|
||||
if (byteIndex >= data.Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(bitIndex),
|
||||
$"accessing this bit field at position {bitIndex} would result in an access to byte " +
|
||||
$"{byteIndex} but byte length is {data.Length}");
|
||||
}
|
||||
|
||||
return (byteIndex, bitInByteIndex);
|
||||
}
|
||||
|
||||
|
@ -71,4 +79,4 @@ internal sealed class FixedSizeBitFieldView(Memory<byte> data) : IList<bool>
|
|||
public int IndexOf(bool item) => throw new NotSupportedException();
|
||||
public void Insert(int index, bool item) => throw new NotSupportedException();
|
||||
public void RemoveAt(int index) => throw new NotSupportedException();
|
||||
}
|
||||
}
|
39
TanksServer/ServicePointDisplay/FixedSizeCharGridView.cs
Normal file
39
TanksServer/ServicePointDisplay/FixedSizeCharGridView.cs
Normal file
|
@ -0,0 +1,39 @@
|
|||
using System.Text;
|
||||
|
||||
namespace TanksServer.ServicePointDisplay;
|
||||
|
||||
internal sealed class FixedSizeCharGridView(Memory<byte> data, ushort rowLength, ushort rowCount)
|
||||
{
|
||||
public char this[int x, int y]
|
||||
{
|
||||
get => (char)data.Span[x + y * rowLength];
|
||||
set => data.Span[x + y * rowLength] = CharToByte(value);
|
||||
}
|
||||
|
||||
public string this[int row]
|
||||
{
|
||||
get
|
||||
{
|
||||
var rowStart = row * rowLength;
|
||||
return Encoding.UTF8.GetString(data[rowStart..(rowStart + rowLength)].Span);
|
||||
}
|
||||
set
|
||||
{
|
||||
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(row, rowCount, nameof(row));
|
||||
ArgumentOutOfRangeException.ThrowIfGreaterThan(value.Length, rowLength, nameof(value));
|
||||
var x = 0;
|
||||
for (; x < value.Length; x++)
|
||||
this[x, row] = value[x];
|
||||
for (; x < rowLength; x++)
|
||||
this[x, row] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
private static byte CharToByte(char c)
|
||||
{
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(c);
|
||||
ArgumentOutOfRangeException.ThrowIfGreaterThan(c, (char)byte.MaxValue, nameof(c));
|
||||
// c# strings are UTF-16
|
||||
return (byte)c;
|
||||
}
|
||||
}
|
29
TanksServer/ServicePointDisplay/PixelDisplayBufferView.cs
Normal file
29
TanksServer/ServicePointDisplay/PixelDisplayBufferView.cs
Normal file
|
@ -0,0 +1,29 @@
|
|||
using TanksServer.Helpers;
|
||||
using TanksServer.Services;
|
||||
|
||||
namespace TanksServer.ServicePointDisplay;
|
||||
|
||||
internal sealed class PixelDisplayBufferView : DisplayBufferView
|
||||
{
|
||||
private PixelDisplayBufferView(byte[] data) : base(data)
|
||||
{
|
||||
Pixels = new FixedSizeBitFieldView(Data.AsMemory(10));
|
||||
}
|
||||
|
||||
// ReSharper disable once CollectionNeverQueried.Global (setting values in collection updates underlying byte array)
|
||||
public FixedSizeBitFieldView Pixels { get; }
|
||||
|
||||
public static PixelDisplayBufferView New(ushort x, ushort y, ushort widthInTiles, ushort pixelRows)
|
||||
{
|
||||
// 10 bytes header, one byte per tile row (with one bit each pixel) after that
|
||||
var size = 10 + widthInTiles * pixelRows;
|
||||
return new PixelDisplayBufferView(new byte[size])
|
||||
{
|
||||
Mode = 19,
|
||||
TileX = x,
|
||||
TileY = y,
|
||||
WidthInTiles = widthInTiles,
|
||||
RowCount = pixelRows
|
||||
};
|
||||
}
|
||||
}
|
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();
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
namespace TanksServer.Models;
|
||||
namespace TanksServer.ServicePointDisplay;
|
||||
|
||||
internal sealed class ServicePointDisplayConfiguration
|
||||
{
|
18
TanksServer/ServicePointDisplay/TextDisplayBuffer.cs
Normal file
18
TanksServer/ServicePointDisplay/TextDisplayBuffer.cs
Normal file
|
@ -0,0 +1,18 @@
|
|||
using TanksServer.Models;
|
||||
|
||||
namespace TanksServer.ServicePointDisplay;
|
||||
|
||||
internal sealed class TextDisplayBuffer : DisplayBufferView
|
||||
{
|
||||
public TextDisplayBuffer(TilePosition position, ushort charsPerRow, ushort rows)
|
||||
: base(new byte[10 + charsPerRow * rows])
|
||||
{
|
||||
Mode = 3;
|
||||
WidthInTiles = charsPerRow;
|
||||
RowCount = rows;
|
||||
Position = position;
|
||||
Rows = new FixedSizeCharGridView(Data.AsMemory(10), charsPerRow, rows);
|
||||
}
|
||||
|
||||
public FixedSizeCharGridView Rows { get; set; }
|
||||
}
|
|
@ -3,12 +3,16 @@ using Microsoft.Extensions.Hosting;
|
|||
using Microsoft.Extensions.Logging;
|
||||
using TanksServer.TickSteps;
|
||||
|
||||
namespace TanksServer;
|
||||
namespace TanksServer.Services;
|
||||
|
||||
internal sealed class GameTickWorker(
|
||||
IEnumerable<ITickStep> steps, IHostApplicationLifetime lifetime, ILogger<GameTickWorker> logger
|
||||
IEnumerable<ITickStep> steps,
|
||||
IHostApplicationLifetime lifetime,
|
||||
ILogger<GameTickWorker> logger
|
||||
) : IHostedService, IDisposable
|
||||
{
|
||||
private const int TicksPerSecond = 25;
|
||||
private static readonly TimeSpan TickPacing = TimeSpan.FromMilliseconds((int)(1000 / TicksPerSecond));
|
||||
private readonly CancellationTokenSource _cancellation = new();
|
||||
private readonly List<ITickStep> _steps = steps.ToList();
|
||||
private Task? _run;
|
||||
|
@ -31,8 +35,10 @@ internal sealed class GameTickWorker(
|
|||
|
||||
foreach (var step in _steps)
|
||||
await step.TickAsync();
|
||||
|
||||
await Task.Delay(TimeSpan.FromMilliseconds(1000 / 25) - sw.Elapsed);
|
||||
|
||||
var wantedDelay = TickPacing - sw.Elapsed;
|
||||
if (wantedDelay.Ticks > 0)
|
||||
await Task.Delay(wantedDelay);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -53,4 +59,4 @@ internal sealed class GameTickWorker(
|
|||
_cancellation.Dispose();
|
||||
_run?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,12 +1,12 @@
|
|||
using TanksServer.Helpers;
|
||||
using TanksServer.ServicePointDisplay;
|
||||
|
||||
namespace TanksServer.Services;
|
||||
|
||||
internal sealed class LastFinishedFrameProvider
|
||||
{
|
||||
private DisplayPixelBuffer? _lastFrame;
|
||||
private PixelDisplayBufferView? _lastFrame;
|
||||
|
||||
public DisplayPixelBuffer LastFrame
|
||||
public PixelDisplayBufferView LastFrame
|
||||
{
|
||||
get => _lastFrame ?? throw new InvalidOperationException("first frame not yet drawn");
|
||||
set => _lastFrame = value;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
using TanksServer.DrawSteps;
|
||||
using TanksServer.Helpers;
|
||||
using TanksServer.ServicePointDisplay;
|
||||
using TanksServer.Services;
|
||||
|
||||
namespace TanksServer.TickSteps;
|
||||
|
@ -8,30 +8,14 @@ internal sealed class DrawStateToFrame(
|
|||
IEnumerable<IDrawStep> drawSteps, LastFinishedFrameProvider lastFrameProvider
|
||||
) : ITickStep
|
||||
{
|
||||
private const uint GameFieldPixelCount = MapService.PixelsPerRow * MapService.PixelsPerColumn;
|
||||
private readonly List<IDrawStep> _drawSteps = drawSteps.ToList();
|
||||
|
||||
public Task TickAsync()
|
||||
{
|
||||
var buffer = CreateGameFieldPixelBuffer();
|
||||
var buffer = PixelDisplayBufferView.New(0, 0, MapService.TilesPerRow, MapService.PixelsPerColumn);
|
||||
foreach (var step in _drawSteps)
|
||||
step.Draw(buffer);
|
||||
lastFrameProvider.LastFrame = buffer;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private static DisplayPixelBuffer CreateGameFieldPixelBuffer()
|
||||
{
|
||||
var data = new byte[10 + GameFieldPixelCount / 8];
|
||||
var result = new DisplayPixelBuffer(data)
|
||||
{
|
||||
Magic1 = 0,
|
||||
Magic2 = 19,
|
||||
X = 0,
|
||||
Y = 0,
|
||||
WidthInTiles = MapService.TilesPerRow,
|
||||
HeightInPixels = MapService.PixelsPerColumn
|
||||
};
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
using System.Net.Sockets;
|
||||
using TanksServer.Models;
|
||||
using TanksServer.Services;
|
||||
|
||||
namespace TanksServer.TickSteps;
|
||||
|
||||
internal sealed class SendToServicePointDisplay(
|
||||
IOptions<ServicePointDisplayConfiguration> options,
|
||||
LastFinishedFrameProvider lastFinishedFrameProvider
|
||||
) : ITickStep, IDisposable
|
||||
{
|
||||
private readonly UdpClient? _udpClient = options.Value.Enable
|
||||
? new(options.Value.Hostname, options.Value.Port)
|
||||
: null;
|
||||
|
||||
public Task TickAsync()
|
||||
{
|
||||
return _udpClient?.SendAsync(lastFinishedFrameProvider.LastFrame.Data).AsTask() ?? Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_udpClient?.Dispose();
|
||||
}
|
||||
}
|
|
@ -4,7 +4,9 @@ using TanksServer.Services;
|
|||
namespace TanksServer.TickSteps;
|
||||
|
||||
internal sealed class ShootFromTanks(
|
||||
TankManager tanks, IOptions<TanksConfiguration> options, BulletManager bulletManager
|
||||
TankManager tanks,
|
||||
IOptions<TanksConfiguration> options,
|
||||
BulletManager bulletManager
|
||||
) : ITickStep
|
||||
{
|
||||
private readonly TanksConfiguration _config = options.Value;
|
||||
|
@ -34,4 +36,4 @@ internal sealed class ShootFromTanks(
|
|||
|
||||
bulletManager.Spawn(new Bullet(tank.Owner, position, tank.Rotation));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,8 +15,9 @@
|
|||
}
|
||||
},
|
||||
"ServicePointDisplay": {
|
||||
"Enable": false,
|
||||
"Hostname": "172.23.42.29",
|
||||
"Enable": true,
|
||||
//"Hostname": "172.23.42.29",
|
||||
"Hostname": "localhost",
|
||||
"Port": 2342
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
VITE_TANK_SCREEN_URL=ws://localhost:3000/screen
|
||||
VITE_TANK_CONTROLS_URL=ws://localhost:3000/controls
|
||||
VITE_TANK_PLAYER_URL=http://localhost:3000/player
|
||||
VITE_TANK_SCREEN_URL=ws://vinzenz-lpt2/screen
|
||||
VITE_TANK_CONTROLS_URL=ws://vinzenz-lpt2/controls
|
||||
VITE_TANK_PLAYER_URL=http://vinzenz-lpt2/player
|
||||
|
|
Loading…
Reference in a new issue