@etothepii/satisfactory-file-parser 0.0.15 → 0.0.17

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 (32) hide show
  1. package/README.md +49 -11
  2. package/build/index.d.ts +10 -8
  3. package/build/index.js +10 -12
  4. package/build/parser/byte/byte-reader.class.d.ts +1 -38
  5. package/build/parser/byte/byte-reader.class.js +0 -11
  6. package/build/parser/byte/byte-writer.class.d.ts +1 -38
  7. package/build/parser/byte/byte-writer.class.js +0 -10
  8. package/build/parser/file.types.d.ts +9 -0
  9. package/build/parser/file.types.js +2 -0
  10. package/build/parser/parser.d.ts +12 -40
  11. package/build/parser/parser.js +51 -47
  12. package/build/parser/satisfactory/blueprint/blueprint-reader.d.ts +18 -0
  13. package/build/parser/satisfactory/blueprint/blueprint-reader.js +124 -0
  14. package/build/parser/satisfactory/blueprint/blueprint-writer.d.ts +15 -0
  15. package/build/parser/satisfactory/blueprint/blueprint-writer.js +63 -0
  16. package/build/parser/satisfactory/blueprint/blueprint.types.d.ts +20 -0
  17. package/build/parser/satisfactory/blueprint/blueprint.types.js +2 -0
  18. package/build/parser/satisfactory/objects/DataFields.d.ts +1 -1
  19. package/build/parser/satisfactory/objects/DataFields.js +0 -25
  20. package/build/parser/satisfactory/objects/Property.d.ts +1 -1
  21. package/build/parser/satisfactory/objects/Property.js +10 -159
  22. package/build/parser/satisfactory/save/level.class.d.ts +21 -0
  23. package/build/parser/satisfactory/save/level.class.js +138 -0
  24. package/build/parser/satisfactory/save/satisfactory-save.d.ts +11 -0
  25. package/build/parser/satisfactory/save/satisfactory-save.js +11 -0
  26. package/build/parser/satisfactory/save/save-reader.d.ts +44 -0
  27. package/build/parser/satisfactory/save/save-reader.js +233 -0
  28. package/build/parser/satisfactory/save/save-writer.d.ts +12 -0
  29. package/build/parser/satisfactory/save/save-writer.js +112 -0
  30. package/build/parser/satisfactory/save/save.types.d.ts +49 -0
  31. package/build/parser/satisfactory/save/save.types.js +2 -0
  32. package/package.json +6 -2
@@ -0,0 +1,124 @@
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
+ exports.BlueprintConfigReader = exports.BlueprintReader = void 0;
7
+ const pako_1 = __importDefault(require("pako"));
8
+ const alignment_enum_1 = require("../../byte/alignment.enum");
9
+ const byte_reader_class_1 = require("../../byte/byte-reader.class");
10
+ const parser_error_1 = require("../../error/parser.error");
11
+ const level_class_1 = require("../save/level.class");
12
+ const util_types_1 = require("../structs/util.types");
13
+ class BlueprintReader extends byte_reader_class_1.ByteReader {
14
+ constructor(bluePrintBuffer) {
15
+ super(bluePrintBuffer, alignment_enum_1.Alignment.LITTLE_ENDIAN);
16
+ this.compressionInfo = {
17
+ packageFileTag: 0,
18
+ maxChunkContentSize: 0,
19
+ chunkHeaderSize: 48
20
+ };
21
+ }
22
+ static ReadHeader(reader) {
23
+ const unk = reader.readBytes(3 * 4);
24
+ const positionThingOrWhat = (0, util_types_1.ParseVec3)(reader);
25
+ let itemTypeCount = reader.readInt32();
26
+ const itemCosts = new Array(itemTypeCount).fill(['', 0]);
27
+ for (let i = 0; i < itemTypeCount; i++) {
28
+ let indexOrWhat = reader.readInt32();
29
+ let itemPathName = reader.readString();
30
+ let itemCount = reader.readInt32();
31
+ itemCosts[i] = [itemPathName, itemCount];
32
+ }
33
+ let recipeCount = reader.readInt32();
34
+ const recipeRefs = new Array(recipeCount).fill('');
35
+ for (let i = 0; i < recipeCount; i++) {
36
+ let indexOrWhat = reader.readInt32();
37
+ const recipeName = reader.readString();
38
+ recipeRefs[i] = recipeName;
39
+ }
40
+ return {
41
+ recipeReferences: recipeRefs,
42
+ itemCosts
43
+ };
44
+ }
45
+ inflateChunks() {
46
+ this.fileBuffer = this.fileBuffer.slice(this.currentByte);
47
+ this.handledByte = 0;
48
+ this.currentByte = 0;
49
+ this.maxByte = this.fileBuffer.byteLength;
50
+ let currentChunks = [];
51
+ let totalUncompressedBodySize = 0;
52
+ while (this.handledByte < this.maxByte) {
53
+ let chunkHeader = new DataView(this.fileBuffer.slice(0, this.compressionInfo.chunkHeaderSize));
54
+ this.currentByte = this.compressionInfo.chunkHeaderSize;
55
+ this.handledByte += this.compressionInfo.chunkHeaderSize;
56
+ if (this.compressionInfo.packageFileTag <= 0) {
57
+ this.compressionInfo.packageFileTag = chunkHeader.getUint32(0, this.alignment === alignment_enum_1.Alignment.LITTLE_ENDIAN);
58
+ }
59
+ if (this.compressionInfo.maxChunkContentSize <= 0) {
60
+ this.compressionInfo.maxChunkContentSize = chunkHeader.getInt32(8, this.alignment === alignment_enum_1.Alignment.LITTLE_ENDIAN);
61
+ }
62
+ const chunkCompressedLength = chunkHeader.getInt32(32, this.alignment === alignment_enum_1.Alignment.LITTLE_ENDIAN);
63
+ const chunkUncompressedLength = chunkHeader.getInt32(40, this.alignment === alignment_enum_1.Alignment.LITTLE_ENDIAN);
64
+ totalUncompressedBodySize += chunkUncompressedLength;
65
+ const currentChunkSize = chunkCompressedLength;
66
+ let currentChunk = this.fileBuffer.slice(this.currentByte, this.currentByte + currentChunkSize);
67
+ this.handledByte += currentChunkSize;
68
+ this.currentByte += currentChunkSize;
69
+ this.fileBuffer = this.fileBuffer.slice(this.currentByte);
70
+ this.currentByte = 0;
71
+ try {
72
+ let currentInflatedChunk = null;
73
+ currentInflatedChunk = pako_1.default.inflate(currentChunk);
74
+ currentChunks.push(currentInflatedChunk);
75
+ }
76
+ catch (err) {
77
+ throw new parser_error_1.ParserError('ParserError', 'An error occurred while calling pako inflate.' + err);
78
+ }
79
+ }
80
+ let newChunkLength = currentChunks.map(cc => cc.length).reduce((prev, cur) => prev + cur);
81
+ const bigWholeChunk = new Uint8Array(newChunkLength);
82
+ let currentLength = 0;
83
+ for (let i = 0; i < currentChunks.length; i++) {
84
+ bigWholeChunk.set(currentChunks[i], currentLength);
85
+ currentLength += currentChunks[i].length;
86
+ }
87
+ this.currentByte = 0;
88
+ this.maxByte = bigWholeChunk.buffer.byteLength;
89
+ this.bufferView = new DataView(bigWholeChunk.buffer);
90
+ return {
91
+ newChunkLength,
92
+ numChunks: currentChunks.length,
93
+ inflatedData: bigWholeChunk
94
+ };
95
+ }
96
+ static ParseObjects(reader) {
97
+ const totalBodyRestSize = reader.readInt32();
98
+ const objectHeadersBinarySize = reader.readInt32();
99
+ let objects = [];
100
+ level_class_1.Level.ReadObjectHeaders(reader, objects, () => { });
101
+ level_class_1.Level.ReadObjectContents(reader, objects, 0, () => { });
102
+ return objects;
103
+ }
104
+ }
105
+ exports.BlueprintReader = BlueprintReader;
106
+ class BlueprintConfigReader extends byte_reader_class_1.ByteReader {
107
+ constructor(bluePrintConfigBuffer) {
108
+ super(bluePrintConfigBuffer, alignment_enum_1.Alignment.LITTLE_ENDIAN);
109
+ this.bluePrintConfigBuffer = bluePrintConfigBuffer;
110
+ this.parse = () => BlueprintConfigReader.ParseConfig(this);
111
+ }
112
+ static ParseConfig(reader) {
113
+ const unk = reader.readInt32();
114
+ const description = reader.readString();
115
+ const unk3 = reader.readInt32();
116
+ const colorMaybe = (0, util_types_1.ParseCol4RGBA)(reader);
117
+ return {
118
+ description,
119
+ color: colorMaybe,
120
+ iconID: unk3
121
+ };
122
+ }
123
+ }
124
+ exports.BlueprintConfigReader = BlueprintConfigReader;
@@ -0,0 +1,15 @@
1
+ import { ByteWriter } from "../../byte/byte-writer.class";
2
+ import { ChunkCompressionInfo, ChunkSummary } from "../../file.types";
3
+ import { SaveComponent } from "../objects/SaveComponent";
4
+ import { SaveEntity } from "../objects/SaveEntity";
5
+ import { BlueprintConfig, BlueprintHeader } from "./blueprint.types";
6
+ export declare class BlueprintWriter extends ByteWriter {
7
+ constructor();
8
+ static SerializeHeader(writer: ByteWriter, header: BlueprintHeader): void;
9
+ generateChunks(compressionInfo: ChunkCompressionInfo, posAfterHeader: number, onBinaryBeforeCompressing: (binary: ArrayBuffer) => void, onHeader: (header: Uint8Array) => void, onChunk: (chunk: Uint8Array) => void): ChunkSummary[];
10
+ static SerializeObjects(writer: ByteWriter, objects: (SaveEntity | SaveComponent)[]): void;
11
+ }
12
+ export declare class BlueprintConfigWriter extends ByteWriter {
13
+ constructor();
14
+ static SerializeConfig(writer: ByteWriter, config: BlueprintConfig): void;
15
+ }
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BlueprintConfigWriter = exports.BlueprintWriter = void 0;
4
+ const alignment_enum_1 = require("../../byte/alignment.enum");
5
+ const byte_writer_class_1 = require("../../byte/byte-writer.class");
6
+ const parser_error_1 = require("../../error/parser.error");
7
+ const level_class_1 = require("../save/level.class");
8
+ const save_writer_1 = require("../save/save-writer");
9
+ const util_types_1 = require("../structs/util.types");
10
+ class BlueprintWriter extends byte_writer_class_1.ByteWriter {
11
+ constructor() {
12
+ super(alignment_enum_1.Alignment.LITTLE_ENDIAN);
13
+ }
14
+ static SerializeHeader(writer, header) {
15
+ writer.writeInt32(2);
16
+ writer.writeInt32(36);
17
+ writer.writeInt32(211839);
18
+ writer.writeInt32(4);
19
+ writer.writeInt32(4);
20
+ writer.writeInt32(4);
21
+ writer.writeInt32(header.itemCosts.length);
22
+ for (const itemCost of header.itemCosts) {
23
+ writer.writeInt32(0);
24
+ writer.writeString(itemCost[0]);
25
+ writer.writeInt32(itemCost[1]);
26
+ }
27
+ writer.writeInt32(header.recipeReferences.length);
28
+ for (const recipeReference of header.recipeReferences) {
29
+ writer.writeInt32(0);
30
+ writer.writeString(recipeReference);
31
+ }
32
+ }
33
+ generateChunks(compressionInfo, posAfterHeader, onBinaryBeforeCompressing, onHeader, onChunk) {
34
+ if (posAfterHeader <= 0) {
35
+ throw new parser_error_1.ParserError('ParserError', 'seems like this buffer has no header. Please write the header first before you can generate chunks.');
36
+ }
37
+ const header = new Uint8Array(this.bufferArray.slice(0, posAfterHeader));
38
+ onHeader(header);
39
+ this.bufferArray = this.bufferArray.slice(posAfterHeader);
40
+ const chunkSummary = save_writer_1.SaveWriter.GenerateCompressedChunksFromData(this.bufferArray, compressionInfo, onBinaryBeforeCompressing, onChunk, this.alignment);
41
+ return chunkSummary;
42
+ }
43
+ static SerializeObjects(writer, objects) {
44
+ const headersLenIndicator = writer.getBufferPosition();
45
+ writer.writeInt32(0);
46
+ level_class_1.Level.SerializeObjectHeaders(writer, objects);
47
+ writer.writeBinarySizeFromPosition(headersLenIndicator, headersLenIndicator + 4);
48
+ level_class_1.Level.SerializeObjectContents(writer, objects, 0);
49
+ }
50
+ }
51
+ exports.BlueprintWriter = BlueprintWriter;
52
+ class BlueprintConfigWriter extends byte_writer_class_1.ByteWriter {
53
+ constructor() {
54
+ super(alignment_enum_1.Alignment.LITTLE_ENDIAN);
55
+ }
56
+ static SerializeConfig(writer, config) {
57
+ writer.writeInt32(2);
58
+ writer.writeString(config.description);
59
+ writer.writeInt32(config.iconID);
60
+ (0, util_types_1.SerializeCol4RGBA)(writer, config.color);
61
+ }
62
+ }
63
+ exports.BlueprintConfigWriter = BlueprintConfigWriter;
@@ -0,0 +1,20 @@
1
+ import { ChunkCompressionInfo } from "../../file.types";
2
+ import { SaveComponent } from "../objects/SaveComponent";
3
+ import { SaveEntity } from "../objects/SaveEntity";
4
+ import { col4 } from "../structs/util.types";
5
+ export interface BlueprintConfig {
6
+ description: string;
7
+ color: col4;
8
+ iconID: number;
9
+ }
10
+ export type BlueprintHeader = {
11
+ itemCosts: [string, number][];
12
+ recipeReferences: string[];
13
+ };
14
+ export interface Blueprint {
15
+ name: string;
16
+ compressionInfo: ChunkCompressionInfo;
17
+ header: BlueprintHeader;
18
+ config: BlueprintConfig;
19
+ objects: (SaveEntity | SaveComponent)[];
20
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,5 +1,5 @@
1
1
  import { ByteReader } from "../../byte/byte-reader.class";
2
- import { SaveWriter } from "../../save-writer";
2
+ import { SaveWriter } from "../save/save-writer";
3
3
  import { AbstractBaseProperty } from "./Property";
4
4
  export declare class DataFields {
5
5
  properties: any[];
@@ -12,7 +12,6 @@ class DataFields {
12
12
  const start = reader.getBufferPosition();
13
13
  const fields = new DataFields();
14
14
  if (length === 0) {
15
- //WARNING
16
15
  fields.shouldBeNulled = true;
17
16
  return fields;
18
17
  }
@@ -24,7 +23,6 @@ class DataFields {
24
23
  }
25
24
  let int1 = reader.readInt32();
26
25
  if (int1 !== 0) {
27
- //WARNING
28
26
  }
29
27
  const end = reader.getBufferPosition();
30
28
  let remainingBytes = start + length - end;
@@ -36,18 +34,6 @@ class DataFields {
36
34
  if (currentProperty.name === 'None') {
37
35
  return null;
38
36
  }
39
- //TODO: What is this extra byte that is appearing sometime?
40
- // i dont think there is an extra byte.
41
- /*
42
- let extraByteTest = reader.readByte();
43
- if (extraByteTest !== 0) {
44
- reader.currentByte -= 1;
45
- }
46
- else {
47
- console.log('Property extra byte', currentProperty);
48
- }
49
- */
50
- //TODO assign type and index after parsing.
51
37
  const propertyType = reader.readString();
52
38
  const binarySize = reader.readInt32();
53
39
  const index = reader.readInt32();
@@ -83,12 +69,6 @@ class DataFields {
83
69
  currentProperty = Property_1.Int64Property.Parse(reader, propertyType, index);
84
70
  overhead = Property_1.Int64Property.CalcOverhead(currentProperty);
85
71
  break;
86
- // TODO
87
- /*
88
- case 'UInt64Property':
89
- currentProperty = Int64Property.Parse(reader, propertyType, index);
90
- break;
91
- */
92
72
  case 'SingleProperty':
93
73
  case 'FloatProperty':
94
74
  currentProperty = Property_1.FloatProperty.Parse(reader, propertyType, index);
@@ -121,7 +101,6 @@ class DataFields {
121
101
  overhead = Property_1.ArrayProperty.CalcOverhead(currentProperty);
122
102
  break;
123
103
  case 'MapProperty':
124
- //currentProperty = reader.readMapProperty(currentProperty, '');
125
104
  currentProperty = Property_1.MapProperty.Parse(reader, propertyName, buildVersion, binarySize);
126
105
  overhead = Property_1.MapProperty.CalcOverhead(currentProperty);
127
106
  break;
@@ -154,10 +133,8 @@ class DataFields {
154
133
  }
155
134
  static SerializeProperty(writer, property, propertyName, buildVersion) {
156
135
  writer.writeString(property.ueType);
157
- // binary length indicator
158
136
  const lenIndicator = writer.getBufferPosition();
159
137
  writer.writeInt32(0);
160
- // write index if it is not 0. Since it normally is.
161
138
  writer.writeInt32(property.index ?? 0);
162
139
  const start = writer.getBufferPosition();
163
140
  let overhead = 0;
@@ -191,7 +168,6 @@ class DataFields {
191
168
  overhead = Property_1.Int64Property.CalcOverhead(property);
192
169
  Property_1.Int64Property.Serialize(writer, property);
193
170
  break;
194
- // TODO: uint64Property
195
171
  case 'SingleProperty':
196
172
  case 'FloatProperty':
197
173
  overhead = Property_1.FloatProperty.CalcOverhead(property);
@@ -242,7 +218,6 @@ class DataFields {
242
218
  default:
243
219
  throw new Error(`Unimplemented type ${property.type}`);
244
220
  }
245
- // replace len indicator.
246
221
  writer.writeBinarySizeFromPosition(lenIndicator, start + overhead);
247
222
  }
248
223
  }
@@ -1,5 +1,5 @@
1
1
  import { ByteReader } from "../../byte/byte-reader.class";
2
- import { SaveWriter } from "../../save-writer";
2
+ import { SaveWriter } from "../save/save-writer";
3
3
  import { col4, vec3, vec4 } from "../structs/util.types";
4
4
  import { ObjectReference } from "./ObjectReference";
5
5
  export type Properties = {