using System.Diagnostics; using System.IO; namespace DorkNet.Launcher.Backend; /// Launches the user's already-patched Rec Room install /// directly. Never goes through Steam — DorkNet users may not own /// the game on Steam. /// /// 2020.03 vs 2020.12 build layout: /// /// 2020.03 (pre-EAC): single binary Recroom_Release.exe /// alongside Recroom_Release_Data/. Run that directly. /// 2020.12+ (EAC): the real Unity binary is RecRoom.exe /// with its data in RecRoom_Data/; Recroom_Release.exe /// is the Easy Anti-Cheat launcher wrapper that Steam invokes. Run /// RecRoom.exe directly to skip EAC entirely — EAC never /// loads into the game process, no binary patching required (this is /// the same approach tools/remove-eac.ps1 documents on the /// per-version branch). /// /// Detection: an EasyAntiCheat/ folder next to the binaries /// flags the EAC layout. Falls back to whichever exe exists if the /// heuristic is ambiguous. public static class RecRoomLauncher { /// The picked install path is the *_Data folder; /// the executable lives at its parent. Returns true if /// succeeded. /// passes Rec Room's /// +forcemode:screen arg so the game opens in 2D desktop /// mode instead of trying to bind a headset. public static bool TryLaunch(string recRoomDataPath, bool screenMode, out string error) { error = ""; if (string.IsNullOrEmpty(recRoomDataPath)) { error = "No Rec Room install picked."; return false; } var parent = Path.GetDirectoryName(recRoomDataPath.TrimEnd(Path.DirectorySeparatorChar)); if (string.IsNullOrEmpty(parent)) { error = $"Couldn't resolve the parent directory of '{recRoomDataPath}'."; return false; } var exe = PickExecutable(parent); if (exe is null) { error = $"Neither RecRoom.exe nor Recroom_Release.exe found next to '{recRoomDataPath}'. " + "Pick the *_Data folder that sits beside the game binary."; return false; } try { Process.Start(new ProcessStartInfo { FileName = exe, WorkingDirectory = parent, UseShellExecute = true, Arguments = screenMode ? "+forcemode:screen" : "", }); return true; } catch (Exception ex) { error = ex.Message; return false; } } /// Pick the right game exe for the install. Prefer /// RecRoom.exe on EAC builds (so we skip the EAC launcher /// wrapper). Fall back to whichever single binary exists when only /// one is present. private static string? PickExecutable(string parent) { var recRoomExe = Path.Combine(parent, "RecRoom.exe"); var legacyExe = Path.Combine(parent, "Recroom_Release.exe"); var hasEac = Directory.Exists(Path.Combine(parent, "EasyAntiCheat")); // EAC build: RecRoom.exe is the actual game; Recroom_Release.exe // is the EAC launcher wrapper. Use the former — it never loads // EAC into the process. if (hasEac && File.Exists(recRoomExe)) return recRoomExe; // Only-one-present cases. if (File.Exists(legacyExe)) return legacyExe; if (File.Exists(recRoomExe)) return recRoomExe; return null; } }