@etothepii/satisfactory-file-parser 0.0.10 → 0.0.11

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.
Files changed (46) hide show
  1. package/build/index.d.ts +11 -0
  2. package/build/index.js +12 -0
  3. package/build/parser/blueprint-reader.d.ts +18 -0
  4. package/build/parser/blueprint-reader.js +128 -0
  5. package/build/parser/blueprint-writer.d.ts +21 -0
  6. package/build/parser/blueprint-writer.js +64 -0
  7. package/build/parser/byte/alignment.enum.d.ts +4 -0
  8. package/build/parser/byte/alignment.enum.js +5 -0
  9. package/build/parser/byte/byte-reader.class.d.ts +38 -0
  10. package/build/parser/byte/byte-reader.class.js +128 -0
  11. package/build/parser/byte/byte-writer.class.d.ts +38 -0
  12. package/build/parser/byte/byte-writer.class.js +146 -0
  13. package/build/parser/error/parser.error.d.ts +12 -0
  14. package/build/parser/error/parser.error.js +21 -0
  15. package/build/parser/parser.d.ts +44 -0
  16. package/build/parser/parser.js +81 -0
  17. package/build/parser/satisfactory/blueprint/blueprint.d.ts +20 -0
  18. package/build/parser/satisfactory/blueprint/blueprint.js +1 -0
  19. package/build/parser/satisfactory/level.class.d.ts +21 -0
  20. package/build/parser/satisfactory/level.class.js +144 -0
  21. package/build/parser/satisfactory/objects/DataFields.d.ts +13 -0
  22. package/build/parser/satisfactory/objects/DataFields.js +245 -0
  23. package/build/parser/satisfactory/objects/ObjectReference.d.ts +9 -0
  24. package/build/parser/satisfactory/objects/ObjectReference.js +13 -0
  25. package/build/parser/satisfactory/objects/Property.d.ts +270 -0
  26. package/build/parser/satisfactory/objects/Property.js +1119 -0
  27. package/build/parser/satisfactory/objects/SaveComponent.d.ts +16 -0
  28. package/build/parser/satisfactory/objects/SaveComponent.js +27 -0
  29. package/build/parser/satisfactory/objects/SaveEntity.d.ts +25 -0
  30. package/build/parser/satisfactory/objects/SaveEntity.js +66 -0
  31. package/build/parser/satisfactory/objects/SaveObject.d.ts +14 -0
  32. package/build/parser/satisfactory/objects/SaveObject.js +25 -0
  33. package/build/parser/satisfactory/satisfactory-save.d.ts +57 -0
  34. package/build/parser/satisfactory/satisfactory-save.js +7 -0
  35. package/build/parser/satisfactory/static-data.d.ts +7 -0
  36. package/build/parser/satisfactory/static-data.js +1 -0
  37. package/build/parser/satisfactory/structs/util.types.d.ts +40 -0
  38. package/build/parser/satisfactory/structs/util.types.js +75 -0
  39. package/build/parser/save-reader.d.ts +43 -0
  40. package/build/parser/save-reader.js +243 -0
  41. package/build/parser/save-writer.d.ts +22 -0
  42. package/build/parser/save-writer.js +114 -0
  43. package/package.json +4 -3
  44. package/index.d.ts +0 -2356
  45. package/index.js +0 -2364
  46. package/rollup.config.mjs +0 -11
@@ -0,0 +1,1119 @@
1
+ import { ParseCol4BGRA, ParseCol4RGBA, ParseVec3, ParseVec4, SerializeCol4BGRA, SerializeCol4RGBA, SerializeVec3, SerializeVec4 } from "../structs/util.types";
2
+ import { DataFields } from "./DataFields";
3
+ import { ObjectReference } from "./ObjectReference";
4
+ export class AbstractProperty {
5
+ constructor(type, index) {
6
+ this.type = type;
7
+ this.index = index;
8
+ }
9
+ }
10
+ export class AbstractBaseProperty extends AbstractProperty {
11
+ // overhead like Guid is not calculated into property size
12
+ constructor(type, ueType, index) {
13
+ super(type, index && index !== 0 ? index : undefined);
14
+ this.ueType = ueType;
15
+ this.name = '';
16
+ }
17
+ }
18
+ export class BasicProperty extends AbstractBaseProperty {
19
+ constructor(type, ueType, guidInfo, index = 0) {
20
+ super(type, ueType, index);
21
+ this.guidInfo = guidInfo;
22
+ }
23
+ }
24
+ export const ParseGUID = (reader) => {
25
+ const hasGuid = reader.readByte() === 1;
26
+ let guid;
27
+ if (hasGuid) {
28
+ throw new Error('Unexpected!');
29
+ guid = reader.readBytes(16); //UE Guid is 4 x uint32
30
+ }
31
+ return guid;
32
+ };
33
+ export const SerializeGUID = (writer, guid) => {
34
+ writer.writeByte(guid ? 1 : 0);
35
+ if (guid) {
36
+ writer.writeBytes(guid);
37
+ }
38
+ };
39
+ export class BoolProperty extends BasicProperty {
40
+ constructor(value, ueType = 'BoolProperty', guidInfo = undefined, index = 0) {
41
+ super('BoolProperty', ueType, guidInfo, index);
42
+ this.value = value;
43
+ }
44
+ static Parse(reader, ueType, index = 0) {
45
+ const value = BoolProperty.ReadValue(reader);
46
+ const guidInfo = ParseGUID(reader);
47
+ return new BoolProperty(value, ueType, guidInfo, index);
48
+ }
49
+ static ReadValue(reader) {
50
+ return reader.readByte() > 0;
51
+ }
52
+ static CalcOverhead(property) {
53
+ return 2;
54
+ }
55
+ static Serialize(writer, property) {
56
+ BoolProperty.SerializeValue(writer, property.value);
57
+ SerializeGUID(writer, property.guidInfo);
58
+ }
59
+ static SerializeValue(writer, value) {
60
+ writer.writeByte(value ? 1 : 0);
61
+ }
62
+ }
63
+ export class ByteProperty extends BasicProperty {
64
+ constructor(value, ueType = 'ByteProperty', guidInfo = undefined, index = 0) {
65
+ super('ByteProperty', ueType, guidInfo, index);
66
+ this.value = value;
67
+ }
68
+ static Parse(reader, ueType, index = 0) {
69
+ const type = reader.readString();
70
+ const guidInfo = ParseGUID(reader);
71
+ let value;
72
+ if (type === 'None') {
73
+ value = {
74
+ type,
75
+ value: ByteProperty.ReadValue(reader)
76
+ };
77
+ }
78
+ else {
79
+ value = {
80
+ type,
81
+ value: reader.readString()
82
+ };
83
+ }
84
+ const property = new ByteProperty(value, ueType, guidInfo, index);
85
+ return property;
86
+ }
87
+ static ReadValue(reader) {
88
+ return reader.readByte();
89
+ }
90
+ static CalcOverhead(property) {
91
+ return property.value.type.length + 5 + 1;
92
+ }
93
+ static Serialize(writer, property) {
94
+ writer.writeString(property.value.type);
95
+ SerializeGUID(writer, property.guidInfo);
96
+ if (property.value.type === 'None') {
97
+ ByteProperty.SerializeValue(writer, property.value.value);
98
+ }
99
+ else {
100
+ writer.writeString(property.value.value);
101
+ }
102
+ }
103
+ static SerializeValue(writer, value) {
104
+ writer.writeByte(value);
105
+ }
106
+ }
107
+ export class Int8Property extends BasicProperty {
108
+ constructor(value, ueType = 'Int8Property', guidInfo = undefined, index = 0) {
109
+ super('Int8Property', ueType, guidInfo, index);
110
+ this.value = value;
111
+ }
112
+ static Parse(reader, ueType, index = 0) {
113
+ const guidInfo = ParseGUID(reader);
114
+ const value = Int8Property.ReadValue(reader);
115
+ return new Int8Property(value, ueType, guidInfo, index);
116
+ }
117
+ static ReadValue(reader) {
118
+ return reader.readInt8();
119
+ }
120
+ static CalcOverhead(property) {
121
+ return 1;
122
+ }
123
+ static Serialize(writer, property) {
124
+ SerializeGUID(writer, property.guidInfo);
125
+ Int8Property.SerializeValue(writer, property.value);
126
+ }
127
+ static SerializeValue(writer, value) {
128
+ writer.writeInt8(value);
129
+ }
130
+ }
131
+ export class Uint8Property extends BasicProperty {
132
+ constructor(value, ueType = 'UInt8Property', guidInfo = undefined, index = 0) {
133
+ super('UInt8Property', ueType, guidInfo, index);
134
+ this.value = value;
135
+ }
136
+ static Parse(reader, ueType, index = 0) {
137
+ const guidInfo = ParseGUID(reader);
138
+ const value = Uint8Property.ReadValue(reader);
139
+ return new Uint8Property(value, ueType, guidInfo, index);
140
+ }
141
+ static ReadValue(reader) {
142
+ return reader.readUint8();
143
+ }
144
+ static CalcOverhead(property) {
145
+ throw new Error('Unimplemented.');
146
+ }
147
+ static Serialize(writer, property) {
148
+ SerializeGUID(writer, property.guidInfo);
149
+ Uint8Property.SerializeValue(writer, property.value);
150
+ }
151
+ static SerializeValue(writer, value) {
152
+ writer.writeUint8(value);
153
+ }
154
+ }
155
+ export class Int32Property extends BasicProperty {
156
+ constructor(value, ueType = 'IntProperty', guidInfo = undefined, index = 0) {
157
+ super('Int32Property', ueType, guidInfo, index);
158
+ this.value = value;
159
+ }
160
+ static Parse(reader, ueType, index = 0) {
161
+ const guidInfo = ParseGUID(reader);
162
+ const value = Int32Property.ReadValue(reader);
163
+ return new Int32Property(value, ueType, guidInfo, index);
164
+ }
165
+ static ReadValue(reader) {
166
+ return reader.readInt32();
167
+ }
168
+ static CalcOverhead(property) {
169
+ return 1;
170
+ }
171
+ static Serialize(writer, property) {
172
+ SerializeGUID(writer, property.guidInfo);
173
+ Int32Property.SerializeValue(writer, property.value);
174
+ }
175
+ static SerializeValue(writer, value) {
176
+ writer.writeInt32(value);
177
+ }
178
+ }
179
+ export class Uint32Property extends BasicProperty {
180
+ constructor(value, ueType = 'UInt32Property', guidInfo = undefined, index = 0) {
181
+ super('UInt32Property', ueType, guidInfo, index);
182
+ this.value = value;
183
+ }
184
+ static Parse(reader, ueType, index = 0) {
185
+ const guidInfo = ParseGUID(reader);
186
+ const value = Uint32Property.ReadValue(reader);
187
+ return new Uint32Property(value, ueType, guidInfo, index);
188
+ }
189
+ static ReadValue(reader) {
190
+ return reader.readUint32();
191
+ }
192
+ static CalcOverhead(property) {
193
+ throw new Error('unimplemented');
194
+ }
195
+ static Serialize(writer, property) {
196
+ SerializeGUID(writer, property.guidInfo);
197
+ Uint32Property.SerializeValue(writer, property.value);
198
+ }
199
+ static SerializeValue(writer, value) {
200
+ writer.writeUint32(value);
201
+ }
202
+ }
203
+ export class Int64Property extends BasicProperty {
204
+ constructor(value, ueType = 'Int64Property', guidInfo = undefined, index = 0) {
205
+ super('Int64Property', ueType, guidInfo, index);
206
+ this.value = value;
207
+ }
208
+ static Parse(reader, ueType, index = 0) {
209
+ const guidInfo = ParseGUID(reader);
210
+ const value = Int64Property.ReadValue(reader);
211
+ return new Int64Property(value, ueType, guidInfo, index);
212
+ }
213
+ static ReadValue(reader) {
214
+ return reader.readLong().toString();
215
+ }
216
+ static CalcOverhead(property) {
217
+ return 1;
218
+ }
219
+ static Serialize(writer, property) {
220
+ SerializeGUID(writer, property.guidInfo);
221
+ Int64Property.SerializeValue(writer, property.value);
222
+ }
223
+ static SerializeValue(writer, value) {
224
+ writer.writeInt64(BigInt(value));
225
+ }
226
+ }
227
+ export class FloatProperty extends BasicProperty {
228
+ constructor(value, ueType = 'FloatProperty', guidInfo = undefined, index = 0) {
229
+ super('FloatProperty', ueType, guidInfo, index);
230
+ this.value = value;
231
+ }
232
+ static Parse(reader, ueType, index = 0) {
233
+ const guidInfo = ParseGUID(reader);
234
+ const value = FloatProperty.ReadValue(reader);
235
+ return new FloatProperty(value, ueType, guidInfo, index);
236
+ }
237
+ static CalcOverhead(property) {
238
+ return 1;
239
+ }
240
+ static ReadValue(reader) {
241
+ return reader.readFloat();
242
+ }
243
+ static Serialize(writer, property) {
244
+ SerializeGUID(writer, property.guidInfo);
245
+ FloatProperty.SerializeValue(writer, property.value);
246
+ }
247
+ static SerializeValue(writer, value) {
248
+ writer.writeFloat(value);
249
+ }
250
+ }
251
+ export class DoubleProperty extends BasicProperty {
252
+ constructor(value, ueType = 'DoubleProperty', guidInfo = undefined, index = 0) {
253
+ super('DoubleProperty', ueType, guidInfo, index);
254
+ this.value = value;
255
+ }
256
+ static Parse(reader, ueType, index = 0) {
257
+ const guidInfo = ParseGUID(reader);
258
+ const value = DoubleProperty.ReadValue(reader);
259
+ return new DoubleProperty(value, ueType, guidInfo, index);
260
+ }
261
+ static ReadValue(reader) {
262
+ return reader.readDouble();
263
+ }
264
+ static CalcOverhead(property) {
265
+ return 1;
266
+ }
267
+ static Serialize(writer, property) {
268
+ SerializeGUID(writer, property.guidInfo);
269
+ DoubleProperty.SerializeValue(writer, property.value);
270
+ }
271
+ static SerializeValue(writer, value) {
272
+ writer.writeDouble(value);
273
+ }
274
+ }
275
+ export class StrProperty extends BasicProperty {
276
+ constructor(value, ueType = 'StrProperty', guidInfo = undefined, index = 0) {
277
+ super('StrProperty', ueType, guidInfo, index);
278
+ this.value = value;
279
+ }
280
+ static Parse(reader, ueType, index = 0) {
281
+ const guidInfo = ParseGUID(reader);
282
+ const value = StrProperty.ReadValue(reader);
283
+ return new StrProperty(value, ueType, guidInfo, index);
284
+ }
285
+ static ReadValue(reader) {
286
+ return reader.readString();
287
+ }
288
+ static CalcOverhead(property) {
289
+ return 1;
290
+ }
291
+ static Serialize(writer, property) {
292
+ SerializeGUID(writer, property.guidInfo);
293
+ StrProperty.SerializeValue(writer, property.value);
294
+ }
295
+ static SerializeValue(writer, value) {
296
+ writer.writeString(value);
297
+ }
298
+ }
299
+ export class ObjectProperty extends BasicProperty {
300
+ constructor(value, ueType = 'ObjectProperty', guidInfo = undefined, index = 0) {
301
+ super('ObjectProperty', ueType, guidInfo, index);
302
+ this.value = value;
303
+ }
304
+ static Parse(reader, ueType, index = 0) {
305
+ const guidInfo = ParseGUID(reader);
306
+ const value = ObjectProperty.ReadValue(reader);
307
+ return new ObjectProperty(value, ueType, guidInfo, index);
308
+ }
309
+ static ReadValue(reader) {
310
+ const x = {
311
+ levelName: reader.readString(),
312
+ pathName: reader.readString()
313
+ };
314
+ return x;
315
+ }
316
+ static CalcOverhead(property) {
317
+ return 1;
318
+ }
319
+ static Serialize(writer, property) {
320
+ SerializeGUID(writer, property.guidInfo);
321
+ ObjectProperty.SerializeValue(writer, property.value);
322
+ }
323
+ static SerializeValue(writer, value) {
324
+ writer.writeString(value.levelName);
325
+ writer.writeString(value.pathName);
326
+ }
327
+ }
328
+ export class EnumProperty extends BasicProperty {
329
+ constructor(value, ueType = 'EnumProperty', guidInfo = undefined, index = 0) {
330
+ super('EnumProperty', ueType, guidInfo, index);
331
+ this.value = value;
332
+ }
333
+ static Parse(reader, ueType, index = 0) {
334
+ let name = reader.readString();
335
+ const guidInfo = ParseGUID(reader);
336
+ const value = EnumProperty.ReadValue(reader);
337
+ const property = new EnumProperty({ name, value }, ueType, guidInfo, index);
338
+ return property;
339
+ }
340
+ static ReadValue(reader) {
341
+ return reader.readString();
342
+ }
343
+ static CalcOverhead(property) {
344
+ return property.value.name.length + 6;
345
+ }
346
+ static Serialize(writer, property) {
347
+ writer.writeString(property.value.name);
348
+ SerializeGUID(writer, property.guidInfo);
349
+ EnumProperty.SerializeValue(writer, property.value.value);
350
+ }
351
+ static SerializeValue(writer, value) {
352
+ writer.writeString(value);
353
+ }
354
+ }
355
+ export class TextProperty extends BasicProperty {
356
+ constructor(value, ueType = 'TextProperty', guidInfo = undefined, index = 0) {
357
+ super('TextProperty', ueType, guidInfo, index);
358
+ this.value = value;
359
+ }
360
+ static Parse(reader, ueType, index = 0) {
361
+ //let name = reader.readString();
362
+ const guidInfo = ParseGUID(reader);
363
+ const value = TextProperty.ParseValue(reader);
364
+ return new TextProperty(value, ueType, guidInfo, index);
365
+ }
366
+ static ParseValue(reader) {
367
+ const prop = {
368
+ flags: reader.readInt32(),
369
+ historyType: reader.readByte()
370
+ };
371
+ switch (prop.historyType) {
372
+ // HISTORYTYPE_BASE
373
+ case 0:
374
+ prop.namespace = reader.readString();
375
+ prop.key = reader.readString();
376
+ prop.value = reader.readString();
377
+ break;
378
+ // HISTORYTYPE_NAMEDFORMAT
379
+ case 1:
380
+ // HISTORYTYPE_ARGUMENTFORMAT
381
+ case 3:
382
+ prop.sourceFmt = TextProperty.ParseValue(reader);
383
+ const argumentsCount = reader.readInt32();
384
+ prop.arguments = [];
385
+ for (let i = 0; i < argumentsCount; i++) {
386
+ let currentArgumentsData = {};
387
+ currentArgumentsData.name = reader.readString();
388
+ currentArgumentsData.valueType = reader.readByte();
389
+ switch (currentArgumentsData.valueType) {
390
+ case 4:
391
+ currentArgumentsData.argumentValue = TextProperty.ParseValue(reader);
392
+ break;
393
+ default:
394
+ throw new Error('Unimplemented FormatArgumentType `' + currentArgumentsData.valueType);
395
+ }
396
+ prop.arguments.push(currentArgumentsData);
397
+ }
398
+ break;
399
+ // see https://github.com/EpicGames/UnrealEngine/blob/4.25/Engine/Source/Runtime/Core/Private/Internationalization/TextHistory.cpp#L2268
400
+ // HISTORYTYPE_TRANSFORM
401
+ case 10:
402
+ prop.sourceText = TextProperty.ParseValue(reader);
403
+ prop.transformType = reader.readByte();
404
+ break;
405
+ // HISTORYTYPE_NONE
406
+ case 255:
407
+ // See: https://github.com/EpicGames/UnrealEngine/blob/4.25/Engine/Source/Runtime/Core/Private/Internationalization/Text.cpp#L894
408
+ // TODO: do i need that? check with goz3rr
409
+ //if (this.header!.buildVersion >= 140822) {
410
+ prop.hasCultureInvariantString = reader.readInt32() === 1;
411
+ if (prop.hasCultureInvariantString) {
412
+ prop.value = reader.readString();
413
+ }
414
+ //}
415
+ break;
416
+ default:
417
+ throw new Error('Unimplemented historyType `' + prop.historyType);
418
+ }
419
+ return prop;
420
+ }
421
+ static CalcOverhead(property) {
422
+ return 1;
423
+ }
424
+ static Serialize(writer, property) {
425
+ SerializeGUID(writer, property.guidInfo);
426
+ TextProperty.SerializeValue(writer, property.value);
427
+ }
428
+ static SerializeValue(writer, value) {
429
+ writer.writeInt32(value.flags);
430
+ writer.writeByte(value.historyType);
431
+ switch (value.historyType) {
432
+ // HISTORYTYPE_BASE
433
+ case 0:
434
+ writer.writeString(value.namespace);
435
+ writer.writeString(value.key);
436
+ writer.writeString(value.value);
437
+ break;
438
+ // HISTORYTYPE_NAMEDFORMAT
439
+ case 1:
440
+ // HISTORYTYPE_ARGUMENTFORMAT
441
+ case 3:
442
+ TextProperty.SerializeValue(writer, value.sourceFmt);
443
+ writer.writeInt32(value.arguments.length);
444
+ for (const arg of value.arguments) {
445
+ let currentArgumentsData = {};
446
+ writer.writeString(arg.name);
447
+ writer.writeByte(arg.valueType);
448
+ switch (arg.valueType) {
449
+ case 4:
450
+ TextProperty.SerializeValue(writer, arg.argumentValue);
451
+ break;
452
+ default:
453
+ throw new Error('Unimplemented FormatArgumentType `' + currentArgumentsData.valueType);
454
+ }
455
+ }
456
+ break;
457
+ // see https://github.com/EpicGames/UnrealEngine/blob/4.25/Engine/Source/Runtime/Core/Private/Internationalization/TextHistory.cpp#L2268
458
+ // HISTORYTYPE_TRANSFORM
459
+ case 10:
460
+ TextProperty.SerializeValue(writer, value.sourceText);
461
+ writer.writeByte(value.transformType);
462
+ break;
463
+ // HISTORYTYPE_NONE
464
+ case 255:
465
+ // See: https://github.com/EpicGames/UnrealEngine/blob/4.25/Engine/Source/Runtime/Core/Private/Internationalization/Text.cpp#L894
466
+ // TODO: do i need that? check with goz3rr
467
+ //if (this.header!.buildVersion >= 140822) {
468
+ writer.writeInt32(value.hasCultureInvariantString ? 1 : 0);
469
+ if (value.hasCultureInvariantString) {
470
+ writer.writeString(value.value);
471
+ }
472
+ //}
473
+ break;
474
+ default:
475
+ throw new Error('Unimplemented historyType `' + value.historyType);
476
+ }
477
+ }
478
+ }
479
+ export class StructProperty extends AbstractBaseProperty {
480
+ constructor(subtype, ueType = 'StructProperty', index = 0, guid = 0) {
481
+ super('StructProperty', ueType, index);
482
+ this.subtype = subtype;
483
+ this.guid = guid;
484
+ this.value = { values: {} };
485
+ }
486
+ static Parse(reader, ueType, index, size) {
487
+ const struct = new StructProperty(reader.readString(), ueType, index, reader.readInt32());
488
+ const unk1 = reader.readInt32();
489
+ if (unk1 !== 0) {
490
+ struct.unk1 = unk1;
491
+ }
492
+ const unk2 = reader.readInt32();
493
+ if (unk2 !== 0) {
494
+ struct.unk2 = unk2;
495
+ }
496
+ const unk3 = reader.readInt32();
497
+ if (unk2 !== 0) {
498
+ struct.unk3 = unk3;
499
+ }
500
+ const unk4 = reader.readByte();
501
+ if (unk4 !== 0) {
502
+ struct.unk4 = unk4;
503
+ }
504
+ const before = reader.getBufferPosition();
505
+ struct.value = StructProperty.ParseValue(reader, struct.subtype, size);
506
+ const readBytes = reader.getBufferPosition() - before;
507
+ if (readBytes !== size) {
508
+ throw new Error(`possibly corrupt. Read ${readBytes} for StructProperty Content of ${struct.subtype}, but ${size} were indicated.`);
509
+ }
510
+ return struct;
511
+ }
512
+ static ParseValue(reader, subtype, size) {
513
+ let value;
514
+ switch (subtype) {
515
+ case 'Color':
516
+ value = ParseCol4BGRA(reader);
517
+ break;
518
+ case 'LinearColor':
519
+ value = ParseCol4RGBA(reader);
520
+ break;
521
+ case 'Vector':
522
+ case 'Rotator':
523
+ case 'Vector2D':
524
+ value = ParseVec3(reader);
525
+ break;
526
+ case 'Quat':
527
+ case 'Vector4':
528
+ case 'Vector4D':
529
+ value = ParseVec4(reader);
530
+ break;
531
+ case 'Box':
532
+ value = {
533
+ min: ParseVec3(reader),
534
+ max: ParseVec3(reader),
535
+ isValid: reader.readByte() >= 1
536
+ };
537
+ break;
538
+ case 'RailroadTrackPosition':
539
+ value = {
540
+ root: reader.readString(),
541
+ instanceName: reader.readString(),
542
+ offset: reader.readFloat(),
543
+ forward: reader.readFloat()
544
+ };
545
+ break;
546
+ case 'TimerHandle':
547
+ value = reader.readString();
548
+ break;
549
+ case 'Guid':
550
+ value = reader.readString();
551
+ break;
552
+ case 'InventoryItem':
553
+ value = {
554
+ unk1: reader.readInt32(),
555
+ itemName: reader.readString(),
556
+ unk2: reader.readString(),
557
+ unk3: reader.readString(),
558
+ properties: [],
559
+ };
560
+ //TODO - what is this? currentProperty.value.properties.push(reader.readProperty());
561
+ break;
562
+ case 'FluidBox':
563
+ value = {
564
+ value: reader.readFloat()
565
+ };
566
+ break;
567
+ case 'SlateBrush':
568
+ value = reader.readString();
569
+ break;
570
+ case 'DateTime':
571
+ value = reader.readLong().toString();
572
+ break;
573
+ // MODS
574
+ case 'FINNetworkTrace':
575
+ value = ReadFINNetworkTrace(reader);
576
+ break;
577
+ case 'FINLuaProcessorStateStorage':
578
+ value = {
579
+ values: ReadFINLuaProcessorStateStorage(reader, size)
580
+ };
581
+ break;
582
+ case 'FICFrameRange': // https://github.com/Panakotta00/FicsIt-Cam/blob/c55e254a84722c56e1badabcfaef1159cd7d2ef1/Source/FicsItCam/Public/Data/FICTypes.h#L34
583
+ value = {
584
+ begin: reader.readLong().toString(),
585
+ end: reader.readLong().toString(),
586
+ };
587
+ break;
588
+ default:
589
+ //TODO: use buildversion
590
+ value = ParseDynamicStructData(reader, 0, subtype);
591
+ }
592
+ return value;
593
+ }
594
+ static CalcOverhead(property) {
595
+ return property.subtype.length + 5 + 17;
596
+ }
597
+ static Serialize(writer, property) {
598
+ writer.writeString(property.subtype);
599
+ writer.writeInt32(property.guid);
600
+ writer.writeInt32(property.unk1 ?? 0);
601
+ writer.writeInt32(property.unk2 ?? 0);
602
+ writer.writeInt32(property.unk3 ?? 0);
603
+ writer.writeByte(property.unk4 ?? 0);
604
+ StructProperty.SerializeValue(writer, property.subtype, property.value);
605
+ }
606
+ static SerializeValue(writer, subtype, value) {
607
+ switch (subtype) {
608
+ case 'Color':
609
+ value = value;
610
+ SerializeCol4BGRA(writer, value);
611
+ break;
612
+ case 'LinearColor':
613
+ value = value;
614
+ SerializeCol4RGBA(writer, value);
615
+ break;
616
+ case 'Vector':
617
+ case 'Rotator':
618
+ case 'Vector2D':
619
+ value = value;
620
+ SerializeVec3(writer, value);
621
+ break;
622
+ case 'Quat':
623
+ case 'Vector4':
624
+ case 'Vector4D':
625
+ value = value;
626
+ SerializeVec4(writer, value);
627
+ break;
628
+ case 'Box':
629
+ value = value;
630
+ SerializeVec3(writer, value.min);
631
+ SerializeVec3(writer, value.max);
632
+ writer.writeByte(value.isValid ? 1 : 0);
633
+ break;
634
+ case 'RailroadTrackPosition':
635
+ value = value;
636
+ writer.writeString(value.root);
637
+ writer.writeString(value.instanceName);
638
+ writer.writeFloat(value.offset);
639
+ writer.writeFloat(value.forward);
640
+ break;
641
+ case 'TimerHandle':
642
+ value = value;
643
+ writer.writeString(value);
644
+ break;
645
+ case 'Guid':
646
+ value = value;
647
+ writer.writeString(value);
648
+ break;
649
+ case 'InventoryItem':
650
+ value = value;
651
+ writer.writeInt32(value.unk1);
652
+ writer.writeString(value.itemName);
653
+ writer.writeString(value.unk2);
654
+ writer.writeString(value.unk3);
655
+ //TODO - how to write properties?
656
+ break;
657
+ case 'FluidBox':
658
+ value = value;
659
+ writer.writeFloat(value.value);
660
+ break;
661
+ case 'SlateBrush':
662
+ value = value;
663
+ writer.writeString(value);
664
+ break;
665
+ case 'DateTime':
666
+ value = value;
667
+ writer.writeInt64(BigInt(value));
668
+ break;
669
+ // MODS
670
+ case 'FINNetworkTrace':
671
+ value = value;
672
+ SerializeFINNetworkTrace(writer, value);
673
+ break;
674
+ case 'FINLuaProcessorStateStorage':
675
+ value = value;
676
+ SerializeFINLuaProcessorStateStorage(writer, value.values);
677
+ break;
678
+ case 'FICFrameRange': // https://github.com/Panakotta00/FicsIt-Cam/blob/c55e254a84722c56e1badabcfaef1159cd7d2ef1/Source/FicsItCam/Public/Data/FICTypes.h#L34
679
+ value = value;
680
+ writer.writeInt64(BigInt(value.begin));
681
+ writer.writeInt64(BigInt(value.end));
682
+ break;
683
+ default:
684
+ //TODO: use buildversion
685
+ value = value;
686
+ SerializeDynamicStructData(writer, 0, value);
687
+ }
688
+ }
689
+ }
690
+ export class ArrayProperty extends BasicProperty {
691
+ constructor(subtype, values, ueType = 'ArrayProperty', index = 0, structValueFields) {
692
+ super('ArrayProperty', ueType, undefined, index);
693
+ this.subtype = subtype;
694
+ this.values = values;
695
+ this.structValueFields = structValueFields;
696
+ }
697
+ static Parse(reader, ueType, index, propertyName) {
698
+ const subtype = reader.readString();
699
+ reader.skipBytes(); // unk
700
+ let property;
701
+ const elementCount = reader.readInt32();
702
+ switch (subtype) {
703
+ case "FloatProperty":
704
+ property = new ArrayProperty(subtype, new Array(elementCount).fill(0).map(e => FloatProperty.ReadValue(reader)), ueType, index);
705
+ break;
706
+ case "BoolProperty":
707
+ property = new ArrayProperty(subtype, new Array(elementCount).fill(0).map(e => BoolProperty.ReadValue(reader)), ueType, index);
708
+ break;
709
+ case "IntProperty":
710
+ property = new ArrayProperty(subtype, new Array(elementCount).fill(0).map(e => Int32Property.ReadValue(reader)), ueType, index);
711
+ break;
712
+ case "Int64Property":
713
+ property = new ArrayProperty(subtype, new Array(elementCount).fill(0).map(e => Int64Property.ReadValue(reader)), ueType, index);
714
+ break;
715
+ case "DoubleProperty":
716
+ property = new ArrayProperty(subtype, new Array(elementCount).fill(0).map(e => DoubleProperty.ReadValue(reader)), ueType, index);
717
+ break;
718
+ case "ByteProperty":
719
+ property = new ArrayProperty(subtype, new Array(elementCount).fill(0).map(e => ByteProperty.ReadValue(reader)), ueType, index);
720
+ break;
721
+ case "StrProperty":
722
+ property = new ArrayProperty(subtype, new Array(elementCount).fill(0).map(e => StrProperty.ReadValue(reader)), ueType, index);
723
+ break;
724
+ case "EnumProperty":
725
+ property = new ArrayProperty(subtype, new Array(elementCount).fill(0).map(e => EnumProperty.ReadValue(reader)), ueType, index);
726
+ break;
727
+ case "TextProperty":
728
+ property = new ArrayProperty(subtype, new Array(elementCount).fill(0).map(e => TextProperty.ParseValue(reader)), ueType, index);
729
+ break;
730
+ case "InterfaceProperty":
731
+ case "ObjectProperty":
732
+ property = new ArrayProperty(subtype, new Array(elementCount).fill(0).map(e => ObjectProperty.ReadValue(reader)), ueType, index);
733
+ break;
734
+ case "StructProperty":
735
+ const name = reader.readString(); // Same as currentProperty.name
736
+ const type = reader.readString(); // StructProperty
737
+ const binarySize = reader.readInt32(); // structureSize
738
+ const allIndex = reader.readInt32(); // 0
739
+ const allStructType = reader.readString();
740
+ const allGuid = reader.readInt32();
741
+ const allUnk1 = reader.readInt32();
742
+ const allUnk2 = reader.readInt32();
743
+ const allUnk3 = reader.readInt32();
744
+ const allUnk4 = reader.readByte();
745
+ const innerStructValueFields = { allStructType, allIndex, allGuid };
746
+ if (allUnk1 !== 0) {
747
+ innerStructValueFields.allUnk1 = allUnk1;
748
+ }
749
+ if (allUnk2 !== 0) {
750
+ innerStructValueFields.allUnk2 = allUnk2;
751
+ }
752
+ if (allUnk3 !== 0) {
753
+ innerStructValueFields.allUnk3 = allUnk3;
754
+ }
755
+ if (allUnk4 !== 0) {
756
+ innerStructValueFields.allUnk4 = allUnk4;
757
+ }
758
+ const before = reader.getBufferPosition();
759
+ const maArr = new Array(elementCount).fill(0).map(e => {
760
+ const struct = new StructProperty(allStructType, type, allIndex, allGuid);
761
+ // we do NOT assign individual unk's here. Since they are only serialized always on ArrayProperty's Level once for all elements.
762
+ //struct.unk1 = allUnk1;
763
+ //struct.unk2 = allUnk2;
764
+ //struct.unk3 = allUnk3;
765
+ //struct.unk4 = allUnk4;
766
+ struct.value = StructProperty.ParseValue(reader, allStructType, binarySize);
767
+ return struct;
768
+ });
769
+ const readBytees = reader.getBufferPosition() - before;
770
+ if (readBytees !== binarySize) {
771
+ throw new Error('possibly corrupt in array of struct.');
772
+ }
773
+ // Array Properties with struct values have some more properties.
774
+ property = new ArrayProperty(subtype, maArr, ueType, index, innerStructValueFields);
775
+ break;
776
+ default:
777
+ console.log(subtype, ueType);
778
+ throw new Error();
779
+ }
780
+ return property;
781
+ }
782
+ static CalcOverhead(property) {
783
+ return property.subtype.length + 5 + 1;
784
+ }
785
+ static Serialize(writer, property, propertyName) {
786
+ writer.writeString(property.subtype);
787
+ writer.writeByte(0);
788
+ writer.writeInt32(property.values.length);
789
+ switch (property.subtype) {
790
+ case "FloatProperty":
791
+ property.values.forEach(v => FloatProperty.SerializeValue(writer, v));
792
+ break;
793
+ case "BoolProperty":
794
+ property.values.forEach(v => BoolProperty.SerializeValue(writer, v));
795
+ break;
796
+ case "IntProperty":
797
+ property.values.forEach(v => Int32Property.SerializeValue(writer, v));
798
+ break;
799
+ case "Int64Property":
800
+ property.values.forEach(v => Int64Property.SerializeValue(writer, v));
801
+ break;
802
+ case "DoubleProperty":
803
+ property.values.forEach(v => DoubleProperty.SerializeValue(writer, v));
804
+ break;
805
+ case "ByteProperty":
806
+ property.values.forEach(v => ByteProperty.SerializeValue(writer, v));
807
+ break;
808
+ case "StrProperty":
809
+ property.values.forEach(v => StrProperty.SerializeValue(writer, v));
810
+ break;
811
+ case "EnumProperty":
812
+ property.values.forEach(v => EnumProperty.SerializeValue(writer, v));
813
+ break;
814
+ case "TextProperty":
815
+ property.values.forEach(v => TextProperty.SerializeValue(writer, v));
816
+ break;
817
+ case "InterfaceProperty":
818
+ case "ObjectProperty":
819
+ property.values.forEach(v => ObjectProperty.SerializeValue(writer, v));
820
+ break;
821
+ case "StructProperty":
822
+ writer.writeString(propertyName);
823
+ writer.writeString(property.subtype);
824
+ const lenIndicator = writer.getBufferPosition();
825
+ writer.writeInt32(0);
826
+ writer.writeInt32(property.structValueFields.allIndex);
827
+ writer.writeString(property.structValueFields.allStructType);
828
+ writer.writeInt32(property.structValueFields.allGuid);
829
+ writer.writeInt32(property.structValueFields.allUnk1 ?? 0);
830
+ writer.writeInt32(property.structValueFields.allUnk2 ?? 0);
831
+ writer.writeInt32(property.structValueFields.allUnk3 ?? 0);
832
+ writer.writeByte(property.structValueFields.allUnk4 ?? 0);
833
+ const before = writer.getBufferPosition();
834
+ property.values.forEach(v => StructProperty.SerializeValue(writer, property.structValueFields.allStructType, v.value));
835
+ writer.writeBinarySizeFromPosition(lenIndicator, before);
836
+ break;
837
+ default:
838
+ console.log(property.type, property.ueType);
839
+ throw new Error();
840
+ }
841
+ }
842
+ }
843
+ export class SetProperty extends BasicProperty {
844
+ constructor(subtype, values, ueType, index) {
845
+ super('SetProperty', ueType, undefined, index);
846
+ this.subtype = subtype;
847
+ this.values = values;
848
+ }
849
+ static Parse(reader, ueType, index, propertyName) {
850
+ const subtype = reader.readString();
851
+ reader.skipBytes(1); // unk
852
+ reader.skipBytes(4); // unk2
853
+ const elementCount = reader.readInt32();
854
+ let property;
855
+ switch (subtype) {
856
+ case "IntProperty":
857
+ property = new SetProperty(subtype, new Array(elementCount).fill(0).map(e => Int32Property.ReadValue(reader)), ueType, index);
858
+ break;
859
+ case "ObjectProperty":
860
+ property = new SetProperty(subtype, new Array(elementCount).fill(0).map(e => ObjectProperty.ReadValue(reader)), ueType, index);
861
+ break;
862
+ case "NameProperty":
863
+ property = new SetProperty(subtype, new Array(elementCount).fill(0).map(e => StrProperty.ReadValue(reader)), ueType, index);
864
+ break;
865
+ case "StructProperty":
866
+ if (propertyName === 'mRemovalLocations') {
867
+ property = new SetProperty(subtype, new Array(elementCount).fill(0).map(e => ParseVec3(reader)), ueType, index);
868
+ }
869
+ break;
870
+ default:
871
+ throw new Error('Not Implemented.');
872
+ }
873
+ return property;
874
+ }
875
+ static CalcOverhead(property) {
876
+ return property.subtype.length + 5 + 1;
877
+ }
878
+ static Serialize(writer, property) {
879
+ writer.writeString(property.subtype);
880
+ //TODO: what is that
881
+ writer.writeByte(0);
882
+ writer.writeInt32(0);
883
+ writer.writeInt32(property.values.length);
884
+ switch (property.subtype) {
885
+ case "IntProperty":
886
+ property.values.forEach(v => Int32Property.SerializeValue(writer, v));
887
+ break;
888
+ case "ObjectProperty":
889
+ property.values.forEach(v => ObjectProperty.SerializeValue(writer, v));
890
+ break;
891
+ case "NameProperty":
892
+ property.values.forEach(v => StrProperty.SerializeValue(writer, v));
893
+ break;
894
+ case "StructProperty":
895
+ //TODO: this would only work for mRemovalLocations. Get a way to check for propertyname at least.
896
+ property.values.forEach(v => SerializeVec3(writer, v));
897
+ break;
898
+ default:
899
+ throw new Error('Not Implemented.');
900
+ }
901
+ }
902
+ }
903
+ export class MapProperty extends BasicProperty {
904
+ constructor(keyType, valueType, ueType, index) {
905
+ super('MapProperty', ueType, undefined, index);
906
+ this.keyType = keyType;
907
+ this.valueType = valueType;
908
+ this.modeType = 2;
909
+ this.modeUnk2 = '';
910
+ this.modeUnk3 = '';
911
+ this.remainingData = [];
912
+ this.values = [];
913
+ }
914
+ static Parse(reader, propertyName, buildVersion, size, ueType = 'MapProperty', index = 0) {
915
+ const start = reader.getBufferPosition();
916
+ const property = new MapProperty(reader.readString(), reader.readString(), ueType, index);
917
+ reader.skipBytes(1);
918
+ property.modeType = reader.readInt32();
919
+ //property.remainingData = reader.readBytes(size - (reader.getBufferPosition() - start));
920
+ property.remainingData = Array.from(reader.readBytes(size - 4));
921
+ // TODO
922
+ /*
923
+
924
+ if (property.modeType === 2) {
925
+ property.modeUnk2 = reader.readString();
926
+ property.modeUnk3 = reader.readString();
927
+ } else if (property.modeType === 3) {
928
+ property.modeUnk1 = reader.readHex(9);
929
+ property.modeUnk2 = reader.readString();
930
+ property.modeUnk3 = reader.readString();
931
+ }
932
+
933
+ let elementCount = reader.readInt32();
934
+ for (let i = 0; i < elementCount; i++) {
935
+ let key: number | string | ObjectReferenceV2 | vec3 | any[] | boolean;
936
+ let value: number | string | ObjectReferenceV2 | any[] | boolean;
937
+
938
+ switch (property.keyType) {
939
+ case 'IntProperty':
940
+ key = Int32Property.ReadValue(reader);
941
+ break;
942
+ case 'Int64Property':
943
+ key = Int64Property.ReadValue(reader);
944
+ break;
945
+ case 'NameProperty':
946
+ case 'StrProperty':
947
+ key = StrProperty.ReadValue(reader);
948
+ break;
949
+ case 'ObjectProperty':
950
+ key = ObjectProperty.ReadValue(reader);
951
+ break;
952
+ case 'EnumProperty':
953
+ key = EnumProperty.ReadValue(reader);
954
+ break;
955
+ case 'StructProperty':
956
+ if (propertyName === 'Destroyed_Foliage_Transform' || parentType === '/BuildGunUtilities/BGU_Subsystem.BGU_Subsystem_C') // Mod: Universal Destroyer/Factory Statistics
957
+ {
958
+ key = ParseVec3(reader);
959
+ break;
960
+ }
961
+
962
+ key = [];
963
+ while (true) {
964
+ let singleValueProperty = DataFieldsV2.ParseProperty(reader, buildVersion, propertyName);
965
+ if (singleValueProperty === null) {
966
+ break;
967
+ }
968
+
969
+ key.push(singleValueProperty);
970
+ }
971
+ break;
972
+ default:
973
+ throw new Error(`not implemented type ${property.keyType}`);
974
+ }
975
+
976
+
977
+ switch (property.valueType) {
978
+ case 'ByteProperty':
979
+ if (property.keyType === 'StrProperty') {
980
+ value = reader.readString();
981
+ }
982
+ else {
983
+ value = reader.readByte();
984
+ }
985
+ break;
986
+ case 'BoolProperty':
987
+ value = BoolProperty.ReadValue(reader);
988
+ break;
989
+ case 'IntProperty':
990
+ value = Int32Property.ReadValue(reader);
991
+ break;
992
+ case 'FloatProperty':
993
+ value = FloatProperty.ReadValue(reader);
994
+ break;
995
+ case 'StrProperty':
996
+ value = StrProperty.ReadValue(reader);
997
+ break;
998
+ case 'ObjectProperty':
999
+ value = ObjectProperty.ReadValue(reader);
1000
+ break;
1001
+ case 'StructProperty':
1002
+ // TODO: what is this
1003
+ /*
1004
+ if (parentType === 'LBBalancerData') {
1005
+ mapPropertySubProperties.mNormalIndex = this.readInt32();
1006
+ mapPropertySubProperties.mOverflowIndex = this.readInt32();
1007
+ mapPropertySubProperties.mFilterIndex = this.readInt32();
1008
+ }
1009
+ else { }
1010
+ */
1011
+ /*
1012
+
1013
+ value = [];
1014
+ while (true) {
1015
+ let singleValueProperty = DataFieldsV2.ParseProperty(reader, buildVersion, propertyName);
1016
+ if (singleValueProperty === null) {
1017
+ break;
1018
+ }
1019
+
1020
+ value.push(singleValueProperty);
1021
+ }
1022
+ break;
1023
+ default:
1024
+ throw new Error(`not implemented type ${property.valueType}`);
1025
+ }
1026
+
1027
+ property.values.push({
1028
+ key, value
1029
+ });
1030
+ }
1031
+ */
1032
+ return property;
1033
+ }
1034
+ static CalcOverhead(property) {
1035
+ return property.keyType.length + 5 + property.valueType.length + 5 + 1;
1036
+ }
1037
+ static Serialize(writer, property) {
1038
+ writer.writeString(property.keyType);
1039
+ writer.writeString(property.valueType);
1040
+ writer.writeByte(0);
1041
+ writer.writeInt32(property.modeType);
1042
+ writer.writeBytesArray(property.remainingData);
1043
+ //TODO: do the actual serialization.
1044
+ }
1045
+ }
1046
+ export const ParseDynamicStructData = (reader, buildVersion, type) => {
1047
+ const data = {
1048
+ type, properties: {}
1049
+ };
1050
+ let propertyName = reader.readString();
1051
+ while (propertyName !== 'None') {
1052
+ const property = DataFields.ParseProperty(reader, buildVersion, propertyName);
1053
+ data.properties[propertyName] = property;
1054
+ propertyName = reader.readString();
1055
+ }
1056
+ return data;
1057
+ };
1058
+ export const SerializeDynamicStructData = (writer, buildVersion, data) => {
1059
+ for (const key in data.properties) {
1060
+ writer.writeString(key);
1061
+ DataFields.SerializeProperty(writer, data.properties[key], key, buildVersion);
1062
+ }
1063
+ writer.writeString('None');
1064
+ };
1065
+ export const ReadFINNetworkTrace = (reader) => {
1066
+ const networkTrace = {};
1067
+ networkTrace.ref = ObjectReference.Parse(reader);
1068
+ networkTrace.hasPrev = reader.readInt32();
1069
+ if (networkTrace.hasPrev) {
1070
+ networkTrace.prev = ReadFINNetworkTrace(reader);
1071
+ }
1072
+ networkTrace.hasStep = reader.readInt32();
1073
+ if (networkTrace.hasStep) {
1074
+ networkTrace.step = reader.readString();
1075
+ }
1076
+ return networkTrace;
1077
+ };
1078
+ export const SerializeFINNetworkTrace = (writer, obj) => {
1079
+ const networkTrace = {};
1080
+ ObjectReference.Serialize(writer, obj.ref);
1081
+ writer.writeInt32(obj.hasPrev);
1082
+ if (obj.hasPrev) {
1083
+ SerializeFINNetworkTrace(writer, obj.prev);
1084
+ }
1085
+ writer.writeInt32(obj.hasStep);
1086
+ if (obj.hasStep) {
1087
+ writer.writeString(obj.step);
1088
+ }
1089
+ };
1090
+ export const ReadFINLuaProcessorStateStorage = (reader, size) => {
1091
+ const stateStorage = { traces: [], references: [], thread: '', globals: '', remainingStructData: {} };
1092
+ const start = reader.getBufferPosition();
1093
+ const traceCount = reader.readInt32();
1094
+ for (let i = 0; i < traceCount; i++) {
1095
+ stateStorage.traces.push(ReadFINNetworkTrace(reader));
1096
+ }
1097
+ const refCount = reader.readInt32();
1098
+ for (let i = 0; i < refCount; i++) {
1099
+ stateStorage.references.push(ObjectReference.Parse(reader));
1100
+ }
1101
+ stateStorage.thread = reader.readString();
1102
+ stateStorage.globals = reader.readString();
1103
+ const remaining = size - (reader.getBufferPosition() - start);
1104
+ stateStorage.remainingStructData = reader.readBytes(remaining);
1105
+ return stateStorage;
1106
+ };
1107
+ export const SerializeFINLuaProcessorStateStorage = (writer, stateStorage) => {
1108
+ writer.writeInt32(stateStorage.traces.length);
1109
+ for (const trace of stateStorage.traces) {
1110
+ SerializeFINNetworkTrace(writer, trace);
1111
+ }
1112
+ writer.writeInt32(stateStorage.references.length);
1113
+ for (const ref of stateStorage.references) {
1114
+ ObjectReference.Serialize(writer, ref);
1115
+ }
1116
+ writer.writeString(stateStorage.thread);
1117
+ writer.writeString(stateStorage.globals);
1118
+ writer.writeBytes(stateStorage.remainingStructData);
1119
+ };