#battle #parser #world #dat #wot #tanks #results

bin+lib wot_datfile_parser

A parser for .dat files generated by the game World of Tanks

4 releases

0.4.2 May 13, 2023
0.4.1 Mar 2, 2023
0.4.0 Mar 2, 2023
0.3.1 Jan 18, 2023
0.3.0 Jan 18, 2023

#1018 in Parser implementations

Download history 7/week @ 2024-02-26 7/week @ 2024-03-11 70/week @ 2024-04-01

77 downloads per month

MIT license

140KB
1K SLoC

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:

C:\Users\<YOUR_USER_NAME>\AppData\Roaming\Wargaming.net\WorldOfTanks\battle_results

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();

assert_eq!(
   &battle.common["teamHealth"],
   &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();
println!("{battle_as_json}");

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 {
                intercept.original_result()
            }
        },
    }
};

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

assert_eq!(
   &battle.common["teamHealth"],
   &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

Dependencies

~5MB
~96K SLoC