mirror of
https://github.com/JogmansonReal/Radicade.git
synced 2026-10-25 15:09:26 -07:00
216 lines
11 KiB
PowerShell
216 lines
11 KiB
PowerShell
<#
|
|
Builds a friend-ready Radicade August 2023 client bundle from a WORKING install.
|
|
|
|
It reads the source install, verifies every required piece against the reference
|
|
hashes, copies them to -OutDir, drops the triage script and a README in with them,
|
|
and optionally zips the result. Nothing in -GameDir is ever modified.
|
|
|
|
Usage:
|
|
powershell -ExecutionPolicy Bypass -File make-august-client-pack.ps1 -OutDir "D:\radicade-pack"
|
|
powershell -ExecutionPolicy Bypass -File make-august-client-pack.ps1 -OutDir "D:\radicade-pack" -Zip
|
|
|
|
Verification is fail-closed: if a piece is unpatched or a different build, the script
|
|
stops and names it instead of producing a bundle that cannot work.
|
|
#>
|
|
[CmdletBinding()]
|
|
param(
|
|
[string]$GameDir,
|
|
[Parameter(Mandatory = $true)][string]$OutDir,
|
|
[switch]$Zip,
|
|
[switch]$Force
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
# Reference values: the install that logs in and loads rooms.
|
|
$expected = @{
|
|
AssemblySize = 167390208
|
|
AssemblyMd5 = '11e14eb35671e2725bd0c78a6a91bb48'
|
|
MetadataSize = 38654794
|
|
MetadataMd5 = 'cc9c32014b5fc3dd1a2a8fb12376be15'
|
|
InteropSize = 38654794
|
|
InteropMd5 = '4a1a28078f957af470f3b31951b32648'
|
|
BootSize = 173
|
|
BootMd5 = 'dc2e5f7af7d5df736a4cc3477b4b1a1f'
|
|
WinhttpSize = 26112
|
|
WinhttpMd5 = 'b2a4d0cb04bf8f5a27ccab237ecc2586'
|
|
LoaderSize = 60928
|
|
LoaderMd5 = '9430bb84349d52b753a181788a86c5e2'
|
|
PluginSize = 62464
|
|
PluginMd5 = '8718a45dd42d7cb72b3e46e04b744d91'
|
|
InteropCount = 335
|
|
}
|
|
|
|
function Get-Md5 {
|
|
param([string]$Path)
|
|
return (Get-FileHash -LiteralPath $Path -Algorithm MD5).Hash.ToLower()
|
|
}
|
|
|
|
function Assert-Piece {
|
|
param(
|
|
[string]$Label,
|
|
[string]$Path,
|
|
[long]$Size,
|
|
[string]$Md5
|
|
)
|
|
if (-not (Test-Path -LiteralPath $Path)) {
|
|
throw "$Label is missing: $Path"
|
|
}
|
|
$info = Get-Item -LiteralPath $Path
|
|
$actual = Get-Md5 $Path
|
|
if ($info.Length -ne $Size -or $actual -ne $Md5) {
|
|
$detail = "$Label does not match the reference: {0} b md5 {1} (expected {2} b md5 {3})" -f $info.Length, $actual, $Size, $Md5
|
|
if ($Force) { Write-Host ("WARNING: " + $detail) }
|
|
else { throw ($detail + ' - fix it or pass -Force if you know this build is fine.') }
|
|
} else {
|
|
Write-Host (" ok {0}" -f $Label)
|
|
}
|
|
}
|
|
|
|
# --- locate the source install ------------------------------------------------
|
|
|
|
if (-not $GameDir) {
|
|
$candidates = @(
|
|
(Join-Path $env:USERPROFILE 'Downloads\2023-08-29T06-53-33Z')
|
|
)
|
|
$downloads = Join-Path $env:USERPROFILE 'Downloads'
|
|
if (Test-Path -LiteralPath $downloads) {
|
|
$candidates += (Get-ChildItem -LiteralPath $downloads -Directory -ErrorAction SilentlyContinue |
|
|
Where-Object { Test-Path -LiteralPath (Join-Path $_.FullName 'RecRoom.exe') } |
|
|
ForEach-Object { $_.FullName })
|
|
}
|
|
foreach ($c in $candidates) {
|
|
if (Test-Path -LiteralPath (Join-Path $c 'BepInEx\plugins\RadicadeAugustClient.dll')) { $GameDir = $c; break }
|
|
}
|
|
}
|
|
if (-not $GameDir) { $GameDir = Read-Host 'Path to the patched Rec Room folder (the one that works)' }
|
|
$GameDir = $GameDir.TrimEnd('\')
|
|
|
|
$metadataDir = Join-Path $GameDir 'Recroom_Data\il2cpp_data\Metadata'
|
|
$bepInEx = Join-Path $GameDir 'BepInEx'
|
|
|
|
Write-Host 'Verifying the source install against the reference hashes...'
|
|
Assert-Piece 'GameAssembly.dll (build identity)' (Join-Path $GameDir 'GameAssembly.dll') $expected.AssemblySize $expected.AssemblyMd5
|
|
Assert-Piece 'global-metadata.dat (host literals patched)' (Join-Path $metadataDir 'global-metadata.dat') $expected.MetadataSize $expected.MetadataMd5
|
|
Assert-Piece 'global-metadata.interop.dat' (Join-Path $metadataDir 'global-metadata.interop.dat') $expected.InteropSize $expected.InteropMd5
|
|
Assert-Piece 'Recroom_Data\boot.config' (Join-Path $GameDir 'Recroom_Data\boot.config') $expected.BootSize $expected.BootMd5
|
|
Assert-Piece 'winhttp.dll (Doorstop 4.3.0)' (Join-Path $GameDir 'winhttp.dll') $expected.WinhttpSize $expected.WinhttpMd5
|
|
Assert-Piece 'BepInEx.Unity.IL2CPP.dll (patched loader)' (Join-Path $bepInEx 'core\BepInEx.Unity.IL2CPP.dll') $expected.LoaderSize $expected.LoaderMd5
|
|
Assert-Piece 'RadicadeAugustClient.dll' (Join-Path $bepInEx 'plugins\RadicadeAugustClient.dll') $expected.PluginSize $expected.PluginMd5
|
|
|
|
if (-not (Test-Path -LiteralPath (Join-Path $GameDir 'doorstop_config.ini'))) { throw 'doorstop_config.ini is missing' }
|
|
$interopCount = (Get-ChildItem -LiteralPath (Join-Path $bepInEx 'interop') -File -ErrorAction SilentlyContinue).Count
|
|
if ($interopCount -lt $expected.InteropCount) {
|
|
throw ("BepInEx\interop holds {0} assemblies, expected at least {1} - interop generation was incomplete" -f $interopCount, $expected.InteropCount)
|
|
}
|
|
Write-Host (" ok BepInEx\interop ({0} assemblies)" -f $interopCount)
|
|
Write-Host 'Source install verified.'
|
|
Write-Host ''
|
|
|
|
# --- assemble the bundle ------------------------------------------------------
|
|
|
|
$bundleRoot = Join-Path $OutDir 'RadicadeAugustClient'
|
|
if (Test-Path -LiteralPath $bundleRoot) {
|
|
if ($Force) { Remove-Item -LiteralPath $bundleRoot -Recurse -Force }
|
|
else { throw "$bundleRoot already exists - delete it or pass -Force to replace it." }
|
|
}
|
|
New-Item -ItemType Directory -Path $bundleRoot -Force | Out-Null
|
|
|
|
Write-Host ("Copying into {0} ..." -f $bundleRoot)
|
|
|
|
# Root-level loader pieces and the patched data files.
|
|
Copy-Item -LiteralPath (Join-Path $GameDir 'winhttp.dll') -Destination $bundleRoot
|
|
Copy-Item -LiteralPath (Join-Path $GameDir 'doorstop_config.ini') -Destination $bundleRoot
|
|
foreach ($name in @('.doorstop_version', 'changelog.txt')) {
|
|
$p = Join-Path $GameDir $name
|
|
if (Test-Path -LiteralPath $p) { Copy-Item -LiteralPath $p -Destination $bundleRoot }
|
|
}
|
|
|
|
$dataTarget = Join-Path $bundleRoot 'Recroom_Data'
|
|
New-Item -ItemType Directory -Path $dataTarget -Force | Out-Null
|
|
Copy-Item -LiteralPath (Join-Path $GameDir 'Recroom_Data\boot.config') -Destination $dataTarget
|
|
foreach ($name in @('radicade-patch.json')) {
|
|
$p = Join-Path $GameDir ('Recroom_Data\' + $name)
|
|
if (Test-Path -LiteralPath $p) { Copy-Item -LiteralPath $p -Destination $dataTarget }
|
|
}
|
|
$metaTarget = Join-Path $dataTarget 'il2cpp_data\Metadata'
|
|
New-Item -ItemType Directory -Path $metaTarget -Force | Out-Null
|
|
foreach ($name in @('global-metadata.dat', 'global-metadata.interop.dat')) {
|
|
Copy-Item -LiteralPath (Join-Path $metadataDir $name) -Destination $metaTarget
|
|
}
|
|
|
|
# The whole BepInEx tree, minus logs, sidecar backups and caches.
|
|
$bepTarget = Join-Path $bundleRoot 'BepInEx'
|
|
# Excluded: logs, sidecar backups of previous builds, and the diagnostic RVA map the
|
|
# plugin writes (18 MB of local crash-analysis output).
|
|
robocopy $bepInEx $bepTarget /E /NFL /NDL /NJH /NJS /NP `
|
|
/XF 'LogOutput.log' '*.log' '*.before-*' '*.tracer-*' '*.march-backup' '*.baseline-disabled' `
|
|
'radicade-addr-map.txt' | Out-Null
|
|
if ($LASTEXITCODE -ge 8) { throw ("robocopy failed with exit code {0}" -f $LASTEXITCODE) }
|
|
$global:LASTEXITCODE = 0
|
|
|
|
# The triage script travels with the bundle so the friend can produce a report.
|
|
$triage = Join-Path $PSScriptRoot 'august-client-triage.ps1'
|
|
if (Test-Path -LiteralPath $triage) { Copy-Item -LiteralPath $triage -Destination $bundleRoot }
|
|
|
|
$assemblyInfo = Get-Item -LiteralPath (Join-Path $GameDir 'GameAssembly.dll')
|
|
$readme = @()
|
|
$readme += 'Radicade August 2023 client patch'
|
|
$readme += ''
|
|
$readme += 'This bundle carries the client half of a Rec Room 2023-08-29 (game version 20230825,'
|
|
$readme += 'Unity 2020.3.33f1) setup pointed at a Radicade server on YOUR OWN machine.'
|
|
$readme += ''
|
|
$readme += 'It only works on the identical game build. Check yours before copying anything:'
|
|
$readme += (" GameAssembly.dll must be {0} bytes, md5 {1}" -f $assemblyInfo.Length, $expected.AssemblyMd5)
|
|
$readme += ''
|
|
$readme += 'Install, into the folder that holds RecRoom.exe:'
|
|
$readme += ' 1. copy winhttp.dll, doorstop_config.ini and .doorstop_version into the game root'
|
|
$readme += ' 2. copy BepInEx\ next to them'
|
|
$readme += ' 3. copy Recroom_Data\boot.config and Recroom_Data\il2cpp_data\Metadata\*.dat over the'
|
|
$readme += ' existing files (keep copies of the originals; global-metadata.dat.orig is the'
|
|
$readme += ' patcher''s own backup and must stay untouched)'
|
|
$readme += ' 4. rename any winhttp.dll.baseline-disabled you already have out of the way'
|
|
$readme += ' 5. start your Radicade server first - https://localhost:3030 plus http://127.0.0.1:3031,'
|
|
$readme += ' ASPNETCORE_ENVIRONMENT=Development - and only then launch the game'
|
|
$readme += ''
|
|
$readme += 'Why the server has to be local: the patched global-metadata.dat rewrites the client''s'
|
|
$readme += 'bootstrap literals to https://localhost:3030, so a remote server cannot answer them.'
|
|
$readme += ''
|
|
$readme += 'Then check the install with the bundled triage script:'
|
|
$readme += ' powershell -ExecutionPolicy Bypass -File august-client-triage.ps1'
|
|
$readme += 'It prints one PASS/MISSING line per required piece and writes august-client-report.txt.'
|
|
$readme += ''
|
|
$readme += 'The line "Failed to load Type RecRoom.Analytics.Statsig.StatsigDebugOverrides" in'
|
|
$readme += 'Player.log is NORMAL and appears in a completely unpatched launch of this build too.'
|
|
$readme += 'It is never the reason a patched install fails.'
|
|
$readme += ''
|
|
$readme += 'Pieces and their reference hashes (the triage script checks these for you):'
|
|
$readme += ' GameAssembly.dll 167390208 b 11e14eb35671e2725bd0c78a6a91bb48'
|
|
$readme += ' Recroom_Data/il2cpp_data/Metadata/global-metadata.dat'
|
|
$readme += ' 38654794 b cc9c32014b5fc3dd1a2a8fb12376be15'
|
|
$readme += ' Recroom_Data/il2cpp_data/Metadata/global-metadata.interop.dat'
|
|
$readme += ' 38654794 b 4a1a28078f957af470f3b31951b32648'
|
|
$readme += ' Recroom_Data/boot.config 173 b dc2e5f7af7d5df736a4cc3477b4b1a1f'
|
|
$readme += ' winhttp.dll 26112 b b2a4d0cb04bf8f5a27ccab237ecc2586'
|
|
$readme += ' BepInEx/core/BepInEx.Unity.IL2CPP.dll'
|
|
$readme += ' 60928 b 9430bb84349d52b753a181788a86c5e2'
|
|
$readme += ' BepInEx/plugins/RadicadeAugustClient.dll'
|
|
$readme += ' 62464 b 8718a45dd42d7cb72b3e46e04b744d91'
|
|
$readme += ' BepInEx/interop/ 335 assemblies'
|
|
$readme += ''
|
|
Set-Content -LiteralPath (Join-Path $bundleRoot 'README-FRIEND.txt') -Value ($readme -join "`r`n") -Encoding UTF8
|
|
|
|
$size = (Get-ChildItem -LiteralPath $bundleRoot -Recurse -File | Measure-Object -Property Length -Sum).Sum
|
|
Write-Host ('Bundle assembled: {0} ({1:N1} MB)' -f $bundleRoot, ($size / 1MB))
|
|
|
|
if ($Zip) {
|
|
$zipPath = $bundleRoot.TrimEnd('\') + '.zip'
|
|
if (Test-Path -LiteralPath $zipPath) { Remove-Item -LiteralPath $zipPath -Force }
|
|
Write-Host ('Compressing to {0} (this takes a while)...' -f $zipPath)
|
|
Compress-Archive -Path (Join-Path $bundleRoot '*') -DestinationPath $zipPath -CompressionLevel Optimal
|
|
Write-Host ('Zip written: {0} ({1:N1} MB)' -f $zipPath, ((Get-Item -LiteralPath $zipPath).Length / 1MB))
|
|
}
|
|
|
|
Write-Host ''
|
|
Write-Host 'Remind the friend that he still needs the game build above and his own Radicade server.'
|