ultimatedarktower 3.0.0 → 4.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 (46) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/README.md +28 -15
  3. package/dist/esm/index.mjs +1039 -45
  4. package/dist/src/UltimateDarkTower.d.ts +42 -0
  5. package/dist/src/UltimateDarkTower.js +102 -2
  6. package/dist/src/UltimateDarkTower.js.map +1 -1
  7. package/dist/src/adapters/NodeBluetoothAdapter.js +9 -5
  8. package/dist/src/adapters/NodeBluetoothAdapter.js.map +1 -1
  9. package/dist/src/adapters/WebBluetoothAdapter.js +11 -8
  10. package/dist/src/adapters/WebBluetoothAdapter.js.map +1 -1
  11. package/dist/src/index.d.ts +8 -0
  12. package/dist/src/index.js +34 -1
  13. package/dist/src/index.js.map +1 -1
  14. package/dist/src/sinks/IndexedDBSink.d.ts +26 -0
  15. package/dist/src/sinks/IndexedDBSink.js +165 -0
  16. package/dist/src/sinks/IndexedDBSink.js.map +1 -0
  17. package/dist/src/udtBleConnection.d.ts +24 -1
  18. package/dist/src/udtBleConnection.js +68 -2
  19. package/dist/src/udtBleConnection.js.map +1 -1
  20. package/dist/src/udtBluetoothAdapter.d.ts +6 -6
  21. package/dist/src/udtBluetoothAdapter.js.map +1 -1
  22. package/dist/src/udtCommandQueue.d.ts +4 -1
  23. package/dist/src/udtCommandQueue.js +26 -2
  24. package/dist/src/udtCommandQueue.js.map +1 -1
  25. package/dist/src/udtConstants.d.ts +2 -0
  26. package/dist/src/udtConstants.js +2 -0
  27. package/dist/src/udtConstants.js.map +1 -1
  28. package/dist/src/udtDiagnostics.d.ts +122 -0
  29. package/dist/src/udtDiagnostics.js +228 -0
  30. package/dist/src/udtDiagnostics.js.map +1 -0
  31. package/dist/src/udtGameBoard.d.ts +38 -0
  32. package/dist/src/udtGameBoard.js +86 -0
  33. package/dist/src/udtGameBoard.js.map +1 -0
  34. package/dist/src/udtLogger.d.ts +15 -0
  35. package/dist/src/udtLogger.js +17 -0
  36. package/dist/src/udtLogger.js.map +1 -1
  37. package/dist/src/udtSeedParser.d.ts +124 -0
  38. package/dist/src/udtSeedParser.js +369 -0
  39. package/dist/src/udtSeedParser.js.map +1 -0
  40. package/dist/src/udtSystemRandom.d.ts +58 -0
  41. package/dist/src/udtSystemRandom.js +154 -0
  42. package/dist/src/udtSystemRandom.js.map +1 -0
  43. package/dist/src/udtTowerCommands.d.ts +2 -0
  44. package/dist/src/udtTowerCommands.js +7 -29
  45. package/dist/src/udtTowerCommands.js.map +1 -1
  46. package/package.json +5 -1
package/CHANGELOG.md CHANGED
@@ -6,6 +6,48 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/), and this
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [4.0.0] - 2026-05-28
10
+
11
+ - **Tower Emulator has been added** — Utilising the UltimateDarkTowerDisplay the example app can now connect to a software rendered version of the tower. The controller and the software tower share actual packets, so this can be a useful feature for testing certain features of both the UDT library and the UDT Display Library.
12
+
13
+ ### Fixed
14
+
15
+ - **Eliminated all 85 `@typescript-eslint/no-explicit-any` lint warnings** — All `any` types across source and test files replaced with proper TypeScript types (`unknown`, type-narrowed catch blocks, typed mock helpers, typed cast chains). Also added a `no-undef` disable comment for the `globalThis` usage in `udtDiagnostics.ts`. Local interface declarations for the Web Bluetooth API (`BluetoothDevice`, `BluetoothRemoteGATTCharacteristic`, etc.) were added to `WebBluetoothAdapter.ts` since these types are not included in TypeScript's standard DOM lib. The codebase now reports `0 problems (0 errors, 0 warnings)` from ESLint.
16
+
17
+ ### Added
18
+
19
+ - **Tower Controller gains a "Seals" tab for 3D emulator seal visibility** — When connected in Tower Emulator mode, a new "Seals" tab appears in the left column of the Tower Controller. It shows a labeled 3×4 grid (Top/Mid/Btm × N/E/S/W) of toggle buttons: clicking a button removes the corresponding seal from the 3D emulator view (button turns dark red); clicking again restores it. "Remove All" and "Replace All" action buttons operate on all 12 seals at once. Seal state is kept in sync with the existing Library tab seal grid on all mutation paths (`breakSeal`, Library grid clicks, "Clear All Lights"). The seal state is communicated to the emulator popup via a new `applySeals` postMessage type, which calls `TowerRenderView.applySeals()` on the display. When not in emulator+connected mode the tab shows an explanatory notice.
20
+
21
+ - **BLE disconnect diagnostics ("flight recorder")** — Opt-in structured capture of BLE disconnect incidents. Each of the five disconnect detection paths is tagged with a typed `DisconnectCause` (`adapter_event`, `gatt_health_check`, `heartbeat_timeout`, `response_timeout`, `bt_unavailable`) plus `user_initiated` and browser-only `page_unload`. Captures a snapshot of `ConnectionStatus`, command queue (including in-flight command + age), tower state, broken seals, the last ~500 structured BLE events (commands sent/received, timeouts, near-miss heartbeats, log lines), and the last 60 battery readings. Pluggable `DiagnosticsSink` interface mirrors `LogOutput`; ships with `InMemorySink` and `IndexedDBSink` (browser-only, durable across page refresh). Off by default — when disabled, hot paths add a single boolean check. Configure via `new UltimateDarkTower({ diagnostics: { enabled: true, ... } })` or toggle at runtime via `tower.setDiagnosticsEnabled(true)`. Public API: `getDiagnosticsRecorder()`, `getLastIncident()`, `exportDiagnosticsJSON()`. Tower Controller example gains a "BLE Debug" tab with capture toggle, live event stream, persistent incident log, breakdown-by-cause metrics, and JSON export. See [`docs/BLE_DIAGNOSTICS.md`](docs/BLE_DIAGNOSTICS.md). Schema version 1.
22
+
23
+ - **Seed parser** — New `src/udtSeedParser.ts` provides complete base-34 seed encoding and decoding, matching the game's C# `SeedParser` class. Exports `decodeSeed()`, `createSeed()`, `encodeSeed()`, `validateSeed()`, `compareSeedsRaw()`, `dumpSeedChars()`, and all related types (`DecodedSeed`, `SeedConfig`, `SeedBank`, `SeedComparison`, `CharDiff`, `CharDump`, foe/adversary/ally union types, and lookup arrays).
24
+
25
+ - **C# System.Random replica** — New `src/udtSystemRandom.ts` implements a byte-exact TypeScript replica of .NET Framework's `System.Random` (modified Knuth subtractive generator). Exports the `SystemRandom` class with `next()`, `nextMax()`, `nextRange()`, and `nextDouble()` methods. Verified against C#-generated test vectors for multiple seeds including edge cases. This is the foundation for future game state prediction from seeds.
26
+
27
+ - **Game board data** — New `src/udtGameBoard.ts` exports types and constants for all 60 Return to Dark Tower board locations: `TerrainType`, `BuildingType`, `BoardKingdom`, `BoardGrouping`, `BoardLocation`, `BOARD_LOCATIONS` (array), `BOARD_LOCATION_BY_NAME` (name-keyed lookup), and `BOARD_GROUPINGS` (Long Water, The Great Woods, Regal Run).
28
+
29
+ - **Tower Emulator shows audio playback notifications** — When an audio command is sent while connected to the Tower Emulator, the emulator popup now briefly displays the sound name, loop state, and volume level. The notification auto-dismisses after 4 seconds. Detection is done at the adapter level by reading the audio bytes from the outgoing command packet, so all audio commands are captured regardless of which API method triggered them.
30
+
31
+ ### Changed
32
+
33
+ - **Tower Emulator now renders a 3D tower model** — The emulator popup now uses `TowerRenderView` from `ultimatedarktowerdisplay` with the `'3d-view'` renderer, replacing the previous `TowerDisplay` default of readout text + 2D SVG side view. The existing connection-status banner and audio-event banner remain above the render, and the render view shows a "Tower Emulator" title bar.
34
+
35
+ - **Tower Emulator plays LED light sequences with bound audio** — `Tower.lightOverrides(N)` (the controller's Light Override dropdown) now drives a transient LED animation on the emulator's 3D tower **and** plays the firmware-bound audio sample alongside it (mirroring real-tower behavior). Same architectural fix as the audio cut-off: the framework strips `state.led_sequence` on every response (parallel to audio), so the popup was previously seeing `SequenceAnimator.apply(0)` immediately after each light-override command and killing the sequence before any frames played. `TowerEmulatorAdapter` now exposes an `onLightSequenceCommand` callback (parallel to `onAudioCommand`); the controller posts a `playSequence` message to the popup, which calls the display package's new `playSequence(id)` transient API (UltimateDarkTowerDisplay ≥ 0.7.0). The popup enables `audio.bindSequenceToSample: true` in its `TowerRenderView` config so the bound sample fires automatically via `playSampleOneShot` inside `playSequence` — same firmware behavior the display's own example app emulates. Detection reads `data[19]` (the `led_sequence` byte) from outgoing stateful commands.
36
+
37
+ - **Tower Emulator plays tower audio (full samples, no cut-off)** — The emulator popup now plays the same audio samples the real tower would, end-to-end. A "Click to enable audio" button appears on first load (required by browser autoplay policy); after clicking, all subsequent audio commands play through the popup. The popup's existing green audio-event banner continues to show sample name / loop / volume in parallel. Audio is driven via the display package's new `playSample(id, opts?)` one-shot API (requires `ultimatedarktowerdisplay` ≥ 0.6.0) — the previous synthetic-state workaround caused samples to cut off after ~100ms because the framework's audio-reset state updates triggered the display's `sync(0)` → `stop()` pipeline. The one-shot path is independent of state-driven `sync()`, so it plays to completion. Polyphony works (overlapping samples). The emulator's esbuild target was bumped from `es2017` to `es2020` and the output format from `iife` to `esm` (with a `<script type="module">` tag) so that the display package's per-file `new URL('./assets/<file>.ogg', import.meta.url)` references resolve at runtime against the bundle URL. Audio samples are copied from `UltimateDarkTowerDisplay/src/audio/assets/` to `dist/examples/controller/assets/` by `build-examples.js`.
38
+
39
+ - **`breakSeal()` now uses the firmware `sealReveal` LED override** — Previously composed ledge and doorway light states manually and sent them as a `lights()` command alongside the audio command. Now sends a single `lightOverrides(TOWER_LIGHT_SEQUENCES.sealReveal, ...)` packet that triggers the firmware's built-in seal reveal animation. The tower blocks until the animation completes before acknowledging the command, so callers no longer need an explicit delay between `breakSeal()` calls.
40
+
41
+ ### Removed
42
+
43
+ - **Old seed decoder** — Deleted `src/udtSeedDecoder.ts` and its exports (`extractBits`, `seedGroupToNumber`, `BitDiff`, `BitDump`, `DecodedField`). The old implementation used an incorrect base-36/62-bit model. All functionality is replaced by `udtSeedParser.ts` with the confirmed base-34 encoding.
44
+
45
+ ### Fixed
46
+
47
+ - **`connect()` swallowed errors instead of propagating to callers** — `udtBleConnection.connect()` caught all errors from the Bluetooth adapter (including `BluetoothUserCancelledError`) and called `onTowerDisconnect()` instead of re-throwing. This prevented callers from detecting user cancellation or connection failures. The catch block also incorrectly fired a disconnect event for a tower that was never connected. Errors are now re-thrown after logging, and the spurious disconnect callback has been removed.
48
+
49
+ - **Tower Emulator popup blocked on GitHub Pages (HTTPS)** — Moved `window.open` for the emulator display window to before the first `await` in `connectToTowerEmulator()`, ensuring it runs within the original user-gesture call stack and is not blocked by browser popup blockers on HTTPS origins.
50
+
9
51
  ## [3.0.0] - 2026-03-24
10
52
 
11
53
  ### Changed
package/README.md CHANGED
@@ -10,12 +10,20 @@ A JavaScript/TypeScript library for controlling the Bluetooth-enabled tower from
10
10
 
11
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
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
+
13
21
  ## Table of Contents
14
22
 
15
23
  - [UltimateDarkTower](#ultimatedarktower)
24
+ - [Live Examples](#live-examples)
16
25
  - [Table of Contents](#table-of-contents)
17
26
  - [Features](#features)
18
- - [Live Examples](#live-examples)
19
27
  - [Installation](#installation)
20
28
  - [Browser / Web Applications](#browser--web-applications)
21
29
  - [Node.js Applications](#nodejs-applications)
@@ -27,6 +35,8 @@ I have spent many hours reverse engineering the Tower's protocol in order to cre
27
35
  - [Documentation](#documentation)
28
36
  - [📖 Complete API Reference](#-complete-api-reference)
29
37
  - [Key Topics Covered:](#key-topics-covered)
38
+ - [Integration Testing](#integration-testing)
39
+ - [Lights Integration Test](#lights-integration-test)
30
40
  - [Development](#development)
31
41
  - [Building and Testing](#building-and-testing)
32
42
  - [Project Structure](#project-structure)
@@ -50,16 +60,6 @@ I have spent many hours reverse engineering the Tower's protocol in order to cre
50
60
  - **Battery Monitoring** - Real-time battery level tracking and low battery warnings
51
61
  - **Extensible Adapter Pattern** - Implement `IBluetoothAdapter` for custom platforms
52
62
 
53
- ## Live Examples
54
-
55
- Try the library in action! Just power on your Tower and visit:
56
-
57
- - **[Tower Controller](https://chessmess.github.io/UltimateDarkTower/dist/examples/controller/TowerController.html)** - Replicates official app functionality and gives examples of library functionality.
58
-
59
- - **[Tower Game](https://chessmess.github.io/UltimateDarkTower/dist/examples/game/TowerGame.html)** - "The Tower's Challenge" - a complete game using just the tower
60
-
61
- _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)._
62
-
63
63
  ## Installation
64
64
 
65
65
  ### Browser / Web Applications
@@ -119,7 +119,7 @@ import UltimateDarkTower, { IBluetoothAdapter } from 'ultimatedarktower';
119
119
 
120
120
  class MyCustomAdapter implements IBluetoothAdapter {
121
121
  // Implement all IBluetoothAdapter methods
122
- // See API_REFERENCE.md for the full interface
122
+ // See docs/API_REFERENCE.md for the full interface
123
123
  }
124
124
 
125
125
  const tower = new UltimateDarkTower({ adapter: new MyCustomAdapter() });
@@ -127,10 +127,18 @@ const tower = new UltimateDarkTower({ adapter: new MyCustomAdapter() });
127
127
 
128
128
  ## Documentation
129
129
 
130
- ### 📖 [Complete API Reference](API_REFERENCE.md)
130
+ ### 📖 [Complete API Reference](docs/API_REFERENCE.md)
131
131
 
132
132
  Comprehensive documentation with TypeScript examples, best practices, and troubleshooting guides.
133
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
+
134
142
  ### Key Topics Covered:
135
143
 
136
144
  - **Multi-Platform Setup** - Configuration for Web, Node.js, Electron, and React Native
@@ -139,6 +147,8 @@ Comprehensive documentation with TypeScript examples, best practices, and troubl
139
147
  - **Tower Control** - Detailed coverage of all tower commands (lights, sounds, rotation)
140
148
  - **Glyph System** - Automatic tracking of glyph positions as towers rotate
141
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
142
152
  - **Event Handling** - Callback system for tower events
143
153
  - **Logging System** - Multi-output logging for debugging and monitoring
144
154
  - **Best Practices** - Performance tips, error handling, and common patterns
@@ -185,7 +195,7 @@ npm run test:integration:lights
185
195
  - All lights breathe effect for 3 seconds
186
196
  - All lights off
187
197
 
188
- See [API_REFERENCE.md](API_REFERENCE.md) for API details on `allLightsOn` and `allLightsOff`.
198
+ See [API_REFERENCE.md](docs/API_REFERENCE.md) for API details on `allLightsOn` and `allLightsOff`.
189
199
 
190
200
  **Prerequisites:**
191
201
 
@@ -230,6 +240,9 @@ src/
230
240
  ├── udtCommandQueue.ts # Command queue management
231
241
  ├── udtTowerResponse.ts # Response handling
232
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
233
246
  ├── udtHelpers.ts # Utility helper functions
234
247
  ├── udtLogger.ts # Logging system
235
248
  ├── udtConstants.ts # Constants and type definitions
@@ -274,7 +287,7 @@ examples/
274
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.
275
288
  - **Light Sequences** - Same as sound for lights that play for a duration.
276
289
 
277
- > See [API_REFERENCE.md](API_REFERENCE.md) for performance best practices and workarounds.
290
+ > See [API_REFERENCE.md](docs/API_REFERENCE.md) for performance best practices and workarounds.
278
291
 
279
292
  ## Community
280
293