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;
}
}