From 88673c1c216de3513ed6df40472a6993e1374a6c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 08:59:02 +0000 Subject: [PATCH 01/10] Bump softprops/action-gh-release from 2 to 3 in the actions-deps group Bumps the actions-deps group with 1 update: [softprops/action-gh-release](https://github.com/softprops/action-gh-release). Updates `softprops/action-gh-release` from 2 to 3 - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/v2...v3) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-version: '3' dependency-type: direct:production update-type: version-update:semver-major dependency-group: actions-deps ... Signed-off-by: dependabot[bot] --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6b65c335..67002d44 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -54,7 +54,7 @@ jobs: - uses: dotnet/nbgv@v0.5.1 id: nbgv - name: Create GitHub release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@v3 with: name: v${{ steps.nbgv.outputs.SemVer2 }} tag_name: v${{ steps.nbgv.outputs.SemVer2 }} From a2118357bd06d096200564537ed068a8e31643c4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 May 2026 15:11:48 +0000 Subject: [PATCH 02/10] Bump the all-deps group with 11 updates Bumps AlamoEngineTools.Modinfo from 8.0.2 to 8.0.6 Bumps coverlet.collector from 8.0.1 to 10.0.1 Bumps GitHubActionsTestLogger from 3.0.1 to 3.0.4 Bumps Microsoft.Extensions.DependencyInjection from 10.0.5 to 10.0.8 Bumps Microsoft.Extensions.DependencyInjection.Abstractions from 10.0.5 to 10.0.8 Bumps Microsoft.Extensions.Logging.Abstractions from 10.0.5 to 10.0.8 Bumps Microsoft.NET.Test.Sdk from 18.3.0 to 18.5.1 Bumps Microsoft.SourceLink.GitHub from 10.0.201 to 10.0.300 Bumps Microsoft.Testing.Platform from 2.1.0 to 2.2.3 Bumps System.Text.Json from 10.0.5 to 10.0.8 Bumps Testably.Abstractions.Testing from 6.0.0 to 6.4.0 --- updated-dependencies: - dependency-name: AlamoEngineTools.Modinfo dependency-version: 8.0.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-deps - dependency-name: coverlet.collector dependency-version: 10.0.1 dependency-type: direct:production update-type: version-update:semver-major dependency-group: all-deps - dependency-name: coverlet.collector dependency-version: 10.0.1 dependency-type: direct:production update-type: version-update:semver-major dependency-group: all-deps - dependency-name: coverlet.collector dependency-version: 10.0.1 dependency-type: direct:production update-type: version-update:semver-major dependency-group: all-deps - dependency-name: GitHubActionsTestLogger dependency-version: 3.0.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-deps - dependency-name: GitHubActionsTestLogger dependency-version: 3.0.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-deps - dependency-name: GitHubActionsTestLogger dependency-version: 3.0.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-deps - dependency-name: Microsoft.Extensions.DependencyInjection dependency-version: 10.0.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-deps - dependency-name: Microsoft.Extensions.DependencyInjection dependency-version: 10.0.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-deps - dependency-name: Microsoft.Extensions.DependencyInjection dependency-version: 10.0.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-deps - dependency-name: Microsoft.Extensions.DependencyInjection dependency-version: 10.0.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-deps - dependency-name: Microsoft.Extensions.DependencyInjection dependency-version: 10.0.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-deps - dependency-name: Microsoft.Extensions.DependencyInjection.Abstractions dependency-version: 10.0.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-deps - dependency-name: Microsoft.Extensions.DependencyInjection.Abstractions dependency-version: 10.0.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-deps - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-version: 10.0.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-deps - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-version: 10.0.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-deps - dependency-name: Microsoft.NET.Test.Sdk dependency-version: 18.5.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all-deps - dependency-name: Microsoft.NET.Test.Sdk dependency-version: 18.5.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all-deps - dependency-name: Microsoft.NET.Test.Sdk dependency-version: 18.5.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all-deps - dependency-name: Microsoft.SourceLink.GitHub dependency-version: 10.0.300 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-deps - dependency-name: Microsoft.Testing.Platform dependency-version: 2.2.3 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all-deps - dependency-name: Microsoft.Testing.Platform dependency-version: 2.2.3 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all-deps - dependency-name: Microsoft.Testing.Platform dependency-version: 2.2.3 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all-deps - dependency-name: System.Text.Json dependency-version: 10.0.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-deps - dependency-name: System.Text.Json dependency-version: 10.0.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all-deps - dependency-name: Testably.Abstractions.Testing dependency-version: 6.4.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all-deps - dependency-name: Testably.Abstractions.Testing dependency-version: 6.4.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all-deps - dependency-name: Testably.Abstractions.Testing dependency-version: 6.4.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all-deps - dependency-name: Testably.Abstractions.Testing dependency-version: 6.4.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all-deps - dependency-name: Testably.Abstractions.Testing dependency-version: 6.4.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all-deps ... Signed-off-by: dependabot[bot] --- Directory.Build.props | 2 +- sampleApp/SampleApplication.csproj | 2 +- src/AET.SteamAbstraction/AET.SteamAbstraction.csproj | 6 +++--- .../PG.StarWarsGame.Infrastructure.csproj | 8 ++++---- .../AET.SteamAbstraction.Test.csproj | 12 ++++++------ .../AET.SteamAbstraction.Testing.csproj | 4 ++-- ...WarsGame.Infrastructure.Clients.Steam.Test.csproj | 10 +++++----- .../PG.StarWarsGame.Infrastructure.Test.csproj | 12 ++++++------ .../PG.StarWarsGame.Infrastructure.Testing.csproj | 4 ++-- 9 files changed, 30 insertions(+), 30 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 062eee37..660d2508 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -32,7 +32,7 @@ 3.9.50 - + all diff --git a/sampleApp/SampleApplication.csproj b/sampleApp/SampleApplication.csproj index fbe8bdcf..c39d28a1 100644 --- a/sampleApp/SampleApplication.csproj +++ b/sampleApp/SampleApplication.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/AET.SteamAbstraction/AET.SteamAbstraction.csproj b/src/AET.SteamAbstraction/AET.SteamAbstraction.csproj index ecbb47df..941bd5aa 100644 --- a/src/AET.SteamAbstraction/AET.SteamAbstraction.csproj +++ b/src/AET.SteamAbstraction/AET.SteamAbstraction.csproj @@ -24,9 +24,9 @@ - - - + + + all diff --git a/src/PG.StarWarsGame.Infrastructure/PG.StarWarsGame.Infrastructure.csproj b/src/PG.StarWarsGame.Infrastructure/PG.StarWarsGame.Infrastructure.csproj index b2fb229b..4ee517a8 100644 --- a/src/PG.StarWarsGame.Infrastructure/PG.StarWarsGame.Infrastructure.csproj +++ b/src/PG.StarWarsGame.Infrastructure/PG.StarWarsGame.Infrastructure.csproj @@ -22,16 +22,16 @@ true - + - - + + - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/AET.SteamAbstraction.Test/AET.SteamAbstraction.Test.csproj b/test/AET.SteamAbstraction.Test/AET.SteamAbstraction.Test.csproj index 9769bbbf..02a912a1 100644 --- a/test/AET.SteamAbstraction.Test/AET.SteamAbstraction.Test.csproj +++ b/test/AET.SteamAbstraction.Test/AET.SteamAbstraction.Test.csproj @@ -14,23 +14,23 @@ - - + + - + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all - - + + diff --git a/test/AET.SteamAbstraction.Testing/AET.SteamAbstraction.Testing.csproj b/test/AET.SteamAbstraction.Testing/AET.SteamAbstraction.Testing.csproj index c4d2727f..1bef986a 100644 --- a/test/AET.SteamAbstraction.Testing/AET.SteamAbstraction.Testing.csproj +++ b/test/AET.SteamAbstraction.Testing/AET.SteamAbstraction.Testing.csproj @@ -34,8 +34,8 @@ - - + + diff --git a/test/PG.StarWarsGame.Infrastructure.Clients.Steam.Test/PG.StarWarsGame.Infrastructure.Clients.Steam.Test.csproj b/test/PG.StarWarsGame.Infrastructure.Clients.Steam.Test/PG.StarWarsGame.Infrastructure.Clients.Steam.Test.csproj index 21800c0d..a1e1d91c 100644 --- a/test/PG.StarWarsGame.Infrastructure.Clients.Steam.Test/PG.StarWarsGame.Infrastructure.Clients.Steam.Test.csproj +++ b/test/PG.StarWarsGame.Infrastructure.Clients.Steam.Test/PG.StarWarsGame.Infrastructure.Clients.Steam.Test.csproj @@ -13,16 +13,16 @@ - - - + + + - + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/test/PG.StarWarsGame.Infrastructure.Test/PG.StarWarsGame.Infrastructure.Test.csproj b/test/PG.StarWarsGame.Infrastructure.Test/PG.StarWarsGame.Infrastructure.Test.csproj index 1899b1d7..403203eb 100644 --- a/test/PG.StarWarsGame.Infrastructure.Test/PG.StarWarsGame.Infrastructure.Test.csproj +++ b/test/PG.StarWarsGame.Infrastructure.Test/PG.StarWarsGame.Infrastructure.Test.csproj @@ -13,24 +13,24 @@ - - + + - + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all - - + + diff --git a/test/PG.StarWarsGame.Infrastructure.Testing/PG.StarWarsGame.Infrastructure.Testing.csproj b/test/PG.StarWarsGame.Infrastructure.Testing/PG.StarWarsGame.Infrastructure.Testing.csproj index 8612b7ef..5036f8d4 100644 --- a/test/PG.StarWarsGame.Infrastructure.Testing/PG.StarWarsGame.Infrastructure.Testing.csproj +++ b/test/PG.StarWarsGame.Infrastructure.Testing/PG.StarWarsGame.Infrastructure.Testing.csproj @@ -34,8 +34,8 @@ - - + + From 4032f6aa225780055215505bed9a3e1b066fc846 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 May 2026 08:54:15 +0000 Subject: [PATCH 03/10] Bump dotnet/nbgv from 0.5.1 to 0.5.2 in the actions-deps group Bumps the actions-deps group with 1 update: [dotnet/nbgv](https://github.com/dotnet/nbgv). Updates `dotnet/nbgv` from 0.5.1 to 0.5.2 - [Release notes](https://github.com/dotnet/nbgv/releases) - [Commits](https://github.com/dotnet/nbgv/compare/v0.5.1...v0.5.2) --- updated-dependencies: - dependency-name: dotnet/nbgv dependency-version: 0.5.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions-deps ... Signed-off-by: dependabot[bot] --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 67002d44..62c8330e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -51,7 +51,7 @@ jobs: path: packages - name: Push packages run: dotnet nuget push "packages/*.nupkg" --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json - - uses: dotnet/nbgv@v0.5.1 + - uses: dotnet/nbgv@v0.5.2 id: nbgv - name: Create GitHub release uses: softprops/action-gh-release@v3 From 32c8499aa569ff586beb0520a92072183dfe1d48 Mon Sep 17 00:00:00 2001 From: AnakinRaW Date: Sat, 23 May 2026 15:17:57 +0200 Subject: [PATCH 04/10] Update AnakinRaW.CommonUtilities dependencies to version 13.0.23 across projects. --- src/AET.SteamAbstraction/AET.SteamAbstraction.csproj | 6 +++--- .../PG.StarWarsGame.Infrastructure.csproj | 6 +++--- .../AET.SteamAbstraction.Testing.csproj | 2 +- .../PG.StarWarsGame.Infrastructure.Testing.csproj | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/AET.SteamAbstraction/AET.SteamAbstraction.csproj b/src/AET.SteamAbstraction/AET.SteamAbstraction.csproj index 941bd5aa..9f96be8a 100644 --- a/src/AET.SteamAbstraction/AET.SteamAbstraction.csproj +++ b/src/AET.SteamAbstraction/AET.SteamAbstraction.csproj @@ -21,9 +21,9 @@ true - - - + + + diff --git a/src/PG.StarWarsGame.Infrastructure/PG.StarWarsGame.Infrastructure.csproj b/src/PG.StarWarsGame.Infrastructure/PG.StarWarsGame.Infrastructure.csproj index 4ee517a8..7cbd5338 100644 --- a/src/PG.StarWarsGame.Infrastructure/PG.StarWarsGame.Infrastructure.csproj +++ b/src/PG.StarWarsGame.Infrastructure/PG.StarWarsGame.Infrastructure.csproj @@ -23,9 +23,9 @@ - - - + + + diff --git a/test/AET.SteamAbstraction.Testing/AET.SteamAbstraction.Testing.csproj b/test/AET.SteamAbstraction.Testing/AET.SteamAbstraction.Testing.csproj index 1bef986a..17d2c6b0 100644 --- a/test/AET.SteamAbstraction.Testing/AET.SteamAbstraction.Testing.csproj +++ b/test/AET.SteamAbstraction.Testing/AET.SteamAbstraction.Testing.csproj @@ -26,7 +26,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/PG.StarWarsGame.Infrastructure.Testing/PG.StarWarsGame.Infrastructure.Testing.csproj b/test/PG.StarWarsGame.Infrastructure.Testing/PG.StarWarsGame.Infrastructure.Testing.csproj index 5036f8d4..f073dc8f 100644 --- a/test/PG.StarWarsGame.Infrastructure.Testing/PG.StarWarsGame.Infrastructure.Testing.csproj +++ b/test/PG.StarWarsGame.Infrastructure.Testing/PG.StarWarsGame.Infrastructure.Testing.csproj @@ -26,7 +26,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive From 3c74c1c89a540e45fb2f251d550032c4f93fe6bf Mon Sep 17 00:00:00 2001 From: AnakinRaW Date: Sat, 23 May 2026 16:02:26 +0200 Subject: [PATCH 05/10] try load balacing online test downloads with retry logic --- .../Steam/SteamWorkshopWebpageDownloader.cs | 50 +++++++++++++++++-- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/src/PG.StarWarsGame.Infrastructure/Services/Steam/SteamWorkshopWebpageDownloader.cs b/src/PG.StarWarsGame.Infrastructure/Services/Steam/SteamWorkshopWebpageDownloader.cs index 2686742a..a04ffb7b 100644 --- a/src/PG.StarWarsGame.Infrastructure/Services/Steam/SteamWorkshopWebpageDownloader.cs +++ b/src/PG.StarWarsGame.Infrastructure/Services/Steam/SteamWorkshopWebpageDownloader.cs @@ -1,4 +1,5 @@ -using System.Globalization; +using System; +using System.Globalization; using System.Net.Http; using System.Threading.Tasks; using System.Web; @@ -9,6 +10,9 @@ namespace PG.StarWarsGame.Infrastructure.Services.Steam; internal class SteamWorkshopWebpageDownloader : ISteamWorkshopWebpageDownloader { private const string SteamWorkshopsBaseUrl = "https://steamcommunity.com/sharedfiles/filedetails/?"; + private const int MaxRetries = 4; + private static readonly TimeSpan InitialBackoff = TimeSpan.FromSeconds(1); + private static readonly TimeSpan MaxBackoff = TimeSpan.FromSeconds(30); public async Task GetSteamWorkshopsPageHtmlAsync(ulong workshopId, CultureInfo? culture) { @@ -20,9 +24,45 @@ public async Task GetSteamWorkshopsPageHtmlAsync(ulong workshopId, var address = $"{SteamWorkshopsBaseUrl}{queryString}"; using var client = new HttpClient(); - var reply = await client.GetStringAsync(address); - var htmlDocument = new HtmlDocument(); - htmlDocument.LoadHtml(reply); - return htmlDocument; + + var backoff = InitialBackoff; + for (var attempt = 0; ; attempt++) + { + using var response = await client.GetAsync(address).ConfigureAwait(false); + + if ((int)response.StatusCode != 429) + { + response.EnsureSuccessStatusCode(); + var reply = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + var htmlDocument = new HtmlDocument(); + htmlDocument.LoadHtml(reply); + return htmlDocument; + } + + if (attempt >= MaxRetries) + response.EnsureSuccessStatusCode(); + + var wait = GetRetryAfter(response) ?? backoff; + if (wait > MaxBackoff) + wait = MaxBackoff; + await Task.Delay(wait).ConfigureAwait(false); + + backoff = TimeSpan.FromTicks(Math.Min(backoff.Ticks * 2, MaxBackoff.Ticks)); + } + } + + private static TimeSpan? GetRetryAfter(HttpResponseMessage response) + { + var header = response.Headers.RetryAfter; + if (header is null) + return null; + if (header.Delta is { } delta && delta > TimeSpan.Zero) + return delta; + if (header.Date is { } when) + { + var delay = when - DateTimeOffset.UtcNow; + return delay > TimeSpan.Zero ? delay : null; + } + return null; } } \ No newline at end of file From e4b3d0d99ad5004aa7b1bfcebf795f61e09c2d18 Mon Sep 17 00:00:00 2001 From: AnakinRaW Date: Sat, 23 May 2026 16:23:00 +0200 Subject: [PATCH 06/10] Refactor `GameProcess` to use `Volatile` and `Interlocked` for thread-safe process termination handling. --- .../Clients/Processes/GameProcess.cs | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/PG.StarWarsGame.Infrastructure/Clients/Processes/GameProcess.cs b/src/PG.StarWarsGame.Infrastructure/Clients/Processes/GameProcess.cs index 00b610bb..f3b58421 100644 --- a/src/PG.StarWarsGame.Infrastructure/Clients/Processes/GameProcess.cs +++ b/src/PG.StarWarsGame.Infrastructure/Clients/Processes/GameProcess.cs @@ -9,7 +9,7 @@ namespace PG.StarWarsGame.Infrastructure.Clients.Processes; internal sealed class GameProcess : DisposableObject, IGameProcess { - private volatile bool _closed; + private int _closedFlag; private EventHandler? _closingHandler; @@ -18,7 +18,7 @@ public event EventHandler? Closed add { // Execute event right away if the process was already closed. - if (_closed) + if (Volatile.Read(ref _closedFlag) != 0) value?.Invoke(this, EventArgs.Empty); else _closingHandler += value; @@ -30,8 +30,8 @@ public event EventHandler? Closed // To avoid complexity this property does not query the underlying process but just "trusts" // on the OnClosed function to set the value when the process was terminated. - // This means this property has theoretically a race condition with the game's process. - public GameProcessState State => _closed ? GameProcessState.Closed : GameProcessState.Running; + // This means this property has theoretically a race condition with the game's process. + public GameProcessState State => Volatile.Read(ref _closedFlag) != 0 ? GameProcessState.Closed : GameProcessState.Running; internal Process Process { get; } @@ -51,10 +51,16 @@ public void Exit() try { Process.Kill(); + Process.WaitForExit(); } catch (Exception e) when (e is InvalidOperationException or Win32Exception) { } + + // Process.Exited is dispatched asynchronously on a ThreadPool work item, so + // WaitForExit can return before OnClosed has been invoked. Drive it synchronously + // here; OnClosed is idempotent via the Interlocked guard. + OnClosed(this, EventArgs.Empty); } public Task WaitForExitAsync(CancellationToken cancellationToken = default) @@ -74,15 +80,13 @@ private void RegisterExitEvent(Process process) Process.EnableRaisingEvents = true; Process.Exited += OnClosed; if (process.HasExited) - { - _closed = true; - Process.Exited -= OnClosed; - } + OnClosed(this, EventArgs.Empty); } private void OnClosed(object? sender, EventArgs e) { - _closed = true; + if (Interlocked.Exchange(ref _closedFlag, 1) != 0) + return; Process.Exited -= OnClosed; _closingHandler?.Invoke(this, EventArgs.Empty); } From 6c0bfad5551ca2a089110b4bd7cc4452442ab70b Mon Sep 17 00:00:00 2001 From: AnakinRaW Date: Sat, 23 May 2026 16:26:05 +0200 Subject: [PATCH 07/10] Add environment-based control for Steam live tests and update workflows/tests accordingly --- .github/workflows/release.yml | 2 ++ .github/workflows/test.yml | 19 +++++++++++++++---- .../SteamWorkshopWebpageDownloaderTest.cs | 5 ++++- .../DirectoryModNameResolverTest.cs | 5 ++++- .../OnlineModGameTypeResolverTest.cs | 5 ++++- .../TestEnvironment.cs | 12 ++++++++++++ 6 files changed, 41 insertions(+), 7 deletions(-) create mode 100644 test/PG.StarWarsGame.Infrastructure.Test/TestEnvironment.cs diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 62c8330e..03524e02 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,6 +10,8 @@ jobs: test: uses: ./.github/workflows/test.yml + with: + steam-live-tests: true pack: name: Pack diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 362dc9aa..5d1e08e7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,7 +2,17 @@ name: Build & Test on: workflow_call: + inputs: + steam-live-tests: + description: 'Run live Steam-network tests (sets STEAM_LIVE_TESTS=1).' + type: boolean + default: false workflow_dispatch: + inputs: + steam-live-tests: + description: 'Run live Steam-network tests (sets STEAM_LIVE_TESTS=1).' + type: boolean + default: false push: branches: [ develop ] pull_request: @@ -16,7 +26,7 @@ jobs: matrix: os: [windows-latest, ubuntu-latest] runs-on: ${{ matrix.os }} - + steps: - uses: actions/checkout@v6 with: @@ -24,10 +34,11 @@ jobs: - uses: actions/setup-dotnet@v5 with: dotnet-version: '10.0.x' - + - name: Build & Test in Release Mode run: dotnet test --configuration Release --report-github - # Ignore exit code 8 on Linux (zero tests are now allowed) + # Ignore exit code 8 on Linux (zero tests are now allowed) # TODO: Remove this when linux is supported env: - TESTINGPLATFORM_EXITCODE_IGNORE: ${{ matrix.os == 'ubuntu-latest' && '8' || '' }} \ No newline at end of file + TESTINGPLATFORM_EXITCODE_IGNORE: ${{ matrix.os == 'ubuntu-latest' && '8' || '' }} + STEAM_LIVE_TESTS: ${{ inputs.steam-live-tests && '1' || '' }} diff --git a/test/PG.StarWarsGame.Infrastructure.Test/GameServices/SteamWorkshopWebpageDownloaderTest.cs b/test/PG.StarWarsGame.Infrastructure.Test/GameServices/SteamWorkshopWebpageDownloaderTest.cs index 1b448854..2013d851 100644 --- a/test/PG.StarWarsGame.Infrastructure.Test/GameServices/SteamWorkshopWebpageDownloaderTest.cs +++ b/test/PG.StarWarsGame.Infrastructure.Test/GameServices/SteamWorkshopWebpageDownloaderTest.cs @@ -7,7 +7,10 @@ namespace PG.StarWarsGame.Infrastructure.Test.GameServices; public class SteamWorkshopWebpageDownloaderTest { - [Fact] + [Fact( + Skip = TestEnvironment.SteamLiveTestsSkipReason, + SkipUnless = nameof(TestEnvironment.SteamLiveTestsEnabled), + SkipType = typeof(TestEnvironment))] public async Task GetSteamWorkshopsPageHtmlAsync() { var downloader = new SteamWorkshopWebpageDownloader(); diff --git a/test/PG.StarWarsGame.Infrastructure.Test/ModServices/DirectoryModNameResolverTest.cs b/test/PG.StarWarsGame.Infrastructure.Test/ModServices/DirectoryModNameResolverTest.cs index 01eedd59..4ba838cd 100644 --- a/test/PG.StarWarsGame.Infrastructure.Test/ModServices/DirectoryModNameResolverTest.cs +++ b/test/PG.StarWarsGame.Infrastructure.Test/ModServices/DirectoryModNameResolverTest.cs @@ -36,7 +36,10 @@ public void Ctor_NullArgs_Throws() Assert.Throws(() => new OnlineModNameResolver(null!)); } - [Theory] + [Theory( + Skip = TestEnvironment.SteamLiveTestsSkipReason, + SkipUnless = nameof(TestEnvironment.SteamLiveTestsEnabled), + SkipType = typeof(TestEnvironment))] [InlineData("path/1125718579", "z3r0x's mod version 3.5")] [InlineData("path/2978074984", "EAWFOC Mod Template")] public void ResolveName_Steam_WithoutModinfo_FindNameOnline(string path, string containsExpected) diff --git a/test/PG.StarWarsGame.Infrastructure.Test/ModServices/OnlineModGameTypeResolverTest.cs b/test/PG.StarWarsGame.Infrastructure.Test/ModServices/OnlineModGameTypeResolverTest.cs index 27e06965..8c37b2c5 100644 --- a/test/PG.StarWarsGame.Infrastructure.Test/ModServices/OnlineModGameTypeResolverTest.cs +++ b/test/PG.StarWarsGame.Infrastructure.Test/ModServices/OnlineModGameTypeResolverTest.cs @@ -23,7 +23,10 @@ public static IEnumerable GetOnlineModsData() yield return ["2508288191", new[] {GameType.Foc, GameType.Eaw}, null!]; //Mod Template } - [Theory] + [Theory( + Skip = TestEnvironment.SteamLiveTestsSkipReason, + SkipUnless = nameof(TestEnvironment.SteamLiveTestsEnabled), + SkipType = typeof(TestEnvironment))] [MemberData(nameof(GetOnlineModsData))] public void Online_GetTagsFromSteamOnline(string knownId, ICollection expectedTypes, GameType? incompatibleWith) { diff --git a/test/PG.StarWarsGame.Infrastructure.Test/TestEnvironment.cs b/test/PG.StarWarsGame.Infrastructure.Test/TestEnvironment.cs new file mode 100644 index 00000000..6bd64caf --- /dev/null +++ b/test/PG.StarWarsGame.Infrastructure.Test/TestEnvironment.cs @@ -0,0 +1,12 @@ +using System; + +namespace PG.StarWarsGame.Infrastructure.Test; + +public static class TestEnvironment +{ + public const string SteamLiveTestsSkipReason = + "Live Steam-network test. Set STEAM_LIVE_TESTS=1 to enable."; + + public static bool SteamLiveTestsEnabled => + !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("STEAM_LIVE_TESTS")); +} From 26cab82db27e5bac19148ae7746a8335bb28f52b Mon Sep 17 00:00:00 2001 From: AnakinRaW Date: Sun, 24 May 2026 17:15:17 +0200 Subject: [PATCH 08/10] Embed Steam Workshop fixtures for tests and replace skipped Steam live tests with local resources --- .../DirectoryModNameResolverTest.cs | 13 +- .../FakeSteamWorkshopWebpageDownloader.cs | 24 + .../Fixtures/workshop_1125718579.html | 1697 +++++++++++++++++ .../Fixtures/workshop_2508288191.html | 1546 +++++++++++++++ .../Fixtures/workshop_2978074984.html | 1539 +++++++++++++++ .../OnlineModGameTypeResolverTest.cs | 13 +- ...PG.StarWarsGame.Infrastructure.Test.csproj | 4 + 7 files changed, 4827 insertions(+), 9 deletions(-) create mode 100644 test/PG.StarWarsGame.Infrastructure.Test/ModServices/FakeSteamWorkshopWebpageDownloader.cs create mode 100644 test/PG.StarWarsGame.Infrastructure.Test/ModServices/Fixtures/workshop_1125718579.html create mode 100644 test/PG.StarWarsGame.Infrastructure.Test/ModServices/Fixtures/workshop_2508288191.html create mode 100644 test/PG.StarWarsGame.Infrastructure.Test/ModServices/Fixtures/workshop_2978074984.html diff --git a/test/PG.StarWarsGame.Infrastructure.Test/ModServices/DirectoryModNameResolverTest.cs b/test/PG.StarWarsGame.Infrastructure.Test/ModServices/DirectoryModNameResolverTest.cs index 4ba838cd..895203a7 100644 --- a/test/PG.StarWarsGame.Infrastructure.Test/ModServices/DirectoryModNameResolverTest.cs +++ b/test/PG.StarWarsGame.Infrastructure.Test/ModServices/DirectoryModNameResolverTest.cs @@ -3,7 +3,9 @@ using AET.Modinfo.Model; using AET.Modinfo.Spec; using AET.Modinfo.Utilities; +using Microsoft.Extensions.DependencyInjection; using PG.StarWarsGame.Infrastructure.Services.Name; +using PG.StarWarsGame.Infrastructure.Services.Steam; using PG.StarWarsGame.Infrastructure.Testing.TestBases; using Xunit; @@ -25,6 +27,12 @@ public void Ctor_NullArgs_Throws() public class OnlineModNameResolverTest : ModNameResolverTestBase { + protected override void SetupServices(IServiceCollection serviceCollection) + { + base.SetupServices(serviceCollection); + serviceCollection.AddSingleton(new FakeSteamWorkshopWebpageDownloader()); + } + public override ModNameResolverBase CreateResolver() { return new OnlineModNameResolver(ServiceProvider); @@ -36,10 +44,7 @@ public void Ctor_NullArgs_Throws() Assert.Throws(() => new OnlineModNameResolver(null!)); } - [Theory( - Skip = TestEnvironment.SteamLiveTestsSkipReason, - SkipUnless = nameof(TestEnvironment.SteamLiveTestsEnabled), - SkipType = typeof(TestEnvironment))] + [Theory] [InlineData("path/1125718579", "z3r0x's mod version 3.5")] [InlineData("path/2978074984", "EAWFOC Mod Template")] public void ResolveName_Steam_WithoutModinfo_FindNameOnline(string path, string containsExpected) diff --git a/test/PG.StarWarsGame.Infrastructure.Test/ModServices/FakeSteamWorkshopWebpageDownloader.cs b/test/PG.StarWarsGame.Infrastructure.Test/ModServices/FakeSteamWorkshopWebpageDownloader.cs new file mode 100644 index 00000000..06b7ee81 --- /dev/null +++ b/test/PG.StarWarsGame.Infrastructure.Test/ModServices/FakeSteamWorkshopWebpageDownloader.cs @@ -0,0 +1,24 @@ +using System; +using System.Globalization; +using System.Threading.Tasks; +using HtmlAgilityPack; +using PG.StarWarsGame.Infrastructure.Services.Steam; + +namespace PG.StarWarsGame.Infrastructure.Test.ModServices; + +internal sealed class FakeSteamWorkshopWebpageDownloader : ISteamWorkshopWebpageDownloader +{ + private const string FixtureNamespace = "PG.StarWarsGame.Infrastructure.Test.ModServices.Fixtures"; + + public Task GetSteamWorkshopsPageHtmlAsync(ulong workshopId, CultureInfo? culture) + { + var doc = new HtmlDocument(); + var resourceName = $"{FixtureNamespace}.workshop_{workshopId}.html"; + var assembly = typeof(FakeSteamWorkshopWebpageDownloader).Assembly; + using var stream = assembly.GetManifestResourceStream(resourceName); + if (stream is null) + return Task.FromResult(doc); + doc.Load(stream); + return Task.FromResult(doc); + } +} diff --git a/test/PG.StarWarsGame.Infrastructure.Test/ModServices/Fixtures/workshop_1125718579.html b/test/PG.StarWarsGame.Infrastructure.Test/ModServices/Fixtures/workshop_1125718579.html new file mode 100644 index 00000000..d762edb4 --- /dev/null +++ b/test/PG.StarWarsGame.Infrastructure.Test/ModServices/Fixtures/workshop_1125718579.html @@ -0,0 +1,1697 @@ + + + + + Steam Workshop::(Original) z3r0x's mod version 3.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
+
+
+ + + +
+
+ + +
+
+ +
+ +
+ +
+ + + + + + + +
+ +
+ + + + +
+ + +
+ + + + + + +
+
+
+
+
+ + + Store Page + +
+
+
+
STAR WARS™ Empire at War: Gold Pack
+
+
+ + +
+ + All + + Discussions + + Screenshots + + Broadcasts + + Videos + + Workshop + + News + + Guides + + Reviews +
+
+ +
+
+
+ +
+
+
+
+
+
+ + + +
+
+

STAR WARS™ Empire at War: Gold Pack

+ +
+
+ + + +
+ +
+
+
+ + +
+ + + + + + + + + + + +
+
+ +
+
+
380 ratings
+
+
(Original) z3r0x's mod version 3.5
+
+
+ + +
+
+ +
+
+ +
+ +
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+ + + + + + + + + + + +
+
+
+
+
+
+
+ +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+
+ +
+
+ +
+
+
+
+ + 2 +
+
+ + +
+
+ + 3 +
+
+
+
+   +   +
+ + Award + + +
+ +
+
Favorite
+
Favorited
+
Unfavorite
+
+
+ + + +
+ +
+ +
+ + +
+ +
+ +
+ + + +
+ + + +
+ +
+ + +
+
+ +
+ +
+
+
File Size
+
Posted
+
Updated
+ +
+
+
850.105 MB
+
1 Sep, 2017 @ 11:01pm
+
2 Sep, 2017 @ 3:47pm
+
+
+
+ 3 Change Notes ( view ) +
+ + +
+
+ +
+
+ + +
+ + +
+ + +
+ +
+ +
+
+ + +
+ You need DLC to use this item.
+
+
+

Subscribe to download
(Original) z3r0x's mod version 3.5

+ +
+
+ + + +
+
Description
+
NEW VERSION AT: https://steamcommunity.com/sharedfiles/filedetails/?id=2099011934

I do not own this mod, I DID NOT MAKE IT

http://www.moddb.com/members/z3r0x - Mod Creators moddb profile

z3r0x's FOC Addon V3.5

This mod adds a significant amount of units, Heroes, Planets, Missions and gameplay features to Forces of Corruption. It Includes a number of Easter Eggs and also contains a number of other new items.

CHANGES FOR V3:

New units:

Underworld:

Space:
Ginivex-class Fighter
Mankvim-814 Fighter
Nantex Fighter
Technounion Destroyer
Pinnance
Hardcell Transport

Land:
R2-D3 Slicer/Suicide Droid
Single Trooper Aerial Platform (STAP)
Droideka MK1
AAT Droid Tank
Hailfire Tank
Multi-Troop Transport (MTT)
V-19 Speeder

Special:
Golan 1-3
Structure: Casino*
Structure: Brothel*
Structure: Gladiator Arena

Empire:

Space:
A9 Interceptor
TIE Advanced
TIE Droid
TIE Raptor
Scimitar Assault Bomber
Tyrant Missile Cruiser
Star Galleon-class frigate
Legacy Class: Star Destoryer
Venator Class: Star Destoryer
Procurator-class Star Battlecruiser
Mandator I-class Star Dreadnought
Sovereign Super Star Destroyer

Land:
Novatroopers
XR-85 Tank Droid
Probe Droid
AT-RT
AT-PT
AT-AP
ISP

Special:
Golan 1-3
Hero: Mara Jade Added in for ALL GC's
Structure: Imperial Intelligence Branch*

Rebels:

Space:
Arc-170
Delta-7 Aethersprite
Eta-2 Actis
E-Wing
K-Wing
Preybird
Barloz-class freighter
Ferret Recon Ship
Fleet Tender
Sacheen-class light escort
Corona-class frigate
Alderaanian War Frigate
Mediator Class Cruiser
Bulwark

Land:
Bothan Spies
R4 Slicer Droids
T1-B Tank
T3-B Tank*

Special:
Golan 1-3
Hero: Kyle Katrarn/w Moldy Crow
Structure: Bothan Listening Post



Vong Units
*V3*
Miid Ro'ik *


Modifications:

*V3.5*
2 New Units (Mediator Cruiser and Scimitar Assault Bomber)
3 New Planets (Bakura, Bastion, Belkadan)
1 New Space Skirmish Map "Duros Assault"
7 New Maps
Re-Worked AI for the mod..
Vong added in as a true faction.
11 New Props

*V3*
3 New Galactic Campaigns (Classic Matchup- Just Imps and Rebs, Humble Beginnings - All factions start with 4-5 planets, Humble Beginnings Fulll - Rebs and Imps only start witth 4-5 planets)
4 New planets Rendili, Ord Mantell, Mygeeto, and Mechis III
6 New Maps
7 New Props
New Skydome added for Zhar.
Each faction has Major production planets. Where Companies like SorroSuub, KDY, Sienar Systems, etc can be built.
New Structures for all factions

Sienar Fleet Systems Empire (Corulag)*
Kuat Drive Yards Empire/Rebels (Kuat) *
Hoersch-Kessel Driveworks Inc Underworld (Mechis III)
Huppla Pasa Tisc Shipwrights Collective Underworld (Geonosis)*
SoroSuub Rebels (Sullust)*
Corellian Engineering Corporation Rebels/Underworld (Corellia)*
MandalMotors Underworld (Mandalore)*
Rendili StarDrive Rebels (Rendili)*
Mon Cal ShipYards Rebels (Mon Calimari)*
Casino (Underworld)
Gladiator Arena (Underworld)
Cantina (Underworld)
Brothel (Underworld)
Imperial Intelligence Agency (Empire)
Imperial Prison (Empire)
Bothan Listening post (Rebels)
Empire Advanced Vehicle Factory only buildable on certain planets..
LAAT, Lancet, AT-AT, AT-AA, Juggernaut buildable at Empire Advanced Vehicle Factory
Golans 1-3's are buildable on most major planets as additional defenses. They do not replace Space Stations.
How and where ships are built has been completely re-vamped.
Space Battle Pop Cap increased for all sides
Executor buildable only on Fondor
Many new sounds for units


New units:

Underworld:

Space:
Cloakshape Fighter
Howl Runner Fighter
Ginivex-class Fighter
Mankvim-814 Fighter
Nantex Fighter
Tri-Droid Fighter
Vulture Droid Fighter
Corellian Frigate
Recusant Frigate
Munificent Frigate
Technounion Destroyer
Corellian Destroyer
Providence Cruiser
Corellian Battlecruiser*
Lucrehulk
Pinnance
Hardcell Transport

Land:
R2-D3 Slicer/Suicide Droid
B1 BattleDroids
Super BattleDroids
Mandalorian Shock Troopers*
Single Trooper Aerial Platform (STAP)
Droideka MK1
Snail Tank*
AAT Droid Tank
Hailfire Tank
Multi-Troop Transport (MTT)
V-19 Speeder

Special:
Golan 1-3
Hero: Guri
Structure: Casino*
Structure: Brothel*
Structure: Gladiator Arena

Empire:

Space:
A9 Interceptor
Assault Gunboat
TIE Advanced
TIE Avenger
TIE Droid
TIE Raptor
Guardian Class Patrol Ship
Bayonet Cruiser
Carrack Cruiser
Strike Cruiser
Tyrant Missile Cruiser
Dominator Cruiser
Escort Carrier
Lancer Frigate
Star Galleon-class frigate
Legacy Class: Star Destoryer
Venator Class: Star Destoryer
Procurator-class Star Battlecruiser
Mandator I-class Star Dreadnought
Eclipse Super Star Destroyer*
Sovereign Super Star Destroyer

Land:
Novatroopers
E-Web Troopers
Darkside Adepts
XR-85 Tank Droid
Probe Droid
AT-RT
AT-PT
AT-AP
ISP
AT-TE Walker
LAAT/i*

Special:
Golan 1-3
Hero: Baron Soontir Fel w/181st Squadron*
Hero: Admiral Ozzel w/Nemesis Star Destroyer*
Hero: Mara Jade Added in for ALL GC's
Structure: Imperial Intelligence Branch*

Rebels:

Space:
Arc-170
Delta-7 Aethersprite
Eta-2 Actis
E-Wing
K-Wing
Preybird
T-Wing
Barloz-class freighter
Ferret Recon Ship
Fleet Tender
Sacheen-class light escort
Corona-class frigate
Alderaanian War Frigate
Assault Frigate MK1
CC-7700 Interdictor
Dreadnaught
Liberator Carrier
Quasar Fire Carrier
Nebulon B2
MC-40
MC-75
MC-80a
MC-90
Dauntless
Bulwark

Land:
AAC Hovertank
Bothan Spies
R4 Slicer Droids
T1-B Tank
T3-B Tank*
V-Wing Speeder

Special:
Golan 1-3
Hero: General Jan Dodonna
Hero: Kyle Katrarn/w Moldy Crow
Structure: Bothan Listening Post

Misc Factions:
R-41 StarChaser*
N1 Fighter*

Vong Units
*V3*
Miid Ro'ik *
Yorik-et*
Matalok*
Ro'ik chuun m'arh*
Uumufalh*
+
+ + + +
+
Popular Discussions View All (2) +
+ +
+ + + +
+
+ 4
+
+ 24 Mar, 2019 @ 5:07pm
+
+
+ +
+
+ Launch
+
+ Shadow-Wind
+
+
+ +
+ + + +
+
+ 3
+
+ 8 Jul, 2018 @ 5:12am
+
+
+ +
+
+ Crash on Startup
+
+ Phantom Sniper
+
+
+
+
+
+
+
+ + 275 Comments +
+
+
+
+ +
+
+ +
+
+ + +
+ +
+
+
+ + +
+
+
+ + stutpip123 + + +  [author] + +
+
+
+
+ 2 Mar @ 11:15am  +
+
+ + +
+
+
+
+ You know nothing if you think I broke 3.5, given it is a 1:1 upload from moddb of the original.
Any bugs in 3.5.3 could be caused by me, but unlikely if it occurs in 3.5 as well.
Gotta remember, this mod dates back to 2007, Empire at War has had several large updates since, including changing from 32 bit to 64 bit. Many things have become broken that weren't originally
+ +
+
+ + +
+ +
+
+
+ + +
+
+
+ + fugazirob + + + + +
+
+
+
+ 2 Mar @ 12:44am  +
+
+ + +
+
+
+
+ Nope, Still broken, Fondor defiler mission causes black screen and many other issues plague this version of this mod witch was fine before someone used it as a test of their lack of abilities.
+ +
+
+ + +
+ +
+
+
+ + +
+
+
+ + stutpip123 + + +  [author] + +
+
+
+
+ 26 Feb @ 10:57am  +
+
+ + +
+
+
+ + +
+
+ + +
+ +
+
+
+ + +
+
+
+ + fugazirob + + + + +
+
+
+
+ 25 Feb @ 11:54pm  +
+
+ + +
+
+
+
+ You didn't make it but obviously with no ill intentions you broke it, please Un-Break What You Broke
+ +
+
+ + +
+ +
+
+
+ + +
+
+
+ + buster1_1 + + + + +
+
+
+
+ 15 Sep, 2024 @ 4:41am  +
+
+ + +
+
+
+
+ Build pads and hero abilities dont work. Zann Consortium are also broken and their annoying factors are jacked up to 11.
+ +
+
+ + +
+ +
+
+
+ + +
+
+
+ + fugazirob + + + + +
+
+
+
+ 9 Jul, 2024 @ 12:47am  +
+
+ + +
+
+
+
+ This Mod is now broken, its a shame because it was one of the best EAW mods
+ +
+
+ + +
+ +
+
+ +
+
+ + Clonardor + + + + +
+
+
+
+ 9 Jan, 2024 @ 9:43pm  +
+
+ + +
+
+
+
+ Where can I build the Lucrehulk
+ +
+
+ + +
+ +
+
+
+ + +
+
+
+ + stutpip123 + + +  [author] + +
+
+
+
+ 20 Dec, 2023 @ 12:27pm  +
+
+ + +
+
+
+ + +
+
+ + +
+ +
+
+
+
+ + + + + +
+ + + + + + +
+
+
+ + CentralCobra70 + + + + +
+
+
+
+ 20 Dec, 2023 @ 3:38am  +
+
+ + +
+
+
+
+ idk if the recent update messed with the mod but i cant build turrets with the consortium anymore was wondering if this happened to anyone else
+ +
+
+ + +
+ +
+
+
+ + +
+
+ +
+
+
+ 15 Jul, 2023 @ 5:55pm  +
+
+ + +
+
+
+
+ how to build battleships and confederate troops for the syndicate ?
+ +
+
+ +
+
+ +
+
+ +
+ +
+ + + + + + + + + +
+ + +
+
+ +
+ +
+ +
+
+
+
Do you mind if we use optional cookies to provide you personalized content and to analyze site traffic?
+
We don't use a lot of cookies; you can see and manage them at any time on our Cookie Settings page. If you click 'Accept All,' you consent to the use of cookies on Steam websites. Learn more about cookies in our Privacy Policy.
+
+
+
Accept All
+
Reject All
+
+
+
\ No newline at end of file diff --git a/test/PG.StarWarsGame.Infrastructure.Test/ModServices/Fixtures/workshop_2508288191.html b/test/PG.StarWarsGame.Infrastructure.Test/ModServices/Fixtures/workshop_2508288191.html new file mode 100644 index 00000000..6bd95bbc --- /dev/null +++ b/test/PG.StarWarsGame.Infrastructure.Test/ModServices/Fixtures/workshop_2508288191.html @@ -0,0 +1,1546 @@ + + + + + Steam Workshop::Empire at War Expanded: Deep Core 3.1 (Updated October 26) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
+

STAR WARS™ Empire at War: Gold Pack

+ +
+ +
+
Game Type: EAW, FOC
+ +
+ +
+
+
File Size
+
Posted
+
Updated
+ +
+
+
285.033 KB
+
5 Jun, 2021 @ 5:32pm
+
26 Oct, 2021 @ 10:16pm
+
+
+
+ 4 Change Notes ( view ) +
+ + +
+
+ +
+
+
+ + + +
+
+ + +
+
+ +
+ +
+ +
+ + + + + + + +
+ +
+ + + + +
+ + +
+ + + + + + +
+
+
+
+
+ + + Store Page + +
+
+
+
STAR WARS™ Empire at War: Gold Pack
+
+
+ + +
+ + All + + Discussions + + Screenshots + + Broadcasts + + Videos + + Workshop + + News + + Guides + + Reviews +
+
+ +
+
+
+ +
+
+
+
+
+
+ + + +
+
+
+ + + +
+ +
+
+
+ + +
+ + + + + + + + + + + +
+
+ +
+
+
81 ratings
+
+
Empire at War Expanded: Deep Core 3.1 (Updated October 26)
+
+
+ + +
+
+ +
+
+ +
+ +
+ +
+
+
+
+ +
+
+ + +
+
+
+ +
+
+
+
+ + 3 +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + 9 +
+
+
+
+   +   +
+ + Award + + +
+ +
+
Favorite
+
Favorited
+
Unfavorite
+
+
+ + + +
+ +
+ +
+ + +
+ +
+ +
+ + + +
+ + + +
+ +
+ +
+
+ + +
+ + +
+ + +
+ +
+
+ + +
+ You need DLC to use this item.
+
+
+

Subscribe to download
Empire at War Expanded: Deep Core 3.1 (Updated October 26)

+ +
+
+ + + +
+
Description
+
Empire at War Expanded: Deep Core
This is a modding resource and not intended to be played by itself!

About this mod

This is a standalone version of DeepCore, the Lua framework that powers most of the mechanics found in Empire at War Expanded.
It is not intended to played by itself, but rather to allow other projects to use the DeepCore framework in sub mods without having to install it into their mods directly.
This mod does not include the mechanics from Empire at War Expanded. It only provides the framework these mechanics are based upon.

Capabilities of DeepCore

DeepCore is primarily designed as a framework that allows the definition of plugins that get loaded and updated at specified times automatically.
This allows for fast implementation of new mechanics without having to modify existing code.
DeepCore also includes an alternative implementation to PGStateMachine with a focus on transitions between states.
States can be setup using a specifically implemented internal domain specific language.
Last but not least, DeepCore also provides the crossplot library which allows for communication between isolated Lua scripts via means of GlobalValues using a publish-subscribe pattern.

Documentation

For a detailed documentation please visit:
https://github.com/SvenMarcus/deepcore-standalone/wiki

Sub mod launching

To launch your sub mod with DeepCore as a base use the following launch arguments:
STEAMMOD=YOURSUBMODID STEAMMOD=2508288191
+
+ + + +
+
+
+
+ + 9 Comments +
+
+
+ +
+ +
+
+ + +
+ +
+
+
+ + +
+
+
+ + Pox + + +  [author] + +
+
+
+
+ 12 Jun, 2021 @ 4:49pm  +
+
+ + +
+
+
+
+ @Bennettopolous DeepCore is intended for people who write new mechanics with Lua, so it requires programming knowledge. If you're interested in adding new units, planets, etc. it's not really what you're looking for.
+ +
+
+ + +
+ +
+
+
+ + +
+
+
+ + dAjOsh42069 + + + + +
+
+
+
+ 12 Jun, 2021 @ 2:34pm  +
+
+ + +
+
+
+
+ I suspect advanced users... I have NO clue how to (personally) use this. lol But with a little bit of study, I'd imagine it would make modding quite a bit easier.
+ +
+
+ + +
+ +
+
+
+
+ + + + + +
+ + + + + + +
+
+
+ + Zeus + + + + +
+
+
+
+ 12 Jun, 2021 @ 2:14am  +
+
+ + +
+
+
+
+ As someone who has never modded but wants to learn, I cannot tell if this is good for beginners or more for the advanced?
+ +
+
+ + +
+ +
+
+
+ + +
+
+
+ + dAjOsh42069 + + + + +
+
+
+
+ 8 Jun, 2021 @ 12:45pm  +
+
+ + +
+
+
+
+ Can't wait til later when I get a chance to play around with this. :) :)
EXTREMELY cool idea. :D
+ +
+
+ + +
+ +
+
+
+
+ + + + + +
+ + +
+
+
+ + Cooler12351 + + + + +
+
+
+
+ 8 Jun, 2021 @ 7:32am  +
+
+ + +
+
+
+
+ It is the Base for the EaWX Features and allows submodders to Work with It easier
+ +
+
+ + +
+ +
+
+
+
+ + + + + +
+ + +
+
+
+ + Izzy012 + + + + +
+
+
+
+ 8 Jun, 2021 @ 1:34am  +
+
+ + +
+
+
+
+ Could someone explain a little more what this does besides being a framework.
+ +
+
+ + +
+ +
+
+
+
+ + + + + +
+ + +
+
+
+ + Zadonic + + + + +
+
+
+
+ 7 Jun, 2021 @ 12:26am  +
+
+ + +
+
+
+
+ Yeah thats really awesome
+ +
+
+ + +
+ +
+
+
+ + +
+
+ +
+
+
+ 6 Jun, 2021 @ 7:46pm  +
+
+ + +
+
+
+
+ Very awesome indeed
+ +
+
+ + +
+ +
+
+
+ + +
+
+
+ + McFly + + + + +
+
+
+
+ 6 Jun, 2021 @ 7:23pm  +
+
+ + +
+
+
+
+ Thanks. This is awesome
+ +
+
+ +
+
+ +
+
+ +
+ +
+ + + + + + + + + +
+ + +
+
+ +
+ +
+ +
+
+
+
Do you mind if we use optional cookies to provide you personalized content and to analyze site traffic?
+
We don't use a lot of cookies; you can see and manage them at any time on our Cookie Settings page. If you click 'Accept All,' you consent to the use of cookies on Steam websites. Learn more about cookies in our Privacy Policy.
+
+
+
Accept All
+
Reject All
+
+
+
\ No newline at end of file diff --git a/test/PG.StarWarsGame.Infrastructure.Test/ModServices/Fixtures/workshop_2978074984.html b/test/PG.StarWarsGame.Infrastructure.Test/ModServices/Fixtures/workshop_2978074984.html new file mode 100644 index 00000000..9d01202b --- /dev/null +++ b/test/PG.StarWarsGame.Infrastructure.Test/ModServices/Fixtures/workshop_2978074984.html @@ -0,0 +1,1539 @@ + + + + + Steam Workshop::EAWFOC Mod Template + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
+
+
+ + + +
+
+ + +
+
+ +
+ +
+ +
+ + + + + + + +
+ +
+ + + + +
+ + +
+ + + + + + +
+
+
+
+
+ + + Store Page + +
+
+
+
STAR WARS™ Empire at War: Gold Pack
+
+
+ + +
+ + All + + Discussions + + Screenshots + + Broadcasts + + Videos + + Workshop + + News + + Guides + + Reviews +
+
+ +
+
+
+ +
+
+
+
+
+
+ + + +
+
+

STAR WARS™ Empire at War: Gold Pack

+ +
+
+ + + +
+ +
+
+
+ + +
+ + + + + + + + + + + +
+
+ +
+
+ Not enough ratings
+
+
EAWFOC Mod Template
+
+
+ + +
+
+ +
+
+ +
+ +
+ +
+
+
+
+ +
+
+ + +
+
+
+ +
+
+
+
+ + +
+
+ + +
+
+ + 2 +
+
+
+
+   +   +
+ + Award + + +
+ +
+
Favorite
+
Favorited
+
Unfavorite
+
+
+ + + +
+ +
+ +
+ + +
+ +
+ +
+ + + +
+ + + +
+ +
+ +
+
Game Type: EAW, FOC
+ +
+ +
+
+
File Size
+
Posted
+ +
+
+
19.689 KB
+
20 May, 2023 @ 7:02am
+
+
+
+ 1 Change Note ( view ) +
+ + +
+
+ +
+
+ + +
+ + +
+ + +
+ +
+ +
+
+ + +
+
+

Subscribe to download
EAWFOC Mod Template

+ +
+
+ + + +
+
Description
+
==================================
EAWFOC Mod Template by CNKommander
==================================

IMPORTANT NOTE: This "mod" project is not intended to be run as a mod! This is just a mod template and does not cover advanced modding topics!

This project is a mod template aimed at helping new modders to Empire at War get started on new mod projects in a quick and easy way.
This mod template should be compatible with both Empire at War and Forces of Corruption


GitHub repository: https://github.com/CNKommander/eawfoc-mod-template
+
+ + + +
+
+
+
+ + 12 Comments +
+
+
+
+ +
+
+ +
+
+ + +
+ +
+
+
+
+ + + + + +
+ + +
+
+
+ + Joewlpc + + + + +
+
+
+
+ 8 Feb, 2025 @ 9:15pm  +
+
+ + +
+
+
+
+ 2978074984
+ +
+
+ + +
+ +
+
+
+ + +
+
+
+ + carterjaeger26 + + + + +
+
+
+
+ 10 Dec, 2024 @ 4:53am  +
+
+ + +
+
+
+
+ whats the STEAMMOD=1234567890
+ +
+
+ + +
+ +
+
+
+
+ + + + + +
+ + +
+
+
+ + StarGhostss + + + + +
+
+
+
+ 23 Jul, 2024 @ 9:14pm  +
+
+ + +
+
+
+
+ @CNKommandar yeah, ive used the correct steammod path, but it still doesnt seem to work, but by using the EAW Mod Launcher, the mod works fine
+ +
+
+ + +
+ +
+
+
+
+ + + + + +
+ + + + + + +
+
+
+ + CNKommander + + +  [author] + +
+
+
+
+ 23 Jul, 2024 @ 6:00pm  +
+
+ + +
+
+
+
+ @StarGhostss have you checked to make sure you have launched your mod correctly? Assuming you are trying to run the workshop version, the right ID should be STEAMMOD=XXXXXXXXXX (X is the string of numbers), otherwise the MODPATH=Mods\modname is used
+ +
+
+ + +
+ +
+
+
+
+ + + + + +
+ + +
+
+
+ + StarGhostss + + + + +
+
+
+
+ 23 Jul, 2024 @ 12:00pm  +
+
+ + +
+
+
+
+ quick question, ive used this template but when i upload my mod to the workshop it just uses the base game and doesnt use the tweaks ive made to the game
+ +
+
+ + +
+ +
+
+
+
+ + + + + +
+ + + + + + +
+
+
+ + CNKommander + + +  [author] + +
+
+
+
+ 16 Nov, 2023 @ 1:48am  +
+
+ + +
+
+
+
+ @crono900 For questions about FotR modding, folks over at CoreyLoses Discord will be a more suitable place for that. I am not a FotR dev or submodder, so I can't really help with that specifically.

This is geared more towards having a good mod template to work off of
+ +
+
+ + +
+ +
+
+
+ + +
+
+
+ + crono900 + + + + +
+
+
+
+ 15 Nov, 2023 @ 10:12am  +
+
+ + +
+
+
+
+ How do I edit the crew cost? I've been playing the FotR mod, and am getting into the modding to make it more lore friendly. I am working on a way to get the ships to resemble that of the SWRPG D20 game. The Venator should have ten times the crew that of the Acclamator has, but they cost the same crew of 10. This is why I'm asking for how to mod it.
+ +
+
+ + +
+ +
+
+
+
+ + + + + +
+ + + + + + +
+
+
+ + CNKommander + + +  [author] + +
+
+
+
+ 3 Jun, 2023 @ 7:24pm  +
+
+ + +
+
+
+
+ @McCorny all good. The GitHub link is really just to highlight the open source nature of the project. And of course as an optional way to download a copy of the project.

It is possible to make use of models and textures from other mods, but permission for use has to be obtained before usage in publicly available mods.

also, depending on the mod the assets came from, it can be tricky to get the model working in game.
+ +
+
+ + +
+ +
+
+
+
+ + + + + +
+ + +
+
+
+ + TalesOf40K + + + + +
+
+
+
+ 1 Jun, 2023 @ 12:48am  +
+
+ + +
+
+
+
+ Ahh my bad, thought i gotta get everything from GitHub..
Will check it out soon. Thanks!

Playing EaW for 15+ Years now and thats why I want to create my own Clone Wars Mod :D
Is it possible to copy models/graphics from other Mods?
+ +
+
+ + +
+ +
+
+
+
+ + + + + +
+ + + + + + +
+
+
+ + CNKommander + + +  [author] + +
+
+
+
+ 29 May, 2023 @ 2:49pm  +
+
+ + +
+
+
+
+ @McCorny you can download the mod template by clicking on the green “Subscribe” button.

If you are downloading the project from GitHub, there should be an option to “Download as ZIP”
+ +
+
+ +
+
+ +
+
+ +
+ +
+ + + + + + + + + +
+ + +
+
+ +
+ +
+ +
+
+
+
Do you mind if we use optional cookies to provide you personalized content and to analyze site traffic?
+
We don't use a lot of cookies; you can see and manage them at any time on our Cookie Settings page. If you click 'Accept All,' you consent to the use of cookies on Steam websites. Learn more about cookies in our Privacy Policy.
+
+
+
Accept All
+
Reject All
+
+
+
\ No newline at end of file diff --git a/test/PG.StarWarsGame.Infrastructure.Test/ModServices/OnlineModGameTypeResolverTest.cs b/test/PG.StarWarsGame.Infrastructure.Test/ModServices/OnlineModGameTypeResolverTest.cs index 8c37b2c5..b49b5289 100644 --- a/test/PG.StarWarsGame.Infrastructure.Test/ModServices/OnlineModGameTypeResolverTest.cs +++ b/test/PG.StarWarsGame.Infrastructure.Test/ModServices/OnlineModGameTypeResolverTest.cs @@ -12,6 +12,12 @@ namespace PG.StarWarsGame.Infrastructure.Test.ModServices; public class OnlineModGameTypeResolverTest : ModGameTypeResolverTestBase { + protected override void SetupServices(IServiceCollection serviceCollection) + { + base.SetupServices(serviceCollection); + serviceCollection.AddSingleton(new FakeSteamWorkshopWebpageDownloader()); + } + public override ModGameTypeResolver CreateResolver() { return new OnlineModGameTypeResolver(ServiceProvider); @@ -20,13 +26,10 @@ public override ModGameTypeResolver CreateResolver() public static IEnumerable GetOnlineModsData() { yield return ["1125718579", new[] {GameType.Foc}, GameType.Eaw]; //z3r0x's Mod (3.5) - yield return ["2508288191", new[] {GameType.Foc, GameType.Eaw}, null!]; //Mod Template + yield return ["2508288191", new[] {GameType.Foc, GameType.Eaw}, null!]; //Deep Core } - [Theory( - Skip = TestEnvironment.SteamLiveTestsSkipReason, - SkipUnless = nameof(TestEnvironment.SteamLiveTestsEnabled), - SkipType = typeof(TestEnvironment))] + [Theory] [MemberData(nameof(GetOnlineModsData))] public void Online_GetTagsFromSteamOnline(string knownId, ICollection expectedTypes, GameType? incompatibleWith) { diff --git a/test/PG.StarWarsGame.Infrastructure.Test/PG.StarWarsGame.Infrastructure.Test.csproj b/test/PG.StarWarsGame.Infrastructure.Test/PG.StarWarsGame.Infrastructure.Test.csproj index 403203eb..547e278b 100644 --- a/test/PG.StarWarsGame.Infrastructure.Test/PG.StarWarsGame.Infrastructure.Test.csproj +++ b/test/PG.StarWarsGame.Infrastructure.Test/PG.StarWarsGame.Infrastructure.Test.csproj @@ -34,4 +34,8 @@
+ + + + From a8039e5e33111f04b5020cafe40ec62eff573512 Mon Sep 17 00:00:00 2001 From: AnakinRaW Date: Sun, 24 May 2026 19:37:09 +0200 Subject: [PATCH 09/10] Update `GameProcessTest` to use `StartUnattendedTestProcess` in Dispose-related test --- .../Clients/Processes/GameProcessTest.cs | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/test/PG.StarWarsGame.Infrastructure.Test/Clients/Processes/GameProcessTest.cs b/test/PG.StarWarsGame.Infrastructure.Test/Clients/Processes/GameProcessTest.cs index a0fa157f..40561bf0 100644 --- a/test/PG.StarWarsGame.Infrastructure.Test/Clients/Processes/GameProcessTest.cs +++ b/test/PG.StarWarsGame.Infrastructure.Test/Clients/Processes/GameProcessTest.cs @@ -29,6 +29,24 @@ private Process StartStableTestProcess() return _testProcess; } + // Long-running process that does not read stdin, so closing the redirected + // stdin handle (e.g. via Process.Dispose) cannot terminate it early. Used by + // tests that need a process which stays alive across a Dispose() call. + private Process StartUnattendedTestProcess() + { + var processStartInfo = new ProcessStartInfo + { + FileName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "cmd.exe" : "/bin/sh", + Arguments = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) + ? "/c ping -n 10 127.0.0.1 > nul" + : "-c \"sleep 10\"", + CreateNoWindow = true, + UseShellExecute = false, + }; + _testProcess = Process.Start(processStartInfo)!; + return _testProcess; + } + public void Dispose() { try @@ -296,7 +314,10 @@ public void Dispose_ClosesProcessAndCleansResources() [Fact] public async Task Dispose_CompletesWaitForExitAsyncSilently() { - var process = StartStableTestProcess(); + // Must not use StartStableTestProcess here: `cmd /c pause` reads from redirected + // stdin and exits on EOF, so disposing the Process (which closes the pipe) would + // race the assertion. + var process = StartUnattendedTestProcess(); var processInfo = new GameProcessInfo(Game, GameBuildType.Release, ArgumentCollection.Empty); var gameProcess = new GameProcess(process, processInfo); From 473dd4bb744d01eeae95349ab4876dfd08d9a63d Mon Sep 17 00:00:00 2001 From: AnakinRaW Date: Sun, 24 May 2026 23:38:17 +0200 Subject: [PATCH 10/10] Simplify `SteamWorkshopWebpageDownloader` by removing retry logic and backoff handling. --- .../Steam/SteamWorkshopWebpageDownloader.cs | 50 ++----------------- 1 file changed, 5 insertions(+), 45 deletions(-) diff --git a/src/PG.StarWarsGame.Infrastructure/Services/Steam/SteamWorkshopWebpageDownloader.cs b/src/PG.StarWarsGame.Infrastructure/Services/Steam/SteamWorkshopWebpageDownloader.cs index a04ffb7b..2686742a 100644 --- a/src/PG.StarWarsGame.Infrastructure/Services/Steam/SteamWorkshopWebpageDownloader.cs +++ b/src/PG.StarWarsGame.Infrastructure/Services/Steam/SteamWorkshopWebpageDownloader.cs @@ -1,5 +1,4 @@ -using System; -using System.Globalization; +using System.Globalization; using System.Net.Http; using System.Threading.Tasks; using System.Web; @@ -10,9 +9,6 @@ namespace PG.StarWarsGame.Infrastructure.Services.Steam; internal class SteamWorkshopWebpageDownloader : ISteamWorkshopWebpageDownloader { private const string SteamWorkshopsBaseUrl = "https://steamcommunity.com/sharedfiles/filedetails/?"; - private const int MaxRetries = 4; - private static readonly TimeSpan InitialBackoff = TimeSpan.FromSeconds(1); - private static readonly TimeSpan MaxBackoff = TimeSpan.FromSeconds(30); public async Task GetSteamWorkshopsPageHtmlAsync(ulong workshopId, CultureInfo? culture) { @@ -24,45 +20,9 @@ public async Task GetSteamWorkshopsPageHtmlAsync(ulong workshopId, var address = $"{SteamWorkshopsBaseUrl}{queryString}"; using var client = new HttpClient(); - - var backoff = InitialBackoff; - for (var attempt = 0; ; attempt++) - { - using var response = await client.GetAsync(address).ConfigureAwait(false); - - if ((int)response.StatusCode != 429) - { - response.EnsureSuccessStatusCode(); - var reply = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - var htmlDocument = new HtmlDocument(); - htmlDocument.LoadHtml(reply); - return htmlDocument; - } - - if (attempt >= MaxRetries) - response.EnsureSuccessStatusCode(); - - var wait = GetRetryAfter(response) ?? backoff; - if (wait > MaxBackoff) - wait = MaxBackoff; - await Task.Delay(wait).ConfigureAwait(false); - - backoff = TimeSpan.FromTicks(Math.Min(backoff.Ticks * 2, MaxBackoff.Ticks)); - } - } - - private static TimeSpan? GetRetryAfter(HttpResponseMessage response) - { - var header = response.Headers.RetryAfter; - if (header is null) - return null; - if (header.Delta is { } delta && delta > TimeSpan.Zero) - return delta; - if (header.Date is { } when) - { - var delay = when - DateTimeOffset.UtcNow; - return delay > TimeSpan.Zero ? delay : null; - } - return null; + var reply = await client.GetStringAsync(address); + var htmlDocument = new HtmlDocument(); + htmlDocument.LoadHtml(reply); + return htmlDocument; } } \ No newline at end of file