1
0
Fork 0
mirror of https://codeberg.org/demostf/parser.git synced 2026-06-03 18:24:05 +02:00

track rounds

This commit is contained in:
Robin Appelman 2019-03-04 21:01:24 +01:00
commit 713ab0de42
12 changed files with 105 additions and 84 deletions

View file

@ -13,7 +13,7 @@ fn main() -> std::result::Result<(), Box<ParseError>> {
//dbg!(header);
//dbg!(state.deaths);
//std::thread::sleep(std::time::Duration::from_secs(5));
let json = serde_json::to_string(&state.borrow().user_spans).unwrap_or("err".to_string());
let json = serde_json::to_string(&state.borrow().rounds).unwrap_or("err".to_string());
println!("{}", json);
Ok(())
}

View file

@ -6,7 +6,6 @@ use num_traits::FromPrimitive;
pub use generated::*;
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
use crate::demo::message::bspdecal::*;
use crate::demo::message::classinfo::*;
use crate::demo::message::gameevent::*;
@ -16,6 +15,7 @@ use crate::demo::message::stringtable::*;
use crate::demo::message::tempentities::*;
use crate::demo::message::usermessage::*;
use crate::demo::message::voice::*;
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
pub mod bspdecal;
pub mod classinfo;
@ -190,4 +190,4 @@ impl Message {
Message::CmdKeyValues(_) => MessageType::CmdKeyValues,
}
}
}
}

View file

@ -5,10 +5,10 @@ use bitstream_reader::{BitBuffer, BitRead, BitReadSized, BitStream, LittleEndian
use num_traits::{PrimInt, Unsigned};
use snap::Decoder;
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
use crate::demo::packet::stringtable::{
ExtraData, FixedUserdataSize, StringTable, StringTableEntry,
};
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
#[derive(Debug)]
pub struct CreateStringTableMessage {
@ -77,8 +77,7 @@ impl Parse for CreateStringTableMessage {
fixed_userdata_size,
};
let entries =
parse_string_table_list(&mut table_data, &table_meta, entity_count)?;
let entries = parse_string_table_list(&mut table_data, &table_meta, entity_count)?;
let table = StringTable {
entries,
@ -178,12 +177,7 @@ fn parse_string_table_list(
panic!("there should be no holes when reading CreateStringTable message");
};
let entry = read_table_entry(
stream,
table_meta,
&history,
None,
)?;
let entry = read_table_entry(stream, table_meta, &history, None)?;
// optimize: any way to get rid of the clone here?
// `entries` always outlives `history` without reallocation
let text = entry.text.clone();
@ -240,7 +234,7 @@ fn read_table_entry(
} else {
None
}
.map(ExtraData::new);
.map(ExtraData::new);
Ok(match existing_entry {
Some(existing_entry) => {

View file

@ -1,4 +1,4 @@
use bitstream_reader::{BitRead, LittleEndian, LazyBitReadSized};
use bitstream_reader::{BitRead, LazyBitReadSized, LittleEndian};
use crate::{ReadResult, Stream};

View file

@ -1,8 +1,8 @@
use bitstream_reader::{BitRead, BitSize, LittleEndian, LazyBitRead};
use bitstream_reader::{BitRead, BitSize, LazyBitRead, LittleEndian};
use crate::{Parse, ParseError, ParserState, Result, Stream, ReadResult};
use crate::demo::message::Message;
use crate::demo::vector::Vector;
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
#[derive(Debug)]
pub struct MessagePacket {

View file

@ -2,9 +2,9 @@ use std::fmt;
use bitstream_reader::{BitRead, LittleEndian};
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
use crate::demo::message::stringtable::StringTableMeta;
use crate::demo::sendprop::SendPropFlag::Exclude;
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
#[derive(BitRead, Clone, Copy, Debug)]
pub struct FixedUserdataSize {
@ -68,10 +68,7 @@ pub struct ExtraData {
impl ExtraData {
pub fn new(data: Stream) -> Self {
let byte_len = (data.bit_len() / 8) as u16;
ExtraData {
byte_len,
data,
}
ExtraData { byte_len, data }
}
}

View file

@ -12,7 +12,7 @@ impl BitRead<LittleEndian> for UserCmdPacket {
fn read(stream: &mut Stream) -> ReadResult<Self> {
let tick = stream.read()?;
let sequence_out = stream.read()?;
let len:u32 = stream.read()?;
let len: u32 = stream.read()?;
let mut _packet_data = stream.read_bits(len as usize * 8)?;
// TODO parse the packet data
Ok(UserCmdPacket { tick, sequence_out })

View file

@ -2,14 +2,16 @@ use std::collections::HashMap;
use serde::Serialize;
use crate::{ReadResult, Stream};
use crate::demo::gameevent_gen::{GameEvent, PlayerDeathEvent, PlayerSpawnEvent};
use crate::demo::message::{Message, MessageType};
use crate::demo::gameevent_gen::{
GameEvent, PlayerDeathEvent, PlayerSpawnEvent, TeamPlayRoundWinEvent,
};
use crate::demo::message::packetentities::EntityId;
use crate::demo::message::usermessage::{ChatMessageKind, UserMessage};
use crate::demo::message::{Message, MessageType};
use crate::demo::packet::stringtable::StringTableEntry;
use crate::demo::parser::dispatcher::{MessageHandler, StringTableEntryHandler};
use crate::demo::vector::Vector;
use crate::{ReadResult, Stream};
#[derive(Debug, Clone, Serialize)]
pub struct ChatMassage {
@ -33,7 +35,7 @@ impl Team {
1 => Team::Spectator,
2 => Team::Red,
3 => Team::Blue,
_ => Team::Other
_ => Team::Other,
}
}
}
@ -64,7 +66,7 @@ impl Class {
7 => Class::Pyro,
8 => Class::Spy,
9 => Class::Engineer,
_ => Class::Other
_ => Class::Other,
}
}
}
@ -127,11 +129,21 @@ impl Death {
#[derive(Debug, Clone, Serialize)]
pub struct Round {
winner: String,
winner: Team,
length: f32,
end_tick: u32,
}
impl Round {
pub fn from_event(event: TeamPlayRoundWinEvent, tick: u32) -> Self {
Round {
winner: Team::new(event.team as u16),
length: event.round_time,
end_tick: tick,
}
}
}
#[derive(Default, Debug, Serialize)]
pub struct World {
boundary_min: Vector,
@ -151,9 +163,8 @@ pub struct Analyser {
impl MessageHandler for Analyser {
fn does_handle(&self, message_type: MessageType) -> bool {
match message_type {
MessageType::GameEvent |
MessageType::UserMessage => true,
_ => false
MessageType::GameEvent | MessageType::UserMessage => true,
_ => false,
}
}
@ -191,17 +202,15 @@ impl Analyser {
fn handle_user_message(&mut self, message: UserMessage, tick: u32) {
match message {
UserMessage::SayText2(message) => {
match message.kind {
ChatMessageKind::NameChange => self.change_name(message.from, message.text),
_ => self.chat.push(ChatMassage {
tick,
text: message.text,
from: message.from,
kind: message.kind,
})
}
}
UserMessage::SayText2(message) => match message.kind {
ChatMessageKind::NameChange => self.change_name(message.from, message.text),
_ => self.chat.push(ChatMassage {
tick,
text: message.text,
from: message.from,
kind: message.kind,
}),
},
_ => {}
}
}
@ -219,6 +228,12 @@ impl Analyser {
match event {
GameEvent::PlayerDeath(event) => self.deaths.push(Death::from_event(event, tick)),
GameEvent::PlayerSpawn(event) => self.user_spans.push(Spawn::from_event(event, tick)),
GameEvent::TeamPlayRoundWin(event) => {
// 6 = time limit
if event.win_reason != 6 {
self.rounds.push(Round::from_event(event, tick))
}
}
_ => {}
}
}
@ -241,4 +256,4 @@ impl Analyser {
}
Ok(())
}
}
}

View file

@ -4,8 +4,8 @@ use std::rc::Rc;
use crate::demo::message::{Message, MessageType};
use crate::demo::packet::datatable::{SendTable, ServerClass};
use crate::demo::packet::Packet;
use crate::demo::packet::stringtable::{StringTable, StringTableEntry};
use crate::demo::packet::Packet;
use crate::ParserState;
pub trait MessageHandler {
@ -24,7 +24,7 @@ pub struct Dispatcher {
string_table_names: Vec<String>,
on_message: Vec<Rc<RefCell<MessageHandler>>>,
on_string_table_entry: Vec<Rc<RefCell<StringTableEntryHandler>>>,
state_handler: Option<Rc<RefCell<ParserState>>>
state_handler: Option<Rc<RefCell<ParserState>>>,
}
impl Dispatcher {
@ -36,7 +36,10 @@ impl Dispatcher {
self.state_handler = Some(handler);
}
pub fn register_string_table_entry_handler(&mut self, handler: Rc<RefCell<StringTableEntryHandler>>) {
pub fn register_string_table_entry_handler(
&mut self,
handler: Rc<RefCell<StringTableEntryHandler>>,
) {
self.on_string_table_entry.push(handler);
}
@ -53,12 +56,14 @@ impl Dispatcher {
Packet::Message(packet) | Packet::Sigon(packet) => {
for message in packet.messages {
match message {
Message::NetTick(message) => {
self.tick = message.tick
Message::NetTick(message) => self.tick = message.tick,
Message::CreateStringTable(message) => {
self.handle_string_table(message.table)
}
Message::CreateStringTable(message) => self.handle_string_table(message.table),
Message::UpdateStringTable(message) => self.handle_table_update(message.table_id, message.entries),
_ => self.handle_message(message)
Message::UpdateStringTable(message) => {
self.handle_table_update(message.table_id, message.entries)
}
_ => self.handle_message(message),
}
}
}
@ -93,13 +98,17 @@ impl Dispatcher {
fn handle_data_table(&mut self, send_tables: Vec<SendTable>, server_classes: Vec<ServerClass>) {
if let Some(handler) = &self.state_handler {
handler.borrow_mut().handle_data_table(send_tables, server_classes);
handler
.borrow_mut()
.handle_data_table(send_tables, server_classes);
}
}
fn handle_string_entry(&mut self, table: &String, index: usize, entries: &StringTableEntry) {
for handler in self.on_string_table_entry.iter() {
handler.borrow_mut().handle_string_entry(table, index, entries);
handler
.borrow_mut()
.handle_string_entry(table, index, entries);
}
}
@ -113,4 +122,4 @@ impl Dispatcher {
}
}
}
}
}

View file

@ -6,8 +6,8 @@ use bitstream_reader::{BitRead, LittleEndian, ReadError};
use crate::demo::gamevent::GameEventValue;
use crate::demo::header::Header;
use crate::demo::message::{Message, MessageType};
use crate::demo::packet::Packet;
use crate::demo::packet::stringtable::StringTableEntry;
use crate::demo::packet::Packet;
use crate::demo::parser::analyser::Analyser;
use crate::demo::parser::dispatcher::{Dispatcher, MessageHandler, StringTableEntryHandler};
pub use crate::demo::parser::state::ParserState;
@ -15,9 +15,9 @@ use crate::Stream;
use std::cell::RefCell;
use std::ops::Deref;
mod state;
mod analyser;
mod dispatcher;
mod state;
/// Errors that can occur during parsing
#[derive(Debug)]
@ -92,7 +92,9 @@ impl DemoParser {
dispatcher.register_message_handler(Rc::clone(&state) as Rc<RefCell<MessageHandler>>);
dispatcher.register_message_handler(Rc::clone(&analyser) as Rc<RefCell<MessageHandler>>);
dispatcher.register_string_table_entry_handler(Rc::clone(&analyser) as Rc<RefCell<StringTableEntryHandler>>);
dispatcher.register_string_table_entry_handler(
Rc::clone(&analyser) as Rc<RefCell<StringTableEntryHandler>>
);
dispatcher.set_state_handler(Rc::clone(&state));
DemoParser {

View file

@ -2,12 +2,12 @@ use std::collections::HashMap;
use crate::demo::gameevent_gen::GameEventType;
use crate::demo::gamevent::GameEventDefinition;
use crate::demo::message::{Message, MessageType};
use crate::demo::message::packetentities::EntityId;
use crate::demo::message::stringtable::StringTableMeta;
use crate::demo::message::{Message, MessageType};
use crate::demo::packet::datatable::{SendTable, ServerClass};
use crate::demo::packet::Packet;
use crate::demo::packet::stringtable::{StringTable, StringTableEntry};
use crate::demo::packet::Packet;
use crate::demo::parser::dispatcher::{MessageHandler, StringTableEntryHandler};
use crate::demo::sendprop::SendProp;
use crate::Stream;
@ -49,7 +49,11 @@ impl ParserState {
ParserState::default()
}
pub fn handle_data_table(&mut self, send_tables: Vec<SendTable>, server_classes: Vec<ServerClass>) {
pub fn handle_data_table(
&mut self,
send_tables: Vec<SendTable>,
server_classes: Vec<ServerClass>,
) {
for table in send_tables {
self.send_tables.insert(table.name.clone(), table);
}
@ -60,7 +64,11 @@ impl ParserState {
self.string_tables.push(table);
}
pub fn handle_string_table_update(&mut self, table_id: u8, entries: HashMap<u16, StringTableEntry>) {
pub fn handle_string_table_update(
&mut self,
table_id: u8,
entries: HashMap<u16, StringTableEntry>,
) {
match self.string_tables.get_mut(table_id as usize) {
Some(table) => {
for (index, entry) in entries {
@ -72,8 +80,8 @@ impl ParserState {
replace(table.entries.get_unchecked_mut(index), entry);
}
}
},
_ => unreachable!()
}
_ => unreachable!(),
}
}
}
@ -81,11 +89,11 @@ impl ParserState {
impl MessageHandler for ParserState {
fn does_handle(&self, message_type: MessageType) -> bool {
match message_type {
MessageType::ServerInfo |
MessageType::GameEventList |
MessageType::CreateStringTable |
MessageType::UpdateStringTable => true,
_ => false
MessageType::ServerInfo
| MessageType::GameEventList
| MessageType::CreateStringTable
| MessageType::UpdateStringTable => true,
_ => false,
}
}
@ -106,21 +114,17 @@ impl MessageHandler for ParserState {
impl StringTableEntryHandler for ParserState {
fn handle_string_entry(&mut self, table: &String, index: usize, entry: &StringTableEntry) {
match table.as_str() {
"instancebaseline" => {
match &entry.extra_data {
Some(extra) => {
match entry.text.parse::<u32>() {
Ok(class_id) => {
let baseline = StaticBaseline::new(class_id, extra.data.clone());
self.static_baselines.insert(class_id, baseline);
}
Err(_) => {}
}
"instancebaseline" => match &entry.extra_data {
Some(extra) => match entry.text.parse::<u32>() {
Ok(class_id) => {
let baseline = StaticBaseline::new(class_id, extra.data.clone());
self.static_baselines.insert(class_id, baseline);
}
_ => unreachable!("missing baseline")
}
}
_ => unreachable!()
Err(_) => {}
},
_ => unreachable!("missing baseline"),
},
_ => unreachable!(),
}
}
}
}

View file

@ -1,4 +1,4 @@
use bitstream_reader::{BitRead, LittleEndian, BitSize};
use bitstream_reader::{BitRead, BitSize, LittleEndian};
use serde::Serialize;
use crate::{ReadResult, Stream};