Skip to content

Commit

Permalink
Merge pull request #825 from TheEadie/process-replays
Browse files Browse the repository at this point in the history
Process replays
  • Loading branch information
TheEadie authored Oct 11, 2024
2 parents cb73737 + ad72797 commit 770a914
Show file tree
Hide file tree
Showing 54 changed files with 675 additions and 124 deletions.
2 changes: 2 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,8 @@ dotnet_diagnostic.CA1812.severity = none
dotnet_diagnostic.CA1848.severity = none
# CA1308 tries to make user facing string upper case
dotnet_diagnostic.CA1308.severity = none
# CA1303 wants localization of text - I'm unlikely to do this
dotnet_diagnostic.CA1303.severity = none
# Workaround for https://github.com/dotnet/roslyn/issues/41640
dotnet_diagnostic.IDE0005.severity = suggestion

Expand Down
37 changes: 30 additions & 7 deletions .github/workflows/hub-gateway.yml → .github/workflows/hub.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
name: Hub.Gateway
name: Hub

on:
push:
paths:
- "src/Directory.Build.props"
- "src/Worms.Hub.Gateway/**"
- "src/Worms.Hub*/**"
- "src/database/**"
- "build/docker/makefile"
- "build/docker/gateway/**"
- "build/docker/**"
- "build/release-github.sh"
- "build/version.sh"
- ".github/workflows/hub-gateway.yml"
- ".github/workflows/hub.yml"

jobs:
build:
build-gateway:
name: Package - Gateway
runs-on: ubuntu-latest

Expand All @@ -36,6 +35,29 @@ jobs:
run: |
make gateway.package
build-replay-processor:
name: Package - Replay Processor
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Expose GitHub Runtime
uses: crazy-max/ghaction-github-runtime@v3

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Package
run: |
make replay-processor.package
build-database:
name: Build - Database
runs-on: ubuntu-latest
Expand Down Expand Up @@ -75,7 +97,7 @@ jobs:
release:
name: Release
runs-on: ubuntu-latest
needs: [build, build-database]
needs: [build-gateway, build-replay-processor, build-database]
if: github.ref == 'refs/heads/main'

steps:
Expand All @@ -102,3 +124,4 @@ jobs:
- name: Release
run: |
make gateway.release GITHUB_AUTH_TOKEN=${{ secrets.GITHUB_TOKEN }}
make replay-processor.release GITHUB_AUTH_TOKEN=${{ secrets.GITHUB_TOKEN }}
12 changes: 12 additions & 0 deletions Worms.sln
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worms.Cli", "src\Worms.Cli\
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worms.Armageddon.Files.Tests", "src\Worms.Armageddon.Files.Tests\Worms.Armageddon.Files.Tests.csproj", "{6233FC52-586A-40A0-B369-FA77ADE35E94}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worms.Hub.ReplayProcessor", "src\Worms.Hub.ReplayProcessor\Worms.Hub.ReplayProcessor.csproj", "{F41B5B20-FDE9-4835-8282-7DB750F06992}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worms.Hub.Storage", "src\Worms.Hub.Storage\Worms.Hub.Storage.csproj", "{EE088F3B-1FF5-4525-8829-4556CC59AE57}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -48,6 +52,14 @@ Global
{6233FC52-586A-40A0-B369-FA77ADE35E94}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6233FC52-586A-40A0-B369-FA77ADE35E94}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6233FC52-586A-40A0-B369-FA77ADE35E94}.Release|Any CPU.Build.0 = Release|Any CPU
{F41B5B20-FDE9-4835-8282-7DB750F06992}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F41B5B20-FDE9-4835-8282-7DB750F06992}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F41B5B20-FDE9-4835-8282-7DB750F06992}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F41B5B20-FDE9-4835-8282-7DB750F06992}.Release|Any CPU.Build.0 = Release|Any CPU
{EE088F3B-1FF5-4525-8829-4556CC59AE57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EE088F3B-1FF5-4525-8829-4556CC59AE57}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EE088F3B-1FF5-4525-8829-4556CC59AE57}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EE088F3B-1FF5-4525-8829-4556CC59AE57}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
EndGlobalSection
Expand Down
13 changes: 7 additions & 6 deletions build/docker/gateway/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
#### Build ####
FROM mcr.microsoft.com/dotnet/sdk:8.0.403@sha256:ff705b99a06144190e2638f8ede64a753915df5ea27fff55f58d0eb5f7054b0b AS build
WORKDIR /app
ARG PROJECT="Worms.Hub.Gateway.csproj"

COPY src/Directory.Build.props .
COPY .editorconfig .
COPY src/Worms.Hub.Gateway/${PROJECT} ./${PROJECT}
RUN dotnet restore ${PROJECT}
COPY src/Worms.Hub.Storage/Worms.Hub.Storage.csproj ./src/Worms.Hub.Storage/Worms.Hub.Storage.csproj
COPY src/Worms.Hub.Gateway/Worms.Hub.Gateway.csproj ./src/Worms.Hub.Gateway/Worms.Hub.Gateway.csproj
RUN dotnet restore src/Worms.Hub.Gateway/Worms.Hub.Gateway.csproj

COPY src/Worms.Hub.Gateway .
COPY src/Worms.Hub.Storage ./src/Worms.Hub.Storage
COPY src/Worms.Hub.Gateway ./src/Worms.Hub.Gateway
ARG VERSION=0.0.1
RUN dotnet publish \
${PROJECT} \
src/Worms.Hub.Gateway/Worms.Hub.Gateway.csproj \
-c Release \
-o out \
--no-restore \
-p:AssemblyVersion=${VERSION} \
-p:Version=${VERSION}

#### Test ####
FROM build as test
FROM build AS test
RUN dotnet test --no-restore --no-build --verbosity normal

#### Runtime ####
Expand Down
79 changes: 79 additions & 0 deletions build/docker/replay-processor/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#### Build ####
FROM mcr.microsoft.com/dotnet/sdk:8.0.303@sha256:7d0ba26469267b563120456557e38eccef9972cb6b9cfbbd47a50d1218fa7b30 AS build
WORKDIR /app

COPY src/Directory.Build.props .
COPY .editorconfig .
COPY src/Worms.Armageddon.Game/Worms.Armageddon.Game.csproj ./src/Worms.Armageddon.Game/Worms.Armageddon.Game.csproj
COPY src/Worms.Hub.Storage/Worms.Hub.Storage.csproj ./src/Worms.Hub.Storage/Worms.Hub.Storage.csproj
COPY src/Worms.Hub.ReplayProcessor/Worms.Hub.ReplayProcessor.csproj ./src/Worms.Hub.ReplayProcessor/Worms.Hub.ReplayProcessor.csproj
RUN dotnet restore src/Worms.Hub.ReplayProcessor/Worms.Hub.ReplayProcessor.csproj

COPY src/Worms.Armageddon.Game ./src/Worms.Armageddon.Game
COPY src/Worms.Hub.Storage ./src/Worms.Hub.Storage
COPY src/Worms.Hub.ReplayProcessor ./src/Worms.Hub.ReplayProcessor
ARG VERSION=0.0.1
RUN dotnet publish \
src/Worms.Hub.ReplayProcessor/Worms.Hub.ReplayProcessor.csproj \
-c Release \
-o out \
--no-restore \
-p:AssemblyVersion=${VERSION} \
-p:Version=${VERSION}

#### Test ####
FROM build AS test
RUN dotnet test --no-restore --no-build --verbosity normal

#### Runtime ####
FROM ubuntu:22.04@sha256:340d9b015b194dc6e2a13938944e0d016e57b9679963fdeb9ce021daac430221 as runtime

RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates \
wget \
gnupg \
dotnet-runtime-8.0 \
&& rm -rf /var/lib/apt/lists/*

# Get key to Wine repo
RUN wget -nc https://dl.winehq.org/wine-builds/winehq.key -O /tmp/winehq.key

# Add Wine repo
RUN apt-get update \
&& apt-get install -y software-properties-common \
&& apt-key add /tmp/winehq.key \
&& add-apt-repository 'deb https://dl.winehq.org/wine-builds/ubuntu/ jammy main' \
&& rm /tmp/winehq.key \
&& rm -rf /var/lib/apt/lists/*

# AMD 32-bit deps for Wine
RUN dpkg --add-architecture i386 \
&& apt-get update \
&& apt-get install -y --install-recommends winehq-stable wine32 xvfb \
&& rm -rf /var/lib/apt/lists/*

# Create WINEPREFIX
RUN WINEDLLOVERRIDES="mscoree,mshtml=" xvfb-run wineboot -i \
&& wineserver -k

# Copy game installation directory

# Some settings for WA
RUN wine reg add 'HKEY_CURRENT_USER\Software\Team17SoftwareLTD\WormsArmageddon\Options' /t REG_DWORD /v WineCompatibilitySuggested /d 0x7FFFFFFF /f \
&& wine reg add 'HKEY_CURRENT_USER\Software\Team17SoftwareLTD\WormsArmageddon\Options' /t REG_DWORD /v WindowedMode /d 0x00000001 /f \
&& wine reg add 'HKEY_CURRENT_USER\Software\Team17SoftwareLTD\WormsArmageddon\Options' /t REG_DWORD /v DetailLevel /d 0x00000005 /f \
&& wine reg add 'HKEY_CURRENT_USER\Software\Team17SoftwareLTD\WormsArmageddon\Options' /t REG_DWORD /v WindowedMode /d 0x00000001 /f \
&& wine reg add 'HKEY_CURRENT_USER\Software\Team17SoftwareLTD\WormsArmageddon\Options' /t REG_DWORD /v PinnedChatLines /d 0x00000007 /f \
&& wine reg add 'HKEY_CURRENT_USER\Software\Team17SoftwareLTD\WormsArmageddon\Options' /t REG_DWORD /v InfoTransparency /d 0x00000001 /f \
&& wine reg add 'HKEY_CURRENT_USER\Software\Team17SoftwareLTD\WormsArmageddon\Options' /t REG_DWORD /v InfoSpy /d 0x00000001 /f \
&& wine reg add 'HKEY_CURRENT_USER\Software\Team17SoftwareLTD\WormsArmageddon\Options' /t REG_DWORD /v DisableSmoothBackgroundGradient /d 0x00000000 /f \
&& wine reg add 'HKEY_CURRENT_USER\Software\Team17SoftwareLTD\WormsArmageddon\Options' /t REG_DWORD /v HardwareRendering /d 0x00000001 /f \
&& wine reg add 'HKEY_CURRENT_USER\Software\Team17SoftwareLTD\WormsArmageddon\Options' /t REG_DWORD /v LargerFonts /d 0x00000000 /f \
&& wine reg add 'HKEY_CURRENT_USER\Software\Team17SoftwareLTD\WormsArmageddon\Options' /t REG_DWORD /v AssistedVsync /d 0x00000000 /f \
&& wine reg add 'HKEY_CURRENT_USER\Software\Team17SoftwareLTD\WormsArmageddon\Options' /t REG_DWORD /v Vsync /d 0x00000000 /f \
&& wineserver -k

WORKDIR /app
COPY --from=build /app/out .
ENTRYPOINT ["./Worms.Hub.ReplayProcessor"]
10 changes: 10 additions & 0 deletions build/docker/replay-processor/Dockerfile.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Ignore everything
**

# Except for these files
!/src
!/scripts
!.editorconfig

**/bin
**/obj
3 changes: 3 additions & 0 deletions build/docker/replay-processor/config.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
replay-processor_IMAGE_NAME := theeadie/worms-hub-replay-processor
replay-processor_NEXT_VERSION := 0.1
replay-processor_TAG_PREFIX := replay-processor/v
32 changes: 31 additions & 1 deletion docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
version: "3.8"
services:
azure-storage:
image: mcr.microsoft.com/azure-storage/azurite
ports:
- "10000:10000"
- "10001:10001"
- "10002:10002"
healthcheck:
test: nc 127.0.0.1 10000 -z
interval: 1s
retries: 30

database:
image: "postgres:15"
environment:
Expand Down Expand Up @@ -43,10 +53,30 @@ services:
- ./sample-data:/data
environment:
- ASPNETCORE_ENVIRONMENT=Development
- WORMS_CONNECTIONSTRINGS__STORAGE=DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://host.docker.internal:10000/devstoreaccount1;QueueEndpoint=http://host.docker.internal:10001/devstoreaccount1;
- WORMS_CONNECTIONSTRINGS__DATABASE=Server=database;Port=5432;Database=worms;Username=worms;Password=worms
- WORMS_STORAGE__TEMPREPLAYFOLDER=/data/replays
- WORMS_STORAGE__CLIFOLDER=/data/cli
- WORMS_STORAGE__SCHEMESFOLDER=/data/schemes
depends_on:
flyway-init:
condition: service_completed_successfully
azure-storage:
condition: service_healthy

worms-replay-processor:
build:
dockerfile: build/docker/replay-processor/Dockerfile
context: .
volumes:
- ./sample-data:/data
- /home/eadie/games/worms:/root/.wine/drive_c/WA
environment:
- WORMS_CONNECTIONSTRINGS__STORAGE=DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://host.docker.internal:10000/devstoreaccount1;QueueEndpoint=http://host.docker.internal:10001/devstoreaccount1;
- WORMS_CONNECTIONSTRINGS__DATABASE=Server=database;Port=5432;Database=worms;Username=worms;Password=worms
- WORMS_STORAGE__TEMPREPLAYFOLDER=/data/replays
depends_on:
flyway-init:
condition: service_completed_successfully
azure-storage:
condition: service_healthy
2 changes: 1 addition & 1 deletion src/Worms.Armageddon.Game/Linux/WormsLocator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public GameInfo Find()
return GameInfo.NotInstalled;
}

var rootLocation = Path.Combine(userHomeDirectory, "games", "worms");
var rootLocation = Path.Combine(userHomeDirectory, ".wine", "drive_c", "WA");
var exeLocation = Path.Combine(rootLocation, processName + ".exe");
var schemesFolder = Path.Combine(rootLocation, "User", "Schemes");
var gamesFolder = Path.Combine(rootLocation, "User", "Games");
Expand Down
49 changes: 43 additions & 6 deletions src/Worms.Armageddon.Game/Linux/WormsRunner.cs
Original file line number Diff line number Diff line change
@@ -1,33 +1,70 @@
using System.Diagnostics;
using Microsoft.Extensions.Logging;

namespace Worms.Armageddon.Game.Linux;

internal sealed class WormsRunner(IWormsLocator wormsLocator) : IWormsRunner
internal sealed class WormsRunner(IWormsLocator wormsLocator, ILogger<WormsRunner> logger) : IWormsRunner
{
public Task RunWorms(params string[] wormsArgs)
{
// Replace " with ' in the args
// Wine doesn't like using "s around arguments
// Windows doesn't like using 's around arguments
for (var i = 0; i < wormsArgs.Length; i++)
{
wormsArgs[i] = wormsArgs[i].Replace("\"", "'", StringComparison.InvariantCulture);
}

return Task.Run(
async () =>
{
var gameInfo = wormsLocator.Find();
var args = string.Join(" ", wormsArgs);
logger.Log(LogLevel.Debug, "Running Worms Armageddon: {Path}", gameInfo.ExeLocation);
logger.Log(LogLevel.Debug, "Args: {Arguments}", args);
var processStartInfo = new ProcessStartInfo
{
FileName = "wine",
Arguments = gameInfo.ExeLocation + " " + args,
FileName = "/bin/bash",
Arguments = $"""
-c "xvfb-run wine "{gameInfo.ExeLocation}" {args}"
""",
RedirectStandardOutput = true,
RedirectStandardError = true
RedirectStandardError = true,
WorkingDirectory = $"{gameInfo.ReplayFolder}",
};
using var process = Process.Start(processStartInfo);
if (process is not null)
{
await process.WaitForExitAsync().ConfigureAwait(false);
var processTask = Task.Run(() => process.WaitForExitAsync());
var output = Task.Run(() => PrintStdOut(process));
var errors = Task.Run(() => PrintStdErr(process));
await Task.WhenAll(processTask, errors, output).ConfigureAwait(false);
await Console.Error.WriteLineAsync("Exit code:" + process.ExitCode).ConfigureAwait(false);
}
return Task.CompletedTask;
});
}

private async Task PrintStdOut(Process process)
{
while (!process.StandardOutput.EndOfStream)
{
var line = await process.StandardOutput.ReadLineAsync().ConfigureAwait(false);
logger.Log(LogLevel.Debug, "StdOut: {Message}", line);
}
}

private async Task PrintStdErr(Process process)
{
while (!process.StandardError.EndOfStream)
{
var line = await process.StandardError.ReadLineAsync().ConfigureAwait(false);
logger.Log(LogLevel.Debug, "StdErr: {Message}", line);
}
}
}
1 change: 1 addition & 0 deletions src/Worms.Armageddon.Game/Worms.Armageddon.Game.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2"/>
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0"/>
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0"/>
</ItemGroup>

Expand Down
4 changes: 2 additions & 2 deletions src/Worms.Hub.Gateway/API/Controllers/CliFilesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
using Microsoft.AspNetCore.Mvc;
using Worms.Hub.Gateway.API.DTOs;
using Worms.Hub.Gateway.API.Validators;
using Worms.Hub.Gateway.Domain;
using Worms.Hub.Gateway.Storage.Files;
using Worms.Hub.Storage.Domain;
using Worms.Hub.Storage.Files;

namespace Worms.Hub.Gateway.API.Controllers;

Expand Down
Loading

0 comments on commit 770a914

Please sign in to comment.