@etothepii/satisfactory-file-parser 0.4.13 → 0.4.15

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 (55) hide show
  1. package/LICENCE.md +1 -1
  2. package/README.md +64 -28
  3. package/build/parser/byte/binary-readable.interface.d.ts +0 -3
  4. package/build/parser/byte/binary-writable.interface.d.ts +20 -0
  5. package/build/parser/byte/binary-writable.interface.js +2 -0
  6. package/build/parser/byte/byte-reader.class.d.ts +0 -3
  7. package/build/parser/byte/byte-reader.class.js +0 -8
  8. package/build/parser/byte/byte-writer.class.d.ts +6 -3
  9. package/build/parser/byte/byte-writer.class.js +3 -1
  10. package/build/parser/satisfactory/blueprint/blueprint-reader.js +8 -8
  11. package/build/parser/satisfactory/edit/edit-constants.d.ts +2 -0
  12. package/build/parser/satisfactory/edit/edit-constants.js +82 -158
  13. package/build/parser/satisfactory/objects/DataFields.js +9 -9
  14. package/build/parser/satisfactory/objects/SaveObject.d.ts +1 -1
  15. package/build/parser/satisfactory/objects/SaveObject.js +1 -1
  16. package/build/parser/satisfactory/objects/property/generic/FloatProperty.js +1 -1
  17. package/build/parser/satisfactory/objects/property/generic/StructProperty.js +11 -4
  18. package/build/parser/satisfactory/save/level.class.d.ts +1 -2
  19. package/build/parser/satisfactory/save/level.class.js +10 -15
  20. package/build/parser/satisfactory/save/save-reader.js +8 -4
  21. package/build/parser/satisfactory/save/save.types.d.ts +0 -25
  22. package/build/parser/satisfactory/structs/util.types.js +8 -8
  23. package/build/parser/stream/reworked/readable-stream-parser.d.ts +1 -0
  24. package/build/parser/stream/reworked/readable-stream-parser.js +28 -3
  25. package/package.json +1 -1
  26. package/build/parser/satisfactory/objects/ObjectReference.d.ts +0 -10
  27. package/build/parser/satisfactory/objects/ObjectReference.js +0 -17
  28. package/build/parser/satisfactory/objects/Property.d.ts +0 -272
  29. package/build/parser/satisfactory/objects/Property.js +0 -1177
  30. package/build/parser/satisfactory/objects/ue/FMD5Hash.d.ts +0 -7
  31. package/build/parser/satisfactory/objects/ue/FMD5Hash.js +0 -19
  32. package/build/parser/satisfactory/objects/ue/GUID.d.ts +0 -6
  33. package/build/parser/satisfactory/objects/ue/GUID.js +0 -21
  34. package/build/parser/satisfactory/save/asynchronous-level.class.d.ts +0 -9
  35. package/build/parser/satisfactory/save/asynchronous-level.class.js +0 -66
  36. package/build/parser/stream/byte-stream-reader.class.d.ts +0 -57
  37. package/build/parser/stream/byte-stream-reader.class.js +0 -241
  38. package/build/parser/stream/json-stream-state-writer.d.ts +0 -12
  39. package/build/parser/stream/json-stream-state-writer.js +0 -18
  40. package/build/parser/stream/json-stream-writable.d.ts +0 -20
  41. package/build/parser/stream/json-stream-writable.js +0 -83
  42. package/build/parser/stream/json-stream-writer.d.ts +0 -22
  43. package/build/parser/stream/json-stream-writer.js +0 -127
  44. package/build/parser/stream/reworked/stream-parser.d.ts +0 -6
  45. package/build/parser/stream/reworked/stream-parser.js +0 -31
  46. package/build/parser/stream/save-stream-json-stringifier.d.ts +0 -6
  47. package/build/parser/stream/save-stream-json-stringifier.js +0 -35
  48. package/build/parser/stream/save-stream-reader.class.d.ts +0 -15
  49. package/build/parser/stream/save-stream-reader.class.js +0 -121
  50. package/build/parser/stream/save-stream-writer.class.d.ts +0 -25
  51. package/build/parser/stream/save-stream-writer.class.js +0 -119
  52. package/build/parser/stream/stream-level.class.d.ts +0 -12
  53. package/build/parser/stream/stream-level.class.js +0 -103
  54. package/build/parser/stream/stream-parser.d.ts +0 -40
  55. package/build/parser/stream/stream-parser.js +0 -225
package/LICENCE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2023 etotheepii
3
+ Copyright (c) 2024 etothepii
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -8,8 +8,8 @@ This parser can read, modify and write:
8
8
  - Save Files `.sav`
9
9
  - Blueprint Files `.sbp`, `.sbpcfg`
10
10
 
11
- ## Supported Versions
12
- The version support of the packages is indicated below.
11
+ # Supported Versions
12
+ The version support of the packages is indicated below. Some bugs might still be present, see Bug Reporting further down.
13
13
 
14
14
  Game Version Files of U5 and below are NOT supported.
15
15
 
@@ -18,31 +18,39 @@ Game Version Files of U5 and below are NOT supported.
18
18
  | <= U5 | ❌ |
19
19
  | U6 + U7 | ✅ 0.0.1 - 0.0.34 |
20
20
  | U8 | ✅ 0.1.20 - 0.3.7 |
21
- | U1.0 | ✅ >= 0.4.13 |
21
+ | U1.0 | ✅ >= 0.4.14 |
22
22
 
23
-
24
- ## Installation via npm
23
+ # Installation via npm
25
24
  `npm install @etothepii/satisfactory-file-parser`
26
25
 
27
- ## Usage of Save Parsing
26
+ # Usage of Save Parsing
28
27
 
29
- I recommend parsing via stream, to save RAM. The binary data of the whole save will still be in memory, but the converted JSON won't.
30
- The returned `stream` is a readable WHATWG stream of type string.
28
+ I recommend parsing via stream, to save RAM. The binary data of the whole save will still be in memory, but the converted JSON can be streamed. (You can of course keep reading the stream in memory).
29
+ The returned `stream` is a readable WHATWG stream of type string and represents a `SatisfactorySave` object. this object can be serialized again.
31
30
  WHATWG is used by default by browsers. Node js can use them using `Writable.toWeb()` and `Writable.fromWeb()` for example.
32
31
 
33
32
  ```js
34
- const jsonFileStream = fs.createWriteStream(outJsonPath, { highWaterMark: 1024 * 1024 * 200 }); // your outgoing JSON stream. In this case directly to file.
35
- const whatwgWriteStream = Writable.toWeb(outJsonStream) as WritableStream<string>; // convert the file stream to WHATWG-compliant stream
36
-
37
- const { stream, startStreaming } = ReadableStreamParser.CreateReadableStreamFromSaveToJson(savename, file, decompressedBody => {
33
+ import * as fs from 'fs';
34
+ import * as path from 'path';
35
+ import { Writable } from 'stream';
36
+ import { WritableStream } from 'stream/web';
37
+ import { ReadableStreamParser } from '@etothepii/satisfactory-file-parser';
38
+
39
+ const filepath = path.join(__dirname, 'MySave.sav');
40
+ const file = fs.readFileSync(filepath);
41
+ const outJsonPath = path.join(__dirname, 'MySave.json');
42
+ const jsonFileStream = fs.createWriteStream(outJsonPath, { highWaterMark: 1024 * 1024 * 200 }); // your outgoing JSON stream. In this case directly to file.
43
+ const whatwgWriteStream = Writable.toWeb(jsonFileStream) as WritableStream<string>; // convert the file stream to WHATWG-compliant stream
44
+
45
+ const { stream, startStreaming } = ReadableStreamParser.CreateReadableStreamFromSaveToJson('MySave', file, decompressedBody => {
38
46
  console.log('on binary body data.');
39
47
  }, (progress: number, msg: string | undefined) => {
40
48
  // a callback for reporting progress as number [0,1]. Sometimes has a message.
41
- console.log(`${new Date().toString()}: progress`, progress, msg);
49
+ console.log(`progress`, progress, msg);
42
50
  });
43
51
 
44
52
  stream.pipeTo(whatwgWriteStream);
45
- whatwgWriteStream.on('close', () => {
53
+ jsonFileStream.on('close', () => {
46
54
  // write stream finished
47
55
  });
48
56
 
@@ -55,44 +63,49 @@ For example, when writing the header or when writing a chunk of the save body.
55
63
  The splitting in individual chunks enables you to more easily stream the binary data to somewhere else.
56
64
  ```js
57
65
  import * as fs from 'fs';
66
+ import * as path from 'path';
58
67
  import { Parser } from "@etothepii/satisfactory-file-parser";
59
68
 
60
- let header: Uint8Array, bodyChunks: Uint8Array[] = [];
61
- Parser.WriteSave(save, binaryBeforeCompressed => {
69
+ // save is your SatisfactorySave object to serialize. In this example i read it back in from a json file.
70
+ const save = JSON.parse(fs.readFileSync(path.join(__dirname, 'MySave.json'), {encoding: 'utf-8'}));
71
+
72
+ let fileHeader: Uint8Array;
73
+ const bodyChunks: Uint8Array[] = [];
74
+ Parser.WriteSave(save, binaryBeforeCompressed => {
62
75
  console.log('on binary data before being compressed.');
63
76
  }, header => {
64
77
  console.log('on save header.');
65
- header = header;
78
+ fileHeader = header;
66
79
  }, chunk => {
67
80
  console.log('on save body chunk.');
68
81
  bodyChunks.push(chunk);
69
82
  });
70
83
 
71
84
  // write complete sav file back to disk
72
- fs.writeFileSync('./MyModifiedSave.sav', Buffer.concat([header!, ...bodyChunks]));
85
+ fs.writeFileSync('./MyModifiedSave.sav', Buffer.concat([fileHeader!, ...bodyChunks]));
73
86
  ```
74
87
 
75
88
 
76
- ### Old Usage of Save Parsing. Deprecated.
89
+ ## Old Save Parsing. Deprecated.
77
90
  For reading a save file (`.sav`) and parse In-Memory, just pass a Buffer to the parser with the file content.
78
91
  ```js
79
92
  import * as fs from 'fs';
80
93
  import { Parser } from "@etothepii/satisfactory-file-parser";
81
94
 
82
95
  const file = fs.readFileSync('./MySave.sav') as Buffer;
83
- const parsedSave = Parser.ParseSaveFile(file);
96
+ const parsedSave = Parser.ParseSaveFile('MySave', file);
84
97
  ```
85
98
 
86
99
 
87
- ## Usage of Blueprint Parsing
88
- Blueprint parsing works very similiar. Note, that blueprints consist of 2 files. The `.sbp` main file and the config file `.sbpcfg`.
100
+ # Usage of Blueprint Parsing
101
+ Note, that blueprints consist of 2 files. The `.sbp` main file and the config file `.sbpcfg`.
89
102
 
90
103
  ```js
91
104
  import * as fs from 'fs';
92
105
  import { Parser } from "@etothepii/satisfactory-file-parser";
93
106
 
94
- const mainFile = fs.readFileSync('./MyBlueprint.sbp') as Buffer;
95
- const configFile = fs.readFileSync('./MyBlueprint.sbpcfg') as Buffer;
107
+ const mainFile = fs.readFileSync('./MyBlueprint.sbp');
108
+ const configFile = fs.readFileSync('./MyBlueprint.sbpcfg');
96
109
  const parsedBlueprint = Parser.ParseBlueprintFiles('MyBlueprint', mainFile, configFile);
97
110
  ```
98
111
 
@@ -101,7 +114,8 @@ Consequently, writing a blueprint into binary data works the same way with getti
101
114
  import * as fs from 'fs';
102
115
  import { Parser } from "@etothepii/satisfactory-file-parser";
103
116
 
104
- let mainFileHeader: Uint8Array, mainFileBodyChunks: Uint8Array[] = [];
117
+ let mainFileHeader: Uint8Array;
118
+ const mainFileBodyChunks: Uint8Array[] = [];
105
119
  const summary = Parser.WriteBlueprintFiles(blueprint, mainFileBinaryBeforeCompressed => {
106
120
  console.log('on main file binary data before being compressed.');
107
121
  }, header => {
@@ -116,13 +130,35 @@ const summary = Parser.WriteBlueprintFiles(blueprint, mainFileBinaryBeforeCompre
116
130
  fs.writeFileSync('./MyModifiedBlueprint.sbp', Buffer.concat([mainFileHeader!, ...mainFileBodyChunks]));
117
131
 
118
132
  // write .sbpcfg file back to disk, we get that data from the result of WriteBlueprintFiles
119
- fs.writeFileSync('./MyModifiedSave.sbpcfg', Buffer.from(summary.configFileBinary));
133
+ fs.writeFileSync('./MyModifiedBlueprint.sbpcfg', Buffer.from(summary.configFileBinary));
120
134
  ```
121
135
 
122
- ## License
136
+ # Bug Reports or Feedback
137
+ So far this was just a private hobby project. But i figure some people actually use it.
138
+ If you find a bug or have feedback about the parser, you can just hit me up on the satisfactory discord `etothepii`.
139
+
140
+ # Changelog
141
+
142
+ ### [0.4.15] (2024-10-02)
143
+ #### updated README
144
+ * changelog document doesn't seem linkable, so it is in the readme for now.
145
+
146
+ ### [0.4.14] (2024-10-02)
147
+ #### updated README
148
+ * updated the code examples with more context
149
+
150
+ ### Internal renamings (won't affect you if you stick to the code examples)
151
+ * improved the interface for abstract parser classes
152
+ * extended some error log messages
153
+ * added an additional check when parsing struct property InventoryItem, since ported saves often have a few more bytes.
154
+ * changed function name `writeFloat()` to `writeFloat32()` of the save writer.
155
+ * changed variable name `saveOrBlueprintIndicator` to `objectVersion` for objects, since the meaning of that number became now more clear.
156
+
157
+
158
+ # License
123
159
  MIT License
124
160
 
125
- Copyright (c) 2023 etothepii
161
+ Copyright (c) 2024 etothepii
126
162
 
127
163
  Permission is hereby granted, free of charge, to any person obtaining a copy
128
164
  of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,5 @@
1
1
  import { BinaryOperable } from "./binary-operable.interface";
2
2
  export interface BinaryReadable extends BinaryOperable {
3
- debug: boolean;
4
3
  skipBytes: (count?: number) => void;
5
4
  readBytes: (count: number) => Uint8Array;
6
5
  readByte: () => number;
@@ -17,6 +16,4 @@ export interface BinaryReadable extends BinaryOperable {
17
16
  readDouble: () => number;
18
17
  readString: () => string;
19
18
  getBufferProgress: () => number;
20
- allocate: (count: number) => PromiseLike<void>;
21
- getAmountAllocatedLeft: () => number;
22
19
  }
@@ -0,0 +1,20 @@
1
+ import { BinaryOperable } from "./binary-operable.interface";
2
+ export interface BinaryWritable extends BinaryOperable {
3
+ skipBytes: (count?: number) => void;
4
+ jumpTo(position: number): void;
5
+ writeByte: (value: number) => void;
6
+ writeBytes: (bytes: Uint8Array) => void;
7
+ writeBytesArray: (bytes: number[]) => void;
8
+ writeInt8: (value: number) => void;
9
+ writeUint8: (value: number) => void;
10
+ writeInt16: (value: number) => void;
11
+ writeUint16: (value: number) => void;
12
+ writeInt32: (value: number) => void;
13
+ writeUint32: (value: number) => void;
14
+ writeInt64: (value: bigint) => void;
15
+ writeUint64: (value: bigint) => void;
16
+ writeFloat32: (value: number) => void;
17
+ writeDouble: (value: number) => void;
18
+ writeString: (value: string) => void;
19
+ getBufferProgress: () => number;
20
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -4,7 +4,6 @@ export declare abstract class ByteReader implements BinaryReadable {
4
4
  protected bufferView: DataView;
5
5
  protected fileBuffer: ArrayBuffer;
6
6
  alignment: Alignment;
7
- debug: boolean;
8
7
  protected currentByte: number;
9
8
  protected handledByte: number;
10
9
  protected maxByte: number;
@@ -27,8 +26,6 @@ export declare abstract class ByteReader implements BinaryReadable {
27
26
  readFloat32(): number;
28
27
  readDouble(): number;
29
28
  readString(): string;
30
- allocate(count: number): Promise<void>;
31
- getAmountAllocatedLeft: () => number;
32
29
  getBufferPosition: () => number;
33
30
  getBufferSlice: (begin: number, end: number | undefined) => ArrayBuffer;
34
31
  getBufferProgress: () => number;
@@ -4,11 +4,9 @@ exports.ByteReader = void 0;
4
4
  const alignment_enum_1 = require("./alignment.enum");
5
5
  class ByteReader {
6
6
  constructor(fileBuffer, alignment) {
7
- this.debug = false;
8
7
  this.currentByte = 0;
9
8
  this.handledByte = 0;
10
9
  this.maxByte = 0;
11
- this.getAmountAllocatedLeft = () => this.bufferView.byteLength - this.currentByte;
12
10
  this.getBufferPosition = () => this.currentByte;
13
11
  this.getBufferSlice = (begin, end) => this.bufferView.buffer.slice(begin, end);
14
12
  this.getBufferProgress = () => this.currentByte / this.bufferView.buffer.byteLength;
@@ -117,11 +115,5 @@ class ByteReader {
117
115
  throw error;
118
116
  }
119
117
  }
120
- allocate(count) {
121
- if (this.currentByte + count < this.bufferView.byteLength) {
122
- console.warn('tried to allocate but there is not enough data left.');
123
- }
124
- return Promise.resolve();
125
- }
126
118
  }
127
119
  exports.ByteReader = ByteReader;
@@ -1,6 +1,7 @@
1
1
  import { Alignment } from "./alignment.enum";
2
- export declare abstract class ByteWriter {
3
- protected alignment: Alignment;
2
+ import { BinaryWritable } from './binary-writable.interface';
3
+ export declare abstract class ByteWriter implements BinaryWritable {
4
+ alignment: Alignment;
4
5
  protected bufferArray: ArrayBuffer;
5
6
  protected bufferView: DataView;
6
7
  protected currentByte: number;
@@ -18,12 +19,14 @@ export declare abstract class ByteWriter {
18
19
  writeUint32(value: number): void;
19
20
  writeInt64(value: bigint): void;
20
21
  writeUint64(value: bigint): void;
21
- writeFloat(value: number): void;
22
+ writeFloat32(value: number): void;
22
23
  writeDouble(value: number): void;
23
24
  writeString(value: string): void;
24
25
  static IsASCIICompatible: (value: string) => boolean;
25
26
  getBufferPosition: () => number;
26
27
  getBufferSlice: (start: number, end?: number) => ArrayBuffer;
28
+ getBufferLength: () => number;
29
+ getBufferProgress: () => number;
27
30
  writeBinarySizeFromPosition(lenIndicatorPos: number, start: number): void;
28
31
  protected extendBufferIfNeeded(countNeededBytes: number, factor?: number): void;
29
32
  protected truncateBuffer(): void;
@@ -6,6 +6,8 @@ class ByteWriter {
6
6
  constructor(alignment, bufferSize = 500) {
7
7
  this.getBufferPosition = () => this.currentByte;
8
8
  this.getBufferSlice = (start, end) => this.bufferArray.slice(start, end);
9
+ this.getBufferLength = () => this.bufferArray.byteLength;
10
+ this.getBufferProgress = () => this.currentByte / this.bufferArray.byteLength;
9
11
  this.alignment = alignment;
10
12
  this.bufferArray = new ArrayBuffer(bufferSize);
11
13
  this.bufferView = new DataView(this.bufferArray);
@@ -69,7 +71,7 @@ class ByteWriter {
69
71
  this.bufferView.setBigUint64(this.currentByte, value, this.alignment === alignment_enum_1.Alignment.LITTLE_ENDIAN);
70
72
  this.currentByte += 8;
71
73
  }
72
- writeFloat(value) {
74
+ writeFloat32(value) {
73
75
  this.extendBufferIfNeeded(4);
74
76
  this.bufferView.setFloat32(this.currentByte, value, this.alignment === alignment_enum_1.Alignment.LITTLE_ENDIAN);
75
77
  this.currentByte += 4;
@@ -29,7 +29,7 @@ class BlueprintReader extends byte_reader_class_1.ByteReader {
29
29
  let itemTypeCount = reader.readInt32();
30
30
  const itemCosts = new Array(itemTypeCount).fill(['', 0]);
31
31
  for (let i = 0; i < itemTypeCount; i++) {
32
- let indexOrWhat = reader.readInt32();
32
+ reader.readInt32();
33
33
  let itemPathName = reader.readString();
34
34
  let itemCount = reader.readInt32();
35
35
  itemCosts[i] = [itemPathName, itemCount];
@@ -37,7 +37,7 @@ class BlueprintReader extends byte_reader_class_1.ByteReader {
37
37
  let recipeCount = reader.readInt32();
38
38
  const recipeRefs = new Array(recipeCount).fill('');
39
39
  for (let i = 0; i < recipeCount; i++) {
40
- let indexOrWhat = reader.readInt32();
40
+ reader.readInt32();
41
41
  const recipeName = reader.readString();
42
42
  recipeRefs[i] = recipeName;
43
43
  }
@@ -105,7 +105,7 @@ class BlueprintReader extends byte_reader_class_1.ByteReader {
105
105
  level_class_1.Level.ReadObjectHeaders(reader, objects, () => { });
106
106
  const someChecksumThing = reader.readInt32();
107
107
  BlueprintReader.ReadBlueprintObjectContents(reader, objects, 0);
108
- const pos = reader.getBufferPosition();
108
+ reader.getBufferPosition();
109
109
  return objects;
110
110
  }
111
111
  static ReadBlueprintObjectContents(reader, objectsList, buildVersion) {
@@ -133,14 +133,14 @@ class BlueprintConfigReader extends byte_reader_class_1.ByteReader {
133
133
  this.parse = () => BlueprintConfigReader.ParseConfig(this);
134
134
  }
135
135
  static ParseConfig(reader) {
136
- const unk = reader.readInt32();
136
+ const alwaysTwo = reader.readInt32();
137
137
  const description = reader.readString();
138
- const unk3 = reader.readInt32();
139
- const colorMaybe = util_types_1.col4.ParseRGBA(reader);
138
+ const iconID = reader.readInt32();
139
+ const color = util_types_1.col4.ParseRGBA(reader);
140
140
  return {
141
141
  description,
142
- color: colorMaybe,
143
- iconID: unk3
142
+ color,
143
+ iconID,
144
144
  };
145
145
  }
146
146
  }
@@ -1630,9 +1630,11 @@ export declare const EDIT: {
1630
1630
  };
1631
1631
  readonly POWER_POLE_WALL_MK1: {
1632
1632
  readonly TYPE_PATH: "/Game/FactoryGame/Buildable/Factory/PowerPoleWall/Build_PowerPoleWall.Build_PowerPoleWall_C";
1633
+ readonly CLASS_NAME: "Build_PowerPoleWall_C";
1633
1634
  };
1634
1635
  readonly POWER_POLE_WALL_MK2: {
1635
1636
  readonly TYPE_PATH: "/Game/FactoryGame/Buildable/Factory/PowerPoleWall/Build_PowerPoleWall_Mk2.Build_PowerPoleWall_Mk2_C";
1637
+ readonly CLASS_NAME: "Build_PowerPoleWall_Mk2_C";
1636
1638
  };
1637
1639
  };
1638
1640
  readonly POWER_LINE: {