dredless 0.2.0 → 0.3.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 (80) hide show
  1. package/README.md +65 -48
  2. package/dist/browser/dredless.global.js +12047 -0
  3. package/dist/browser/dredless.global.js.map +7 -0
  4. package/docs/API_REFERENCE.md +2481 -2481
  5. package/docs/BROWSER_API.md +98 -98
  6. package/docs/NODE_API.md +359 -359
  7. package/package.json +40 -35
  8. package/src/browser-global.js +3 -0
  9. package/src/browser.d.ts +212 -212
  10. package/src/browser.js +133 -133
  11. package/src/client/core.js +1202 -1202
  12. package/src/client/domains/index.js +1818 -1818
  13. package/src/client/index.d.ts +2 -2
  14. package/src/client/index.js +1 -1
  15. package/src/compression/lz4.d.ts +1 -1
  16. package/src/compression/lz4.js +112 -112
  17. package/src/constants.js +74 -74
  18. package/src/crypto/chacha-native.d.ts +9 -9
  19. package/src/crypto/chacha-native.js +48 -48
  20. package/src/crypto/chacha.d.ts +25 -25
  21. package/src/crypto/chacha.js +274 -274
  22. package/src/events.js +39 -39
  23. package/src/index.d.ts +2277 -2277
  24. package/src/index.js +125 -125
  25. package/src/network/browser-session.js +291 -291
  26. package/src/network/connection.d.ts +1 -1
  27. package/src/network/connection.js +31 -31
  28. package/src/network/cookies.js +85 -85
  29. package/src/network/http.js +34 -34
  30. package/src/network/index.d.ts +4 -4
  31. package/src/network/index.js +4 -4
  32. package/src/network/servers.d.ts +7 -7
  33. package/src/network/servers.js +133 -133
  34. package/src/network/session.d.ts +7 -7
  35. package/src/network/session.js +320 -320
  36. package/src/network/ships.d.ts +12 -12
  37. package/src/network/ships.js +73 -73
  38. package/src/node.d.ts +2 -2
  39. package/src/node.js +8 -8
  40. package/src/protocol/codec/binary.d.ts +3 -3
  41. package/src/protocol/codec/binary.js +52 -52
  42. package/src/protocol/codec/msgpack.d.ts +3 -3
  43. package/src/protocol/codec/msgpack.js +555 -555
  44. package/src/protocol/inbound/frame.d.ts +1 -1
  45. package/src/protocol/inbound/frame.js +8 -8
  46. package/src/protocol/inbound/world-payload.d.ts +3 -3
  47. package/src/protocol/inbound/world-payload.js +21 -21
  48. package/src/protocol/index.d.ts +11 -11
  49. package/src/protocol/index.js +19 -19
  50. package/src/protocol/outbound/blueprint.d.ts +22 -22
  51. package/src/protocol/outbound/blueprint.js +36 -36
  52. package/src/protocol/outbound/commands.d.ts +3 -3
  53. package/src/protocol/outbound/commands.js +149 -149
  54. package/src/protocol/outbound/comms.d.ts +28 -28
  55. package/src/protocol/outbound/comms.js +40 -40
  56. package/src/protocol/outbound/inventory.d.ts +64 -64
  57. package/src/protocol/outbound/inventory.js +147 -147
  58. package/src/protocol/outbound/ship-management.d.ts +84 -84
  59. package/src/protocol/outbound/ship-management.js +221 -221
  60. package/src/protocol/outbound/sign.d.ts +18 -18
  61. package/src/protocol/outbound/sign.js +45 -45
  62. package/src/protocol/outbound/ui-config.d.ts +157 -157
  63. package/src/protocol/outbound/ui-config.js +578 -578
  64. package/src/runtime.js +36 -36
  65. package/src/state/generator-maze.d.ts +32 -32
  66. package/src/state/generator-maze.js +370 -370
  67. package/src/state/index.d.ts +3 -3
  68. package/src/state/index.js +3 -3
  69. package/src/state/items.js +20 -20
  70. package/src/state/model/decoder.js +1554 -1554
  71. package/src/state/model/index.d.ts +33 -33
  72. package/src/state/model/index.js +2 -2
  73. package/src/state/model/loader-config.js +1020 -1020
  74. package/src/state/model/reader.js +69 -69
  75. package/src/state/model/state.js +1257 -1257
  76. package/src/state/overworld.js +72 -72
  77. package/src/state/tilesets.js +53 -53
  78. package/src/state/world/index.d.ts +29 -29
  79. package/src/state/world/index.js +180 -180
  80. package/src/state/world/state.js +297 -297
@@ -1,578 +1,578 @@
1
- import {encoder} from "../../constants.js";
2
-
3
- const NAV_UNIT_COMMAND = "config_nav_unit";
4
- const GENERATOR_MAZE_PUZZLE_COMMAND = "maze_puzzle";
5
- const CLIPBOARD_ANGLE_COMMAND = "angle";
6
- const CLIPBOARD_FIXED_ANGLE_COMMAND = "angle_fixed";
7
- const LOADER_CONFIG_COMMAND = "config_loader";
8
- const LOADER_FILTER_CONFIG_COMMAND = "filter_config";
9
- const LOADER_FILTER_ITEMS_COMMAND = "filter_items";
10
- const PUSHER_CONFIG_COMMAND = "config_pusher";
11
- const PUSHER_FILTER_ITEMS_COMMAND = "filter_items";
12
- const NAV_UNIT_STRING_TAG = 0x8a;
13
- const NAV_UNIT_HEADER_TAG = 0x90;
14
- const NAV_UNIT_TRUE = 0x8e;
15
- const NAV_UNIT_FALSE = 0x8d;
16
- const NAV_UNIT_TRAILER = [0x91, 0x91];
17
- const PUSHER_FILTER_INVENTORY_ON = 0x8d;
18
- const PUSHER_FILTER_INVENTORY_OFF = 0x8e;
19
- const LOADER_TRUE = 0x8d;
20
- const LOADER_FALSE = 0x8e;
21
- const UI_COMMAND_END = 0x91;
22
- const CLIPBOARD_ACTION = 1;
23
-
24
- export const PusherMode = Object.freeze({
25
- Push: "push",
26
- Pull: "pull",
27
- DoNothing: "do-nothing"
28
- });
29
-
30
- export const LoaderPosition = Object.freeze({
31
- TopLeft: "top-left",
32
- TopMiddle: "top-middle",
33
- TopRight: "top-right",
34
- MiddleLeft: "middle-left",
35
- MiddleRight: "middle-right",
36
- BottomLeft: "bottom-left",
37
- BottomMiddle: "bottom-middle",
38
- BottomRight: "bottom-right"
39
- });
40
-
41
- export const LoaderFilterMode = Object.freeze({
42
- AllowAll: "allow-all",
43
- BlockFilter: "block-filter",
44
- AllowFilter: "allow-filter",
45
- BlockAll: "block-all"
46
- });
47
-
48
- export const FixedAngleDirection = Object.freeze({
49
- Right: "right",
50
- Up: "up",
51
- Left: "left",
52
- Down: "down"
53
- });
54
-
55
- export const LoaderPriority = Object.freeze({
56
- Low: "low",
57
- Normal: "normal",
58
- High: "high"
59
- });
60
-
61
- function requireByteInteger(value, name) {
62
- const number = Number(value);
63
- if (!Number.isInteger(number) || number < 0 || number > 255) {
64
- throw new RangeError(`${name} must be an integer between 0 and 255`);
65
- }
66
- return number;
67
- }
68
-
69
- function requireUint16(value, name) {
70
- const number = Number(value);
71
- if (!Number.isInteger(number) || number < 0 || number > 0xffff) {
72
- throw new RangeError(`${name} must be an integer between 0 and 65535`);
73
- }
74
- return number;
75
- }
76
-
77
- function navConfigBool(value) {
78
- return value ? NAV_UNIT_TRUE : NAV_UNIT_FALSE;
79
- }
80
-
81
- function navWarpByte(value) {
82
- if (value === true || value === "start") return NAV_UNIT_FALSE;
83
- if (value === false || value == null || value === "idle" || value === "cancel") return NAV_UNIT_TRUE;
84
- throw new TypeError(`warp must be true, false, "start", "idle", or "cancel"`);
85
- }
86
-
87
- function requirePusherMode(value, name) {
88
- const number = PUSHER_MODE_VALUES.get(value);
89
- if (number == null || !Number.isInteger(number) || number < 0 || number > 2) {
90
- throw new RangeError(`${name} must be PusherMode.Push, PusherMode.Pull, or PusherMode.DoNothing`);
91
- }
92
- return number;
93
- }
94
-
95
- function requireLoaderPosition(value, name) {
96
- const number = LOADER_POSITION_VALUES.get(value);
97
- if (number == null || !Number.isInteger(number) || number < 0 || number > 7) {
98
- throw new RangeError(`${name} must be a LoaderPosition value`);
99
- }
100
- return number;
101
- }
102
-
103
- function requireLoaderPriority(value, name) {
104
- const number = LOADER_PRIORITY_VALUES.get(value);
105
- if (number == null || !Number.isInteger(number) || number < -1 || number > 1) {
106
- throw new RangeError(`${name} must be a LoaderPriority value`);
107
- }
108
- return number + 1;
109
- }
110
-
111
- function requireLoaderFilterMode(value, name) {
112
- const number = LOADER_FILTER_MODE_VALUES.get(value);
113
- if (number == null || !Number.isInteger(number) || number < 0 || number > 3) {
114
- throw new RangeError(`${name} must be a LoaderFilterMode value`);
115
- }
116
- return number;
117
- }
118
-
119
- const CLIPBOARD_TARGET_VALUES = new Map([
120
- ["loader", 1],
121
- ["loader-config", 1],
122
- ["loaderConfig", 1],
123
- ["hatch", 0],
124
- ["cargo-hatch", 0],
125
- ["cargoHatch", 0],
126
- ["ejector", 7],
127
- ["cargo-ejector", 7],
128
- ["cargoEjector", 7],
129
- ["expando", 3],
130
- ["expando-box", 3],
131
- ["expandoBox", 3],
132
- ["generator", 4],
133
- ["shield-generator", 4],
134
- ["shieldGenerator", 4],
135
- ["navigation", 6],
136
- ["navigation-unit", 6],
137
- ["navigationUnit", 6],
138
- ["nav", 6],
139
- ["nav-unit", 6],
140
- ["navUnit", 6]
141
- ]);
142
-
143
- const FIXED_ANGLE_VALUES = new Map([
144
- [FixedAngleDirection.Right, 0],
145
- [FixedAngleDirection.Up, 1],
146
- [FixedAngleDirection.Left, 2],
147
- [FixedAngleDirection.Down, 3]
148
- ]);
149
-
150
- function requireClipboardTarget(value, name = "target") {
151
- const number = typeof value === "string" ? CLIPBOARD_TARGET_VALUES.get(value) : Number(value);
152
- if (number == null || !Number.isInteger(number) || number < 0 || number > 255) {
153
- throw new RangeError(`${name} must be a clipboard target byte or known target name`);
154
- }
155
- return number;
156
- }
157
-
158
- function requireFixedAngle(value, name = "direction") {
159
- const number = FIXED_ANGLE_VALUES.get(value);
160
- if (number == null || !Number.isInteger(number) || number < 0 || number > 3) {
161
- throw new RangeError(`${name} must be a FixedAngleDirection value`);
162
- }
163
- return number;
164
- }
165
-
166
- function requireAngleDegrees(value, name = "angle") {
167
- const number = Number(value);
168
- if (!Number.isInteger(number) || number < 0 || number > 359) {
169
- throw new RangeError(`${name} must be an integer degree value between 0 and 359`);
170
- }
171
- return number;
172
- }
173
-
174
- function requireFiniteNumber(value, name) {
175
- const number = Number(value);
176
- if (!Number.isFinite(number)) throw new RangeError(`${name} must be a finite number`);
177
- return number;
178
- }
179
-
180
- function requireNonNegativeInteger(value, name) {
181
- const number = Number(value);
182
- if (!Number.isInteger(number) || number < 0) throw new RangeError(`${name} must be a non-negative integer`);
183
- return number;
184
- }
185
-
186
- function encodeCompactNumber(value, name) {
187
- const number = requireFiniteNumber(value, name);
188
- if (!Number.isInteger(number)) {
189
- const out = new Uint8Array(5);
190
- out[0] = 0x88;
191
- new DataView(out.buffer).setFloat32(1, number, true);
192
- return [...out];
193
- }
194
- if (number < 0) throw new RangeError(`${name} must be non-negative`);
195
- if (number <= 0x1f) return [number];
196
- if (number <= 0x7f) return [0x84, number];
197
- if (number <= 0xffff) return [0x85, number & 0xff, (number >> 8) & 0xff];
198
- throw new RangeError(`${name} must be 65535 or lower`);
199
- }
200
-
201
- function encodeCompactItemId(value, name) {
202
- const number = requireNonNegativeInteger(value, name);
203
- if (number === 0) return [0];
204
- return encodeCompactNumber(number, name);
205
- }
206
-
207
- function encodeLoaderCycle(cycle) {
208
- const seconds = requireFiniteNumber(cycle, "cycle");
209
- if (seconds < 1) throw new RangeError(`cycle must be at least 1 second`);
210
- const ticks = Math.round(seconds * 20);
211
- if (ticks <= 0x3f) return [ticks];
212
- if (ticks <= 0xff) return [0x80, ticks];
213
- if (ticks <= 0xffff) return [0x85, ticks & 0xff, (ticks >> 8) & 0xff];
214
- throw new RangeError(`cycle is too large`);
215
- }
216
-
217
- function encodeUiCommandTarget(entity, action = 0) {
218
- const entityId = requireUint16(entity, "entity");
219
- const actionId = requireByteInteger(action, "action");
220
- if (actionId && entityId > 0xff) {
221
- throw new RangeError(`copy/paste UI config currently requires an entity id below 256`);
222
- }
223
- return [
224
- NAV_UNIT_HEADER_TAG,
225
- actionId ? actionId : (entityId >> 8) & 0xff,
226
- entityId & 0xff
227
- ];
228
- }
229
-
230
- function encodeUiCommandSection(commandName) {
231
- const command = encoder.encode(commandName);
232
- if (command.byteLength > 255) throw new RangeError(`command name is too long`);
233
- return [
234
- NAV_UNIT_STRING_TAG,
235
- command.byteLength,
236
- ...command,
237
- 0x00
238
- ];
239
- }
240
-
241
- function encodeUiCommandHeader(entity, commandName) {
242
- return [
243
- ...encodeUiCommandTarget(entity),
244
- ...encodeUiCommandSection(commandName)
245
- ];
246
- }
247
-
248
- function encodeLoaderConfigPayload({
249
- pick = LoaderPosition.TopLeft,
250
- place = LoaderPosition.TopRight,
251
- priority = LoaderPriority.Normal,
252
- stack = 16,
253
- cycle = 1,
254
- requireOutput = false,
255
- waitForStack = false
256
- } = {}) {
257
- return [
258
- NAV_UNIT_HEADER_TAG,
259
- requireLoaderPosition(pick, "pick"),
260
- requireLoaderPosition(place, "place"),
261
- requireLoaderPriority(priority, "priority"),
262
- requireNonNegativeInteger(stack, "stack"),
263
- ...encodeLoaderCycle(cycle),
264
- requireOutput ? LOADER_TRUE : LOADER_FALSE,
265
- waitForStack ? LOADER_TRUE : LOADER_FALSE
266
- ];
267
- }
268
-
269
- function encodeLoaderFilterConfigPayload(filterMode = LoaderFilterMode.AllowAll) {
270
- return [
271
- NAV_UNIT_HEADER_TAG,
272
- requireLoaderFilterMode(filterMode, "filterMode")
273
- ];
274
- }
275
-
276
- function encodeLoaderFilterItemsPayload(filterSlots = []) {
277
- const slots = [0, 1, 2].map((index) => requireNonNegativeInteger(filterSlots[index] ?? 0, `filterSlots[${index}]`));
278
- return [
279
- NAV_UNIT_HEADER_TAG,
280
- ...slots.flatMap((slot, index) => encodeCompactItemId(slot, `filterSlots[${index}]`))
281
- ];
282
- }
283
-
284
- export function buildNavigationUnitConfigData(entity, {
285
- destination,
286
- page = 0,
287
- warp = "idle",
288
- autoWarpOnShieldFailure = false,
289
- autoWarpOnNoCaptains = false
290
- } = {}) {
291
- return Uint8Array.from([
292
- ...encodeUiCommandHeader(entity, NAV_UNIT_COMMAND),
293
- ...encodeNavigationUnitConfigPayload({destination, page, warp, autoWarpOnShieldFailure, autoWarpOnNoCaptains}),
294
- ...NAV_UNIT_TRAILER
295
- ]);
296
- }
297
-
298
- function encodeNavigationUnitConfigPayload({
299
- destination,
300
- page = 0,
301
- warp = "idle",
302
- autoWarpOnShieldFailure = false,
303
- autoWarpOnNoCaptains = false
304
- } = {}) {
305
- return [
306
- NAV_UNIT_HEADER_TAG,
307
- requireByteInteger(destination, "destination"),
308
- requireByteInteger(page, "page"),
309
- navWarpByte(warp),
310
- navConfigBool(autoWarpOnShieldFailure),
311
- navConfigBool(autoWarpOnNoCaptains)
312
- ];
313
- }
314
-
315
- export function buildGeneratorMazePuzzleData(entity, solution) {
316
- const value = String(solution);
317
- if (!/^\d+$/.test(value)) throw new TypeError(`solution must contain only digits`);
318
- const encoded = encoder.encode(value);
319
- if (encoded.byteLength > 255) throw new RangeError(`solution is too long`);
320
-
321
- return Uint8Array.from([
322
- ...encodeUiCommandHeader(entity, GENERATOR_MAZE_PUZZLE_COMMAND),
323
- NAV_UNIT_HEADER_TAG,
324
- NAV_UNIT_STRING_TAG,
325
- encoded.byteLength,
326
- ...encoded,
327
- NAV_UNIT_FALSE,
328
- ...NAV_UNIT_TRAILER
329
- ]);
330
- }
331
-
332
- export function buildPusherConfigData(entity, {
333
- mode = 2,
334
- filteredMode = 0,
335
- angle = 0,
336
- speed = 20,
337
- filterInventory = false,
338
- length = 1000
339
- } = {}) {
340
- return Uint8Array.from([
341
- ...encodeUiCommandHeader(entity, PUSHER_CONFIG_COMMAND),
342
- NAV_UNIT_HEADER_TAG,
343
- requirePusherMode(mode, "mode"),
344
- requirePusherMode(filteredMode, "filteredMode"),
345
- ...encodeCompactNumber(angle, "angle"),
346
- ...encodeCompactNumber(speed, "speed"),
347
- filterInventory ? PUSHER_FILTER_INVENTORY_ON : PUSHER_FILTER_INVENTORY_OFF,
348
- ...encodeCompactNumber(length, "length"),
349
- ...NAV_UNIT_TRAILER
350
- ]);
351
- }
352
-
353
- export function buildPusherFilterItemsData(entity, filterSlots = []) {
354
- const slots = [0, 1, 2].map((index) => requireNonNegativeInteger(filterSlots[index] ?? 0, `filterSlots[${index}]`));
355
- return Uint8Array.from([
356
- ...encodeUiCommandHeader(entity, PUSHER_FILTER_ITEMS_COMMAND),
357
- NAV_UNIT_HEADER_TAG,
358
- ...slots.flatMap((slot, index) => encodeCompactItemId(slot, `filterSlots[${index}]`)),
359
- ...NAV_UNIT_TRAILER
360
- ]);
361
- }
362
-
363
- export function buildLoaderConfigData(entity, {
364
- pick = LoaderPosition.TopLeft,
365
- place = LoaderPosition.TopRight,
366
- priority = LoaderPriority.Normal,
367
- stack = 16,
368
- cycle = 1,
369
- requireOutput = false,
370
- waitForStack = false
371
- } = {}) {
372
- return Uint8Array.from([
373
- ...encodeUiCommandHeader(entity, LOADER_CONFIG_COMMAND),
374
- ...encodeLoaderConfigPayload({pick, place, priority, stack, cycle, requireOutput, waitForStack}),
375
- ...NAV_UNIT_TRAILER
376
- ]);
377
- }
378
-
379
- export function buildLoaderFilterConfigData(entity, filterMode = LoaderFilterMode.AllowAll) {
380
- return Uint8Array.from([
381
- ...encodeUiCommandHeader(entity, LOADER_FILTER_CONFIG_COMMAND),
382
- ...encodeLoaderFilterConfigPayload(filterMode),
383
- ...NAV_UNIT_TRAILER
384
- ]);
385
- }
386
-
387
- export function buildLoaderFilterItemsData(entity, filterSlots = []) {
388
- return Uint8Array.from([
389
- ...encodeUiCommandHeader(entity, LOADER_FILTER_ITEMS_COMMAND),
390
- ...encodeLoaderFilterItemsPayload(filterSlots),
391
- ...NAV_UNIT_TRAILER
392
- ]);
393
- }
394
-
395
- export function buildCargoHatchFilterConfigData(entity, filterMode = LoaderFilterMode.AllowAll) {
396
- return buildLoaderFilterConfigData(entity, filterMode);
397
- }
398
-
399
- export function buildCargoHatchFilterItemsData(entity, filterSlots = []) {
400
- return buildLoaderFilterItemsData(entity, filterSlots);
401
- }
402
-
403
- function buildLoaderFullConfigPayload(entity, action, {
404
- filterMode = LoaderFilterMode.AllowAll,
405
- filterSlots = [],
406
- ...config
407
- } = {}) {
408
- return Uint8Array.from([
409
- ...encodeUiCommandTarget(entity, action),
410
- ...encodeUiCommandSection(LOADER_CONFIG_COMMAND),
411
- ...encodeLoaderConfigPayload(config),
412
- UI_COMMAND_END,
413
- ...encodeUiCommandSection(LOADER_FILTER_CONFIG_COMMAND),
414
- ...encodeLoaderFilterConfigPayload(filterMode),
415
- UI_COMMAND_END,
416
- ...encodeUiCommandSection(LOADER_FILTER_ITEMS_COMMAND),
417
- ...encodeLoaderFilterItemsPayload(filterSlots),
418
- UI_COMMAND_END,
419
- UI_COMMAND_END
420
- ]);
421
- }
422
-
423
- function buildFilterOnlyConfigPayload(entity, action, {
424
- filterMode = 0,
425
- filterSlots = []
426
- } = {}) {
427
- return Uint8Array.from([
428
- ...encodeUiCommandTarget(entity, action),
429
- ...encodeUiCommandSection(LOADER_FILTER_CONFIG_COMMAND),
430
- ...encodeLoaderFilterConfigPayload(filterMode),
431
- UI_COMMAND_END,
432
- ...encodeUiCommandSection(LOADER_FILTER_ITEMS_COMMAND),
433
- ...encodeLoaderFilterItemsPayload(filterSlots),
434
- UI_COMMAND_END,
435
- UI_COMMAND_END
436
- ]);
437
- }
438
-
439
- export function buildLoaderFullConfigData(entity, config = {}) {
440
- return buildLoaderFullConfigPayload(entity, 2, config);
441
- }
442
-
443
- export function buildLoaderCopyConfigData(config = {}) {
444
- return buildLoaderFullConfigPayload(1, 1, config);
445
- }
446
-
447
- export function buildCargoHatchFullConfigData(entity, config = {}) {
448
- return buildFilterOnlyConfigPayload(entity, 2, config);
449
- }
450
-
451
- export function buildCargoHatchCopyConfigData(config = {}) {
452
- return buildFilterOnlyConfigPayload(0, 1, config);
453
- }
454
-
455
- export function buildLoaderClipboardConfigData(config = {}) {
456
- return Uint8Array.from([
457
- ...encodeUiCommandTarget(1, CLIPBOARD_ACTION),
458
- ...encodeUiCommandSection(LOADER_CONFIG_COMMAND),
459
- ...encodeLoaderConfigPayload(config),
460
- ...NAV_UNIT_TRAILER
461
- ]);
462
- }
463
-
464
- export function buildNavigationUnitClipboardConfigData(config = {}) {
465
- return Uint8Array.from([
466
- ...encodeUiCommandTarget(6, CLIPBOARD_ACTION),
467
- ...encodeUiCommandSection(NAV_UNIT_COMMAND),
468
- ...encodeNavigationUnitConfigPayload(config),
469
- ...NAV_UNIT_TRAILER
470
- ]);
471
- }
472
-
473
- export function buildNavigationUnitPasteConfigData(entity, config = {}) {
474
- return Uint8Array.from([
475
- ...encodeUiCommandTarget(entity, 2),
476
- ...encodeUiCommandSection(NAV_UNIT_COMMAND),
477
- ...encodeNavigationUnitConfigPayload(config),
478
- ...NAV_UNIT_TRAILER
479
- ]);
480
- }
481
-
482
- export function buildClipboardConfigData(target, commandName, values = []) {
483
- if (typeof commandName !== "string" || !commandName) throw new TypeError(`commandName must be a non-empty string`);
484
- return Uint8Array.from([
485
- ...encodeUiCommandTarget(requireClipboardTarget(target), CLIPBOARD_ACTION),
486
- ...encodeUiCommandSection(commandName),
487
- NAV_UNIT_HEADER_TAG,
488
- ...values,
489
- ...NAV_UNIT_TRAILER
490
- ]);
491
- }
492
-
493
- export function buildClipboardFixedAngleData(target, direction) {
494
- return buildClipboardConfigData(target, CLIPBOARD_FIXED_ANGLE_COMMAND, [requireFixedAngle(direction)]);
495
- }
496
-
497
- function buildFixedAngleConfigData(entity, action, direction) {
498
- return Uint8Array.from([
499
- ...encodeUiCommandTarget(entity, action),
500
- ...encodeUiCommandSection(CLIPBOARD_FIXED_ANGLE_COMMAND),
501
- NAV_UNIT_HEADER_TAG,
502
- requireFixedAngle(direction),
503
- ...NAV_UNIT_TRAILER
504
- ]);
505
- }
506
-
507
- export function buildGeneratorClipboardDirectionData(direction) {
508
- return buildClipboardFixedAngleData("generator", direction);
509
- }
510
-
511
- export function buildCargoEjectorDirectionData(entity, direction) {
512
- return buildFixedAngleConfigData(entity, 0, direction);
513
- }
514
-
515
- export function buildCargoEjectorPasteConfigData(entity, direction) {
516
- return buildFixedAngleConfigData(entity, 2, direction);
517
- }
518
-
519
- export function buildCargoEjectorCopyConfigData(direction) {
520
- return buildFixedAngleConfigData(7, CLIPBOARD_ACTION, direction);
521
- }
522
-
523
- export function buildCargoEjectorClipboardDirectionData(direction) {
524
- return buildClipboardFixedAngleData("ejector", direction);
525
- }
526
-
527
- export function buildExpandoClipboardAngleData(angle) {
528
- return buildClipboardConfigData("expando", CLIPBOARD_ANGLE_COMMAND, encodeCompactNumber(requireAngleDegrees(angle), "angle"));
529
- }
530
-
531
- export {
532
- CLIPBOARD_ACTION,
533
- CLIPBOARD_ANGLE_COMMAND,
534
- CLIPBOARD_FIXED_ANGLE_COMMAND,
535
- CLIPBOARD_TARGET_VALUES,
536
- FIXED_ANGLE_VALUES,
537
- GENERATOR_MAZE_PUZZLE_COMMAND,
538
- LOADER_CONFIG_COMMAND,
539
- LOADER_FALSE,
540
- LOADER_FILTER_CONFIG_COMMAND,
541
- LOADER_FILTER_ITEMS_COMMAND,
542
- LOADER_TRUE,
543
- NAV_UNIT_COMMAND,
544
- NAV_UNIT_FALSE,
545
- NAV_UNIT_TRUE,
546
- PUSHER_CONFIG_COMMAND,
547
- PUSHER_FILTER_ITEMS_COMMAND
548
- };
549
-
550
- const PUSHER_MODE_VALUES = new Map([
551
- [PusherMode.Push, 0],
552
- [PusherMode.Pull, 1],
553
- [PusherMode.DoNothing, 2]
554
- ]);
555
-
556
- const LOADER_POSITION_VALUES = new Map([
557
- [LoaderPosition.TopLeft, 0],
558
- [LoaderPosition.TopMiddle, 1],
559
- [LoaderPosition.TopRight, 2],
560
- [LoaderPosition.MiddleLeft, 3],
561
- [LoaderPosition.MiddleRight, 4],
562
- [LoaderPosition.BottomLeft, 5],
563
- [LoaderPosition.BottomMiddle, 6],
564
- [LoaderPosition.BottomRight, 7]
565
- ]);
566
-
567
- const LOADER_PRIORITY_VALUES = new Map([
568
- [LoaderPriority.Low, -1],
569
- [LoaderPriority.Normal, 0],
570
- [LoaderPriority.High, 1]
571
- ]);
572
-
573
- const LOADER_FILTER_MODE_VALUES = new Map([
574
- [LoaderFilterMode.AllowAll, 0],
575
- [LoaderFilterMode.BlockFilter, 1],
576
- [LoaderFilterMode.AllowFilter, 2],
577
- [LoaderFilterMode.BlockAll, 3]
578
- ]);
1
+ import {encoder} from "../../constants.js";
2
+
3
+ const NAV_UNIT_COMMAND = "config_nav_unit";
4
+ const GENERATOR_MAZE_PUZZLE_COMMAND = "maze_puzzle";
5
+ const CLIPBOARD_ANGLE_COMMAND = "angle";
6
+ const CLIPBOARD_FIXED_ANGLE_COMMAND = "angle_fixed";
7
+ const LOADER_CONFIG_COMMAND = "config_loader";
8
+ const LOADER_FILTER_CONFIG_COMMAND = "filter_config";
9
+ const LOADER_FILTER_ITEMS_COMMAND = "filter_items";
10
+ const PUSHER_CONFIG_COMMAND = "config_pusher";
11
+ const PUSHER_FILTER_ITEMS_COMMAND = "filter_items";
12
+ const NAV_UNIT_STRING_TAG = 0x8a;
13
+ const NAV_UNIT_HEADER_TAG = 0x90;
14
+ const NAV_UNIT_TRUE = 0x8e;
15
+ const NAV_UNIT_FALSE = 0x8d;
16
+ const NAV_UNIT_TRAILER = [0x91, 0x91];
17
+ const PUSHER_FILTER_INVENTORY_ON = 0x8d;
18
+ const PUSHER_FILTER_INVENTORY_OFF = 0x8e;
19
+ const LOADER_TRUE = 0x8d;
20
+ const LOADER_FALSE = 0x8e;
21
+ const UI_COMMAND_END = 0x91;
22
+ const CLIPBOARD_ACTION = 1;
23
+
24
+ export const PusherMode = Object.freeze({
25
+ Push: "push",
26
+ Pull: "pull",
27
+ DoNothing: "do-nothing"
28
+ });
29
+
30
+ export const LoaderPosition = Object.freeze({
31
+ TopLeft: "top-left",
32
+ TopMiddle: "top-middle",
33
+ TopRight: "top-right",
34
+ MiddleLeft: "middle-left",
35
+ MiddleRight: "middle-right",
36
+ BottomLeft: "bottom-left",
37
+ BottomMiddle: "bottom-middle",
38
+ BottomRight: "bottom-right"
39
+ });
40
+
41
+ export const LoaderFilterMode = Object.freeze({
42
+ AllowAll: "allow-all",
43
+ BlockFilter: "block-filter",
44
+ AllowFilter: "allow-filter",
45
+ BlockAll: "block-all"
46
+ });
47
+
48
+ export const FixedAngleDirection = Object.freeze({
49
+ Right: "right",
50
+ Up: "up",
51
+ Left: "left",
52
+ Down: "down"
53
+ });
54
+
55
+ export const LoaderPriority = Object.freeze({
56
+ Low: "low",
57
+ Normal: "normal",
58
+ High: "high"
59
+ });
60
+
61
+ function requireByteInteger(value, name) {
62
+ const number = Number(value);
63
+ if (!Number.isInteger(number) || number < 0 || number > 255) {
64
+ throw new RangeError(`${name} must be an integer between 0 and 255`);
65
+ }
66
+ return number;
67
+ }
68
+
69
+ function requireUint16(value, name) {
70
+ const number = Number(value);
71
+ if (!Number.isInteger(number) || number < 0 || number > 0xffff) {
72
+ throw new RangeError(`${name} must be an integer between 0 and 65535`);
73
+ }
74
+ return number;
75
+ }
76
+
77
+ function navConfigBool(value) {
78
+ return value ? NAV_UNIT_TRUE : NAV_UNIT_FALSE;
79
+ }
80
+
81
+ function navWarpByte(value) {
82
+ if (value === true || value === "start") return NAV_UNIT_FALSE;
83
+ if (value === false || value == null || value === "idle" || value === "cancel") return NAV_UNIT_TRUE;
84
+ throw new TypeError(`warp must be true, false, "start", "idle", or "cancel"`);
85
+ }
86
+
87
+ function requirePusherMode(value, name) {
88
+ const number = PUSHER_MODE_VALUES.get(value);
89
+ if (number == null || !Number.isInteger(number) || number < 0 || number > 2) {
90
+ throw new RangeError(`${name} must be PusherMode.Push, PusherMode.Pull, or PusherMode.DoNothing`);
91
+ }
92
+ return number;
93
+ }
94
+
95
+ function requireLoaderPosition(value, name) {
96
+ const number = LOADER_POSITION_VALUES.get(value);
97
+ if (number == null || !Number.isInteger(number) || number < 0 || number > 7) {
98
+ throw new RangeError(`${name} must be a LoaderPosition value`);
99
+ }
100
+ return number;
101
+ }
102
+
103
+ function requireLoaderPriority(value, name) {
104
+ const number = LOADER_PRIORITY_VALUES.get(value);
105
+ if (number == null || !Number.isInteger(number) || number < -1 || number > 1) {
106
+ throw new RangeError(`${name} must be a LoaderPriority value`);
107
+ }
108
+ return number + 1;
109
+ }
110
+
111
+ function requireLoaderFilterMode(value, name) {
112
+ const number = LOADER_FILTER_MODE_VALUES.get(value);
113
+ if (number == null || !Number.isInteger(number) || number < 0 || number > 3) {
114
+ throw new RangeError(`${name} must be a LoaderFilterMode value`);
115
+ }
116
+ return number;
117
+ }
118
+
119
+ const CLIPBOARD_TARGET_VALUES = new Map([
120
+ ["loader", 1],
121
+ ["loader-config", 1],
122
+ ["loaderConfig", 1],
123
+ ["hatch", 0],
124
+ ["cargo-hatch", 0],
125
+ ["cargoHatch", 0],
126
+ ["ejector", 7],
127
+ ["cargo-ejector", 7],
128
+ ["cargoEjector", 7],
129
+ ["expando", 3],
130
+ ["expando-box", 3],
131
+ ["expandoBox", 3],
132
+ ["generator", 4],
133
+ ["shield-generator", 4],
134
+ ["shieldGenerator", 4],
135
+ ["navigation", 6],
136
+ ["navigation-unit", 6],
137
+ ["navigationUnit", 6],
138
+ ["nav", 6],
139
+ ["nav-unit", 6],
140
+ ["navUnit", 6]
141
+ ]);
142
+
143
+ const FIXED_ANGLE_VALUES = new Map([
144
+ [FixedAngleDirection.Right, 0],
145
+ [FixedAngleDirection.Up, 1],
146
+ [FixedAngleDirection.Left, 2],
147
+ [FixedAngleDirection.Down, 3]
148
+ ]);
149
+
150
+ function requireClipboardTarget(value, name = "target") {
151
+ const number = typeof value === "string" ? CLIPBOARD_TARGET_VALUES.get(value) : Number(value);
152
+ if (number == null || !Number.isInteger(number) || number < 0 || number > 255) {
153
+ throw new RangeError(`${name} must be a clipboard target byte or known target name`);
154
+ }
155
+ return number;
156
+ }
157
+
158
+ function requireFixedAngle(value, name = "direction") {
159
+ const number = FIXED_ANGLE_VALUES.get(value);
160
+ if (number == null || !Number.isInteger(number) || number < 0 || number > 3) {
161
+ throw new RangeError(`${name} must be a FixedAngleDirection value`);
162
+ }
163
+ return number;
164
+ }
165
+
166
+ function requireAngleDegrees(value, name = "angle") {
167
+ const number = Number(value);
168
+ if (!Number.isInteger(number) || number < 0 || number > 359) {
169
+ throw new RangeError(`${name} must be an integer degree value between 0 and 359`);
170
+ }
171
+ return number;
172
+ }
173
+
174
+ function requireFiniteNumber(value, name) {
175
+ const number = Number(value);
176
+ if (!Number.isFinite(number)) throw new RangeError(`${name} must be a finite number`);
177
+ return number;
178
+ }
179
+
180
+ function requireNonNegativeInteger(value, name) {
181
+ const number = Number(value);
182
+ if (!Number.isInteger(number) || number < 0) throw new RangeError(`${name} must be a non-negative integer`);
183
+ return number;
184
+ }
185
+
186
+ function encodeCompactNumber(value, name) {
187
+ const number = requireFiniteNumber(value, name);
188
+ if (!Number.isInteger(number)) {
189
+ const out = new Uint8Array(5);
190
+ out[0] = 0x88;
191
+ new DataView(out.buffer).setFloat32(1, number, true);
192
+ return [...out];
193
+ }
194
+ if (number < 0) throw new RangeError(`${name} must be non-negative`);
195
+ if (number <= 0x1f) return [number];
196
+ if (number <= 0x7f) return [0x84, number];
197
+ if (number <= 0xffff) return [0x85, number & 0xff, (number >> 8) & 0xff];
198
+ throw new RangeError(`${name} must be 65535 or lower`);
199
+ }
200
+
201
+ function encodeCompactItemId(value, name) {
202
+ const number = requireNonNegativeInteger(value, name);
203
+ if (number === 0) return [0];
204
+ return encodeCompactNumber(number, name);
205
+ }
206
+
207
+ function encodeLoaderCycle(cycle) {
208
+ const seconds = requireFiniteNumber(cycle, "cycle");
209
+ if (seconds < 1) throw new RangeError(`cycle must be at least 1 second`);
210
+ const ticks = Math.round(seconds * 20);
211
+ if (ticks <= 0x3f) return [ticks];
212
+ if (ticks <= 0xff) return [0x80, ticks];
213
+ if (ticks <= 0xffff) return [0x85, ticks & 0xff, (ticks >> 8) & 0xff];
214
+ throw new RangeError(`cycle is too large`);
215
+ }
216
+
217
+ function encodeUiCommandTarget(entity, action = 0) {
218
+ const entityId = requireUint16(entity, "entity");
219
+ const actionId = requireByteInteger(action, "action");
220
+ if (actionId && entityId > 0xff) {
221
+ throw new RangeError(`copy/paste UI config currently requires an entity id below 256`);
222
+ }
223
+ return [
224
+ NAV_UNIT_HEADER_TAG,
225
+ actionId ? actionId : (entityId >> 8) & 0xff,
226
+ entityId & 0xff
227
+ ];
228
+ }
229
+
230
+ function encodeUiCommandSection(commandName) {
231
+ const command = encoder.encode(commandName);
232
+ if (command.byteLength > 255) throw new RangeError(`command name is too long`);
233
+ return [
234
+ NAV_UNIT_STRING_TAG,
235
+ command.byteLength,
236
+ ...command,
237
+ 0x00
238
+ ];
239
+ }
240
+
241
+ function encodeUiCommandHeader(entity, commandName) {
242
+ return [
243
+ ...encodeUiCommandTarget(entity),
244
+ ...encodeUiCommandSection(commandName)
245
+ ];
246
+ }
247
+
248
+ function encodeLoaderConfigPayload({
249
+ pick = LoaderPosition.TopLeft,
250
+ place = LoaderPosition.TopRight,
251
+ priority = LoaderPriority.Normal,
252
+ stack = 16,
253
+ cycle = 1,
254
+ requireOutput = false,
255
+ waitForStack = false
256
+ } = {}) {
257
+ return [
258
+ NAV_UNIT_HEADER_TAG,
259
+ requireLoaderPosition(pick, "pick"),
260
+ requireLoaderPosition(place, "place"),
261
+ requireLoaderPriority(priority, "priority"),
262
+ requireNonNegativeInteger(stack, "stack"),
263
+ ...encodeLoaderCycle(cycle),
264
+ requireOutput ? LOADER_TRUE : LOADER_FALSE,
265
+ waitForStack ? LOADER_TRUE : LOADER_FALSE
266
+ ];
267
+ }
268
+
269
+ function encodeLoaderFilterConfigPayload(filterMode = LoaderFilterMode.AllowAll) {
270
+ return [
271
+ NAV_UNIT_HEADER_TAG,
272
+ requireLoaderFilterMode(filterMode, "filterMode")
273
+ ];
274
+ }
275
+
276
+ function encodeLoaderFilterItemsPayload(filterSlots = []) {
277
+ const slots = [0, 1, 2].map((index) => requireNonNegativeInteger(filterSlots[index] ?? 0, `filterSlots[${index}]`));
278
+ return [
279
+ NAV_UNIT_HEADER_TAG,
280
+ ...slots.flatMap((slot, index) => encodeCompactItemId(slot, `filterSlots[${index}]`))
281
+ ];
282
+ }
283
+
284
+ export function buildNavigationUnitConfigData(entity, {
285
+ destination,
286
+ page = 0,
287
+ warp = "idle",
288
+ autoWarpOnShieldFailure = false,
289
+ autoWarpOnNoCaptains = false
290
+ } = {}) {
291
+ return Uint8Array.from([
292
+ ...encodeUiCommandHeader(entity, NAV_UNIT_COMMAND),
293
+ ...encodeNavigationUnitConfigPayload({destination, page, warp, autoWarpOnShieldFailure, autoWarpOnNoCaptains}),
294
+ ...NAV_UNIT_TRAILER
295
+ ]);
296
+ }
297
+
298
+ function encodeNavigationUnitConfigPayload({
299
+ destination,
300
+ page = 0,
301
+ warp = "idle",
302
+ autoWarpOnShieldFailure = false,
303
+ autoWarpOnNoCaptains = false
304
+ } = {}) {
305
+ return [
306
+ NAV_UNIT_HEADER_TAG,
307
+ requireByteInteger(destination, "destination"),
308
+ requireByteInteger(page, "page"),
309
+ navWarpByte(warp),
310
+ navConfigBool(autoWarpOnShieldFailure),
311
+ navConfigBool(autoWarpOnNoCaptains)
312
+ ];
313
+ }
314
+
315
+ export function buildGeneratorMazePuzzleData(entity, solution) {
316
+ const value = String(solution);
317
+ if (!/^\d+$/.test(value)) throw new TypeError(`solution must contain only digits`);
318
+ const encoded = encoder.encode(value);
319
+ if (encoded.byteLength > 255) throw new RangeError(`solution is too long`);
320
+
321
+ return Uint8Array.from([
322
+ ...encodeUiCommandHeader(entity, GENERATOR_MAZE_PUZZLE_COMMAND),
323
+ NAV_UNIT_HEADER_TAG,
324
+ NAV_UNIT_STRING_TAG,
325
+ encoded.byteLength,
326
+ ...encoded,
327
+ NAV_UNIT_FALSE,
328
+ ...NAV_UNIT_TRAILER
329
+ ]);
330
+ }
331
+
332
+ export function buildPusherConfigData(entity, {
333
+ mode = 2,
334
+ filteredMode = 0,
335
+ angle = 0,
336
+ speed = 20,
337
+ filterInventory = false,
338
+ length = 1000
339
+ } = {}) {
340
+ return Uint8Array.from([
341
+ ...encodeUiCommandHeader(entity, PUSHER_CONFIG_COMMAND),
342
+ NAV_UNIT_HEADER_TAG,
343
+ requirePusherMode(mode, "mode"),
344
+ requirePusherMode(filteredMode, "filteredMode"),
345
+ ...encodeCompactNumber(angle, "angle"),
346
+ ...encodeCompactNumber(speed, "speed"),
347
+ filterInventory ? PUSHER_FILTER_INVENTORY_ON : PUSHER_FILTER_INVENTORY_OFF,
348
+ ...encodeCompactNumber(length, "length"),
349
+ ...NAV_UNIT_TRAILER
350
+ ]);
351
+ }
352
+
353
+ export function buildPusherFilterItemsData(entity, filterSlots = []) {
354
+ const slots = [0, 1, 2].map((index) => requireNonNegativeInteger(filterSlots[index] ?? 0, `filterSlots[${index}]`));
355
+ return Uint8Array.from([
356
+ ...encodeUiCommandHeader(entity, PUSHER_FILTER_ITEMS_COMMAND),
357
+ NAV_UNIT_HEADER_TAG,
358
+ ...slots.flatMap((slot, index) => encodeCompactItemId(slot, `filterSlots[${index}]`)),
359
+ ...NAV_UNIT_TRAILER
360
+ ]);
361
+ }
362
+
363
+ export function buildLoaderConfigData(entity, {
364
+ pick = LoaderPosition.TopLeft,
365
+ place = LoaderPosition.TopRight,
366
+ priority = LoaderPriority.Normal,
367
+ stack = 16,
368
+ cycle = 1,
369
+ requireOutput = false,
370
+ waitForStack = false
371
+ } = {}) {
372
+ return Uint8Array.from([
373
+ ...encodeUiCommandHeader(entity, LOADER_CONFIG_COMMAND),
374
+ ...encodeLoaderConfigPayload({pick, place, priority, stack, cycle, requireOutput, waitForStack}),
375
+ ...NAV_UNIT_TRAILER
376
+ ]);
377
+ }
378
+
379
+ export function buildLoaderFilterConfigData(entity, filterMode = LoaderFilterMode.AllowAll) {
380
+ return Uint8Array.from([
381
+ ...encodeUiCommandHeader(entity, LOADER_FILTER_CONFIG_COMMAND),
382
+ ...encodeLoaderFilterConfigPayload(filterMode),
383
+ ...NAV_UNIT_TRAILER
384
+ ]);
385
+ }
386
+
387
+ export function buildLoaderFilterItemsData(entity, filterSlots = []) {
388
+ return Uint8Array.from([
389
+ ...encodeUiCommandHeader(entity, LOADER_FILTER_ITEMS_COMMAND),
390
+ ...encodeLoaderFilterItemsPayload(filterSlots),
391
+ ...NAV_UNIT_TRAILER
392
+ ]);
393
+ }
394
+
395
+ export function buildCargoHatchFilterConfigData(entity, filterMode = LoaderFilterMode.AllowAll) {
396
+ return buildLoaderFilterConfigData(entity, filterMode);
397
+ }
398
+
399
+ export function buildCargoHatchFilterItemsData(entity, filterSlots = []) {
400
+ return buildLoaderFilterItemsData(entity, filterSlots);
401
+ }
402
+
403
+ function buildLoaderFullConfigPayload(entity, action, {
404
+ filterMode = LoaderFilterMode.AllowAll,
405
+ filterSlots = [],
406
+ ...config
407
+ } = {}) {
408
+ return Uint8Array.from([
409
+ ...encodeUiCommandTarget(entity, action),
410
+ ...encodeUiCommandSection(LOADER_CONFIG_COMMAND),
411
+ ...encodeLoaderConfigPayload(config),
412
+ UI_COMMAND_END,
413
+ ...encodeUiCommandSection(LOADER_FILTER_CONFIG_COMMAND),
414
+ ...encodeLoaderFilterConfigPayload(filterMode),
415
+ UI_COMMAND_END,
416
+ ...encodeUiCommandSection(LOADER_FILTER_ITEMS_COMMAND),
417
+ ...encodeLoaderFilterItemsPayload(filterSlots),
418
+ UI_COMMAND_END,
419
+ UI_COMMAND_END
420
+ ]);
421
+ }
422
+
423
+ function buildFilterOnlyConfigPayload(entity, action, {
424
+ filterMode = 0,
425
+ filterSlots = []
426
+ } = {}) {
427
+ return Uint8Array.from([
428
+ ...encodeUiCommandTarget(entity, action),
429
+ ...encodeUiCommandSection(LOADER_FILTER_CONFIG_COMMAND),
430
+ ...encodeLoaderFilterConfigPayload(filterMode),
431
+ UI_COMMAND_END,
432
+ ...encodeUiCommandSection(LOADER_FILTER_ITEMS_COMMAND),
433
+ ...encodeLoaderFilterItemsPayload(filterSlots),
434
+ UI_COMMAND_END,
435
+ UI_COMMAND_END
436
+ ]);
437
+ }
438
+
439
+ export function buildLoaderFullConfigData(entity, config = {}) {
440
+ return buildLoaderFullConfigPayload(entity, 2, config);
441
+ }
442
+
443
+ export function buildLoaderCopyConfigData(config = {}) {
444
+ return buildLoaderFullConfigPayload(1, 1, config);
445
+ }
446
+
447
+ export function buildCargoHatchFullConfigData(entity, config = {}) {
448
+ return buildFilterOnlyConfigPayload(entity, 2, config);
449
+ }
450
+
451
+ export function buildCargoHatchCopyConfigData(config = {}) {
452
+ return buildFilterOnlyConfigPayload(0, 1, config);
453
+ }
454
+
455
+ export function buildLoaderClipboardConfigData(config = {}) {
456
+ return Uint8Array.from([
457
+ ...encodeUiCommandTarget(1, CLIPBOARD_ACTION),
458
+ ...encodeUiCommandSection(LOADER_CONFIG_COMMAND),
459
+ ...encodeLoaderConfigPayload(config),
460
+ ...NAV_UNIT_TRAILER
461
+ ]);
462
+ }
463
+
464
+ export function buildNavigationUnitClipboardConfigData(config = {}) {
465
+ return Uint8Array.from([
466
+ ...encodeUiCommandTarget(6, CLIPBOARD_ACTION),
467
+ ...encodeUiCommandSection(NAV_UNIT_COMMAND),
468
+ ...encodeNavigationUnitConfigPayload(config),
469
+ ...NAV_UNIT_TRAILER
470
+ ]);
471
+ }
472
+
473
+ export function buildNavigationUnitPasteConfigData(entity, config = {}) {
474
+ return Uint8Array.from([
475
+ ...encodeUiCommandTarget(entity, 2),
476
+ ...encodeUiCommandSection(NAV_UNIT_COMMAND),
477
+ ...encodeNavigationUnitConfigPayload(config),
478
+ ...NAV_UNIT_TRAILER
479
+ ]);
480
+ }
481
+
482
+ export function buildClipboardConfigData(target, commandName, values = []) {
483
+ if (typeof commandName !== "string" || !commandName) throw new TypeError(`commandName must be a non-empty string`);
484
+ return Uint8Array.from([
485
+ ...encodeUiCommandTarget(requireClipboardTarget(target), CLIPBOARD_ACTION),
486
+ ...encodeUiCommandSection(commandName),
487
+ NAV_UNIT_HEADER_TAG,
488
+ ...values,
489
+ ...NAV_UNIT_TRAILER
490
+ ]);
491
+ }
492
+
493
+ export function buildClipboardFixedAngleData(target, direction) {
494
+ return buildClipboardConfigData(target, CLIPBOARD_FIXED_ANGLE_COMMAND, [requireFixedAngle(direction)]);
495
+ }
496
+
497
+ function buildFixedAngleConfigData(entity, action, direction) {
498
+ return Uint8Array.from([
499
+ ...encodeUiCommandTarget(entity, action),
500
+ ...encodeUiCommandSection(CLIPBOARD_FIXED_ANGLE_COMMAND),
501
+ NAV_UNIT_HEADER_TAG,
502
+ requireFixedAngle(direction),
503
+ ...NAV_UNIT_TRAILER
504
+ ]);
505
+ }
506
+
507
+ export function buildGeneratorClipboardDirectionData(direction) {
508
+ return buildClipboardFixedAngleData("generator", direction);
509
+ }
510
+
511
+ export function buildCargoEjectorDirectionData(entity, direction) {
512
+ return buildFixedAngleConfigData(entity, 0, direction);
513
+ }
514
+
515
+ export function buildCargoEjectorPasteConfigData(entity, direction) {
516
+ return buildFixedAngleConfigData(entity, 2, direction);
517
+ }
518
+
519
+ export function buildCargoEjectorCopyConfigData(direction) {
520
+ return buildFixedAngleConfigData(7, CLIPBOARD_ACTION, direction);
521
+ }
522
+
523
+ export function buildCargoEjectorClipboardDirectionData(direction) {
524
+ return buildClipboardFixedAngleData("ejector", direction);
525
+ }
526
+
527
+ export function buildExpandoClipboardAngleData(angle) {
528
+ return buildClipboardConfigData("expando", CLIPBOARD_ANGLE_COMMAND, encodeCompactNumber(requireAngleDegrees(angle), "angle"));
529
+ }
530
+
531
+ export {
532
+ CLIPBOARD_ACTION,
533
+ CLIPBOARD_ANGLE_COMMAND,
534
+ CLIPBOARD_FIXED_ANGLE_COMMAND,
535
+ CLIPBOARD_TARGET_VALUES,
536
+ FIXED_ANGLE_VALUES,
537
+ GENERATOR_MAZE_PUZZLE_COMMAND,
538
+ LOADER_CONFIG_COMMAND,
539
+ LOADER_FALSE,
540
+ LOADER_FILTER_CONFIG_COMMAND,
541
+ LOADER_FILTER_ITEMS_COMMAND,
542
+ LOADER_TRUE,
543
+ NAV_UNIT_COMMAND,
544
+ NAV_UNIT_FALSE,
545
+ NAV_UNIT_TRUE,
546
+ PUSHER_CONFIG_COMMAND,
547
+ PUSHER_FILTER_ITEMS_COMMAND
548
+ };
549
+
550
+ const PUSHER_MODE_VALUES = new Map([
551
+ [PusherMode.Push, 0],
552
+ [PusherMode.Pull, 1],
553
+ [PusherMode.DoNothing, 2]
554
+ ]);
555
+
556
+ const LOADER_POSITION_VALUES = new Map([
557
+ [LoaderPosition.TopLeft, 0],
558
+ [LoaderPosition.TopMiddle, 1],
559
+ [LoaderPosition.TopRight, 2],
560
+ [LoaderPosition.MiddleLeft, 3],
561
+ [LoaderPosition.MiddleRight, 4],
562
+ [LoaderPosition.BottomLeft, 5],
563
+ [LoaderPosition.BottomMiddle, 6],
564
+ [LoaderPosition.BottomRight, 7]
565
+ ]);
566
+
567
+ const LOADER_PRIORITY_VALUES = new Map([
568
+ [LoaderPriority.Low, -1],
569
+ [LoaderPriority.Normal, 0],
570
+ [LoaderPriority.High, 1]
571
+ ]);
572
+
573
+ const LOADER_FILTER_MODE_VALUES = new Map([
574
+ [LoaderFilterMode.AllowAll, 0],
575
+ [LoaderFilterMode.BlockFilter, 1],
576
+ [LoaderFilterMode.AllowFilter, 2],
577
+ [LoaderFilterMode.BlockAll, 3]
578
+ ]);