From bc8d5ad6d0c2f7d88c2024c17fb07074a679ed35 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 6 Apr 2024 16:38:26 +0200 Subject: [PATCH] first image in client --- TanksServer/ClientScreenServer.cs | 52 ++++++++++++++++++++++++ TanksServer/FixedSizeBitFieldView.cs | 41 ++++--------------- TanksServer/GlobalUsings.cs | 1 + TanksServer/Program.cs | 14 ++++++- TanksServer/appsettings.Development.json | 4 +- TanksServer/appsettings.json | 9 +++- 6 files changed, 82 insertions(+), 39 deletions(-) create mode 100644 TanksServer/ClientScreenServer.cs diff --git a/TanksServer/ClientScreenServer.cs b/TanksServer/ClientScreenServer.cs new file mode 100644 index 0000000..9c5b828 --- /dev/null +++ b/TanksServer/ClientScreenServer.cs @@ -0,0 +1,52 @@ +using System.Net.WebSockets; + +namespace TanksServer; + +internal sealed class ClientScreenServer +{ + private readonly List _connections = new(); + + public ClientScreenServerConnection AddClient(WebSocket socket) + { + var connection = new ClientScreenServerConnection(socket); + _connections.Add(connection); + return connection; + } + + public Task Send(DisplayPixelBuffer buf) + { + return Task.WhenAll(_connections.Select(c => c.Send(buf))); + } +} + +internal sealed class ClientScreenServerConnection +{ + private readonly WebSocket _socket; + private readonly Task _readTask; + private readonly TaskCompletionSource _completionSource = new(); + private bool _wantsNewFrame = true; + + public ClientScreenServerConnection(WebSocket webSocket) + { + _socket = webSocket; + _readTask = Read(); + } + + public Task Done => _completionSource.Task; + + private async Task Read() + { + while (true) + { + await _socket.ReceiveAsync(ArraySegment.Empty, default); + _wantsNewFrame = true; + } + } + + public Task Send(DisplayPixelBuffer buf) + { + if (!_wantsNewFrame) + return Task.CompletedTask; + return _socket.SendAsync(buf.Data, WebSocketMessageType.Binary, true, default); + } +} diff --git a/TanksServer/FixedSizeBitFieldView.cs b/TanksServer/FixedSizeBitFieldView.cs index fcd9671..20f9076 100644 --- a/TanksServer/FixedSizeBitFieldView.cs +++ b/TanksServer/FixedSizeBitFieldView.cs @@ -7,11 +7,7 @@ public sealed class FixedSizeBitFieldView(Memory data) : IList public int Count => data.Length * 8; public bool IsReadOnly => false; - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); public IEnumerator GetEnumerator() { return Enumerable().GetEnumerator(); @@ -69,33 +65,10 @@ public sealed class FixedSizeBitFieldView(Memory data) : IList } } - public void Add(bool item) - { - throw new NotSupportedException(); - } - - public bool Contains(bool item) - { - throw new NotSupportedException(); - } - - public bool Remove(bool item) - { - throw new NotSupportedException(); - } - - 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(); - } + public void Add(bool item) => throw new NotSupportedException(); + public bool Contains(bool item) => throw new NotSupportedException(); + public bool Remove(bool item) => throw new NotSupportedException(); + 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(); } diff --git a/TanksServer/GlobalUsings.cs b/TanksServer/GlobalUsings.cs index cc5fbc3..29ee885 100644 --- a/TanksServer/GlobalUsings.cs +++ b/TanksServer/GlobalUsings.cs @@ -1,3 +1,4 @@ global using System; global using System.Collections.Generic; +global using System.Linq; global using System.Threading.Tasks; diff --git a/TanksServer/Program.cs b/TanksServer/Program.cs index 85fc25c..1d51777 100644 --- a/TanksServer/Program.cs +++ b/TanksServer/Program.cs @@ -1,5 +1,7 @@ +using System.IO; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.FileProviders; namespace TanksServer; @@ -11,18 +13,25 @@ internal static class Program var display = app.Services.GetRequiredService(); var mapDrawer = app.Services.GetRequiredService(); + var clientScreenServer = app.Services.GetRequiredService(); var buffer = mapDrawer.CreateGameFieldPixelBuffer(); mapDrawer.DrawInto(buffer); await display.Send(buffer); - app.UseWebSockets(); + var clientFileProvider = new PhysicalFileProvider(Path.Combine(app.Environment.ContentRootPath, "client")); + app.UseDefaultFiles(new DefaultFilesOptions { FileProvider = clientFileProvider }); + app.UseStaticFiles(new StaticFileOptions { FileProvider = clientFileProvider }); + app.UseWebSockets(); app.Map("/screen", async context => { if (!context.WebSockets.IsWebSocketRequest) return; - using var ws = await context.WebSockets.AcceptWebSocketAsync(); + var ws = await context.WebSockets.AcceptWebSocketAsync(); + var client = clientScreenServer.AddClient(ws); + await client.Send(buffer); + await client.Done; }); await app.RunAsync(); @@ -35,6 +44,7 @@ internal static class Program builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); + builder.Services.AddSingleton(); return builder.Build(); } diff --git a/TanksServer/appsettings.Development.json b/TanksServer/appsettings.Development.json index a34cd70..bf10e05 100644 --- a/TanksServer/appsettings.Development.json +++ b/TanksServer/appsettings.Development.json @@ -1,8 +1,8 @@ { "Logging": { "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" + "Default": "Debug", + "Microsoft.AspNetCore": "Information" } } } diff --git a/TanksServer/appsettings.json b/TanksServer/appsettings.json index 23160a4..525e690 100644 --- a/TanksServer/appsettings.json +++ b/TanksServer/appsettings.json @@ -5,5 +5,12 @@ "Microsoft.AspNetCore": "Warning" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "Kestrel": { + "Endpoints": { + "Http": { + "Url": "http://localhost:3000" + } + } + } }