Files
djhackersdev_minime/src/idz/userdb/decoder/saveProfile2.ts
T
Tau 435634a9b2 idz: Push story geometry down into codecs
Sparsify the data model returned from the repository layer. Different
versions of the game can have drastically different dimensions for the
story data grid, so handling those dimensions is best done in the
encoders themselves.
2021-02-03 23:43:40 +00:00

101 lines
2.8 KiB
TypeScript

import { car } from "./_car";
import { mission } from "./_mission";
import { BackgroundCode, CourseNo, TitleCode } from "../model/base";
import { StoryCell, StoryRow } from "../model/story";
import { SaveProfileRequest } from "../request/saveProfile";
import { bitmap } from "./_bitmap";
import { AimeId } from "../../../model";
saveProfile2.msgCode = 0x0068;
saveProfile2.msgLen = 0x0940;
export function saveProfile2(buf: Buffer): SaveProfileRequest {
const storyRows = new Map<number, StoryRow>();
for (let i = 0; i < 9; i++) {
const cells = new Map<number, StoryCell>();
const rowOffset = 0x01a8 + i * 0x3c;
for (let j = 0; j < 9; j++) {
const a = buf.readUInt32LE(rowOffset + 0x04 + j * 4);
const b = buf.readUInt16LE(rowOffset + 0x28 + j * 2);
const cell = { a, b };
cells.set(j, cell);
}
const row = { cells };
storyRows.set(i, row);
}
const coursePlays = new Map<CourseNo, number>();
for (let i = 0; i < 16; i++) {
coursePlays.set(i as CourseNo, buf.readUInt16LE(0x04c0 + 2 * i));
}
const freeCar = {
validFrom: buf.readUInt32LE(0x0138),
};
const freeContinue = {
validFrom: buf.readUInt32LE(0x0038),
validTo: buf.readUInt32LE(0x003c),
};
return {
type: "save_profile_req",
aimeId: buf.readUInt32LE(0x0004) as AimeId,
version: 1,
lv: buf.readUInt16LE(0x0026),
exp: buf.readUInt32LE(0x0028),
fame: buf.readUInt32LE(0x0468),
dpoint: buf.readUInt32LE(0x0464),
mileage: buf.readUInt32LE(0x0008),
title: buf.readUInt16LE(0x0040) as TitleCode,
titles: bitmap(buf.slice(0x0042, 0x00f6)),
background: buf.readUInt8(0x0750) as BackgroundCode,
coursePlays,
missions: {
team: mission(buf.slice(0x03c4, 0x03e6)),
solo: mission(buf.slice(0x0724, 0x0746)),
},
car: car(buf.slice(0x0834, 0x0894)),
story: {
x: buf.readUInt16LE(0x06fc),
y: buf.readUInt8(0x06e0),
rows: storyRows,
},
unlocks: {
auras: buf.readUInt16LE(0x010c),
cup: buf.readUInt8(0x0110),
gauges: buf.readUInt16LE(0x0114),
music: buf.readUInt16LE(0x0140),
lastMileageReward: buf.readUInt32LE(0x013c),
},
tickets: {
freeCar:
freeCar.validFrom !== 0
? {
validFrom: new Date(freeCar.validFrom * 1000),
}
: undefined,
freeContinue:
freeContinue.validFrom !== 0 && freeContinue.validTo !== 0
? {
validFrom: new Date(freeContinue.validFrom * 1000),
validTo: new Date(freeContinue.validTo * 1000),
}
: undefined,
},
settings: {
music: buf.readUInt16LE(0x045a),
pack: buf.readUInt32LE(0x0034),
aura: buf.readUInt8(0x002c),
paperCup: buf.readUInt8(0x00f6),
gauges: buf.readUInt8(0x00f7),
},
};
}