dredless 0.2.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.
- package/LICENSE +21 -0
- package/README.md +48 -0
- package/docs/API_REFERENCE.md +2481 -0
- package/docs/BROWSER_API.md +98 -0
- package/docs/NODE_API.md +359 -0
- package/package.json +173 -0
- package/src/browser.d.ts +212 -0
- package/src/browser.js +133 -0
- package/src/client/core.js +1202 -0
- package/src/client/domains/index.js +1818 -0
- package/src/client/index.d.ts +2 -0
- package/src/client/index.js +1 -0
- package/src/compression/lz4.d.ts +1 -0
- package/src/compression/lz4.js +112 -0
- package/src/constants.js +74 -0
- package/src/crypto/chacha-native.d.ts +9 -0
- package/src/crypto/chacha-native.js +48 -0
- package/src/crypto/chacha.d.ts +25 -0
- package/src/crypto/chacha.js +274 -0
- package/src/data/item-schema.js +2235 -0
- package/src/data/official-client-data.js +156 -0
- package/src/events.js +39 -0
- package/src/index.d.ts +2277 -0
- package/src/index.js +125 -0
- package/src/network/browser-session.js +291 -0
- package/src/network/connection.d.ts +1 -0
- package/src/network/connection.js +31 -0
- package/src/network/cookies.js +85 -0
- package/src/network/http.js +34 -0
- package/src/network/index.d.ts +4 -0
- package/src/network/index.js +4 -0
- package/src/network/servers.d.ts +7 -0
- package/src/network/servers.js +133 -0
- package/src/network/session.d.ts +7 -0
- package/src/network/session.js +320 -0
- package/src/network/ships.d.ts +12 -0
- package/src/network/ships.js +73 -0
- package/src/node.d.ts +2 -0
- package/src/node.js +8 -0
- package/src/protocol/codec/binary.d.ts +3 -0
- package/src/protocol/codec/binary.js +52 -0
- package/src/protocol/codec/msgpack.d.ts +3 -0
- package/src/protocol/codec/msgpack.js +555 -0
- package/src/protocol/inbound/frame.d.ts +1 -0
- package/src/protocol/inbound/frame.js +8 -0
- package/src/protocol/inbound/world-payload.d.ts +3 -0
- package/src/protocol/inbound/world-payload.js +21 -0
- package/src/protocol/index.d.ts +11 -0
- package/src/protocol/index.js +19 -0
- package/src/protocol/outbound/blueprint.d.ts +22 -0
- package/src/protocol/outbound/blueprint.js +36 -0
- package/src/protocol/outbound/commands.d.ts +3 -0
- package/src/protocol/outbound/commands.js +149 -0
- package/src/protocol/outbound/comms.d.ts +28 -0
- package/src/protocol/outbound/comms.js +40 -0
- package/src/protocol/outbound/inventory.d.ts +64 -0
- package/src/protocol/outbound/inventory.js +147 -0
- package/src/protocol/outbound/ship-management.d.ts +84 -0
- package/src/protocol/outbound/ship-management.js +221 -0
- package/src/protocol/outbound/sign.d.ts +18 -0
- package/src/protocol/outbound/sign.js +45 -0
- package/src/protocol/outbound/ui-config.d.ts +157 -0
- package/src/protocol/outbound/ui-config.js +578 -0
- package/src/runtime.js +36 -0
- package/src/state/generator-maze.d.ts +32 -0
- package/src/state/generator-maze.js +370 -0
- package/src/state/index.d.ts +3 -0
- package/src/state/index.js +3 -0
- package/src/state/items.js +20 -0
- package/src/state/model/decoder.js +1554 -0
- package/src/state/model/index.d.ts +33 -0
- package/src/state/model/index.js +2 -0
- package/src/state/model/loader-config.js +1020 -0
- package/src/state/model/reader.js +69 -0
- package/src/state/model/state.js +1257 -0
- package/src/state/overworld.js +72 -0
- package/src/state/tilesets.js +53 -0
- package/src/state/world/index.d.ts +29 -0
- package/src/state/world/index.js +180 -0
- package/src/state/world/state.js +297 -0
|
@@ -0,0 +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
|
+
]);
|
package/src/runtime.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import {DEFAULT_BASE_URL} from "./constants.js";
|
|
2
|
+
|
|
3
|
+
export const isNode = () => typeof process !== "undefined" && Boolean(process.versions?.node);
|
|
4
|
+
export const isBrowser = () => typeof window !== "undefined" && typeof document !== "undefined";
|
|
5
|
+
export const normalizeBaseUrl = (baseUrl = DEFAULT_BASE_URL) => new URL(baseUrl, DEFAULT_BASE_URL).origin;
|
|
6
|
+
export const resolveUrl = (baseUrl, path = "") => new URL(String(path).replace(/^\//, ""), `${normalizeBaseUrl(baseUrl)}/`).href;
|
|
7
|
+
export const hostName = (baseUrl) => new URL(normalizeBaseUrl(baseUrl)).hostname;
|
|
8
|
+
export const asNumber = (value, fallback = 0) => {
|
|
9
|
+
const number = Number(value);
|
|
10
|
+
return Number.isFinite(number) ? number : fallback;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export function debug(...args) {
|
|
14
|
+
if (isNode() && process.env.DREDLESS_LOG === "1") console.log("[dredless]", ...args);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function getFetch() {
|
|
18
|
+
if (typeof fetch !== "function") throw new Error("globalThis.fetch is not available");
|
|
19
|
+
return fetch.bind(globalThis);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let wsModulePromise = null;
|
|
23
|
+
|
|
24
|
+
export async function getWebSocket() {
|
|
25
|
+
if (isBrowser()) {
|
|
26
|
+
if (typeof WebSocket !== "function") throw new Error("globalThis.WebSocket is not available");
|
|
27
|
+
return WebSocket;
|
|
28
|
+
}
|
|
29
|
+
if (typeof WebSocket === "function" && WebSocket.name !== "WebSocket") return WebSocket;
|
|
30
|
+
if (isNode()) {
|
|
31
|
+
wsModulePromise ??= import("ws").then((module) => module.default || module.WebSocket || module);
|
|
32
|
+
return wsModulePromise;
|
|
33
|
+
}
|
|
34
|
+
if (typeof WebSocket === "function") return WebSocket;
|
|
35
|
+
throw new Error("globalThis.WebSocket is not available");
|
|
36
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export interface GeneratorMazeCellWalls {
|
|
2
|
+
up: boolean;
|
|
3
|
+
down: boolean;
|
|
4
|
+
left: boolean;
|
|
5
|
+
right: boolean;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface GeneratorMazeCell {
|
|
9
|
+
x: number;
|
|
10
|
+
y: number;
|
|
11
|
+
value: number;
|
|
12
|
+
hex: string;
|
|
13
|
+
digit: number;
|
|
14
|
+
walls: GeneratorMazeCellWalls;
|
|
15
|
+
backtrackDirection: number;
|
|
16
|
+
marker: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface GeneratorMaze {
|
|
20
|
+
seed: number;
|
|
21
|
+
width: number;
|
|
22
|
+
height: number;
|
|
23
|
+
cells: GeneratorMazeCell[];
|
|
24
|
+
rows: GeneratorMazeCell[][];
|
|
25
|
+
solution: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function generateGeneratorMaze(seed: number): GeneratorMaze;
|
|
29
|
+
|
|
30
|
+
export function solveGeneratorMazeSeed(seed: number): string;
|
|
31
|
+
|
|
32
|
+
export function maybeSolveGeneratorMazeSeed(seed: number | null | undefined): string | null;
|