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.
- package/README.md +65 -48
- package/dist/browser/dredless.global.js +12047 -0
- package/dist/browser/dredless.global.js.map +7 -0
- package/docs/API_REFERENCE.md +2481 -2481
- package/docs/BROWSER_API.md +98 -98
- package/docs/NODE_API.md +359 -359
- package/package.json +40 -35
- package/src/browser-global.js +3 -0
- package/src/browser.d.ts +212 -212
- package/src/browser.js +133 -133
- package/src/client/core.js +1202 -1202
- package/src/client/domains/index.js +1818 -1818
- package/src/client/index.d.ts +2 -2
- package/src/client/index.js +1 -1
- package/src/compression/lz4.d.ts +1 -1
- package/src/compression/lz4.js +112 -112
- package/src/constants.js +74 -74
- package/src/crypto/chacha-native.d.ts +9 -9
- package/src/crypto/chacha-native.js +48 -48
- package/src/crypto/chacha.d.ts +25 -25
- package/src/crypto/chacha.js +274 -274
- package/src/events.js +39 -39
- package/src/index.d.ts +2277 -2277
- package/src/index.js +125 -125
- package/src/network/browser-session.js +291 -291
- package/src/network/connection.d.ts +1 -1
- package/src/network/connection.js +31 -31
- package/src/network/cookies.js +85 -85
- package/src/network/http.js +34 -34
- package/src/network/index.d.ts +4 -4
- package/src/network/index.js +4 -4
- package/src/network/servers.d.ts +7 -7
- package/src/network/servers.js +133 -133
- package/src/network/session.d.ts +7 -7
- package/src/network/session.js +320 -320
- package/src/network/ships.d.ts +12 -12
- package/src/network/ships.js +73 -73
- package/src/node.d.ts +2 -2
- package/src/node.js +8 -8
- package/src/protocol/codec/binary.d.ts +3 -3
- package/src/protocol/codec/binary.js +52 -52
- package/src/protocol/codec/msgpack.d.ts +3 -3
- package/src/protocol/codec/msgpack.js +555 -555
- package/src/protocol/inbound/frame.d.ts +1 -1
- package/src/protocol/inbound/frame.js +8 -8
- package/src/protocol/inbound/world-payload.d.ts +3 -3
- package/src/protocol/inbound/world-payload.js +21 -21
- package/src/protocol/index.d.ts +11 -11
- package/src/protocol/index.js +19 -19
- package/src/protocol/outbound/blueprint.d.ts +22 -22
- package/src/protocol/outbound/blueprint.js +36 -36
- package/src/protocol/outbound/commands.d.ts +3 -3
- package/src/protocol/outbound/commands.js +149 -149
- package/src/protocol/outbound/comms.d.ts +28 -28
- package/src/protocol/outbound/comms.js +40 -40
- package/src/protocol/outbound/inventory.d.ts +64 -64
- package/src/protocol/outbound/inventory.js +147 -147
- package/src/protocol/outbound/ship-management.d.ts +84 -84
- package/src/protocol/outbound/ship-management.js +221 -221
- package/src/protocol/outbound/sign.d.ts +18 -18
- package/src/protocol/outbound/sign.js +45 -45
- package/src/protocol/outbound/ui-config.d.ts +157 -157
- package/src/protocol/outbound/ui-config.js +578 -578
- package/src/runtime.js +36 -36
- package/src/state/generator-maze.d.ts +32 -32
- package/src/state/generator-maze.js +370 -370
- package/src/state/index.d.ts +3 -3
- package/src/state/index.js +3 -3
- package/src/state/items.js +20 -20
- package/src/state/model/decoder.js +1554 -1554
- package/src/state/model/index.d.ts +33 -33
- package/src/state/model/index.js +2 -2
- package/src/state/model/loader-config.js +1020 -1020
- package/src/state/model/reader.js +69 -69
- package/src/state/model/state.js +1257 -1257
- package/src/state/overworld.js +72 -72
- package/src/state/tilesets.js +53 -53
- package/src/state/world/index.d.ts +29 -29
- package/src/state/world/index.js +180 -180
- package/src/state/world/state.js +297 -297
|
@@ -1,1818 +1,1818 @@
|
|
|
1
|
-
import {itemEquipmentSlotFromId} from "../../state/items.js";
|
|
2
|
-
import {buildInventoryDragCommand, normalizeEquipmentSlot, normalizeInventoryEvent} from "../../protocol/outbound/inventory.js";
|
|
3
|
-
|
|
4
|
-
export function normalizeAttachMode(mode = "observe") {
|
|
5
|
-
const value = String(mode || "observe").toLowerCase();
|
|
6
|
-
if (value === "observe" || value === "bootstrap" || value === "readonly") return value;
|
|
7
|
-
throw new Error(`Unsupported websocket attach mode: ${mode}`);
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export class ClientNetDomain {
|
|
11
|
-
constructor(client) {
|
|
12
|
-
this.client = client;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
get connected() {
|
|
16
|
-
return this.client.connected;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
get ready() {
|
|
20
|
-
return this.client.ready;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
get sid() {
|
|
24
|
-
return this.client.sid;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
get packetCount() {
|
|
28
|
-
return this.client.packetCount;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
get lastPacket() {
|
|
32
|
-
return this.client.lastPacket;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
send(command = {}) {
|
|
36
|
-
return this.client.send(command);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
sendMessage(message, options = {}) {
|
|
40
|
-
return this.client.sendMessage(message, options);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
sendRaw(message, options = {}) {
|
|
44
|
-
return this.client.sendRaw(message, options);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
sendEntityCommand(cmd, args = [-1, -1, -1]) {
|
|
48
|
-
return this.client.sendEntityCommand(cmd, args);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
sendUiConfig(data) {
|
|
52
|
-
return this.client.sendUiConfig(data);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
sendBlueprintPlacement(placement) {
|
|
56
|
-
return this.client.sendBlueprintPlacement(placement);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
setOutfit(outfit) {
|
|
60
|
-
return this.client.setOutfit(outfit);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export class ClientDebugDomain {
|
|
65
|
-
constructor(client) {
|
|
66
|
-
this.client = client;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
packets() {
|
|
70
|
-
return this.client.packets.slice();
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
decodeErrors() {
|
|
74
|
-
return this.client.decodeErrors.slice();
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
worldStore() {
|
|
78
|
-
return this.client.worlds;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
modelTable(worldId, tableId) {
|
|
82
|
-
return this.client.worlds.worlds.get(Number(worldId))?.model.table(tableId) || new Map();
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
modelRecord(worldId, tableId, entityId) {
|
|
86
|
-
return this.client.worlds.worlds.get(Number(worldId))?.model.record(tableId, entityId) || null;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
entities(scope = "ship") {
|
|
90
|
-
return summariesFor(this.client, scope);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
entity(scope = "ship", entity = null) {
|
|
94
|
-
if (entity == null) return null;
|
|
95
|
-
return summaryForEntity(this.client, scope, entityIdOf(entity));
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
puiPanels() {
|
|
99
|
-
return [...this.client.puiPanels.values()];
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
commsPanels() {
|
|
103
|
-
return [...this.client.commsPanels.values()];
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export class PlayerDomain {
|
|
108
|
-
constructor(client) {
|
|
109
|
-
this.client = client;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
current() {
|
|
113
|
-
return currentPlayerSummary(this.client);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
entity() {
|
|
117
|
-
return this.client.currentPlayerEntity();
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
name() {
|
|
121
|
-
return this.current()?.name ?? null;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
rank() {
|
|
125
|
-
return currentPlayerRank(this.client);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
move({x = 0, y = 0} = {}, command = {}) {
|
|
129
|
-
return this.client.move(x, y, command);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
aim({x = 0, y = 0, mx = x, my = y} = {}, command = {}) {
|
|
133
|
-
return this.client.aim(mx, my, command);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
action(flags = {}, command = {}) {
|
|
137
|
-
return this.client.action(flags, command);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
useEntity(entity, options = {}, command = {}) {
|
|
141
|
-
return this.client.useEntity(entityIdOf(entity), options, command);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
useHeldItem(options = {}, command = {}) {
|
|
145
|
-
return this.client.useHeldItem(options, command);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
placeHeldItem(options = {}, command = {}) {
|
|
149
|
-
return this.client.placeHeldItem(options, command);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
placeBlueprint(placement, options = {}, command = {}) {
|
|
153
|
-
return this.client.placeBlueprint(placement, options, command);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
rotateHeldItem(options = {}, command = {}) {
|
|
157
|
-
return this.client.rotateHeldItem(options, command);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
selectSlot(invSlot = 0, command = {}) {
|
|
161
|
-
return this.client.send({...command, inv_slot: inventorySlotIndexOf(invSlot)});
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
inputSettings() {
|
|
165
|
-
return this.client.inputSettings();
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
setInputSettings(settings = {}, options = {}) {
|
|
169
|
-
return this.client.setInputSettings(settings, options);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
setView(width, height, options = {}) {
|
|
173
|
-
return this.client.setView(width, height, options);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
setScreenSize(width, height, options = {}) {
|
|
177
|
-
return this.client.setScreenSize(width, height, options);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
setWrenchMode(mode, options = {}) {
|
|
181
|
-
return this.client.setWrenchMode(mode, options);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
setTurretMode(mode, options = {}) {
|
|
185
|
-
return this.client.setTurretMode(mode, options);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
export class ShipManagementDomain {
|
|
190
|
-
constructor(client) {
|
|
191
|
-
this.client = client;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
requestPlayerList() {
|
|
195
|
-
return this.client.requestPlayerList();
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
resetInvite() {
|
|
199
|
-
return this.client.resetInvite();
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
setPrivacy(privacy) {
|
|
203
|
-
return this.client.setShipPrivacy(privacy);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
recoverStarterItem(itemId) {
|
|
207
|
-
return this.client.recoverStarterItem(itemId);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
setPlayerRank(refId, rank) {
|
|
211
|
-
return this.client.setPlayerRank(refId, rank);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
kickPlayer(refId) {
|
|
215
|
-
return this.client.kickPlayer(refId);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
banPlayer(refId) {
|
|
219
|
-
return this.client.banPlayer(refId);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
demoteSelf() {
|
|
223
|
-
return this.client.demoteSelf();
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
config() {
|
|
227
|
-
return this.client.shipConfig;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
hasCheats() {
|
|
231
|
-
return Boolean(this.client.captainSubrank?.enableCheats);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
playerList() {
|
|
235
|
-
return this.client.playerList;
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
export class InventoryDomain {
|
|
240
|
-
constructor(client) {
|
|
241
|
-
this.client = client;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
state() {
|
|
245
|
-
return this.client.inventoryState;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
hotbarSize() {
|
|
249
|
-
return this.state()?.hotbarSize ?? 0;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
allSlots() {
|
|
253
|
-
return (this.state()?.slots || []).map((slot) => this.slot(slot.index));
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
slot(ref) {
|
|
257
|
-
return new InventorySlotHandle(this, inventorySlotIndexOf(ref));
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
hotbarSlots() {
|
|
261
|
-
return (this.state()?.hotbar || []).map((slot) => this.slot(slot.index));
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
equipmentSlots() {
|
|
265
|
-
return {
|
|
266
|
-
head: this.slot("head"),
|
|
267
|
-
face: this.slot("face"),
|
|
268
|
-
body: this.slot("body"),
|
|
269
|
-
back: this.slot("back"),
|
|
270
|
-
hands: this.slot("hands"),
|
|
271
|
-
feet: this.slot("feet")
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
findItem(itemId, {area = "all"} = {}) {
|
|
276
|
-
return this.findItems(itemId, {area})[0] || null;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
findItems(itemId, {area = "all"} = {}) {
|
|
280
|
-
const normalized = Number(itemId);
|
|
281
|
-
if (!Number.isFinite(normalized)) return [];
|
|
282
|
-
return inventoryHandlesForArea(this, area).filter((slot) => slot.itemId === normalized);
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
firstEmpty({area = "all"} = {}) {
|
|
286
|
-
return inventoryHandlesForArea(this, area).find((slot) => slot.empty) || null;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
move(source, target, {split = false} = {}, command = {}) {
|
|
290
|
-
return this.client.send({
|
|
291
|
-
...command,
|
|
292
|
-
...buildInventoryDragCommand(inventorySlotIndexOf(source, "source"), inventorySlotIndexOf(target, "target"), split)
|
|
293
|
-
});
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
equip(source, equipmentSlot = null, options = {}, command = {}) {
|
|
297
|
-
const args = normalizeEquipArguments(equipmentSlot, options, command);
|
|
298
|
-
const target = args.equipmentSlot == null ? inferEquipmentSlotForInventorySource(this, source) : args.equipmentSlot;
|
|
299
|
-
return this.move(source, normalizeEquipmentSlot(target), {split: args.split}, args.command);
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
unequip(equipmentSlot, target = 0, {split = false} = {}, command = {}) {
|
|
303
|
-
return this.move(normalizeEquipmentSlot(equipmentSlot), target, {split}, command);
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
select(slot, command = {}) {
|
|
307
|
-
return this.client.send({...command, inv_slot: inventorySlotIndexOf(slot)});
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
export class InventorySlotHandle {
|
|
312
|
-
constructor(domain, index) {
|
|
313
|
-
this.domain = domain;
|
|
314
|
-
this.client = domain.client;
|
|
315
|
-
this.index = index;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
get state() {
|
|
319
|
-
return this.domain.state()?.slots?.find((slot) => slot.index === this.index) || null;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
get kind() {
|
|
323
|
-
return this.state?.kind ?? null;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
get equipmentSlot() {
|
|
327
|
-
return this.state?.equipmentSlot ?? null;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
get itemId() {
|
|
331
|
-
return this.state?.itemId ?? null;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
get itemName() {
|
|
335
|
-
return this.state?.itemName ?? null;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
get count() {
|
|
339
|
-
return this.state?.count ?? 0;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
get empty() {
|
|
343
|
-
return this.state?.empty ?? true;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
exists() {
|
|
347
|
-
return Boolean(this.state);
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
snapshot() {
|
|
351
|
-
return this.state ? Object.freeze({...this.state}) : null;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
moveTo(target, options = {}, command = {}) {
|
|
355
|
-
return this.domain.move(this, target, options, command);
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
equip(equipmentSlot = null, options = {}, command = {}) {
|
|
359
|
-
if (equipmentSlot && typeof equipmentSlot === "object") return this.domain.equip(this, null, equipmentSlot, options);
|
|
360
|
-
return this.domain.equip(this, equipmentSlot, options, command);
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
unequip(target = 0, options = {}, command = {}) {
|
|
364
|
-
if (!this.equipmentSlot) throw new RangeError(`inventory slot ${this.index} is not an equipment slot`);
|
|
365
|
-
return this.domain.unequip(this.equipmentSlot, target, options, command);
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
select(command = {}) {
|
|
369
|
-
return this.domain.select(this, command);
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
export class WorldDomain {
|
|
374
|
-
constructor(client, scope) {
|
|
375
|
-
this.client = client;
|
|
376
|
-
this.scope = scope;
|
|
377
|
-
this.entities = new EntityCollection(client, scope);
|
|
378
|
-
this.machines = new MachineCollection(client, scope);
|
|
379
|
-
this.players = new PlayerCollection(client, scope);
|
|
380
|
-
this.blocks = new BlockCollection(client, scope);
|
|
381
|
-
this.materials = new MaterialCollection(client, scope);
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
get id() {
|
|
385
|
-
return worldStateFor(this.client, this.scope)?.id ?? null;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
exists() {
|
|
389
|
-
return Boolean(worldStateFor(this.client, this.scope));
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
snapshot(options = {}) {
|
|
393
|
-
return worldStateFor(this.client, this.scope)?.snapshot(options) || null;
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
export class ShipDomain extends WorldDomain {
|
|
398
|
-
entity() {
|
|
399
|
-
const summary = this.client.worlds.currentShipEntity();
|
|
400
|
-
return summary ? new EntityHandle(this.client, summary.entity, "overworld") : null;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
get overworldEntity() {
|
|
404
|
-
return this.entity();
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
get metadata() {
|
|
408
|
-
return worldStateFor(this.client, this.scope)?.model.shipMetadata() || null;
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
export class OverworldDomain extends WorldDomain {
|
|
413
|
-
ships(options = {}) {
|
|
414
|
-
return this.client.ships(options).map((summary) => new ShipHandle(this.client, summary));
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
shipByHex(hexCode, options = {}) {
|
|
418
|
-
const summary = this.client.shipByHex(hexCode, options);
|
|
419
|
-
return summary ? new ShipHandle(this.client, summary) : null;
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
shipByEntity(entity, options = {}) {
|
|
423
|
-
const summary = this.client.shipByEntity(entityIdOf(entity), options);
|
|
424
|
-
return summary ? new ShipHandle(this.client, summary) : null;
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
const ENTITY_SNAPSHOT_CACHE = new WeakMap();
|
|
429
|
-
|
|
430
|
-
function entitySnapshotFor(summary) {
|
|
431
|
-
if (!summary || typeof summary !== "object") return null;
|
|
432
|
-
let snapshot = ENTITY_SNAPSHOT_CACHE.get(summary);
|
|
433
|
-
if (!snapshot) {
|
|
434
|
-
snapshot = new EntitySnapshot(summary);
|
|
435
|
-
ENTITY_SNAPSHOT_CACHE.set(summary, snapshot);
|
|
436
|
-
}
|
|
437
|
-
return snapshot;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
export class EntitySnapshot {
|
|
441
|
-
#contents;
|
|
442
|
-
|
|
443
|
-
constructor(summary) {
|
|
444
|
-
const data = clonePlain(summary || {});
|
|
445
|
-
this.#contents = data.contents || null;
|
|
446
|
-
delete data.contents;
|
|
447
|
-
Object.assign(this, data);
|
|
448
|
-
this.id = Number(data.entity ?? data.id);
|
|
449
|
-
this.entity = this.id;
|
|
450
|
-
this.position = data.transform || null;
|
|
451
|
-
this.rotation = data.transform?.rotation ?? null;
|
|
452
|
-
this.type = entityPublicType(data, this.#contents);
|
|
453
|
-
this.features = Object.freeze(entityFeatures(data, this.#contents));
|
|
454
|
-
deepFreeze(this.#contents);
|
|
455
|
-
deepFreeze(this);
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
is(type) {
|
|
459
|
-
const key = normalizeEntityKey(type);
|
|
460
|
-
if (!key) return false;
|
|
461
|
-
const publicType = normalizeEntityKey(this.type);
|
|
462
|
-
if (key === publicType) return true;
|
|
463
|
-
if (key === normalizeEntityKey(this.category)) return true;
|
|
464
|
-
if (key === "placedentity" && this.category === "placed_entity") return true;
|
|
465
|
-
if (key === "looseitem" && this.category === "loose_item") return true;
|
|
466
|
-
if (key === "ship" && (this.category === "ship_control" || this.#contents?.shipControl)) return true;
|
|
467
|
-
if (key === "machine") return Boolean(entityMachineType(this.#contents));
|
|
468
|
-
if (key === "item") return Boolean(this.#contents?.itemHolder || this.#contents?.itemCrate || this.#contents?.expandoBox);
|
|
469
|
-
if (key === "bot") return Boolean(this.#contents?.bot);
|
|
470
|
-
if (key === "player") return Boolean(this.#contents?.player || this.category === "player");
|
|
471
|
-
if (this.kind?.some((kind) => normalizeEntityKey(kind) === key)) return true;
|
|
472
|
-
return Boolean(componentFor(this.#contents, key));
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
has(feature) {
|
|
476
|
-
return this.feature(feature) != null;
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
feature(feature) {
|
|
480
|
-
return entityFeature(this, this.#contents, feature);
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
export class EntityCollection {
|
|
485
|
-
constructor(client, scope) {
|
|
486
|
-
this.client = client;
|
|
487
|
-
this.scope = scope;
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
all() {
|
|
491
|
-
return summariesFor(this.client, this.scope).map((summary) => new EntityHandle(this.client, summary.entity, this.scope));
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
snapshots() {
|
|
495
|
-
return summariesFor(this.client, this.scope).map(entitySnapshotFor);
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
states() {
|
|
499
|
-
return this.snapshots();
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
get(entity) {
|
|
503
|
-
return new EntityHandle(this.client, entityIdOf(entity), this.scope);
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
export class PlayerCollection {
|
|
508
|
-
constructor(client, scope) {
|
|
509
|
-
this.client = client;
|
|
510
|
-
this.scope = scope;
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
all() {
|
|
514
|
-
return worldStateFor(this.client, this.scope)?.model.players() || [];
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
current() {
|
|
518
|
-
return currentPlayerSummary(this.client, this.scope);
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
export class BlockCollection {
|
|
523
|
-
constructor(client, scope) {
|
|
524
|
-
this.client = client;
|
|
525
|
-
this.scope = scope;
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
all() {
|
|
529
|
-
return worldStateFor(this.client, this.scope)?.blocks() || [];
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
at(x, y) {
|
|
533
|
-
return worldStateFor(this.client, this.scope)?.blockAt(x, y) || null;
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
export class MaterialCollection {
|
|
538
|
-
constructor(client, scope) {
|
|
539
|
-
this.client = client;
|
|
540
|
-
this.scope = scope;
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
all() {
|
|
544
|
-
return worldStateFor(this.client, this.scope)?.materials() || [];
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
export class MachineCollection {
|
|
549
|
-
constructor(client, scope) {
|
|
550
|
-
this.client = client;
|
|
551
|
-
this.scope = scope;
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
state() {
|
|
555
|
-
return worldStateFor(this.client, this.scope)?.model.machines() || emptyMachineSummary();
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
raw() {
|
|
559
|
-
return this.state();
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
loaders() {
|
|
563
|
-
return this.state().loaders.map((item) => new LoaderHandle(this.client, item.entity, this.scope));
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
loader(entity) {
|
|
567
|
-
return new LoaderHandle(this.client, entityIdOf(entity), this.scope);
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
pushers() {
|
|
571
|
-
return this.state().pushers.map((item) => new PusherHandle(this.client, item.entity, this.scope));
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
pusher(entity) {
|
|
575
|
-
return new PusherHandle(this.client, entityIdOf(entity), this.scope);
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
launchers() {
|
|
579
|
-
return this.state().launchers.map((item) => new LauncherHandle(this.client, item.entity, this.scope));
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
launcher(entity) {
|
|
583
|
-
return new LauncherHandle(this.client, entityIdOf(entity), this.scope);
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
navigationUnits() {
|
|
587
|
-
return this.state().navigationUnits.map((item) => new NavigationUnitHandle(this.client, item.entity, this.scope));
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
navigationUnit(entity = null) {
|
|
591
|
-
const id = entity == null ? this.state().navigationUnits[0]?.entity : entityIdOf(entity);
|
|
592
|
-
return id == null ? null : new NavigationUnitHandle(this.client, id, this.scope);
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
fabricators() {
|
|
596
|
-
return this.state().fabricators.map((item) => new FabricatorHandle(this.client, item.entity, this.scope));
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
fabricator(entity) {
|
|
600
|
-
return new FabricatorHandle(this.client, entityIdOf(entity), this.scope);
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
commsStations() {
|
|
604
|
-
return this.state().commsStations.map((item) => new CommsStationHandle(this.client, item.entity, this.scope));
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
commsStation(entity = null) {
|
|
608
|
-
const id = entity == null ? this.state().commsStations[0]?.entity : entityIdOf(entity);
|
|
609
|
-
return id == null ? null : new CommsStationHandle(this.client, id, this.scope);
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
signs() {
|
|
613
|
-
return summariesFor(this.client, this.scope).filter((item) => item.contents?.sign).map((item) => new SignHandle(this.client, item.entity, this.scope));
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
sign(entity) {
|
|
617
|
-
return new SignHandle(this.client, entityIdOf(entity), this.scope);
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
generators() {
|
|
621
|
-
return this.state().shieldGenerators.map((item) => new GeneratorHandle(this.client, item.entity, this.scope));
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
generator(entity) {
|
|
625
|
-
return new GeneratorHandle(this.client, entityIdOf(entity), this.scope);
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
cargoHatches() {
|
|
629
|
-
return this.state().cargoHatches.map((item) => new CargoHatchHandle(this.client, item.entity, this.scope));
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
cargoHatch(entity) {
|
|
633
|
-
return new CargoHatchHandle(this.client, entityIdOf(entity), this.scope);
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
cargoEjectors() {
|
|
637
|
-
return this.state().cargoEjectors.map((item) => new CargoEjectorHandle(this.client, item.entity, this.scope));
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
cargoEjector(entity) {
|
|
641
|
-
return new CargoEjectorHandle(this.client, entityIdOf(entity), this.scope);
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
cannons() {
|
|
645
|
-
return this.state().cannons.map((item) => new CannonHandle(this.client, item.entity, this.scope));
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
cannon(entity) {
|
|
649
|
-
return new CannonHandle(this.client, entityIdOf(entity), this.scope);
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
thrusters() {
|
|
653
|
-
return this.state().thrusters.map((item) => new ThrusterHandle(this.client, item.entity, this.scope));
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
thruster(entity) {
|
|
657
|
-
return new ThrusterHandle(this.client, entityIdOf(entity), this.scope);
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
helms() {
|
|
661
|
-
return this.state().helms.map((item) => new HelmHandle(this.client, item.entity, this.scope));
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
helm(entity) {
|
|
665
|
-
return new HelmHandle(this.client, entityIdOf(entity), this.scope);
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
doors() {
|
|
669
|
-
return this.state().doors.map((item) => new DoorHandle(this.client, item.entity, this.scope));
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
door(entity) {
|
|
673
|
-
return new DoorHandle(this.client, entityIdOf(entity), this.scope);
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
spawnPoints() {
|
|
677
|
-
return this.state().spawnPoints.map((item) => new SpawnPointHandle(this.client, item.entity, this.scope));
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
spawnPoint(entity) {
|
|
681
|
-
return new SpawnPointHandle(this.client, entityIdOf(entity), this.scope);
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
shieldProjectors() {
|
|
685
|
-
return this.state().shieldProjectors.map((item) => new ShieldProjectorHandle(this.client, item.entity, this.scope));
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
shieldProjector(entity) {
|
|
689
|
-
return new ShieldProjectorHandle(this.client, entityIdOf(entity), this.scope);
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
fluidTanks() {
|
|
693
|
-
return this.state().fluidTanks.map((item) => new FluidTankHandle(this.client, item.entity, this.scope));
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
fluidTank(entity) {
|
|
697
|
-
return new FluidTankHandle(this.client, entityIdOf(entity), this.scope);
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
expandoBoxes() {
|
|
701
|
-
return this.state().expandoBoxes.map((item) => new ExpandoBoxHandle(this.client, item.entity, this.scope));
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
expandoBox(entity) {
|
|
705
|
-
return new ExpandoBoxHandle(this.client, entityIdOf(entity), this.scope);
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
export class EntityHandle {
|
|
710
|
-
constructor(client, entity, scope = "ship") {
|
|
711
|
-
this.client = client;
|
|
712
|
-
this.id = Number(entity);
|
|
713
|
-
this.entity = this.id;
|
|
714
|
-
this.scope = scope;
|
|
715
|
-
this._cachedSummary = undefined;
|
|
716
|
-
this._cachedSnapshot = null;
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
exists() {
|
|
720
|
-
return Boolean(this.snapshot());
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
// Reading five properties off a handle used to walk the world/derived-state
|
|
724
|
-
// resolution chain five times. The summary object identity changes whenever
|
|
725
|
-
// the entity is refreshed, so it doubles as the cache key.
|
|
726
|
-
snapshot() {
|
|
727
|
-
const summary = worldStateFor(this.client, this.scope)?.entity(this.id) || null;
|
|
728
|
-
if (summary !== this._cachedSummary) {
|
|
729
|
-
this._cachedSummary = summary;
|
|
730
|
-
this._cachedSnapshot = entitySnapshotFor(summary);
|
|
731
|
-
}
|
|
732
|
-
return this._cachedSnapshot;
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
get position() {
|
|
736
|
-
return summaryForEntity(this.client, this.scope, this.id)?.transform || null;
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
get health() {
|
|
740
|
-
return summaryForEntity(this.client, this.scope, this.id)?.contents?.health || null;
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
get type() {
|
|
744
|
-
return this.snapshot()?.type ?? "unknown";
|
|
745
|
-
}
|
|
746
|
-
|
|
747
|
-
get features() {
|
|
748
|
-
return this.snapshot()?.features ?? [];
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
is(type) {
|
|
752
|
-
return this.snapshot()?.is(type) ?? false;
|
|
753
|
-
}
|
|
754
|
-
|
|
755
|
-
has(feature) {
|
|
756
|
-
return this.snapshot()?.has(feature) ?? false;
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
feature(feature) {
|
|
760
|
-
return this.snapshot()?.feature(feature) ?? null;
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
as(type) {
|
|
764
|
-
return entityDomainHandle(this.client, this.id, this.scope, type, this.snapshot());
|
|
765
|
-
}
|
|
766
|
-
|
|
767
|
-
asLoader() {
|
|
768
|
-
return this.as("loader");
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
asPusher() {
|
|
772
|
-
return this.as("pusher");
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
asLauncher() {
|
|
776
|
-
return this.as("launcher");
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
asNavigationUnit() {
|
|
780
|
-
return this.as("navigationUnit");
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
asCommsStation() {
|
|
784
|
-
return this.as("commsStation");
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
asSign() {
|
|
788
|
-
return this.as("sign");
|
|
789
|
-
}
|
|
790
|
-
|
|
791
|
-
asGenerator() {
|
|
792
|
-
return this.as("shieldGenerator");
|
|
793
|
-
}
|
|
794
|
-
|
|
795
|
-
asCargoHatch() {
|
|
796
|
-
return this.as("cargoHatch");
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
asCannon() {
|
|
800
|
-
return this.as("cannon");
|
|
801
|
-
}
|
|
802
|
-
|
|
803
|
-
asThruster() {
|
|
804
|
-
return this.as("thruster");
|
|
805
|
-
}
|
|
806
|
-
|
|
807
|
-
asHelm() {
|
|
808
|
-
return this.as("helm");
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
asDoor() {
|
|
812
|
-
return this.as("door");
|
|
813
|
-
}
|
|
814
|
-
|
|
815
|
-
asSpawnPoint() {
|
|
816
|
-
return this.as("spawnPoint");
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
asShieldProjector() {
|
|
820
|
-
return this.as("shieldProjector");
|
|
821
|
-
}
|
|
822
|
-
|
|
823
|
-
asFluidTank() {
|
|
824
|
-
return this.as("fluidTank");
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
asCargoEjector() {
|
|
828
|
-
return this.as("cargoEjector");
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
asExpandoBox() {
|
|
832
|
-
return this.as("expandoBox");
|
|
833
|
-
}
|
|
834
|
-
|
|
835
|
-
use(options = {}, command = {}) {
|
|
836
|
-
return this.client.player.useEntity(this.id, options, command);
|
|
837
|
-
}
|
|
838
|
-
}
|
|
839
|
-
|
|
840
|
-
export class MachineHandle extends EntityHandle {
|
|
841
|
-
open(options = {}, command = {}) {
|
|
842
|
-
return this.use(options, command);
|
|
843
|
-
}
|
|
844
|
-
}
|
|
845
|
-
|
|
846
|
-
export class LoaderHandle extends MachineHandle {
|
|
847
|
-
get state() {
|
|
848
|
-
return summaryForEntity(this.client, this.scope, this.id)?.contents?.loader || null;
|
|
849
|
-
}
|
|
850
|
-
|
|
851
|
-
configure(config = {}) {
|
|
852
|
-
return this.client.sendLoaderConfig(this.id, config);
|
|
853
|
-
}
|
|
854
|
-
|
|
855
|
-
configureFull(config = {}) {
|
|
856
|
-
return this.client.sendLoaderFullConfig(this.id, config);
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
copy(config = {}) {
|
|
860
|
-
return this.client.copyLoaderConfig(this.id, config);
|
|
861
|
-
}
|
|
862
|
-
|
|
863
|
-
setPickPlace(pick, place, config = {}) {
|
|
864
|
-
return this.client.setLoaderPickPlace(this.id, pick, place, config);
|
|
865
|
-
}
|
|
866
|
-
|
|
867
|
-
setPriority(priority, config = {}) {
|
|
868
|
-
return this.client.setLoaderPriority(this.id, priority, config);
|
|
869
|
-
}
|
|
870
|
-
|
|
871
|
-
setStack(stack, config = {}) {
|
|
872
|
-
return this.client.setLoaderStack(this.id, stack, config);
|
|
873
|
-
}
|
|
874
|
-
|
|
875
|
-
setCycle(cycle, config = {}) {
|
|
876
|
-
return this.client.setLoaderCycle(this.id, cycle, config);
|
|
877
|
-
}
|
|
878
|
-
|
|
879
|
-
setRequireOutput(requireOutput, config = {}) {
|
|
880
|
-
return this.client.setLoaderRequireOutput(this.id, requireOutput, config);
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
setWaitForStack(waitForStack, config = {}) {
|
|
884
|
-
return this.client.setLoaderWaitForStack(this.id, waitForStack, config);
|
|
885
|
-
}
|
|
886
|
-
|
|
887
|
-
setFilterMode(filterMode) {
|
|
888
|
-
return this.client.setLoaderFilterMode(this.id, filterMode);
|
|
889
|
-
}
|
|
890
|
-
|
|
891
|
-
setFilterItems(filterSlots = []) {
|
|
892
|
-
return this.client.setLoaderFilterItems(this.id, filterSlots);
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
get pick() {
|
|
896
|
-
return this.state?.pick;
|
|
897
|
-
}
|
|
898
|
-
|
|
899
|
-
get place() {
|
|
900
|
-
return this.state?.place;
|
|
901
|
-
}
|
|
902
|
-
|
|
903
|
-
get priority() {
|
|
904
|
-
return this.state?.priority;
|
|
905
|
-
}
|
|
906
|
-
|
|
907
|
-
get stack() {
|
|
908
|
-
return this.state?.stack;
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
get cycle() {
|
|
912
|
-
return this.state?.cycle;
|
|
913
|
-
}
|
|
914
|
-
|
|
915
|
-
get requireOutput() {
|
|
916
|
-
return this.state?.requireOutput;
|
|
917
|
-
}
|
|
918
|
-
|
|
919
|
-
get waitForStack() {
|
|
920
|
-
return this.state?.waitForStack;
|
|
921
|
-
}
|
|
922
|
-
|
|
923
|
-
get filterMode() {
|
|
924
|
-
return this.state?.filterMode;
|
|
925
|
-
}
|
|
926
|
-
|
|
927
|
-
get filterSlots() {
|
|
928
|
-
return this.state?.filterSlots || [];
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
get active() {
|
|
932
|
-
return this.state?.active;
|
|
933
|
-
}
|
|
934
|
-
|
|
935
|
-
get heldItem() {
|
|
936
|
-
const state = this.state;
|
|
937
|
-
if (!state || state.heldItemId == null) return null;
|
|
938
|
-
return {itemId: state.heldItemId, itemName: state.heldItemName, count: state.heldCount};
|
|
939
|
-
}
|
|
940
|
-
|
|
941
|
-
get progress() {
|
|
942
|
-
return this.state?.progress;
|
|
943
|
-
}
|
|
944
|
-
}
|
|
945
|
-
|
|
946
|
-
export class PusherHandle extends MachineHandle {
|
|
947
|
-
get state() {
|
|
948
|
-
return summaryForEntity(this.client, this.scope, this.id)?.contents?.pusher || null;
|
|
949
|
-
}
|
|
950
|
-
|
|
951
|
-
get beam() {
|
|
952
|
-
return summaryForEntity(this.client, this.scope, this.id)?.contents?.pusherBeam || null;
|
|
953
|
-
}
|
|
954
|
-
|
|
955
|
-
configure(config = {}) {
|
|
956
|
-
return this.client.sendPusherConfig(this.id, config);
|
|
957
|
-
}
|
|
958
|
-
|
|
959
|
-
setAngle(angle, config = {}) {
|
|
960
|
-
return this.client.setPusherAngle(this.id, angle, config);
|
|
961
|
-
}
|
|
962
|
-
|
|
963
|
-
setSpeed(speed, config = {}) {
|
|
964
|
-
return this.client.setPusherSpeed(this.id, speed, config);
|
|
965
|
-
}
|
|
966
|
-
|
|
967
|
-
setLength(length, config = {}) {
|
|
968
|
-
return this.client.setPusherLength(this.id, length, config);
|
|
969
|
-
}
|
|
970
|
-
|
|
971
|
-
setMode(mode, config = {}) {
|
|
972
|
-
return this.client.setPusherMode(this.id, mode, config);
|
|
973
|
-
}
|
|
974
|
-
|
|
975
|
-
setFilteredMode(mode, config = {}) {
|
|
976
|
-
return this.client.setPusherFilteredMode(this.id, mode, config);
|
|
977
|
-
}
|
|
978
|
-
|
|
979
|
-
setFilterInventory(filterInventory, config = {}) {
|
|
980
|
-
return this.client.setPusherFilterInventory(this.id, filterInventory, config);
|
|
981
|
-
}
|
|
982
|
-
|
|
983
|
-
setFilterItems(filterSlots = []) {
|
|
984
|
-
return this.client.setPusherFilterItems(this.id, filterSlots);
|
|
985
|
-
}
|
|
986
|
-
|
|
987
|
-
get angle() {
|
|
988
|
-
return this.state?.angle;
|
|
989
|
-
}
|
|
990
|
-
|
|
991
|
-
get speed() {
|
|
992
|
-
return this.state?.speed;
|
|
993
|
-
}
|
|
994
|
-
|
|
995
|
-
get length() {
|
|
996
|
-
return this.state?.length;
|
|
997
|
-
}
|
|
998
|
-
|
|
999
|
-
get mode() {
|
|
1000
|
-
return this.state?.mode;
|
|
1001
|
-
}
|
|
1002
|
-
|
|
1003
|
-
get filteredMode() {
|
|
1004
|
-
return this.state?.filteredMode;
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
|
|
1008
|
-
export class LauncherHandle extends MachineHandle {
|
|
1009
|
-
get state() {
|
|
1010
|
-
return summaryForEntity(this.client, this.scope, this.id)?.contents?.launcher || null;
|
|
1011
|
-
}
|
|
1012
|
-
|
|
1013
|
-
setAngle(angle) {
|
|
1014
|
-
return this.client.setLauncherAngle(angle);
|
|
1015
|
-
}
|
|
1016
|
-
|
|
1017
|
-
setPower(power) {
|
|
1018
|
-
return this.client.setLauncherPower(power);
|
|
1019
|
-
}
|
|
1020
|
-
|
|
1021
|
-
get angleDegrees() {
|
|
1022
|
-
return this.state?.angleDegrees;
|
|
1023
|
-
}
|
|
1024
|
-
|
|
1025
|
-
get angleRadians() {
|
|
1026
|
-
return this.state?.angleRadians;
|
|
1027
|
-
}
|
|
1028
|
-
|
|
1029
|
-
get angleRaw() {
|
|
1030
|
-
return this.state?.angleRaw;
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
|
|
1034
|
-
export class NavigationUnitHandle extends MachineHandle {
|
|
1035
|
-
get state() {
|
|
1036
|
-
return summaryForEntity(this.client, this.scope, this.id)?.contents?.navigationUnit || null;
|
|
1037
|
-
}
|
|
1038
|
-
|
|
1039
|
-
configure(config = {}) {
|
|
1040
|
-
return this.client.sendNavigationUnitConfig(this.id, config);
|
|
1041
|
-
}
|
|
1042
|
-
|
|
1043
|
-
copy(config = {}) {
|
|
1044
|
-
return this.client.copyNavigationUnitConfig(this.id, config);
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
|
-
paste(config = {}) {
|
|
1048
|
-
return this.client.pasteNavigationUnitConfig(this.id, config);
|
|
1049
|
-
}
|
|
1050
|
-
|
|
1051
|
-
setDestination(destination, config = {}) {
|
|
1052
|
-
return this.client.setNavigationDestination(this.id, destination, config);
|
|
1053
|
-
}
|
|
1054
|
-
|
|
1055
|
-
setAutoWarp(config = {}) {
|
|
1056
|
-
return this.client.setNavigationAutoWarp(this.id, config);
|
|
1057
|
-
}
|
|
1058
|
-
|
|
1059
|
-
startWarp(config = {}) {
|
|
1060
|
-
return this.client.startWarp(this.id, config);
|
|
1061
|
-
}
|
|
1062
|
-
|
|
1063
|
-
cancelWarp(config = {}) {
|
|
1064
|
-
return this.client.cancelWarp(this.id, config);
|
|
1065
|
-
}
|
|
1066
|
-
|
|
1067
|
-
get destination() {
|
|
1068
|
-
return this.state?.destination;
|
|
1069
|
-
}
|
|
1070
|
-
|
|
1071
|
-
get autoWarpOnShieldFailure() {
|
|
1072
|
-
return this.state?.autoWarpOnShieldFailure;
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
|
-
get autoWarpOnNoCaptains() {
|
|
1076
|
-
return this.state?.autoWarpOnNoCaptains;
|
|
1077
|
-
}
|
|
1078
|
-
|
|
1079
|
-
get warp() {
|
|
1080
|
-
return this.state?.warp;
|
|
1081
|
-
}
|
|
1082
|
-
}
|
|
1083
|
-
|
|
1084
|
-
export class FabricatorHandle extends MachineHandle {
|
|
1085
|
-
get state() {
|
|
1086
|
-
return summaryForEntity(this.client, this.scope, this.id)?.contents?.fabricator || null;
|
|
1087
|
-
}
|
|
1088
|
-
|
|
1089
|
-
get progress() {
|
|
1090
|
-
return this.state?.progress;
|
|
1091
|
-
}
|
|
1092
|
-
|
|
1093
|
-
get active() {
|
|
1094
|
-
return this.state?.active;
|
|
1095
|
-
}
|
|
1096
|
-
|
|
1097
|
-
get craftingItem() {
|
|
1098
|
-
const state = this.state;
|
|
1099
|
-
if (!state || state.craftingItemId == null) return null;
|
|
1100
|
-
return {itemId: state.craftingItemId, itemName: state.craftingItemName, count: state.craftingCount};
|
|
1101
|
-
}
|
|
1102
|
-
|
|
1103
|
-
panel() {
|
|
1104
|
-
return this.client.puiPanels.get(this.id) || null;
|
|
1105
|
-
}
|
|
1106
|
-
|
|
1107
|
-
add(itemId, count = 1, index = -1) {
|
|
1108
|
-
return this.client.craftAdd(itemId, count, index);
|
|
1109
|
-
}
|
|
1110
|
-
|
|
1111
|
-
sub(itemId, count = 1, index = 0) {
|
|
1112
|
-
return this.client.craftSub(itemId, count, index);
|
|
1113
|
-
}
|
|
1114
|
-
|
|
1115
|
-
clearQueue() {
|
|
1116
|
-
return this.client.craftClearQueue();
|
|
1117
|
-
}
|
|
1118
|
-
|
|
1119
|
-
toggleRepeat() {
|
|
1120
|
-
return this.client.craftToggleRepeat();
|
|
1121
|
-
}
|
|
1122
|
-
|
|
1123
|
-
lockResource(row) {
|
|
1124
|
-
return this.client.fabricatorLockResource(row);
|
|
1125
|
-
}
|
|
1126
|
-
|
|
1127
|
-
unlockResource(row) {
|
|
1128
|
-
return this.client.fabricatorUnlockResource(row);
|
|
1129
|
-
}
|
|
1130
|
-
|
|
1131
|
-
eject(row) {
|
|
1132
|
-
return this.client.fabricatorEject(row);
|
|
1133
|
-
}
|
|
1134
|
-
}
|
|
1135
|
-
|
|
1136
|
-
export class CommsStationHandle extends MachineHandle {
|
|
1137
|
-
get state() {
|
|
1138
|
-
return summaryForEntity(this.client, this.scope, this.id)?.contents?.commsStation || null;
|
|
1139
|
-
}
|
|
1140
|
-
|
|
1141
|
-
panel() {
|
|
1142
|
-
return this.client.commsPanels.get(this.id) || null;
|
|
1143
|
-
}
|
|
1144
|
-
|
|
1145
|
-
sendMessage(message = "") {
|
|
1146
|
-
return this.client.sendCommsMessage(message);
|
|
1147
|
-
}
|
|
1148
|
-
}
|
|
1149
|
-
|
|
1150
|
-
export class SignHandle extends MachineHandle {
|
|
1151
|
-
get state() {
|
|
1152
|
-
return summaryForEntity(this.client, this.scope, this.id)?.contents?.sign || null;
|
|
1153
|
-
}
|
|
1154
|
-
|
|
1155
|
-
setText(text = "", mode = 0) {
|
|
1156
|
-
return this.client.setSignText(text, mode);
|
|
1157
|
-
}
|
|
1158
|
-
|
|
1159
|
-
get text() {
|
|
1160
|
-
return this.state?.text;
|
|
1161
|
-
}
|
|
1162
|
-
|
|
1163
|
-
get mode() {
|
|
1164
|
-
return this.state?.mode;
|
|
1165
|
-
}
|
|
1166
|
-
}
|
|
1167
|
-
|
|
1168
|
-
export class GeneratorHandle extends MachineHandle {
|
|
1169
|
-
get state() {
|
|
1170
|
-
return summaryForEntity(this.client, this.scope, this.id)?.contents?.shieldGenerator || null;
|
|
1171
|
-
}
|
|
1172
|
-
|
|
1173
|
-
solvePuzzle(solution) {
|
|
1174
|
-
return this.client.solveGeneratorPuzzle(this.id, solution);
|
|
1175
|
-
}
|
|
1176
|
-
}
|
|
1177
|
-
|
|
1178
|
-
export class CargoHatchHandle extends MachineHandle {
|
|
1179
|
-
get state() {
|
|
1180
|
-
return summaryForEntity(this.client, this.scope, this.id)?.contents?.cargoHatch || null;
|
|
1181
|
-
}
|
|
1182
|
-
|
|
1183
|
-
get openFraction() {
|
|
1184
|
-
return this.state?.openFraction;
|
|
1185
|
-
}
|
|
1186
|
-
|
|
1187
|
-
configure(config = {}) {
|
|
1188
|
-
return this.client.sendCargoHatchFullConfig(this.id, config);
|
|
1189
|
-
}
|
|
1190
|
-
|
|
1191
|
-
copy(config = {}) {
|
|
1192
|
-
return this.client.copyCargoHatchConfig(this.id, config);
|
|
1193
|
-
}
|
|
1194
|
-
|
|
1195
|
-
paste(config = {}) {
|
|
1196
|
-
return this.client.pasteCargoHatchConfig(this.id, config);
|
|
1197
|
-
}
|
|
1198
|
-
|
|
1199
|
-
setFilterMode(filterMode) {
|
|
1200
|
-
return this.client.setCargoHatchFilterMode(this.id, filterMode);
|
|
1201
|
-
}
|
|
1202
|
-
|
|
1203
|
-
setFilterItems(filterSlots = []) {
|
|
1204
|
-
return this.client.setCargoHatchFilterItems(this.id, filterSlots);
|
|
1205
|
-
}
|
|
1206
|
-
}
|
|
1207
|
-
|
|
1208
|
-
export class CannonHandle extends MachineHandle {
|
|
1209
|
-
get state() {
|
|
1210
|
-
return summaryForEntity(this.client, this.scope, this.id)?.contents?.cannon || null;
|
|
1211
|
-
}
|
|
1212
|
-
}
|
|
1213
|
-
|
|
1214
|
-
export class ThrusterHandle extends MachineHandle {
|
|
1215
|
-
get state() {
|
|
1216
|
-
return summaryForEntity(this.client, this.scope, this.id)?.contents?.thruster || null;
|
|
1217
|
-
}
|
|
1218
|
-
}
|
|
1219
|
-
|
|
1220
|
-
export class HelmHandle extends MachineHandle {
|
|
1221
|
-
get state() {
|
|
1222
|
-
return summaryForEntity(this.client, this.scope, this.id)?.contents?.helm || null;
|
|
1223
|
-
}
|
|
1224
|
-
|
|
1225
|
-
get occupied() {
|
|
1226
|
-
return this.state?.occupied;
|
|
1227
|
-
}
|
|
1228
|
-
}
|
|
1229
|
-
|
|
1230
|
-
export class DoorHandle extends MachineHandle {
|
|
1231
|
-
get state() {
|
|
1232
|
-
return summaryForEntity(this.client, this.scope, this.id)?.contents?.door || null;
|
|
1233
|
-
}
|
|
1234
|
-
|
|
1235
|
-
get rank() {
|
|
1236
|
-
return this.state?.rank;
|
|
1237
|
-
}
|
|
1238
|
-
|
|
1239
|
-
get open() {
|
|
1240
|
-
return this.state?.open;
|
|
1241
|
-
}
|
|
1242
|
-
}
|
|
1243
|
-
|
|
1244
|
-
export class SpawnPointHandle extends MachineHandle {
|
|
1245
|
-
get state() {
|
|
1246
|
-
return summaryForEntity(this.client, this.scope, this.id)?.contents?.spawnPoint || null;
|
|
1247
|
-
}
|
|
1248
|
-
|
|
1249
|
-
get rank() {
|
|
1250
|
-
return this.state?.rank;
|
|
1251
|
-
}
|
|
1252
|
-
}
|
|
1253
|
-
|
|
1254
|
-
export class ShieldProjectorHandle extends MachineHandle {
|
|
1255
|
-
get state() {
|
|
1256
|
-
return summaryForEntity(this.client, this.scope, this.id)?.contents?.shieldProjector || null;
|
|
1257
|
-
}
|
|
1258
|
-
|
|
1259
|
-
get active() {
|
|
1260
|
-
return this.state?.active;
|
|
1261
|
-
}
|
|
1262
|
-
}
|
|
1263
|
-
|
|
1264
|
-
export class FluidTankHandle extends MachineHandle {
|
|
1265
|
-
get state() {
|
|
1266
|
-
return summaryForEntity(this.client, this.scope, this.id)?.contents?.fluidTank || null;
|
|
1267
|
-
}
|
|
1268
|
-
|
|
1269
|
-
get amount() {
|
|
1270
|
-
return this.state?.amount;
|
|
1271
|
-
}
|
|
1272
|
-
}
|
|
1273
|
-
|
|
1274
|
-
export class ExpandoBoxHandle extends MachineHandle {
|
|
1275
|
-
get state() {
|
|
1276
|
-
return summaryForEntity(this.client, this.scope, this.id)?.contents?.expandoBox || null;
|
|
1277
|
-
}
|
|
1278
|
-
|
|
1279
|
-
get item() {
|
|
1280
|
-
return this.state?.itemId;
|
|
1281
|
-
}
|
|
1282
|
-
|
|
1283
|
-
get count() {
|
|
1284
|
-
return this.state?.count;
|
|
1285
|
-
}
|
|
1286
|
-
}
|
|
1287
|
-
|
|
1288
|
-
export class CargoEjectorHandle extends MachineHandle {
|
|
1289
|
-
get state() {
|
|
1290
|
-
return summaryForEntity(this.client, this.scope, this.id)?.contents?.cargoEjector || null;
|
|
1291
|
-
}
|
|
1292
|
-
|
|
1293
|
-
get progress() {
|
|
1294
|
-
return this.state?.progress;
|
|
1295
|
-
}
|
|
1296
|
-
|
|
1297
|
-
get active() {
|
|
1298
|
-
return this.state?.active;
|
|
1299
|
-
}
|
|
1300
|
-
|
|
1301
|
-
setDirection(direction) {
|
|
1302
|
-
return this.client.setCargoEjectorDirection(this.id, direction);
|
|
1303
|
-
}
|
|
1304
|
-
|
|
1305
|
-
copy(direction = "right") {
|
|
1306
|
-
return this.client.copyCargoEjectorConfig(this.id, direction);
|
|
1307
|
-
}
|
|
1308
|
-
|
|
1309
|
-
paste(direction = "right") {
|
|
1310
|
-
return this.client.pasteCargoEjectorConfig(this.id, direction);
|
|
1311
|
-
}
|
|
1312
|
-
}
|
|
1313
|
-
|
|
1314
|
-
export class ShipHandle {
|
|
1315
|
-
constructor(client, summary) {
|
|
1316
|
-
this.client = client;
|
|
1317
|
-
this.summary = summary;
|
|
1318
|
-
}
|
|
1319
|
-
|
|
1320
|
-
get entity() {
|
|
1321
|
-
return this.summary.entity;
|
|
1322
|
-
}
|
|
1323
|
-
|
|
1324
|
-
get name() {
|
|
1325
|
-
return this.summary.name;
|
|
1326
|
-
}
|
|
1327
|
-
|
|
1328
|
-
get hexCode() {
|
|
1329
|
-
return this.summary.hexCode;
|
|
1330
|
-
}
|
|
1331
|
-
|
|
1332
|
-
get distance() {
|
|
1333
|
-
return this.summary.distance;
|
|
1334
|
-
}
|
|
1335
|
-
|
|
1336
|
-
get worldId() {
|
|
1337
|
-
return this.summary.worldId;
|
|
1338
|
-
}
|
|
1339
|
-
|
|
1340
|
-
get hasWorldData() {
|
|
1341
|
-
return this.summary.hasWorldData;
|
|
1342
|
-
}
|
|
1343
|
-
|
|
1344
|
-
world() {
|
|
1345
|
-
return this.worldId == null ? null : this.client.world(this.worldId);
|
|
1346
|
-
}
|
|
1347
|
-
|
|
1348
|
-
snapshot() {
|
|
1349
|
-
return this.summary;
|
|
1350
|
-
}
|
|
1351
|
-
}
|
|
1352
|
-
|
|
1353
|
-
const ENTITY_COMPONENT_ALIASES = new Map([
|
|
1354
|
-
["hoveroutline", "hoverOutline"],
|
|
1355
|
-
["outline", "hoverOutline"],
|
|
1356
|
-
["itemholder", "itemHolder"],
|
|
1357
|
-
["itemcrate", "itemCrate"],
|
|
1358
|
-
["expandobox", "expandoBox"],
|
|
1359
|
-
["expando", "expandoBox"],
|
|
1360
|
-
["blueprintpreview", "blueprintPreview"],
|
|
1361
|
-
["blueprint", "blueprintPreview"],
|
|
1362
|
-
["pusherbeam", "pusherBeam"],
|
|
1363
|
-
["beam", "pusherBeam"],
|
|
1364
|
-
["cargohatch", "cargoHatch"],
|
|
1365
|
-
["cargoejector", "cargoEjector"],
|
|
1366
|
-
["ejector", "cargoEjector"],
|
|
1367
|
-
["navigationunit", "navigationUnit"],
|
|
1368
|
-
["nav", "navigationUnit"],
|
|
1369
|
-
["navunit", "navigationUnit"],
|
|
1370
|
-
["commsstation", "commsStation"],
|
|
1371
|
-
["fluidtank", "fluidTank"],
|
|
1372
|
-
["shieldgenerator", "shieldGenerator"],
|
|
1373
|
-
["generator", "shieldGenerator"],
|
|
1374
|
-
["shieldprojector", "shieldProjector"],
|
|
1375
|
-
["shipcontrol", "shipControl"],
|
|
1376
|
-
["spawnpoint", "spawnPoint"],
|
|
1377
|
-
["shipsize", "shipSize"],
|
|
1378
|
-
["mapmarker", "mapMarker"],
|
|
1379
|
-
["marker", "mapMarker"],
|
|
1380
|
-
["dockingspring", "dockingSpring"],
|
|
1381
|
-
["hugethruster", "hugeThruster"]
|
|
1382
|
-
]);
|
|
1383
|
-
|
|
1384
|
-
const MACHINE_COMPONENTS = [
|
|
1385
|
-
"loader",
|
|
1386
|
-
"pusher",
|
|
1387
|
-
"launcher",
|
|
1388
|
-
"navigationUnit",
|
|
1389
|
-
"fabricator",
|
|
1390
|
-
"cargoEjector",
|
|
1391
|
-
"cannon",
|
|
1392
|
-
"thruster",
|
|
1393
|
-
"cargoHatch",
|
|
1394
|
-
"commsStation",
|
|
1395
|
-
"fluidTank",
|
|
1396
|
-
"shieldGenerator",
|
|
1397
|
-
"shieldProjector",
|
|
1398
|
-
"helm",
|
|
1399
|
-
"sign",
|
|
1400
|
-
"spawnPoint",
|
|
1401
|
-
"door",
|
|
1402
|
-
"expandoBox"
|
|
1403
|
-
];
|
|
1404
|
-
|
|
1405
|
-
const ENTITY_FEATURES = [
|
|
1406
|
-
"health",
|
|
1407
|
-
"position",
|
|
1408
|
-
"outline",
|
|
1409
|
-
"inventory",
|
|
1410
|
-
"item",
|
|
1411
|
-
"filter",
|
|
1412
|
-
"filterMode",
|
|
1413
|
-
"filterSlots",
|
|
1414
|
-
"filterInventory",
|
|
1415
|
-
"beam",
|
|
1416
|
-
"occupied",
|
|
1417
|
-
"loaderConfig",
|
|
1418
|
-
"pusherConfig",
|
|
1419
|
-
"launcherConfig",
|
|
1420
|
-
"navigationConfig",
|
|
1421
|
-
"fabricatorQueue",
|
|
1422
|
-
"progress"
|
|
1423
|
-
];
|
|
1424
|
-
|
|
1425
|
-
function normalizeEntityKey(value) {
|
|
1426
|
-
return String(value ?? "").toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
1427
|
-
}
|
|
1428
|
-
|
|
1429
|
-
function clonePlain(value) {
|
|
1430
|
-
if (value == null) return value;
|
|
1431
|
-
if (typeof structuredClone === "function") return structuredClone(value);
|
|
1432
|
-
return JSON.parse(JSON.stringify(value));
|
|
1433
|
-
}
|
|
1434
|
-
|
|
1435
|
-
function deepFreeze(value) {
|
|
1436
|
-
if (!value || typeof value !== "object" || Object.isFrozen(value)) return value;
|
|
1437
|
-
Object.freeze(value);
|
|
1438
|
-
for (const item of Object.values(value)) deepFreeze(item);
|
|
1439
|
-
return value;
|
|
1440
|
-
}
|
|
1441
|
-
|
|
1442
|
-
function componentFor(contents, key) {
|
|
1443
|
-
if (!contents) return null;
|
|
1444
|
-
const component = ENTITY_COMPONENT_ALIASES.get(key) || key;
|
|
1445
|
-
return contents[component] ?? null;
|
|
1446
|
-
}
|
|
1447
|
-
|
|
1448
|
-
function entityMachineType(contents) {
|
|
1449
|
-
if (!contents) return null;
|
|
1450
|
-
return MACHINE_COMPONENTS.find((component) => contents[component]) || null;
|
|
1451
|
-
}
|
|
1452
|
-
|
|
1453
|
-
function firstFeatureSource(contents, names) {
|
|
1454
|
-
if (!contents) return null;
|
|
1455
|
-
for (const name of names) {
|
|
1456
|
-
const source = contents[name];
|
|
1457
|
-
if (source != null) return source;
|
|
1458
|
-
}
|
|
1459
|
-
return null;
|
|
1460
|
-
}
|
|
1461
|
-
|
|
1462
|
-
function sourceWithProperty(contents, names, property) {
|
|
1463
|
-
if (!contents) return null;
|
|
1464
|
-
for (const name of names) {
|
|
1465
|
-
const source = contents[name];
|
|
1466
|
-
if (source && source[property] != null) return source;
|
|
1467
|
-
}
|
|
1468
|
-
return null;
|
|
1469
|
-
}
|
|
1470
|
-
|
|
1471
|
-
function entityPublicType(summary, contents) {
|
|
1472
|
-
const machine = entityMachineType(contents);
|
|
1473
|
-
if (machine) return machine;
|
|
1474
|
-
if (contents?.player || summary?.category === "player") return "player";
|
|
1475
|
-
if (contents?.shipControl || summary?.category === "ship_control") return "ship";
|
|
1476
|
-
if (contents?.bot) return "bot";
|
|
1477
|
-
if (summary?.category === "loose_item" || contents?.itemCrate || contents?.itemHolder) return "looseItem";
|
|
1478
|
-
if (contents?.mapMarker) return "mapMarker";
|
|
1479
|
-
if (contents?.dockingSpring) return "dockingSpring";
|
|
1480
|
-
if (contents?.hugeThruster) return "hugeThruster";
|
|
1481
|
-
if (contents?.blueprintPreview) return "blueprintPreview";
|
|
1482
|
-
return "unknown";
|
|
1483
|
-
}
|
|
1484
|
-
|
|
1485
|
-
function entityFeatures(summary, contents) {
|
|
1486
|
-
return ENTITY_FEATURES.filter((feature) => entityFeature(summary, contents, feature) != null);
|
|
1487
|
-
}
|
|
1488
|
-
|
|
1489
|
-
function entityFeature(summary, contents, feature) {
|
|
1490
|
-
const key = normalizeEntityKey(feature);
|
|
1491
|
-
if (!key) return null;
|
|
1492
|
-
if (key === "position" || key === "transform") return summary?.position || summary?.transform || null;
|
|
1493
|
-
if (!contents) return null;
|
|
1494
|
-
const component = componentFor(contents, key);
|
|
1495
|
-
if (component != null) return component;
|
|
1496
|
-
if (key === "machine") return firstFeatureSource(contents, MACHINE_COMPONENTS);
|
|
1497
|
-
if (key === "inventory") return firstFeatureSource(contents, ["itemHolder", "expandoBox"]);
|
|
1498
|
-
if (key === "item") return firstFeatureSource(contents, ["itemCrate", "itemHolder", "expandoBox"]);
|
|
1499
|
-
if (key === "filter") return firstFeatureSource(contents, ["loader", "pusher", "cargoHatch"]);
|
|
1500
|
-
if (key === "filtermode") {
|
|
1501
|
-
const filterModeSource = sourceWithProperty(contents, ["loader", "pusher", "cargoHatch"], "filterMode");
|
|
1502
|
-
if (filterModeSource) return filterModeSource.filterMode;
|
|
1503
|
-
return sourceWithProperty(contents, ["pusher"], "filteredMode")?.filteredMode ?? null;
|
|
1504
|
-
}
|
|
1505
|
-
if (key === "filterslots") return sourceWithProperty(contents, ["loader", "pusher", "cargoHatch"], "filterSlots")?.filterSlots ?? null;
|
|
1506
|
-
if (key === "filterinventory") return contents.pusher?.filterInventory ?? null;
|
|
1507
|
-
if (key === "beam") return contents.pusherBeam ?? null;
|
|
1508
|
-
if (key === "outline") return contents.hoverOutline ?? null;
|
|
1509
|
-
if (key === "occupied") return sourceWithProperty(contents, ["helm", "commsStation"], "occupied")?.occupied ?? null;
|
|
1510
|
-
if (key === "health") return contents.health ?? null;
|
|
1511
|
-
if (key === "loaderconfig") return contents.loader ?? null;
|
|
1512
|
-
if (key === "pusherconfig") return contents.pusher ?? null;
|
|
1513
|
-
if (key === "launcherconfig") return contents.launcher ?? null;
|
|
1514
|
-
if (key === "navigationconfig") return contents.navigationUnit ?? null;
|
|
1515
|
-
if (key === "fabricatorqueue") return contents.fabricator?.rows ?? null;
|
|
1516
|
-
if (key === "progress") return contents.fabricator?.progress ?? contents.cargoEjector?.progress ?? contents.loader?.progress ?? contents.cargoHatch?.openFraction ?? null;
|
|
1517
|
-
return null;
|
|
1518
|
-
}
|
|
1519
|
-
|
|
1520
|
-
function entityDomainHandle(client, entity, scope, type, snapshot = null) {
|
|
1521
|
-
const key = normalizeEntityKey(type);
|
|
1522
|
-
const state = snapshot || new EntityHandle(client, entity, scope).snapshot();
|
|
1523
|
-
if (!state) return null;
|
|
1524
|
-
const constructors = new Map([
|
|
1525
|
-
["loader", LoaderHandle],
|
|
1526
|
-
["pusher", PusherHandle],
|
|
1527
|
-
["launcher", LauncherHandle],
|
|
1528
|
-
["navigationunit", NavigationUnitHandle],
|
|
1529
|
-
["nav", NavigationUnitHandle],
|
|
1530
|
-
["navunit", NavigationUnitHandle],
|
|
1531
|
-
["fabricator", FabricatorHandle],
|
|
1532
|
-
["cargoejector", CargoEjectorHandle],
|
|
1533
|
-
["ejector", CargoEjectorHandle],
|
|
1534
|
-
["cannon", CannonHandle],
|
|
1535
|
-
["thruster", ThrusterHandle],
|
|
1536
|
-
["commsstation", CommsStationHandle],
|
|
1537
|
-
["sign", SignHandle],
|
|
1538
|
-
["shieldgenerator", GeneratorHandle],
|
|
1539
|
-
["generator", GeneratorHandle],
|
|
1540
|
-
["cargohatch", CargoHatchHandle],
|
|
1541
|
-
["shieldprojector", ShieldProjectorHandle],
|
|
1542
|
-
["fluidtank", FluidTankHandle],
|
|
1543
|
-
["helm", HelmHandle],
|
|
1544
|
-
["spawnpoint", SpawnPointHandle],
|
|
1545
|
-
["door", DoorHandle],
|
|
1546
|
-
["expandobox", ExpandoBoxHandle],
|
|
1547
|
-
["expando", ExpandoBoxHandle]
|
|
1548
|
-
]);
|
|
1549
|
-
const Handle = constructors.get(key);
|
|
1550
|
-
return Handle && state.is(key) ? new Handle(client, entity, scope) : null;
|
|
1551
|
-
}
|
|
1552
|
-
|
|
1553
|
-
function worldStateFor(client, scope = "ship") {
|
|
1554
|
-
if (scope == null || scope === "ship" || scope === "current") return client.worlds.shipWorld();
|
|
1555
|
-
if (scope === "overworld") return client.worlds.overworld();
|
|
1556
|
-
return client.worlds.worlds.get(Number(scope)) || null;
|
|
1557
|
-
}
|
|
1558
|
-
|
|
1559
|
-
export function summariesFor(client, scope = "ship") {
|
|
1560
|
-
return worldStateFor(client, scope)?.entities() || [];
|
|
1561
|
-
}
|
|
1562
|
-
|
|
1563
|
-
function summaryForEntity(client, scope, entity) {
|
|
1564
|
-
return worldStateFor(client, scope)?.entity(entity) || null;
|
|
1565
|
-
}
|
|
1566
|
-
|
|
1567
|
-
function entityIdOf(value) {
|
|
1568
|
-
if (value && typeof value === "object") return Number(value.entity ?? value.id);
|
|
1569
|
-
return Number(value);
|
|
1570
|
-
}
|
|
1571
|
-
|
|
1572
|
-
function inventorySlotIndexOf(value, name = "slot") {
|
|
1573
|
-
if (value && typeof value === "object") {
|
|
1574
|
-
if (value.index != null) return normalizeInventorySlotIndex(value.index, name);
|
|
1575
|
-
if (value.entity != null || value.id != null) throw new TypeError(`${name} must be an inventory slot, slot snapshot, equipment slot, or index`);
|
|
1576
|
-
}
|
|
1577
|
-
if (typeof value === "string") return normalizeEquipmentSlot(value);
|
|
1578
|
-
return normalizeInventorySlotIndex(value, name);
|
|
1579
|
-
}
|
|
1580
|
-
|
|
1581
|
-
function normalizeInventorySlotIndex(value, name = "slot") {
|
|
1582
|
-
const number = Number(value);
|
|
1583
|
-
if (!Number.isInteger(number) || number < 0) throw new RangeError(`${name} must be a non-negative inventory slot index`);
|
|
1584
|
-
return number;
|
|
1585
|
-
}
|
|
1586
|
-
|
|
1587
|
-
export function currentPlayerSummary(client, scope = "current") {
|
|
1588
|
-
const sid = Number(client?.sid);
|
|
1589
|
-
if (!Number.isFinite(sid)) return null;
|
|
1590
|
-
return worldStateFor(client, scope)?.model.players().find((player) => player.entity === sid) || null;
|
|
1591
|
-
}
|
|
1592
|
-
|
|
1593
|
-
function currentPlayerRank(client) {
|
|
1594
|
-
const player = currentPlayerSummary(client);
|
|
1595
|
-
const subrank = client?.captainSubrank?.subrank ?? null;
|
|
1596
|
-
const shipRank = player?.shipRank ?? null;
|
|
1597
|
-
return {
|
|
1598
|
-
shipRank,
|
|
1599
|
-
subrank: shipRank === "captain" ? subrank : null,
|
|
1600
|
-
isCaptain: shipRank === "captain",
|
|
1601
|
-
patronTier: player?.patronTier ?? null
|
|
1602
|
-
};
|
|
1603
|
-
}
|
|
1604
|
-
|
|
1605
|
-
function normalizeEquipArguments(equipmentSlot, options = {}, command = {}) {
|
|
1606
|
-
if (equipmentSlot && typeof equipmentSlot === "object") {
|
|
1607
|
-
return {equipmentSlot: null, split: Boolean(equipmentSlot.split), command: options || {}};
|
|
1608
|
-
}
|
|
1609
|
-
return {equipmentSlot, split: Boolean(options?.split), command};
|
|
1610
|
-
}
|
|
1611
|
-
|
|
1612
|
-
function inferEquipmentSlotForInventorySource(domain, source) {
|
|
1613
|
-
const handle = source instanceof InventorySlotHandle ? source : domain.slot(source);
|
|
1614
|
-
if (!handle.exists() || handle.itemId == null) throw new RangeError(`inventory slot ${handle.index} is empty; pass equipmentSlot explicitly`);
|
|
1615
|
-
const equipmentSlot = itemEquipmentSlotFromId(handle.itemId);
|
|
1616
|
-
if (!equipmentSlot) {
|
|
1617
|
-
const label = handle.itemName ? ` (${handle.itemName})` : "";
|
|
1618
|
-
throw new RangeError(`item ${handle.itemId}${label} does not map to an equipment slot; pass equipmentSlot explicitly`);
|
|
1619
|
-
}
|
|
1620
|
-
return equipmentSlot;
|
|
1621
|
-
}
|
|
1622
|
-
|
|
1623
|
-
function inventoryHandlesForArea(domain, area = "all") {
|
|
1624
|
-
switch (area) {
|
|
1625
|
-
case "all":
|
|
1626
|
-
return domain.allSlots();
|
|
1627
|
-
case "hotbar":
|
|
1628
|
-
return domain.hotbarSlots();
|
|
1629
|
-
case "equipment":
|
|
1630
|
-
return Object.values(domain.equipmentSlots());
|
|
1631
|
-
default:
|
|
1632
|
-
throw new RangeError(`Unknown inventory area: ${area}`);
|
|
1633
|
-
}
|
|
1634
|
-
}
|
|
1635
|
-
|
|
1636
|
-
export const WrenchMode = Object.freeze({
|
|
1637
|
-
DropAllItems: "drop-all-items",
|
|
1638
|
-
GrabPrimaryItems: "grab-primary-items",
|
|
1639
|
-
GrabAllItems: "grab-all-items"
|
|
1640
|
-
});
|
|
1641
|
-
|
|
1642
|
-
const WRENCH_MODES = new Map([
|
|
1643
|
-
[0, WrenchMode.DropAllItems],
|
|
1644
|
-
[1, WrenchMode.GrabPrimaryItems],
|
|
1645
|
-
[2, WrenchMode.GrabAllItems]
|
|
1646
|
-
]);
|
|
1647
|
-
|
|
1648
|
-
const WRENCH_MODE_VALUES = new Map([...WRENCH_MODES].map(([value, name]) => [name, value]));
|
|
1649
|
-
|
|
1650
|
-
export const TurretMode = Object.freeze({
|
|
1651
|
-
ContinuousFire: "continuous-fire",
|
|
1652
|
-
VolleyFire: "volley-fire"
|
|
1653
|
-
});
|
|
1654
|
-
|
|
1655
|
-
const TURRET_MODES = new Map([
|
|
1656
|
-
[0, TurretMode.ContinuousFire],
|
|
1657
|
-
[1, TurretMode.VolleyFire]
|
|
1658
|
-
]);
|
|
1659
|
-
|
|
1660
|
-
const TURRET_MODE_VALUES = new Map([...TURRET_MODES].map(([value, name]) => [name, value]));
|
|
1661
|
-
|
|
1662
|
-
function wrenchModeName(value) {
|
|
1663
|
-
return WRENCH_MODES.get(value) ?? null;
|
|
1664
|
-
}
|
|
1665
|
-
|
|
1666
|
-
function turretModeName(value) {
|
|
1667
|
-
return TURRET_MODES.get(value) ?? null;
|
|
1668
|
-
}
|
|
1669
|
-
|
|
1670
|
-
export function normalizeWrenchMode(value) {
|
|
1671
|
-
const normalized = WRENCH_MODE_VALUES.get(value);
|
|
1672
|
-
if (normalized == null || !WRENCH_MODES.has(normalized)) {
|
|
1673
|
-
throw new RangeError(`Unknown wrench mode: ${value}`);
|
|
1674
|
-
}
|
|
1675
|
-
return normalized;
|
|
1676
|
-
}
|
|
1677
|
-
|
|
1678
|
-
export function normalizeTurretMode(value) {
|
|
1679
|
-
const normalized = TURRET_MODE_VALUES.get(value);
|
|
1680
|
-
if (normalized == null || !TURRET_MODES.has(normalized)) {
|
|
1681
|
-
throw new RangeError(`Unknown turret mode: ${value}`);
|
|
1682
|
-
}
|
|
1683
|
-
return normalized;
|
|
1684
|
-
}
|
|
1685
|
-
|
|
1686
|
-
export function normalizePositiveFinite(value, name) {
|
|
1687
|
-
const number = Number(value);
|
|
1688
|
-
if (!Number.isFinite(number) || number <= 0) throw new RangeError(`${name} must be a positive finite number`);
|
|
1689
|
-
return number;
|
|
1690
|
-
}
|
|
1691
|
-
|
|
1692
|
-
export function normalizePositiveInteger(value, name) {
|
|
1693
|
-
const number = Number(value);
|
|
1694
|
-
if (!Number.isInteger(number) || number <= 0) throw new RangeError(`${name} must be a positive integer`);
|
|
1695
|
-
return number;
|
|
1696
|
-
}
|
|
1697
|
-
|
|
1698
|
-
export function normalizeDegrees(value) {
|
|
1699
|
-
const number = Number(value);
|
|
1700
|
-
if (!Number.isFinite(number)) throw new RangeError(`angle must be a finite number`);
|
|
1701
|
-
return ((Math.round(number) % 360) + 360) % 360;
|
|
1702
|
-
}
|
|
1703
|
-
|
|
1704
|
-
export function normalizeLauncherPower(value) {
|
|
1705
|
-
const number = Number(value);
|
|
1706
|
-
if (!Number.isInteger(number) || number < 0 || number > 30) {
|
|
1707
|
-
throw new RangeError(`launcher power must be an integer between 0 and 30`);
|
|
1708
|
-
}
|
|
1709
|
-
return number;
|
|
1710
|
-
}
|
|
1711
|
-
|
|
1712
|
-
export function normalizeScannerResultPacket(packet) {
|
|
1713
|
-
const manifest = packet?.manifest && typeof packet.manifest === "object" ? packet.manifest : {};
|
|
1714
|
-
const hasMaterials = manifest.materials && typeof manifest.materials === "object";
|
|
1715
|
-
const hasManifest = (
|
|
1716
|
-
(manifest.blocks && typeof manifest.blocks === "object") ||
|
|
1717
|
-
(manifest.objects && typeof manifest.objects === "object") ||
|
|
1718
|
-
(manifest.inventories && typeof manifest.inventories === "object")
|
|
1719
|
-
);
|
|
1720
|
-
return {
|
|
1721
|
-
kind: hasMaterials ? "bom" : hasManifest ? "manifest" : "unknown",
|
|
1722
|
-
sid: packet?.sid ?? null,
|
|
1723
|
-
shipHex: typeof manifest.ship_hex === "string" ? manifest.ship_hex : null,
|
|
1724
|
-
shipName: typeof manifest.ship_name === "string" ? manifest.ship_name : null,
|
|
1725
|
-
blocks: copyCountMap(manifest.blocks),
|
|
1726
|
-
objects: copyCountMap(manifest.objects),
|
|
1727
|
-
inventories: copyCountMap(manifest.inventories),
|
|
1728
|
-
materials: copyCountMap(manifest.materials)
|
|
1729
|
-
};
|
|
1730
|
-
}
|
|
1731
|
-
|
|
1732
|
-
function copyCountMap(value) {
|
|
1733
|
-
if (!value || typeof value !== "object") return null;
|
|
1734
|
-
return Object.fromEntries(
|
|
1735
|
-
Object.entries(value)
|
|
1736
|
-
.filter(([, count]) => typeof count === "number")
|
|
1737
|
-
.map(([itemId, count]) => [String(itemId), count])
|
|
1738
|
-
);
|
|
1739
|
-
}
|
|
1740
|
-
|
|
1741
|
-
export function emptyMachineSummary() {
|
|
1742
|
-
return {
|
|
1743
|
-
itemHolders: [],
|
|
1744
|
-
health: [],
|
|
1745
|
-
fabricators: [],
|
|
1746
|
-
cargoEjectors: [],
|
|
1747
|
-
cannons: [],
|
|
1748
|
-
thrusters: [],
|
|
1749
|
-
pushers: [],
|
|
1750
|
-
pusherBeams: [],
|
|
1751
|
-
launchers: [],
|
|
1752
|
-
loaders: [],
|
|
1753
|
-
cargoHatches: [],
|
|
1754
|
-
navigationUnits: [],
|
|
1755
|
-
commsStations: [],
|
|
1756
|
-
fluidTanks: [],
|
|
1757
|
-
shieldGenerators: [],
|
|
1758
|
-
shieldProjectors: [],
|
|
1759
|
-
helms: [],
|
|
1760
|
-
signs: [],
|
|
1761
|
-
spawnPoints: [],
|
|
1762
|
-
doors: [],
|
|
1763
|
-
expandoBoxes: []
|
|
1764
|
-
};
|
|
1765
|
-
}
|
|
1766
|
-
|
|
1767
|
-
export function normalizeShipReadOptions(options) {
|
|
1768
|
-
if (options == null || options === true) options = {};
|
|
1769
|
-
return {
|
|
1770
|
-
includeWorld: options.includeWorld !== false,
|
|
1771
|
-
includeTiles: Boolean(options.includeTiles),
|
|
1772
|
-
includeModel: Boolean(options.includeModel),
|
|
1773
|
-
includeBlocks: Boolean(options.includeBlocks),
|
|
1774
|
-
sort: options.sort ?? null
|
|
1775
|
-
};
|
|
1776
|
-
}
|
|
1777
|
-
|
|
1778
|
-
export function shipReadSummary(entity, options, worlds, currentEntity = undefined) {
|
|
1779
|
-
const control = entity.contents.shipControl;
|
|
1780
|
-
const worldState = options.includeWorld && control.shipWorldId != null
|
|
1781
|
-
? worlds.worlds.get(Number(control.shipWorldId)) || null
|
|
1782
|
-
: null;
|
|
1783
|
-
const world = worldState ? worldState.snapshot({
|
|
1784
|
-
includeTiles: options.includeTiles,
|
|
1785
|
-
includeModel: options.includeModel,
|
|
1786
|
-
includeBlocks: options.includeBlocks
|
|
1787
|
-
}) : null;
|
|
1788
|
-
const current = currentEntity === undefined ? worlds.currentShipEntity() : currentEntity;
|
|
1789
|
-
const distance = distanceBetween(entity.transform, current?.transform);
|
|
1790
|
-
return {
|
|
1791
|
-
entity: entity.entity,
|
|
1792
|
-
name: control.name,
|
|
1793
|
-
hexCode: control.hexCode,
|
|
1794
|
-
color: control.color,
|
|
1795
|
-
colorCss: control.colorCss,
|
|
1796
|
-
position: entity.transform ? {x: entity.transform.x, y: entity.transform.y, rot: entity.transform.rot} : null,
|
|
1797
|
-
distance,
|
|
1798
|
-
footprint: entity.footprint,
|
|
1799
|
-
label: entity.label,
|
|
1800
|
-
kind: entity.kind,
|
|
1801
|
-
thrust: {
|
|
1802
|
-
x: control.thrustX,
|
|
1803
|
-
y: control.thrustY
|
|
1804
|
-
},
|
|
1805
|
-
shield: control.shield,
|
|
1806
|
-
warp: control.warp,
|
|
1807
|
-
worldId: control.shipWorldId,
|
|
1808
|
-
hasWorldData: Boolean(world),
|
|
1809
|
-
world,
|
|
1810
|
-
control,
|
|
1811
|
-
entitySummary: entity
|
|
1812
|
-
};
|
|
1813
|
-
}
|
|
1814
|
-
|
|
1815
|
-
function distanceBetween(a, b) {
|
|
1816
|
-
if (!a || !b || typeof a.x !== "number" || typeof a.y !== "number" || typeof b.x !== "number" || typeof b.y !== "number") return null;
|
|
1817
|
-
return Math.hypot(a.x - b.x, a.y - b.y);
|
|
1818
|
-
}
|
|
1
|
+
import {itemEquipmentSlotFromId} from "../../state/items.js";
|
|
2
|
+
import {buildInventoryDragCommand, normalizeEquipmentSlot, normalizeInventoryEvent} from "../../protocol/outbound/inventory.js";
|
|
3
|
+
|
|
4
|
+
export function normalizeAttachMode(mode = "observe") {
|
|
5
|
+
const value = String(mode || "observe").toLowerCase();
|
|
6
|
+
if (value === "observe" || value === "bootstrap" || value === "readonly") return value;
|
|
7
|
+
throw new Error(`Unsupported websocket attach mode: ${mode}`);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export class ClientNetDomain {
|
|
11
|
+
constructor(client) {
|
|
12
|
+
this.client = client;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
get connected() {
|
|
16
|
+
return this.client.connected;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
get ready() {
|
|
20
|
+
return this.client.ready;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
get sid() {
|
|
24
|
+
return this.client.sid;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
get packetCount() {
|
|
28
|
+
return this.client.packetCount;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
get lastPacket() {
|
|
32
|
+
return this.client.lastPacket;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
send(command = {}) {
|
|
36
|
+
return this.client.send(command);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
sendMessage(message, options = {}) {
|
|
40
|
+
return this.client.sendMessage(message, options);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
sendRaw(message, options = {}) {
|
|
44
|
+
return this.client.sendRaw(message, options);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
sendEntityCommand(cmd, args = [-1, -1, -1]) {
|
|
48
|
+
return this.client.sendEntityCommand(cmd, args);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
sendUiConfig(data) {
|
|
52
|
+
return this.client.sendUiConfig(data);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
sendBlueprintPlacement(placement) {
|
|
56
|
+
return this.client.sendBlueprintPlacement(placement);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
setOutfit(outfit) {
|
|
60
|
+
return this.client.setOutfit(outfit);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export class ClientDebugDomain {
|
|
65
|
+
constructor(client) {
|
|
66
|
+
this.client = client;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
packets() {
|
|
70
|
+
return this.client.packets.slice();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
decodeErrors() {
|
|
74
|
+
return this.client.decodeErrors.slice();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
worldStore() {
|
|
78
|
+
return this.client.worlds;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
modelTable(worldId, tableId) {
|
|
82
|
+
return this.client.worlds.worlds.get(Number(worldId))?.model.table(tableId) || new Map();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
modelRecord(worldId, tableId, entityId) {
|
|
86
|
+
return this.client.worlds.worlds.get(Number(worldId))?.model.record(tableId, entityId) || null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
entities(scope = "ship") {
|
|
90
|
+
return summariesFor(this.client, scope);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
entity(scope = "ship", entity = null) {
|
|
94
|
+
if (entity == null) return null;
|
|
95
|
+
return summaryForEntity(this.client, scope, entityIdOf(entity));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
puiPanels() {
|
|
99
|
+
return [...this.client.puiPanels.values()];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
commsPanels() {
|
|
103
|
+
return [...this.client.commsPanels.values()];
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export class PlayerDomain {
|
|
108
|
+
constructor(client) {
|
|
109
|
+
this.client = client;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
current() {
|
|
113
|
+
return currentPlayerSummary(this.client);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
entity() {
|
|
117
|
+
return this.client.currentPlayerEntity();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
name() {
|
|
121
|
+
return this.current()?.name ?? null;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
rank() {
|
|
125
|
+
return currentPlayerRank(this.client);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
move({x = 0, y = 0} = {}, command = {}) {
|
|
129
|
+
return this.client.move(x, y, command);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
aim({x = 0, y = 0, mx = x, my = y} = {}, command = {}) {
|
|
133
|
+
return this.client.aim(mx, my, command);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
action(flags = {}, command = {}) {
|
|
137
|
+
return this.client.action(flags, command);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
useEntity(entity, options = {}, command = {}) {
|
|
141
|
+
return this.client.useEntity(entityIdOf(entity), options, command);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
useHeldItem(options = {}, command = {}) {
|
|
145
|
+
return this.client.useHeldItem(options, command);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
placeHeldItem(options = {}, command = {}) {
|
|
149
|
+
return this.client.placeHeldItem(options, command);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
placeBlueprint(placement, options = {}, command = {}) {
|
|
153
|
+
return this.client.placeBlueprint(placement, options, command);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
rotateHeldItem(options = {}, command = {}) {
|
|
157
|
+
return this.client.rotateHeldItem(options, command);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
selectSlot(invSlot = 0, command = {}) {
|
|
161
|
+
return this.client.send({...command, inv_slot: inventorySlotIndexOf(invSlot)});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
inputSettings() {
|
|
165
|
+
return this.client.inputSettings();
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
setInputSettings(settings = {}, options = {}) {
|
|
169
|
+
return this.client.setInputSettings(settings, options);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
setView(width, height, options = {}) {
|
|
173
|
+
return this.client.setView(width, height, options);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
setScreenSize(width, height, options = {}) {
|
|
177
|
+
return this.client.setScreenSize(width, height, options);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
setWrenchMode(mode, options = {}) {
|
|
181
|
+
return this.client.setWrenchMode(mode, options);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
setTurretMode(mode, options = {}) {
|
|
185
|
+
return this.client.setTurretMode(mode, options);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export class ShipManagementDomain {
|
|
190
|
+
constructor(client) {
|
|
191
|
+
this.client = client;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
requestPlayerList() {
|
|
195
|
+
return this.client.requestPlayerList();
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
resetInvite() {
|
|
199
|
+
return this.client.resetInvite();
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
setPrivacy(privacy) {
|
|
203
|
+
return this.client.setShipPrivacy(privacy);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
recoverStarterItem(itemId) {
|
|
207
|
+
return this.client.recoverStarterItem(itemId);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
setPlayerRank(refId, rank) {
|
|
211
|
+
return this.client.setPlayerRank(refId, rank);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
kickPlayer(refId) {
|
|
215
|
+
return this.client.kickPlayer(refId);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
banPlayer(refId) {
|
|
219
|
+
return this.client.banPlayer(refId);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
demoteSelf() {
|
|
223
|
+
return this.client.demoteSelf();
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
config() {
|
|
227
|
+
return this.client.shipConfig;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
hasCheats() {
|
|
231
|
+
return Boolean(this.client.captainSubrank?.enableCheats);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
playerList() {
|
|
235
|
+
return this.client.playerList;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export class InventoryDomain {
|
|
240
|
+
constructor(client) {
|
|
241
|
+
this.client = client;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
state() {
|
|
245
|
+
return this.client.inventoryState;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
hotbarSize() {
|
|
249
|
+
return this.state()?.hotbarSize ?? 0;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
allSlots() {
|
|
253
|
+
return (this.state()?.slots || []).map((slot) => this.slot(slot.index));
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
slot(ref) {
|
|
257
|
+
return new InventorySlotHandle(this, inventorySlotIndexOf(ref));
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
hotbarSlots() {
|
|
261
|
+
return (this.state()?.hotbar || []).map((slot) => this.slot(slot.index));
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
equipmentSlots() {
|
|
265
|
+
return {
|
|
266
|
+
head: this.slot("head"),
|
|
267
|
+
face: this.slot("face"),
|
|
268
|
+
body: this.slot("body"),
|
|
269
|
+
back: this.slot("back"),
|
|
270
|
+
hands: this.slot("hands"),
|
|
271
|
+
feet: this.slot("feet")
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
findItem(itemId, {area = "all"} = {}) {
|
|
276
|
+
return this.findItems(itemId, {area})[0] || null;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
findItems(itemId, {area = "all"} = {}) {
|
|
280
|
+
const normalized = Number(itemId);
|
|
281
|
+
if (!Number.isFinite(normalized)) return [];
|
|
282
|
+
return inventoryHandlesForArea(this, area).filter((slot) => slot.itemId === normalized);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
firstEmpty({area = "all"} = {}) {
|
|
286
|
+
return inventoryHandlesForArea(this, area).find((slot) => slot.empty) || null;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
move(source, target, {split = false} = {}, command = {}) {
|
|
290
|
+
return this.client.send({
|
|
291
|
+
...command,
|
|
292
|
+
...buildInventoryDragCommand(inventorySlotIndexOf(source, "source"), inventorySlotIndexOf(target, "target"), split)
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
equip(source, equipmentSlot = null, options = {}, command = {}) {
|
|
297
|
+
const args = normalizeEquipArguments(equipmentSlot, options, command);
|
|
298
|
+
const target = args.equipmentSlot == null ? inferEquipmentSlotForInventorySource(this, source) : args.equipmentSlot;
|
|
299
|
+
return this.move(source, normalizeEquipmentSlot(target), {split: args.split}, args.command);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
unequip(equipmentSlot, target = 0, {split = false} = {}, command = {}) {
|
|
303
|
+
return this.move(normalizeEquipmentSlot(equipmentSlot), target, {split}, command);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
select(slot, command = {}) {
|
|
307
|
+
return this.client.send({...command, inv_slot: inventorySlotIndexOf(slot)});
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
export class InventorySlotHandle {
|
|
312
|
+
constructor(domain, index) {
|
|
313
|
+
this.domain = domain;
|
|
314
|
+
this.client = domain.client;
|
|
315
|
+
this.index = index;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
get state() {
|
|
319
|
+
return this.domain.state()?.slots?.find((slot) => slot.index === this.index) || null;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
get kind() {
|
|
323
|
+
return this.state?.kind ?? null;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
get equipmentSlot() {
|
|
327
|
+
return this.state?.equipmentSlot ?? null;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
get itemId() {
|
|
331
|
+
return this.state?.itemId ?? null;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
get itemName() {
|
|
335
|
+
return this.state?.itemName ?? null;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
get count() {
|
|
339
|
+
return this.state?.count ?? 0;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
get empty() {
|
|
343
|
+
return this.state?.empty ?? true;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
exists() {
|
|
347
|
+
return Boolean(this.state);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
snapshot() {
|
|
351
|
+
return this.state ? Object.freeze({...this.state}) : null;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
moveTo(target, options = {}, command = {}) {
|
|
355
|
+
return this.domain.move(this, target, options, command);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
equip(equipmentSlot = null, options = {}, command = {}) {
|
|
359
|
+
if (equipmentSlot && typeof equipmentSlot === "object") return this.domain.equip(this, null, equipmentSlot, options);
|
|
360
|
+
return this.domain.equip(this, equipmentSlot, options, command);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
unequip(target = 0, options = {}, command = {}) {
|
|
364
|
+
if (!this.equipmentSlot) throw new RangeError(`inventory slot ${this.index} is not an equipment slot`);
|
|
365
|
+
return this.domain.unequip(this.equipmentSlot, target, options, command);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
select(command = {}) {
|
|
369
|
+
return this.domain.select(this, command);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
export class WorldDomain {
|
|
374
|
+
constructor(client, scope) {
|
|
375
|
+
this.client = client;
|
|
376
|
+
this.scope = scope;
|
|
377
|
+
this.entities = new EntityCollection(client, scope);
|
|
378
|
+
this.machines = new MachineCollection(client, scope);
|
|
379
|
+
this.players = new PlayerCollection(client, scope);
|
|
380
|
+
this.blocks = new BlockCollection(client, scope);
|
|
381
|
+
this.materials = new MaterialCollection(client, scope);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
get id() {
|
|
385
|
+
return worldStateFor(this.client, this.scope)?.id ?? null;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
exists() {
|
|
389
|
+
return Boolean(worldStateFor(this.client, this.scope));
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
snapshot(options = {}) {
|
|
393
|
+
return worldStateFor(this.client, this.scope)?.snapshot(options) || null;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
export class ShipDomain extends WorldDomain {
|
|
398
|
+
entity() {
|
|
399
|
+
const summary = this.client.worlds.currentShipEntity();
|
|
400
|
+
return summary ? new EntityHandle(this.client, summary.entity, "overworld") : null;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
get overworldEntity() {
|
|
404
|
+
return this.entity();
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
get metadata() {
|
|
408
|
+
return worldStateFor(this.client, this.scope)?.model.shipMetadata() || null;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
export class OverworldDomain extends WorldDomain {
|
|
413
|
+
ships(options = {}) {
|
|
414
|
+
return this.client.ships(options).map((summary) => new ShipHandle(this.client, summary));
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
shipByHex(hexCode, options = {}) {
|
|
418
|
+
const summary = this.client.shipByHex(hexCode, options);
|
|
419
|
+
return summary ? new ShipHandle(this.client, summary) : null;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
shipByEntity(entity, options = {}) {
|
|
423
|
+
const summary = this.client.shipByEntity(entityIdOf(entity), options);
|
|
424
|
+
return summary ? new ShipHandle(this.client, summary) : null;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
const ENTITY_SNAPSHOT_CACHE = new WeakMap();
|
|
429
|
+
|
|
430
|
+
function entitySnapshotFor(summary) {
|
|
431
|
+
if (!summary || typeof summary !== "object") return null;
|
|
432
|
+
let snapshot = ENTITY_SNAPSHOT_CACHE.get(summary);
|
|
433
|
+
if (!snapshot) {
|
|
434
|
+
snapshot = new EntitySnapshot(summary);
|
|
435
|
+
ENTITY_SNAPSHOT_CACHE.set(summary, snapshot);
|
|
436
|
+
}
|
|
437
|
+
return snapshot;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
export class EntitySnapshot {
|
|
441
|
+
#contents;
|
|
442
|
+
|
|
443
|
+
constructor(summary) {
|
|
444
|
+
const data = clonePlain(summary || {});
|
|
445
|
+
this.#contents = data.contents || null;
|
|
446
|
+
delete data.contents;
|
|
447
|
+
Object.assign(this, data);
|
|
448
|
+
this.id = Number(data.entity ?? data.id);
|
|
449
|
+
this.entity = this.id;
|
|
450
|
+
this.position = data.transform || null;
|
|
451
|
+
this.rotation = data.transform?.rotation ?? null;
|
|
452
|
+
this.type = entityPublicType(data, this.#contents);
|
|
453
|
+
this.features = Object.freeze(entityFeatures(data, this.#contents));
|
|
454
|
+
deepFreeze(this.#contents);
|
|
455
|
+
deepFreeze(this);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
is(type) {
|
|
459
|
+
const key = normalizeEntityKey(type);
|
|
460
|
+
if (!key) return false;
|
|
461
|
+
const publicType = normalizeEntityKey(this.type);
|
|
462
|
+
if (key === publicType) return true;
|
|
463
|
+
if (key === normalizeEntityKey(this.category)) return true;
|
|
464
|
+
if (key === "placedentity" && this.category === "placed_entity") return true;
|
|
465
|
+
if (key === "looseitem" && this.category === "loose_item") return true;
|
|
466
|
+
if (key === "ship" && (this.category === "ship_control" || this.#contents?.shipControl)) return true;
|
|
467
|
+
if (key === "machine") return Boolean(entityMachineType(this.#contents));
|
|
468
|
+
if (key === "item") return Boolean(this.#contents?.itemHolder || this.#contents?.itemCrate || this.#contents?.expandoBox);
|
|
469
|
+
if (key === "bot") return Boolean(this.#contents?.bot);
|
|
470
|
+
if (key === "player") return Boolean(this.#contents?.player || this.category === "player");
|
|
471
|
+
if (this.kind?.some((kind) => normalizeEntityKey(kind) === key)) return true;
|
|
472
|
+
return Boolean(componentFor(this.#contents, key));
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
has(feature) {
|
|
476
|
+
return this.feature(feature) != null;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
feature(feature) {
|
|
480
|
+
return entityFeature(this, this.#contents, feature);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
export class EntityCollection {
|
|
485
|
+
constructor(client, scope) {
|
|
486
|
+
this.client = client;
|
|
487
|
+
this.scope = scope;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
all() {
|
|
491
|
+
return summariesFor(this.client, this.scope).map((summary) => new EntityHandle(this.client, summary.entity, this.scope));
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
snapshots() {
|
|
495
|
+
return summariesFor(this.client, this.scope).map(entitySnapshotFor);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
states() {
|
|
499
|
+
return this.snapshots();
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
get(entity) {
|
|
503
|
+
return new EntityHandle(this.client, entityIdOf(entity), this.scope);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
export class PlayerCollection {
|
|
508
|
+
constructor(client, scope) {
|
|
509
|
+
this.client = client;
|
|
510
|
+
this.scope = scope;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
all() {
|
|
514
|
+
return worldStateFor(this.client, this.scope)?.model.players() || [];
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
current() {
|
|
518
|
+
return currentPlayerSummary(this.client, this.scope);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
export class BlockCollection {
|
|
523
|
+
constructor(client, scope) {
|
|
524
|
+
this.client = client;
|
|
525
|
+
this.scope = scope;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
all() {
|
|
529
|
+
return worldStateFor(this.client, this.scope)?.blocks() || [];
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
at(x, y) {
|
|
533
|
+
return worldStateFor(this.client, this.scope)?.blockAt(x, y) || null;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
export class MaterialCollection {
|
|
538
|
+
constructor(client, scope) {
|
|
539
|
+
this.client = client;
|
|
540
|
+
this.scope = scope;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
all() {
|
|
544
|
+
return worldStateFor(this.client, this.scope)?.materials() || [];
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
export class MachineCollection {
|
|
549
|
+
constructor(client, scope) {
|
|
550
|
+
this.client = client;
|
|
551
|
+
this.scope = scope;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
state() {
|
|
555
|
+
return worldStateFor(this.client, this.scope)?.model.machines() || emptyMachineSummary();
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
raw() {
|
|
559
|
+
return this.state();
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
loaders() {
|
|
563
|
+
return this.state().loaders.map((item) => new LoaderHandle(this.client, item.entity, this.scope));
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
loader(entity) {
|
|
567
|
+
return new LoaderHandle(this.client, entityIdOf(entity), this.scope);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
pushers() {
|
|
571
|
+
return this.state().pushers.map((item) => new PusherHandle(this.client, item.entity, this.scope));
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
pusher(entity) {
|
|
575
|
+
return new PusherHandle(this.client, entityIdOf(entity), this.scope);
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
launchers() {
|
|
579
|
+
return this.state().launchers.map((item) => new LauncherHandle(this.client, item.entity, this.scope));
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
launcher(entity) {
|
|
583
|
+
return new LauncherHandle(this.client, entityIdOf(entity), this.scope);
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
navigationUnits() {
|
|
587
|
+
return this.state().navigationUnits.map((item) => new NavigationUnitHandle(this.client, item.entity, this.scope));
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
navigationUnit(entity = null) {
|
|
591
|
+
const id = entity == null ? this.state().navigationUnits[0]?.entity : entityIdOf(entity);
|
|
592
|
+
return id == null ? null : new NavigationUnitHandle(this.client, id, this.scope);
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
fabricators() {
|
|
596
|
+
return this.state().fabricators.map((item) => new FabricatorHandle(this.client, item.entity, this.scope));
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
fabricator(entity) {
|
|
600
|
+
return new FabricatorHandle(this.client, entityIdOf(entity), this.scope);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
commsStations() {
|
|
604
|
+
return this.state().commsStations.map((item) => new CommsStationHandle(this.client, item.entity, this.scope));
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
commsStation(entity = null) {
|
|
608
|
+
const id = entity == null ? this.state().commsStations[0]?.entity : entityIdOf(entity);
|
|
609
|
+
return id == null ? null : new CommsStationHandle(this.client, id, this.scope);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
signs() {
|
|
613
|
+
return summariesFor(this.client, this.scope).filter((item) => item.contents?.sign).map((item) => new SignHandle(this.client, item.entity, this.scope));
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
sign(entity) {
|
|
617
|
+
return new SignHandle(this.client, entityIdOf(entity), this.scope);
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
generators() {
|
|
621
|
+
return this.state().shieldGenerators.map((item) => new GeneratorHandle(this.client, item.entity, this.scope));
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
generator(entity) {
|
|
625
|
+
return new GeneratorHandle(this.client, entityIdOf(entity), this.scope);
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
cargoHatches() {
|
|
629
|
+
return this.state().cargoHatches.map((item) => new CargoHatchHandle(this.client, item.entity, this.scope));
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
cargoHatch(entity) {
|
|
633
|
+
return new CargoHatchHandle(this.client, entityIdOf(entity), this.scope);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
cargoEjectors() {
|
|
637
|
+
return this.state().cargoEjectors.map((item) => new CargoEjectorHandle(this.client, item.entity, this.scope));
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
cargoEjector(entity) {
|
|
641
|
+
return new CargoEjectorHandle(this.client, entityIdOf(entity), this.scope);
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
cannons() {
|
|
645
|
+
return this.state().cannons.map((item) => new CannonHandle(this.client, item.entity, this.scope));
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
cannon(entity) {
|
|
649
|
+
return new CannonHandle(this.client, entityIdOf(entity), this.scope);
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
thrusters() {
|
|
653
|
+
return this.state().thrusters.map((item) => new ThrusterHandle(this.client, item.entity, this.scope));
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
thruster(entity) {
|
|
657
|
+
return new ThrusterHandle(this.client, entityIdOf(entity), this.scope);
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
helms() {
|
|
661
|
+
return this.state().helms.map((item) => new HelmHandle(this.client, item.entity, this.scope));
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
helm(entity) {
|
|
665
|
+
return new HelmHandle(this.client, entityIdOf(entity), this.scope);
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
doors() {
|
|
669
|
+
return this.state().doors.map((item) => new DoorHandle(this.client, item.entity, this.scope));
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
door(entity) {
|
|
673
|
+
return new DoorHandle(this.client, entityIdOf(entity), this.scope);
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
spawnPoints() {
|
|
677
|
+
return this.state().spawnPoints.map((item) => new SpawnPointHandle(this.client, item.entity, this.scope));
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
spawnPoint(entity) {
|
|
681
|
+
return new SpawnPointHandle(this.client, entityIdOf(entity), this.scope);
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
shieldProjectors() {
|
|
685
|
+
return this.state().shieldProjectors.map((item) => new ShieldProjectorHandle(this.client, item.entity, this.scope));
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
shieldProjector(entity) {
|
|
689
|
+
return new ShieldProjectorHandle(this.client, entityIdOf(entity), this.scope);
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
fluidTanks() {
|
|
693
|
+
return this.state().fluidTanks.map((item) => new FluidTankHandle(this.client, item.entity, this.scope));
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
fluidTank(entity) {
|
|
697
|
+
return new FluidTankHandle(this.client, entityIdOf(entity), this.scope);
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
expandoBoxes() {
|
|
701
|
+
return this.state().expandoBoxes.map((item) => new ExpandoBoxHandle(this.client, item.entity, this.scope));
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
expandoBox(entity) {
|
|
705
|
+
return new ExpandoBoxHandle(this.client, entityIdOf(entity), this.scope);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
export class EntityHandle {
|
|
710
|
+
constructor(client, entity, scope = "ship") {
|
|
711
|
+
this.client = client;
|
|
712
|
+
this.id = Number(entity);
|
|
713
|
+
this.entity = this.id;
|
|
714
|
+
this.scope = scope;
|
|
715
|
+
this._cachedSummary = undefined;
|
|
716
|
+
this._cachedSnapshot = null;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
exists() {
|
|
720
|
+
return Boolean(this.snapshot());
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
// Reading five properties off a handle used to walk the world/derived-state
|
|
724
|
+
// resolution chain five times. The summary object identity changes whenever
|
|
725
|
+
// the entity is refreshed, so it doubles as the cache key.
|
|
726
|
+
snapshot() {
|
|
727
|
+
const summary = worldStateFor(this.client, this.scope)?.entity(this.id) || null;
|
|
728
|
+
if (summary !== this._cachedSummary) {
|
|
729
|
+
this._cachedSummary = summary;
|
|
730
|
+
this._cachedSnapshot = entitySnapshotFor(summary);
|
|
731
|
+
}
|
|
732
|
+
return this._cachedSnapshot;
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
get position() {
|
|
736
|
+
return summaryForEntity(this.client, this.scope, this.id)?.transform || null;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
get health() {
|
|
740
|
+
return summaryForEntity(this.client, this.scope, this.id)?.contents?.health || null;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
get type() {
|
|
744
|
+
return this.snapshot()?.type ?? "unknown";
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
get features() {
|
|
748
|
+
return this.snapshot()?.features ?? [];
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
is(type) {
|
|
752
|
+
return this.snapshot()?.is(type) ?? false;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
has(feature) {
|
|
756
|
+
return this.snapshot()?.has(feature) ?? false;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
feature(feature) {
|
|
760
|
+
return this.snapshot()?.feature(feature) ?? null;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
as(type) {
|
|
764
|
+
return entityDomainHandle(this.client, this.id, this.scope, type, this.snapshot());
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
asLoader() {
|
|
768
|
+
return this.as("loader");
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
asPusher() {
|
|
772
|
+
return this.as("pusher");
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
asLauncher() {
|
|
776
|
+
return this.as("launcher");
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
asNavigationUnit() {
|
|
780
|
+
return this.as("navigationUnit");
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
asCommsStation() {
|
|
784
|
+
return this.as("commsStation");
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
asSign() {
|
|
788
|
+
return this.as("sign");
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
asGenerator() {
|
|
792
|
+
return this.as("shieldGenerator");
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
asCargoHatch() {
|
|
796
|
+
return this.as("cargoHatch");
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
asCannon() {
|
|
800
|
+
return this.as("cannon");
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
asThruster() {
|
|
804
|
+
return this.as("thruster");
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
asHelm() {
|
|
808
|
+
return this.as("helm");
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
asDoor() {
|
|
812
|
+
return this.as("door");
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
asSpawnPoint() {
|
|
816
|
+
return this.as("spawnPoint");
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
asShieldProjector() {
|
|
820
|
+
return this.as("shieldProjector");
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
asFluidTank() {
|
|
824
|
+
return this.as("fluidTank");
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
asCargoEjector() {
|
|
828
|
+
return this.as("cargoEjector");
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
asExpandoBox() {
|
|
832
|
+
return this.as("expandoBox");
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
use(options = {}, command = {}) {
|
|
836
|
+
return this.client.player.useEntity(this.id, options, command);
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
export class MachineHandle extends EntityHandle {
|
|
841
|
+
open(options = {}, command = {}) {
|
|
842
|
+
return this.use(options, command);
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
export class LoaderHandle extends MachineHandle {
|
|
847
|
+
get state() {
|
|
848
|
+
return summaryForEntity(this.client, this.scope, this.id)?.contents?.loader || null;
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
configure(config = {}) {
|
|
852
|
+
return this.client.sendLoaderConfig(this.id, config);
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
configureFull(config = {}) {
|
|
856
|
+
return this.client.sendLoaderFullConfig(this.id, config);
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
copy(config = {}) {
|
|
860
|
+
return this.client.copyLoaderConfig(this.id, config);
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
setPickPlace(pick, place, config = {}) {
|
|
864
|
+
return this.client.setLoaderPickPlace(this.id, pick, place, config);
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
setPriority(priority, config = {}) {
|
|
868
|
+
return this.client.setLoaderPriority(this.id, priority, config);
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
setStack(stack, config = {}) {
|
|
872
|
+
return this.client.setLoaderStack(this.id, stack, config);
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
setCycle(cycle, config = {}) {
|
|
876
|
+
return this.client.setLoaderCycle(this.id, cycle, config);
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
setRequireOutput(requireOutput, config = {}) {
|
|
880
|
+
return this.client.setLoaderRequireOutput(this.id, requireOutput, config);
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
setWaitForStack(waitForStack, config = {}) {
|
|
884
|
+
return this.client.setLoaderWaitForStack(this.id, waitForStack, config);
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
setFilterMode(filterMode) {
|
|
888
|
+
return this.client.setLoaderFilterMode(this.id, filterMode);
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
setFilterItems(filterSlots = []) {
|
|
892
|
+
return this.client.setLoaderFilterItems(this.id, filterSlots);
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
get pick() {
|
|
896
|
+
return this.state?.pick;
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
get place() {
|
|
900
|
+
return this.state?.place;
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
get priority() {
|
|
904
|
+
return this.state?.priority;
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
get stack() {
|
|
908
|
+
return this.state?.stack;
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
get cycle() {
|
|
912
|
+
return this.state?.cycle;
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
get requireOutput() {
|
|
916
|
+
return this.state?.requireOutput;
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
get waitForStack() {
|
|
920
|
+
return this.state?.waitForStack;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
get filterMode() {
|
|
924
|
+
return this.state?.filterMode;
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
get filterSlots() {
|
|
928
|
+
return this.state?.filterSlots || [];
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
get active() {
|
|
932
|
+
return this.state?.active;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
get heldItem() {
|
|
936
|
+
const state = this.state;
|
|
937
|
+
if (!state || state.heldItemId == null) return null;
|
|
938
|
+
return {itemId: state.heldItemId, itemName: state.heldItemName, count: state.heldCount};
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
get progress() {
|
|
942
|
+
return this.state?.progress;
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
export class PusherHandle extends MachineHandle {
|
|
947
|
+
get state() {
|
|
948
|
+
return summaryForEntity(this.client, this.scope, this.id)?.contents?.pusher || null;
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
get beam() {
|
|
952
|
+
return summaryForEntity(this.client, this.scope, this.id)?.contents?.pusherBeam || null;
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
configure(config = {}) {
|
|
956
|
+
return this.client.sendPusherConfig(this.id, config);
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
setAngle(angle, config = {}) {
|
|
960
|
+
return this.client.setPusherAngle(this.id, angle, config);
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
setSpeed(speed, config = {}) {
|
|
964
|
+
return this.client.setPusherSpeed(this.id, speed, config);
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
setLength(length, config = {}) {
|
|
968
|
+
return this.client.setPusherLength(this.id, length, config);
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
setMode(mode, config = {}) {
|
|
972
|
+
return this.client.setPusherMode(this.id, mode, config);
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
setFilteredMode(mode, config = {}) {
|
|
976
|
+
return this.client.setPusherFilteredMode(this.id, mode, config);
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
setFilterInventory(filterInventory, config = {}) {
|
|
980
|
+
return this.client.setPusherFilterInventory(this.id, filterInventory, config);
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
setFilterItems(filterSlots = []) {
|
|
984
|
+
return this.client.setPusherFilterItems(this.id, filterSlots);
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
get angle() {
|
|
988
|
+
return this.state?.angle;
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
get speed() {
|
|
992
|
+
return this.state?.speed;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
get length() {
|
|
996
|
+
return this.state?.length;
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
get mode() {
|
|
1000
|
+
return this.state?.mode;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
get filteredMode() {
|
|
1004
|
+
return this.state?.filteredMode;
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
export class LauncherHandle extends MachineHandle {
|
|
1009
|
+
get state() {
|
|
1010
|
+
return summaryForEntity(this.client, this.scope, this.id)?.contents?.launcher || null;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
setAngle(angle) {
|
|
1014
|
+
return this.client.setLauncherAngle(angle);
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
setPower(power) {
|
|
1018
|
+
return this.client.setLauncherPower(power);
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
get angleDegrees() {
|
|
1022
|
+
return this.state?.angleDegrees;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
get angleRadians() {
|
|
1026
|
+
return this.state?.angleRadians;
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
get angleRaw() {
|
|
1030
|
+
return this.state?.angleRaw;
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
export class NavigationUnitHandle extends MachineHandle {
|
|
1035
|
+
get state() {
|
|
1036
|
+
return summaryForEntity(this.client, this.scope, this.id)?.contents?.navigationUnit || null;
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
configure(config = {}) {
|
|
1040
|
+
return this.client.sendNavigationUnitConfig(this.id, config);
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
copy(config = {}) {
|
|
1044
|
+
return this.client.copyNavigationUnitConfig(this.id, config);
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
paste(config = {}) {
|
|
1048
|
+
return this.client.pasteNavigationUnitConfig(this.id, config);
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
setDestination(destination, config = {}) {
|
|
1052
|
+
return this.client.setNavigationDestination(this.id, destination, config);
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
setAutoWarp(config = {}) {
|
|
1056
|
+
return this.client.setNavigationAutoWarp(this.id, config);
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
startWarp(config = {}) {
|
|
1060
|
+
return this.client.startWarp(this.id, config);
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
cancelWarp(config = {}) {
|
|
1064
|
+
return this.client.cancelWarp(this.id, config);
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
get destination() {
|
|
1068
|
+
return this.state?.destination;
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
get autoWarpOnShieldFailure() {
|
|
1072
|
+
return this.state?.autoWarpOnShieldFailure;
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
get autoWarpOnNoCaptains() {
|
|
1076
|
+
return this.state?.autoWarpOnNoCaptains;
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
get warp() {
|
|
1080
|
+
return this.state?.warp;
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
export class FabricatorHandle extends MachineHandle {
|
|
1085
|
+
get state() {
|
|
1086
|
+
return summaryForEntity(this.client, this.scope, this.id)?.contents?.fabricator || null;
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
get progress() {
|
|
1090
|
+
return this.state?.progress;
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
get active() {
|
|
1094
|
+
return this.state?.active;
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
get craftingItem() {
|
|
1098
|
+
const state = this.state;
|
|
1099
|
+
if (!state || state.craftingItemId == null) return null;
|
|
1100
|
+
return {itemId: state.craftingItemId, itemName: state.craftingItemName, count: state.craftingCount};
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
panel() {
|
|
1104
|
+
return this.client.puiPanels.get(this.id) || null;
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
add(itemId, count = 1, index = -1) {
|
|
1108
|
+
return this.client.craftAdd(itemId, count, index);
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
sub(itemId, count = 1, index = 0) {
|
|
1112
|
+
return this.client.craftSub(itemId, count, index);
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
clearQueue() {
|
|
1116
|
+
return this.client.craftClearQueue();
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
toggleRepeat() {
|
|
1120
|
+
return this.client.craftToggleRepeat();
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
lockResource(row) {
|
|
1124
|
+
return this.client.fabricatorLockResource(row);
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
unlockResource(row) {
|
|
1128
|
+
return this.client.fabricatorUnlockResource(row);
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
eject(row) {
|
|
1132
|
+
return this.client.fabricatorEject(row);
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
export class CommsStationHandle extends MachineHandle {
|
|
1137
|
+
get state() {
|
|
1138
|
+
return summaryForEntity(this.client, this.scope, this.id)?.contents?.commsStation || null;
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
panel() {
|
|
1142
|
+
return this.client.commsPanels.get(this.id) || null;
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
sendMessage(message = "") {
|
|
1146
|
+
return this.client.sendCommsMessage(message);
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
export class SignHandle extends MachineHandle {
|
|
1151
|
+
get state() {
|
|
1152
|
+
return summaryForEntity(this.client, this.scope, this.id)?.contents?.sign || null;
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
setText(text = "", mode = 0) {
|
|
1156
|
+
return this.client.setSignText(text, mode);
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
get text() {
|
|
1160
|
+
return this.state?.text;
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
get mode() {
|
|
1164
|
+
return this.state?.mode;
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
export class GeneratorHandle extends MachineHandle {
|
|
1169
|
+
get state() {
|
|
1170
|
+
return summaryForEntity(this.client, this.scope, this.id)?.contents?.shieldGenerator || null;
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
solvePuzzle(solution) {
|
|
1174
|
+
return this.client.solveGeneratorPuzzle(this.id, solution);
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
export class CargoHatchHandle extends MachineHandle {
|
|
1179
|
+
get state() {
|
|
1180
|
+
return summaryForEntity(this.client, this.scope, this.id)?.contents?.cargoHatch || null;
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
get openFraction() {
|
|
1184
|
+
return this.state?.openFraction;
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
configure(config = {}) {
|
|
1188
|
+
return this.client.sendCargoHatchFullConfig(this.id, config);
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
copy(config = {}) {
|
|
1192
|
+
return this.client.copyCargoHatchConfig(this.id, config);
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
paste(config = {}) {
|
|
1196
|
+
return this.client.pasteCargoHatchConfig(this.id, config);
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
setFilterMode(filterMode) {
|
|
1200
|
+
return this.client.setCargoHatchFilterMode(this.id, filterMode);
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
setFilterItems(filterSlots = []) {
|
|
1204
|
+
return this.client.setCargoHatchFilterItems(this.id, filterSlots);
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
export class CannonHandle extends MachineHandle {
|
|
1209
|
+
get state() {
|
|
1210
|
+
return summaryForEntity(this.client, this.scope, this.id)?.contents?.cannon || null;
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
export class ThrusterHandle extends MachineHandle {
|
|
1215
|
+
get state() {
|
|
1216
|
+
return summaryForEntity(this.client, this.scope, this.id)?.contents?.thruster || null;
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1220
|
+
export class HelmHandle extends MachineHandle {
|
|
1221
|
+
get state() {
|
|
1222
|
+
return summaryForEntity(this.client, this.scope, this.id)?.contents?.helm || null;
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
get occupied() {
|
|
1226
|
+
return this.state?.occupied;
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
export class DoorHandle extends MachineHandle {
|
|
1231
|
+
get state() {
|
|
1232
|
+
return summaryForEntity(this.client, this.scope, this.id)?.contents?.door || null;
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
get rank() {
|
|
1236
|
+
return this.state?.rank;
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
get open() {
|
|
1240
|
+
return this.state?.open;
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
export class SpawnPointHandle extends MachineHandle {
|
|
1245
|
+
get state() {
|
|
1246
|
+
return summaryForEntity(this.client, this.scope, this.id)?.contents?.spawnPoint || null;
|
|
1247
|
+
}
|
|
1248
|
+
|
|
1249
|
+
get rank() {
|
|
1250
|
+
return this.state?.rank;
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
export class ShieldProjectorHandle extends MachineHandle {
|
|
1255
|
+
get state() {
|
|
1256
|
+
return summaryForEntity(this.client, this.scope, this.id)?.contents?.shieldProjector || null;
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
get active() {
|
|
1260
|
+
return this.state?.active;
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
export class FluidTankHandle extends MachineHandle {
|
|
1265
|
+
get state() {
|
|
1266
|
+
return summaryForEntity(this.client, this.scope, this.id)?.contents?.fluidTank || null;
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
get amount() {
|
|
1270
|
+
return this.state?.amount;
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
export class ExpandoBoxHandle extends MachineHandle {
|
|
1275
|
+
get state() {
|
|
1276
|
+
return summaryForEntity(this.client, this.scope, this.id)?.contents?.expandoBox || null;
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
get item() {
|
|
1280
|
+
return this.state?.itemId;
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
get count() {
|
|
1284
|
+
return this.state?.count;
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
export class CargoEjectorHandle extends MachineHandle {
|
|
1289
|
+
get state() {
|
|
1290
|
+
return summaryForEntity(this.client, this.scope, this.id)?.contents?.cargoEjector || null;
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
get progress() {
|
|
1294
|
+
return this.state?.progress;
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
get active() {
|
|
1298
|
+
return this.state?.active;
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
setDirection(direction) {
|
|
1302
|
+
return this.client.setCargoEjectorDirection(this.id, direction);
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
copy(direction = "right") {
|
|
1306
|
+
return this.client.copyCargoEjectorConfig(this.id, direction);
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
paste(direction = "right") {
|
|
1310
|
+
return this.client.pasteCargoEjectorConfig(this.id, direction);
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1314
|
+
export class ShipHandle {
|
|
1315
|
+
constructor(client, summary) {
|
|
1316
|
+
this.client = client;
|
|
1317
|
+
this.summary = summary;
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
get entity() {
|
|
1321
|
+
return this.summary.entity;
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
get name() {
|
|
1325
|
+
return this.summary.name;
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
get hexCode() {
|
|
1329
|
+
return this.summary.hexCode;
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
get distance() {
|
|
1333
|
+
return this.summary.distance;
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
get worldId() {
|
|
1337
|
+
return this.summary.worldId;
|
|
1338
|
+
}
|
|
1339
|
+
|
|
1340
|
+
get hasWorldData() {
|
|
1341
|
+
return this.summary.hasWorldData;
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
world() {
|
|
1345
|
+
return this.worldId == null ? null : this.client.world(this.worldId);
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
snapshot() {
|
|
1349
|
+
return this.summary;
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
const ENTITY_COMPONENT_ALIASES = new Map([
|
|
1354
|
+
["hoveroutline", "hoverOutline"],
|
|
1355
|
+
["outline", "hoverOutline"],
|
|
1356
|
+
["itemholder", "itemHolder"],
|
|
1357
|
+
["itemcrate", "itemCrate"],
|
|
1358
|
+
["expandobox", "expandoBox"],
|
|
1359
|
+
["expando", "expandoBox"],
|
|
1360
|
+
["blueprintpreview", "blueprintPreview"],
|
|
1361
|
+
["blueprint", "blueprintPreview"],
|
|
1362
|
+
["pusherbeam", "pusherBeam"],
|
|
1363
|
+
["beam", "pusherBeam"],
|
|
1364
|
+
["cargohatch", "cargoHatch"],
|
|
1365
|
+
["cargoejector", "cargoEjector"],
|
|
1366
|
+
["ejector", "cargoEjector"],
|
|
1367
|
+
["navigationunit", "navigationUnit"],
|
|
1368
|
+
["nav", "navigationUnit"],
|
|
1369
|
+
["navunit", "navigationUnit"],
|
|
1370
|
+
["commsstation", "commsStation"],
|
|
1371
|
+
["fluidtank", "fluidTank"],
|
|
1372
|
+
["shieldgenerator", "shieldGenerator"],
|
|
1373
|
+
["generator", "shieldGenerator"],
|
|
1374
|
+
["shieldprojector", "shieldProjector"],
|
|
1375
|
+
["shipcontrol", "shipControl"],
|
|
1376
|
+
["spawnpoint", "spawnPoint"],
|
|
1377
|
+
["shipsize", "shipSize"],
|
|
1378
|
+
["mapmarker", "mapMarker"],
|
|
1379
|
+
["marker", "mapMarker"],
|
|
1380
|
+
["dockingspring", "dockingSpring"],
|
|
1381
|
+
["hugethruster", "hugeThruster"]
|
|
1382
|
+
]);
|
|
1383
|
+
|
|
1384
|
+
const MACHINE_COMPONENTS = [
|
|
1385
|
+
"loader",
|
|
1386
|
+
"pusher",
|
|
1387
|
+
"launcher",
|
|
1388
|
+
"navigationUnit",
|
|
1389
|
+
"fabricator",
|
|
1390
|
+
"cargoEjector",
|
|
1391
|
+
"cannon",
|
|
1392
|
+
"thruster",
|
|
1393
|
+
"cargoHatch",
|
|
1394
|
+
"commsStation",
|
|
1395
|
+
"fluidTank",
|
|
1396
|
+
"shieldGenerator",
|
|
1397
|
+
"shieldProjector",
|
|
1398
|
+
"helm",
|
|
1399
|
+
"sign",
|
|
1400
|
+
"spawnPoint",
|
|
1401
|
+
"door",
|
|
1402
|
+
"expandoBox"
|
|
1403
|
+
];
|
|
1404
|
+
|
|
1405
|
+
const ENTITY_FEATURES = [
|
|
1406
|
+
"health",
|
|
1407
|
+
"position",
|
|
1408
|
+
"outline",
|
|
1409
|
+
"inventory",
|
|
1410
|
+
"item",
|
|
1411
|
+
"filter",
|
|
1412
|
+
"filterMode",
|
|
1413
|
+
"filterSlots",
|
|
1414
|
+
"filterInventory",
|
|
1415
|
+
"beam",
|
|
1416
|
+
"occupied",
|
|
1417
|
+
"loaderConfig",
|
|
1418
|
+
"pusherConfig",
|
|
1419
|
+
"launcherConfig",
|
|
1420
|
+
"navigationConfig",
|
|
1421
|
+
"fabricatorQueue",
|
|
1422
|
+
"progress"
|
|
1423
|
+
];
|
|
1424
|
+
|
|
1425
|
+
function normalizeEntityKey(value) {
|
|
1426
|
+
return String(value ?? "").toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1429
|
+
function clonePlain(value) {
|
|
1430
|
+
if (value == null) return value;
|
|
1431
|
+
if (typeof structuredClone === "function") return structuredClone(value);
|
|
1432
|
+
return JSON.parse(JSON.stringify(value));
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
function deepFreeze(value) {
|
|
1436
|
+
if (!value || typeof value !== "object" || Object.isFrozen(value)) return value;
|
|
1437
|
+
Object.freeze(value);
|
|
1438
|
+
for (const item of Object.values(value)) deepFreeze(item);
|
|
1439
|
+
return value;
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1442
|
+
function componentFor(contents, key) {
|
|
1443
|
+
if (!contents) return null;
|
|
1444
|
+
const component = ENTITY_COMPONENT_ALIASES.get(key) || key;
|
|
1445
|
+
return contents[component] ?? null;
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1448
|
+
function entityMachineType(contents) {
|
|
1449
|
+
if (!contents) return null;
|
|
1450
|
+
return MACHINE_COMPONENTS.find((component) => contents[component]) || null;
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1453
|
+
function firstFeatureSource(contents, names) {
|
|
1454
|
+
if (!contents) return null;
|
|
1455
|
+
for (const name of names) {
|
|
1456
|
+
const source = contents[name];
|
|
1457
|
+
if (source != null) return source;
|
|
1458
|
+
}
|
|
1459
|
+
return null;
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
function sourceWithProperty(contents, names, property) {
|
|
1463
|
+
if (!contents) return null;
|
|
1464
|
+
for (const name of names) {
|
|
1465
|
+
const source = contents[name];
|
|
1466
|
+
if (source && source[property] != null) return source;
|
|
1467
|
+
}
|
|
1468
|
+
return null;
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
function entityPublicType(summary, contents) {
|
|
1472
|
+
const machine = entityMachineType(contents);
|
|
1473
|
+
if (machine) return machine;
|
|
1474
|
+
if (contents?.player || summary?.category === "player") return "player";
|
|
1475
|
+
if (contents?.shipControl || summary?.category === "ship_control") return "ship";
|
|
1476
|
+
if (contents?.bot) return "bot";
|
|
1477
|
+
if (summary?.category === "loose_item" || contents?.itemCrate || contents?.itemHolder) return "looseItem";
|
|
1478
|
+
if (contents?.mapMarker) return "mapMarker";
|
|
1479
|
+
if (contents?.dockingSpring) return "dockingSpring";
|
|
1480
|
+
if (contents?.hugeThruster) return "hugeThruster";
|
|
1481
|
+
if (contents?.blueprintPreview) return "blueprintPreview";
|
|
1482
|
+
return "unknown";
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
function entityFeatures(summary, contents) {
|
|
1486
|
+
return ENTITY_FEATURES.filter((feature) => entityFeature(summary, contents, feature) != null);
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
function entityFeature(summary, contents, feature) {
|
|
1490
|
+
const key = normalizeEntityKey(feature);
|
|
1491
|
+
if (!key) return null;
|
|
1492
|
+
if (key === "position" || key === "transform") return summary?.position || summary?.transform || null;
|
|
1493
|
+
if (!contents) return null;
|
|
1494
|
+
const component = componentFor(contents, key);
|
|
1495
|
+
if (component != null) return component;
|
|
1496
|
+
if (key === "machine") return firstFeatureSource(contents, MACHINE_COMPONENTS);
|
|
1497
|
+
if (key === "inventory") return firstFeatureSource(contents, ["itemHolder", "expandoBox"]);
|
|
1498
|
+
if (key === "item") return firstFeatureSource(contents, ["itemCrate", "itemHolder", "expandoBox"]);
|
|
1499
|
+
if (key === "filter") return firstFeatureSource(contents, ["loader", "pusher", "cargoHatch"]);
|
|
1500
|
+
if (key === "filtermode") {
|
|
1501
|
+
const filterModeSource = sourceWithProperty(contents, ["loader", "pusher", "cargoHatch"], "filterMode");
|
|
1502
|
+
if (filterModeSource) return filterModeSource.filterMode;
|
|
1503
|
+
return sourceWithProperty(contents, ["pusher"], "filteredMode")?.filteredMode ?? null;
|
|
1504
|
+
}
|
|
1505
|
+
if (key === "filterslots") return sourceWithProperty(contents, ["loader", "pusher", "cargoHatch"], "filterSlots")?.filterSlots ?? null;
|
|
1506
|
+
if (key === "filterinventory") return contents.pusher?.filterInventory ?? null;
|
|
1507
|
+
if (key === "beam") return contents.pusherBeam ?? null;
|
|
1508
|
+
if (key === "outline") return contents.hoverOutline ?? null;
|
|
1509
|
+
if (key === "occupied") return sourceWithProperty(contents, ["helm", "commsStation"], "occupied")?.occupied ?? null;
|
|
1510
|
+
if (key === "health") return contents.health ?? null;
|
|
1511
|
+
if (key === "loaderconfig") return contents.loader ?? null;
|
|
1512
|
+
if (key === "pusherconfig") return contents.pusher ?? null;
|
|
1513
|
+
if (key === "launcherconfig") return contents.launcher ?? null;
|
|
1514
|
+
if (key === "navigationconfig") return contents.navigationUnit ?? null;
|
|
1515
|
+
if (key === "fabricatorqueue") return contents.fabricator?.rows ?? null;
|
|
1516
|
+
if (key === "progress") return contents.fabricator?.progress ?? contents.cargoEjector?.progress ?? contents.loader?.progress ?? contents.cargoHatch?.openFraction ?? null;
|
|
1517
|
+
return null;
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
function entityDomainHandle(client, entity, scope, type, snapshot = null) {
|
|
1521
|
+
const key = normalizeEntityKey(type);
|
|
1522
|
+
const state = snapshot || new EntityHandle(client, entity, scope).snapshot();
|
|
1523
|
+
if (!state) return null;
|
|
1524
|
+
const constructors = new Map([
|
|
1525
|
+
["loader", LoaderHandle],
|
|
1526
|
+
["pusher", PusherHandle],
|
|
1527
|
+
["launcher", LauncherHandle],
|
|
1528
|
+
["navigationunit", NavigationUnitHandle],
|
|
1529
|
+
["nav", NavigationUnitHandle],
|
|
1530
|
+
["navunit", NavigationUnitHandle],
|
|
1531
|
+
["fabricator", FabricatorHandle],
|
|
1532
|
+
["cargoejector", CargoEjectorHandle],
|
|
1533
|
+
["ejector", CargoEjectorHandle],
|
|
1534
|
+
["cannon", CannonHandle],
|
|
1535
|
+
["thruster", ThrusterHandle],
|
|
1536
|
+
["commsstation", CommsStationHandle],
|
|
1537
|
+
["sign", SignHandle],
|
|
1538
|
+
["shieldgenerator", GeneratorHandle],
|
|
1539
|
+
["generator", GeneratorHandle],
|
|
1540
|
+
["cargohatch", CargoHatchHandle],
|
|
1541
|
+
["shieldprojector", ShieldProjectorHandle],
|
|
1542
|
+
["fluidtank", FluidTankHandle],
|
|
1543
|
+
["helm", HelmHandle],
|
|
1544
|
+
["spawnpoint", SpawnPointHandle],
|
|
1545
|
+
["door", DoorHandle],
|
|
1546
|
+
["expandobox", ExpandoBoxHandle],
|
|
1547
|
+
["expando", ExpandoBoxHandle]
|
|
1548
|
+
]);
|
|
1549
|
+
const Handle = constructors.get(key);
|
|
1550
|
+
return Handle && state.is(key) ? new Handle(client, entity, scope) : null;
|
|
1551
|
+
}
|
|
1552
|
+
|
|
1553
|
+
function worldStateFor(client, scope = "ship") {
|
|
1554
|
+
if (scope == null || scope === "ship" || scope === "current") return client.worlds.shipWorld();
|
|
1555
|
+
if (scope === "overworld") return client.worlds.overworld();
|
|
1556
|
+
return client.worlds.worlds.get(Number(scope)) || null;
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1559
|
+
export function summariesFor(client, scope = "ship") {
|
|
1560
|
+
return worldStateFor(client, scope)?.entities() || [];
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
function summaryForEntity(client, scope, entity) {
|
|
1564
|
+
return worldStateFor(client, scope)?.entity(entity) || null;
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1567
|
+
function entityIdOf(value) {
|
|
1568
|
+
if (value && typeof value === "object") return Number(value.entity ?? value.id);
|
|
1569
|
+
return Number(value);
|
|
1570
|
+
}
|
|
1571
|
+
|
|
1572
|
+
function inventorySlotIndexOf(value, name = "slot") {
|
|
1573
|
+
if (value && typeof value === "object") {
|
|
1574
|
+
if (value.index != null) return normalizeInventorySlotIndex(value.index, name);
|
|
1575
|
+
if (value.entity != null || value.id != null) throw new TypeError(`${name} must be an inventory slot, slot snapshot, equipment slot, or index`);
|
|
1576
|
+
}
|
|
1577
|
+
if (typeof value === "string") return normalizeEquipmentSlot(value);
|
|
1578
|
+
return normalizeInventorySlotIndex(value, name);
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
function normalizeInventorySlotIndex(value, name = "slot") {
|
|
1582
|
+
const number = Number(value);
|
|
1583
|
+
if (!Number.isInteger(number) || number < 0) throw new RangeError(`${name} must be a non-negative inventory slot index`);
|
|
1584
|
+
return number;
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
export function currentPlayerSummary(client, scope = "current") {
|
|
1588
|
+
const sid = Number(client?.sid);
|
|
1589
|
+
if (!Number.isFinite(sid)) return null;
|
|
1590
|
+
return worldStateFor(client, scope)?.model.players().find((player) => player.entity === sid) || null;
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1593
|
+
function currentPlayerRank(client) {
|
|
1594
|
+
const player = currentPlayerSummary(client);
|
|
1595
|
+
const subrank = client?.captainSubrank?.subrank ?? null;
|
|
1596
|
+
const shipRank = player?.shipRank ?? null;
|
|
1597
|
+
return {
|
|
1598
|
+
shipRank,
|
|
1599
|
+
subrank: shipRank === "captain" ? subrank : null,
|
|
1600
|
+
isCaptain: shipRank === "captain",
|
|
1601
|
+
patronTier: player?.patronTier ?? null
|
|
1602
|
+
};
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1605
|
+
function normalizeEquipArguments(equipmentSlot, options = {}, command = {}) {
|
|
1606
|
+
if (equipmentSlot && typeof equipmentSlot === "object") {
|
|
1607
|
+
return {equipmentSlot: null, split: Boolean(equipmentSlot.split), command: options || {}};
|
|
1608
|
+
}
|
|
1609
|
+
return {equipmentSlot, split: Boolean(options?.split), command};
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
function inferEquipmentSlotForInventorySource(domain, source) {
|
|
1613
|
+
const handle = source instanceof InventorySlotHandle ? source : domain.slot(source);
|
|
1614
|
+
if (!handle.exists() || handle.itemId == null) throw new RangeError(`inventory slot ${handle.index} is empty; pass equipmentSlot explicitly`);
|
|
1615
|
+
const equipmentSlot = itemEquipmentSlotFromId(handle.itemId);
|
|
1616
|
+
if (!equipmentSlot) {
|
|
1617
|
+
const label = handle.itemName ? ` (${handle.itemName})` : "";
|
|
1618
|
+
throw new RangeError(`item ${handle.itemId}${label} does not map to an equipment slot; pass equipmentSlot explicitly`);
|
|
1619
|
+
}
|
|
1620
|
+
return equipmentSlot;
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
function inventoryHandlesForArea(domain, area = "all") {
|
|
1624
|
+
switch (area) {
|
|
1625
|
+
case "all":
|
|
1626
|
+
return domain.allSlots();
|
|
1627
|
+
case "hotbar":
|
|
1628
|
+
return domain.hotbarSlots();
|
|
1629
|
+
case "equipment":
|
|
1630
|
+
return Object.values(domain.equipmentSlots());
|
|
1631
|
+
default:
|
|
1632
|
+
throw new RangeError(`Unknown inventory area: ${area}`);
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1636
|
+
export const WrenchMode = Object.freeze({
|
|
1637
|
+
DropAllItems: "drop-all-items",
|
|
1638
|
+
GrabPrimaryItems: "grab-primary-items",
|
|
1639
|
+
GrabAllItems: "grab-all-items"
|
|
1640
|
+
});
|
|
1641
|
+
|
|
1642
|
+
const WRENCH_MODES = new Map([
|
|
1643
|
+
[0, WrenchMode.DropAllItems],
|
|
1644
|
+
[1, WrenchMode.GrabPrimaryItems],
|
|
1645
|
+
[2, WrenchMode.GrabAllItems]
|
|
1646
|
+
]);
|
|
1647
|
+
|
|
1648
|
+
const WRENCH_MODE_VALUES = new Map([...WRENCH_MODES].map(([value, name]) => [name, value]));
|
|
1649
|
+
|
|
1650
|
+
export const TurretMode = Object.freeze({
|
|
1651
|
+
ContinuousFire: "continuous-fire",
|
|
1652
|
+
VolleyFire: "volley-fire"
|
|
1653
|
+
});
|
|
1654
|
+
|
|
1655
|
+
const TURRET_MODES = new Map([
|
|
1656
|
+
[0, TurretMode.ContinuousFire],
|
|
1657
|
+
[1, TurretMode.VolleyFire]
|
|
1658
|
+
]);
|
|
1659
|
+
|
|
1660
|
+
const TURRET_MODE_VALUES = new Map([...TURRET_MODES].map(([value, name]) => [name, value]));
|
|
1661
|
+
|
|
1662
|
+
function wrenchModeName(value) {
|
|
1663
|
+
return WRENCH_MODES.get(value) ?? null;
|
|
1664
|
+
}
|
|
1665
|
+
|
|
1666
|
+
function turretModeName(value) {
|
|
1667
|
+
return TURRET_MODES.get(value) ?? null;
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1670
|
+
export function normalizeWrenchMode(value) {
|
|
1671
|
+
const normalized = WRENCH_MODE_VALUES.get(value);
|
|
1672
|
+
if (normalized == null || !WRENCH_MODES.has(normalized)) {
|
|
1673
|
+
throw new RangeError(`Unknown wrench mode: ${value}`);
|
|
1674
|
+
}
|
|
1675
|
+
return normalized;
|
|
1676
|
+
}
|
|
1677
|
+
|
|
1678
|
+
export function normalizeTurretMode(value) {
|
|
1679
|
+
const normalized = TURRET_MODE_VALUES.get(value);
|
|
1680
|
+
if (normalized == null || !TURRET_MODES.has(normalized)) {
|
|
1681
|
+
throw new RangeError(`Unknown turret mode: ${value}`);
|
|
1682
|
+
}
|
|
1683
|
+
return normalized;
|
|
1684
|
+
}
|
|
1685
|
+
|
|
1686
|
+
export function normalizePositiveFinite(value, name) {
|
|
1687
|
+
const number = Number(value);
|
|
1688
|
+
if (!Number.isFinite(number) || number <= 0) throw new RangeError(`${name} must be a positive finite number`);
|
|
1689
|
+
return number;
|
|
1690
|
+
}
|
|
1691
|
+
|
|
1692
|
+
export function normalizePositiveInteger(value, name) {
|
|
1693
|
+
const number = Number(value);
|
|
1694
|
+
if (!Number.isInteger(number) || number <= 0) throw new RangeError(`${name} must be a positive integer`);
|
|
1695
|
+
return number;
|
|
1696
|
+
}
|
|
1697
|
+
|
|
1698
|
+
export function normalizeDegrees(value) {
|
|
1699
|
+
const number = Number(value);
|
|
1700
|
+
if (!Number.isFinite(number)) throw new RangeError(`angle must be a finite number`);
|
|
1701
|
+
return ((Math.round(number) % 360) + 360) % 360;
|
|
1702
|
+
}
|
|
1703
|
+
|
|
1704
|
+
export function normalizeLauncherPower(value) {
|
|
1705
|
+
const number = Number(value);
|
|
1706
|
+
if (!Number.isInteger(number) || number < 0 || number > 30) {
|
|
1707
|
+
throw new RangeError(`launcher power must be an integer between 0 and 30`);
|
|
1708
|
+
}
|
|
1709
|
+
return number;
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1712
|
+
export function normalizeScannerResultPacket(packet) {
|
|
1713
|
+
const manifest = packet?.manifest && typeof packet.manifest === "object" ? packet.manifest : {};
|
|
1714
|
+
const hasMaterials = manifest.materials && typeof manifest.materials === "object";
|
|
1715
|
+
const hasManifest = (
|
|
1716
|
+
(manifest.blocks && typeof manifest.blocks === "object") ||
|
|
1717
|
+
(manifest.objects && typeof manifest.objects === "object") ||
|
|
1718
|
+
(manifest.inventories && typeof manifest.inventories === "object")
|
|
1719
|
+
);
|
|
1720
|
+
return {
|
|
1721
|
+
kind: hasMaterials ? "bom" : hasManifest ? "manifest" : "unknown",
|
|
1722
|
+
sid: packet?.sid ?? null,
|
|
1723
|
+
shipHex: typeof manifest.ship_hex === "string" ? manifest.ship_hex : null,
|
|
1724
|
+
shipName: typeof manifest.ship_name === "string" ? manifest.ship_name : null,
|
|
1725
|
+
blocks: copyCountMap(manifest.blocks),
|
|
1726
|
+
objects: copyCountMap(manifest.objects),
|
|
1727
|
+
inventories: copyCountMap(manifest.inventories),
|
|
1728
|
+
materials: copyCountMap(manifest.materials)
|
|
1729
|
+
};
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
function copyCountMap(value) {
|
|
1733
|
+
if (!value || typeof value !== "object") return null;
|
|
1734
|
+
return Object.fromEntries(
|
|
1735
|
+
Object.entries(value)
|
|
1736
|
+
.filter(([, count]) => typeof count === "number")
|
|
1737
|
+
.map(([itemId, count]) => [String(itemId), count])
|
|
1738
|
+
);
|
|
1739
|
+
}
|
|
1740
|
+
|
|
1741
|
+
export function emptyMachineSummary() {
|
|
1742
|
+
return {
|
|
1743
|
+
itemHolders: [],
|
|
1744
|
+
health: [],
|
|
1745
|
+
fabricators: [],
|
|
1746
|
+
cargoEjectors: [],
|
|
1747
|
+
cannons: [],
|
|
1748
|
+
thrusters: [],
|
|
1749
|
+
pushers: [],
|
|
1750
|
+
pusherBeams: [],
|
|
1751
|
+
launchers: [],
|
|
1752
|
+
loaders: [],
|
|
1753
|
+
cargoHatches: [],
|
|
1754
|
+
navigationUnits: [],
|
|
1755
|
+
commsStations: [],
|
|
1756
|
+
fluidTanks: [],
|
|
1757
|
+
shieldGenerators: [],
|
|
1758
|
+
shieldProjectors: [],
|
|
1759
|
+
helms: [],
|
|
1760
|
+
signs: [],
|
|
1761
|
+
spawnPoints: [],
|
|
1762
|
+
doors: [],
|
|
1763
|
+
expandoBoxes: []
|
|
1764
|
+
};
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
export function normalizeShipReadOptions(options) {
|
|
1768
|
+
if (options == null || options === true) options = {};
|
|
1769
|
+
return {
|
|
1770
|
+
includeWorld: options.includeWorld !== false,
|
|
1771
|
+
includeTiles: Boolean(options.includeTiles),
|
|
1772
|
+
includeModel: Boolean(options.includeModel),
|
|
1773
|
+
includeBlocks: Boolean(options.includeBlocks),
|
|
1774
|
+
sort: options.sort ?? null
|
|
1775
|
+
};
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1778
|
+
export function shipReadSummary(entity, options, worlds, currentEntity = undefined) {
|
|
1779
|
+
const control = entity.contents.shipControl;
|
|
1780
|
+
const worldState = options.includeWorld && control.shipWorldId != null
|
|
1781
|
+
? worlds.worlds.get(Number(control.shipWorldId)) || null
|
|
1782
|
+
: null;
|
|
1783
|
+
const world = worldState ? worldState.snapshot({
|
|
1784
|
+
includeTiles: options.includeTiles,
|
|
1785
|
+
includeModel: options.includeModel,
|
|
1786
|
+
includeBlocks: options.includeBlocks
|
|
1787
|
+
}) : null;
|
|
1788
|
+
const current = currentEntity === undefined ? worlds.currentShipEntity() : currentEntity;
|
|
1789
|
+
const distance = distanceBetween(entity.transform, current?.transform);
|
|
1790
|
+
return {
|
|
1791
|
+
entity: entity.entity,
|
|
1792
|
+
name: control.name,
|
|
1793
|
+
hexCode: control.hexCode,
|
|
1794
|
+
color: control.color,
|
|
1795
|
+
colorCss: control.colorCss,
|
|
1796
|
+
position: entity.transform ? {x: entity.transform.x, y: entity.transform.y, rot: entity.transform.rot} : null,
|
|
1797
|
+
distance,
|
|
1798
|
+
footprint: entity.footprint,
|
|
1799
|
+
label: entity.label,
|
|
1800
|
+
kind: entity.kind,
|
|
1801
|
+
thrust: {
|
|
1802
|
+
x: control.thrustX,
|
|
1803
|
+
y: control.thrustY
|
|
1804
|
+
},
|
|
1805
|
+
shield: control.shield,
|
|
1806
|
+
warp: control.warp,
|
|
1807
|
+
worldId: control.shipWorldId,
|
|
1808
|
+
hasWorldData: Boolean(world),
|
|
1809
|
+
world,
|
|
1810
|
+
control,
|
|
1811
|
+
entitySummary: entity
|
|
1812
|
+
};
|
|
1813
|
+
}
|
|
1814
|
+
|
|
1815
|
+
function distanceBetween(a, b) {
|
|
1816
|
+
if (!a || !b || typeof a.x !== "number" || typeof a.y !== "number" || typeof b.x !== "number" || typeof b.y !== "number") return null;
|
|
1817
|
+
return Math.hypot(a.x - b.x, a.y - b.y);
|
|
1818
|
+
}
|