ultimatedarktower 4.0.1 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +105 -253
  3. package/dist/esm/index.mjs +2061 -132
  4. package/dist/src/UltimateDarkTower.d.ts +7 -0
  5. package/dist/src/UltimateDarkTower.js +13 -1
  6. package/dist/src/UltimateDarkTower.js.map +1 -1
  7. package/dist/src/adapters/NoopBluetoothAdapter.d.ts +26 -0
  8. package/dist/src/adapters/NoopBluetoothAdapter.js +50 -0
  9. package/dist/src/adapters/NoopBluetoothAdapter.js.map +1 -0
  10. package/dist/src/data/board/index.d.ts +9 -0
  11. package/dist/src/data/board/index.js +26 -0
  12. package/dist/src/data/board/index.js.map +1 -0
  13. package/dist/src/data/board/udtBoardAdjacency.d.ts +25 -0
  14. package/dist/src/data/board/udtBoardAdjacency.js +397 -0
  15. package/dist/src/data/board/udtBoardAdjacency.js.map +1 -0
  16. package/dist/src/data/board/udtBoardAnchors.d.ts +34 -0
  17. package/dist/src/data/board/udtBoardAnchors.js +357 -0
  18. package/dist/src/data/board/udtBoardAnchors.js.map +1 -0
  19. package/dist/src/data/board/udtGameBoard.js.map +1 -0
  20. package/dist/src/data/index.d.ts +19 -0
  21. package/dist/src/data/index.js +56 -0
  22. package/dist/src/data/index.js.map +1 -0
  23. package/dist/src/data/udtBoxInventory.d.ts +47 -0
  24. package/dist/src/data/udtBoxInventory.js +679 -0
  25. package/dist/src/data/udtBoxInventory.js.map +1 -0
  26. package/dist/src/data/udtFoes.d.ts +53 -0
  27. package/dist/src/data/udtFoes.js +47 -0
  28. package/dist/src/data/udtFoes.js.map +1 -0
  29. package/dist/src/data/udtGameContent.d.ts +418 -0
  30. package/dist/src/data/udtGameContent.js +293 -0
  31. package/dist/src/data/udtGameContent.js.map +1 -0
  32. package/dist/src/data/udtHeroes.d.ts +30 -0
  33. package/dist/src/data/udtHeroes.js +38 -0
  34. package/dist/src/data/udtHeroes.js.map +1 -0
  35. package/dist/src/data/udtMonuments.d.ts +23 -0
  36. package/dist/src/data/udtMonuments.js +20 -0
  37. package/dist/src/data/udtMonuments.js.map +1 -0
  38. package/dist/src/index.d.ts +2 -5
  39. package/dist/src/index.js +30 -27
  40. package/dist/src/index.js.map +1 -1
  41. package/dist/src/seed/index.d.ts +7 -0
  42. package/dist/src/seed/index.js +24 -0
  43. package/dist/src/seed/index.js.map +1 -0
  44. package/dist/src/seed/udtSeedParser.js.map +1 -0
  45. package/dist/src/seed/udtSystemRandom.js.map +1 -0
  46. package/dist/src/udtBleConnection.d.ts +13 -0
  47. package/dist/src/udtBleConnection.js +66 -19
  48. package/dist/src/udtBleConnection.js.map +1 -1
  49. package/dist/src/udtBluetoothAdapterFactory.d.ts +3 -1
  50. package/dist/src/udtBluetoothAdapterFactory.js +6 -0
  51. package/dist/src/udtBluetoothAdapterFactory.js.map +1 -1
  52. package/dist/src/udtDisplayExports.d.ts +2 -0
  53. package/dist/src/udtDisplayExports.js +26 -0
  54. package/dist/src/udtDisplayExports.js.map +1 -0
  55. package/dist/src/udtTowerResponse.js +1 -2
  56. package/dist/src/udtTowerResponse.js.map +1 -1
  57. package/package.json +2 -2
  58. package/dist/src/udtGameBoard.js.map +0 -1
  59. package/dist/src/udtSeedParser.js.map +0 -1
  60. package/dist/src/udtSystemRandom.js.map +0 -1
  61. /package/dist/src/{udtGameBoard.d.ts → data/board/udtGameBoard.d.ts} +0 -0
  62. /package/dist/src/{udtGameBoard.js → data/board/udtGameBoard.js} +0 -0
  63. /package/dist/src/{udtSeedParser.d.ts → seed/udtSeedParser.d.ts} +0 -0
  64. /package/dist/src/{udtSeedParser.js → seed/udtSeedParser.js} +0 -0
  65. /package/dist/src/{udtSystemRandom.d.ts → seed/udtSystemRandom.d.ts} +0 -0
  66. /package/dist/src/{udtSystemRandom.js → seed/udtSystemRandom.js} +0 -0
package/CHANGELOG.md CHANGED
@@ -6,6 +6,50 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/), and this
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [5.0.0] - 2026-06-20
10
+
11
+ ### Changed
12
+
13
+ - **BREAKING — reference/game data and the seed subsystem moved off the flat root API into the `data` and `seed` namespaces.** The library's exports are now split by concern: tower control / BLE / protocol stay at the root (`UltimateDarkTower`, adapters, state, logger, diagnostics, helpers, all `udtConstants` like `GLYPHS`/`TOWER_AUDIO_LIBRARY` — unchanged), while browseable reference data lives under `data.*` and the seed encode/decode + RNG subsystem under `seed.*`. The modules also moved on disk into `src/data/` (with `src/data/board/`) and `src/seed/`. Migrate imports:
14
+
15
+ | Old (flat, `'ultimatedarktower'`) | New |
16
+ |---|---|
17
+ | `HEROES`, `HERO_BY_ID`, `Hero`, `HeroId`, `ContentSource` | `data.heroes.*` |
18
+ | `MONUMENTS`, `MONUMENT_BY_ID`, `Monument`, `MonumentId` | `data.monuments.*` |
19
+ | `FOE_STATUSES`, `FOES`, `ADVERSARY_ROSTER`, `ALL_FOES`, `FOE_BY_ID`, `FOE_BY_NAME`, `FoeStatus`/`FoeLevel`/`FoeId`/`FoeName`/`Foe` | `data.foes.*` |
20
+ | `BOARD_LOCATIONS`, `BOARD_LOCATION_BY_NAME`, `BOARD_GROUPINGS`, `BOARD_ANCHORS`, `BOARD_IMAGE_INFO`, `BOARD_ADJACENCY`, `neighborsOf`, `stepDistance`, `shortestPath` + board types | `data.board.*` |
21
+ | seed fns (`charToValue`…`dumpSeedChars`), rosters (`TIER1_FOES`…`GAME_SOURCES`), seed types | `seed.*` |
22
+ | `SystemRandom` | `seed.SystemRandom` |
23
+
24
+ Example: `import { HEROES } from 'ultimatedarktower'` → `import { data } from 'ultimatedarktower'; data.heroes.HEROES`. Sub-namespacing also lets the two distinct hero/foe datasets coexist (board roster `data.heroes.HEROES` vs gameplay content `data.content.HEROES`). This is a major (v5.0.0) change; downstream consumers (`ultimatedarktowerboard`, `ultimatedarktowerdigital`) migrate to the namespaces and bump their dependency.
25
+
26
+ ### Added
27
+
28
+ - **`data.content` — gameplay reference content** (`src/data/udtGameContent.ts`). Keyed records with derived union types for the 10 playable heroes (`HEROES` with `defaultVirtues`/`unlockableVirtues`/`bannerAction`), the level 2–4 `FOES` and level-5 `ADVERSARIES`, `COMPANIONS`, and `KINGDOM_VIRTUES` (keyed East/North/South/West), plus list views (`heroes`/`foes`/`adversaries`/`companions`/`kingdomVirtues`). Uses the official spreadsheet wording — intentionally **not** reconciled with `TOWER_AUDIO_LIBRARY` keys (e.g. "Isa The Exile" vs the audio cue `IsatheHollow`).
29
+ - **`data.inventory` — box component counts** (`src/data/udtBoxInventory.ts`). `expansions` / `EXPANSIONS` (Base Game, Alliances, Covenant, Dark Horde) of categorized `Component` line-items, plus `coffers`, `coffers2`, `skullsPack`, and `sleeves`.
30
+
31
+ ## [4.1.0] - 2026-06-18
32
+
33
+ ### Added
34
+
35
+ - **`onTowerResponse` public callback (`UltimateDarkTower`).** A new assignable hook that fires with the **raw, verbatim bytes** (`Uint8Array`) of every non-battery tower notification (tower-state responses, command acknowledgements). It complements the decoded `onTowerStateUpdate` for consumers that need the exact packet rather than the parsed `TowerState` — e.g. a relay forwarding the tower's 20-byte state to other consumers. Documented in `docs/api/events.md`.
36
+ - **Hero + monument reference rosters (`src/udtHeroes.ts`, `src/udtMonuments.ts`).** New static rosters consumed by `ultimatedarktowerboard` (re-exported, not vendored); neither is seed-encoded. `HEROES` is the 14 heroes (4 base, 2 Alliances, 4 Covenant, 4 Expeditions — Expeditions provisional/unreleased) and `MONUMENTS` is the 8 Covenant monuments, each modeled as `{ id, name, source }` objects with `HERO_BY_ID` / `MONUMENT_BY_ID` lookups and `Hero`/`HeroId`/`Monument`/`MonumentId` types (per the data-additions plan §4/§6). `source` is a new `ContentSource` type (`'base' | 'alliances' | 'covenant' | 'expeditions'`) — distinct from the seed parser's `ExpansionType` and from `GameSource`. The Astromancer uses the Restoration Games store spelling, **Reverent**. (Supersedes the brief flat-string `MONUMENTS` added earlier in this Unreleased cycle.)
37
+ - **Board layout anchors + adjacency datasets** — two new data modules consumed by the `ultimatedarktowerboard` package (re-exported, not vendored). `udtBoardAnchors.ts` ships `BOARD_ANCHORS` (multi-slot `building`/`skull`/`hero`/`foe`/`marker` positions, normalized `[0,1]`, for all 60 locations) and `BOARD_IMAGE_INFO` (board-image size + circle center/radius + north heading), with types `Anchor`, `AnchorSlot`, `LocationAnchors`, `BoardAnchorMap`, `BoardImageInfo`. `udtBoardAdjacency.ts` ships `BOARD_ADJACENCY` (the undirected movement graph) plus pure BFS helpers `neighborsOf` / `stepDistance` / `shortestPath` and the `BoardAdjacency` type. Authored with `tools/location-marker` and generated by `tools/location-marker/gen-board-data.mjs` from `udtBoardData.json`; the graph reflects physical adjacency only (disconnected pairs → `Infinity`) and enforces no movement rules.
38
+ - **`BluetoothPlatform.NONE` + no-op adapter** — a software-only mode for consumers that hold tower state (broken seals, rendering) but never open a BLE connection. `new UltimateDarkTower({ platform: BluetoothPlatform.NONE })` returns a `NoopBluetoothAdapter` that reports "not connected" and throws a clear error if `connect()`/commands are attempted.
39
+
40
+ ### Fixed
41
+
42
+ - **Tower Emulator now plays the calibration sweep when "Calibrate" is pressed** — In the Tower Controller example, calibrating against the emulator only flipped the drums' calibrated flags; the 3D popup never ran the animated home sweep (top→middle→bottom) the way the Display package's own example does. The popup display only runs `runCalibration()` when an applied state carries the transient `command: TOWER_COMMANDS.calibration` marker, but the controller mirrors the plain BLE state (which has no `command` field), so the drums just snapped to "calibrated". The controller now sends a dedicated `calibrate` side-channel message to the popup on click (mirroring the existing `playAudio`/`playSequence` side-channels), and the popup stamps the command onto its current state to trigger the visual sweep. The popup also ignores the emulator's interim mirrored state (~1.5 s in) while its own sweep is animating so the staged sweep isn't cut short. The emulator imports `TOWER_COMMANDS`/`createDefaultTowerState` from the cycle-free `udtDisplayExports` barrel to stay clear of the bundle's circular dependency.
43
+
44
+ - **`npm run build` no longer fails on the Tower Emulator bundle** — `build:examples` aliases the bundled `ultimatedarktower` specifier to a constants-only module (not `index.ts`) to dodge the `UltimateDarkTower.ts` circular dependency that breaks the display package's module-level constant init. The display's `TowerDisplay.ts` imports `createDefaultTowerState`, which lives in `udtHelpers.ts` rather than `udtConstants.ts`, so esbuild failed with *"No matching export for import 'createDefaultTowerState'"*. Added a cycle-free barrel `src/udtDisplayExports.ts` (re-exports `udtConstants` + the pure `createDefaultTowerState` helper) and pointed the emulator alias at it.
45
+
46
+ - **Construction no longer throws in environments without Bluetooth** — Bluetooth platform detection is now deferred from the `UltimateDarkTower` constructor to `connect()`. Previously `new UltimateDarkTower()` with the default `AUTO` platform called `detectPlatform()` eagerly and threw *"Unable to detect Bluetooth platform"* where Web Bluetooth is unavailable (e.g. iOS Safari/Chrome — all iOS browsers use WebKit), crashing software-only consumers on load. The adapter is now created lazily on first `connect()`, so that error (if any) surfaces only when a connection is actually attempted. Explicit `WEB`/`NODE`/`NONE` still create eagerly.
47
+
48
+ ### Changed
49
+
50
+ - **Documentation restructured** — Slimmed `README.md` to a hero page with screenshot strip, quickstart, and a documentation map. Split the 1,900-line `docs/API_REFERENCE.md` into focused topic files under `docs/api/` (connection, adapters, commands, state, events, logging, seed, diagnostics) plus an index at `docs/api/README.md`. Added new top-level docs: `docs/README.md` (hub), `docs/GETTING_STARTED.md` (tutorial), `docs/ARCHITECTURE.md` (layer diagrams + lifecycle), `docs/EXAMPLES.md` (what each demo demonstrates), `docs/ECOSYSTEM.md` (companion repos). Renamed `docs/TOWER_TROUBLESHOOTING_RG.md` → `docs/TROUBLESHOOTING.md`. Embedded real nRF Connect screenshots of the tower's BLE service tree in `docs/TOWER_TECH_NOTES.md` and added a Mermaid layer/position anatomy diagram. Added README files for the controller and game example apps. Replaced `docs/API_REFERENCE.md` with a stub that redirects to the new `docs/api/` index. Removed the obsolete `examples/controller/TOWER_EMULATOR_NPM_MIGRATION.md`.
51
+ - **API reference: board-data page + full coverage pass.** Added `docs/api/board-data.md` documenting the board geometry (`BOARD_LOCATIONS`/`BOARD_GROUPINGS`, `BOARD_ANCHORS`/`BOARD_IMAGE_INFO`, `BOARD_ADJACENCY` + `neighborsOf`/`stepDistance`/`shortestPath`) and the hero/monument/foe reference rosters — previously only mentioned in `ECOSYSTEM.md`. Backfilled the remaining un-referenced exports into their topic pages (`Confidence` + base-34 char helpers in seed, `DisconnectCause`/`DiagEventKind`/`BatterySample`/`CommandQueueSnapshot` in diagnostics, `TowerEventCallbacks` in events, `LogLevel`/`LogOutput` in logging, `parseDifferentialReadings` in state) so every public export now has a reference entry. Added the shared `docs/API_STYLE.md` standard plus a breadcrumb + changelog pointer on the API index.
52
+
9
53
  ## [4.0.1] - 2026-05-28
10
54
 
11
55
  ### Fixed
package/README.md CHANGED
@@ -1,294 +1,146 @@
1
- # UltimateDarkTower
2
-
3
- [![npm version](https://img.shields.io/npm/v/ultimatedarktower)](https://www.npmjs.com/package/ultimatedarktower)
4
- [![npm downloads](https://img.shields.io/npm/dm/ultimatedarktower)](https://www.npmjs.com/package/ultimatedarktower)
5
- [![license](https://img.shields.io/npm/l/ultimatedarktower)](LICENSE)
6
- [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue)](https://www.typescriptlang.org/)
7
- [![node](https://img.shields.io/node/v/ultimatedarktower)](https://nodejs.org/)
8
-
9
- A JavaScript/TypeScript library for controlling the Bluetooth-enabled tower from Restoration Games' Return to Dark Tower board game. Control lights, sounds, drum rotation, and track game state via Bluetooth - works in browsers (Web Bluetooth), Node.js, Electron, and React Native.
10
-
11
- I have spent many hours reverse engineering the Tower's protocol in order to create this library, I look forward to what others will create using this! - Chris
12
-
13
- ## Live Examples
14
-
15
- Try the library in action! Just power on your Tower and visit:
16
-
17
- - **[Tower Controller](https://chessmess.github.io/UltimateDarkTower/dist/examples/controller/TowerController.html)** - Replicates official app functionality and gives examples of library functionality.
18
-
19
- _Requires Web Bluetooth support (Chrome, Edge, Samsung Internet). For iOS, use the [Bluefy app](https://apps.apple.com/us/app/bluefy-web-ble-browser/id1492822055)._
20
-
21
- ## Table of Contents
22
-
23
- - [UltimateDarkTower](#ultimatedarktower)
24
- - [Live Examples](#live-examples)
25
- - [Table of Contents](#table-of-contents)
26
- - [Features](#features)
27
- - [Installation](#installation)
28
- - [Browser / Web Applications](#browser--web-applications)
29
- - [Node.js Applications](#nodejs-applications)
30
- - [Quick Start](#quick-start)
31
- - [Browser (auto-detected)](#browser-auto-detected)
32
- - [Node.js (auto-detected)](#nodejs-auto-detected)
33
- - [Explicit Platform Selection](#explicit-platform-selection)
34
- - [Custom Adapter (React Native, etc.)](#custom-adapter-react-native-etc)
35
- - [Documentation](#documentation)
36
- - [📖 Complete API Reference](#-complete-api-reference)
37
- - [Key Topics Covered:](#key-topics-covered)
38
- - [Integration Testing](#integration-testing)
39
- - [Lights Integration Test](#lights-integration-test)
40
- - [Development](#development)
41
- - [Building and Testing](#building-and-testing)
42
- - [Project Structure](#project-structure)
43
- - [Platform Support](#platform-support)
44
- - [Built-in Support (auto-detected)](#built-in-support-auto-detected)
45
- - [Custom Adapter Support](#custom-adapter-support)
46
- - [Browser Support](#browser-support)
47
- - [Known Issues](#known-issues)
48
- - [Community](#community)
49
-
50
- ## Features
51
-
52
- - **Multi-Platform Bluetooth** - Works in browsers (Web Bluetooth), Node.js (`@stoprocent/noble`), Electron, and React Native via custom adapters
53
- - **Bluetooth Connection Management** - Reliable connection with automatic monitoring and disconnect detection
54
- - **Tower Control** - Complete control over lights, sounds, and drum rotation
55
- - **Game State Tracking** - Track glyph positions, broken seals, and skull counts
56
- - **Event System** - Callback-based event handling for tower events
57
- - **ESM + CJS** - Ships both an ES Module build and a CommonJS build; works with `import` and `require` without configuration
58
- - **TypeScript Support** - Full TypeScript definitions and type safety
59
- - **Comprehensive Logging** - Multi-output logging system for debugging
60
- - **Battery Monitoring** - Real-time battery level tracking and low battery warnings
61
- - **Extensible Adapter Pattern** - Implement `IBluetoothAdapter` for custom platforms
62
-
63
- ## Installation
64
-
65
- ### Browser / Web Applications
1
+ <p align="center">
2
+ <img src="examples/assets/rtdtlogo.png" alt="Return to Dark Tower" width="420" />
3
+ </p>
4
+
5
+ <h1 align="center">UltimateDarkTower</h1>
6
+
7
+ <p align="center">
8
+ TypeScript / JavaScript driver for the Bluetooth-enabled tower from Restoration Games' <em>Return to Dark Tower</em>.<br/>
9
+ Control lights, sounds, drum rotation, and track game state from browsers, Node.js, Electron, and React Native.
10
+ </p>
11
+
12
+ <p align="center">
13
+ <a href="https://www.npmjs.com/package/ultimatedarktower"><img alt="npm version" src="https://img.shields.io/npm/v/ultimatedarktower"></a>
14
+ <a href="https://www.npmjs.com/package/ultimatedarktower"><img alt="npm downloads" src="https://img.shields.io/npm/dm/ultimatedarktower"></a>
15
+ <a href="https://github.com/ChessMess/UltimateDarkTower/actions/workflows/ci-matrix.yml"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/ChessMess/UltimateDarkTower/ci-matrix.yml?branch=main&label=CI"></a>
16
+ <a href="LICENSE"><img alt="license" src="https://img.shields.io/npm/l/ultimatedarktower"></a>
17
+ <a href="https://www.typescriptlang.org/"><img alt="TypeScript" src="https://img.shields.io/badge/TypeScript-Ready-blue"></a>
18
+ <a href="https://nodejs.org/"><img alt="node" src="https://img.shields.io/node/v/ultimatedarktower"></a>
19
+ </p>
20
+
21
+ ---
22
+
23
+ <p align="center"><strong>
24
+ <a href="https://chessmess.github.io/UltimateDarkTower/dist/examples/controller/TowerController.html">▶ Live Demo — Tower Controller</a>
25
+ </strong></p>
26
+
27
+ <p align="center"><em>
28
+ Power on your Tower and connect from Chrome / Edge / Samsung Internet or leave it in the box and use the built in Tower Emulator with full 3D rendered Tower!
29
+ </p><p align="center">
30
+ iOS users: Safari and Chrome doesn't support Web Bluetooth yet on Apples platform (works fine in Chrome on Android), you can use an app on the appstore that provides this feature. </br>Open the demo in the <a href="https://apps.apple.com/us/app/bluefy-web-ble-browser/id1492822055">Bluefy app</a>.
31
+ </em></p>
32
+
33
+ <table>
34
+ <tr>
35
+ <td align="center" width="34%"><a href="examples/controller/README.md"><img src="docs/screenshots/controller-thumb.png" alt="Controller example" /><br/><strong>Controller</strong></a><br/><sub>Full command surface + BLE diagnostics</sub></td>
36
+ <td align="center" width="33%"><a href="examples/game/README.md"><strong>Game</strong></a><br/><sub>A complete playable game on the tower</sub><br/><br/><em>(screenshot soon)</em></td>
37
+ <td align="center" width="33%"><a href="examples/node/README.md"><strong>Node CLI</strong></a><br/><sub>Minimal command-line driver</sub><br/><br/><em>(screenshot soon)</em></td>
38
+ </tr>
39
+ </table>
40
+
41
+ ---
42
+
43
+ ## Install
66
44
 
67
45
  ```bash
46
+ # Browser
68
47
  npm install ultimatedarktower
69
- ```
70
48
 
71
- ### Node.js Applications
72
-
73
- ```bash
49
+ # Node.js (adds the optional BLE peer dependency)
74
50
  npm install ultimatedarktower @stoprocent/noble
75
51
  ```
76
52
 
77
- > `@stoprocent/noble` is an optional peer dependency for BLE support in Node.js environments.
78
- >
79
- > **Platform requirements:** macOS works out of the box. Linux requires BlueZ (`sudo apt install bluetooth bluez libbluetooth-dev`). Windows requires Windows 10+ with BLE support.
53
+ > **Platform notes.** Node.js 18+. macOS works out of the box. Linux needs BlueZ (`sudo apt install bluetooth bluez libbluetooth-dev`). Windows needs Windows 10+ with BLE support.
80
54
 
81
- ## Quick Start
82
-
83
- ### Browser (auto-detected)
55
+ ## Quick start
84
56
 
85
57
  ```typescript
86
58
  import UltimateDarkTower from 'ultimatedarktower';
87
59
 
88
60
  const tower = new UltimateDarkTower();
89
- await tower.connect(); // Opens browser device picker
90
- await tower.calibrate();
91
- await tower.playSound(1);
92
- await tower.cleanup();
93
- ```
94
-
95
- ### Node.js (auto-detected)
96
61
 
97
- ```typescript
98
- import UltimateDarkTower from 'ultimatedarktower';
62
+ tower.onTowerConnect = () => console.log('Connected.');
63
+ tower.onCalibrationComplete = () => console.log('Calibrated.');
99
64
 
100
- const tower = new UltimateDarkTower();
101
- await tower.connect(); // Scans for device automatically
102
- await tower.calibrate();
65
+ await tower.connect(); // browser: opens device picker; node: scans
66
+ await tower.calibrate(); // required before drum rotation is reliable
103
67
  await tower.playSound(1);
104
- await tower.cleanup();
105
- ```
106
-
107
- ### Explicit Platform Selection
108
-
109
- ```typescript
110
- import UltimateDarkTower, { BluetoothPlatform } from 'ultimatedarktower';
111
-
112
- const tower = new UltimateDarkTower({ platform: BluetoothPlatform.NODE });
68
+ await tower.cleanup(); // always clean up on shutdown
113
69
  ```
114
70
 
115
- ### Custom Adapter (React Native, etc.)
71
+ > Walkthrough with explanations, error handling, lights, drum rotation, and a full example: [docs/GETTING_STARTED.md](docs/GETTING_STARTED.md).
116
72
 
117
- ```typescript
118
- import UltimateDarkTower, { IBluetoothAdapter } from 'ultimatedarktower';
119
-
120
- class MyCustomAdapter implements IBluetoothAdapter {
121
- // Implement all IBluetoothAdapter methods
122
- // See docs/API_REFERENCE.md for the full interface
123
- }
73
+ ## Features
124
74
 
125
- const tower = new UltimateDarkTower({ adapter: new MyCustomAdapter() });
126
- ```
75
+ - **Multi-platform Bluetooth** Web Bluetooth, Node.js (`@stoprocent/noble`), Electron, React Native via custom adapters.
76
+ - **Complete tower control** — lights, sounds, drum rotation, seal breaking, skull counter.
77
+ - **Stateful command variants** — preserve every other state when changing one field.
78
+ - **Glyph tracking** — automatic glyph position updates as drums rotate.
79
+ - **Game state** — seal state, broken seals, software-tracked across sessions.
80
+ - **BLE flight recorder** — opt-in disconnect diagnostics with structured event capture.
81
+ - **Event callbacks** — connect, calibrate, skull drop, battery, state change.
82
+ - **Logger** — pluggable outputs (console, DOM, in-memory buffer).
83
+ - **TypeScript-first** — full type definitions, ESM + CJS builds.
84
+ - **Seed parser** — decode, encode, validate, and compare game seeds.
127
85
 
128
86
  ## Documentation
129
87
 
130
- ### 📖 [Complete API Reference](docs/API_REFERENCE.md)
131
-
132
- Comprehensive documentation with TypeScript examples, best practices, and troubleshooting guides.
133
-
134
- ### 📄 [Seed Format Specification](docs/SEED_FORMAT.md)
135
-
136
- Complete documentation of the Return to Dark Tower game seed encoding — base-34 alphabet, setup section bitwise layout, RNG seed polynomial, and what each seed field controls.
137
-
138
- ### 🛠 [BLE Diagnostics (Flight Recorder)](docs/BLE_DIAGNOSTICS.md)
139
-
140
- Opt-in diagnostic system for capturing BLE disconnect incidents. Tags each detection path, snapshots connection / queue / tower state at the moment of the drop, and includes a ring buffer of recent events so you can see the lead-up. Off by default; the controller example has a "BLE Debug" tab that exposes the full UI (toggle, live event stream, persistent incident log, JSON export).
141
-
142
- ### Key Topics Covered:
143
-
144
- - **Multi-Platform Setup** - Configuration for Web, Node.js, Electron, and React Native
145
- - **Connection Management** - Connecting, disconnecting, and monitoring connection health
146
- - **Bluetooth Adapters** - Custom adapter interface for extending platform support
147
- - **Tower Control** - Detailed coverage of all tower commands (lights, sounds, rotation)
148
- - **Glyph System** - Automatic tracking of glyph positions as towers rotate
149
- - **Seal Management** - Breaking seals and tracking game state
150
- - **Seed Parser** - Decode, encode, validate, and compare game seeds
151
- - **SystemRandom** - C# System.Random PRNG replica for game state prediction
152
- - **Event Handling** - Callback system for tower events
153
- - **Logging System** - Multi-output logging for debugging and monitoring
154
- - **Best Practices** - Performance tips, error handling, and common patterns
155
- - **Troubleshooting** - Solutions for common issues and debugging techniques
156
-
157
- ## Integration Testing
88
+ A guided map of the docs lives at [docs/README.md](docs/README.md). The headline pages:
158
89
 
159
- Integration tests that require real hardware are located in `tests/integration/` and are not run by default with the main test suite. These tests use the Node.js Bluetooth adapter and require a physical Return to Dark Tower device in range.
90
+ | Page | Use it when… |
91
+ | -------------------------------------------- | --------------------------------------------------- |
92
+ | [Getting Started](docs/GETTING_STARTED.md) | …you're new and want a working tower in 10 minutes. |
93
+ | [API Reference](docs/api/README.md) | …you need the full surface, split by topic. |
94
+ | [Architecture](docs/ARCHITECTURE.md) | …you want to understand how the layers fit. |
95
+ | [Examples](docs/EXAMPLES.md) | …you want to know what the demo apps demonstrate. |
96
+ | [Tower Tech Notes](docs/TOWER_TECH_NOTES.md) | …you're reverse-engineering the protocol. |
97
+ | [Seed Format](docs/SEED_FORMAT.md) | …you're working with game seeds at the byte level. |
98
+ | [BLE Diagnostics](docs/BLE_DIAGNOSTICS.md) | …you want disconnect flight-recorder data. |
99
+ | [Troubleshooting](docs/TROUBLESHOOTING.md) | …the hardware is misbehaving. |
100
+ | [Ecosystem](docs/ECOSYSTEM.md) | …you want the companion libraries & tools. |
160
101
 
161
- To run the calibration integration test:
102
+ ## Examples
162
103
 
163
- ```bash
164
- npm run test:integration
165
- ```
166
-
167
- - This will connect to the tower, perform a full calibration sequence, and print the resulting glyph positions.
168
- - The test will fail if the tower is not available or calibration does not complete within 60 seconds.
169
- - Integration tests are not included in automated test runs or npm publish.
170
-
171
- ### Lights Integration Test
172
-
173
- The lights integration test validates the `allLightsOn` and `allLightsOff` API methods using real tower hardware.
174
-
175
- **Test steps:**
176
-
177
- - Turns all 24 LEDs on (solid effect) for 2 seconds
178
- - Turns all 24 LEDs on (breathe effect) for 3 seconds
179
- - Turns all 24 LEDs off
180
-
181
- **How to run:**
182
-
183
- ```bash
184
- npm run test:integration:lights
185
- ```
186
-
187
- **Prerequisites:**
188
-
189
- - Tower must be powered on and in Bluetooth range
190
- - `@stoprocent/noble` must be installed
191
-
192
- **Visual verification:**
193
-
194
- - All lights on (solid) for 2 seconds
195
- - All lights breathe effect for 3 seconds
196
- - All lights off
197
-
198
- See [API_REFERENCE.md](docs/API_REFERENCE.md) for API details on `allLightsOn` and `allLightsOff`.
104
+ - **[Controller](examples/controller/README.md)** — full reference UI with a BLE diagnostics tab and tower emulator.
105
+ - **[Game](examples/game/README.md)** — The Tower's Challenge, a complete browser game.
106
+ - **[Node CLI](examples/node/README.md)** — minimal interactive driver for verifying the Node adapter.
199
107
 
200
- **Prerequisites:**
108
+ ## Platform support
201
109
 
202
- - Tower must be powered on and in Bluetooth range
203
- - `@stoprocent/noble` must be installed (it is a peer dependency)
110
+ | Platform | Adapter | Notes |
111
+ | ---------------------------------------------------- | -------------- | ------------------------------------------------------------------------------- |
112
+ | Chrome / Edge / Samsung Internet (desktop + Android) | Built-in | Web Bluetooth |
113
+ | Node.js 18+ | Built-in | Requires `@stoprocent/noble` |
114
+ | Electron | Built-in | Auto-detects renderer vs main process |
115
+ | iOS Safari / iOS Chrome | — | Use [Bluefy](https://apps.apple.com/us/app/bluefy-web-ble-browser/id1492822055) |
116
+ | Firefox | — | No Web Bluetooth |
117
+ | React Native | Custom adapter | `react-native-ble-plx` recommended — see [adapters guide](docs/api/adapters.md) |
118
+ | Cordova / Capacitor | Custom adapter | See [adapters guide](docs/api/adapters.md) |
204
119
 
205
- ## Development
120
+ ## Related projects
206
121
 
207
- ### Building and Testing
122
+ This library is part of a wider Return to Dark Tower family. See [docs/ECOSYSTEM.md](docs/ECOSYSTEM.md) for the full list. Highlights:
208
123
 
209
- ```bash
210
- # Install dependencies
211
- npm install
212
-
213
- # Build the project
214
- npm run build
215
-
216
- # Run tests
217
- npm test
218
-
219
- # Run tests with coverage
220
- npm run test:coverage
221
-
222
- # Lint code
223
- npm run lint
224
-
225
- # Watch mode for development
226
- npm run watch
227
- ```
228
-
229
- ### Project Structure
124
+ - **[UltimateDarkTowerDisplay](https://github.com/ChessMess/UltimateDarkTowerDisplay)** — composable renderers (text, 2D, 3D) for tower state.
125
+ - **[UltimateDarkTowerSync](https://github.com/ChessMess/UltimateDarkTowerSync)** — state synchronization across devices.
126
+ - **[mcp-server-return-to-dark-tower](https://github.com/ChessMess/mcp-server-return-to-dark-tower)** — MCP server exposing tower control to AI agents.
230
127
 
231
- ```
232
- src/
233
- ├── index.ts # Main exports
234
- ├── UltimateDarkTower.ts # Main class
235
- ├── udtBluetoothAdapter.ts # Bluetooth adapter interface & error types
236
- ├── udtBluetoothAdapterFactory.ts # Platform auto-detection factory
237
- ├── udtBleConnection.ts # Bluetooth connection management
238
- ├── udtTowerCommands.ts # Tower command implementations
239
- ├── udtCommandFactory.ts # Command creation utilities
240
- ├── udtCommandQueue.ts # Command queue management
241
- ├── udtTowerResponse.ts # Response handling
242
- ├── udtTowerState.ts # Tower state management
243
- ├── udtGameBoard.ts # Board locations, kingdoms, and terrain data
244
- ├── udtSeedParser.ts # Game seed encoding/decoding (base-34)
245
- ├── udtSystemRandom.ts # C# System.Random PRNG replica
246
- ├── udtHelpers.ts # Utility helper functions
247
- ├── udtLogger.ts # Logging system
248
- ├── udtConstants.ts # Constants and type definitions
249
- └── adapters/
250
- ├── WebBluetoothAdapter.ts # Browser Web Bluetooth implementation
251
- └── NodeBluetoothAdapter.ts # Node.js @stoprocent/noble BLE implementation
252
-
253
- examples/
254
- ├── controller/ # Tower controller web app
255
- ├── game/ # Tower game web app
256
- ├── node/ # Node.js CLI example
257
- └── assets/ # Shared assets (images, fonts, etc.)
258
- ```
259
-
260
- ## Platform Support
261
-
262
- ### Built-in Support (auto-detected)
128
+ ## Known issues
263
129
 
264
- | Platform | Bluetooth Library | Notes |
265
- | -------------------------------- | ------------------------------------ | ---------------------------------------- |
266
- | Chrome / Edge / Samsung Internet | Web Bluetooth API | Desktop and Android |
267
- | Node.js | `@stoprocent/noble` | Requires `npm install @stoprocent/noble` |
268
- | Electron | Web Bluetooth or `@stoprocent/noble` | Auto-detects renderer vs main process |
130
+ - **Sound and animation completion** — the tower reports "command complete" the moment a sound or animation _starts_, not when it ends. Don't use the completion response as a "ready for next sound" signal; sleep or use the LED-sequence response timing documented in [docs/TOWER_TECH_NOTES.md](docs/TOWER_TECH_NOTES.md#animation-response-timing).
269
131
 
270
- ### Custom Adapter Support
132
+ ## Contributing
271
133
 
272
- | Platform | Recommended Library | Notes |
273
- | -------------------------- | ---------------------- | ----------------------------- |
274
- | React Native | `react-native-ble-plx` | Implement `IBluetoothAdapter` |
275
- | iOS (via React Native) | `react-native-ble-plx` | Same as React Native |
276
- | Android (via React Native) | `react-native-ble-plx` | Same as React Native |
277
- | Cordova / Capacitor | Platform BLE plugin | Implement `IBluetoothAdapter` |
134
+ Workflow, code standards, release process, and hardware testing instructions: [CONTRIBUTING.md](CONTRIBUTING.md).
278
135
 
279
- ### Browser Support
280
-
281
- **iOS:** Use the [Bluefy app](https://apps.apple.com/us/app/bluefy-web-ble-browser/id1492822055) as Chrome/Safari does not support Web Bluetooth on Apple platforms.
282
-
283
- **Not Supported:** Firefox, Safari ([compatibility details](https://caniuse.com/?search=web%20bluetooth))
136
+ ## Community
284
137
 
285
- ## Known Issues
138
+ Questions? Ideas? Join us on our UltimateDarkTower [Discord Server](https://discord.gg/njgXj6ay3g)!
286
139
 
287
- - **Sounds** - Sounds show as command complete which is true even though the sound itself has not completed. This is just the way the tower works. I'll have to add time lengths to each at some point, just don't use the command complete response as a way of thinking the associated sound has finished playing and you can play another sound.
288
- - **Light Sequences** - Same as sound for lights that play for a duration.
140
+ You can also find us in the RTDT Fan Content Channel on [Restoration Games Discord](https://discord.com/channels/722465956265197618/1167555008376610945/1167842435766952158).
289
141
 
290
- > See [API_REFERENCE.md](docs/API_REFERENCE.md) for performance best practices and workarounds.
142
+ ---
291
143
 
292
- ## Community
144
+ ## Personal note from the Developer
293
145
 
294
- Questions? Ideas? Join us on our [Discord Server](https://discord.com/channels/722465956265197618/1167555008376610945/1167842435766952158)!
146
+ I have spent many hours reverse engineering the Tower's protocol (by hand, this was before AI existed :D) in order to create this library, I look forward to what others will create using this! - Chris