diff --git a/BepInEx/config/net.rec.plugin.cfg b/BepInEx/config/net.rec.plugin.cfg deleted file mode 100644 index 6bbc466..0000000 --- a/BepInEx/config/net.rec.plugin.cfg +++ /dev/null @@ -1,91 +0,0 @@ -## Settings file was created by plugin RecNet Plugin v1.0.0 -## Plugin GUID: net.rec.plugin - -[Advanced] - -## Allows other fields below in the advanced section to be modified. -# Setting type: Boolean -# Default value: false -Enabled Advanced Settings = true - -## Custom Photon NameServer -# Setting type: String -# Default value: -Photon NameServer = photon.recflare.net - -## Custom Photon NameServer Port (if 0, it will be default) -# Setting type: Int32 -# Default value: 0 -Photon NameServer Port = 5058 - -## Show debug logs (HTTP tracing, etc. WARNING: will include sensitive information such as passwords and auth tokens in the logs, be careful when sharing them!) -# Setting type: Boolean -# Default value: false -Debug = false - -## Force CheckForDUIDMismatch to return TRUE (fakes the comparison only). Reproduces the hang path but does not corrupt any stored value. Leave false for normal play. -# Setting type: Boolean -# Default value: false -Simulate DUID Mismatch = false - -## Force CheckForDUIDMismatch to return FALSE (the workaround fix, ON by default): the client never migrates and never takes the Create Account hang path. No-op on healthy machines (the real check returns false anyway); on mismatched machines it skips the hang. Set false only to observe the real mismatch behavior for debugging. -# Setting type: Boolean -# Default value: true -Suppress DUID Mismatch = true - -## ONE-SHOT TEST: on next launch, write a truncated device id into the DUID pref via the game's own WriteDUIDs, producing a genuinely corrupt STORED value (real current id) — exactly the friend's condition. After it logs '[CORRUPT] wrote', set this back to false and relaunch to drive the real mismatch path. Use 'Restore Stored DUID' to undo. -# Setting type: Boolean -# Default value: false -Corrupt Stored DUID = false - -## ONE-SHOT UNDO: on next launch, call WriteDUIDs with the real device id, overwriting any corrupt stored value with a good one. Set back to false after it logs '[CORRUPT] restored'. -# Setting type: Boolean -# Default value: false -Restore Stored DUID = false - -## Replace the body of the PlayerReporting/v1/deviceId response with this text, to test what shape the client will accept. Empty = leave the server's response alone. -# Setting type: String -# Default value: -DeviceId Response Override = - -## HTTP status to force on the PlayerReporting/v1/deviceId response. Only applies when the override body is set. -# Setting type: Int32 -# Default value: 200 -DeviceId Response Status = 200 - -[Photon] - -## Photon Realtime App ID -# Setting type: String -# Default value: -App Id Realtime = rf-8f322bdb - -## Photon Voice App ID -# Setting type: String -# Default value: -App Id Voice = rf-6b4682e1 - -## Photon Chat App ID -# Setting type: String -# Default value: -App Id Chat = rf-55fae86e - -[Server] - -## Host for the RecNet NameServer. -# Setting type: String -# Default value: https://ns.rec.net -RecNet NameServer Host = https://ns.recflare.net - -[Signing] - -## Force RSA signature verification to succeed (ON by default), so the client stops checking that images are signed with Rec Room's private key. This is what lets a self-hosted server serve its own images without the baked-in modulus matching. Set false only if you actually want signed images, in which case use 'Signing Modulus Override' instead. NOTE: this forces ALL mscorlib RSA verification to pass, not just image signatures. -# Setting type: Boolean -# Default value: true -Disable Signature Verification = true - -## Optional alternative to disabling verification: your own RSA public modulus, base64, RAW 2048-bit (256 bytes decoded) — NOT a PEM/DER key. When set, it is substituted for the modulus baked into global-metadata.dat and real verification still runs, so images stay signed with your keypair. Redundant while 'Disable Signature Verification' is true. Empty = leave the stock modulus alone. -# Setting type: String -# Default value: -Signing Modulus Override = - diff --git a/README.md b/README.md index 8c4ace0..ff98e0f 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,13 @@ Automatic download and setup of a game client to play [RecFlare](https://github.com/djdevin/recflare). -[BepInEx](https://github.com/BepInEx/BepInEx) and the [RecNet Plugin](https://github.com/djdevin/recnet-plugin) are installed as part of the setup. +The [Rec Room 2025 patch](https://github.com/recflare/patch-2025) is installed as part of the setup and configured to point at the RecFlare servers. ## Download/update and play ### Easy way: installer -Download and run `RecFlareSetup.exe` from the [releases page](https://github.com/djdevin/recflare-client/releases). The wizard asks whether you have Rec Room in your Steam library: if you do, it downloads the game client from Steam (DepotDownloader, signing in with your username or a Steam mobile app QR code); if not, it downloads the game files from a mirror instead. It then installs BepInEx and the RecNet plugin, and creates Start menu/desktop shortcuts for desktop and VR mode. +Download and run `RecFlareSetup.exe` from the [releases page](https://github.com/djdevin/recflare-client/releases). The wizard asks whether you have Rec Room in your Steam library: if you do, it downloads the game client from Steam (DepotDownloader, signing in with your username or a Steam mobile app QR code); if not, it downloads the game files from a mirror instead. It then installs the 2025 patch, points `2025patch.ini` at RecFlare, and creates Start menu/desktop shortcuts for desktop and VR mode. If Windows SmartScreen shows "Windows protected your PC", click **More info** and then **Run anyway** (the installer is unsigned). @@ -16,10 +16,10 @@ To build the installer yourself, compile `RecFlareSetup.iss` with [Inno Setup](h ### Manual way: scripts -1. Check out this repository or extract the ZIP: https://github.com/djdevin/recflare-client/archive/refs/heads/master.zip -2. Run `download.bat`. The script will ask whether you have Rec Room in your Steam library: if you do, it downloads the game client from Steam (DepotDownloader); if not, it syncs the game files from a mirror instead. Either way it then applies patches and configuration. +1. Check out this repository or extract the ZIP: https://github.com/djdevin/recflare-client/archive/refs/heads/2025.zip +2. Run `download.bat`. The script will ask whether you have Rec Room in your Steam library: if you do, it downloads the game client from Steam (DepotDownloader); if not, it syncs the game files from a mirror instead. Either way it then installs the 2025 patch and writes `2025patch.ini` pointing at RecFlare. 3. Run `RecRoomScreen.bat` or `RecRoomVR.bat` ## Custom server -Fork this project and change `/BepInEx/config/net.rec.plugin.cfg` to your own instance. +Fork this project and change the `ApiHost` and `PhotonHost` values in `download.bat` (the `powershell` line) and `RecFlareSetup.iss` (the `ApiHost`/`PhotonHost` constants) to your own instance. You can also edit `2025patch.ini` in the game folder directly after installing. diff --git a/RecFlareSetup.iss b/RecFlareSetup.iss index e30505e..f2bf92f 100644 --- a/RecFlareSetup.iss +++ b/RecFlareSetup.iss @@ -6,7 +6,7 @@ [Setup] AppId={{8E1D2A7B-6C43-4F0A-9B7E-3D5F80C21A96} AppName=RecFlare -AppVersion=20230414 +AppVersion=2025.1 AppPublisher=RecFlare project AppSupportURL=https://github.com/djdevin/recflare DefaultDirName={sd}\Games\RecFlare @@ -28,10 +28,6 @@ Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{ Source: "icon.ico"; DestDir: "{app}"; Flags: ignoreversion Source: "RecRoomScreen.bat"; DestDir: "{app}"; Flags: ignoreversion Source: "RecRoomVR.bat"; DestDir: "{app}"; Flags: ignoreversion -; Points the client at the RecFlare server. Always overwrite so reinstalls pick -; up server changes; to use your own instance, fork and edit this file, then -; rebuild the installer (see README "Custom server"). -Source: "BepInEx\config\net.rec.plugin.cfg"; DestDir: "{app}\BepInEx\config"; Flags: ignoreversion [Icons] Name: "{autoprograms}\RecFlare (Desktop mode)"; Filename: "{app}\recroom.exe"; Parameters: "+forcemode:screen"; WorkingDir: "{app}"; IconFilename: "{app}\icon.ico" @@ -46,11 +42,16 @@ Type: filesandordirs; Name: "{app}" [Code] const - ClientMD5 = '4c4a94624eba99028bb36445ccb03253'; - ClientURL = 'https://s3.g.megas4.com/2koayuyiwxv4groxzwdbbxg43cwustavrkvfb/recflare/client.zip'; + PatchVersion = 'v0.0.5'; + DepotManifest = '1151455856673601091'; + ClientMD5 = '6820e89bff41906ded7f5c066027f1d6'; + ClientURL = 'https://s3.g.megas4.com/2koayuyiwxv4groxzwdbbxg43cwustavrkvfb/recflare/2025/client.zip'; DepotDownloaderURL = 'https://github.com/SteamRE/DepotDownloader/releases/download/DepotDownloader_3.4.0/DepotDownloader-windows-x64.zip'; - BepInExURL = 'https://github.com/BepInEx/BepInEx/releases/download/v6.0.0-pre.2/BepInEx-Unity.IL2CPP-win-x64-6.0.0-pre.2.zip'; - PluginURL = 'https://github.com/djdevin/recnet-plugin/releases/download/20230414.2/RecNetPlugin.dll'; + PatchURL = 'https://github.com/recflare/patch-2025/releases/download/' + PatchVersion + '/2025Patch-' + PatchVersion + '-x64.zip'; + { Points the client at the RecFlare server; to use your own instance, fork and + change these, then rebuild the installer (see README "Custom server"). } + ApiHost = 'ns.recflare.net'; + PhotonHost = 'photon.recflare.net'; var SourcePage: TInputOptionWizardPage; @@ -113,8 +114,7 @@ begin else DownloadPage.Add(ClientURL, 'client.zip', ''); end; - DownloadPage.Add(BepInExURL, 'BepInEx.zip', ''); - DownloadPage.Add(PluginURL, 'RecNetPlugin.dll', ''); + DownloadPage.Add(PatchURL, '2025Patch.zip', ''); DownloadPage.Show; try try @@ -164,7 +164,7 @@ begin ErrorMsg := 'Could not extract DepotDownloader.'; Exit; end; - Args := '-app 471710 -depot 471711 -manifest 6426603215211043630 -remember-password' + + Args := '-app 471710 -depot 471711 -manifest ' + DepotManifest + ' -remember-password' + ' -dir "' + ExpandConstant('{app}') + '"'; if Trim(SteamPage.Values[0]) <> '' then Args := Args + ' -username "' + Trim(SteamPage.Values[0]) + '"' @@ -181,6 +181,37 @@ begin Result := True; end; +{ Sets Key=Value in the ini shipped by the patch, replacing an existing line + for that key or appending one, so other settings in the file are kept. } +procedure SetIniKey(var Lines: TArrayOfString; const Key, Value: String); +var + I: Integer; + L: String; +begin + for I := 0 to GetArrayLength(Lines) - 1 do begin + L := Trim(Lines[I]); + if (Pos('=', L) > 0) and SameText(Trim(Copy(L, 1, Pos('=', L) - 1)), Key) then begin + Lines[I] := Key + '=' + Value; + Exit; + end; + end; + SetArrayLength(Lines, GetArrayLength(Lines) + 1); + Lines[GetArrayLength(Lines) - 1] := Key + '=' + Value; +end; + +function WritePatchIni(const IniPath: String): Boolean; +var + Lines: TArrayOfString; +begin + if not FileExists(IniPath) or not LoadStringsFromFile(IniPath, Lines) then begin + SetArrayLength(Lines, 1); + Lines[0] := '[config]'; + end; + SetIniKey(Lines, 'ApiHost', ApiHost); + SetIniKey(Lines, 'PhotonHost', PhotonHost); + Result := SaveStringsToFile(IniPath, Lines, False); +end; + function PrepareToInstall(var NeedsRestart: Boolean): String; var ClientZip: String; @@ -206,21 +237,19 @@ begin end; end; - SetPreparingStatus('Installing BepInEx...'); - if not ExtractZip(ExpandConstant('{tmp}\BepInEx.zip'), ExpandConstant('{app}')) then begin - Result := 'Could not extract BepInEx.'; - Exit; - end; - if not SaveStringToFile(ExpandConstant('{app}\steam_appid.txt'), '480', False) then begin Result := 'Could not write steam_appid.txt.'; Exit; end; - if not ForceDirectories(ExpandConstant('{app}\BepInEx\plugins')) or - not FileCopy(ExpandConstant('{tmp}\RecNetPlugin.dll'), - ExpandConstant('{app}\BepInEx\plugins\RecNetPlugin.dll'), False) then begin - Result := 'Could not install RecNetPlugin.dll.'; + SetPreparingStatus('Installing the Rec Room 2025 patch...'); + if not ExtractZip(ExpandConstant('{tmp}\2025Patch.zip'), ExpandConstant('{app}')) then begin + Result := 'Could not extract the Rec Room 2025 patch.'; + Exit; + end; + + if not WritePatchIni(ExpandConstant('{app}\2025patch.ini')) then begin + Result := 'Could not write 2025patch.ini.'; Exit; end; end;