@astefanski/storm-parser 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -36,39 +36,271 @@ declare class ReplayParser {
36
36
  getTrackerEvents(): ReplayEvent[];
37
37
  getGameEvents(): ReplayEvent[];
38
38
  extractFile(filename: string): Buffer | null;
39
+ getHeader(): Record<string, unknown> | undefined;
40
+ getBuild(): number;
39
41
  }
40
42
 
41
- interface PlayerStat {
43
+ interface ReplayVersion {
44
+ m_flags: number;
45
+ m_major: number;
46
+ m_minor: number;
47
+ m_revision: number;
48
+ m_build: number;
49
+ m_baseBuild: number;
50
+ }
51
+ interface KillParticipant {
52
+ player: string;
42
53
  hero: string;
54
+ }
55
+ interface TakedownEvent {
56
+ loop: number;
57
+ time: number;
58
+ x: number;
59
+ y: number;
60
+ killers: KillParticipant[];
61
+ victim: KillParticipant;
62
+ }
63
+ interface LevelTime {
64
+ loop: number;
65
+ level: number;
66
+ team: string;
67
+ time: number;
68
+ }
69
+ interface BanEntry {
70
+ hero: string;
71
+ order: number;
72
+ absolute: number;
73
+ }
74
+ interface PickData {
75
+ 0: string[];
76
+ 1: string[];
77
+ first: number;
78
+ }
79
+ interface XPValues {
80
+ GameTime: number;
81
+ PreviousGameTime: number;
82
+ MinionXP: number;
83
+ CreepXP: number;
84
+ StructureXP: number;
85
+ HeroXP: number;
86
+ TrickleXP: number;
87
+ }
88
+ interface XPBreakdownEntry {
89
+ loop: number;
90
+ time: number;
91
+ team: number;
92
+ teamLevel?: number;
93
+ breakdown: XPValues;
94
+ theoreticalMinionXP: number;
95
+ }
96
+ interface MercCapture {
97
+ loop: number;
98
+ type: string;
99
+ team: number;
100
+ time: number;
101
+ }
102
+ interface MercUnitLocation {
103
+ x: number;
104
+ y: number;
105
+ }
106
+ interface MercUnit {
107
+ loop: number;
108
+ team: number;
109
+ type: string;
110
+ locations: MercUnitLocation[];
111
+ time: number;
112
+ duration: number;
113
+ }
114
+ interface MercsData {
115
+ captures: MercCapture[];
116
+ units: Record<string, MercUnit>;
117
+ }
118
+ interface StructureInfo {
119
+ type: string;
43
120
  name: string;
44
- tag: string;
121
+ tag: number;
122
+ rtag: number;
123
+ x: number;
124
+ y: number;
45
125
  team: number;
46
- win: boolean;
47
- gameStats: Record<string, number>;
126
+ destroyedLoop?: number;
127
+ destroyed?: number;
128
+ }
129
+ interface ObjectiveEvent {
130
+ team: number;
131
+ score?: number;
132
+ loop: number;
133
+ time: number;
134
+ duration?: number;
135
+ endLoop?: number;
136
+ end?: number;
137
+ }
138
+ interface TeamObjective {
139
+ count: number;
140
+ events: ObjectiveEvent[];
141
+ }
142
+ interface ObjectiveData {
143
+ 0: TeamObjective;
144
+ 1: TeamObjective;
145
+ type: string;
146
+ }
147
+ interface StructureStats {
148
+ lost: number;
149
+ destroyed: number;
150
+ first: number;
151
+ }
152
+ interface UptimeEntry {
153
+ time: number;
154
+ heroes: number;
155
+ }
156
+ interface TeamTotals {
157
+ DamageTaken: number;
158
+ CreepDamage: number;
159
+ Healing: number;
160
+ HeroDamage: number;
161
+ MinionDamage: number;
162
+ SelfHealing: number;
163
+ SiegeDamage: number;
164
+ ProtectionGivenToAllies: number;
165
+ TeamfightDamageTaken: number;
166
+ TeamfightHealingDone: number;
167
+ TeamfightHeroDamage: number;
168
+ TimeCCdEnemyHeroes: number;
169
+ TimeRootingEnemyHeroes: number;
170
+ TimeSpentDead: number;
171
+ TimeStunningEnemyHeroes: number;
172
+ TimeSilencingEnemyHeroes: number;
173
+ avgTimeSpentDead: number;
174
+ timeDeadPct: number;
175
+ }
176
+ interface TeamStats {
177
+ mercCaptures: number;
178
+ mercUptime: number;
179
+ mercUptimePercent: number;
180
+ structures: Record<string, StructureStats>;
181
+ KDA: number;
182
+ PPK: number;
183
+ timeTo10: number;
184
+ totals: TeamTotals;
185
+ levelAdvTime: number;
186
+ maxLevelAdv: number;
187
+ avgLevelAdv: number;
188
+ levelAdvPct: number;
189
+ uptime: UptimeEntry[];
190
+ uptimeHistogram: Record<string, number>;
191
+ wipes: number;
192
+ avgHeroesAlive: number;
193
+ aces: number;
194
+ timeWithHeroAdv: number;
195
+ pctWithHeroAdv: number;
196
+ passiveXPRate: number;
197
+ passiveXPDiff: number;
198
+ passiveXPGain: number;
48
199
  }
49
200
  interface TeamStat {
50
201
  level: number;
51
202
  takedowns: number;
52
203
  ids: string[];
204
+ names: string[];
205
+ heroes: string[];
206
+ tags: number[];
207
+ stats: TeamStats;
208
+ }
209
+ interface LevelAdvSegment {
210
+ start: number;
211
+ end: number;
212
+ levelDiff: number;
213
+ length: number;
214
+ }
215
+ interface TalentChoices {
216
+ Tier1Choice?: string;
217
+ Tier2Choice?: string;
218
+ Tier3Choice?: string;
219
+ Tier4Choice?: string;
220
+ Tier5Choice?: string;
221
+ Tier6Choice?: string;
222
+ Tier7Choice?: string;
223
+ }
224
+ interface UnitPosition {
225
+ x: number;
226
+ y: number;
227
+ time: number;
228
+ }
229
+ interface UnitLife {
230
+ born: number;
231
+ locations: UnitPosition[];
232
+ died?: number;
233
+ duration: number;
234
+ }
235
+ interface PlayerUnit {
236
+ lives: UnitLife[];
237
+ }
238
+ interface PlayerStat {
239
+ hero: string;
240
+ name: string;
241
+ uuid: number;
242
+ region: number;
243
+ realm: number;
244
+ ToonHandle: string;
245
+ tag: number;
246
+ team: number;
247
+ win: boolean;
248
+ gameStats: Record<string, number>;
249
+ awards: string[];
250
+ talents: TalentChoices;
251
+ takedowns: TakedownEvent[];
252
+ deaths: TakedownEvent[];
253
+ units: Record<string, PlayerUnit>;
53
254
  }
54
255
  interface MatchStat {
256
+ version: ReplayVersion;
257
+ type?: number;
258
+ mode?: number;
55
259
  map?: string;
56
260
  date: string;
261
+ rawDate?: number;
57
262
  length: number;
58
263
  winner: number;
59
- version: {
60
- m_build: number;
61
- };
264
+ region?: number;
265
+ loopLength?: number;
266
+ loopGameStart?: number;
267
+ playerIDs: string[];
268
+ heroes: string[];
269
+ levelTimes: Record<string, Record<string, LevelTime>>;
270
+ bans: Record<string, BanEntry[]>;
271
+ picks: PickData;
272
+ XPBreakdown: XPBreakdownEntry[];
273
+ takedowns: TakedownEvent[];
274
+ mercs: MercsData;
275
+ team0Takedowns: number;
276
+ team1Takedowns: number;
277
+ structures: Record<string, StructureInfo>;
278
+ objective: ObjectiveData;
62
279
  teams: Record<string, TeamStat>;
280
+ winningPlayers: string[];
281
+ levelAdvTimeline: LevelAdvSegment[];
282
+ firstPickWin: boolean;
283
+ firstObjective?: number;
284
+ firstObjectiveWin?: boolean;
285
+ firstFort?: number;
286
+ firstKeep?: number;
287
+ firstFortWin?: boolean;
288
+ firstKeepWin?: boolean;
63
289
  }
290
+ interface AnalysisResult {
291
+ status: number;
292
+ match?: MatchStat;
293
+ players?: Record<string, PlayerStat>;
294
+ error?: string;
295
+ }
296
+
64
297
  declare class ReplayAnalyzer {
65
- static analyze(filePath: string): Promise<{
66
- status: number;
67
- match?: MatchStat;
68
- players?: Record<string, PlayerStat>;
69
- error?: string;
70
- }>;
298
+ static analyze(filePath: string): Promise<AnalysisResult>;
299
+ private static emptyTeam;
300
+ private static extractBattleTags;
301
+ private static extractDraft;
302
+ private static processScoreEvents;
71
303
  private static fileTimeToDate;
72
304
  }
73
305
 
74
- export { type Protocol, ReplayAnalyzer, type ReplayEvent, ReplayParser };
306
+ export { type AnalysisResult, type BanEntry, type KillParticipant, type LevelAdvSegment, type LevelTime, type MatchStat, type MercCapture, type MercUnit, type MercUnitLocation, type MercsData, type ObjectiveData, type ObjectiveEvent, type PickData, type PlayerStat, type PlayerUnit, type Protocol, ReplayAnalyzer, type ReplayEvent, ReplayParser, type ReplayVersion, type StructureInfo, type StructureStats, type TakedownEvent, type TalentChoices, type TeamObjective, type TeamStat, type TeamStats, type TeamTotals, type UnitLife, type UnitPosition, type UptimeEntry, type XPBreakdownEntry, type XPValues };
package/dist/index.d.ts CHANGED
@@ -36,39 +36,271 @@ declare class ReplayParser {
36
36
  getTrackerEvents(): ReplayEvent[];
37
37
  getGameEvents(): ReplayEvent[];
38
38
  extractFile(filename: string): Buffer | null;
39
+ getHeader(): Record<string, unknown> | undefined;
40
+ getBuild(): number;
39
41
  }
40
42
 
41
- interface PlayerStat {
43
+ interface ReplayVersion {
44
+ m_flags: number;
45
+ m_major: number;
46
+ m_minor: number;
47
+ m_revision: number;
48
+ m_build: number;
49
+ m_baseBuild: number;
50
+ }
51
+ interface KillParticipant {
52
+ player: string;
42
53
  hero: string;
54
+ }
55
+ interface TakedownEvent {
56
+ loop: number;
57
+ time: number;
58
+ x: number;
59
+ y: number;
60
+ killers: KillParticipant[];
61
+ victim: KillParticipant;
62
+ }
63
+ interface LevelTime {
64
+ loop: number;
65
+ level: number;
66
+ team: string;
67
+ time: number;
68
+ }
69
+ interface BanEntry {
70
+ hero: string;
71
+ order: number;
72
+ absolute: number;
73
+ }
74
+ interface PickData {
75
+ 0: string[];
76
+ 1: string[];
77
+ first: number;
78
+ }
79
+ interface XPValues {
80
+ GameTime: number;
81
+ PreviousGameTime: number;
82
+ MinionXP: number;
83
+ CreepXP: number;
84
+ StructureXP: number;
85
+ HeroXP: number;
86
+ TrickleXP: number;
87
+ }
88
+ interface XPBreakdownEntry {
89
+ loop: number;
90
+ time: number;
91
+ team: number;
92
+ teamLevel?: number;
93
+ breakdown: XPValues;
94
+ theoreticalMinionXP: number;
95
+ }
96
+ interface MercCapture {
97
+ loop: number;
98
+ type: string;
99
+ team: number;
100
+ time: number;
101
+ }
102
+ interface MercUnitLocation {
103
+ x: number;
104
+ y: number;
105
+ }
106
+ interface MercUnit {
107
+ loop: number;
108
+ team: number;
109
+ type: string;
110
+ locations: MercUnitLocation[];
111
+ time: number;
112
+ duration: number;
113
+ }
114
+ interface MercsData {
115
+ captures: MercCapture[];
116
+ units: Record<string, MercUnit>;
117
+ }
118
+ interface StructureInfo {
119
+ type: string;
43
120
  name: string;
44
- tag: string;
121
+ tag: number;
122
+ rtag: number;
123
+ x: number;
124
+ y: number;
45
125
  team: number;
46
- win: boolean;
47
- gameStats: Record<string, number>;
126
+ destroyedLoop?: number;
127
+ destroyed?: number;
128
+ }
129
+ interface ObjectiveEvent {
130
+ team: number;
131
+ score?: number;
132
+ loop: number;
133
+ time: number;
134
+ duration?: number;
135
+ endLoop?: number;
136
+ end?: number;
137
+ }
138
+ interface TeamObjective {
139
+ count: number;
140
+ events: ObjectiveEvent[];
141
+ }
142
+ interface ObjectiveData {
143
+ 0: TeamObjective;
144
+ 1: TeamObjective;
145
+ type: string;
146
+ }
147
+ interface StructureStats {
148
+ lost: number;
149
+ destroyed: number;
150
+ first: number;
151
+ }
152
+ interface UptimeEntry {
153
+ time: number;
154
+ heroes: number;
155
+ }
156
+ interface TeamTotals {
157
+ DamageTaken: number;
158
+ CreepDamage: number;
159
+ Healing: number;
160
+ HeroDamage: number;
161
+ MinionDamage: number;
162
+ SelfHealing: number;
163
+ SiegeDamage: number;
164
+ ProtectionGivenToAllies: number;
165
+ TeamfightDamageTaken: number;
166
+ TeamfightHealingDone: number;
167
+ TeamfightHeroDamage: number;
168
+ TimeCCdEnemyHeroes: number;
169
+ TimeRootingEnemyHeroes: number;
170
+ TimeSpentDead: number;
171
+ TimeStunningEnemyHeroes: number;
172
+ TimeSilencingEnemyHeroes: number;
173
+ avgTimeSpentDead: number;
174
+ timeDeadPct: number;
175
+ }
176
+ interface TeamStats {
177
+ mercCaptures: number;
178
+ mercUptime: number;
179
+ mercUptimePercent: number;
180
+ structures: Record<string, StructureStats>;
181
+ KDA: number;
182
+ PPK: number;
183
+ timeTo10: number;
184
+ totals: TeamTotals;
185
+ levelAdvTime: number;
186
+ maxLevelAdv: number;
187
+ avgLevelAdv: number;
188
+ levelAdvPct: number;
189
+ uptime: UptimeEntry[];
190
+ uptimeHistogram: Record<string, number>;
191
+ wipes: number;
192
+ avgHeroesAlive: number;
193
+ aces: number;
194
+ timeWithHeroAdv: number;
195
+ pctWithHeroAdv: number;
196
+ passiveXPRate: number;
197
+ passiveXPDiff: number;
198
+ passiveXPGain: number;
48
199
  }
49
200
  interface TeamStat {
50
201
  level: number;
51
202
  takedowns: number;
52
203
  ids: string[];
204
+ names: string[];
205
+ heroes: string[];
206
+ tags: number[];
207
+ stats: TeamStats;
208
+ }
209
+ interface LevelAdvSegment {
210
+ start: number;
211
+ end: number;
212
+ levelDiff: number;
213
+ length: number;
214
+ }
215
+ interface TalentChoices {
216
+ Tier1Choice?: string;
217
+ Tier2Choice?: string;
218
+ Tier3Choice?: string;
219
+ Tier4Choice?: string;
220
+ Tier5Choice?: string;
221
+ Tier6Choice?: string;
222
+ Tier7Choice?: string;
223
+ }
224
+ interface UnitPosition {
225
+ x: number;
226
+ y: number;
227
+ time: number;
228
+ }
229
+ interface UnitLife {
230
+ born: number;
231
+ locations: UnitPosition[];
232
+ died?: number;
233
+ duration: number;
234
+ }
235
+ interface PlayerUnit {
236
+ lives: UnitLife[];
237
+ }
238
+ interface PlayerStat {
239
+ hero: string;
240
+ name: string;
241
+ uuid: number;
242
+ region: number;
243
+ realm: number;
244
+ ToonHandle: string;
245
+ tag: number;
246
+ team: number;
247
+ win: boolean;
248
+ gameStats: Record<string, number>;
249
+ awards: string[];
250
+ talents: TalentChoices;
251
+ takedowns: TakedownEvent[];
252
+ deaths: TakedownEvent[];
253
+ units: Record<string, PlayerUnit>;
53
254
  }
54
255
  interface MatchStat {
256
+ version: ReplayVersion;
257
+ type?: number;
258
+ mode?: number;
55
259
  map?: string;
56
260
  date: string;
261
+ rawDate?: number;
57
262
  length: number;
58
263
  winner: number;
59
- version: {
60
- m_build: number;
61
- };
264
+ region?: number;
265
+ loopLength?: number;
266
+ loopGameStart?: number;
267
+ playerIDs: string[];
268
+ heroes: string[];
269
+ levelTimes: Record<string, Record<string, LevelTime>>;
270
+ bans: Record<string, BanEntry[]>;
271
+ picks: PickData;
272
+ XPBreakdown: XPBreakdownEntry[];
273
+ takedowns: TakedownEvent[];
274
+ mercs: MercsData;
275
+ team0Takedowns: number;
276
+ team1Takedowns: number;
277
+ structures: Record<string, StructureInfo>;
278
+ objective: ObjectiveData;
62
279
  teams: Record<string, TeamStat>;
280
+ winningPlayers: string[];
281
+ levelAdvTimeline: LevelAdvSegment[];
282
+ firstPickWin: boolean;
283
+ firstObjective?: number;
284
+ firstObjectiveWin?: boolean;
285
+ firstFort?: number;
286
+ firstKeep?: number;
287
+ firstFortWin?: boolean;
288
+ firstKeepWin?: boolean;
63
289
  }
290
+ interface AnalysisResult {
291
+ status: number;
292
+ match?: MatchStat;
293
+ players?: Record<string, PlayerStat>;
294
+ error?: string;
295
+ }
296
+
64
297
  declare class ReplayAnalyzer {
65
- static analyze(filePath: string): Promise<{
66
- status: number;
67
- match?: MatchStat;
68
- players?: Record<string, PlayerStat>;
69
- error?: string;
70
- }>;
298
+ static analyze(filePath: string): Promise<AnalysisResult>;
299
+ private static emptyTeam;
300
+ private static extractBattleTags;
301
+ private static extractDraft;
302
+ private static processScoreEvents;
71
303
  private static fileTimeToDate;
72
304
  }
73
305
 
74
- export { type Protocol, ReplayAnalyzer, type ReplayEvent, ReplayParser };
306
+ export { type AnalysisResult, type BanEntry, type KillParticipant, type LevelAdvSegment, type LevelTime, type MatchStat, type MercCapture, type MercUnit, type MercUnitLocation, type MercsData, type ObjectiveData, type ObjectiveEvent, type PickData, type PlayerStat, type PlayerUnit, type Protocol, ReplayAnalyzer, type ReplayEvent, ReplayParser, type ReplayVersion, type StructureInfo, type StructureStats, type TakedownEvent, type TalentChoices, type TeamObjective, type TeamStat, type TeamStats, type TeamTotals, type UnitLife, type UnitPosition, type UptimeEntry, type XPBreakdownEntry, type XPValues };
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- "use strict";var C=Object.create;var P=Object.defineProperty;var q=Object.getOwnPropertyDescriptor;var j=Object.getOwnPropertyNames;var G=Object.getPrototypeOf,V=Object.prototype.hasOwnProperty;var W=(i,e)=>{for(var t in e)P(i,t,{get:e[t],enumerable:!0})},Q=(i,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of j(e))!V.call(i,n)&&n!==t&&P(i,n,{get:()=>e[n],enumerable:!(r=q(e,n))||r.enumerable});return i};var M=(i,e,t)=>(t=i!=null?C(G(i)):{},Q(e||!i||!i.__esModule?P(t,"default",{value:i,enumerable:!0}):t,i)),X=i=>Q(P({},"__esModule",{value:!0}),i);var se={};W(se,{ReplayAnalyzer:()=>L,ReplayParser:()=>x});module.exports=X(se);var A=M(require("fs")),S=M(require("zlib")),J=require("seek-bzip"),z=512,K=65536,Y=16777216,Z=67108864,ee=2147483648,te={TABLE_OFFSET:0,HASH_A:1,HASH_B:2,TABLE:3};function re(){let i=1048577,e=new Uint32Array(256*5);for(let t=0;t<256;t++){let r=t;for(let n=0;n<5;n++){i=(i*125+3)%2796203;let s=(i&65535)<<16;i=(i*125+3)%2796203;let l=i&65535;e[r]=(s|l)>>>0,r+=256}}return e}var F=re(),R=class{file;header;hashTable;blockTable;files;constructor(e,t=!0){if(Buffer.isBuffer(e)?this.file=e:this.file=A.readFileSync(e),this.header=this.readHeader(),this.hashTable=this.readTable("hash"),this.blockTable=this.readTable("block"),t){let r=this.readFile("(listfile)");r?this.files=r.toString("utf8").trim().split(`\r
2
- `):this.files=null}else this.files=null}readHeader(){let e=this.file.toString("utf8",0,4),t;if(e==="MPQ")t=this.readMPQHeader(),t.offset=0;else if(e==="MPQ\x1B"){let r=this.readMPQUserDataHeader();t=this.readMPQHeader(r.mpqHeaderOffset),t.offset=r.mpqHeaderOffset,t.userDataHeader=r}else throw new Error("Invalid MPQ file header");return t}readMPQHeader(e=0){let t=this.file.subarray(e,e+32),r={magic:t.toString("utf8",0,4),headerSize:t.readUInt32LE(4),archiveSize:t.readUInt32LE(8),formatVersion:t.readUInt16LE(12),sectorSizeShift:t.readUInt16LE(14),hashTableOffset:t.readUInt32LE(16),blockTableOffset:t.readUInt32LE(20),hashTableEntries:t.readUInt32LE(24),blockTableEntries:t.readUInt32LE(28)};if(r.formatVersion===1){let n=this.file.subarray(e+32,e+32+12);r.extendedBlockTableOffset=n.readUInt32LE(0)+n.readUInt32LE(4)*4294967296,r.hashTableOffsetHigh=n.readInt8(8),r.blockTableOffsetHigh=n.readInt8(10)}return r}readMPQUserDataHeader(){let e=this.file.subarray(0,16),t={magic:e.toString("utf8",0,4),userDataSize:e.readUInt32LE(4),mpqHeaderOffset:e.readUInt32LE(8),userDataHeaderSize:e.readUInt32LE(12)};return t.content=this.file.subarray(16,16+t.userDataHeaderSize),t}readTable(e){let t=e==="hash"?"hashTableOffset":"blockTableOffset",r=e==="hash"?"hashTableEntries":"blockTableEntries",n=this.header[t],s=this.header[r];if(n==null||s==null)throw new Error("Missing "+e+" offset or entries");let l=this.hash("("+e+" table)","TABLE"),a=this.file.subarray(n+(this.header.offset||0),n+(this.header.offset||0)+s*16);a=this.decrypt(a,l);let c=[];for(let _=0;_<s;_++){let h=a.subarray(_*16,_*16+16);e==="hash"?c.push({hashA:h.readUInt32LE(0),hashB:h.readUInt32LE(4),locale:h.readUInt16LE(8),platform:h.readUInt16LE(10),blockTableIndex:h.readUInt32LE(12)}):c.push({offset:h.readUInt32LE(0),archivedSize:h.readUInt32LE(4),size:h.readUInt32LE(8),flags:h.readUInt32LE(12)})}return c}getHashTableEntry(e){let t=this.hash(e,"HASH_A"),r=this.hash(e,"HASH_B");for(let n of this.hashTable)if(n.hashA===t&&n.hashB===r)return n}readFile(e,t=!1){function r(c){let _=c[0];if(_===0)return c;if(_===2)return S.inflateSync(c.subarray(1));if(_===16)return J.decode(c.subarray(1));try{return S.inflateSync(c.subarray(1))}catch{return S.inflateRawSync(c.subarray(1))}}let n=this.getHashTableEntry(e);if(!n)return null;let s=this.blockTable[n.blockTableIndex];if(!s||!(s.flags&ee))return null;if(s.archivedSize===0)return Buffer.alloc(0);let l=s.offset+(this.header.offset||0),a=this.file.subarray(l,l+s.archivedSize);if(s.flags&K)throw new Error("Encryption is not supported");if(s.flags&Y)s.flags&z&&(t||s.size>s.archivedSize)&&(a=r(a));else{let c=512<<this.header.sectorSizeShift,_=Math.trunc(s.size/c)+1,h=!1;s.flags&Z&&(h=!0,_+=1);let o=[];for(let d=0;d<_+1;d++)o.push(a.readUInt32LE(4*d));let u=o.length-(h?2:1),f=[],b=s.size;for(let d=0;d<u;d++){let m=a.subarray(o[d],o[d+1]);s.flags&z&&(t||b>m.length)&&(m=r(m)),b-=m.length,f.push(m)}a=Buffer.concat(f)}return a}hash(e,t){let r=2146271213,n=4008636142;for(let s=0;s<e.length;s++){let l=e.toUpperCase().charCodeAt(s);r=(F[(te[t]<<8)+l]^r+n)>>>0,n=l+r+n+(n<<5)+3>>>0}return r}decrypt(e,t){let r=t>>>0,n=4008636142,s=Buffer.alloc(e.length),l=e.length/4;for(let a=0;a<l;a++){n=n+F[1024+(r&255)]>>>0;let c=e.readUInt32LE(a*4);c=(c^r+n)>>>0,r=((~r<<21)+286331153|r>>>11)>>>0,n=c+n+(n<<5)+3>>>0,s.writeUInt32LE(c,a*4)}return s}};var B=class extends Error{constructor(e="Truncated Buffer"){super(e),this.name="TruncatedError"}},y=class extends Error{constructor(e="Corrupted Buffer"){super(e),this.name="CorruptedError"}},T=class{_data;_used;_next;_nextbits;_bigendian;constructor(e,t="big"){this._data=e,this._used=0,this._next=0,this._nextbits=0,this._bigendian=t==="big"}done(){return this._nextbits===0&&this._used>=this._data.length}used_bits(){return this._used*8-this._nextbits}byte_align(){this._nextbits=0}read_aligned_bytes(e){if(this.byte_align(),this._used+e>this._data.length)throw new B;let t=this._data.subarray(this._used,this._used+e);return this._used+=e,t}read_bits(e){let t=0,r=0;for(;r!==e;){if(this._nextbits===0){if(this.done())throw new B;this._next=this._data[this._used],this._used+=1,this._nextbits=8}let n=Math.min(e-r,this._nextbits),s=this._next&(1<<n)-1;this._bigendian?t+=s*Math.pow(2,e-r-n):t+=s*Math.pow(2,r),this._next>>=n,this._nextbits-=n,r+=n}return t}read_bits_bigint(e){let t=0n,r=0;for(;r!==e;){if(this._nextbits===0){if(this.done())throw new B;this._next=this._data[this._used],this._used+=1,this._nextbits=8}let n=Math.min(e-r,this._nextbits),s=BigInt(this._next&(1<<n)-1);this._bigendian?t|=s<<BigInt(e-r-n):t|=s<<BigInt(r),this._next>>=n,this._nextbits-=n,r+=n}return t}read_unaligned_bytes(e){let t=Buffer.alloc(e);for(let r=0;r<e;r++)t[r]=this.read_bits(8);return t}};var I=class{_buffer;_typeinfos;constructor(e,t){this._buffer=new T(e),this._typeinfos=t}instance(e){if(e>=this._typeinfos.length)throw new y(`Invalid typeid ${e}`);let t=this._typeinfos[e],r=t[0],n=t[1]||[],s=this[r];if(typeof s!="function")throw new Error(`Decoder method ${r} not implemented`);return s.apply(this,n)}byte_align(){this._buffer.byte_align()}done(){return this._buffer.done()}used_bits(){return this._buffer.used_bits()}_array(e,t){let r=this._int(e),n=new Array(r);for(let s=0;s<r;s++)n[s]=this.instance(t);return n}_bitarray(e){let t=this._int(e);return[t,this._buffer.read_bits(t)]}_blob(e){let t=this._int(e);return this._buffer.read_aligned_bytes(t)}_bool(){return this._int([0,1])!==0}_choice(e,t){let r=this._int(e);if(!(r in t))throw new y(`Choice tag ${r} not found`);let n=t[r];return{[n[0]]:this.instance(n[1])}}_fourcc(){let e=this._buffer.read_bits(32),t=Buffer.alloc(4);return t.writeUInt32BE(e,0),t.toString("ascii")}_int(e){return e[0]+this._buffer.read_bits(e[1])}_null(){return null}_optional(e){return this._bool()?this.instance(e):null}_real32(){return this._buffer.read_unaligned_bytes(4).readFloatBE(0)}_real64(){return this._buffer.read_unaligned_bytes(8).readDoubleBE(0)}_struct(e){let t={};for(let r of e)if(r[0]==="__parent"){let n=this.instance(r[1]);if(typeof n=="object"&&n!==null)t={...t,...n};else{if(e.length===1)return n;t[r[0]]=n}}else t[r[0]]=this.instance(r[1]);return t}},w=class{_buffer;_typeinfos;constructor(e,t){this._buffer=new T(e),this._typeinfos=t}instance(e){if(e>=this._typeinfos.length)throw new y(`Invalid typeid ${e}`);let t=this._typeinfos[e],r=t[0],n=t[1]||[],s=this[r];if(typeof s!="function")throw new Error(`Decoder method ${r} not implemented`);return s.apply(this,n)}byte_align(){this._buffer.byte_align()}done(){return this._buffer.done()}used_bits(){return this._buffer.used_bits()}_expect_skip(e){if(this._buffer.read_bits(8)!==e)throw new y(`Expected skip ${e}`)}_vint(){let e=this._buffer.read_bits(8),t=(e&1)!==0,r=BigInt(e>>1&63),n=6n;for(;(e&128)!==0;)e=this._buffer.read_bits(8),r|=BigInt(e&127)<<n,n+=7n;let s=t?-r:r;return s>=BigInt(Number.MIN_SAFE_INTEGER)&&s<=BigInt(Number.MAX_SAFE_INTEGER)?Number(s):s}_array(e,t){this._expect_skip(0);let r=Number(this._vint()),n=new Array(r);for(let s=0;s<r;s++)n[s]=this.instance(t);return n}_bitarray(e){this._expect_skip(1);let t=Number(this._vint());return[t,this._buffer.read_aligned_bytes(Math.floor((t+7)/8))]}_blob(e){this._expect_skip(2);let t=Number(this._vint());return this._buffer.read_aligned_bytes(t)}_bool(){return this._expect_skip(6),this._buffer.read_bits(8)!==0}_choice(e,t){this._expect_skip(3);let r=Number(this._vint());if(!(r in t))return this._skip_instance(),{};let n=t[r];return{[n[0]]:this.instance(n[1])}}_fourcc(){return this._expect_skip(7),this._buffer.read_aligned_bytes(4)}_int(e){return this._expect_skip(9),Number(this._vint())}_null(){return null}_optional(e){return this._expect_skip(4),this._buffer.read_bits(8)!==0?this.instance(e):null}_real32(){return this._expect_skip(7),this._buffer.read_aligned_bytes(4).readFloatBE(0)}_real64(){return this._expect_skip(8),this._buffer.read_aligned_bytes(8).readDoubleBE(0)}_struct(e){this._expect_skip(5);let t={},r=Number(this._vint());for(let n=0;n<r;n++){let s=Number(this._vint()),l=e.find(a=>a[2]===s);if(l)if(l[0]==="__parent"){let a=this.instance(l[1]);typeof a=="object"&&a!==null?t={...t,...a}:e.length===1?t=a:t[l[0]]=a}else t[l[0]]=this.instance(l[1]);else this._skip_instance()}return t}_skip_instance(){let e=this._buffer.read_bits(8);if(e===0){let t=Number(this._vint());for(let r=0;r<t;r++)this._skip_instance()}else if(e===1){let t=Number(this._vint());this._buffer.read_aligned_bytes(Math.floor((t+7)/8))}else if(e===2){let t=Number(this._vint());this._buffer.read_aligned_bytes(t)}else if(e===3)this._vint(),this._skip_instance();else if(e===4)this._buffer.read_bits(8)!==0&&this._skip_instance();else if(e===5){let t=Number(this._vint());for(let r=0;r<t;r++)this._vint(),this._skip_instance()}else e===6?this._buffer.read_aligned_bytes(1):e===7?this._buffer.read_aligned_bytes(4):e===8?this._buffer.read_aligned_bytes(8):e===9&&this._vint()}};var E=M(require("fs")),g=M(require("path"));function ne(){let i=[];try{i.push(g.default.resolve(__dirname,"..","protocols")),i.push(g.default.resolve(__dirname,"..","..","protocols"))}catch{}i.push(g.default.resolve(process.cwd(),"protocols"));let e=process.cwd();for(;e!==g.default.dirname(e);){let t=g.default.join(e,"node_modules","@astefanski","storm-parser","protocols");i.push(t),e=g.default.dirname(e)}for(let t of i)if(E.default.existsSync(t)&&E.default.readdirSync(t).some(r=>r.endsWith(".json")))return t;throw new Error(`@astefanski/storm-parser: Protocols directory not found. Did postinstall run? Try: npx tsx node_modules/@astefanski/storm-parser/scripts/postinstall.ts
3
- Searched: `+i.join(", "))}var U=new Map,N=null;function O(){return N||(N=ne()),N}function H(i){if(U.has(i))return U.get(i);let e=O(),t=g.default.join(e,`protocol${i}.json`);if(!E.default.existsSync(t))return null;let r=JSON.parse(E.default.readFileSync(t,"utf-8"));return U.set(i,r),r}function $(){let i=O();return E.default.readdirSync(i).filter(e=>/^protocol\d+\.json$/.test(e)).map(e=>parseInt(e.match(/\d+/)[0],10)).sort((e,t)=>e-t)}var x=class{mpq;header;build=0;protocol;baseProtocol;constructor(e){this.mpq=new R(e,!1)}init(){let e=H(29406);if(!e)throw new Error("Base protocol29406 not found. Did postinstall run? Try: npx tsx node_modules/@astefanski/storm-parser/scripts/postinstall.ts");this.baseProtocol=e;let t=this.mpq.header.userDataHeader;if(!t||!t.content)throw new Error("Replay does not have a user data header");let r=new w(t.content,this.baseProtocol.typeinfos);this.header=r.instance(this.baseProtocol.replay_header_typeid),this.build=this.header.m_version.m_baseBuild,this.protocol=this.loadProtocolForBuild(this.build)}loadProtocolForBuild(e){let t=H(e);if(!t){let r=$(),n=r[0];for(let s of r)s<=e&&s>n&&(n=s);t=H(n)}if(!t)throw new Error(`No protocol found for build ${e}`);return t}*decodeEventStream(e,t,r,n){if(!this.protocol)throw new Error("Protocol not loaded");let s=0;for(;!e.done();){let l=e.used_bits(),a=e.instance(this.protocol.svaruint32_typeid),c=Object.keys(a)[0],_=a[c];s+=_;let h=n?e.instance(this.protocol.replay_userid_typeid):void 0,o=Number(e.instance(t)),u=r[o];if(!u)throw new Error(`Unknown eventid(${o})`);let f=u[0],b=u[1],d=e.instance(f);d._event=b,d._eventid=o,d._gameloop=s,n&&(d._userid=h),e.byte_align(),d._bits=e.used_bits()-l,yield d}}getDetails(){if(!this.protocol)throw new Error("Protocol not loaded");let e=this.mpq.readFile("replay.details");return e?new w(e,this.protocol.typeinfos).instance(this.protocol.game_details_typeid):null}getInitData(){if(!this.protocol)throw new Error("Protocol not loaded");let e=this.mpq.readFile("replay.initData");return e?new I(e,this.protocol.typeinfos).instance(this.protocol.replay_initdata_typeid):null}getTrackerEvents(){if(!this.protocol)throw new Error("Protocol not loaded");let e=this.mpq.readFile("replay.tracker.events");if(!e)return[];let t=new w(e,this.protocol.typeinfos);return Array.from(this.decodeEventStream(t,this.protocol.tracker_eventid_typeid,this.protocol.tracker_event_types,!1))}getGameEvents(){if(!this.protocol)throw new Error("Protocol not loaded");let e=this.mpq.readFile("replay.game.events");if(!e)return[];let t=new I(e,this.protocol.typeinfos);return Array.from(this.decodeEventStream(t,this.protocol.game_eventid_typeid,this.protocol.game_event_types,!0))}extractFile(e){return this.mpq.readFile(e)}};var L=class{static async analyze(e){try{let t=new x(e);await t.init();let r=t.getDetails(),n=t.getTrackerEvents();if(!r)throw new Error("Missing replay.details from parsed MPQ archive");console.log("Raw TimeUTC:",r?.m_timeUTC,"Type:",typeof r?.m_timeUTC);let s={map:r?.m_title?.toString("utf8"),date:r?this.fileTimeToDate(r.m_timeUTC).toISOString():new Date().toISOString(),length:0,winner:-1,version:{m_build:t.build},teams:{0:{level:0,takedowns:0,ids:[]},1:{level:0,takedowns:0,ids:[]}}},l={};for(let o of r.m_playerList){if(!o||!o.m_toon)continue;let u=o.m_toon,f=`${u.m_region}-${u.m_programId}-${u.m_realm}-${u.m_id}`;l[f]={hero:o.m_hero?.toString("utf8")||"",name:o.m_name?.toString("utf8")||"",tag:"",team:o.m_teamId,win:o.m_result===1,gameStats:{}}}let a=t.extractFile("replay.server.battlelobby");if(a)try{let o=new RegExp("([\\p{L}\\d]{3,24}#\\d{4,10})[z\xD8]?","gu"),u=a.toString("utf8").match(o);if(u){let f=0;for(let b of r.m_playerList){if(!b||!b.m_toon)continue;let d=b.m_name?.toString("utf8");for(;f<u.length;){let p=u[f].split("#"),D=p[0],k=p[1].replace(/[zØ]/g,"");if(f++,D===d){let v=`${b.m_toon.m_region}-${b.m_toon.m_programId}-${b.m_toon.m_realm}-${b.m_toon.m_id}`;l[v]&&(l[v].tag=k);break}}}}}catch(o){console.error("BattleTag regex error:",o)}let c={},_=0,h=0;for(let o of n){if(o._event==="NNet.Replay.Tracker.SStatGameEvent"){let u=o.m_eventName?.toString("utf8");if(u==="PlayerInit"){let f=o.m_intData,b=o.m_stringData,d=f[0].m_value,m=b[1].m_value?.toString("utf8");m&&l[m]&&(c[d]=m)}else u==="GatesOpen"&&(_=o._gameloop)}h=Math.max(h,o._gameloop)}s.length=Math.floor((h-_)/16);for(let o of n)if(o._event==="NNet.Replay.Tracker.SScoreResultEvent"){let u=o.m_instanceList;for(let f of u){let b=f.m_name?.toString("utf8"),d=f.m_values,m=0;if(!b.startsWith("EndOfMatchAward"))for(let p of d)if(p&&p.length>0&&p[0]!==void 0){let D=m+1,k=c[D];if(k&&l[k]){let v=typeof p[0]=="object"&&p[0]!==null&&"m_value"in p[0]?p[0].m_value:p[0];v!=null&&(l[k].gameStats[b]=v)}m++}else p&&p.length===0&&m++}}for(let[o,u]of Object.entries(l)){u.win&&(s.winner=u.team);let f=s.teams[u.team.toString()];f&&(f.level=Math.max(f.level,u.gameStats.Level||0),f.takedowns+=u.gameStats.Takedowns||0,f.ids.push(o))}return{status:1,match:s,players:l}}catch(t){return console.error("ReplayAnalyzer Error:",t),{status:-2,error:String(t)}}}static fileTimeToDate(e){return new Date(Number(e)/1e4-116444736e5)}};0&&(module.exports={ReplayAnalyzer,ReplayParser});
1
+ "use strict";var Ue=Object.create;var Y=Object.defineProperty;var Le=Object.getOwnPropertyDescriptor;var Ne=Object.getOwnPropertyNames;var ze=Object.getPrototypeOf,Xe=Object.prototype.hasOwnProperty;var K=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports),Fe=(t,e)=>{for(var r in e)Y(t,r,{get:e[r],enumerable:!0})},ue=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Ne(e))!Xe.call(t,i)&&i!==r&&Y(t,i,{get:()=>e[i],enumerable:!(n=Le(e,i))||n.enumerable});return t};var Z=(t,e,r)=>(r=t!=null?Ue(ze(t)):{},ue(e||!t||!t.__esModule?Y(r,"default",{value:t,enumerable:!0}):r,t)),Ke=t=>ue(Y({},"__esModule",{value:!0}),t);var be=K((Pt,me)=>{"use strict";var de=[0,1,3,7,15,31,63,127,255],j=function(t){this.stream=t,this.bitOffset=0,this.curByte=0,this.hasByte=!1};j.prototype._ensureByte=function(){this.hasByte||(this.curByte=this.stream.readByte(),this.hasByte=!0)};j.prototype.read=function(t){for(var e=0;t>0;){this._ensureByte();var r=8-this.bitOffset;if(t>=r)e<<=r,e|=de[r]&this.curByte,this.hasByte=!1,this.bitOffset=0,t-=r;else{e<<=t;var n=r-t;e|=(this.curByte&de[t]<<n)>>n,this.bitOffset+=t,t=0}}return e};j.prototype.seek=function(t){var e=t%8,r=(t-e)/8;this.bitOffset=e,this.stream.seek(r),this.hasByte=!1};j.prototype.pi=function(){var t=new Buffer(6),e;for(e=0;e<t.length;e++)t[e]=this.read(8);return t.toString("hex")};me.exports=j});var he=K((Rt,pe)=>{"use strict";var M=function(){};M.prototype.readByte=function(){throw new Error("abstract method readByte() not implemented")};M.prototype.read=function(t,e,r){for(var n=0;n<r;){var i=this.readByte();if(i<0)return n===0?-1:n;t[e++]=i,n++}return n};M.prototype.seek=function(t){throw new Error("abstract method seek() not implemented")};M.prototype.writeByte=function(t){throw new Error("abstract method readByte() not implemented")};M.prototype.write=function(t,e,r){var n;for(n=0;n<r;n++)this.writeByte(t[e++]);return r};M.prototype.flush=function(){};pe.exports=M});var ge=K((Bt,_e)=>{"use strict";_e.exports=(function(){var t=new Uint32Array([0,79764919,159529838,222504665,319059676,398814059,445009330,507990021,638119352,583659535,797628118,726387553,890018660,835552979,1015980042,944750013,1276238704,1221641927,1167319070,1095957929,1595256236,1540665371,1452775106,1381403509,1780037320,1859660671,1671105958,1733955601,2031960084,2111593891,1889500026,1952343757,2552477408,2632100695,2443283854,2506133561,2334638140,2414271883,2191915858,2254759653,3190512472,3135915759,3081330742,3009969537,2905550212,2850959411,2762807018,2691435357,3560074640,3505614887,3719321342,3648080713,3342211916,3287746299,3467911202,3396681109,4063920168,4143685023,4223187782,4286162673,3779000052,3858754371,3904687514,3967668269,881225847,809987520,1023691545,969234094,662832811,591600412,771767749,717299826,311336399,374308984,453813921,533576470,25881363,88864420,134795389,214552010,2023205639,2086057648,1897238633,1976864222,1804852699,1867694188,1645340341,1724971778,1587496639,1516133128,1461550545,1406951526,1302016099,1230646740,1142491917,1087903418,2896545431,2825181984,2770861561,2716262478,3215044683,3143675388,3055782693,3001194130,2326604591,2389456536,2200899649,2280525302,2578013683,2640855108,2418763421,2498394922,3769900519,3832873040,3912640137,3992402750,4088425275,4151408268,4197601365,4277358050,3334271071,3263032808,3476998961,3422541446,3585640067,3514407732,3694837229,3640369242,1762451694,1842216281,1619975040,1682949687,2047383090,2127137669,1938468188,2001449195,1325665622,1271206113,1183200824,1111960463,1543535498,1489069629,1434599652,1363369299,622672798,568075817,748617968,677256519,907627842,853037301,1067152940,995781531,51762726,131386257,177728840,240578815,269590778,349224269,429104020,491947555,4046411278,4126034873,4172115296,4234965207,3794477266,3874110821,3953728444,4016571915,3609705398,3555108353,3735388376,3664026991,3290680682,3236090077,3449943556,3378572211,3174993278,3120533705,3032266256,2961025959,2923101090,2868635157,2813903052,2742672763,2604032198,2683796849,2461293480,2524268063,2284983834,2364738477,2175806836,2238787779,1569362073,1498123566,1409854455,1355396672,1317987909,1246755826,1192025387,1137557660,2072149281,2135122070,1912620623,1992383480,1753615357,1816598090,1627664531,1707420964,295390185,358241886,404320391,483945776,43990325,106832002,186451547,266083308,932423249,861060070,1041341759,986742920,613929101,542559546,756411363,701822548,3316196985,3244833742,3425377559,3370778784,3601682597,3530312978,3744426955,3689838204,3819031489,3881883254,3928223919,4007849240,4037393693,4100235434,4180117107,4259748804,2310601993,2373574846,2151335527,2231098320,2596047829,2659030626,2470359227,2550115596,2947551409,2876312838,2788305887,2733848168,3165939309,3094707162,3040238851,2985771188]),e=function(){var r=4294967295;this.getCRC=function(){return~r>>>0},this.updateCRC=function(n){r=r<<8^t[(r>>>24^n)&255]},this.updateCRCRun=function(n,i){for(;i-- >0;)r=r<<8^t[(r>>>24^n)&255]}};return e})()});var ye=K((Dt,je)=>{je.exports={name:"seek-bzip",version:"2.0.0",contributors:["C. Scott Ananian (http://cscott.net)","Eli Skeggs","Kevin Kwok","Rob Landley (http://landley.net)"],description:"a pure-JavaScript Node.JS module for random-access decoding bzip2 data",main:"./lib/index.js",repository:{type:"git",url:"https://github.com/cscott/seek-bzip.git"},license:"MIT",bin:{"seek-bunzip":"./bin/seek-bunzip","seek-table":"./bin/seek-bzip-table"},directories:{test:"test"},dependencies:{commander:"^6.0.0"},devDependencies:{fibers:"^5.0.0",mocha:"^8.1.0"},scripts:{test:"mocha"}}});var Pe=K((Ct,Ee)=>{"use strict";var Ge=be(),G=he(),ke=ge(),we=ye(),J=20,xe=258,ve=0,Qe=1,$e=2,Ve=6,We=50,qe="314159265359",Ye="177245385090",Te=function(t,e){var r=t[e],n;for(n=e;n>0;n--)t[n]=t[n-1];return t[0]=r,r},g={OK:0,LAST_BLOCK:-1,NOT_BZIP_DATA:-2,UNEXPECTED_INPUT_EOF:-3,UNEXPECTED_OUTPUT_EOF:-4,DATA_ERROR:-5,OUT_OF_MEMORY:-6,OBSOLETE_INPUT:-7,END_OF_BLOCK:-8},B={};B[g.LAST_BLOCK]="Bad file checksum";B[g.NOT_BZIP_DATA]="Not bzip data";B[g.UNEXPECTED_INPUT_EOF]="Unexpected input EOF";B[g.UNEXPECTED_OUTPUT_EOF]="Unexpected output EOF";B[g.DATA_ERROR]="Data error";B[g.OUT_OF_MEMORY]="Out of memory";B[g.OBSOLETE_INPUT]="Obsolete (pre 0.9.5) bzip format not supported.";var T=function(t,e){var r=B[t]||"unknown error";e&&(r+=": "+e);var n=new TypeError(r);throw n.errorCode=t,n},k=function(t,e){this.writePos=this.writeCurrent=this.writeCount=0,this._start_bunzip(t,e)};k.prototype._init_block=function(){var t=this._get_next_block();return t?(this.blockCRC=new ke,!0):(this.writeCount=-1,!1)};k.prototype._start_bunzip=function(t,e){var r=new Buffer(4);(t.read(r,0,4)!==4||String.fromCharCode(r[0],r[1],r[2])!=="BZh")&&T(g.NOT_BZIP_DATA,"bad magic");var n=r[3]-48;(n<1||n>9)&&T(g.NOT_BZIP_DATA,"level out of range"),this.reader=new Ge(t),this.dbufSize=1e5*n,this.nextoutput=0,this.outputStream=e,this.streamCRC=0};k.prototype._get_next_block=function(){var t,e,r,n=this.reader,i=n.pi();if(i===Ye)return!1;i!==qe&&T(g.NOT_BZIP_DATA),this.targetBlockCRC=n.read(32)>>>0,this.streamCRC=(this.targetBlockCRC^(this.streamCRC<<1|this.streamCRC>>>31))>>>0,n.read(1)&&T(g.OBSOLETE_INPUT);var s=n.read(24);s>this.dbufSize&&T(g.DATA_ERROR,"initial position out of bounds");var o=n.read(16),a=new Buffer(256),f=0;for(t=0;t<16;t++)if(o&1<<15-t){var l=t*16;for(r=n.read(16),e=0;e<16;e++)r&1<<15-e&&(a[f++]=l+e)}var c=n.read(3);(c<$e||c>Ve)&&T(g.DATA_ERROR);var u=n.read(15);u===0&&T(g.DATA_ERROR);var b=new Buffer(256);for(t=0;t<c;t++)b[t]=t;var h=new Buffer(u);for(t=0;t<u;t++){for(e=0;n.read(1);e++)e>=c&&T(g.DATA_ERROR);h[t]=Te(b,e)}var m=f+2,p=[],d;for(e=0;e<c;e++){var _=new Buffer(m),y=new Uint16Array(J+1);for(o=n.read(5),t=0;t<m;t++){for(;(o<1||o>J)&&T(g.DATA_ERROR),!!n.read(1);)n.read(1)?o--:o++;_[t]=o}var x,E;for(x=E=_[0],t=1;t<m;t++)_[t]>E?E=_[t]:_[t]<x&&(x=_[t]);d={},p.push(d),d.permute=new Uint16Array(xe),d.limit=new Uint32Array(J+2),d.base=new Uint32Array(J+1),d.minLen=x,d.maxLen=E;var I=0;for(t=x;t<=E;t++)for(y[t]=d.limit[t]=0,o=0;o<m;o++)_[o]===t&&(d.permute[I++]=o);for(t=0;t<m;t++)y[_[t]]++;for(I=o=0,t=x;t<E;t++)I+=y[t],d.limit[t]=I-1,I<<=1,o+=y[t],d.base[t+1]=I-o;d.limit[E+1]=Number.MAX_VALUE,d.limit[E]=I+y[E]-1,d.base[x]=0}var U=new Uint32Array(256);for(t=0;t<256;t++)b[t]=t;var A=0,R=0,fe=0,S,X=this.dbuf=new Uint32Array(this.dbufSize);for(m=0;;){for(m--||(m=We-1,fe>=u&&T(g.DATA_ERROR),d=p[h[fe++]]),t=d.minLen,e=n.read(t);t>d.maxLen&&T(g.DATA_ERROR),!(e<=d.limit[t]);t++)e=e<<1|n.read(1);e-=d.base[t],(e<0||e>=xe)&&T(g.DATA_ERROR);var F=d.permute[e];if(F===ve||F===Qe){A||(A=1,o=0),F===ve?o+=A:o+=2*A,A<<=1;continue}if(A)for(A=0,R+o>this.dbufSize&&T(g.DATA_ERROR),S=a[b[0]],U[S]+=o;o--;)X[R++]=S;if(F>f)break;R>=this.dbufSize&&T(g.DATA_ERROR),t=F-1,S=Te(b,t),S=a[S],U[S]++,X[R++]=S}for((s<0||s>=R)&&T(g.DATA_ERROR),e=0,t=0;t<256;t++)r=e+U[t],U[t]=e,e=r;for(t=0;t<R;t++)S=X[t]&255,X[U[S]]|=t<<8,U[S]++;var q=0,ce=0,le=0;return R&&(q=X[s],ce=q&255,q>>=8,le=-1),this.writePos=q,this.writeCurrent=ce,this.writeCount=R,this.writeRun=le,!0};k.prototype._read_bunzip=function(t,e){var r,n,i;if(this.writeCount<0)return 0;for(var s=0,o=this.dbuf,a=this.writePos,f=this.writeCurrent,l=this.writeCount,c=this.outputsize,u=this.writeRun;l;){for(l--,n=f,a=o[a],f=a&255,a>>=8,u++===3?(r=f,i=n,f=-1):(r=1,i=f),this.blockCRC.updateCRCRun(i,r);r--;)this.outputStream.writeByte(i),this.nextoutput++;f!=n&&(u=0)}return this.writeCount=l,this.blockCRC.getCRC()!==this.targetBlockCRC&&T(g.DATA_ERROR,"Bad block CRC (got "+this.blockCRC.getCRC().toString(16)+" expected "+this.targetBlockCRC.toString(16)+")"),this.nextoutput};var ie=function(t){if("readByte"in t)return t;var e=new G;return e.pos=0,e.readByte=function(){return t[this.pos++]},e.seek=function(r){this.pos=r},e.eof=function(){return this.pos>=t.length},e},Se=function(t){var e=new G,r=!0;if(t)if(typeof t=="number")e.buffer=new Buffer(t),r=!1;else{if("writeByte"in t)return t;e.buffer=t,r=!1}else e.buffer=new Buffer(16384);return e.pos=0,e.writeByte=function(n){if(r&&this.pos>=this.buffer.length){var i=new Buffer(this.buffer.length*2);this.buffer.copy(i),this.buffer=i}this.buffer[this.pos++]=n},e.getBuffer=function(){if(this.pos!==this.buffer.length){if(!r)throw new TypeError("outputsize does not match decoded input");var n=new Buffer(this.pos);this.buffer.copy(n,0,0,this.pos),this.buffer=n}return this.buffer},e._coerced=!0,e};k.Err=g;k.decode=function(t,e,r){for(var n=ie(t),i=Se(e),s=new k(n,i);!("eof"in n&&n.eof());)if(s._init_block())s._read_bunzip();else{var o=s.reader.read(32)>>>0;if(o!==s.streamCRC&&T(g.DATA_ERROR,"Bad stream CRC (got "+s.streamCRC.toString(16)+" expected "+o.toString(16)+")"),r&&"eof"in n&&!n.eof())s._start_bunzip(n,i);else break}if("getBuffer"in i)return i.getBuffer()};k.decodeBlock=function(t,e,r){var n=ie(t),i=Se(r),s=new k(n,i);s.reader.seek(e);var o=s._get_next_block();if(o&&(s.blockCRC=new ke,s.writeCopies=0,s._read_bunzip()),"getBuffer"in i)return i.getBuffer()};k.table=function(t,e,r){var n=new G;n.delegate=ie(t),n.pos=0,n.readByte=function(){return this.pos++,this.delegate.readByte()},n.delegate.eof&&(n.eof=n.delegate.eof.bind(n.delegate));var i=new G;i.pos=0,i.writeByte=function(){this.pos++};for(var s=new k(n,i),o=s.dbufSize;!("eof"in n&&n.eof());){var a=n.pos*8+s.reader.bitOffset;if(s.reader.hasByte&&(a-=8),s._init_block()){var f=i.pos;s._read_bunzip(),e(a,i.pos-f)}else{var l=s.reader.read(32);if(r&&"eof"in n&&!n.eof())s._start_bunzip(n,i),console.assert(s.dbufSize===o,"shouldn't change block size within multistream file");else break}}};k.Stream=G;k.version=we.version;k.license=we.license;Ee.exports=k});var St={};Fe(St,{ReplayAnalyzer:()=>ne,ReplayParser:()=>z});module.exports=Ke(St);var De=Z(require("fs")),Q=Z(require("zlib")),Ze=Pe(),Re=512,Je=65536,et=16777216,tt=67108864,rt=2147483648,nt={TABLE_OFFSET:0,HASH_A:1,HASH_B:2,TABLE:3};function it(){let t=1048577,e=new Uint32Array(256*5);for(let r=0;r<256;r++){let n=r;for(let i=0;i<5;i++){t=(t*125+3)%2796203;let s=(t&65535)<<16;t=(t*125+3)%2796203;let o=t&65535;e[n]=(s|o)>>>0,n+=256}}return e}var Be=it(),ee=class{file;header;hashTable;blockTable;files;constructor(e,r=!0){if(Buffer.isBuffer(e)?this.file=e:this.file=De.readFileSync(e),this.header=this.readHeader(),this.hashTable=this.readTable("hash"),this.blockTable=this.readTable("block"),r){let n=this.readFile("(listfile)");n?this.files=n.toString("utf8").trim().split(`\r
2
+ `):this.files=null}else this.files=null}readHeader(){let e=this.file.toString("utf8",0,4),r;if(e==="MPQ")r=this.readMPQHeader(),r.offset=0;else if(e==="MPQ\x1B"){let n=this.readMPQUserDataHeader();r=this.readMPQHeader(n.mpqHeaderOffset),r.offset=n.mpqHeaderOffset,r.userDataHeader=n}else throw new Error("Invalid MPQ file header");return r}readMPQHeader(e=0){let r=this.file.subarray(e,e+32),n={magic:r.toString("utf8",0,4),headerSize:r.readUInt32LE(4),archiveSize:r.readUInt32LE(8),formatVersion:r.readUInt16LE(12),sectorSizeShift:r.readUInt16LE(14),hashTableOffset:r.readUInt32LE(16),blockTableOffset:r.readUInt32LE(20),hashTableEntries:r.readUInt32LE(24),blockTableEntries:r.readUInt32LE(28)};if(n.formatVersion===1){let i=this.file.subarray(e+32,e+32+12);n.extendedBlockTableOffset=i.readUInt32LE(0)+i.readUInt32LE(4)*4294967296,n.hashTableOffsetHigh=i.readInt8(8),n.blockTableOffsetHigh=i.readInt8(10)}return n}readMPQUserDataHeader(){let e=this.file.subarray(0,16),r={magic:e.toString("utf8",0,4),userDataSize:e.readUInt32LE(4),mpqHeaderOffset:e.readUInt32LE(8),userDataHeaderSize:e.readUInt32LE(12)};return r.content=this.file.subarray(16,16+r.userDataHeaderSize),r}readTable(e){let r=e==="hash"?"hashTableOffset":"blockTableOffset",n=e==="hash"?"hashTableEntries":"blockTableEntries",i=this.header[r],s=this.header[n];if(i==null||s==null)throw new Error("Missing "+e+" offset or entries");let o=this.hash("("+e+" table)","TABLE"),a=this.file.subarray(i+(this.header.offset||0),i+(this.header.offset||0)+s*16);a=this.decrypt(a,o);let f=[];for(let l=0;l<s;l++){let c=a.subarray(l*16,l*16+16);e==="hash"?f.push({hashA:c.readUInt32LE(0),hashB:c.readUInt32LE(4),locale:c.readUInt16LE(8),platform:c.readUInt16LE(10),blockTableIndex:c.readUInt32LE(12)}):f.push({offset:c.readUInt32LE(0),archivedSize:c.readUInt32LE(4),size:c.readUInt32LE(8),flags:c.readUInt32LE(12)})}return f}getHashTableEntry(e){let r=this.hash(e,"HASH_A"),n=this.hash(e,"HASH_B");for(let i of this.hashTable)if(i.hashA===r&&i.hashB===n)return i}readFile(e,r=!1){function n(f){let l=f[0];if(l===0)return f;if(l===2)return Q.inflateSync(f.subarray(1));if(l===16)return Ze.decode(f.subarray(1));try{return Q.inflateSync(f.subarray(1))}catch{return Q.inflateRawSync(f.subarray(1))}}let i=this.getHashTableEntry(e);if(!i)return null;let s=this.blockTable[i.blockTableIndex];if(!s||!(s.flags&rt))return null;if(s.archivedSize===0)return Buffer.alloc(0);let o=s.offset+(this.header.offset||0),a=this.file.subarray(o,o+s.archivedSize);if(s.flags&Je)throw new Error("Encryption is not supported");if(s.flags&et)s.flags&Re&&(r||s.size>s.archivedSize)&&(a=n(a));else{let f=512<<this.header.sectorSizeShift,l=Math.trunc(s.size/f)+1,c=!1;s.flags&tt&&(c=!0,l+=1);let u=[];for(let p=0;p<l+1;p++)u.push(a.readUInt32LE(4*p));let b=u.length-(c?2:1),h=[],m=s.size;for(let p=0;p<b;p++){let d=a.subarray(u[p],u[p+1]);s.flags&Re&&(r||m>d.length)&&(d=n(d)),m-=d.length,h.push(d)}a=Buffer.concat(h)}return a}hash(e,r){let n=2146271213,i=4008636142;for(let s=0;s<e.length;s++){let o=e.toUpperCase().charCodeAt(s);n=(Be[(nt[r]<<8)+o]^n+i)>>>0,i=o+n+i+(i<<5)+3>>>0}return n}decrypt(e,r){let n=r>>>0,i=4008636142,s=Buffer.alloc(e.length),o=e.length/4;for(let a=0;a<o;a++){i=i+Be[1024+(n&255)]>>>0;let f=e.readUInt32LE(a*4);f=(f^n+i)>>>0,n=((~n<<21)+286331153|n>>>11)>>>0,i=f+i+(i<<5)+3>>>0,s.writeUInt32LE(f,a*4)}return s}};var $=class extends Error{constructor(e="Truncated Buffer"){super(e),this.name="TruncatedError"}},H=class extends Error{constructor(e="Corrupted Buffer"){super(e),this.name="CorruptedError"}},V=class{_data;_used;_next;_nextbits;_bigendian;constructor(e,r="big"){this._data=e,this._used=0,this._next=0,this._nextbits=0,this._bigendian=r==="big"}done(){return this._nextbits===0&&this._used>=this._data.length}used_bits(){return this._used*8-this._nextbits}byte_align(){this._nextbits=0}read_aligned_bytes(e){if(this.byte_align(),this._used+e>this._data.length)throw new $;let r=this._data.subarray(this._used,this._used+e);return this._used+=e,r}read_bits(e){let r=0,n=0;for(;n!==e;){if(this._nextbits===0){if(this.done())throw new $;this._next=this._data[this._used],this._used+=1,this._nextbits=8}let i=Math.min(e-n,this._nextbits),s=this._next&(1<<i)-1;this._bigendian?r+=s*Math.pow(2,e-n-i):r+=s*Math.pow(2,n),this._next>>=i,this._nextbits-=i,n+=i}return r}read_bits_bigint(e){let r=0n,n=0;for(;n!==e;){if(this._nextbits===0){if(this.done())throw new $;this._next=this._data[this._used],this._used+=1,this._nextbits=8}let i=Math.min(e-n,this._nextbits),s=BigInt(this._next&(1<<i)-1);this._bigendian?r|=s<<BigInt(e-n-i):r|=s<<BigInt(n),this._next>>=i,this._nextbits-=i,n+=i}return r}read_unaligned_bytes(e){let r=Buffer.alloc(e);for(let n=0;n<e;n++)r[n]=this.read_bits(8);return r}};var W=class{_buffer;_typeinfos;constructor(e,r){this._buffer=new V(e),this._typeinfos=r}instance(e){if(e>=this._typeinfos.length)throw new H(`Invalid typeid ${e}`);let r=this._typeinfos[e],n=r[0],i=r[1]||[],s=this[n];if(typeof s!="function")throw new Error(`Decoder method ${n} not implemented`);return s.apply(this,i)}byte_align(){this._buffer.byte_align()}done(){return this._buffer.done()}used_bits(){return this._buffer.used_bits()}_array(e,r){let n=this._int(e),i=new Array(n);for(let s=0;s<n;s++)i[s]=this.instance(r);return i}_bitarray(e){let r=this._int(e);return[r,this._buffer.read_bits(r)]}_blob(e){let r=this._int(e);return this._buffer.read_aligned_bytes(r)}_bool(){return this._int([0,1])!==0}_choice(e,r){let n=this._int(e);if(!(n in r))throw new H(`Choice tag ${n} not found`);let i=r[n];return{[i[0]]:this.instance(i[1])}}_fourcc(){let e=this._buffer.read_bits(32),r=Buffer.alloc(4);return r.writeUInt32BE(e,0),r.toString("ascii")}_int(e){return e[0]+this._buffer.read_bits(e[1])}_null(){return null}_optional(e){return this._bool()?this.instance(e):null}_real32(){return this._buffer.read_unaligned_bytes(4).readFloatBE(0)}_real64(){return this._buffer.read_unaligned_bytes(8).readDoubleBE(0)}_struct(e){let r={};for(let n of e)if(n[0]==="__parent"){let i=this.instance(n[1]);if(typeof i=="object"&&i!==null)r={...r,...i};else{if(e.length===1)return i;r[n[0]]=i}}else r[n[0]]=this.instance(n[1]);return r}},L=class{_buffer;_typeinfos;constructor(e,r){this._buffer=new V(e),this._typeinfos=r}instance(e){if(e>=this._typeinfos.length)throw new H(`Invalid typeid ${e}`);let r=this._typeinfos[e],n=r[0],i=r[1]||[],s=this[n];if(typeof s!="function")throw new Error(`Decoder method ${n} not implemented`);return s.apply(this,i)}byte_align(){this._buffer.byte_align()}done(){return this._buffer.done()}used_bits(){return this._buffer.used_bits()}_expect_skip(e){if(this._buffer.read_bits(8)!==e)throw new H(`Expected skip ${e}`)}_vint(){let e=this._buffer.read_bits(8),r=(e&1)!==0,n=BigInt(e>>1&63),i=6n;for(;(e&128)!==0;)e=this._buffer.read_bits(8),n|=BigInt(e&127)<<i,i+=7n;let s=r?-n:n;return s>=BigInt(Number.MIN_SAFE_INTEGER)&&s<=BigInt(Number.MAX_SAFE_INTEGER)?Number(s):s}_array(e,r){this._expect_skip(0);let n=Number(this._vint()),i=new Array(n);for(let s=0;s<n;s++)i[s]=this.instance(r);return i}_bitarray(e){this._expect_skip(1);let r=Number(this._vint());return[r,this._buffer.read_aligned_bytes(Math.floor((r+7)/8))]}_blob(e){this._expect_skip(2);let r=Number(this._vint());return this._buffer.read_aligned_bytes(r)}_bool(){return this._expect_skip(6),this._buffer.read_bits(8)!==0}_choice(e,r){this._expect_skip(3);let n=Number(this._vint());if(!(n in r))return this._skip_instance(),{};let i=r[n];return{[i[0]]:this.instance(i[1])}}_fourcc(){return this._expect_skip(7),this._buffer.read_aligned_bytes(4)}_int(e){return this._expect_skip(9),Number(this._vint())}_null(){return null}_optional(e){return this._expect_skip(4),this._buffer.read_bits(8)!==0?this.instance(e):null}_real32(){return this._expect_skip(7),this._buffer.read_aligned_bytes(4).readFloatBE(0)}_real64(){return this._expect_skip(8),this._buffer.read_aligned_bytes(8).readDoubleBE(0)}_struct(e){this._expect_skip(5);let r={},n=Number(this._vint());for(let i=0;i<n;i++){let s=Number(this._vint()),o=e.find(a=>a[2]===s);if(o)if(o[0]==="__parent"){let a=this.instance(o[1]);typeof a=="object"&&a!==null?r={...r,...a}:e.length===1?r=a:r[o[0]]=a}else r[o[0]]=this.instance(o[1]);else this._skip_instance()}return r}_skip_instance(){let e=this._buffer.read_bits(8);if(e===0){let r=Number(this._vint());for(let n=0;n<r;n++)this._skip_instance()}else if(e===1){let r=Number(this._vint());this._buffer.read_aligned_bytes(Math.floor((r+7)/8))}else if(e===2){let r=Number(this._vint());this._buffer.read_aligned_bytes(r)}else if(e===3)this._vint(),this._skip_instance();else if(e===4)this._buffer.read_bits(8)!==0&&this._skip_instance();else if(e===5){let r=Number(this._vint());for(let n=0;n<r;n++)this._vint(),this._skip_instance()}else e===6?this._buffer.read_aligned_bytes(1):e===7?this._buffer.read_aligned_bytes(4):e===8?this._buffer.read_aligned_bytes(8):e===9&&this._vint()}};var N=Z(require("fs")),D=Z(require("path"));function st(){let t=[];try{t.push(D.default.resolve(__dirname,"..","protocols")),t.push(D.default.resolve(__dirname,"..","..","protocols"))}catch{}t.push(D.default.resolve(process.cwd(),"protocols"));let e=process.cwd();for(;e!==D.default.dirname(e);){let r=D.default.join(e,"node_modules","@astefanski","storm-parser","protocols");t.push(r),e=D.default.dirname(e)}for(let r of t)if(N.default.existsSync(r)&&N.default.readdirSync(r).some(n=>n.endsWith(".json")))return r;throw new Error(`@astefanski/storm-parser: Protocols directory not found. Did postinstall run? Try: npx tsx node_modules/@astefanski/storm-parser/scripts/postinstall.ts
3
+ Searched: `+t.join(", "))}var se=new Map,oe=null;function Ce(){return oe||(oe=st()),oe}function te(t){if(se.has(t))return se.get(t);let e=Ce(),r=D.default.join(e,`protocol${t}.json`);if(!N.default.existsSync(r))return null;let n=JSON.parse(N.default.readFileSync(r,"utf-8"));return se.set(t,n),n}function Ie(){let t=Ce();return N.default.readdirSync(t).filter(e=>/^protocol\d+\.json$/.test(e)).map(e=>parseInt(e.match(/\d+/)[0],10)).sort((e,r)=>e-r)}var z=class{mpq;header;build=0;protocol;baseProtocol;constructor(e){this.mpq=new ee(e,!1)}init(){let e=te(29406);if(!e)throw new Error("Base protocol29406 not found. Did postinstall run? Try: npx tsx node_modules/@astefanski/storm-parser/scripts/postinstall.ts");this.baseProtocol=e;let r=this.mpq.header.userDataHeader;if(!r||!r.content)throw new Error("Replay does not have a user data header");let n=new L(r.content,this.baseProtocol.typeinfos);this.header=n.instance(this.baseProtocol.replay_header_typeid),this.build=this.header.m_version.m_baseBuild,this.protocol=this.loadProtocolForBuild(this.build)}loadProtocolForBuild(e){let r=te(e);if(!r){let n=Ie(),i=n[0];for(let s of n)s<=e&&s>i&&(i=s);r=te(i)}if(!r)throw new Error(`No protocol found for build ${e}`);return r}*decodeEventStream(e,r,n,i){if(!this.protocol)throw new Error("Protocol not loaded");let s=0;for(;!e.done();){let o=e.used_bits(),a=e.instance(this.protocol.svaruint32_typeid),f=Object.keys(a)[0],l=a[f];s+=l;let c=i?e.instance(this.protocol.replay_userid_typeid):void 0,u=Number(e.instance(r)),b=n[u];if(!b)throw new Error(`Unknown eventid(${u})`);let h=b[0],m=b[1],p=e.instance(h);p._event=m,p._eventid=u,p._gameloop=s,i&&(p._userid=c),e.byte_align(),p._bits=e.used_bits()-o,yield p}}getDetails(){if(!this.protocol)throw new Error("Protocol not loaded");let e=this.mpq.readFile("replay.details");return e?new L(e,this.protocol.typeinfos).instance(this.protocol.game_details_typeid):null}getInitData(){if(!this.protocol)throw new Error("Protocol not loaded");let e=this.mpq.readFile("replay.initData");return e?new W(e,this.protocol.typeinfos).instance(this.protocol.replay_initdata_typeid):null}getTrackerEvents(){if(!this.protocol)throw new Error("Protocol not loaded");let e=this.mpq.readFile("replay.tracker.events");if(!e)return[];let r=new L(e,this.protocol.typeinfos);return Array.from(this.decodeEventStream(r,this.protocol.tracker_eventid_typeid,this.protocol.tracker_event_types,!1))}getGameEvents(){if(!this.protocol)throw new Error("Protocol not loaded");let e=this.mpq.readFile("replay.game.events");if(!e)return[];let r=new W(e,this.protocol.typeinfos);return Array.from(this.decodeEventStream(r,this.protocol.game_eventid_typeid,this.protocol.game_event_types,!0))}extractFile(e){return this.mpq.readFile(e)}getHeader(){return this.header}getBuild(){return this.build}};var Ae={TownCannonTowerL2:"Fort Tower",TownCannonTowerL3:"Keep Tower",TownTownHallL2:"Fort",TownTownHallL3:"Keep",TownMoonwellL2:"Fort Well",TownMoonwellL3:"Keep Well"},ot={MercLanerMeleeKnight:"Bruiser Camp",MercLanerRangedMage:"Bruiser Camp",MercLanerSiegeGiant:"Siege Camp",MercLanerRangedMinion:"Siege Camp"};function O(t){return Buffer.isBuffer(t)?t.toString("utf8"):typeof t=="string"?t:String(t??"")}function v(t,e){if(!t)return;let r=t.find(n=>O(n.m_key)===e);return r!==void 0?r.m_value:void 0}function re(t,e){if(!t)return;let r=t.find(n=>O(n.m_key)===e);return r!==void 0?O(r.m_value):void 0}function w(t,e){if(!t)return;let r=t.find(n=>O(n.m_key)===e);return r!==void 0?r.m_value:void 0}function ae(t,e){return`${t}-${e}`}function P(t,e){return(t-e)/16}function Me(t,e,r){let n={playerIDMap:{},loopGameStart:0,loopGameEnd:0,unitIndex:{},heroUnits:{},heroLives:{}};r.levelTimes={0:{},1:{}},r.takedowns=[],r.structures={},r.XPBreakdown=[],r.mercs={captures:[],units:{}},r.objective={0:{count:0,events:[]},1:{count:0,events:[]},type:r.map||""};for(let i of t)switch(n.loopGameEnd=Math.max(n.loopGameEnd,i._gameloop),i._event){case"NNet.Replay.Tracker.SStatGameEvent":at(i,n,e,r);break;case"NNet.Replay.Tracker.SUnitBornEvent":lt(i,n,r);break;case"NNet.Replay.Tracker.SUnitDiedEvent":ut(i,n,r);break;case"NNet.Replay.Tracker.SUnitOwnerChangeEvent":dt(i,n);break}return r.loopGameStart=n.loopGameStart,r.loopLength=n.loopGameEnd,r.length=(n.loopGameEnd-n.loopGameStart)/16,mt(n,e),{playerIDMap:n.playerIDMap}}function at(t,e,r,n){let i=O(t.m_eventName),s=t.m_intData,o=t.m_stringData,a=t.m_fixedData;switch(i){case"PlayerInit":{let f=v(s,"PlayerID"),l=re(o,"ToonHandle");f!==void 0&&l&&r[l]&&(e.playerIDMap[f]=l);break}case"GatesOpen":e.loopGameStart=t._gameloop;break;case"LevelUp":{let f=v(s,"PlayerID"),l=v(s,"Level");if(f===void 0||l===void 0)break;let c;if(f>=1&&f<=5)c="0";else if(f>=6&&f<=10)c="1";else break;n.levelTimes[c][String(l)]||(n.levelTimes[c][String(l)]={loop:t._gameloop,level:l,team:c,time:P(t._gameloop,e.loopGameStart)});break}case"TalentChosen":{let f=v(s,"PlayerID"),l=re(o,"PurchaseName");if(f===void 0||!l)break;let c=e.playerIDMap[f];if(!c||!r[c])break;let u=["Tier1Choice","Tier2Choice","Tier3Choice","Tier4Choice","Tier5Choice","Tier6Choice","Tier7Choice"];for(let b of u)if(!r[c].talents[b]){r[c].talents[b]=l;break}break}case"PlayerDeath":{let f=v(s,"PlayerID"),l=v(s,"KillingPlayer"),c=w(a,"PositionX")??0,u=w(a,"PositionY")??0;if(f===void 0)break;let b=e.playerIDMap[f];if(!b)break;let h={player:b,hero:r[b]?.hero||""},m=[],p=r[b]?.team;if(l&&l>0){let _=e.playerIDMap[l];_&&r[_]&&m.push({player:_,hero:r[_].hero})}for(let[_,y]of Object.entries(e.playerIDMap)){let x=r[y];!x||x.team===p||parseInt(_)===l||m.push({player:y,hero:x.hero})}let d={loop:t._gameloop,time:P(t._gameloop,e.loopGameStart),x:c,y:u,killers:m,victim:h};n.takedowns.push(d),r[b]&&r[b].deaths.push(d);for(let _ of m)r[_.player]&&r[_.player].takedowns.push(d);break}case"PeriodicXPBreakdown":{let f=v(s,"Team");if(f===void 0)break;let l={GameTime:v(s,"GameTime")??0,PreviousGameTime:v(s,"PreviousGameTime")??0,MinionXP:w(a,"MinionXP")??0,CreepXP:w(a,"CreepXP")??0,StructureXP:w(a,"StructureXP")??0,HeroXP:w(a,"HeroXP")??0,TrickleXP:w(a,"TrickleXP")??0};n.XPBreakdown.push({loop:t._gameloop,time:P(t._gameloop,e.loopGameStart),team:f,teamLevel:v(s,"TeamLevel")??0,breakdown:l,theoreticalMinionXP:v(s,"TheoreticalMinionXP")??0});break}case"EndOfGameXPBreakdown":{let f=v(s,"Team");if(f===void 0)break;n.XPBreakdown.push({loop:t._gameloop,time:P(t._gameloop,e.loopGameStart),team:f,theoreticalMinionXP:v(s,"TheoreticalMinionXP")??0,breakdown:{GameTime:0,PreviousGameTime:0,MinionXP:w(a,"MinionXP")??0,CreepXP:w(a,"CreepXP")??0,StructureXP:w(a,"StructureXP")??0,HeroXP:w(a,"HeroXP")??0,TrickleXP:w(a,"TrickleXP")??0}});break}case"JungleCampCapture":{let f=v(s,"CampTeam")??v(s,"Team")??0;n.mercs.captures.push({loop:t._gameloop,type:re(o,"CampType")??re(o,"Result")??"Unknown Camp",team:f,time:P(t._gameloop,e.loopGameStart)});break}case"EndOfGameTalentChoices":{let f=v(s,"PlayerID");if(f===void 0)break;let l=e.playerIDMap[f];if(!l||!r[l])break;let c={},u=["Tier1Choice","Tier2Choice","Tier3Choice","Tier4Choice","Tier5Choice","Tier6Choice","Tier7Choice"];if(o)for(let b=0;b<o.length&&b<u.length;b++){let h=O(o[b].m_value);h&&(c[u[b]]=h)}r[l].talents=c;break}default:ct(i,t,e,n,s,a);break}}var ft=new Set(["SoulEatersSpawned","TributeCollected","RavenCurseActivated","AltarCaptured","SkyTempleShotsFired","DragonKnightActivated","GardenTerrorActivated","InfernalShrineCaptured","PunisherKilled","VolskayaVehicleCapture","BraxisWaveStart","ImmortalDefeated","NukeExploded","PayloadDelivered","AlteracCavalryCharge","AlteracCavalry"]);function ct(t,e,r,n,i,s){if(!ft.has(t)||!i)return;let o=v(i,"Team")??v(i,"Event")??0,a=o===0||o===1?o:0,f={team:o,loop:e._gameloop,time:P(e._gameloop,r.loopGameStart),score:v(i,"Score"),duration:w(s,"Duration")};n.objective[a].events.push(f),n.objective[a].count=n.objective[a].events.length}function lt(t,e,r){let n=O(t.m_unitTypeName),i=t.m_unitTagIndex,s=t.m_unitTagRecycle,o=ae(i,s),a=t.m_controlPlayerId??t.m_upkeepPlayerId,f=t.m_x??0,l=t.m_y??0,c;if(a>=1&&a<=5?c=0:a>=6&&a<=10?c=1:a===11?c=0:a===12?c=1:c=a<=5?0:1,e.unitIndex[o]={type:n,playerId:a,team:c,x:f,y:l,bornLoop:t._gameloop},n.startsWith("Town")&&Ae[n]&&(r.structures[o]={type:n,name:Ae[n],tag:i,rtag:s,x:f,y:l,team:c}),n.startsWith("Hero")&&a>=1&&a<=10){e.heroUnits[o]=a,e.heroLives[a]||(e.heroLives[a]=[]);let u=P(t._gameloop,e.loopGameStart);e.heroLives[a].push({born:u,locations:[{x:f,y:l,time:u}],duration:0})}if(ot[n]){let b=r.mercs.captures[r.mercs.captures.length-1]?.loop??t._gameloop;r.mercs.units[o]={loop:b,team:c,type:n,locations:[{x:f,y:l}],time:P(b,e.loopGameStart),duration:0}}}function ut(t,e,r){let n=ae(t.m_unitTagIndex,t.m_unitTagRecycle),i=P(t._gameloop,e.loopGameStart);r.structures[n]&&(r.structures[n].destroyedLoop=t._gameloop,r.structures[n].destroyed=i),r.mercs.units[n]&&(r.mercs.units[n].duration=i-r.mercs.units[n].time);let s=e.heroUnits[n];if(s!==void 0&&e.heroLives[s]){let o=e.heroLives[s],a=o[o.length-1];a&&a.died===void 0&&(a.died=i,a.duration=i-a.born)}}function dt(t,e){let r=ae(t.m_unitTagIndex,t.m_unitTagRecycle),n=t.m_controlPlayerId??t.m_upkeepPlayerId;e.unitIndex[r]&&(e.unitIndex[r].playerId=n,n>=1&&n<=5?e.unitIndex[r].team=0:n>=6&&n<=10&&(e.unitIndex[r].team=1))}function mt(t,e){for(let[r,n]of Object.entries(t.heroLives)){let i=parseInt(r,10),s=t.playerIDMap[i];if(!s||!e[s])continue;for(let a of n)if(a.died===void 0){let f=a.locations[a.locations.length-1];a.duration=f?f.time-a.born:0}let o="";for(let[a,f]of Object.entries(t.heroUnits))if(f===i){o=a;break}o&&(e[s].units[o]={lives:n})}}var bt=["DamageTaken","CreepDamage","Healing","HeroDamage","MinionDamage","SelfHealing","SiegeDamage","ProtectionGivenToAllies","TeamfightDamageTaken","TeamfightHealingDone","TeamfightHeroDamage","TimeCCdEnemyHeroes","TimeRootingEnemyHeroes","TimeSpentDead","TimeStunningEnemyHeroes","TimeSilencingEnemyHeroes"];function pt(){return{DamageTaken:0,CreepDamage:0,Healing:0,HeroDamage:0,MinionDamage:0,SelfHealing:0,SiegeDamage:0,ProtectionGivenToAllies:0,TeamfightDamageTaken:0,TeamfightHealingDone:0,TeamfightHeroDamage:0,TimeCCdEnemyHeroes:0,TimeRootingEnemyHeroes:0,TimeSpentDead:0,TimeStunningEnemyHeroes:0,TimeSilencingEnemyHeroes:0,avgTimeSpentDead:0,timeDeadPct:0}}function ht(){return{mercCaptures:0,mercUptime:0,mercUptimePercent:0,structures:{},KDA:0,PPK:0,timeTo10:0,totals:pt(),levelAdvTime:0,maxLevelAdv:0,avgLevelAdv:0,levelAdvPct:0,uptime:[],uptimeHistogram:{},wipes:0,avgHeroesAlive:0,aces:0,timeWithHeroAdv:0,pctWithHeroAdv:0,passiveXPRate:0,passiveXPDiff:0,passiveXPGain:0}}function Oe(t,e){_t(t,e),yt(t,e),xt(t),vt(t),Tt(t,e),wt(t)}function _t(t,e){for(let r of["0","1"]){let n=t.teams[r];if(!n)continue;n.names=[],n.heroes=[],n.tags=[],n.stats=ht();for(let u of n.ids){let b=e[u];b&&(n.names.push(b.name),n.heroes.push(b.hero),n.tags.push(b.tag))}for(let u of n.ids){let b=e[u];if(b)for(let h of bt){let m=b.gameStats[h];typeof m=="number"&&(n.stats.totals[h]+=m)}}let i=n.ids.reduce((u,b)=>u+(e[b]?.gameStats.Deaths??0),0);i>0&&(n.stats.totals.avgTimeSpentDead=n.stats.totals.TimeSpentDead/i),t.length>0&&(n.stats.totals.timeDeadPct=n.stats.totals.TimeSpentDead/(t.length*n.ids.length));let s=n.takedowns,o=i;n.stats.KDA=o>0?s/o:s,n.stats.PPK=s>0?t.takedowns.filter(u=>n.ids.includes(u.killers[0]?.player)).reduce((u,b)=>u+b.killers.length,0)/s:0;let a=t.levelTimes[r];a?.["10"]&&(n.stats.timeTo10=a[10].time);let f=parseInt(r,10),l=t.mercs.captures.filter(u=>u.team===f);n.stats.mercCaptures=l.length;let c=0;for(let u of Object.values(t.mercs.units))u.team===f&&u.duration>0&&(c+=u.duration);n.stats.mercUptime=c,n.stats.mercUptimePercent=t.length>0?c/t.length:0,gt(t,n,r)}}function gt(t,e,r){let n=parseInt(r,10),i=n===0?1:0,s={};for(let o of Object.values(t.structures)){let a=o.name;s[a]||(s[a]={lost:0,destroyed:0,first:t.length}),o.team===i&&o.destroyed!==void 0&&(s[a].destroyed++,s[a].first=Math.min(s[a].first,o.destroyed)),o.team===n&&o.destroyed!==void 0&&s[a].lost++}e.stats.structures=s}function yt(t,e){let r=t.length/60;for(let n of Object.values(e)){let i=n.gameStats,s=i.Deaths??0,o=i.TeamTakedowns??0;r>0&&(i.DPM=(i.HeroDamage??0)/r,i.HPM=((i.Healing??0)+(i.SelfHealing??0))/r,i.XPM=(i.ExperienceContribution??0)/r),i.KDA=s>0?(i.Takedowns??0)/s:i.Takedowns??0,i.KillParticipation=o>0?(i.Takedowns??0)/o:0,i.damageDonePerDeath=s>0?(i.HeroDamage??0)/s:i.HeroDamage??0,i.damageTakenPerDeath=s>0?(i.DamageTaken??0)/s:i.DamageTaken??0,i.healingDonePerDeath=s>0?((i.Healing??0)+(i.SelfHealing??0))/s:(i.Healing??0)+(i.SelfHealing??0),i.length=t.length}}function xt(t){let e=0,r=0,n=new Set(t.teams[0]?.ids||[]);for(let i of t.takedowns)n.has(i.victim.player)?r++:e++;t.team0Takedowns=e,t.team1Takedowns=r}function vt(t){let e=t.levelTimes[0]||{},r=t.levelTimes[1]||{},n=[];for(let l of Object.values(e))n.push({time:l.time,team:0,level:l.level});for(let l of Object.values(r))n.push({time:l.time,team:1,level:l.level});if(n.sort((l,c)=>l.time-c.time),n.length===0){t.levelAdvTimeline=[];return}let i=[],s=0,o=0,a=n[0].time;for(let l of n){let c=s-o;l.time>a&&i.push({start:a,end:l.time,levelDiff:c,length:l.time-a}),l.team===0?s=l.level:o=l.level,a=l.time}let f=s-o;t.length>a&&i.push({start:a,end:t.length,levelDiff:f,length:t.length-a}),t.levelAdvTimeline=i;for(let l of["0","1"]){let c=t.teams[l];if(!c)continue;let u=l==="0"?1:-1,b=0,h=0,m=0,p=0;for(let d of i){let _=d.levelDiff*u;_>0&&(b+=d.length),h=Math.max(h,_),m+=_*d.length,p+=d.length}c.stats.levelAdvTime=b,c.stats.maxLevelAdv=h,c.stats.avgLevelAdv=p>0?m/p:0,c.stats.levelAdvPct=t.length>0?b/t.length:0}}function Tt(t,e){for(let s of["0","1"]){let o=t.teams[s];if(!o)continue;let a=[];for(let d of o.ids){let _=e[d];if(_)for(let y of _.deaths){a.push({time:y.time,delta:-1});let x=y.time+kt(_.gameStats.Level??1,y.time,t.length);x<t.length&&a.push({time:x,delta:1})}}a.sort((d,_)=>d.time-_.time);let f=[{time:0,heroes:o.ids.length}],l=o.ids.length;for(let d of a)l+=d.delta,l=Math.max(0,Math.min(o.ids.length,l)),f.push({time:d.time,heroes:l});o.stats.uptime=f;let c={};for(let d=0;d<f.length;d++){let y=(d<f.length-1?f[d+1].time:t.length)-f[d].time,x=String(f[d].heroes);c[x]=(c[x]||0)+y}o.stats.uptimeHistogram=c;let u=0,b=0;for(let d=0;d<f.length;d++){let y=(d<f.length-1?f[d+1].time:t.length)-f[d].time;u+=f[d].heroes*y,b+=y}o.stats.avgHeroesAlive=b>0?u/b:o.ids.length,o.stats.wipes=f.filter(d=>d.heroes===0).length,o.stats.aces=0;let h=s==="0"?"1":"0",m=t.teams[h];m?.stats?.uptime&&(o.stats.aces=m.stats.uptime.filter(d=>d.heroes===0).length);let p=t.XPBreakdown.filter(d=>d.team===parseInt(s,10));if(p.length>0){let _=p[p.length-1].breakdown.TrickleXP;o.stats.passiveXPGain=_,o.stats.passiveXPRate=t.length>0?_/(t.length/60):0}}for(let s of["0","1"]){let o=t.teams[s],a=s==="0"?"1":"0",f=t.teams[a];if(!o||!f)continue;let l=o.stats.uptime,c=f.stats.uptime;if(!l.length||!c.length)continue;let u=new Set;for(let m of l)u.add(m.time);for(let m of c)u.add(m.time);let b=Array.from(u).sort((m,p)=>m-p),h=0;for(let m=0;m<b.length;m++){let p=b[m],_=(m<b.length-1?b[m+1]:t.length)-p,y=He(l,p),x=He(c,p);y>x&&(h+=_)}o.stats.timeWithHeroAdv=h,o.stats.pctWithHeroAdv=t.length>0?h/t.length:0}let r=t.teams[0]?.stats.passiveXPRate??0,n=t.teams[1]?.stats.passiveXPRate??0,i=(r+n)/2;t.teams[0]&&(t.teams[0].stats.passiveXPDiff=i>0?r/i:0),t.teams[1]&&(t.teams[1].stats.passiveXPDiff=i>0?n/i:0)}function He(t,e){let r=0;for(let n of t)if(n.time<=e)r=n.heroes;else break;return r}function kt(t,e,r){return t<=1?15:t<=5?15+(t-1)*2:t<=10?23+(t-5)*3:t<=15?38+(t-10)*4:58+(t-15)*5}function wt(t){let e=1/0,r=-1,n=1/0,i=-1;for(let o of Object.values(t.structures))o.destroyed!==void 0&&(o.name==="Fort"&&o.destroyed<e&&(e=o.destroyed,r=o.team===0?1:0),o.name==="Keep"&&o.destroyed<n&&(n=o.destroyed,i=o.team===0?1:0));r>=0&&(t.firstFort=r,t.firstFortWin=r===t.winner),i>=0&&(t.firstKeep=i,t.firstKeepWin=i===t.winner);let s=[...t.objective[0].events.map(o=>({...o,assignedTeam:0})),...t.objective[1].events.map(o=>({...o,assignedTeam:1}))].sort((o,a)=>o.loop-a.loop);s.length>0&&(t.firstObjective=s[0].assignedTeam,t.firstObjectiveWin=s[0].assignedTeam===t.winner),t.firstPickWin=t.picks.first===t.winner}function C(t){return Buffer.isBuffer(t)?t.toString("utf8"):typeof t=="string"?t:String(t??"")}var ne=class{static async analyze(e){try{let r=new z(e);await r.init();let n=r.getDetails();if(!n)throw new Error("Missing replay.details from parsed MPQ archive");let i=r.getTrackerEvents(),s=r.getInitData(),a=r.getHeader()?.m_version??{},f={m_flags:a.m_flags??0,m_major:a.m_major??0,m_minor:a.m_minor??0,m_revision:a.m_revision??0,m_build:a.m_baseBuild??r.getBuild(),m_baseBuild:a.m_baseBuild??r.getBuild()},l=n.m_playerList.find(h=>h?.m_toon)?.m_toon,c={version:f,map:C(n.m_title),date:this.fileTimeToDate(n.m_timeUTC).toISOString(),rawDate:Number(n.m_timeUTC),length:0,winner:-1,region:l?.m_region,playerIDs:[],heroes:[],levelTimes:{0:{},1:{}},bans:{0:[],1:[]},picks:{0:[],1:[],first:0},XPBreakdown:[],takedowns:[],mercs:{captures:[],units:{}},team0Takedowns:0,team1Takedowns:0,structures:{},objective:{0:{count:0,events:[]},1:{count:0,events:[]},type:""},teams:{0:this.emptyTeam(),1:this.emptyTeam()},winningPlayers:[],levelAdvTimeline:[],firstPickWin:!1};c.objective.type=c.map||"";let u={};for(let h of n.m_playerList){if(!h?.m_toon)continue;let m=h.m_toon,p=C(m.m_programId),d=`${m.m_region}-${p}-${m.m_realm}-${m.m_id}`,_=C(h.m_hero);u[d]={hero:_,name:C(h.m_name),uuid:m.m_id,region:m.m_region,realm:m.m_realm,ToonHandle:d,tag:0,team:h.m_teamId,win:h.m_result===1,gameStats:{},awards:[],talents:{},takedowns:[],deaths:[],units:{}},c.playerIDs.push(d),c.heroes.push(_)}this.extractBattleTags(r,n,u),this.extractDraft(s,c,n);let{playerIDMap:b}=Me(i,u,c);this.processScoreEvents(i,b,u);for(let[h,m]of Object.entries(u)){m.win&&(c.winner=m.team,c.winningPlayers.push(h));let p=c.teams[m.team.toString()];p&&(p.level=Math.max(p.level,m.gameStats.Level||0),p.takedowns+=m.gameStats.Takedowns||0,p.ids.push(h))}return Oe(c,u),{status:1,match:c,players:u}}catch(r){return console.error("ReplayAnalyzer Error:",r),{status:-2,error:String(r)}}}static emptyTeam(){return{level:0,takedowns:0,ids:[],names:[],heroes:[],tags:[],stats:{mercCaptures:0,mercUptime:0,mercUptimePercent:0,structures:{},KDA:0,PPK:0,timeTo10:0,totals:{DamageTaken:0,CreepDamage:0,Healing:0,HeroDamage:0,MinionDamage:0,SelfHealing:0,SiegeDamage:0,ProtectionGivenToAllies:0,TeamfightDamageTaken:0,TeamfightHealingDone:0,TeamfightHeroDamage:0,TimeCCdEnemyHeroes:0,TimeRootingEnemyHeroes:0,TimeSpentDead:0,TimeStunningEnemyHeroes:0,TimeSilencingEnemyHeroes:0,avgTimeSpentDead:0,timeDeadPct:0},levelAdvTime:0,maxLevelAdv:0,avgLevelAdv:0,levelAdvPct:0,uptime:[],uptimeHistogram:{},wipes:0,avgHeroesAlive:0,aces:0,timeWithHeroAdv:0,pctWithHeroAdv:0,passiveXPRate:0,passiveXPDiff:0,passiveXPGain:0}}}static extractBattleTags(e,r,n){let i=e.extractFile("replay.server.battlelobby");if(i)try{let s=new RegExp("([\\p{L}\\d]{3,24}#\\d{4,10})[z\xD8]?","gu"),o=i.toString("utf8").match(s);if(!o)return;let a=0;for(let f of r.m_playerList){if(!f?.m_toon)continue;let l=C(f.m_name);for(;a<o.length;){let u=o[a].split("#"),b=u[0],h=u[1].replace(/[zØ]/g,"");if(a++,b===l){let m=f.m_toon,p=`${m.m_region}-${C(m.m_programId)}-${m.m_realm}-${m.m_id}`;n[p]&&(n[p].tag=parseInt(h,10)||0);break}}}}catch(s){console.error("BattleTag regex error:",s)}}static extractDraft(e,r,n){if(e)try{let i=e.m_syncLobbyState;if(!i)return;let s=i.m_lobbyState;if(!s)return;let o=[],a=[];for(let c of n.m_playerList){if(!c?.m_toon)continue;let u=C(c.m_hero);c.m_teamId===0?o.push(u):c.m_teamId===1&&a.push(u)}if(r.picks={0:o,1:a,first:0},typeof s.m_gameMode=="number"&&(r.mode=s.m_gameMode),typeof s.m_gameType=="number"&&(r.type=s.m_gameType),!s.m_slots)return;if(s.m_pickedMapTag!==void 0){let c=s.m_firstPickTeam??0;r.picks.first=c}}catch{}}static processScoreEvents(e,r,n){for(let i of e){if(i._event!=="NNet.Replay.Tracker.SScoreResultEvent")continue;let s=i.m_instanceList;for(let o of s){let a=C(o.m_name),f=o.m_values,l=a.startsWith("EndOfMatchAward"),c=0;for(let u of f)if(u&&u.length>0&&u[0]!==void 0){let b=c+1,h=r[b];if(h&&n[h]){let m=typeof u[0]=="object"&&u[0]!==null&&"m_value"in u[0]?u[0].m_value:u[0];m!=null&&(l?m===1&&n[h].awards.push(a):n[h].gameStats[a]=m)}c++}else u&&u.length===0&&c++}}}static fileTimeToDate(e){return new Date(Number(e)/1e4-116444736e5)}};0&&(module.exports={ReplayAnalyzer,ReplayParser});
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- var A=(i=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(i,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):i)(function(i){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+i+'" is not supported')});import*as Q from"fs";import*as x from"zlib";var O=A("seek-bzip"),U=512,$=65536,C=16777216,q=67108864,j=2147483648,G={TABLE_OFFSET:0,HASH_A:1,HASH_B:2,TABLE:3};function V(){let i=1048577,e=new Uint32Array(256*5);for(let t=0;t<256;t++){let r=t;for(let n=0;n<5;n++){i=(i*125+3)%2796203;let s=(i&65535)<<16;i=(i*125+3)%2796203;let l=i&65535;e[r]=(s|l)>>>0,r+=256}}return e}var N=V(),P=class{file;header;hashTable;blockTable;files;constructor(e,t=!0){if(Buffer.isBuffer(e)?this.file=e:this.file=Q.readFileSync(e),this.header=this.readHeader(),this.hashTable=this.readTable("hash"),this.blockTable=this.readTable("block"),t){let r=this.readFile("(listfile)");r?this.files=r.toString("utf8").trim().split(`\r
2
- `):this.files=null}else this.files=null}readHeader(){let e=this.file.toString("utf8",0,4),t;if(e==="MPQ")t=this.readMPQHeader(),t.offset=0;else if(e==="MPQ\x1B"){let r=this.readMPQUserDataHeader();t=this.readMPQHeader(r.mpqHeaderOffset),t.offset=r.mpqHeaderOffset,t.userDataHeader=r}else throw new Error("Invalid MPQ file header");return t}readMPQHeader(e=0){let t=this.file.subarray(e,e+32),r={magic:t.toString("utf8",0,4),headerSize:t.readUInt32LE(4),archiveSize:t.readUInt32LE(8),formatVersion:t.readUInt16LE(12),sectorSizeShift:t.readUInt16LE(14),hashTableOffset:t.readUInt32LE(16),blockTableOffset:t.readUInt32LE(20),hashTableEntries:t.readUInt32LE(24),blockTableEntries:t.readUInt32LE(28)};if(r.formatVersion===1){let n=this.file.subarray(e+32,e+32+12);r.extendedBlockTableOffset=n.readUInt32LE(0)+n.readUInt32LE(4)*4294967296,r.hashTableOffsetHigh=n.readInt8(8),r.blockTableOffsetHigh=n.readInt8(10)}return r}readMPQUserDataHeader(){let e=this.file.subarray(0,16),t={magic:e.toString("utf8",0,4),userDataSize:e.readUInt32LE(4),mpqHeaderOffset:e.readUInt32LE(8),userDataHeaderSize:e.readUInt32LE(12)};return t.content=this.file.subarray(16,16+t.userDataHeaderSize),t}readTable(e){let t=e==="hash"?"hashTableOffset":"blockTableOffset",r=e==="hash"?"hashTableEntries":"blockTableEntries",n=this.header[t],s=this.header[r];if(n==null||s==null)throw new Error("Missing "+e+" offset or entries");let l=this.hash("("+e+" table)","TABLE"),a=this.file.subarray(n+(this.header.offset||0),n+(this.header.offset||0)+s*16);a=this.decrypt(a,l);let c=[];for(let _=0;_<s;_++){let h=a.subarray(_*16,_*16+16);e==="hash"?c.push({hashA:h.readUInt32LE(0),hashB:h.readUInt32LE(4),locale:h.readUInt16LE(8),platform:h.readUInt16LE(10),blockTableIndex:h.readUInt32LE(12)}):c.push({offset:h.readUInt32LE(0),archivedSize:h.readUInt32LE(4),size:h.readUInt32LE(8),flags:h.readUInt32LE(12)})}return c}getHashTableEntry(e){let t=this.hash(e,"HASH_A"),r=this.hash(e,"HASH_B");for(let n of this.hashTable)if(n.hashA===t&&n.hashB===r)return n}readFile(e,t=!1){function r(c){let _=c[0];if(_===0)return c;if(_===2)return x.inflateSync(c.subarray(1));if(_===16)return O.decode(c.subarray(1));try{return x.inflateSync(c.subarray(1))}catch{return x.inflateRawSync(c.subarray(1))}}let n=this.getHashTableEntry(e);if(!n)return null;let s=this.blockTable[n.blockTableIndex];if(!s||!(s.flags&j))return null;if(s.archivedSize===0)return Buffer.alloc(0);let l=s.offset+(this.header.offset||0),a=this.file.subarray(l,l+s.archivedSize);if(s.flags&$)throw new Error("Encryption is not supported");if(s.flags&C)s.flags&U&&(t||s.size>s.archivedSize)&&(a=r(a));else{let c=512<<this.header.sectorSizeShift,_=Math.trunc(s.size/c)+1,h=!1;s.flags&q&&(h=!0,_+=1);let o=[];for(let d=0;d<_+1;d++)o.push(a.readUInt32LE(4*d));let u=o.length-(h?2:1),f=[],b=s.size;for(let d=0;d<u;d++){let m=a.subarray(o[d],o[d+1]);s.flags&U&&(t||b>m.length)&&(m=r(m)),b-=m.length,f.push(m)}a=Buffer.concat(f)}return a}hash(e,t){let r=2146271213,n=4008636142;for(let s=0;s<e.length;s++){let l=e.toUpperCase().charCodeAt(s);r=(N[(G[t]<<8)+l]^r+n)>>>0,n=l+r+n+(n<<5)+3>>>0}return r}decrypt(e,t){let r=t>>>0,n=4008636142,s=Buffer.alloc(e.length),l=e.length/4;for(let a=0;a<l;a++){n=n+N[1024+(r&255)]>>>0;let c=e.readUInt32LE(a*4);c=(c^r+n)>>>0,r=((~r<<21)+286331153|r>>>11)>>>0,n=c+n+(n<<5)+3>>>0,s.writeUInt32LE(c,a*4)}return s}};var k=class extends Error{constructor(e="Truncated Buffer"){super(e),this.name="TruncatedError"}},g=class extends Error{constructor(e="Corrupted Buffer"){super(e),this.name="CorruptedError"}},S=class{_data;_used;_next;_nextbits;_bigendian;constructor(e,t="big"){this._data=e,this._used=0,this._next=0,this._nextbits=0,this._bigendian=t==="big"}done(){return this._nextbits===0&&this._used>=this._data.length}used_bits(){return this._used*8-this._nextbits}byte_align(){this._nextbits=0}read_aligned_bytes(e){if(this.byte_align(),this._used+e>this._data.length)throw new k;let t=this._data.subarray(this._used,this._used+e);return this._used+=e,t}read_bits(e){let t=0,r=0;for(;r!==e;){if(this._nextbits===0){if(this.done())throw new k;this._next=this._data[this._used],this._used+=1,this._nextbits=8}let n=Math.min(e-r,this._nextbits),s=this._next&(1<<n)-1;this._bigendian?t+=s*Math.pow(2,e-r-n):t+=s*Math.pow(2,r),this._next>>=n,this._nextbits-=n,r+=n}return t}read_bits_bigint(e){let t=0n,r=0;for(;r!==e;){if(this._nextbits===0){if(this.done())throw new k;this._next=this._data[this._used],this._used+=1,this._nextbits=8}let n=Math.min(e-r,this._nextbits),s=BigInt(this._next&(1<<n)-1);this._bigendian?t|=s<<BigInt(e-r-n):t|=s<<BigInt(r),this._next>>=n,this._nextbits-=n,r+=n}return t}read_unaligned_bytes(e){let t=Buffer.alloc(e);for(let r=0;r<e;r++)t[r]=this.read_bits(8);return t}};var B=class{_buffer;_typeinfos;constructor(e,t){this._buffer=new S(e),this._typeinfos=t}instance(e){if(e>=this._typeinfos.length)throw new g(`Invalid typeid ${e}`);let t=this._typeinfos[e],r=t[0],n=t[1]||[],s=this[r];if(typeof s!="function")throw new Error(`Decoder method ${r} not implemented`);return s.apply(this,n)}byte_align(){this._buffer.byte_align()}done(){return this._buffer.done()}used_bits(){return this._buffer.used_bits()}_array(e,t){let r=this._int(e),n=new Array(r);for(let s=0;s<r;s++)n[s]=this.instance(t);return n}_bitarray(e){let t=this._int(e);return[t,this._buffer.read_bits(t)]}_blob(e){let t=this._int(e);return this._buffer.read_aligned_bytes(t)}_bool(){return this._int([0,1])!==0}_choice(e,t){let r=this._int(e);if(!(r in t))throw new g(`Choice tag ${r} not found`);let n=t[r];return{[n[0]]:this.instance(n[1])}}_fourcc(){let e=this._buffer.read_bits(32),t=Buffer.alloc(4);return t.writeUInt32BE(e,0),t.toString("ascii")}_int(e){return e[0]+this._buffer.read_bits(e[1])}_null(){return null}_optional(e){return this._bool()?this.instance(e):null}_real32(){return this._buffer.read_unaligned_bytes(4).readFloatBE(0)}_real64(){return this._buffer.read_unaligned_bytes(8).readDoubleBE(0)}_struct(e){let t={};for(let r of e)if(r[0]==="__parent"){let n=this.instance(r[1]);if(typeof n=="object"&&n!==null)t={...t,...n};else{if(e.length===1)return n;t[r[0]]=n}}else t[r[0]]=this.instance(r[1]);return t}},w=class{_buffer;_typeinfos;constructor(e,t){this._buffer=new S(e),this._typeinfos=t}instance(e){if(e>=this._typeinfos.length)throw new g(`Invalid typeid ${e}`);let t=this._typeinfos[e],r=t[0],n=t[1]||[],s=this[r];if(typeof s!="function")throw new Error(`Decoder method ${r} not implemented`);return s.apply(this,n)}byte_align(){this._buffer.byte_align()}done(){return this._buffer.done()}used_bits(){return this._buffer.used_bits()}_expect_skip(e){if(this._buffer.read_bits(8)!==e)throw new g(`Expected skip ${e}`)}_vint(){let e=this._buffer.read_bits(8),t=(e&1)!==0,r=BigInt(e>>1&63),n=6n;for(;(e&128)!==0;)e=this._buffer.read_bits(8),r|=BigInt(e&127)<<n,n+=7n;let s=t?-r:r;return s>=BigInt(Number.MIN_SAFE_INTEGER)&&s<=BigInt(Number.MAX_SAFE_INTEGER)?Number(s):s}_array(e,t){this._expect_skip(0);let r=Number(this._vint()),n=new Array(r);for(let s=0;s<r;s++)n[s]=this.instance(t);return n}_bitarray(e){this._expect_skip(1);let t=Number(this._vint());return[t,this._buffer.read_aligned_bytes(Math.floor((t+7)/8))]}_blob(e){this._expect_skip(2);let t=Number(this._vint());return this._buffer.read_aligned_bytes(t)}_bool(){return this._expect_skip(6),this._buffer.read_bits(8)!==0}_choice(e,t){this._expect_skip(3);let r=Number(this._vint());if(!(r in t))return this._skip_instance(),{};let n=t[r];return{[n[0]]:this.instance(n[1])}}_fourcc(){return this._expect_skip(7),this._buffer.read_aligned_bytes(4)}_int(e){return this._expect_skip(9),Number(this._vint())}_null(){return null}_optional(e){return this._expect_skip(4),this._buffer.read_bits(8)!==0?this.instance(e):null}_real32(){return this._expect_skip(7),this._buffer.read_aligned_bytes(4).readFloatBE(0)}_real64(){return this._expect_skip(8),this._buffer.read_aligned_bytes(8).readDoubleBE(0)}_struct(e){this._expect_skip(5);let t={},r=Number(this._vint());for(let n=0;n<r;n++){let s=Number(this._vint()),l=e.find(a=>a[2]===s);if(l)if(l[0]==="__parent"){let a=this.instance(l[1]);typeof a=="object"&&a!==null?t={...t,...a}:e.length===1?t=a:t[l[0]]=a}else t[l[0]]=this.instance(l[1]);else this._skip_instance()}return t}_skip_instance(){let e=this._buffer.read_bits(8);if(e===0){let t=Number(this._vint());for(let r=0;r<t;r++)this._skip_instance()}else if(e===1){let t=Number(this._vint());this._buffer.read_aligned_bytes(Math.floor((t+7)/8))}else if(e===2){let t=Number(this._vint());this._buffer.read_aligned_bytes(t)}else if(e===3)this._vint(),this._skip_instance();else if(e===4)this._buffer.read_bits(8)!==0&&this._skip_instance();else if(e===5){let t=Number(this._vint());for(let r=0;r<t;r++)this._vint(),this._skip_instance()}else e===6?this._buffer.read_aligned_bytes(1):e===7?this._buffer.read_aligned_bytes(4):e===8?this._buffer.read_aligned_bytes(8):e===9&&this._vint()}};import T from"fs";import y from"path";function W(){let i=[];try{i.push(y.resolve(__dirname,"..","protocols")),i.push(y.resolve(__dirname,"..","..","protocols"))}catch{}i.push(y.resolve(process.cwd(),"protocols"));let e=process.cwd();for(;e!==y.dirname(e);){let t=y.join(e,"node_modules","@astefanski","storm-parser","protocols");i.push(t),e=y.dirname(e)}for(let t of i)if(T.existsSync(t)&&T.readdirSync(t).some(r=>r.endsWith(".json")))return t;throw new Error(`@astefanski/storm-parser: Protocols directory not found. Did postinstall run? Try: npx tsx node_modules/@astefanski/storm-parser/scripts/postinstall.ts
3
- Searched: `+i.join(", "))}var H=new Map,L=null;function z(){return L||(L=W()),L}function M(i){if(H.has(i))return H.get(i);let e=z(),t=y.join(e,`protocol${i}.json`);if(!T.existsSync(t))return null;let r=JSON.parse(T.readFileSync(t,"utf-8"));return H.set(i,r),r}function F(){let i=z();return T.readdirSync(i).filter(e=>/^protocol\d+\.json$/.test(e)).map(e=>parseInt(e.match(/\d+/)[0],10)).sort((e,t)=>e-t)}var I=class{mpq;header;build=0;protocol;baseProtocol;constructor(e){this.mpq=new P(e,!1)}init(){let e=M(29406);if(!e)throw new Error("Base protocol29406 not found. Did postinstall run? Try: npx tsx node_modules/@astefanski/storm-parser/scripts/postinstall.ts");this.baseProtocol=e;let t=this.mpq.header.userDataHeader;if(!t||!t.content)throw new Error("Replay does not have a user data header");let r=new w(t.content,this.baseProtocol.typeinfos);this.header=r.instance(this.baseProtocol.replay_header_typeid),this.build=this.header.m_version.m_baseBuild,this.protocol=this.loadProtocolForBuild(this.build)}loadProtocolForBuild(e){let t=M(e);if(!t){let r=F(),n=r[0];for(let s of r)s<=e&&s>n&&(n=s);t=M(n)}if(!t)throw new Error(`No protocol found for build ${e}`);return t}*decodeEventStream(e,t,r,n){if(!this.protocol)throw new Error("Protocol not loaded");let s=0;for(;!e.done();){let l=e.used_bits(),a=e.instance(this.protocol.svaruint32_typeid),c=Object.keys(a)[0],_=a[c];s+=_;let h=n?e.instance(this.protocol.replay_userid_typeid):void 0,o=Number(e.instance(t)),u=r[o];if(!u)throw new Error(`Unknown eventid(${o})`);let f=u[0],b=u[1],d=e.instance(f);d._event=b,d._eventid=o,d._gameloop=s,n&&(d._userid=h),e.byte_align(),d._bits=e.used_bits()-l,yield d}}getDetails(){if(!this.protocol)throw new Error("Protocol not loaded");let e=this.mpq.readFile("replay.details");return e?new w(e,this.protocol.typeinfos).instance(this.protocol.game_details_typeid):null}getInitData(){if(!this.protocol)throw new Error("Protocol not loaded");let e=this.mpq.readFile("replay.initData");return e?new B(e,this.protocol.typeinfos).instance(this.protocol.replay_initdata_typeid):null}getTrackerEvents(){if(!this.protocol)throw new Error("Protocol not loaded");let e=this.mpq.readFile("replay.tracker.events");if(!e)return[];let t=new w(e,this.protocol.typeinfos);return Array.from(this.decodeEventStream(t,this.protocol.tracker_eventid_typeid,this.protocol.tracker_event_types,!1))}getGameEvents(){if(!this.protocol)throw new Error("Protocol not loaded");let e=this.mpq.readFile("replay.game.events");if(!e)return[];let t=new B(e,this.protocol.typeinfos);return Array.from(this.decodeEventStream(t,this.protocol.game_eventid_typeid,this.protocol.game_event_types,!0))}extractFile(e){return this.mpq.readFile(e)}};var D=class{static async analyze(e){try{let t=new I(e);await t.init();let r=t.getDetails(),n=t.getTrackerEvents();if(!r)throw new Error("Missing replay.details from parsed MPQ archive");console.log("Raw TimeUTC:",r?.m_timeUTC,"Type:",typeof r?.m_timeUTC);let s={map:r?.m_title?.toString("utf8"),date:r?this.fileTimeToDate(r.m_timeUTC).toISOString():new Date().toISOString(),length:0,winner:-1,version:{m_build:t.build},teams:{0:{level:0,takedowns:0,ids:[]},1:{level:0,takedowns:0,ids:[]}}},l={};for(let o of r.m_playerList){if(!o||!o.m_toon)continue;let u=o.m_toon,f=`${u.m_region}-${u.m_programId}-${u.m_realm}-${u.m_id}`;l[f]={hero:o.m_hero?.toString("utf8")||"",name:o.m_name?.toString("utf8")||"",tag:"",team:o.m_teamId,win:o.m_result===1,gameStats:{}}}let a=t.extractFile("replay.server.battlelobby");if(a)try{let o=new RegExp("([\\p{L}\\d]{3,24}#\\d{4,10})[z\xD8]?","gu"),u=a.toString("utf8").match(o);if(u){let f=0;for(let b of r.m_playerList){if(!b||!b.m_toon)continue;let d=b.m_name?.toString("utf8");for(;f<u.length;){let p=u[f].split("#"),R=p[0],E=p[1].replace(/[zØ]/g,"");if(f++,R===d){let v=`${b.m_toon.m_region}-${b.m_toon.m_programId}-${b.m_toon.m_realm}-${b.m_toon.m_id}`;l[v]&&(l[v].tag=E);break}}}}}catch(o){console.error("BattleTag regex error:",o)}let c={},_=0,h=0;for(let o of n){if(o._event==="NNet.Replay.Tracker.SStatGameEvent"){let u=o.m_eventName?.toString("utf8");if(u==="PlayerInit"){let f=o.m_intData,b=o.m_stringData,d=f[0].m_value,m=b[1].m_value?.toString("utf8");m&&l[m]&&(c[d]=m)}else u==="GatesOpen"&&(_=o._gameloop)}h=Math.max(h,o._gameloop)}s.length=Math.floor((h-_)/16);for(let o of n)if(o._event==="NNet.Replay.Tracker.SScoreResultEvent"){let u=o.m_instanceList;for(let f of u){let b=f.m_name?.toString("utf8"),d=f.m_values,m=0;if(!b.startsWith("EndOfMatchAward"))for(let p of d)if(p&&p.length>0&&p[0]!==void 0){let R=m+1,E=c[R];if(E&&l[E]){let v=typeof p[0]=="object"&&p[0]!==null&&"m_value"in p[0]?p[0].m_value:p[0];v!=null&&(l[E].gameStats[b]=v)}m++}else p&&p.length===0&&m++}}for(let[o,u]of Object.entries(l)){u.win&&(s.winner=u.team);let f=s.teams[u.team.toString()];f&&(f.level=Math.max(f.level,u.gameStats.Level||0),f.takedowns+=u.gameStats.Takedowns||0,f.ids.push(o))}return{status:1,match:s,players:l}}catch(t){return console.error("ReplayAnalyzer Error:",t),{status:-2,error:String(t)}}}static fileTimeToDate(e){return new Date(Number(e)/1e4-116444736e5)}};export{D as ReplayAnalyzer,I as ReplayParser};
1
+ var X=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var ue=X((ht,le)=>{"use strict";var ce=[0,1,3,7,15,31,63,127,255],F=function(t){this.stream=t,this.bitOffset=0,this.curByte=0,this.hasByte=!1};F.prototype._ensureByte=function(){this.hasByte||(this.curByte=this.stream.readByte(),this.hasByte=!0)};F.prototype.read=function(t){for(var e=0;t>0;){this._ensureByte();var r=8-this.bitOffset;if(t>=r)e<<=r,e|=ce[r]&this.curByte,this.hasByte=!1,this.bitOffset=0,t-=r;else{e<<=t;var n=r-t;e|=(this.curByte&ce[t]<<n)>>n,this.bitOffset+=t,t=0}}return e};F.prototype.seek=function(t){var e=t%8,r=(t-e)/8;this.bitOffset=e,this.stream.seek(r),this.hasByte=!1};F.prototype.pi=function(){var t=new Buffer(6),e;for(e=0;e<t.length;e++)t[e]=this.read(8);return t.toString("hex")};le.exports=F});var me=X((_t,de)=>{"use strict";var A=function(){};A.prototype.readByte=function(){throw new Error("abstract method readByte() not implemented")};A.prototype.read=function(t,e,r){for(var n=0;n<r;){var i=this.readByte();if(i<0)return n===0?-1:n;t[e++]=i,n++}return n};A.prototype.seek=function(t){throw new Error("abstract method seek() not implemented")};A.prototype.writeByte=function(t){throw new Error("abstract method readByte() not implemented")};A.prototype.write=function(t,e,r){var n;for(n=0;n<r;n++)this.writeByte(t[e++]);return r};A.prototype.flush=function(){};de.exports=A});var pe=X((gt,be)=>{"use strict";be.exports=(function(){var t=new Uint32Array([0,79764919,159529838,222504665,319059676,398814059,445009330,507990021,638119352,583659535,797628118,726387553,890018660,835552979,1015980042,944750013,1276238704,1221641927,1167319070,1095957929,1595256236,1540665371,1452775106,1381403509,1780037320,1859660671,1671105958,1733955601,2031960084,2111593891,1889500026,1952343757,2552477408,2632100695,2443283854,2506133561,2334638140,2414271883,2191915858,2254759653,3190512472,3135915759,3081330742,3009969537,2905550212,2850959411,2762807018,2691435357,3560074640,3505614887,3719321342,3648080713,3342211916,3287746299,3467911202,3396681109,4063920168,4143685023,4223187782,4286162673,3779000052,3858754371,3904687514,3967668269,881225847,809987520,1023691545,969234094,662832811,591600412,771767749,717299826,311336399,374308984,453813921,533576470,25881363,88864420,134795389,214552010,2023205639,2086057648,1897238633,1976864222,1804852699,1867694188,1645340341,1724971778,1587496639,1516133128,1461550545,1406951526,1302016099,1230646740,1142491917,1087903418,2896545431,2825181984,2770861561,2716262478,3215044683,3143675388,3055782693,3001194130,2326604591,2389456536,2200899649,2280525302,2578013683,2640855108,2418763421,2498394922,3769900519,3832873040,3912640137,3992402750,4088425275,4151408268,4197601365,4277358050,3334271071,3263032808,3476998961,3422541446,3585640067,3514407732,3694837229,3640369242,1762451694,1842216281,1619975040,1682949687,2047383090,2127137669,1938468188,2001449195,1325665622,1271206113,1183200824,1111960463,1543535498,1489069629,1434599652,1363369299,622672798,568075817,748617968,677256519,907627842,853037301,1067152940,995781531,51762726,131386257,177728840,240578815,269590778,349224269,429104020,491947555,4046411278,4126034873,4172115296,4234965207,3794477266,3874110821,3953728444,4016571915,3609705398,3555108353,3735388376,3664026991,3290680682,3236090077,3449943556,3378572211,3174993278,3120533705,3032266256,2961025959,2923101090,2868635157,2813903052,2742672763,2604032198,2683796849,2461293480,2524268063,2284983834,2364738477,2175806836,2238787779,1569362073,1498123566,1409854455,1355396672,1317987909,1246755826,1192025387,1137557660,2072149281,2135122070,1912620623,1992383480,1753615357,1816598090,1627664531,1707420964,295390185,358241886,404320391,483945776,43990325,106832002,186451547,266083308,932423249,861060070,1041341759,986742920,613929101,542559546,756411363,701822548,3316196985,3244833742,3425377559,3370778784,3601682597,3530312978,3744426955,3689838204,3819031489,3881883254,3928223919,4007849240,4037393693,4100235434,4180117107,4259748804,2310601993,2373574846,2151335527,2231098320,2596047829,2659030626,2470359227,2550115596,2947551409,2876312838,2788305887,2733848168,3165939309,3094707162,3040238851,2985771188]),e=function(){var r=4294967295;this.getCRC=function(){return~r>>>0},this.updateCRC=function(n){r=r<<8^t[(r>>>24^n)&255]},this.updateCRCRun=function(n,i){for(;i-- >0;)r=r<<8^t[(r>>>24^n)&255]}};return e})()});var he=X((yt,Me)=>{Me.exports={name:"seek-bzip",version:"2.0.0",contributors:["C. Scott Ananian (http://cscott.net)","Eli Skeggs","Kevin Kwok","Rob Landley (http://landley.net)"],description:"a pure-JavaScript Node.JS module for random-access decoding bzip2 data",main:"./lib/index.js",repository:{type:"git",url:"https://github.com/cscott/seek-bzip.git"},license:"MIT",bin:{"seek-bunzip":"./bin/seek-bunzip","seek-table":"./bin/seek-bzip-table"},directories:{test:"test"},dependencies:{commander:"^6.0.0"},devDependencies:{fibers:"^5.0.0",mocha:"^8.1.0"},scripts:{test:"mocha"}}});var we=X((xt,ke)=>{"use strict";var He=ue(),K=me(),xe=pe(),ve=he(),Y=20,_e=258,ge=0,Oe=1,Ue=2,Le=6,Ne=50,ze="314159265359",Xe="177245385090",ye=function(t,e){var r=t[e],n;for(n=e;n>0;n--)t[n]=t[n-1];return t[0]=r,r},g={OK:0,LAST_BLOCK:-1,NOT_BZIP_DATA:-2,UNEXPECTED_INPUT_EOF:-3,UNEXPECTED_OUTPUT_EOF:-4,DATA_ERROR:-5,OUT_OF_MEMORY:-6,OBSOLETE_INPUT:-7,END_OF_BLOCK:-8},B={};B[g.LAST_BLOCK]="Bad file checksum";B[g.NOT_BZIP_DATA]="Not bzip data";B[g.UNEXPECTED_INPUT_EOF]="Unexpected input EOF";B[g.UNEXPECTED_OUTPUT_EOF]="Unexpected output EOF";B[g.DATA_ERROR]="Data error";B[g.OUT_OF_MEMORY]="Out of memory";B[g.OBSOLETE_INPUT]="Obsolete (pre 0.9.5) bzip format not supported.";var T=function(t,e){var r=B[t]||"unknown error";e&&(r+=": "+e);var n=new TypeError(r);throw n.errorCode=t,n},k=function(t,e){this.writePos=this.writeCurrent=this.writeCount=0,this._start_bunzip(t,e)};k.prototype._init_block=function(){var t=this._get_next_block();return t?(this.blockCRC=new xe,!0):(this.writeCount=-1,!1)};k.prototype._start_bunzip=function(t,e){var r=new Buffer(4);(t.read(r,0,4)!==4||String.fromCharCode(r[0],r[1],r[2])!=="BZh")&&T(g.NOT_BZIP_DATA,"bad magic");var n=r[3]-48;(n<1||n>9)&&T(g.NOT_BZIP_DATA,"level out of range"),this.reader=new He(t),this.dbufSize=1e5*n,this.nextoutput=0,this.outputStream=e,this.streamCRC=0};k.prototype._get_next_block=function(){var t,e,r,n=this.reader,i=n.pi();if(i===Xe)return!1;i!==ze&&T(g.NOT_BZIP_DATA),this.targetBlockCRC=n.read(32)>>>0,this.streamCRC=(this.targetBlockCRC^(this.streamCRC<<1|this.streamCRC>>>31))>>>0,n.read(1)&&T(g.OBSOLETE_INPUT);var s=n.read(24);s>this.dbufSize&&T(g.DATA_ERROR,"initial position out of bounds");var o=n.read(16),a=new Buffer(256),f=0;for(t=0;t<16;t++)if(o&1<<15-t){var l=t*16;for(r=n.read(16),e=0;e<16;e++)r&1<<15-e&&(a[f++]=l+e)}var c=n.read(3);(c<Ue||c>Le)&&T(g.DATA_ERROR);var u=n.read(15);u===0&&T(g.DATA_ERROR);var b=new Buffer(256);for(t=0;t<c;t++)b[t]=t;var h=new Buffer(u);for(t=0;t<u;t++){for(e=0;n.read(1);e++)e>=c&&T(g.DATA_ERROR);h[t]=ye(b,e)}var m=f+2,p=[],d;for(e=0;e<c;e++){var _=new Buffer(m),y=new Uint16Array(Y+1);for(o=n.read(5),t=0;t<m;t++){for(;(o<1||o>Y)&&T(g.DATA_ERROR),!!n.read(1);)n.read(1)?o--:o++;_[t]=o}var x,E;for(x=E=_[0],t=1;t<m;t++)_[t]>E?E=_[t]:_[t]<x&&(x=_[t]);d={},p.push(d),d.permute=new Uint16Array(_e),d.limit=new Uint32Array(Y+2),d.base=new Uint32Array(Y+1),d.minLen=x,d.maxLen=E;var C=0;for(t=x;t<=E;t++)for(y[t]=d.limit[t]=0,o=0;o<m;o++)_[o]===t&&(d.permute[C++]=o);for(t=0;t<m;t++)y[_[t]]++;for(C=o=0,t=x;t<E;t++)C+=y[t],d.limit[t]=C-1,C<<=1,o+=y[t],d.base[t+1]=C-o;d.limit[E+1]=Number.MAX_VALUE,d.limit[E]=C+y[E]-1,d.base[x]=0}var U=new Uint32Array(256);for(t=0;t<256;t++)b[t]=t;var I=0,R=0,oe=0,S,N=this.dbuf=new Uint32Array(this.dbufSize);for(m=0;;){for(m--||(m=Ne-1,oe>=u&&T(g.DATA_ERROR),d=p[h[oe++]]),t=d.minLen,e=n.read(t);t>d.maxLen&&T(g.DATA_ERROR),!(e<=d.limit[t]);t++)e=e<<1|n.read(1);e-=d.base[t],(e<0||e>=_e)&&T(g.DATA_ERROR);var z=d.permute[e];if(z===ge||z===Oe){I||(I=1,o=0),z===ge?o+=I:o+=2*I,I<<=1;continue}if(I)for(I=0,R+o>this.dbufSize&&T(g.DATA_ERROR),S=a[b[0]],U[S]+=o;o--;)N[R++]=S;if(z>f)break;R>=this.dbufSize&&T(g.DATA_ERROR),t=z-1,S=ye(b,t),S=a[S],U[S]++,N[R++]=S}for((s<0||s>=R)&&T(g.DATA_ERROR),e=0,t=0;t<256;t++)r=e+U[t],U[t]=e,e=r;for(t=0;t<R;t++)S=N[t]&255,N[U[S]]|=t<<8,U[S]++;var q=0,ae=0,fe=0;return R&&(q=N[s],ae=q&255,q>>=8,fe=-1),this.writePos=q,this.writeCurrent=ae,this.writeCount=R,this.writeRun=fe,!0};k.prototype._read_bunzip=function(t,e){var r,n,i;if(this.writeCount<0)return 0;for(var s=0,o=this.dbuf,a=this.writePos,f=this.writeCurrent,l=this.writeCount,c=this.outputsize,u=this.writeRun;l;){for(l--,n=f,a=o[a],f=a&255,a>>=8,u++===3?(r=f,i=n,f=-1):(r=1,i=f),this.blockCRC.updateCRCRun(i,r);r--;)this.outputStream.writeByte(i),this.nextoutput++;f!=n&&(u=0)}return this.writeCount=l,this.blockCRC.getCRC()!==this.targetBlockCRC&&T(g.DATA_ERROR,"Bad block CRC (got "+this.blockCRC.getCRC().toString(16)+" expected "+this.targetBlockCRC.toString(16)+")"),this.nextoutput};var te=function(t){if("readByte"in t)return t;var e=new K;return e.pos=0,e.readByte=function(){return t[this.pos++]},e.seek=function(r){this.pos=r},e.eof=function(){return this.pos>=t.length},e},Te=function(t){var e=new K,r=!0;if(t)if(typeof t=="number")e.buffer=new Buffer(t),r=!1;else{if("writeByte"in t)return t;e.buffer=t,r=!1}else e.buffer=new Buffer(16384);return e.pos=0,e.writeByte=function(n){if(r&&this.pos>=this.buffer.length){var i=new Buffer(this.buffer.length*2);this.buffer.copy(i),this.buffer=i}this.buffer[this.pos++]=n},e.getBuffer=function(){if(this.pos!==this.buffer.length){if(!r)throw new TypeError("outputsize does not match decoded input");var n=new Buffer(this.pos);this.buffer.copy(n,0,0,this.pos),this.buffer=n}return this.buffer},e._coerced=!0,e};k.Err=g;k.decode=function(t,e,r){for(var n=te(t),i=Te(e),s=new k(n,i);!("eof"in n&&n.eof());)if(s._init_block())s._read_bunzip();else{var o=s.reader.read(32)>>>0;if(o!==s.streamCRC&&T(g.DATA_ERROR,"Bad stream CRC (got "+s.streamCRC.toString(16)+" expected "+o.toString(16)+")"),r&&"eof"in n&&!n.eof())s._start_bunzip(n,i);else break}if("getBuffer"in i)return i.getBuffer()};k.decodeBlock=function(t,e,r){var n=te(t),i=Te(r),s=new k(n,i);s.reader.seek(e);var o=s._get_next_block();if(o&&(s.blockCRC=new xe,s.writeCopies=0,s._read_bunzip()),"getBuffer"in i)return i.getBuffer()};k.table=function(t,e,r){var n=new K;n.delegate=te(t),n.pos=0,n.readByte=function(){return this.pos++,this.delegate.readByte()},n.delegate.eof&&(n.eof=n.delegate.eof.bind(n.delegate));var i=new K;i.pos=0,i.writeByte=function(){this.pos++};for(var s=new k(n,i),o=s.dbufSize;!("eof"in n&&n.eof());){var a=n.pos*8+s.reader.bitOffset;if(s.reader.hasByte&&(a-=8),s._init_block()){var f=i.pos;s._read_bunzip(),e(a,i.pos-f)}else{var l=s.reader.read(32);if(r&&"eof"in n&&!n.eof())s._start_bunzip(n,i),console.assert(s.dbufSize===o,"shouldn't change block size within multistream file");else break}}};k.Stream=K;k.version=ve.version;k.license=ve.license;ke.exports=k});import*as Pe from"fs";import*as j from"zlib";var Fe=we(),Se=512,Ke=65536,je=16777216,Ge=67108864,Qe=2147483648,$e={TABLE_OFFSET:0,HASH_A:1,HASH_B:2,TABLE:3};function Ve(){let t=1048577,e=new Uint32Array(256*5);for(let r=0;r<256;r++){let n=r;for(let i=0;i<5;i++){t=(t*125+3)%2796203;let s=(t&65535)<<16;t=(t*125+3)%2796203;let o=t&65535;e[n]=(s|o)>>>0,n+=256}}return e}var Ee=Ve(),Z=class{file;header;hashTable;blockTable;files;constructor(e,r=!0){if(Buffer.isBuffer(e)?this.file=e:this.file=Pe.readFileSync(e),this.header=this.readHeader(),this.hashTable=this.readTable("hash"),this.blockTable=this.readTable("block"),r){let n=this.readFile("(listfile)");n?this.files=n.toString("utf8").trim().split(`\r
2
+ `):this.files=null}else this.files=null}readHeader(){let e=this.file.toString("utf8",0,4),r;if(e==="MPQ")r=this.readMPQHeader(),r.offset=0;else if(e==="MPQ\x1B"){let n=this.readMPQUserDataHeader();r=this.readMPQHeader(n.mpqHeaderOffset),r.offset=n.mpqHeaderOffset,r.userDataHeader=n}else throw new Error("Invalid MPQ file header");return r}readMPQHeader(e=0){let r=this.file.subarray(e,e+32),n={magic:r.toString("utf8",0,4),headerSize:r.readUInt32LE(4),archiveSize:r.readUInt32LE(8),formatVersion:r.readUInt16LE(12),sectorSizeShift:r.readUInt16LE(14),hashTableOffset:r.readUInt32LE(16),blockTableOffset:r.readUInt32LE(20),hashTableEntries:r.readUInt32LE(24),blockTableEntries:r.readUInt32LE(28)};if(n.formatVersion===1){let i=this.file.subarray(e+32,e+32+12);n.extendedBlockTableOffset=i.readUInt32LE(0)+i.readUInt32LE(4)*4294967296,n.hashTableOffsetHigh=i.readInt8(8),n.blockTableOffsetHigh=i.readInt8(10)}return n}readMPQUserDataHeader(){let e=this.file.subarray(0,16),r={magic:e.toString("utf8",0,4),userDataSize:e.readUInt32LE(4),mpqHeaderOffset:e.readUInt32LE(8),userDataHeaderSize:e.readUInt32LE(12)};return r.content=this.file.subarray(16,16+r.userDataHeaderSize),r}readTable(e){let r=e==="hash"?"hashTableOffset":"blockTableOffset",n=e==="hash"?"hashTableEntries":"blockTableEntries",i=this.header[r],s=this.header[n];if(i==null||s==null)throw new Error("Missing "+e+" offset or entries");let o=this.hash("("+e+" table)","TABLE"),a=this.file.subarray(i+(this.header.offset||0),i+(this.header.offset||0)+s*16);a=this.decrypt(a,o);let f=[];for(let l=0;l<s;l++){let c=a.subarray(l*16,l*16+16);e==="hash"?f.push({hashA:c.readUInt32LE(0),hashB:c.readUInt32LE(4),locale:c.readUInt16LE(8),platform:c.readUInt16LE(10),blockTableIndex:c.readUInt32LE(12)}):f.push({offset:c.readUInt32LE(0),archivedSize:c.readUInt32LE(4),size:c.readUInt32LE(8),flags:c.readUInt32LE(12)})}return f}getHashTableEntry(e){let r=this.hash(e,"HASH_A"),n=this.hash(e,"HASH_B");for(let i of this.hashTable)if(i.hashA===r&&i.hashB===n)return i}readFile(e,r=!1){function n(f){let l=f[0];if(l===0)return f;if(l===2)return j.inflateSync(f.subarray(1));if(l===16)return Fe.decode(f.subarray(1));try{return j.inflateSync(f.subarray(1))}catch{return j.inflateRawSync(f.subarray(1))}}let i=this.getHashTableEntry(e);if(!i)return null;let s=this.blockTable[i.blockTableIndex];if(!s||!(s.flags&Qe))return null;if(s.archivedSize===0)return Buffer.alloc(0);let o=s.offset+(this.header.offset||0),a=this.file.subarray(o,o+s.archivedSize);if(s.flags&Ke)throw new Error("Encryption is not supported");if(s.flags&je)s.flags&Se&&(r||s.size>s.archivedSize)&&(a=n(a));else{let f=512<<this.header.sectorSizeShift,l=Math.trunc(s.size/f)+1,c=!1;s.flags&Ge&&(c=!0,l+=1);let u=[];for(let p=0;p<l+1;p++)u.push(a.readUInt32LE(4*p));let b=u.length-(c?2:1),h=[],m=s.size;for(let p=0;p<b;p++){let d=a.subarray(u[p],u[p+1]);s.flags&Se&&(r||m>d.length)&&(d=n(d)),m-=d.length,h.push(d)}a=Buffer.concat(h)}return a}hash(e,r){let n=2146271213,i=4008636142;for(let s=0;s<e.length;s++){let o=e.toUpperCase().charCodeAt(s);n=(Ee[($e[r]<<8)+o]^n+i)>>>0,i=o+n+i+(i<<5)+3>>>0}return n}decrypt(e,r){let n=r>>>0,i=4008636142,s=Buffer.alloc(e.length),o=e.length/4;for(let a=0;a<o;a++){i=i+Ee[1024+(n&255)]>>>0;let f=e.readUInt32LE(a*4);f=(f^n+i)>>>0,n=((~n<<21)+286331153|n>>>11)>>>0,i=f+i+(i<<5)+3>>>0,s.writeUInt32LE(f,a*4)}return s}};var G=class extends Error{constructor(e="Truncated Buffer"){super(e),this.name="TruncatedError"}},M=class extends Error{constructor(e="Corrupted Buffer"){super(e),this.name="CorruptedError"}},Q=class{_data;_used;_next;_nextbits;_bigendian;constructor(e,r="big"){this._data=e,this._used=0,this._next=0,this._nextbits=0,this._bigendian=r==="big"}done(){return this._nextbits===0&&this._used>=this._data.length}used_bits(){return this._used*8-this._nextbits}byte_align(){this._nextbits=0}read_aligned_bytes(e){if(this.byte_align(),this._used+e>this._data.length)throw new G;let r=this._data.subarray(this._used,this._used+e);return this._used+=e,r}read_bits(e){let r=0,n=0;for(;n!==e;){if(this._nextbits===0){if(this.done())throw new G;this._next=this._data[this._used],this._used+=1,this._nextbits=8}let i=Math.min(e-n,this._nextbits),s=this._next&(1<<i)-1;this._bigendian?r+=s*Math.pow(2,e-n-i):r+=s*Math.pow(2,n),this._next>>=i,this._nextbits-=i,n+=i}return r}read_bits_bigint(e){let r=0n,n=0;for(;n!==e;){if(this._nextbits===0){if(this.done())throw new G;this._next=this._data[this._used],this._used+=1,this._nextbits=8}let i=Math.min(e-n,this._nextbits),s=BigInt(this._next&(1<<i)-1);this._bigendian?r|=s<<BigInt(e-n-i):r|=s<<BigInt(n),this._next>>=i,this._nextbits-=i,n+=i}return r}read_unaligned_bytes(e){let r=Buffer.alloc(e);for(let n=0;n<e;n++)r[n]=this.read_bits(8);return r}};var $=class{_buffer;_typeinfos;constructor(e,r){this._buffer=new Q(e),this._typeinfos=r}instance(e){if(e>=this._typeinfos.length)throw new M(`Invalid typeid ${e}`);let r=this._typeinfos[e],n=r[0],i=r[1]||[],s=this[n];if(typeof s!="function")throw new Error(`Decoder method ${n} not implemented`);return s.apply(this,i)}byte_align(){this._buffer.byte_align()}done(){return this._buffer.done()}used_bits(){return this._buffer.used_bits()}_array(e,r){let n=this._int(e),i=new Array(n);for(let s=0;s<n;s++)i[s]=this.instance(r);return i}_bitarray(e){let r=this._int(e);return[r,this._buffer.read_bits(r)]}_blob(e){let r=this._int(e);return this._buffer.read_aligned_bytes(r)}_bool(){return this._int([0,1])!==0}_choice(e,r){let n=this._int(e);if(!(n in r))throw new M(`Choice tag ${n} not found`);let i=r[n];return{[i[0]]:this.instance(i[1])}}_fourcc(){let e=this._buffer.read_bits(32),r=Buffer.alloc(4);return r.writeUInt32BE(e,0),r.toString("ascii")}_int(e){return e[0]+this._buffer.read_bits(e[1])}_null(){return null}_optional(e){return this._bool()?this.instance(e):null}_real32(){return this._buffer.read_unaligned_bytes(4).readFloatBE(0)}_real64(){return this._buffer.read_unaligned_bytes(8).readDoubleBE(0)}_struct(e){let r={};for(let n of e)if(n[0]==="__parent"){let i=this.instance(n[1]);if(typeof i=="object"&&i!==null)r={...r,...i};else{if(e.length===1)return i;r[n[0]]=i}}else r[n[0]]=this.instance(n[1]);return r}},L=class{_buffer;_typeinfos;constructor(e,r){this._buffer=new Q(e),this._typeinfos=r}instance(e){if(e>=this._typeinfos.length)throw new M(`Invalid typeid ${e}`);let r=this._typeinfos[e],n=r[0],i=r[1]||[],s=this[n];if(typeof s!="function")throw new Error(`Decoder method ${n} not implemented`);return s.apply(this,i)}byte_align(){this._buffer.byte_align()}done(){return this._buffer.done()}used_bits(){return this._buffer.used_bits()}_expect_skip(e){if(this._buffer.read_bits(8)!==e)throw new M(`Expected skip ${e}`)}_vint(){let e=this._buffer.read_bits(8),r=(e&1)!==0,n=BigInt(e>>1&63),i=6n;for(;(e&128)!==0;)e=this._buffer.read_bits(8),n|=BigInt(e&127)<<i,i+=7n;let s=r?-n:n;return s>=BigInt(Number.MIN_SAFE_INTEGER)&&s<=BigInt(Number.MAX_SAFE_INTEGER)?Number(s):s}_array(e,r){this._expect_skip(0);let n=Number(this._vint()),i=new Array(n);for(let s=0;s<n;s++)i[s]=this.instance(r);return i}_bitarray(e){this._expect_skip(1);let r=Number(this._vint());return[r,this._buffer.read_aligned_bytes(Math.floor((r+7)/8))]}_blob(e){this._expect_skip(2);let r=Number(this._vint());return this._buffer.read_aligned_bytes(r)}_bool(){return this._expect_skip(6),this._buffer.read_bits(8)!==0}_choice(e,r){this._expect_skip(3);let n=Number(this._vint());if(!(n in r))return this._skip_instance(),{};let i=r[n];return{[i[0]]:this.instance(i[1])}}_fourcc(){return this._expect_skip(7),this._buffer.read_aligned_bytes(4)}_int(e){return this._expect_skip(9),Number(this._vint())}_null(){return null}_optional(e){return this._expect_skip(4),this._buffer.read_bits(8)!==0?this.instance(e):null}_real32(){return this._expect_skip(7),this._buffer.read_aligned_bytes(4).readFloatBE(0)}_real64(){return this._expect_skip(8),this._buffer.read_aligned_bytes(8).readDoubleBE(0)}_struct(e){this._expect_skip(5);let r={},n=Number(this._vint());for(let i=0;i<n;i++){let s=Number(this._vint()),o=e.find(a=>a[2]===s);if(o)if(o[0]==="__parent"){let a=this.instance(o[1]);typeof a=="object"&&a!==null?r={...r,...a}:e.length===1?r=a:r[o[0]]=a}else r[o[0]]=this.instance(o[1]);else this._skip_instance()}return r}_skip_instance(){let e=this._buffer.read_bits(8);if(e===0){let r=Number(this._vint());for(let n=0;n<r;n++)this._skip_instance()}else if(e===1){let r=Number(this._vint());this._buffer.read_aligned_bytes(Math.floor((r+7)/8))}else if(e===2){let r=Number(this._vint());this._buffer.read_aligned_bytes(r)}else if(e===3)this._vint(),this._skip_instance();else if(e===4)this._buffer.read_bits(8)!==0&&this._skip_instance();else if(e===5){let r=Number(this._vint());for(let n=0;n<r;n++)this._vint(),this._skip_instance()}else e===6?this._buffer.read_aligned_bytes(1):e===7?this._buffer.read_aligned_bytes(4):e===8?this._buffer.read_aligned_bytes(8):e===9&&this._vint()}};import V from"fs";import H from"path";function We(){let t=[];try{t.push(H.resolve(__dirname,"..","protocols")),t.push(H.resolve(__dirname,"..","..","protocols"))}catch{}t.push(H.resolve(process.cwd(),"protocols"));let e=process.cwd();for(;e!==H.dirname(e);){let r=H.join(e,"node_modules","@astefanski","storm-parser","protocols");t.push(r),e=H.dirname(e)}for(let r of t)if(V.existsSync(r)&&V.readdirSync(r).some(n=>n.endsWith(".json")))return r;throw new Error(`@astefanski/storm-parser: Protocols directory not found. Did postinstall run? Try: npx tsx node_modules/@astefanski/storm-parser/scripts/postinstall.ts
3
+ Searched: `+t.join(", "))}var re=new Map,ne=null;function Re(){return ne||(ne=We()),ne}function J(t){if(re.has(t))return re.get(t);let e=Re(),r=H.join(e,`protocol${t}.json`);if(!V.existsSync(r))return null;let n=JSON.parse(V.readFileSync(r,"utf-8"));return re.set(t,n),n}function Be(){let t=Re();return V.readdirSync(t).filter(e=>/^protocol\d+\.json$/.test(e)).map(e=>parseInt(e.match(/\d+/)[0],10)).sort((e,r)=>e-r)}var W=class{mpq;header;build=0;protocol;baseProtocol;constructor(e){this.mpq=new Z(e,!1)}init(){let e=J(29406);if(!e)throw new Error("Base protocol29406 not found. Did postinstall run? Try: npx tsx node_modules/@astefanski/storm-parser/scripts/postinstall.ts");this.baseProtocol=e;let r=this.mpq.header.userDataHeader;if(!r||!r.content)throw new Error("Replay does not have a user data header");let n=new L(r.content,this.baseProtocol.typeinfos);this.header=n.instance(this.baseProtocol.replay_header_typeid),this.build=this.header.m_version.m_baseBuild,this.protocol=this.loadProtocolForBuild(this.build)}loadProtocolForBuild(e){let r=J(e);if(!r){let n=Be(),i=n[0];for(let s of n)s<=e&&s>i&&(i=s);r=J(i)}if(!r)throw new Error(`No protocol found for build ${e}`);return r}*decodeEventStream(e,r,n,i){if(!this.protocol)throw new Error("Protocol not loaded");let s=0;for(;!e.done();){let o=e.used_bits(),a=e.instance(this.protocol.svaruint32_typeid),f=Object.keys(a)[0],l=a[f];s+=l;let c=i?e.instance(this.protocol.replay_userid_typeid):void 0,u=Number(e.instance(r)),b=n[u];if(!b)throw new Error(`Unknown eventid(${u})`);let h=b[0],m=b[1],p=e.instance(h);p._event=m,p._eventid=u,p._gameloop=s,i&&(p._userid=c),e.byte_align(),p._bits=e.used_bits()-o,yield p}}getDetails(){if(!this.protocol)throw new Error("Protocol not loaded");let e=this.mpq.readFile("replay.details");return e?new L(e,this.protocol.typeinfos).instance(this.protocol.game_details_typeid):null}getInitData(){if(!this.protocol)throw new Error("Protocol not loaded");let e=this.mpq.readFile("replay.initData");return e?new $(e,this.protocol.typeinfos).instance(this.protocol.replay_initdata_typeid):null}getTrackerEvents(){if(!this.protocol)throw new Error("Protocol not loaded");let e=this.mpq.readFile("replay.tracker.events");if(!e)return[];let r=new L(e,this.protocol.typeinfos);return Array.from(this.decodeEventStream(r,this.protocol.tracker_eventid_typeid,this.protocol.tracker_event_types,!1))}getGameEvents(){if(!this.protocol)throw new Error("Protocol not loaded");let e=this.mpq.readFile("replay.game.events");if(!e)return[];let r=new $(e,this.protocol.typeinfos);return Array.from(this.decodeEventStream(r,this.protocol.game_eventid_typeid,this.protocol.game_event_types,!0))}extractFile(e){return this.mpq.readFile(e)}getHeader(){return this.header}getBuild(){return this.build}};var De={TownCannonTowerL2:"Fort Tower",TownCannonTowerL3:"Keep Tower",TownTownHallL2:"Fort",TownTownHallL3:"Keep",TownMoonwellL2:"Fort Well",TownMoonwellL3:"Keep Well"},qe={MercLanerMeleeKnight:"Bruiser Camp",MercLanerRangedMage:"Bruiser Camp",MercLanerSiegeGiant:"Siege Camp",MercLanerRangedMinion:"Siege Camp"};function O(t){return Buffer.isBuffer(t)?t.toString("utf8"):typeof t=="string"?t:String(t??"")}function v(t,e){if(!t)return;let r=t.find(n=>O(n.m_key)===e);return r!==void 0?r.m_value:void 0}function ee(t,e){if(!t)return;let r=t.find(n=>O(n.m_key)===e);return r!==void 0?O(r.m_value):void 0}function w(t,e){if(!t)return;let r=t.find(n=>O(n.m_key)===e);return r!==void 0?r.m_value:void 0}function ie(t,e){return`${t}-${e}`}function P(t,e){return(t-e)/16}function Ce(t,e,r){let n={playerIDMap:{},loopGameStart:0,loopGameEnd:0,unitIndex:{},heroUnits:{},heroLives:{}};r.levelTimes={0:{},1:{}},r.takedowns=[],r.structures={},r.XPBreakdown=[],r.mercs={captures:[],units:{}},r.objective={0:{count:0,events:[]},1:{count:0,events:[]},type:r.map||""};for(let i of t)switch(n.loopGameEnd=Math.max(n.loopGameEnd,i._gameloop),i._event){case"NNet.Replay.Tracker.SStatGameEvent":Ye(i,n,e,r);break;case"NNet.Replay.Tracker.SUnitBornEvent":et(i,n,r);break;case"NNet.Replay.Tracker.SUnitDiedEvent":tt(i,n,r);break;case"NNet.Replay.Tracker.SUnitOwnerChangeEvent":rt(i,n);break}return r.loopGameStart=n.loopGameStart,r.loopLength=n.loopGameEnd,r.length=(n.loopGameEnd-n.loopGameStart)/16,nt(n,e),{playerIDMap:n.playerIDMap}}function Ye(t,e,r,n){let i=O(t.m_eventName),s=t.m_intData,o=t.m_stringData,a=t.m_fixedData;switch(i){case"PlayerInit":{let f=v(s,"PlayerID"),l=ee(o,"ToonHandle");f!==void 0&&l&&r[l]&&(e.playerIDMap[f]=l);break}case"GatesOpen":e.loopGameStart=t._gameloop;break;case"LevelUp":{let f=v(s,"PlayerID"),l=v(s,"Level");if(f===void 0||l===void 0)break;let c;if(f>=1&&f<=5)c="0";else if(f>=6&&f<=10)c="1";else break;n.levelTimes[c][String(l)]||(n.levelTimes[c][String(l)]={loop:t._gameloop,level:l,team:c,time:P(t._gameloop,e.loopGameStart)});break}case"TalentChosen":{let f=v(s,"PlayerID"),l=ee(o,"PurchaseName");if(f===void 0||!l)break;let c=e.playerIDMap[f];if(!c||!r[c])break;let u=["Tier1Choice","Tier2Choice","Tier3Choice","Tier4Choice","Tier5Choice","Tier6Choice","Tier7Choice"];for(let b of u)if(!r[c].talents[b]){r[c].talents[b]=l;break}break}case"PlayerDeath":{let f=v(s,"PlayerID"),l=v(s,"KillingPlayer"),c=w(a,"PositionX")??0,u=w(a,"PositionY")??0;if(f===void 0)break;let b=e.playerIDMap[f];if(!b)break;let h={player:b,hero:r[b]?.hero||""},m=[],p=r[b]?.team;if(l&&l>0){let _=e.playerIDMap[l];_&&r[_]&&m.push({player:_,hero:r[_].hero})}for(let[_,y]of Object.entries(e.playerIDMap)){let x=r[y];!x||x.team===p||parseInt(_)===l||m.push({player:y,hero:x.hero})}let d={loop:t._gameloop,time:P(t._gameloop,e.loopGameStart),x:c,y:u,killers:m,victim:h};n.takedowns.push(d),r[b]&&r[b].deaths.push(d);for(let _ of m)r[_.player]&&r[_.player].takedowns.push(d);break}case"PeriodicXPBreakdown":{let f=v(s,"Team");if(f===void 0)break;let l={GameTime:v(s,"GameTime")??0,PreviousGameTime:v(s,"PreviousGameTime")??0,MinionXP:w(a,"MinionXP")??0,CreepXP:w(a,"CreepXP")??0,StructureXP:w(a,"StructureXP")??0,HeroXP:w(a,"HeroXP")??0,TrickleXP:w(a,"TrickleXP")??0};n.XPBreakdown.push({loop:t._gameloop,time:P(t._gameloop,e.loopGameStart),team:f,teamLevel:v(s,"TeamLevel")??0,breakdown:l,theoreticalMinionXP:v(s,"TheoreticalMinionXP")??0});break}case"EndOfGameXPBreakdown":{let f=v(s,"Team");if(f===void 0)break;n.XPBreakdown.push({loop:t._gameloop,time:P(t._gameloop,e.loopGameStart),team:f,theoreticalMinionXP:v(s,"TheoreticalMinionXP")??0,breakdown:{GameTime:0,PreviousGameTime:0,MinionXP:w(a,"MinionXP")??0,CreepXP:w(a,"CreepXP")??0,StructureXP:w(a,"StructureXP")??0,HeroXP:w(a,"HeroXP")??0,TrickleXP:w(a,"TrickleXP")??0}});break}case"JungleCampCapture":{let f=v(s,"CampTeam")??v(s,"Team")??0;n.mercs.captures.push({loop:t._gameloop,type:ee(o,"CampType")??ee(o,"Result")??"Unknown Camp",team:f,time:P(t._gameloop,e.loopGameStart)});break}case"EndOfGameTalentChoices":{let f=v(s,"PlayerID");if(f===void 0)break;let l=e.playerIDMap[f];if(!l||!r[l])break;let c={},u=["Tier1Choice","Tier2Choice","Tier3Choice","Tier4Choice","Tier5Choice","Tier6Choice","Tier7Choice"];if(o)for(let b=0;b<o.length&&b<u.length;b++){let h=O(o[b].m_value);h&&(c[u[b]]=h)}r[l].talents=c;break}default:Je(i,t,e,n,s,a);break}}var Ze=new Set(["SoulEatersSpawned","TributeCollected","RavenCurseActivated","AltarCaptured","SkyTempleShotsFired","DragonKnightActivated","GardenTerrorActivated","InfernalShrineCaptured","PunisherKilled","VolskayaVehicleCapture","BraxisWaveStart","ImmortalDefeated","NukeExploded","PayloadDelivered","AlteracCavalryCharge","AlteracCavalry"]);function Je(t,e,r,n,i,s){if(!Ze.has(t)||!i)return;let o=v(i,"Team")??v(i,"Event")??0,a=o===0||o===1?o:0,f={team:o,loop:e._gameloop,time:P(e._gameloop,r.loopGameStart),score:v(i,"Score"),duration:w(s,"Duration")};n.objective[a].events.push(f),n.objective[a].count=n.objective[a].events.length}function et(t,e,r){let n=O(t.m_unitTypeName),i=t.m_unitTagIndex,s=t.m_unitTagRecycle,o=ie(i,s),a=t.m_controlPlayerId??t.m_upkeepPlayerId,f=t.m_x??0,l=t.m_y??0,c;if(a>=1&&a<=5?c=0:a>=6&&a<=10?c=1:a===11?c=0:a===12?c=1:c=a<=5?0:1,e.unitIndex[o]={type:n,playerId:a,team:c,x:f,y:l,bornLoop:t._gameloop},n.startsWith("Town")&&De[n]&&(r.structures[o]={type:n,name:De[n],tag:i,rtag:s,x:f,y:l,team:c}),n.startsWith("Hero")&&a>=1&&a<=10){e.heroUnits[o]=a,e.heroLives[a]||(e.heroLives[a]=[]);let u=P(t._gameloop,e.loopGameStart);e.heroLives[a].push({born:u,locations:[{x:f,y:l,time:u}],duration:0})}if(qe[n]){let b=r.mercs.captures[r.mercs.captures.length-1]?.loop??t._gameloop;r.mercs.units[o]={loop:b,team:c,type:n,locations:[{x:f,y:l}],time:P(b,e.loopGameStart),duration:0}}}function tt(t,e,r){let n=ie(t.m_unitTagIndex,t.m_unitTagRecycle),i=P(t._gameloop,e.loopGameStart);r.structures[n]&&(r.structures[n].destroyedLoop=t._gameloop,r.structures[n].destroyed=i),r.mercs.units[n]&&(r.mercs.units[n].duration=i-r.mercs.units[n].time);let s=e.heroUnits[n];if(s!==void 0&&e.heroLives[s]){let o=e.heroLives[s],a=o[o.length-1];a&&a.died===void 0&&(a.died=i,a.duration=i-a.born)}}function rt(t,e){let r=ie(t.m_unitTagIndex,t.m_unitTagRecycle),n=t.m_controlPlayerId??t.m_upkeepPlayerId;e.unitIndex[r]&&(e.unitIndex[r].playerId=n,n>=1&&n<=5?e.unitIndex[r].team=0:n>=6&&n<=10&&(e.unitIndex[r].team=1))}function nt(t,e){for(let[r,n]of Object.entries(t.heroLives)){let i=parseInt(r,10),s=t.playerIDMap[i];if(!s||!e[s])continue;for(let a of n)if(a.died===void 0){let f=a.locations[a.locations.length-1];a.duration=f?f.time-a.born:0}let o="";for(let[a,f]of Object.entries(t.heroUnits))if(f===i){o=a;break}o&&(e[s].units[o]={lives:n})}}var it=["DamageTaken","CreepDamage","Healing","HeroDamage","MinionDamage","SelfHealing","SiegeDamage","ProtectionGivenToAllies","TeamfightDamageTaken","TeamfightHealingDone","TeamfightHeroDamage","TimeCCdEnemyHeroes","TimeRootingEnemyHeroes","TimeSpentDead","TimeStunningEnemyHeroes","TimeSilencingEnemyHeroes"];function st(){return{DamageTaken:0,CreepDamage:0,Healing:0,HeroDamage:0,MinionDamage:0,SelfHealing:0,SiegeDamage:0,ProtectionGivenToAllies:0,TeamfightDamageTaken:0,TeamfightHealingDone:0,TeamfightHeroDamage:0,TimeCCdEnemyHeroes:0,TimeRootingEnemyHeroes:0,TimeSpentDead:0,TimeStunningEnemyHeroes:0,TimeSilencingEnemyHeroes:0,avgTimeSpentDead:0,timeDeadPct:0}}function ot(){return{mercCaptures:0,mercUptime:0,mercUptimePercent:0,structures:{},KDA:0,PPK:0,timeTo10:0,totals:st(),levelAdvTime:0,maxLevelAdv:0,avgLevelAdv:0,levelAdvPct:0,uptime:[],uptimeHistogram:{},wipes:0,avgHeroesAlive:0,aces:0,timeWithHeroAdv:0,pctWithHeroAdv:0,passiveXPRate:0,passiveXPDiff:0,passiveXPGain:0}}function Ae(t,e){at(t,e),ct(t,e),lt(t),ut(t),dt(t,e),bt(t)}function at(t,e){for(let r of["0","1"]){let n=t.teams[r];if(!n)continue;n.names=[],n.heroes=[],n.tags=[],n.stats=ot();for(let u of n.ids){let b=e[u];b&&(n.names.push(b.name),n.heroes.push(b.hero),n.tags.push(b.tag))}for(let u of n.ids){let b=e[u];if(b)for(let h of it){let m=b.gameStats[h];typeof m=="number"&&(n.stats.totals[h]+=m)}}let i=n.ids.reduce((u,b)=>u+(e[b]?.gameStats.Deaths??0),0);i>0&&(n.stats.totals.avgTimeSpentDead=n.stats.totals.TimeSpentDead/i),t.length>0&&(n.stats.totals.timeDeadPct=n.stats.totals.TimeSpentDead/(t.length*n.ids.length));let s=n.takedowns,o=i;n.stats.KDA=o>0?s/o:s,n.stats.PPK=s>0?t.takedowns.filter(u=>n.ids.includes(u.killers[0]?.player)).reduce((u,b)=>u+b.killers.length,0)/s:0;let a=t.levelTimes[r];a?.["10"]&&(n.stats.timeTo10=a[10].time);let f=parseInt(r,10),l=t.mercs.captures.filter(u=>u.team===f);n.stats.mercCaptures=l.length;let c=0;for(let u of Object.values(t.mercs.units))u.team===f&&u.duration>0&&(c+=u.duration);n.stats.mercUptime=c,n.stats.mercUptimePercent=t.length>0?c/t.length:0,ft(t,n,r)}}function ft(t,e,r){let n=parseInt(r,10),i=n===0?1:0,s={};for(let o of Object.values(t.structures)){let a=o.name;s[a]||(s[a]={lost:0,destroyed:0,first:t.length}),o.team===i&&o.destroyed!==void 0&&(s[a].destroyed++,s[a].first=Math.min(s[a].first,o.destroyed)),o.team===n&&o.destroyed!==void 0&&s[a].lost++}e.stats.structures=s}function ct(t,e){let r=t.length/60;for(let n of Object.values(e)){let i=n.gameStats,s=i.Deaths??0,o=i.TeamTakedowns??0;r>0&&(i.DPM=(i.HeroDamage??0)/r,i.HPM=((i.Healing??0)+(i.SelfHealing??0))/r,i.XPM=(i.ExperienceContribution??0)/r),i.KDA=s>0?(i.Takedowns??0)/s:i.Takedowns??0,i.KillParticipation=o>0?(i.Takedowns??0)/o:0,i.damageDonePerDeath=s>0?(i.HeroDamage??0)/s:i.HeroDamage??0,i.damageTakenPerDeath=s>0?(i.DamageTaken??0)/s:i.DamageTaken??0,i.healingDonePerDeath=s>0?((i.Healing??0)+(i.SelfHealing??0))/s:(i.Healing??0)+(i.SelfHealing??0),i.length=t.length}}function lt(t){let e=0,r=0,n=new Set(t.teams[0]?.ids||[]);for(let i of t.takedowns)n.has(i.victim.player)?r++:e++;t.team0Takedowns=e,t.team1Takedowns=r}function ut(t){let e=t.levelTimes[0]||{},r=t.levelTimes[1]||{},n=[];for(let l of Object.values(e))n.push({time:l.time,team:0,level:l.level});for(let l of Object.values(r))n.push({time:l.time,team:1,level:l.level});if(n.sort((l,c)=>l.time-c.time),n.length===0){t.levelAdvTimeline=[];return}let i=[],s=0,o=0,a=n[0].time;for(let l of n){let c=s-o;l.time>a&&i.push({start:a,end:l.time,levelDiff:c,length:l.time-a}),l.team===0?s=l.level:o=l.level,a=l.time}let f=s-o;t.length>a&&i.push({start:a,end:t.length,levelDiff:f,length:t.length-a}),t.levelAdvTimeline=i;for(let l of["0","1"]){let c=t.teams[l];if(!c)continue;let u=l==="0"?1:-1,b=0,h=0,m=0,p=0;for(let d of i){let _=d.levelDiff*u;_>0&&(b+=d.length),h=Math.max(h,_),m+=_*d.length,p+=d.length}c.stats.levelAdvTime=b,c.stats.maxLevelAdv=h,c.stats.avgLevelAdv=p>0?m/p:0,c.stats.levelAdvPct=t.length>0?b/t.length:0}}function dt(t,e){for(let s of["0","1"]){let o=t.teams[s];if(!o)continue;let a=[];for(let d of o.ids){let _=e[d];if(_)for(let y of _.deaths){a.push({time:y.time,delta:-1});let x=y.time+mt(_.gameStats.Level??1,y.time,t.length);x<t.length&&a.push({time:x,delta:1})}}a.sort((d,_)=>d.time-_.time);let f=[{time:0,heroes:o.ids.length}],l=o.ids.length;for(let d of a)l+=d.delta,l=Math.max(0,Math.min(o.ids.length,l)),f.push({time:d.time,heroes:l});o.stats.uptime=f;let c={};for(let d=0;d<f.length;d++){let y=(d<f.length-1?f[d+1].time:t.length)-f[d].time,x=String(f[d].heroes);c[x]=(c[x]||0)+y}o.stats.uptimeHistogram=c;let u=0,b=0;for(let d=0;d<f.length;d++){let y=(d<f.length-1?f[d+1].time:t.length)-f[d].time;u+=f[d].heroes*y,b+=y}o.stats.avgHeroesAlive=b>0?u/b:o.ids.length,o.stats.wipes=f.filter(d=>d.heroes===0).length,o.stats.aces=0;let h=s==="0"?"1":"0",m=t.teams[h];m?.stats?.uptime&&(o.stats.aces=m.stats.uptime.filter(d=>d.heroes===0).length);let p=t.XPBreakdown.filter(d=>d.team===parseInt(s,10));if(p.length>0){let _=p[p.length-1].breakdown.TrickleXP;o.stats.passiveXPGain=_,o.stats.passiveXPRate=t.length>0?_/(t.length/60):0}}for(let s of["0","1"]){let o=t.teams[s],a=s==="0"?"1":"0",f=t.teams[a];if(!o||!f)continue;let l=o.stats.uptime,c=f.stats.uptime;if(!l.length||!c.length)continue;let u=new Set;for(let m of l)u.add(m.time);for(let m of c)u.add(m.time);let b=Array.from(u).sort((m,p)=>m-p),h=0;for(let m=0;m<b.length;m++){let p=b[m],_=(m<b.length-1?b[m+1]:t.length)-p,y=Ie(l,p),x=Ie(c,p);y>x&&(h+=_)}o.stats.timeWithHeroAdv=h,o.stats.pctWithHeroAdv=t.length>0?h/t.length:0}let r=t.teams[0]?.stats.passiveXPRate??0,n=t.teams[1]?.stats.passiveXPRate??0,i=(r+n)/2;t.teams[0]&&(t.teams[0].stats.passiveXPDiff=i>0?r/i:0),t.teams[1]&&(t.teams[1].stats.passiveXPDiff=i>0?n/i:0)}function Ie(t,e){let r=0;for(let n of t)if(n.time<=e)r=n.heroes;else break;return r}function mt(t,e,r){return t<=1?15:t<=5?15+(t-1)*2:t<=10?23+(t-5)*3:t<=15?38+(t-10)*4:58+(t-15)*5}function bt(t){let e=1/0,r=-1,n=1/0,i=-1;for(let o of Object.values(t.structures))o.destroyed!==void 0&&(o.name==="Fort"&&o.destroyed<e&&(e=o.destroyed,r=o.team===0?1:0),o.name==="Keep"&&o.destroyed<n&&(n=o.destroyed,i=o.team===0?1:0));r>=0&&(t.firstFort=r,t.firstFortWin=r===t.winner),i>=0&&(t.firstKeep=i,t.firstKeepWin=i===t.winner);let s=[...t.objective[0].events.map(o=>({...o,assignedTeam:0})),...t.objective[1].events.map(o=>({...o,assignedTeam:1}))].sort((o,a)=>o.loop-a.loop);s.length>0&&(t.firstObjective=s[0].assignedTeam,t.firstObjectiveWin=s[0].assignedTeam===t.winner),t.firstPickWin=t.picks.first===t.winner}function D(t){return Buffer.isBuffer(t)?t.toString("utf8"):typeof t=="string"?t:String(t??"")}var se=class{static async analyze(e){try{let r=new W(e);await r.init();let n=r.getDetails();if(!n)throw new Error("Missing replay.details from parsed MPQ archive");let i=r.getTrackerEvents(),s=r.getInitData(),a=r.getHeader()?.m_version??{},f={m_flags:a.m_flags??0,m_major:a.m_major??0,m_minor:a.m_minor??0,m_revision:a.m_revision??0,m_build:a.m_baseBuild??r.getBuild(),m_baseBuild:a.m_baseBuild??r.getBuild()},l=n.m_playerList.find(h=>h?.m_toon)?.m_toon,c={version:f,map:D(n.m_title),date:this.fileTimeToDate(n.m_timeUTC).toISOString(),rawDate:Number(n.m_timeUTC),length:0,winner:-1,region:l?.m_region,playerIDs:[],heroes:[],levelTimes:{0:{},1:{}},bans:{0:[],1:[]},picks:{0:[],1:[],first:0},XPBreakdown:[],takedowns:[],mercs:{captures:[],units:{}},team0Takedowns:0,team1Takedowns:0,structures:{},objective:{0:{count:0,events:[]},1:{count:0,events:[]},type:""},teams:{0:this.emptyTeam(),1:this.emptyTeam()},winningPlayers:[],levelAdvTimeline:[],firstPickWin:!1};c.objective.type=c.map||"";let u={};for(let h of n.m_playerList){if(!h?.m_toon)continue;let m=h.m_toon,p=D(m.m_programId),d=`${m.m_region}-${p}-${m.m_realm}-${m.m_id}`,_=D(h.m_hero);u[d]={hero:_,name:D(h.m_name),uuid:m.m_id,region:m.m_region,realm:m.m_realm,ToonHandle:d,tag:0,team:h.m_teamId,win:h.m_result===1,gameStats:{},awards:[],talents:{},takedowns:[],deaths:[],units:{}},c.playerIDs.push(d),c.heroes.push(_)}this.extractBattleTags(r,n,u),this.extractDraft(s,c,n);let{playerIDMap:b}=Ce(i,u,c);this.processScoreEvents(i,b,u);for(let[h,m]of Object.entries(u)){m.win&&(c.winner=m.team,c.winningPlayers.push(h));let p=c.teams[m.team.toString()];p&&(p.level=Math.max(p.level,m.gameStats.Level||0),p.takedowns+=m.gameStats.Takedowns||0,p.ids.push(h))}return Ae(c,u),{status:1,match:c,players:u}}catch(r){return console.error("ReplayAnalyzer Error:",r),{status:-2,error:String(r)}}}static emptyTeam(){return{level:0,takedowns:0,ids:[],names:[],heroes:[],tags:[],stats:{mercCaptures:0,mercUptime:0,mercUptimePercent:0,structures:{},KDA:0,PPK:0,timeTo10:0,totals:{DamageTaken:0,CreepDamage:0,Healing:0,HeroDamage:0,MinionDamage:0,SelfHealing:0,SiegeDamage:0,ProtectionGivenToAllies:0,TeamfightDamageTaken:0,TeamfightHealingDone:0,TeamfightHeroDamage:0,TimeCCdEnemyHeroes:0,TimeRootingEnemyHeroes:0,TimeSpentDead:0,TimeStunningEnemyHeroes:0,TimeSilencingEnemyHeroes:0,avgTimeSpentDead:0,timeDeadPct:0},levelAdvTime:0,maxLevelAdv:0,avgLevelAdv:0,levelAdvPct:0,uptime:[],uptimeHistogram:{},wipes:0,avgHeroesAlive:0,aces:0,timeWithHeroAdv:0,pctWithHeroAdv:0,passiveXPRate:0,passiveXPDiff:0,passiveXPGain:0}}}static extractBattleTags(e,r,n){let i=e.extractFile("replay.server.battlelobby");if(i)try{let s=new RegExp("([\\p{L}\\d]{3,24}#\\d{4,10})[z\xD8]?","gu"),o=i.toString("utf8").match(s);if(!o)return;let a=0;for(let f of r.m_playerList){if(!f?.m_toon)continue;let l=D(f.m_name);for(;a<o.length;){let u=o[a].split("#"),b=u[0],h=u[1].replace(/[zØ]/g,"");if(a++,b===l){let m=f.m_toon,p=`${m.m_region}-${D(m.m_programId)}-${m.m_realm}-${m.m_id}`;n[p]&&(n[p].tag=parseInt(h,10)||0);break}}}}catch(s){console.error("BattleTag regex error:",s)}}static extractDraft(e,r,n){if(e)try{let i=e.m_syncLobbyState;if(!i)return;let s=i.m_lobbyState;if(!s)return;let o=[],a=[];for(let c of n.m_playerList){if(!c?.m_toon)continue;let u=D(c.m_hero);c.m_teamId===0?o.push(u):c.m_teamId===1&&a.push(u)}if(r.picks={0:o,1:a,first:0},typeof s.m_gameMode=="number"&&(r.mode=s.m_gameMode),typeof s.m_gameType=="number"&&(r.type=s.m_gameType),!s.m_slots)return;if(s.m_pickedMapTag!==void 0){let c=s.m_firstPickTeam??0;r.picks.first=c}}catch{}}static processScoreEvents(e,r,n){for(let i of e){if(i._event!=="NNet.Replay.Tracker.SScoreResultEvent")continue;let s=i.m_instanceList;for(let o of s){let a=D(o.m_name),f=o.m_values,l=a.startsWith("EndOfMatchAward"),c=0;for(let u of f)if(u&&u.length>0&&u[0]!==void 0){let b=c+1,h=r[b];if(h&&n[h]){let m=typeof u[0]=="object"&&u[0]!==null&&"m_value"in u[0]?u[0].m_value:u[0];m!=null&&(l?m===1&&n[h].awards.push(a):n[h].gameStats[a]=m)}c++}else u&&u.length===0&&c++}}}static fileTimeToDate(e){return new Date(Number(e)/1e4-116444736e5)}};export{se as ReplayAnalyzer,W as ReplayParser};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astefanski/storm-parser",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "Storm Parser is a tool for parsing Heroes of the Storm replays.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -49,7 +49,7 @@
49
49
  "test:watch": "vitest",
50
50
  "lint": "eslint . --cache",
51
51
  "lint:fix": "eslint . --fix --cache",
52
- "build": "tsup src/index.ts --format cjs,esm --dts --minify --clean --no-splitting",
52
+ "build": "tsup",
53
53
  "postinstall": "tsx scripts/postinstall.ts",
54
54
  "generate:protocols": "tsx scripts/postinstall.ts"
55
55
  }