mirror of
https://github.com/djhackersdev/minime.git
synced 2026-04-24 07:26:53 -05:00
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.
This commit is contained in:
parent
efcc1caa76
commit
03d0e87b55
|
|
@ -1,6 +1,7 @@
|
|||
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";
|
||||
|
|
@ -9,10 +10,10 @@ saveProfile2.msgCode = 0x0068;
|
|||
saveProfile2.msgLen = 0x0940;
|
||||
|
||||
export function saveProfile2(buf: Buffer): SaveProfileRequest {
|
||||
const storyRows = new Array();
|
||||
const storyRows = new Map<number, StoryRow>();
|
||||
|
||||
for (let i = 0; i < 9; i++) {
|
||||
const cells = new Array();
|
||||
const cells = new Map<number, StoryCell>();
|
||||
const rowOffset = 0x01a8 + i * 0x3c;
|
||||
|
||||
for (let j = 0; j < 9; j++) {
|
||||
|
|
@ -20,12 +21,12 @@ export function saveProfile2(buf: Buffer): SaveProfileRequest {
|
|||
const b = buf.readUInt16LE(rowOffset + 0x28 + j * 2);
|
||||
const cell = { a, b };
|
||||
|
||||
cells.push(cell);
|
||||
cells.set(j, cell);
|
||||
}
|
||||
|
||||
const row = { cells };
|
||||
|
||||
storyRows.push(row);
|
||||
storyRows.set(i, row);
|
||||
}
|
||||
|
||||
const coursePlays = new Map<CourseNo, number>();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
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";
|
||||
|
|
@ -9,12 +10,12 @@ saveProfile3.msgCode = 0x0138;
|
|||
saveProfile3.msgLen = 0x0a70;
|
||||
|
||||
export function saveProfile3(buf: Buffer): SaveProfileRequest {
|
||||
const storyRows = new Array();
|
||||
const storyRows = new Map<number, StoryRow>();
|
||||
|
||||
// Story layout has changed somewhat...
|
||||
|
||||
for (let i = 0; i < 27; i++) {
|
||||
const cells = new Array();
|
||||
const cells = new Map<number, StoryCell>();
|
||||
const rowOffset = 0x01ac + i * 0x18;
|
||||
|
||||
for (let j = 0; j < 9; j++) {
|
||||
|
|
@ -22,12 +23,12 @@ export function saveProfile3(buf: Buffer): SaveProfileRequest {
|
|||
const b = buf.readUInt8(rowOffset + 0x09 + j);
|
||||
const cell = { a, b };
|
||||
|
||||
cells.push(cell);
|
||||
cells.set(j, cell);
|
||||
}
|
||||
|
||||
const row = { cells };
|
||||
|
||||
storyRows.push(row);
|
||||
storyRows.set(i, row);
|
||||
}
|
||||
|
||||
const coursePlays = new Map<CourseNo, number>();
|
||||
|
|
|
|||
|
|
@ -37,14 +37,22 @@ export function loadProfile2(res: LoadProfileResponse) {
|
|||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < 9 && i < res.story.rows.length; i++) {
|
||||
const row = res.story.rows[i];
|
||||
for (let i = 0; i < 9; i++) {
|
||||
const row = res.story.rows.get(i);
|
||||
const rowOffset = 0x0228 + i * 0x26;
|
||||
|
||||
for (let j = 0; j < 9 && j < row.cells.length; j++) {
|
||||
const cell = row.cells[j];
|
||||
if (row === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (let j = 0; j < 9; j++) {
|
||||
const cell = row.cells.get(j);
|
||||
const cellOffset = rowOffset + j * 4;
|
||||
|
||||
if (cell === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
buf.writeUInt16LE(cell.a, cellOffset + 0);
|
||||
buf.writeUInt16LE(cell.b, cellOffset + 2);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,14 +37,22 @@ export function loadProfile3(res: LoadProfileResponse) {
|
|||
// space for story cells, and 27 rows * 19 bytes per row = 513 bytes, which
|
||||
// is the max that will fit (the final byte of each row is unused).
|
||||
|
||||
for (let i = 0; i < 27 && i < res.story.rows.length; i++) {
|
||||
const row = res.story.rows[i];
|
||||
for (let i = 0; i < 27; i++) {
|
||||
const row = res.story.rows.get(i);
|
||||
const rowOffset = 0x0256 + i * 0x13;
|
||||
|
||||
for (let j = 0; j < 9 && j < row.cells.length; j++) {
|
||||
const cell = row.cells[j];
|
||||
if (row === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (let j = 0; j < 9; j++) {
|
||||
const cell = row.cells.get(j);
|
||||
const cellOffset = rowOffset + j * 2;
|
||||
|
||||
if (cell === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
buf.writeUInt8(cell.a, cellOffset + 0);
|
||||
buf.writeUInt8(cell.b, cellOffset + 1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { MissionState } from "../model/mission";
|
||||
import { Profile } from "../model/profile";
|
||||
import { Settings } from "../model/settings";
|
||||
import { Story } from "../model/story";
|
||||
import { Story, StoryRow } from "../model/story";
|
||||
import { Unlocks } from "../model/unlocks";
|
||||
import { CreateProfileRequest } from "../request/createProfile";
|
||||
import { CreateProfileResponse } from "../response/createProfile";
|
||||
|
|
@ -35,7 +35,11 @@ export async function createProfile(
|
|||
paperCup: 0,
|
||||
gauges: 5,
|
||||
};
|
||||
const story: Story = { x: 0, y: 0, rows: [] };
|
||||
const story: Story = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
rows: new Map<number, StoryRow>(),
|
||||
};
|
||||
const unlocks: Unlocks = {
|
||||
auras: 1,
|
||||
cup: 0,
|
||||
|
|
|
|||
|
|
@ -4,11 +4,11 @@ export interface StoryCell {
|
|||
}
|
||||
|
||||
export interface StoryRow {
|
||||
cells: StoryCell[];
|
||||
cells: Map<number, StoryCell>;
|
||||
}
|
||||
|
||||
export interface Story {
|
||||
x: number;
|
||||
y: number;
|
||||
rows: StoryRow[];
|
||||
rows: Map<number, StoryRow>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,21 @@ import { FacetRepository } from "../repo";
|
|||
import { Id } from "../../../model";
|
||||
import { Transaction } from "../../../sql";
|
||||
|
||||
function cellChanged(
|
||||
lhs: StoryCell | undefined,
|
||||
rhs: StoryCell | undefined
|
||||
): boolean {
|
||||
if (!lhs) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!rhs) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return lhs.a !== rhs.a || lhs.b !== rhs.b;
|
||||
}
|
||||
|
||||
export class SqlStoryRepository implements FacetRepository<Story> {
|
||||
constructor(private readonly _txn: Transaction) {}
|
||||
|
||||
|
|
@ -19,22 +34,12 @@ export class SqlStoryRepository implements FacetRepository<Story> {
|
|||
|
||||
// Must succeed even if nonexistent (required by save method below)
|
||||
|
||||
const result = {
|
||||
const result: Story = {
|
||||
x: header !== undefined ? parseInt(header.x!) : 0,
|
||||
y: header !== undefined ? parseInt(header.y!) : 0,
|
||||
rows: new Array<StoryRow>(),
|
||||
rows: new Map<number, StoryRow>(),
|
||||
};
|
||||
|
||||
for (let i = 0; i < 27; i++) {
|
||||
const row: StoryRow = { cells: new Array<StoryCell>() };
|
||||
|
||||
for (let j = 0; j < 9; j++) {
|
||||
row.cells.push({ a: 0, b: 0 });
|
||||
}
|
||||
|
||||
result.rows.push(row);
|
||||
}
|
||||
|
||||
const loadCellSql = sql
|
||||
.select("sc.*")
|
||||
.from("idz_story_cell_state sc")
|
||||
|
|
@ -45,7 +50,23 @@ export class SqlStoryRepository implements FacetRepository<Story> {
|
|||
for (const row of rows) {
|
||||
const rowNo = parseInt(row.row_no!);
|
||||
const colNo = parseInt(row.col_no!);
|
||||
const cell = result.rows[rowNo].cells[colNo];
|
||||
|
||||
if (!result.rows.has(rowNo)) {
|
||||
result.rows.set(rowNo, {
|
||||
cells: new Map<number, StoryCell>(),
|
||||
});
|
||||
}
|
||||
|
||||
const gridRow = result.rows.get(rowNo)!;
|
||||
|
||||
if (gridRow.cells.has(colNo)) {
|
||||
gridRow.cells.set(colNo, {
|
||||
a: 0,
|
||||
b: 0,
|
||||
});
|
||||
}
|
||||
|
||||
const cell = gridRow.cells.get(colNo)!;
|
||||
|
||||
cell.a = parseInt(row.a!);
|
||||
cell.b = parseInt(row.b!);
|
||||
|
|
@ -68,15 +89,15 @@ export class SqlStoryRepository implements FacetRepository<Story> {
|
|||
|
||||
await this._txn.modify(headSql);
|
||||
|
||||
for (let i = 0; i < story.rows.length; i++) {
|
||||
const exRow = existing.rows[i];
|
||||
const row = story.rows[i];
|
||||
for (const i of story.rows.keys()) {
|
||||
const exRow = existing.rows.get(i);
|
||||
const row = story.rows.get(i)!;
|
||||
|
||||
for (let j = 0; j < row.cells.length; j++) {
|
||||
const exCell = exRow.cells[j];
|
||||
const cell = row.cells[j];
|
||||
for (const j of row.cells.keys()) {
|
||||
const exCell = exRow !== undefined ? exRow.cells.get(j) : undefined;
|
||||
const cell = row.cells.get(j)!;
|
||||
|
||||
if (cell.a === exCell.a && cell.b === exCell.b) {
|
||||
if (!cellChanged(cell, exCell)) {
|
||||
continue; // Most if not all cells are unchanged on profile save.
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user