clientmod: build without a local Rec Room install

The mod resolves every game-side type at runtime via
AccessTools.TypeByName, so the IL2CPP interop assemblies
(Assembly-CSharp, Photon3Unity3D, UnityEngine.*) in the csproj were
dead references. Dropped them entirely — only MelonLoader's own
DLLs are actually needed at compile time.

tools/build-patcher-zip.ps1 now downloads MelonLoader BEFORE the
dotnet build and points MelonLoaderDir at the extracted contents,
so a fresh contributor checkout builds the patcher zip cold with
no Rec Room install required. (Previously the csproj defaulted
RecRoomDir to a hardcoded user path and failed for anyone else.)

Verified by deleting bin/obj and running the script from scratch
on a machine without RecRoomDir set — produces a 20 MB zip with
the same manifest/DLL/MelonLoader.zip layout as before.
This commit is contained in:
Alexa
2026-05-27 11:47:25 +03:00
parent d471b418b9
commit 1f407ef7b3
2 changed files with 48 additions and 51 deletions
+13 -37
View File
@@ -12,21 +12,22 @@
</PropertyGroup>
<!--
MelonLoader 0.6.x build of the DorkNet client patches. This is the
MelonLoader-targeted twin of DorkNet.ClientPatch (which is a BepInEx
plugin). Both apply the same Harmony patches needed for the watch
to point at a DorkNet server — Photon AppId override, .rec.net →
custom-host URI rewrite, Photon CustomAuth identity injection, TLS
trust bypass, Photon region shortcut.
MelonLoader 0.6.x build of the DorkNet client patches. Resolves
every game-side type at runtime via AccessTools.TypeByName, so
Rec Room's IL2CPP-derived interop assemblies (Assembly-CSharp,
Photon3Unity3D, UnityEngine.*) are NOT needed at compile time —
they would be derivative works of the game anyway, so we never
reference them. Only MelonLoader's own DLLs are needed.
Set MelonLoaderDir to <RecRoomInstall>\MelonLoader. Override on the
command line:
dotnet build -p:MelonLoaderDir=C:\... -p:Il2CppAssembliesDir=C:\...
tools/build-patcher-zip.ps1 downloads the MelonLoader release zip
and points MelonLoaderDir at its extracted contents, so a fresh
contributor checkout builds without a local Rec Room install.
To build outside the script (manual dev loop):
dotnet build -p:MelonLoaderDir=<path-to-extracted-MelonLoader>
-->
<PropertyGroup>
<RecRoomDir Condition="'$(RecRoomDir)' == ''">C:\Users\you\Documents\Recnet\dist\RecRoom-Clean-2020.03.10</RecRoomDir>
<MelonLoaderDir Condition="'$(MelonLoaderDir)' == ''">$(RecRoomDir)\MelonLoader</MelonLoaderDir>
<Il2CppAssembliesDir Condition="'$(Il2CppAssembliesDir)' == ''">$(MelonLoaderDir)\Il2CppAssemblies</Il2CppAssembliesDir>
<MelonLoaderDir Condition="'$(MelonLoaderDir)' == ''">$(MSBuildThisFileDirectory)..\build\melonloader</MelonLoaderDir>
</PropertyGroup>
<ItemGroup>
@@ -46,31 +47,6 @@
<HintPath>$(MelonLoaderDir)\net6\Il2CppInterop.Common.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="Il2Cppmscorlib">
<HintPath>$(Il2CppAssembliesDir)\Il2Cppmscorlib.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="Il2CppSystem">
<HintPath>$(Il2CppAssembliesDir)\Il2CppSystem.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="Assembly-CSharp">
<HintPath>$(Il2CppAssembliesDir)\Assembly-CSharp.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="Assembly-CSharp-firstpass">
<HintPath>$(Il2CppAssembliesDir)\Assembly-CSharp-firstpass.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="Photon3Unity3D">
<HintPath>$(Il2CppAssembliesDir)\Photon3Unity3D.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="UnityEngine.CoreModule">
<HintPath>$(Il2CppAssembliesDir)\UnityEngine.CoreModule.dll</HintPath>
<Private>false</Private>
</Reference>
</ItemGroup>
</Project>
+35 -14
View File
@@ -16,6 +16,11 @@
user's Rec Room install root, copies the DLL into Mods/, then
renders the config template into UserData/.
Self-contained: downloads MelonLoader before the dotnet build and
feeds its DLLs into the build as references, so no local Rec Room
install is required to compile DorkNet.ClientMod. (The mod resolves
every game-side type at runtime via AccessTools.TypeByName.)
.PARAMETER VersionKey
The version key matching versions.json on the public main branch
(e.g. december_2020_12_18 or march_2020_03_10).
@@ -45,10 +50,35 @@ New-Item -ItemType Directory -Force $OutputDir | Out-Null
$stage = Join-Path $env:TEMP "dorknet-patcher-$VersionKey-$([guid]::NewGuid().Guid.Substring(0,8))"
New-Item -ItemType Directory -Force $stage | Out-Null
try {
# ── 1. Build DorkNet.ClientMod ───────────────────────────────────────
# ── 1. Fetch MelonLoader from upstream releases ──────────────────────
# We download it first so the DLLs inside can serve as compile-time
# references for DorkNet.ClientMod — keeps the build self-contained
# (no local Rec Room install required to compile the mod).
# x64 .NET 6 build targets 2020-era Rec Room. The asset name pattern
# is stable across 0.6.x: MelonLoader.x64.zip.
$mlAsset = "MelonLoader.x64.zip"
$mlUrl = "https://github.com/LavaGang/MelonLoader/releases/download/$MelonLoaderVersion/$mlAsset"
$mlZip = "$stage\MelonLoader.zip"
$mlExtract = "$stage\melonloader-extracted"
Write-Host "[fetch] downloading $mlUrl"
Invoke-WebRequest -Uri $mlUrl -OutFile $mlZip
if (-not (Test-Path $mlZip) -or (Get-Item $mlZip).Length -lt 1MB) {
throw "MelonLoader download failed or produced an unexpectedly small file"
}
Expand-Archive -Path $mlZip -DestinationPath $mlExtract -Force
# The 0.6.x release zip layout has a top-level `MelonLoader` folder
# containing net6, net35, Dependencies, Documentation. Point the
# csproj at that inner folder.
$mlRefRoot = Join-Path $mlExtract 'MelonLoader'
if (-not (Test-Path "$mlRefRoot\net6\MelonLoader.dll")) {
throw "Extracted MelonLoader is missing net6\MelonLoader.dll — release layout may have changed"
}
# ── 2. Build DorkNet.ClientMod (no Rec Room install needed) ─────────
Write-Host "[build] dotnet build DorkNet.ClientMod (Release)"
dotnet build "$repoRoot\DorkNet.ClientMod\DorkNet.ClientMod.csproj" `
-c Release --nologo | Out-Null
-c Release --nologo `
"-p:MelonLoaderDir=$mlRefRoot" | Out-Null
if ($LASTEXITCODE -ne 0) { throw "ClientMod build failed" }
$dll = Get-ChildItem "$repoRoot\DorkNet.ClientMod\bin\Release" -Recurse `
-Filter "DorkNet.ClientMod.dll" |
@@ -58,18 +88,6 @@ try {
Copy-Item $dll.FullName "$stage\DorkNet.ClientMod.dll"
Write-Host "[build] copied $($dll.FullName)"
# ── 2. Fetch MelonLoader from upstream releases ──────────────────────
# The x64 .NET 6 build is what targets 2020-era Rec Room. The asset
# name pattern is stable across 0.6.x: MelonLoader.x64.zip.
$mlAsset = "MelonLoader.x64.zip"
$mlUrl = "https://github.com/LavaGang/MelonLoader/releases/download/$MelonLoaderVersion/$mlAsset"
$mlOut = "$stage\MelonLoader.zip"
Write-Host "[build] downloading $mlUrl"
Invoke-WebRequest -Uri $mlUrl -OutFile $mlOut
if (-not (Test-Path $mlOut) -or (Get-Item $mlOut).Length -lt 1MB) {
throw "MelonLoader download failed or produced an unexpectedly small file"
}
# ── 3. Copy the config template ──────────────────────────────────────
$template = "$repoRoot\DorkNet.ClientMod\dorknet-clientmod.json.template"
if (-not (Test-Path $template)) {
@@ -92,6 +110,9 @@ try {
Set-Content -LiteralPath "$stage\manifest.json" -Value $manifest
# ── 5. Bundle into the final zip ────────────────────────────────────
# Strip the extracted MelonLoader scratch dir before zipping so it
# doesn't bloat the artifact. The MelonLoader.zip itself stays.
Remove-Item -Recurse -Force $mlExtract
$outZip = Join-Path $OutputDir "dorknet-clientpatch-$VersionKey.zip"
if (Test-Path $outZip) { Remove-Item $outZip -Force }
Compress-Archive -Path "$stage\*" -DestinationPath $outZip