rbx-reader-ts 1.5.4 → 1.5.6

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.
@@ -0,0 +1,29 @@
1
+ import ByteReader from './ByteReader';
2
+ import { Instance, InstanceRoot } from './Instance';
3
+ export interface ParserResult {
4
+ result: InstanceRoot;
5
+ reader: ByteReader;
6
+ instances: Instance[];
7
+ groups: Group[];
8
+ sharedStrings: string[];
9
+ meta: object;
10
+ arrays: any[][];
11
+ arrayIndex: number;
12
+ }
13
+ export interface Group {
14
+ ClassName: string;
15
+ Objects: Instance[];
16
+ }
17
+ declare const BinaryParser: {
18
+ HeaderBytes: number[];
19
+ Faces: number[][];
20
+ DataTypes: (string | null)[];
21
+ parse(buffer: ArrayBuffer): ParserResult;
22
+ parseChunk(parser: ParserResult, startIndex: number): void;
23
+ parseMETA(parser: any, chunk: any): void;
24
+ parseSSTR(parser: any, chunk: any): void;
25
+ parseINST(parser: any, chunk: any): void;
26
+ parsePROP(parser: any, chunk: any): void;
27
+ parsePRNT(parser: any, chunk: any): void;
28
+ };
29
+ export default BinaryParser;
@@ -0,0 +1,539 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const ByteReader_1 = __importDefault(require("./ByteReader"));
7
+ const Instance_1 = require("./Instance");
8
+ const attributes_parser_1 = require("./attributes-parser/attributes_parser");
9
+ const BinaryParser = {
10
+ HeaderBytes: [0x3C, 0x72, 0x6F, 0x62, 0x6C, 0x6F, 0x78, 0x21, 0x89, 0xFF, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00],
11
+ Faces: [[1, 0, 0], [0, 1, 0], [0, 0, 1], [-1, 0, 0], [0, -1, 0], [0, 0, -1]],
12
+ DataTypes: [
13
+ null, 'string', 'bool', 'int', 'float', 'double', 'UDim', 'UDim2', // 7
14
+ 'Ray', 'Faces', 'Axes', 'BrickColor', 'Color3', 'Vector2', 'Vector3', 'Vector2int16', // 15
15
+ 'CFrame', 'Quaternion', 'Enum', 'Instance', 'Vector3int16', 'NumberSequence', 'ColorSequence', // 22
16
+ 'NumberRange', 'Rect2D', 'PhysicalProperties', 'Color3uint8', 'int64', 'SharedString', 'UnknownScriptFormat', // 29
17
+ 'Optional', 'UniqueId'
18
+ ],
19
+ parse(buffer) {
20
+ const reader = new ByteReader_1.default(buffer);
21
+ if (!reader.Match(this.HeaderBytes)) {
22
+ throw new Error('[RobloxBinaryParser] Header bytes did not match (Did binary format change?)');
23
+ }
24
+ const groupsCount = reader.UInt32LE();
25
+ const instancesCount = reader.UInt32LE();
26
+ reader.Jump(8);
27
+ const parser = {
28
+ result: new Instance_1.InstanceRoot(),
29
+ reader: reader,
30
+ instances: [],
31
+ groups: [],
32
+ sharedStrings: [],
33
+ meta: {},
34
+ arrays: [],
35
+ arrayIndex: 0,
36
+ };
37
+ for (var i = 0; i < 6; i++) {
38
+ parser.arrays.push(new Array(256));
39
+ }
40
+ reader.GetIndex();
41
+ var maxChunkSize = 0;
42
+ var chunkIndices = [];
43
+ while (reader.GetRemaining() >= 4) {
44
+ chunkIndices.push(reader.GetIndex());
45
+ reader.String(4);
46
+ const comLength = reader.UInt32LE();
47
+ const decomLength = reader.UInt32LE();
48
+ if (comLength > 0) {
49
+ reader.Jump(4 + comLength);
50
+ if (decomLength > maxChunkSize) {
51
+ maxChunkSize = decomLength;
52
+ }
53
+ }
54
+ else {
55
+ reader.Jump(4 + decomLength);
56
+ }
57
+ }
58
+ reader.chunkBuffer = new Uint8Array(maxChunkSize);
59
+ for (const startIndex of chunkIndices) {
60
+ this.parseChunk(parser, startIndex);
61
+ }
62
+ return parser;
63
+ },
64
+ parseChunk(parser, startIndex) {
65
+ parser.reader.SetIndex(startIndex);
66
+ const chunkType = parser.reader.String(4);
67
+ if (chunkType === 'END\0') {
68
+ return;
69
+ }
70
+ const chunkData = parser.reader.LZ4(parser.reader.chunkBuffer);
71
+ const chunkReader = new ByteReader_1.default(chunkData);
72
+ parser.arrayIndex = 0;
73
+ switch (chunkType) {
74
+ case 'INST':
75
+ this.parseINST(parser, chunkReader);
76
+ break;
77
+ case 'PROP':
78
+ this.parsePROP(parser, chunkReader);
79
+ break;
80
+ case 'PRNT':
81
+ this.parsePRNT(parser, chunkReader);
82
+ break;
83
+ case 'SSTR':
84
+ this.parseSSTR(parser, chunkReader);
85
+ break;
86
+ case 'META':
87
+ this.parseMETA(parser, chunkReader);
88
+ break;
89
+ case 'SIGN':
90
+ break;
91
+ default:
92
+ }
93
+ },
94
+ parseMETA(parser, chunk) {
95
+ const numEntries = chunk.UInt32LE();
96
+ for (var i = 0; i < numEntries; i++) {
97
+ const key = chunk.String(chunk.UInt32LE());
98
+ const value = chunk.String(chunk.UInt32LE());
99
+ parser.meta[key] = value;
100
+ }
101
+ },
102
+ parseSSTR(parser, chunk) {
103
+ chunk.UInt32LE(); // version
104
+ const stringCount = chunk.UInt32LE();
105
+ for (var i = 0; i < stringCount; i++) {
106
+ const md5 = chunk.Array(16);
107
+ const length = chunk.UInt32LE();
108
+ const value = chunk.String(length);
109
+ parser.sharedStrings[i] = { md5, value };
110
+ }
111
+ },
112
+ parseINST(parser, chunk) {
113
+ const groupId = chunk.UInt32LE();
114
+ const className = chunk.String(chunk.UInt32LE());
115
+ chunk.Byte(); // isService
116
+ const instCount = chunk.UInt32LE();
117
+ const instIds = chunk.RBXInterleavedInt32(instCount, parser.arrays[parser.arrayIndex++]);
118
+ const group = parser.groups[groupId] = {
119
+ ClassName: className,
120
+ Objects: []
121
+ };
122
+ var instId = 0;
123
+ for (var i = 0; i < instCount; i++) {
124
+ instId += instIds[i];
125
+ group.Objects.push(parser.instances[instId] = Instance_1.Instance.new(className));
126
+ }
127
+ },
128
+ parsePROP(parser, chunk) {
129
+ const group = parser.groups[chunk.UInt32LE()];
130
+ const prop = chunk.String(chunk.UInt32LE());
131
+ if (chunk.GetRemaining() <= 0) {
132
+ return; // empty chunk?
133
+ }
134
+ const instCount = group.Objects.length;
135
+ const values = parser.arrays[parser.arrayIndex++];
136
+ var dataType = chunk.Byte();
137
+ var typeName = this.DataTypes[dataType];
138
+ var isOptional = typeName === 'Optional';
139
+ if (isOptional) {
140
+ dataType = chunk.Byte();
141
+ typeName = this.DataTypes[dataType];
142
+ }
143
+ var resultTypeName = typeName || 'Unknown';
144
+ switch (typeName) {
145
+ case 'string':
146
+ for (var i = 0; i < instCount; i++) {
147
+ const len = chunk.UInt32LE();
148
+ values[i] = chunk.String(len);
149
+ }
150
+ break;
151
+ case 'bool':
152
+ for (var i = 0; i < instCount; i++) {
153
+ values[i] = chunk.Byte() !== 0;
154
+ }
155
+ break;
156
+ case 'int':
157
+ chunk.RBXInterleavedInt32(instCount, values);
158
+ break;
159
+ case 'float':
160
+ chunk.RBXInterleavedFloat(instCount, values);
161
+ break;
162
+ case 'double':
163
+ for (var i = 0; i < instCount; i++) {
164
+ values[i] = chunk.DoubleLE();
165
+ }
166
+ break;
167
+ case 'UDim': {
168
+ const scale = chunk.RBXInterleavedFloat(instCount, parser.arrays[parser.arrayIndex++]);
169
+ const offset = chunk.RBXInterleavedInt32(instCount, parser.arrays[parser.arrayIndex++]);
170
+ for (var i = 0; i < instCount; i++) {
171
+ values[i] = [scale[i], offset[i]];
172
+ }
173
+ break;
174
+ }
175
+ case 'UDim2': {
176
+ const scaleX = chunk.RBXInterleavedFloat(instCount, parser.arrays[parser.arrayIndex++]);
177
+ const scaleY = chunk.RBXInterleavedFloat(instCount, parser.arrays[parser.arrayIndex++]);
178
+ const offsetX = chunk.RBXInterleavedInt32(instCount, parser.arrays[parser.arrayIndex++]);
179
+ const offsetY = chunk.RBXInterleavedInt32(instCount, parser.arrays[parser.arrayIndex++]);
180
+ for (var i = 0; i < instCount; i++) {
181
+ values[i] = [
182
+ [scaleX[i], offsetX[i]],
183
+ [scaleY[i], offsetY[i]]
184
+ ];
185
+ }
186
+ break;
187
+ }
188
+ case 'Ray': {
189
+ for (var i = 0; i < instCount; i++) {
190
+ values[i] = [
191
+ [chunk.RBXFloatLE(), chunk.RBXFloatLE(), chunk.RBXFloatLE()],
192
+ [chunk.RBXFloatLE(), chunk.RBXFloatLE(), chunk.RBXFloatLE()]
193
+ ];
194
+ }
195
+ break;
196
+ }
197
+ case 'Faces':
198
+ for (var i = 0; i < instCount; i++) {
199
+ const data = chunk.Byte();
200
+ values[i] = {
201
+ Right: !!(data & 1),
202
+ Top: !!(data & 2),
203
+ Back: !!(data & 4),
204
+ Left: !!(data & 8),
205
+ Bottom: !!(data & 16),
206
+ Front: !!(data & 32)
207
+ };
208
+ }
209
+ break;
210
+ case 'Axes':
211
+ for (var i = 0; i < instCount; i++) {
212
+ const data = chunk.Byte();
213
+ values[i] = {
214
+ X: !!(data & 1),
215
+ Y: !!(data & 2),
216
+ Z: !!(data & 4)
217
+ };
218
+ }
219
+ break;
220
+ case 'BrickColor':
221
+ chunk.RBXInterleavedUint32(instCount, values);
222
+ break;
223
+ case 'Color3': {
224
+ const red = chunk.RBXInterleavedFloat(instCount, parser.arrays[parser.arrayIndex++]);
225
+ const green = chunk.RBXInterleavedFloat(instCount, parser.arrays[parser.arrayIndex++]);
226
+ const blue = chunk.RBXInterleavedFloat(instCount, parser.arrays[parser.arrayIndex++]);
227
+ for (var i = 0; i < instCount; i++) {
228
+ values[i] = [red[i], green[i], blue[i]];
229
+ }
230
+ break;
231
+ }
232
+ case 'Vector2': {
233
+ const vecX = chunk.RBXInterleavedFloat(instCount, parser.arrays[parser.arrayIndex++]);
234
+ const vecY = chunk.RBXInterleavedFloat(instCount, parser.arrays[parser.arrayIndex++]);
235
+ for (var i = 0; i < instCount; i++) {
236
+ values[i] = [vecX[i], vecY[i]];
237
+ }
238
+ break;
239
+ }
240
+ case 'Vector3': {
241
+ const vecX = chunk.RBXInterleavedFloat(instCount, parser.arrays[parser.arrayIndex++]);
242
+ const vecY = chunk.RBXInterleavedFloat(instCount, parser.arrays[parser.arrayIndex++]);
243
+ const vecZ = chunk.RBXInterleavedFloat(instCount, parser.arrays[parser.arrayIndex++]);
244
+ for (var i = 0; i < instCount; i++) {
245
+ values[i] = [vecX[i], vecY[i], vecZ[i]];
246
+ }
247
+ break;
248
+ }
249
+ case 'Vector2int16': break; // Not used anywhere?
250
+ case 'CFrame': {
251
+ for (var vi = 0; vi < instCount; vi++) {
252
+ const value = values[vi] = [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1];
253
+ const type = chunk.Byte();
254
+ if (type !== 0) {
255
+ const right = this.Faces[Math.floor((type - 1) / 6)];
256
+ const up = this.Faces[Math.floor(type - 1) % 6];
257
+ const back = [
258
+ right[1] * up[2] - up[1] * right[2],
259
+ right[2] * up[0] - up[2] * right[0],
260
+ right[0] * up[1] - up[0] * right[1]
261
+ ];
262
+ for (var i = 0; i < 3; i++) {
263
+ value[3 + i * 3] = right[i];
264
+ value[4 + i * 3] = up[i];
265
+ value[5 + i * 3] = back[i];
266
+ }
267
+ }
268
+ else {
269
+ for (var i = 0; i < 9; i++) {
270
+ value[i + 3] = chunk.FloatLE();
271
+ }
272
+ }
273
+ }
274
+ const vecX = chunk.RBXInterleavedFloat(instCount, parser.arrays[parser.arrayIndex++]);
275
+ const vecY = chunk.RBXInterleavedFloat(instCount, parser.arrays[parser.arrayIndex++]);
276
+ const vecZ = chunk.RBXInterleavedFloat(instCount, parser.arrays[parser.arrayIndex++]);
277
+ for (var i = 0; i < instCount; i++) {
278
+ values[i][0] = vecX[i];
279
+ values[i][1] = vecY[i];
280
+ values[i][2] = vecZ[i];
281
+ }
282
+ break;
283
+ }
284
+ // case 'Quaternion': break // Not used anywhere?
285
+ case 'Enum':
286
+ chunk.RBXInterleavedUint32(instCount, values);
287
+ break;
288
+ case 'Instance': {
289
+ const refIds = chunk.RBXInterleavedInt32(instCount, parser.arrays[parser.arrayIndex++]);
290
+ var refId = 0;
291
+ for (var i = 0; i < instCount; i++) {
292
+ refId += refIds[i];
293
+ values[i] = parser.instances[refId];
294
+ }
295
+ break;
296
+ }
297
+ case 'Vector3int16':
298
+ break; // Not used anywhere?
299
+ case 'NumberSequence': {
300
+ for (var i = 0; i < instCount; i++) {
301
+ const seqLength = chunk.UInt32LE();
302
+ const seq = values[i] = [];
303
+ for (var j = 0; j < seqLength; j++) {
304
+ seq.push({
305
+ Time: chunk.FloatLE(),
306
+ Value: chunk.FloatLE(),
307
+ Envelope: chunk.FloatLE()
308
+ });
309
+ }
310
+ }
311
+ break;
312
+ }
313
+ case 'ColorSequence':
314
+ for (var i = 0; i < instCount; i++) {
315
+ const seqLength = chunk.UInt32LE();
316
+ const seq = values[i] = [];
317
+ for (var j = 0; j < seqLength; j++) {
318
+ seq.push({
319
+ Time: chunk.FloatLE(),
320
+ Color: [chunk.FloatLE(), chunk.FloatLE(), chunk.FloatLE()],
321
+ EnvelopeMaybe: chunk.FloatLE()
322
+ });
323
+ }
324
+ }
325
+ break;
326
+ case 'NumberRange':
327
+ for (var i = 0; i < instCount; i++) {
328
+ values[i] = {
329
+ Min: chunk.FloatLE(),
330
+ Max: chunk.FloatLE()
331
+ };
332
+ }
333
+ break;
334
+ case 'Rect2D': {
335
+ const x0 = chunk.RBXInterleavedFloat(instCount, parser.arrays[parser.arrayIndex++]);
336
+ const y0 = chunk.RBXInterleavedFloat(instCount, parser.arrays[parser.arrayIndex++]);
337
+ const x1 = chunk.RBXInterleavedFloat(instCount, parser.arrays[parser.arrayIndex++]);
338
+ const y1 = chunk.RBXInterleavedFloat(instCount, parser.arrays[parser.arrayIndex++]);
339
+ for (var i = 0; i < instCount; i++) {
340
+ values[i] = [x0[i], y0[i], x1[i], y1[i]];
341
+ }
342
+ break;
343
+ }
344
+ case 'PhysicalProperties':
345
+ for (var i = 0; i < instCount; i++) {
346
+ const enabled = chunk.Byte() !== 0;
347
+ values[i] = {
348
+ CustomPhysics: enabled,
349
+ Density: enabled ? chunk.RBXFloatLE() : undefined,
350
+ Friction: enabled ? chunk.RBXFloatLE() : undefined,
351
+ Elasticity: enabled ? chunk.RBXFloatLE() : undefined,
352
+ FrictionWeight: enabled ? chunk.RBXFloatLE() : undefined,
353
+ ElasticityWeight: enabled ? chunk.RBXFloatLE() : undefined
354
+ };
355
+ }
356
+ break;
357
+ case 'Color3uint8': {
358
+ const rgb = chunk.Array(instCount * 3);
359
+ for (var i = 0; i < instCount; i++) {
360
+ values[i] = [rgb[i] / 255, rgb[i + instCount] / 255, rgb[i + instCount * 2] / 255];
361
+ }
362
+ resultTypeName = 'Color3';
363
+ break;
364
+ }
365
+ case 'int64': { // Two's complement
366
+ const bytes = chunk.Array(instCount * 8);
367
+ for (var i = 0; i < instCount; i++) {
368
+ var byte0 = bytes[i + instCount * 0] * (256 ** 3) + bytes[i + instCount * 1] * (256 ** 2) +
369
+ bytes[i + instCount * 2] * 256 + bytes[i + instCount * 3];
370
+ var byte1 = bytes[i + instCount * 4] * (256 ** 3) + bytes[i + instCount * 5] * (256 ** 2) +
371
+ bytes[i + instCount * 6] * 256 + bytes[i + instCount * 7];
372
+ const neg = byte1 % 2;
373
+ byte1 = (byte0 % 2) * (2 ** 31) + (byte1 + neg) / 2;
374
+ byte0 = Math.floor(byte0 / 2);
375
+ if (byte0 < 2097152) {
376
+ const value = byte0 * (256 ** 4) + byte1;
377
+ values[i] = String(neg ? -value : value);
378
+ }
379
+ else { // Slow path
380
+ var result = '';
381
+ while (byte1 || byte0) {
382
+ const cur0 = byte0;
383
+ const res0 = cur0 % 10;
384
+ byte0 = (cur0 - res0) / 10;
385
+ const cur1 = byte1 + res0 * (256 ** 4);
386
+ const res1 = cur1 % 10;
387
+ byte1 = (cur1 - res1) / 10;
388
+ result = res1 + result;
389
+ }
390
+ values[i] = (neg ? '-' : '') + (result || '0');
391
+ }
392
+ }
393
+ break;
394
+ }
395
+ case 'SharedString': {
396
+ const indices = chunk.RBXInterleavedUint32(instCount, parser.arrays[parser.arrayIndex++]);
397
+ for (var i = 0; i < instCount; i++) {
398
+ values[i] = parser.sharedStrings[indices[i]].value;
399
+ }
400
+ break;
401
+ }
402
+ case 'UniqueId': {
403
+ const bytes = chunk.Array(instCount * 16);
404
+ for (var i = 0; i < instCount; i++) {
405
+ var result = '';
406
+ for (var j = 0; j < 16; j++) {
407
+ const byte = bytes[j * instCount + i];
408
+ result += ('0' + byte.toString(16)).slice(-2);
409
+ }
410
+ values[i] = result;
411
+ }
412
+ break;
413
+ }
414
+ default:
415
+ if (!typeName) {
416
+ // console.warn(`[RobloxBinaryParser] Unknown dataType 0x${dataType.toString(16).toUpperCase()} (${dataType}) for ${group.ClassName}.${prop}`)
417
+ }
418
+ else {
419
+ // console.warn(`[RobloxBinaryParser] Unimplemented dataType '${typeName}' for ${group.ClassName}.${prop}`)
420
+ }
421
+ break;
422
+ case 'UnknownScriptFormat':
423
+ for (var i = 0; i < instCount; i++) {
424
+ values[i] = `<${typeName || 'Unknown'}>`;
425
+ }
426
+ break;
427
+ }
428
+ if (isOptional) {
429
+ if (this.DataTypes[chunk.Byte()] !== 'bool' || chunk.GetRemaining() !== instCount) {
430
+ // console.warn(`[RobloxBinaryParser] Missing byte array at end of optional`)
431
+ isOptional = false;
432
+ for (var i = 0; i < instCount; i++) {
433
+ values[i] = `<Optional>`;
434
+ }
435
+ }
436
+ }
437
+ for (var index = 0; index < instCount; index++) {
438
+ if (isOptional)
439
+ if (chunk.Byte() === 0)
440
+ continue;
441
+ if (prop == 'AttributesSerialize') {
442
+ try {
443
+ const result = (0, attributes_parser_1.parse_attrs)(Buffer.from(values[index]));
444
+ const Attributes = {};
445
+ result.forEach((v, k) => {
446
+ Attributes[k] = v;
447
+ });
448
+ const finalAttrs = {};
449
+ Object.keys(Attributes).forEach(k => {
450
+ const v = Attributes[k];
451
+ if (Instance_1.AttrAssertions.isBoolAttr(v))
452
+ finalAttrs[k] = v.Bool;
453
+ else if (Instance_1.AttrAssertions.isStringAttr(v))
454
+ finalAttrs[k] = v.BinaryString;
455
+ else if (Instance_1.AttrAssertions.isNumberSequenceAttr(v))
456
+ finalAttrs[k] = v.NumberSequence;
457
+ else if (Instance_1.AttrAssertions.isRectAttr(v))
458
+ finalAttrs[k] = v.Rect;
459
+ else if (Instance_1.AttrAssertions.isCFrameAttr(v))
460
+ finalAttrs[k] = v.CFrame;
461
+ else if (Instance_1.AttrAssertions.isNumberRangeAttr(v))
462
+ finalAttrs[k] = {
463
+ lower: v.NumberRange[0],
464
+ upper: v.NumberRange[1]
465
+ };
466
+ else if (Instance_1.AttrAssertions.isColorSequenceAttr(v))
467
+ finalAttrs[k] = v.ColorSequence;
468
+ else if (Instance_1.AttrAssertions.isVector3Attr(v))
469
+ finalAttrs[k] = {
470
+ x: v.Vector3[0],
471
+ y: v.Vector3[1],
472
+ z: v.Vector3[2]
473
+ };
474
+ else if (Instance_1.AttrAssertions.isUDim2Attr(v))
475
+ finalAttrs[k] = {
476
+ x: {
477
+ scale: v.UDim2[0][0],
478
+ offset: v.UDim2[0][1]
479
+ },
480
+ y: {
481
+ scale: v.UDim2[1][0],
482
+ offset: v.UDim2[1][1]
483
+ }
484
+ };
485
+ else if (Instance_1.AttrAssertions.isVector2Attr(v))
486
+ finalAttrs[k] = {
487
+ x: v.Vector2[0],
488
+ y: v.Vector2[1]
489
+ };
490
+ else if (Instance_1.AttrAssertions.isColor3Attr(v))
491
+ finalAttrs[k] = {
492
+ r: v.Color3[0],
493
+ g: v.Color3[1],
494
+ b: v.Color3[2]
495
+ };
496
+ else if (Instance_1.AttrAssertions.isNumberAttr(v))
497
+ finalAttrs[k] = v.Float64;
498
+ else if (Instance_1.AttrAssertions.isUDimAttr(v))
499
+ finalAttrs[k] = {
500
+ scale: v.UDim[0],
501
+ offset: v.UDim[1]
502
+ };
503
+ else if (Instance_1.AttrAssertions.isBrickColorAttr(v))
504
+ finalAttrs[k] = {
505
+ ...v
506
+ };
507
+ });
508
+ group.Objects[index].Attributes = finalAttrs;
509
+ }
510
+ catch {
511
+ group.Objects[index].setProperty(prop, values[index], resultTypeName);
512
+ }
513
+ }
514
+ else {
515
+ group.Objects[index].setProperty(prop, values[index], resultTypeName);
516
+ }
517
+ }
518
+ },
519
+ parsePRNT(parser, chunk) {
520
+ chunk.Byte();
521
+ const parentCount = chunk.UInt32LE();
522
+ const childIds = chunk.RBXInterleavedInt32(parentCount, parser.arrays[parser.arrayIndex++]);
523
+ const parentIds = chunk.RBXInterleavedInt32(parentCount, parser.arrays[parser.arrayIndex++]);
524
+ var childId = 0;
525
+ var parentId = 0;
526
+ for (var i = 0; i < parentCount; i++) {
527
+ childId += childIds[i];
528
+ parentId += parentIds[i];
529
+ const child = parser.instances[childId];
530
+ if (parentId === -1) {
531
+ parser.result.push(child);
532
+ }
533
+ else {
534
+ child.setProperty('Parent', parser.instances[parentId], 'Instance');
535
+ }
536
+ }
537
+ }
538
+ };
539
+ exports.default = BinaryParser;
@@ -0,0 +1,38 @@
1
+ declare class ByteReader extends Uint8Array {
2
+ index: number;
3
+ chunkBuffer: Uint8Array;
4
+ static ParseFloat(long: any): number;
5
+ static ParseRBXFloat(long: any): number;
6
+ static ParseDouble(long0: any, long1: any): number;
7
+ constructor(...args: any[]);
8
+ SetIndex(n: number): void;
9
+ GetIndex(): number;
10
+ GetRemaining(): number;
11
+ GetLength(): number;
12
+ Jump(n: number): void;
13
+ Array(n: number): Uint8Array<ArrayBuffer>;
14
+ Match(arr: any): boolean;
15
+ Byte(): number;
16
+ UInt8(): number;
17
+ UInt16LE(): number;
18
+ UInt16BE(): number;
19
+ UInt32LE(): number;
20
+ UInt32BE(): number;
21
+ Int8(): number;
22
+ Int16LE(): number;
23
+ Int16BE(): number;
24
+ Int32LE(): number;
25
+ Int32BE(): number;
26
+ FloatLE(): number;
27
+ FloatBE(): number;
28
+ DoubleLE(): number;
29
+ DoubleBE(): number;
30
+ String(n: number): string;
31
+ LZ4(buffer: any): any;
32
+ RBXFloatLE(): number;
33
+ RBXFloatBE(): number;
34
+ RBXInterleavedUint32(count: any, result: any): any;
35
+ RBXInterleavedInt32(count: any, result: any): any;
36
+ RBXInterleavedFloat(count: any, result: any): any;
37
+ }
38
+ export default ByteReader;