UNPKG

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
"use strict"; 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, };