diff --git a/.envrc b/.envrc index 1d953f4..3550a30 100644 --- a/.envrc +++ b/.envrc @@ -1 +1 @@ -use nix +use flake diff --git a/flake.lock b/flake.lock index 0f7109b..4583957 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1730327045, - "narHash": "sha256-xKel5kd1AbExymxoIfQ7pgcX6hjw9jCgbiBjiUfSVJ8=", + "lastModified": 1731797254, + "narHash": "sha256-df3dJApLPhd11AlueuoN0Q4fHo/hagP75LlM5K1sz9g=", "owner": "nixos", "repo": "nixpkgs", - "rev": "080166c15633801df010977d9d7474b4a6c549d7", + "rev": "e8c38b73aeb218e27163376a2d617e61a2ad9b59", "type": "github" }, "original": { diff --git a/tanks-backend/TanksServer.sln b/tanks-backend/TanksServer.sln index 01b194e..9c43f9a 100644 --- a/tanks-backend/TanksServer.sln +++ b/tanks-backend/TanksServer.sln @@ -1,5 +1,6 @@  Microsoft Visual Studio Solution File, Format Version 12.00 +# Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TanksServer", "TanksServer\TanksServer.csproj", "{D88BF376-47A4-4C72-ADD1-983F9285C351}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shared", "shared", "{12DB7D48-1BB2-488B-B4D9-4126087D2F8C}" @@ -9,7 +10,19 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shared", "shared", "{12DB7D ..\.envrc = ..\.envrc EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServicePoint", "servicepoint/crates/servicepoint_binding_cs/ServicePoint/ServicePoint.csproj", "{DFCC69ED-E02B-4631-8A23-5D394BA01E03}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "servicepoint", "servicepoint", "{A10FB29A-9078-4E90-9CE1-E6C2B5209E19}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "crates", "crates", "{656A7CBA-9445-41CC-B1AF-A6897AAC9F17}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "servicepoint_binding_uniffi", "servicepoint_binding_uniffi", "{5FD9FAD7-07BA-4DF9-8C84-15A9558373F1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "libraries", "libraries", "{6082A0DC-5345-48C8-BA2E-667754A2F0E9}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "csharp", "csharp", "{D8A3290B-5DFB-43C6-99EE-56AB5F53F468}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServicePoint", "servicepoint\crates\servicepoint_binding_uniffi\libraries\csharp\ServicePoint\ServicePoint.csproj", "{D1DDCD0D-6152-45E6-B673-DD78C466BDC3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServicePoint.Tests", "servicepoint\crates\servicepoint_binding_uniffi\libraries\csharp\ServicePoint.Tests\ServicePoint.Tests.csproj", "{EF42D6B7-70B1-490B-BB5F-5A44D1309A7C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -21,9 +34,21 @@ Global {D88BF376-47A4-4C72-ADD1-983F9285C351}.Debug|Any CPU.Build.0 = Debug|Any CPU {D88BF376-47A4-4C72-ADD1-983F9285C351}.Release|Any CPU.ActiveCfg = Release|Any CPU {D88BF376-47A4-4C72-ADD1-983F9285C351}.Release|Any CPU.Build.0 = Release|Any CPU - {DFCC69ED-E02B-4631-8A23-5D394BA01E03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DFCC69ED-E02B-4631-8A23-5D394BA01E03}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DFCC69ED-E02B-4631-8A23-5D394BA01E03}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DFCC69ED-E02B-4631-8A23-5D394BA01E03}.Release|Any CPU.Build.0 = Release|Any CPU + {D1DDCD0D-6152-45E6-B673-DD78C466BDC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D1DDCD0D-6152-45E6-B673-DD78C466BDC3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D1DDCD0D-6152-45E6-B673-DD78C466BDC3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D1DDCD0D-6152-45E6-B673-DD78C466BDC3}.Release|Any CPU.Build.0 = Release|Any CPU + {EF42D6B7-70B1-490B-BB5F-5A44D1309A7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EF42D6B7-70B1-490B-BB5F-5A44D1309A7C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EF42D6B7-70B1-490B-BB5F-5A44D1309A7C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EF42D6B7-70B1-490B-BB5F-5A44D1309A7C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {656A7CBA-9445-41CC-B1AF-A6897AAC9F17} = {A10FB29A-9078-4E90-9CE1-E6C2B5209E19} + {5FD9FAD7-07BA-4DF9-8C84-15A9558373F1} = {656A7CBA-9445-41CC-B1AF-A6897AAC9F17} + {6082A0DC-5345-48C8-BA2E-667754A2F0E9} = {5FD9FAD7-07BA-4DF9-8C84-15A9558373F1} + {D8A3290B-5DFB-43C6-99EE-56AB5F53F468} = {6082A0DC-5345-48C8-BA2E-667754A2F0E9} + {D1DDCD0D-6152-45E6-B673-DD78C466BDC3} = {D8A3290B-5DFB-43C6-99EE-56AB5F53F468} + {EF42D6B7-70B1-490B-BB5F-5A44D1309A7C} = {D8A3290B-5DFB-43C6-99EE-56AB5F53F468} EndGlobalSection EndGlobal diff --git a/tanks-backend/TanksServer/Endpoints.cs b/tanks-backend/TanksServer/Endpoints.cs index 74ec4cb..6b40fbd 100644 --- a/tanks-backend/TanksServer/Endpoints.cs +++ b/tanks-backend/TanksServer/Endpoints.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Text; using System.Text.Json; @@ -7,7 +8,6 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Diagnostics.HealthChecks; -using ServicePoint; using TanksServer.GameLogic; using TanksServer.Interactivity; @@ -22,6 +22,8 @@ internal sealed class Endpoints( Connection displayConnection ) { + [RequiresUnreferencedCode("Calls Microsoft.AspNetCore.Builder.EndpointRouteBuilderExtensions.MapPost(String, Delegate)")] + [RequiresDynamicCode("Calls Microsoft.AspNetCore.Builder.EndpointRouteBuilderExtensions.MapPost(String, Delegate)")] public void Map(WebApplication app) { app.MapPost("/player", PostPlayer); @@ -31,7 +33,7 @@ internal sealed class Endpoints( app.Map("/controls", ConnectControlsAsync); app.MapGet("/map", () => mapService.MapNames); app.MapPost("/map", PostMap); - app.MapPost("/resetDisplay", () => displayConnection.Send(Command.HardReset().IntoPacket())); + app.MapPost("/resetDisplay", () => displayConnection.Send(Command.HardReset())); app.MapGet("/map/{name}", GetMapByName); app.MapHealthChecks("/health", new HealthCheckOptions @@ -117,7 +119,7 @@ internal sealed class Endpoints( if (!mapService.TryGetPreview(name, out var preview)) return TypedResults.NotFound(); - var mapInfo = new MapInfo(prototype.Name, prototype.GetType().Name, preview.Data.ToArray()); + var mapInfo = new MapInfo(prototype.Name, prototype.GetType().Name, preview.CopyRaw()); return TypedResults.Ok(mapInfo); } diff --git a/tanks-backend/TanksServer/GameLogic/CollideBullets.cs b/tanks-backend/TanksServer/GameLogic/CollideBullets.cs index c75fe6a..05dfe5a 100644 --- a/tanks-backend/TanksServer/GameLogic/CollideBullets.cs +++ b/tanks-backend/TanksServer/GameLogic/CollideBullets.cs @@ -88,13 +88,13 @@ internal sealed class CollideBullets : ITickStep pixel = pixel.GetPixelRelative(-4, -4); for (short dx = 0; dx < _explosiveSprite.Width; dx++) - for (short dy = 0; dy < _explosiveSprite.Height; dy++) - { - if (!_explosiveSprite[dx, dy].HasValue) - continue; + for (short dy = 0; dy < _explosiveSprite.Height; dy++) + { + if (!_explosiveSprite[dx, dy].HasValue) + continue; - Core(pixel.GetPixelRelative(dx, dy)); - } + Core(pixel.GetPixelRelative(dx, dy)); + } return; diff --git a/tanks-backend/TanksServer/GameLogic/EmptyTileFinder.cs b/tanks-backend/TanksServer/GameLogic/EmptyTileFinder.cs index 16a34cf..3f1aac1 100644 --- a/tanks-backend/TanksServer/GameLogic/EmptyTileFinder.cs +++ b/tanks-backend/TanksServer/GameLogic/EmptyTileFinder.cs @@ -10,22 +10,22 @@ internal sealed class EmptyTileFinder( var maxMinDistance = 0d; TilePosition spawnTile = default; for (ushort x = 1; x < MapService.TilesPerRow - 1; x++) - for (ushort y = 1; y < MapService.TilesPerColumn - 1; y++) - { - var tile = new TilePosition(x, y); - if (mapService.Current.IsWall(tile)) - continue; + for (ushort y = 1; y < MapService.TilesPerColumn - 1; y++) + { + var tile = new TilePosition(x, y); + if (mapService.Current.IsWall(tile)) + continue; - var tilePixelCenter = tile.GetCenter().ToFloatPosition(); - var minDistance = entityManager.AllEntities - .Select(entity => entity.Position.Distance(tilePixelCenter)) - .Aggregate(double.MaxValue, Math.Min); - if (minDistance <= maxMinDistance) - continue; + var tilePixelCenter = tile.GetCenter().ToFloatPosition(); + var minDistance = entityManager.AllEntities + .Select(entity => entity.Position.Distance(tilePixelCenter)) + .Aggregate(double.MaxValue, Math.Min); + if (minDistance <= maxMinDistance) + continue; - maxMinDistance = minDistance; - spawnTile = tile; - } + maxMinDistance = minDistance; + spawnTile = tile; + } return spawnTile; } diff --git a/tanks-backend/TanksServer/GameLogic/GameTickWorker.cs b/tanks-backend/TanksServer/GameLogic/GameTickWorker.cs index e684b80..de806bd 100644 --- a/tanks-backend/TanksServer/GameLogic/GameTickWorker.cs +++ b/tanks-backend/TanksServer/GameLogic/GameTickWorker.cs @@ -7,13 +7,11 @@ internal sealed class GameTickWorker( IEnumerable steps, IHostApplicationLifetime lifetime, ILogger logger -) : IHostedLifecycleService, IDisposable +) : BackgroundService, IDisposable { - private readonly CancellationTokenSource _cancellation = new(); - private readonly TaskCompletionSource _shutdownCompletion = new(); private readonly List _steps = steps.ToList(); - public async Task StartedAsync(CancellationToken cancellationToken) + protected override async Task ExecuteAsync(CancellationToken cancellationToken) { await Task.Yield(); @@ -23,7 +21,7 @@ internal sealed class GameTickWorker( try { - while (!_cancellation.IsCancellationRequested) + while (!cancellationToken.IsCancellationRequested) { var delta = sw.Elapsed; sw.Restart(); @@ -37,19 +35,5 @@ internal sealed class GameTickWorker( logger.LogError(ex, "game tick service crashed"); lifetime.StopApplication(); } - - _shutdownCompletion.SetResult(); } - - public Task StoppingAsync(CancellationToken cancellationToken) => _cancellation.CancelAsync(); - - public Task StopAsync(CancellationToken cancellationToken) => _shutdownCompletion.Task; - - public void Dispose() => _cancellation.Dispose(); - - public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask; - - public Task StartingAsync(CancellationToken cancellationToken) => Task.CompletedTask; - - public Task StoppedAsync(CancellationToken cancellationToken) => Task.CompletedTask; } diff --git a/tanks-backend/TanksServer/GameLogic/Map.cs b/tanks-backend/TanksServer/GameLogic/Map.cs index d83a61d..07123ca 100644 --- a/tanks-backend/TanksServer/GameLogic/Map.cs +++ b/tanks-backend/TanksServer/GameLogic/Map.cs @@ -4,7 +4,7 @@ internal sealed class Map(string name, bool[,] walls) { public string Name => name; - public bool IsWall(int x, int y) => walls[x, y]; + public bool IsWall(ulong x, ulong y) => walls[x, y]; public bool IsWall(PixelPosition position) => walls[position.X, position.Y]; @@ -12,12 +12,12 @@ internal sealed class Map(string name, bool[,] walls) { var pixel = position.ToPixelPosition(); - for (short dx = 0; dx < MapService.TileSize; dx++) - for (short dy = 0; dy < MapService.TileSize; dy++) - { - if (IsWall(pixel.GetPixelRelative(dx, dy))) - return true; - } + for (long dx = 0; dx < (long)MapService.TileSize; dx++) + for (long dy = 0; dy < (long)MapService.TileSize; dy++) + { + if (IsWall(pixel.GetPixelRelative(dx, dy))) + return true; + } return false; } diff --git a/tanks-backend/TanksServer/GameLogic/MapEntityManager.cs b/tanks-backend/TanksServer/GameLogic/MapEntityManager.cs index dd674a1..d3f3b0d 100644 --- a/tanks-backend/TanksServer/GameLogic/MapEntityManager.cs +++ b/tanks-backend/TanksServer/GameLogic/MapEntityManager.cs @@ -37,7 +37,7 @@ internal sealed class MapEntityManager( { Rotation = Random.Shared.NextDouble(), MaxBullets = _rules.MagazineSize, - BulletStats =new BulletStats(_rules.BulletSpeed, 0, false, false) + BulletStats = new BulletStats(_rules.BulletSpeed, 0, false, false) }; _playerTanks[player] = tank; logger.LogInformation("Tank added for player {}", player.Name); diff --git a/tanks-backend/TanksServer/GameLogic/MapService.cs b/tanks-backend/TanksServer/GameLogic/MapService.cs index 816cb0f..a79bd94 100644 --- a/tanks-backend/TanksServer/GameLogic/MapService.cs +++ b/tanks-backend/TanksServer/GameLogic/MapService.cs @@ -1,18 +1,17 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; -using ServicePoint; using TanksServer.Graphics; namespace TanksServer.GameLogic; internal sealed class MapService { - public const ushort TilesPerRow = 44; - public const ushort TilesPerColumn = 20; - public const ushort TileSize = 8; - public const ushort PixelsPerRow = TilesPerRow * TileSize; - public const ushort PixelsPerColumn = TilesPerColumn * TileSize; + public static readonly ulong TilesPerRow = 44; + public static readonly ulong TilesPerColumn = ServicePointConstants.TileHeight; + public static readonly ulong TileSize = ServicePointConstants.TileSize; + public static readonly ulong PixelsPerRow = TilesPerRow * TileSize; + public static readonly ulong PixelsPerColumn = TilesPerColumn * TileSize; private readonly ConcurrentDictionary _mapPrototypes = new(); private readonly ConcurrentDictionary _mapPreviews = new(); diff --git a/tanks-backend/TanksServer/GameLogic/MoveTanks.cs b/tanks-backend/TanksServer/GameLogic/MoveTanks.cs index 0b36bfd..a1841f2 100644 --- a/tanks-backend/TanksServer/GameLogic/MoveTanks.cs +++ b/tanks-backend/TanksServer/GameLogic/MoveTanks.cs @@ -68,13 +68,13 @@ internal sealed class MoveTanks( { var (topLeft, _) = newPosition.GetBoundsForCenter(MapService.TileSize); - for (short y = 0; y < MapService.TileSize; y++) - for (short x = 0; x < MapService.TileSize; x++) - { - var pixelToCheck = topLeft.GetPixelRelative(x, y); - if (map.Current.IsWall(pixelToCheck)) - return true; - } + for (ulong y = 0; y < MapService.TileSize; y++) + for (ulong x = 0; x < MapService.TileSize; x++) + { + var pixelToCheck = topLeft.GetPixelRelative((long)x, (long)y); + if (map.Current.IsWall(pixelToCheck)) + return true; + } return false; } diff --git a/tanks-backend/TanksServer/GameLogic/SpriteMapPrototype.cs b/tanks-backend/TanksServer/GameLogic/SpriteMapPrototype.cs index 202bf98..8d6532b 100644 --- a/tanks-backend/TanksServer/GameLogic/SpriteMapPrototype.cs +++ b/tanks-backend/TanksServer/GameLogic/SpriteMapPrototype.cs @@ -11,7 +11,7 @@ internal sealed class SpriteMapPrototype : MapPrototype public SpriteMapPrototype(string name, Sprite sprite) { - if (sprite.Width != MapService.PixelsPerRow || sprite.Height != MapService.PixelsPerColumn) + if ((ulong)sprite.Width != MapService.PixelsPerRow || (ulong)sprite.Height != MapService.PixelsPerColumn) throw new FileLoadException($"invalid image size in file {Name}"); Name = name; diff --git a/tanks-backend/TanksServer/GameLogic/TextMapPrototype.cs b/tanks-backend/TanksServer/GameLogic/TextMapPrototype.cs index 21f95d8..3c69258 100644 --- a/tanks-backend/TanksServer/GameLogic/TextMapPrototype.cs +++ b/tanks-backend/TanksServer/GameLogic/TextMapPrototype.cs @@ -8,7 +8,7 @@ internal sealed class TextMapPrototype : MapPrototype public TextMapPrototype(string name, string text) { - if (text.Length != MapService.TilesPerColumn * MapService.TilesPerRow) + if ((ulong)text.Length != MapService.TilesPerColumn * MapService.TilesPerRow) throw new ArgumentException($"cannot load map {name}: invalid length"); Name = name; Text = text; @@ -19,20 +19,20 @@ internal sealed class TextMapPrototype : MapPrototype { var walls = new bool[MapService.PixelsPerRow, MapService.PixelsPerColumn]; - for (ushort tileX = 0; tileX < MapService.TilesPerRow; tileX++) - for (ushort tileY = 0; tileY < MapService.TilesPerColumn; tileY++) - { - var tile = new TilePosition(tileX, tileY); - if (Text[tileX + tileY * MapService.TilesPerRow] != '#') - continue; - - for (byte pixelInTileX = 0; pixelInTileX < MapService.TileSize; pixelInTileX++) - for (byte pixelInTileY = 0; pixelInTileY < MapService.TileSize; pixelInTileY++) + for (ulong tileX = 0; tileX < MapService.TilesPerRow; tileX++) + for (ulong tileY = 0; tileY < MapService.TilesPerColumn; tileY++) { - var (x, y) = tile.ToPixelPosition().GetPixelRelative(pixelInTileX, pixelInTileY); - walls[x, y] = true; + var tile = new TilePosition(tileX, tileY); + if (Text[(int)(tileX + tileY * MapService.TilesPerRow)] != '#') + continue; + + for (byte pixelInTileX = 0; pixelInTileX < MapService.TileSize; pixelInTileX++) + for (byte pixelInTileY = 0; pixelInTileY < MapService.TileSize; pixelInTileY++) + { + var (x, y) = tile.ToPixelPosition().GetPixelRelative(pixelInTileX, pixelInTileY); + walls[x, y] = true; + } } - } return new Map(Name, walls); } diff --git a/tanks-backend/TanksServer/GlobalUsings.cs b/tanks-backend/TanksServer/GlobalUsings.cs index 7dab1c6..5c674f0 100644 --- a/tanks-backend/TanksServer/GlobalUsings.cs +++ b/tanks-backend/TanksServer/GlobalUsings.cs @@ -7,3 +7,4 @@ global using System.Threading.Tasks; global using Microsoft.Extensions.Logging; global using Microsoft.Extensions.Options; global using TanksServer.Models; +global using ServicePoint; diff --git a/tanks-backend/TanksServer/Graphics/DrawMapStep.cs b/tanks-backend/TanksServer/Graphics/DrawMapStep.cs index 027e9a5..ba0523d 100644 --- a/tanks-backend/TanksServer/Graphics/DrawMapStep.cs +++ b/tanks-backend/TanksServer/Graphics/DrawMapStep.cs @@ -1,4 +1,3 @@ -using ServicePoint; using TanksServer.GameLogic; namespace TanksServer.Graphics; @@ -9,24 +8,24 @@ internal sealed class DrawMapStep(MapService map) : IDrawStep private static void Draw(GamePixelGrid pixels, Map map) { - for (ushort y = 0; y < MapService.PixelsPerColumn; y++) - for (ushort x = 0; x < MapService.PixelsPerRow; x++) - { - if (!map.IsWall(x, y)) - continue; + for (ulong y = 0; y < MapService.PixelsPerColumn; y++) + for (ulong x = 0; x < MapService.PixelsPerRow; x++) + { + if (!map.IsWall(x, y)) + continue; - pixels[x, y].EntityType = GamePixelEntityType.Wall; - } + pixels[x, y].EntityType = GamePixelEntityType.Wall; + } } public static void Draw(Bitmap pixels, Map map) { - for (ushort y = 0; y < MapService.PixelsPerColumn; y++) - for (ushort x = 0; x < MapService.PixelsPerRow; x++) - { - if (!map.IsWall(x, y)) - continue; - pixels[x, y] = true; - } + for (ulong y = 0; y < MapService.PixelsPerColumn; y++) + for (ulong x = 0; x < MapService.PixelsPerRow; x++) + { + if (!map.IsWall(x, y)) + continue; + pixels.Set(x, y, true); + } } } diff --git a/tanks-backend/TanksServer/Graphics/DrawPowerUpsStep.cs b/tanks-backend/TanksServer/Graphics/DrawPowerUpsStep.cs index c6125ec..87076f8 100644 --- a/tanks-backend/TanksServer/Graphics/DrawPowerUpsStep.cs +++ b/tanks-backend/TanksServer/Graphics/DrawPowerUpsStep.cs @@ -30,16 +30,16 @@ internal sealed class DrawPowerUpsStep(MapEntityManager entityManager) : IDrawSt private static void DrawPowerUp(GamePixelGrid pixels, Sprite sprite, PixelPosition position) { for (byte dy = 0; dy < MapService.TileSize; dy++) - for (byte dx = 0; dx < MapService.TileSize; dx++) - { - var pixelState = sprite[dx, dy]; - if (!pixelState.HasValue) - continue; + for (byte dx = 0; dx < MapService.TileSize; dx++) + { + var pixelState = sprite[dx, dy]; + if (!pixelState.HasValue) + continue; - var (x, y) = position.GetPixelRelative(dx, dy); - pixels[x, y].EntityType = pixelState.Value - ? GamePixelEntityType.PowerUp - : null; - } + var (x, y) = position.GetPixelRelative(dx, dy); + pixels[x, y].EntityType = pixelState.Value + ? GamePixelEntityType.PowerUp + : null; + } } } diff --git a/tanks-backend/TanksServer/Graphics/DrawTanksStep.cs b/tanks-backend/TanksServer/Graphics/DrawTanksStep.cs index 9bd365e..2b592db 100644 --- a/tanks-backend/TanksServer/Graphics/DrawTanksStep.cs +++ b/tanks-backend/TanksServer/Graphics/DrawTanksStep.cs @@ -5,7 +5,7 @@ namespace TanksServer.Graphics; internal sealed class DrawTanksStep(MapEntityManager entityManager) : IDrawStep { private readonly SpriteSheet _tankSprites = - SpriteSheet.FromImageFile("assets/tank.png", MapService.TileSize, MapService.TileSize); + SpriteSheet.FromImageFile("assets/tank.png", (int)MapService.TileSize, (int)MapService.TileSize); public void Draw(GamePixelGrid pixels) { @@ -14,16 +14,16 @@ internal sealed class DrawTanksStep(MapEntityManager entityManager) : IDrawStep var tankPosition = tank.Bounds.TopLeft; for (byte dy = 0; dy < MapService.TileSize; dy++) - for (byte dx = 0; dx < MapService.TileSize; dx++) - { - var pixel = _tankSprites[tank.Orientation][dx, dy]; - if (!pixel.HasValue || !pixel.Value) - continue; + for (byte dx = 0; dx < MapService.TileSize; dx++) + { + var pixel = _tankSprites[tank.Orientation][dx, dy]; + if (!pixel.HasValue || !pixel.Value) + continue; - var (x, y) = tankPosition.GetPixelRelative(dx, dy); - pixels[x, y].EntityType = GamePixelEntityType.Tank; - pixels[x, y].BelongsTo = tank.Owner; - } + var (x, y) = tankPosition.GetPixelRelative(dx, dy); + pixels[x, y].EntityType = GamePixelEntityType.Tank; + pixels[x, y].BelongsTo = tank.Owner; + } } } } diff --git a/tanks-backend/TanksServer/Graphics/GamePixelGrid.cs b/tanks-backend/TanksServer/Graphics/GamePixelGrid.cs index 1c35f71..1b2f37f 100644 --- a/tanks-backend/TanksServer/Graphics/GamePixelGrid.cs +++ b/tanks-backend/TanksServer/Graphics/GamePixelGrid.cs @@ -5,27 +5,27 @@ namespace TanksServer.Graphics; internal sealed class GamePixelGrid : IEnumerable { - public int Width { get; } - public int Height { get; } + public ulong Width { get; } + public ulong Height { get; } private readonly GamePixel[,] _pixels; - public GamePixelGrid(int width, int height) + public GamePixelGrid(ulong width, ulong height) { Width = width; Height = height; _pixels = new GamePixel[width, height]; - for (var y = 0; y < height; y++) - for (var x = 0; x < width; x++) - this[x, y] = new GamePixel(); + for (ulong y = 0; y < height; y++) + for (ulong x = 0; x < width; x++) + this[x, y] = new GamePixel(); } - public GamePixel this[int x, int y] + public GamePixel this[ulong x, ulong y] { get { - Debug.Assert(y * Width + x < _pixels.Length); + Debug.Assert(y * Width + x < (ulong)_pixels.Length); return _pixels[x, y]; } set => _pixels[x, y] = value; @@ -41,8 +41,8 @@ internal sealed class GamePixelGrid : IEnumerable public IEnumerator GetEnumerator() { - for (var y = 0; y < Height; y++) - for (var x = 0; x < Width; x++) - yield return this[x, y]; + for (ulong y = 0; y < Height; y++) + for (ulong x = 0; x < Width; x++) + yield return this[x, y]; } } diff --git a/tanks-backend/TanksServer/Graphics/GeneratePixelsTickStep.cs b/tanks-backend/TanksServer/Graphics/GeneratePixelsTickStep.cs index 1db7259..af2f781 100644 --- a/tanks-backend/TanksServer/Graphics/GeneratePixelsTickStep.cs +++ b/tanks-backend/TanksServer/Graphics/GeneratePixelsTickStep.cs @@ -1,4 +1,3 @@ -using ServicePoint; using TanksServer.GameLogic; using TanksServer.Interactivity; @@ -20,7 +19,7 @@ internal sealed class GeneratePixelsTickStep( public async ValueTask TickAsync(TimeSpan _) { Draw(_gamePixelGrid, _observerPixelGrid); - if (_observerPixelGrid.Data.SequenceEqual(_lastObserverPixelGrid.Data)) + if (_observerPixelGrid.Equals(_lastObserverPixelGrid)) return; await _consumers.Select(c => c.OnFrameDoneAsync(_gamePixelGrid, _observerPixelGrid)) @@ -37,12 +36,12 @@ internal sealed class GeneratePixelsTickStep( step.Draw(gamePixelGrid); observerPixelGrid.Fill(false); - for (var y = 0; y < MapService.PixelsPerColumn; y++) - for (var x = 0; x < MapService.PixelsPerRow; x++) - { - if (gamePixelGrid[x, y].EntityType.HasValue) - observerPixelGrid[(ushort)x, (ushort)y] = true; - } + for (ulong y = 0; y < MapService.PixelsPerColumn; y++) + for (ulong x = 0; x < MapService.PixelsPerRow; x++) + { + if (gamePixelGrid[x, y].EntityType.HasValue) + observerPixelGrid.Set(x, y, true); + } } public void Dispose() diff --git a/tanks-backend/TanksServer/Graphics/IFrameConsumer.cs b/tanks-backend/TanksServer/Graphics/IFrameConsumer.cs index 09fc940..6f1e463 100644 --- a/tanks-backend/TanksServer/Graphics/IFrameConsumer.cs +++ b/tanks-backend/TanksServer/Graphics/IFrameConsumer.cs @@ -1,5 +1,3 @@ -using ServicePoint; - namespace TanksServer.Graphics; internal interface IFrameConsumer diff --git a/tanks-backend/TanksServer/Graphics/Sprite.cs b/tanks-backend/TanksServer/Graphics/Sprite.cs index 8a8b854..7128468 100644 --- a/tanks-backend/TanksServer/Graphics/Sprite.cs +++ b/tanks-backend/TanksServer/Graphics/Sprite.cs @@ -12,13 +12,13 @@ internal sealed class Sprite(bool?[,] data) var whitePixel = new Rgba32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue); for (var y = 0; y < image.Height; y++) - for (var x = 0; x < image.Width; x++) - { - var pixelValue = image[x, y]; - data[x, y] = pixelValue.A == 0 - ? null - : pixelValue == whitePixel; - } + for (var x = 0; x < image.Width; x++) + { + var pixelValue = image[x, y]; + data[x, y] = pixelValue.A == 0 + ? null + : pixelValue == whitePixel; + } return new Sprite(data); } @@ -34,8 +34,8 @@ internal sealed class Sprite(bool?[,] data) var result = new bool[Width, Height]; for (var y = 0; y < Height; y++) - for (var x = 0; x < Width; x++) - result[x, y] = this[x, y] ?? false; + for (var x = 0; x < Width; x++) + result[x, y] = this[x, y] ?? false; return result; } diff --git a/tanks-backend/TanksServer/Graphics/SpriteSheet.cs b/tanks-backend/TanksServer/Graphics/SpriteSheet.cs index 514cfb1..4d121a1 100644 --- a/tanks-backend/TanksServer/Graphics/SpriteSheet.cs +++ b/tanks-backend/TanksServer/Graphics/SpriteSheet.cs @@ -21,24 +21,24 @@ internal sealed class SpriteSheet(Sprite[,] sprites) var whitePixel = new Rgba32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue); for (var spriteY = 0; spriteY < spritesPerColumn; spriteY++) - for (var spriteX = 0; spriteX < spritesPerRow; spriteX++) - { - var data = new bool?[spriteWidth, spriteHeight]; - for (var dy = 0; dy < spriteHeight; dy++) - for (var dx = 0; dx < spriteWidth; dx++) + for (var spriteX = 0; spriteX < spritesPerRow; spriteX++) { - var x = spriteX * spriteWidth + dx; - var y = spriteY * spriteHeight + dy; + var data = new bool?[spriteWidth, spriteHeight]; + for (var dy = 0; dy < spriteHeight; dy++) + for (var dx = 0; dx < spriteWidth; dx++) + { + var x = spriteX * spriteWidth + dx; + var y = spriteY * spriteHeight + dy; - var pixelValue = image[x, y]; - data[dx, dy] = pixelValue.A == 0 - ? null - : pixelValue == whitePixel; + var pixelValue = image[x, y]; + data[dx, dy] = pixelValue.A == 0 + ? null + : pixelValue == whitePixel; + } + + sprites[spriteX, spriteY] = new Sprite(data); } - sprites[spriteX, spriteY] = new Sprite(data); - } - return new SpriteSheet(sprites); } diff --git a/tanks-backend/TanksServer/Interactivity/BufferPool.cs b/tanks-backend/TanksServer/Interactivity/BufferPool.cs index 8e7ad5c..0756db0 100644 --- a/tanks-backend/TanksServer/Interactivity/BufferPool.cs +++ b/tanks-backend/TanksServer/Interactivity/BufferPool.cs @@ -2,13 +2,13 @@ using System.Buffers; namespace TanksServer.Interactivity; -internal sealed class BufferPool: MemoryPool +internal sealed class BufferPool : MemoryPool { private readonly MemoryPool _actualPool = Shared; public override int MaxBufferSize => int.MaxValue; - protected override void Dispose(bool disposing) {} + protected override void Dispose(bool disposing) { } public override IMemoryOwner Rent(int minBufferSize = -1) { @@ -16,7 +16,7 @@ internal sealed class BufferPool: MemoryPool return new BufferPoolMemoryOwner(_actualPool.Rent(minBufferSize), minBufferSize); } - private sealed class BufferPoolMemoryOwner(IMemoryOwner actualOwner, int wantedSize): IMemoryOwner + private sealed class BufferPoolMemoryOwner(IMemoryOwner actualOwner, int wantedSize) : IMemoryOwner { public Memory Memory { get; } = actualOwner.Memory[..wantedSize]; diff --git a/tanks-backend/TanksServer/Interactivity/ClientScreenServer.cs b/tanks-backend/TanksServer/Interactivity/ClientScreenServer.cs index 6c1165f..695f404 100644 --- a/tanks-backend/TanksServer/Interactivity/ClientScreenServer.cs +++ b/tanks-backend/TanksServer/Interactivity/ClientScreenServer.cs @@ -1,5 +1,4 @@ using System.Net.WebSockets; -using ServicePoint; using TanksServer.Graphics; namespace TanksServer.Interactivity; diff --git a/tanks-backend/TanksServer/Interactivity/ClientScreenServerConnection.cs b/tanks-backend/TanksServer/Interactivity/ClientScreenServerConnection.cs index 01e91e2..a1640da 100644 --- a/tanks-backend/TanksServer/Interactivity/ClientScreenServerConnection.cs +++ b/tanks-backend/TanksServer/Interactivity/ClientScreenServerConnection.cs @@ -1,6 +1,5 @@ using System.Buffers; using System.Net.WebSockets; -using ServicePoint; using TanksServer.Graphics; namespace TanksServer.Interactivity; @@ -36,7 +35,7 @@ internal sealed class ClientScreenServerConnection private Package BuildNextPackage(Bitmap pixels, GamePixelGrid gamePixelGrid) { - var pixelsData = pixels.Data; + var pixelsData = pixels.CopyRaw(); var nextPixels = _bufferPool.Rent(pixelsData.Length); pixelsData.CopyTo(nextPixels.Memory.Span); diff --git a/tanks-backend/TanksServer/Interactivity/LoggingLifecycleService.cs b/tanks-backend/TanksServer/Interactivity/LoggingLifecycleService.cs new file mode 100644 index 0000000..a083dfa --- /dev/null +++ b/tanks-backend/TanksServer/Interactivity/LoggingLifecycleService.cs @@ -0,0 +1,42 @@ +using Microsoft.Extensions.Hosting; + +internal class LoggingLifecycleService(ILogger logger) : IHostedLifecycleService +{ + private protected readonly ILogger Logger = logger; + + public virtual Task StartAsync(CancellationToken cancellationToken) + { + Logger.LogDebug("StartAsync"); + return Task.CompletedTask; + } + + public virtual Task StartedAsync(CancellationToken cancellationToken) + { + Logger.LogDebug("StartedAsync"); + return Task.CompletedTask; + } + + public virtual Task StartingAsync(CancellationToken cancellationToken) + { + Logger.LogDebug("StartingAsync"); + return Task.CompletedTask; + } + + public virtual Task StopAsync(CancellationToken cancellationToken) + { + Logger.LogDebug("StopAsync"); + return Task.CompletedTask; + } + + public virtual Task StoppedAsync(CancellationToken cancellationToken) + { + Logger.LogDebug("StoppedAsync"); + return Task.CompletedTask; + } + + public virtual Task StoppingAsync(CancellationToken cancellationToken) + { + Logger.LogDebug("StoppingAsync"); + return Task.CompletedTask; + } +} diff --git a/tanks-backend/TanksServer/Interactivity/SendToServicePointDisplay.cs b/tanks-backend/TanksServer/Interactivity/SendToServicePointDisplay.cs index de055de..cb96f0c 100644 --- a/tanks-backend/TanksServer/Interactivity/SendToServicePointDisplay.cs +++ b/tanks-backend/TanksServer/Interactivity/SendToServicePointDisplay.cs @@ -1,7 +1,6 @@ using System.Diagnostics; using System.Net; using System.Net.Sockets; -using ServicePoint; using TanksServer.GameLogic; using TanksServer.Graphics; @@ -17,7 +16,7 @@ internal sealed class SendToServicePointDisplay : IFrameConsumer, IDisposable private readonly MapService _mapService; private readonly ILogger _logger; private readonly PlayerServer _players; - private readonly Cp437Grid _scoresBuffer; + private readonly CharGrid _scoresBuffer; private readonly TimeSpan _minFrameTime; private readonly IOptionsMonitor _options; @@ -42,13 +41,13 @@ internal sealed class SendToServicePointDisplay : IFrameConsumer, IDisposable var localIp = GetLocalIPv4(displayConfig.Value).Split('.'); Debug.Assert(localIp.Length == 4); - _scoresBuffer = new Cp437Grid(12, 20); + _scoresBuffer = new CharGrid(ScoresWidth, ScoresHeight); - _scoresBuffer[00] = "== TANKS! =="; - _scoresBuffer[01] = "-- scores --"; - _scoresBuffer[17] = "-- join --"; - _scoresBuffer[18] = string.Join('.', localIp[..2]); - _scoresBuffer[19] = string.Join('.', localIp[2..]); + _scoresBuffer.SetRow(00, "== TANKS! =="); + _scoresBuffer.SetRow(01, "-- scores --"); + _scoresBuffer.SetRow(17, "-- join --"); + _scoresBuffer.SetRow(18, $"{localIp[0]}.{localIp[1]}".PadRight(ScoresWidth)); + _scoresBuffer.SetRow(19, $"{localIp[2]}.{localIp[3]}".PadRight(ScoresWidth)); } public async Task OnFrameDoneAsync(GamePixelGrid gamePixelGrid, Bitmap observerPixels) @@ -66,9 +65,8 @@ internal sealed class SendToServicePointDisplay : IFrameConsumer, IDisposable try { - _displayConnection.Send(Command.BitmapLinearWin(0, 0, observerPixels.Clone(), CompressionCode.Lzma) - .IntoPacket()); - _displayConnection.Send(Command.Cp437Data(MapService.TilesPerRow, 0, _scoresBuffer.Clone()).IntoPacket()); + _displayConnection.Send(Command.BitmapLinearWin(0, 0, observerPixels, CompressionCode.Lzma)); + _displayConnection.Send(Command.Cp437Data(MapService.TilesPerRow, 0, _scoresBuffer.ToCp437())); } catch (SocketException ex) { @@ -95,14 +93,14 @@ internal sealed class SendToServicePointDisplay : IFrameConsumer, IDisposable var name = p.Name[..nameLength]; var spaces = new string(' ', ScoresWidth - score.Length - nameLength); - _scoresBuffer[row] = name + spaces + score; + _scoresBuffer.SetRow(row, name + spaces + score); row++; } for (; row < 16; row++) - _scoresBuffer[row] = string.Empty; + _scoresBuffer.SetRow(row, new string(' ', ScoresWidth)); - _scoresBuffer[16] = _mapService.Current.Name[..(Math.Min(ScoresWidth, _mapService.Current.Name.Length) - 1)]; + _scoresBuffer.SetRow(16, _mapService.Current.Name[..(Math.Min(ScoresWidth, _mapService.Current.Name.Length) - 1)].PadRight(ScoresWidth)); } private static string GetLocalIPv4(DisplayConfiguration configuration) diff --git a/tanks-backend/TanksServer/Interactivity/WebsocketServer.cs b/tanks-backend/TanksServer/Interactivity/WebsocketServer.cs index 0c33e4c..6c1f24e 100644 --- a/tanks-backend/TanksServer/Interactivity/WebsocketServer.cs +++ b/tanks-backend/TanksServer/Interactivity/WebsocketServer.cs @@ -1,23 +1,23 @@ using System.Diagnostics; -using Microsoft.Extensions.Hosting; namespace TanksServer.Interactivity; internal abstract class WebsocketServer( ILogger logger -) : IHostedLifecycleService +) : LoggingLifecycleService(logger) where T : WebsocketServerConnection { private bool _closing; private readonly ConcurrentDictionary _connections = []; - public async Task StoppingAsync(CancellationToken cancellationToken) + public async override Task StoppingAsync(CancellationToken cancellationToken) { + await base.StoppingAsync(cancellationToken); _closing = true; - logger.LogInformation("closing connections"); + Logger.LogInformation("closing connections"); await _connections.Keys.Select(c => c.CloseAsync()) .WhenAll(); - logger.LogInformation("closed connections"); + Logger.LogInformation("closed connections"); } protected IEnumerable Connections => _connections.Keys; @@ -26,7 +26,7 @@ internal abstract class WebsocketServer( { if (_closing) { - logger.LogWarning("refusing connection because server is shutting down"); + Logger.LogWarning("refusing connection because server is shutting down"); await connection.CloseAsync(); return; } @@ -39,14 +39,4 @@ internal abstract class WebsocketServer( _ = _connections.TryRemove(connection, out _); connection.Dispose(); } - - public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask; - - public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; - - public Task StartedAsync(CancellationToken cancellationToken) => Task.CompletedTask; - - public Task StartingAsync(CancellationToken cancellationToken) => Task.CompletedTask; - - public Task StoppedAsync(CancellationToken cancellationToken) => Task.CompletedTask; } diff --git a/tanks-backend/TanksServer/Interactivity/WebsocketServerConnection.cs b/tanks-backend/TanksServer/Interactivity/WebsocketServerConnection.cs index 893b7a5..9434462 100644 --- a/tanks-backend/TanksServer/Interactivity/WebsocketServerConnection.cs +++ b/tanks-backend/TanksServer/Interactivity/WebsocketServerConnection.cs @@ -3,7 +3,7 @@ namespace TanksServer.Interactivity; internal abstract class WebsocketServerConnection( ILogger logger, ByteChannelWebSocket socket -): IDisposable +) : IDisposable { protected readonly ByteChannelWebSocket Socket = socket; protected readonly ILogger Logger = logger; diff --git a/tanks-backend/TanksServer/Models/PixelPosition.cs b/tanks-backend/TanksServer/Models/PixelPosition.cs index e92e3a9..03b4ce1 100644 --- a/tanks-backend/TanksServer/Models/PixelPosition.cs +++ b/tanks-backend/TanksServer/Models/PixelPosition.cs @@ -4,12 +4,12 @@ using TanksServer.GameLogic; namespace TanksServer.Models; [DebuggerDisplay("({X} | {Y})")] -internal readonly struct PixelPosition(int x, int y) +internal readonly struct PixelPosition(ulong x, ulong y) { - public int X { get; } = (x + MapService.PixelsPerRow) % MapService.PixelsPerRow; - public int Y { get; } = (y + MapService.PixelsPerColumn) % MapService.PixelsPerColumn; + public ulong X { get; } = (x + MapService.PixelsPerRow) % MapService.PixelsPerRow; + public ulong Y { get; } = (y + MapService.PixelsPerColumn) % MapService.PixelsPerColumn; - public void Deconstruct(out int x, out int y) + public void Deconstruct(out ulong x, out ulong y) { x = X; y = Y; diff --git a/tanks-backend/TanksServer/Models/PositionHelpers.cs b/tanks-backend/TanksServer/Models/PositionHelpers.cs index 0596233..bf2fb66 100644 --- a/tanks-backend/TanksServer/Models/PositionHelpers.cs +++ b/tanks-backend/TanksServer/Models/PositionHelpers.cs @@ -4,20 +4,20 @@ namespace TanksServer.Models; internal static class PositionHelpers { - public static PixelPosition GetPixelRelative(this PixelPosition position, short subX, short subY) - => new(position.X + subX, position.Y + subY); + public static PixelPosition GetPixelRelative(this PixelPosition position, long subX, long subY) + => new((ulong)((long)position.X + subX), (ulong)((long)position.Y + subY)); public static PixelPosition ToPixelPosition(this FloatPosition position) - => new((int)Math.Round(position.X), (int)Math.Round(position.Y)); + => new((ulong)Math.Round(position.X), (ulong)Math.Round(position.Y)); public static PixelPosition ToPixelPosition(this TilePosition position) => new( - (ushort)(position.X * MapService.TileSize), - (ushort)(position.Y * MapService.TileSize) + (ulong)(position.X * MapService.TileSize), + (ulong)(position.Y * MapService.TileSize) ); public static TilePosition ToTilePosition(this PixelPosition position) => new( - (ushort)(position.X / MapService.TileSize), - (ushort)(position.Y / MapService.TileSize) + (ulong)(position.X / MapService.TileSize), + (ulong)(position.Y / MapService.TileSize) ); public static FloatPosition ToFloatPosition(this PixelPosition position) => new(position.X, position.Y); @@ -28,10 +28,10 @@ internal static class PositionHelpers Math.Pow(p1.Y - p2.Y, 2) ); - public static PixelBounds GetBoundsForCenter(this FloatPosition position, ushort size) + public static PixelBounds GetBoundsForCenter(this FloatPosition position, ulong size) { - var sub = (short)(-size / 2d); - var add = (short)(size / 2d - 1); + var sub = (long)(-(long)size / 2d); + var add = (long)(size / 2d - 1); var pixelPosition = position.ToPixelPosition(); return new PixelBounds( pixelPosition.GetPixelRelative(sub, sub), diff --git a/tanks-backend/TanksServer/Models/PowerUp.cs b/tanks-backend/TanksServer/Models/PowerUp.cs index 318a3a4..ba5a11b 100644 --- a/tanks-backend/TanksServer/Models/PowerUp.cs +++ b/tanks-backend/TanksServer/Models/PowerUp.cs @@ -11,7 +11,7 @@ internal enum PowerUpType SmartBullets, } -internal sealed class PowerUp: IMapEntity +internal sealed class PowerUp : IMapEntity { public required FloatPosition Position { get; init; } diff --git a/tanks-backend/TanksServer/Models/Tank.cs b/tanks-backend/TanksServer/Models/Tank.cs index 7147349..093c00f 100644 --- a/tanks-backend/TanksServer/Models/Tank.cs +++ b/tanks-backend/TanksServer/Models/Tank.cs @@ -10,7 +10,8 @@ internal sealed class Tank(Player owner, FloatPosition position) : IMapEntity [JsonIgnore] public Player Owner { get; } = owner; - [JsonIgnore] public double Rotation + [JsonIgnore] + public double Rotation { get => _rotation; set diff --git a/tanks-backend/TanksServer/Models/TilePosition.cs b/tanks-backend/TanksServer/Models/TilePosition.cs index 089ff6f..98cf9ee 100644 --- a/tanks-backend/TanksServer/Models/TilePosition.cs +++ b/tanks-backend/TanksServer/Models/TilePosition.cs @@ -4,8 +4,8 @@ using TanksServer.GameLogic; namespace TanksServer.Models; [DebuggerDisplay("({X} | {Y})")] -internal readonly struct TilePosition(ushort x, ushort y) +internal readonly struct TilePosition(ulong x, ulong y) { - public ushort X { get; } = (ushort)((x + MapService.TilesPerRow) % MapService.TilesPerRow); - public ushort Y { get; } = (ushort)((y + MapService.TilesPerColumn) % MapService.TilesPerColumn); + public ulong X { get; } = (ulong)((x + MapService.TilesPerRow) % MapService.TilesPerRow); + public ulong Y { get; } = (ulong)((y + MapService.TilesPerColumn) % MapService.TilesPerColumn); } diff --git a/tanks-backend/TanksServer/Program.cs b/tanks-backend/TanksServer/Program.cs index 56cc6ad..e794589 100644 --- a/tanks-backend/TanksServer/Program.cs +++ b/tanks-backend/TanksServer/Program.cs @@ -1,8 +1,8 @@ +using System.Diagnostics.CodeAnalysis; using System.IO; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.FileProviders; -using ServicePoint; using TanksServer.GameLogic; using TanksServer.Graphics; using TanksServer.Interactivity; @@ -11,6 +11,8 @@ namespace TanksServer; public static class Program { + [RequiresUnreferencedCode("Calls Endpoints.Map")] + [RequiresDynamicCode("Calls Endpoints.Map")] public static async Task Main(string[] args) { var app = Configure(args); @@ -25,6 +27,8 @@ public static class Program await app.RunAsync(); } + [RequiresUnreferencedCode("Calls Microsoft.Extensions.DependencyInjection.OptionsConfigurationServiceCollectionExtensions.Configure(IConfiguration)")] + [RequiresDynamicCode("Calls Microsoft.Extensions.DependencyInjection.OptionsConfigurationServiceCollectionExtensions.Configure(IConfiguration)")] private static WebApplication Configure(string[] args) { var builder = WebApplication.CreateSlimBuilder(args); @@ -43,10 +47,7 @@ public static class Program .AllowAnyOrigin()) ); - builder.Services.ConfigureHttpJsonOptions(options => - { - options.SerializerOptions.TypeInfoResolverChain.Insert(0, new AppSerializerContext()); - }); + builder.Services.ConfigureHttpJsonOptions(options => options.SerializerOptions.TypeInfoResolverChain.Insert(0, new AppSerializerContext())); builder.Services.AddHttpLogging(_ => { }); @@ -66,8 +67,8 @@ public static class Program builder.Services.AddSingleton(); builder.Services.AddHostedService(); - builder.Services.AddHostedService(sp => sp.GetRequiredService()); - builder.Services.AddHostedService(sp => sp.GetRequiredService()); + builder.Services.AddHostedService(FromServices); + builder.Services.AddHostedService(FromServices); builder.Services.AddSingleton(sp => sp.GetRequiredService()); @@ -100,10 +101,7 @@ public static class Program builder.Services.AddSingleton(sp => { var config = sp.GetRequiredService>().Value; - var connection = Connection.Open($"{config.Hostname}:{config.Port}"); - if (connection == null) - throw new IOException($"Could not open connection to {config.Hostname}:{config.Port}"); - + var connection = new Connection($"{config.Hostname}:{config.Port}"); return connection; }); @@ -115,4 +113,6 @@ public static class Program return app; } + + private static T FromServices(IServiceProvider sp) where T : notnull => sp.GetRequiredService(); } diff --git a/tanks-backend/TanksServer/TanksServer.csproj b/tanks-backend/TanksServer/TanksServer.csproj index 702cd9c..08109f7 100644 --- a/tanks-backend/TanksServer/TanksServer.csproj +++ b/tanks-backend/TanksServer/TanksServer.csproj @@ -29,7 +29,7 @@ - + diff --git a/tanks-backend/servicepoint b/tanks-backend/servicepoint index f968f92..93657c9 160000 --- a/tanks-backend/servicepoint +++ b/tanks-backend/servicepoint @@ -1 +1 @@ -Subproject commit f968f929173c6646acb7d9a3ed19112e626732b3 +Subproject commit 93657c9f85d021c04270e1f5af573a6cda51f18a