Skip to content

Instantly share code, notes, and snippets.

@yaniv-aknin
Last active April 24, 2021 21:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yaniv-aknin/fd0155b62f3d673e2c05fee5d8df0ba5 to your computer and use it in GitHub Desktop.
Save yaniv-aknin/fd0155b62f3d673e2c05fee5d8df0ba5 to your computer and use it in GitHub Desktop.
Quick tour of FAF (Forged Alliance Forever) historic game data, in the database and the replay files
{
"id": "4874853",
"type": "game",
"endTime": "2016-06-24T21:36:48Z",
"name": "coca Vs murf64",
"replayAvailable": true,
"replayTicks": null,
"replayUrl": "https://content.faforever.com/replays/0/4/87/48/4874853.fafreplay",
"startTime": "2016-06-24T21:16:18Z",
"validity": "VALID",
"victoryCondition": "DEMORALIZATION",
"mapVersion": {
"id": "532",
"type": "mapVersion",
"createTime": "2014-03-22T14:21:20Z",
"description": "<LOC SCMP_004_Description>Underwater for millennia, tectonic shifts have drained the Crater, exposing the Mass needed to continue the Infinite War. Sparse forests have sprung up in the intervening years, though they are often destroyed in the continuous fighting that rages in the Crater.",
"downloadUrl": "https://content.faforever.com/maps/scmp_004.zip",
"filename": "maps/scmp_004.zip",
"folderName": "scmp_004",
"height": 1024,
"hidden": true,
"maxPlayers": 4,
"ranked": true,
"thumbnailUrlLarge": "https://content.faforever.com/maps/previews/large/scmp_004.png",
"thumbnailUrlSmall": "https://content.faforever.com/maps/previews/small/scmp_004.png",
"updateTime": "2014-03-22T14:21:20Z",
"version": 3,
"width": 1024,
"map": {
"id": "416",
"type": "map",
"battleType": "FFA",
"createTime": "2016-08-08T05:48:04Z",
"displayName": "Emerald Crater",
"mapType": "skirmish",
"updateTime": "2016-08-08T05:48:04Z"
}
},
"playerStats": {
"0": {
"id": "9084965",
"type": "gamePlayerStats",
"afterDeviation": 47.7535,
"afterMean": 779.176,
"ai": false,
"beforeDeviation": 47.7728,
"beforeMean": 773.736,
"color": 2,
"faction": 1,
"result": "UNKNOWN",
"score": 1,
"scoreTime": "2016-06-24T21:36:48Z",
"startSpot": 2,
"team": 1,
"player": {
"id": "71779",
"type": "player",
"createTime": "2013-09-16T15:28:18Z",
"login": "murf64",
"updateTime": "2018-09-10T05:24:07Z",
"userAgent": "faf-client"
}
},
"1": {
"id": "9084966",
"type": "gamePlayerStats",
"afterDeviation": 47.6891,
"afterMean": 752.309,
"ai": false,
"beforeDeviation": 47.7069,
"beforeMean": 757.734,
"color": 1,
"faction": 3,
"result": "UNKNOWN",
"score": 0,
"scoreTime": "2016-06-24T21:36:48Z",
"startSpot": 1,
"team": 1,
"player": {
"id": "116558",
"type": "player",
"createTime": "2014-10-16T20:26:40Z",
"login": "coca",
"updateTime": "2021-04-21T18:56:17Z",
"userAgent": "downlords-faf-client"
}
}
}
}
# each replay has ~thousands of these commands
# most of them are Advance (advance game time),
# SetCommandSource (state that the next command belongs to player N), and some kind of CheckSum
# the Issue command is probably the most common/interesting "actual do something command"
# here we PROBABLY see player 1 telling its ACU to build a mass extractor (urb1103)
# I say probably because we can't say for sure without seeing earlier commands in this replay
# and trying to convince ourself unit 1048576 is really the ACU
# ACU's are pretty easy to identify in the replay; other units... much harder if not impossible.
{1: {'Advance': {'type': 'advance', 'advance': 1},
'SetCommandSource': {'type': 'set_command_source', 'player_id': 1}},
0: {'SetCommandSource': {'type': 'set_command_source', 'player_id': 0}}},
{1: {'Advance': {'type': 'advance', 'advance': 1},
'SetCommandSource': {'type': 'set_command_source', 'player_id': 1}},
0: {'SetCommandSource': {'type': 'set_command_source', 'player_id': 0}}},
{1: {'Advance': {'type': 'advance', 'advance': 1},
'SetCommandSource': {'type': 'set_command_source', 'player_id': 1},
'IssueCommand': {'type': 'issue',
'entity_ids_set': {'units_number': 1, 'unit_ids': [1048576]},
'cmd_data': {'command_id': 16777217,
'command_type': 8,
'target': {'target': 2,
'entity_id': None,
'position': (489.5, 20.09375, 840.5)},
'formation': None,
'blueprint_id': 'urb1103',
'cells': None,
'arg1': b'\xff\xff\xff\xff',
'arg2': b'\xff\xff\xff\xff',
'arg3': b'\x00',
'arg4': b'\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00',
'arg5': None}}},
0: {'SetCommandSource': {'type': 'set_command_source', 'player_id': 0}}},
{
"id": 4874853,
"headers": {
"json": { # <-- this is the JSON at the beginning of the replay file
"num_players": 2,
"featured_mod_versions": {},
"game_end": 1466804198.77615,
"uid": 4874853,
"title": "coca Vs murf64",
"game_type": 0,
"teams": {
"1": [
"coca"
]
},
"mapname": "scmp_004",
"host": "coca",
"featured_mod": "ladder1v1",
"complete": true,
"version": 2,
"compression": "zstd"
},
"binary": { # <-- this is primarily extracted from the replay file's header
"version": "Supreme Commander v1.50.3654",
"replay_version": "Replay v1.9",
"map_name": "/maps/SCMP_004/SCMP_004.scmap",
"mods": {},
"cheats_enabled": false,
"numbers_of_armies": 2,
"armies": {
"0": {
"MEAN": 761.8480224609375,
"StartSpot": 1.0,
"ArmyColor": 1.0,
"NG": 18.0,
"Team": 1.0,
"Ready": false,
"PlayerColor": 1.0,
"Civilian": false,
"PlayerName": "coca",
"AIPersonality": "",
"DEV": 47.691898345947266,
"Faction": 3.0,
"ArmyName": "ARMY_1",
"PL": 618.0,
"Human": true,
"OwnerID": "116558"
},
"1": {
"MEAN": 773.7360229492188,
"StartSpot": 1.0,
"ArmyColor": 1.0,
"NG": 594.0,
"Team": 1.0,
"Ready": false,
"PlayerColor": 2.0,
"Civilian": false,
"PlayerName": "murf64",
"AIPersonality": "",
"Human": true,
"OwnerID": "71779",
"ArmyName": "ARMY_2",
"PL": 630.0,
"Faction": 1.0,
"DEV": 47.77280044555664
}
},
"random_seed": 14616284,
"last_tick": 11284,
"desync": {
"count": 0,
"ticks": ""
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment