diff --git a/src/idz/decoder/createTeam.ts b/src/idz/decoder/createTeam.ts index 7cb68bb..3025aa7 100644 --- a/src/idz/decoder/createTeam.ts +++ b/src/idz/decoder/createTeam.ts @@ -20,6 +20,6 @@ export function createTeam(buf: Buffer): CreateTeamRequest { nameBg: buf.readUInt8(0x0030), field_0032: buf.readUInt16LE(0x0032), prevTeamId: buf.readUInt32LE(0x0034), - field_0038: buf.slice(0x0038, 0x0045), + pcbId: buf.slice(0x0038, buf.indexOf("\0", 0x0038)).toString("ascii"), }; } diff --git a/src/idz/decoder/loadTeam.ts b/src/idz/decoder/loadTeam.ts index e604288..a94cd1b 100644 --- a/src/idz/decoder/loadTeam.ts +++ b/src/idz/decoder/loadTeam.ts @@ -1,13 +1,17 @@ import { RequestCode } from "./_defs"; import { LoadTeamRequest } from "../request/loadTeam"; +import { ExtId } from "../model/base"; +import { Team } from "../model/team"; loadTeam.msgCode = 0x0077 as RequestCode; loadTeam.msgLen = 0x0010; export function loadTeam(buf: Buffer): LoadTeamRequest { + const extId = buf.readUInt32LE(0x0008); + return { type: "load_team_req", aimeId: buf.readUInt32LE(0x0004), - teamId: buf.readUInt32LE(0x0008), + teamExtId: extId !== 0xffffffff ? (extId as ExtId) : undefined, }; } diff --git a/src/idz/encoder/_team.ts b/src/idz/encoder/_team.ts index f050894..4c8c59b 100644 --- a/src/idz/encoder/_team.ts +++ b/src/idz/encoder/_team.ts @@ -1,42 +1,58 @@ import iconv = require("iconv-lite"); + import { JoinAutoTeamResponse } from "../response/joinAutoTeam"; import { LoadTeamResponse } from "../response/loadTeam"; +import { encodeChara } from "./_chara"; export function _team(res: JoinAutoTeamResponse | LoadTeamResponse) { const buf = Buffer.alloc(0x0ca0); - buf.writeUInt32LE(res.team.id, 0x000c); - iconv.encode(res.team.name, "shift_jis").copy(buf, 0x0024); - - for (let i = 0; i < 6; i++) { - const base = 0x011c + i * 0x004c; - const member = res.members[i]; - - if (member === undefined) { - break; - } - - buf.writeInt32LE(1, base + 0x0000); // Presence - iconv.encode(member.name + "\0", "shift_jis").copy(buf, base + 0x0004); - buf.writeInt32LE(member.lv, base + 0x0018); - buf.writeInt32LE(member.monthPoints, base + 0x0024); - } - - // xM - - /* - buf.writeInt16LE(0x00001, 0x0344 + 0x0000); - buf.writeInt8(0x02, 0x0344 + 0x0003); - buf.writeInt32LE(0x00000003, 0x0344 + 0x0004); - iconv.encode("str\0", sjis).copy(buf, 0x0344 + 0x0008); - buf.writeInt32LE(0x00000004, 0x0344 + 0x001c); - */ - if (res.type === "join_auto_team_res") { buf.writeInt16LE(0x007c, 0x0000); } else { buf.writeInt16LE(0x0078, 0x0000); } + const leader = res.members.find(item => item.leader); + + buf.writeUInt32LE(res.team.extId, 0x000c); + iconv.encode(res.team.name, "shift_jis").copy(buf, 0x0024); + buf.writeUInt32LE(res.team.nameBg, 0x00d8); + buf.writeUInt32LE(res.team.nameFx, 0x00dc); + buf.fill(0xff, 0x00e0, 0x00f9); // Bitset: Unlocked BGs probably + buf.fill(0xff, 0x00f9, 0x0101); // Bitset: Unlocked FX probably + buf.writeUInt32LE(leader ? leader.profile.aimeId : 0, 0x0080); + + for (let i = 0; i < 6; i++) { + const base = 0x011c + i * 0x005c; + const member = res.members[i]; + + if (member === undefined) { + break; + } + + const { profile, chara } = member; + const accessTime = (profile.accessTime.getTime() / 1000) | 0; + + buf.writeInt32LE(profile.aimeId, base + 0x0000); + iconv.encode(profile.name + "\0", "shift_jis").copy(buf, base + 0x0004); + buf.writeInt32LE(profile.lv, base + 0x0018); + buf.writeInt32LE(0, base + 0x0024); // Month points, TODO + buf.writeUInt32LE(accessTime, base + 0x0034); + encodeChara(chara).copy(buf, base + 0x0044); + } + + // Team Time Attack: + + /*for (let i = 0; i < 6; i++) { + const base = 0x0344 + 0x20 * i; + + buf.writeInt16LE(0x00001, base + 0x0000); + buf.writeInt8(0x02, base + 0x0003); + buf.writeInt32LE(0x00000003, base + 0x0004); + iconv.encode("str\0", "shift_jis").copy(buf, base + 0x0008); + buf.writeInt32LE(0x00000004, base + 0x001c); + }*/ + return buf; } diff --git a/src/idz/encoder/createTeam.ts b/src/idz/encoder/createTeam.ts index 0f48984..404a8b8 100644 --- a/src/idz/encoder/createTeam.ts +++ b/src/idz/encoder/createTeam.ts @@ -5,7 +5,7 @@ export function createTeam(res: CreateTeamResponse): Buffer { buf.writeUInt16LE(0x0072, 0x0000); buf.writeUInt32LE(res.status, 0x0004); - buf.writeUInt32LE(res.teamId, 0x0008); + buf.writeUInt32LE(res.teamExtId, 0x0008); return buf; } diff --git a/src/idz/handler/_team.ts b/src/idz/handler/_team.ts index acd7fec..9e5797d 100644 --- a/src/idz/handler/_team.ts +++ b/src/idz/handler/_team.ts @@ -6,15 +6,23 @@ import { JoinAutoTeamResponse } from "../response/joinAutoTeam"; import { LoadTeamResponse } from "../response/loadTeam"; import { Repositories } from "../repo"; +// Even if a profile does not belong to a team, a team must still be loaded +// (and then ignored by the client). + +const dummy: Team = { + extId: 0 as ExtId, + name: "", + nameBg: 0, + nameFx: 0, + registerTime: new Date(0), +}; + export function _team( w: Repositories, req: JoinAutoTeamRequest | LoadTeamRequest ): JoinAutoTeamResponse | LoadTeamResponse { const bits = { - team: { - id: 2 as ExtId, - name: process.env.TEAM_NAME || "", - }, + team: dummy, members: [], }; diff --git a/src/idz/handler/createTeam.ts b/src/idz/handler/createTeam.ts index 13b5e73..1c19b3d 100644 --- a/src/idz/handler/createTeam.ts +++ b/src/idz/handler/createTeam.ts @@ -11,6 +11,6 @@ export function createTeam( return { type: "create_team_res", status: 0, - teamId: 3 as ExtId, + teamExtId: 3 as ExtId, }; } diff --git a/src/idz/model/index.ts b/src/idz/model/index.ts index 9d584d4..5b8b7ce 100644 --- a/src/idz/model/index.ts +++ b/src/idz/model/index.ts @@ -5,7 +5,7 @@ export { MissionState, MissionGrid } from "./mission"; export { Profile } from "./profile"; export { Settings } from "./settings"; export { Story } from "./story"; -export { Team } from "./team"; +export { Team, TeamMember } from "./team"; export { Tickets } from "./tickets"; export { TimeAttackScore } from "./timeAttack"; export { Unlocks } from "./unlocks"; diff --git a/src/idz/model/team.ts b/src/idz/model/team.ts index d55e6a6..bd7368b 100644 --- a/src/idz/model/team.ts +++ b/src/idz/model/team.ts @@ -1,6 +1,18 @@ import { ExtId } from "./base"; +import { Chara } from "./chara"; +import { Profile } from "./profile"; export interface Team { - id: ExtId; + extId: ExtId; name: string; + nameBg: number; + nameFx: number; + registerTime: Date; +} + +export interface TeamMember { + profile: Profile; + chara: Chara; + leader: boolean; + joinTime: Date; } diff --git a/src/idz/request/createTeam.ts b/src/idz/request/createTeam.ts index edd292e..8bca943 100644 --- a/src/idz/request/createTeam.ts +++ b/src/idz/request/createTeam.ts @@ -9,5 +9,5 @@ export interface CreateTeamRequest { nameBg: number; // u8 field_0032: number; // u16 prevTeamId: number; // u32 - field_0038: Buffer; // len 0x0D ..? weird length + pcbId: string; } diff --git a/src/idz/request/loadTeam.ts b/src/idz/request/loadTeam.ts index 0c5729b..034ae70 100644 --- a/src/idz/request/loadTeam.ts +++ b/src/idz/request/loadTeam.ts @@ -1,5 +1,8 @@ +import { ExtId } from "../model/base"; +import { Team } from "../model/team"; + export interface LoadTeamRequest { type: "load_team_req"; aimeId: number; - teamId: number; + teamExtId?: ExtId; } diff --git a/src/idz/response/_team.ts b/src/idz/response/_team.ts index 7d9d004..57c2be8 100644 --- a/src/idz/response/_team.ts +++ b/src/idz/response/_team.ts @@ -1,10 +1,4 @@ -import { Team } from "../model/team"; - -export interface TeamMember { - name: string; - lv: number; - monthPoints: number; -} +import { Team, TeamMember } from "../model/team"; export interface BaseTeamResponse { team: Team; diff --git a/src/idz/response/createTeam.ts b/src/idz/response/createTeam.ts index b164732..9c84696 100644 --- a/src/idz/response/createTeam.ts +++ b/src/idz/response/createTeam.ts @@ -4,5 +4,5 @@ import { Team } from "../model/team"; export interface CreateTeamResponse { type: "create_team_res"; status: number; // 0 is success, 1 is failure - teamId: ExtId; + teamExtId: ExtId; }