herostats 0.1.0

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.
Files changed (85) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.travis.yml +4 -0
  4. data/CODE_OF_CONDUCT.md +13 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +7 -0
  7. data/README.md +34 -0
  8. data/Rakefile +10 -0
  9. data/bin/console +14 -0
  10. data/bin/setup +7 -0
  11. data/herostats.gemspec +33 -0
  12. data/lib/heroprotocol/LICENSE +19 -0
  13. data/lib/heroprotocol/README.md +91 -0
  14. data/lib/heroprotocol/__init__.py +0 -0
  15. data/lib/heroprotocol/decoders.py +311 -0
  16. data/lib/heroprotocol/heroprotocol.py +136 -0
  17. data/lib/heroprotocol/mpyq/LICENSE +22 -0
  18. data/lib/heroprotocol/mpyq/MANIFEST.in +3 -0
  19. data/lib/heroprotocol/mpyq/README.md +202 -0
  20. data/lib/heroprotocol/mpyq/__init__.py +0 -0
  21. data/lib/heroprotocol/mpyq/mpyq.py +406 -0
  22. data/lib/heroprotocol/mpyq/setup.py +33 -0
  23. data/lib/heroprotocol/protocol29406.py +491 -0
  24. data/lib/heroprotocol/protocol30414.py +492 -0
  25. data/lib/heroprotocol/protocol30509.py +492 -0
  26. data/lib/heroprotocol/protocol30829.py +492 -0
  27. data/lib/heroprotocol/protocol30948.py +492 -0
  28. data/lib/heroprotocol/protocol31090.py +492 -0
  29. data/lib/heroprotocol/protocol31360.py +494 -0
  30. data/lib/heroprotocol/protocol31566.py +494 -0
  31. data/lib/heroprotocol/protocol31726.py +494 -0
  32. data/lib/heroprotocol/protocol31948.py +494 -0
  33. data/lib/heroprotocol/protocol32120.py +494 -0
  34. data/lib/heroprotocol/protocol32253.py +494 -0
  35. data/lib/heroprotocol/protocol32455.py +496 -0
  36. data/lib/heroprotocol/protocol32524.py +496 -0
  37. data/lib/heroprotocol/protocol33182.py +499 -0
  38. data/lib/heroprotocol/protocol33353.py +499 -0
  39. data/lib/heroprotocol/protocol33684.py +502 -0
  40. data/lib/heroprotocol/protocol34053.py +502 -0
  41. data/lib/heroprotocol/protocol34190.py +502 -0
  42. data/lib/heroprotocol/protocol34659.py +502 -0
  43. data/lib/heroprotocol/protocol34846.py +502 -0
  44. data/lib/heroprotocol/protocol35360.py +502 -0
  45. data/lib/heroprotocol/protocol35529.py +502 -0
  46. data/lib/heroprotocol/protocol35634.py +502 -0
  47. data/lib/heroprotocol/protocol35702.py +502 -0
  48. data/lib/heroprotocol/protocol36144.py +502 -0
  49. data/lib/heroprotocol/protocol36280.py +502 -0
  50. data/lib/heroprotocol/protocol36359.py +502 -0
  51. data/lib/heroprotocol/protocol36536.py +502 -0
  52. data/lib/heroprotocol/protocol36693.py +502 -0
  53. data/lib/heroprotocol/protocol37069.py +507 -0
  54. data/lib/heroprotocol/protocol37117.py +507 -0
  55. data/lib/heroprotocol/protocol37274.py +507 -0
  56. data/lib/heroprotocol/protocol37351.py +507 -0
  57. data/lib/heroprotocol/protocol37569.py +507 -0
  58. data/lib/heroprotocol/protocol37795.py +507 -0
  59. data/lib/heroprotocol/protocol38236.py +508 -0
  60. data/lib/heroprotocol/protocol38500.py +508 -0
  61. data/lib/heroprotocol/protocol38593.py +508 -0
  62. data/lib/heroprotocol/protocol38793.py +508 -0
  63. data/lib/heroprotocol/protocol39015.py +508 -0
  64. data/lib/heroprotocol/protocol39153.py +508 -0
  65. data/lib/heroprotocol/protocol39271.py +508 -0
  66. data/lib/heroprotocol/protocol39445.py +508 -0
  67. data/lib/heroprotocol/protocol39595.py +508 -0
  68. data/lib/heroprotocol/protocol39709.py +508 -0
  69. data/lib/heroprotocol/protocol39951.py +508 -0
  70. data/lib/heroprotocol/protocol40087.py +508 -0
  71. data/lib/heroprotocol/protocol40322.py +508 -0
  72. data/lib/heroprotocol/protocol40336.py +526 -0
  73. data/lib/heroprotocol/protocol40431.py +526 -0
  74. data/lib/heroprotocol/protocol40697.py +526 -0
  75. data/lib/heroprotocol/protocol40798.py +526 -0
  76. data/lib/herostats.rb +10 -0
  77. data/lib/herostats/exp_breakdown.rb +24 -0
  78. data/lib/herostats/game.rb +25 -0
  79. data/lib/herostats/init_data_parser.rb +45 -0
  80. data/lib/herostats/player.rb +25 -0
  81. data/lib/herostats/replay_parser.rb +34 -0
  82. data/lib/herostats/team.rb +10 -0
  83. data/lib/herostats/tracker_events_parser.rb +158 -0
  84. data/lib/herostats/version.rb +3 -0
  85. metadata +171 -0
@@ -0,0 +1,508 @@
1
+ # Copyright (c) 2015 Blizzard Entertainment
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ from decoders import *
22
+
23
+
24
+ # Decoding instructions for each protocol type.
25
+ typeinfos = [
26
+ ('_int',[(0,7)]), #0
27
+ ('_int',[(0,4)]), #1
28
+ ('_int',[(0,5)]), #2
29
+ ('_int',[(0,6)]), #3
30
+ ('_int',[(0,14)]), #4
31
+ ('_int',[(0,22)]), #5
32
+ ('_int',[(0,32)]), #6
33
+ ('_choice',[(0,2),{0:('m_uint6',3),1:('m_uint14',4),2:('m_uint22',5),3:('m_uint32',6)}]), #7
34
+ ('_struct',[[('m_userId',2,-1)]]), #8
35
+ ('_blob',[(0,8)]), #9
36
+ ('_int',[(0,8)]), #10
37
+ ('_struct',[[('m_flags',10,0),('m_major',10,1),('m_minor',10,2),('m_revision',10,3),('m_build',6,4),('m_baseBuild',6,5)]]), #11
38
+ ('_int',[(0,3)]), #12
39
+ ('_bool',[]), #13
40
+ ('_array',[(16,0),10]), #14
41
+ ('_optional',[14]), #15
42
+ ('_blob',[(16,0)]), #16
43
+ ('_struct',[[('m_dataDeprecated',15,0),('m_data',16,1)]]), #17
44
+ ('_struct',[[('m_signature',9,0),('m_version',11,1),('m_type',12,2),('m_elapsedGameLoops',6,3),('m_useScaledTime',13,4),('m_ngdpRootKey',17,5),('m_dataBuildNum',6,6),('m_fixedFileHash',17,7)]]), #18
45
+ ('_fourcc',[]), #19
46
+ ('_blob',[(0,7)]), #20
47
+ ('_int',[(0,64)]), #21
48
+ ('_struct',[[('m_region',10,0),('m_programId',19,1),('m_realm',6,2),('m_name',20,3),('m_id',21,4)]]), #22
49
+ ('_struct',[[('m_a',10,0),('m_r',10,1),('m_g',10,2),('m_b',10,3)]]), #23
50
+ ('_int',[(0,2)]), #24
51
+ ('_optional',[10]), #25
52
+ ('_struct',[[('m_name',9,0),('m_toon',22,1),('m_race',9,2),('m_color',23,3),('m_control',10,4),('m_teamId',1,5),('m_handicap',0,6),('m_observe',24,7),('m_result',24,8),('m_workingSetSlotId',25,9),('m_hero',9,10)]]), #26
53
+ ('_array',[(0,5),26]), #27
54
+ ('_optional',[27]), #28
55
+ ('_blob',[(0,10)]), #29
56
+ ('_blob',[(0,11)]), #30
57
+ ('_struct',[[('m_file',30,0)]]), #31
58
+ ('_optional',[13]), #32
59
+ ('_int',[(-9223372036854775808,64)]), #33
60
+ ('_blob',[(0,12)]), #34
61
+ ('_blob',[(40,0)]), #35
62
+ ('_array',[(0,6),35]), #36
63
+ ('_optional',[36]), #37
64
+ ('_array',[(0,6),30]), #38
65
+ ('_optional',[38]), #39
66
+ ('_struct',[[('m_playerList',28,0),('m_title',29,1),('m_difficulty',9,2),('m_thumbnail',31,3),('m_isBlizzardMap',13,4),('m_restartAsTransitionMap',32,16),('m_timeUTC',33,5),('m_timeLocalOffset',33,6),('m_description',34,7),('m_imageFilePath',30,8),('m_campaignIndex',10,15),('m_mapFileName',30,9),('m_cacheHandles',37,10),('m_miniSave',13,11),('m_gameSpeed',12,12),('m_defaultDifficulty',3,13),('m_modPaths',39,14)]]), #40
67
+ ('_optional',[9]), #41
68
+ ('_optional',[35]), #42
69
+ ('_optional',[6]), #43
70
+ ('_struct',[[('m_race',25,-1)]]), #44
71
+ ('_struct',[[('m_team',25,-1)]]), #45
72
+ ('_blob',[(0,9)]), #46
73
+ ('_struct',[[('m_name',9,-18),('m_clanTag',41,-17),('m_clanLogo',42,-16),('m_highestLeague',25,-15),('m_combinedRaceLevels',43,-14),('m_randomSeed',6,-13),('m_racePreference',44,-12),('m_teamPreference',45,-11),('m_testMap',13,-10),('m_testAuto',13,-9),('m_examine',13,-8),('m_customInterface',13,-7),('m_testType',6,-6),('m_observe',24,-5),('m_hero',46,-4),('m_skin',46,-3),('m_mount',46,-2),('m_toonHandle',20,-1)]]), #47
74
+ ('_array',[(0,5),47]), #48
75
+ ('_struct',[[('m_lockTeams',13,-15),('m_teamsTogether',13,-14),('m_advancedSharedControl',13,-13),('m_randomRaces',13,-12),('m_battleNet',13,-11),('m_amm',13,-10),('m_competitive',13,-9),('m_practice',13,-8),('m_cooperative',13,-7),('m_noVictoryOrDefeat',13,-6),('m_heroDuplicatesAllowed',13,-5),('m_fog',24,-4),('m_observers',24,-3),('m_userDifficulty',24,-2),('m_clientDebugFlags',21,-1)]]), #49
76
+ ('_int',[(1,4)]), #50
77
+ ('_int',[(1,8)]), #51
78
+ ('_bitarray',[(0,6)]), #52
79
+ ('_bitarray',[(0,8)]), #53
80
+ ('_bitarray',[(0,2)]), #54
81
+ ('_bitarray',[(0,7)]), #55
82
+ ('_struct',[[('m_allowedColors',52,-6),('m_allowedRaces',53,-5),('m_allowedDifficulty',52,-4),('m_allowedControls',53,-3),('m_allowedObserveTypes',54,-2),('m_allowedAIBuilds',55,-1)]]), #56
83
+ ('_array',[(0,5),56]), #57
84
+ ('_struct',[[('m_randomValue',6,-26),('m_gameCacheName',29,-25),('m_gameOptions',49,-24),('m_gameSpeed',12,-23),('m_gameType',12,-22),('m_maxUsers',2,-21),('m_maxObservers',2,-20),('m_maxPlayers',2,-19),('m_maxTeams',50,-18),('m_maxColors',3,-17),('m_maxRaces',51,-16),('m_maxControls',10,-15),('m_mapSizeX',10,-14),('m_mapSizeY',10,-13),('m_mapFileSyncChecksum',6,-12),('m_mapFileName',30,-11),('m_mapAuthorName',9,-10),('m_modFileSyncChecksum',6,-9),('m_slotDescriptions',57,-8),('m_defaultDifficulty',3,-7),('m_defaultAIBuild',0,-6),('m_cacheHandles',36,-5),('m_hasExtensionMod',13,-4),('m_isBlizzardMap',13,-3),('m_isPremadeFFA',13,-2),('m_isCoopMode',13,-1)]]), #58
85
+ ('_optional',[1]), #59
86
+ ('_optional',[2]), #60
87
+ ('_struct',[[('m_color',60,-1)]]), #61
88
+ ('_array',[(0,4),46]), #62
89
+ ('_array',[(0,17),6]), #63
90
+ ('_array',[(0,9),6]), #64
91
+ ('_struct',[[('m_control',10,-22),('m_userId',59,-21),('m_teamId',1,-20),('m_colorPref',61,-19),('m_racePref',44,-18),('m_difficulty',3,-17),('m_aiBuild',0,-16),('m_handicap',0,-15),('m_observe',24,-14),('m_logoIndex',6,-13),('m_hero',46,-12),('m_skin',46,-11),('m_mount',46,-10),('m_artifacts',62,-9),('m_workingSetSlotId',25,-8),('m_rewards',63,-7),('m_toonHandle',20,-6),('m_licenses',64,-5),('m_tandemLeaderUserId',59,-4),('m_commander',46,-3),('m_commanderLevel',6,-2),('m_hasSilencePenalty',13,-1)]]), #65
92
+ ('_array',[(0,5),65]), #66
93
+ ('_struct',[[('m_phase',12,-11),('m_maxUsers',2,-10),('m_maxObservers',2,-9),('m_slots',66,-8),('m_randomSeed',6,-7),('m_hostUserId',59,-6),('m_isSinglePlayer',13,-5),('m_pickedMapTag',10,-4),('m_gameDuration',6,-3),('m_defaultDifficulty',3,-2),('m_defaultAIBuild',0,-1)]]), #67
94
+ ('_struct',[[('m_userInitialData',48,-3),('m_gameDescription',58,-2),('m_lobbyState',67,-1)]]), #68
95
+ ('_struct',[[('m_syncLobbyState',68,-1)]]), #69
96
+ ('_struct',[[('m_name',20,-1)]]), #70
97
+ ('_blob',[(0,6)]), #71
98
+ ('_struct',[[('m_name',71,-1)]]), #72
99
+ ('_struct',[[('m_name',71,-3),('m_type',6,-2),('m_data',20,-1)]]), #73
100
+ ('_struct',[[('m_type',6,-3),('m_name',71,-2),('m_data',34,-1)]]), #74
101
+ ('_array',[(0,5),10]), #75
102
+ ('_struct',[[('m_signature',75,-2),('m_toonHandle',20,-1)]]), #76
103
+ ('_struct',[[('m_gameFullyDownloaded',13,-14),('m_developmentCheatsEnabled',13,-13),('m_testCheatsEnabled',13,-12),('m_multiplayerCheatsEnabled',13,-11),('m_syncChecksummingEnabled',13,-10),('m_isMapToMapTransition',13,-9),('m_debugPauseEnabled',13,-8),('m_useGalaxyAsserts',13,-7),('m_platformMac',13,-6),('m_cameraFollow',13,-5),('m_baseBuildNum',6,-4),('m_buildNum',6,-3),('m_versionFlags',6,-2),('m_hotkeyProfile',46,-1)]]), #77
104
+ ('_struct',[[]]), #78
105
+ ('_int',[(0,16)]), #79
106
+ ('_struct',[[('x',79,-2),('y',79,-1)]]), #80
107
+ ('_struct',[[('m_which',12,-2),('m_target',80,-1)]]), #81
108
+ ('_struct',[[('m_fileName',30,-5),('m_automatic',13,-4),('m_overwrite',13,-3),('m_name',9,-2),('m_description',29,-1)]]), #82
109
+ ('_struct',[[('m_sequence',6,-1)]]), #83
110
+ ('_null',[]), #84
111
+ ('_int',[(0,20)]), #85
112
+ ('_int',[(-2147483648,32)]), #86
113
+ ('_struct',[[('x',85,-3),('y',85,-2),('z',86,-1)]]), #87
114
+ ('_struct',[[('m_targetUnitFlags',79,-7),('m_timer',10,-6),('m_tag',6,-5),('m_snapshotUnitLink',79,-4),('m_snapshotControlPlayerId',59,-3),('m_snapshotUpkeepPlayerId',59,-2),('m_snapshotPoint',87,-1)]]), #88
115
+ ('_choice',[(0,2),{0:('None',84),1:('TargetPoint',87),2:('TargetUnit',88)}]), #89
116
+ ('_struct',[[('m_target',89,-4),('m_time',86,-3),('m_verb',29,-2),('m_arguments',29,-1)]]), #90
117
+ ('_struct',[[('m_data',90,-1)]]), #91
118
+ ('_int',[(0,25)]), #92
119
+ ('_struct',[[('m_abilLink',79,-3),('m_abilCmdIndex',2,-2),('m_abilCmdData',25,-1)]]), #93
120
+ ('_optional',[93]), #94
121
+ ('_choice',[(0,2),{0:('None',84),1:('TargetPoint',87),2:('TargetUnit',88),3:('Data',6)}]), #95
122
+ ('_int',[(1,32)]), #96
123
+ ('_struct',[[('m_cmdFlags',92,-6),('m_abil',94,-5),('m_data',95,-4),('m_sequence',96,-3),('m_otherUnit',43,-2),('m_unitGroup',43,-1)]]), #97
124
+ ('_int',[(0,9)]), #98
125
+ ('_bitarray',[(0,9)]), #99
126
+ ('_array',[(0,9),98]), #100
127
+ ('_choice',[(0,2),{0:('None',84),1:('Mask',99),2:('OneIndices',100),3:('ZeroIndices',100)}]), #101
128
+ ('_struct',[[('m_unitLink',79,-4),('m_subgroupPriority',10,-3),('m_intraSubgroupPriority',10,-2),('m_count',98,-1)]]), #102
129
+ ('_array',[(0,9),102]), #103
130
+ ('_struct',[[('m_subgroupIndex',98,-4),('m_removeMask',101,-3),('m_addSubgroups',103,-2),('m_addUnitTags',64,-1)]]), #104
131
+ ('_struct',[[('m_controlGroupId',1,-2),('m_delta',104,-1)]]), #105
132
+ ('_struct',[[('m_controlGroupIndex',1,-3),('m_controlGroupUpdate',12,-2),('m_mask',101,-1)]]), #106
133
+ ('_struct',[[('m_count',98,-6),('m_subgroupCount',98,-5),('m_activeSubgroupIndex',98,-4),('m_unitTagsChecksum',6,-3),('m_subgroupIndicesChecksum',6,-2),('m_subgroupsChecksum',6,-1)]]), #107
134
+ ('_struct',[[('m_controlGroupId',1,-2),('m_selectionSyncData',107,-1)]]), #108
135
+ ('_array',[(0,3),86]), #109
136
+ ('_struct',[[('m_recipientId',1,-2),('m_resources',109,-1)]]), #110
137
+ ('_struct',[[('m_chatMessage',29,-1)]]), #111
138
+ ('_int',[(-128,8)]), #112
139
+ ('_struct',[[('x',86,-3),('y',86,-2),('z',86,-1)]]), #113
140
+ ('_struct',[[('m_beacon',112,-9),('m_ally',112,-8),('m_flags',112,-7),('m_build',112,-6),('m_targetUnitTag',6,-5),('m_targetUnitSnapshotUnitLink',79,-4),('m_targetUnitSnapshotUpkeepPlayerId',112,-3),('m_targetUnitSnapshotControlPlayerId',112,-2),('m_targetPoint',113,-1)]]), #114
141
+ ('_struct',[[('m_speed',12,-1)]]), #115
142
+ ('_struct',[[('m_delta',112,-1)]]), #116
143
+ ('_struct',[[('x',86,-2),('y',86,-1)]]), #117
144
+ ('_struct',[[('m_point',117,-4),('m_unit',6,-3),('m_pingedMinimap',13,-2),('m_option',86,-1)]]), #118
145
+ ('_struct',[[('m_verb',29,-2),('m_arguments',29,-1)]]), #119
146
+ ('_struct',[[('m_alliance',6,-2),('m_control',6,-1)]]), #120
147
+ ('_struct',[[('m_unitTag',6,-1)]]), #121
148
+ ('_struct',[[('m_unitTag',6,-2),('m_flags',10,-1)]]), #122
149
+ ('_struct',[[('m_conversationId',86,-2),('m_replyId',86,-1)]]), #123
150
+ ('_optional',[20]), #124
151
+ ('_struct',[[('m_gameUserId',1,-6),('m_observe',24,-5),('m_name',9,-4),('m_toonHandle',124,-3),('m_clanTag',41,-2),('m_clanLogo',42,-1)]]), #125
152
+ ('_array',[(0,5),125]), #126
153
+ ('_int',[(0,1)]), #127
154
+ ('_struct',[[('m_userInfos',126,-2),('m_method',127,-1)]]), #128
155
+ ('_struct',[[('m_purchaseItemId',86,-1)]]), #129
156
+ ('_struct',[[('m_difficultyLevel',86,-1)]]), #130
157
+ ('_choice',[(0,3),{0:('None',84),1:('Checked',13),2:('ValueChanged',6),3:('SelectionChanged',86),4:('TextChanged',30),5:('MouseButton',6)}]), #131
158
+ ('_struct',[[('m_controlId',86,-3),('m_eventType',86,-2),('m_eventData',131,-1)]]), #132
159
+ ('_struct',[[('m_soundHash',6,-2),('m_length',6,-1)]]), #133
160
+ ('_array',[(0,7),6]), #134
161
+ ('_struct',[[('m_soundHash',134,-2),('m_length',134,-1)]]), #135
162
+ ('_struct',[[('m_syncInfo',135,-1)]]), #136
163
+ ('_struct',[[('m_queryId',79,-3),('m_lengthMs',6,-2),('m_finishGameLoop',6,-1)]]), #137
164
+ ('_struct',[[('m_queryId',79,-2),('m_lengthMs',6,-1)]]), #138
165
+ ('_struct',[[('m_animWaitQueryId',79,-1)]]), #139
166
+ ('_struct',[[('m_sound',6,-1)]]), #140
167
+ ('_struct',[[('m_transmissionId',86,-2),('m_thread',6,-1)]]), #141
168
+ ('_struct',[[('m_transmissionId',86,-1)]]), #142
169
+ ('_optional',[80]), #143
170
+ ('_optional',[79]), #144
171
+ ('_optional',[112]), #145
172
+ ('_struct',[[('m_target',143,-6),('m_distance',144,-5),('m_pitch',144,-4),('m_yaw',144,-3),('m_reason',145,-2),('m_follow',13,-1)]]), #146
173
+ ('_struct',[[('m_skipType',127,-1)]]), #147
174
+ ('_int',[(0,11)]), #148
175
+ ('_struct',[[('x',148,-2),('y',148,-1)]]), #149
176
+ ('_struct',[[('m_button',6,-5),('m_down',13,-4),('m_posUI',149,-3),('m_posWorld',87,-2),('m_flags',112,-1)]]), #150
177
+ ('_struct',[[('m_posUI',149,-3),('m_posWorld',87,-2),('m_flags',112,-1)]]), #151
178
+ ('_struct',[[('m_achievementLink',79,-1)]]), #152
179
+ ('_struct',[[('m_hotkey',6,-2),('m_down',13,-1)]]), #153
180
+ ('_struct',[[('m_abilLink',79,-3),('m_abilCmdIndex',2,-2),('m_state',112,-1)]]), #154
181
+ ('_struct',[[('m_soundtrack',6,-1)]]), #155
182
+ ('_struct',[[('m_planetId',86,-1)]]), #156
183
+ ('_struct',[[('m_key',112,-2),('m_flags',112,-1)]]), #157
184
+ ('_struct',[[('m_resources',109,-1)]]), #158
185
+ ('_struct',[[('m_fulfillRequestId',86,-1)]]), #159
186
+ ('_struct',[[('m_cancelRequestId',86,-1)]]), #160
187
+ ('_struct',[[('m_error',86,-2),('m_abil',94,-1)]]), #161
188
+ ('_struct',[[('m_researchItemId',86,-1)]]), #162
189
+ ('_struct',[[('m_mercenaryId',86,-1)]]), #163
190
+ ('_struct',[[('m_battleReportId',86,-2),('m_difficultyLevel',86,-1)]]), #164
191
+ ('_struct',[[('m_battleReportId',86,-1)]]), #165
192
+ ('_int',[(0,19)]), #166
193
+ ('_struct',[[('m_decrementMs',166,-1)]]), #167
194
+ ('_struct',[[('m_portraitId',86,-1)]]), #168
195
+ ('_struct',[[('m_functionName',20,-1)]]), #169
196
+ ('_struct',[[('m_result',86,-1)]]), #170
197
+ ('_struct',[[('m_gameMenuItemIndex',86,-1)]]), #171
198
+ ('_int',[(-32768,16)]), #172
199
+ ('_struct',[[('m_wheelSpin',172,-2),('m_flags',112,-1)]]), #173
200
+ ('_struct',[[('m_purchaseCategoryId',86,-1)]]), #174
201
+ ('_struct',[[('m_button',79,-1)]]), #175
202
+ ('_struct',[[('m_cutsceneId',86,-2),('m_bookmarkName',20,-1)]]), #176
203
+ ('_struct',[[('m_cutsceneId',86,-1)]]), #177
204
+ ('_struct',[[('m_cutsceneId',86,-3),('m_conversationLine',20,-2),('m_altConversationLine',20,-1)]]), #178
205
+ ('_struct',[[('m_cutsceneId',86,-2),('m_conversationLine',20,-1)]]), #179
206
+ ('_struct',[[('m_leaveReason',1,-1)]]), #180
207
+ ('_struct',[[('m_observe',24,-7),('m_name',9,-6),('m_toonHandle',124,-5),('m_clanTag',41,-4),('m_clanLogo',42,-3),('m_hijack',13,-2),('m_hijackCloneGameUserId',59,-1)]]), #181
208
+ ('_optional',[96]), #182
209
+ ('_struct',[[('m_state',24,-2),('m_sequence',182,-1)]]), #183
210
+ ('_struct',[[('m_target',87,-1)]]), #184
211
+ ('_struct',[[('m_target',88,-1)]]), #185
212
+ ('_struct',[[('m_catalog',10,-4),('m_entry',79,-3),('m_field',9,-2),('m_value',9,-1)]]), #186
213
+ ('_struct',[[('m_index',6,-1)]]), #187
214
+ ('_struct',[[('m_shown',13,-1)]]), #188
215
+ ('_struct',[[('m_recipient',12,-2),('m_string',30,-1)]]), #189
216
+ ('_struct',[[('m_recipient',12,-2),('m_point',117,-1)]]), #190
217
+ ('_struct',[[('m_progress',86,-1)]]), #191
218
+ ('_struct',[[('m_status',24,-1)]]), #192
219
+ ('_struct',[[('m_scoreValueMineralsCurrent',86,0),('m_scoreValueVespeneCurrent',86,1),('m_scoreValueMineralsCollectionRate',86,2),('m_scoreValueVespeneCollectionRate',86,3),('m_scoreValueWorkersActiveCount',86,4),('m_scoreValueMineralsUsedInProgressArmy',86,5),('m_scoreValueMineralsUsedInProgressEconomy',86,6),('m_scoreValueMineralsUsedInProgressTechnology',86,7),('m_scoreValueVespeneUsedInProgressArmy',86,8),('m_scoreValueVespeneUsedInProgressEconomy',86,9),('m_scoreValueVespeneUsedInProgressTechnology',86,10),('m_scoreValueMineralsUsedCurrentArmy',86,11),('m_scoreValueMineralsUsedCurrentEconomy',86,12),('m_scoreValueMineralsUsedCurrentTechnology',86,13),('m_scoreValueVespeneUsedCurrentArmy',86,14),('m_scoreValueVespeneUsedCurrentEconomy',86,15),('m_scoreValueVespeneUsedCurrentTechnology',86,16),('m_scoreValueMineralsLostArmy',86,17),('m_scoreValueMineralsLostEconomy',86,18),('m_scoreValueMineralsLostTechnology',86,19),('m_scoreValueVespeneLostArmy',86,20),('m_scoreValueVespeneLostEconomy',86,21),('m_scoreValueVespeneLostTechnology',86,22),('m_scoreValueMineralsKilledArmy',86,23),('m_scoreValueMineralsKilledEconomy',86,24),('m_scoreValueMineralsKilledTechnology',86,25),('m_scoreValueVespeneKilledArmy',86,26),('m_scoreValueVespeneKilledEconomy',86,27),('m_scoreValueVespeneKilledTechnology',86,28),('m_scoreValueFoodUsed',86,29),('m_scoreValueFoodMade',86,30),('m_scoreValueMineralsUsedActiveForces',86,31),('m_scoreValueVespeneUsedActiveForces',86,32),('m_scoreValueMineralsFriendlyFireArmy',86,33),('m_scoreValueMineralsFriendlyFireEconomy',86,34),('m_scoreValueMineralsFriendlyFireTechnology',86,35),('m_scoreValueVespeneFriendlyFireArmy',86,36),('m_scoreValueVespeneFriendlyFireEconomy',86,37),('m_scoreValueVespeneFriendlyFireTechnology',86,38)]]), #193
220
+ ('_struct',[[('m_playerId',1,0),('m_stats',193,1)]]), #194
221
+ ('_struct',[[('m_unitTagIndex',6,0),('m_unitTagRecycle',6,1),('m_unitTypeName',29,2),('m_controlPlayerId',1,3),('m_upkeepPlayerId',1,4),('m_x',10,5),('m_y',10,6)]]), #195
222
+ ('_struct',[[('m_unitTagIndex',6,0),('m_unitTagRecycle',6,1),('m_killerPlayerId',59,2),('m_x',10,3),('m_y',10,4),('m_killerUnitTagIndex',43,5),('m_killerUnitTagRecycle',43,6)]]), #196
223
+ ('_struct',[[('m_unitTagIndex',6,0),('m_unitTagRecycle',6,1),('m_controlPlayerId',1,2),('m_upkeepPlayerId',1,3)]]), #197
224
+ ('_struct',[[('m_unitTagIndex',6,0),('m_unitTagRecycle',6,1),('m_unitTypeName',29,2)]]), #198
225
+ ('_struct',[[('m_playerId',1,0),('m_upgradeTypeName',29,1),('m_count',86,2)]]), #199
226
+ ('_struct',[[('m_unitTagIndex',6,0),('m_unitTagRecycle',6,1)]]), #200
227
+ ('_array',[(0,10),86]), #201
228
+ ('_struct',[[('m_firstUnitIndex',6,0),('m_items',201,1)]]), #202
229
+ ('_struct',[[('m_playerId',1,0),('m_type',6,1),('m_userId',43,2),('m_slotId',43,3)]]), #203
230
+ ]
231
+
232
+ # Map from protocol NNet.Game.*Event eventid to (typeid, name)
233
+ game_event_types = {
234
+ 5: (78, 'NNet.Game.SUserFinishedLoadingSyncEvent'),
235
+ 7: (77, 'NNet.Game.SUserOptionsEvent'),
236
+ 9: (70, 'NNet.Game.SBankFileEvent'),
237
+ 10: (72, 'NNet.Game.SBankSectionEvent'),
238
+ 11: (73, 'NNet.Game.SBankKeyEvent'),
239
+ 12: (74, 'NNet.Game.SBankValueEvent'),
240
+ 13: (76, 'NNet.Game.SBankSignatureEvent'),
241
+ 14: (81, 'NNet.Game.SCameraSaveEvent'),
242
+ 21: (82, 'NNet.Game.SSaveGameEvent'),
243
+ 22: (78, 'NNet.Game.SSaveGameDoneEvent'),
244
+ 23: (78, 'NNet.Game.SLoadGameDoneEvent'),
245
+ 25: (83, 'NNet.Game.SCommandManagerResetEvent'),
246
+ 26: (91, 'NNet.Game.SGameCheatEvent'),
247
+ 27: (97, 'NNet.Game.SCmdEvent'),
248
+ 28: (105, 'NNet.Game.SSelectionDeltaEvent'),
249
+ 29: (106, 'NNet.Game.SControlGroupUpdateEvent'),
250
+ 30: (108, 'NNet.Game.SSelectionSyncCheckEvent'),
251
+ 31: (110, 'NNet.Game.SResourceTradeEvent'),
252
+ 32: (111, 'NNet.Game.STriggerChatMessageEvent'),
253
+ 33: (114, 'NNet.Game.SAICommunicateEvent'),
254
+ 34: (115, 'NNet.Game.SSetAbsoluteGameSpeedEvent'),
255
+ 35: (116, 'NNet.Game.SAddAbsoluteGameSpeedEvent'),
256
+ 36: (118, 'NNet.Game.STriggerPingEvent'),
257
+ 37: (119, 'NNet.Game.SBroadcastCheatEvent'),
258
+ 38: (120, 'NNet.Game.SAllianceEvent'),
259
+ 39: (121, 'NNet.Game.SUnitClickEvent'),
260
+ 40: (122, 'NNet.Game.SUnitHighlightEvent'),
261
+ 41: (123, 'NNet.Game.STriggerReplySelectedEvent'),
262
+ 43: (128, 'NNet.Game.SHijackReplayGameEvent'),
263
+ 44: (78, 'NNet.Game.STriggerSkippedEvent'),
264
+ 45: (133, 'NNet.Game.STriggerSoundLengthQueryEvent'),
265
+ 46: (140, 'NNet.Game.STriggerSoundOffsetEvent'),
266
+ 47: (141, 'NNet.Game.STriggerTransmissionOffsetEvent'),
267
+ 48: (142, 'NNet.Game.STriggerTransmissionCompleteEvent'),
268
+ 49: (146, 'NNet.Game.SCameraUpdateEvent'),
269
+ 50: (78, 'NNet.Game.STriggerAbortMissionEvent'),
270
+ 51: (129, 'NNet.Game.STriggerPurchaseMadeEvent'),
271
+ 52: (78, 'NNet.Game.STriggerPurchaseExitEvent'),
272
+ 53: (130, 'NNet.Game.STriggerPlanetMissionLaunchedEvent'),
273
+ 54: (78, 'NNet.Game.STriggerPlanetPanelCanceledEvent'),
274
+ 55: (132, 'NNet.Game.STriggerDialogControlEvent'),
275
+ 56: (136, 'NNet.Game.STriggerSoundLengthSyncEvent'),
276
+ 57: (147, 'NNet.Game.STriggerConversationSkippedEvent'),
277
+ 58: (150, 'NNet.Game.STriggerMouseClickedEvent'),
278
+ 59: (151, 'NNet.Game.STriggerMouseMovedEvent'),
279
+ 60: (152, 'NNet.Game.SAchievementAwardedEvent'),
280
+ 61: (153, 'NNet.Game.STriggerHotkeyPressedEvent'),
281
+ 62: (154, 'NNet.Game.STriggerTargetModeUpdateEvent'),
282
+ 63: (78, 'NNet.Game.STriggerPlanetPanelReplayEvent'),
283
+ 64: (155, 'NNet.Game.STriggerSoundtrackDoneEvent'),
284
+ 65: (156, 'NNet.Game.STriggerPlanetMissionSelectedEvent'),
285
+ 66: (157, 'NNet.Game.STriggerKeyPressedEvent'),
286
+ 67: (169, 'NNet.Game.STriggerMovieFunctionEvent'),
287
+ 68: (78, 'NNet.Game.STriggerPlanetPanelBirthCompleteEvent'),
288
+ 69: (78, 'NNet.Game.STriggerPlanetPanelDeathCompleteEvent'),
289
+ 70: (158, 'NNet.Game.SResourceRequestEvent'),
290
+ 71: (159, 'NNet.Game.SResourceRequestFulfillEvent'),
291
+ 72: (160, 'NNet.Game.SResourceRequestCancelEvent'),
292
+ 73: (78, 'NNet.Game.STriggerResearchPanelExitEvent'),
293
+ 74: (78, 'NNet.Game.STriggerResearchPanelPurchaseEvent'),
294
+ 75: (162, 'NNet.Game.STriggerResearchPanelSelectionChangedEvent'),
295
+ 76: (161, 'NNet.Game.STriggerCommandErrorEvent'),
296
+ 77: (78, 'NNet.Game.STriggerMercenaryPanelExitEvent'),
297
+ 78: (78, 'NNet.Game.STriggerMercenaryPanelPurchaseEvent'),
298
+ 79: (163, 'NNet.Game.STriggerMercenaryPanelSelectionChangedEvent'),
299
+ 80: (78, 'NNet.Game.STriggerVictoryPanelExitEvent'),
300
+ 81: (78, 'NNet.Game.STriggerBattleReportPanelExitEvent'),
301
+ 82: (164, 'NNet.Game.STriggerBattleReportPanelPlayMissionEvent'),
302
+ 83: (165, 'NNet.Game.STriggerBattleReportPanelPlaySceneEvent'),
303
+ 84: (165, 'NNet.Game.STriggerBattleReportPanelSelectionChangedEvent'),
304
+ 85: (130, 'NNet.Game.STriggerVictoryPanelPlayMissionAgainEvent'),
305
+ 86: (78, 'NNet.Game.STriggerMovieStartedEvent'),
306
+ 87: (78, 'NNet.Game.STriggerMovieFinishedEvent'),
307
+ 88: (167, 'NNet.Game.SDecrementGameTimeRemainingEvent'),
308
+ 89: (168, 'NNet.Game.STriggerPortraitLoadedEvent'),
309
+ 90: (170, 'NNet.Game.STriggerCustomDialogDismissedEvent'),
310
+ 91: (171, 'NNet.Game.STriggerGameMenuItemSelectedEvent'),
311
+ 92: (173, 'NNet.Game.STriggerMouseWheelEvent'),
312
+ 93: (129, 'NNet.Game.STriggerPurchasePanelSelectedPurchaseItemChangedEvent'),
313
+ 94: (174, 'NNet.Game.STriggerPurchasePanelSelectedPurchaseCategoryChangedEvent'),
314
+ 95: (175, 'NNet.Game.STriggerButtonPressedEvent'),
315
+ 96: (78, 'NNet.Game.STriggerGameCreditsFinishedEvent'),
316
+ 97: (176, 'NNet.Game.STriggerCutsceneBookmarkFiredEvent'),
317
+ 98: (177, 'NNet.Game.STriggerCutsceneEndSceneFiredEvent'),
318
+ 99: (178, 'NNet.Game.STriggerCutsceneConversationLineEvent'),
319
+ 100: (179, 'NNet.Game.STriggerCutsceneConversationLineMissingEvent'),
320
+ 101: (180, 'NNet.Game.SGameUserLeaveEvent'),
321
+ 102: (181, 'NNet.Game.SGameUserJoinEvent'),
322
+ 103: (183, 'NNet.Game.SCommandManagerStateEvent'),
323
+ 104: (184, 'NNet.Game.SCmdUpdateTargetPointEvent'),
324
+ 105: (185, 'NNet.Game.SCmdUpdateTargetUnitEvent'),
325
+ 106: (137, 'NNet.Game.STriggerAnimLengthQueryByNameEvent'),
326
+ 107: (138, 'NNet.Game.STriggerAnimLengthQueryByPropsEvent'),
327
+ 108: (139, 'NNet.Game.STriggerAnimOffsetEvent'),
328
+ 109: (186, 'NNet.Game.SCatalogModifyEvent'),
329
+ 110: (187, 'NNet.Game.SHeroTalentTreeSelectedEvent'),
330
+ 111: (78, 'NNet.Game.STriggerProfilerLoggingFinishedEvent'),
331
+ 112: (188, 'NNet.Game.SHeroTalentTreeSelectionPanelToggledEvent'),
332
+ }
333
+
334
+ # The typeid of the NNet.Game.EEventId enum.
335
+ game_eventid_typeid = 0
336
+
337
+ # Map from protocol NNet.Game.*Message eventid to (typeid, name)
338
+ message_event_types = {
339
+ 0: (189, 'NNet.Game.SChatMessage'),
340
+ 1: (190, 'NNet.Game.SPingMessage'),
341
+ 2: (191, 'NNet.Game.SLoadingProgressMessage'),
342
+ 3: (78, 'NNet.Game.SServerPingMessage'),
343
+ 4: (192, 'NNet.Game.SReconnectNotifyMessage'),
344
+ }
345
+
346
+ # The typeid of the NNet.Game.EMessageId enum.
347
+ message_eventid_typeid = 1
348
+
349
+ # Map from protocol NNet.Replay.Tracker.*Event eventid to (typeid, name)
350
+ tracker_event_types = {
351
+ 0: (194, 'NNet.Replay.Tracker.SPlayerStatsEvent'),
352
+ 1: (195, 'NNet.Replay.Tracker.SUnitBornEvent'),
353
+ 2: (196, 'NNet.Replay.Tracker.SUnitDiedEvent'),
354
+ 3: (197, 'NNet.Replay.Tracker.SUnitOwnerChangeEvent'),
355
+ 4: (198, 'NNet.Replay.Tracker.SUnitTypeChangeEvent'),
356
+ 5: (199, 'NNet.Replay.Tracker.SUpgradeEvent'),
357
+ 6: (195, 'NNet.Replay.Tracker.SUnitInitEvent'),
358
+ 7: (200, 'NNet.Replay.Tracker.SUnitDoneEvent'),
359
+ 8: (202, 'NNet.Replay.Tracker.SUnitPositionsEvent'),
360
+ 9: (203, 'NNet.Replay.Tracker.SPlayerSetupEvent'),
361
+ }
362
+
363
+ # The typeid of the NNet.Replay.Tracker.EEventId enum.
364
+ tracker_eventid_typeid = 2
365
+
366
+ # The typeid of NNet.SVarUint32 (the type used to encode gameloop deltas).
367
+ svaruint32_typeid = 7
368
+
369
+ # The typeid of NNet.Replay.SGameUserId (the type used to encode player ids).
370
+ replay_userid_typeid = 8
371
+
372
+ # The typeid of NNet.Replay.SHeader (the type used to store replay game version and length).
373
+ replay_header_typeid = 18
374
+
375
+ # The typeid of NNet.Game.SDetails (the type used to store overall replay details).
376
+ game_details_typeid = 40
377
+
378
+ # The typeid of NNet.Replay.SInitData (the type used to store the inital lobby).
379
+ replay_initdata_typeid = 69
380
+
381
+
382
+ def _varuint32_value(value):
383
+ # Returns the numeric value from a SVarUint32 instance.
384
+ for k,v in value.iteritems():
385
+ return v
386
+ return 0
387
+
388
+
389
+ def _decode_event_stream(decoder, eventid_typeid, event_types, decode_user_id):
390
+ # Decodes events prefixed with a gameloop and possibly userid
391
+ gameloop = 0
392
+ while not decoder.done():
393
+ start_bits = decoder.used_bits()
394
+
395
+ # decode the gameloop delta before each event
396
+ delta = _varuint32_value(decoder.instance(svaruint32_typeid))
397
+ gameloop += delta
398
+
399
+ # decode the userid before each event
400
+ if decode_user_id:
401
+ userid = decoder.instance(replay_userid_typeid)
402
+
403
+ # decode the event id
404
+ eventid = decoder.instance(eventid_typeid)
405
+ typeid, typename = event_types.get(eventid, (None, None))
406
+ if typeid is None:
407
+ raise CorruptedError('eventid(%d) at %s' % (eventid, decoder))
408
+
409
+ # decode the event struct instance
410
+ event = decoder.instance(typeid)
411
+ event['_event'] = typename
412
+ event['_eventid'] = eventid
413
+
414
+ # insert gameloop and userid
415
+ event['_gameloop'] = gameloop
416
+ if decode_user_id:
417
+ event['_userid'] = userid
418
+
419
+ # the next event is byte aligned
420
+ decoder.byte_align()
421
+
422
+ # insert bits used in stream
423
+ event['_bits'] = decoder.used_bits() - start_bits
424
+
425
+ yield event
426
+
427
+
428
+ def decode_replay_game_events(contents):
429
+ """Decodes and yields each game event from the contents byte string."""
430
+ decoder = BitPackedDecoder(contents, typeinfos)
431
+ for event in _decode_event_stream(decoder,
432
+ game_eventid_typeid,
433
+ game_event_types,
434
+ decode_user_id=True):
435
+ yield event
436
+
437
+
438
+ def decode_replay_message_events(contents):
439
+ """Decodes and yields each message event from the contents byte string."""
440
+ decoder = BitPackedDecoder(contents, typeinfos)
441
+ for event in _decode_event_stream(decoder,
442
+ message_eventid_typeid,
443
+ message_event_types,
444
+ decode_user_id=True):
445
+ yield event
446
+
447
+
448
+ def decode_replay_tracker_events(contents):
449
+ """Decodes and yields each tracker event from the contents byte string."""
450
+ decoder = VersionedDecoder(contents, typeinfos)
451
+ for event in _decode_event_stream(decoder,
452
+ tracker_eventid_typeid,
453
+ tracker_event_types,
454
+ decode_user_id=False):
455
+ yield event
456
+
457
+
458
+ def decode_replay_header(contents):
459
+ """Decodes and return the replay header from the contents byte string."""
460
+ decoder = VersionedDecoder(contents, typeinfos)
461
+ return decoder.instance(replay_header_typeid)
462
+
463
+
464
+ def decode_replay_details(contents):
465
+ """Decodes and returns the game details from the contents byte string."""
466
+ decoder = VersionedDecoder(contents, typeinfos)
467
+ return decoder.instance(game_details_typeid)
468
+
469
+
470
+ def decode_replay_initdata(contents):
471
+ """Decodes and return the replay init data from the contents byte string."""
472
+ decoder = BitPackedDecoder(contents, typeinfos)
473
+ return decoder.instance(replay_initdata_typeid)
474
+
475
+
476
+ def decode_replay_attributes_events(contents):
477
+ """Decodes and yields each attribute from the contents byte string."""
478
+ buffer = BitPackedBuffer(contents, 'little')
479
+ attributes = {}
480
+ if not buffer.done():
481
+ attributes['source'] = buffer.read_bits(8)
482
+ attributes['mapNamespace'] = buffer.read_bits(32)
483
+ count = buffer.read_bits(32)
484
+ attributes['scopes'] = {}
485
+ while not buffer.done():
486
+ value = {}
487
+ value['namespace'] = buffer.read_bits(32)
488
+ value['attrid'] = attrid = buffer.read_bits(32)
489
+ scope = buffer.read_bits(8)
490
+ value['value'] = buffer.read_aligned_bytes(4)[::-1].strip('\x00')
491
+ if not scope in attributes['scopes']:
492
+ attributes['scopes'][scope] = {}
493
+ if not attrid in attributes['scopes'][scope]:
494
+ attributes['scopes'][scope][attrid] = []
495
+ attributes['scopes'][scope][attrid].append(value)
496
+ return attributes
497
+
498
+
499
+ def unit_tag(unitTagIndex, unitTagRecycle):
500
+ return (unitTagIndex << 18) + unitTagRecycle
501
+
502
+
503
+ def unit_tag_index(unitTag):
504
+ return (unitTag >> 18) & 0x00003fff
505
+
506
+
507
+ def unit_tag_recycle(unitTag):
508
+ return (unitTag) & 0x0003ffff