@abextm/cache2
Version:
Utilities for reading OSRS "caches"
183 lines (182 loc) • 5.79 kB
JavaScript
import { Loadable, PerFileLoadable } from "../Loadable.js";
import { Reader } from "../Reader.js";
import { Typed } from "../reflect.js";
import { BaseVarType, ScriptVarType } from "../ScriptVarType.js";
import { DBColumnID } from "../types.js";
function readTypes(r) {
let size = r.u8();
let types = new Array(size).fill(undefined);
for (let i = 0; i < size; i++) {
types[i] = r.u8o16();
}
return types;
}
function readVarType(r, type) {
switch (type) {
case "int":
return r.i32();
break;
case "string":
return r.string();
break;
case "long":
return r.i64();
break;
default:
throw new Error(`unknown BaseVarType ${type}`);
}
}
function readValues(r, types) {
let strides = r.u8o16();
let values = new Array(types.length * strides).fill(undefined);
for (let stride = 0; stride < strides; stride++) {
for (let i = 0; i < types.length; i++) {
let type = ScriptVarType.forID(types[i]);
if (type === undefined) {
throw new Error(`unknown type ${types[i]}`);
}
values[stride * types.length + i] = readVarType(r, type.baseType);
}
}
return values;
}
export class DBRow extends PerFileLoadable {
id;
constructor(id) {
super();
this.id = id;
}
static index = 2;
static archive = 38;
static gameval = 9;
table = -1;
values = [];
types = [];
static decode(r, id) {
const v = new DBRow(id);
for (let opcode; (opcode = r.u8()) != 0;) {
switch (opcode) {
case 3: {
let len = r.u8();
v.values = new Array(len).fill(undefined);
v.types = new Array(len).fill(undefined);
for (;;) {
let column = r.u8();
if (column == 255) {
break;
}
let types = v.types[column] = readTypes(r);
v.values[column] = readValues(r, types);
}
break;
}
case 4:
v.table = r.leVarInt();
break;
default:
throw new Error(`unknown opcode ${opcode}`);
}
}
return v;
}
}
export class DBTable extends PerFileLoadable {
id;
constructor(id) {
super();
this.id = id;
}
static index = 2;
static archive = 39;
static gameval = 10;
types = [];
defaultValues = [];
static decode(r, id) {
const v = new DBTable(id);
for (let opcode; (opcode = r.u8()) != 0;) {
switch (opcode) {
case 1: {
let len = r.u8();
v.defaultValues = new Array(len).fill(undefined);
v.types = new Array(len).fill(undefined);
for (;;) {
let bits = r.u8();
if (bits == 255) {
break;
}
let column = bits & 0x7F;
let types = v.types[column] = readTypes(r);
if (bits & 0x80) {
v.defaultValues[column] = readValues(r, types);
}
}
break;
}
default:
throw new Error(`unknown opcode ${opcode}`);
}
}
return v;
}
static async loadRowIDs(cache, table) {
let idx = await DBTableIndex.load(cache, table, DBTableIndex.MASTER_COLUMN);
let vs = idx?.values[0];
if (!vs) {
return undefined;
}
return vs.get(0) ?? [];
}
static async loadRows(cache, table) {
let rows = await this.loadRowIDs(cache, table);
if (!rows) {
return undefined;
}
return await Promise.all(rows.map(id => DBRow.load(cache, id)));
}
}
export class DBTableIndex extends Loadable {
id;
column;
constructor(id, column) {
super();
this.id = id;
this.column = column;
}
static index = 21;
static MASTER_COLUMN = -1;
types = [];
values = [];
static async loadData(cache, ...args) {
if (args.length == 1) {
args = DBColumnID.unpack(args[0]);
}
let archive = await cache.getArchive(this.index, args[0]);
let version = await cache.getVersion(this.index);
let data = archive?.getFile(args[1] + 1)?.data;
return data ? new Reader(data, version) : undefined;
}
static decode(r, ...args) {
if (args.length == 1) {
args = DBColumnID.unpack(args[0]);
}
const v = new DBTableIndex(args[0], args[1]);
let len = r.leVarInt();
v.types = new Array(len).fill(undefined);
v.values = new Array(len).fill(undefined);
for (let tupleIndex = 0; tupleIndex < len; tupleIndex++) {
let type = v.types[tupleIndex] = BaseVarType.forOrdinal(r.u8());
let map = v.values[tupleIndex] = new Map();
let numKeys = r.leVarInt();
for (let i = 0; i < numKeys; i++) {
let key = readVarType(r, type);
let numRows = r.leVarInt();
let rows = new Array(numRows).fill(undefined);
map.set(key, rows);
for (let i = 0; i < numRows; i++) {
rows[i] = r.leVarInt();
}
}
}
return v;
}
}