@etothepii/satisfactory-file-parser
Version:
A file parser for satisfactory files. Includes save files and blueprint files.
104 lines (103 loc) • 4.7 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.StreamLevel = void 0;
const __1 = require("../..");
const SaveComponent_1 = require("../satisfactory/objects/SaveComponent");
const SaveEntity_1 = require("../satisfactory/objects/SaveEntity");
class StreamLevel {
constructor(name) {
this.name = name;
}
static async ReadLevelAsync(reader, writer, levelName, buildVersion) {
const binaryLength = reader.readInt32();
await reader.allocate(binaryLength);
const objectHeaders = StreamLevel.ReadObjectHeaders(reader);
const collectables = __1.Level.ReadCollectablesList(reader);
await writer.openLevel(levelName);
await StreamLevel.StreamObjectContentsAsync(reader, writer, objectHeaders, buildVersion);
await writer.switchInLevelToCollectables();
await writer.writeCollectables(...collectables);
await writer.endLevel();
__1.Level.ReadCollectablesList(reader);
return;
}
static ReadObjectHeaders(reader) {
let countObjectHeaders = reader.readInt32();
const headers = [];
for (let i = 0; i < countObjectHeaders; i++) {
let objectType = reader.readInt32();
switch (objectType) {
case 1:
headers.push({
typePath: reader.readString(),
rootObject: reader.readString(),
instanceName: reader.readString(),
needTransform: reader.readInt32() == 1,
transform: (0, __1.ParseTransform)(reader),
wasPlacedInLevel: reader.readInt32() == 1
});
break;
case 0:
headers.push({
typePath: reader.readString(),
rootObject: reader.readString(),
instanceName: reader.readString(),
parentEntityName: reader.readString()
});
break;
default:
console.log('Unknown object type', objectType);
break;
}
}
return headers;
}
static async StreamObjectContentsAsync(reader, writer, headerList, buildVersion) {
const binarySize = reader.readInt32();
const posBefore = reader.getBufferPosition();
await reader.allocate(Math.min(binarySize, 300 * 1000 * 1000));
const countEntities = reader.readInt32();
if (countEntities !== headerList.length) {
throw new Error(`possibly corrupt. entity content count ${countEntities} does not object count of ${headerList.length}`);
}
let bufferedObjects = [];
for (let i = 0; i < countEntities; i++) {
if ((i + 1) % 10000 === 0) {
await writer.writeObjects(...bufferedObjects);
bufferedObjects = [];
}
const len = reader.readInt32();
if (reader.getAmountAllocatedLeft() <= len) {
const allocateAmount = Math.min(binarySize - (reader.getBufferPosition() - posBefore) + 4, 300 * 1000 * 1000);
await reader.allocate(allocateAmount);
}
const before = reader.getBufferPosition();
const obj = headerList.shift();
if (!obj) {
throw new Error();
}
const isComponent = obj.parentEntityName !== undefined;
if (!isComponent) {
const entity = new SaveEntity_1.SaveEntity(obj.typePath, obj.rootObject, obj.instanceName, '', obj.needTransform);
SaveEntity_1.SaveEntity.ParseData(entity, len, reader, buildVersion, obj.typePath);
bufferedObjects.push(entity);
}
else if (isComponent) {
const component = new SaveComponent_1.SaveComponent(obj.typePath, obj.rootObject, obj.instanceName, obj.parentEntityName);
SaveComponent_1.SaveComponent.ParseData(component, len, reader, buildVersion, obj.typePath);
bufferedObjects.push(component);
}
const after = reader.getBufferPosition();
if (after - before !== len) {
console.warn('entity may be corrupt.', i);
}
}
await writer.writeObjects(...bufferedObjects);
bufferedObjects = [];
const posAfter = reader.getBufferPosition();
if (posAfter - posBefore !== binarySize) {
console.warn('save seems corrupt.', this.name);
}
}
}
exports.StreamLevel = StreamLevel;
;