wip client "secret"
This commit is contained in:
		
							parent
							
								
									698271ae9f
								
							
						
					
					
						commit
						b192cd7da0
					
				
					 15 changed files with 117 additions and 71 deletions
				
			
		|  | @ -22,8 +22,8 @@ internal sealed class CollideBulletsWithTanks( | |||
|                 continue; | ||||
| 
 | ||||
|             if (bullet.Owner != tank.Owner) | ||||
|                 bullet.Owner.Kills++; | ||||
|             tank.Owner.Deaths++; | ||||
|                 bullet.Owner.Scores.Kills++; | ||||
|             tank.Owner.Scores.Deaths++; | ||||
| 
 | ||||
|             tanks.Remove(tank); | ||||
|             spawnQueue.EnqueueForDelayedSpawn(tank.Owner); | ||||
|  |  | |||
|  | @ -36,7 +36,7 @@ internal sealed class MoveTanks( | |||
|                 return false; | ||||
|         } | ||||
| 
 | ||||
|         var angle = tank.Rotation * 2d * Math.PI; | ||||
|         var angle = tank.Orientation / 16d * 2d * Math.PI; | ||||
|         var newX = tank.Position.X + Math.Sin(angle) * speed; | ||||
|         var newY = tank.Position.Y - Math.Cos(angle) * speed; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,10 @@ | |||
| namespace TanksServer.GameLogic; | ||||
| 
 | ||||
| internal sealed class RotateTanks(TankManager tanks, IOptions<TanksConfiguration> options) : ITickStep | ||||
| internal sealed class RotateTanks( | ||||
|     TankManager tanks, | ||||
|     IOptions<TanksConfiguration> options, | ||||
|     ILogger<RotateTanks> logger | ||||
| ) : ITickStep | ||||
| { | ||||
|     private readonly TanksConfiguration _config = options.Value; | ||||
| 
 | ||||
|  | @ -10,10 +14,20 @@ internal sealed class RotateTanks(TankManager tanks, IOptions<TanksConfiguration | |||
|         { | ||||
|             var player = tank.Owner; | ||||
| 
 | ||||
|             if (player.Controls.TurnLeft) | ||||
|                 tank.Rotation -= _config.TurnSpeed / 16d; | ||||
|             if (player.Controls.TurnRight) | ||||
|                 tank.Rotation += _config.TurnSpeed / 16d; | ||||
|             switch (player.Controls) | ||||
|             { | ||||
|                 case { TurnRight: true, TurnLeft: true }: | ||||
|                 case { TurnRight: false, TurnLeft: false }: | ||||
|                     continue; | ||||
|                 case { TurnLeft: true }: | ||||
|                     tank.Rotation -= _config.TurnSpeed; | ||||
|                     break; | ||||
|                 case { TurnRight: true }: | ||||
|                     tank.Rotation += _config.TurnSpeed; | ||||
|                     break; | ||||
|             } | ||||
| 
 | ||||
|             logger.LogTrace("rotated tank to {}", tank.Rotation); | ||||
|         } | ||||
| 
 | ||||
|         return Task.CompletedTask; | ||||
|  |  | |||
|  | @ -25,12 +25,13 @@ internal sealed class ShootFromTanks( | |||
| 
 | ||||
|         tank.NextShotAfter = DateTime.Now.AddMilliseconds(_config.ShootDelayMs); | ||||
| 
 | ||||
|         var angle = tank.Rotation * 2 * Math.PI; | ||||
|         var rotation = tank.Orientation / 16d; | ||||
|         var angle = rotation * 2d * Math.PI; | ||||
|         var position = new FloatPosition( | ||||
|             tank.Position.X + Math.Sin(angle) * _config.BulletSpeed, | ||||
|             tank.Position.Y - Math.Cos(angle) * _config.BulletSpeed | ||||
|         ); | ||||
| 
 | ||||
|         bulletManager.Spawn(new Bullet(tank.Owner, position, tank.Rotation)); | ||||
|         bulletManager.Spawn(new Bullet(tank.Owner, position, rotation)); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -32,12 +32,11 @@ internal sealed class DrawTanksStep : IDrawStep | |||
|         foreach (var tank in _tanks) | ||||
|         { | ||||
|             var tankPosition = tank.Bounds.TopLeft; | ||||
|             var orientation = (int)Math.Round(tank.Rotation * 16d) % 16; | ||||
| 
 | ||||
|             for (byte dy = 0; dy < MapService.TileSize; dy++) | ||||
|             for (byte dx = 0; dx < MapService.TileSize; dx++) | ||||
|             { | ||||
|                 if (!TankSpriteAt(dx, dy, orientation)) | ||||
|                 if (!TankSpriteAt(dx, dy, tank.Orientation)) | ||||
|                     continue; | ||||
| 
 | ||||
|                 var (x, y) = tankPosition.GetPixelRelative(dx, dy); | ||||
|  |  | |||
|  | @ -3,4 +3,6 @@ using System.Text.Json.Serialization; | |||
| namespace TanksServer.Interactivity; | ||||
| 
 | ||||
| [JsonSerializable(typeof(Player))] | ||||
| [JsonSerializable(typeof(IEnumerable<Player>))] | ||||
| [JsonSerializable(typeof(Guid))] | ||||
| internal sealed partial class AppSerializerContext : JsonSerializerContext; | ||||
|  |  | |||
|  | @ -7,9 +7,19 @@ internal sealed class PlayerServer(ILogger<PlayerServer> logger, SpawnQueue spaw | |||
| { | ||||
|     private readonly ConcurrentDictionary<string, Player> _players = new(); | ||||
| 
 | ||||
|     public Player GetOrAdd(string name) | ||||
|     public Player? GetOrAdd(string name, Guid id) | ||||
|     { | ||||
|         var player = _players.GetOrAdd(name, AddAndSpawn); | ||||
|         Player AddAndSpawn() | ||||
|         { | ||||
|             var player = new Player(name, id); | ||||
|             spawnQueue.EnqueueForImmediateSpawn(player); | ||||
|             return player; | ||||
|         } | ||||
| 
 | ||||
|         var player = _players.GetOrAdd(name, _ => AddAndSpawn()); | ||||
|         if (player.Id != id) | ||||
|             return null; | ||||
| 
 | ||||
|         logger.LogInformation("player {} (re)joined", player.Id); | ||||
|         return player; | ||||
|     } | ||||
|  | @ -29,11 +39,4 @@ internal sealed class PlayerServer(ILogger<PlayerServer> logger, SpawnQueue spaw | |||
|     } | ||||
| 
 | ||||
|     public IEnumerable<Player> GetAll() => _players.Values; | ||||
| 
 | ||||
|     private Player AddAndSpawn(string name) | ||||
|     { | ||||
|         var player = new Player(name); | ||||
|         spawnQueue.EnqueueForImmediateSpawn(player); | ||||
|         return player; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -71,13 +71,13 @@ internal sealed class SendToServicePointDisplay : ITickStep | |||
|     private void RefreshScores() | ||||
|     { | ||||
|         var playersToDisplay = _players.GetAll() | ||||
|             .OrderByDescending(p => p.Kills) | ||||
|             .OrderByDescending(p => p.Scores.Kills) | ||||
|             .Take(ScoresPlayerRows); | ||||
| 
 | ||||
|         ushort row = 2; | ||||
|         foreach (var p in playersToDisplay) | ||||
|         { | ||||
|             var score = p.Kills.ToString(); | ||||
|             var score = p.Scores.Kills.ToString(); | ||||
|             var nameLength = Math.Min(p.Name.Length, ScoresWidth - score.Length - 1); | ||||
| 
 | ||||
|             var name = p.Name[..nameLength]; | ||||
|  |  | |||
|  | @ -2,17 +2,15 @@ using System.Text.Json.Serialization; | |||
| 
 | ||||
| namespace TanksServer.Models; | ||||
| 
 | ||||
| internal sealed class Player(string name) | ||||
| internal sealed class Player(string name, Guid id) | ||||
| { | ||||
|     public string Name => name; | ||||
| 
 | ||||
|     public Guid Id { get; } = Guid.NewGuid(); | ||||
|     [JsonIgnore] public Guid Id => id; | ||||
| 
 | ||||
|     [JsonIgnore] public PlayerControls Controls { get; } = new(); | ||||
| 
 | ||||
|     public int Kills { get; set; } | ||||
| 
 | ||||
|     public int Deaths { get; set; } | ||||
|     public Scores Scores { get; } = new(); | ||||
| 
 | ||||
|     public DateTime LastInput { get; set; } = DateTime.Now; | ||||
| } | ||||
|  |  | |||
|  | @ -23,8 +23,8 @@ internal static class PositionHelpers | |||
|     public static FloatPosition ToFloatPosition(this PixelPosition position) => new(position.X, position.Y); | ||||
| 
 | ||||
| 
 | ||||
|     public static double Distance(this FloatPosition p1, FloatPosition p2) => | ||||
|         Math.Sqrt( | ||||
|     public static double Distance(this FloatPosition p1, FloatPosition p2) | ||||
|         => Math.Sqrt( | ||||
|             Math.Pow(p1.X - p2.X, 2) + | ||||
|             Math.Pow(p1.Y - p2.Y, 2) | ||||
|         ); | ||||
|  |  | |||
							
								
								
									
										8
									
								
								TanksServer/Models/Scores.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								TanksServer/Models/Scores.cs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| namespace TanksServer.Models; | ||||
| 
 | ||||
| internal sealed record class Scores(int Kills = 0, int Deaths = 0) | ||||
| { | ||||
|     public int Kills { get; set; } = Kills; | ||||
| 
 | ||||
|     public int Deaths { get; set; } = Deaths; | ||||
| } | ||||
|  | @ -1,5 +1,4 @@ | |||
| using System.Diagnostics; | ||||
| using TanksServer.GameLogic; | ||||
| 
 | ||||
| namespace TanksServer.Models; | ||||
| 
 | ||||
|  | @ -28,12 +27,14 @@ internal sealed class Tank(Player player, FloatPosition spawnPosition) : IMapEnt | |||
| 
 | ||||
|     public PixelBounds Bounds => GetBoundsForCenter(Position); | ||||
| 
 | ||||
|     public int Orientation => (int)Math.Round(Rotation * 16) % 16; | ||||
| 
 | ||||
|     public static PixelBounds GetBoundsForCenter(FloatPosition position) | ||||
|     { | ||||
|         var pixelPosition = position.ToPixelPosition(); | ||||
|         return new PixelBounds( | ||||
|             pixelPosition.GetPixelRelative(-3, -3), | ||||
|             pixelPosition.GetPixelRelative(4, 4) | ||||
|             pixelPosition.GetPixelRelative(-4, -4), | ||||
|             pixelPosition.GetPixelRelative(3, 3) | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -25,18 +25,29 @@ public static class Program | |||
|         app.UseDefaultFiles(new DefaultFilesOptions { FileProvider = clientFileProvider }); | ||||
|         app.UseStaticFiles(new StaticFileOptions { FileProvider = clientFileProvider }); | ||||
| 
 | ||||
|         app.MapGet("/player", playerService.GetOrAdd); | ||||
|         app.MapPost("/player", (string name, Guid id) => | ||||
|         { | ||||
|             var player = playerService.GetOrAdd(name, id); | ||||
|             return player != null | ||||
|                 ? Results.Ok(player.Id) | ||||
|                 : Results.Unauthorized(); | ||||
|         }); | ||||
|         app.MapGet("/player", ([FromQuery] Guid id) => | ||||
|             playerService.TryGet(id, out var foundPlayer) | ||||
|                 ? Results.Ok((object?)foundPlayer) | ||||
|                 : Results.NotFound() | ||||
|         ); | ||||
| 
 | ||||
|         app.Map("/screen", async context => | ||||
|         app.MapGet("/scores", () => playerService.GetAll()); | ||||
| 
 | ||||
|         app.Map("/screen", async (HttpContext context) => | ||||
|         { | ||||
|             if (!context.WebSockets.IsWebSocketRequest) | ||||
|             { | ||||
|                 context.Response.StatusCode = StatusCodes.Status400BadRequest; | ||||
|                 return; | ||||
|             } | ||||
|                 return Results.BadRequest(); | ||||
| 
 | ||||
|             using var ws = await context.WebSockets.AcceptWebSocketAsync(); | ||||
|             await clientScreenServer.HandleClient(ws); | ||||
|             return null; | ||||
|         }); | ||||
| 
 | ||||
|         app.Map("/controls", async (HttpContext context, [FromQuery] Guid playerId) => | ||||
|  | @ -49,7 +60,7 @@ public static class Program | |||
| 
 | ||||
|             using var ws = await context.WebSockets.AcceptWebSocketAsync(); | ||||
|             await controlsServer.HandleClient(ws, player); | ||||
|             return Results.Ok(); | ||||
|             return null; | ||||
|         }); | ||||
| 
 | ||||
|         app.Run(); | ||||
|  | @ -122,4 +133,4 @@ public static class Program | |||
| 
 | ||||
|         return app; | ||||
|     } | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -1,33 +1,34 @@ | |||
| { | ||||
|   "Logging": { | ||||
|     "LogLevel": { | ||||
|       "Default": "Information", | ||||
|       "Microsoft.AspNetCore": "Warning", | ||||
|       "TanksServer": "Debug", | ||||
|       "Microsoft.AspNetCore.HttpLogging": "Information" | ||||
|     "Logging": { | ||||
|         "LogLevel": { | ||||
|             "Default": "Information", | ||||
|             "Microsoft.AspNetCore": "Warning", | ||||
|             "TanksServer": "Debug", | ||||
|             "Microsoft.AspNetCore.HttpLogging": "Information", | ||||
|             "TanksServer.GameLogic.RotateTanks": "Trace" | ||||
|         } | ||||
|     }, | ||||
|     "AllowedHosts": "*", | ||||
|     "Kestrel": { | ||||
|         "Endpoints": { | ||||
|             "Http": { | ||||
|                 "Url": "http://localhost:3000" | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "ServicePointDisplay": { | ||||
|         "Enable": true, | ||||
|         "Hostname": "172.23.42.29", | ||||
|         "Port": 2342 | ||||
|     }, | ||||
|     "Tanks": { | ||||
|         "MoveSpeed": 1.5, | ||||
|         "TurnSpeed": 0.02, | ||||
|         "ShootDelayMs": 450, | ||||
|         "BulletSpeed":4 | ||||
|     }, | ||||
|     "Players": { | ||||
|         "SpawnDelayMs": 3000, | ||||
|         "IdleTimeoutMs": 30000 | ||||
|     } | ||||
|   }, | ||||
|   "AllowedHosts": "*", | ||||
|   "Kestrel": { | ||||
|     "Endpoints": { | ||||
|       "Http": { | ||||
|         "Url": "http://localhost:3000" | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   "ServicePointDisplay": { | ||||
|     "Enable": true, | ||||
|     "Hostname": "172.23.42.29", | ||||
|     "Port": 2342 | ||||
|   }, | ||||
|   "Tanks": { | ||||
|     "MoveSpeed": 1.4, | ||||
|     "TurnSpeed": 0.4, | ||||
|     "ShootDelayMs": 400, | ||||
|     "BulletSpeed": 3 | ||||
|   }, | ||||
|   "Players": { | ||||
|     "SpawnDelayMs": 3000, | ||||
|     "IdleTimeoutMs": 30000 | ||||
|   } | ||||
| } | ||||
|  |  | |||
							
								
								
									
										8
									
								
								TanksServer/userRequests.http
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								TanksServer/userRequests.http
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| POST localhost/player?name=test&id=a31d35c2-1d9e-4a34-93e5-680195c6a9d2 | ||||
| 
 | ||||
| ### | ||||
| 
 | ||||
| GET localhost/scores | ||||
| 
 | ||||
| ### | ||||
| 
 | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Vinzenz Schroeter
						Vinzenz Schroeter