xcom2charpool
Version:
Library for reading, manipulating, and managing XCOM 2 character pool binary files, supporting both browser and Node.js environments.
109 lines (108 loc) • 4.57 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Packer = void 0;
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 NoneProperty_1 = require("./Properties/NoneProperty");
const ArrayOfStructs_1 = require("./Arrays/ArrayOfStructs");
class Packer {
constructor(writer) {
this.writer = writer;
}
writeFile(data) {
// Write the magic number
this.writer.uint32(0xffffffff);
// Write the properties
this.writeProperties(data.state);
// Write the 'None' property to signify the end of properties
NoneProperty_1.NoneProperty.to(this.writer);
// Write the 'CharacterPoolDataElements' array
// Assuming data.data.items is the array of elements
ArrayProperty_1.ArrayProperty.to(this.writer, data.data.items, this);
}
writeProperties(obj) {
for (const [name, value] of Object.entries(obj)) {
this.writeProperty(name, value);
}
}
writeProperty(name, property, isArrayElement = false) {
// Determine property type
let type = typeof property === 'object' && 'constructor' in property ? property.constructor.name : '';
switch (typeof property) {
case 'number':
type = 'IntProperty';
break;
case 'string':
type = 'StrProperty';
break;
case 'boolean':
type = 'BoolProperty';
break;
case 'object':
if (property instanceof ArrayOfStructs_1.ArrayOfStructs) {
property = property.items;
type = 'ArrayProperty';
}
if (!Array.isArray(property) &&
!Object.values(this.constructor.types).find((t) => property instanceof t)) {
type = 'StructProperty';
}
break;
}
if (type === 'Array')
type = 'ArrayProperty';
if (!type) {
throw new Error(`Property type is missing for property with name ${name}`);
}
const factory = this.constructor.types[type];
if (!factory) {
throw new Error(`Unknown property type ${type} with name ${name}`);
}
let sizePosition = 0;
if (!isArrayElement) {
// Write property name and padding
this.writer.string(name);
this.writer.padding();
// Write property type and padding
this.writer.string(type);
this.writer.padding();
// Reserve space for size
sizePosition = this.writer.position;
this.writer.uint32(0);
this.writer.padding(); // Write padding after placeholder size
}
// Record the start position of the property data
const dataStartPosition = this.writer.position;
// Write the property data
let size = factory.to(this.writer, property, this, isArrayElement);
if (typeof size !== 'number') {
// Calculate the size of the property data
const dataEndPosition = this.writer.position;
size = dataEndPosition - dataStartPosition;
}
if (!isArrayElement) {
// Go back and write the actual size
const currentPosition = this.writer.position;
this.writer.position = sizePosition;
this.writer.uint32(size);
// Do not write padding again here
// Restore the writer position to continue writing
this.writer.position = currentPosition;
}
}
}
exports.Packer = Packer;
Packer.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,
};