xcom2charpool
Version:
Library for reading, manipulating, and managing XCOM 2 character pool binary files, supporting both browser and Node.js environments.
92 lines (91 loc) • 4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Unpacker = void 0;
const NoneProperty_1 = require("./Properties/NoneProperty");
const ArrayProperty_1 = require("./Properties/ArrayProperty");
const BoolProperty_1 = require("./Properties/BoolProperty");
const ByteProperty_1 = require("./Properties/ByteProperty");
const IntProperty_1 = require("./Properties/IntProperty");
const NameProperty_1 = require("./Properties/NameProperty");
const StrProperty_1 = require("./Properties/StrProperty");
const StructProperty_1 = require("./Properties/StructProperty");
const CharacterPoolDataElements_1 = require("./Arrays/CharacterPoolDataElements");
const ArrayOfStructs_1 = require("./Arrays/ArrayOfStructs");
class Unpacker {
get position() {
return this.reader.position;
}
get length() {
return this.reader.length;
}
constructor(reader) {
this.reader = reader;
}
readFile() {
const magic = this.reader.uint32();
if (magic !== 0xffffffff) {
throw new Error(`Incorrect file magic 0x${magic.toString(16).padStart(8, '0')}`);
}
const state = this.properties();
// Почему-то внизу файла присобачен еще один массив
const arr = ArrayProperty_1.ArrayProperty.from(this.reader, CharacterPoolDataElements_1.CharacterPoolDataElements.name, this.reader.length - this.reader.position);
const data = new CharacterPoolDataElements_1.CharacterPoolDataElements(arr, (reader) => new Unpacker(reader));
if (this.reader.position < this.reader.length) {
throw new Error(`Reader is not in the end of file! ${this.reader.length - this.reader.position} bytes remains`);
}
return { state, data };
}
properties() {
const props = {};
while (this.reader.position < this.reader.length) {
const prop = this.property();
if (!prop)
return props;
props[prop.name] = prop.property;
}
return props;
}
property() {
const name = this.reader.string();
this.reader.padding();
if (name === NoneProperty_1.NoneProperty.PropertyName)
return;
const type = this.reader.string();
this.reader.padding();
const factory = this.constructor.types[type];
if (!factory) {
throw new Error(`Unknown property type ${type} with name ${name}`);
}
const size = this.reader.uint32();
this.reader.padding();
const property = factory.from(this.reader, name, size, (reader) => new Unpacker(reader));
if (property instanceof ArrayProperty_1.ArrayProperty) {
const factory = this.constructor.knownArrays[name];
if (factory) {
return { name, property: factory.from(property, name, (reader) => new Unpacker(reader)) };
}
else {
console.warn(`[Unpacker] Array of unknown type ${name}`);
}
}
return { name, property };
}
}
exports.Unpacker = Unpacker;
Unpacker.types = {
[ArrayProperty_1.ArrayProperty.name]: ArrayProperty_1.ArrayProperty,
[BoolProperty_1.BoolProperty.name]: BoolProperty_1.BoolProperty,
[ByteProperty_1.ByteProperty.name]: ByteProperty_1.ByteProperty,
[IntProperty_1.IntProperty.name]: IntProperty_1.IntProperty,
[NameProperty_1.NameProperty.name]: NameProperty_1.NameProperty,
[StrProperty_1.StrProperty.name]: StrProperty_1.StrProperty,
[StructProperty_1.StructProperty.name]: StructProperty_1.StructProperty,
};
Unpacker.knownArrays = {
CharacterPool: ArrayOfStructs_1.ArrayOfStructs,
ExtraDatas: ArrayOfStructs_1.ArrayOfStructs,
AppearanceStore: ArrayOfStructs_1.ArrayOfStructs,
CharacterPoolLoadout: ArrayOfStructs_1.ArrayOfStructs,
UniformSettings: ArrayOfStructs_1.ArrayOfStructs,
CosmeticOptions: ArrayOfStructs_1.ArrayOfStructs,
};