diff --git a/replays/reforged_truncated_playernames.w3g b/replays/reforged_truncated_playernames.w3g new file mode 100644 index 0000000..80d8435 Binary files /dev/null and b/replays/reforged_truncated_playernames.w3g differ diff --git a/src/W3GReplay.ts b/src/W3GReplay.ts index 7dcf4e6..b6ab496 100644 --- a/src/W3GReplay.ts +++ b/src/W3GReplay.ts @@ -11,7 +11,8 @@ import { CommandDataBlock, ParserOutput, PlayerChatMessageBlock, - Platform + Platform, + ExtraPlayerListEntry } from './types' import { sortPlayers } from './sort' @@ -91,18 +92,23 @@ class W3GReplay extends ReplayParser { return this.finalize() } - handleMetaData (metaData: GameMetaDataDecoded) { + handleMetaData (metaData: GameMetaDataDecoded): void { this.slots = metaData.playerSlotRecords this.playerList = [metaData.player, ...metaData.playerList] this.meta = metaData const tempPlayers: {[key: string]: GameMetaDataDecoded['player'] } = {} this.teams = [] this.players = {} - this.playerList.forEach((player: GameMetaDataDecoded['player']): void => { tempPlayers[player.playerId] = player }) + if (metaData.extraPlayerList) { + metaData.extraPlayerList.forEach((extraPlayer: ExtraPlayerListEntry) => { + tempPlayers[extraPlayer.playerId].playerName = extraPlayer.name + }) + } + this.slots.forEach((slot: SlotRecord) => { if (slot.slotStatus > 1) { this.teams[slot.teamId] = this.teams[slot.teamId] || [] @@ -115,7 +121,7 @@ class W3GReplay extends ReplayParser { }) } - processGameDataBlock (block: GameDataBlock) { + processGameDataBlock (block: GameDataBlock): void { switch (block.type) { case 31: case 30: @@ -143,7 +149,7 @@ class W3GReplay extends ReplayParser { }) } - processCommandDataBlock (block: CommandDataBlock) { + processCommandDataBlock (block: CommandDataBlock): void { const currentPlayer = this.players[block.playerId] currentPlayer.currentTimePlayed = this.totalTimeTracker currentPlayer._lastActionWasDeselect = false @@ -156,7 +162,7 @@ class W3GReplay extends ReplayParser { } } - handleActionBlock (action: ActionBlock, currentPlayer: Player) { + handleActionBlock (action: ActionBlock, currentPlayer: Player): void { this.playerActionTracker[currentPlayer.id] = this.playerActionTracker[currentPlayer.id] || [] this.playerActionTracker[currentPlayer.id].push(action) diff --git a/src/parsers/header.ts b/src/parsers/header.ts index 043ea89..7c8a299 100644 --- a/src/parsers/header.ts +++ b/src/parsers/header.ts @@ -177,7 +177,10 @@ const GameMetaDataReforged = (buildNo: number) => new Parser() .array('extraPlayerList', { type: new Parser() .int8('preVars1') - .buffer('pre', { length: 4 }) + .int8('pre1') + .int8('pre2') + .int8('playerId') + .int8('pre4') .int8('nameLength') .string('name', { length: 'nameLength' }) .skip(1) diff --git a/src/types.ts b/src/types.ts index 07084c8..b0d05ee 100644 --- a/src/types.ts +++ b/src/types.ts @@ -23,6 +23,12 @@ export interface SlotRecord { handicapFlag: number; } +export interface ExtraPlayerListEntry{ + nameLength: number; + name: string; + playerId: number; +} + export interface GameMetaDataDecoded { player: { hasRecord?: number; @@ -65,6 +71,7 @@ export interface GameMetaDataDecoded { mapChecksum: string; mapName: string; creator: string; + extraPlayerList?: ExtraPlayerListEntry[]; } export interface ActionBlock{ diff --git a/test/replays.test.ts b/test/replays.test.ts index 0896ec9..27b3a02 100644 --- a/test/replays.test.ts +++ b/test/replays.test.ts @@ -333,4 +333,13 @@ describe('Replay parsing tests', () => { expect(test.players[0].name).toBe('HurricaneBo') expect(test.players[1].name).toBe('SimplyHunteR') }) + + it('handles truncated player names in reforged replays', () => { + const test = Parser.parse('./replays/reforged_truncated_playernames.w3g') + expect(test.version).toBe('1.32') + expect(test.buildNumber).toBe(6105) + expect(test.players.length).toBe(2) + expect(test.players[0].name).toBe('WaN#1734') + expect(test.players[1].name).toBe('РозовыйПони#228941') + }) })