@etothepii/satisfactory-file-parser 0.0.31 → 0.0.33
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/LICENCE.md +20 -20
- package/README.md +112 -112
- package/build/index.d.ts +5 -1
- package/build/index.js +7 -7
- package/build/parser/byte/binary-operable.interface.d.ts +6 -0
- package/build/parser/byte/binary-operable.interface.js +12 -0
- package/build/parser/byte/binary-readable.interface.d.ts +22 -0
- package/build/parser/byte/binary-readable.interface.js +12 -0
- package/build/parser/byte/byte-reader.class.d.ts +11 -9
- package/build/parser/byte/byte-reader.class.js +23 -15
- package/build/parser/error/parser.error.d.ts +6 -0
- package/build/parser/error/parser.error.js +13 -1
- package/build/parser/satisfactory/blueprint/blueprint-reader.d.ts +3 -2
- package/build/parser/satisfactory/blueprint/blueprint-writer.js +1 -1
- package/build/parser/satisfactory/objects/DataFields.d.ts +34 -6
- package/build/parser/satisfactory/objects/DataFields.js +86 -3
- package/build/parser/satisfactory/objects/ObjectReference.d.ts +2 -2
- package/build/parser/satisfactory/objects/Property.d.ts +72 -72
- package/build/parser/satisfactory/objects/Property.js +24 -23
- package/build/parser/satisfactory/objects/SaveComponent.d.ts +8 -5
- package/build/parser/satisfactory/objects/SaveComponent.js +2 -2
- package/build/parser/satisfactory/objects/SaveEntity.d.ts +9 -4
- package/build/parser/satisfactory/objects/SaveEntity.js +2 -2
- package/build/parser/satisfactory/objects/SaveObject.d.ts +9 -4
- package/build/parser/satisfactory/objects/SaveObject.js +3 -3
- package/build/parser/satisfactory/save/asynchronous-level.class.d.ts +9 -0
- package/build/parser/satisfactory/save/asynchronous-level.class.js +76 -0
- package/build/parser/satisfactory/save/level.class.d.ts +5 -5
- package/build/parser/satisfactory/save/level.class.js +6 -6
- package/build/parser/satisfactory/save/save-reader.d.ts +4 -13
- package/build/parser/satisfactory/save/save-reader.js +17 -72
- package/build/parser/satisfactory/structs/util.types.d.ts +7 -7
- package/build/parser/satisfactory/structs/util.types.js +10 -10
- package/build/parser/stream/byte-stream-reader.class.d.ts +57 -0
- package/build/parser/stream/byte-stream-reader.class.js +251 -0
- package/build/parser/stream/json-stream-state-writer.d.ts +12 -0
- package/build/parser/stream/json-stream-state-writer.js +28 -0
- package/build/parser/stream/json-stream-writable.d.ts +20 -0
- package/build/parser/stream/json-stream-writable.js +93 -0
- package/build/parser/stream/json-stream-writer.d.ts +22 -0
- package/build/parser/stream/json-stream-writer.js +137 -0
- package/build/parser/stream/save-stream-json-stringifier.d.ts +6 -0
- package/build/parser/stream/save-stream-json-stringifier.js +43 -0
- package/build/parser/stream/save-stream-reader.class.d.ts +15 -0
- package/build/parser/stream/save-stream-reader.class.js +131 -0
- package/build/parser/stream/save-stream-writer.class.d.ts +22 -0
- package/build/parser/stream/save-stream-writer.class.js +115 -0
- package/build/parser/stream/stream-level.class.d.ts +12 -0
- package/build/parser/stream/stream-level.class.js +113 -0
- package/package.json +3 -1
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
(function (factory) {
|
|
2
|
+
if (typeof module === "object" && typeof module.exports === "object") {
|
|
3
|
+
var v = factory(require, exports);
|
|
4
|
+
if (v !== undefined) module.exports = v;
|
|
5
|
+
}
|
|
6
|
+
else if (typeof define === "function" && define.amd) {
|
|
7
|
+
define(["require", "exports", "../byte/alignment.enum", "../byte/byte-writer.class", "../error/parser.error"], factory);
|
|
8
|
+
}
|
|
9
|
+
})(function (require, exports) {
|
|
10
|
+
"use strict";
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.ByteStreamReader = void 0;
|
|
13
|
+
const alignment_enum_1 = require("../byte/alignment.enum");
|
|
14
|
+
const byte_writer_class_1 = require("../byte/byte-writer.class");
|
|
15
|
+
const parser_error_1 = require("../error/parser.error");
|
|
16
|
+
class ByteStreamReader {
|
|
17
|
+
constructor(reader, onCloseCallback, timeout = 30000, maxBufferThreshold = 100 * 1000 * 1000, alignment = alignment_enum_1.Alignment.LITTLE_ENDIAN) {
|
|
18
|
+
this.reader = reader;
|
|
19
|
+
this.onCloseCallback = onCloseCallback;
|
|
20
|
+
this.timeout = timeout;
|
|
21
|
+
this.maxBufferThreshold = maxBufferThreshold;
|
|
22
|
+
this.alignment = alignment;
|
|
23
|
+
this.debug = false;
|
|
24
|
+
this.closedAlready = false;
|
|
25
|
+
this.totalNumberOfBytesRead = 0;
|
|
26
|
+
this.trailingBufferSize = 0;
|
|
27
|
+
this.continuousRead = async () => {
|
|
28
|
+
while (!this.inputStreamIsDone && !this.paused) {
|
|
29
|
+
const { done, value } = await this.reader.read();
|
|
30
|
+
if (!this.inputStreamIsDone) {
|
|
31
|
+
if (value) {
|
|
32
|
+
const trailingPos = Math.max(0, this.currentByte - this.trailingBufferSize);
|
|
33
|
+
this.operatingStreamBuffer = new Uint8Array(byte_writer_class_1.ByteWriter.AppendBuffer(this.operatingStreamBuffer.slice(trailingPos), value));
|
|
34
|
+
this.operatingDataView = new DataView(this.operatingStreamBuffer.buffer);
|
|
35
|
+
this.currentByte = Math.min(this.currentByte, this.trailingBufferSize);
|
|
36
|
+
if (this.operatingStreamBuffer.byteLength > this.maxBufferThreshold) {
|
|
37
|
+
console.warn('pausing due to size.');
|
|
38
|
+
this.pause();
|
|
39
|
+
}
|
|
40
|
+
if (this.callbackAfterRead) {
|
|
41
|
+
this.callbackAfterRead();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
this.close();
|
|
47
|
+
}
|
|
48
|
+
this.inputStreamIsDone = done;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
this.operatingStreamBuffer = new Uint8Array();
|
|
52
|
+
this.operatingDataView = new DataView(this.operatingStreamBuffer.buffer);
|
|
53
|
+
this.inputStreamIsDone = false;
|
|
54
|
+
this.currentByte = 0;
|
|
55
|
+
this.neededNextAmountOfBytes = 0;
|
|
56
|
+
this.paused = false;
|
|
57
|
+
this.trailingBufferSize = 2000;
|
|
58
|
+
this.readLoopHandle = setTimeout(this.continuousRead);
|
|
59
|
+
this.waitingTimeoutHandle = undefined;
|
|
60
|
+
}
|
|
61
|
+
pause() {
|
|
62
|
+
this.paused = true;
|
|
63
|
+
clearTimeout(this.readLoopHandle);
|
|
64
|
+
this.readLoopHandle = undefined;
|
|
65
|
+
if (this.waitingTimeoutHandle) {
|
|
66
|
+
clearTimeout(this.waitingTimeoutHandle);
|
|
67
|
+
this.waitingTimeoutHandle = undefined;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
resume() {
|
|
71
|
+
if (this.paused) {
|
|
72
|
+
this.paused = false;
|
|
73
|
+
this.readLoopHandle = setTimeout(this.continuousRead);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
hasInput() {
|
|
77
|
+
return !this.inputStreamIsDone;
|
|
78
|
+
}
|
|
79
|
+
async close() {
|
|
80
|
+
this.inputStreamIsDone = true;
|
|
81
|
+
this.pause();
|
|
82
|
+
await this.onCloseCallback();
|
|
83
|
+
this.closedAlready = true;
|
|
84
|
+
}
|
|
85
|
+
async allocate(count) {
|
|
86
|
+
if (count > this.maxBufferThreshold * 0.5) {
|
|
87
|
+
console.warn(`you are waiting for a very big chunk here mate. ${count} bytes. U sure you have your numbers right?`);
|
|
88
|
+
}
|
|
89
|
+
if (this.getAmountAllocatedLeft() < count) {
|
|
90
|
+
if (this.inputStreamIsDone) {
|
|
91
|
+
throw new parser_error_1.CorruptSaveError('Input Stream has finished before needed data was received.');
|
|
92
|
+
}
|
|
93
|
+
if (this.paused) {
|
|
94
|
+
this.resume();
|
|
95
|
+
}
|
|
96
|
+
await this.waitUntilNumBytesAvailable(count);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
waitUntilNumBytesAvailable(count) {
|
|
100
|
+
this.neededNextAmountOfBytes = count;
|
|
101
|
+
return new Promise((resolve, reject) => {
|
|
102
|
+
if (this.getAmountAllocatedLeft() >= this.neededNextAmountOfBytes) {
|
|
103
|
+
this.neededNextAmountOfBytes = 0;
|
|
104
|
+
return resolve();
|
|
105
|
+
}
|
|
106
|
+
this.callbackAfterRead = () => {
|
|
107
|
+
if (this.getAmountAllocatedLeft() >= this.neededNextAmountOfBytes) {
|
|
108
|
+
if (this.waitingTimeoutHandle) {
|
|
109
|
+
clearTimeout(this.waitingTimeoutHandle);
|
|
110
|
+
}
|
|
111
|
+
this.neededNextAmountOfBytes = 0;
|
|
112
|
+
this.callbackAfterRead = undefined;
|
|
113
|
+
return resolve();
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
if (this.waitingTimeoutHandle) {
|
|
117
|
+
clearTimeout(this.waitingTimeoutHandle);
|
|
118
|
+
}
|
|
119
|
+
this.waitingTimeoutHandle = setTimeout(() => {
|
|
120
|
+
if (!this.inputStreamIsDone) {
|
|
121
|
+
reject(new parser_error_1.TimeoutError(`Timed out before ${this.neededNextAmountOfBytes} bytes were available to read next.`));
|
|
122
|
+
}
|
|
123
|
+
return resolve();
|
|
124
|
+
}, this.timeout);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
skipBytes(byteLength = 1) {
|
|
128
|
+
this.currentByte += byteLength;
|
|
129
|
+
this.totalNumberOfBytesRead += byteLength;
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
readByte() {
|
|
133
|
+
this.totalNumberOfBytesRead += 1;
|
|
134
|
+
return this.operatingDataView.getUint8(this.currentByte++);
|
|
135
|
+
}
|
|
136
|
+
readBytes(count) {
|
|
137
|
+
this.totalNumberOfBytesRead += count;
|
|
138
|
+
return new Uint8Array(new Array(count).fill(0).map(pl => this.operatingDataView.getUint8(this.currentByte++)));
|
|
139
|
+
}
|
|
140
|
+
readHex(hexLength) {
|
|
141
|
+
let hexPart = [];
|
|
142
|
+
for (let i = 0; i < hexLength; i++) {
|
|
143
|
+
let currentHex = String.fromCharCode(this.operatingDataView.getUint8(this.currentByte++));
|
|
144
|
+
hexPart.push(currentHex);
|
|
145
|
+
}
|
|
146
|
+
this.totalNumberOfBytesRead += hexLength;
|
|
147
|
+
return hexPart.join('');
|
|
148
|
+
}
|
|
149
|
+
readInt8() {
|
|
150
|
+
this.totalNumberOfBytesRead += 1;
|
|
151
|
+
let data = this.operatingDataView.getInt8(this.currentByte++);
|
|
152
|
+
return data;
|
|
153
|
+
}
|
|
154
|
+
readUint8() {
|
|
155
|
+
this.totalNumberOfBytesRead += 1;
|
|
156
|
+
let data = this.operatingDataView.getUint8(this.currentByte++);
|
|
157
|
+
return data;
|
|
158
|
+
}
|
|
159
|
+
readInt16() {
|
|
160
|
+
this.totalNumberOfBytesRead += 2;
|
|
161
|
+
let data = this.operatingDataView.getInt16(this.currentByte, this.alignment === alignment_enum_1.Alignment.LITTLE_ENDIAN);
|
|
162
|
+
this.currentByte += 2;
|
|
163
|
+
return data;
|
|
164
|
+
}
|
|
165
|
+
readUint16() {
|
|
166
|
+
this.totalNumberOfBytesRead += 2;
|
|
167
|
+
let data = this.operatingDataView.getUint16(this.currentByte, this.alignment === alignment_enum_1.Alignment.LITTLE_ENDIAN);
|
|
168
|
+
this.currentByte += 2;
|
|
169
|
+
return data;
|
|
170
|
+
}
|
|
171
|
+
readInt32() {
|
|
172
|
+
this.totalNumberOfBytesRead += 4;
|
|
173
|
+
let data = this.operatingDataView.getInt32(this.currentByte, this.alignment === alignment_enum_1.Alignment.LITTLE_ENDIAN);
|
|
174
|
+
this.currentByte += 4;
|
|
175
|
+
return data;
|
|
176
|
+
}
|
|
177
|
+
readUint32() {
|
|
178
|
+
this.totalNumberOfBytesRead += 4;
|
|
179
|
+
let data = this.operatingDataView.getUint32(this.currentByte, this.alignment === alignment_enum_1.Alignment.LITTLE_ENDIAN);
|
|
180
|
+
this.currentByte += 4;
|
|
181
|
+
return data;
|
|
182
|
+
}
|
|
183
|
+
readLong() {
|
|
184
|
+
this.totalNumberOfBytesRead += 8;
|
|
185
|
+
let data = this.operatingDataView.getBigInt64(this.currentByte, this.alignment === alignment_enum_1.Alignment.LITTLE_ENDIAN);
|
|
186
|
+
this.currentByte += 8;
|
|
187
|
+
return data;
|
|
188
|
+
}
|
|
189
|
+
readInt64() {
|
|
190
|
+
return this.readLong();
|
|
191
|
+
}
|
|
192
|
+
readUint64() {
|
|
193
|
+
this.totalNumberOfBytesRead += 8;
|
|
194
|
+
let data = this.operatingDataView.getBigUint64(this.currentByte, this.alignment === alignment_enum_1.Alignment.LITTLE_ENDIAN);
|
|
195
|
+
this.currentByte += 8;
|
|
196
|
+
return data;
|
|
197
|
+
}
|
|
198
|
+
readFloat32() {
|
|
199
|
+
this.totalNumberOfBytesRead += 4;
|
|
200
|
+
let data = this.operatingDataView.getFloat32(this.currentByte, this.alignment === alignment_enum_1.Alignment.LITTLE_ENDIAN);
|
|
201
|
+
this.currentByte += 4;
|
|
202
|
+
return data;
|
|
203
|
+
}
|
|
204
|
+
readDouble() {
|
|
205
|
+
this.totalNumberOfBytesRead += 8;
|
|
206
|
+
let data = this.operatingDataView.getFloat64(this.currentByte, this.alignment === alignment_enum_1.Alignment.LITTLE_ENDIAN);
|
|
207
|
+
this.currentByte += 8;
|
|
208
|
+
return data;
|
|
209
|
+
}
|
|
210
|
+
readString() {
|
|
211
|
+
let strLength = this.readInt32();
|
|
212
|
+
if (strLength === 0) {
|
|
213
|
+
return '';
|
|
214
|
+
}
|
|
215
|
+
if (strLength > (this.operatingDataView.buffer.byteLength - this.currentByte)) {
|
|
216
|
+
let errorMessage = `Cannot read string of length ${strLength} at position ${this.currentByte} as it exceeds the end at ${this.operatingDataView.buffer.byteLength}`;
|
|
217
|
+
throw new Error(errorMessage);
|
|
218
|
+
}
|
|
219
|
+
if (strLength < 0) {
|
|
220
|
+
const string = new Array(-strLength - 1).fill('').map(c => String.fromCharCode(this.readUint16()));
|
|
221
|
+
this.currentByte += 2;
|
|
222
|
+
this.totalNumberOfBytesRead += 2;
|
|
223
|
+
return string.join('');
|
|
224
|
+
}
|
|
225
|
+
try {
|
|
226
|
+
const string = new Array(strLength - 1).fill('').map(c => String.fromCharCode(this.readUint8()));
|
|
227
|
+
this.currentByte += 1;
|
|
228
|
+
this.totalNumberOfBytesRead += 1;
|
|
229
|
+
return string.join('');
|
|
230
|
+
}
|
|
231
|
+
catch (error) {
|
|
232
|
+
let errorMessage = `Cannot read UTF8 string of length ${strLength} at position ${this.currentByte}.`;
|
|
233
|
+
console.log(errorMessage, error);
|
|
234
|
+
throw error;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
getBufferPosition() {
|
|
238
|
+
return this.totalNumberOfBytesRead;
|
|
239
|
+
}
|
|
240
|
+
getBufferProgress() {
|
|
241
|
+
throw new parser_error_1.UnimplementedError();
|
|
242
|
+
}
|
|
243
|
+
getBufferLength() {
|
|
244
|
+
return this.operatingStreamBuffer.byteLength;
|
|
245
|
+
}
|
|
246
|
+
getAmountAllocatedLeft() {
|
|
247
|
+
return this.operatingStreamBuffer.byteLength - this.currentByte;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
exports.ByteStreamReader = ByteStreamReader;
|
|
251
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { JsonStreamWritable } from "./json-stream-writable";
|
|
2
|
+
export type Transition<S extends string> = {
|
|
3
|
+
name: string;
|
|
4
|
+
requiresOneOfThemToBeBefore: S[];
|
|
5
|
+
do: (...params: any[]) => Promise<void>;
|
|
6
|
+
assignOnFinish: S;
|
|
7
|
+
};
|
|
8
|
+
export declare abstract class JsonStreamStateWriter<S extends string> extends JsonStreamWritable {
|
|
9
|
+
private currentState;
|
|
10
|
+
constructor(pushWritable: (value: string) => Promise<void>, startState: S);
|
|
11
|
+
protected useTransition(transition: Transition<S>, ...params: any[]): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
(function (factory) {
|
|
2
|
+
if (typeof module === "object" && typeof module.exports === "object") {
|
|
3
|
+
var v = factory(require, exports);
|
|
4
|
+
if (v !== undefined) module.exports = v;
|
|
5
|
+
}
|
|
6
|
+
else if (typeof define === "function" && define.amd) {
|
|
7
|
+
define(["require", "exports", "./json-stream-writable"], factory);
|
|
8
|
+
}
|
|
9
|
+
})(function (require, exports) {
|
|
10
|
+
"use strict";
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.JsonStreamStateWriter = void 0;
|
|
13
|
+
const json_stream_writable_1 = require("./json-stream-writable");
|
|
14
|
+
class JsonStreamStateWriter extends json_stream_writable_1.JsonStreamWritable {
|
|
15
|
+
constructor(pushWritable, startState) {
|
|
16
|
+
super(pushWritable);
|
|
17
|
+
this.currentState = startState;
|
|
18
|
+
}
|
|
19
|
+
async useTransition(transition, ...params) {
|
|
20
|
+
if (!transition.requiresOneOfThemToBeBefore.includes(this.currentState)) {
|
|
21
|
+
throw new Error(`Invalid command. Method ${transition.name} is not allowed to be called at this state.`);
|
|
22
|
+
}
|
|
23
|
+
await transition.do(...params);
|
|
24
|
+
this.currentState = transition.assignOnFinish;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.JsonStreamStateWriter = JsonStreamStateWriter;
|
|
28
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare abstract class JsonStreamWritable {
|
|
2
|
+
protected pushWritable: (value: string) => Promise<void>;
|
|
3
|
+
private openedSymbols;
|
|
4
|
+
private numberPropertiesInOpenedSymbol;
|
|
5
|
+
private currentPropertyOpen;
|
|
6
|
+
constructor(pushWritable: (value: string) => Promise<void>);
|
|
7
|
+
protected isValid: () => boolean;
|
|
8
|
+
private numPropertiesInCurrentOpenedSymbol;
|
|
9
|
+
protected startObject(): Promise<void>;
|
|
10
|
+
protected endObject(): Promise<void>;
|
|
11
|
+
protected startArray(): Promise<void>;
|
|
12
|
+
protected endArray(): Promise<void>;
|
|
13
|
+
protected writeProperty<T>(name: string, value: Promise<string>): Promise<void>;
|
|
14
|
+
protected writeProperties<T>(properties: {
|
|
15
|
+
name: string;
|
|
16
|
+
value: Promise<string>;
|
|
17
|
+
}[]): Promise<void>;
|
|
18
|
+
protected writePropertyName(name: string): Promise<void>;
|
|
19
|
+
protected writeValue<T>(value: Promise<string>): Promise<void>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
(function (factory) {
|
|
2
|
+
if (typeof module === "object" && typeof module.exports === "object") {
|
|
3
|
+
var v = factory(require, exports);
|
|
4
|
+
if (v !== undefined) module.exports = v;
|
|
5
|
+
}
|
|
6
|
+
else if (typeof define === "function" && define.amd) {
|
|
7
|
+
define(["require", "exports"], factory);
|
|
8
|
+
}
|
|
9
|
+
})(function (require, exports) {
|
|
10
|
+
"use strict";
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.JsonStreamWritable = void 0;
|
|
13
|
+
class JsonStreamWritable {
|
|
14
|
+
constructor(pushWritable) {
|
|
15
|
+
this.pushWritable = pushWritable;
|
|
16
|
+
this.isValid = () => this.openedSymbols.length === 0;
|
|
17
|
+
this.numPropertiesInCurrentOpenedSymbol = () => this.numberPropertiesInOpenedSymbol.length > 0 ? this.numberPropertiesInOpenedSymbol.at(-1) : 0;
|
|
18
|
+
this.openedSymbols = [];
|
|
19
|
+
this.numberPropertiesInOpenedSymbol = [];
|
|
20
|
+
this.currentPropertyOpen = false;
|
|
21
|
+
}
|
|
22
|
+
async startObject() {
|
|
23
|
+
await this.pushWritable('{');
|
|
24
|
+
this.openedSymbols.push('object');
|
|
25
|
+
this.numberPropertiesInOpenedSymbol.push(0);
|
|
26
|
+
this.currentPropertyOpen = false;
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
async endObject() {
|
|
30
|
+
await this.pushWritable('}');
|
|
31
|
+
this.openedSymbols.splice(this.openedSymbols.lastIndexOf('object'), 1);
|
|
32
|
+
if (this.numberPropertiesInOpenedSymbol.length > 0) {
|
|
33
|
+
this.numberPropertiesInOpenedSymbol.splice(this.numberPropertiesInOpenedSymbol.length - 1, 1);
|
|
34
|
+
}
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
async startArray() {
|
|
38
|
+
await this.pushWritable('[');
|
|
39
|
+
this.openedSymbols.push('array');
|
|
40
|
+
this.numberPropertiesInOpenedSymbol.push(0);
|
|
41
|
+
this.currentPropertyOpen = false;
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
async endArray() {
|
|
45
|
+
this.pushWritable(']');
|
|
46
|
+
this.openedSymbols.splice(this.openedSymbols.lastIndexOf('array'), 1);
|
|
47
|
+
if (this.numberPropertiesInOpenedSymbol.length > 0) {
|
|
48
|
+
this.numberPropertiesInOpenedSymbol.splice(this.numberPropertiesInOpenedSymbol.length - 1, 1);
|
|
49
|
+
}
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
async writeProperty(name, value) {
|
|
53
|
+
if (this.openedSymbols.length <= 0 || this.openedSymbols.at(-1) !== 'object' || this.currentPropertyOpen) {
|
|
54
|
+
throw new Error(`Json Write Method is not allowed for property ${name} here.`);
|
|
55
|
+
}
|
|
56
|
+
const prefix = this.numPropertiesInCurrentOpenedSymbol() > 0 ? ', ' : '';
|
|
57
|
+
await this.pushWritable(`${prefix}${name}: ${await value}`);
|
|
58
|
+
this.numberPropertiesInOpenedSymbol[this.numberPropertiesInOpenedSymbol.length - 1] += 1;
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
async writeProperties(properties) {
|
|
62
|
+
if (this.currentPropertyOpen) {
|
|
63
|
+
throw new Error(`Json Write Method is not allowed, since currently a property value needs to be written.`);
|
|
64
|
+
}
|
|
65
|
+
for (const property of properties) {
|
|
66
|
+
await this.writeProperty(property.name, property.value);
|
|
67
|
+
}
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
async writePropertyName(name) {
|
|
71
|
+
if (this.currentPropertyOpen) {
|
|
72
|
+
throw new Error(`Json Write Method is not allowed, since currently a property value needs to be written.`);
|
|
73
|
+
}
|
|
74
|
+
const prefix = this.numPropertiesInCurrentOpenedSymbol() > 0 ? ', ' : '';
|
|
75
|
+
this.currentPropertyOpen = true;
|
|
76
|
+
await this.pushWritable(`${prefix}${name}:`);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
async writeValue(value) {
|
|
80
|
+
if (this.openedSymbols.length <= 0 || (!this.currentPropertyOpen && this.openedSymbols.at(-1) !== 'array')) {
|
|
81
|
+
throw new Error(`Json Write Method is not allowed for any value here.`);
|
|
82
|
+
}
|
|
83
|
+
const prefix = this.numPropertiesInCurrentOpenedSymbol() > 0 ? ', ' : '';
|
|
84
|
+
if (this.currentPropertyOpen) {
|
|
85
|
+
this.currentPropertyOpen = false;
|
|
86
|
+
}
|
|
87
|
+
await this.pushWritable(`${prefix}${await value}`);
|
|
88
|
+
this.numberPropertiesInOpenedSymbol[this.numberPropertiesInOpenedSymbol.length - 1] += 1;
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
exports.JsonStreamWritable = JsonStreamWritable;
|
|
93
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { WritableStreamDefaultWriter } from "stream/web";
|
|
3
|
+
import { ChunkCompressionInfo, ObjectReference, SatisfactorySaveHeader, SaveComponent, SaveEntity } from "../..";
|
|
4
|
+
import { JsonStreamStateWriter } from "./json-stream-state-writer";
|
|
5
|
+
type State = 'BEFORE_START' | 'OPENED_SAVE' | 'FINISHED_HEADER' | 'OPENED_LEVELS' | 'FINISHED_LEVELS' | 'OPENED_LEVEL' | 'FINISHED_LEVEL' | 'FINISHED_SAVE' | 'WROTE_COMPRESSION_INFO' | 'WROTE_OBJECT' | 'SWITCH_TO_COLLECTABLES' | 'WROTE_COLLECTABLE';
|
|
6
|
+
export declare class JsonStreamWriter extends JsonStreamStateWriter<State> {
|
|
7
|
+
private writer;
|
|
8
|
+
private readonly stateMachine;
|
|
9
|
+
constructor(writer: WritableStreamDefaultWriter<string>);
|
|
10
|
+
beginSave(): Promise<void>;
|
|
11
|
+
writeHeader(header: SatisfactorySaveHeader): Promise<void>;
|
|
12
|
+
writeCompressionInfo(compressionInfo: ChunkCompressionInfo): Promise<void>;
|
|
13
|
+
openLevels(): Promise<void>;
|
|
14
|
+
openLevel(): Promise<void>;
|
|
15
|
+
writeObject(object: SaveEntity | SaveComponent): Promise<void>;
|
|
16
|
+
switchToCollectables(): Promise<void>;
|
|
17
|
+
writeCollectable(object: ObjectReference): Promise<void>;
|
|
18
|
+
closeLevel(): Promise<void>;
|
|
19
|
+
closeLevels(): Promise<void>;
|
|
20
|
+
endSave(): Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
(function (factory) {
|
|
2
|
+
if (typeof module === "object" && typeof module.exports === "object") {
|
|
3
|
+
var v = factory(require, exports);
|
|
4
|
+
if (v !== undefined) module.exports = v;
|
|
5
|
+
}
|
|
6
|
+
else if (typeof define === "function" && define.amd) {
|
|
7
|
+
define(["require", "exports", "./json-stream-state-writer"], factory);
|
|
8
|
+
}
|
|
9
|
+
})(function (require, exports) {
|
|
10
|
+
"use strict";
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.JsonStreamWriter = void 0;
|
|
13
|
+
const json_stream_state_writer_1 = require("./json-stream-state-writer");
|
|
14
|
+
class JsonStreamWriter extends json_stream_state_writer_1.JsonStreamStateWriter {
|
|
15
|
+
constructor(writer) {
|
|
16
|
+
super(async (value) => await writer.write(value), 'BEFORE_START');
|
|
17
|
+
this.writer = writer;
|
|
18
|
+
this.stateMachine = {
|
|
19
|
+
openSave: {
|
|
20
|
+
name: 'Open Save',
|
|
21
|
+
requiresOneOfThemToBeBefore: ['BEFORE_START'],
|
|
22
|
+
do: async () => await this.startObject(),
|
|
23
|
+
assignOnFinish: 'OPENED_SAVE',
|
|
24
|
+
},
|
|
25
|
+
writeHeader: {
|
|
26
|
+
name: 'Write Header',
|
|
27
|
+
requiresOneOfThemToBeBefore: ['OPENED_SAVE'],
|
|
28
|
+
do: async (param) => await this.writeProperty('header', Promise.resolve(JSON.stringify(param))),
|
|
29
|
+
assignOnFinish: 'FINISHED_HEADER',
|
|
30
|
+
},
|
|
31
|
+
writeCompressionInfo: {
|
|
32
|
+
name: 'Write Compression Info',
|
|
33
|
+
requiresOneOfThemToBeBefore: ['FINISHED_HEADER'],
|
|
34
|
+
do: async (param) => await this.writeProperty('compressionInfo', Promise.resolve(JSON.stringify(param))),
|
|
35
|
+
assignOnFinish: 'WROTE_COMPRESSION_INFO',
|
|
36
|
+
},
|
|
37
|
+
openLevels: {
|
|
38
|
+
name: 'Open Levels',
|
|
39
|
+
requiresOneOfThemToBeBefore: ['WROTE_COMPRESSION_INFO'],
|
|
40
|
+
do: async () => await this.startArray(),
|
|
41
|
+
assignOnFinish: 'OPENED_LEVELS',
|
|
42
|
+
},
|
|
43
|
+
openLevel: {
|
|
44
|
+
name: 'Open Level',
|
|
45
|
+
requiresOneOfThemToBeBefore: ['OPENED_LEVELS', 'FINISHED_LEVEL'],
|
|
46
|
+
do: async (param) => {
|
|
47
|
+
await this.writePropertyName(param);
|
|
48
|
+
await this.startObject();
|
|
49
|
+
await this.writeProperty('name', Promise.resolve(param));
|
|
50
|
+
await this.writePropertyName('objects');
|
|
51
|
+
await this.startArray();
|
|
52
|
+
},
|
|
53
|
+
assignOnFinish: 'OPENED_LEVEL',
|
|
54
|
+
},
|
|
55
|
+
writeObject: {
|
|
56
|
+
name: 'Write Object',
|
|
57
|
+
requiresOneOfThemToBeBefore: ['OPENED_LEVEL', 'WROTE_OBJECT'],
|
|
58
|
+
do: async (param) => await this.writeValue(Promise.resolve(JSON.stringify(param))),
|
|
59
|
+
assignOnFinish: 'WROTE_OBJECT',
|
|
60
|
+
},
|
|
61
|
+
switchToCollectables: {
|
|
62
|
+
name: 'Switch To collectables',
|
|
63
|
+
requiresOneOfThemToBeBefore: ['OPENED_LEVEL', 'WROTE_OBJECT'],
|
|
64
|
+
do: async () => {
|
|
65
|
+
await this.endArray();
|
|
66
|
+
await this.writePropertyName('collectables');
|
|
67
|
+
await this.startArray();
|
|
68
|
+
},
|
|
69
|
+
assignOnFinish: 'SWITCH_TO_COLLECTABLES',
|
|
70
|
+
},
|
|
71
|
+
writeCollectable: {
|
|
72
|
+
name: 'Write Collectables',
|
|
73
|
+
requiresOneOfThemToBeBefore: ['SWITCH_TO_COLLECTABLES'],
|
|
74
|
+
do: async (param) => {
|
|
75
|
+
await this.writeValue(Promise.resolve(JSON.stringify(param)));
|
|
76
|
+
},
|
|
77
|
+
assignOnFinish: 'WROTE_COLLECTABLE',
|
|
78
|
+
},
|
|
79
|
+
closeLevel: {
|
|
80
|
+
name: 'Close Level',
|
|
81
|
+
requiresOneOfThemToBeBefore: ['SWITCH_TO_COLLECTABLES', 'WROTE_COLLECTABLE'],
|
|
82
|
+
do: async () => {
|
|
83
|
+
await this.endArray();
|
|
84
|
+
await this.endObject();
|
|
85
|
+
},
|
|
86
|
+
assignOnFinish: 'FINISHED_LEVEL',
|
|
87
|
+
},
|
|
88
|
+
closeLevels: {
|
|
89
|
+
name: 'Close Levels',
|
|
90
|
+
requiresOneOfThemToBeBefore: [],
|
|
91
|
+
do: async () => await this.endArray(),
|
|
92
|
+
assignOnFinish: "FINISHED_LEVELS",
|
|
93
|
+
},
|
|
94
|
+
closeSave: {
|
|
95
|
+
name: 'Close Save',
|
|
96
|
+
requiresOneOfThemToBeBefore: ['FINISHED_LEVELS'],
|
|
97
|
+
do: async () => await this.startObject(),
|
|
98
|
+
assignOnFinish: 'FINISHED_SAVE',
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
async beginSave() {
|
|
103
|
+
await this.useTransition(this.stateMachine.openSave);
|
|
104
|
+
}
|
|
105
|
+
async writeHeader(header) {
|
|
106
|
+
await this.useTransition(this.stateMachine.writeHeader, header);
|
|
107
|
+
}
|
|
108
|
+
async writeCompressionInfo(compressionInfo) {
|
|
109
|
+
await this.useTransition(this.stateMachine.writeCompressionInfo, compressionInfo);
|
|
110
|
+
}
|
|
111
|
+
async openLevels() {
|
|
112
|
+
await this.useTransition(this.stateMachine.openLevels);
|
|
113
|
+
}
|
|
114
|
+
async openLevel() {
|
|
115
|
+
await this.useTransition(this.stateMachine.openLevel);
|
|
116
|
+
}
|
|
117
|
+
async writeObject(object) {
|
|
118
|
+
await this.useTransition(this.stateMachine.writeObject, object);
|
|
119
|
+
}
|
|
120
|
+
async switchToCollectables() {
|
|
121
|
+
await this.useTransition(this.stateMachine.switchToCollectables);
|
|
122
|
+
}
|
|
123
|
+
async writeCollectable(object) {
|
|
124
|
+
await this.useTransition(this.stateMachine.writeCollectable, object);
|
|
125
|
+
}
|
|
126
|
+
async closeLevel() {
|
|
127
|
+
await this.useTransition(this.stateMachine.closeLevel);
|
|
128
|
+
}
|
|
129
|
+
async closeLevels() {
|
|
130
|
+
await this.useTransition(this.stateMachine.closeLevels);
|
|
131
|
+
}
|
|
132
|
+
async endSave() {
|
|
133
|
+
await this.useTransition(this.stateMachine.closeSave);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
exports.JsonStreamWriter = JsonStreamWriter;
|
|
137
|
+
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { WritableStream } from "stream/web";
|
|
3
|
+
import { SatisfactorySave } from "../..";
|
|
4
|
+
export declare class SaveStreamJsonStringifier {
|
|
5
|
+
static StreamStringifySave(save: SatisfactorySave, output: WritableStream<string>): Promise<void>;
|
|
6
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
(function (factory) {
|
|
2
|
+
if (typeof module === "object" && typeof module.exports === "object") {
|
|
3
|
+
var v = factory(require, exports);
|
|
4
|
+
if (v !== undefined) module.exports = v;
|
|
5
|
+
}
|
|
6
|
+
else if (typeof define === "function" && define.amd) {
|
|
7
|
+
define(["require", "exports", "./save-stream-writer.class"], factory);
|
|
8
|
+
}
|
|
9
|
+
})(function (require, exports) {
|
|
10
|
+
"use strict";
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.SaveStreamJsonStringifier = void 0;
|
|
13
|
+
const save_stream_writer_class_1 = require("./save-stream-writer.class");
|
|
14
|
+
class SaveStreamJsonStringifier {
|
|
15
|
+
static async StreamStringifySave(save, output) {
|
|
16
|
+
const writer = new save_stream_writer_class_1.SaveStreamWriter(output.getWriter());
|
|
17
|
+
await writer.beginSave();
|
|
18
|
+
await writer.writeHeader(save.header);
|
|
19
|
+
if (save.compressionInfo) {
|
|
20
|
+
await writer.writeCompressionInfo(save.compressionInfo);
|
|
21
|
+
}
|
|
22
|
+
await writer.openLevels();
|
|
23
|
+
const objectBatchSize = 10000;
|
|
24
|
+
for (const level of save.levels) {
|
|
25
|
+
await writer.openLevel(level.name);
|
|
26
|
+
let i = 0;
|
|
27
|
+
for (i; i < level.objects.length; i += objectBatchSize) {
|
|
28
|
+
await writer.writeObjects(...level.objects.slice(i, Math.min(i + objectBatchSize, level.objects.length)));
|
|
29
|
+
}
|
|
30
|
+
await writer.switchInLevelToCollectables();
|
|
31
|
+
i = 0;
|
|
32
|
+
for (i; i < level.collectables.length; i += objectBatchSize) {
|
|
33
|
+
await writer.writeCollectables(...level.collectables.slice(i, Math.min(i + objectBatchSize, level.collectables.length)));
|
|
34
|
+
}
|
|
35
|
+
await writer.endLevel();
|
|
36
|
+
}
|
|
37
|
+
await writer.endLevels();
|
|
38
|
+
await writer.endSave();
|
|
39
|
+
await writer.close();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.SaveStreamJsonStringifier = SaveStreamJsonStringifier;
|
|
43
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { ReadableStreamDefaultReader } from "stream/web";
|
|
3
|
+
import { ChunkCompressionInfo, SatisfactorySaveHeader } from "../..";
|
|
4
|
+
import { ByteStreamReader } from "./byte-stream-reader.class";
|
|
5
|
+
import { SaveStreamWriter } from "./save-stream-writer.class";
|
|
6
|
+
export declare class SaveStreamReader extends ByteStreamReader {
|
|
7
|
+
static readonly EPOCH_TICKS = 621355968000000000n;
|
|
8
|
+
static readonly DEFAULT_SATISFACTORY_CHUNK_HEADER_SIZE = 48;
|
|
9
|
+
compressionInfo: ChunkCompressionInfo;
|
|
10
|
+
constructor(reader: ReadableStreamDefaultReader<Uint8Array>, maxBufferThreshold: number, onCloseCallback?: () => Promise<void>);
|
|
11
|
+
readHeader(): Promise<SatisfactorySaveHeader>;
|
|
12
|
+
readBodyChunk(): Promise<Uint8Array>;
|
|
13
|
+
debugInfo(): string;
|
|
14
|
+
streamLevelsToOutput(writer: SaveStreamWriter, header: SatisfactorySaveHeader): Promise<void>;
|
|
15
|
+
}
|