From e1cfd714c108375821fd83eff51fa5e944b87248 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Mon, 13 May 2024 01:23:34 +0200 Subject: [PATCH] WIP switch to ServicePoint2 library --- tanks-backend/DisplayCommands/ByteGrid.cs | 42 --- tanks-backend/DisplayCommands/Cp437Grid.cs | 71 ----- .../DisplayCommands/DisplayCommands.csproj | 23 -- .../DisplayCommands/DisplayExtensions.cs | 25 -- tanks-backend/DisplayCommands/GlobalUsings.cs | 2 - .../DisplayCommands/IDisplayConnection.cs | 24 -- .../Internals/DisplayCommand.cs | 17 -- .../Internals/DisplayConnection.cs | 126 --------- .../Internals/DisplaySubCommand.cs | 10 - .../DisplayCommands/Internals/HeaderBitmap.cs | 19 -- .../DisplayCommands/Internals/HeaderWindow.cs | 19 -- tanks-backend/DisplayCommands/PixelGrid.cs | 59 ---- .../EndiannessGenerator.cs | 260 ------------------ .../EndiannessSourceGenerator.csproj | 25 -- .../Properties/launchSettings.json | 9 - .../EndiannessSourceGenerator/Readme.md | 5 - tanks-backend/TanksServer.sln | 18 +- tanks-backend/TanksServer/Endpoints.cs | 8 +- .../TanksServer/GameLogic/MapService.cs | 4 +- .../TanksServer/GameLogic/SpawnPowerUp.cs | 2 - .../TanksServer/Graphics/DrawMapStep.cs | 2 +- .../Graphics/GeneratePixelsTickStep.cs | 10 +- .../TanksServer/Graphics/IFrameConsumer.cs | 2 +- .../Interactivity/ClientScreenServer.cs | 2 +- .../ClientScreenServerConnection.cs | 7 +- .../Interactivity/PlayerInfoConnection.cs | 2 +- .../SendToServicePointDisplay.cs | 42 +-- .../Models}/DisplayConfiguration.cs | 4 +- tanks-backend/TanksServer/Program.cs | 10 +- tanks-backend/TanksServer/TanksServer.csproj | 5 +- tanks-backend/TanksServer/appsettings.json | 3 +- 31 files changed, 66 insertions(+), 791 deletions(-) delete mode 100644 tanks-backend/DisplayCommands/ByteGrid.cs delete mode 100644 tanks-backend/DisplayCommands/Cp437Grid.cs delete mode 100644 tanks-backend/DisplayCommands/DisplayCommands.csproj delete mode 100644 tanks-backend/DisplayCommands/DisplayExtensions.cs delete mode 100644 tanks-backend/DisplayCommands/GlobalUsings.cs delete mode 100644 tanks-backend/DisplayCommands/IDisplayConnection.cs delete mode 100644 tanks-backend/DisplayCommands/Internals/DisplayCommand.cs delete mode 100644 tanks-backend/DisplayCommands/Internals/DisplayConnection.cs delete mode 100644 tanks-backend/DisplayCommands/Internals/DisplaySubCommand.cs delete mode 100644 tanks-backend/DisplayCommands/Internals/HeaderBitmap.cs delete mode 100644 tanks-backend/DisplayCommands/Internals/HeaderWindow.cs delete mode 100644 tanks-backend/DisplayCommands/PixelGrid.cs delete mode 100644 tanks-backend/EndiannessSourceGenerator/EndiannessGenerator.cs delete mode 100644 tanks-backend/EndiannessSourceGenerator/EndiannessSourceGenerator.csproj delete mode 100644 tanks-backend/EndiannessSourceGenerator/Properties/launchSettings.json delete mode 100644 tanks-backend/EndiannessSourceGenerator/Readme.md rename tanks-backend/{DisplayCommands => TanksServer/Models}/DisplayConfiguration.cs (81%) diff --git a/tanks-backend/DisplayCommands/ByteGrid.cs b/tanks-backend/DisplayCommands/ByteGrid.cs deleted file mode 100644 index f7e990f..0000000 --- a/tanks-backend/DisplayCommands/ByteGrid.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.Diagnostics; - -namespace DisplayCommands; - -public sealed class ByteGrid(ushort width, ushort height) : IEquatable -{ - public ushort Height { get; } = height; - - public ushort Width { get; } = width; - - internal Memory Data { get; } = new byte[width * height].AsMemory(); - - public byte this[ushort x, ushort y] - { - get => Data.Span[GetIndex(x, y)]; - 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); - Debug.Assert(y < Height); - return x + y * Width; - } - - public void Clear() => Data.Span.Clear(); - - 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); -} diff --git a/tanks-backend/DisplayCommands/Cp437Grid.cs b/tanks-backend/DisplayCommands/Cp437Grid.cs deleted file mode 100644 index 19afe2f..0000000 --- a/tanks-backend/DisplayCommands/Cp437Grid.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System.Diagnostics; -using System.Text; - -namespace DisplayCommands; - -public sealed class Cp437Grid(ushort width, ushort height) : IEquatable -{ - private readonly ByteGrid _byteGrid = new(width, height); - private readonly Encoding _encoding = Encoding.GetEncoding(437); - - public ushort Height { get; } = height; - - public ushort Width { get; } = width; - - internal Memory Data => _byteGrid.Data; - - public char this[ushort x, ushort y] - { - get => ByteToChar(_byteGrid[x, y]); - set => _byteGrid[x, y] = CharToByte(value); - } - - public string this[ushort row] - { - get - { - var rowStart = row * Width; - return _encoding.GetString(_byteGrid.Data[rowStart..(rowStart + Width)].Span); - } - set - { - ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(row, Height, nameof(row)); - ArgumentOutOfRangeException.ThrowIfGreaterThan(value.Length, Width, nameof(value)); - ushort x = 0; - for (; x < value.Length; x++) - _byteGrid[x, row] = CharToByte(value[x]); - for (; x < Width; x++) - _byteGrid[x, row] = CharToByte(' '); - } - } - - private byte CharToByte(char c) - { - ReadOnlySpan valuesStr = stackalloc char[] { c }; - Span convertedStr = stackalloc byte[1]; - var consumed = _encoding.GetBytes(valuesStr, convertedStr); - Debug.Assert(consumed == 1); - return convertedStr[0]; - } - - private char ByteToChar(byte b) - { - ReadOnlySpan valueBytes = stackalloc byte[] { b }; - Span resultStr = stackalloc char[1]; - var consumed = _encoding.GetChars(valueBytes, resultStr); - Debug.Assert(consumed == 1); - return resultStr[0]; - } - - public bool Equals(Cp437Grid? other) - { - if (ReferenceEquals(null, other)) return false; - if (ReferenceEquals(this, other)) return true; - return Height == other.Height && Width == other.Width && _byteGrid.Equals(other._byteGrid); - } - - public override bool Equals(object? obj) => ReferenceEquals(this, obj) || (obj is Cp437Grid other && Equals(other)); - public override int GetHashCode() => HashCode.Combine(_byteGrid, Height, Width); - public static bool operator ==(Cp437Grid? left, Cp437Grid? right) => Equals(left, right); - public static bool operator !=(Cp437Grid? left, Cp437Grid? right) => !Equals(left, right); -} diff --git a/tanks-backend/DisplayCommands/DisplayCommands.csproj b/tanks-backend/DisplayCommands/DisplayCommands.csproj deleted file mode 100644 index ca146b4..0000000 --- a/tanks-backend/DisplayCommands/DisplayCommands.csproj +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - true - true - - - - - - - - - - - - - - diff --git a/tanks-backend/DisplayCommands/DisplayExtensions.cs b/tanks-backend/DisplayCommands/DisplayExtensions.cs deleted file mode 100644 index 5c94d8d..0000000 --- a/tanks-backend/DisplayCommands/DisplayExtensions.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Text; -using DisplayCommands.Internals; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; - -namespace DisplayCommands; - -public static class DisplayExtensions -{ - static DisplayExtensions() - { - Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); - } - - public static IServiceCollection AddDisplay( - this IServiceCollection services, - IConfigurationSection? configurationSection = null - ) - { - services.AddSingleton(); - if (configurationSection != null) - services.Configure(configurationSection); - return services; - } -} \ No newline at end of file diff --git a/tanks-backend/DisplayCommands/GlobalUsings.cs b/tanks-backend/DisplayCommands/GlobalUsings.cs deleted file mode 100644 index b124d17..0000000 --- a/tanks-backend/DisplayCommands/GlobalUsings.cs +++ /dev/null @@ -1,2 +0,0 @@ -global using System; -global using System.Threading.Tasks; diff --git a/tanks-backend/DisplayCommands/IDisplayConnection.cs b/tanks-backend/DisplayCommands/IDisplayConnection.cs deleted file mode 100644 index 950e75b..0000000 --- a/tanks-backend/DisplayCommands/IDisplayConnection.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace DisplayCommands; - -public interface IDisplayConnection -{ - ValueTask SendClearAsync(); - - ValueTask SendCp437DataAsync(ushort x, ushort y, Cp437Grid grid); - - ValueTask SendBrightnessAsync(byte brightness); - - ValueTask SendCharBrightnessAsync(ushort x, ushort y, ByteGrid luma); - - ValueTask SendHardResetAsync(); - - ValueTask SendFadeOutAsync(byte loops); - - 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. - /// - /// IPv4 as text - public string GetLocalIPv4(); -} diff --git a/tanks-backend/DisplayCommands/Internals/DisplayCommand.cs b/tanks-backend/DisplayCommands/Internals/DisplayCommand.cs deleted file mode 100644 index abe94e1..0000000 --- a/tanks-backend/DisplayCommands/Internals/DisplayCommand.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace DisplayCommands.Internals; - -internal enum DisplayCommand : ushort -{ - Clear = 0x0002, - Cp437Data = 0x0003, - CharBrightness = 0x0005, - Brightness = 0x0007, - HardReset = 0x000b, - FadeOut = 0x000d, - [Obsolete("ignored by display code")] BitmapLegacy = 0x0010, - BitmapLinear = 0x0012, - BitmapLinearWin = 0x0013, - BitmapLinearAnd = 0x0014, - BitmapLinearOr = 0x0015, - BitmapLinearXor = 0x0016 -} diff --git a/tanks-backend/DisplayCommands/Internals/DisplayConnection.cs b/tanks-backend/DisplayCommands/Internals/DisplayConnection.cs deleted file mode 100644 index 972a5db..0000000 --- a/tanks-backend/DisplayCommands/Internals/DisplayConnection.cs +++ /dev/null @@ -1,126 +0,0 @@ -using System.Buffers; -using System.Diagnostics; -using System.Net; -using System.Net.Sockets; -using System.Runtime.InteropServices; -using Microsoft.Extensions.Options; - -namespace DisplayCommands.Internals; - -internal sealed class DisplayConnection(IOptions options) : IDisplayConnection, IDisposable -{ - private readonly ArrayPool _arrayPool = ArrayPool.Shared; - private readonly UdpClient _udpClient = new(options.Value.Hostname, options.Value.Port); - - public ValueTask SendClearAsync() - { - var header = new HeaderWindow { Command = (ushort)DisplayCommand.Clear }; - - return SendAsync(header, Memory.Empty); - } - - public ValueTask SendCp437DataAsync(ushort x, ushort y, Cp437Grid grid) - { - var header = new HeaderWindow - { - Command = (ushort)DisplayCommand.Cp437Data, - Height = grid.Height, - Width = grid.Width, - PosX = x, - PosY = y - }; - - return SendAsync(header, grid.Data); - } - - public ValueTask SendCharBrightnessAsync(ushort x, ushort y, ByteGrid luma) - { - var header = new HeaderWindow - { - Command = (ushort)DisplayCommand.CharBrightness, - PosX = x, - PosY = y, - Height = luma.Height, - Width = luma.Width - }; - - return SendAsync(header, luma.Data); - } - - public async ValueTask SendBrightnessAsync(byte brightness) - { - var header = new HeaderWindow { Command = (ushort)DisplayCommand.Brightness }; - - var payloadBuffer = _arrayPool.Rent(1); - var payload = payloadBuffer.AsMemory(0, 1); - payload.Span[0] = brightness; - - await SendAsync(header, payload); - _arrayPool.Return(payloadBuffer); - } - - public ValueTask SendHardResetAsync() - { - var header = new HeaderWindow { Command = (ushort)DisplayCommand.HardReset }; - return SendAsync(header, Memory.Empty); - } - - public async ValueTask SendFadeOutAsync(byte loops) - { - var header = new HeaderWindow { Command = (ushort)DisplayCommand.FadeOut }; - - var payloadBuffer = _arrayPool.Rent(1); - var payload = payloadBuffer.AsMemory(0, 1); - payload.Span[0] = loops; - - await SendAsync(header, payload); - _arrayPool.Return(payloadBuffer); - } - - public ValueTask SendBitmapLinearWindowAsync(ushort x, ushort y, PixelGrid pixels) - { - var header = new HeaderWindow - { - Command = (ushort)DisplayCommand.BitmapLinearWin, - PosX = x, - PosY = y, - Width = (ushort)(pixels.Width / 8), - Height = pixels.Height - }; - - return SendAsync(header, pixels.Data); - } - - public string GetLocalIPv4() - { - using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0); - socket.Connect(options.Value.Hostname, options.Value.Port); - var endPoint = socket.LocalEndPoint as IPEndPoint ?? throw new NotSupportedException(); - return endPoint.Address.ToString(); - } - - private async ValueTask SendAsync(HeaderWindow header, Memory payload) - { - int headerSize; - unsafe - { - // because we specified the struct layout, no platform-specific padding will be added and this is be safe. - headerSize = sizeof(HeaderWindow); - } - - Debug.Assert(headerSize == 10); - var messageSize = headerSize + payload.Length; - - var buffer = _arrayPool.Rent(messageSize); - var message = buffer.AsMemory(0, messageSize); - - MemoryMarshal.Write(message.Span, header); - payload.CopyTo(message[headerSize..]); - - await _udpClient.SendAsync(message); - - _arrayPool.Return(buffer); - } - - public void Dispose() => _udpClient.Dispose(); -} diff --git a/tanks-backend/DisplayCommands/Internals/DisplaySubCommand.cs b/tanks-backend/DisplayCommands/Internals/DisplaySubCommand.cs deleted file mode 100644 index bf5427f..0000000 --- a/tanks-backend/DisplayCommands/Internals/DisplaySubCommand.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace DisplayCommands.Internals; - -internal enum DisplaySubCommand : ushort -{ - BitmapNormal = 0x0, - BitmapCompressZ = 0x677a, - BitmapCompressBz = 0x627a, - BitmapCompressLz = 0x6c7a, - BitmapCompressZs = 0x7a73 -} diff --git a/tanks-backend/DisplayCommands/Internals/HeaderBitmap.cs b/tanks-backend/DisplayCommands/Internals/HeaderBitmap.cs deleted file mode 100644 index b733995..0000000 --- a/tanks-backend/DisplayCommands/Internals/HeaderBitmap.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Runtime.InteropServices; -using EndiannessSourceGenerator; - -namespace DisplayCommands.Internals; - -[StructEndianness(IsLittleEndian = false)] -[StructLayout(LayoutKind.Sequential, Pack = 16, Size = 10)] -internal partial struct HeaderBitmap -{ - private ushort _command; - - private ushort _offset; - - private ushort _length; - - private ushort _subCommand; - - private ushort _reserved; -} diff --git a/tanks-backend/DisplayCommands/Internals/HeaderWindow.cs b/tanks-backend/DisplayCommands/Internals/HeaderWindow.cs deleted file mode 100644 index 2be4916..0000000 --- a/tanks-backend/DisplayCommands/Internals/HeaderWindow.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Runtime.InteropServices; -using EndiannessSourceGenerator; - -namespace DisplayCommands.Internals; - -[StructEndianness(IsLittleEndian = false)] -[StructLayout(LayoutKind.Sequential, Pack = 16, Size = 10)] -internal partial struct HeaderWindow -{ - private ushort _command; - - private ushort _posX; - - private ushort _posY; - - private ushort _width; - - private ushort _height; -} diff --git a/tanks-backend/DisplayCommands/PixelGrid.cs b/tanks-backend/DisplayCommands/PixelGrid.cs deleted file mode 100644 index 5006ddb..0000000 --- a/tanks-backend/DisplayCommands/PixelGrid.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System.Diagnostics; - -namespace DisplayCommands; - -public sealed class PixelGrid(ushort width, ushort height) : IEquatable -{ - private readonly ByteGrid _byteGrid = new((ushort)(width / 8u), height); - - public ushort Width { get; } = width; - - public ushort Height { get; } = height; - - public Memory Data => _byteGrid.Data; - - public bool this[ushort x, ushort y] - { - get - { - Debug.Assert(y < Height); - var (byteIndex, bitInByteMask) = GetIndexes(x); - var byteVal = _byteGrid[byteIndex, y]; - return (byteVal & bitInByteMask) != 0; - } - set - { - Debug.Assert(y < Height); - var (byteIndex, bitInByteMask) = GetIndexes(x); - if (value) - _byteGrid[byteIndex, y] |= bitInByteMask; - else - _byteGrid[byteIndex, y] &= (byte)(ushort.MaxValue ^ bitInByteMask); - } - } - - public void Clear() => _byteGrid.Clear(); - - public bool Equals(PixelGrid? other) - { - if (ReferenceEquals(null, other)) return false; - if (ReferenceEquals(this, other)) return true; - return Width == other.Width && Height == other.Height && _byteGrid.Equals(other._byteGrid); - } - - public override bool Equals(object? obj) => ReferenceEquals(this, obj) || (obj is PixelGrid other && Equals(other)); - public override int GetHashCode() => HashCode.Combine(_byteGrid, Width, Height); - public static bool operator ==(PixelGrid? left, PixelGrid? right) => Equals(left, right); - public static bool operator !=(PixelGrid? left, PixelGrid? right) => !Equals(left, right); - - private (ushort byteIndex, byte bitInByteMask) GetIndexes(int x) - { - Debug.Assert(x < Width); - var byteIndex = (ushort)(x / 8); - Debug.Assert(byteIndex < Width); - var bitInByteIndex = (byte)(7 - x % 8); - Debug.Assert(bitInByteIndex < 8); - var bitInByteMask = (byte)(1 << bitInByteIndex); - return (byteIndex, bitInByteMask); - } -} diff --git a/tanks-backend/EndiannessSourceGenerator/EndiannessGenerator.cs b/tanks-backend/EndiannessSourceGenerator/EndiannessGenerator.cs deleted file mode 100644 index eb772e5..0000000 --- a/tanks-backend/EndiannessSourceGenerator/EndiannessGenerator.cs +++ /dev/null @@ -1,260 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; -using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; - -namespace EndiannessSourceGenerator; - -internal class DebugMeException(string message) : Exception(message); - -internal class InvalidUsageException(string message) : Exception(message); - -[Generator] -public class StructEndiannessSourceGenerator : ISourceGenerator -{ - private const string Namespace = "EndiannessSourceGenerator"; - private const string AttributeName = "StructEndiannessAttribute"; - private const string IsLittleEndianProperty = "IsLittleEndian"; - - private const string AttributeSourceCode = - $$""" - // - namespace {{Namespace}} - { - [System.AttributeUsage(System.AttributeTargets.Struct)] - public class {{AttributeName}}: System.Attribute - { - public required bool {{IsLittleEndianProperty}} { get; init; } - } - } - """; - - public void Initialize(GeneratorInitializationContext context) - { - // Register the attribute source - context.RegisterForPostInitialization(i => i.AddSource($"{AttributeName}.g.cs", AttributeSourceCode)); - } - - public void Execute(GeneratorExecutionContext context) - { - var treesWithStructsWithAttributes = context.Compilation.SyntaxTrees - .Where(st => st.GetRoot().DescendantNodes() - .OfType() - .Any(p => p.DescendantNodes() - .OfType() - .Any())) - .ToList(); - - foreach (var tree in treesWithStructsWithAttributes) - { - var semanticModel = context.Compilation.GetSemanticModel(tree); - - var structsWithAttributes = tree.GetRoot().DescendantNodes() - .OfType() - .Where(cd => cd.DescendantNodes() - .OfType() - .Any()); - - foreach (var structDeclaration in structsWithAttributes) - { - var foundAttribute = GetEndiannessAttribute(structDeclaration, semanticModel); - if (foundAttribute == null) - continue; // not my type - - var structIsLittleEndian = GetStructIsLittleEndian(foundAttribute); - HandleStruct(context, structDeclaration, semanticModel, structIsLittleEndian); - } - } - } - - private static void HandleStruct(GeneratorExecutionContext context, TypeDeclarationSyntax structDeclaration, - SemanticModel semanticModel, bool structIsLittleEndian) - { - var isPartial = structDeclaration.Modifiers.Any(m => m.IsKind(SyntaxKind.PartialKeyword)); - if (!isPartial) - throw new InvalidUsageException("struct is not marked partial"); - - var accessibilityModifier = structDeclaration.Modifiers.Any(m => m.IsKind(SyntaxKind.InternalKeyword)) - ? Token(SyntaxKind.InternalKeyword) - : Token(SyntaxKind.PublicKeyword); - - var structType = semanticModel.GetDeclaredSymbol(structDeclaration); - if (structType == null) - throw new DebugMeException("struct type info is null"); - - var structNamespace = structType.ContainingNamespace?.ToDisplayString(); - if (structNamespace == null) - throw new InvalidUsageException("struct has to be contained in a namespace"); - - if (structDeclaration.Members.Any(m => m.IsKind(SyntaxKind.PropertyDeclaration))) - throw new InvalidUsageException("struct cannot have properties"); - - var fieldDeclarations = structDeclaration.Members - .Where(m => m.IsKind(SyntaxKind.FieldDeclaration)).OfType(); - - var generatedCode = CompilationUnit() - .WithUsings(List([ - UsingDirective(IdentifierName("System")), - UsingDirective(IdentifierName("System.Buffers.Binary")) - ])) - .WithMembers(List([ - FileScopedNamespaceDeclaration(IdentifierName(structNamespace)), - StructDeclaration(structType.Name) - .WithModifiers(TokenList([accessibilityModifier, Token(SyntaxKind.PartialKeyword)])) - .WithMembers(GenerateStructProperties(fieldDeclarations, semanticModel, structIsLittleEndian)) - ])) - .NormalizeWhitespace() - .ToFullString(); - - context.AddSource( - $"{structNamespace}.{structType.Name}.g.cs", - SourceText.From(generatedCode, Encoding.UTF8) - ); - } - - private static SyntaxList GenerateStructProperties( - IEnumerable fieldDeclarations, SemanticModel semanticModel, bool structIsLittleEndian) - { - var result = new List(); - foreach (var field in fieldDeclarations) - { - if (!field.Modifiers.Any(m => m.IsKind(SyntaxKind.PrivateKeyword))) - throw new InvalidUsageException("fields have to be private"); - - var variableDeclaration = field.DescendantNodes() - .OfType() - .FirstOrDefault(); - if (variableDeclaration == null) - throw new DebugMeException("variable declaration of field declaration null"); - - var variableTypeInfo = semanticModel.GetTypeInfo(variableDeclaration.Type).Type; - if (variableTypeInfo == null) - throw new DebugMeException("variable type info of field declaration null"); - - var typeName = variableTypeInfo.ToDisplayString(); - var fieldName = variableDeclaration.Variables.First().Identifier.ToString(); - - result.Add(GenerateProperty(typeName, structIsLittleEndian, fieldName)); - } - - return new SyntaxList(result); - } - - private static PropertyDeclarationSyntax GenerateProperty(string typeName, - bool structIsLittleEndian, string fieldName) - { - var propertyName = GeneratePropertyName(fieldName); - var fieldIdentifier = IdentifierName(fieldName); - - ExpressionSyntax condition = MemberAccessExpression( - kind: SyntaxKind.SimpleMemberAccessExpression, - expression: IdentifierName("BitConverter"), - name: IdentifierName("IsLittleEndian") - ); - - if (!structIsLittleEndian) - condition = PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, condition); - - var reverseEndiannessMethod = MemberAccessExpression( - kind: SyntaxKind.SimpleMemberAccessExpression, - expression: IdentifierName("BinaryPrimitives"), - name: IdentifierName("ReverseEndianness") - ); - - var valueIdentifier = IdentifierName("value"); - - return PropertyDeclaration(ParseTypeName(typeName), propertyName) - .WithModifiers(TokenList([Token(SyntaxKind.PublicKeyword)])) - .WithAccessorList(AccessorList(List([ - AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) - .WithExpressionBody(ArrowExpressionClause(ConditionalExpression( - condition: condition, - whenTrue: fieldIdentifier, - whenFalse: InvocationExpression( - expression: reverseEndiannessMethod, - argumentList: ArgumentList(SingletonSeparatedList( - Argument(fieldIdentifier) - )) - ) - ))) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), - AccessorDeclaration(SyntaxKind.SetAccessorDeclaration) - .WithExpressionBody(ArrowExpressionClause(AssignmentExpression( - kind: SyntaxKind.SimpleAssignmentExpression, - left: fieldIdentifier, - right: ConditionalExpression( - condition: condition, - whenTrue: valueIdentifier, - whenFalse: InvocationExpression( - expression: reverseEndiannessMethod, - argumentList: ArgumentList(SingletonSeparatedList( - Argument(valueIdentifier) - )) - ) - ) - ))) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) - ])) - ); - } - - private static SyntaxToken GeneratePropertyName(string fieldName) - { - var propertyName = fieldName; - if (propertyName.StartsWith("_")) - propertyName = propertyName.Substring(1); - if (!char.IsLetter(propertyName, 0) || char.IsUpper(propertyName, 0)) - throw new InvalidUsageException("field names have to start with a lower case letter"); - propertyName = propertyName.Substring(0, 1).ToUpperInvariant() - + propertyName.Substring(1); - return Identifier(propertyName); - } - - private static AttributeSyntax? GetEndiannessAttribute(SyntaxNode structDeclaration, SemanticModel semanticModel) - { - AttributeSyntax? foundAttribute = null; - foreach (var attributeSyntax in structDeclaration.DescendantNodes().OfType()) - { - var attributeTypeInfo = semanticModel.GetTypeInfo(attributeSyntax).Type; - if (attributeTypeInfo == null) - throw new DebugMeException("attribute type info is null"); - - if (attributeTypeInfo.ContainingNamespace?.Name != Namespace) - continue; - if (attributeTypeInfo.Name != AttributeName) - continue; - - foundAttribute = attributeSyntax; - break; - } - - return foundAttribute; - } - - private static bool GetStructIsLittleEndian(AttributeSyntax foundAttribute) - { - var endiannessArguments = foundAttribute.ArgumentList; - if (endiannessArguments == null) - throw new InvalidUsageException("endianness attribute has no arguments"); - - var isLittleEndianArgumentSyntax = endiannessArguments.Arguments - .FirstOrDefault(argumentSyntax => - argumentSyntax.NameEquals?.Name.Identifier.ToString() == IsLittleEndianProperty); - if (isLittleEndianArgumentSyntax == null) - throw new InvalidUsageException("endianness attribute argument not found"); - - bool? structIsLittleEndian = isLittleEndianArgumentSyntax.Expression.Kind() switch - { - SyntaxKind.FalseLiteralExpression => false, - SyntaxKind.TrueLiteralExpression => true, - SyntaxKind.DefaultLiteralExpression => false, - _ => throw new InvalidUsageException($"{IsLittleEndianProperty} has to be set with a literal") - }; - return structIsLittleEndian.Value; - } -} diff --git a/tanks-backend/EndiannessSourceGenerator/EndiannessSourceGenerator.csproj b/tanks-backend/EndiannessSourceGenerator/EndiannessSourceGenerator.csproj deleted file mode 100644 index ae25c62..0000000 --- a/tanks-backend/EndiannessSourceGenerator/EndiannessSourceGenerator.csproj +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - netstandard2.0 - false - enable - latest - - true - true - EndiannessSourceGenerator - false - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - diff --git a/tanks-backend/EndiannessSourceGenerator/Properties/launchSettings.json b/tanks-backend/EndiannessSourceGenerator/Properties/launchSettings.json deleted file mode 100644 index b8b1379..0000000 --- a/tanks-backend/EndiannessSourceGenerator/Properties/launchSettings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "http://json.schemastore.org/launchsettings.json", - "profiles": { - "Generators": { - "commandName": "DebugRoslynComponent", - "targetProject": "../DisplayCommands/DisplayCommands.csproj" - } - } -} diff --git a/tanks-backend/EndiannessSourceGenerator/Readme.md b/tanks-backend/EndiannessSourceGenerator/Readme.md deleted file mode 100644 index a69efd1..0000000 --- a/tanks-backend/EndiannessSourceGenerator/Readme.md +++ /dev/null @@ -1,5 +0,0 @@ -# Endianness Source Generator - -When annotating a struct with the `StructEndianness` attribute, this code generator will generate properties for the declared fields. - -Each time a property is read or written, the endianness is converted from runtime endianness to struct endianness or vice-versa. diff --git a/tanks-backend/TanksServer.sln b/tanks-backend/TanksServer.sln index fc3a074..b28b08a 100644 --- a/tanks-backend/TanksServer.sln +++ b/tanks-backend/TanksServer.sln @@ -2,10 +2,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("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DisplayCommands", "DisplayCommands\DisplayCommands.csproj", "{B4B43561-7A2C-486B-99F7-E58A67BC370A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EndiannessSourceGenerator", "EndiannessSourceGenerator\EndiannessSourceGenerator.csproj", "{D77FE880-F2B8-43B6-8B33-B6FA089CC337}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shared", "shared", "{12DB7D48-1BB2-488B-B4D9-4126087D2F8C}" ProjectSection(SolutionItems) = preProject global.json = global.json @@ -13,6 +9,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shared", "shared", "{12DB7D Dockerfile = Dockerfile EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServicePoint2", "..\..\servicepoint2\servicepoint2-binding-cs\ServicePoint2\ServicePoint2.csproj", "{BC27CED4-82FE-4CD4-B784-B7596586801D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -23,13 +21,9 @@ 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 - {B4B43561-7A2C-486B-99F7-E58A67BC370A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B4B43561-7A2C-486B-99F7-E58A67BC370A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B4B43561-7A2C-486B-99F7-E58A67BC370A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B4B43561-7A2C-486B-99F7-E58A67BC370A}.Release|Any CPU.Build.0 = Release|Any CPU - {D77FE880-F2B8-43B6-8B33-B6FA089CC337}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D77FE880-F2B8-43B6-8B33-B6FA089CC337}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D77FE880-F2B8-43B6-8B33-B6FA089CC337}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D77FE880-F2B8-43B6-8B33-B6FA089CC337}.Release|Any CPU.Build.0 = Release|Any CPU + {BC27CED4-82FE-4CD4-B784-B7596586801D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BC27CED4-82FE-4CD4-B784-B7596586801D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BC27CED4-82FE-4CD4-B784-B7596586801D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BC27CED4-82FE-4CD4-B784-B7596586801D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/tanks-backend/TanksServer/Endpoints.cs b/tanks-backend/TanksServer/Endpoints.cs index 1456f0f..99da3b1 100644 --- a/tanks-backend/TanksServer/Endpoints.cs +++ b/tanks-backend/TanksServer/Endpoints.cs @@ -1,13 +1,13 @@ using System.IO; using System.Text; using System.Text.Json; -using DisplayCommands; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Diagnostics.HealthChecks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Diagnostics.HealthChecks; +using ServicePoint2; using TanksServer.GameLogic; using TanksServer.Interactivity; @@ -19,7 +19,7 @@ internal sealed class Endpoints( ControlsServer controlsServer, MapService mapService, ChangeToRequestedMap changeToRequestedMap, - IDisplayConnection displayConnection + Connection displayConnection ) { public void Map(WebApplication app) @@ -31,7 +31,7 @@ internal sealed class Endpoints( app.Map("/controls", ConnectControlsAsync); app.MapGet("/map", () => mapService.MapNames); app.MapPost("/map", PostMap); - app.MapPost("/resetDisplay", displayConnection.SendHardResetAsync); + app.MapPost("/resetDisplay", () => displayConnection.Send(Command.HardReset())); app.MapGet("/map/{name}", GetMapByName); app.MapHealthChecks("/health", new HealthCheckOptions @@ -117,7 +117,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); + var mapInfo = new MapInfo(prototype.Name, prototype.GetType().Name, preview.Data.ToArray()); return TypedResults.Ok(mapInfo); } diff --git a/tanks-backend/TanksServer/GameLogic/MapService.cs b/tanks-backend/TanksServer/GameLogic/MapService.cs index 28a5aef..753d007 100644 --- a/tanks-backend/TanksServer/GameLogic/MapService.cs +++ b/tanks-backend/TanksServer/GameLogic/MapService.cs @@ -1,7 +1,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; -using DisplayCommands; +using ServicePoint2; using TanksServer.Graphics; namespace TanksServer.GameLogic; @@ -42,7 +42,7 @@ internal sealed class MapService if (!_mapPrototypes.TryGetValue(name, out var prototype)) return false; // name not found - pixelGrid = new PixelGrid(PixelsPerRow, PixelsPerColumn); + pixelGrid = PixelGrid.New(PixelsPerRow, PixelsPerColumn); DrawMapStep.Draw(pixelGrid, prototype.CreateInstance()); _mapPreviews.TryAdd(name, pixelGrid); // another thread may have added the map already diff --git a/tanks-backend/TanksServer/GameLogic/SpawnPowerUp.cs b/tanks-backend/TanksServer/GameLogic/SpawnPowerUp.cs index 3107b71..b79abb0 100644 --- a/tanks-backend/TanksServer/GameLogic/SpawnPowerUp.cs +++ b/tanks-backend/TanksServer/GameLogic/SpawnPowerUp.cs @@ -1,5 +1,3 @@ -using System.Diagnostics; - namespace TanksServer.GameLogic; internal sealed class SpawnPowerUp( diff --git a/tanks-backend/TanksServer/Graphics/DrawMapStep.cs b/tanks-backend/TanksServer/Graphics/DrawMapStep.cs index 3be6a37..3fc59b5 100644 --- a/tanks-backend/TanksServer/Graphics/DrawMapStep.cs +++ b/tanks-backend/TanksServer/Graphics/DrawMapStep.cs @@ -1,4 +1,4 @@ -using DisplayCommands; +using ServicePoint2; using TanksServer.GameLogic; namespace TanksServer.Graphics; diff --git a/tanks-backend/TanksServer/Graphics/GeneratePixelsTickStep.cs b/tanks-backend/TanksServer/Graphics/GeneratePixelsTickStep.cs index 7edf1a0..de83cbb 100644 --- a/tanks-backend/TanksServer/Graphics/GeneratePixelsTickStep.cs +++ b/tanks-backend/TanksServer/Graphics/GeneratePixelsTickStep.cs @@ -1,4 +1,4 @@ -using DisplayCommands; +using ServicePoint2; using TanksServer.GameLogic; using TanksServer.Interactivity; @@ -10,9 +10,9 @@ internal sealed class GeneratePixelsTickStep( ) : ITickStep { private GamePixelGrid _lastGamePixelGrid = new(MapService.PixelsPerRow, MapService.PixelsPerColumn); - private PixelGrid _lastObserverPixelGrid = new(MapService.PixelsPerRow, MapService.PixelsPerColumn); + private PixelGrid _lastObserverPixelGrid = PixelGrid.New(MapService.PixelsPerRow, MapService.PixelsPerColumn); private GamePixelGrid _gamePixelGrid = new(MapService.PixelsPerRow, MapService.PixelsPerColumn); - private PixelGrid _observerPixelGrid = new(MapService.PixelsPerRow, MapService.PixelsPerColumn); + private PixelGrid _observerPixelGrid = PixelGrid.New(MapService.PixelsPerRow, MapService.PixelsPerColumn); private readonly List _drawSteps = drawSteps.ToList(); private readonly List _consumers = consumers.ToList(); @@ -20,7 +20,7 @@ internal sealed class GeneratePixelsTickStep( public async ValueTask TickAsync(TimeSpan _) { Draw(_gamePixelGrid, _observerPixelGrid); - if (_observerPixelGrid.Data.Span.SequenceEqual(_lastObserverPixelGrid.Data.Span)) + if (_observerPixelGrid.Data.SequenceEqual(_lastObserverPixelGrid.Data)) return; await _consumers.Select(c => c.OnFrameDoneAsync(_gamePixelGrid, _observerPixelGrid)) @@ -36,7 +36,7 @@ internal sealed class GeneratePixelsTickStep( foreach (var step in _drawSteps) step.Draw(gamePixelGrid); - observerPixelGrid.Clear(); + observerPixelGrid.Fill(false); for (var y = 0; y < MapService.PixelsPerColumn; y++) for (var x = 0; x < MapService.PixelsPerRow; x++) { diff --git a/tanks-backend/TanksServer/Graphics/IFrameConsumer.cs b/tanks-backend/TanksServer/Graphics/IFrameConsumer.cs index 5a83a86..9ee8d3e 100644 --- a/tanks-backend/TanksServer/Graphics/IFrameConsumer.cs +++ b/tanks-backend/TanksServer/Graphics/IFrameConsumer.cs @@ -1,4 +1,4 @@ -using DisplayCommands; +using ServicePoint2; namespace TanksServer.Graphics; diff --git a/tanks-backend/TanksServer/Interactivity/ClientScreenServer.cs b/tanks-backend/TanksServer/Interactivity/ClientScreenServer.cs index 6955c4d..2832fba 100644 --- a/tanks-backend/TanksServer/Interactivity/ClientScreenServer.cs +++ b/tanks-backend/TanksServer/Interactivity/ClientScreenServer.cs @@ -1,5 +1,5 @@ using System.Net.WebSockets; -using DisplayCommands; +using ServicePoint2; using TanksServer.Graphics; namespace TanksServer.Interactivity; diff --git a/tanks-backend/TanksServer/Interactivity/ClientScreenServerConnection.cs b/tanks-backend/TanksServer/Interactivity/ClientScreenServerConnection.cs index 6208cbf..483176a 100644 --- a/tanks-backend/TanksServer/Interactivity/ClientScreenServerConnection.cs +++ b/tanks-backend/TanksServer/Interactivity/ClientScreenServerConnection.cs @@ -1,6 +1,6 @@ using System.Buffers; using System.Net.WebSockets; -using DisplayCommands; +using ServicePoint2; using TanksServer.Graphics; namespace TanksServer.Interactivity; @@ -36,8 +36,9 @@ internal sealed class ClientScreenServerConnection private Package BuildNextPackage(PixelGrid pixels, GamePixelGrid gamePixelGrid) { - var nextPixels = _bufferPool.Rent(pixels.Data.Length); - pixels.Data.CopyTo(nextPixels.Memory); + var pixelsData = pixels.Data; + var nextPixels = _bufferPool.Rent(pixelsData.Length); + pixelsData.CopyTo(nextPixels.Memory.Span); if (_playerDataBuilder == null) return new Package(nextPixels, null); diff --git a/tanks-backend/TanksServer/Interactivity/PlayerInfoConnection.cs b/tanks-backend/TanksServer/Interactivity/PlayerInfoConnection.cs index a81d2c4..6340fbc 100644 --- a/tanks-backend/TanksServer/Interactivity/PlayerInfoConnection.cs +++ b/tanks-backend/TanksServer/Interactivity/PlayerInfoConnection.cs @@ -13,7 +13,7 @@ internal sealed class PlayerInfoConnection private readonly MapEntityManager _entityManager; private readonly BufferPool _bufferPool; private readonly MemoryStream _tempStream = new(); - private IMemoryOwner? _lastMessage = null; + private IMemoryOwner? _lastMessage; public PlayerInfoConnection( Player player, diff --git a/tanks-backend/TanksServer/Interactivity/SendToServicePointDisplay.cs b/tanks-backend/TanksServer/Interactivity/SendToServicePointDisplay.cs index fc64cc9..0c7cc7d 100644 --- a/tanks-backend/TanksServer/Interactivity/SendToServicePointDisplay.cs +++ b/tanks-backend/TanksServer/Interactivity/SendToServicePointDisplay.cs @@ -1,6 +1,7 @@ using System.Diagnostics; +using System.Net; using System.Net.Sockets; -using DisplayCommands; +using ServicePoint2; using TanksServer.GameLogic; using TanksServer.Graphics; @@ -12,11 +13,11 @@ internal sealed class SendToServicePointDisplay : IFrameConsumer private const int ScoresHeight = 20; private const int ScoresPlayerRows = ScoresHeight - 6; - private readonly IDisplayConnection _displayConnection; + private readonly Connection _displayConnection; private readonly MapService _mapService; private readonly ILogger _logger; private readonly PlayerServer _players; - private readonly Cp437Grid _scoresBuffer; + private readonly ByteGrid _scoresBuffer; private readonly TimeSpan _minFrameTime; private readonly IOptionsMonitor _options; @@ -26,11 +27,11 @@ internal sealed class SendToServicePointDisplay : IFrameConsumer public SendToServicePointDisplay( PlayerServer players, ILogger logger, - IDisplayConnection displayConnection, + Connection displayConnection, IOptions hostOptions, MapService mapService, - IOptionsMonitor options - ) + IOptionsMonitor options, + IOptions displayConfig) { _players = players; _logger = logger; @@ -39,16 +40,15 @@ internal sealed class SendToServicePointDisplay : IFrameConsumer _minFrameTime = TimeSpan.FromMilliseconds(hostOptions.Value.ServicePointDisplayMinFrameTimeMs); _options = options; - var localIp = _displayConnection.GetLocalIPv4().Split('.'); + var localIp = GetLocalIPv4(displayConfig.Value).Split('.'); Debug.Assert(localIp.Length == 4); - _scoresBuffer = new Cp437Grid(12, 20) - { - [00] = "== TANKS! ==", - [01] = "-- scores --", - [17] = "-- join --", - [18] = string.Join('.', localIp[..2]), - [19] = string.Join('.', localIp[2..]) - }; + _scoresBuffer = ByteGrid.New(12, 20); + + _scoresBuffer[00] = "== TANKS! =="; + _scoresBuffer[01] = "-- scores --"; + _scoresBuffer[17] = "-- join --"; + _scoresBuffer[18] = string.Join('.', localIp[..2]); + _scoresBuffer[19] = string.Join('.', localIp[2..]); } public async Task OnFrameDoneAsync(GamePixelGrid gamePixelGrid, PixelGrid observerPixels) @@ -66,8 +66,8 @@ internal sealed class SendToServicePointDisplay : IFrameConsumer try { - await _displayConnection.SendBitmapLinearWindowAsync(0, 0, observerPixels); - await _displayConnection.SendCp437DataAsync(MapService.TilesPerRow, 0, _scoresBuffer); + _displayConnection.Send(Command.BitmapLinearWin(0, 0, observerPixels.Clone())); + _displayConnection.Send(Command.Cp437Data(MapService.TilesPerRow, 0, _scoresBuffer.Clone())); } catch (SocketException ex) { @@ -103,4 +103,12 @@ internal sealed class SendToServicePointDisplay : IFrameConsumer _scoresBuffer[16] = _mapService.Current.Name[..(Math.Min(ScoresWidth, _mapService.Current.Name.Length) - 1)]; } + + private static string GetLocalIPv4(DisplayConfiguration configuration) + { + using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0); + socket.Connect(configuration.Hostname, configuration.Port); + var endPoint = socket.LocalEndPoint as IPEndPoint ?? throw new NotSupportedException(); + return endPoint.Address.ToString(); + } } diff --git a/tanks-backend/DisplayCommands/DisplayConfiguration.cs b/tanks-backend/TanksServer/Models/DisplayConfiguration.cs similarity index 81% rename from tanks-backend/DisplayCommands/DisplayConfiguration.cs rename to tanks-backend/TanksServer/Models/DisplayConfiguration.cs index ff3cf05..fc9e941 100644 --- a/tanks-backend/DisplayCommands/DisplayConfiguration.cs +++ b/tanks-backend/TanksServer/Models/DisplayConfiguration.cs @@ -1,8 +1,8 @@ -namespace DisplayCommands; +namespace TanksServer.Models; public class DisplayConfiguration { public string Hostname { get; set; } = "172.23.42.29"; public int Port { get; set; } = 2342; -} \ No newline at end of file +} diff --git a/tanks-backend/TanksServer/Program.cs b/tanks-backend/TanksServer/Program.cs index efe9bb4..89c71ae 100644 --- a/tanks-backend/TanksServer/Program.cs +++ b/tanks-backend/TanksServer/Program.cs @@ -1,8 +1,9 @@ using System.IO; -using DisplayCommands; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.FileProviders; +using ServicePoint2; +using SixLabors.ImageSharp; using TanksServer.GameLogic; using TanksServer.Graphics; using TanksServer.Interactivity; @@ -94,9 +95,14 @@ public static class Program builder.Services.Configure(builder.Configuration.GetSection("GameRules")); builder.Services.Configure(builder.Configuration.GetSection("Host")); + builder.Services.Configure(builder.Configuration.GetSection("ServicePointDisplay")); builder.Services.AddSingleton(); - builder.Services.AddDisplay(builder.Configuration.GetSection("ServicePointDisplay")); + builder.Services.AddSingleton(sp => + { + var config = sp.GetRequiredService>().Value; + return Connection.Open($"{config.Hostname}:{config.Port}"); + }); var app = builder.Build(); diff --git a/tanks-backend/TanksServer/TanksServer.csproj b/tanks-backend/TanksServer/TanksServer.csproj index 4cce028..8da3166 100644 --- a/tanks-backend/TanksServer/TanksServer.csproj +++ b/tanks-backend/TanksServer/TanksServer.csproj @@ -10,11 +10,14 @@ - + + + + diff --git a/tanks-backend/TanksServer/appsettings.json b/tanks-backend/TanksServer/appsettings.json index 0eaa26e..4555c28 100644 --- a/tanks-backend/TanksServer/appsettings.json +++ b/tanks-backend/TanksServer/appsettings.json @@ -16,7 +16,8 @@ } }, "ServicePointDisplay": { - "Hostname": "172.23.42.29", + //"Hostname": "172.23.42.29", + "Hostname": "127.0.0.1", "Port": 2342 }, "GameRules": {