mirror of
https://codeberg.org/demostf/parser.git
synced 2026-06-03 10:14:06 +02:00
more efficient message handling
This commit is contained in:
parent
e5bbfd699e
commit
3c6d814e9b
4 changed files with 114 additions and 40 deletions
|
|
@ -1,8 +1,12 @@
|
||||||
|
use std::mem::discriminant;
|
||||||
|
|
||||||
|
use bitstream_reader::{BitRead, LittleEndian};
|
||||||
use enum_primitive_derive::Primitive;
|
use enum_primitive_derive::Primitive;
|
||||||
use num_traits::FromPrimitive;
|
use num_traits::FromPrimitive;
|
||||||
|
|
||||||
pub use generated::*;
|
pub use generated::*;
|
||||||
|
|
||||||
|
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
||||||
use crate::demo::message::bspdecal::*;
|
use crate::demo::message::bspdecal::*;
|
||||||
use crate::demo::message::classinfo::*;
|
use crate::demo::message::classinfo::*;
|
||||||
use crate::demo::message::gameevent::*;
|
use crate::demo::message::gameevent::*;
|
||||||
|
|
@ -12,8 +16,6 @@ use crate::demo::message::stringtable::*;
|
||||||
use crate::demo::message::tempentities::*;
|
use crate::demo::message::tempentities::*;
|
||||||
use crate::demo::message::usermessage::*;
|
use crate::demo::message::usermessage::*;
|
||||||
use crate::demo::message::voice::*;
|
use crate::demo::message::voice::*;
|
||||||
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
|
||||||
use bitstream_reader::{BitRead, LittleEndian};
|
|
||||||
|
|
||||||
pub mod bspdecal;
|
pub mod bspdecal;
|
||||||
pub mod classinfo;
|
pub mod classinfo;
|
||||||
|
|
@ -154,3 +156,38 @@ impl Parse for Message {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Message {
|
||||||
|
pub fn get_message_type(&self) -> MessageType {
|
||||||
|
match self {
|
||||||
|
Message::Empty => MessageType::Empty,
|
||||||
|
Message::File(_) => MessageType::File,
|
||||||
|
Message::NetTick(_) => MessageType::NetTick,
|
||||||
|
Message::StringCmd(_) => MessageType::StringCmd,
|
||||||
|
Message::SetConVar(_) => MessageType::SetConVar,
|
||||||
|
Message::SigOnState(_) => MessageType::SigOnState,
|
||||||
|
Message::Print(_) => MessageType::Print,
|
||||||
|
Message::ServerInfo(_) => MessageType::ServerInfo,
|
||||||
|
Message::ClassInfo(_) => MessageType::ClassInfo,
|
||||||
|
Message::SetPause(_) => MessageType::SetPause,
|
||||||
|
Message::CreateStringTable(_) => MessageType::CreateStringTable,
|
||||||
|
Message::UpdateStringTable(_) => MessageType::UpdateStringTable,
|
||||||
|
Message::VoiceInit(_) => MessageType::VoiceInit,
|
||||||
|
Message::VoiceData(_) => MessageType::VoiceData,
|
||||||
|
Message::ParseSounds(_) => MessageType::ParseSounds,
|
||||||
|
Message::SetView(_) => MessageType::SetView,
|
||||||
|
Message::FixAngle(_) => MessageType::FixAngle,
|
||||||
|
Message::BspDecal(_) => MessageType::BspDecal,
|
||||||
|
Message::UserMessage(_) => MessageType::UserMessage,
|
||||||
|
Message::EntityMessage(_) => MessageType::EntityMessage,
|
||||||
|
Message::GameEvent(_) => MessageType::GameEvent,
|
||||||
|
Message::PacketEntities(_) => MessageType::PacketEntities,
|
||||||
|
Message::TempEntities(_) => MessageType::TempEntities,
|
||||||
|
Message::PreFetch(_) => MessageType::PreFetch,
|
||||||
|
Message::Menu(_) => MessageType::Menu,
|
||||||
|
Message::GameEventList(_) => MessageType::GameEventList,
|
||||||
|
Message::GetCvarValue(_) => MessageType::GetCvarValue,
|
||||||
|
Message::CmdKeyValues(_) => MessageType::CmdKeyValues,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::demo::gameevent_gen::{GameEvent, PlayerDeathEvent};
|
use crate::demo::gameevent_gen::{GameEvent, PlayerDeathEvent};
|
||||||
use crate::demo::message::Message;
|
use crate::demo::message::{Message, MessageType};
|
||||||
use crate::demo::message::usermessage::{SayText2Kind, UserMessage};
|
use crate::demo::message::usermessage::{SayText2Kind, UserMessage};
|
||||||
|
use crate::demo::parser::MessageHandler;
|
||||||
use crate::demo::vector::Vector;
|
use crate::demo::vector::Vector;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
|
@ -58,18 +59,28 @@ pub struct Analyser {
|
||||||
pub world: World,
|
pub world: World,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Analyser {
|
impl MessageHandler for Analyser {
|
||||||
pub fn new() -> Self {
|
fn does_handle(&self, message_type: MessageType) -> bool {
|
||||||
Self::default()
|
match message_type {
|
||||||
|
MessageType::GameEvent |
|
||||||
|
MessageType::UserMessage => true,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_message(&mut self, message: Message, tick: u32) {
|
fn handle_message(&mut self, message: Message, tick: u32) {
|
||||||
match message {
|
match message {
|
||||||
Message::GameEvent(message) => self.handle_event(message.event, tick),
|
Message::GameEvent(message) => self.handle_event(message.event, tick),
|
||||||
Message::UserMessage(message) => self.handle_user_message(message, tick),
|
Message::UserMessage(message) => self.handle_user_message(message, tick),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Analyser {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_user_message(&mut self, message: UserMessage, tick: u32) {
|
fn handle_user_message(&mut self, message: UserMessage, tick: u32) {
|
||||||
match message {
|
match message {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ use bitstream_reader::{BitRead, LittleEndian, ReadError};
|
||||||
|
|
||||||
use crate::demo::gamevent::GameEventValue;
|
use crate::demo::gamevent::GameEventValue;
|
||||||
use crate::demo::header::Header;
|
use crate::demo::header::Header;
|
||||||
|
use crate::demo::message::{Message, MessageType};
|
||||||
use crate::demo::packet::Packet;
|
use crate::demo::packet::Packet;
|
||||||
use crate::demo::parser::analyser::Analyser;
|
use crate::demo::parser::analyser::Analyser;
|
||||||
pub use crate::demo::parser::state::ParserState;
|
pub use crate::demo::parser::state::ParserState;
|
||||||
|
|
@ -70,6 +71,12 @@ impl<T: BitRead<LittleEndian>> Parse for T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait MessageHandler {
|
||||||
|
fn does_handle(&self, message_type: MessageType) -> bool;
|
||||||
|
|
||||||
|
fn handle_message(&mut self, message: Message, tick: u32);
|
||||||
|
}
|
||||||
|
|
||||||
pub struct DemoParser {
|
pub struct DemoParser {
|
||||||
stream: Stream,
|
stream: Stream,
|
||||||
state: ParserState,
|
state: ParserState,
|
||||||
|
|
@ -99,17 +106,29 @@ impl DemoParser {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn dispatch_messages(&mut self, messages: Vec<Message>) {
|
||||||
|
let tick = self.state.tick;
|
||||||
|
for message in messages {
|
||||||
|
let message_type = message.get_message_type();
|
||||||
|
if self.state.does_handle(message_type) {
|
||||||
|
self.state.handle_message(message, tick);
|
||||||
|
} else if self.analyser.does_handle(message_type) {
|
||||||
|
self.analyser.handle_message(message, tick);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parse_demo(mut self) -> Result<(Header, Analyser)> {
|
pub fn parse_demo(mut self) -> Result<(Header, Analyser)> {
|
||||||
let header = self.read::<Header>()?;
|
let header = self.read::<Header>()?;
|
||||||
loop {
|
loop {
|
||||||
let packet = self.read::<Packet>()?;
|
let packet = self.read::<Packet>()?;
|
||||||
let messages = match packet {
|
match packet {
|
||||||
Packet::Stop(_) => break,
|
Packet::Stop(_) => break,
|
||||||
|
Packet::Message(packet) | Packet::Sigon(packet) => {
|
||||||
|
self.dispatch_messages(packet.messages);
|
||||||
|
}
|
||||||
packet => self.state.handle_packet(packet),
|
packet => self.state.handle_packet(packet),
|
||||||
};
|
};
|
||||||
for message in messages {
|
|
||||||
self.analyser.handle_message(message, self.state.tick);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok((header, self.analyser))
|
Ok((header, self.analyser))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,12 @@ use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::demo::gameevent_gen::GameEventType;
|
use crate::demo::gameevent_gen::GameEventType;
|
||||||
use crate::demo::gamevent::GameEventDefinition;
|
use crate::demo::gamevent::GameEventDefinition;
|
||||||
use crate::demo::message::Message;
|
use crate::demo::message::{Message, MessageType};
|
||||||
use crate::demo::message::packetentities::EntityId;
|
use crate::demo::message::packetentities::EntityId;
|
||||||
use crate::demo::packet::datatable::{SendTable, ServerClass};
|
use crate::demo::packet::datatable::{SendTable, ServerClass};
|
||||||
use crate::demo::packet::Packet;
|
use crate::demo::packet::Packet;
|
||||||
use crate::demo::packet::stringtable::{StringTable, StringTableEntry};
|
use crate::demo::packet::stringtable::{StringTable, StringTableEntry};
|
||||||
|
use crate::demo::parser::MessageHandler;
|
||||||
use crate::demo::sendprop::SendProp;
|
use crate::demo::sendprop::SendProp;
|
||||||
use crate::Stream;
|
use crate::Stream;
|
||||||
|
|
||||||
|
|
@ -36,13 +37,8 @@ impl ParserState {
|
||||||
ParserState::default()
|
ParserState::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_packet(&mut self, packet: Packet) -> Vec<Message> {
|
pub fn handle_packet(&mut self, packet: Packet) {
|
||||||
match packet {
|
match packet {
|
||||||
Packet::Message(packet) | Packet::Sigon(packet) => {
|
|
||||||
return packet.messages.into_iter()
|
|
||||||
.filter_map(|message| self.handle_message(message))
|
|
||||||
.collect();
|
|
||||||
}
|
|
||||||
Packet::DataTables(packet) => {
|
Packet::DataTables(packet) => {
|
||||||
if self.send_tables.len() > 0 {
|
if self.send_tables.len() > 0 {
|
||||||
unreachable!("overwriting tables");
|
unreachable!("overwriting tables");
|
||||||
|
|
@ -59,28 +55,6 @@ impl ParserState {
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
Vec::new()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_message(&mut self, message: Message) -> Option<Message> {
|
|
||||||
match message {
|
|
||||||
Message::NetTick(message) => self.tick = message.tick,
|
|
||||||
Message::ServerInfo(message) => {
|
|
||||||
self.version = message.version;
|
|
||||||
self.game = message.game;
|
|
||||||
}
|
|
||||||
Message::GameEventList(message) => {
|
|
||||||
self.event_definitions = message.event_list;
|
|
||||||
}
|
|
||||||
Message::CreateStringTable(message) => {
|
|
||||||
self.handle_table(message.table);
|
|
||||||
}
|
|
||||||
Message::UpdateStringTable(message) => {
|
|
||||||
self.handle_table_update(message.table_id, message.entries);
|
|
||||||
}
|
|
||||||
_ => return Some(message)
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_table(&mut self, table: StringTable) {
|
fn handle_table(&mut self, table: StringTable) {
|
||||||
|
|
@ -102,3 +76,36 @@ impl ParserState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl MessageHandler for ParserState {
|
||||||
|
fn does_handle(&self, message_type: MessageType) -> bool {
|
||||||
|
match message_type {
|
||||||
|
MessageType::NetTick |
|
||||||
|
MessageType::ServerInfo |
|
||||||
|
MessageType::GameEventList |
|
||||||
|
MessageType::CreateStringTable |
|
||||||
|
MessageType::UpdateStringTable => true,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_message(&mut self, message: Message, _tick: u32) {
|
||||||
|
match message {
|
||||||
|
Message::NetTick(message) => self.tick = message.tick,
|
||||||
|
Message::ServerInfo(message) => {
|
||||||
|
self.version = message.version;
|
||||||
|
self.game = message.game;
|
||||||
|
}
|
||||||
|
Message::GameEventList(message) => {
|
||||||
|
self.event_definitions = message.event_list;
|
||||||
|
}
|
||||||
|
Message::CreateStringTable(message) => {
|
||||||
|
self.handle_table(message.table);
|
||||||
|
}
|
||||||
|
Message::UpdateStringTable(message) => {
|
||||||
|
self.handle_table_update(message.table_id, message.entries);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue