73 lines
		
	
	
	
		
			2.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			73 lines
		
	
	
	
		
			2.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System.Net.WebSockets;
 | |
| using DisplayCommands;
 | |
| using TanksServer.Graphics;
 | |
| 
 | |
| namespace TanksServer.Interactivity;
 | |
| 
 | |
| internal sealed class ClientScreenServerConnection(
 | |
|     WebSocket webSocket,
 | |
|     ILogger<ClientScreenServerConnection> logger,
 | |
|     string? playerName = null
 | |
| ) : WebsocketServerConnection(logger, new ByteChannelWebSocket(webSocket, logger, 0))
 | |
| {
 | |
|     private bool _wantsFrameOnTick = true;
 | |
| 
 | |
|     private PixelGrid? _lastSentPixels;
 | |
|     private PixelGrid? _nextPixels;
 | |
|     private readonly PlayerScreenData? _nextPlayerData = playerName != null ? new PlayerScreenData(logger) : null;
 | |
| 
 | |
|     protected override async ValueTask HandleMessageLockedAsync(Memory<byte> _)
 | |
|     {
 | |
|         if (_nextPixels == null)
 | |
|         {
 | |
|             _wantsFrameOnTick = true;
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         await SendNowAsync();
 | |
|     }
 | |
| 
 | |
|     public ValueTask OnGameTickAsync(PixelGrid pixels, GamePixelGrid gamePixelGrid) => LockedAsync(async () =>
 | |
|     {
 | |
|         if (pixels == _lastSentPixels)
 | |
|             return;
 | |
| 
 | |
|         if (_nextPlayerData != null)
 | |
|         {
 | |
|             _nextPlayerData.Clear();
 | |
|             foreach (var gamePixel in gamePixelGrid)
 | |
|             {
 | |
|                 if (!gamePixel.EntityType.HasValue)
 | |
|                     continue;
 | |
|                 _nextPlayerData.Add(gamePixel.EntityType.Value, gamePixel.BelongsTo?.Name == playerName);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         _nextPixels = pixels;
 | |
|         if (_wantsFrameOnTick)
 | |
|             _ = await SendNowAsync();
 | |
|     });
 | |
| 
 | |
|     private async ValueTask<bool> SendNowAsync()
 | |
|     {
 | |
|         var pixels = _nextPixels
 | |
|                      ?? throw new InvalidOperationException("next pixels not set");
 | |
| 
 | |
|         try
 | |
|         {
 | |
|             await Socket.SendBinaryAsync(pixels.Data, _nextPlayerData == null);
 | |
|             if (_nextPlayerData != null)
 | |
|                 await Socket.SendBinaryAsync(_nextPlayerData.GetPacket());
 | |
| 
 | |
|             _lastSentPixels = _nextPixels;
 | |
|             _nextPixels = null;
 | |
|             _wantsFrameOnTick = false;
 | |
|             return true;
 | |
|         }
 | |
|         catch (WebSocketException ex)
 | |
|         {
 | |
|             Logger.LogWarning(ex, "send failed");
 | |
|             return false;
 | |
|         }
 | |
|     }
 | |
| }
 | 
