mirror of
https://github.com/DorkSquadRR/DorkNet.git
synced 2026-10-25 15:08:47 -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"
|
/// "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_template": "dorknet-clientmod.json.template", // optional — rendered with {HOST}/{PHOTON_APPID}/{PHOTON_VOICE_APPID}
|
||||||
/// "config_dest": "MelonLoader/UserData/dorknet-clientmod.json", // optional — defaults shown
|
/// "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>
|
/// </code>
|
||||||
/// Config template placeholders: <c>{HOST}</c>, <c>{PHOTON_APPID}</c>,
|
/// Config template placeholders: <c>{HOST}</c>, <c>{PHOTON_APPID}</c>,
|
||||||
@@ -119,7 +126,68 @@ public sealed class ClientPatcher
|
|||||||
File.Copy(dllSrc, dllDest, overwrite: true);
|
File.Copy(dllSrc, dllDest, overwrite: true);
|
||||||
log.AppendLine($"[patch] installed plugin: {Path.GetFileName(manifest.PluginDll)} → {pluginDestDir}");
|
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))
|
if (!string.IsNullOrEmpty(manifest.ConfigTemplate))
|
||||||
{
|
{
|
||||||
var templatePath = Path.Combine(patcherDir, 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_template")] public string? ConfigTemplate { get; set; }
|
||||||
[JsonPropertyName("config_dest")] public string? ConfigDest { get; set; }
|
[JsonPropertyName("config_dest")] public string? ConfigDest { get; set; }
|
||||||
[JsonPropertyName("old_plugin_paths")] public string[]? OldPluginPaths { 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