# 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 — and **only** this — copies over an install. | | `patches/` | Unified diffs against stock ServUO for files we must modify rather than add. | | `tools/` | Never deployed. Test scaffolding and anything else that must not reach a server. | | `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 ```powershell .\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`) | **done, acceptance in `docs/PLAN.md` §11** | | 2 — event streams (`BridgeEvents`) | **done, acceptance in `docs/PLAN.md` §12** | | 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 loads `Scripts.dll` from the base directory, and - `TRACE;NEWTIMERS;ServUO` went 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`. ## The plugin (Phase 1) `overlay/Scripts/Custom/Bridge/`: | File | Responsibility | |------|----------------| | `BridgeConfig.cs` | Reads `Config/Bridge.cfg` in `Configure()`, before `World.Load`. | | `BridgeJson.cs` | Outbound JSON by hand (Core thread, so no reflection serializer). Inbound via `JavaScriptSerializer`. | | `BridgeLink.cs` | The socket. Link thread owns it; a bounded drop-oldest queue fronts it; a reader thread marshals inbound lines to the Core thread. | | `BridgeBoot.cs` | Lifecycle, inbound dispatch, `[bridge status\|reload\|ping]`. | | `BridgeEvents.cs` | EventSink subscriptions (Phase 2). Read-only, player-filtered, never emits secrets. | `Emit()` is called from the Core thread. It enqueues and returns — it never touches the socket, never blocks, never allocates a syscall. **A wedged or absent sidecar cannot stall the shard**, and that is the property everything else depends on. ## Testing `tools/stub_sidecar.ps1` is a loopback listener that logs every line the shard sends. Run it, boot the shard, watch `server.hello` arrive. ```powershell .\tools\stub_sidecar.ps1 -Port 7788 -Log .\sidecar.log ``` `tools/scaffolding/` holds the world seeder and the performance probe. Neither is deployed — `deploy.ps1` only copies `overlay/`. They produced the budget in `docs/PLAN.md` §1. See `tools/scaffolding/README.md`.