Python bindings for faf-replay-parser
Project description
FAF Replay Parser
A fast library for parsing Supreme Commander Forged Alliance replay files.
Installation
Pre-built packages are available for Linux, MacOS, and Windows. You can install them with:
pip install faf-replay-parser
Documentation
Here are some examples of using the parser. Check help(fafreplay)
for more
details on available functions.
Gathering basic info
For the most basic uses there are a few special functions that should be
preferred over constructing a Parser
object. These do only one job, but they
do it very quickly.
Current functions:
body_offset
- Used for splitting replay data into header and body.body_ticks
- Used for extracting the game length.
Example
from datetime import timedelta
from fafreplay import body_offset, body_ticks
# Split replay data into header and body
offset = body_offset(data)
header_data, body_data = data[:offset], data[offset:]
# Get replay length in ticks
ticks = body_ticks(body_data)
print("Game length:", timedelta(milliseconds=ticks*100))
Using the Parser object
The Parser
object can be used to get fine grained control over how replay
commands are parsed. Generally it's a good idea to parse only the minimum
commands needed, as conversion back to python dictionaries is quite expensive.
from datetime import timedelta
from fafreplay import Parser, commands
parser = Parser(
# Skip all commands except the ones defined here
commands=[
commands.Advance, # For the tick counter
commands.VerifyChecksum, # For desync detection
],
# Throw away commands right after we parse them. Setting this to `True` will
# significantly increase the parse time.
save_commands=False,
limit=None,
stop_on_desync=False
)
# Or create a parser with default arguments (turn off save_commands though)
# parser = Parser(save_commands=False)
# Read replay to a `bytes` object
with open("12345.scfareplay", "rb") as f:
data = f.read()
# Parse to a python dictionary. Data must of type `bytes` or `bytearray`
replay = parser.parse(data)
print("Game time:", timedelta(milliseconds=replay["body"]["sim"]["tick"]*100))
if replay["body"]["sim"]["desync_ticks"]:
print("Replay desynced!")
Benchmark comparison
To see how much faster the basic functions can be, consider this simple example
done on replay 8653680
(an almost 50 minute long Seton's game).
>>> len(body_data)
5586339
>>> body_ticks(body_data)
28917
>>> parser = Parser(
... commands=[commands.Advance],
... save_commands=False
... )
>>> timeit.timeit("parser.parse_body(body_data)['sim']['tick']", globals=globals(), number=100)
1.4510237049980788
>>> timeit.timeit("body_ticks(body_data)", globals=globals(), number=100)
0.20173147800232982
In this case body_ticks
turned out to be more than 7x faster than using a
Parser
.
Reading .fafreplay files
Replays downloaded from faforever.com use a compressed
data format to reduce the size of the files. These can be decompressed to the
original .scfareplay
data using the extract_scfa
function.
from fafreplay import extract_scfa
with open("12345.scfareplay", "rb") as f:
scfa_data = f.read()
with open("12345.fafreplay", "rb") as f:
faf_data = extract_scfa(f)
# The extracted data is in the .scfareplay format
assert faf_data == scfa_data
Note that there are several versions of the .fafreplay
format. Version 1 uses
base64 and zlib compression which are both part of the python standard library.
However, version 2 uses zstd
which must be installed through a third party
package. To ensure that this dependency is installed you can use the faf
extra
when installing the parser:
pip install "faf-replay-parser[faf]"
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Hashes for faf_replay_parser-0.5.3-pp39-pypy39_pp73-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | dc2fc4fb5faf0bf243a65150a8d015518fe7f3458ad021e732811df4c77cbb29 |
|
MD5 | 0c3892f5c9e84654d1fa152269a6ad0c |
|
BLAKE2b-256 | b96bcdb441c508016db6eb1f0b027620394a2646168f7546b978e29ecd3783fc |
Hashes for faf_replay_parser-0.5.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5ab18f9960d8e9378a264ae4fb90b62c35cb8cbca5274a18e4272c03fb33a7c3 |
|
MD5 | c6e725acfeae3e45fbc6ee4d8ced84a9 |
|
BLAKE2b-256 | 3b585eb25822c9c0145000c6f7302a75bfb500b1785ac3fb33cfa655726b0c95 |
Hashes for faf_replay_parser-0.5.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 216a2006c15d9d179874ca6245c3016757f2c2a7f16aa5001319dadde3010432 |
|
MD5 | c8b0256e5a99f7aa6bbdaa60436ad2d5 |
|
BLAKE2b-256 | 1c403dd8691eaaea4424a928f79dd37edbd128b7205f1be1f83e89e8be99c457 |
Hashes for faf_replay_parser-0.5.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 767d813153dcc2f05b2d16ebadce95834076e111ea092e560c8b9efe75df18ab |
|
MD5 | 99618055e6ccc1d210e5305a39e5901d |
|
BLAKE2b-256 | 9dad75055703a3ad81de31c833abd5edb6d119b474d683f9967b19c06333bfb5 |
Hashes for faf_replay_parser-0.5.3-pp38-pypy38_pp73-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 02a4f6bbcb3fd5d01a8e39a9fa104773446c3dfe0f1c91fbbe8d811e25daaedb |
|
MD5 | 4cf2ab56f234b5de8a88de2482127669 |
|
BLAKE2b-256 | 42645af3bd2d1f9419a2d772e0539bc95b6def6fefb1e2b1ec8abf5fc970ea4d |
Hashes for faf_replay_parser-0.5.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 256aa388489b5074f1da1a28e4f8170ae60440f6d7dc605161dc8b6d6b59c0f9 |
|
MD5 | d518d4fac3266b94a7dc385edcc51260 |
|
BLAKE2b-256 | 52ac0db600f30af3c8d9b127cf71dc357605d09ef00d1d972d3e5be62ff54a50 |
Hashes for faf_replay_parser-0.5.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | c984629ca3a516e3a014832477eb78b2372b0973065dfeb2443de0be6db0eb7a |
|
MD5 | 068539b5671bd53f179e1b9da5d1422f |
|
BLAKE2b-256 | 6b0e62f0a2f83f5c759551a7d177e8eac7a57bb524d9b7a977a80e8b62db9d69 |
Hashes for faf_replay_parser-0.5.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 882dcbb9046eb33505543d472d419a687a51be39766ab7a3eba075e3f14ac81b |
|
MD5 | 27c420f377379126ade50b97968cc500 |
|
BLAKE2b-256 | 49b40e318ab033d734dc71800b3e65554bde85ea77346d8752b05eabf93a7efa |
Hashes for faf_replay_parser-0.5.3-pp37-pypy37_pp73-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | bf67d1df3c001cf08031e86f32e729714ee2371d5eaf83ba1d175433d3067428 |
|
MD5 | 09fe2db3d3221b994e573a4a5f93ea95 |
|
BLAKE2b-256 | 19a75142d0b05274f86c1785db003d630ca2399cef0be7fc4a5964676f135c06 |
Hashes for faf_replay_parser-0.5.3-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 19542447343dbc523fc655e6456e1f45a43e3df1c0536d3d30725e8a3c5e98ba |
|
MD5 | 119c7fcc66140ddd940a50fb49a63ed6 |
|
BLAKE2b-256 | aefca4c675e08f758c12cdba16f8d577174cc5a1aed751469296dc71ec7cc895 |
Hashes for faf_replay_parser-0.5.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | e36fb2e1387e94af6d03dafc65bcf0e863362c6af8d9b46ea654fd0079e8df9f |
|
MD5 | e38f9df34da19046058bc1f464f8eda1 |
|
BLAKE2b-256 | f88fa59edbd0bec6d7c2e20a0e8568a40ac29df0929796ea435edc2c670ead14 |
Hashes for faf_replay_parser-0.5.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | a38e7ff4e9385e75d034ca25f9234614a54063a6b091fcfe83737bfe0e98d989 |
|
MD5 | ce3376270788090be41d65cf2bac575b |
|
BLAKE2b-256 | b29edb257ddd40f80237aad25e6f2e0dcf30f061ccfad15c02daff539ce7397f |
Hashes for faf_replay_parser-0.5.3-cp310-cp310-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 94b1629ff3af9934d95e330ac24a5076880b83e1d616ff77a3a82f8602c9ff2b |
|
MD5 | 5f5e8ffef7bd89d6d3bccfff59152526 |
|
BLAKE2b-256 | 69fef58c5adeedabcff17b25dcaf15dd3d7b96a52e29350cd8585fa1cf4f1284 |
Hashes for faf_replay_parser-0.5.3-cp310-cp310-win32.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 28ff2b8b090e1a242889858407a7dda7b73015e6225f69c9f14d76ec11bde2ab |
|
MD5 | 6b4f234346e71b1751fe29f2aba6fce7 |
|
BLAKE2b-256 | 953c4016095c614be56c2b7154a0336b0829481c4d6e9bd4a4159650ba22b01b |
Hashes for faf_replay_parser-0.5.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 7ec6040e4681985e3c6d791c5947ac665117b085654b5bd15a4d7b798166a839 |
|
MD5 | 39f36404dceff1f795b6c22cbae771c7 |
|
BLAKE2b-256 | 5e9d223d5389e69bdeea5cb57970673dfc11c2c63095682b8843fb90df2a6a1f |
Hashes for faf_replay_parser-0.5.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | dcb381c0d62d6d53aa4b97b64c37a1940376c265572314db55e090c8bfd1eade |
|
MD5 | 397ac188c2d3079f8e045bf30b6939a8 |
|
BLAKE2b-256 | 0385b63839d4d2cdb078a7326462e07bf87fb5e5a46549e309f8876e9558edf3 |
Hashes for faf_replay_parser-0.5.3-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 25b56b2a913042851fbc3b3bcfe7a0f9db6d2e12fd1333640d3a72ad5106c1a0 |
|
MD5 | 4672bff4e4a1b465dfaf1a19cec20c43 |
|
BLAKE2b-256 | d2814c6a8df13a9ba5402fa24bb5692d596ddc89de854e1f6ec2e31df81a31ee |
Hashes for faf_replay_parser-0.5.3-cp39-cp39-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | a3eeac1c01b01906fe2eccd7a5a31bc6a2e5f845f31405036b0c75f6c83f0f2f |
|
MD5 | 991ee6facdb7fe0883ab9e2a8f5d0475 |
|
BLAKE2b-256 | a4a88ef3ff8f57fe41eea423d7781f25238f719c847a6386912e524b02f07c04 |
Hashes for faf_replay_parser-0.5.3-cp39-cp39-win32.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 3fa03d16723361b6300cf8d3ad6f438fa3a819c96f3d03ced450658ff85f52e0 |
|
MD5 | 069fe2e2bfe2c3272f777780af71be3f |
|
BLAKE2b-256 | 3d279158ceeede95d05700a9a57cea9755b32a3572e6bf68cc4a5eafc68793c0 |
Hashes for faf_replay_parser-0.5.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | f47c10028045432f35c13a10254355924479bbca88270c9f2a6d333755bf6e51 |
|
MD5 | 02c83ac7fefb39fbaf7e0ca321f9cb6d |
|
BLAKE2b-256 | 2f162443faaa03ba684049cbe264cfb4b1f03f6ec1b0c22416414c5635b4d834 |
Hashes for faf_replay_parser-0.5.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1cbff2778dbdf52072afa6c741e2fa47aa50fb160fc5eabe1cc9f388284e8a4c |
|
MD5 | 0af6256fc01cef50530a54eaa81f96e5 |
|
BLAKE2b-256 | a60c14289cca83061352bf19fe260b25aafe5ab8f619253f01dd61c17a1edc5e |
Hashes for faf_replay_parser-0.5.3-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 940e3d16fecc07c6f7496cd0999f1ae616281e41e89db17c63bef707905df3ab |
|
MD5 | 607c9f0e82d3a6a0c0511857f1046e37 |
|
BLAKE2b-256 | 7643d632aa057278f3452a32a6873e0f46ed051b11c66084f30e4f09d196ab5b |
Hashes for faf_replay_parser-0.5.3-cp38-cp38-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 766997f1b1e7d07a69884548f1109c638203e8278a3bb25a853338688ec88caa |
|
MD5 | 5e9c3a744da96e485fca22d7f015f69a |
|
BLAKE2b-256 | 854987f07a10722d449f570e67337795e55ebf88847d4bc908e89faa900e4a07 |
Hashes for faf_replay_parser-0.5.3-cp38-cp38-win32.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 3f151c9b655e49fc13f65255fb38f772c098e416c27e0fdc48f895e4d5639f08 |
|
MD5 | 1b54f239824573e446972a3fff62a949 |
|
BLAKE2b-256 | 1b612c55cf198e4d82d1786c239adbceb6609d301463c6038ce9a684afc43c91 |
Hashes for faf_replay_parser-0.5.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 6aecb9584b477563144d4fbdfd8561eb627c693d2b9163a656991265d50ad50a |
|
MD5 | c0523389527683bb052042ad81397864 |
|
BLAKE2b-256 | 350e2ee6a5d5de313b63cf6e879fc66c1f38f45d395b691f0774197390333aea |
Hashes for faf_replay_parser-0.5.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | d8d7ee1a4fe3bda853e2124f2cad58d675d48d8a464e27604783d67ebbba7bc4 |
|
MD5 | f564c278c20b9deabac91998785e3dc2 |
|
BLAKE2b-256 | 82976a81cce6f262291f8873a915918710e51d96603bb8489d71652bb6ccbc0c |
Hashes for faf_replay_parser-0.5.3-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2387c619f2948a628f5c7cee73010aa00e71a1edafc6cdd1ddebc1149aace502 |
|
MD5 | c6c409ab5887dfdbc243e2840631d113 |
|
BLAKE2b-256 | bd2023cc84ada11a8f9ffd352a3e4313550791c13949610c30f3e4e63031639a |
Hashes for faf_replay_parser-0.5.3-cp37-cp37m-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 0b210abd43793b7a60fe411c47f3d4dc9532caba46a5462107bc97338b97768b |
|
MD5 | 8acfbed0d6a8ba68477c42d52ca8b93d |
|
BLAKE2b-256 | efee52d778041b5121a327088e00b7de0a1c716968de0cc3022ca5f9dade4aa5 |
Hashes for faf_replay_parser-0.5.3-cp37-cp37m-win32.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 6bb9074f43fc880decc461ecf7c8f1b7f2edbe4acc1782d49bc2a156464dce36 |
|
MD5 | 957b61fd07e9684800f1756e83175b3d |
|
BLAKE2b-256 | ebcdb32eb20c627e5cdc11207bd05eccba4bbddbf9f716afcdf26884d83fa33c |
Hashes for faf_replay_parser-0.5.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | f34900b038fa08f61a50046a3c4f962612f3871fe335960fff09fb8f2bae9d55 |
|
MD5 | ae02947c14a342acf82ca41e605a5f53 |
|
BLAKE2b-256 | 256249a2e419dfd6d9969f34083e95a34802bbda58879234c4ba1c0ec6d9a895 |
Hashes for faf_replay_parser-0.5.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | c56b0f886fdd89b706ad8cefd8e517d1c7234bc23e1641dc639db103a89f73c4 |
|
MD5 | 03fe6911ac7f95e4bd26a3397720fad9 |
|
BLAKE2b-256 | 52528150b9796ea85adcf6a5dbf8be656b7ac793720c28d4820d9fff70485282 |
Hashes for faf_replay_parser-0.5.3-cp37-cp37m-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5fe036c07e88fb4ffa947fc09df730ae9d52426dba3131255aec040c6006f639 |
|
MD5 | 114d5c2db53e65e8b94186225e942815 |
|
BLAKE2b-256 | 853b5d129478c11e32629dc37cb88b5a49e22f1af332172eba6e0fc4b2e9ec07 |