@xpgamesllc/ipcs-be 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -674
- package/README.md +20 -11
- package/dist/index.d.mts +40 -8
- package/dist/index.d.ts +40 -8
- package/dist/index.js +201 -34
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +199 -35
- package/dist/index.mjs.map +1 -1
- package/package.json +51 -52
package/README.md
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
|
-
# ipcs-be
|
|
2
|
-
|
|
3
|
-
A set of standardized types and functions for interacting with other Minecraft Bedrock Edition add-ons.
|
|
4
|
-
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
##
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
# ipcs-be
|
|
2
|
+
|
|
3
|
+
A set of standardized types and functions for interacting with other Minecraft Bedrock Edition add-ons.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
The pack must depend on `@minecraft/server` 2.10.0 or newer in its manifest (stable or beta).
|
|
8
|
+
|
|
9
|
+
## Logging
|
|
10
|
+
|
|
11
|
+
Warnings (invalid hello packets, errors thrown by listeners) are wrapped in a `DEBUG:` label. Strip them in
|
|
12
|
+
release builds by dropping the label in your bundler, e.g. esbuild `dropLabels: ["DEBUG"]`.
|
|
13
|
+
|
|
14
|
+
## Contributing
|
|
15
|
+
|
|
16
|
+
Feel free to raise an issue or submit a pull request if you have any improvements or features to suggest.
|
|
17
|
+
|
|
18
|
+
## License
|
|
19
|
+
|
|
20
|
+
This project is licensed under the MIT License.
|
package/dist/index.d.mts
CHANGED
|
@@ -1,20 +1,52 @@
|
|
|
1
|
+
interface SendOptions {
|
|
2
|
+
encoding?: string;
|
|
3
|
+
/** message UUID: 32 hex digits, hyphens allowed, any case */
|
|
4
|
+
id?: string;
|
|
5
|
+
/** with a callback: stop waiting for the response after this many ticks (default Net.ResponseTimeoutTicks) */
|
|
6
|
+
timeoutTicks?: number;
|
|
7
|
+
/** with a callback: called once when no response came in time */
|
|
8
|
+
onTimeout?: () => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
1
11
|
declare function setVersion(v: number): void;
|
|
2
12
|
/**
|
|
3
13
|
* Send a script event, fragmenting JSON/text payload if needed. Optionally receive a response.
|
|
4
14
|
* @param channel - The script-event channel to send to.
|
|
5
15
|
* @param payload - The payload to send.
|
|
6
|
-
* @param opts - Optional encoding and
|
|
7
|
-
* @param callback - Optional callback to receive a response.
|
|
16
|
+
* @param opts - Optional encoding, message ID, and response timeout (`timeoutTicks`, `onTimeout`).
|
|
17
|
+
* @param callback - Optional callback to receive a response. It is dropped after the timeout.
|
|
8
18
|
*/
|
|
9
|
-
declare function send(channel: string, payload: any, opts?:
|
|
10
|
-
encoding?: string;
|
|
11
|
-
id?: string;
|
|
12
|
-
}, callback?: (response: any) => void): void;
|
|
19
|
+
declare function send(channel: string, payload: any, opts?: SendOptions, callback?: (response: any) => void): string;
|
|
13
20
|
/**
|
|
14
21
|
* Subscribe to reassembled messages on a channel.
|
|
15
22
|
* @param channel - The script-event channel to subscribe to.
|
|
16
23
|
* @param cb - The callback to invoke when a message is received.
|
|
17
24
|
*/
|
|
18
|
-
declare function on(channel: string, cb: (payload: any, respond?: (resp: any) => void) => void): void;
|
|
25
|
+
declare function on(channel: string, cb: (id: string, payload: any, respond?: (resp: any) => void) => void): void;
|
|
26
|
+
/**
|
|
27
|
+
* Unsubscribe a callback registered with `on`.
|
|
28
|
+
* @param channel - The script-event channel.
|
|
29
|
+
* @param cb - The same callback that was passed to `on`.
|
|
30
|
+
*/
|
|
31
|
+
declare function off(channel: string, cb: (id: string, payload: any, respond?: (resp: any) => void) => void): void;
|
|
32
|
+
interface InitData {
|
|
33
|
+
/**
|
|
34
|
+
* The pack name.
|
|
35
|
+
*/
|
|
36
|
+
packName: string;
|
|
37
|
+
/**
|
|
38
|
+
* The pack author.
|
|
39
|
+
*/
|
|
40
|
+
packAuthor: string;
|
|
41
|
+
}
|
|
42
|
+
interface KnownPack {
|
|
43
|
+
name: string;
|
|
44
|
+
author: string;
|
|
45
|
+
}
|
|
46
|
+
declare function init(data: InitData): void;
|
|
47
|
+
/**
|
|
48
|
+
* Get the currently known packs.
|
|
49
|
+
*/
|
|
50
|
+
declare function getKnownPacks(): KnownPack[];
|
|
19
51
|
|
|
20
|
-
export { on, send, setVersion };
|
|
52
|
+
export { InitData, KnownPack, SendOptions, getKnownPacks, init, off, on, send, setVersion };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,20 +1,52 @@
|
|
|
1
|
+
interface SendOptions {
|
|
2
|
+
encoding?: string;
|
|
3
|
+
/** message UUID: 32 hex digits, hyphens allowed, any case */
|
|
4
|
+
id?: string;
|
|
5
|
+
/** with a callback: stop waiting for the response after this many ticks (default Net.ResponseTimeoutTicks) */
|
|
6
|
+
timeoutTicks?: number;
|
|
7
|
+
/** with a callback: called once when no response came in time */
|
|
8
|
+
onTimeout?: () => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
1
11
|
declare function setVersion(v: number): void;
|
|
2
12
|
/**
|
|
3
13
|
* Send a script event, fragmenting JSON/text payload if needed. Optionally receive a response.
|
|
4
14
|
* @param channel - The script-event channel to send to.
|
|
5
15
|
* @param payload - The payload to send.
|
|
6
|
-
* @param opts - Optional encoding and
|
|
7
|
-
* @param callback - Optional callback to receive a response.
|
|
16
|
+
* @param opts - Optional encoding, message ID, and response timeout (`timeoutTicks`, `onTimeout`).
|
|
17
|
+
* @param callback - Optional callback to receive a response. It is dropped after the timeout.
|
|
8
18
|
*/
|
|
9
|
-
declare function send(channel: string, payload: any, opts?:
|
|
10
|
-
encoding?: string;
|
|
11
|
-
id?: string;
|
|
12
|
-
}, callback?: (response: any) => void): void;
|
|
19
|
+
declare function send(channel: string, payload: any, opts?: SendOptions, callback?: (response: any) => void): string;
|
|
13
20
|
/**
|
|
14
21
|
* Subscribe to reassembled messages on a channel.
|
|
15
22
|
* @param channel - The script-event channel to subscribe to.
|
|
16
23
|
* @param cb - The callback to invoke when a message is received.
|
|
17
24
|
*/
|
|
18
|
-
declare function on(channel: string, cb: (payload: any, respond?: (resp: any) => void) => void): void;
|
|
25
|
+
declare function on(channel: string, cb: (id: string, payload: any, respond?: (resp: any) => void) => void): void;
|
|
26
|
+
/**
|
|
27
|
+
* Unsubscribe a callback registered with `on`.
|
|
28
|
+
* @param channel - The script-event channel.
|
|
29
|
+
* @param cb - The same callback that was passed to `on`.
|
|
30
|
+
*/
|
|
31
|
+
declare function off(channel: string, cb: (id: string, payload: any, respond?: (resp: any) => void) => void): void;
|
|
32
|
+
interface InitData {
|
|
33
|
+
/**
|
|
34
|
+
* The pack name.
|
|
35
|
+
*/
|
|
36
|
+
packName: string;
|
|
37
|
+
/**
|
|
38
|
+
* The pack author.
|
|
39
|
+
*/
|
|
40
|
+
packAuthor: string;
|
|
41
|
+
}
|
|
42
|
+
interface KnownPack {
|
|
43
|
+
name: string;
|
|
44
|
+
author: string;
|
|
45
|
+
}
|
|
46
|
+
declare function init(data: InitData): void;
|
|
47
|
+
/**
|
|
48
|
+
* Get the currently known packs.
|
|
49
|
+
*/
|
|
50
|
+
declare function getKnownPacks(): KnownPack[];
|
|
19
51
|
|
|
20
|
-
export { on, send, setVersion };
|
|
52
|
+
export { InitData, KnownPack, SendOptions, getKnownPacks, init, off, on, send, setVersion };
|
package/dist/index.js
CHANGED
|
@@ -20,6 +20,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var src_exports = {};
|
|
22
22
|
__export(src_exports, {
|
|
23
|
+
getKnownPacks: () => getKnownPacks,
|
|
24
|
+
init: () => init,
|
|
25
|
+
off: () => off,
|
|
23
26
|
on: () => on,
|
|
24
27
|
send: () => send,
|
|
25
28
|
setVersion: () => setVersion
|
|
@@ -393,6 +396,45 @@ var Net = class _Net {
|
|
|
393
396
|
static buffers = /* @__PURE__ */ new Map();
|
|
394
397
|
static encoders = /* @__PURE__ */ new Map();
|
|
395
398
|
static DefaultEncoding = "text";
|
|
399
|
+
/** a partial message is dropped when no fragment arrived for this long */
|
|
400
|
+
static BufferTimeoutMs = 1e4;
|
|
401
|
+
/** at most this many partial messages are kept; a new one drops the oldest */
|
|
402
|
+
static MaxBuffers = 64;
|
|
403
|
+
/** fragment indices at or above this are refused */
|
|
404
|
+
static MaxFragments = 4096;
|
|
405
|
+
/** how long send() waits for a response by default (20 ticks = 1 s) */
|
|
406
|
+
static ResponseTimeoutTicks = 200;
|
|
407
|
+
/** the engine only passes script events of these namespaces to the script */
|
|
408
|
+
static namespaces = /* @__PURE__ */ new Set(["ipcs"]);
|
|
409
|
+
static handler;
|
|
410
|
+
/** (re)subscribe to script events with the current namespace filter; the old handler works until the new one is in */
|
|
411
|
+
static subscribe(retry = true) {
|
|
412
|
+
const signal = import_server.system.afterEvents.scriptEventReceive;
|
|
413
|
+
const handler = (evt) => _Net.handleScriptEvent(evt.id, evt.message);
|
|
414
|
+
try {
|
|
415
|
+
signal.subscribe(handler, { namespaces: [..._Net.namespaces] });
|
|
416
|
+
} catch (e) {
|
|
417
|
+
if (retry) {
|
|
418
|
+
import_server.system.run(() => _Net.subscribe(false));
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
DEBUG: {
|
|
422
|
+
console.warn(`IPCS-BE: could not subscribe to script events: ${e}`);
|
|
423
|
+
}
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
if (_Net.handler)
|
|
427
|
+
signal.unsubscribe(_Net.handler);
|
|
428
|
+
_Net.handler = handler;
|
|
429
|
+
}
|
|
430
|
+
static watchNamespace(channel) {
|
|
431
|
+
const namespace = channel.split(":")[0];
|
|
432
|
+
if (_Net.namespaces.has(namespace))
|
|
433
|
+
return;
|
|
434
|
+
_Net.namespaces.add(namespace);
|
|
435
|
+
if (_Net.handler)
|
|
436
|
+
_Net.subscribe();
|
|
437
|
+
}
|
|
396
438
|
/**
|
|
397
439
|
* Register a new encoder implementation by its unique name.
|
|
398
440
|
*/
|
|
@@ -401,32 +443,37 @@ var Net = class _Net {
|
|
|
401
443
|
}
|
|
402
444
|
/** fire a script event, fragmenting JSON/text payload if needed. Optionally receive a response. */
|
|
403
445
|
static send(channel, payload, opts, callback) {
|
|
446
|
+
const id = (opts?.id ?? makeUUID()).replace(/-/g, "").toLowerCase();
|
|
447
|
+
if (!/^[0-9a-f]{32}$/.test(id))
|
|
448
|
+
throw new Error(`Invalid message id "${opts?.id}": expected a UUID`);
|
|
449
|
+
return _Net.sendWithId(channel, payload, id, opts, callback);
|
|
450
|
+
}
|
|
451
|
+
/** responses reuse the request id as it came, older versions did not check it */
|
|
452
|
+
static sendWithId(channel, payload, id, opts, callback) {
|
|
404
453
|
const encodingName = opts?.encoding ?? _Net.DefaultEncoding;
|
|
405
454
|
const encoder = _Net.encoders.get(encodingName);
|
|
406
455
|
if (!encoder)
|
|
407
456
|
throw new Error(`Unknown encoder: ${encodingName}`);
|
|
408
457
|
const raw = encoder.encode(payload);
|
|
409
|
-
const id = (opts?.id ?? makeUUID()).replace(/-/g, "");
|
|
410
458
|
if (callback) {
|
|
411
459
|
const respChannel = `ipcs:${id}`;
|
|
412
|
-
const wrapper = (respPayload) => {
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
_Net.off(respChannel, wrapper);
|
|
417
|
-
}
|
|
460
|
+
const wrapper = (id2, respPayload) => {
|
|
461
|
+
import_server.system.clearRun(timer);
|
|
462
|
+
_Net.off(respChannel, wrapper);
|
|
463
|
+
callback(respPayload);
|
|
418
464
|
};
|
|
419
465
|
_Net.on(respChannel, wrapper);
|
|
466
|
+
const timer = import_server.system.runTimeout(() => {
|
|
467
|
+
_Net.off(respChannel, wrapper);
|
|
468
|
+
opts?.onTimeout?.();
|
|
469
|
+
}, opts?.timeoutTicks ?? _Net.ResponseTimeoutTicks);
|
|
420
470
|
}
|
|
421
471
|
const totalLen = raw.length;
|
|
422
|
-
const metaPart = `${SPEC_VERSION}|${encodingName}`;
|
|
423
472
|
let chunks = [];
|
|
424
473
|
const meta = { version: SPEC_VERSION, encoding: encodingName };
|
|
425
474
|
const metaLength = getEnvelopeLength(meta);
|
|
426
475
|
const noFragHdr = encoder.encodeHeader({ id });
|
|
427
|
-
|
|
428
|
-
const noFragOverhead = metaPart.length + RS.length + ETX.length + noFragHdrLen;
|
|
429
|
-
if (totalLen + noFragOverhead + metaLength <= MAX_CHUNK) {
|
|
476
|
+
if (totalLen + noFragHdr.length + metaLength <= MAX_CHUNK) {
|
|
430
477
|
chunks = [[noFragHdr, raw]];
|
|
431
478
|
} else {
|
|
432
479
|
let i = 0;
|
|
@@ -454,12 +501,14 @@ var Net = class _Net {
|
|
|
454
501
|
import_server.system.sendScriptEvent(channel, envelope);
|
|
455
502
|
}
|
|
456
503
|
}
|
|
504
|
+
return id;
|
|
457
505
|
}
|
|
458
506
|
/** subscribe to reassembled messages on a channel */
|
|
459
507
|
static on(channel, cb) {
|
|
460
508
|
const arr = _Net.listeners.get(channel) ?? [];
|
|
461
509
|
arr.push(cb);
|
|
462
510
|
_Net.listeners.set(channel, arr);
|
|
511
|
+
_Net.watchNamespace(channel);
|
|
463
512
|
}
|
|
464
513
|
/** unsubscribe a callback from a channel */
|
|
465
514
|
static off(channel, cb) {
|
|
@@ -481,18 +530,25 @@ var Net = class _Net {
|
|
|
481
530
|
try {
|
|
482
531
|
if (id && !channel.startsWith("ipcs:")) {
|
|
483
532
|
const respond = (responsePayload) => {
|
|
484
|
-
_Net.
|
|
533
|
+
_Net.sendWithId(`ipcs:${id}`, responsePayload, id, { encoding: encodingName });
|
|
485
534
|
};
|
|
486
|
-
cb(payload, respond);
|
|
535
|
+
cb(id, payload, respond);
|
|
536
|
+
} else if (id) {
|
|
537
|
+
cb(id, payload);
|
|
487
538
|
} else {
|
|
488
|
-
|
|
539
|
+
throw new Error(`No ID provided for channel ${channel}`);
|
|
540
|
+
}
|
|
541
|
+
} catch (e) {
|
|
542
|
+
DEBUG: {
|
|
543
|
+
console.warn(`IPCS-BE: listener on ${channel} threw: ${e}`);
|
|
489
544
|
}
|
|
490
|
-
} catch {
|
|
491
545
|
}
|
|
492
546
|
}
|
|
493
547
|
}
|
|
494
548
|
/** internal dispatcher: parse envelope, reassemble if needed, then fire user-cb */
|
|
495
549
|
static handleScriptEvent(channel, raw) {
|
|
550
|
+
if (!_Net.listeners.has(channel))
|
|
551
|
+
return;
|
|
496
552
|
const [metaPart, rest] = raw.split(RS, 2);
|
|
497
553
|
if (!rest)
|
|
498
554
|
return;
|
|
@@ -515,29 +571,56 @@ var Net = class _Net {
|
|
|
515
571
|
_Net.dispatch(channel, payload, id, encodingName);
|
|
516
572
|
return;
|
|
517
573
|
}
|
|
518
|
-
|
|
574
|
+
if (!Number.isInteger(frag) || frag < 0 || frag >= _Net.MaxFragments)
|
|
575
|
+
return;
|
|
576
|
+
const now = Date.now();
|
|
577
|
+
_Net.dropStale(now);
|
|
578
|
+
const key = `${channel}|${id}`;
|
|
579
|
+
let buf = _Net.buffers.get(key);
|
|
519
580
|
if (!buf) {
|
|
520
|
-
|
|
521
|
-
|
|
581
|
+
if (_Net.buffers.size >= _Net.MaxBuffers)
|
|
582
|
+
_Net.dropOldest();
|
|
583
|
+
buf = { parts: [], received: 0, touched: now };
|
|
584
|
+
_Net.buffers.set(key, buf);
|
|
522
585
|
}
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
};
|
|
529
|
-
if (header.last) {
|
|
586
|
+
buf.touched = now;
|
|
587
|
+
if (buf.parts[frag] === void 0) {
|
|
588
|
+
buf.parts[frag] = body;
|
|
589
|
+
buf.received++;
|
|
590
|
+
if (last)
|
|
530
591
|
buf.lastIndex = frag;
|
|
531
|
-
}
|
|
532
592
|
}
|
|
533
|
-
if (buf.lastIndex !== void 0 && buf.
|
|
534
|
-
const full = buf.parts.
|
|
535
|
-
_Net.buffers.delete(
|
|
593
|
+
if (buf.lastIndex !== void 0 && buf.received === buf.lastIndex + 1) {
|
|
594
|
+
const full = buf.parts.join("");
|
|
595
|
+
_Net.buffers.delete(key);
|
|
536
596
|
const payload = encoder.decode(full);
|
|
537
597
|
if (payload !== null)
|
|
538
598
|
_Net.dispatch(channel, payload, id, encodingName);
|
|
539
599
|
}
|
|
540
600
|
}
|
|
601
|
+
/** drop partial messages that got no fragment for BufferTimeoutMs */
|
|
602
|
+
static dropStale(now) {
|
|
603
|
+
for (const [key, buf] of _Net.buffers) {
|
|
604
|
+
if (now - buf.touched > _Net.BufferTimeoutMs)
|
|
605
|
+
_Net.buffers.delete(key);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
static dropOldest() {
|
|
609
|
+
let oldestKey;
|
|
610
|
+
let oldest = Infinity;
|
|
611
|
+
for (const [key, buf] of _Net.buffers) {
|
|
612
|
+
if (buf.touched < oldest) {
|
|
613
|
+
oldest = buf.touched;
|
|
614
|
+
oldestKey = key;
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
if (oldestKey !== void 0)
|
|
618
|
+
_Net.buffers.delete(oldestKey);
|
|
619
|
+
}
|
|
620
|
+
/** number of partial messages waiting for fragments */
|
|
621
|
+
static pendingCount() {
|
|
622
|
+
return _Net.buffers.size;
|
|
623
|
+
}
|
|
541
624
|
};
|
|
542
625
|
Net.registerEncoder(new TextPacketEncoder());
|
|
543
626
|
Net.registerEncoder(new Base64PacketEncoder());
|
|
@@ -547,24 +630,108 @@ var version = 1;
|
|
|
547
630
|
var MaxVersion = 1;
|
|
548
631
|
var MinVersion = 1;
|
|
549
632
|
function setVersion(v) {
|
|
550
|
-
if (
|
|
551
|
-
throw new Error(`IPCS-BE spec version ${
|
|
633
|
+
if (v < MinVersion || v > MaxVersion) {
|
|
634
|
+
throw new Error(`IPCS-BE spec version ${v} is not supported`);
|
|
552
635
|
}
|
|
553
636
|
version = v;
|
|
554
637
|
}
|
|
555
638
|
function send(channel, payload, opts, callback) {
|
|
556
639
|
if (version === 1) {
|
|
557
|
-
Net.send(channel, payload,
|
|
640
|
+
return Net.send(channel, payload, {
|
|
641
|
+
...opts,
|
|
642
|
+
// By default, use the most preferred encoding
|
|
643
|
+
encoding: opts?.encoding ?? supportedEncodings[0]
|
|
644
|
+
}, callback);
|
|
558
645
|
}
|
|
646
|
+
throw new Error(`IPCS-BE spec version ${version} is not supported`);
|
|
559
647
|
}
|
|
560
648
|
function on(channel, cb) {
|
|
561
649
|
Net.on(channel, cb);
|
|
562
650
|
}
|
|
563
|
-
|
|
564
|
-
Net.
|
|
651
|
+
function off(channel, cb) {
|
|
652
|
+
Net.off(channel, cb);
|
|
653
|
+
}
|
|
654
|
+
Net.subscribe();
|
|
655
|
+
var initialized = false;
|
|
656
|
+
var KnownPacks = [];
|
|
657
|
+
var supportedEncodings = ["b64", "text"];
|
|
658
|
+
var HelloChannel = "ipcs:hello";
|
|
659
|
+
var worldLoaded = false;
|
|
660
|
+
var initData;
|
|
661
|
+
var helloId = "";
|
|
662
|
+
function init(data) {
|
|
663
|
+
if (initialized) {
|
|
664
|
+
throw new Error("IPCS-BE is already initialized");
|
|
665
|
+
}
|
|
666
|
+
initData = data;
|
|
667
|
+
helloId = makeUUID().replace(/-/g, "");
|
|
668
|
+
initialized = true;
|
|
669
|
+
if (worldLoaded)
|
|
670
|
+
import_server2.system.run(sendHello);
|
|
671
|
+
}
|
|
672
|
+
function sendHello() {
|
|
673
|
+
if (!initData)
|
|
674
|
+
return;
|
|
675
|
+
const packet = {
|
|
676
|
+
name: initData.packName,
|
|
677
|
+
author: initData.packAuthor,
|
|
678
|
+
// Adjusted according to the library
|
|
679
|
+
v: version,
|
|
680
|
+
enc: ["text", "b64"]
|
|
681
|
+
};
|
|
682
|
+
send(HelloChannel, packet, {
|
|
683
|
+
id: helloId,
|
|
684
|
+
encoding: "text"
|
|
685
|
+
});
|
|
686
|
+
}
|
|
687
|
+
import_server2.world.afterEvents.worldLoad.subscribe(() => {
|
|
688
|
+
worldLoaded = true;
|
|
689
|
+
sendHello();
|
|
690
|
+
});
|
|
691
|
+
on(HelloChannel, (id, payload) => {
|
|
692
|
+
if (id === helloId) {
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
695
|
+
const helloPayload = payload;
|
|
696
|
+
if (helloPayload.v > MaxVersion || helloPayload.v < MinVersion) {
|
|
697
|
+
warn(`Received hello packet with unsupported version ${helloPayload.v}`);
|
|
698
|
+
return;
|
|
699
|
+
}
|
|
700
|
+
if (!helloPayload.name || !helloPayload.author) {
|
|
701
|
+
warn("Received hello packet with missing name or author");
|
|
702
|
+
return;
|
|
703
|
+
}
|
|
704
|
+
if (!helloPayload.enc || !Array.isArray(helloPayload.enc) || helloPayload.enc.length === 0) {
|
|
705
|
+
warn("Received hello packet with missing or invalid encodings");
|
|
706
|
+
return;
|
|
707
|
+
}
|
|
708
|
+
for (const enc of [...supportedEncodings]) {
|
|
709
|
+
if (enc === "text")
|
|
710
|
+
continue;
|
|
711
|
+
if (!helloPayload.enc.includes(enc)) {
|
|
712
|
+
supportedEncodings = supportedEncodings.filter((e) => e !== enc);
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
const known = KnownPacks.some((p) => p.name === helloPayload.name && p.author === helloPayload.author);
|
|
716
|
+
if (!known)
|
|
717
|
+
KnownPacks.push({ name: helloPayload.name, author: helloPayload.author });
|
|
565
718
|
});
|
|
719
|
+
function getKnownPacks() {
|
|
720
|
+
if (!initialized) {
|
|
721
|
+
throw new Error("IPCS-BE is not initialized");
|
|
722
|
+
}
|
|
723
|
+
return KnownPacks.map((p) => ({ ...p }));
|
|
724
|
+
}
|
|
725
|
+
function warn(message) {
|
|
726
|
+
DEBUG: {
|
|
727
|
+
console.warn(message);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
566
730
|
// Annotate the CommonJS export names for ESM import in node:
|
|
567
731
|
0 && (module.exports = {
|
|
732
|
+
getKnownPacks,
|
|
733
|
+
init,
|
|
734
|
+
off,
|
|
568
735
|
on,
|
|
569
736
|
send,
|
|
570
737
|
setVersion
|