dredless 0.6.3 → 1.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 (41) hide show
  1. package/README.md +22 -57
  2. package/dist/browser/dredless.global.js +827 -1058
  3. package/dist/browser/dredless.global.js.map +4 -4
  4. package/docs/ACCOUNT.md +146 -0
  5. package/docs/API_REFERENCE.md +63 -2550
  6. package/docs/BROWSER_API.md +151 -70
  7. package/docs/CLIENT.md +183 -0
  8. package/docs/EVENTS.md +136 -0
  9. package/docs/GETTING_STARTED.md +135 -0
  10. package/docs/MACHINES.md +351 -0
  11. package/docs/MANAGEMENT.md +285 -0
  12. package/docs/NODE_API.md +120 -318
  13. package/docs/PLAYER_INVENTORY.md +235 -0
  14. package/docs/PROTOCOL.md +227 -0
  15. package/docs/README.md +44 -0
  16. package/docs/TROUBLESHOOTING.md +91 -0
  17. package/docs/WORLD_STATE.md +183 -0
  18. package/package.json +1 -2
  19. package/src/browser.d.ts +31 -1
  20. package/src/browser.js +10 -0
  21. package/src/client/core.js +302 -15
  22. package/src/client/domains/index.js +57 -7
  23. package/src/client/index.d.ts +1 -1
  24. package/src/index.d.ts +303 -14
  25. package/src/index.js +10 -0
  26. package/src/network/account.js +182 -0
  27. package/src/network/disconnect.d.ts +2 -0
  28. package/src/network/disconnect.js +53 -0
  29. package/src/network/index.d.ts +1 -0
  30. package/src/network/index.js +1 -0
  31. package/src/network/invites.d.ts +0 -3
  32. package/src/network/invites.js +3 -40
  33. package/src/network/session.d.ts +2 -0
  34. package/src/network/session.js +21 -0
  35. package/src/protocol/outbound/ship-management.d.ts +66 -1
  36. package/src/protocol/outbound/ship-management.js +83 -0
  37. package/src/state/model/decoder.js +101 -56
  38. package/src/state/model/index.d.ts +4 -0
  39. package/src/state/model/loader-config.js +0 -997
  40. package/src/state/model/state.js +28 -80
  41. package/src/state/world/index.js +27 -1
@@ -1,2571 +1,84 @@
1
- # Dredless API Reference
1
+ # API reference
2
2
 
3
- This document describes the public JavaScript API exposed by the package.
4
- Here, "endpoint" means a public method, constructor, domain method, or exported
5
- helper function. The actual browser/game wire protocol remains an implementation
6
- detail unless a helper explicitly builds or decodes protocol payloads.
3
+ [Documentation index](README.md) · [Getting started](GETTING_STARTED.md)
7
4
 
8
- Use the runtime-specific top-level API references for session, token, and start/join helpers:
5
+ ## Find an API
9
6
 
10
- - [NODE_API.md](./NODE_API.md): explicit multi-session `Session` / `AnonSession` API for Node.
11
- - [BROWSER_API.md](./BROWSER_API.md): ambient browser-session API for browser contexts.
7
+ | Area | Entry points | Reference |
8
+ |------------------------------------------------|--------------------------------------------|---------------------------------------------|
9
+ | Node HTTP sessions and connections | `Session`, `AnonSession`, `Dredless` | [Node API](NODE_API.md) |
10
+ | Browser sessions and socket attachment | `BrowserSession`, browser `Dredless` | [Browser API](BROWSER_API.md) |
11
+ | Client readiness, retention, disconnects | `DredlessClient`, `client.net` | [Client](CLIENT.md) |
12
+ | Callbacks and event payloads | `on`, `off`, `once` | [Events](EVENTS.md) |
13
+ | World, entity, and nearby ship reads | `currentShip`, `overworld`, entity handles | [World state](WORLD_STATE.md) |
14
+ | Input, inventory, blueprints, chat | `client.player`, `client.inventory` | [Player and inventory](PLAYER_INVENTORY.md) |
15
+ | Machine configuration and context menus | `ship.machines`, `client.tips` | [Machines](MACHINES.md) |
16
+ | Crew, logs, ship settings, saving, perks | `client.management` | [Management](MANAGEMENT.md) |
17
+ | Account details, clan tags, applied perk ships | Session account methods | [Account](ACCOUNT.md) |
18
+ | Builders, decoders, generator mazes, raw state | Protocol subpaths, `client.debug` | [Protocol and debugging](PROTOCOL.md) |
19
+ | Failures and unsupported assumptions | - | [Troubleshooting](TROUBLESHOOTING.md) |
12
20
 
13
- This shared reference covers common input/output shapes, `DredlessClient`, world/entity/domain APIs, protocol helpers, and other runtime-neutral APIs.
21
+ ## Imports
14
22
 
15
- Subpath imports are available for focused low-level helpers:
23
+ Use `dredless/node` for explicit Node sessions and `dredless/browser` for ambient browser authentication. Both provide a
24
+ runtime namespace as the default export and shared APIs as named exports. The package root selects a runtime through
25
+ package export conditions; explicit imports make that choice clear.
16
26
 
17
27
  ```js
18
- import { DredlessClient } from "dredless/client";
19
- import { WorldStore, WorldState } from "dredless/world";
20
- import { generateGeneratorMaze } from "dredless/game/generator-maze";
21
- import { encodeMsgpack, decodeMsgpack, decodeIncomingFrame } from "dredless/protocol";
28
+ import Dredless, {DredlessClient, LoaderPosition, DropReason} from "dredless/node";
22
29
  ```
23
30
 
24
- ## Public Package Exports
31
+ Focused imports include `dredless/client`, `dredless/session`, `dredless/network`, `dredless/world`, `dredless/model`,
32
+ `dredless/state`, and [protocol subpaths](PROTOCOL.md#import-map). Subpaths do not necessarily re-export everything
33
+ available from a runtime entrypoint. `package.json` is the authoritative [export map](../package.json).
25
34
 
26
- `package.json` currently exposes these module specifiers:
35
+ ## Reading signatures
27
36
 
28
- ```txt
29
- dredless
30
- dredless/browser
31
- dredless/node
32
- dredless/client
33
- dredless/network
34
- dredless/state
35
- dredless/session
36
- dredless/servers
37
- dredless/ships
38
- dredless/connection
39
- dredless/world
40
- dredless/model
41
- dredless/game/generator-maze
42
- dredless/game/model
43
- dredless/protocol
44
- dredless/protocol/blueprint
45
- dredless/protocol/comms
46
- dredless/protocol/commands
47
- dredless/protocol/inventory
48
- dredless/protocol/ship-management
49
- dredless/protocol/sign
50
- dredless/protocol/ui-config
51
- dredless/crypto/chacha
52
- dredless/compression/lz4
53
- ```
54
-
55
- The root module defaults to the Node API for types and direct Node imports. Browser bundlers may use the root `browser` condition for JavaScript, but `dredless/browser` is the reliable import for browser IntelliSense.
56
-
57
- Both runtime entrypoints re-export world/model classes, protocol builders, config builders, codec helpers, and common type shapes.
58
-
59
- ## Common Input Types
60
-
61
- ### `Server`
62
-
63
- Returned by `fetchServers()`. Player counts and ping are returned separately by `fetchServerStatus()` or `fetchServerStatuses()`.
64
-
65
- ```ts
66
- interface Server {
67
- index: number;
68
- domain: string;
69
- description: string;
70
- }
71
- ```
72
-
73
- ### `ServerRef`
74
-
75
- Accepted anywhere a server is required.
76
-
77
- ```ts
78
- type ServerRef = number | Server;
79
- ```
80
-
81
- Passing a number selects a server index. Passing a `Server` object uses its
82
- domain and index directly.
83
-
84
- ### `Ship`
85
-
86
- Returned by ship list reads.
87
-
88
- ```ts
89
- interface Ship {
90
- id: number | null;
91
- hexCode: string | null;
92
- name: string;
93
- iconUrl: string | null;
94
- playerCount: number;
95
- owned: boolean;
96
- saved: boolean;
97
- color: string;
98
- time: number | null;
99
- }
100
- ```
101
-
102
- Ship names are returned exactly as provided by the Drednot server. In
103
- particular, `fetchShips()` and `fetchShipList()` preserve leading and trailing
104
- spaces; it is up to callers to optionally trim those spaces from `name`.
105
-
106
- ### `InviteMetadata`
107
-
108
- Returned by `fetchInviteMetadata()`.
109
-
110
- ```ts
111
- interface InviteMetadata {
112
- shipId: string | null;
113
- name: string | null;
114
- previewImageUrl: string | null;
115
- hostname: string;
116
- inviteCode: string;
117
- color?: string | null;
118
- }
119
- ```
120
-
121
- Invite metadata also preserves leading and trailing spaces in the
122
- ship name returned by the invite page. The optional `color` field is included
123
- only when `includeColor: true` is passed and is sampled from the preview image.
124
-
125
- ### `ShipList`
126
-
127
- Returned by `fetchShipList()`.
128
-
129
- ```ts
130
- interface ShipList {
131
- playerCount?: number;
132
- maxPlayerCount?: number;
133
- isMuted?: boolean;
134
- ships: Ship[];
135
- }
136
- ```
137
-
138
- ### `ShipSpec`, `ShipRef`
139
-
140
- Accepted by join/start methods.
141
-
142
- ```ts
143
- type ShipSpec =
144
- | { type: "join_or_load"; id: number | string }
145
- | { type: "new"; name?: string | null; color?: string | null }
146
- | { type: "invite"; code: string };
147
-
148
- type ShipRef = number | string | Ship | ShipSpec | null;
149
- ```
150
-
151
- Useful interpretations:
152
-
153
- ```txt
154
- number -> ship id
155
- string -> ship id/hex-like selector, depending on server API
156
- Ship -> ship from fetchShips/fetchShipList
157
- { type: "new" } -> create or start a new ship
158
- { type: "invite" } -> join by invite code
159
- null or undefined -> default behavior for the method
160
- ```
161
-
162
- ## Runtime Top-Level APIs
163
-
164
- Top-level runtime APIs are split by environment:
165
-
166
- - Node explicit session/token/start helpers: [NODE_API.md](./NODE_API.md)
167
- - Browser ambient session/start helpers: [BROWSER_API.md](./BROWSER_API.md)
168
-
169
- `Connection`, `Session`, `AnonSession`, `BrowserSession`, `Dredless`, and `DredlessBrowser` are documented in those runtime-specific files.
170
-
171
- ## `DredlessClient`
172
-
173
- `DredlessClient` owns the websocket, outgoing commands, incoming packets, and
174
- decoded state domains.
175
-
176
- ```ts
177
- class DredlessClient {
178
- constructor(connection: Connection, options?: { connect?: boolean });
179
- static attachWebSocket(websocket: unknown, options?: AttachWebSocketOptions): DredlessClient;
180
-
181
- connection: Connection | null;
182
- session: Session | null;
183
- baseUrl: string | null;
184
- attachMode: "observe" | "bootstrap" | "readonly" | null;
185
- attached: boolean;
186
- serverId: number | null;
187
- server: Server | null;
188
- netPort: number | null;
189
- gameToken: string;
190
- ws: unknown;
191
- sid: number | null;
192
- connected: boolean;
193
- ready: boolean;
194
- packetCount: number;
195
- lastPacket: unknown;
196
-
197
- net: ClientNetDomain;
198
- debug: ClientDebugDomain;
199
- player: PlayerDomain;
200
- inventory: InventoryDomain;
201
- management: ShipManagementDomain;
202
- readyPromise: Promise<this>;
203
-
204
- whenReady(): Promise<this>;
205
- close(code?: number, reason?: string): this;
206
- disconnect(code?: number, reason?: string): this;
207
-
208
- currentShip(): ShipDomain | null;
209
- ship(): ShipDomain | null;
210
- overworld(): OverworldDomain | null;
211
- world(id: number): WorldDomain | null;
212
- shipWorld(options?: { includeTiles?: boolean; includeModel?: boolean }): WorldSnapshot | null;
213
- state(options?: { includeTiles?: boolean; includeModel?: boolean }): ClientSnapshot;
214
- entities(scope?: number | string): EntitySummary[];
215
- entity(entityId: number, scope?: number | string): EntitySnapshot | null;
216
- currentPlayerEntity(): EntityHandle | null;
217
-
218
- on(type: string, callback: (...args: unknown[]) => void): this;
219
- off(type: string, callback: (...args: unknown[]) => void): this;
220
- once(type: string, callback: (...args: unknown[]) => void): this;
221
- }
222
- ```
223
-
224
- ### Constructor
225
-
226
- ```js
227
- const client = new DredlessClient(connection);
228
- ```
229
-
230
- By default the constructor opens the websocket. For tests or offline state
231
- inspection, pass `{ connect: false }`:
232
-
233
- ```js
234
- const client = new DredlessClient(connection, { connect: false });
235
- ```
236
-
237
- ### `DredlessClient.attachWebSocket(websocket, options?)`
238
-
239
- ```ts
240
- type WebSocketAttachMode = "observe" | "bootstrap" | "readonly";
241
-
242
- interface AttachWebSocketOptions {
243
- mode?: WebSocketAttachMode;
244
- connected?: boolean | null;
245
- ready?: boolean;
246
- sid?: number | null;
247
- baseUrl?: string | null;
248
- session?: Session | null;
249
- serverId?: number | null;
250
- server?: Server | null;
251
- netPort?: number | null;
252
- gameToken?: string;
253
- }
254
- ```
255
-
256
- Attaches Dredless to an existing websocket without requiring a `Connection`.
257
- This is intended for observing or integrating with an already-open browser/game websocket.
258
-
259
- Modes:
260
-
261
- - `"observe"` default: decodes incoming packets and allows explicit writes through normal handle/client methods, but does not send hello, bootstrap, or keepalive automatically.
262
- - `"bootstrap"`: treats the websocket like a normally owned Dredless socket; sends hello on open and runs bootstrap, keepalive, and queued-message flushing on ready.
263
- - `"readonly"`: decodes incoming packets only and rejects all write methods. `close()` is a no-op in this mode.
264
-
265
- Optional metadata such as `server`, `serverId`, and `netPort` is only used for snapshots/logging; it is not required to attach.
266
-
267
- ```js
268
- const client = DredlessClient.attachWebSocket(window.tpgaClient.repsocket.websocket);
269
- client.on("packet", (packet) => console.log(packet.type));
270
- ```
271
-
272
- ### Lifecycle endpoints
273
-
274
- ```ts
275
- whenReady(): Promise<this>;
276
- close(code?: number, reason?: string): this;
277
- disconnect(code?: number, reason?: string): this;
278
- ```
279
-
280
- `whenReady()` resolves once the ready packet is received. For normally-owned clients and `attachWebSocket(..., { mode: "bootstrap" })`, bootstrap commands have also been sent.
281
-
282
- ### World/domain endpoints
283
-
284
- ```ts
285
- currentShip(): ShipDomain | null;
286
- ship(): ShipDomain | null;
287
- currentPlayerEntity(): EntityHandle | null;
288
- overworld(): OverworldDomain | null;
289
- world(id: number): WorldDomain | null;
290
- shipWorld(options?): WorldSnapshot | null;
291
- ```
292
-
293
- Use `currentShip()` for the currently loaded ship world. Use `overworld()` for
294
- zone-level objects such as nearby ships and overworld entities.
295
-
296
- `currentPlayerEntity()` returns the current player entity handle in the loaded
297
- ship world, or `null` before the player entity is known.
298
-
299
- ### Compatibility entity endpoints
300
-
301
- ```ts
302
- entities(scope?: number | string): EntitySummary[];
303
- entity(entityId: number, scope?: number | string): EntitySnapshot | null;
304
- ```
305
-
306
- Prefer `client.currentShip()?.entities` and `client.overworld()?.entities` for
307
- new code. These compatibility methods use `"ship"` by default.
308
-
309
- Valid common scopes are:
310
-
311
- ```txt
312
- "ship"
313
- "current"
314
- "overworld"
315
- number world id
316
- ```
317
-
318
- ### Events
319
-
320
- ```ts
321
- on(type: string, callback: (...args: unknown[]) => void): this;
322
- off(type: string, callback: (...args: unknown[]) => void): this;
323
- once(type: string, callback: (...args: unknown[]) => void): this;
324
- ```
325
-
326
- Events are implementation-defined strings emitted by the client event bus.
327
-
328
- ### Context menus: `client.tips`
329
-
330
- ```js
331
- const door = client.currentShip().machines.doors()[0];
332
- const menu = await door.openTips();
333
- console.log(menu.options);
334
- client.tips.select("Restrict to Crew"); // Also accepts a zero-based option index.
335
-
336
- // Open and select in one operation:
337
- await client.tips.choose(door, "Restrict to Captains");
338
-
339
- // Dismiss without selecting an option:
340
- await door.openTips();
341
- await client.tips.close();
342
-
343
- // Set access and wait for the server's model update:
344
- await door.setRank("guest");
345
- await client.currentShip().machines.spawnPoints()[0].setRank("crew");
346
- ```
347
-
348
- `client.tips.open(entity, options?)` accepts an entity handle or an entity id in
349
- the current world and resolves to a frozen `TipList` with
350
- `{ entity, world, filter, x, y, options }`. Every entity handle also exposes
351
- `openTips(options?)`. `client.tips.current` is the latest menu, or `null` after
352
- selection, an empty menu, or disconnect. The `tip-list` event receives
353
- `(menu, world)` including empty menus; the existing raw `side-event` is preserved.
354
- The server does not send an entity id in a tip list: `entity` is inferred from
355
- the API's requested target and is `null` for unsolicited menus. Avoid mixing raw
356
- context-menu commands with an API operation in progress.
357
-
358
- `select(option, command?)` sends the selected index and returns the client.
359
- `choose(entity, option, options?)` opens a fresh menu and selects by exact text
360
- or index, resolving to the client once selection is sent. Neither method waits
361
- for the resulting action to complete.
362
-
363
- `close(options?)` sends the captured left-click dismissal input with no focused
364
- entity or selected option, then resolves to the client after the server sends an
365
- empty tip list for the menu's world. It skips sending when no menu is open and
366
- uses the same timeout and overlap rules as `open()`. Optional `command` fields
367
- can supply click coordinates or inventory/view settings.
368
-
369
- Door and spawn-point `setRank(rank, options?)` accept `"guest"`, `"crew"`,
370
- `"captain"`, or `0`, `1`, `3`. They resolve to the client after the model confirms
371
- the requested rank, and skip sending when the rank already matches. These are
372
- access restrictions; they do not change a player's ship rank.
373
-
374
- Options are `{ timeout?: number, command?: Command }`. The timeout defaults to
375
- 5000 milliseconds per response (menu and, for `setRank`, rank confirmation).
376
- Calls reject on timeout, disconnect, unknown options, invalid ranks, or a target
377
- outside the current world. Only one asynchronous tip operation may run per
378
- client; overlapping calls reject. The server still enforces permissions and
379
- interaction range; these helpers do not move the player or grant access.
380
-
381
- ## `client.state()` Output
382
-
383
- ```ts
384
- interface ClientSnapshot {
385
- baseUrl: string;
386
- session: SessionSnapshot;
387
- connection: ConnectionSnapshot | null;
388
- attachMode: "observe" | "bootstrap" | "readonly" | null;
389
- serverId: number | null;
390
- server: Server | null;
391
- netPort: number | null;
392
- sid: number | null;
393
- ready: boolean;
394
- connected: boolean;
395
- currentWorldId: number | null;
396
- worlds: WorldSnapshot[];
397
- cpuLoad: number | null;
398
- inventory: InventoryState;
399
- puiPanels: PuiEvent[];
400
- commsPanels: CommsEvent[];
401
- currentCommsPanel: CommsEvent | null;
402
- warnings: unknown[];
403
- effects: unknown[];
404
- chat: unknown[];
405
- motd: unknown[];
406
- sessionMessages: unknown[];
407
- scannerResults: ScannerResult[];
408
- lastScannerResult: ScannerResult | null;
409
- shipConfig: ShipConfig | null;
410
- captainSubrank: CaptainSubrank | null;
411
- playerList: ShipPlayerList | null;
412
- outfits: { sid: number; outfit: unknown }[];
413
- commandAcks: CommandAck[];
414
- lastCommandAck: CommandAck | null;
415
- decodeErrors: unknown[];
416
- packetCount: number;
417
- lastPacket: unknown;
418
- }
419
- ```
420
-
421
- ## Client Domain APIs
422
-
423
- ### `client.net`
424
-
425
- Low-level outgoing network domain.
426
-
427
- ```ts
428
- interface ClientNetDomain {
429
- connected: boolean;
430
- ready: boolean;
431
- sid: number | null;
432
- packetCount: number;
433
- lastPacket: unknown;
434
- send(command?: Command): DredlessClient;
435
- sendMessage(message: unknown, options?: { afterReady?: boolean }): DredlessClient;
436
- sendRaw(message: unknown, options?: { afterReady?: boolean }): DredlessClient;
437
- sendEntityCommand(cmd: string, args?: unknown[]): DredlessClient;
438
- sendUiConfig(data: unknown): DredlessClient;
439
- sendBlueprintPlacement(placement: BlueprintPlacement): DredlessClient;
440
- setOutfit(outfit: unknown): DredlessClient;
441
- }
442
- ```
443
-
444
- `send()` signs and sends a command-like packet. `sendMessage()` sends a decoded
445
- protocol message. `sendRaw()` sends already-built/raw content. The specialized
446
- helpers build the corresponding protocol command and return the client for
447
- chaining.
448
-
449
- ### `Command`
450
-
451
- General command shape for movement, actions, UI focus, and drag operations.
452
-
453
- ```ts
454
- interface Command {
455
- type?: number;
456
- n?: number | null;
457
- x?: number;
458
- y?: number;
459
- mx?: number;
460
- my?: number;
461
- vx?: number;
462
- vy?: number;
463
- jump?: boolean;
464
- jump_held?: boolean;
465
- drop?: boolean;
466
- act1?: boolean;
467
- act1_held?: boolean;
468
- exit?: boolean;
469
- act2?: boolean;
470
- act_alt?: boolean;
471
- act_alt_held?: boolean;
472
- wrench_mode?: number;
473
- turret_mode?: number;
474
- scr_w?: number;
475
- scr_h?: number;
476
- motion?: number;
477
- focus_ent?: number | null;
478
- config_ent?: number | null;
479
- tip_select?: number | null;
480
- inv_slot?: number;
481
- blur?: boolean;
482
- drag?: DragPayload | null;
483
- }
484
- ```
485
-
486
- ### `client.debug`
487
-
488
- Read-only debugging and raw-state access.
489
-
490
- ```ts
491
- interface ClientDebugDomain {
492
- packets(): unknown[];
493
- decodeErrors(): unknown[];
494
- worldStore(): WorldStore;
495
- modelTable(worldId: number, tableId: number): Map<number, ModelRecord>;
496
- modelRecord(worldId: number, tableId: number, entityId: number): ModelRecord | null;
497
- puiPanels(): PuiEvent[];
498
- commsPanels(): CommsEvent[];
499
- }
500
- ```
501
-
502
- ### `client.player`
503
-
504
- Player input and action domain.
505
-
506
- ```ts
507
- interface PlayerDomain {
508
- current(): PlayerSummary | null;
509
- entity(): EntityHandle | null;
510
- name(): string | null;
511
- rank(): CurrentPlayerRank;
512
- move(vector?: { x?: number; y?: number }, command?: Command): DredlessClient;
513
- aim(point?: { x?: number; y?: number; mx?: number; my?: number }, command?: Command): DredlessClient;
514
- action(flags?: Command, command?: Command): DredlessClient;
515
- useEntity(entity: number | EntityHandle | EntitySummary, options?: { invSlot?: number; hold?: boolean }, command?: Command): DredlessClient;
516
- useHeldItem(options?: { invSlot?: number; hold?: boolean }, command?: Command): DredlessClient;
517
- placeHeldItem(options?: { invSlot?: number; hold?: boolean }, command?: Command): DredlessClient;
518
- placeBlueprint(placement: BlueprintPlacement, options?: { invSlot?: number; hold?: boolean; mx?: number; my?: number }, command?: Command): DredlessClient;
519
- rotateHeldItem(options?: { invSlot?: number; hold?: boolean }, command?: Command): DredlessClient;
520
- selectSlot(invSlot?: number, command?: Command): DredlessClient;
521
- inputSettings(): CurrentInputSettings;
522
- setInputSettings(settings?: InputSettings, options?: { send?: boolean }): DredlessClient;
523
- setView(width: number, height: number, options?: { send?: boolean }): DredlessClient;
524
- setScreenSize(width: number, height: number, options?: { send?: boolean }): DredlessClient;
525
- setWrenchMode(mode: WrenchMode, options?: { send?: boolean }): DredlessClient;
526
- setTurretMode(mode: TurretMode, options?: { send?: boolean }): DredlessClient;
527
- }
528
- ```
529
-
530
- ### Input setting shapes
531
-
532
- ```ts
533
- const WrenchMode = { DropAllItems: "drop-all-items", GrabPrimaryItems: "grab-primary-items", GrabAllItems: "grab-all-items" } as const;
534
- type WrenchMode = typeof WrenchMode[keyof typeof WrenchMode];
535
-
536
- const TurretMode = { ContinuousFire: "continuous-fire", VolleyFire: "volley-fire" } as const;
537
- type TurretMode = typeof TurretMode[keyof typeof TurretMode];
538
-
539
- interface InputSettings {
540
- wrenchMode?: WrenchMode;
541
- turretMode?: TurretMode;
542
- viewWidth?: number;
543
- viewHeight?: number;
544
- screenWidth?: number;
545
- screenHeight?: number;
546
- }
547
-
548
- interface CurrentInputSettings {
549
- wrenchMode: "drop-all-items" | "grab-primary-items" | "grab-all-items" | null;
550
- turretMode: "continuous-fire" | "volley-fire" | null;
551
- viewWidth: number | null;
552
- viewHeight: number | null;
553
- screenWidth: number | null;
554
- screenHeight: number | null;
555
- }
556
- ```
557
-
558
- ### `client.inventory`
559
-
560
- Inventory read and slot movement domain.
561
-
562
- ```ts
563
- type InventoryArea = "all" | "hotbar" | "equipment";
564
- type InventorySlotRef = number | EquipmentSlot | InventorySlotHandle | InventorySlotSnapshot;
565
- const EquipmentSlot = { Head: "head", Face: "face", Body: "body", Back: "back", Hands: "hands", Feet: "feet" } as const;
566
- type EquipmentSlot = typeof EquipmentSlot[keyof typeof EquipmentSlot];
567
-
568
- interface InventoryDomain {
569
- state(): InventoryState;
570
- hotbarSize(): number;
571
- allSlots(): InventorySlotHandle[];
572
- slot(ref: InventorySlotRef): InventorySlotHandle;
573
- hotbarSlots(): InventorySlotHandle[];
574
- equipmentSlots(): { head: InventorySlotHandle; face: InventorySlotHandle; body: InventorySlotHandle; back: InventorySlotHandle; hands: InventorySlotHandle; feet: InventorySlotHandle };
575
- findItem(itemId: number, options?: { area?: InventoryArea }): InventorySlotHandle | null;
576
- findItems(itemId: number, options?: { area?: InventoryArea }): InventorySlotHandle[];
577
- firstEmpty(options?: { area?: InventoryArea }): InventorySlotHandle | null;
578
- move(source: InventorySlotRef, target: InventorySlotRef, options?: { split?: boolean }, command?: Command): DredlessClient;
579
- equip(source: InventorySlotRef, equipmentSlot?: EquipmentSlot | { split?: boolean }, options?: { split?: boolean } | Command, command?: Command): DredlessClient;
580
- unequip(equipmentSlot: EquipmentSlot, target?: InventorySlotRef, options?: { split?: boolean }, command?: Command): DredlessClient;
581
- select(slot: InventorySlotRef, command?: Command): DredlessClient;
582
- }
583
- ```
584
-
585
- Slot handles expose live slot reads and convenience actions:
586
-
587
- ```ts
588
- interface InventorySlotHandle {
589
- index: number;
590
- kind: "hotbar" | "equipment" | null;
591
- equipmentSlot: "head" | "face" | "body" | "back" | "hands" | "feet" | null;
592
- itemId: number | null;
593
- itemName: string | null;
594
- count: number;
595
- empty: boolean;
596
- exists(): boolean;
597
- snapshot(): InventorySlotSnapshot | null;
598
- moveTo(target: InventorySlotRef, options?: { split?: boolean }, command?: Command): DredlessClient;
599
- equip(equipmentSlot?: EquipmentSlot | { split?: boolean }, options?: { split?: boolean } | Command, command?: Command): DredlessClient;
600
- unequip(target?: InventorySlotRef, options?: { split?: boolean }, command?: Command): DredlessClient;
601
- select(command?: Command): DredlessClient;
602
- }
603
- ```
604
-
605
- Inventory state is normalized and does not expose raw `items`, `item_counts`, or `general_slots` arrays. `hotbarSize` is the protocol-provided hotbar slot count from `general_slots`; equipment slots are separate fixed absolute indexes (`16`, `17`, `18`, `19`, `20`, `21`). `equip()` may omit the equipment slot; in that case it infers the target from the item schema and throws if the source slot is empty or the item is not equipment.
606
-
607
- ```ts
608
- interface InventorySlotSnapshot {
609
- index: number;
610
- itemId: number | null;
611
- itemName: string | null;
612
- count: number;
613
- kind: "hotbar" | "equipment";
614
- equipmentSlot: "head" | "face" | "body" | "back" | "hands" | "feet" | null;
615
- empty: boolean;
616
- }
617
-
618
- interface InventoryState {
619
- type: "inventory";
620
- filter?: number;
621
- hotbarSize: number;
622
- slots: InventorySlotSnapshot[];
623
- hotbar: InventorySlotSnapshot[];
624
- equipment: {
625
- head: InventorySlotSnapshot;
626
- face: InventorySlotSnapshot;
627
- body: InventorySlotSnapshot;
628
- back: InventorySlotSnapshot;
629
- hands: InventorySlotSnapshot;
630
- feet: InventorySlotSnapshot;
631
- };
632
- }
633
- ```
634
- ### `client.management`
635
-
636
- Ship-management command and state domain.
637
-
638
- ```ts
639
- interface ShipManagementDomain {
640
- requestPlayerList(): DredlessClient;
641
- resetInvite(): DredlessClient;
642
- setPrivacy(privacy: ShipPrivacy): DredlessClient;
643
- recoverStarterItem(itemId: number): DredlessClient;
644
- setPlayerRank(refId: number, rank: ShipPlayerRank): DredlessClient;
645
- kickPlayer(refId: number): DredlessClient;
646
- banPlayer(refId: number): DredlessClient;
647
- demoteSelf(): DredlessClient;
648
- config(): ShipConfig | null;
649
- hasCheats(): boolean;
650
- playerList(): ShipPlayerList | null;
651
- }
652
- ```
653
-
654
- Input aliases:
655
-
656
- ```ts
657
- type ShipPrivacy = 0 | 1 | boolean | "public" | "private";
658
- type ShipPlayerRank = 0 | 1 | 3 | "guest" | "crew" | "captain";
659
- type PlayerShipRank = "guest" | "crew" | "crew-invite-pending-deprecated" | "captain" | "banned";
660
- ```
661
-
662
- Output shapes:
663
-
664
- ```ts
665
- interface ShipConfig {
666
- privacy: number | null;
667
- privacyName: "public" | "private" | null;
668
- inviteKey: string | null;
669
- teamId: number | null;
670
- patronPerks: unknown[];
671
- }
672
-
673
- interface CaptainSubrank {
674
- subrank: number | null;
675
- enableCheats: boolean;
676
- }
677
-
678
- interface CurrentPlayerRank {
679
- shipRank: PlayerShipRank | null;
680
- subrank: number | null;
681
- isCaptain: boolean;
682
- patronTier: "bronze" | "silver" | "gold" | "plat" | "flux" | null;
683
- }
684
-
685
- interface PlayerListEntry {
686
- refId: number | null;
687
- discrim: string | null;
688
- discrimColor: number | null;
689
- teamRank: number | null;
690
- captainRank: number | null;
691
- isCaptain: boolean;
692
- isShipOwner: boolean;
693
- canBeManaged: boolean;
694
- time: number | null;
695
- items: unknown[];
696
- aliasDiscrims: unknown[];
697
- extraAliasCount: number;
698
- onlineCount: number | null;
699
- }
700
-
701
- interface ShipPlayerList {
702
- ownerCaptainRank: number | null;
703
- shipOwners: PlayerListEntry[];
704
- players: PlayerListEntry[];
705
- changes: PlayerListEntry[];
706
- removedPlayers: number[];
707
- }
708
- ```
709
-
710
- ## World Domains
711
-
712
- ### `WorldDomain`
713
-
714
- Available from `client.currentShip()`, `client.overworld()`, and
715
- `client.world(id)`.
716
-
717
- ```ts
718
- interface WorldDomain {
719
- id: number | null;
720
- entities: EntityCollection;
721
- machines: MachineCollection;
722
- players: PlayerCollection;
723
- blocks: BlockCollection;
724
- materials: MaterialCollection;
725
- exists(): boolean;
726
- snapshot(options?: { includeTiles?: boolean; includeModel?: boolean }): WorldSnapshot | null;
727
- }
728
- ```
729
-
730
- ### `ShipDomain`
731
-
732
- ```ts
733
- interface ShipDomain extends WorldDomain {
734
- metadata: ShipWorldMetadataSummary | null;
735
- entity(): EntityHandle | null;
736
- overworldEntity: EntityHandle | null;
737
- }
738
- ```
739
-
740
- `entity()` returns the current ship's overworld entity handle, not a ship-world
741
- placed entity.
742
-
743
- ### `OverworldDomain`
744
-
745
- ```ts
746
- interface OverworldDomain extends WorldDomain {
747
- ships(options?: ShipReadOptions): ShipHandle[];
748
- shipByHex(hexCode: string, options?: ShipReadOptions): ShipHandle | null;
749
- shipByEntity(entity: number | EntityHandle | EntitySummary, options?: ShipReadOptions): ShipHandle | null;
750
- }
751
- ```
752
-
753
- Ship read options:
754
-
755
- ```ts
756
- interface ShipReadOptions {
757
- includeWorld?: boolean;
758
- includeTiles?: boolean;
759
- includeModel?: boolean;
760
- sort?: "distance" | null;
761
- }
762
- ```
763
-
764
- ## Entity API
765
-
766
- Entity ids are scoped to their world. Overworld entities and ship-world entities
767
- do not share one global id pool.
768
-
769
- ### `EntityCollection`
770
-
771
- ```ts
772
- interface EntityCollection {
773
- all(): EntityHandle[];
774
- snapshots(): EntitySnapshot[];
775
- states(): EntitySnapshot[];
776
- raw(): EntitySummary[];
777
- get(entity: number | EntityHandle | EntitySummary): EntityHandle;
778
- }
779
- ```
780
-
781
- Use:
782
-
783
- ```js
784
- const shipEntity = client.currentShip().entities.get(14);
785
- const overworldEntity = client.overworld().entities.get(2495754);
786
- ```
787
-
788
- Costs:
789
-
790
- ```txt
791
- all() -> creates lightweight handles
792
- raw() -> returns current summary objects
793
- snapshots() -> clones and freezes summaries
794
- states() -> alias of snapshots()
795
- get(id) -> creates one lightweight handle
796
- ```
797
-
798
- ### `EntityHandle`
799
-
800
- ```ts
801
- interface EntityHandle {
802
- /** @deprecated Use id. */
803
- entity: number;
804
- id: number;
805
- position: TransformSummary | null;
806
- health: HealthSummary | null;
807
- contents: EntityContentsSummary | null;
808
- exists(): boolean;
809
- snapshot(): EntitySnapshot | null;
810
- is(type: EntityTypeName): boolean;
811
- has(feature: EntityFeatureName): boolean;
812
- feature(feature: EntityFeatureName): unknown | null;
813
- as(type: EntityTypeName): MachineHandle | null;
814
- asLoader(): LoaderHandle | null;
815
- asPusher(): PusherHandle | null;
816
- asLauncher(): LauncherHandle | null;
817
- asNavigationUnit(): NavigationUnitHandle | null;
818
- asCommsStation(): CommsStationHandle | null;
819
- asSign(): SignHandle | null;
820
- asGenerator(): GeneratorHandle | null;
821
- asCargoHatch(): CargoHatchHandle | null;
822
- asCannon(): CannonHandle | null;
823
- asThruster(): ThrusterHandle | null;
824
- asHelm(): HelmHandle | null;
825
- asDoor(): DoorHandle | null;
826
- asSpawnPoint(): SpawnPointHandle | null;
827
- asShieldProjector(): ShieldProjectorHandle | null;
828
- asFluidTank(): FluidTankHandle | null;
829
- asCargoEjector(): CargoEjectorHandle | null;
830
- asExpandoBox(): ExpandoBoxHandle | null;
831
- use(options?: { invSlot?: number; hold?: boolean }, command?: Command): DredlessClient;
832
- }
833
- ```
834
-
835
- ### `EntitySnapshot`
836
-
837
- Frozen point-in-time entity read.
838
-
839
- ```ts
840
- interface EntitySnapshot extends EntitySummary {
841
- id: number;
842
- position: TransformSummary | null;
843
- rotation: number | null;
844
- type: EntitySnapshotType;
845
- is(type: EntityTypeName): boolean;
846
- has(feature: EntityFeatureName): boolean;
847
- feature(feature: EntityFeatureName): unknown | null;
848
- }
849
-
850
- interface EntitySnapshotType {
851
- category: EntitySummary["category"] | null;
852
- machine: string | null;
853
- item: string | null;
854
- components: string[];
855
- }
856
- ```
857
-
858
- ### `EntitySummary`
859
-
860
- Raw normalized entity shape.
861
-
862
- ```ts
863
- interface EntitySummary {
864
- entity: number;
865
- category:
866
- | "placed_entity"
867
- | "loose_item"
868
- | "untyped_holder"
869
- | "metadata"
870
- | "player"
871
- | "ship_control"
872
- | "blueprint_preview"
873
- | "entity";
874
- typeId: number | null;
875
- typeName: string | null;
876
- markerTypeId: number | null;
877
- markerTypeName: string | null;
878
- label: string;
879
- kind: string[];
880
- transform: TransformSummary | null;
881
- footprint: {
882
- width: number;
883
- height: number;
884
- source:
885
- | "type"
886
- | "marker"
887
- | "heuristic"
888
- | "default"
889
- | "crate"
890
- | "huge_thruster"
891
- | "hover_outline";
892
- };
893
- contents: EntityContentsSummary | null;
894
- occupies: { x: number; y: number }[];
895
- tables: { tableId: number; name: string | null; record: ModelRecord }[];
896
- }
897
- ```
898
-
899
- ### `EntityContentsSummary`
900
-
901
- Feature/component container for an entity.
902
-
903
- ```ts
904
- interface EntityContentsSummary {
905
- itemHolder?: ItemHolderSummary;
906
- expandoBox?: ExpandoBoxSummary;
907
- hoverOutline?: HoverOutlineSummary;
908
- mapMarker?: MapMarkerSummary;
909
- dockingSpring?: DockingSpringSummary;
910
- hugeThruster?: HugeThrusterSummary;
911
- blueprintPreview?: BlueprintPreviewSummary;
912
- itemCrate?: ItemCrateSummary;
913
- health?: HealthSummary;
914
- bot?: BotSummary;
915
- fabricator?: FabricatorSummary;
916
- cargoEjector?: CargoEjectorSummary;
917
- cannon?: CannonSummary;
918
- thruster?: ThrusterSummary;
919
- pusher?: PusherSummary;
920
- pusherBeam?: PusherBeamSummary;
921
- launcher?: LauncherSummary;
922
- loader?: LoaderSummary;
923
- cargoHatch?: CargoHatchSummary;
924
- navigationUnit?: NavigationUnitSummary;
925
- commsStation?: CommsStationSummary;
926
- fluidTank?: FluidTankSummary;
927
- shieldGenerator?: ShieldGeneratorSummary;
928
- shieldProjector?: ShieldProjectorSummary;
929
- helm?: HelmSummary;
930
- player?: PlayerSummary;
931
- shipControl?: ShipControlSummary;
932
- sign?: SignSummary;
933
- spawnPoint?: SpawnPointSummary;
934
- door?: DoorSummary;
935
- shipSize?: ShipSizeSummary;
936
- }
937
- ```
938
-
939
- Feature lookup accepts the canonical component names above and selected aliases
940
- such as `outline`, `beam`, `inventory`, `filter`, `filterMode`, `filterSlots`,
941
- `occupied`, `mapMarker`, and `blueprint`.
942
-
943
- ## Machine API
944
-
945
- ### `MachineCollection`
946
-
947
- ```ts
948
- interface MachineCollection {
949
- state(): MachineSummary;
950
- raw(): MachineSummary;
951
- loaders(): LoaderHandle[];
952
- loader(entity: number | EntityHandle | EntitySummary): LoaderHandle;
953
- pushers(): PusherHandle[];
954
- pusher(entity: number | EntityHandle | EntitySummary): PusherHandle;
955
- launchers(): LauncherHandle[];
956
- launcher(entity: number | EntityHandle | EntitySummary): LauncherHandle;
957
- navigationUnits(): NavigationUnitHandle[];
958
- navigationUnit(entity?: number | EntityHandle | EntitySummary | null): NavigationUnitHandle | null;
959
- fabricators(): FabricatorHandle[];
960
- fabricator(entity: number | EntityHandle | EntitySummary): FabricatorHandle;
961
- commsStations(): CommsStationHandle[];
962
- commsStation(entity?: number | EntityHandle | EntitySummary | null): CommsStationHandle | null;
963
- signs(): SignHandle[];
964
- sign(entity: number | EntityHandle | EntitySummary): SignHandle;
965
- generators(): GeneratorHandle[];
966
- generator(entity: number | EntityHandle | EntitySummary): GeneratorHandle;
967
- cargoHatches(): CargoHatchHandle[];
968
- cargoHatch(entity: number | EntityHandle | EntitySummary): CargoHatchHandle;
969
- cargoEjectors(): CargoEjectorHandle[];
970
- cargoEjector(entity: number | EntityHandle | EntitySummary): CargoEjectorHandle;
971
- cannons(): CannonHandle[];
972
- cannon(entity: number | EntityHandle | EntitySummary): CannonHandle;
973
- thrusters(): ThrusterHandle[];
974
- thruster(entity: number | EntityHandle | EntitySummary): ThrusterHandle;
975
- helms(): HelmHandle[];
976
- helm(entity: number | EntityHandle | EntitySummary): HelmHandle;
977
- doors(): DoorHandle[];
978
- door(entity: number | EntityHandle | EntitySummary): DoorHandle;
979
- spawnPoints(): SpawnPointHandle[];
980
- spawnPoint(entity: number | EntityHandle | EntitySummary): SpawnPointHandle;
981
- shieldProjectors(): ShieldProjectorHandle[];
982
- shieldProjector(entity: number | EntityHandle | EntitySummary): ShieldProjectorHandle;
983
- fluidTanks(): FluidTankHandle[];
984
- fluidTank(entity: number | EntityHandle | EntitySummary): FluidTankHandle;
985
- expandoBoxes(): ExpandoBoxHandle[];
986
- expandoBox(entity: number | EntityHandle | EntitySummary): ExpandoBoxHandle;
987
- }
988
- ```
989
-
990
- ### `MachineSummary`
991
-
992
- Grouped machine/component state.
993
-
994
- ```ts
995
- interface MachineSummary {
996
- itemHolders: ItemHolderSummary[];
997
- health: HealthSummary[];
998
- fabricators: FabricatorSummary[];
999
- cargoEjectors: CargoEjectorSummary[];
1000
- cannons: CannonSummary[];
1001
- thrusters: ThrusterSummary[];
1002
- pushers: PusherSummary[];
1003
- pusherBeams: PusherBeamSummary[];
1004
- launchers: LauncherSummary[];
1005
- loaders: LoaderSummary[];
1006
- cargoHatches: CargoHatchSummary[];
1007
- navigationUnits: NavigationUnitSummary[];
1008
- commsStations: CommsStationSummary[];
1009
- fluidTanks: FluidTankSummary[];
1010
- shieldGenerators: ShieldGeneratorSummary[];
1011
- shieldProjectors: ShieldProjectorSummary[];
1012
- helms: HelmSummary[];
1013
- signs: SignSummary[];
1014
- spawnPoints: SpawnPointSummary[];
1015
- doors: DoorSummary[];
1016
- expandoBoxes: ExpandoBoxSummary[];
1017
- }
1018
- ```
1019
-
1020
- ### Common machine handle
1021
-
1022
- ```ts
1023
- interface MachineHandle extends EntityHandle {
1024
- open(options?: { invSlot?: number; hold?: boolean }, command?: Command): DredlessClient;
1025
- }
1026
- ```
1027
-
1028
- `open()` focuses/uses the entity through the player command path.
1029
-
1030
- ### `LoaderHandle`
1031
-
1032
- ```ts
1033
- interface LoaderHandle extends MachineHandle {
1034
- state: LoaderSummary | null;
1035
- configure(config?: LoaderConfig): DredlessClient;
1036
- configureFull(config?: LoaderFullConfig): DredlessClient;
1037
- copy(config?: LoaderFullConfig): DredlessClient;
1038
- setPickPlace(pick: LoaderPosition, place: LoaderPosition, config?: LoaderConfig): DredlessClient;
1039
- setPriority(priority: LoaderPriority, config?: LoaderConfig): DredlessClient;
1040
- setStack(stack: number, config?: LoaderConfig): DredlessClient;
1041
- setCycle(cycle: number, config?: LoaderConfig): DredlessClient;
1042
- setRequireOutput(requireOutput: boolean, config?: LoaderConfig): DredlessClient;
1043
- setWaitForStack(waitForStack: boolean, config?: LoaderConfig): DredlessClient;
1044
- setFilterMode(filterMode: LoaderFilterMode): DredlessClient;
1045
- setFilterItems(filterSlots?: Array<number | null | undefined>): DredlessClient;
1046
- pick: number | undefined;
1047
- place: number | undefined;
1048
- priority: number | undefined;
1049
- stack: number | undefined;
1050
- cycle: number | undefined;
1051
- requireOutput: boolean | undefined;
1052
- waitForStack: boolean | undefined;
1053
- filterMode: number | undefined;
1054
- filterSlots: Array<number | null>;
1055
- }
1056
- ```
1057
-
1058
- Config inputs:
1059
-
1060
- ```ts
1061
- const LoaderPosition = { TopLeft: "top-left", TopMiddle: "top-middle", TopRight: "top-right", MiddleLeft: "middle-left", MiddleRight: "middle-right", BottomLeft: "bottom-left", BottomMiddle: "bottom-middle", BottomRight: "bottom-right" } as const;
1062
- type LoaderPosition = typeof LoaderPosition[keyof typeof LoaderPosition];
1063
-
1064
- const LoaderPriority = { Low: "low", Normal: "normal", High: "high" } as const;
1065
- type LoaderPriority = typeof LoaderPriority[keyof typeof LoaderPriority];
1066
-
1067
- const LoaderFilterMode = { AllowAll: "allow-all", BlockFilter: "block-filter", AllowFilter: "allow-filter", BlockAll: "block-all" } as const;
1068
- type LoaderFilterMode = typeof LoaderFilterMode[keyof typeof LoaderFilterMode];
1069
-
1070
- interface LoaderConfig {
1071
- pick?: LoaderPosition;
1072
- place?: LoaderPosition;
1073
- priority?: LoaderPriority;
1074
- stack?: number;
1075
- cycle?: number;
1076
- requireOutput?: boolean;
1077
- waitForStack?: boolean;
1078
- }
1079
-
1080
- interface LoaderFullConfig extends LoaderConfig {
1081
- filterMode?: LoaderFilterMode;
1082
- filterSlots?: Array<number | null | undefined>;
1083
- }
1084
- ```
1085
-
1086
- State output:
1087
-
1088
- ```ts
1089
- interface LoaderSummary {
1090
- entity: number;
1091
- pick: number | null;
1092
- pickName: string | null;
1093
- place: number | null;
1094
- placeName: string | null;
1095
- priority: number | null;
1096
- priorityName: string | null;
1097
- requireOutput: boolean | null;
1098
- waitForStack: boolean | null;
1099
- stack: number | null;
1100
- cycle: number | null;
1101
- filterMode: number | null;
1102
- filterModeName: string | null;
1103
- filterSlots: (number | null)[] | null;
1104
- heldItemId: number | null;
1105
- heldItemName: string | null;
1106
- heldCount: number | null;
1107
- active: boolean;
1108
- progress: number | null;
1109
- state: ModelRecord;
1110
- filterState: ModelRecord;
1111
- filterSlotsState: ModelRecord;
1112
- }
1113
- ```
1114
-
1115
- ### `PusherHandle`
1116
-
1117
- ```ts
1118
- interface PusherHandle extends MachineHandle {
1119
- state: PusherSummary | null;
1120
- beam: PusherBeamSummary | null;
1121
- configure(config?: PusherConfig): DredlessClient;
1122
- setAngle(angle: number, config?: PusherConfig): DredlessClient;
1123
- setSpeed(speed: number, config?: PusherConfig): DredlessClient;
1124
- setLength(length: number, config?: PusherConfig): DredlessClient;
1125
- setMode(mode: PusherMode, config?: PusherConfig): DredlessClient;
1126
- setFilteredMode(mode: PusherMode, config?: PusherConfig): DredlessClient;
1127
- setFilterInventory(filterInventory: boolean, config?: PusherConfig): DredlessClient;
1128
- setFilterItems(filterSlots?: Array<number | null | undefined>): DredlessClient;
1129
- angle: number | undefined;
1130
- speed: number | undefined;
1131
- length: number | undefined;
1132
- mode: number | undefined;
1133
- filteredMode: number | undefined;
1134
- }
1135
- ```
1136
-
1137
- Config input:
1138
-
1139
- ```ts
1140
- const PusherMode = { Push: "push", Pull: "pull", DoNothing: "do-nothing" } as const;
1141
- type PusherMode = typeof PusherMode[keyof typeof PusherMode];
1142
-
1143
- interface PusherConfig {
1144
- mode?: PusherMode;
1145
- filteredMode?: PusherMode;
1146
- angle?: number;
1147
- speed?: number;
1148
- filterInventory?: boolean;
1149
- length?: number;
1150
- }
1151
- ```
1152
-
1153
- State output:
1154
-
1155
- ```ts
1156
- interface PusherSummary {
1157
- entity: number;
1158
- mode: number;
1159
- modeName: string | null;
1160
- filteredMode: number;
1161
- filteredModeName: string | null;
1162
- angle: number | null;
1163
- speed: number;
1164
- length: number;
1165
- filterInventory: boolean;
1166
- filterSlots: (number | null)[] | null;
1167
- state: ModelRecord;
1168
- filterSlotsState: ModelRecord;
1169
- }
1170
-
1171
- interface PusherBeamSummary {
1172
- entity: number;
1173
- active: boolean;
1174
- mode: number;
1175
- modeName: string | null;
1176
- lengthRaw: number;
1177
- length: number;
1178
- state: ModelRecord;
1179
- }
1180
- ```
1181
-
1182
- Pusher beams are associated with the same entity as their parent pusher, exposed
1183
- as `pusher.beam`, `entity.feature("beam")`, and `machines.state().pusherBeams`.
1184
-
1185
- ### `LauncherHandle`
1186
-
1187
- ```ts
1188
- interface LauncherHandle extends MachineHandle {
1189
- state: LauncherSummary | null;
1190
- setAngle(angle: number): DredlessClient;
1191
- setPower(power: number): DredlessClient;
1192
- angleDegrees: number | undefined;
1193
- angleRadians: number | undefined;
1194
- angleRaw: number | null | undefined;
1195
- }
1196
-
1197
- interface LauncherSummary {
1198
- entity: number;
1199
- angleRaw: number | null;
1200
- angleRadians: number | null;
1201
- angleDegrees: number | null;
1202
- state: ModelRecord;
1203
- }
1204
- ```
1205
-
1206
- Launcher power may not be present until the relevant UI has exposed it.
1207
-
1208
- ### `NavigationUnitHandle`
1209
-
1210
- ```ts
1211
- interface NavigationUnitHandle extends MachineHandle {
1212
- state: NavigationUnitSummary | null;
1213
- configure(config?: NavigationUnitConfig): DredlessClient;
1214
- copy(config?: NavigationUnitConfig): DredlessClient;
1215
- paste(config?: NavigationUnitConfig): DredlessClient;
1216
- setDestination(destination: number, config?: NavigationUnitConfig): DredlessClient;
1217
- setAutoWarp(config?: NavigationUnitConfig): DredlessClient;
1218
- startWarp(config?: NavigationUnitConfig): DredlessClient;
1219
- cancelWarp(config?: NavigationUnitConfig): DredlessClient;
1220
- destination: number | undefined;
1221
- autoWarpOnShieldFailure: boolean | undefined;
1222
- autoWarpOnNoCaptains: boolean | undefined;
1223
- warp: string | undefined;
1224
- }
1225
- ```
1226
-
1227
- Config and state:
1228
-
1229
- ```ts
1230
- interface NavigationUnitConfig {
1231
- destination?: number;
1232
- page?: number;
1233
- warp?: boolean | "start" | "idle" | "cancel";
1234
- autoWarpOnShieldFailure?: boolean;
1235
- autoWarpOnNoCaptains?: boolean;
1236
- }
1237
-
1238
- interface NavigationUnitSummary {
1239
- entity: number;
1240
- destination: number;
1241
- destinationName: string | null;
1242
- autoWarpOnShieldFailure: boolean | null;
1243
- autoWarpOnNoCaptains: boolean | null;
1244
- state: ModelRecord;
1245
- }
1246
- ```
1247
-
1248
- ### `FabricatorHandle`
1249
-
1250
- ```ts
1251
- interface FabricatorHandle extends MachineHandle {
1252
- state: FabricatorSummary | null;
1253
- panel(): PuiEvent | null;
1254
- add(itemId: number, count?: number, index?: number): DredlessClient;
1255
- sub(itemId: number, count?: number, index?: number): DredlessClient;
1256
- clearQueue(): DredlessClient;
1257
- toggleRepeat(): DredlessClient;
1258
- lockResource(row: number): DredlessClient;
1259
- unlockResource(row: number): DredlessClient;
1260
- eject(row: number): DredlessClient;
1261
- }
1262
-
1263
- const FabricatorType = { Starter: "starter", Munitions: "munitions", Engineering: "engineering", Equipment: "equipment" } as const;
1264
- type FabricatorType = typeof FabricatorType[keyof typeof FabricatorType];
1265
-
1266
- interface FabricatorSummary {
1267
- entity: number;
1268
- type: FabricatorType | null;
1269
- typeIndex: number | null;
1270
- state: ModelRecord;
1271
- rows: { itemId: number | null; itemName: string | null; count: number | null }[];
1272
- progress: number | null;
1273
- progressRaw: number | null;
1274
- active: boolean;
1275
- craftingItemId: number | null;
1276
- craftingItemName: string | null;
1277
- craftingCount: number | null;
1278
- }
1279
- ```
1280
-
1281
- ### `CommsStationHandle`
1282
-
1283
- ```ts
1284
- interface CommsStationHandle extends MachineHandle {
1285
- state: CommsStationSummary | null;
1286
- panel(): CommsEvent | null;
1287
- sendMessage(message?: string): DredlessClient;
1288
- }
1289
-
1290
- interface CommsStationSummary {
1291
- entity: number;
1292
- typeId: number;
1293
- typeName: string | null;
1294
- charges: number | null;
1295
- maxCharges: number;
1296
- chargeRatio: number | null;
1297
- occupied: boolean;
1298
- state: ModelRecord;
1299
- }
1300
- ```
1301
-
1302
- ### `SignHandle`
1303
-
1304
- ```ts
1305
- interface SignHandle extends MachineHandle {
1306
- state: SignSummary | null;
1307
- setText(text?: string, mode?: SignDisplayMode): DredlessClient;
1308
- text: string | undefined;
1309
- mode: number | undefined;
1310
- }
1311
-
1312
- const SignDisplayMode = { Always: "always", WhenNear: "when-near", OnHover: "on-hover" } as const;
1313
- type SignDisplayMode = typeof SignDisplayMode[keyof typeof SignDisplayMode];
1314
-
1315
- interface SignSummary {
1316
- entity: number;
1317
- text: string;
1318
- displayMode: number;
1319
- displayModeName: string | null;
1320
- state: ModelRecord;
1321
- }
1322
- ```
1323
-
1324
- ### `GeneratorHandle`
37
+ Signature blocks show how to call the API, using TypeScript notation for optional arguments and return values. They are
38
+ reference notation, not JavaScript programs to paste into an application. Examples labeled **fragment** require
39
+ variables established in a setup guide.
1325
40
 
1326
- ```ts
1327
- interface GeneratorHandle extends MachineHandle {
1328
- state: ShieldGeneratorSummary | null;
1329
- solvePuzzle(solution: string | number): DredlessClient;
1330
- }
41
+ - `DredlessClient` return: sent or queued, without server confirmation.
42
+ - `Promise<T>` return: asynchronous; read the method's documented completion condition. A promise can mean permission
43
+ granted and commit sent, observed state changed, or a server response arrived.
44
+ - `null`/`undefined`: state may be unavailable, not loaded, removed, or not applicable. Read the specific method's
45
+ contract before treating absence as an empty list or zero.
46
+ - `state` is usually a property on a machine handle; `state()` is a method on domains such as inventory and machine
47
+ collections.
48
+ - Large summary interfaces are linked to the declarations instead of duplicated field by field here.
1331
49
 
1332
- interface ShieldGeneratorSummary {
1333
- entity: number;
1334
- charge: number;
1335
- maxCharge: number;
1336
- chargeRatio: number | null;
1337
- efficiencyPercent: number | null;
1338
- efficiency: number | null;
1339
- storedItemId: number | null;
1340
- storedItemName: string | null;
1341
- storedItemCount: number | null;
1342
- hasShieldCore: boolean;
1343
- boostState: number;
1344
- boostStateName: string | null;
1345
- boostTimer: number;
1346
- boostActive: boolean;
1347
- puzzleSeed: number | null;
1348
- puzzleSolution: string | null;
1349
- state: ModelRecord;
1350
- itemState: ModelRecord;
1351
- boostStateRaw: ModelRecord;
1352
- }
1353
- ```
1354
-
1355
- ### `CargoHatchHandle`
1356
-
1357
- ```ts
1358
- interface CargoHatchHandle extends MachineHandle {
1359
- state: CargoHatchSummary | null;
1360
- configure(config?: Pick<LoaderFullConfig, "filterMode" | "filterSlots">): DredlessClient;
1361
- copy(config?: Pick<LoaderFullConfig, "filterMode" | "filterSlots">): DredlessClient;
1362
- paste(config?: Pick<LoaderFullConfig, "filterMode" | "filterSlots">): DredlessClient;
1363
- setFilterMode(filterMode: LoaderFilterMode): DredlessClient;
1364
- setFilterItems(filterSlots?: Array<number | null | undefined>): DredlessClient;
1365
- }
1366
-
1367
- interface CargoHatchSummary {
1368
- entity: number;
1369
- typeId: number;
1370
- typeName: string | null;
1371
- filterMode: number;
1372
- filterModeName: string | null;
1373
- filterSlots: (number | null)[] | null;
1374
- openFraction: number | null;
1375
- filterState: ModelRecord;
1376
- filterSlotsState: ModelRecord;
1377
- }
1378
- ```
1379
-
1380
- ### Other machine handles
1381
-
1382
- ```ts
1383
- interface CannonHandle extends MachineHandle {
1384
- state: CannonSummary | null;
1385
- }
1386
-
1387
- interface ThrusterHandle extends MachineHandle {
1388
- state: ThrusterSummary | null;
1389
- }
1390
-
1391
- interface HelmHandle extends MachineHandle {
1392
- state: HelmSummary | null;
1393
- occupied: boolean | undefined;
1394
- }
1395
-
1396
- interface DoorHandle extends EntityHandle {
1397
- state: DoorSummary | null;
1398
- rank: number | undefined;
1399
- open: boolean | undefined;
1400
- }
1401
-
1402
- interface SpawnPointHandle extends MachineHandle {
1403
- state: SpawnPointSummary | null;
1404
- rank: number | undefined;
1405
- }
1406
-
1407
- interface ShieldProjectorHandle extends MachineHandle {
1408
- state: ShieldProjectorSummary | null;
1409
- active: boolean | undefined;
1410
- }
1411
-
1412
- interface FluidTankHandle extends MachineHandle {
1413
- state: FluidTankSummary | null;
1414
- amount: number | null | undefined;
1415
- }
1416
-
1417
- interface ExpandoBoxHandle extends MachineHandle {
1418
- state: ExpandoBoxSummary | null;
1419
- item: number | null | undefined;
1420
- count: number | null | undefined;
1421
- }
1422
-
1423
- interface CargoEjectorSummary {
1424
- entity: number;
1425
- typeId: number;
1426
- typeName: string | null;
1427
- progress: number | null;
1428
- active: boolean | null;
1429
- }
1430
-
1431
- interface CargoEjectorHandle extends MachineHandle {
1432
- state: CargoEjectorSummary | null;
1433
- progress: number | null | undefined;
1434
- active: boolean | null | undefined;
1435
- setDirection(direction: FixedAngleDirection): DredlessClient;
1436
- copy(direction?: FixedAngleDirection): DredlessClient;
1437
- paste(direction?: FixedAngleDirection): DredlessClient;
1438
- }
1439
- ```
1440
-
1441
- Associated summary shapes:
1442
-
1443
- ```ts
1444
- interface CannonSummary {
1445
- entity: number;
1446
- typeId: number;
1447
- typeName: string | null;
1448
- ammoItemId: number | null;
1449
- ammoName: string | null;
1450
- ammoCount: number;
1451
- aim: number | null;
1452
- recoil: number | null;
1453
- recoil2: number | null;
1454
- recoils: [number | null, number | null];
1455
- charge: number | null;
1456
- charged: boolean | null;
1457
- spin: number | null;
1458
- coolingCellCount: number;
1459
- state: ModelRecord;
1460
- }
1461
-
1462
- interface ThrusterSummary {
1463
- entity: number;
1464
- typeId: number;
1465
- typeName: string | null;
1466
- facing: number;
1467
- facingName:
1468
- | "bottom"
1469
- | "top"
1470
- | "right"
1471
- | "left"
1472
- | "bottom-right"
1473
- | "bottom-left"
1474
- | "top-right"
1475
- | "top-left"
1476
- | null;
1477
- fuel: number | null;
1478
- state: ModelRecord;
1479
- }
1480
-
1481
- interface HelmSummary {
1482
- entity: number;
1483
- typeId: number;
1484
- typeName: string | null;
1485
- occupied: boolean;
1486
- }
1487
-
1488
- interface DoorSummary {
1489
- entity: number;
1490
- rank: number;
1491
- rankName: string | null;
1492
- open: boolean;
1493
- rankState: ModelRecord;
1494
- state: ModelRecord;
1495
- }
1496
-
1497
- interface SpawnPointSummary {
1498
- entity: number;
1499
- rank: number;
1500
- rankName: string | null;
1501
- state: ModelRecord;
1502
- }
1503
-
1504
- interface ShieldProjectorSummary {
1505
- entity: number;
1506
- active: boolean;
1507
- state: ModelRecord;
1508
- }
1509
-
1510
- interface FluidTankSummary {
1511
- entity: number;
1512
- amount: number | null;
1513
- state: ModelRecord;
1514
- }
1515
-
1516
- interface ExpandoBoxSummary {
1517
- entity: number;
1518
- itemId: number | null;
1519
- itemName: string | null;
1520
- count: number | null;
1521
- width: number | null;
1522
- height: number | null;
1523
- rawWidth: number | null;
1524
- rawHeight: number | null;
1525
- itemState: ModelRecord;
1526
- sizeState: ModelRecord;
1527
- }
1528
- ```
1529
-
1530
- ## Ship Reads
1531
-
1532
- ### `ShipHandle`
1533
-
1534
- Returned by `client.overworld()?.ships()`.
1535
-
1536
- ```ts
1537
- interface ShipHandle {
1538
- entity: number;
1539
- name: string | null;
1540
- hexCode: string | null;
1541
- distance: number | null;
1542
- worldId: number | null;
1543
- hasWorldData: boolean;
1544
- world(): WorldDomain | null;
1545
- snapshot(): ShipReadSummary;
1546
- }
1547
- ```
1548
-
1549
- ### `ShipReadSummary`
1550
-
1551
- ```ts
1552
- interface ShipReadSummary {
1553
- entity: number;
1554
- name: string | null;
1555
- hexCode: string | null;
1556
- color: number | null;
1557
- colorCss: string | null;
1558
- position: { x: number | null; y: number | null; rot: number | null } | null;
1559
- distance: number | null;
1560
- footprint: EntitySummary["footprint"];
1561
- label: string;
1562
- kind: string[];
1563
- thrust: { x: number | null; y: number | null };
1564
- shield: ShipShieldSummary | null;
1565
- warp: ShipWarpSummary | null;
1566
- worldId: number | null;
1567
- hasWorldData: boolean;
1568
- world: WorldSnapshot | null;
1569
- control: ShipControlSummary;
1570
- entitySummary: EntitySummary;
1571
- }
1572
- ```
1573
-
1574
- ### `ShipControlSummary`
1575
-
1576
- ```ts
1577
- interface ShipControlSummary {
1578
- entity: number;
1579
- name: string | null;
1580
- hexCode: string | null;
1581
- shipWorldId: number | null;
1582
- color: number | null;
1583
- colorCss: string | null;
1584
- thrustX: number | null;
1585
- thrustY: number | null;
1586
- value52: number | null;
1587
- value84: number | null;
1588
- value96: number | null;
1589
- shield: ShipShieldSummary | null;
1590
- warp: ShipWarpSummary | null;
1591
- state: ModelRecord;
1592
- }
1593
- ```
1594
-
1595
- ### Ship shield and warp summaries
1596
-
1597
- ```ts
1598
- interface ShipShieldSummary {
1599
- maxHp: number | null;
1600
- baseHp: number | null;
1601
- activeTankHp: number | null;
1602
- inactiveTankHp: number | null;
1603
- tankValues: number[];
1604
- }
1605
-
1606
- interface ShipWarpSummary {
1607
- active: boolean;
1608
- ticks: number;
1609
- elapsedSeconds: number;
1610
- durationSeconds: number;
1611
- remainingSeconds: number;
1612
- }
1613
- ```
1614
-
1615
- ## Player, Blocks, Materials
1616
-
1617
- ```ts
1618
- interface PlayerCollection {
1619
- all(): PlayerSummary[];
1620
- current(): PlayerSummary | null;
1621
- }
1622
-
1623
- interface BlockCollection {
1624
- all(): BlockSummary[];
1625
- at(x: number, y: number): BlockSummary | null;
1626
- }
1627
-
1628
- interface MaterialCollection {
1629
- all(): MaterialSummary[];
1630
- }
1631
- ```
1632
-
1633
- ### `PlayerSummary`
1634
-
1635
- ```ts
1636
- interface PlayerSummary {
1637
- entity: number;
1638
- name: string | null;
1639
- heldItemId: number | null;
1640
- heldItemName: string | null;
1641
- repairTargetDistance: number | null;
1642
- repairTargetAngle: number | null;
1643
- shipRank: PlayerShipRank | null;
1644
- patronTier: "bronze" | "silver" | "gold" | "plat" | "flux" | null;
1645
- isDeveloper: boolean;
1646
- isPatron: boolean;
1647
- piloting: boolean;
1648
- muted: boolean;
1649
- actionPreview: PlayerActionPreviewSummary | null;
1650
- state: ModelRecord;
1651
- }
1652
- ```
1653
-
1654
- ### `PlayerActionPreviewSummary`
1655
-
1656
- ```ts
1657
- interface PlayerActionPreviewSummary {
1658
- entity: number;
1659
- active: boolean;
1660
- x: number | null;
1661
- y: number | null;
1662
- width: number | null;
1663
- height: number | null;
1664
- progress: number | null;
1665
- color: number | null;
1666
- colorCss: string | null;
1667
- actionName: "place" | "break" | "blueprint" | null;
1668
- blueprintId: number | null;
1669
- blueprintItems: BlueprintPreviewSummary[];
1670
- state: ModelRecord;
1671
- }
1672
- ```
1673
-
1674
- ### `BlockSummary`
1675
-
1676
- ```ts
1677
- interface BlockSummary {
1678
- x: number;
1679
- y: number;
1680
- entities: EntitySummary[];
1681
- }
1682
- ```
1683
-
1684
- ### `MaterialSummary`
1685
-
1686
- ```ts
1687
- interface MaterialSummary {
1688
- material: number;
1689
- name: string | null;
1690
- count: number;
1691
- solid: boolean | null;
1692
- hp: number | null;
1693
- }
1694
- ```
1695
-
1696
- ## World State Classes
1697
-
1698
- These classes are public mostly for inspection, replay, testing, and lower-level
1699
- tooling.
1700
-
1701
- ### `WorldStore`
1702
-
1703
- ```ts
1704
- class WorldStore {
1705
- currentWorldId: number | null;
1706
- worlds: Map<number, WorldState>;
1707
-
1708
- get(id: number): WorldState;
1709
- apply(packet: unknown): WorldUpdate | null;
1710
- snapshot(options?: { includeTiles?: boolean; includeModel?: boolean }): WorldSnapshot[];
1711
- ids(): number[];
1712
- overworld(): WorldState | null;
1713
- shipWorld(): WorldState | null;
1714
- currentShipEntity(): EntitySummary | null;
1715
- }
1716
- ```
1717
-
1718
- ### `WorldState`
1719
-
1720
- ```ts
1721
- class WorldState {
1722
- constructor(id: number);
1723
-
1724
- id: number;
1725
- seed: number | null;
1726
- isOverworld: boolean | null;
1727
- tileset: Tileset | null;
1728
- blockWidth: number | null;
1729
- blockHeight: number | null;
1730
- parentWorld: number | null;
1731
- parentEntity: number | null;
1732
- tiles: Map<string, Tile>;
1733
- chunks: unknown[];
1734
- events: unknown[];
1735
- modelPackets: unknown[];
1736
- commsBubbles: CommsBubbleSummary[];
1737
- model: ModelState;
1738
- lastChunkPatch: unknown;
1739
- lastPacket: unknown;
1740
- meta: unknown;
1741
-
1742
- readMeta(packet: unknown): void;
1743
- addCommsBubble(packet: unknown): CommsBubbleSummary;
1744
- decodeEncrypted(data: Uint8Array | ArrayBuffer | number[]): unknown;
1745
- applyTile(value: unknown): Tile | null;
1746
- applyChunk(value: unknown): Tile[] | null;
1747
- setTile(tile: Tile): Tile;
1748
- normalizeTile(tile: Tile): Tile;
1749
- materials(): MaterialSummary[];
1750
- snapshot(options?: { includeTiles?: boolean; includeModel?: boolean }): WorldSnapshot;
1751
- table(id: number): Map<number, ModelRecord>;
1752
- record(tableId: number, entityId: number): ModelRecord | null;
1753
- tileDefinition(material: number): TileDefinition | null;
1754
- entity(entityId: number): EntitySummary | null;
1755
- entities(): EntitySummary[];
1756
- blocks(): BlockSummary[];
1757
- }
1758
- ```
1759
-
1760
- ### `ModelState`
1761
-
1762
- ```ts
1763
- class ModelState {
1764
- generation: number | null;
1765
- tables: Map<number, Map<number, ModelRecord>>;
1766
- removedEntities: number[];
1767
- lastUpdate: unknown;
1768
- errors: unknown[];
1769
-
1770
- table(id: number): Map<number, ModelRecord>;
1771
- record(tableId: number, entityId: number): ModelRecord | null;
1772
- entity(entityId: number): EntitySummary | null;
1773
- entities(): EntitySummary[];
1774
- blocks(): BlockSummary[];
1775
- apply(bytes: Uint8Array | ArrayBuffer | number[]): unknown;
1776
- snapshot(options?: { includeTables?: boolean }): ModelSnapshot;
1777
- tablesSnapshot(): unknown[];
1778
- transforms(): TransformSummary[];
1779
- itemHolders(): ItemHolderSummary[];
1780
- fabricators(): FabricatorSummary[];
1781
- players(): PlayerSummary[];
1782
- shipControls(): ShipControlSummary[];
1783
- shipMetadata(): ShipWorldMetadataSummary | null;
1784
- machines(): MachineSummary;
1785
- }
1786
-
1787
- type ModelRecord = Record<string, unknown>;
1788
- ```
1789
-
1790
- ### `WorldSnapshot`
1791
-
1792
- ```ts
1793
- interface WorldSnapshot {
1794
- id: number;
1795
- is_overworld: boolean | null;
1796
- overworldZone: OverworldZoneSummary | null;
1797
- shipMetadata: ShipWorldMetadataSummary | null;
1798
- tileset: Tileset | null;
1799
- seed: number | null;
1800
- block_w: number | null;
1801
- block_h: number | null;
1802
- parent_world: number | null;
1803
- parent_ent: number | null;
1804
- tileCount: number;
1805
- chunkCount: number;
1806
- lastChunkPatch: unknown;
1807
- lastPacket: unknown;
1808
- meta: unknown;
1809
- materials: MaterialSummary[];
1810
- model: ModelSnapshot;
1811
- entities: EntitySummary[];
1812
- blocks: BlockSummary[];
1813
- transforms: TransformSummary[];
1814
- machines: MachineSummary;
1815
- players: PlayerSummary[];
1816
- shipControls: ShipControlSummary[];
1817
- commsBubbles: CommsBubbleSummary[];
1818
- tiles?: Tile[];
1819
- }
1820
- ```
1821
-
1822
- ### World metadata
1823
-
1824
- ```ts
1825
- interface OverworldZoneSummary {
1826
- id: number;
1827
- baseId: number;
1828
- layer: number;
1829
- key: string;
1830
- name: string;
1831
- tiered: boolean;
1832
- displayName: string;
1833
- }
1834
-
1835
- interface ShipWorldMetadataSummary {
1836
- name: string | null;
1837
- color: number | null;
1838
- colorCss: string | null;
1839
- width: number | null;
1840
- height: number | null;
1841
- lockdownTimerSeconds: number | null;
1842
- lockdownCountdownSeconds: number | null;
1843
- onlineShipOwnerCount: number | null;
1844
- requiredShipOwnerCount: number | null;
1845
- allShipOwnersOnline: boolean | null;
1846
- lockdownEngaged: boolean | null;
1847
- lockdownState: ModelRecord;
1848
- shipState: ModelRecord;
1849
- }
1850
-
1851
- interface WorldUpdate {
1852
- type: string;
1853
- world: WorldState | null;
1854
- packet?: unknown;
1855
- bubble?: CommsBubbleSummary;
1856
- decoded?: unknown;
1857
- updates?: unknown[];
1858
- result?: unknown;
1859
- }
1860
- ```
1861
-
1862
- ### Tiles
1863
-
1864
- ```ts
1865
- interface Tile {
1866
- x: number;
1867
- y: number;
1868
- material: number;
1869
- materialName?: string | null;
1870
- shape: number;
1871
- shapeName?: string | null;
1872
- hp: number;
1873
- /** @deprecated Use hp. Raw 0-255 HP fraction byte, not absolute integrity. */
1874
- integrity: number;
1875
- color: number | null;
1876
- solid?: boolean | null;
1877
- maxHp?: number | null;
1878
- hpRatio?: number | null;
1879
- hpValue?: number | null;
1880
- }
1881
-
1882
- interface TilePhysics {
1883
- filter?: {
1884
- categoryBits: number;
1885
- maskBits: number;
1886
- groupIndex: number;
1887
- };
1888
- transparent?: boolean;
1889
- walkway?: boolean;
1890
- restitution?: number;
1891
- friction?: number;
1892
- }
1893
-
1894
- interface TileDefinition {
1895
- name?: string;
1896
- solid: boolean;
1897
- destruct_item?: number;
1898
- blocks_bullets?: boolean;
1899
- hp?: number;
1900
- no_build_surface?: boolean;
1901
- physics?: TilePhysics;
1902
- }
1903
-
1904
- interface Tileset {
1905
- scale: number;
1906
- atlas: string;
1907
- tile_width: number;
1908
- tiles: TileDefinition[];
1909
- }
1910
- ```
1911
-
1912
- ### `ModelSnapshot`
1913
-
1914
- ```ts
1915
- interface ModelSnapshot {
1916
- generation: number | null;
1917
- tableCount: number;
1918
- entityCount: number;
1919
- removedEntities: number[];
1920
- lastUpdate: unknown;
1921
- errors: unknown[];
1922
- entities: EntitySummary[];
1923
- blocks: BlockSummary[];
1924
- transforms: TransformSummary[];
1925
- players: PlayerSummary[];
1926
- shipControls: ShipControlSummary[];
1927
- machines: MachineSummary;
1928
- tables: unknown[];
1929
- }
1930
- ```
1931
-
1932
- ## Additional Entity Component Shapes
1933
-
1934
- ```ts
1935
- interface TransformSummary {
1936
- entity: number;
1937
- x: number | null;
1938
- y: number | null;
1939
- rot: number | null;
1940
- flags: unknown[];
1941
- }
1942
-
1943
- interface ItemHolderSummary {
1944
- entity: number;
1945
- itemId: number | null;
1946
- itemName: string | null;
1947
- count: number | null;
1948
- }
1949
-
1950
- interface ItemCrateSummary {
1951
- entity: number;
1952
- itemId: number | null;
1953
- itemName: string | null;
1954
- count: number | null;
1955
- width: number | null;
1956
- height: number | null;
1957
- itemState: ModelRecord;
1958
- sizeState: ModelRecord;
1959
- }
1960
-
1961
- interface HoverOutlineSummary {
1962
- entity: number;
1963
- width: number | null;
1964
- height: number | null;
1965
- rawWidth: number | null;
1966
- rawHeight: number | null;
1967
- state: ModelRecord;
1968
- }
1969
-
1970
- interface MapMarkerSummary {
1971
- entity: number;
1972
- kind: string;
1973
- title: string | null;
1974
- key: string | null;
1975
- description: string | null;
1976
- color: number | null;
1977
- colorCss: string | null;
1978
- accentColor: number | null;
1979
- accentColorCss: string | null;
1980
- width: number | null;
1981
- height: number | null;
1982
- labelState: ModelRecord;
1983
- zoneState: ModelRecord;
1984
- }
1985
-
1986
- interface DockingSpringSummary {
1987
- entity: number;
1988
- id: number | null;
1989
- width: number;
1990
- height: number;
1991
- state: ModelRecord;
1992
- }
1993
-
1994
- interface HugeThrusterSummary {
1995
- entity: number;
1996
- width: number;
1997
- height: number;
1998
- state: ModelRecord;
1999
- }
2000
-
2001
- interface ShipSizeSummary {
2002
- entity: number;
2003
- width: number | null;
2004
- height: number | null;
2005
- rawWidth: number | null;
2006
- rawHeight: number | null;
2007
- state: ModelRecord;
2008
- }
2009
-
2010
- interface HealthSummary {
2011
- entity: number;
2012
- hp: number | null;
2013
- maxHp: number | null;
2014
- ratio: number | null;
2015
- state: ModelRecord;
2016
- }
2017
-
2018
- interface BotSummary {
2019
- entity: number;
2020
- className: string;
2021
- identifier: string;
2022
- typeA: number | null;
2023
- typeB: number | null;
2024
- }
2025
- ```
2026
-
2027
- ## Blueprint Shapes
2028
-
2029
- ### Placement request
2030
-
2031
- ```ts
2032
- interface BlueprintPlacement {
2033
- x: number;
2034
- y: number;
2035
- width?: number;
2036
- height?: number;
2037
- w?: number;
2038
- h?: number;
2039
- source: string;
2040
- }
2041
-
2042
- interface BlueprintPlacementMessage {
2043
- type: 9;
2044
- x: number;
2045
- y: number;
2046
- w: number;
2047
- h: number;
2048
- source: string;
2049
- }
2050
- ```
2051
-
2052
- ### Preview state
2053
-
2054
- ```ts
2055
- interface BlueprintPreviewSummary {
2056
- entity: number;
2057
- itemId: number;
2058
- itemName: string | null;
2059
- bits: number;
2060
- rawBits: number | null;
2061
- placementOffsets: number[];
2062
- placementCount: number;
2063
- placements: {
2064
- offset: number;
2065
- x: number | null;
2066
- y: number | null;
2067
- itemId: number;
2068
- itemName: string | null;
2069
- }[];
2070
- x: number | null;
2071
- y: number | null;
2072
- rot: number | null;
2073
- state: ModelRecord;
2074
- }
2075
- ```
2076
-
2077
- ## PUI And Comms Shapes
2078
-
2079
- ```ts
2080
- interface PuiEvent {
2081
- type: "pui";
2082
- filter?: number;
2083
- ent_id?: number;
2084
- update?: boolean;
2085
- data?: unknown;
2086
- world?: number | null;
2087
- }
2088
-
2089
- interface CommsMessage {
2090
- type: 3;
2091
- msg: string;
2092
- }
2093
-
2094
- interface NormalizedCommsMessage {
2095
- raw: unknown;
2096
- text: string;
2097
- }
2098
-
2099
- interface CommsEvent {
2100
- type: "comms";
2101
- filter?: number;
2102
- ent_id: number | null;
2103
- entity: number | null;
2104
- msgs_text: unknown[];
2105
- rawMessages: unknown[];
2106
- messages: NormalizedCommsMessage[];
2107
- update?: boolean;
2108
- world?: number | null;
2109
- }
2110
-
2111
- interface CommsBubbleSummary {
2112
- sequence: number;
2113
- worldId: number;
2114
- entity: number | null;
2115
- modelId: number | null;
2116
- message: string;
2117
- color: number | null;
2118
- colorCss: string | null;
2119
- durationSeconds: number | null;
2120
- raw: unknown;
2121
- }
2122
- ```
2123
-
2124
- ## Scanner And Ack Shapes
2125
-
2126
- ```ts
2127
- interface CommandAck {
2128
- world: number;
2129
- commandNumber: number;
2130
- }
2131
-
2132
- interface ScannerResult {
2133
- kind: "manifest" | "bom" | "unknown";
2134
- sid: number | null;
2135
- shipHex: string | null;
2136
- shipName: string | null;
2137
- blocks: Record<string, number> | null;
2138
- objects: Record<string, number> | null;
2139
- inventories: Record<string, number> | null;
2140
- materials: Record<string, number> | null;
2141
- }
2142
- ```
2143
-
2144
- ## Helper Function Exports
2145
-
2146
- These are public lower-level helpers. Prefer the object/domain methods unless
2147
- you explicitly need protocol payloads or decoded utility functions.
2148
-
2149
- ### Msgpack
2150
-
2151
- Module: `dredless/protocol/msgpack` or root.
2152
-
2153
- ```ts
2154
- function decodeMsgpack(bytes: Uint8Array | ArrayBuffer | number[]): unknown;
2155
- function encodeMsgpack(value: unknown): Uint8Array;
2156
- ```
2157
-
2158
- ### Commands
2159
-
2160
- Module: `dredless/protocol/commands` or root.
2161
-
2162
- ```ts
2163
- function buildSignedCommandPacket(command: Command, sessionId: number): Uint8Array;
2164
- ```
2165
-
2166
- ### Inventory helpers
2167
-
2168
- Module: `dredless/protocol/inventory` or root.
2169
-
2170
- ```ts
2171
- function normalizeEquipmentSlot(slot: EquipmentSlot): 16 | 17 | 18 | 19 | 20 | 21;
2172
- function equipmentSlotName(slot: number): "head" | "face" | "body" | "back" | "hands" | "feet" | null;
2173
- function buildInventoryDragCommand(source: number, target: number, split?: boolean): InventoryDragCommand;
2174
- function buildEquipItemCommand(source: number, slot: EquipmentSlot, split?: boolean): InventoryDragCommand;
2175
- function buildUnequipItemCommand(slot: EquipmentSlot, target?: number, split?: boolean): InventoryDragCommand;
2176
- function normalizeInventoryEvent(event: unknown): InventoryState;
2177
- ```
2178
-
2179
- Inventory drag output remains protocol-shaped:
2180
-
2181
- ```ts
2182
- interface InventoryDragCommand {
2183
- drag: {
2184
- source: number;
2185
- target: number;
2186
- split: boolean;
2187
- };
2188
- }
2189
- ```
2190
-
2191
- `normalizeInventoryEvent()` returns the normalized `InventoryState` shape documented under `client.inventory`.
2192
-
2193
- ### Chat helpers
2194
-
2195
- Module: `dredless/protocol/chat` or root.
2196
-
2197
- ```ts
2198
- function buildChatMessage(message?: string): ChatMessage;
2199
- ```
2200
-
2201
- Ship chat uses protocol message type 2. It is separate from comms-station
2202
- messages, which use type 3. The game handles ship chat through the same
2203
- chat-command path used by its chat commands, so client.sendChatMessage() can
2204
- send executable chat commands as well as ordinary chat text. For example:
2205
-
2206
- ```js
2207
- client.sendChatMessage("/save");
2208
- ```
2209
-
2210
- ### Comms helpers
2211
-
2212
- Module: `dredless/protocol/comms` or root.
2213
-
2214
- ```ts
2215
- function buildCommsMessage(message?: string): CommsMessage;
2216
- function normalizeCommsEvent(event: unknown): CommsEvent;
2217
- function flattenRichText(value: unknown): string;
2218
- ```
2219
-
2220
- ### Sign helpers
2221
-
2222
- Module: `dredless/protocol/sign` or root.
2223
-
2224
- ```ts
2225
- function buildSignTextMessage(text?: string, mode?: SignDisplayMode): SignTextMessage;
2226
- function normalizeSignDisplayMode(mode?: SignDisplayMode): 0 | 1 | 2;
2227
- function signDisplayModeName(mode: number): SignDisplayMode | null;
2228
- ```
2229
-
2230
- Output:
2231
-
2232
- ```ts
2233
- interface SignTextMessage {
2234
- type: 5;
2235
- cmd: "sign_text";
2236
- args: [string, 0 | 1 | 2];
2237
- }
2238
- ```
2239
-
2240
- ### Ship-management helpers
2241
-
2242
- Module: `dredless/protocol/ship-management` or root.
2243
-
2244
- ```ts
2245
- function buildShipManagementMessage(act: string, arg?: unknown, extra?: Record<string, unknown> | null): ShipManagementMessage;
2246
- function buildShipPrivacyMessage(privacy: ShipPrivacy): ShipManagementMessage;
2247
- function buildStarterRecoveryMessage(itemId: number): ShipManagementMessage;
2248
- function buildPlayerListMessage(): ShipManagementMessage;
2249
- function buildInviteResetMessage(): ShipManagementMessage;
2250
- function buildSetPlayerRankMessage(refId: number, rank: ShipPlayerRank): ShipManagementMessage;
2251
- function buildKickPlayerMessage(refId: number): ShipManagementMessage;
2252
- function buildBanPlayerMessage(refId: number): ShipManagementMessage;
2253
- function buildDemoteSelfMessage(): ShipManagementMessage;
2254
- function normalizePrivacy(privacy: ShipPrivacy): 0 | 1;
2255
- function normalizePlayerRank(rank: ShipPlayerRank): 0 | 1 | 3;
2256
- function normalizeShipConfig(event: unknown): ShipConfig;
2257
- function normalizeCaptainSubrank(event: unknown): CaptainSubrank;
2258
- function normalizeShipPlayerList(event: unknown, previous?: ShipPlayerList | null, currentCaptainSubrank?: CaptainSubrank | null): ShipPlayerList;
2259
- ```
2260
-
2261
- Message output:
2262
-
2263
- ```ts
2264
- interface ShipManagementMessage {
2265
- type: 4;
2266
- act: string;
2267
- arg: unknown;
2268
- rank?: unknown;
2269
- }
2270
- ```
2271
-
2272
- ### Blueprint helpers
2273
-
2274
- Module: `dredless/protocol/blueprint` or root.
2275
-
2276
- ```ts
2277
- function buildBlueprintPlacementMessage(placement: BlueprintPlacement): BlueprintPlacementMessage;
2278
- ```
2279
-
2280
- ### UI config helpers
2281
-
2282
- Module: `dredless/protocol/ui-config` or root.
2283
-
2284
- ```ts
2285
- function buildNavigationUnitConfigData(entity: number, config: NavigationUnitConfig & { destination: number }): Uint8Array;
2286
- function buildNavigationUnitClipboardConfigData(config: NavigationUnitConfig & { destination: number }): Uint8Array;
2287
- function buildNavigationUnitPasteConfigData(entity: number, config: NavigationUnitConfig & { destination: number }): Uint8Array;
2288
- function buildGeneratorMazePuzzleData(entity: number, solution: string | number): Uint8Array;
2289
- function buildCargoHatchFilterConfigData(entity: number, filterMode?: LoaderFilterMode): Uint8Array;
2290
- function buildCargoHatchFilterItemsData(entity: number, filterSlots?: Array<number | null | undefined>): Uint8Array;
2291
- function buildCargoHatchFullConfigData(entity: number, config?: Pick<LoaderFullConfig, "filterMode" | "filterSlots">): Uint8Array;
2292
- function buildCargoHatchCopyConfigData(config?: Pick<LoaderFullConfig, "filterMode" | "filterSlots">): Uint8Array;
2293
- function buildClipboardConfigData(target: ClipboardTarget, commandName: string, values?: Iterable<number>): Uint8Array;
2294
- function buildClipboardFixedAngleData(target: ClipboardTarget, direction: FixedAngleDirection): Uint8Array;
2295
- function buildGeneratorClipboardDirectionData(direction: FixedAngleDirection): Uint8Array;
2296
- function buildCargoEjectorDirectionData(entity: number, direction: FixedAngleDirection): Uint8Array;
2297
- function buildCargoEjectorPasteConfigData(entity: number, direction: FixedAngleDirection): Uint8Array;
2298
- function buildCargoEjectorCopyConfigData(direction: FixedAngleDirection): Uint8Array;
2299
- function buildCargoEjectorClipboardDirectionData(direction: FixedAngleDirection): Uint8Array;
2300
- function buildExpandoClipboardAngleData(angle: number): Uint8Array;
2301
- function buildLoaderClipboardConfigData(config?: LoaderConfig): Uint8Array;
2302
- function buildLoaderConfigData(entity: number, config?: LoaderConfig): Uint8Array;
2303
- function buildLoaderCopyConfigData(config?: LoaderFullConfig): Uint8Array;
2304
- function buildLoaderFilterConfigData(entity: number, filterMode?: LoaderFilterMode): Uint8Array;
2305
- function buildLoaderFilterItemsData(entity: number, filterSlots?: Array<number | null | undefined>): Uint8Array;
2306
- function buildLoaderFullConfigData(entity: number, config?: LoaderFullConfig): Uint8Array;
2307
- function buildPusherConfigData(entity: number, config?: PusherConfig): Uint8Array;
2308
- function buildPusherFilterItemsData(entity: number, filterSlots?: Array<number | null | undefined>): Uint8Array;
2309
- ```
2310
-
2311
- Clipboard/config input types:
2312
-
2313
- ```ts
2314
- type ClipboardTarget =
2315
- | number
2316
- | "loader" | "loader-config" | "loaderConfig"
2317
- | "hatch" | "cargo-hatch" | "cargoHatch"
2318
- | "ejector" | "cargo-ejector" | "cargoEjector"
2319
- | "expando" | "expando-box" | "expandoBox"
2320
- | "generator" | "shield-generator" | "shieldGenerator"
2321
- | "navigation" | "navigation-unit" | "navigationUnit"
2322
- | "nav" | "nav-unit" | "navUnit";
2323
-
2324
- const FixedAngleDirection = { Right: "right", Up: "up", Left: "left", Down: "down" } as const;
2325
- type FixedAngleDirection = typeof FixedAngleDirection[keyof typeof FixedAngleDirection];
2326
- ```
2327
-
2328
- ### Generator maze helpers
2329
-
2330
- Module: `dredless/game/generator-maze` or root.
2331
-
2332
- ```ts
2333
- function generateGeneratorMaze(seed: number): GeneratorMaze;
2334
- function solveGeneratorMazeSeed(seed: number): string;
2335
- function maybeSolveGeneratorMazeSeed(seed: number | null | undefined): string | null;
2336
- ```
2337
-
2338
- Output:
2339
-
2340
- ```ts
2341
- interface GeneratorMazeCellWalls {
2342
- up: boolean;
2343
- down: boolean;
2344
- left: boolean;
2345
- right: boolean;
2346
- }
2347
-
2348
- interface GeneratorMazeCell {
2349
- x: number;
2350
- y: number;
2351
- value: number;
2352
- hex: string;
2353
- digit: number;
2354
- walls: GeneratorMazeCellWalls;
2355
- backtrackDirection: number;
2356
- marker: number;
2357
- }
2358
-
2359
- interface GeneratorMaze {
2360
- seed: number;
2361
- width: number;
2362
- height: number;
2363
- cells: GeneratorMazeCell[];
2364
- rows: GeneratorMazeCell[][];
2365
- solution: string;
2366
- }
2367
- ```
2368
-
2369
- ### Crypto, compression, and model decoding
2370
-
2371
- Modules: `dredless/crypto/chacha`, `dredless/compression/lz4`,
2372
- `dredless/model`, and root.
2373
-
2374
- ```ts
2375
- function decryptPayload(
2376
- wireBytes: Uint8Array | ArrayBuffer | number[],
2377
- worldId: number,
2378
- seed: number
2379
- ): Uint8Array;
2380
-
2381
- function decompressLz4Frame(bytes: Uint8Array | ArrayBuffer | number[]): Uint8Array;
50
+ ## IDs and scopes
2382
51
 
2383
- function decodeModelData(bytes: Uint8Array | ArrayBuffer | number[]): unknown;
2384
- ```
2385
-
2386
- ### Ship spec helpers
2387
-
2388
- Module: `dredless/ships`.
2389
-
2390
- ```ts
2391
- function createShipSpec(name?: string, color?: string): ShipSpec;
2392
- function createInviteShipSpec(code: string): ShipSpec;
2393
- ```
2394
-
2395
- `createShipSpec()` returns a `{ type: "new", ... }` ship spec.
2396
- `createInviteShipSpec()` returns a `{ type: "invite", code }` ship spec.
2397
-
2398
- ## Public Constants From Subpath Modules
2399
-
2400
- These constants are exported by helper subpaths for consumers that need protocol
2401
- symbols. They are not required for normal object-domain use.
2402
-
2403
- ### `dredless/protocol/blueprint`
2404
-
2405
- ```ts
2406
- const BLUEPRINT_PLACEMENT_TYPE: 9;
2407
- ```
2408
-
2409
- ### `dredless/protocol/comms`
2410
-
2411
- ```ts
2412
- const COMMS_MESSAGE_TYPE: 3;
2413
- ```
2414
-
2415
- ### `dredless/protocol/inventory`
2416
-
2417
- ```ts
2418
- const EQUIPMENT_SLOT_INDEXES: Readonly<{
2419
- head: 16;
2420
- face: 17;
2421
- body: 18;
2422
- back: 19;
2423
- hands: 20;
2424
- feet: 21;
2425
- }>;
2426
- ```
2427
-
2428
- ### `dredless/protocol/ship-management`
2429
-
2430
- ```ts
2431
- const BAN_ACTION: "ban";
2432
- const DEMOTE_SELF_ACTION: "demote_self";
2433
- const KICK_ACTION: "kick";
2434
- const PLAYER_LIST_ACTION: "player_list";
2435
- const INVITE_RESET_ACTION: "invite_reset";
2436
- const SET_PRIVACY_ACTION: "set_privacy";
2437
- const SET_RANK_ACTION: "set_rank";
2438
- const SHIP_MANAGEMENT_TYPE: 4;
2439
- const STARTER_RECOVERY_ACTION: "starter_recovery";
2440
- ```
2441
-
2442
- ### `dredless/protocol/sign`
2443
-
2444
- ```ts
2445
- const SIGN_TEXT_COMMAND: "sign_text";
2446
- const SIGN_DISPLAY_MODES: Map<0 | 1 | 2, "always" | "when-near" | "on-hover">;
2447
- ```
2448
-
2449
- ### `dredless/protocol/ui-config`
2450
-
2451
- ```ts
2452
- const CLIPBOARD_ACTION: 1;
2453
- const CLIPBOARD_ANGLE_COMMAND: "angle";
2454
- const CLIPBOARD_FIXED_ANGLE_COMMAND: "angle_fixed";
2455
- const CLIPBOARD_TARGET_VALUES: Map<string, number>;
2456
- const FIXED_ANGLE_VALUES: Map<string, 0 | 1 | 2 | 3>;
2457
- const GENERATOR_MAZE_PUZZLE_COMMAND: "maze_puzzle";
2458
- const LOADER_CONFIG_COMMAND: "config_loader";
2459
- const LOADER_FALSE: 0x8e;
2460
- const LOADER_FILTER_CONFIG_COMMAND: "filter_config";
2461
- const LOADER_FILTER_ITEMS_COMMAND: "filter_items";
2462
- const LOADER_TRUE: 0x8d;
2463
- const NAV_UNIT_COMMAND: "config_nav_unit";
2464
- const NAV_UNIT_FALSE: 0x8d;
2465
- const NAV_UNIT_TRUE: 0x8e;
2466
- const PUSHER_CONFIG_COMMAND: "config_pusher";
2467
- const PUSHER_FILTER_ITEMS_COMMAND: "filter_items";
2468
- ```
2469
-
2470
- ## Usage Patterns
2471
-
2472
- ### Read loaders from a live client
2473
-
2474
- Use [NODE_API.md](./NODE_API.md) or [BROWSER_API.md](./BROWSER_API.md) to start a client for the current runtime.
2475
-
2476
- ```js
2477
- await client.whenReady();
2478
-
2479
- for (const loader of client.currentShip().machines.loaders()) {
2480
- console.log(loader.id, loader.pick, loader.place, loader.cycle);
2481
- }
2482
- ```
2483
-
2484
- ### Read all nearby ships, including detailed loaded worlds when available
2485
-
2486
- ```js
2487
- const ships = client.overworld().ships({
2488
- includeWorld: true,
2489
- includeModel: true,
2490
- sort: "distance"
2491
- });
2492
-
2493
- for (const ship of ships) {
2494
- const snapshot = ship.snapshot();
2495
- console.log(snapshot.name, snapshot.hexCode, snapshot.hasWorldData);
2496
- }
2497
- ```
2498
-
2499
- ### Use generic features before narrowing to a machine type
2500
-
2501
- ```js
2502
- const entity = client.currentShip().entities.get(14);
2503
-
2504
- if (entity.has("loader")) {
2505
- const loader = entity.asLoader();
2506
- loader.setCycle(10);
2507
- }
2508
-
2509
- if (entity.has("outline")) {
2510
- console.log(entity.feature("outline"));
2511
- }
2512
- ```
2513
-
2514
- ### Configure a pusher
2515
-
2516
- ```js
2517
- const pusher = client.currentShip().machines.pusher(27);
2518
-
2519
- pusher.configure({
2520
- mode: "push",
2521
- filteredMode: "pull",
2522
- angle: 90,
2523
- speed: 20,
2524
- length: 30,
2525
- filterInventory: true
2526
- });
2527
- ```
2528
-
2529
- ### Configure a navigation unit
2530
-
2531
- ```js
2532
- const nav = client.currentShip().machines.navigationUnit();
2533
-
2534
- nav.setDestination(30, {
2535
- autoWarpOnShieldFailure: true,
2536
- autoWarpOnNoCaptains: false
2537
- });
2538
- ```
2539
-
2540
- ## Cost Guidelines
2541
-
2542
- Use handles for normal live code:
52
+ | Value | Meaning |
53
+ |--------------------------------|------------------------------------------------------------------------------------|
54
+ | `server.index` | Server selector; numeric `ServerRef` means this index, not an array position |
55
+ | World ID | Identifies a decoded world in `client.debug.worldStore()` |
56
+ | Entity `id` / summary `entity` | Entity ID within a world; the same number can mean something else in another world |
57
+ | Player `refId` | Management player-list reference for rank, kick, ban, and unban operations |
58
+ | `sid` | WebSocket protocol session ID; not the player's entity ID |
59
+ | Ship `hexCode` | Human-visible ship code, without braces |
60
+ | Account perk ship `shipId` | Decimal string from the account removal form; use it with `removeShipPerks()` |
2543
61
 
2544
- ```js
2545
- client.currentShip().entities.get(id);
2546
- client.currentShip().machines.loader(id);
2547
- ```
62
+ Do not convert account perk ship `shipId` to/from `hexCode`; the form and display identifiers are
63
+ distinct. [Account methods](ACCOUNT.md#ships-with-patron-perks) returns both.
2548
64
 
2549
- Use raw grouped state for display, sorting, and cheap bulk reads:
65
+ `ReadWorldScope` accepts `"ship"`, `"current"`, `"overworld"`, or a numeric world ID. Prefer world-scoped handles for
66
+ writes. A handle does not guarantee the entity exists, belongs to the current world, or is in range.
2550
67
 
2551
- ```js
2552
- client.currentShip().entities.raw();
2553
- client.currentShip().machines.state();
2554
- ```
68
+ ## Types and state shapes
2555
69
 
2556
- Use snapshots when you need immutable point-in-time data:
70
+ The maintained declaration files are the full field/overload reference:
2557
71
 
2558
- ```js
2559
- entity.snapshot();
2560
- client.currentShip().entities.snapshots();
2561
- client.state({ includeModel: true });
2562
- ```
72
+ | Need | Declaration |
73
+ |--------------------------------------------------------------------|--------------------------------------------------------------------------|
74
+ | Shared client, handles, config, summary, snapshot, and event types | [src/index.d.ts](../src/index.d.ts) |
75
+ | Browser factories and ambient sessions | [src/browser.d.ts](../src/browser.d.ts) |
76
+ | Protocol-only helpers and constants | [src/protocol/index.d.ts](../src/protocol/index.d.ts) and its re-exports |
2563
77
 
2564
- Use debug and world/model classes when reverse engineering, replaying captures,
2565
- or validating protocol assumptions:
78
+ Useful type families: `Server`/`ServerStatus`/`Ship`/`ShipList`; `AccountDetails`/`ClanTagDetails`/`AccountPerkShip`;
79
+ `ClientSnapshot`/`WorldSnapshot`/`ModelSnapshot`; `EntitySnapshot`/`EntitySummary`/`EntityContentsSummary`;
80
+ machine-specific `*Handle`, `*Config`, and `*Summary`; `InventoryState`; `ShipConfig`/`ShipPlayerList`/`CrewLog`; and
81
+ `Command`/`TipList`/`DisconnectInfo`.
2566
82
 
2567
- ```js
2568
- client.debug.modelRecord(worldId, tableId, entityId);
2569
- client.debug.decodeErrors();
2570
- client.debug.worldStore();
2571
- ```
83
+ Some implementation methods and overloads predate the declarations. A reference page calls out known differences where
84
+ they affect usage; do not infer runtime support from a signature alone.