happyleavesaoc / aoc-mgz

Age of Empires II recorded game parsing and summarization in Python 3.
MIT License
197 stars 41 forks source link

Exception: Unpack Requires a Buffer of 24 Bytes #74

Closed juliastic closed 2 years ago

juliastic commented 2 years ago

Hello, when trying to analyse a recent replay of AoE II DE (from early March) with the following simple code snippet:

from mgz.model import parse_match
with open('path/replay.aoe2record', 'rb') as data:
    match = parse_match(data)
    match.map.name
    match.file.perspective.number

I came across this exception (with stack trace for your convenience):

unpack requires a buffer of 24 bytes
Traceback (most recent call last):
  File "/path/aoc-mgz/mgz/fast/header.py", line 469, in parse
    players, mod = parse_players(header, num_players, version)
  File "/path/aoc-mgz/mgz/fast/header.py", line 434, in parse_players
    players = [parse_player(header, number, num_players) for number in range(num_players)]
  File "/path/aoc-mgz/mgz/fast/header.py", line 434, in <listcomp>
    players = [parse_player(header, number, num_players) for number in range(num_players)]
  File "/path/aoc-mgz/mgz/fast/header.py", line 120, in parse_player
    start_x, start_y, civilization_id, color_id = unpack('<xff9xb3xbx', header)
  File "/path/aoc-mgz/mgz/fast/header.py", line 34, in unpack
    output = struct.unpack(fmt, data.read(struct.calcsize(fmt)))
struct.error: unpack requires a buffer of 24 bytes

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "aoe2test.py", line 7, in <module>
    match = parse_match(data)
  File "/path/aoc-mgz/mgz/model/__init__.py", line 93, in parse_match
    data = parse(handle)
  File "/path/aoc-mgz/mgz/fast/header.py", line 475, in parse
    raise RuntimeError("could not parse")
RuntimeError: could not parse

I am guessing a recent format change has caused this. Attached you can also find an example record file.

replay.aoe2record.zip

happyleavesaoc commented 2 years ago

You're right -- the most recent patch broke the fast parser. I recommend using the full parser (which does support the latest patch) until the fast parser is fixed.

juliastic commented 2 years ago

When trying to print match data with a full summary with open('replay.aoe2record', 'rb') as data: s = FullSummary(data, True) print(s.get_players()[0]) I get "NONE" for player achievements when fetching player data. {'name': '_WWP_Yo', 'civilization': 24, 'human': True, 'number': 1, 'color_id': 2, 'winner': False, 'mvp': None, 'score': None, 'position': (0.0, 0.0), 'rate_snapshot': None, 'user_id': 197964, 'cheater': False, 'prefer_random': False, 'achievements': {'military': {'score': None, 'units_killed': None, 'hit_points_killed': None, 'units_lost': None, 'buildings_razed': None, 'hit_points_razed': None, 'buildings_lost': None, 'units_converted': None}, 'economy': {'score': None, 'food_collected': None, 'wood_collected': None, 'stone_collected': None, 'gold_collected': None, 'tribute_sent': None, 'tribute_received': None, 'trade_gold': None, 'relic_gold': None}, 'technology': {'score': None, 'feudal_time': None, 'castle_time': None, 'imperial_time': None, 'explored_percent': None, 'research_count': None, 'research_percent': None}, 'society': {'score': None, 'total_wonders': None, 'total_castles': None, 'total_relics': None, 'villager_high': None}}} Am I doing something wrong or is this related to the recent patch as well?

happyleavesaoc commented 2 years ago

That is expected behavior. DE does not support achievements in the recorded game.