initial profile save wire-up

This commit is contained in:
Tau
2019-04-07 20:01:34 -04:00
parent 9bdc840019
commit c79c1b870d
18 changed files with 145 additions and 8 deletions

View File

@@ -16,6 +16,7 @@ import { loadTeam } from "./loadTeam";
import { loadTeamRanking, loadTeamRanking2 } from "./loadTeamRanking";
import { lockGarage } from "./lockGarage";
import { lockProfile } from "./lockProfile";
import { msg00AD } from "./msg00AD";
import { saveExpedition } from "./saveExpedition";
import { saveGarage } from "./saveGarage";
import { saveProfile } from "./saveProfile";
@@ -56,6 +57,7 @@ const funcList: ReaderFn[] = [
loadTopTen,
lockGarage,
lockProfile,
msg00AD,
saveExpedition,
saveGarage,
saveProfile,

View File

@@ -0,0 +1,9 @@
import { RequestCode } from "./_defs";
import { Message00AD } from "../request/msg00AD";
msg00AD.msgCode = 0x00ad as RequestCode;
msg00AD.msgLen = 0x061c;
export function msg00AD(buf: Buffer): Message00AD {
return { type: "msg_00AD_req" };
}

View File

@@ -1,12 +1,44 @@
import { RequestCode } from "./_defs";
import { Id, TitleCode } from "../model/base";
import { Profile } from "../model/profile";
import { SaveProfileRequest } from "../request/saveProfile";
import { bitmap } from "./_bitmap";
saveProfile.msgCode = 0x0068 as RequestCode;
saveProfile.msgLen = 0x0940;
export function saveProfile(buf: Buffer): SaveProfileRequest {
const storyRows = new Array();
for (let i = 0; i < 9; i++) {
const cells = new Array();
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.push(cell);
}
const row = { cells };
storyRows.push(row);
}
return {
type: "save_profile_req",
// mega TODO
profileId: buf.readUInt32LE(0x0004) as Id<Profile>,
lv: buf.readUInt16LE(0x0026),
exp: buf.readUInt32LE(0x0028),
fame: buf.readUInt32LE(0x0468),
dpoint: buf.readUInt32LE(0x0464),
titles: bitmap(buf.slice(0x0042, 0x00f6)) as TitleCode[],
story: {
x: buf.readUInt16LE(0x06fc),
y: buf.readUInt8(0x06e0),
rows: storyRows,
},
};
}

View File

@@ -6,9 +6,6 @@ import { chara } from "./_chara";
import { LoadProfileResponse2 } from "../response/loadProfile2";
export function loadProfile2(res: LoadProfileResponse2) {
// Story stuff
//buf.writeUInt32LE(0x1ff, 0x0228);
const settingsPack =
((res.settings.forceQuitEn ? 1 : 0) << 0) |
(res.settings.steeringForce << 1) |
@@ -21,6 +18,24 @@ export function loadProfile2(res: LoadProfileResponse2) {
const buf = Buffer.alloc(0x0d30);
//buf.writeUInt16LE(0x0001, 0x06bc); // story_X
//buf.writeUInt8(0x00, 0x0670); // story_Y
//buf.writeUInt16LE(0x0001, 0x0228 + 0); // records[0].pairs[0].a
//buf.writeUInt16LE(0x0003, 0x0228 + 2); // records[0].pairs[0].b
for (let i = 0; i < 9 && i < res.story.rows.length; i++) {
const row = res.story.rows[i];
const rowOffset = 0x0228 + i * 0x26;
for (let j = 0; j < 9 && j < row.cells.length; j++) {
const cell = row.cells[j];
const cellOffset = rowOffset + j * 4;
buf.writeUInt16LE(cell.a, cellOffset + 0);
buf.writeUInt16LE(cell.b, cellOffset + 2);
}
}
buf.writeInt16LE(0x0065, 0x0000);
buf.writeInt32LE(res.profileId, 0x03b8);
buf.writeUInt16LE(res.settings.bgMusic, 0x03c8);
@@ -29,6 +44,8 @@ export function loadProfile2(res: LoadProfileResponse2) {
buf.writeInt32LE(res.dpoint, 0x03e8);
buf.writeInt32LE(res.fame, 0x0404);
iconv.encode(res.name + "\0", "shift_jis").copy(buf, 0x03ee);
buf.writeUInt16LE(res.story.x, 0x06bc);
buf.writeUInt8(res.story.y, 0x0670);
chara(res.chara).copy(buf, 0x070c);
bitmap(res.titles, 0xb4).copy(buf, 0x720);
buf.writeInt32LE(res.teamId || 0, 0x07e0);

View File

@@ -1,5 +1,7 @@
import { Id } from "../model/base";
import { Profile } from "../model/profile";
import { Settings } from "../model/settings";
import { Story } from "../model/story";
import { Team } from "../model/team";
import { CreateProfileRequest } from "../request/createProfile";
import { GenericResponse } from "../response/generic";
@@ -14,11 +16,12 @@ export async function createProfile(
teamId: 2 as Id<Team>,
name: req.name,
lv: 1,
exp: 0,
fame: 0,
dpoint: 0,
};
const settings = {
const settings: Settings = {
bgMusic: 0,
forceQuitEn: false,
steeringForce: 4,
@@ -30,6 +33,8 @@ export async function createProfile(
taResultSkip: false,
};
const story: Story = { x: 0, y: 0, rows: [] };
await Promise.all([
w.profile().save(profile.id, profile),
w.chara().save(profile.id, req.chara),

View File

@@ -14,6 +14,7 @@ import { loadTeamRanking } from "./loadTeamRanking";
import { loadTopTen } from "./loadTopTen";
import { lockGarage } from "./lockGarage";
import { lockProfile } from "./lockProfile";
import { msg00AD } from "./msg00AD";
import { saveExpedition } from "./saveExpedition";
import { saveGarage } from "./saveGarage";
import { saveProfile } from "./saveProfile";
@@ -83,6 +84,9 @@ export async function dispatch(w: World, req: Request): Promise<Response> {
case "load_team_ranking_req":
return loadTeamRanking(w, req);
case "msg_00AD_req":
return msg00AD(w, req);
case "save_expedition_req":
return saveExpedition(w, req);

View File

@@ -6,11 +6,15 @@ export async function loadProfile(
w: World,
req: LoadProfileRequest
): Promise<LoadProfileResponse2> {
// Promise.all would be messy here, who cares anyway this isn't supposed to
// be a high-performance server.
const profile = await w.profile().loadByAimeId(req.aimeId);
const settings = await w.settings().load(profile.id);
const chara = await w.chara().load(profile.id);
const titles = await w.titles().load(profile.id);
const car = await w.car().load(profile.id);
const story = await w.story().load(profile.id);
return {
type: "load_profile_v2_res",
@@ -24,5 +28,6 @@ export async function loadProfile(
chara,
titles,
car,
story,
};
}

View File

@@ -0,0 +1,7 @@
import { Message00AD } from "../request/msg00AD";
import { GenericResponse } from "../response/generic";
import { World } from "../world";
export function msg00AD(w: World, req: Message00AD): GenericResponse {
return { type: "generic_res" };
}

View File

@@ -2,10 +2,24 @@ import { SaveProfileRequest } from "../request/saveProfile";
import { GenericResponse } from "../response/generic";
import { World } from "../world";
export function saveProfile(
export async function saveProfile(
w: World,
req: SaveProfileRequest
): GenericResponse {
): Promise<GenericResponse> {
const profile = await w.profile().load(req.profileId);
await Promise.all([
w.profile().save(req.profileId, {
...profile,
lv: req.lv,
exp: req.exp,
fame: req.fame,
dpoint: req.dpoint,
}),
w.story().save(req.profileId, req.story),
w.titles().save(req.profileId, req.titles),
]);
return {
type: "generic_res",
status: 1,

View File

@@ -3,4 +3,5 @@ export { Car } from "./car";
export { Chara } from "./chara";
export { Profile } from "./profile";
export { Settings } from "./settings";
export { Story } from "./story";
export { Team } from "./team";

View File

@@ -6,6 +6,7 @@ export interface Profile {
teamId?: Id<Team>;
name: string;
lv: number;
exp: number;
fame: number;
dpoint: number;
}

14
src/idz/model/story.ts Normal file
View File

@@ -0,0 +1,14 @@
export interface StoryCell {
a: number;
b: number;
}
export interface StoryRow {
cells: StoryCell[];
}
export interface Story {
x: number;
y: number;
rows: StoryRow[];
}

View File

@@ -15,6 +15,7 @@ import { LoadTeamRankingRequest } from "./loadTeamRanking";
import { LoadTopTenRequest } from "./loadTopTen";
import { LockAccountRequest } from "./lockProfile";
import { LockGarageRequest } from "./lockGarage";
import { Message00AD } from "./msg00AD";
import { SaveExpeditionRequest } from "./saveExpedition";
import { SaveGarageRequest } from "./saveGarage";
import { SaveProfileRequest } from "./saveProfile";
@@ -46,6 +47,7 @@ export type Request =
| LoadTopTenRequest
| LockAccountRequest
| LockGarageRequest
| Message00AD
| SaveExpeditionRequest
| SaveGarageRequest
| SaveProfileRequest

View File

@@ -0,0 +1,3 @@
export interface Message00AD {
type: "msg_00AD_req";
}

View File

@@ -1,4 +1,14 @@
import { Id, TitleCode } from "../model/base";
import { Profile } from "../model/profile";
import { Story } from "../model/story";
export interface SaveProfileRequest {
type: "save_profile_req";
// giga TODO
profileId: Id<Profile>;
lv: number;
exp: number;
fame: number;
dpoint: number;
titles: TitleCode[];
story: Story;
}

View File

@@ -3,6 +3,7 @@ import { Car } from "../model/car";
import { Chara } from "../model/chara";
import { Profile } from "../model/profile";
import { Settings } from "../model/settings";
import { Story } from "../model/story";
export interface LoadProfileResponse2 {
type: "load_profile_v2_res";
@@ -16,5 +17,6 @@ export interface LoadProfileResponse2 {
chara: Chara;
titles: number[];
car: Car;
story: Story;
// giga TODO
}

View File

@@ -25,5 +25,7 @@ export interface World {
settings(): Repository<Model.Settings, Model.Profile>;
story(): Repository<Model.Story, Model.Profile>;
titles(): Repository<Model.TitleCode[], Model.Profile>;
}

View File

@@ -43,6 +43,13 @@ class WorldImpl implements World {
);
}
story() {
return new SingletonJsonRepo<Model.Story, Model.Profile>(
this._root,
"story"
);
}
titles() {
return new SingletonTextRepo<Model.TitleCode[], Model.Profile>(
this._root,