wip client "secret"

This commit is contained in:
Vinzenz Schroeter 2024-04-13 18:35:36 +02:00
parent 698271ae9f
commit b192cd7da0
15 changed files with 117 additions and 71 deletions

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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));
}
}

View file

@ -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);

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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];

View file

@ -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;
}

View file

@ -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)
);

View 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;
}

View file

@ -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)
);
}
}

View file

@ -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;
}
}
}

View file

@ -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
}
}

View file

@ -0,0 +1,8 @@
POST localhost/player?name=test&id=a31d35c2-1d9e-4a34-93e5-680195c6a9d2
###
GET localhost/scores
###