Skip to content

Commit

Permalink
[#78] Update cache2 (#79)
Browse files Browse the repository at this point in the history
  • Loading branch information
allenkinzalow authored Dec 18, 2024
1 parent 4684454 commit 793b2e7
Show file tree
Hide file tree
Showing 9 changed files with 337 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/great-cycles-notice.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@osrs-wiki/cache-mediawiki": minor
---

Update cache2 from latest abextm/cache2 changes
2 changes: 1 addition & 1 deletion src/utils/cache2/Cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export class ArchiveData {
const numChunks = dv.getUint8(dv.byteLength - 1);

let off = dv.byteLength - 1 - numChunks * fileCount * 4;
let doff = data.byteOffset;
let doff = 0;

if (numChunks == 1) {
let size = 0;
Expand Down
24 changes: 22 additions & 2 deletions src/utils/cache2/Reader.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CacheVersion } from "./Cache";
import { ParamID, Params } from "./types";
import { ItemID, KitID, KitOrItem, ParamID, Params } from "./types";

export const cp1252CharMap: string[] = (() => {
const ext = "€?‚ƒ„…†‡ˆ‰Š‹Œ?Ž??‘’“”•–—˜™š›œ?žŸ";
Expand Down Expand Up @@ -177,12 +177,32 @@ export class Reader {

return out;
}
public kit(): KitOrItem {
const id = this.u16();
if (id === 0) {
return undefined;
} else if (id >= 512) {
return { item: (id - 512) as ItemID };
} else if (id >= 256) {
return { kit: (id - 256) as KitID };
} else {
throw new Error(`invalid KitOrItem ${id}`);
}
}
public u32o16(): number {
// rl BigSmart
if (this.view.getUint8(this.offset) & 0x80) {
return this.u16();
return this.i32() & (-1 >>> 1);
} else {
return this.u16();
}
}
public u32o16n(): number {
// rl BigSmart2
if (this.view.getUint8(this.offset) & 0x80) {
return this.i32() & (-1 >>> 1);
} else {
return this.u16n();
}
}
public leVarInt(): number {
Expand Down
207 changes: 207 additions & 0 deletions src/utils/cache2/loaders/Animation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
import { PerFileLoadable } from "../Loadable";
import { Reader } from "../Reader";
import { Typed } from "../reflect";
import {
AnimationID,
AnimMayaID,
AnimRestartMode,
KitOrItem,
PoseID,
PostAnimMoveMode,
PreAnimMoveMode,
SkeletonID,
SoundEffectID,
} from "../types";
export class FrameSound {
constructor(
public id: SoundEffectID,
public weight: number,
public loops: number,
location: number,
public retain: number
) {
this.offsetX = (location >> 16) & 0xff;
this.offsetY = (location >> 8) & 0xff;
this.maxDistance = location & 0xff;
this.isAreaSound = location === 0;
}
public offsetX: number;
public offsetY: number;
public isAreaSound: boolean;
public maxDistance: number;
}
export class Animation extends PerFileLoadable {
constructor(public id: AnimationID) {
super();
}
public declare [Typed.type]: Typed.Any;
public static readonly index = 2;
public static readonly archive = 12;
public frameLengths?: number[] = undefined;
public frameIDs?: [SkeletonID, PoseID][] = undefined;
public chatheadFrameIDs?: [SkeletonID, PoseID][] = undefined;
public animMayaID?: AnimMayaID = undefined;
public animMayaStart = 0;
public animMayaEnd = 0;
public masks?: boolean[] = undefined;
public frameStep = -1;
public interleaveLeave?: number[] = undefined;
public stretches = true;
public priority = 5;
public leftHandItem?: KitOrItem = undefined;
public rightHandItem?: KitOrItem = undefined;
public maxLoops?: number = undefined;
public preAnimMove!: PreAnimMoveMode;
public postAnimMove!: PostAnimMoveMode;
public restartMode = AnimRestartMode.ResetLoops;
public sounds: Map<number, FrameSound[]> = new Map();
public static decode(r: Reader, id: AnimationID): Animation {
const v = new Animation(id);
const [legacyFrameSounds, animMayaID, frameSounds, animMayaBounds] =
r.isAfter({ era: "osrs", indexRevision: 4470 })
? [-1, 13, 14, 15]
: [13, 14, 15, 16];
for (let opcode: number; (opcode = r.u8()) != 0; ) {
switch (opcode) {
case 1: {
const len = r.u16();
v.frameLengths = new Array(len);
v.frameIDs = new Array(len);
for (let i = 0; i < len; i++) {
v.frameLengths[i] = r.u16();
}
for (let i = 0; i < len; i++) {
v.frameIDs[i] = [0 as SkeletonID, r.u16() as PoseID];
}
for (let i = 0; i < len; i++) {
v.frameIDs[i][0] = r.u16() as SkeletonID;
}
break;
}
case 2:
v.frameStep = r.u16();
break;
case 3: {
const len = r.u8();
v.interleaveLeave = new Array(len + 1);
for (let i = 0; i < len; i++) {
v.interleaveLeave[i] = r.u8();
}
v.interleaveLeave[len] = 9999999;
break;
}
case 4:
v.stretches = true;
break;
case 5:
v.priority = r.u8();
break;
case 6:
v.leftHandItem = r.kit();
break;
case 7:
v.rightHandItem = r.kit();
break;
case 8:
v.maxLoops = r.u8();
break;
case 9:
v.preAnimMove = r.u8() as PreAnimMoveMode;
break;
case 10:
v.postAnimMove = r.u8() as PostAnimMoveMode;
break;
case 11:
v.restartMode = r.u8() as AnimRestartMode;
break;
case 12: {
const len = r.u8();
v.chatheadFrameIDs = new Array(len);
for (let i = 0; i < len; i++) {
v.chatheadFrameIDs[i] = [0 as SkeletonID, r.u16() as PoseID];
}
for (let i = 0; i < len; i++) {
v.chatheadFrameIDs[i][0] = r.u16() as SkeletonID;
}
break;
}
case legacyFrameSounds: {
const len = r.u8();
for (let i = 0; i < len; i++) {
readFrameSound(v, r, i);
}
break;
}
case animMayaID:
v.animMayaID = r.i32() as AnimMayaID;
break;
case frameSounds: {
const len = r.u16();
for (let i = 0; i < len; i++) {
const frame = r.u16();
readFrameSound(v, r, frame);
}
break;
}
case animMayaBounds:
v.animMayaStart = r.u16();
v.animMayaEnd = r.u16();
break;
case 17: {
v.masks = new Array(256);
v.masks.fill(false);
const len = r.u8();
for (let i = 0; i < len; i++) {
v.masks[r.u8()] = true;
}
break;
}
default:
throw new Error(`unknown animation opcode ${opcode}`);
}
}
const defaultAnimMode =
v.interleaveLeave === undefined && v.masks == undefined
? PreAnimMoveMode.DelayMove
: PreAnimMoveMode.Merge;
v.preAnimMove ??= defaultAnimMode;
v.postAnimMove ??= defaultAnimMode as any as PostAnimMoveMode;
return v;
}
}
function readFrameSound(v: Animation, r: Reader, frame: number): void {
let sound: FrameSound;
if (r.isAfter({ era: "osrs", indexRevision: 4106 })) {
const id = r.u16();
const weight = r.isAfter({ era: "osrs", indexRevision: 4470 })
? r.u8()
: -1;
const loops = r.u8();
const location = r.u8();
const retain = r.u8();
sound = new FrameSound(
id as SoundEffectID,
weight,
loops,
location,
retain
);
} else {
const bits = r.u24();
sound = new FrameSound(
(bits >> 8) as SoundEffectID,
-1,
(bits >> 4) & 7,
bits & 15,
0
);
}
if (sound.id >= 1 && sound.loops >= 1) {
let list = v.sounds.get(frame);
if (!list) {
list = [];
v.sounds.set(frame, list);
}
list.push(sound);
}
}
65 changes: 65 additions & 0 deletions src/utils/cache2/loaders/HealthBar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { PerFileLoadable } from "../Loadable";
import { Reader } from "../Reader";
import { Typed } from "../reflect";
import { HealthBarID, SpriteID } from "../types";
export class HealthBar extends PerFileLoadable {
constructor(public id: HealthBarID) {
super();
}
public declare [Typed.type]: Typed.Any;
public static readonly index = 2;
public static readonly archive = 33;
public unused1: number | undefined = undefined;
public sortOrder = 255;
public despawnPriority = 255;
public fadeOutAt = -1;
public duration = 70;
public unused2: number | undefined = undefined;
public filledSprite = -1 as SpriteID;
public emptySprite = -1 as SpriteID;
public denominator = 30;
public borderSize = 0;
public static decode(r: Reader, id: HealthBarID): HealthBar {
const v = new HealthBar(id);
for (let opcode: number; (opcode = r.u8()) != 0; ) {
switch (opcode) {
case 1:
v.unused1 = r.u16();
break;
case 2:
v.sortOrder = r.u8();
break;
case 3:
v.despawnPriority = r.u8();
break;
case 4:
v.fadeOutAt = 0;
break;
case 5:
v.duration = r.u16();
break;
case 6:
v.unused2 = r.u8();
break;
case 7:
v.filledSprite = r.u32o16n() as SpriteID;
break;
case 8:
v.emptySprite = r.u32o16n() as SpriteID;
break;
case 11:
v.fadeOutAt = r.u16();
break;
case 14:
v.denominator = r.u8();
break;
case 15:
v.borderSize = r.u8();
break;
default:
throw new Error(`unknown opcode ${opcode}`);
}
}
return v;
}
}
2 changes: 1 addition & 1 deletion src/utils/cache2/loaders/Item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ export class Item extends PerFileLoadable {
break;
}
case 42:
v.shiftClickIndex = r.u8();
v.shiftClickIndex = r.i8();
break;
case 65:
v.isGrandExchangable = true;
Expand Down
4 changes: 4 additions & 0 deletions src/utils/cache2/loaders/Obj.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export class Obj extends PerFileLoadable {
public ambientSoundChangeTicksMax = 0;
public randomizeAnimationStart = true;
public blockingMask: undefined | number = undefined;
public deferAnimChange = false;
public params = new Params();

public static decode(r: Reader, id: ObjID): Obj {
Expand Down Expand Up @@ -242,6 +243,9 @@ export class Obj extends PerFileLoadable {
case 89:
v.randomizeAnimationStart = false;
break;
case 90:
v.deferAnimChange = true;
break;
case 92: {
v.varbit = <VarbitID>r.u16n();
v.varp = <VarPID>r.u16n();
Expand Down
2 changes: 2 additions & 0 deletions src/utils/cache2/loaders/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
export * from "./Animation";
export * from "./Area";
export * from "./DBRow";
export * from "./Enum";
export * from "./HealthBar";
export * from "./Hitsplat";
export * from "./Item";
export * from "./NPC";
Expand Down
Loading

0 comments on commit 793b2e7

Please sign in to comment.