mcbe-ipc 2.0.1 → 3.0.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 -71
- package/dist/direct.ipc.d.ts +61 -0
- package/dist/direct.ipc.js +369 -0
- package/dist/ipc.d.ts +69 -56
- package/dist/ipc.js +492 -426
- package/dist/proto.d.ts +82 -0
- package/dist/proto.js +396 -0
- package/package.json +7 -7
- package/dist/ipc.min.js +0 -1
package/dist/ipc.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @license
|
|
3
3
|
* MIT License
|
|
4
4
|
*
|
|
5
|
-
* Copyright (c)
|
|
5
|
+
* Copyright (c) 2025 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
|
|
@@ -22,405 +22,455 @@
|
|
|
22
22
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
23
23
|
* SOFTWARE.
|
|
24
24
|
*/
|
|
25
|
-
import {
|
|
26
|
-
var
|
|
27
|
-
(function (
|
|
28
|
-
class
|
|
29
|
-
|
|
30
|
-
return this.
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return this.
|
|
34
|
-
}
|
|
35
|
-
get
|
|
36
|
-
return this.
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
this.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
this.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
25
|
+
import { ScriptEventSource, system, world } from '@minecraft/server';
|
|
26
|
+
export var PROTO;
|
|
27
|
+
(function (PROTO) {
|
|
28
|
+
class ByteQueue {
|
|
29
|
+
get end() {
|
|
30
|
+
return this._length + this._offset;
|
|
31
|
+
}
|
|
32
|
+
get front() {
|
|
33
|
+
return this._offset;
|
|
34
|
+
}
|
|
35
|
+
get data_view() {
|
|
36
|
+
return this._data_view;
|
|
37
|
+
}
|
|
38
|
+
constructor(size = 256) {
|
|
39
|
+
this._buffer = new Uint8Array(size);
|
|
40
|
+
this._data_view = new DataView(this._buffer.buffer);
|
|
41
|
+
this._length = 0;
|
|
42
|
+
this._offset = 0;
|
|
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);
|
|
56
|
+
}
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
ensure_capacity(size) {
|
|
60
|
+
if (this.end + size > this._buffer.length) {
|
|
61
|
+
const larger_buffer = new Uint8Array((this.end + size) * 2);
|
|
62
|
+
larger_buffer.set(this._buffer.subarray(this._offset, this.end), 0);
|
|
63
|
+
this._buffer = larger_buffer;
|
|
64
|
+
this._offset = 0;
|
|
65
|
+
this._data_view = new DataView(this._buffer.buffer);
|
|
53
66
|
}
|
|
54
67
|
}
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
68
|
+
static from_uint8array(array) {
|
|
69
|
+
const byte_queue = new ByteQueue();
|
|
70
|
+
byte_queue._buffer = array;
|
|
71
|
+
byte_queue._length = array.length;
|
|
72
|
+
byte_queue._offset = 0;
|
|
73
|
+
byte_queue._data_view = new DataView(array.buffer);
|
|
74
|
+
return byte_queue;
|
|
61
75
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
system.runJob((function* () {
|
|
65
|
-
const data = yield* $.MAYBE_ENCRYPT(args);
|
|
66
|
-
yield* NET.emit('ipc', `${$._to}:${channel}:invoke`, [$._from, data]);
|
|
67
|
-
})());
|
|
68
|
-
return new Promise(resolve => {
|
|
69
|
-
const terminate = NET.listen('ipc', `${$._from}:${channel}:handle`, function* (args) {
|
|
70
|
-
if (args[0] === $._to) {
|
|
71
|
-
const data = yield* $.MAYBE_DECRYPT(args);
|
|
72
|
-
resolve(data);
|
|
73
|
-
terminate();
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
});
|
|
76
|
+
to_uint8array() {
|
|
77
|
+
return this._buffer.subarray(this._offset, this.end);
|
|
77
78
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
79
|
+
}
|
|
80
|
+
PROTO.ByteQueue = ByteQueue;
|
|
81
|
+
let MIPS;
|
|
82
|
+
(function (MIPS) {
|
|
83
|
+
function* serialize(byte_queue) {
|
|
84
|
+
const uint8array = byte_queue.to_uint8array();
|
|
85
|
+
let str = '(0x';
|
|
86
|
+
for (let i = 0; i < uint8array.length; i++) {
|
|
87
|
+
const hex = uint8array[i].toString(16).padStart(2, '0').toUpperCase();
|
|
88
|
+
str += hex;
|
|
89
|
+
yield;
|
|
90
|
+
}
|
|
91
|
+
str += ')';
|
|
92
|
+
return str;
|
|
93
|
+
}
|
|
94
|
+
MIPS.serialize = serialize;
|
|
95
|
+
function* deserialize(str) {
|
|
96
|
+
if (str.startsWith('(0x') && str.endsWith(')')) {
|
|
97
|
+
const result = [];
|
|
98
|
+
const hex_str = str.slice(3, str.length - 1);
|
|
99
|
+
for (let i = 0; i < hex_str.length; i++) {
|
|
100
|
+
const hex = hex_str[i] + hex_str[++i];
|
|
101
|
+
result.push(parseInt(hex, 16));
|
|
102
|
+
yield;
|
|
84
103
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
return
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
104
|
+
return ByteQueue.from_uint8array(new Uint8Array(result));
|
|
105
|
+
}
|
|
106
|
+
return new ByteQueue();
|
|
107
|
+
}
|
|
108
|
+
MIPS.deserialize = deserialize;
|
|
109
|
+
})(MIPS = PROTO.MIPS || (PROTO.MIPS = {}));
|
|
110
|
+
PROTO.Void = {
|
|
111
|
+
*serialize() { },
|
|
112
|
+
*deserialize() { }
|
|
113
|
+
};
|
|
114
|
+
PROTO.Int8 = {
|
|
115
|
+
*serialize(value, stream) {
|
|
116
|
+
const length = 1;
|
|
117
|
+
stream.write(...globalThis.Array(length).fill(0));
|
|
118
|
+
stream.data_view.setInt8(stream.end - length, value);
|
|
119
|
+
},
|
|
120
|
+
*deserialize(stream) {
|
|
121
|
+
const value = stream.data_view.getInt8(stream.front);
|
|
122
|
+
stream.read(1);
|
|
123
|
+
return value;
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
PROTO.Int16 = {
|
|
127
|
+
*serialize(value, stream) {
|
|
128
|
+
const length = 2;
|
|
129
|
+
stream.write(...globalThis.Array(length).fill(0));
|
|
130
|
+
stream.data_view.setInt16(stream.end - length, value);
|
|
131
|
+
},
|
|
132
|
+
*deserialize(stream) {
|
|
133
|
+
const value = stream.data_view.getInt16(stream.front);
|
|
134
|
+
stream.read(2);
|
|
135
|
+
return value;
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
PROTO.Int32 = {
|
|
139
|
+
*serialize(value, stream) {
|
|
140
|
+
const length = 4;
|
|
141
|
+
stream.write(...globalThis.Array(length).fill(0));
|
|
142
|
+
stream.data_view.setInt32(stream.end - length, value);
|
|
143
|
+
},
|
|
144
|
+
*deserialize(stream) {
|
|
145
|
+
const value = stream.data_view.getInt32(stream.front);
|
|
146
|
+
stream.read(4);
|
|
147
|
+
return value;
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
PROTO.UInt8 = {
|
|
151
|
+
*serialize(value, stream) {
|
|
152
|
+
const length = 1;
|
|
153
|
+
stream.write(...globalThis.Array(length).fill(0));
|
|
154
|
+
stream.data_view.setUint8(stream.end - length, value);
|
|
155
|
+
},
|
|
156
|
+
*deserialize(stream) {
|
|
157
|
+
const value = stream.data_view.getUint8(stream.front);
|
|
158
|
+
stream.read(1);
|
|
159
|
+
return value;
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
PROTO.UInt16 = {
|
|
163
|
+
*serialize(value, stream) {
|
|
164
|
+
const length = 2;
|
|
165
|
+
stream.write(...globalThis.Array(length).fill(0));
|
|
166
|
+
stream.data_view.setUint16(stream.end - length, value);
|
|
167
|
+
},
|
|
168
|
+
*deserialize(stream) {
|
|
169
|
+
const value = stream.data_view.getUint16(stream.front);
|
|
170
|
+
stream.read(2);
|
|
171
|
+
return value;
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
PROTO.UInt32 = {
|
|
175
|
+
*serialize(value, stream) {
|
|
176
|
+
const length = 4;
|
|
177
|
+
stream.write(...globalThis.Array(length).fill(0));
|
|
178
|
+
stream.data_view.setUint32(stream.end - length, value);
|
|
179
|
+
},
|
|
180
|
+
*deserialize(stream) {
|
|
181
|
+
const value = stream.data_view.getUint32(stream.front);
|
|
182
|
+
stream.read(4);
|
|
183
|
+
return value;
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
PROTO.UVarInt32 = {
|
|
187
|
+
*serialize(value, stream) {
|
|
188
|
+
while (value >= 0x80) {
|
|
189
|
+
stream.write((value & 0x7f) | 0x80);
|
|
190
|
+
value >>= 7;
|
|
191
|
+
yield;
|
|
192
|
+
}
|
|
193
|
+
stream.write(value);
|
|
194
|
+
},
|
|
195
|
+
*deserialize(stream) {
|
|
196
|
+
let value = 0;
|
|
197
|
+
let size = 0;
|
|
198
|
+
let byte;
|
|
199
|
+
do {
|
|
200
|
+
byte = stream.read()[0];
|
|
201
|
+
value |= (byte & 0x7f) << (size * 7);
|
|
202
|
+
size += 1;
|
|
203
|
+
yield;
|
|
204
|
+
} while ((byte & 0x80) !== 0 && size < 10);
|
|
205
|
+
return value;
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
PROTO.Float32 = {
|
|
209
|
+
*serialize(value, stream) {
|
|
210
|
+
const length = 4;
|
|
211
|
+
stream.write(...globalThis.Array(length).fill(0));
|
|
212
|
+
stream.data_view.setFloat32(stream.end - length, value);
|
|
213
|
+
},
|
|
214
|
+
*deserialize(stream) {
|
|
215
|
+
const value = stream.data_view.getFloat32(stream.front);
|
|
216
|
+
stream.read(4);
|
|
217
|
+
return value;
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
PROTO.Float64 = {
|
|
221
|
+
*serialize(value, stream) {
|
|
222
|
+
const length = 8;
|
|
223
|
+
stream.write(...globalThis.Array(length).fill(0));
|
|
224
|
+
stream.data_view.setFloat64(stream.end - length, value);
|
|
225
|
+
},
|
|
226
|
+
*deserialize(stream) {
|
|
227
|
+
const value = stream.data_view.getFloat64(stream.front);
|
|
228
|
+
stream.read(8);
|
|
229
|
+
return value;
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
PROTO.String = {
|
|
233
|
+
*serialize(value, stream) {
|
|
234
|
+
yield* PROTO.UVarInt32.serialize(value.length, stream);
|
|
235
|
+
for (let i = 0; i < value.length; i++) {
|
|
236
|
+
const code = value.charCodeAt(i);
|
|
237
|
+
yield* PROTO.UVarInt32.serialize(code, stream);
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
*deserialize(stream) {
|
|
241
|
+
const length = yield* PROTO.UVarInt32.deserialize(stream);
|
|
242
|
+
let value = '';
|
|
243
|
+
for (let i = 0; i < length; i++) {
|
|
244
|
+
const code = yield* PROTO.UVarInt32.deserialize(stream);
|
|
245
|
+
value += globalThis.String.fromCharCode(code);
|
|
246
|
+
}
|
|
247
|
+
return value;
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
PROTO.Boolean = {
|
|
251
|
+
*serialize(value, stream) {
|
|
252
|
+
stream.write(value ? 1 : 0);
|
|
253
|
+
},
|
|
254
|
+
*deserialize(stream) {
|
|
255
|
+
const value = stream.read()[0];
|
|
256
|
+
return value === 1;
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
PROTO.UInt8Array = {
|
|
260
|
+
*serialize(value, stream) {
|
|
261
|
+
yield* PROTO.UVarInt32.serialize(value.length, stream);
|
|
262
|
+
stream.write(...value);
|
|
263
|
+
},
|
|
264
|
+
*deserialize(stream) {
|
|
265
|
+
const length = yield* PROTO.UVarInt32.deserialize(stream);
|
|
266
|
+
return new Uint8Array(stream.read(length));
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
PROTO.Date = {
|
|
270
|
+
*serialize(value, stream) {
|
|
271
|
+
yield* PROTO.Float64.serialize(value.getTime(), stream);
|
|
272
|
+
},
|
|
273
|
+
*deserialize(stream) {
|
|
274
|
+
return new globalThis.Date(yield* PROTO.Float64.deserialize(stream));
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
function Object(obj) {
|
|
278
|
+
return {
|
|
279
|
+
*serialize(value, stream) {
|
|
280
|
+
for (const key in obj) {
|
|
281
|
+
yield* obj[key].serialize(value[key], stream);
|
|
96
282
|
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const $ = this;
|
|
103
|
-
const terminate = NET.listen('ipc', `${$._from}:${channel}:invoke`, function* (args) {
|
|
104
|
-
if (args[0] === $._to) {
|
|
105
|
-
const data = yield* $.MAYBE_DECRYPT(args);
|
|
106
|
-
const result = listener(...data);
|
|
107
|
-
const return_data = yield* $.MAYBE_ENCRYPT([result]);
|
|
108
|
-
yield* NET.emit('ipc', `${$._to}:${channel}:handle`, [$._from, return_data]);
|
|
283
|
+
},
|
|
284
|
+
*deserialize(stream) {
|
|
285
|
+
const result = {};
|
|
286
|
+
for (const key in obj) {
|
|
287
|
+
result[key] = yield* obj[key].deserialize(stream);
|
|
109
288
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
289
|
+
return result;
|
|
290
|
+
}
|
|
291
|
+
};
|
|
114
292
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
get id() {
|
|
124
|
-
return this._id;
|
|
125
|
-
}
|
|
126
|
-
constructor(id, force_encryption = false) {
|
|
127
|
-
const $ = this;
|
|
128
|
-
this._id = id;
|
|
129
|
-
this._enc_map = new Map();
|
|
130
|
-
this._con_map = new Map();
|
|
131
|
-
this._enc_force = force_encryption;
|
|
132
|
-
NET.listen('ipc', `${this._id}:handshake:SYN`, function* (args) {
|
|
133
|
-
const secret = CRYPTO.make_secret(args[4]);
|
|
134
|
-
const public_key = yield* CRYPTO.make_public(secret, args[4], args[3]);
|
|
135
|
-
const enc = args[1] === 1 || $._enc_force ? yield* CRYPTO.make_shared(secret, args[2], args[3]) : false;
|
|
136
|
-
$._enc_map.set(args[0], enc);
|
|
137
|
-
yield* NET.emit('ipc', `${args[0]}:handshake:ACK`, [
|
|
138
|
-
$._id,
|
|
139
|
-
$._enc_force ? 1 : 0,
|
|
140
|
-
public_key
|
|
141
|
-
]);
|
|
142
|
-
});
|
|
143
|
-
NET.listen('ipc', `${this._id}:terminate`, function* (args) {
|
|
144
|
-
$._enc_map.delete(args[0]);
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
connect(to, encrypted = false, timeout = 20) {
|
|
148
|
-
const $ = this;
|
|
149
|
-
return new Promise((resolve, reject) => {
|
|
150
|
-
const con = this._con_map.get(to);
|
|
151
|
-
if (con !== undefined) {
|
|
152
|
-
con.terminate(false);
|
|
153
|
-
resolve(con);
|
|
293
|
+
PROTO.Object = Object;
|
|
294
|
+
function Array(value) {
|
|
295
|
+
return {
|
|
296
|
+
*serialize(array, stream) {
|
|
297
|
+
yield* PROTO.UVarInt32.serialize(array.length, stream);
|
|
298
|
+
for (const item of array) {
|
|
299
|
+
yield* value.serialize(item, stream);
|
|
154
300
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
$._id,
|
|
162
|
-
enc_flag,
|
|
163
|
-
public_key,
|
|
164
|
-
CRYPTO.PRIME,
|
|
165
|
-
CRYPTO.MOD
|
|
166
|
-
]);
|
|
167
|
-
})());
|
|
168
|
-
function clear() {
|
|
169
|
-
terminate();
|
|
170
|
-
system.clearRun(timeout_handle);
|
|
171
|
-
}
|
|
172
|
-
const timeout_handle = system.runTimeout(() => {
|
|
173
|
-
reject();
|
|
174
|
-
clear();
|
|
175
|
-
}, timeout);
|
|
176
|
-
const terminate = NET.listen('ipc', `${this._id}:handshake:ACK`, function* (args) {
|
|
177
|
-
if (args[0] === to) {
|
|
178
|
-
const enc = args[1] === 1 || encrypted ? yield* CRYPTO.make_shared(secret, args[2]) : false;
|
|
179
|
-
const new_con = new Connection($._id, to, enc);
|
|
180
|
-
$._con_map.set(to, new_con);
|
|
181
|
-
resolve(new_con);
|
|
182
|
-
clear();
|
|
183
|
-
}
|
|
184
|
-
});
|
|
301
|
+
},
|
|
302
|
+
*deserialize(stream) {
|
|
303
|
+
const result = [];
|
|
304
|
+
const length = yield* PROTO.UVarInt32.deserialize(stream);
|
|
305
|
+
for (let i = 0; i < length; i++) {
|
|
306
|
+
result[i] = yield* value.deserialize(stream);
|
|
185
307
|
}
|
|
186
|
-
|
|
187
|
-
}
|
|
188
|
-
send(channel, ...args) {
|
|
189
|
-
const $ = this;
|
|
190
|
-
system.runJob((function* () {
|
|
191
|
-
for (const [key, value] of $._enc_map) {
|
|
192
|
-
const data = yield* $.MAYBE_ENCRYPT(args, value);
|
|
193
|
-
yield* NET.emit('ipc', `${key}:${channel}:send`, [$._id, data]);
|
|
194
|
-
}
|
|
195
|
-
})());
|
|
196
|
-
}
|
|
197
|
-
invoke(channel, ...args) {
|
|
198
|
-
const $ = this;
|
|
199
|
-
const promises = [];
|
|
200
|
-
for (const [key, value] of $._enc_map) {
|
|
201
|
-
system.runJob((function* () {
|
|
202
|
-
const data = yield* $.MAYBE_ENCRYPT(args, value);
|
|
203
|
-
yield* NET.emit('ipc', `${key}:${channel}:invoke`, [$._id, data]);
|
|
204
|
-
})());
|
|
205
|
-
promises.push(new Promise(resolve => {
|
|
206
|
-
const terminate = NET.listen('ipc', `${$._id}:${channel}:handle`, function* (args) {
|
|
207
|
-
if (args[0] === key) {
|
|
208
|
-
const data = yield* $.MAYBE_DECRYPT(args, value);
|
|
209
|
-
resolve(data);
|
|
210
|
-
terminate();
|
|
211
|
-
}
|
|
212
|
-
});
|
|
213
|
-
}));
|
|
308
|
+
return result;
|
|
214
309
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
listener(...data);
|
|
224
|
-
}
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
once(channel, listener) {
|
|
228
|
-
const $ = this;
|
|
229
|
-
const terminate = NET.listen('ipc', `${$._id}:${channel}:send`, function* (args) {
|
|
230
|
-
const enc = $._enc_map.get(args[0]);
|
|
231
|
-
if (enc !== undefined) {
|
|
232
|
-
const data = yield* $.MAYBE_DECRYPT(args, enc);
|
|
233
|
-
listener(...data);
|
|
234
|
-
terminate();
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
PROTO.Array = Array;
|
|
313
|
+
function Tuple(...values) {
|
|
314
|
+
return {
|
|
315
|
+
*serialize(tuple, stream) {
|
|
316
|
+
for (let i = 0; i < values.length; i++) {
|
|
317
|
+
yield* values[i].serialize(tuple[i], stream);
|
|
235
318
|
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
return NET.listen('ipc', `${$._id}:${channel}:invoke`, function* (args) {
|
|
242
|
-
const enc = $._enc_map.get(args[0]);
|
|
243
|
-
if (enc !== undefined) {
|
|
244
|
-
const data = yield* $.MAYBE_DECRYPT(args, enc);
|
|
245
|
-
const result = listener(...data);
|
|
246
|
-
const return_data = yield* $.MAYBE_ENCRYPT([result], enc);
|
|
247
|
-
yield* NET.emit('ipc', `${args[0]}:${channel}:handle`, [$._id, return_data]);
|
|
319
|
+
},
|
|
320
|
+
*deserialize(stream) {
|
|
321
|
+
const result = [];
|
|
322
|
+
for (let i = 0; i < values.length; i++) {
|
|
323
|
+
result[i] = yield* values[i].deserialize(stream);
|
|
248
324
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
IPC.ConnectionManager = ConnectionManager;
|
|
253
|
-
/** Sends a message with `args` to `channel` */
|
|
254
|
-
function send(channel, ...args) {
|
|
255
|
-
system.runJob(NET.emit('ipc', `${channel}:send`, args));
|
|
256
|
-
}
|
|
257
|
-
IPC.send = send;
|
|
258
|
-
function invoke(channel, ...args) {
|
|
259
|
-
system.runJob(NET.emit('ipc', `${channel}:invoke`, args));
|
|
260
|
-
return new Promise(resolve => {
|
|
261
|
-
const terminate = NET.listen('ipc', `${channel}:handle`, function* (args) {
|
|
262
|
-
resolve(args);
|
|
263
|
-
terminate();
|
|
264
|
-
});
|
|
265
|
-
});
|
|
266
|
-
}
|
|
267
|
-
IPC.invoke = invoke;
|
|
268
|
-
/** Listens to `channel`. When a new message arrives, `listener` will be called with `listener(args)`. */
|
|
269
|
-
function on(channel, listener) {
|
|
270
|
-
return NET.listen('ipc', `${channel}:send`, function* (args) {
|
|
271
|
-
listener(...args);
|
|
272
|
-
});
|
|
273
|
-
}
|
|
274
|
-
IPC.on = on;
|
|
275
|
-
/** Listens to `channel` once. When a new message arrives, `listener` will be called with `listener(args)`, and then removed. */
|
|
276
|
-
function once(channel, listener) {
|
|
277
|
-
const terminate = NET.listen('ipc', `${channel}:send`, function* (args) {
|
|
278
|
-
listener(...args);
|
|
279
|
-
terminate();
|
|
280
|
-
});
|
|
281
|
-
return terminate;
|
|
325
|
+
return result;
|
|
326
|
+
}
|
|
327
|
+
};
|
|
282
328
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
329
|
+
PROTO.Tuple = Tuple;
|
|
330
|
+
function Optional(value) {
|
|
331
|
+
return {
|
|
332
|
+
*serialize(optional, stream) {
|
|
333
|
+
yield* PROTO.Boolean.serialize(value !== undefined, stream);
|
|
334
|
+
if (optional !== undefined) {
|
|
335
|
+
yield* value.serialize(optional, stream);
|
|
336
|
+
}
|
|
337
|
+
},
|
|
338
|
+
*deserialize(stream) {
|
|
339
|
+
const defined = yield* PROTO.Boolean.deserialize(stream);
|
|
340
|
+
if (defined) {
|
|
341
|
+
return yield* value.deserialize(stream);
|
|
342
|
+
}
|
|
343
|
+
return undefined;
|
|
344
|
+
}
|
|
345
|
+
};
|
|
290
346
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
(
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
347
|
+
PROTO.Optional = Optional;
|
|
348
|
+
function Map(key, value) {
|
|
349
|
+
return {
|
|
350
|
+
*serialize(map, stream) {
|
|
351
|
+
yield* PROTO.UVarInt32.serialize(map.size, stream);
|
|
352
|
+
for (const [k, v] of map.entries()) {
|
|
353
|
+
yield* key.serialize(k, stream);
|
|
354
|
+
yield* value.serialize(v, stream);
|
|
355
|
+
}
|
|
356
|
+
},
|
|
357
|
+
*deserialize(stream) {
|
|
358
|
+
const size = yield* PROTO.UVarInt32.deserialize(stream);
|
|
359
|
+
const result = new globalThis.Map();
|
|
360
|
+
for (let i = 0; i < size; i++) {
|
|
361
|
+
const k = yield* key.deserialize(stream);
|
|
362
|
+
const v = yield* value.deserialize(stream);
|
|
363
|
+
result.set(k, v);
|
|
364
|
+
}
|
|
365
|
+
return result;
|
|
366
|
+
}
|
|
367
|
+
};
|
|
312
368
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
369
|
+
PROTO.Map = Map;
|
|
370
|
+
function Set(value) {
|
|
371
|
+
return {
|
|
372
|
+
*serialize(set, stream) {
|
|
373
|
+
yield* PROTO.UVarInt32.serialize(set.size, stream);
|
|
374
|
+
for (const [_, v] of set.entries()) {
|
|
375
|
+
yield* value.serialize(v, stream);
|
|
376
|
+
}
|
|
377
|
+
},
|
|
378
|
+
*deserialize(stream) {
|
|
379
|
+
const size = yield* PROTO.UVarInt32.deserialize(stream);
|
|
380
|
+
const result = new globalThis.Set();
|
|
381
|
+
for (let i = 0; i < size; i++) {
|
|
382
|
+
const v = yield* value.deserialize(stream);
|
|
383
|
+
result.add(v);
|
|
384
|
+
}
|
|
385
|
+
return result;
|
|
386
|
+
}
|
|
387
|
+
};
|
|
320
388
|
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
389
|
+
PROTO.Set = Set;
|
|
390
|
+
PROTO.Endpoint = PROTO.String;
|
|
391
|
+
PROTO.Header = PROTO.Object({
|
|
392
|
+
guid: PROTO.String,
|
|
393
|
+
encoding: PROTO.String,
|
|
394
|
+
index: PROTO.UVarInt32,
|
|
395
|
+
final: PROTO.Boolean
|
|
396
|
+
});
|
|
397
|
+
})(PROTO || (PROTO = {}));
|
|
398
|
+
export var NET;
|
|
399
|
+
(function (NET) {
|
|
400
|
+
const FRAG_MAX = 2048;
|
|
401
|
+
const ENCODING = 'mcbe-ipc:v3';
|
|
402
|
+
const ENDPOINTS = new Map();
|
|
403
|
+
function* serialize(byte_queue, max_size = Infinity) {
|
|
404
|
+
const uint8array = byte_queue.to_uint8array();
|
|
405
|
+
const result = [];
|
|
406
|
+
let acc_str = '';
|
|
407
|
+
let acc_size = 0;
|
|
408
|
+
for (let i = 0; i < uint8array.length; i++) {
|
|
409
|
+
const char_code = uint8array[i] | (uint8array[++i] << 8);
|
|
410
|
+
const utf16_size = char_code <= 0x7f ? 1 : char_code <= 0x7ff ? 2 : char_code <= 0xffff ? 3 : 4;
|
|
411
|
+
const char_size = char_code > 0xff ? utf16_size : 3;
|
|
412
|
+
if (acc_size + char_size > max_size) {
|
|
413
|
+
result.push(acc_str);
|
|
414
|
+
acc_str = '';
|
|
415
|
+
acc_size = 0;
|
|
328
416
|
}
|
|
329
|
-
|
|
330
|
-
|
|
417
|
+
if (char_code > 0xff) {
|
|
418
|
+
acc_str += String.fromCharCode(char_code);
|
|
419
|
+
acc_size += utf16_size;
|
|
331
420
|
}
|
|
332
|
-
yield;
|
|
333
|
-
}
|
|
334
|
-
return result;
|
|
335
|
-
}
|
|
336
|
-
SERDE.encode = encode;
|
|
337
|
-
function* decode(str) {
|
|
338
|
-
let result = '';
|
|
339
|
-
const seqs = str.match(sequence_regex) ?? [];
|
|
340
|
-
for (let i = 0; i < seqs.length; i++) {
|
|
341
|
-
const seq = seqs[i];
|
|
342
|
-
if (seq.startsWith('?') && encoded_regex.test(seq))
|
|
343
|
-
result += yield* b64_decode(seq.slice(1));
|
|
344
421
|
else {
|
|
345
|
-
|
|
422
|
+
acc_str += char_code.toString(16).padStart(2, '0').toUpperCase();
|
|
423
|
+
acc_size += 2;
|
|
346
424
|
}
|
|
347
425
|
yield;
|
|
348
426
|
}
|
|
427
|
+
result.push(acc_str);
|
|
349
428
|
return result;
|
|
350
429
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
(
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
430
|
+
NET.serialize = serialize;
|
|
431
|
+
function* deserialize(strings) {
|
|
432
|
+
const result = [];
|
|
433
|
+
for (let i = 0; i < strings.length; i++) {
|
|
434
|
+
const str = strings[i];
|
|
435
|
+
for (let j = 0; j < str.length; j++) {
|
|
436
|
+
const char_code = str.charCodeAt(j);
|
|
437
|
+
if (char_code <= 0xff) {
|
|
438
|
+
const hex = str[j] + str[++j];
|
|
439
|
+
const hex_code = parseInt(hex, 16);
|
|
440
|
+
result.push(hex_code & 0xff);
|
|
441
|
+
result.push(hex_code >> 8);
|
|
442
|
+
}
|
|
443
|
+
else {
|
|
444
|
+
result.push(char_code & 0xff);
|
|
445
|
+
result.push(char_code >> 8);
|
|
446
|
+
}
|
|
447
|
+
yield;
|
|
365
448
|
}
|
|
366
|
-
b = (b * b) % mod;
|
|
367
|
-
yield;
|
|
368
|
-
}
|
|
369
|
-
return result;
|
|
370
|
-
}
|
|
371
|
-
function make_secret(mod = CRYPTO.MOD) {
|
|
372
|
-
return Math.floor(Math.random() * (mod - 1)) + 1;
|
|
373
|
-
}
|
|
374
|
-
CRYPTO.make_secret = make_secret;
|
|
375
|
-
function* make_public(secret, mod = CRYPTO.MOD, prime = CRYPTO.PRIME) {
|
|
376
|
-
return to_HEX(yield* mod_exp(mod, secret, prime));
|
|
377
|
-
}
|
|
378
|
-
CRYPTO.make_public = make_public;
|
|
379
|
-
function* make_shared(secret, other, prime = CRYPTO.PRIME) {
|
|
380
|
-
return to_HEX(yield* mod_exp(to_NUM(other), secret, prime));
|
|
381
|
-
}
|
|
382
|
-
CRYPTO.make_shared = make_shared;
|
|
383
|
-
function* encrypt(raw, key) {
|
|
384
|
-
let encrypted = '';
|
|
385
|
-
for (let i = 0; i < raw.length; i++) {
|
|
386
|
-
encrypted += String.fromCharCode(raw.charCodeAt(i) ^ key.charCodeAt(i % key.length));
|
|
387
|
-
yield;
|
|
388
|
-
}
|
|
389
|
-
return encrypted;
|
|
390
|
-
}
|
|
391
|
-
CRYPTO.encrypt = encrypt;
|
|
392
|
-
function* decrypt(encrypted, key) {
|
|
393
|
-
let decrypted = '';
|
|
394
|
-
for (let i = 0; i < encrypted.length; i++) {
|
|
395
|
-
decrypted += String.fromCharCode(encrypted.charCodeAt(i) ^ key.charCodeAt(i % key.length));
|
|
396
449
|
yield;
|
|
397
450
|
}
|
|
398
|
-
return
|
|
451
|
+
return PROTO.ByteQueue.from_uint8array(new Uint8Array(result));
|
|
399
452
|
}
|
|
400
|
-
|
|
401
|
-
})(CRYPTO || (CRYPTO = {}));
|
|
402
|
-
export var NET;
|
|
403
|
-
(function (NET) {
|
|
404
|
-
const FRAG_MAX = 2048;
|
|
405
|
-
const namespace_listeners = new Map();
|
|
453
|
+
NET.deserialize = deserialize;
|
|
406
454
|
system.afterEvents.scriptEventReceive.subscribe(event => {
|
|
407
455
|
system.runJob((function* () {
|
|
408
|
-
const
|
|
409
|
-
const
|
|
410
|
-
const
|
|
456
|
+
const [serialized_endpoint, serialized_header] = event.id.split(':');
|
|
457
|
+
const endpoint_stream = yield* PROTO.MIPS.deserialize(serialized_endpoint);
|
|
458
|
+
const endpoint = yield* PROTO.Endpoint.deserialize(endpoint_stream);
|
|
459
|
+
const listeners = ENDPOINTS.get(endpoint);
|
|
411
460
|
if (event.sourceType === ScriptEventSource.Server && listeners) {
|
|
412
|
-
const
|
|
461
|
+
const header_stream = yield* PROTO.MIPS.deserialize(serialized_header);
|
|
462
|
+
const header = yield* PROTO.Header.deserialize(header_stream);
|
|
413
463
|
for (let i = 0; i < listeners.length; i++) {
|
|
414
|
-
yield* listeners[i](
|
|
464
|
+
yield* listeners[i](header, event.message);
|
|
415
465
|
}
|
|
416
466
|
}
|
|
417
467
|
})());
|
|
418
468
|
});
|
|
419
|
-
function create_listener(
|
|
420
|
-
let listeners =
|
|
469
|
+
function create_listener(endpoint, listener) {
|
|
470
|
+
let listeners = ENDPOINTS.get(endpoint);
|
|
421
471
|
if (!listeners) {
|
|
422
472
|
listeners = new Array();
|
|
423
|
-
|
|
473
|
+
ENDPOINTS.set(endpoint, listeners);
|
|
424
474
|
}
|
|
425
475
|
listeners.push(listener);
|
|
426
476
|
return () => {
|
|
@@ -428,21 +478,10 @@ export var NET;
|
|
|
428
478
|
if (idx !== -1)
|
|
429
479
|
listeners.splice(idx, 1);
|
|
430
480
|
if (listeners.length === 0) {
|
|
431
|
-
|
|
481
|
+
ENDPOINTS.delete(endpoint);
|
|
432
482
|
}
|
|
433
483
|
};
|
|
434
484
|
}
|
|
435
|
-
let Payload;
|
|
436
|
-
(function (Payload) {
|
|
437
|
-
function toString(p) {
|
|
438
|
-
return JSON.stringify(p);
|
|
439
|
-
}
|
|
440
|
-
Payload.toString = toString;
|
|
441
|
-
function fromString(s) {
|
|
442
|
-
return JSON.parse(s);
|
|
443
|
-
}
|
|
444
|
-
Payload.fromString = fromString;
|
|
445
|
-
})(Payload || (Payload = {}));
|
|
446
485
|
function generate_id() {
|
|
447
486
|
const r = (Math.random() * 0x100000000) >>> 0;
|
|
448
487
|
return ((r & 0xff).toString(16).padStart(2, '0') +
|
|
@@ -450,66 +489,93 @@ export var NET;
|
|
|
450
489
|
((r >> 16) & 0xff).toString(16).padStart(2, '0') +
|
|
451
490
|
((r >> 24) & 0xff).toString(16).padStart(2, '0')).toUpperCase();
|
|
452
491
|
}
|
|
453
|
-
function* emit(
|
|
454
|
-
const
|
|
455
|
-
const
|
|
456
|
-
|
|
457
|
-
const
|
|
458
|
-
|
|
459
|
-
|
|
492
|
+
function* emit(endpoint, serializer, value) {
|
|
493
|
+
const guid = generate_id();
|
|
494
|
+
const endpoint_stream = new PROTO.ByteQueue();
|
|
495
|
+
yield* PROTO.Endpoint.serialize(endpoint, endpoint_stream);
|
|
496
|
+
const serialized_endpoint = yield* PROTO.MIPS.serialize(endpoint_stream);
|
|
497
|
+
const RUN = function* (header, serialized_packet) {
|
|
498
|
+
const header_stream = new PROTO.ByteQueue();
|
|
499
|
+
yield* PROTO.Header.serialize(header, header_stream);
|
|
500
|
+
const serialized_header = yield* PROTO.MIPS.serialize(header_stream);
|
|
501
|
+
world
|
|
502
|
+
.getDimension('overworld')
|
|
503
|
+
.runCommand(`scriptevent ${serialized_endpoint}:${serialized_header} ${serialized_packet}`);
|
|
460
504
|
};
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
for (let i = 0; i <
|
|
465
|
-
const
|
|
466
|
-
|
|
467
|
-
const char_size = code <= 0x7f ? 1 : code <= 0x7ff ? 2 : code <= 0xffff ? 3 : 4;
|
|
468
|
-
if (str_size + char_size < FRAG_MAX) {
|
|
469
|
-
str += char;
|
|
470
|
-
str_size += char_size;
|
|
471
|
-
}
|
|
472
|
-
else {
|
|
473
|
-
yield* RUN([channel, id, len], str);
|
|
474
|
-
len++;
|
|
475
|
-
str = char;
|
|
476
|
-
str_size = char_size;
|
|
477
|
-
}
|
|
478
|
-
yield;
|
|
505
|
+
const packet_stream = new PROTO.ByteQueue();
|
|
506
|
+
yield* serializer.serialize(value, packet_stream);
|
|
507
|
+
const serialized_packets = yield* serialize(packet_stream, FRAG_MAX);
|
|
508
|
+
for (let i = 0; i < serialized_packets.length; i++) {
|
|
509
|
+
const serialized_packet = serialized_packets[i];
|
|
510
|
+
yield* RUN({ guid, encoding: ENCODING, index: i, final: i === serialized_packets.length - 1 }, serialized_packet);
|
|
479
511
|
}
|
|
480
|
-
yield* RUN(len === 0 ? [channel, id] : [channel, id, len, 1], str);
|
|
481
512
|
}
|
|
482
513
|
NET.emit = emit;
|
|
483
|
-
function listen(
|
|
514
|
+
function listen(endpoint, serializer, callback) {
|
|
484
515
|
const buffer = new Map();
|
|
485
|
-
const listener = function* (
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
let full_str = '';
|
|
502
|
-
for (let i = 0; i < fragment.data_strs.length; i++) {
|
|
503
|
-
full_str += fragment.data_strs[i];
|
|
504
|
-
yield;
|
|
505
|
-
}
|
|
506
|
-
yield* callback(JSON.parse(yield* SERDE.decode(full_str)));
|
|
507
|
-
buffer.delete(p_id);
|
|
508
|
-
}
|
|
509
|
-
}
|
|
516
|
+
const listener = function* (payload, serialized_packet) {
|
|
517
|
+
let fragment = buffer.get(payload.guid);
|
|
518
|
+
if (!fragment) {
|
|
519
|
+
fragment = { size: -1, serialized_packets: [], data_size: 0 };
|
|
520
|
+
buffer.set(payload.guid, fragment);
|
|
521
|
+
}
|
|
522
|
+
if (payload.final) {
|
|
523
|
+
fragment.size = payload.index + 1;
|
|
524
|
+
}
|
|
525
|
+
fragment.serialized_packets[payload.index] = serialized_packet;
|
|
526
|
+
fragment.data_size += payload.index + 1;
|
|
527
|
+
if (fragment.size !== -1 && fragment.data_size === (fragment.size * (fragment.size + 1)) / 2) {
|
|
528
|
+
const stream = yield* deserialize(fragment.serialized_packets);
|
|
529
|
+
const value = yield* serializer.deserialize(stream);
|
|
530
|
+
yield* callback(value);
|
|
531
|
+
buffer.delete(payload.guid);
|
|
510
532
|
}
|
|
511
533
|
};
|
|
512
|
-
return create_listener(
|
|
534
|
+
return create_listener(endpoint, listener);
|
|
513
535
|
}
|
|
514
536
|
NET.listen = listen;
|
|
515
537
|
})(NET || (NET = {}));
|
|
538
|
+
export var IPC;
|
|
539
|
+
(function (IPC) {
|
|
540
|
+
/** Sends a message with `args` to `channel` */
|
|
541
|
+
function send(channel, serializer, value) {
|
|
542
|
+
system.runJob(NET.emit(`ipc:${channel}:send`, serializer, value));
|
|
543
|
+
}
|
|
544
|
+
IPC.send = send;
|
|
545
|
+
/** Sends an `invoke` message through IPC, and expects a result asynchronously. */
|
|
546
|
+
function invoke(channel, serializer, value, deserializer) {
|
|
547
|
+
system.runJob(NET.emit(`ipc:${channel}:invoke`, serializer, value));
|
|
548
|
+
return new Promise(resolve => {
|
|
549
|
+
const terminate = NET.listen(`ipc:${channel}:handle`, deserializer, function* (value) {
|
|
550
|
+
resolve(value);
|
|
551
|
+
terminate();
|
|
552
|
+
});
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
IPC.invoke = invoke;
|
|
556
|
+
/** Listens to `channel`. When a new message arrives, `listener` will be called with `listener(args)`. */
|
|
557
|
+
function on(channel, deserializer, listener) {
|
|
558
|
+
return NET.listen(`ipc:${channel}:send`, deserializer, function* (value) {
|
|
559
|
+
listener(value);
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
IPC.on = on;
|
|
563
|
+
/** Listens to `channel` once. When a new message arrives, `listener` will be called with `listener(args)`, and then removed. */
|
|
564
|
+
function once(channel, deserializer, listener) {
|
|
565
|
+
const terminate = NET.listen(`ipc:${channel}:send`, deserializer, function* (value) {
|
|
566
|
+
listener(value);
|
|
567
|
+
terminate();
|
|
568
|
+
});
|
|
569
|
+
return terminate;
|
|
570
|
+
}
|
|
571
|
+
IPC.once = once;
|
|
572
|
+
/** Adds a handler for an `invoke` IPC. This handler will be called whenever `invoke(channel, ...args)` is called */
|
|
573
|
+
function handle(channel, deserializer, serializer, listener) {
|
|
574
|
+
return NET.listen(`ipc:${channel}:invoke`, deserializer, function* (value) {
|
|
575
|
+
const result = listener(value);
|
|
576
|
+
yield* NET.emit(`ipc:${channel}:handle`, serializer, result);
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
IPC.handle = handle;
|
|
580
|
+
})(IPC || (IPC = {}));
|
|
581
|
+
export default IPC;
|