feat: Implement SteamLauncher for game directory preparation and proxy launching #241
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Greptile Summary
This PR introduces a comprehensive Steam integration solution that enables full Steam features (overlay, playtime tracking) for modded game profiles while maintaining GenHub's workspace isolation model.
Key Changes:
SteamLauncherservice to deploy/cleanup proxy, backup original executables, and manage Steam environmentGenHub.ProxyLauncherproject that handles Steam environment injection and spawned process detectionHardLinkStrategyto prioritize files by content type (GameClient > GameInstallation) preventing modded clients from being overwrittenManifestGenerationServiceto use backup executables (.ghbak) as source during manifest generationSteamAppIdResolverhelper for dynamic AppID detection from Steam appmanifest filesArchitecture:
The proxy launcher approach replaces
generals.exewith the proxy, which then launches the workspace executable. This ensures Steam tracks the proxy process while the actual game runs from an isolated workspace. The proxy handles edge cases like launcher processes that spawn children and exit immediately, ensuring playtime tracking remains accurate.File Deduplication Improvement:
The refactored
HardLinkStrategynow prioritizes files by content type during workspace preparation, ensuring that modded game client executables (ContentType.GameClient) are never overwritten by base installation files (ContentType.GameInstallation). This fixes a critical bug where modded clients could be replaced by vanilla game files.Confidence Score: 4/5
SteamLauncher.csfor the file backup/restore logic andGameLauncher.csfor the cleanup timing during profile switchesImportant Files Changed
.ghbakfiles as source for manifests to ensure original game files are referenced instead of proxy launcherSequence Diagram
sequenceDiagram participant User participant GameLauncher participant SteamLauncher participant WorkspaceManager participant Steam participant ProxyLauncher participant GameProcess User->>GameLauncher: LaunchProfileAsync(profile, useSteamLaunch=true) Note over GameLauncher: Validate profile and resolve dependencies GameLauncher->>SteamLauncher: CleanupGameDirectoryAsync() Note over SteamLauncher: Restore generals.exe from .ghbak if exists SteamLauncher-->>GameLauncher: Cleanup complete GameLauncher->>WorkspaceManager: PrepareWorkspaceAsync() Note over WorkspaceManager: Create isolated workspace with<br/>prioritized file deduplication<br/>(GameClient > GameInstallation) WorkspaceManager-->>GameLauncher: Workspace ready GameLauncher->>SteamLauncher: PrepareForProfileAsync() Note over SteamLauncher: 1. Backup generals.exe → generals.exe.ghbak SteamLauncher->>SteamLauncher: Deploy GenHub.ProxyLauncher.exe as generals.exe SteamLauncher->>SteamLauncher: Create proxy_config.json with workspace path SteamLauncher->>SteamLauncher: Write steam_appid.txt files SteamLauncher->>SteamLauncher: Copy runtime dependencies (steam_api.dll, etc.) SteamLauncher->>SteamLauncher: Create workspace junction SteamLauncher-->>GameLauncher: Proxy deployed GameLauncher->>Steam: Launch via steam://rungameid/{appId} Steam->>ProxyLauncher: Start generals.exe (proxy) Note over ProxyLauncher: Read proxy_config.json<br/>Inject Steam environment variables ProxyLauncher->>GameProcess: Launch workspace executable Note over ProxyLauncher: Wait for process to exit alt Launcher exits quickly (spawned child) ProxyLauncher->>ProxyLauncher: Detect spawned process Note over ProxyLauncher: Continue waiting on child process<br/>to preserve Steam tracking end GameProcess-->>ProxyLauncher: Process exits ProxyLauncher-->>Steam: Exit (playtime recorded) Note over User: When switching profiles or closing User->>GameLauncher: Switch profile or cleanup GameLauncher->>SteamLauncher: CleanupGameDirectoryAsync() SteamLauncher->>SteamLauncher: Restore generals.exe from .ghbak SteamLauncher->>SteamLauncher: Remove proxy_config.json SteamLauncher->>SteamLauncher: Remove workspace junction SteamLauncher-->>GameLauncher: Original state restoredContext used:
dashboard- Custom context (source)dashboard- Use dedicated constants classes instead of hardcoding constants string, integers or variables in ser... (source)