@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.
- package/README.md +49 -11
- package/build/index.d.ts +10 -8
- package/build/index.js +10 -12
- package/build/parser/byte/byte-reader.class.d.ts +1 -38
- package/build/parser/byte/byte-reader.class.js +0 -11
- package/build/parser/byte/byte-writer.class.d.ts +1 -38
- package/build/parser/byte/byte-writer.class.js +0 -10
- package/build/parser/file.types.d.ts +9 -0
- package/build/parser/file.types.js +2 -0
- package/build/parser/parser.d.ts +12 -40
- package/build/parser/parser.js +51 -47
- package/build/parser/satisfactory/blueprint/blueprint-reader.d.ts +18 -0
- package/build/parser/satisfactory/blueprint/blueprint-reader.js +124 -0
- package/build/parser/satisfactory/blueprint/blueprint-writer.d.ts +15 -0
- package/build/parser/satisfactory/blueprint/blueprint-writer.js +63 -0
- package/build/parser/satisfactory/blueprint/blueprint.types.d.ts +20 -0
- package/build/parser/satisfactory/blueprint/blueprint.types.js +2 -0
- package/build/parser/satisfactory/objects/DataFields.d.ts +1 -1
- package/build/parser/satisfactory/objects/DataFields.js +0 -25
- package/build/parser/satisfactory/objects/Property.d.ts +1 -1
- package/build/parser/satisfactory/objects/Property.js +10 -159
- package/build/parser/satisfactory/save/level.class.d.ts +21 -0
- package/build/parser/satisfactory/save/level.class.js +138 -0
- package/build/parser/satisfactory/save/satisfactory-save.d.ts +11 -0
- package/build/parser/satisfactory/save/satisfactory-save.js +11 -0
- package/build/parser/satisfactory/save/save-reader.d.ts +44 -0
- package/build/parser/satisfactory/save/save-reader.js +233 -0
- package/build/parser/satisfactory/save/save-writer.d.ts +12 -0
- package/build/parser/satisfactory/save/save-writer.js +112 -0
- package/build/parser/satisfactory/save/save.types.d.ts +49 -0
- package/build/parser/satisfactory/save/save.types.js +2 -0
- 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
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ByteReader } from "../../byte/byte-reader.class";
|
|
2
|
-
import { SaveWriter } from "
|
|
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 "
|
|
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 = {
|