unpak.js
Version:
Modern TypeScript library for reading Unreal Engine pak files and assets, inspired by CUE4Parse
164 lines • 6.47 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FValueHandle = exports.FPartialMapHandle = exports.ELoadOrder = exports.FStore = exports.END_MAGIC = exports.BEGIN_MAGIC = exports.OLD_BEGIN_MAGIC = void 0;
const AssetDataTagMap_1 = require("./AssetDataTagMap");
const NameTypes_1 = require("../../objects/uobject/NameTypes");
const Exceptions_1 = require("../../../exceptions/Exceptions");
exports.OLD_BEGIN_MAGIC = 0x12345678;
exports.BEGIN_MAGIC = 0x12345679;
exports.END_MAGIC = 0x87654321;
/** Stores a fixed set of values and all the key-values maps used for lookup */
class FStore {
Ar;
constructor(Ar) {
this.Ar = Ar;
this.nameMap = this.Ar.names;
// init
const initialMagic = Ar.readUInt32();
const order = this.getLoadOrder(initialMagic);
if (!order)
throw new Exceptions_1.ParserException("Bad init magic", Ar);
const nums = new Array(11);
for (let i = 0; i < 11; ++i) {
nums[i] = Ar.readInt32();
}
if (order === ELoadOrder.TextFirst) {
const textDataBytes = Ar.readUInt32();
const len = nums[4];
this.texts = new Array(len);
for (let i = 0; i < len; ++i) {
this.texts[i] = Ar.readString();
}
}
const len1 = nums[0];
this.numberlessNames = new Array(len1);
for (let i = 0; i < len1; ++i) {
this.numberlessNames[i] = new NameTypes_1.FNameEntryId(Ar);
}
const len2 = nums[1];
this.names = new Array(len2);
for (let i = 0; i < len2; ++i) {
this.names[i] = Ar.readFName();
}
const len3 = nums[2];
this.numberlessExportPaths = new Array(len3);
for (let i = 0; i < len3; ++i) {
this.numberlessExportPaths[i] = new AssetDataTagMap_1.FNumberlessExportPath(Ar, this.nameMap);
}
const len4 = nums[3];
this.exportPaths = new Array(len4);
for (let i = 0; i < len4; ++i) {
this.exportPaths[i] = new AssetDataTagMap_1.FAssetRegistryExportPath(Ar);
}
if (order === ELoadOrder.Member) {
const _len = nums[4];
this.texts = new Array(_len);
for (let i = 0; i < _len; ++i) {
this.texts[i] = Ar.readString();
}
}
const len5 = nums[5];
this.ansiStringOffsets = new Array(len5);
for (let i = 0; i < len5; ++i) {
this.ansiStringOffsets[i] = Ar.readUInt32();
}
const len6 = nums[6];
this.wideStringOffsets = new Array(len6);
for (let i = 0; i < len6; ++i) {
this.wideStringOffsets[i] = Ar.readUInt32();
}
this.ansiStrings = Ar.read(nums[7]);
this.wideStrings = Ar.wrappedAr.read(nums[8] * 2);
const len7 = nums[9];
this.numberlessPairs = new Array(len7);
for (let i = 0; i < len7; ++i) {
this.numberlessPairs[i] = new AssetDataTagMap_1.FNumberlessPair(Ar);
}
const len8 = nums[10];
this.pairs = new Array(len8);
for (let i = 0; i < len8; ++i) {
this.pairs[i] = new AssetDataTagMap_1.FNumberedPair(Ar);
}
if (Ar.readUInt32() !== exports.END_MAGIC)
throw new Error("Bytes did not match 'END_MAGIC' at end");
}
// Pairs for all unsorted maps that uses this store
pairs;
numberlessPairs;
// Values for all maps in this store
ansiStringOffsets;
ansiStrings;
wideStringOffsets;
wideStrings;
numberlessNames;
names;
numberlessExportPaths;
exportPaths;
texts = []; // FText objects serialized in NSLOCTEXT() strings
nameMap;
getLoadOrder(initialMagic) {
return initialMagic === exports.OLD_BEGIN_MAGIC ? ELoadOrder.Member :
initialMagic === exports.BEGIN_MAGIC ? ELoadOrder.TextFirst :
null;
}
getAnsiString(idx) {
const offset = this.ansiStringOffsets[idx];
let length = 0;
while (this.ansiStrings[offset + length] !== 0)
++length;
return this.ansiStrings.subarray(offset, offset + length).toString("utf-8");
}
getWideString(idx) {
const offset = this.wideStringOffsets[idx];
var length = 0;
while (this.wideStrings[offset + length] !== 0 && this.wideStrings[offset + length + 1] !== 0)
length += 2;
return this.wideStrings.subarray(offset, offset + length).toString("utf16le");
}
}
exports.FStore = FStore;
var ELoadOrder;
(function (ELoadOrder) {
ELoadOrder["Member"] = "Member";
ELoadOrder["TextFirst"] = "TextFirst";
})(ELoadOrder || (exports.ELoadOrder = ELoadOrder = {}));
class FPartialMapHandle {
int;
bHasNumberlessKeys;
num;
pairBegin;
constructor(int) {
this.int = int;
this.bHasNumberlessKeys = int >> 63 > 0;
this.num = int >> 32;
this.pairBegin = int;
}
makeFullHandle(store) {
return new AssetDataTagMap_1.FMapHandle(this, store);
}
toInt() {
return ((this.bHasNumberlessKeys ? 1 : 0) << 63) | (this.num << 32) | this.pairBegin;
}
}
exports.FPartialMapHandle = FPartialMapHandle;
class FValueHandle {
store;
id;
constructor(store, id) {
this.store = store;
this.id = id;
}
asString() {
const index = this.id.index;
return this.id.type === AssetDataTagMap_1.EValueType.AnsiString ? this.store.getAnsiString(index) :
this.id.type === AssetDataTagMap_1.EValueType.WideString ? this.store.getWideString(index) :
this.id.type === AssetDataTagMap_1.EValueType.NumberlessName ? this.store.nameMap[this.store.numberlessNames[index].value] :
this.id.type === AssetDataTagMap_1.EValueType.Name ? this.store.names[index].text :
this.id.type === AssetDataTagMap_1.EValueType.NumberlessExportPath ? this.store.numberlessExportPaths[index].toString() :
this.id.type === AssetDataTagMap_1.EValueType.ExportPath ? this.store.exportPaths[index].toString() :
this.id.type === AssetDataTagMap_1.EValueType.LocalizedText ? this.store.texts[index].toString() :
"";
}
}
exports.FValueHandle = FValueHandle;
//# sourceMappingURL=AssetDataTagMapSerializationDetails.js.map