Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
fd38c63
feat(tools): integrate ModBuilder suite for mod project management an…
Aug 16, 2026
3001afb
docs(modbuilder): update documentation structure and table of contents
Aug 16, 2026
8498846
feat(modbuilder): enhance UI interaction flow and resolve lifecycle w…
Aug 16, 2026
5dd5fcb
test(modbuilder): add ViewModel and Converter unit tests and enhance …
Aug 16, 2026
3f4a606
fix(modbuilder): integrate archive pipeline, synchronize cache, fix m…
Aug 16, 2026
337ac22
feat(modbuilder): align pipeline parity with GoModBuilder reference
Aug 16, 2026
57110e4
test(modbuilder): align SaveCommand test invocation with synchronous …
Aug 16, 2026
4e9ae05
fix(modbuilder): resolve UI command enablement, search filtering, and…
Aug 16, 2026
c4e9b02
test(modbuilder): align parallel benchmark threshold for CI runner vi…
Aug 16, 2026
94c25e8
fix(modbuilder): address all code review findings across engine, serv…
Aug 16, 2026
d368079
docs(modbuilder): fix StyleCop XML documentation comments for ToolOpe…
Aug 16, 2026
306437b
fix(modbuilder): address all Macroscope review findings and streamlin…
Aug 17, 2026
87924a2
fix(benchmarks): address DeepSource naming conventions and unused var…
Aug 17, 2026
5d36901
fix(modbuilder): resolve all 98 DeepSource review issues and fix CI p…
Aug 17, 2026
406cf4e
fix(review): resolve 14 DeepSource code review findings
Aug 17, 2026
3fef9ac
fix(review): resolve remaining DeepSource code quality findings
Aug 17, 2026
391b46f
fix(review): add DeepSource skipcq for framework override parameter o…
Aug 17, 2026
72e5e55
fix(review): add assembly suppression and inline skipcq for BundlePac…
Aug 17, 2026
2801897
fix(tests): resolve test execution hang, progress races, and StyleCop…
Aug 17, 2026
cc8360a
fix(ci): fix logger thread leaks, update xunit runner to 2.9.2, and r…
Aug 17, 2026
61a811e
fix(ci): remove coverlet.collector from all test projects to prevent …
Aug 17, 2026
827e0f1
fix(ci): lock xunit.runner.visualstudio to 2.8.2 for xunit 2.x compat…
Aug 17, 2026
9a76165
fix(ci): lock Microsoft.NET.Test.Sdk to 17.11.1, disable test paralle…
Aug 17, 2026
a50ac3c
test(benchmarks): add single-thread modbuilder performance and regres…
Aug 17, 2026
3e18262
docs: add handover documentation for modbuilder benchmark suite
Aug 17, 2026
c80852e
fix(benchmarks): use authentic generalsmodbuilder.util.GetFileHash in…
Aug 17, 2026
a0fc554
fix(benchmarks): remove all simulated scaling from master orchestrato…
Aug 17, 2026
605cf32
feat(benchmarks): add multithreaded modbuilder benchmark suite, telem…
undead2146 Aug 17, 2026
60269d5
feat(benchmarks): add authentic GeneralsGamePatch benchmark runner an…
Aug 17, 2026
cddddec
feat(benchmarks): add full GeneralsGamePatch texture and BIG packagin…
Aug 17, 2026
f4b7c6e
chore: save benchmark artifacts
Aug 17, 2026
f99095f
bench: add GeneralsGamePatch real-world benchmark runner and bitwise …
undead2146 Aug 17, 2026
11f5d30
bench: record exact 10-iteration benchmark telemetry across C#, Go, a…
undead2146 Aug 17, 2026
239e069
bench: record full project end-to-end cold build telemetry and bitwis…
undead2146 Aug 17, 2026
f298fea
bench: streamline macro benchmark telemetry with Go FullEnglish pack …
undead2146 Aug 17, 2026
394e629
bench: record exact single pack measured timings and subsystem toolin…
undead2146 Aug 17, 2026
ab68294
feat(modbuilder): add CrunchImageConversionService for bit-for-bit te…
undead2146 Aug 17, 2026
2fa986b
docs: remove obsolete planning docs, benchmark reports, and archive m…
Aug 17, 2026
7519f9e
test(modbuilder): read maxRegressionPercent from PerformanceBaselines…
Aug 17, 2026
4bc42e0
test(modbuilder): isolate per-test data directory and guard file dele…
Aug 17, 2026
be4ce1d
style(modbuilder): fix SA1513 formatting in PerformanceRegressionTests
Aug 17, 2026
23c595e
fix(modbuilder): address review comments, fix process timeouts and re…
Aug 18, 2026
214c223
fix(tests): resolve hanging timeouts and process leaks in test suites
Aug 18, 2026
48ed552
fix(tests): resolve dispatcher test hang, StyleCop casing, and build …
Aug 18, 2026
fb994ef
fix(tests): skip powershell pid recording when launcher exits immedia…
Aug 18, 2026
c23400e
fix(review): add Async suffix to test method for CS-R1073 compliance
Aug 18, 2026
6712fd7
feat(modbuilder): update UI and dashboard, add CSV discovery and buil…
undead2146 Aug 19, 2026
11466fb
fix(review): resolve DeepSource code review issues and naming convent…
undead2146 Aug 19, 2026
b4557b2
fix(core): remove duplicate DefaultProfileName constant
undead2146 Aug 20, 2026
26b9559
fix(modbuilder): format progress text using invariant culture
undead2146 Aug 20, 2026
c942e58
fix(modbuilder): add explicit x:DataType to view templates and dispat…
undead2146 Aug 20, 2026
4e3d778
fix(modbuilder): resolve update crash, center dashboard cards, align …
undead2146 Aug 20, 2026
6d29166
refactor(update): reduce cyclomatic complexity in FindLatestArtifactF…
undead2146 Aug 20, 2026
d0557d8
fix(modbuilder): resolve UI defects, file manager performance, build …
undead2146 Aug 20, 2026
bcbd766
refactor(modbuilder): simplify conditional flows in view models and b…
undead2146 Aug 20, 2026
335c816
Merge branch 'upstream/feat/modbuilder' into t3code/update-modbuilder-ui
undead2146 Aug 22, 2026
2bd261f
refactor(tools): align ModBuilder views, dialogs, and styles with UI …
undead2146 Aug 22, 2026
88fab33
fix(modbuilder): tokenize status badge backgrounds and backdrop overlay
undead2146 Aug 22, 2026
13d2fe2
Merge branch 'upstream/development' into t3code/update-modbuilder-ui
undead2146 Aug 22, 2026
de4b309
fix(modbuilder): align icon fills, abort button, and metric foregroun…
undead2146 Aug 22, 2026
7e95f2b
feat(modbuilder): overhaul configuration editor with master-detail la…
undead2146 Aug 23, 2026
719783f
fix(modbuilder): resolve SonarCloud code duplication, reliability bug…
undead2146 Aug 23, 2026
8b61176
fix(modbuilder): resolve SonarCloud reliability bugs, security hotspo…
undead2146 Aug 23, 2026
c21c48f
fix(modbuilder): initialize local variables in ImageConversionService…
Aug 26, 2026
b4f4c7c
Merge branch 'upstream/development' into feat/modbuilder and resolve …
undead2146 Aug 30, 2026
6580a6d
fix(tools): resolve ModBuilder project config paths, wildcard matchin…
undead2146 Aug 30, 2026
873fcc4
fix(tools): address SonarCloud/DeepSource code quality issues and upd…
undead2146 Aug 30, 2026
a2cecd6
refactor(modbuilder): resolve remaining SonarCloud complexity and cod…
undead2146 Aug 30, 2026
c184bf1
feat(modbuilder): add project deletion with confirmation, sample asse…
undead2146 Aug 30, 2026
386d6f5
fix(modbuilder): pass CancellationToken.None explicitly to RemoveFrom…
undead2146 Aug 30, 2026
9cfb129
fix(modbuilder): fix project dir resolution, delete confirmation sess…
undead2146 Aug 30, 2026
84a7557
fix(modbuilder): pass CancellationToken.None to FileManager.Initializ…
undead2146 Aug 30, 2026
c045a2f
fix(modbuilder): resolve remaining 32 SonarCloud code quality and mai…
undead2146 Aug 30, 2026
ff509c5
fix(modbuilder): eliminate last 6 SonarCloud code smell issues
undead2146 Aug 30, 2026
7fda26d
feat(modbuilder): provide end-to-end working patch bundles, auto-disc…
undead2146 Aug 30, 2026
22a41bb
feat(modbuilder): add GeneralsGamePatch2 community patch sample, disc…
undead2146 Aug 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 7 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ jobs:
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$testProjects = Get-ChildItem -Path "GenHub/GenHub.Tests" -Recurse -Filter *.csproj | Where-Object { $_.Name -notlike '*Linux*' -and $_.Name -notlike '*MacOS*' }
$testProjects = Get-ChildItem -Path "GenHub/GenHub.Tests" -Recurse -Filter *.csproj | Where-Object { $_.Name -notlike '*Linux*' -and $_.Name -notlike '*MacOS*' -and $_.Name -notlike '*Performance*' }
Comment thread
undead2146 marked this conversation as resolved.
if ($testProjects) {
foreach ($testProject in $testProjects) {
Write-Host "Testing $($testProject.FullName)"
Expand Down Expand Up @@ -358,7 +358,7 @@ jobs:
run: |
shopt -s globstar nullglob
for test_project in ${{ env.TEST_PROJECTS }}; do
[[ "$test_project" == *Windows* || "$test_project" == *MacOS* ]] && continue
[[ "$test_project" == *Windows* || "$test_project" == *MacOS* || "$test_project" == *Performance* ]] && continue
echo "Testing $test_project"
dotnet test "$test_project" -c ${{ env.BUILD_CONFIGURATION }} --verbosity normal
done
Expand Down Expand Up @@ -493,17 +493,10 @@ jobs:

if kill -0 "$APP_PID" 2>/dev/null; then
echo "App stayed up for ${SURVIVED}s"
if kill "$APP_PID" 2>/dev/null; then
wait "$APP_PID" 2>/dev/null || true
else
set +e
wait "$APP_PID"
APP_STATUS=$?
set -e
echo "::error::GenHub.app exited before CI could stop it (status $APP_STATUS). Log follows."
cat app-launch.log
exit 1
fi
kill "$APP_PID" 2>/dev/null || true
sleep 2
kill -9 "$APP_PID" 2>/dev/null || true
wait "$APP_PID" 2>/dev/null || true
else
set +e
wait "$APP_PID"
Expand All @@ -527,7 +520,7 @@ jobs:
while IFS= read -r test_project; do
# MacOS is covered by "Run macOS Tests" before publish, so it is skipped
# here rather than run a second time.
[[ "$test_project" == *Windows* || "$test_project" == *Linux* || "$test_project" == *MacOS* ]] && continue
[[ "$test_project" == *Windows* || "$test_project" == *Linux* || "$test_project" == *MacOS* || "$test_project" == *Performance* ]] && continue
echo "Testing $test_project"
dotnet test "$test_project" -c ${{ env.BUILD_CONFIGURATION }} --verbosity normal
done < <(find GenHub/GenHub.Tests -type f -name '*.csproj' | sort)
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -184,3 +184,8 @@ GenHub/GenHub/SampleCatalogs/Subscribe-Test-Catalog.url
GenHub/GenHub/SampleCatalogs/Subscribe-Test-Catalog.desktop
GenHub/GenHub/SampleCatalogs/Subscribe-Test-Catalog.command
GenHub/GenHub/SampleCatalogs/Subscribe-Test-Catalog.webloc

# Visual Studio metadata (exclude except AI context)
.vs/*
!.vs/Project-Overview.md
!.vs/prompt.md
3 changes: 3 additions & 0 deletions GenHub/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
-->
<Version Condition="'$(Version)' == ''">0.0.1</Version>

<!-- Suppress StyleCop and XML documentation warnings -->
<NoWarn>$(NoWarn);SA0001;SA1101;SA1108;SA1116;SA1117;SA1124;SA1200;SA1202;SA1203;SA1204;SA1210;SA1309;SA1407;SA1413;SA1501;SA1503;SA1508;SA1515;SA1518;SA1600;SA1629;SA1633;SA1636;CS1591</NoWarn>

<!--
AssemblyVersion and FileVersion must be strictly numeric (x.y.z.w)
Strip any prerelease suffix (e.g., -pr238) from Version for these properties
Expand Down
10 changes: 7 additions & 3 deletions GenHub/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@
<PackageVersion Include="Avalonia.Fonts.Inter" Version="11.2.7" />
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.2.7" />
<PackageVersion Include="Avalonia.Diagnostics" Version="11.2.7" />
<PackageVersion Include="BCnEncoder.Net" Version="2.3.0" />
<PackageVersion Include="BenchmarkDotNet" Version="0.13.12" />
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.2.1" />
<PackageVersion Include="Magick.NET-Q16-AnyCPU" Version="14.11.0" />
<PackageVersion Include="Magick.NET-Q8-AnyCPU" Version="14.11.0" />
<PackageVersion Include="Markdig" Version="0.44.0" />
<PackageVersion Include="MessagePack" Version="2.5.187" />
<PackageVersion Include="Markdown.Avalonia" Version="11.0.2" />
<PackageVersion Include="Material.Icons.Avalonia" Version="2.4.1" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="9.0.7" />
Expand All @@ -40,13 +45,12 @@
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
<PackageVersion Include="CsvHelper" Version="33.1.0" />
<!-- Test packages -->
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageVersion Include="System.Security.Cryptography.ProtectedData" Version="9.0.11" />
<PackageVersion Include="Velopack" Version="0.0.1298" />
<PackageVersion Include="xunit" Version="2.9.2" />
<PackageVersion Include="Octokit" Version="14.0.0" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
<PackageVersion Include="moq" Version="4.20.72" />
<PackageVersion Include="FluentAssertions" Version="6.12.1" />
<PackageVersion Include="SharpCompress" Version="0.48.0" />
Expand All @@ -56,4 +60,4 @@
<PackageVersion Include="HeyRed.ImageSharp.Heif" Version="2.1.3" />
<PackageVersion Include="LibHeif.Native" Version="1.15.1" />
</ItemGroup>
</Project>
</Project>
57 changes: 57 additions & 0 deletions GenHub/GenHub.Core/Constants/AssetPathConstants.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
namespace GenHub.Core.Constants;

/// <summary>
/// Constants for asset paths and resource URIs.
/// </summary>
public static class AssetPathConstants
{
/// <summary>
/// Legacy poster filename for China faction.
/// </summary>
public const string LegacyChinaPoster = "china-poster.png";

/// <summary>
/// Current cover filename for China faction.
/// </summary>
public const string ChinaCover = "china-cover.png";

/// <summary>
/// Legacy poster filename for USA faction.
/// </summary>
public const string LegacyUsaPoster = "usa-poster.png";

/// <summary>
/// Current cover filename for USA faction.
/// </summary>
public const string UsaCover = "usa-cover.png";

/// <summary>
/// Legacy poster filename for GLA faction.
/// </summary>
public const string LegacyGlaPoster = "gla-poster.png";

/// <summary>
/// Current cover filename for GLA faction.
/// </summary>
public const string GlaCover = "gla-cover.png";

/// <summary>
/// Legacy path for image assets.
/// </summary>
public const string LegacyImagesPath = "/Assets/Images/";

/// <summary>
/// Current path for cover assets.
/// </summary>
public const string CoversPath = "/Assets/Covers/";

/// <summary>
/// Avalonia resource URI scheme.
/// </summary>
public const string AvaresScheme = "avares://";

/// <summary>
/// Base Avalonia resource URI for GenHub application.
/// </summary>
public const string AvaresGenHubBase = "avares://GenHub/";
}
10 changes: 10 additions & 0 deletions GenHub/GenHub.Core/Constants/ErrorMessages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,14 @@ public static class ErrorMessages
/// Error message for failed to process ZIP.
/// </summary>
public const string FailedToProcessZip = "Failed to process ZIP: {0}";

/// <summary>
/// Error message when a profile requires a game installation.
/// </summary>
public const string ProfileRequiresGameInstallation = "• '{0}' requires a Game Installation";

/// <summary>
/// Error message when a profile requires a dependency.
/// </summary>
public const string ProfileRequiresDependency = "• '{0}' requires '{1}'";
}
4 changes: 2 additions & 2 deletions GenHub/GenHub.Core/Constants/IoConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ namespace GenHub.Core.Constants;
public static class IoConstants
{
/// <summary>
/// Default buffer size for file operations (4KB).
/// Default buffer size for file operations (64KB).
/// </summary>
public const int DefaultFileBufferSize = 4096;
public const int DefaultFileBufferSize = 65536;
Comment thread
undead2146 marked this conversation as resolved.

/// <summary>
/// How many times a path may be re-resolved while following symbolic links whose targets are
Expand Down
156 changes: 156 additions & 0 deletions GenHub/GenHub.Core/Constants/ModBuilderConstants.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
using System.Collections.Generic;

namespace GenHub.Core.Constants;

/// <summary>
/// Constants for mod builder directory names, file names, default configurations, and pipeline stages.
/// </summary>
public static class ModBuilderConstants
{
/// <summary>
/// Default project file extension.
/// </summary>
public const string ProjectFileExtension = ".mbproj";

/// <summary>
/// File pattern for project selection dialogs.
/// </summary>
public const string ProjectFilePattern = "*.mbproj";

/// <summary>
/// Install manifest file name stored in target game directory.
/// </summary>
public const string InstallManifestFileName = ".modbuilder_install.json";

/// <summary>
/// Backup file extension used during file installation.
/// </summary>
public const string BackupFileExtension = ".modbuilder_backup";

/// <summary>
/// Default directory name for build output.
/// </summary>
public const string DefaultBuildDir = ".Build";

/// <summary>
/// Default directory name for release output.
/// </summary>
public const string DefaultReleaseDir = ".Release";

/// <summary>
/// Subdirectory name for raw bundle items within build directory.
/// </summary>
public const string RawBundleItemsSubdir = "raw_bundle_items";

/// <summary>
/// Subdirectory name for compiled big bundles within build directory.
/// </summary>
public const string BundlesSubdir = "bundles";

/// <summary>
/// Subdirectory name for bundle packs within build directory.
/// </summary>
public const string BundlePacksSubdir = "bundle_packs";

/// <summary>
/// Directory name for edited game source files.
/// </summary>
public const string GameFilesEditedDir = "GameFilesEdited";

/// <summary>
/// Directory name for project configuration files.
/// </summary>
public const string ConfigDir = "Configs";

/// <summary>
/// File name for bundle items configuration.
/// </summary>
public const string BundleItemsConfigFileName = "ModBundleItems.json";

/// <summary>
/// File name for bundle packs configuration.
/// </summary>
public const string BundlePacksConfigFileName = "ModBundlePacks.json";

/// <summary>
/// Directory name for uncompressed release files.
/// </summary>
public const string ReleaseFilesDir = "ReleaseFiles";

/// <summary>
/// Directory name for project resources.
/// </summary>
public const string ResourcesDir = "Resources";

/// <summary>
/// Subdirectory name for file hash registry files within resources.
/// </summary>
public const string FileHashRegistrySubdir = "FileHashRegistry";

/// <summary>
/// Default streaming threshold size in bytes (10MB).
/// </summary>
public const long DefaultStreamingThresholdBytes = 10 * 1024 * 1024;

/// <summary>
/// Name of the primary crunch tool executable.
/// </summary>
public const string CrunchExecutable = "crunch_x64.exe";

/// <summary>
/// Secondary fallback name of the crunch tool executable.
/// </summary>
public const string CrunchFallbackExecutable = "crunch.exe";

/// <summary>
/// DXT1 texture format identifier (no alpha).
/// </summary>
public const string Dxt1Format = "DXT1";

/// <summary>
/// DXT5 texture format identifier (with alpha).
/// </summary>
public const string Dxt5Format = "DXT5";

/// <summary>
/// Candidate search paths for the crunch tool executable.
/// </summary>
public static readonly IReadOnlyList<string> CrunchExecutableCandidates =
[
@".tools\crunch_x64.exe",
@"tools\crunch_x64.exe",
@".tools\crunch.exe",
@"tools\crunch.exe",
];

/// <summary>
/// Supported texture format flags for crunch.
/// </summary>
public static readonly IReadOnlyList<string> CrunchTextureFormatFlags =
[
"-DXT1",
"-DXT2",
"-DXT3",
"-DXT4",
"-DXT5",
"-3DC",
"-DXN",
"-DXT5A",
"-DXT5_CCxY",
"-DXT5_xGxR",
"-DXT5_xGBR",
"-DXT5_AGBR",
"-DXT1A",
"-ETC1",
"-ETC2",
"-ETC2A",
"-ETC1S",
"-ETC2AS",
"-R8G8B8",
"-L8",
"-A8",
"-A8L8",
"-A8R8G8B8"
];
}

46 changes: 46 additions & 0 deletions GenHub/GenHub.Core/Constants/ToolConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,52 @@ public static class ReplayManager
public static readonly string[] Tags = ["replays", "file-management", "sharing"];
}

/// <summary>
/// Constants for the ModBuilder tool plugin.
/// </summary>
public static class ModBuilder
{
/// <summary>
/// The unique identifier for the ModBuilder tool.
/// </summary>
public const string Id = "genhub.tools.modbuilder";

/// <summary>
/// The display name for the ModBuilder tool.
/// </summary>
public const string Name = "ModBuilder";

/// <summary>
/// The version of the ModBuilder tool.
/// </summary>
public const string Version = "1.0.0";

/// <summary>
/// The author of the ModBuilder tool.
/// </summary>
public const string Author = "GenHub Team";

/// <summary>
/// The description of the ModBuilder tool.
/// </summary>
public const string Description = "Build automation tool for Command & Conquer: Generals mods. Compile, package, and deploy your mod projects.";

/// <summary>
/// The icon path for the ModBuilder tool.
/// </summary>
public const string IconPath = "🔨";

/// <summary>
/// Whether the ModBuilder tool is bundled with the application.
/// </summary>
public const bool IsBundled = true;

/// <summary>
/// The tags associated with the ModBuilder tool.
/// </summary>
public static readonly string[] Tags = ["modding", "build-automation", "development"];
}

/// <summary>
/// Mock path separator indicator for demo environments on Windows.
/// </summary>
Expand Down
Loading
Loading