5.1 KiB
Tachyon — voice server for an NGO/LiteNetLib client
A clean-room, protocol-compatible voice server (project name Tachyon) for the Rec Room client's in-room proximity voice. Same clean-room posture as the sibling LuxonServer, but a different, unrelated protocol: compatibility logic is derived from public MIT sources (NGO, the community LiteNetLib transport, LiteNetLib itself) and from black-box observation of network traffic. The stack, bottom-up, is Dissonance over NGO over the RecRoom encrypt layer over LiteNetLib.
Two real clients hear each other through it, in plaintext, with no client patch — and voice is scoped to rooms server-side.
Layout
-
src/+CMakeLists.txt— Tachyon (C++23). Dependency-light: the LiteNetLib transport comes from thevendor/LiteNetLibPPsubmodule, hashing from the official single-header xxHash inthird_party/, and the recflare room lookup from libcurl. -
patches/—0001-tachyon-packet-layer-hook.patch, applied to the LiteNetLibPP submodule at configure time (adds the datagram-layer hook the RecRoom0x11marker needs). Seepatches/README.md. -
docs/ngo-litenetlib-wire.md— the wire specification. Read this first. -
docs/tachyon-findings.md— client static-analysis findings (the full Tachyon stack). -
docs/client-agent-request-*.md— questions to the client-side static-analysis agent. -
tools/decode_lnl.py— decoder for hex-dump captures of LiteNetLib traffic. -
traffic.txt— an early capture of the client failing to connect (see spec §7). -
vendor/litenetlib,vendor/ngo,vendor/mcc— upstream reference clones, git-ignored and not built against; re-create if you need to re-check the spec:mkdir -p vendor && cd vendor git clone --filter=blob:none https://github.com/Unity-Technologies/com.unity.netcode.gameobjects.git ngo git clone --filter=blob:none https://github.com/Unity-Technologies/multiplayer-community-contributions.git mcc git clone --filter=blob:none https://github.com/RevenantX/LiteNetLib.git litenetlib
(A C#/.NET reference implementation lived in reference/ earlier and proved the protocol end to end;
it has been removed now that the C++ server is the product. Old commits still have it.)
Build & run
Needs CMake, a C++23 compiler, libcurl-devel (room lookup) and openssl-devel (blob decryption)
— e.g. sudo dnf install libcurl-devel openssl-devel. vendor/LiteNetLibPP is a submodule, so
clone with it:
git clone --recurse-submodules <repo> # or: git submodule update --init --recursive
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
./build/tachyon --config tachyon.conf # or all-flags; fork+dissonance+0x11+rooms are defaults
Settings load from a key = value config file (--config, see tachyon.conf.example); CLI flags
override it. The RSA private key that decrypts the client's wire blobs (AT/VB/CKA/CIA/CPK)
is set via private_key in the config or --private-key <file> — a .NET RSAKeyValue XML file.
Offline self-test (no network): ./build/tachyon --selftest [batch.hex] — checks packing, batch
build↔parse + hashes (fork & stock), and Dissonance primitives; exit 0 = pass. An optional captured
NGO batch (hex) is fed through the parser.
Flags: --no-fork / --no-dissonance / --no-encrypt / --no-rooms / --room-url <u> /
--room-timeout <ms> / --ds-count-width N, plus logging: -v/--verbose (debug: per-message +
per-relay), -q/--quiet (warnings/errors only), --log-level error|warn|info|debug. The default
is info — a startup banner plus connect/disconnect/handshake lifecycle and all warnings, quiet
enough to run as a service. It logs to stdout (line-buffered) and shuts down cleanly on SIGINT/SIGTERM
(exit 0), so a minimal systemd unit is just:
[Service]
ExecStart=/path/to/tachyon --port 7777 --quiet
Restart=on-failure
With --verbose, a connection walks through, in order: LiteNetLib connect accepted →
ConnectionRequest parsed → ConnectionApproved sent → room resolved (account=… -> room=…) →
Dissonance HandshakeResponse → ClientState roster relays → [relay] … delivered=1/1 when
same-room clients talk.
Current status
Works end to end against the real client (build 20250718.01): LiteNetLib (ProtocolId 13) + RecRoom
0x11 marker + forked NGO batch + the Tachyon "Carrot" approval + the Dissonance session/relay,
all plaintext. Same-room clients hear each other; cross-room is silent; room membership follows
players live as they switch rooms (resolved per handshake from recflare).
Scope
Connection handshake, time sync, the Dissonance session handshake, voice relay (ServerRelay unwrap +
per-client fan-out), and server-side room scoping. Rooms come from recflare
(GET <room-url>?id=<AccountId> → room instance id — there is no room id on the wire); each room
gets its own Dissonance session, and the relay/roster are scoped to same-room peers, with a
lookup-failure fail-safe that isolates the client. There is no object replication, no NetworkVariable
sync and no scene management — the client build does not contain those message types.