mcbe-ipc 3.1.3 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # MCBE-IPC 📡
2
2
 
3
- An IPC[^1] system for Minecraft Bedrock Edition Script API projects
3
+ An IPC[^1] system for MCBE Script API projects
4
4
 
5
5
  ## 🔗 Dependencies
6
6
 
@@ -23,4 +23,4 @@ npm install mcbe-ipc
23
23
 
24
24
 
25
25
 
26
- [^1]: Inter-Pack Communication
26
+ [^1]: Inter-Pack Communication
package/dist/ipc.d.ts CHANGED
@@ -27,6 +27,7 @@ export declare namespace PROTO {
27
27
  serialize(value: T, stream: Buffer): Generator<void, void, void>;
28
28
  deserialize(stream: Buffer): Generator<void, T, void>;
29
29
  }
30
+ type Infer<S> = S extends PROTO.Serializable<infer T> ? T : never;
30
31
  class Buffer {
31
32
  private _buffer;
32
33
  private _data_view;
@@ -36,8 +37,12 @@ export declare namespace PROTO {
36
37
  get front(): number;
37
38
  get data_view(): DataView;
38
39
  constructor(size?: number);
39
- write(...values: number[]): void;
40
- read(amount?: number): number[];
40
+ reserve(amount: number): number;
41
+ consume(amount: number): number;
42
+ write(byte: number): void;
43
+ write(bytes: Uint8Array): void;
44
+ read(): number;
45
+ read(amount: number): Uint8Array;
41
46
  ensure_capacity(size: number): void;
42
47
  static from_uint8array(array: Uint8Array): Buffer;
43
48
  to_uint8array(): Uint8Array;
@@ -56,22 +61,23 @@ export declare namespace PROTO {
56
61
  const UInt16: PROTO.Serializable<number>;
57
62
  const UInt32: PROTO.Serializable<number>;
58
63
  const UVarInt32: PROTO.Serializable<number>;
64
+ const VarInt32: PROTO.Serializable<number>;
59
65
  const Float32: PROTO.Serializable<number>;
60
66
  const Float64: PROTO.Serializable<number>;
61
67
  const String: PROTO.Serializable<string>;
62
68
  const Boolean: PROTO.Serializable<boolean>;
63
69
  const UInt8Array: PROTO.Serializable<Uint8Array>;
64
70
  const Date: PROTO.Serializable<Date>;
65
- function Object<T extends object>(obj: {
71
+ function Object<T extends object>(s: {
66
72
  [K in keyof T]: PROTO.Serializable<T[K]>;
67
73
  }): PROTO.Serializable<T>;
68
- function Array<T>(value: PROTO.Serializable<T>): PROTO.Serializable<T[]>;
69
- function Tuple<T extends any[]>(...values: {
74
+ function Array<T>(s: PROTO.Serializable<T>): PROTO.Serializable<T[]>;
75
+ function Tuple<T extends any[]>(...s: {
70
76
  [K in keyof T]: PROTO.Serializable<T[K]>;
71
77
  }): PROTO.Serializable<T>;
72
- function Optional<T>(value: PROTO.Serializable<T>): PROTO.Serializable<T | undefined>;
73
- function Map<K, V>(key: PROTO.Serializable<K>, value: PROTO.Serializable<V>): PROTO.Serializable<Map<K, V>>;
74
- function Set<V>(value: PROTO.Serializable<V>): PROTO.Serializable<Set<V>>;
78
+ function Optional<T>(s: PROTO.Serializable<T>): PROTO.Serializable<T | undefined>;
79
+ function Map<K, V>(kS: PROTO.Serializable<K>, vS: PROTO.Serializable<V>): PROTO.Serializable<Map<K, V>>;
80
+ function Set<V>(s: PROTO.Serializable<V>): PROTO.Serializable<Set<V>>;
75
81
  type Endpoint = string;
76
82
  type Header = {
77
83
  guid: string;
@@ -86,19 +92,19 @@ export declare namespace NET {
86
92
  let FRAG_MAX: number;
87
93
  function serialize(buffer: PROTO.Buffer, max_size?: number): Generator<void, string[], void>;
88
94
  function deserialize(strings: string[]): Generator<void, PROTO.Buffer, void>;
89
- function emit<S extends PROTO.Serializable<T>, T>(endpoint: string, serializer: S & PROTO.Serializable<T>, value: T): Generator<void, void, void>;
90
- function listen<T, S extends PROTO.Serializable<T>>(endpoint: string, serializer: S & PROTO.Serializable<T>, callback: (value: T) => Generator<void, void, void>): () => void;
95
+ function emit<S extends PROTO.Serializable<any>>(endpoint: string, serializer: S, value: PROTO.Infer<S>): Generator<void, void, void>;
96
+ function listen<S extends PROTO.Serializable<any>>(endpoint: string, serializer: S, callback: (value: PROTO.Infer<S>) => Generator<void, void, void>): () => void;
91
97
  }
92
98
  export declare namespace IPC {
93
99
  /** Sends a message with `args` to `channel` */
94
- function send<S extends PROTO.Serializable<T>, T>(channel: string, serializer: S & PROTO.Serializable<T>, value: T): void;
100
+ function send<S extends PROTO.Serializable<any>>(channel: string, serializer: S, value: PROTO.Infer<S>): void;
95
101
  /** Sends an `invoke` message through IPC, and expects a result asynchronously. */
96
- function invoke<TS extends PROTO.Serializable<T>, T, RS extends PROTO.Serializable<R>, R>(channel: string, serializer: TS & PROTO.Serializable<T>, value: T, deserializer: RS & PROTO.Serializable<R>): Promise<R>;
102
+ function invoke<S extends PROTO.Serializable<any>, D extends PROTO.Serializable<any>>(channel: string, serializer: S, value: PROTO.Infer<S>, deserializer: D): Promise<PROTO.Infer<D>>;
97
103
  /** Listens to `channel`. When a new message arrives, `listener` will be called with `listener(args)`. */
98
- function on<S extends PROTO.Serializable<T>, T>(channel: string, deserializer: S & PROTO.Serializable<T>, listener: (value: T) => void): () => void;
104
+ function on<D extends PROTO.Serializable<any>>(channel: string, deserializer: D, listener: (value: PROTO.Infer<D>) => void): () => void;
99
105
  /** Listens to `channel` once. When a new message arrives, `listener` will be called with `listener(args)`, and then removed. */
100
- function once<S extends PROTO.Serializable<T>, T>(channel: string, deserializer: S & PROTO.Serializable<T>, listener: (value: T) => void): () => void;
106
+ function once<D extends PROTO.Serializable<any>>(channel: string, deserializer: D, listener: (value: PROTO.Infer<D>) => void): () => void;
101
107
  /** Adds a handler for an `invoke` IPC. This handler will be called whenever `invoke(channel, ...args)` is called */
102
- function handle<TS extends PROTO.Serializable<T>, T, RS extends PROTO.Serializable<R>, R>(channel: string, deserializer: TS & PROTO.Serializable<T>, serializer: RS & PROTO.Serializable<R>, listener: (value: T) => R): () => void;
108
+ function handle<D extends PROTO.Serializable<any>, S extends PROTO.Serializable<any>>(channel: string, deserializer: D, serializer: S, listener: (value: PROTO.Infer<D>) => PROTO.Infer<S>): () => void;
103
109
  }
104
110
  export default IPC;
package/dist/ipc.js CHANGED
@@ -41,20 +41,39 @@ export var PROTO;
41
41
  this._length = 0;
42
42
  this._offset = 0;
43
43
  }
44
- write(...values) {
45
- this.ensure_capacity(values.length);
46
- this._buffer.set(values, this.end);
47
- this._length += values.length;
48
- }
49
- read(amount = 1) {
50
- if (this._length > 0) {
51
- const max_amount = amount > this._length ? this._length : amount;
52
- const values = this._buffer.subarray(this._offset, this._offset + max_amount);
53
- this._length -= max_amount;
54
- this._offset += max_amount;
55
- return globalThis.Array.from(values);
44
+ reserve(amount) {
45
+ this.ensure_capacity(amount);
46
+ const end = this.end;
47
+ this._length += amount;
48
+ return end;
49
+ }
50
+ consume(amount) {
51
+ if (amount > this._length)
52
+ throw new Error('not enough bytes');
53
+ const front = this.front;
54
+ this._length -= amount;
55
+ this._offset += amount;
56
+ return front;
57
+ }
58
+ write(input) {
59
+ if (typeof input === 'number') {
60
+ const offset = this.reserve(1);
61
+ this._buffer[offset] = input;
62
+ }
63
+ else {
64
+ const offset = this.reserve(input.length);
65
+ this._buffer.set(input, offset);
66
+ }
67
+ }
68
+ read(amount) {
69
+ if (amount === undefined) {
70
+ const offset = this.consume(1);
71
+ return this._buffer[offset];
72
+ }
73
+ else {
74
+ const offset = this.consume(amount);
75
+ return this._buffer.slice(offset, offset + amount);
56
76
  }
57
- return [];
58
77
  }
59
78
  ensure_capacity(size) {
60
79
  if (this.end + size > this._buffer.length) {
@@ -125,120 +144,98 @@ export var PROTO;
125
144
  };
126
145
  PROTO.Int8 = {
127
146
  *serialize(value, stream) {
128
- const length = 1;
129
- stream.write(...globalThis.Array(length).fill(0));
130
- stream.data_view.setInt8(stream.end - length, value);
147
+ stream.data_view.setInt8(stream.reserve(1), value);
131
148
  },
132
149
  *deserialize(stream) {
133
- const value = stream.data_view.getInt8(stream.front);
134
- stream.read(1);
135
- return value;
150
+ return stream.data_view.getInt8(stream.consume(1));
136
151
  }
137
152
  };
138
153
  PROTO.Int16 = {
139
154
  *serialize(value, stream) {
140
- const length = 2;
141
- stream.write(...globalThis.Array(length).fill(0));
142
- stream.data_view.setInt16(stream.end - length, value);
155
+ stream.data_view.setInt16(stream.reserve(2), value);
143
156
  },
144
157
  *deserialize(stream) {
145
- const value = stream.data_view.getInt16(stream.front);
146
- stream.read(2);
147
- return value;
158
+ return stream.data_view.getInt16(stream.consume(2));
148
159
  }
149
160
  };
150
161
  PROTO.Int32 = {
151
162
  *serialize(value, stream) {
152
- const length = 4;
153
- stream.write(...globalThis.Array(length).fill(0));
154
- stream.data_view.setInt32(stream.end - length, value);
163
+ stream.data_view.setInt32(stream.reserve(4), value);
155
164
  },
156
165
  *deserialize(stream) {
157
- const value = stream.data_view.getInt32(stream.front);
158
- stream.read(4);
159
- return value;
166
+ return stream.data_view.getInt32(stream.consume(4));
160
167
  }
161
168
  };
162
169
  PROTO.UInt8 = {
163
170
  *serialize(value, stream) {
164
- const length = 1;
165
- stream.write(...globalThis.Array(length).fill(0));
166
- stream.data_view.setUint8(stream.end - length, value);
171
+ stream.data_view.setUint8(stream.reserve(1), value);
167
172
  },
168
173
  *deserialize(stream) {
169
- const value = stream.data_view.getUint8(stream.front);
170
- stream.read(1);
171
- return value;
174
+ return stream.data_view.getUint8(stream.consume(1));
172
175
  }
173
176
  };
174
177
  PROTO.UInt16 = {
175
178
  *serialize(value, stream) {
176
- const length = 2;
177
- stream.write(...globalThis.Array(length).fill(0));
178
- stream.data_view.setUint16(stream.end - length, value);
179
+ stream.data_view.setUint16(stream.reserve(2), value);
179
180
  },
180
181
  *deserialize(stream) {
181
- const value = stream.data_view.getUint16(stream.front);
182
- stream.read(2);
183
- return value;
182
+ return stream.data_view.getUint16(stream.consume(2));
184
183
  }
185
184
  };
186
185
  PROTO.UInt32 = {
187
186
  *serialize(value, stream) {
188
- const length = 4;
189
- stream.write(...globalThis.Array(length).fill(0));
190
- stream.data_view.setUint32(stream.end - length, value);
187
+ stream.data_view.setUint32(stream.reserve(4), value);
191
188
  },
192
189
  *deserialize(stream) {
193
- const value = stream.data_view.getUint32(stream.front);
194
- stream.read(4);
195
- return value;
190
+ return stream.data_view.getUint32(stream.consume(4));
196
191
  }
197
192
  };
198
193
  PROTO.UVarInt32 = {
199
194
  *serialize(value, stream) {
195
+ value >>>= 0;
200
196
  while (value >= 0x80) {
201
197
  stream.write((value & 0x7f) | 0x80);
202
- value >>= 7;
198
+ value >>>= 7;
203
199
  yield;
204
200
  }
205
201
  stream.write(value);
206
202
  },
207
203
  *deserialize(stream) {
208
204
  let value = 0;
209
- let size = 0;
210
- let byte;
211
- do {
212
- byte = stream.read()[0];
205
+ for (let size = 0; size < 5; size++) {
206
+ const byte = stream.read();
213
207
  value |= (byte & 0x7f) << (size * 7);
214
- size += 1;
215
208
  yield;
216
- } while ((byte & 0x80) !== 0 && size < 10);
217
- return value;
209
+ if ((byte & 0x80) == 0)
210
+ break;
211
+ }
212
+ return value >>> 0;
213
+ }
214
+ };
215
+ PROTO.VarInt32 = {
216
+ *serialize(value, stream) {
217
+ const zigzag = (value << 1) ^ (value >> 31);
218
+ yield* PROTO.UVarInt32.serialize(zigzag, stream);
219
+ },
220
+ *deserialize(stream) {
221
+ const zigzag = yield* PROTO.UVarInt32.deserialize(stream);
222
+ return (zigzag >>> 1) ^ -(zigzag & 1);
218
223
  }
219
224
  };
220
225
  PROTO.Float32 = {
221
226
  *serialize(value, stream) {
222
- const length = 4;
223
- stream.write(...globalThis.Array(length).fill(0));
224
- stream.data_view.setFloat32(stream.end - length, value);
227
+ stream.data_view.setFloat32(stream.reserve(4), value);
225
228
  },
226
229
  *deserialize(stream) {
227
- const value = stream.data_view.getFloat32(stream.front);
228
- stream.read(4);
229
- return value;
230
+ return stream.data_view.getFloat32(stream.consume(4));
230
231
  }
231
232
  };
232
233
  PROTO.Float64 = {
233
234
  *serialize(value, stream) {
234
- const length = 8;
235
- stream.write(...globalThis.Array(length).fill(0));
236
- stream.data_view.setFloat64(stream.end - length, value);
235
+ stream.data_view.setFloat64(stream.reserve(8), value);
237
236
  },
238
237
  *deserialize(stream) {
239
- const value = stream.data_view.getFloat64(stream.front);
240
- stream.read(8);
241
- return value;
238
+ return stream.data_view.getFloat64(stream.consume(8));
242
239
  }
243
240
  };
244
241
  PROTO.String = {
@@ -264,18 +261,17 @@ export var PROTO;
264
261
  stream.write(value ? 1 : 0);
265
262
  },
266
263
  *deserialize(stream) {
267
- const value = stream.read()[0];
268
- return value === 1;
264
+ return stream.read() !== 0;
269
265
  }
270
266
  };
271
267
  PROTO.UInt8Array = {
272
268
  *serialize(value, stream) {
273
269
  yield* PROTO.UVarInt32.serialize(value.length, stream);
274
- stream.write(...value);
270
+ stream.write(value);
275
271
  },
276
272
  *deserialize(stream) {
277
273
  const length = yield* PROTO.UVarInt32.deserialize(stream);
278
- return new Uint8Array(stream.read(length));
274
+ return stream.read(length);
279
275
  }
280
276
  };
281
277
  PROTO.Date = {
@@ -286,92 +282,91 @@ export var PROTO;
286
282
  return new globalThis.Date(yield* PROTO.Float64.deserialize(stream));
287
283
  }
288
284
  };
289
- function Object(obj) {
285
+ function Object(s) {
290
286
  return {
291
287
  *serialize(value, stream) {
292
- for (const key in obj) {
293
- yield* obj[key].serialize(value[key], stream);
288
+ for (const key in s) {
289
+ yield* s[key].serialize(value[key], stream);
294
290
  }
295
291
  },
296
292
  *deserialize(stream) {
297
293
  const result = {};
298
- for (const key in obj) {
299
- result[key] = yield* obj[key].deserialize(stream);
294
+ for (const key in s) {
295
+ result[key] = yield* s[key].deserialize(stream);
300
296
  }
301
297
  return result;
302
298
  }
303
299
  };
304
300
  }
305
301
  PROTO.Object = Object;
306
- function Array(value) {
302
+ function Array(s) {
307
303
  return {
308
- *serialize(array, stream) {
309
- yield* PROTO.UVarInt32.serialize(array.length, stream);
310
- for (const item of array) {
311
- yield* value.serialize(item, stream);
304
+ *serialize(value, stream) {
305
+ yield* PROTO.UVarInt32.serialize(value.length, stream);
306
+ for (const item of value) {
307
+ yield* s.serialize(item, stream);
312
308
  }
313
309
  },
314
310
  *deserialize(stream) {
315
311
  const result = [];
316
312
  const length = yield* PROTO.UVarInt32.deserialize(stream);
317
313
  for (let i = 0; i < length; i++) {
318
- result[i] = yield* value.deserialize(stream);
314
+ result[i] = yield* s.deserialize(stream);
319
315
  }
320
316
  return result;
321
317
  }
322
318
  };
323
319
  }
324
320
  PROTO.Array = Array;
325
- function Tuple(...values) {
321
+ function Tuple(...s) {
326
322
  return {
327
- *serialize(tuple, stream) {
328
- for (let i = 0; i < values.length; i++) {
329
- yield* values[i].serialize(tuple[i], stream);
323
+ *serialize(value, stream) {
324
+ for (let i = 0; i < s.length; i++) {
325
+ yield* s[i].serialize(value[i], stream);
330
326
  }
331
327
  },
332
328
  *deserialize(stream) {
333
329
  const result = [];
334
- for (let i = 0; i < values.length; i++) {
335
- result[i] = yield* values[i].deserialize(stream);
330
+ for (let i = 0; i < s.length; i++) {
331
+ result[i] = yield* s[i].deserialize(stream);
336
332
  }
337
333
  return result;
338
334
  }
339
335
  };
340
336
  }
341
337
  PROTO.Tuple = Tuple;
342
- function Optional(value) {
338
+ function Optional(s) {
343
339
  return {
344
- *serialize(optional, stream) {
345
- yield* PROTO.Boolean.serialize(optional !== undefined, stream);
346
- if (optional !== undefined) {
347
- yield* value.serialize(optional, stream);
348
- }
340
+ *serialize(value, stream) {
341
+ const def = value !== undefined;
342
+ yield* PROTO.Boolean.serialize(def, stream);
343
+ if (def)
344
+ yield* s.serialize(value, stream);
349
345
  },
350
346
  *deserialize(stream) {
351
- const defined = yield* PROTO.Boolean.deserialize(stream);
352
- if (defined) {
353
- return yield* value.deserialize(stream);
354
- }
347
+ const def = yield* PROTO.Boolean.deserialize(stream);
348
+ if (def)
349
+ return yield* s.deserialize(stream);
355
350
  return undefined;
356
351
  }
357
352
  };
358
353
  }
359
354
  PROTO.Optional = Optional;
360
- function Map(key, value) {
355
+ function Map(kS, vS) {
361
356
  return {
362
- *serialize(map, stream) {
363
- yield* PROTO.UVarInt32.serialize(map.size, stream);
364
- for (const [k, v] of map.entries()) {
365
- yield* key.serialize(k, stream);
366
- yield* value.serialize(v, stream);
357
+ *serialize(value, stream) {
358
+ yield* PROTO.UVarInt32.serialize(value.size, stream);
359
+ for (const [k, v] of value) {
360
+ yield* kS.serialize(k, stream);
361
+ yield* vS.serialize(v, stream);
367
362
  }
368
363
  },
369
364
  *deserialize(stream) {
370
365
  const size = yield* PROTO.UVarInt32.deserialize(stream);
371
366
  const result = new globalThis.Map();
372
367
  for (let i = 0; i < size; i++) {
373
- const k = yield* key.deserialize(stream);
374
- const v = yield* value.deserialize(stream);
368
+ const k = yield* kS.deserialize(stream);
369
+ const v = yield* vS.deserialize(stream);
375
370
  result.set(k, v);
376
371
  }
377
372
  return result;
@@ -379,19 +374,19 @@ export var PROTO;
379
374
  };
380
375
  }
381
376
  PROTO.Map = Map;
382
- function Set(value) {
377
+ function Set(s) {
383
378
  return {
384
379
  *serialize(set, stream) {
385
380
  yield* PROTO.UVarInt32.serialize(set.size, stream);
386
- for (const [_, v] of set.entries()) {
387
- yield* value.serialize(v, stream);
381
+ for (const v of set) {
382
+ yield* s.serialize(v, stream);
388
383
  }
389
384
  },
390
385
  *deserialize(stream) {
391
386
  const size = yield* PROTO.UVarInt32.deserialize(stream);
392
387
  const result = new globalThis.Set();
393
388
  for (let i = 0; i < size; i++) {
394
- const v = yield* value.deserialize(stream);
389
+ const v = yield* s.deserialize(stream);
395
390
  result.add(v);
396
391
  }
397
392
  return result;
@@ -465,16 +460,26 @@ export var NET;
465
460
  NET.deserialize = deserialize;
466
461
  system.afterEvents.scriptEventReceive.subscribe(event => {
467
462
  system.runJob((function* () {
463
+ if (event.sourceType !== ScriptEventSource.Server)
464
+ return;
468
465
  const [serialized_endpoint, serialized_header] = event.id.split(':');
469
466
  const endpoint_stream = yield* PROTO.MIPS.deserialize(serialized_endpoint);
470
467
  const endpoint = yield* PROTO.Endpoint.deserialize(endpoint_stream);
471
468
  const listeners = ENDPOINTS.get(endpoint);
472
- if (event.sourceType === ScriptEventSource.Server && listeners) {
469
+ if (listeners !== undefined) {
473
470
  const header_stream = yield* PROTO.MIPS.deserialize(serialized_header);
474
471
  const header = yield* PROTO.Header.deserialize(header_stream);
472
+ const errors = [];
475
473
  for (let i = 0; i < listeners.length; i++) {
476
- yield* listeners[i](header, event.message);
474
+ try {
475
+ yield* listeners[i](header, event.message);
476
+ }
477
+ catch (e) {
478
+ errors.push(e);
479
+ }
477
480
  }
481
+ if (errors.length > 0)
482
+ throw new AggregateError(errors, 'one or more listeners failed');
478
483
  }
479
484
  })());
480
485
  });
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "author": "OmniacDev",
4
4
  "description": "IPC system for MCBE Script API projects",
5
5
  "license": "MIT",
6
- "version": "3.1.3",
6
+ "version": "3.2.0",
7
7
  "repository": {
8
8
  "type": "git",
9
9
  "url": "git+https://github.com/OmniacDev/MCBE-IPC.git"