UNPKG

@abextm/cache2

Version:

Utilities for reading OSRS "caches"

196 lines (195 loc) 4.92 kB
import { CacheVersion } from "./Cache.js"; import { Params } from "./types.js"; export const cp1252CharMap = (() => { const ext = "€?‚ƒ„…†‡ˆ‰Š‹Œ?Ž??‘’“”•–—˜™š›œ?žŸ"; let out = new Array(256); for (let i = 0; i < out.length; i++) { let v; let ei = i - 128; if (ei > 0 && ei < ext.length) { v = ext.charAt(ei); } else { v = String.fromCodePoint(i); } out[i] = v; } return out; })(); export class Reader { version; view; offset = 0; get length() { return this.view.byteLength; } get remaining() { return this.length - this.offset; } set remaining(v) { this.offset = this.length - v; } static makeViewOf(typ, view) { if (view instanceof typ) { return view; } if (view instanceof ArrayBuffer) { return new typ(view, 0, view.byteLength); } return new typ(view.buffer, view.byteOffset, view.byteLength); } constructor(view, version) { this.version = version; this.view = Reader.makeViewOf(DataView, view); } bump(delta) { let r = this.offset; this.offset += delta; return r; } subreader(length) { let start = this.bump(length); return new Reader(new DataView(this.view.buffer, this.view.byteOffset + start, length), this.version); } array(length) { let start = this.bump(length); return new Uint8Array(this.view.buffer, this.view.byteOffset + start, length); } isAfter(ver) { return CacheVersion.isAfter(this.version, ver); } u8() { return this.view.getUint8(this.bump(1)); } u8p1() { return this.u8() + 1; } i8() { return this.view.getInt8(this.bump(1)); } u16() { return this.view.getUint16(this.bump(2)); } u16n() { let v = this.view.getUint16(this.bump(2)); return v == 0xFFFF ? -1 : v; } i16() { return this.view.getInt16(this.bump(2)); } u8o16() { if (this.view.getUint8(this.offset) < 128) { return this.u8(); } else { return this.u16() - 0x8000; } } u8o16m1() { if (this.view.getUint8(this.offset) < 128) { return this.u8() - 1; } else { return this.u16() - 0x8001; } } u24() { let off = this.bump(3); return (this.view.getUint8(off) << 16) | this.view.getUint16(off + 1); } i32() { return this.view.getInt32(this.bump(4)); } s2o4n() { if (this.view.getUint8(this.offset) & 0x80) { return this.i32() & (-1 >>> 1); } else { return this.u16n(); } } i64() { return this.view.getBigInt64(this.bump(8)); } string() { let s = ""; for (let c; (c = this.u8()) != 0;) { s += cp1252CharMap[c]; } return s; } vString() { if (this.u8() != 0) { throw new Error("invalid string"); } return this.string(); } stringNullHidden() { let s = this.string(); if (s == "hidden") { return null; } return s; } params() { let count = this.u8(); let out = new Params(); for (let i = 0; i < count; i++) { let type = this.u8(); let param = this.u24(); switch (type) { case 0: out.set(param, this.i32()); break; case 1: out.set(param, this.string()); break; default: throw new Error(`invalid type in param table ${type}`); } } return out; } kit() { let id = this.u16(); if (id === 0) { return undefined; } else if (id >= 512) { return { item: (id - 512) }; } else if (id >= 256) { return { kit: (id - 256) }; } else { throw new Error(`invalid KitOrItem ${id}`); } } u32o16() { if (this.view.getUint8(this.offset) & 0x80) { return this.i32() & (-1 >>> 1); } else { return this.u16(); } } u32o16n() { if (this.view.getUint8(this.offset) & 0x80) { return this.i32() & (-1 >>> 1); } else { return this.u16n(); } } leVarInt() { let v = 0; let shift = 0; let octet; do { octet = this.u8(); v |= (octet & 127) << shift; shift += 7; } while (octet > 127); return v; } }