210 lines
5.1 KiB
TypeScript
210 lines
5.1 KiB
TypeScript
/**
|
|
* D2GS S->C Party, Roster, and Player Relation Packet Decoders (1.13c).
|
|
* Verified against D2Client.dll:
|
|
* - 0x5B PlayerInGame (variable u16@1, 0x6fb5d8f0)
|
|
* - 0x5C PlayerLeftGame (5B, 0x6fb5d8e0)
|
|
* - 0x65 PlayerKillCount (7B, 0x6fb5d890)
|
|
* - 0x66 PartyMemberUpdate (7B, 0x6fb5c040)
|
|
* - 0x74 PlayerCorpseAssign (10B, 0x6fb5def0)
|
|
* - 0x75 PlayerPartyInfo (13B, 0x6fb5d870)
|
|
* - 0x7F PartyMemberState (10B, 0x6fb5d820)
|
|
* - 0x8B PlayerPartyRelationship (6B, 0x6fb5d800)
|
|
* - 0x8C RelationshipUpdate (11B, 0x6fb5d7b0)
|
|
* - 0x8D AssignPlayerToParty (7B, 0x6fb5d780)
|
|
* - 0x8E CorpseAssign (10B, 0x6fb5d130)
|
|
* - 0x90 PartyMemberMapPos (13B, 0x6fb5d220)
|
|
*/
|
|
|
|
import { ByteReader } from '../../core/byte-reader.ts'
|
|
import type { ServerEvent } from '../../domain/server-event.ts'
|
|
|
|
/** 0x5B PlayerInGame (variable u16@1 = 36B, D2Client.dll 0x6fb5d8f0) */
|
|
export function decode0x5BPlayerInGame(pkt: Uint8Array): ServerEvent {
|
|
const r = new ByteReader(pkt)
|
|
r.u8() // 0x5B
|
|
r.u16LE() // packetLen
|
|
const unitId = r.u32LE()
|
|
const charClass = r.u8()
|
|
const charName = r.fixedCString(16)
|
|
const charLevel = r.u16LE()
|
|
const partyId = r.u16LE()
|
|
return {
|
|
type: 'Party',
|
|
kind: 'roster',
|
|
unitId,
|
|
charClass,
|
|
charName,
|
|
charLevel,
|
|
partyId,
|
|
}
|
|
}
|
|
|
|
/** 0x5C PlayerLeftGame (5B, D2Client.dll 0x6fb5d8e0) */
|
|
export function decode0x5CPlayerLeftGame(pkt: Uint8Array): ServerEvent {
|
|
const r = new ByteReader(pkt)
|
|
r.u8() // 0x5C
|
|
const unitId = r.u32LE()
|
|
return {
|
|
type: 'Party',
|
|
kind: 'roster',
|
|
unitId,
|
|
partyId: 0xffff,
|
|
}
|
|
}
|
|
|
|
/** 0x65 PlayerKillCount (7B, D2Client.dll 0x6fb5d890) */
|
|
export function decode0x65PlayerKillCount(pkt: Uint8Array): ServerEvent {
|
|
const r = new ByteReader(pkt)
|
|
r.u8() // 0x65
|
|
const unitId = r.u32LE()
|
|
const count = r.u16LE()
|
|
return {
|
|
type: 'Party',
|
|
kind: 'relation',
|
|
unitId,
|
|
relation: count,
|
|
}
|
|
}
|
|
|
|
/** 0x66 PartyMemberUpdate (7B, D2Client.dll 0x6fb5c040) */
|
|
export function decode0x66PartyMemberUpdate(pkt: Uint8Array): ServerEvent {
|
|
const r = new ByteReader(pkt)
|
|
r.u8() // 0x66
|
|
const unitId = r.u32LE()
|
|
const lifePct = r.u16LE()
|
|
return {
|
|
type: 'Party',
|
|
kind: 'memberState',
|
|
unitId,
|
|
lifePct,
|
|
}
|
|
}
|
|
|
|
/** 0x74 PlayerCorpseAssign (10B, D2Client.dll 0x6fb5def0) */
|
|
export function decode0x74PlayerCorpseAssign(pkt: Uint8Array): ServerEvent {
|
|
const r = new ByteReader(pkt)
|
|
r.u8() // 0x74
|
|
const assign = r.u8()
|
|
const unitId = r.u32LE()
|
|
const otherId = r.u32LE()
|
|
return {
|
|
type: 'Party',
|
|
kind: 'relation',
|
|
unitId,
|
|
otherId,
|
|
relation: assign,
|
|
}
|
|
}
|
|
|
|
/** 0x75 PlayerPartyInfo (13B, D2Client.dll 0x6fb5d870) */
|
|
export function decode0x75PlayerPartyInfo(pkt: Uint8Array): ServerEvent {
|
|
const r = new ByteReader(pkt)
|
|
r.u8() // 0x75
|
|
const unitId = r.u32LE()
|
|
const partyId = r.u16LE()
|
|
const charLevel = r.u16LE()
|
|
const relation = r.u16LE()
|
|
const inParty = r.u16LE()
|
|
return {
|
|
type: 'Party',
|
|
kind: 'roster',
|
|
unitId,
|
|
partyId,
|
|
charLevel,
|
|
relation: (inParty << 16) | relation,
|
|
}
|
|
}
|
|
|
|
/** 0x7F PartyMemberState (10B, D2Client.dll 0x6fb5d820) */
|
|
export function decode0x7FPartyMemberState(pkt: Uint8Array): ServerEvent {
|
|
const r = new ByteReader(pkt)
|
|
r.u8() // 0x7F
|
|
const isPlayer = r.u8()
|
|
const lifePct = r.u16LE()
|
|
const unitId = r.u32LE()
|
|
const areaId = r.u16LE()
|
|
return {
|
|
type: 'Party',
|
|
kind: 'memberState',
|
|
unitId,
|
|
lifePct,
|
|
areaId,
|
|
relation: isPlayer,
|
|
}
|
|
}
|
|
|
|
/** 0x8B PlayerPartyRelationship (6B, D2Client.dll 0x6fb5d800) */
|
|
export function decode0x8BPlayerPartyRelation(pkt: Uint8Array): ServerEvent {
|
|
const r = new ByteReader(pkt)
|
|
r.u8() // 0x8B
|
|
const unitId = r.u32LE()
|
|
const relation = r.u8()
|
|
return {
|
|
type: 'Party',
|
|
kind: 'relation',
|
|
unitId,
|
|
relation,
|
|
}
|
|
}
|
|
|
|
/** 0x8C RelationshipUpdate (11B, D2Client.dll 0x6fb5d7b0) */
|
|
export function decode0x8CRelationshipUpdate(pkt: Uint8Array): ServerEvent {
|
|
const r = new ByteReader(pkt)
|
|
r.u8() // 0x8C
|
|
const unitId = r.u32LE()
|
|
const otherId = r.u32LE()
|
|
const relation = r.u16LE()
|
|
return {
|
|
type: 'Party',
|
|
kind: 'relation',
|
|
unitId,
|
|
otherId,
|
|
relation,
|
|
}
|
|
}
|
|
|
|
/** 0x8D AssignPlayerToParty (7B, D2Client.dll 0x6fb5d780) */
|
|
export function decode0x8DAssignPlayerToParty(pkt: Uint8Array): ServerEvent {
|
|
const r = new ByteReader(pkt)
|
|
r.u8() // 0x8D
|
|
const unitId = r.u32LE()
|
|
const partyId = r.u16LE()
|
|
return {
|
|
type: 'Party',
|
|
kind: 'roster',
|
|
unitId,
|
|
partyId,
|
|
}
|
|
}
|
|
|
|
/** 0x8E CorpseAssign (10B, D2Client.dll 0x6fb5d130) */
|
|
export function decode0x8ECorpseAssign(pkt: Uint8Array): ServerEvent {
|
|
const r = new ByteReader(pkt)
|
|
r.u8() // 0x8E
|
|
const assign = r.u8()
|
|
const unitId = r.u32LE()
|
|
const otherId = r.u32LE()
|
|
return {
|
|
type: 'Party',
|
|
kind: 'relation',
|
|
unitId,
|
|
otherId,
|
|
relation: assign,
|
|
}
|
|
}
|
|
|
|
/** 0x90 PartyMemberMapPos (13B, D2Client.dll 0x6fb5d220) */
|
|
export function decode0x90PartyMemberPos(pkt: Uint8Array): ServerEvent {
|
|
const r = new ByteReader(pkt)
|
|
r.u8() // 0x90
|
|
const unitId = r.u32LE()
|
|
const x = r.u32LE()
|
|
const y = r.u32LE()
|
|
return {
|
|
type: 'Party',
|
|
kind: 'memberPos',
|
|
unitId,
|
|
at: { x, y },
|
|
}
|
|
}
|