mcbe-ipc 3.2.1 → 3.3.1
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 +1 -1
- package/README.md +1 -1
- package/dist/ipc.d.ts +51 -53
- package/dist/ipc.js +83 -50
- package/package.json +1 -1
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ npm install mcbe-ipc
|
|
|
27
27
|
> [!NOTE]
|
|
28
28
|
> Official documentation is still in progress.
|
|
29
29
|
>
|
|
30
|
-
> For now, you can
|
|
30
|
+
> For now, you can [](https://deepwiki.com/OmniacDev/MCBE-IPC).
|
|
31
31
|
> Please note that while it is generally accurate, some of the more advanced sections may contain small inaccuracies.
|
|
32
32
|
|
|
33
33
|
|
package/dist/ipc.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @license
|
|
3
3
|
* MIT License
|
|
4
4
|
*
|
|
5
|
-
* Copyright (c)
|
|
5
|
+
* Copyright (c) 2026 OmniacDev
|
|
6
6
|
*
|
|
7
7
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
8
|
* of this software and associated documentation files (the "Software"), to deal
|
|
@@ -23,20 +23,15 @@
|
|
|
23
23
|
* SOFTWARE.
|
|
24
24
|
*/
|
|
25
25
|
export declare namespace PROTO {
|
|
26
|
-
|
|
27
|
-
interface Phantom<T> {
|
|
28
|
-
readonly [t]?: T;
|
|
29
|
-
}
|
|
30
|
-
export interface Serializer<T> extends Phantom<T> {
|
|
26
|
+
interface Serializer<T> {
|
|
31
27
|
serialize(value: T, stream: Buffer): Generator<void, void, void>;
|
|
32
28
|
}
|
|
33
|
-
|
|
29
|
+
interface Deserializer<T> {
|
|
34
30
|
deserialize(stream: Buffer): Generator<void, T, void>;
|
|
35
31
|
}
|
|
36
|
-
|
|
32
|
+
interface Serializable<T> extends Serializer<T>, Deserializer<T> {
|
|
37
33
|
}
|
|
38
|
-
|
|
39
|
-
export class Buffer {
|
|
34
|
+
class Buffer {
|
|
40
35
|
private _buffer;
|
|
41
36
|
private _data_view;
|
|
42
37
|
private _length;
|
|
@@ -55,65 +50,68 @@ export declare namespace PROTO {
|
|
|
55
50
|
static from_uint8array(array: Uint8Array): Buffer;
|
|
56
51
|
to_uint8array(): Uint8Array;
|
|
57
52
|
}
|
|
58
|
-
|
|
53
|
+
namespace MIPS {
|
|
59
54
|
function serialize(stream: PROTO.Buffer): Generator<void, string, void>;
|
|
60
55
|
function deserialize(str: string): Generator<void, PROTO.Buffer, void>;
|
|
61
56
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
57
|
+
const Void: PROTO.Serializable<void>;
|
|
58
|
+
const Null: PROTO.Serializable<null>;
|
|
59
|
+
const Undefined: PROTO.Serializable<undefined>;
|
|
60
|
+
const Int8: PROTO.Serializable<number>;
|
|
61
|
+
const Int16: PROTO.Serializable<number>;
|
|
62
|
+
const Int32: PROTO.Serializable<number>;
|
|
63
|
+
const UInt8: PROTO.Serializable<number>;
|
|
64
|
+
const UInt16: PROTO.Serializable<number>;
|
|
65
|
+
const UInt32: PROTO.Serializable<number>;
|
|
66
|
+
const UVarInt32: PROTO.Serializable<number>;
|
|
67
|
+
const VarInt32: PROTO.Serializable<number>;
|
|
68
|
+
const Float32: PROTO.Serializable<number>;
|
|
69
|
+
const Float64: PROTO.Serializable<number>;
|
|
70
|
+
const String: PROTO.Serializable<string>;
|
|
71
|
+
const Boolean: PROTO.Serializable<boolean>;
|
|
72
|
+
const UInt8Array: PROTO.Serializable<Uint8Array>;
|
|
73
|
+
const Date: PROTO.Serializable<Date>;
|
|
74
|
+
function Object<T extends object>(s: {
|
|
80
75
|
[K in keyof T]: PROTO.Serializable<T[K]>;
|
|
81
76
|
}): PROTO.Serializable<T>;
|
|
82
|
-
|
|
83
|
-
|
|
77
|
+
function Array<T>(s: PROTO.Serializable<T>): PROTO.Serializable<T[]>;
|
|
78
|
+
function Tuple<T extends any[]>(...s: {
|
|
84
79
|
[K in keyof T]: PROTO.Serializable<T[K]>;
|
|
85
80
|
}): PROTO.Serializable<T>;
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
81
|
+
function Optional<T>(s: PROTO.Serializable<T>): PROTO.Serializable<T | undefined>;
|
|
82
|
+
function Map<K, V>(kS: PROTO.Serializable<K>, vS: PROTO.Serializable<V>): PROTO.Serializable<Map<K, V>>;
|
|
83
|
+
function Set<V>(s: PROTO.Serializable<V>): PROTO.Serializable<Set<V>>;
|
|
84
|
+
}
|
|
85
|
+
export declare namespace NET {
|
|
86
|
+
type Meta = {
|
|
91
87
|
guid: string;
|
|
92
|
-
|
|
93
|
-
index: number;
|
|
94
|
-
final: boolean;
|
|
88
|
+
signature: string;
|
|
95
89
|
};
|
|
96
|
-
|
|
97
|
-
export const
|
|
90
|
+
const Meta: PROTO.Serializable<Meta>;
|
|
91
|
+
export const SIGNATURE: string;
|
|
92
|
+
export let FRAG_MAX: number;
|
|
93
|
+
export function serialize(buffer: PROTO.Buffer, max_size?: number): Generator<void, string[], void>;
|
|
94
|
+
export function deserialize(strings: string[]): Generator<void, PROTO.Buffer, void>;
|
|
95
|
+
export interface EmitOptions {
|
|
96
|
+
metaOverride?: Partial<Meta>;
|
|
97
|
+
}
|
|
98
|
+
export function emit<S>(endpoint: string, serializer: PROTO.Serializer<S>, value: NoInfer<S>, options?: EmitOptions): Generator<void, void, void>;
|
|
99
|
+
export interface ListenOptions {
|
|
100
|
+
filter?: (meta: Meta) => boolean;
|
|
101
|
+
}
|
|
102
|
+
export function listen<D>(endpoint: string, deserializer: PROTO.Deserializer<D>, callback: (value: NoInfer<D>, meta: Meta) => Generator<void, void, void>, options?: ListenOptions): () => void;
|
|
98
103
|
export {};
|
|
99
104
|
}
|
|
100
|
-
export declare namespace NET {
|
|
101
|
-
let FRAG_MAX: number;
|
|
102
|
-
function serialize(buffer: PROTO.Buffer, max_size?: number): Generator<void, string[], void>;
|
|
103
|
-
function deserialize(strings: string[]): Generator<void, PROTO.Buffer, void>;
|
|
104
|
-
function emit<S extends PROTO.Serializer<any>>(endpoint: string, serializer: S, value: PROTO.Infer<S>): Generator<void, void, void>;
|
|
105
|
-
function listen<D extends PROTO.Deserializer<any>>(endpoint: string, deserializer: D, callback: (value: PROTO.Infer<D>) => Generator<void, void, void>): () => void;
|
|
106
|
-
}
|
|
107
105
|
export declare namespace IPC {
|
|
108
106
|
/** Sends a message with `args` to `channel` */
|
|
109
|
-
function send<S
|
|
107
|
+
function send<S>(channel: string, serializer: PROTO.Serializer<S>, value: NoInfer<S>): void;
|
|
110
108
|
/** Sends an `invoke` message through IPC, and expects a result asynchronously. */
|
|
111
|
-
function invoke<S
|
|
109
|
+
function invoke<S, D>(channel: string, serializer: PROTO.Serializer<S>, value: NoInfer<S>, deserializer: PROTO.Deserializer<D>): Promise<NoInfer<D>>;
|
|
112
110
|
/** Listens to `channel`. When a new message arrives, `listener` will be called with `listener(args)`. */
|
|
113
|
-
function on<D
|
|
111
|
+
function on<D>(channel: string, deserializer: PROTO.Deserializer<D>, listener: (value: NoInfer<D>) => void): () => void;
|
|
114
112
|
/** Listens to `channel` once. When a new message arrives, `listener` will be called with `listener(args)`, and then removed. */
|
|
115
|
-
function once<D
|
|
113
|
+
function once<D>(channel: string, deserializer: PROTO.Deserializer<D>, listener: (value: NoInfer<D>) => void): () => void;
|
|
116
114
|
/** Adds a handler for an `invoke` IPC. This handler will be called whenever `invoke(channel, ...args)` is called */
|
|
117
|
-
function handle<D
|
|
115
|
+
function handle<D, S>(channel: string, deserializer: PROTO.Deserializer<D>, serializer: PROTO.Serializer<S>, listener: (value: NoInfer<D>) => NoInfer<S>): () => void;
|
|
118
116
|
}
|
|
119
117
|
export default IPC;
|
package/dist/ipc.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @license
|
|
3
3
|
* MIT License
|
|
4
4
|
*
|
|
5
|
-
* Copyright (c)
|
|
5
|
+
* Copyright (c) 2026 OmniacDev
|
|
6
6
|
*
|
|
7
7
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
8
|
* of this software and associated documentation files (the "Software"), to deal
|
|
@@ -23,6 +23,14 @@
|
|
|
23
23
|
* SOFTWARE.
|
|
24
24
|
*/
|
|
25
25
|
import { ScriptEventSource, system } from '@minecraft/server';
|
|
26
|
+
var UTIL;
|
|
27
|
+
(function (UTIL) {
|
|
28
|
+
function generate_id() {
|
|
29
|
+
const r = (Math.random() * 0x100000000) >>> 0;
|
|
30
|
+
return r.toString(16).padStart(8, '0').toUpperCase();
|
|
31
|
+
}
|
|
32
|
+
UTIL.generate_id = generate_id;
|
|
33
|
+
})(UTIL || (UTIL = {}));
|
|
26
34
|
export var PROTO;
|
|
27
35
|
(function (PROTO) {
|
|
28
36
|
class Buffer {
|
|
@@ -394,19 +402,22 @@ export var PROTO;
|
|
|
394
402
|
};
|
|
395
403
|
}
|
|
396
404
|
PROTO.Set = Set;
|
|
397
|
-
|
|
398
|
-
|
|
405
|
+
})(PROTO || (PROTO = {}));
|
|
406
|
+
export var NET;
|
|
407
|
+
(function (NET) {
|
|
408
|
+
const Endpoint = PROTO.String;
|
|
409
|
+
const Meta = PROTO.Object({
|
|
399
410
|
guid: PROTO.String,
|
|
400
|
-
|
|
411
|
+
signature: PROTO.String
|
|
412
|
+
});
|
|
413
|
+
const Header = PROTO.Object({
|
|
414
|
+
meta: Meta,
|
|
401
415
|
index: PROTO.UVarInt32,
|
|
402
416
|
final: PROTO.Boolean
|
|
403
417
|
});
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
(function (NET) {
|
|
418
|
+
const LISTENERS = new Map();
|
|
419
|
+
NET.SIGNATURE = 'mcbe-ipc:v3';
|
|
407
420
|
NET.FRAG_MAX = 2048;
|
|
408
|
-
const ENCODING = 'mcbe-ipc:v3';
|
|
409
|
-
const ENDPOINTS = new Map();
|
|
410
421
|
function* serialize(buffer, max_size = Infinity) {
|
|
411
422
|
const uint8array = buffer.to_uint8array();
|
|
412
423
|
const result = [];
|
|
@@ -464,15 +475,15 @@ export var NET;
|
|
|
464
475
|
return;
|
|
465
476
|
const [serialized_endpoint, serialized_header] = event.id.split(':');
|
|
466
477
|
const endpoint_stream = yield* PROTO.MIPS.deserialize(serialized_endpoint);
|
|
467
|
-
const endpoint = yield*
|
|
468
|
-
const listeners =
|
|
478
|
+
const endpoint = yield* Endpoint.deserialize(endpoint_stream);
|
|
479
|
+
const listeners = LISTENERS.get(endpoint);
|
|
469
480
|
if (listeners !== undefined) {
|
|
470
481
|
const header_stream = yield* PROTO.MIPS.deserialize(serialized_header);
|
|
471
|
-
const header = yield*
|
|
482
|
+
const header = yield* Header.deserialize(header_stream);
|
|
472
483
|
const errors = [];
|
|
473
|
-
for (
|
|
484
|
+
for (const listener of [...listeners]) {
|
|
474
485
|
try {
|
|
475
|
-
yield*
|
|
486
|
+
yield* listener(header, event.message);
|
|
476
487
|
}
|
|
477
488
|
catch (e) {
|
|
478
489
|
errors.push(e);
|
|
@@ -483,11 +494,11 @@ export var NET;
|
|
|
483
494
|
}
|
|
484
495
|
})());
|
|
485
496
|
});
|
|
486
|
-
function
|
|
487
|
-
let listeners =
|
|
488
|
-
if (
|
|
497
|
+
function register(endpoint, listener) {
|
|
498
|
+
let listeners = LISTENERS.get(endpoint);
|
|
499
|
+
if (listeners === undefined) {
|
|
489
500
|
listeners = new Array();
|
|
490
|
-
|
|
501
|
+
LISTENERS.set(endpoint, listeners);
|
|
491
502
|
}
|
|
492
503
|
listeners.push(listener);
|
|
493
504
|
return () => {
|
|
@@ -495,56 +506,61 @@ export var NET;
|
|
|
495
506
|
if (idx !== -1)
|
|
496
507
|
listeners.splice(idx, 1);
|
|
497
508
|
if (listeners.length === 0) {
|
|
498
|
-
|
|
509
|
+
LISTENERS.delete(endpoint);
|
|
499
510
|
}
|
|
500
511
|
};
|
|
501
512
|
}
|
|
502
|
-
function
|
|
503
|
-
const
|
|
504
|
-
|
|
505
|
-
((r >> 8) & 0xff).toString(16).padStart(2, '0') +
|
|
506
|
-
((r >> 16) & 0xff).toString(16).padStart(2, '0') +
|
|
507
|
-
((r >> 24) & 0xff).toString(16).padStart(2, '0')).toUpperCase();
|
|
508
|
-
}
|
|
509
|
-
function* emit(endpoint, serializer, value) {
|
|
510
|
-
const guid = generate_id();
|
|
513
|
+
function* emit(endpoint, serializer, value, options) {
|
|
514
|
+
const guid = options?.metaOverride?.guid ?? UTIL.generate_id();
|
|
515
|
+
const signature = options?.metaOverride?.signature ?? NET.SIGNATURE;
|
|
511
516
|
const endpoint_stream = new PROTO.Buffer();
|
|
512
|
-
yield*
|
|
517
|
+
yield* Endpoint.serialize(endpoint, endpoint_stream);
|
|
513
518
|
const serialized_endpoint = yield* PROTO.MIPS.serialize(endpoint_stream);
|
|
514
519
|
const packet_stream = new PROTO.Buffer();
|
|
515
520
|
yield* serializer.serialize(value, packet_stream);
|
|
516
521
|
const serialized_packets = yield* serialize(packet_stream, NET.FRAG_MAX);
|
|
517
522
|
for (let i = 0; i < serialized_packets.length; i++) {
|
|
518
523
|
const serialized_packet = serialized_packets[i];
|
|
519
|
-
const header = {
|
|
524
|
+
const header = {
|
|
525
|
+
meta: { guid, signature },
|
|
526
|
+
index: i,
|
|
527
|
+
final: i === serialized_packets.length - 1
|
|
528
|
+
};
|
|
520
529
|
const header_stream = new PROTO.Buffer();
|
|
521
|
-
yield*
|
|
530
|
+
yield* Header.serialize(header, header_stream);
|
|
522
531
|
const serialized_header = yield* PROTO.MIPS.serialize(header_stream);
|
|
523
532
|
system.sendScriptEvent(`${serialized_endpoint}:${serialized_header}`, serialized_packet);
|
|
524
533
|
}
|
|
525
534
|
}
|
|
526
535
|
NET.emit = emit;
|
|
527
|
-
function listen(endpoint, deserializer, callback) {
|
|
536
|
+
function listen(endpoint, deserializer, callback, options) {
|
|
528
537
|
const buffer = new Map();
|
|
529
|
-
const listener = function* (
|
|
530
|
-
let
|
|
531
|
-
if (
|
|
532
|
-
|
|
533
|
-
|
|
538
|
+
const listener = function* (header, fragment) {
|
|
539
|
+
let packet = buffer.get(header.meta.guid);
|
|
540
|
+
if (packet === undefined) {
|
|
541
|
+
if (options?.filter?.(header.meta) === false)
|
|
542
|
+
return;
|
|
543
|
+
packet = { size: -1, fragments: [], received: 0 };
|
|
544
|
+
buffer.set(header.meta.guid, packet);
|
|
534
545
|
}
|
|
535
|
-
if (
|
|
536
|
-
|
|
546
|
+
if (header.final) {
|
|
547
|
+
packet.size = header.index + 1;
|
|
537
548
|
}
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
549
|
+
if (packet.fragments[header.index] === undefined) {
|
|
550
|
+
packet.fragments[header.index] = fragment;
|
|
551
|
+
packet.received++;
|
|
552
|
+
}
|
|
553
|
+
else {
|
|
554
|
+
throw new Error(`received duplicate fragment ${header.index} for packet ${header.meta.guid}`);
|
|
555
|
+
}
|
|
556
|
+
if (packet.size !== -1 && packet.size === packet.received) {
|
|
557
|
+
const stream = yield* deserialize(packet.fragments);
|
|
542
558
|
const value = yield* deserializer.deserialize(stream);
|
|
543
|
-
yield* callback(value);
|
|
544
|
-
buffer.delete(
|
|
559
|
+
yield* callback(value, header.meta);
|
|
560
|
+
buffer.delete(header.meta.guid);
|
|
545
561
|
}
|
|
546
562
|
};
|
|
547
|
-
return
|
|
563
|
+
return register(endpoint, listener);
|
|
548
564
|
}
|
|
549
565
|
NET.listen = listen;
|
|
550
566
|
})(NET || (NET = {}));
|
|
@@ -557,12 +573,22 @@ export var IPC;
|
|
|
557
573
|
IPC.send = send;
|
|
558
574
|
/** Sends an `invoke` message through IPC, and expects a result asynchronously. */
|
|
559
575
|
function invoke(channel, serializer, value, deserializer) {
|
|
576
|
+
const id = UTIL.generate_id();
|
|
560
577
|
return new Promise(resolve => {
|
|
561
|
-
const terminate = NET.listen(`ipc:${channel}:handle`, deserializer, function* (value) {
|
|
578
|
+
const terminate = NET.listen(`ipc:${channel}:handle`, deserializer, function* (value, meta) {
|
|
579
|
+
if (meta.signature.includes(`+correlation`) && meta.guid !== id)
|
|
580
|
+
return;
|
|
562
581
|
resolve(value);
|
|
563
582
|
terminate();
|
|
583
|
+
}, {
|
|
584
|
+
filter: meta => !meta.signature.includes(`+correlation`) || meta.guid === id
|
|
564
585
|
});
|
|
565
|
-
system.runJob(NET.emit(`ipc:${channel}:invoke`, serializer, value
|
|
586
|
+
system.runJob(NET.emit(`ipc:${channel}:invoke`, serializer, value, {
|
|
587
|
+
metaOverride: {
|
|
588
|
+
guid: id,
|
|
589
|
+
signature: `${NET.SIGNATURE}+correlation`
|
|
590
|
+
}
|
|
591
|
+
}));
|
|
566
592
|
});
|
|
567
593
|
}
|
|
568
594
|
IPC.invoke = invoke;
|
|
@@ -584,9 +610,16 @@ export var IPC;
|
|
|
584
610
|
IPC.once = once;
|
|
585
611
|
/** Adds a handler for an `invoke` IPC. This handler will be called whenever `invoke(channel, ...args)` is called */
|
|
586
612
|
function handle(channel, deserializer, serializer, listener) {
|
|
587
|
-
return NET.listen(`ipc:${channel}:invoke`, deserializer, function* (value) {
|
|
613
|
+
return NET.listen(`ipc:${channel}:invoke`, deserializer, function* (value, meta) {
|
|
588
614
|
const result = listener(value);
|
|
589
|
-
yield* NET.emit(`ipc:${channel}:handle`, serializer, result
|
|
615
|
+
yield* NET.emit(`ipc:${channel}:handle`, serializer, result, {
|
|
616
|
+
metaOverride: meta.signature.includes(`+correlation`)
|
|
617
|
+
? {
|
|
618
|
+
guid: meta.guid,
|
|
619
|
+
signature: `${NET.SIGNATURE}+correlation`
|
|
620
|
+
}
|
|
621
|
+
: undefined
|
|
622
|
+
});
|
|
590
623
|
});
|
|
591
624
|
}
|
|
592
625
|
IPC.handle = handle;
|
package/package.json
CHANGED