mirror of
https://github.com/DorkSquadRR/DorkNet.git
synced 2026-10-25 23:18:44 -07:00
launcher: ClientPatcher handles steam_stub manifest block
Per-version patcher zips now ship a Goldberg steam_api64.dll + steam_appid.txt alongside the existing MelonLoader stuff. The manifest's new steam_stub block describes where to install them: - api_dll / api_dest: stub DLL location and target path under Rec Room root (typically Recroom_Release_Data/Plugins/...) - api_backup_suffix: the original Valve DLL gets renamed to <dest> + suffix on first install; re-runs detect the existing backup and leave it alone so the real DLL is preserved - appid_file / appid_value + appid_dest: writes a steam_appid.txt next to the exe so the stub knows what game ID to claim Block is optional — manifests without steam_stub patch nothing extra, preserving back-compat with pre-stub patcher zips.
This commit is contained in:
@@ -24,7 +24,14 @@ namespace DorkNet.Launcher.Backend;
|
||||
/// "plugin_dest": "MelonLoader/Mods", // optional — defaults to "MelonLoader/Mods"
|
||||
/// "config_template": "dorknet-clientmod.json.template", // optional — rendered with {HOST}/{PHOTON_APPID}/{PHOTON_VOICE_APPID}
|
||||
/// "config_dest": "MelonLoader/UserData/dorknet-clientmod.json", // optional — defaults shown
|
||||
/// "old_plugin_paths": ["BepInEx/plugins/DorkNet.ClientPatch.dll"] // optional — deleted before install
|
||||
/// "old_plugin_paths": ["BepInEx/plugins/DorkNet.ClientPatch.dll"], // optional — deleted before install
|
||||
/// "steam_stub": { // optional — replaces Valve steam_api64.dll
|
||||
/// "api_dll": "steam_api64.dll", // file in zip
|
||||
/// "api_dest": "Recroom_Release_Data/Plugins/steam_api64.dll",
|
||||
/// "api_backup_suffix": ".steam-original", // original is renamed to dll + suffix
|
||||
/// "appid_file": "steam_appid.txt", // file in zip (or omit if appid_value set)
|
||||
/// "appid_dest": "steam_appid.txt" // relative to Rec Room root
|
||||
/// }
|
||||
/// }
|
||||
/// </code>
|
||||
/// Config template placeholders: <c>{HOST}</c>, <c>{PHOTON_APPID}</c>,
|
||||
@@ -119,7 +126,68 @@ public sealed class ClientPatcher
|
||||
File.Copy(dllSrc, dllDest, overwrite: true);
|
||||
log.AppendLine($"[patch] installed plugin: {Path.GetFileName(manifest.PluginDll)} → {pluginDestDir}");
|
||||
|
||||
// 4. Render the config template.
|
||||
// 4. Replace Valve's steam_api64.dll with the bundled stub
|
||||
// (Goldberg emulator) so the unwrapped exe runs without
|
||||
// Steam loaded. Backs up the original next to the dest
|
||||
// DLL with the configured suffix so users can revert.
|
||||
if (manifest.SteamStub is { } stub && !string.IsNullOrEmpty(stub.ApiDll))
|
||||
{
|
||||
var stubSrc = Path.Combine(patcherDir, stub.ApiDll);
|
||||
if (!File.Exists(stubSrc))
|
||||
return PatchResult.Failure($"steam_stub.api_dll listed but missing on disk: {stubSrc}");
|
||||
if (string.IsNullOrEmpty(stub.ApiDest))
|
||||
return PatchResult.Failure("steam_stub.api_dest is required when steam_stub is set.");
|
||||
|
||||
var dllTarget = Path.Combine(recRoomRoot, stub.ApiDest.Replace('/', Path.DirectorySeparatorChar));
|
||||
var dllTargetDir = Path.GetDirectoryName(dllTarget);
|
||||
if (!string.IsNullOrEmpty(dllTargetDir)) Directory.CreateDirectory(dllTargetDir);
|
||||
|
||||
// Back up the original once. If a .steam-original already
|
||||
// exists we assume a previous patch ran — leave it alone
|
||||
// rather than clobber the actual Valve DLL with our stub.
|
||||
var backupSuffix = string.IsNullOrEmpty(stub.ApiBackupSuffix)
|
||||
? ".steam-original" : stub.ApiBackupSuffix;
|
||||
var backupPath = dllTarget + backupSuffix;
|
||||
if (File.Exists(dllTarget) && !File.Exists(backupPath))
|
||||
{
|
||||
File.Move(dllTarget, backupPath);
|
||||
log.AppendLine($"[patch] backed up Valve steam_api64.dll → {Path.GetFileName(backupPath)}");
|
||||
}
|
||||
File.Copy(stubSrc, dllTarget, overwrite: true);
|
||||
log.AppendLine($"[patch] installed Steam stub: {Path.GetFileName(dllTarget)}");
|
||||
|
||||
// appid_dest is required; appid source can be a literal
|
||||
// value or a file in the zip — file wins if both set.
|
||||
if (!string.IsNullOrEmpty(stub.AppidDest))
|
||||
{
|
||||
var appidTarget = Path.Combine(recRoomRoot,
|
||||
stub.AppidDest.Replace('/', Path.DirectorySeparatorChar));
|
||||
var appidTargetDir = Path.GetDirectoryName(appidTarget);
|
||||
if (!string.IsNullOrEmpty(appidTargetDir)) Directory.CreateDirectory(appidTargetDir);
|
||||
|
||||
string appidContent;
|
||||
if (!string.IsNullOrEmpty(stub.AppidFile))
|
||||
{
|
||||
var appidSrc = Path.Combine(patcherDir, stub.AppidFile);
|
||||
if (!File.Exists(appidSrc))
|
||||
return PatchResult.Failure($"steam_stub.appid_file listed but missing on disk: {appidSrc}");
|
||||
appidContent = File.ReadAllText(appidSrc).Trim();
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(stub.AppidValue))
|
||||
{
|
||||
appidContent = stub.AppidValue.Trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
return PatchResult.Failure(
|
||||
"steam_stub.appid_dest set without appid_file or appid_value to source the value from.");
|
||||
}
|
||||
File.WriteAllText(appidTarget, appidContent);
|
||||
log.AppendLine($"[patch] wrote {Path.GetFileName(appidTarget)} ({appidContent})");
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Render the config template.
|
||||
if (!string.IsNullOrEmpty(manifest.ConfigTemplate))
|
||||
{
|
||||
var templatePath = Path.Combine(patcherDir, manifest.ConfigTemplate);
|
||||
@@ -191,6 +259,17 @@ public sealed class ClientPatcher
|
||||
[JsonPropertyName("config_template")] public string? ConfigTemplate { get; set; }
|
||||
[JsonPropertyName("config_dest")] public string? ConfigDest { get; set; }
|
||||
[JsonPropertyName("old_plugin_paths")] public string[]? OldPluginPaths { get; set; }
|
||||
[JsonPropertyName("steam_stub")] public SteamStubBlock? SteamStub { get; set; }
|
||||
}
|
||||
|
||||
private sealed class SteamStubBlock
|
||||
{
|
||||
[JsonPropertyName("api_dll")] public string? ApiDll { get; set; }
|
||||
[JsonPropertyName("api_dest")] public string? ApiDest { get; set; }
|
||||
[JsonPropertyName("api_backup_suffix")] public string? ApiBackupSuffix { get; set; }
|
||||
[JsonPropertyName("appid_file")] public string? AppidFile { get; set; }
|
||||
[JsonPropertyName("appid_value")] public string? AppidValue { get; set; }
|
||||
[JsonPropertyName("appid_dest")] public string? AppidDest { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user