ultimatedarktowerrelay-client
v0.2.0
Published
UltimateDarkTowerRelay consumer SDK — connect to a relay host over WebSocket, receive decoded tower state, and report participant player actions. Framework-agnostic; browser or Node.
Maintainers
Readme
What this is
A relay host advertises a tower-emulator the official Return to Dark Tower companion app connects to, decodes every 20-byte command, and broadcasts it over WebSocket. This package is what a consumer runs. It speaks the relay's WebSocket protocol so you don't have to: handshake, decoded TowerState events, participant actions, auto-reconnect with backoff, and protocol-version-mismatch handling.
It's isomorphic — use the browser's global WebSocket, or inject the ws package in Node. Consumers fall into two roles:
- Observer / screen-only — render the decoded tower state (LEDs, drum positions, skull drops) without any hardware.
- Participant — has a physical tower or reports player actions; pair
RelayClientwithPhysicalTowerReplayto mirror the host's tower onto a local one over Web Bluetooth.
Install
npm install ultimatedarktowerrelay-clientultimatedarktower is installed alongside it (decoded TowerState types + the PhysicalTowerReplay tower interface).
Quick start
Observer (screen-only, browser)
import { RelayClient } from 'ultimatedarktowerrelay-client';
const client = new RelayClient({
label: 'My Visualizer',
observer: true,
onEvent: (e) => {
if (e.type === 'state') render(e.state); // decoded TowerState
},
});
await client.connect('ws://192.168.1.5:8765');Node consumer
In Node there is no global WebSocket, so inject one:
import { RelayClient } from 'ultimatedarktowerrelay-client';
import WebSocket from 'ws';
const client = new RelayClient({ observer: true, webSocketImpl: WebSocket, onEvent });
await client.connect('ws://192.168.1.5:8765');Participant — mirror the host onto a local tower
import { RelayClient, PhysicalTowerReplay } from 'ultimatedarktowerrelay-client';
import UltimateDarkTower from 'ultimatedarktower';
const tower = new UltimateDarkTower(); // satisfies TowerWriter structurally
const replay = new PhysicalTowerReplay({ tower });
const client = new RelayClient({
label: 'Player 2',
onEvent: (e) => replay.handleEvent(e), // mirrors tower:command + sync:state onto my tower
});
await client.connect('ws://192.168.1.5:8765');
// Report a player action back to the host:
client.dropSkull();Events
onEvent receives a discriminated union (RelayClientEvent). Common types:
| Type | Meaning |
|---|---|
| state | Decoded TowerState + the raw lastCommand. |
| tower:command | Raw 20-byte command with a monotonic seq. |
| sync:state | Late-join catch-up (last command). |
| relay:connected · relay:disconnected · relay:reconnecting | Connection lifecycle. |
| relay:version-mismatch | Host/client PROTOCOL_VERSION disagree. |
| host:status · client:connected · client:disconnected | Room/host status. |
Documentation
- SDK API reference
- WebSocket protocol
- Getting started · Architecture
- Project overview: UltimateDarkTowerRelay
License
MIT. Return to Dark Tower and its art, sounds, and likeness are © Restoration Games. This is an unofficial, fan-made project.
