diff --git a/.editorconfig b/.editorconfig index b175ed5..e892ae3 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,3 +8,24 @@ indent_style = space insert_final_newline = true max_line_length = 120 tab_width = 4 +trim_trailing_whitespace = true + +csharp_style_expression_bodied_methods = when_on_single_line:warning +csharp_style_expression_bodied_lambdas = when_on_single_line:warning +csharp_style_expression_bodied_properties = when_on_single_line:warning + +dotnet_style_collection_initializer = true:warning + +dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:none +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:none +dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:none + +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion + +dotnet_style_qualification_for_event = false:suggestion +dotnet_style_qualification_for_field = false:suggestion +dotnet_style_qualification_for_method = false:suggestion +dotnet_style_qualification_for_property = false:suggestion + +dotnet_style_require_accessibility_modifiers = for_non_interface_members:warning diff --git a/DisplayCommands/ByteGrid.cs b/DisplayCommands/ByteGrid.cs index 6b70e44..f7e990f 100644 --- a/DisplayCommands/ByteGrid.cs +++ b/DisplayCommands/ByteGrid.cs @@ -16,6 +16,13 @@ public sealed class ByteGrid(ushort width, ushort height) : IEquatable set => Data.Span[GetIndex(x, y)] = value; } + public bool Equals(ByteGrid? other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return Height == other.Height && Width == other.Width && Data.Span.SequenceEqual(other.Data.Span); + } + private int GetIndex(ushort x, ushort y) { Debug.Assert(x < Width); @@ -25,15 +32,11 @@ public sealed class ByteGrid(ushort width, ushort height) : IEquatable public void Clear() => Data.Span.Clear(); - public bool Equals(ByteGrid? other) - { - if (ReferenceEquals(null, other)) return false; - if (ReferenceEquals(this, other)) return true; - return Height == other.Height && Width == other.Width && Data.Span.SequenceEqual(other.Data.Span); - } - public override bool Equals(object? obj) => ReferenceEquals(this, obj) || (obj is ByteGrid other && Equals(other)); + public override int GetHashCode() => HashCode.Combine(Height, Width, Data); + public static bool operator ==(ByteGrid? left, ByteGrid? right) => Equals(left, right); + public static bool operator !=(ByteGrid? left, ByteGrid? right) => !Equals(left, right); -} \ No newline at end of file +} diff --git a/DisplayCommands/DisplayCommands.csproj b/DisplayCommands/DisplayCommands.csproj index 068e186..f621f74 100644 --- a/DisplayCommands/DisplayCommands.csproj +++ b/DisplayCommands/DisplayCommands.csproj @@ -14,14 +14,14 @@ true CA1805,CA1848 - + - - - + + + - + - + diff --git a/DisplayCommands/IDisplayConnection.cs b/DisplayCommands/IDisplayConnection.cs index 0e16af1..950e75b 100644 --- a/DisplayCommands/IDisplayConnection.cs +++ b/DisplayCommands/IDisplayConnection.cs @@ -7,7 +7,7 @@ public interface IDisplayConnection ValueTask SendCp437DataAsync(ushort x, ushort y, Cp437Grid grid); ValueTask SendBrightnessAsync(byte brightness); - + ValueTask SendCharBrightnessAsync(ushort x, ushort y, ByteGrid luma); ValueTask SendHardResetAsync(); @@ -17,8 +17,8 @@ public interface IDisplayConnection public ValueTask SendBitmapLinearWindowAsync(ushort x, ushort y, PixelGrid pixels); /// - /// Returns the IPv4 address that is associated with the interface with which the display is reachable. + /// Returns the IPv4 address that is associated with the interface with which the display is reachable. /// /// IPv4 as text public string GetLocalIPv4(); -} \ No newline at end of file +} diff --git a/DisplayCommands/Internals/DisplayCommand.cs b/DisplayCommands/Internals/DisplayCommand.cs index 42c96ba..abe94e1 100644 --- a/DisplayCommands/Internals/DisplayCommand.cs +++ b/DisplayCommands/Internals/DisplayCommand.cs @@ -13,5 +13,5 @@ internal enum DisplayCommand : ushort BitmapLinearWin = 0x0013, BitmapLinearAnd = 0x0014, BitmapLinearOr = 0x0015, - BitmapLinearXor = 0x0016, -} \ No newline at end of file + BitmapLinearXor = 0x0016 +} diff --git a/DisplayCommands/Internals/DisplayConnection.cs b/DisplayCommands/Internals/DisplayConnection.cs index 5083b8b..466aa1c 100644 --- a/DisplayCommands/Internals/DisplayConnection.cs +++ b/DisplayCommands/Internals/DisplayConnection.cs @@ -9,8 +9,8 @@ namespace DisplayCommands.Internals; internal sealed class DisplayConnection(IOptions options) : IDisplayConnection, IDisposable { - private readonly UdpClient _udpClient = new(options.Value.Hostname, options.Value.Port); private readonly ArrayPool _arrayPool = ArrayPool.Shared; + private readonly UdpClient _udpClient = new(options.Value.Hostname, options.Value.Port); public ValueTask SendClearAsync() { @@ -119,8 +119,5 @@ internal sealed class DisplayConnection(IOptions options) _arrayPool.Return(buffer); } - public void Dispose() - { - _udpClient.Dispose(); - } -} \ No newline at end of file + public void Dispose() => _udpClient.Dispose(); +} diff --git a/DisplayCommands/Internals/DisplaySubCommand.cs b/DisplayCommands/Internals/DisplaySubCommand.cs index 57fe8f3..bf5427f 100644 --- a/DisplayCommands/Internals/DisplaySubCommand.cs +++ b/DisplayCommands/Internals/DisplaySubCommand.cs @@ -6,5 +6,5 @@ internal enum DisplaySubCommand : ushort BitmapCompressZ = 0x677a, BitmapCompressBz = 0x627a, BitmapCompressLz = 0x6c7a, - BitmapCompressZs = 0x7a73, -} \ No newline at end of file + BitmapCompressZs = 0x7a73 +} diff --git a/DisplayCommands/PixelGrid.cs b/DisplayCommands/PixelGrid.cs index ea40ab5..5006ddb 100644 --- a/DisplayCommands/PixelGrid.cs +++ b/DisplayCommands/PixelGrid.cs @@ -56,4 +56,4 @@ public sealed class PixelGrid(ushort width, ushort height) : IEquatable _bullets = new(); + private readonly HashSet _bullets = []; public void Spawn(Bullet bullet) => _bullets.Add(bullet); public IEnumerable GetAll() => _bullets; - public void RemoveWhere(Predicate predicate) - { - _bullets.RemoveWhere(predicate); - } + public void RemoveWhere(Predicate predicate) => _bullets.RemoveWhere(predicate); } diff --git a/TanksServer/GameLogic/CollideBulletsWithMap.cs b/TanksServer/GameLogic/CollideBulletsWithMap.cs index b0c0221..faf0bf6 100644 --- a/TanksServer/GameLogic/CollideBulletsWithMap.cs +++ b/TanksServer/GameLogic/CollideBulletsWithMap.cs @@ -8,8 +8,6 @@ internal sealed class CollideBulletsWithMap(BulletManager bullets, MapService ma return Task.CompletedTask; } - private bool BulletHitsWall(Bullet bullet) - { - return map.IsCurrentlyWall(bullet.Position.ToPixelPosition().ToTilePosition()); - } + private bool BulletHitsWall(Bullet bullet) => + map.IsCurrentlyWall(bullet.Position.ToPixelPosition().ToTilePosition()); } diff --git a/TanksServer/GameLogic/GameTickWorker.cs b/TanksServer/GameLogic/GameTickWorker.cs index 1a3abea..25732f1 100644 --- a/TanksServer/GameLogic/GameTickWorker.cs +++ b/TanksServer/GameLogic/GameTickWorker.cs @@ -10,17 +10,29 @@ internal sealed class GameTickWorker( ) : IHostedService, IDisposable { private const int TicksPerSecond = 25; - private static readonly TimeSpan TickPacing = TimeSpan.FromMilliseconds((int)(1000 / TicksPerSecond)); + private static readonly TimeSpan TickPacing = TimeSpan.FromMilliseconds(1000 / TicksPerSecond); private readonly CancellationTokenSource _cancellation = new(); private readonly List _steps = steps.ToList(); private Task? _run; + public void Dispose() + { + _cancellation.Dispose(); + _run?.Dispose(); + } + public Task StartAsync(CancellationToken cancellationToken) { _run = RunAsync(); return Task.CompletedTask; } + public async Task StopAsync(CancellationToken cancellationToken) + { + await _cancellation.CancelAsync(); + if (_run != null) await _run; + } + private async Task RunAsync() { try @@ -45,16 +57,4 @@ internal sealed class GameTickWorker( lifetime.StopApplication(); } } - - public async Task StopAsync(CancellationToken cancellationToken) - { - await _cancellation.CancelAsync(); - if (_run != null) await _run; - } - - public void Dispose() - { - _cancellation.Dispose(); - _run?.Dispose(); - } -} \ No newline at end of file +} diff --git a/TanksServer/GameLogic/MapService.cs b/TanksServer/GameLogic/MapService.cs index bbdf204..e12251d 100644 --- a/TanksServer/GameLogic/MapService.cs +++ b/TanksServer/GameLogic/MapService.cs @@ -35,8 +35,5 @@ internal sealed class MapService private char this[int tileX, int tileY] => _map[tileX + tileY * TilesPerRow]; - public bool IsCurrentlyWall(TilePosition position) - { - return this[position.X, position.Y] == '#'; - } + public bool IsCurrentlyWall(TilePosition position) => this[position.X, position.Y] == '#'; } diff --git a/TanksServer/GameLogic/MoveBullets.cs b/TanksServer/GameLogic/MoveBullets.cs index e29c56c..de75272 100644 --- a/TanksServer/GameLogic/MoveBullets.cs +++ b/TanksServer/GameLogic/MoveBullets.cs @@ -18,4 +18,4 @@ internal sealed class MoveBullets(BulletManager bullets, IOptions _queue.Enqueue(player); public void EnqueueForDelayedSpawn(Player player) { @@ -33,7 +30,7 @@ internal sealed class SpawnQueue( _queue.Enqueue(player); return false; } - + var now = DateTime.Now; if (_spawnTimes.GetOrAdd(player, DateTime.MinValue) > now) { @@ -44,4 +41,4 @@ internal sealed class SpawnQueue( return true; } -} \ No newline at end of file +} diff --git a/TanksServer/Graphics/LastFinishedFrameProvider.cs b/TanksServer/Graphics/LastFinishedFrameProvider.cs index eb58723..fd0d457 100644 --- a/TanksServer/Graphics/LastFinishedFrameProvider.cs +++ b/TanksServer/Graphics/LastFinishedFrameProvider.cs @@ -5,7 +5,7 @@ namespace TanksServer.Graphics; internal sealed class LastFinishedFrameProvider { private PixelGrid? _lastFrame; - + public PixelGrid LastFrame { get => _lastFrame ?? throw new InvalidOperationException("first frame not yet drawn"); diff --git a/TanksServer/Interactivity/AppSerializerContext.cs b/TanksServer/Interactivity/AppSerializerContext.cs index 98153bf..f2d7a7a 100644 --- a/TanksServer/Interactivity/AppSerializerContext.cs +++ b/TanksServer/Interactivity/AppSerializerContext.cs @@ -3,4 +3,4 @@ using System.Text.Json.Serialization; namespace TanksServer.Interactivity; [JsonSerializable(typeof(Player))] -internal sealed partial class AppSerializerContext: JsonSerializerContext; +internal sealed partial class AppSerializerContext : JsonSerializerContext; diff --git a/TanksServer/Interactivity/PlayerServer.cs b/TanksServer/Interactivity/PlayerServer.cs index 19956a5..3a3c8a1 100644 --- a/TanksServer/Interactivity/PlayerServer.cs +++ b/TanksServer/Interactivity/PlayerServer.cs @@ -29,7 +29,7 @@ internal sealed class PlayerServer(ILogger logger, SpawnQueue spaw } public IEnumerable GetAll() => _players.Values; - + private Player AddAndSpawn(string name) { var player = new Player(name); diff --git a/TanksServer/Interactivity/SendToServicePointDisplay.cs b/TanksServer/Interactivity/SendToServicePointDisplay.cs index 50d6883..7ba5c1b 100644 --- a/TanksServer/Interactivity/SendToServicePointDisplay.cs +++ b/TanksServer/Interactivity/SendToServicePointDisplay.cs @@ -8,19 +8,19 @@ namespace TanksServer.Interactivity; internal sealed class SendToServicePointDisplay : ITickStep { - private readonly LastFinishedFrameProvider _lastFinishedFrameProvider; - private readonly Cp437Grid _scoresBuffer; - private readonly PlayerServer _players; - private readonly ILogger _logger; - private readonly IDisplayConnection _displayConnection; - private PixelGrid? _lastSentFrame; - - private DateTime _nextFailLog = DateTime.Now; - private const int ScoresWidth = 12; private const int ScoresHeight = 20; private const int ScoresPlayerRows = ScoresHeight - 5; + private readonly IDisplayConnection _displayConnection; + private readonly LastFinishedFrameProvider _lastFinishedFrameProvider; + private readonly ILogger _logger; + private readonly PlayerServer _players; + private readonly Cp437Grid _scoresBuffer; + + private PixelGrid? _lastSentFrame; + private DateTime _nextFailLog = DateTime.Now; + public SendToServicePointDisplay( LastFinishedFrameProvider lastFinishedFrameProvider, PlayerServer players, @@ -90,4 +90,4 @@ internal sealed class SendToServicePointDisplay : ITickStep for (; row < 17; row++) _scoresBuffer[row] = string.Empty; } -} \ No newline at end of file +} diff --git a/TanksServer/Models/Player.cs b/TanksServer/Models/Player.cs index 24c414b..cf8cb88 100644 --- a/TanksServer/Models/Player.cs +++ b/TanksServer/Models/Player.cs @@ -8,12 +8,11 @@ internal sealed class Player(string name) public Guid Id { get; } = Guid.NewGuid(); - [JsonIgnore] - public PlayerControls Controls { get; } = new(); + [JsonIgnore] public PlayerControls Controls { get; } = new(); public int Kills { get; set; } - + public int Deaths { get; set; } public DateTime LastInput { get; set; } = DateTime.Now; -} \ No newline at end of file +}