From a5ae5da344873b281a897b1db7ba72b3911e8389 Mon Sep 17 00:00:00 2001
From: Alexa <53471801+Alexa-RR@users.noreply.github.com>
Date: Wed, 27 May 2026 01:02:25 +0300
Subject: [PATCH] launcher: pass PhotonCloudRegion to patcher template
DorkNet.ClientMod's config reads PhotonCloudRegion alongside the
AppIds, and the joining client needs the host's region to connect
to the right Photon cloud. Adds {PHOTON_REGION} to the substitution
map and threads region through ClientPatcher.ApplyAsync from both
host (AppState.PhotonRegion) and join (JoinPayload.PhotonRegion)
flows.
---
launcher/Backend/ClientPatcher.cs | 10 +++++++---
launcher/MainWindow.xaml.cs | 4 ++--
launcher/RELEASES.md | 1 +
3 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/launcher/Backend/ClientPatcher.cs b/launcher/Backend/ClientPatcher.cs
index c4285f0..830c166 100644
--- a/launcher/Backend/ClientPatcher.cs
+++ b/launcher/Backend/ClientPatcher.cs
@@ -28,7 +28,8 @@ namespace DorkNet.Launcher.Backend;
/// }
///
/// Config template placeholders: {HOST}, {PHOTON_APPID},
-/// {PHOTON_VOICE_APPID}. Anything else passes through unchanged.
+/// {PHOTON_VOICE_APPID}, {PHOTON_REGION}. Anything else
+/// passes through unchanged.
public sealed class ClientPatcher
{
private const string DefaultPluginDest = "MelonLoader/Mods";
@@ -39,11 +40,12 @@ public sealed class ClientPatcher
string recRoomDataPath,
string photonAppId,
string photonVoiceAppId,
+ string photonRegion,
string apexHost,
CancellationToken ct = default)
{
return Task.Run(() => ApplyCore(patcherDir, recRoomDataPath,
- photonAppId, photonVoiceAppId, apexHost), ct);
+ photonAppId, photonVoiceAppId, photonRegion, apexHost), ct);
}
private PatchResult ApplyCore(
@@ -51,6 +53,7 @@ public sealed class ClientPatcher
string recRoomDataPath,
string photonAppId,
string photonVoiceAppId,
+ string photonRegion,
string apexHost)
{
var log = new System.Text.StringBuilder();
@@ -133,7 +136,8 @@ public sealed class ClientPatcher
.Replace("{HOST}", apexHost ?? "")
.Replace("{PHOTON_APPID}", photonAppId ?? "")
.Replace("{PHOTON_VOICE_APPID}",
- string.IsNullOrEmpty(photonVoiceAppId) ? photonAppId ?? "" : photonVoiceAppId);
+ string.IsNullOrEmpty(photonVoiceAppId) ? photonAppId ?? "" : photonVoiceAppId)
+ .Replace("{PHOTON_REGION}", string.IsNullOrEmpty(photonRegion) ? "us" : photonRegion);
File.WriteAllText(configDest, rendered);
log.AppendLine($"[patch] wrote config: {Path.GetFileName(configDest)}");
}
diff --git a/launcher/MainWindow.xaml.cs b/launcher/MainWindow.xaml.cs
index dde5d1c..2d72a47 100644
--- a/launcher/MainWindow.xaml.cs
+++ b/launcher/MainWindow.xaml.cs
@@ -224,7 +224,7 @@ public partial class MainWindow : Window
HostStatusText.Text = "Patching your Rec Room client…";
var patch = await _patcher.ApplyAsync(
patcherDir, _state.RecRoomPath!,
- _state.PhotonAppId, _state.PhotonVoiceAppId, _hostApex);
+ _state.PhotonAppId, _state.PhotonVoiceAppId, _state.PhotonRegion, _hostApex);
if (!patch.Ok) { ShowError("Patcher failed: " + Truncate(patch.Log, 500)); return; }
var code = JoinCode.Encode(new JoinPayload
@@ -324,7 +324,7 @@ public partial class MainWindow : Window
JoinStatusText.Text = "Patching your Rec Room client…";
var patch = await _patcher.ApplyAsync(
patcherDir, _state.RecRoomPath!,
- payload.PhotonAppId, payload.PhotonVoiceAppId, payload.Host);
+ payload.PhotonAppId, payload.PhotonVoiceAppId, payload.PhotonRegion, payload.Host);
if (!patch.Ok) { ShowError("Patcher failed: " + Truncate(patch.Log, 500)); return; }
JoinStatusText.Text = $"Patched and ready. Connecting to {payload.Host}. " +
diff --git a/launcher/RELEASES.md b/launcher/RELEASES.md
index c858354..d8913a9 100644
--- a/launcher/RELEASES.md
+++ b/launcher/RELEASES.md
@@ -95,6 +95,7 @@ Defaults:
| `{HOST}` | Host's tunnel hostname (or join code's `host` field) |
| `{PHOTON_APPID}` | Host's Photon Realtime AppId |
| `{PHOTON_VOICE_APPID}` | Host's Photon Voice AppId (falls back to Realtime if empty) |
+| `{PHOTON_REGION}` | Photon Cloud region (us/eu/asia/jp/sa/kr/in/au); defaults to `us` |
Example template: