diff --git a/src/idz/decoder/index.ts b/src/idz/decoder/index.ts index 5b46647..92586fe 100644 --- a/src/idz/decoder/index.ts +++ b/src/idz/decoder/index.ts @@ -8,6 +8,7 @@ import { discoverProfile } from "./discoverProfile"; import { load2on2 } from "./load2on2"; import { loadConfig } from "./loadConfig"; import { loadConfig2 } from "./loadConfig2"; +import { loadGarage } from "./loadGarage"; import { loadGeneralReward } from "./loadGeneralReward"; import { loadGhost } from "./loadGhost"; import { loadProfile } from "./loadProfile"; @@ -21,6 +22,7 @@ import { lockProfile } from "./lockProfile"; import { msg00AD } from "./msg00AD"; import { saveExpedition } from "./saveExpedition"; import { saveGarage } from "./saveGarage"; +import { saveNewCar } from "./saveNewCar"; import { saveProfile } from "./saveProfile"; import { saveSettings } from "./saveSettings"; import { saveStocker } from "./saveStocker"; @@ -51,6 +53,7 @@ const funcList: ReaderFn[] = [ load2on2, loadConfig, loadConfig2, + loadGarage, loadGeneralReward, loadGhost, loadProfile, @@ -66,6 +69,7 @@ const funcList: ReaderFn[] = [ msg00AD, saveExpedition, saveGarage, + saveNewCar, saveProfile, saveSettings, saveStocker, diff --git a/src/idz/decoder/loadGarage.ts b/src/idz/decoder/loadGarage.ts new file mode 100644 index 0000000..465f489 --- /dev/null +++ b/src/idz/decoder/loadGarage.ts @@ -0,0 +1,16 @@ +import { RequestCode } from "./_defs"; +import { Id } from "../model/base"; +import { Profile } from "../model/profile"; +import { LoadGarageRequest } from "../request/loadGarage"; + +loadGarage.msgCode = 0x0090 as RequestCode; +loadGarage.msgLen = 0x0010; + +export function loadGarage(buf: Buffer): LoadGarageRequest { + return { + type: "load_garage_req", + profileId: buf.readUInt32LE(0x0004) as Id, + fetchOffset: buf.readUInt8(0x0008), + field_000A: buf.readUInt16LE(0x000a), + }; +} diff --git a/src/idz/decoder/saveNewCar.ts b/src/idz/decoder/saveNewCar.ts new file mode 100644 index 0000000..d6cc558 --- /dev/null +++ b/src/idz/decoder/saveNewCar.ts @@ -0,0 +1,18 @@ +import { car } from "./_car"; +import { RequestCode } from "./_defs"; +import { Id } from "../model/base"; +import { Profile } from "../model/profile"; +import { SaveNewCarRequest } from "../request/saveNewCar"; + +saveNewCar.msgCode = 0x0079 as RequestCode; +saveNewCar.msgLen = 0x0090; + +export function saveNewCar(buf: Buffer): SaveNewCarRequest { + return { + type: "save_new_car_req", + profileId: buf.readUInt32LE(0x0004) as Id, + luid: buf.slice(0x0008, buf.indexOf(0, 0x0008)).toString("ascii"), + car: car(buf.slice(0x0020, 0x0080)), + field_0080: buf.readUInt32LE(0x0080), + }; +} diff --git a/src/idz/encoder/index.ts b/src/idz/encoder/index.ts index f3f6daf..97026e7 100644 --- a/src/idz/encoder/index.ts +++ b/src/idz/encoder/index.ts @@ -9,6 +9,7 @@ import { lockProfile } from "./lockProfile"; import { load2on2 } from "./load2on2"; import { loadConfig } from "./loadConfig"; import { loadConfig2 } from "./loadConfig2"; +import { loadGarage } from "./loadGarage"; import { loadGeneralReward } from "./loadGeneralReward"; import { loadGhost } from "./loadGhost"; import { loadProfile } from "./loadProfile"; @@ -20,6 +21,7 @@ import { loadTeamRanking } from "./loadTeamRanking"; import { loadTopTen } from "./loadTopTen"; import { saveExpedition } from "./saveExpedition"; import { saveGarage } from "./saveGarage"; +import { saveNewCar } from "./saveNewCar"; import { saveTimeAttack } from "./saveTimeAttack"; import { saveTopic } from "./saveTopic"; import { unlockProfile } from "./unlockProfile"; @@ -53,6 +55,9 @@ function encode(res: Response): Buffer { case "load_config_v2_res": return loadConfig2(res); + case "load_garage_res": + return loadGarage(res); + case "load_general_reward_res": return loadGeneralReward(res); @@ -92,6 +97,9 @@ function encode(res: Response): Buffer { case "save_garage_res": return saveGarage(res); + case "save_new_car_res": + return saveNewCar(res); + case "save_time_attack_res": return saveTimeAttack(res); diff --git a/src/idz/encoder/loadGarage.ts b/src/idz/encoder/loadGarage.ts new file mode 100644 index 0000000..f3c6de5 --- /dev/null +++ b/src/idz/encoder/loadGarage.ts @@ -0,0 +1,15 @@ +import { car } from "./_car"; +import { LoadGarageResponse } from "../response/loadGarage"; + +export function loadGarage(res: LoadGarageResponse): Buffer { + const buf = Buffer.alloc(0x03d0); + + buf.writeUInt16LE(0x0091, 0x0000); + buf.writeUInt16LE(res.cars.length, 0x0002); + + for (let i = 0; i < res.cars.length; i++) { + car(res.cars[i]).copy(buf, 0x0004 + 0x0060 * i); + } + + return buf; +} diff --git a/src/idz/encoder/loadProfile2.ts b/src/idz/encoder/loadProfile2.ts index 56dbc80..14de54a 100644 --- a/src/idz/encoder/loadProfile2.ts +++ b/src/idz/encoder/loadProfile2.ts @@ -74,6 +74,7 @@ export function loadProfile2(res: LoadProfileResponse2) { buf.writeUInt8(res.settings.gauges, 0x07da); buf.writeUInt32LE(res.teamId || 0xffffffff, 0x07e0); car(res.car).copy(buf, 0x0c5c); + buf.writeUInt32LE(1, 0x0c58); // Cars in garage // [1] Currently unknown, but if this field is zero then the player will have // a "model record" emblem in their profile card. diff --git a/src/idz/encoder/saveNewCar.ts b/src/idz/encoder/saveNewCar.ts new file mode 100644 index 0000000..c8a3f9d --- /dev/null +++ b/src/idz/encoder/saveNewCar.ts @@ -0,0 +1,10 @@ +import { SaveNewCarResponse } from "../response/saveNewCar"; + +export function saveNewCar(res: SaveNewCarResponse): Buffer { + const buf = Buffer.alloc(0x0010); + + buf.writeUInt16LE(0x007a, 0x0000); + buf.writeUInt8(res.status, 0x0002); + + return buf; +} diff --git a/src/idz/handler/index.ts b/src/idz/handler/index.ts index 2dd7379..c985688 100644 --- a/src/idz/handler/index.ts +++ b/src/idz/handler/index.ts @@ -6,6 +6,7 @@ import { discoverProfile } from "./discoverProfile"; import { load2on2 } from "./load2on2"; import { loadConfig } from "./loadConfig"; import { loadConfig2 } from "./loadConfig2"; +import { loadGarage } from "./loadGarage"; import { loadGeneralReward } from "./loadGeneralReward"; import { loadGhost } from "./loadGhost"; import { loadProfile } from "./loadProfile"; @@ -19,6 +20,7 @@ import { lockProfile } from "./lockProfile"; import { msg00AD } from "./msg00AD"; import { saveExpedition } from "./saveExpedition"; import { saveGarage } from "./saveGarage"; +import { saveNewCar } from "./saveNewCar"; import { saveProfile } from "./saveProfile"; import { saveSettings } from "./saveSettings"; import { saveStocker } from "./saveStocker"; @@ -61,6 +63,9 @@ export async function dispatch(w: World, req: Request): Promise { case "discover_profile_req": return discoverProfile(w, req); + case "load_garage_req": + return loadGarage(w, req); + case "load_general_reward_req": return loadGeneralReward(w, req); @@ -103,6 +108,9 @@ export async function dispatch(w: World, req: Request): Promise { case "save_garage_req": return saveGarage(w, req); + case "save_new_car_req": + return saveNewCar(w, req); + case "save_profile_req": return saveProfile(w, req); diff --git a/src/idz/handler/loadGarage.ts b/src/idz/handler/loadGarage.ts new file mode 100644 index 0000000..3829abe --- /dev/null +++ b/src/idz/handler/loadGarage.ts @@ -0,0 +1,12 @@ +import { Car } from "../model"; +import { LoadGarageRequest } from "../request/loadGarage"; +import { LoadGarageResponse } from "../response/loadGarage"; +import { World } from "../world"; +import { loadJson } from "../world/_util"; + +export async function loadGarage( + w: World, + req: LoadGarageRequest +): Promise { + throw new Error("TODO"); +} diff --git a/src/idz/handler/saveNewCar.ts b/src/idz/handler/saveNewCar.ts new file mode 100644 index 0000000..85b6f6b --- /dev/null +++ b/src/idz/handler/saveNewCar.ts @@ -0,0 +1,13 @@ +import { SaveNewCarRequest } from "../request/saveNewCar"; +import { SaveNewCarResponse } from "../response/saveNewCar"; +import { World } from "../world"; + +export function saveNewCar( + w: World, + req: SaveNewCarRequest +): SaveNewCarResponse { + return { + type: "save_new_car_res", + status: 0, + }; +} diff --git a/src/idz/request/index.ts b/src/idz/request/index.ts index 5419934..1984839 100644 --- a/src/idz/request/index.ts +++ b/src/idz/request/index.ts @@ -6,6 +6,7 @@ import { JoinAutoTeamRequest } from "./joinAutoTeam"; import { Load2on2Request } from "./load2on2"; import { LoadConfigRequest } from "./loadConfig"; import { LoadConfigRequest2 } from "./loadConfig2"; +import { LoadGarageRequest } from "./loadGarage"; import { LoadGeneralRewardRequest } from "./loadGeneralReward"; import { LoadGhostRequest } from "./loadGhost"; import { LoadProfileRequest } from "./loadProfile"; @@ -20,6 +21,7 @@ import { LockGarageRequest } from "./lockGarage"; import { Message00AD } from "./msg00AD"; import { SaveExpeditionRequest } from "./saveExpedition"; import { SaveGarageRequest } from "./saveGarage"; +import { SaveNewCarRequest } from "./saveNewCar"; import { SaveProfileRequest } from "./saveProfile"; import { SaveSettingsRequest } from "./saveSettings"; import { SaveStockerRequest } from "./saveStocker"; @@ -42,6 +44,7 @@ export type Request = | Load2on2Request | LoadConfigRequest | LoadConfigRequest2 + | LoadGarageRequest | LoadGeneralRewardRequest | LoadGhostRequest | LoadProfileRequest @@ -56,6 +59,7 @@ export type Request = | Message00AD | SaveExpeditionRequest | SaveGarageRequest + | SaveNewCarRequest | SaveProfileRequest | SaveSettingsRequest | SaveStockerRequest diff --git a/src/idz/request/loadGarage.ts b/src/idz/request/loadGarage.ts new file mode 100644 index 0000000..b69daa5 --- /dev/null +++ b/src/idz/request/loadGarage.ts @@ -0,0 +1,9 @@ +import { Id } from "../model/base"; +import { Profile } from "../model/profile"; + +export interface LoadGarageRequest { + type: "load_garage_req"; + profileId: Id; + fetchOffset: number; + field_000A: number; +} diff --git a/src/idz/request/saveNewCar.ts b/src/idz/request/saveNewCar.ts new file mode 100644 index 0000000..4af34e5 --- /dev/null +++ b/src/idz/request/saveNewCar.ts @@ -0,0 +1,11 @@ +import { Id } from "../model/base"; +import { Car } from "../model/car"; +import { Profile } from "../model/profile"; + +export interface SaveNewCarRequest { + type: "save_new_car_req"; + profileId: Id; + luid: string; + car: Car; + field_0080: number; +} diff --git a/src/idz/response/index.ts b/src/idz/response/index.ts index 836b412..a644b8d 100644 --- a/src/idz/response/index.ts +++ b/src/idz/response/index.ts @@ -6,6 +6,7 @@ import { JoinAutoTeamResponse } from "./joinAutoTeam"; import { Load2on2Response } from "./load2on2"; import { LoadConfigResponse } from "./loadConfig"; import { LoadConfigResponse2 } from "./loadConfig2"; +import { LoadGarageResponse } from "./loadGarage"; import { LoadGeneralRewardResponse } from "./loadGeneralReward"; import { LoadGhostResponse } from "./loadGhost"; import { LoadProfileResponse } from "./loadProfile"; @@ -19,6 +20,7 @@ import { LoadTopTenResponse } from "./loadTopTen"; import { LockProfileResponse } from "./lockProfile"; import { SaveExpeditionResponse } from "./saveExpedition"; import { SaveGarageResponse } from "./saveGarage"; +import { SaveNewCarResponse } from "./saveNewCar"; import { SaveTimeAttackResponse } from "./saveTimeAttack"; import { SaveTopicResponse } from "./saveTopic"; import { UpdateProvisionalStoreRankResponse } from "./updateProvisionalStoreRank"; @@ -34,6 +36,7 @@ export type Response = | Load2on2Response | LoadConfigResponse | LoadConfigResponse2 + | LoadGarageResponse | LoadGeneralRewardResponse | LoadGhostResponse | LoadProfileResponse @@ -50,5 +53,6 @@ export type Response = | UpdateStoryClearNumResponse | SaveExpeditionResponse | SaveGarageResponse + | SaveNewCarResponse | SaveTimeAttackResponse | SaveTopicResponse; diff --git a/src/idz/response/loadGarage.ts b/src/idz/response/loadGarage.ts new file mode 100644 index 0000000..d3ef9d8 --- /dev/null +++ b/src/idz/response/loadGarage.ts @@ -0,0 +1,6 @@ +import { Car } from "../model/car"; + +export interface LoadGarageResponse { + type: "load_garage_res"; + cars: Car[]; // max 10 +} diff --git a/src/idz/response/saveNewCar.ts b/src/idz/response/saveNewCar.ts new file mode 100644 index 0000000..ea3c55f --- /dev/null +++ b/src/idz/response/saveNewCar.ts @@ -0,0 +1,4 @@ +export interface SaveNewCarResponse { + type: "save_new_car_res"; + status: number; +}