first image in client
This commit is contained in:
		
							parent
							
								
									ea7f12b0c2
								
							
						
					
					
						commit
						bc8d5ad6d0
					
				
					 6 changed files with 82 additions and 39 deletions
				
			
		
							
								
								
									
										52
									
								
								TanksServer/ClientScreenServer.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								TanksServer/ClientScreenServer.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,52 @@
 | 
			
		|||
using System.Net.WebSockets;
 | 
			
		||||
 | 
			
		||||
namespace TanksServer;
 | 
			
		||||
 | 
			
		||||
internal sealed class ClientScreenServer
 | 
			
		||||
{
 | 
			
		||||
    private readonly List<ClientScreenServerConnection> _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<byte>.Empty, default);
 | 
			
		||||
            _wantsNewFrame = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Task Send(DisplayPixelBuffer buf)
 | 
			
		||||
    {
 | 
			
		||||
        if (!_wantsNewFrame)
 | 
			
		||||
            return Task.CompletedTask;
 | 
			
		||||
        return _socket.SendAsync(buf.Data, WebSocketMessageType.Binary, true, default);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -7,11 +7,7 @@ public sealed class FixedSizeBitFieldView(Memory<byte> data) : IList<bool>
 | 
			
		|||
    public int Count => data.Length * 8;
 | 
			
		||||
    public bool IsReadOnly => false;
 | 
			
		||||
 | 
			
		||||
    IEnumerator IEnumerable.GetEnumerator()
 | 
			
		||||
    {
 | 
			
		||||
        return GetEnumerator();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
 | 
			
		||||
    public IEnumerator<bool> GetEnumerator()
 | 
			
		||||
    {
 | 
			
		||||
        return Enumerable().GetEnumerator();
 | 
			
		||||
| 
						 | 
				
			
			@ -69,33 +65,10 @@ public sealed class FixedSizeBitFieldView(Memory<byte> data) : IList<bool>
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,4 @@
 | 
			
		|||
global using System;
 | 
			
		||||
global using System.Collections.Generic;
 | 
			
		||||
global using System.Linq;
 | 
			
		||||
global using System.Threading.Tasks;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<ServicePointDisplay>();
 | 
			
		||||
        var mapDrawer = app.Services.GetRequiredService<MapDrawer>();
 | 
			
		||||
        var clientScreenServer = app.Services.GetRequiredService<ClientScreenServer>();
 | 
			
		||||
 | 
			
		||||
        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<ServicePointDisplay>();
 | 
			
		||||
        builder.Services.AddSingleton<MapService>();
 | 
			
		||||
        builder.Services.AddSingleton<MapDrawer>();
 | 
			
		||||
        builder.Services.AddSingleton<ClientScreenServer>();
 | 
			
		||||
 | 
			
		||||
        return builder.Build();
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,8 @@
 | 
			
		|||
{
 | 
			
		||||
    "Logging": {
 | 
			
		||||
        "LogLevel": {
 | 
			
		||||
            "Default": "Information",
 | 
			
		||||
            "Microsoft.AspNetCore": "Warning"
 | 
			
		||||
            "Default": "Debug",
 | 
			
		||||
            "Microsoft.AspNetCore": "Information"
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,5 +5,12 @@
 | 
			
		|||
            "Microsoft.AspNetCore": "Warning"
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "AllowedHosts": "*"
 | 
			
		||||
    "AllowedHosts": "*",
 | 
			
		||||
    "Kestrel": {
 | 
			
		||||
        "Endpoints": {
 | 
			
		||||
            "Http": {
 | 
			
		||||
                "Url": "http://localhost:3000"
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue