mirror of
https://github.com/eigenein/wotbreplay-parser.git
synced 2026-10-23 19:29:48 +02:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1830536224 | ||
|
|
897f98c17c | ||
|
|
59353a9aca | ||
|
|
c9a2adff4c |
No files matched your search
@@ -1,5 +1,5 @@
|
|||||||
use prost::bytes::Buf;
|
use prost::bytes::Buf;
|
||||||
use prost::Message;
|
use prost::{Enumeration, Message};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::result::Result;
|
use crate::result::Result;
|
||||||
@@ -22,8 +22,8 @@ pub struct BattleResults {
|
|||||||
#[prost(int64, tag = "2")]
|
#[prost(int64, tag = "2")]
|
||||||
pub timestamp: i64,
|
pub timestamp: i64,
|
||||||
|
|
||||||
#[prost(enumeration = "TeamNumber", tag = "3")]
|
#[prost(enumeration = "TeamNumber", optional, tag = "3")]
|
||||||
pub winner_team_number: i32,
|
pub winner_team_number: Option<i32>,
|
||||||
|
|
||||||
/// Replay's author results.
|
/// Replay's author results.
|
||||||
#[prost(message, required, tag = "8")]
|
#[prost(message, required, tag = "8")]
|
||||||
@@ -78,9 +78,7 @@ pub struct PlayerInfo {
|
|||||||
pub avatar: Avatar,
|
pub avatar: Avatar,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Enumeration, Serialize)]
|
||||||
Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, prost::Enumeration, Serialize,
|
|
||||||
)]
|
|
||||||
#[repr(i32)]
|
#[repr(i32)]
|
||||||
pub enum TeamNumber {
|
pub enum TeamNumber {
|
||||||
One = 1,
|
One = 1,
|
||||||
|
|||||||
+2
-3
@@ -1,10 +1,9 @@
|
|||||||
//! `data.wotreplay` models.
|
//! Models for `data.wotreplay` contents.
|
||||||
|
|
||||||
|
pub mod base_player_create;
|
||||||
pub mod entity_method;
|
pub mod entity_method;
|
||||||
pub mod packet;
|
pub mod packet;
|
||||||
pub mod payload;
|
pub mod payload;
|
||||||
pub mod subtype_2f;
|
|
||||||
pub mod type_0;
|
|
||||||
|
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,8 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// Looks like some sort of replay summary.
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct Type0 {
|
pub struct BasePlayerCreate {
|
||||||
#[serde(rename(deserialize = "playersBattleCategoriesIds"))]
|
#[serde(rename(deserialize = "playersBattleCategoriesIds"))]
|
||||||
pub players_battle_categories_ids: HashMap<u32, (u8, u32)>,
|
pub players_battle_categories_ids: HashMap<u32, (u8, u32)>,
|
||||||
|
|
||||||
@@ -4,16 +4,19 @@ use prost::Message;
|
|||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_with::serde_as;
|
use serde_with::serde_as;
|
||||||
|
|
||||||
|
use self::update_arena::UpdateArena;
|
||||||
use crate::models::data::read_quirky_length;
|
use crate::models::data::read_quirky_length;
|
||||||
use crate::models::data::subtype_2f::Subtype2F;
|
|
||||||
use crate::result::Result;
|
use crate::result::Result;
|
||||||
|
|
||||||
|
pub mod update_arena;
|
||||||
|
|
||||||
#[serde_as]
|
#[serde_as]
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
pub enum EntityMethod {
|
pub enum EntityMethod {
|
||||||
Subtype2F {
|
/// Subtype `0x2F`.
|
||||||
|
UpdateArena {
|
||||||
field_number: u64,
|
field_number: u64,
|
||||||
sub_type_2f: Subtype2F,
|
arguments: UpdateArena,
|
||||||
|
|
||||||
/// Original payload for investigation.
|
/// Original payload for investigation.
|
||||||
#[serde_as(as = "serde_with::hex::Hex")]
|
#[serde_as(as = "serde_with::hex::Hex")]
|
||||||
@@ -31,6 +34,7 @@ pub enum EntityMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EntityMethod {
|
impl EntityMethod {
|
||||||
|
/// Parse the entity method payload.
|
||||||
pub fn new(payload: Vec<u8>) -> Result<Self> {
|
pub fn new(payload: Vec<u8>) -> Result<Self> {
|
||||||
let mut reader = payload.as_slice();
|
let mut reader = payload.as_slice();
|
||||||
|
|
||||||
@@ -43,9 +47,9 @@ impl EntityMethod {
|
|||||||
|
|
||||||
let field_number = decode_varint(&mut reader)?;
|
let field_number = decode_varint(&mut reader)?;
|
||||||
let message_length = read_quirky_length(&mut reader)?;
|
let message_length = read_quirky_length(&mut reader)?;
|
||||||
Self::Subtype2F {
|
Self::UpdateArena {
|
||||||
field_number,
|
field_number,
|
||||||
sub_type_2f: Subtype2F::decode(&reader[..message_length])?,
|
arguments: UpdateArena::decode(&reader[..message_length])?,
|
||||||
payload,
|
payload,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use prost::Message;
|
|||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
#[derive(Message, Serialize)]
|
#[derive(Message, Serialize)]
|
||||||
pub struct Subtype2F {
|
pub struct UpdateArena {
|
||||||
#[prost(message, tag = "1")]
|
#[prost(message, tag = "1")]
|
||||||
pub players: Option<Players>,
|
pub players: Option<Players>,
|
||||||
}
|
}
|
||||||
@@ -4,22 +4,23 @@ use byteorder::{LittleEndian, ReadBytesExt};
|
|||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_with::serde_as;
|
use serde_with::serde_as;
|
||||||
|
|
||||||
|
use crate::models::data::base_player_create::BasePlayerCreate;
|
||||||
use crate::models::data::entity_method::EntityMethod;
|
use crate::models::data::entity_method::EntityMethod;
|
||||||
use crate::models::data::type_0::Type0;
|
|
||||||
use crate::models::data::{read_pickled, read_quirky_length, read_string};
|
use crate::models::data::{read_pickled, read_quirky_length, read_string};
|
||||||
use crate::result::Result;
|
use crate::result::Result;
|
||||||
|
|
||||||
#[serde_as]
|
#[serde_as]
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
pub enum Payload {
|
pub enum Payload {
|
||||||
/// Looks like some sort of replay summary.
|
/// Type 0.
|
||||||
Type0 {
|
BasePlayerCreate {
|
||||||
author_nickname: String,
|
author_nickname: String,
|
||||||
arena_unique_id: u64,
|
arena_unique_id: u64,
|
||||||
arena_type_id: u32,
|
arena_type_id: u32,
|
||||||
type_0: Box<Type0>,
|
arguments: Box<BasePlayerCreate>,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// Type 8.
|
||||||
EntityMethod(EntityMethod),
|
EntityMethod(EntityMethod),
|
||||||
|
|
||||||
/// Default payload when type is not known by the parser.
|
/// Default payload when type is not known by the parser.
|
||||||
@@ -46,8 +47,8 @@ impl Payload {
|
|||||||
let pickled_length = read_quirky_length(&mut reader)?;
|
let pickled_length = read_quirky_length(&mut reader)?;
|
||||||
read_pickled(&mut reader, pickled_length)?
|
read_pickled(&mut reader, pickled_length)?
|
||||||
};
|
};
|
||||||
Self::Type0 {
|
Self::BasePlayerCreate {
|
||||||
type_0,
|
arguments: type_0,
|
||||||
author_nickname,
|
author_nickname,
|
||||||
arena_unique_id,
|
arena_unique_id,
|
||||||
arena_type_id,
|
arena_type_id,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//! Models for `meta.json` contents.
|
||||||
#![cfg(feature = "meta")]
|
#![cfg(feature = "meta")]
|
||||||
|
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ fn player_results_ok() -> Result<()> {
|
|||||||
assert_eq!(battle_results_dat.arena_unique_id, 1661909200500084);
|
assert_eq!(battle_results_dat.arena_unique_id, 1661909200500084);
|
||||||
let battle_results: BattleResults = battle_results_dat.try_into()?;
|
let battle_results: BattleResults = battle_results_dat.try_into()?;
|
||||||
|
|
||||||
assert_eq!(battle_results.winner_team_number, 2);
|
assert_eq!(battle_results.winner_team_number, Some(2));
|
||||||
|
|
||||||
assert_eq!(battle_results.author.team_number, 2);
|
assert_eq!(battle_results.author.team_number, 2);
|
||||||
assert_eq!(battle_results.author.credits_earned, 59518);
|
assert_eq!(battle_results.author.credits_earned, 59518);
|
||||||
@@ -117,3 +117,11 @@ fn victory_points_ok() -> Result<()> {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn draw_ok() -> Result<()> {
|
||||||
|
let battle_results = Replay::open(File::open("tests/replays/20230503_0027__helaas_pindakaas_A140_ASTRON_REX_105_2319058483532631656.wotbreplay")?)?
|
||||||
|
.read_battle_results()?;
|
||||||
|
assert_eq!(battle_results.winner_team_number, None);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
+3
-3
@@ -29,11 +29,11 @@ fn type0_ok() -> Result<()> {
|
|||||||
.packets
|
.packets
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|packet| {
|
.filter_map(|packet| {
|
||||||
if let Payload::Type0 {
|
if let Payload::BasePlayerCreate {
|
||||||
author_nickname,
|
author_nickname,
|
||||||
arena_unique_id,
|
arena_unique_id,
|
||||||
arena_type_id,
|
arena_type_id,
|
||||||
type_0,
|
arguments: type_0,
|
||||||
} = &packet.payload
|
} = &packet.payload
|
||||||
{
|
{
|
||||||
Some((author_nickname, arena_unique_id, arena_type_id, type_0))
|
Some((author_nickname, arena_unique_id, arena_type_id, type_0))
|
||||||
@@ -74,7 +74,7 @@ fn subtype_2f_players_ok() -> Result<()> {
|
|||||||
.packets
|
.packets
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|packet| match &packet.payload {
|
.filter_map(|packet| match &packet.payload {
|
||||||
Payload::EntityMethod(EntityMethod::Subtype2F { sub_type_2f, .. }) => {
|
Payload::EntityMethod(EntityMethod::UpdateArena { arguments: sub_type_2f, .. }) => {
|
||||||
sub_type_2f.players.as_ref()
|
sub_type_2f.players.as_ref()
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|||||||
Generated
BIN
Binary file not shown.
Reference in new issue
Block a user