ScriptCompiler.Compile() runs `dotnet build Scripts/Scripts.csproj -c Release` with no Platform, so MSBuild defaults to AnyCPU. Scripts.csproj gated both OutputPath and DefineConstants on Configuration|Platform == Release|x64, so under the server's own build the DLL landed in Scripts/bin/Release/ (while the core loads Scripts.dll from the base directory) and TRACE;NEWTIMERS;ServUO went undefined (XmlSpawner compiled its non-ServUO branches). Compile() also never checks the build's exit code before Assembly.LoadFrom, so the failure was silent and the stale DLL reloaded. Runtime script compilation had had no effect since 2026-05-30. Condition both property groups on Configuration alone. Server.csproj is left alone: nothing under Server/ uses those symbols, and giving it OutputPath=..\ would make the boot-time build try to overwrite the running ServUO.exe. Verified end-to-end: a plain boot now logs "Core: Compiling scripts... / Build succeeded." and loads 206208 items, 42771 mobiles. Also adds the implementation plan, the measured performance budget, the test scaffolding used to produce it (seeder + probe, both default-off), and the record of shard repairs that had to precede any of this. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
uo-link
ServUO ⇄ Rust sidecar bridge. The shard emits newline-delimited JSON over a loopback TCP socket; the sidecar owns the WebSocket the website consumes.
ServUO plugin (C#, net48) ──loopback TCP, newline-JSON──► Rust sidecar ──WebSocket/JSON──► website
(Core-thread reads) ◄──inbound commands─────────────┘ (owns WS, auth, buffering, fan-out)
The shard never speaks WebSocket. Every world read happens on the Core thread; the socket is touched only by a dedicated writer thread draining a bounded queue.
Layout
| Path | What |
|---|---|
overlay/ |
Mirrors the ServUO server root. Everything here copies straight over an install. |
patches/ |
Unified diffs against stock ServUO for files we must modify rather than add. |
docs/PLAN.md |
Implementation plan, measured performance budget, and the full data catalog. |
docs/RESEARCH.md |
Original source-level research. Partly superseded — see the corrections table in PLAN.md §8. |
docs/SHARD_PREREQS.md |
Repairs the target shard needed before any of this could load. |
deploy.ps1 |
Copies overlay/ into a server root. -Verify diffs instead of writing. |
Anything under overlay/ is authoritative. Do not edit files in the server tree directly — edit here and deploy.
Deploy
.\deploy.ps1 -ServerPath C:\Users\colby\Desktop\servuo -Verify # show what would change
.\deploy.ps1 -ServerPath C:\Users\colby\Desktop\servuo # write
Status
| Phase | State |
|---|---|
0 — build fix (Scripts.csproj) |
done, verified end-to-end |
1 — transport (BridgeLink) |
not started |
| 2 — event streams | not started |
| 3 — sweeps | not started |
| 4 — request/response | not started |
5 — [link account linking |
not started |
| 6 — town-crier inbound | not started |
7 — PlayerVendorSale core event |
not started |
| 8 — cheat signals | not started |
Phase 0 — what it fixes
ScriptCompiler.Compile() runs dotnet build Scripts/Scripts.csproj -c Release, prints the output, and never checks the exit code, then Assembly.LoadFrom("Scripts.dll") and returns true. Because that build passed no Platform, MSBuild defaulted to AnyCPU, and Scripts.csproj gated both OutputPath and DefineConstants on Configuration|Platform == Release|x64. So:
- the DLL landed in
Scripts/bin/Release/while the core loadsScripts.dllfrom the base directory, and TRACE;NEWTIMERS;ServUOwent undefined, so XmlSpawner compiled its non-ServUO branches.
Runtime script compilation therefore had no effect, silently. overlay/Scripts/Scripts.csproj conditions both property groups on Configuration alone.
Server.csproj is deliberately left alone: nothing under Server/ uses those symbols, and giving it OutputPath=..\ would make the boot-time build try to overwrite the running ServUO.exe.
Test scaffolding
overlay/Scripts/Custom/BridgeSeeder.cs and BridgeProbe.cs are not part of the bridge. They populate a synthetic world and time the reads the plugin will perform. Both default to off via Config/Bridge.cfg. Delete before production.
| Flag | Effect |
|---|---|
SeedOnStart |
Seed 50 accounts / 150 chars / 30 houses / 30 vendors, then save. Refuses to run twice. |
CensusOnStart |
Read-only report of what the loaded world actually contains. |
ProbeOnStart |
Time profile / vitals / decay / economy / vendor reads on the Core thread. |
In-game: [seedworld, [unseedworld (Administrator).