Refactor configuration endpoints and update client installation scripts

- Removed Photon configuration fields from dorknet-clientmod.json.template.
- Added new backtrace and Azure Speech configuration endpoints in ConfigController.
- Updated response format for IsCreationEnabled and IsRenderingEnabled endpoints in CustomAvatarItemsController.
- Enhanced InfluencerPartnerProgramController to include additional player properties.
- Implemented RoomKeepsakes endpoint in KeepsakesController to retrieve keepsakes by room ID.
- Modified ReportsController to standardize response for Hile reporting.
- Added PlayerDataForMe and RoomsRequiring endpoints in RoomsController for enhanced player data retrieval.
- Introduced new dorm matchmaking methods in MatchController for player session management.
- Updated MatchPlayerController to handle exclusive login functionality.
- Revised install scripts to reflect changes in Photon AppId handling and patching process.
- Added new patch-client.ps1 script for applying static byte patches to the Rec Room client.
This commit is contained in:
Alexa
2026-06-23 10:42:25 +03:00
parent 142f52569a
commit 4034449a6d
15 changed files with 823 additions and 641 deletions
+264
View File
@@ -0,0 +1,264 @@
<#
.SYNOPSIS
Applies static DorkNet byte patches to an extracted Rec Room client.
.DESCRIPTION
RecRoomPath must point at the Unity data folder, usually
Recroom_Release_Data or RecRoom_Data. The script resolves the install root
from that folder, then patches the hardcoded Photon Realtime and Voice
AppIds wherever the build stores them: GameAssembly.dll,
il2cpp_data\Metadata\global-metadata.dat, and resources.assets.
The replacement values must be GUID strings, so the byte length stays
unchanged and the patch can be done in place.
.PARAMETER RecRoomPath
Path to Recroom_Release_Data.
.PARAMETER PhotonAppId
Photon Cloud Realtime AppId.
.PARAMETER PhotonVoiceAppId
Photon Cloud Voice AppId. Defaults to PhotonAppId.
.PARAMETER DisableSignatureChecks
Deprecated compatibility switch. File-check bypass is handled by
DorkNet.ClientMod so the embedded build/signature identifiers stay valid.
.PARAMETER Revert
Restore patched files from backups created by this script.
.PARAMETER DryRun
Show what would be patched without writing files.
#>
[CmdletBinding(DefaultParameterSetName = 'Patch')]
param(
[Parameter(Mandatory = $true)]
[string]$RecRoomPath,
[Parameter(Mandatory = $true, ParameterSetName = 'Patch')]
[ValidatePattern('(?i)^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$')]
[string]$PhotonAppId,
[Parameter(ParameterSetName = 'Patch')]
[ValidatePattern('(?i)^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$')]
[string]$PhotonVoiceAppId,
[Parameter(ParameterSetName = 'Patch')]
[switch]$DisableSignatureChecks,
[Parameter(ParameterSetName = 'Patch')]
[string]$ImageSigningPublicKeyPath,
[Parameter(ParameterSetName = 'Patch')]
[string]$ServerIp,
[Parameter(ParameterSetName = 'Patch')]
[string]$CertPath,
[Parameter(Mandatory = $true, ParameterSetName = 'Revert')]
[switch]$Revert,
[switch]$DryRun
)
$ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest
$OfficialPhotonAppId = '9372aa8d-d3f4-44a0-986d-419e145a2b83'
$OfficialPhotonVoiceAppId = 'e93ae440-f238-4b6c-848f-1df89faf14f5'
function Write-Step($msg) { Write-Host ('> ' + $msg) -ForegroundColor Cyan }
function Write-OK($msg) { Write-Host ('OK: ' + $msg) -ForegroundColor Green }
function Write-Warn($msg) { Write-Host ('WARN: ' + $msg) -ForegroundColor Yellow }
function Find-SequenceOffsets {
param(
[Parameter(Mandatory = $true)][byte[]]$Haystack,
[Parameter(Mandatory = $true)][byte[]]$Needle
)
$offsets = New-Object System.Collections.Generic.List[int]
if ($Needle.Length -eq 0 -or $Haystack.Length -lt $Needle.Length) {
return $offsets
}
$last = $Haystack.Length - $Needle.Length
for ($i = 0; $i -le $last; $i++) {
if ($Haystack[$i] -ne $Needle[0]) { continue }
$matched = $true
for ($j = 1; $j -lt $Needle.Length; $j++) {
if ($Haystack[$i + $j] -ne $Needle[$j]) {
$matched = $false
break
}
}
if ($matched) { $offsets.Add($i) }
}
return $offsets
}
function Format-HexOffset([int]$Offset) {
return '0x{0:X}' -f $Offset
}
function Apply-AsciiStringPatch {
param(
[Parameter(Mandatory = $true)][byte[]]$Bytes,
[Parameter(Mandatory = $true)][string]$Original,
[Parameter(Mandatory = $true)][string]$Replacement,
[Parameter(Mandatory = $true)][string]$Label
)
$enc = [System.Text.Encoding]::ASCII
$originalBytes = $enc.GetBytes($Original)
$replacementBytes = $enc.GetBytes($Replacement)
if ($originalBytes.Length -ne $replacementBytes.Length) {
throw "$Label replacement length differs from original. Expected $($originalBytes.Length) bytes, got $($replacementBytes.Length)."
}
$offsets = @(Find-SequenceOffsets -Haystack $Bytes -Needle $originalBytes)
if ($offsets.Count -eq 0) {
$replacementOffsets = @(Find-SequenceOffsets -Haystack $Bytes -Needle $replacementBytes)
if ($replacementOffsets.Count -gt 0) {
Write-OK "$Label already patched at $((@($replacementOffsets) | ForEach-Object { Format-HexOffset $_ }) -join ', ')"
return $false
}
Write-Warn "$Label official AppId '$Original' was not found, and replacement '$Replacement' is not already present."
return $null
}
foreach ($offset in $offsets) {
[System.Array]::Copy($replacementBytes, 0, $Bytes, $offset, $replacementBytes.Length)
}
Write-OK "$Label patched at $((@($offsets) | ForEach-Object { Format-HexOffset $_ }) -join ', ')"
return $true
}
function Get-ClientPaths {
param([Parameter(Mandatory = $true)][string]$Path)
$resolved = Resolve-Path -LiteralPath $Path -ErrorAction SilentlyContinue
if (-not $resolved) {
throw "RecRoomPath '$Path' does not exist."
}
$dataPath = $resolved.Path
if (-not (Test-Path -LiteralPath (Join-Path $dataPath 'resources.assets') -PathType Leaf)) {
throw "resources.assets not found in '$dataPath'. Point RecRoomPath at the Recroom_Release_Data folder."
}
$root = Split-Path -Parent $dataPath
$gameAssembly = Join-Path $root 'GameAssembly.dll'
if (-not (Test-Path -LiteralPath $gameAssembly -PathType Leaf)) {
throw "GameAssembly.dll not found next to '$dataPath'."
}
[pscustomobject]@{
DataPath = $dataPath
Root = $root
GameAssembly = $gameAssembly
Resources = Join-Path $dataPath 'resources.assets'
GlobalMetadata = Join-Path $dataPath 'il2cpp_data\Metadata\global-metadata.dat'
}
}
$paths = Get-ClientPaths -Path $RecRoomPath
$patchTargets = @(
[pscustomobject]@{ Label = 'GameAssembly.dll'; Path = $paths.GameAssembly },
[pscustomobject]@{ Label = 'global-metadata.dat'; Path = $paths.GlobalMetadata },
[pscustomobject]@{ Label = 'resources.assets'; Path = $paths.Resources }
) | Where-Object { Test-Path -LiteralPath $_.Path -PathType Leaf }
if ($Revert) {
$restored = 0
foreach ($target in $patchTargets) {
$backup = "$($target.Path).dorknet-appid-backup"
if (-not (Test-Path -LiteralPath $backup -PathType Leaf)) {
continue
}
Write-Step "Reverting $($target.Label) from $backup"
if ($DryRun) {
Write-Host "DRY RUN: would restore $($target.Path) from $backup"
$restored++
continue
}
Copy-Item -LiteralPath $backup -Destination $target.Path -Force
Write-OK "$($target.Label) restored."
$restored++
}
if ($restored -eq 0) {
throw "No DorkNet AppId backups found under $($paths.Root)."
}
exit 0
}
if (-not $PhotonVoiceAppId) {
$PhotonVoiceAppId = $PhotonAppId
}
if ($ImageSigningPublicKeyPath) {
Write-Warn 'ImageSigningPublicKeyPath is accepted for installer compatibility, but this patcher currently only applies Photon AppId byte patches.'
}
if ($ServerIp -or $CertPath) {
Write-Warn 'ServerIp/CertPath are accepted for legacy installer compatibility, but hosts/cert patching is not applied by this script.'
}
if ($DisableSignatureChecks) {
Write-Warn 'DisableSignatureChecks is handled by DorkNet.ClientMod; no signature metadata bytepatch is applied.'
}
if ($patchTargets.Count -eq 0) {
throw "No patchable client files found under $($paths.Root)."
}
$anyChanged = $false
$anyFound = $false
foreach ($target in $patchTargets) {
Write-Step "Patching Photon AppIds in $($target.Path)"
$bytes = [System.IO.File]::ReadAllBytes($target.Path)
$fileChanged = $false
$realtimeResult = Apply-AsciiStringPatch -Bytes $bytes -Original $OfficialPhotonAppId -Replacement $PhotonAppId.ToLowerInvariant() -Label "$($target.Label) Photon Realtime AppId"
if ($null -ne $realtimeResult) {
$anyFound = $true
$fileChanged = $realtimeResult -or $fileChanged
}
$voiceResult = Apply-AsciiStringPatch -Bytes $bytes -Original $OfficialPhotonVoiceAppId -Replacement $PhotonVoiceAppId.ToLowerInvariant() -Label "$($target.Label) Photon Voice AppId"
if ($null -ne $voiceResult) {
$anyFound = $true
$fileChanged = $voiceResult -or $fileChanged
}
if (-not $fileChanged) {
Write-OK "No $($target.Label) changes needed."
continue
}
$anyChanged = $true
$backup = "$($target.Path).dorknet-appid-backup"
if ($DryRun) {
Write-Host "DRY RUN: would write patched $($target.Label)"
if (-not (Test-Path -LiteralPath $backup -PathType Leaf)) {
Write-Host "DRY RUN: would create backup $backup"
}
continue
}
if (-not (Test-Path -LiteralPath $backup -PathType Leaf)) {
Copy-Item -LiteralPath $target.Path -Destination $backup
Write-OK "Backup written to $backup"
}
[System.IO.File]::WriteAllBytes($target.Path, $bytes)
Write-OK "$($target.Label) Photon AppIds patched."
}
if (-not $anyFound) {
throw "Official Photon AppIds were not found in any patch target, and requested replacements were not already present."
}
if (-not $anyChanged) {
Write-OK 'No Photon AppId changes needed.'
}