mirror of
https://github.com/DorkSquadRR/DorkNet.git
synced 2026-10-26 07:28:45 -07:00
258183fb94
ClientMod (2023-03-21): opt-in Rec Royale night mode. RRO scenes never
enable the room mood engine (no data blob → SceneMoodSettings.isEnabled
stays false, CurrentMood null, the per-frame update returns at once), so
the mod replays the room-data loader's bring-up, registers a shipped
night MoodSetting (Night_Calm_Outdoor_Mood by default) as the scene's
default mood, supplies a skybox material on the Custom/SkyBox shader
(MoodConfig.SkyBoxMaterial is not loaded outside custom rooms), assigns
the scene's directional light as RenderSettings.sun, matches the key
light to the engine-driven sun, darkens via the mood's post-exposure and
sun/ambient intensities, forces post-processing on, keeps or disables
fog, hides the daytime cloud meshes, unlocks weapon flashlights, and
restores everything on hotkey-off / scene change. All knobs live in
dorknet-clientmod.json (RecRoyaleNight*), written by install-melon.ps1.
Server/admin: baked Rec Room Originals are seeded with an empty
DataBlobName, which the 2023 client reads as "no room data" — no Maker
Pen, no CV2 room-settings chips, no saves, and for Rec Royale no game at
all (its game-rule chip RecRoyaleSolos_GameRuleWrapperCircuit ships in
the blob, not the scene). New admin actions on the Sub-rooms tab:
POST rooms/{id}/subrooms/{sub}/blob/enable stamps the synthetic default
blob name (which CdnController already answers with the RRO-editable
blob) and blob/reset clears it back to scene-only. IsRRO is derived from
IsAGRoom, so the client keeps loading the baked map.
Docs: README section, docs/admin.md procedure, docs/recroom-2023-room-save.md,
new docs/recroom-2023-scene-moods.md with the ISIL offsets behind all of it.
Tests: RroRoomBlobTests.
464 lines
21 KiB
Markdown
464 lines
21 KiB
Markdown
# DorkNet — `march-2023-03-21`
|
|
|
|
This is the **December 2020.12.18** branch of DorkNet — a self-hostable
|
|
reimplementation of the Rec Room backend tuned to the wire protocol of
|
|
the **Rec Room 2020.12.18** client build.
|
|
|
|
> ⚠️ **Not affiliated with Rec Room Inc. or Against Gravity.**
|
|
> See [DISCLAIMER](../../blob/main/DISCLAIMER.md). DorkNet ships no Rec
|
|
> Room game assets or modified binaries — you supply your own
|
|
> legally-acquired Rec Room 2020.12.18 install.
|
|
|
|
If you're not sure which DorkNet branch you want, start at the
|
|
[main branch's chart](../../blob/main/BRANCHES.md). The launcher on
|
|
main also auto-detects your install.
|
|
|
|
---
|
|
|
|
## What this branch targets
|
|
|
|
| | |
|
|
|---|---|
|
|
| **Client build** | Rec Room 2020.12.18 |
|
|
| **Version key** (sent as `X-DorkNet-Version` header) | `december_2020_12_18` |
|
|
| **Version plugin** | `DorkNet.Server/Versions/Late2020/Late2020VersionPlugin.cs` |
|
|
| **Schema** | One EF `Initial` migration; SQLite + Postgres both work |
|
|
| **Runtime topology** | Gateway-fronted microservices with dedicated service slices and a monolith fallback |
|
|
| **Diverges from `march-2020-03-10` by** | ~170 files |
|
|
|
|
Subsystems present on this branch that the March branch doesn't have:
|
|
|
|
- Chat threads + group DMs (`ChatThreads`, `ChatThreadMembers`)
|
|
- Clubs surface (`clubs.{apex}/*` — announcements, categories, subscriptions)
|
|
- Playlists (curated + user-created)
|
|
- Weekly challenges
|
|
- Room keys (purchasable room access)
|
|
- Room roles (per-room co-owner / moderator / host grants)
|
|
- Leaderboard channel metadata
|
|
- Loading-screen tips
|
|
|
|
---
|
|
|
|
## Quickstart
|
|
|
|
**1. Install .NET 9 SDK** and (optionally) `dotnet-ef`:
|
|
|
|
```pwsh
|
|
dotnet tool install --global dotnet-ef
|
|
```
|
|
|
|
**2. Clone this branch:**
|
|
|
|
```pwsh
|
|
git clone --branch december-2020-12-18 https://github.com/DorkSquadRR/DorkNet
|
|
cd DorkNet
|
|
```
|
|
|
|
**3. Configure secrets.** Drop in `DorkNet.Server/appsettings.Local.json`
|
|
(gitignored) or export environment variables:
|
|
|
|
| Config key | Env var | Required | Notes |
|
|
|---|---|---|---|
|
|
| `Jwt:Secret` | `DORKNET_JWT_SECRET` or `Jwt__Secret` | yes | >=64 random chars |
|
|
| `Photon:AppId` | `Photon__AppId` | yes | Photon Realtime AppId (free at dashboard.photonengine.com) |
|
|
| `Photon:VoiceAppId` | `Photon__VoiceAppId` | no | only if voice chat |
|
|
| `Photon:CloudRegion` | `Photon__CloudRegion` | no | defaults to `us` |
|
|
| `Database:Provider` | `Database__Provider` | no | `sqlite` (default) or `postgres` |
|
|
| `ConnectionStrings:Default` | `ConnectionStrings__Default` | postgres-only | full Npgsql connection string |
|
|
| `ConnectionStrings:Redis` | `ConnectionStrings__Redis` | no | enables SignalR backplane |
|
|
| `Domain:Apex` | `DORKNET_DOMAIN` | no | defaults to `localhost`; set for production |
|
|
| `S3:Endpoint` | `S3__Endpoint` | production | S3-compatible API endpoint for blobs/images |
|
|
| `S3:AccessKey` | `S3__AccessKey` | production | S3 access key |
|
|
| `S3:SecretKey` | `S3__SecretKey` | production | S3 secret key |
|
|
| `S3:Region` | `S3__Region` | no | defaults to `garage`; use `auto` for R2 |
|
|
|
|
**4. Boot a local standalone server:**
|
|
|
|
```pwsh
|
|
dotnet run --project DorkNet.Server
|
|
```
|
|
|
|
First boot creates `bin/Debug/net9.0/data/dorknet.db`, runs every
|
|
`LegacyUpgrades` pass, seeds canonical rooms / store catalog / club
|
|
categories / playlists, and starts listening. You should see
|
|
`Application started.` in the log; `curl http://localhost:8080/healthz`
|
|
returns 200.
|
|
|
|
For the production microservices stack, Docker, and Dokploy deploy
|
|
notes, see
|
|
[docs/deploy.md](docs/deploy.md).
|
|
|
|
---
|
|
|
|
## Patching your client
|
|
|
|
```pwsh
|
|
.\tools\install-melon.ps1 `
|
|
-RecRoomPath "C:\Path\To\Recroom_Release_Data" `
|
|
-PhotonAppId "<your-photon-realtime-app-id>" `
|
|
-PhotonVoiceAppId "<your-photon-voice-app-id>"
|
|
```
|
|
|
|
This installs the MelonLoader mod (`DorkNet.ClientMod`) into the
|
|
client's `Mods/` folder and writes its config to
|
|
`MelonLoader/UserData/dorknet-clientmod.json`. The mod rewrites all
|
|
`*.rec.net` URIs to your configured DorkNet apex, swaps the Photon
|
|
AppIds, and bypasses TLS verification on the client's HTTPS calls so
|
|
self-signed certs work. (First run prints "launch the game once"; do
|
|
that, then re-run with `-ResumeBuild` to finish — see the script's
|
|
`-?` help.)
|
|
|
|
### Standalone Quest build (experimental)
|
|
|
|
The December Quest APK is also IL2CPP and can build the same
|
|
`DorkNet.ClientMod` source against LemonLoader's Android runtime. The
|
|
current Quest path is still device-tested manually: build the mod as a
|
|
net8 LemonLoader DLL, install it into a LemonLoader-patched APK, then
|
|
sideload the resigned APK.
|
|
|
|
From this branch:
|
|
|
|
```pwsh
|
|
dotnet build .\DorkNet.ClientMod\DorkNet.ClientMod.csproj `
|
|
-p:TargetFrameworks=net8.0 `
|
|
-p:MelonLoaderDir="C:\path\to\LemonLoader\melon_data\MelonLoader"
|
|
```
|
|
|
|
Output lands at
|
|
`DorkNet.ClientMod\bin\Debug\net8.0\DorkNet.ClientMod.dll`. Desktop
|
|
builds still default to net6 and keep the historical flat output path.
|
|
|
|
Quest notes:
|
|
|
|
- Target package: `com.AgainstGravity.RecRoom`.
|
|
- Use a public HTTPS DorkNet host; keep `"EnableTlsTrustBypass": false`
|
|
for Quest builds.
|
|
- The Dec Photon hooks are discovered from the unique
|
|
`PUNNetworkManager` methods returning `AppSettings` and
|
|
`AuthenticationValues`, with the known Dec obfuscated names as fallback.
|
|
- Standalone APK patching/resigning is not yet wrapped by
|
|
`install-melon.ps1`; this is the porting path, not a public one-click
|
|
installer yet.
|
|
|
|
### Debugging (opt-in — `DorkNet.DebugMod`)
|
|
|
|
The shipping `DorkNet.ClientMod` carries only what's needed to connect and
|
|
survive anti-cheat. All diagnostics — HTTP/request tracing, join/quit/studio/
|
|
room-load traces, the process-exception sink, auth-token tracing, the
|
|
registration-dialog trace, and the in-game debug console — live in a separate
|
|
`DorkNet.DebugMod`. Drop `DorkNet.DebugMod.dll` into the `Mods` folder next to
|
|
`DorkNet.ClientMod.dll` to turn them on; remove it to ship a quiet, minimal
|
|
client. Debug knobs are read from the same `dorknet-clientmod.json`.
|
|
|
|
Retail builds keep the `RecRoom.Debugging.DebugConsole` UI and serialized
|
|
`DebugConsoleCommandConfig` list, but the public 2023 client strips the
|
|
native command submit path. With `DorkNet.DebugMod` installed, set
|
|
`"EnableDebugConsole": true` and relaunch: it force-toggles the console UI on
|
|
a hotkey (`"DebugConsoleToggleKey"`, default `BackQuote` = the `~` key),
|
|
intercepts the dead submit callback, and invokes commands from the runtime
|
|
command metadata directly. Type `help` in the console to list discovered
|
|
commands. `"DevCommands"` may contain optional `"Label=Command args"`
|
|
shortcuts. The feature stays off by default and also silences the retail
|
|
`CheatManager` callbacks used by movement/time commands.
|
|
|
|
### Desktop Screen Sharing FPS (opt-in)
|
|
|
|
The Maker Pen "Desktop Sharing Screen"
|
|
(`RecRoom.Tools.Productivity.DesktopScreenSharingDisplay`) broadcasts at a
|
|
baked refresh rate (~5 fps). Set `"DesktopScreenShareFps"` in
|
|
`dorknet-clientmod.json` (e.g. `30`) and relaunch to override it — the mod
|
|
rewrites the gadget's `screenShareImageRefreshFrequency` at runtime and,
|
|
when `"DesktopScreenShareRaisePhotonRate"` is true (default), lifts
|
|
`PhotonNetwork.SendRate`/`SerializationRate` to match so the frames
|
|
actually transmit (the image streams over `OnPhotonSerializeView`, capped
|
|
at the serialization rate otherwise). This is **global** — it raises every
|
|
object's network sync rate, so back it off on a busy room.
|
|
`"DesktopScreenShareResolution"`/`"DesktopScreenShareQuality"` (both `0` =
|
|
keep the prefab value) trade per-frame size for bandwidth if a high FPS
|
|
saturates the link. Only the player *sharing* needs the override. Default
|
|
`0` (off).
|
|
|
|
### RRO quest team size (opt-in)
|
|
|
|
RRO quests ship with a baked 4-player `GameConfigurationAsset` team cap.
|
|
Set `"QuestMaxTeamSize"` in `dorknet-clientmod.json` (for example `8`) to
|
|
raise that cap for the allowlisted quest configs in
|
|
`"QuestMaxTeamSizeRooms"`:
|
|
|
|
```json
|
|
{
|
|
"QuestMaxTeamSize": 8,
|
|
"QuestMaxTeamSizeRooms": [
|
|
"CrimsonCauldron",
|
|
"Crescendo",
|
|
"GoldenTrophy",
|
|
"IsleOfLostSkulls",
|
|
"TheRiseofJumbotron"
|
|
]
|
|
}
|
|
```
|
|
|
|
The quest host must run the mod: the host builds the game configuration
|
|
that gets networked to joiners. The patch also relaxes the quest spawn
|
|
filter for extra players, so player indexes above the four baked spawn
|
|
slots can reuse existing quest spawn points instead of being left out.
|
|
Default `0` (off).
|
|
|
|
### Rec Royale night mode (opt-in)
|
|
|
|
Rec Royale never shipped a night variant, but the client carries the room
|
|
"mood" engine (`RecRoom.Core.Scene.SceneMoodSettings`) and ready-made
|
|
night `MoodSetting` assets in `resources.assets`. Set
|
|
`"RecRoyaleNightMode"` in `dorknet-clientmod.json` and the mod applies one
|
|
of those moods (sky dome, sun, fog, bloom and colour grading) as soon as
|
|
the `RecRoyale_Frontier` scene finishes loading, and unlocks the weapon
|
|
flashlight prefab while it is on:
|
|
|
|
```json
|
|
{
|
|
"RecRoyaleNightMode": true,
|
|
"RecRoyaleNightMood": "Night_Calm_Outdoor_Mood",
|
|
"RecRoyaleNightScenes": ["RecRoyale"],
|
|
"RecRoyaleNightFlashlights": true,
|
|
"RecRoyaleNightFog": false,
|
|
"RecRoyaleNightExposure": -3.5,
|
|
"RecRoyaleNightSunScale": 0.15,
|
|
"RecRoyaleNightAmbientScale": 0.2,
|
|
"RecRoyaleNightForcePostProcessing": true,
|
|
"RecRoyaleNightMatchSunLights": true,
|
|
"RecRoyaleNightDisableFog": false,
|
|
"RecRoyaleNightHideObjects": ["Cloud"],
|
|
"RecRoyaleNightToggleKey": "N"
|
|
}
|
|
```
|
|
|
|
`RecRoyaleNightDisableFog` turns fog off entirely while night is on
|
|
(`RenderSettings.fog` forced off and the mood's fog block pushed out of
|
|
range); it is ignored when `RecRoyaleNightFog` is `true`.
|
|
`RecRoyaleNightHideObjects` hides every renderer whose object or material
|
|
name contains one of the entries; the default hides Frontier's daytime
|
|
cloud meshes (`CloudPlane`, `Clouds`, the `_Cloud_RecRoyale_Frontier_Mat`
|
|
static batch). Both are restored on toggle-off or scene change.
|
|
|
|
The mood engine only ever drives `RenderSettings.sun`, which on Frontier
|
|
is the sun-disc light, not the map's key light, so daylight would keep
|
|
casting. `RecRoyaleNightMatchSunLights` (default `true`) copies the
|
|
engine-driven sun's rotation and colour onto every other directional
|
|
light and scales their intensity by `RecRoyaleNightSunScale`.
|
|
|
|
Two more RRO quirks the mod works around: the mood skybox material the
|
|
engine swaps in (`MoodConfig.SkyBoxMaterial`) is not loaded outside
|
|
custom-room scenes, so the mod builds one on the `Custom/SkyBox` shader
|
|
and hands it to the engine (otherwise the sky is plain black and the
|
|
engine refuses to touch sky colours or the sun); and post-exposure only
|
|
shows when the scene Volume is on and the camera renders
|
|
post-processing, which `RecRoyaleNightForcePostProcessing` (default
|
|
`true`) forces while night mode is active.
|
|
|
|
Brightness: RRO maps are lightmapped, and baked lighting ignores the sun
|
|
and ambient changes a mood makes, so the mod also darkens the mood data
|
|
itself before applying it. `RecRoyaleNightExposure` is an EV offset added
|
|
to the mood's colour-grading post-exposure (a full-frame post effect, so
|
|
it dims lightmapped surfaces too; `0` = mood default), and
|
|
`RecRoyaleNightSunScale` / `RecRoyaleNightAmbientScale` multiply the
|
|
mood's sun and ambient intensities (`1` = unchanged). Raise the exposure
|
|
toward `0` if it is too dark.
|
|
|
|
RRO scenes have no room data blob, so the mood engine starts disabled
|
|
there; the mod replays the room-data loader's bring-up (disable, capture
|
|
the scene's own lighting, enable), points `RenderSettings.sun` at the
|
|
scene's directional light (Frontier ships without the reference, which
|
|
would otherwise skip every sun change), and re-captures once the mood
|
|
skybox material is in place so the sky colours apply. `RecRoyaleNightFog`
|
|
is off by default: the mood's fog block is swapped for one captured from
|
|
the scene, so fog stays as the map author left it.
|
|
|
|
Shipped moods: `Night_Calm_Outdoor_Mood` ("Calm Night"),
|
|
`Night_Spooky_Outdoor_Mood` ("Spooky Night"), `Night_Wild_Outdoor_Mood`
|
|
("Wild Night"), `Night_StuntRunner_Outdoor_Mood` and `OuterSpace_Mood`.
|
|
`RecRoyaleNightToggleKey` is an optional `UnityEngine.KeyCode` name that
|
|
flips night on/off in-game (off restores the scene's own mood); setting a
|
|
key also arms the feature when `RecRoyaleNightMode` is `false`. This is
|
|
purely **client-side**: the mod calls the mood engine's apply step
|
|
directly and never touches the networked room-mood index, so other players
|
|
keep their own view. Baked lightmaps are not changed, so interiors stay
|
|
lit; the mood's colour grading does the darkening. Default `false` (off).
|
|
Wire-level notes: `docs/recroom-2023-scene-moods.md`.
|
|
|
|
---
|
|
|
|
## Code map
|
|
|
|
| Folder | Purpose |
|
|
|---|---|
|
|
| `DorkNet.Server/` | Shared ASP.NET Core controller/service stack, standalone fallback, monolith fallback |
|
|
| `DorkNet.Models/` | DTOs shared between server and client mod |
|
|
| `DorkNet.Contracts/` | Shared service names, route ownership, service-map options, and health/probe contracts |
|
|
| `DorkNet.ServiceDefaults/` | Shared service health, JSON, HTTP client, service identity, and route-guard setup |
|
|
| `DorkNet.Gateway/` | Edge reverse proxy with service-map, route-table, and service-health endpoints |
|
|
| `DorkNet.Services.*` | Gateway-fronted service hosts for identity, rooms, notify, content, social, commerce, platform, moderation, and web |
|
|
| `DorkNet.ClientMod/` | MelonLoader IL2CPP mod — the client patcher |
|
|
| `tools/` | Installers (`install-melon.ps1`, `install-legacy-client.ps1`, `remove-eac.ps1`), Cloudflare tunnel templates |
|
|
| `Dockerfile`, `Dockerfile.service`, `docker-compose.microservices*.yml` | Standalone fallback image, reusable service image, and local/Dokploy microservices entrypoints |
|
|
|
|
See [docs/architecture.md](docs/architecture.md) for the full mental
|
|
model (project layout, request lifecycle, watch-mirror controller
|
|
pattern, where to start contributing).
|
|
|
|
### Client API contracts
|
|
|
|
Rec Room is shut down, so the clients can only be studied statically.
|
|
[docs/recroom-2023-client-api-complete.md](docs/recroom-2023-client-api-complete.md)
|
|
is the complete contract for the March-2023 client: every route it can
|
|
call, the HTTP verb, the request and response shapes, and a per-subsystem
|
|
diff against what this server currently implements. Read it before adding
|
|
or changing any endpoint that build touches — it also documents how to
|
|
recover verbs and response shapes from the disassembly yourself.
|
|
|
|
The equivalent material for the December-2020 client is in the
|
|
`recroom-2020-client-*` files alongside it.
|
|
|
|
### Microservices
|
|
|
|
The production topology is the gateway-fronted compose stack.
|
|
`docker-compose.microservices.yml` starts the gateway, identity, rooms,
|
|
notify, content, social, commerce, platform, moderation, web, and
|
|
monolith fallback service hosts plus Compose-managed Postgres and Redis
|
|
for local testing. `docker-compose.microservices.dokploy.yml` is the
|
|
Dokploy version; it adds a `cloudflared` sidecar so Cloudflare Tunnel
|
|
can route the apex and wildcard hostnames to the gateway without Dokploy
|
|
domain rows.
|
|
|
|
The gateway routes owned host/path slices to the dedicated service hosts.
|
|
The `web` service owns the apex, `www`, `admin`, and `feed` static hosts.
|
|
The monolith fallback is still present for unknown route families, so
|
|
public client URLs remain stable while the split continues.
|
|
|
|
The compose file intentionally does not start object storage. Point it at
|
|
your separate S3-compatible instance:
|
|
|
|
```pwsh
|
|
$env:DORKNET_S3_ENDPOINT="https://your-s3-endpoint"
|
|
$env:DORKNET_S3_ACCESS_KEY="..."
|
|
$env:DORKNET_S3_SECRET_KEY="..."
|
|
$env:DORKNET_S3_REGION="garage" # or auto for R2
|
|
docker compose -f docker-compose.microservices.yml up --build
|
|
```
|
|
|
|
For deployment details, including Dokploy env vars, Cloudflare Tunnel
|
|
routing, external Postgres, and S3 setup, see
|
|
[docs/deploy.md](docs/deploy.md).
|
|
|
|
For the browser admin console, its routes, auth model, and production
|
|
troubleshooting, see [docs/admin.md](docs/admin.md).
|
|
|
|
---
|
|
|
|
## Database & migrations
|
|
|
|
One EF migration (`Migrations/<timestamp>_Initial.cs`) captures the
|
|
schema. SQLite dev DBs apply it via `Database.Migrate()`; Postgres uses
|
|
`EnsureCreated()` behind a transaction-scoped advisory lock. The
|
|
entity model is the single source of truth — to add a column, edit the
|
|
entity, boot, done (on SQLite — Postgres prod needs a migration).
|
|
|
|
Data transforms that can't be schema (seed renames, computed backfills)
|
|
go in [`DorkNet.Server/Data/LegacyUpgrades.cs`](DorkNet.Server/Data/LegacyUpgrades.cs).
|
|
See [`DorkNet.Server/Data/MIGRATIONS.md`](DorkNet.Server/Data/MIGRATIONS.md)
|
|
for the full discipline.
|
|
|
|
Tables added after the consolidated `Initial` migration (e.g.
|
|
`SignupCodes` / `PendingDevices`) are created by an idempotent
|
|
`CREATE TABLE IF NOT EXISTS` step in
|
|
[`Startup/DatabaseBootstrap.cs`](DorkNet.Server/Startup/DatabaseBootstrap.cs)
|
|
so both providers pick them up on existing DBs without a new migration
|
|
(the Postgres path is `EnsureCreated`-only and never replays migrations).
|
|
|
|
### Signup codes
|
|
|
|
When account creation is disabled (admin **Settings → Server**), the only
|
|
way in is an admin-issued single-use **signup code**: generate one in the
|
|
admin panel's **Settings → Signup codes** tab (with a descriptor + optional expiry),
|
|
hand it to the player, and they redeem it on the site's **`/join`** page —
|
|
which creates their account bound to the device their game client
|
|
reported, so the next launch logs straight in.
|
|
|
|
### Everyone-is-friends toggle
|
|
|
|
For small servers where searching + friend-requesting each other is
|
|
friction, admin **Settings → Server → "Everyone is friends"** makes every
|
|
account a friend of every other account. It writes **no** relationship
|
|
rows — the friend graph is synthesized at read time
|
|
(`RelationshipQueries.EffectiveFriendIdsAsync`, gated on
|
|
`ServerSettings.GlobalFriendsEnabled`), so flipping it off reverts
|
|
instantly. Blocks are still honored and the system/coach account is
|
|
excluded, as are auto-generated `Player_NNN` placeholder accounts that
|
|
never set a real username (they only appear if there's a genuine friend
|
|
row). Flipping it broadcasts `RelationshipsInvalid` to every connected
|
|
watch, which calls `Relationships.RefreshList` and re-pulls
|
|
`api/relationships/v2/get` — so players see everyone appear (or disappear)
|
|
**without relogging**. It covers the friends list, the friends-online HUD,
|
|
and room-move presence fan-out.
|
|
|
|
---
|
|
|
|
## Single-server defaults (review before going public)
|
|
|
|
Several values are hardcoded or defaulted for the convenience of running a
|
|
small, trusted, single-operator server. They work out of the box for a group
|
|
of friends but should be reviewed / adapted before exposing the server to the
|
|
public internet:
|
|
|
|
- **Client build version (`appVersion`).** Hardcoded to this branch's client
|
|
build (`20230317`) in the presence/match/notification responses
|
|
(`MatchPlayerController`, `PlayerPresenceController`, `NotificationService`,
|
|
`RoomsController`). It must match the build everyone runs, or players get a
|
|
"version mismatch" and can't join each other. If you serve a different
|
|
client build, change it (ideally hoist it to one shared constant).
|
|
- **No real authentication.** Accounts are keyed by a per-install `deviceId`
|
|
the client generates (`PlayerService.GetOrCreateByDeviceAsync`) — **not** a
|
|
verified identity (Steam ID is deliberately ignored so emulators work).
|
|
Anyone who can reach the server with a patched client gets/creates an
|
|
account. Use **Settings → Server → disable signups** + the
|
|
[signup-code](#signup-codes) flow to gate who can join; there is no password
|
|
wall by default.
|
|
- **First account becomes admin.** The first account created on a fresh DB is
|
|
granted `IsAdmin` so there's always a root admin. On a public server, create
|
|
your admin account first and verify no one else beat you to it.
|
|
- **Online status = Everyone.** Presence reports `StatusVisibility = 0`
|
|
(Everyone) so every player appears online to every other player, matching
|
|
the [everyone-is-friends](#everyone-is-friends-toggle) convenience. A public
|
|
server may instead want to persist and honor each player's own visibility
|
|
preference.
|
|
- **Room / matchmaking capacity.** New matchmade sessions and subrooms default
|
|
to **8** players and are capped at **40** (`GameSessionService`,
|
|
`RoomSceneEntity.MaxPlayers`, admin `MaxCapacity` clamp). The in-game "Max
|
|
Player Count in This Subroom" slider raises it per room (slider ceiling 40).
|
|
- **Avatar unlock clamp.** The wardrobe clamp defaults high
|
|
(`Avatar:MaxUnlockedItems` 4000 / per-slot 1000) for this desktop client —
|
|
tune in config if you change the ownership model.
|
|
- **Hosts / domain.** The apex and per-service subdomains come from
|
|
`DomainConfig` (`Domain:Apex`) / `appsettings`; set these to your own
|
|
domain. The `Everyone-is-friends`, signup-disable, and similar switches live
|
|
in **admin Settings**, not source.
|
|
|
|
None of these are security boundaries as shipped — treat the server as trusted
|
|
LAN/friends infrastructure unless you harden the items above.
|
|
|
|
---
|
|
|
|
## Contributing
|
|
|
|
See [main's CONTRIBUTING guide](../../blob/main/CONTRIBUTING.md) for
|
|
the project-wide rules.
|
|
|
|
Branch-specific: schema changes on this branch don't flow to
|
|
`march-2020-03-10` automatically. If a fix applies to both, cherry-pick
|
|
it across. Don't rebase across branches.
|
|
|
|
---
|
|
|
|
## License
|
|
|
|
[AGPL-3.0](LICENSE). Hosted forks must publish their source.
|