created_at2023-01-18 08:18:59.024403
updated_at2023-05-13 21:50:05.830111
descriptionA parser for `.dat` files generated by the game World of Tanks



World of Tanks Datfile Parser

A parser for .dat battle result files generated by the game World of Tanks. .dat files are generated whenever a battle's results are viewed in-game. For Windows, these files are found in a location like:


The .dat files are simply pickle dumps. In theory, this would mean that reading these files are as simple as opening these files using the pickle module in Python (v2.7). However, the problem is that there is no information on the identifiers of a field. This means that reading from the file directly gives you results like this:

[-43243256354, 1673683215, 70, 1]

This crate simply identifies the correct identifiers based on the checksum value (which is usualy the first item in a list of values like above) and converts the above into something like this:

    "arenaCreateTime": 1673683215,
    "arenaTypeID": 70,
    "bonusType": 1

Simple Example

use wot_datfile_parser::DatFileParser;

let file = std::fs::read("input_files/WOT_1_19_1_0/19011713064132879.dat").unwrap();

// You must construct the parser first as it needs to
// do some initialization to parse the datfiles.
// You can then use this same parser to parse any number of datfiles
let parser = DatFileParser::new();

// The parser generates a Battle struct
let battle = parser.parse(&file).unwrap();

   &serde_json::json!({ "1": 13595, "2": 12985 })
assert_eq!(&battle.common["duration"], &serde_json::json!(407));

// Battle implements serde::Serialize and serde::Deserialize.
// So, you can use other data formats as well.
// Here we will convert it to json and print it:
let battle_as_json = serde_json::to_string_pretty(&battle).unwrap();

Advanced Example

If you need to change how some serde_pickle::Value are converted to serde_json::Value, you can intercept it and provide your own implementation:

use wot_datfile_parser::{DatFileParser, Intercept};

let file = std::fs::read("input_files/WOT_1_19_1_0/19011713064132879.dat").unwrap();
let parser = DatFileParser::new();

// We use the following closure to change how a serde_pickle::Value is
// converted to serde_json::Value. We can also use it to log any errors
// in the datfile_parser(by matching the Failed variant)
let intercept_fn = |intercept, _original_value| {
    use Intercept::*;
    match intercept {
        Success(field, _) | NotPresent(field, _) |
        ManuallyParsed(field, _) |  Failed(field, _, _) => {
            if field.name == "teamHealth" {
                // Here we can inspect the original_value and provide our own impl
                // for converting the serde_pickle::Value to serde_json::Value
                // But for this example, we will just return the following:
                serde_json::Value::String("My own parser for teamHealth".into())
            } else {

// The parser generates a Battle struct
let battle = parser.parse_intercept(&file, intercept_fn).unwrap();

   &serde_json::json!("My own parser for teamHealth")
assert_eq!(&battle.common["duration"], &serde_json::json!(407));

Supported WoT Versions

1.20.0, 1.20.1

Commit count: 325

cargo fmt