Files
healer-man/scripts/coa-reference/archive-dbc.mjs

42 lines
2.0 KiB
JavaScript

/** Reconstruct the exact scalar/string semantics of positional archive rows. */
export function archiveRowsToDbc(records, fieldTypes) {
if (!Array.isArray(fieldTypes) || fieldTypes.length !== 234) throw new Error("Archived Spell requires all 234 column types");
const strings = [Buffer.from([0])];
let stringSize = 1;
const stringOffsets = new Map([["", 0]]);
const rows = records.map((record) => {
const row = Buffer.alloc(234 * 4);
for (let index = 0; index < 234; index += 1) {
const key = `f${index}`;
if (!Object.hasOwn(record, key)) throw new Error(`Archived spell ${record.f0} is missing ${key}`);
const value = record[key];
const localized = (index >= 136 && index <= 151) || (index >= 153 && index <= 168)
|| (index >= 170 && index <= 185) || (index >= 187 && index <= 202);
const text = typeof value === "string" ? value : localized && typeof record[`${key}s`] === "string" ? record[`${key}s`] : null;
if (text !== null) {
if (!stringOffsets.has(text)) {
const bytes = Buffer.from(`${text}\0`, "utf8");
stringOffsets.set(text, stringSize);
strings.push(bytes);
stringSize += bytes.length;
}
row.writeUInt32LE(stringOffsets.get(text), index * 4);
} else if (fieldTypes[index] === "float") {
if (!Number.isFinite(value)) throw new Error(`Archived spell ${record.f0} has invalid ${key}`);
row.writeFloatLE(value, index * 4);
} else {
if (!Number.isInteger(value) || value < -2147483648 || value > 4294967295) throw new Error(`Archived spell ${record.f0} has invalid integer ${key}`);
row.writeUInt32LE(value >>> 0, index * 4);
}
}
return row;
});
const header = Buffer.alloc(20);
header.write("WDBC", 0);
header.writeUInt32LE(rows.length, 4);
header.writeUInt32LE(234, 8);
header.writeUInt32LE(234 * 4, 12);
header.writeUInt32LE(stringSize, 16);
return Buffer.concat([header, ...rows, ...strings]);
}