mgz-fast
A stripped-down version of aoc-mgz, tailored specifically for the needs of AoE2Insights. It contains only the bare essentials required for fast header and body parsing -- everything else has been removed.
Supported Formats
- Userpatch 1.5 (
.mgz) - HD Edition 5.8 (
.aoe2record) - Definitive Edition (
.aoe2record)
Installation
pip install mgz-fast
Usage
Parsing the Header
Extract game metadata like players, map, version, and settings from a recorded game file.
from mgz.fast.header import parse
with open("match.aoe2record", "rb") as f:
header = parse(f)
print(header["version"]) # Version.DE
print(header["game_version"]) # e.g. "7.7"
print(header["save_version"]) # e.g. 13.34
Players
from mgz.fast.header import parse
with open("match.aoe2record", "rb") as f:
header = parse(f)
for player in header["players"]:
print(player["name"])
print(player["civilization_id"])
print(player["color_id"])
print(player["position"]) # {"x": ..., "y": ...}
For Definitive Edition recordings, additional player data is available:
for de_player in header["de"]["players"]:
print(de_player["name"])
print(de_player["censored_name"])
print(de_player["team_id"])
Map and Game Settings
from mgz.fast.header import parse
with open("match.aoe2record", "rb") as f:
header = parse(f)
print(header["scenario"]["map_id"])
print(header["lobby"]["seed"])
print(header["lobby"]["population"])
print(header["lobby"]["game_type_id"])
print(header["metadata"]["speed"])
Parsing the Body (Actions)
Iterate over in-game operations like player actions, chat messages, and sync ticks.
import os
from mgz.fast import operation, meta
from mgz.fast.header import parse
from mgz.fast.enums import Operation, Action
with open("match.aoe2record", "rb") as f:
eof = os.fstat(f.fileno()).st_size
header = parse(f)
meta(f)
while f.tell() < eof:
try:
op_type, payload = operation(f)
except EOFError:
break
if op_type == Operation.ACTION:
action_type, action_data = payload
if action_type == Action.RESIGN:
print(f"Player {action_data['player_id']} resigned")
elif action_type == Action.RESEARCH:
print(f"Player {action_data['player_id']} researched {action_data['technology_id']}")
elif action_type == Action.BUILD:
print(f"Player {action_data['player_id']} built {action_data['building_id']}")
elif op_type == Operation.CHAT:
print(f"Chat: {payload}")
Extracting Chat Messages
import os
from mgz.fast import operation, meta
from mgz.fast.header import parse
from mgz.fast.enums import Operation
with open("match.aoe2record", "rb") as f:
eof = os.fstat(f.fileno()).st_size
header = parse(f)
meta(f)
while f.tell() < eof:
try:
op_type, payload = operation(f)
except EOFError:
break
if op_type == Operation.CHAT:
print(payload.decode("utf-8", errors="replace"))
Calculating Game Duration
import os
from mgz.fast import operation, meta
from mgz.fast.header import parse
from mgz.fast.enums import Operation
with open("match.aoe2record", "rb") as f:
eof = os.fstat(f.fileno()).st_size
header = parse(f)
meta(f)
elapsed_ms = 0
while f.tell() < eof:
try:
op_type, payload = operation(f)
except EOFError:
break
if op_type == Operation.SYNC:
increment, checksum, data = payload
elapsed_ms += increment
minutes = elapsed_ms / 1000 / 60
print(f"Game duration: {minutes:.1f} minutes")
CLI Tools
Installing mgz-fast also provides four command-line utilities for working with recorded game files.
mgz-parse-header
Parse the header of a recorded game and output it as JSON.
# Parse header and write JSON to file
mgz-parse-header match.aoe2record -o header.json
# Parse with debug logging (useful for troubleshooting)
mgz-parse-header match.aoe2record --debug
# Also works with ZIP archives
mgz-parse-header match.zip -o header.json
mgz-parse-body
Parse the body (actions/events) of a recorded game. Expects an extracted body file as input (see mgz-extract) and outputs JSON Lines to stdout.
# Parse body and print operations as JSON Lines
mgz-parse-body match.body.bin
# Pretty-print each operation
mgz-parse-body match.body.bin --indent 2
mgz-extract
Extract the header and body from a recorded game into separate binary files. The header is automatically decompressed.
# Extract to default paths (<name>.header.bin, <name>.body.bin)
mgz-extract match.aoe2record
# Specify custom output paths
mgz-extract match.aoe2record --header h.bin --body b.bin
mgz-dump
Hex-dump arbitrary byte ranges from a recorded game's header or body. Useful for reverse engineering and debugging.
# Dump first 256 bytes of the decompressed header
mgz-dump match.aoe2record header
# Dump 128 bytes starting at offset 0x2e0
mgz-dump match.aoe2record header --offset 0x2e0 --length 128
# Dump the beginning of the body
mgz-dump match.aoe2record body --offset 0 --length 64
Header Fields Reference
The dictionary returned by parse() contains:
| Key | Type | Description |
|---|---|---|
version |
Version |
Game version (USERPATCH15, DE, HD) |
game_version |
str |
Version string |
save_version |
float |
Save file version |
players |
list[dict] |
Player info (name, civ, color, position, diplomacy) |
map |
dict |
Map dimensions and tile data |
scenario |
dict |
Map ID, difficulty, scenario filename |
lobby |
dict |
Seed, population, game type, chat, lock teams |
metadata |
dict |
Game speed, perspective owner, cheats |
de |
dict|None |
DE-specific data (extended player info, settings) |
hd |
dict|None |
HD-specific data |
License
MIT
Metadata
Release files for mgz-fast 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| mgz_fast-1.0.0.tar.gz | 20.4 MB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mgz_fast-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 20.4 MB
Release files / mgz_fast-1.0.0.tar.gz
| Download URL | mgz_fast-1.0.0.tar.gz |
|---|---|
| Size | 20.4 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9d111dfe66a2306c161901546693be97b33d72334a6daa76f42d7a16c047b435
|
|
BLAKE2b-256 checksum How to use checksums |
0036f338800447e64614b2abac883091098d9f2ac7fdcad7b47227e9d6ca4db6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.10.6 {"installer":{"name":"uv","version":"0.10.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / mgz_fast-1.0.0-py3-none-any.whl
| Download URL | mgz_fast-1.0.0-py3-none-any.whl |
|---|---|
| Size | 30.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
79489857034cce6ff4acd68fdb247241fa5ff5408cccdeb307996b609568257e
|
|
BLAKE2b-256 checksum How to use checksums |
4afe5fb1da9950cd9c58f63a19e4e19c9893c25064570e5dbe41527a2ac6b979
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.10.6 {"installer":{"name":"uv","version":"0.10.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for mgz-fast 1.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.