diff --git a/.dockerignore b/.dockerignore index 38bece4..2cee31d 100644 --- a/.dockerignore +++ b/.dockerignore @@ -22,4 +22,5 @@ **/secrets.dev.yaml **/values.dev.yaml LICENSE -README.md \ No newline at end of file +README.md +**/node_modules diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..2a97396 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,38 @@ +FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build-server + +RUN apk add clang binutils musl-dev build-base zlib-static cmake openssl-dev openssl-libs-static openssl + +WORKDIR /src/TanksServer + +# dependencies +COPY TanksServer/TanksServer.csproj . +RUN dotnet restore --runtime linux-musl-x64 TanksServer.csproj + +#build +COPY TanksServer . +RUN dotnet build TanksServer.csproj -c Release -o /app/build +RUN dotnet publish TanksServer.csproj -r linux-musl-x64 -c Release -o /app/publish + + +FROM node:21-alpine AS build-client +WORKDIR /app + +# dependencies +COPY tank-frontend/package.json . +COPY tank-frontend/package-lock.json . +RUN npm i + +# build +env CONTAINERMODE 1 +COPY tank-frontend . +RUN npm run build + + +FROM mcr.microsoft.com/dotnet/runtime-deps:8.0-alpine AS final +WORKDIR /app + +COPY --from=build-server /app/publish . +COPY --from=build-client /app/dist ./client + +EXPOSE 80 +ENTRYPOINT ./TanksServer diff --git a/TanksServer/Dockerfile b/TanksServer/Dockerfile deleted file mode 100644 index 9d92e08..0000000 --- a/TanksServer/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base -WORKDIR /app -EXPOSE 80 -EXPOSE 443 - -FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build -WORKDIR /src -COPY ["TanksServer/TanksServer.csproj", "TanksServer/"] -RUN dotnet restore "TanksServer/TanksServer.csproj" -COPY . . -WORKDIR "/src/TanksServer" -RUN dotnet build "TanksServer.csproj" -c Release -o /app/build - -FROM build AS publish -RUN dotnet publish "TanksServer.csproj" -c Release -o /app/publish /p:UseAppHost=false - -FROM base AS final -WORKDIR /app -COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "TanksServer.dll"] diff --git a/TanksServer/Models/Player.cs b/TanksServer/Models/Player.cs index 3af9c24..30638ba 100644 --- a/TanksServer/Models/Player.cs +++ b/TanksServer/Models/Player.cs @@ -1,3 +1,5 @@ +using System.Text.Json.Serialization; + namespace TanksServer.Models; internal sealed class Player(string name) @@ -6,18 +8,10 @@ internal sealed class Player(string name) public Guid Id { get; } = Guid.NewGuid(); + [JsonIgnore] public PlayerControls Controls { get; } = new(); public int Kills { get; set; } public int Deaths { get; set; } -} - -internal sealed class PlayerControls -{ - public bool Forward { get; set; } - public bool Backward { get; set; } - public bool TurnLeft { get; set; } - public bool TurnRight { get; set; } - public bool Shoot { get; set; } -} +} \ No newline at end of file diff --git a/TanksServer/Models/PlayerControls.cs b/TanksServer/Models/PlayerControls.cs new file mode 100644 index 0000000..82e0bef --- /dev/null +++ b/TanksServer/Models/PlayerControls.cs @@ -0,0 +1,10 @@ +namespace TanksServer.Models; + +internal sealed class PlayerControls +{ + public bool Forward { get; set; } + public bool Backward { get; set; } + public bool TurnLeft { get; set; } + public bool TurnRight { get; set; } + public bool Shoot { get; set; } +} \ No newline at end of file diff --git a/TanksServer/Program.cs b/TanksServer/Program.cs index b8b87ca..e3cf71f 100644 --- a/TanksServer/Program.cs +++ b/TanksServer/Program.cs @@ -11,15 +11,12 @@ using TanksServer.ServicePointDisplay; namespace TanksServer; -internal static class Program +public static class Program { - public static async Task Main(string[] args) + public static void Main(string[] args) { var app = Configure(args); - app.UseCors(); - app.UseWebSockets(); - var clientScreenServer = app.Services.GetRequiredService(); var playerService = app.Services.GetRequiredService(); var controlsServer = app.Services.GetRequiredService(); @@ -52,10 +49,10 @@ internal static class Program using var ws = await context.WebSockets.AcceptWebSocketAsync(); await controlsServer.HandleClient(ws, player); - return Results.Empty; + return Results.Ok(); }); - await app.RunAsync(); + app.Run(); } private static WebApplication Configure(string[] args) @@ -74,7 +71,7 @@ internal static class Program options.SerializerOptions.TypeInfoResolverChain.Insert(0, new AppSerializerContext()); }); - builder.Services.AddOptions(); + builder.Services.AddHttpLogging(_ => { }); builder.Services.AddSingleton(); builder.Services.AddSingleton(); @@ -107,6 +104,12 @@ internal static class Program builder.Services.Configure( builder.Configuration.GetSection("ServicePointDisplay")); - return builder.Build(); + var app = builder.Build(); + + app.UseCors(); + app.UseWebSockets(); + app.UseHttpLogging(); + + return app; } -} +} \ No newline at end of file diff --git a/TanksServer/ServicePointDisplay/SendToServicePointDisplay.cs b/TanksServer/ServicePointDisplay/SendToServicePointDisplay.cs index acb0f29..7906f2f 100644 --- a/TanksServer/ServicePointDisplay/SendToServicePointDisplay.cs +++ b/TanksServer/ServicePointDisplay/SendToServicePointDisplay.cs @@ -14,6 +14,7 @@ internal sealed class SendToServicePointDisplay : ITickStep, IDisposable private readonly TextDisplayBuffer _scoresBuffer; private readonly PlayerServer _players; private readonly ILogger _logger; + private DateTime _nextFailLog = DateTime.Now; private const int ScoresWidth = 12; private const int ScoresHeight = 20; @@ -70,7 +71,11 @@ internal sealed class SendToServicePointDisplay : ITickStep, IDisposable } catch (SocketException ex) { - _logger.LogWarning(ex, "could not send data to service point display"); + if (DateTime.Now > _nextFailLog) + { + _logger.LogWarning("could not send data to service point display: {}", ex.Message); + _nextFailLog = DateTime.Now + TimeSpan.FromSeconds(5); + } } } } diff --git a/TanksServer/TanksServer.csproj b/TanksServer/TanksServer.csproj index 059aefa..b6d1a42 100644 --- a/TanksServer/TanksServer.csproj +++ b/TanksServer/TanksServer.csproj @@ -5,25 +5,41 @@ enable disable true - true Linux - - - .dockerignore - - - - - - - - Recommended true CA1805,CA1848 + + true + true + + false + true + true + true + true + + + + + + + + + + + + ..\Dockerfile + + + ../Dockerfile + + + + diff --git a/tank-frontend/package-lock.json b/tank-frontend/package-lock.json index aeedc40..9839298 100644 --- a/tank-frontend/package-lock.json +++ b/tank-frontend/package-lock.json @@ -13,6 +13,7 @@ "react-use-websocket": "^4.8.1" }, "devDependencies": { + "@types/node": "^20.12.7", "@types/react": "^18.2.66", "@types/react-dom": "^18.2.22", "@typescript-eslint/eslint-plugin": "^7.2.0", @@ -1240,6 +1241,15 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, + "node_modules/@types/node": { + "version": "20.12.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", + "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, "node_modules/@types/prop-types": { "version": "15.7.12", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", @@ -3143,6 +3153,12 @@ "node": ">=14.17" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, "node_modules/update-browserslist-db": { "version": "1.0.13", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", diff --git a/tank-frontend/package.json b/tank-frontend/package.json index cbd66b6..17be3e5 100644 --- a/tank-frontend/package.json +++ b/tank-frontend/package.json @@ -15,6 +15,7 @@ "react-use-websocket": "^4.8.1" }, "devDependencies": { + "@types/node": "^20.12.7", "@types/react": "^18.2.66", "@types/react-dom": "^18.2.22", "@typescript-eslint/eslint-plugin": "^7.2.0", diff --git a/tank-frontend/vite.config.ts b/tank-frontend/vite.config.ts index 6e81bac..208faab 100644 --- a/tank-frontend/vite.config.ts +++ b/tank-frontend/vite.config.ts @@ -1,12 +1,15 @@ -import {defineConfig} from 'vite'; +import {ConfigEnv, defineConfig} from 'vite'; import react from '@vitejs/plugin-react'; // https://vitejs.dev/config/ -export default defineConfig({ - plugins: [react()], +export default defineConfig(() => { + const isContainer = process.env.CONTAINERMODE; + return { + plugins: [react()], - build: { - outDir: '../TanksServer/client', - emptyOutDir: true - } + build: { + outDir: isContainer ? undefined : '../TanksServer/client', + emptyOutDir: true + } + }; });