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 |
|
#1589 in Parser implementations
34 downloads per month
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
~97K SLoC