mirror of
https://codeberg.org/demostf/parser.git
synced 2026-06-03 10:14:06 +02:00
fix tempentities for protocol version 23
This commit is contained in:
parent
185ff6365f
commit
3055242fd9
10 changed files with 85 additions and 65 deletions
|
|
@ -108,7 +108,7 @@ fn test_game_event_roundtrip() {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseBitSkip<'_> for GameEventMessage {
|
impl ParseBitSkip<'_> for GameEventMessage {
|
||||||
fn parse_skip(stream: &mut Stream) -> Result<()> {
|
fn parse_skip(stream: &mut Stream, _state: &ParserState) -> Result<()> {
|
||||||
let length: u16 = stream.read_sized(11)?;
|
let length: u16 = stream.read_sized(11)?;
|
||||||
stream.skip_bits(length as usize).map_err(ParseError::from)
|
stream.skip_bits(length as usize).map_err(ParseError::from)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -193,36 +193,40 @@ impl<'a> Message<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn skip_type(message_type: MessageType, stream: &mut Stream) -> Result<()> {
|
pub fn skip_type(
|
||||||
|
message_type: MessageType,
|
||||||
|
stream: &mut Stream,
|
||||||
|
state: &ParserState,
|
||||||
|
) -> Result<()> {
|
||||||
match message_type {
|
match message_type {
|
||||||
MessageType::Empty => Ok(()),
|
MessageType::Empty => Ok(()),
|
||||||
MessageType::File => FileMessage::parse_skip(stream),
|
MessageType::File => FileMessage::parse_skip(stream, state),
|
||||||
MessageType::NetTick => NetTickMessage::parse_skip(stream),
|
MessageType::NetTick => NetTickMessage::parse_skip(stream, state),
|
||||||
MessageType::StringCmd => StringCmdMessage::parse_skip(stream),
|
MessageType::StringCmd => StringCmdMessage::parse_skip(stream, state),
|
||||||
MessageType::SetConVar => SetConVarMessage::parse_skip(stream),
|
MessageType::SetConVar => SetConVarMessage::parse_skip(stream, state),
|
||||||
MessageType::SigOnState => SignOnStateMessage::parse_skip(stream),
|
MessageType::SigOnState => SignOnStateMessage::parse_skip(stream, state),
|
||||||
MessageType::Print => PrintMessage::parse_skip(stream),
|
MessageType::Print => PrintMessage::parse_skip(stream, state),
|
||||||
MessageType::ServerInfo => ServerInfoMessage::parse_skip(stream),
|
MessageType::ServerInfo => ServerInfoMessage::parse_skip(stream, state),
|
||||||
MessageType::ClassInfo => ClassInfoMessage::parse_skip(stream),
|
MessageType::ClassInfo => ClassInfoMessage::parse_skip(stream, state),
|
||||||
MessageType::SetPause => SetPauseMessage::parse_skip(stream),
|
MessageType::SetPause => SetPauseMessage::parse_skip(stream, state),
|
||||||
MessageType::CreateStringTable => CreateStringTableMessage::parse_skip(stream),
|
MessageType::CreateStringTable => CreateStringTableMessage::parse_skip(stream, state),
|
||||||
MessageType::UpdateStringTable => UpdateStringTableMessage::parse_skip(stream),
|
MessageType::UpdateStringTable => UpdateStringTableMessage::parse_skip(stream, state),
|
||||||
MessageType::VoiceInit => VoiceInitMessage::parse_skip(stream),
|
MessageType::VoiceInit => VoiceInitMessage::parse_skip(stream, state),
|
||||||
MessageType::VoiceData => VoiceDataMessage::parse_skip(stream),
|
MessageType::VoiceData => VoiceDataMessage::parse_skip(stream, state),
|
||||||
MessageType::ParseSounds => ParseSoundsMessage::parse_skip(stream),
|
MessageType::ParseSounds => ParseSoundsMessage::parse_skip(stream, state),
|
||||||
MessageType::SetView => SetViewMessage::parse_skip(stream),
|
MessageType::SetView => SetViewMessage::parse_skip(stream, state),
|
||||||
MessageType::FixAngle => FixAngleMessage::parse_skip(stream),
|
MessageType::FixAngle => FixAngleMessage::parse_skip(stream, state),
|
||||||
MessageType::BspDecal => BSPDecalMessage::parse_skip(stream),
|
MessageType::BspDecal => BSPDecalMessage::parse_skip(stream, state),
|
||||||
MessageType::UserMessage => UserMessage::parse_skip(stream),
|
MessageType::UserMessage => UserMessage::parse_skip(stream, state),
|
||||||
MessageType::EntityMessage => EntityMessage::parse_skip(stream),
|
MessageType::EntityMessage => EntityMessage::parse_skip(stream, state),
|
||||||
MessageType::GameEvent => GameEventMessage::parse_skip(stream),
|
MessageType::GameEvent => GameEventMessage::parse_skip(stream, state),
|
||||||
MessageType::PacketEntities => PacketEntitiesMessage::parse_skip(stream),
|
MessageType::PacketEntities => PacketEntitiesMessage::parse_skip(stream, state),
|
||||||
MessageType::TempEntities => TempEntitiesMessage::parse_skip(stream),
|
MessageType::TempEntities => TempEntitiesMessage::parse_skip(stream, state),
|
||||||
MessageType::PreFetch => PreFetchMessage::parse_skip(stream),
|
MessageType::PreFetch => PreFetchMessage::parse_skip(stream, state),
|
||||||
MessageType::Menu => MenuMessage::parse_skip(stream),
|
MessageType::Menu => MenuMessage::parse_skip(stream, state),
|
||||||
MessageType::GameEventList => GameEventListMessage::parse_skip(stream),
|
MessageType::GameEventList => GameEventListMessage::parse_skip(stream, state),
|
||||||
MessageType::GetCvarValue => GetCvarValueMessage::parse_skip(stream),
|
MessageType::GetCvarValue => GetCvarValueMessage::parse_skip(stream, state),
|
||||||
MessageType::CmdKeyValues => CmdKeyValuesMessage::parse_skip(stream),
|
MessageType::CmdKeyValues => CmdKeyValuesMessage::parse_skip(stream, state),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -439,7 +439,7 @@ impl PacketEntitiesMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseBitSkip<'_> for PacketEntitiesMessage {
|
impl ParseBitSkip<'_> for PacketEntitiesMessage {
|
||||||
fn parse_skip(stream: &mut Stream) -> Result<()> {
|
fn parse_skip(stream: &mut Stream, _state: &ParserState) -> Result<()> {
|
||||||
stream.skip_bits(11)?;
|
stream.skip_bits(11)?;
|
||||||
if stream.read()? {
|
if stream.read()? {
|
||||||
stream.skip_bits(32)?;
|
stream.skip_bits(32)?;
|
||||||
|
|
|
||||||
|
|
@ -133,12 +133,16 @@ impl<'a> Parse<'a> for CreateStringTableMessage<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ParseBitSkip<'a> for CreateStringTableMessage<'a> {
|
impl<'a> ParseBitSkip<'a> for CreateStringTableMessage<'a> {
|
||||||
fn parse_skip(stream: &mut Stream<'a>) -> Result<()> {
|
fn parse_skip(stream: &mut Stream<'a>, state: &ParserState) -> Result<()> {
|
||||||
let _: String = stream.read()?;
|
let _: String = stream.read()?;
|
||||||
let max_entries: u16 = stream.read()?;
|
let max_entries: u16 = stream.read()?;
|
||||||
let encode_bits = log_base2(max_entries);
|
let encode_bits = log_base2(max_entries);
|
||||||
let _: u16 = stream.read_sized(encode_bits as usize + 1)?;
|
let _: u16 = stream.read_sized(encode_bits as usize + 1)?;
|
||||||
let length = read_var_int(stream)?;
|
let length = if state.protocol_version > 23 {
|
||||||
|
read_var_int(stream)?
|
||||||
|
} else {
|
||||||
|
stream.read_sized(20)?
|
||||||
|
};
|
||||||
|
|
||||||
let _: Option<FixedUserDataSize> = stream.read()?;
|
let _: Option<FixedUserDataSize> = stream.read()?;
|
||||||
|
|
||||||
|
|
@ -263,7 +267,7 @@ impl<'a> Parse<'a> for UpdateStringTableMessage<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ParseBitSkip<'a> for UpdateStringTableMessage<'a> {
|
impl<'a> ParseBitSkip<'a> for UpdateStringTableMessage<'a> {
|
||||||
fn parse_skip(stream: &mut Stream<'a>) -> Result<()> {
|
fn parse_skip(stream: &mut Stream<'a>, _state: &ParserState) -> Result<()> {
|
||||||
let _: u8 = stream.read_sized(5)?;
|
let _: u8 = stream.read_sized(5)?;
|
||||||
|
|
||||||
let _: u16 = if stream.read()? { stream.read()? } else { 1 };
|
let _: u16 = if stream.read()? { stream.read()? } else { 1 };
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
use crate::{ReadResult, Stream};
|
use crate::{Parse, ParserState, ReadResult, Stream};
|
||||||
|
|
||||||
use super::packetentities::PacketEntity;
|
use super::packetentities::PacketEntity;
|
||||||
use super::stringtable::read_var_int;
|
use super::stringtable::read_var_int;
|
||||||
use crate::demo::message::stringtable::write_var_int;
|
use crate::demo::message::stringtable::write_var_int;
|
||||||
use bitbuffer::{BitRead, BitWrite, BitWriteStream, LittleEndian};
|
use crate::demo::parser::ParseBitSkip;
|
||||||
|
use crate::Result;
|
||||||
|
use bitbuffer::{BitWrite, BitWriteStream, LittleEndian};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct TempEntitiesMessage<'a> {
|
pub struct TempEntitiesMessage<'a> {
|
||||||
|
|
@ -12,10 +14,14 @@ pub struct TempEntitiesMessage<'a> {
|
||||||
pub entities: Vec<PacketEntity>,
|
pub entities: Vec<PacketEntity>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> BitRead<'a, LittleEndian> for TempEntitiesMessage<'a> {
|
impl<'a> Parse<'a> for TempEntitiesMessage<'a> {
|
||||||
fn read(stream: &mut Stream<'a>) -> ReadResult<Self> {
|
fn parse(stream: &mut Stream<'a>, state: &ParserState) -> Result<Self> {
|
||||||
let count: u8 = stream.read()?;
|
let count: u8 = stream.read()?;
|
||||||
let length = read_var_int(stream)?;
|
let length = if state.protocol_version > 23 {
|
||||||
|
read_var_int(stream)?
|
||||||
|
} else {
|
||||||
|
stream.read_sized(17)?
|
||||||
|
};
|
||||||
let data = stream.read_bits(length as usize)?;
|
let data = stream.read_bits(length as usize)?;
|
||||||
|
|
||||||
Ok(TempEntitiesMessage {
|
Ok(TempEntitiesMessage {
|
||||||
|
|
@ -24,11 +30,18 @@ impl<'a> BitRead<'a, LittleEndian> for TempEntitiesMessage<'a> {
|
||||||
entities: Vec::new(),
|
entities: Vec::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn skip(stream: &mut Stream) -> ReadResult<()> {
|
impl<'a> ParseBitSkip<'a> for TempEntitiesMessage<'a> {
|
||||||
|
fn parse_skip(stream: &mut Stream<'a>, state: &ParserState) -> Result<()> {
|
||||||
let _: u8 = stream.read()?;
|
let _: u8 = stream.read()?;
|
||||||
let length = read_var_int(stream)?;
|
let length = if state.protocol_version > 23 {
|
||||||
stream.skip_bits(length as usize)
|
read_var_int(stream)?
|
||||||
|
} else {
|
||||||
|
stream.read_sized(17)?
|
||||||
|
};
|
||||||
|
stream.skip_bits(length as usize)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ impl<'a> Parse<'a> for MessagePacket<'a> {
|
||||||
if state.should_parse_message(message_type) && message_type != MessageType::Empty {
|
if state.should_parse_message(message_type) && message_type != MessageType::Empty {
|
||||||
messages.push(Message::from_type(message_type, &mut packet_data, state)?);
|
messages.push(Message::from_type(message_type, &mut packet_data, state)?);
|
||||||
} else {
|
} else {
|
||||||
Message::skip_type(message_type, &mut packet_data)?;
|
Message::skip_type(message_type, &mut packet_data, state)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,12 +45,12 @@ impl<T: BitWrite<LittleEndian>> Encode for T {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ParseBitSkip<'a> {
|
pub trait ParseBitSkip<'a> {
|
||||||
fn parse_skip(stream: &mut Stream<'a>) -> Result<()>;
|
fn parse_skip(stream: &mut Stream<'a>, state: &ParserState) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: BitRead<'a, LittleEndian>> ParseBitSkip<'a> for T {
|
impl<'a, T: BitRead<'a, LittleEndian>> ParseBitSkip<'a> for T {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn parse_skip(stream: &mut Stream<'a>) -> Result<()> {
|
fn parse_skip(stream: &mut Stream<'a>, _state: &ParserState) -> Result<()> {
|
||||||
Self::skip(stream).map_err(ParseError::from)
|
Self::skip(stream).map_err(ParseError::from)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
BIN
test_data/protocol23.dem
Normal file
BIN
test_data/protocol23.dem
Normal file
Binary file not shown.
1
test_data/protocol23.json
Normal file
1
test_data/protocol23.json
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -4,46 +4,44 @@ use test_case::test_case;
|
||||||
use tf_demo_parser::demo::parser::gamestateanalyser::{GameState, GameStateAnalyser};
|
use tf_demo_parser::demo::parser::gamestateanalyser::{GameState, GameStateAnalyser};
|
||||||
use tf_demo_parser::{Demo, DemoParser, MatchState};
|
use tf_demo_parser::{Demo, DemoParser, MatchState};
|
||||||
|
|
||||||
#[test_case("test_data/small.dem", "test_data/small.json"; "small.dem")]
|
#[test_case("small.dem", "small.json"; "small.dem")]
|
||||||
#[test_case("test_data/gully.dem", "test_data/gully.json"; "gully.dem")]
|
#[test_case("gully.dem", "gully.json"; "gully.dem")]
|
||||||
#[test_case("test_data/comp.dem", "test_data/comp.json"; "comp.dem")]
|
#[test_case("comp.dem", "comp.json"; "comp.dem")]
|
||||||
#[test_case("test_data/malformed_cvar.dem", "test_data/malformed_cvar.json"; "malformed_cvar.dem")]
|
#[test_case("malformed_cvar.dem", "malformed_cvar.json"; "malformed_cvar.dem")]
|
||||||
#[test_case("test_data/unicode-saytext.dem", "test_data/unicode-saytext.json"; "unicode-saytext.dem")]
|
#[test_case("unicode-saytext.dem", "unicode-saytext.json"; "unicode-saytext.dem")]
|
||||||
#[test_case("test_data/nousers.dem", "test_data/nousers.json"; "nousers.dem")]
|
#[test_case("nousers.dem", "nousers.json"; "nousers.dem")]
|
||||||
#[test_case("test_data/decal.dem", "test_data/decal.json"; "decal.dem")]
|
#[test_case("decal.dem", "decal.json"; "decal.dem")]
|
||||||
#[test_case("test_data/saytext2.dem", "test_data/saytext2.json"; "saytext2.dem")]
|
#[test_case("saytext2.dem", "saytext2.json"; "saytext2.dem")]
|
||||||
#[test_case("test_data/emptysaytext.dem", "test_data/emptysaytext.json"; "emptysaytext.dem")]
|
#[test_case("emptysaytext.dem", "emptysaytext.json"; "emptysaytext.dem")]
|
||||||
|
#[test_case("protocol23.dem", "protocol23.json"; "protocol23.dem")]
|
||||||
fn snapshot_test(input_file: &str, snapshot_file: &str) {
|
fn snapshot_test(input_file: &str, snapshot_file: &str) {
|
||||||
let file = fs::read(input_file).expect("Unable to read file");
|
let file = fs::read(format!("test_data/{}", input_file)).expect("Unable to read file");
|
||||||
let demo = Demo::new(&file);
|
let demo = Demo::new(&file);
|
||||||
let (_, state) = DemoParser::new(demo.get_stream()).parse().unwrap();
|
let (_, state) = DemoParser::new(demo.get_stream()).parse().unwrap();
|
||||||
|
|
||||||
let expected: MatchState = serde_json::from_slice(
|
let expected: MatchState = serde_json::from_slice(
|
||||||
fs::read(snapshot_file)
|
fs::read(format!("test_data/{}", snapshot_file))
|
||||||
.expect("Unable to read file")
|
.expect("Unable to read file")
|
||||||
.as_slice(),
|
.as_slice(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
pretty_assertions::assert_eq!(expected.start_tick, state.start_tick);
|
pretty_assertions::assert_eq!(expected, state);
|
||||||
pretty_assertions::assert_eq!(expected.chat, state.chat);
|
|
||||||
pretty_assertions::assert_eq!(expected.deaths, state.deaths);
|
let (_, state) = DemoParser::new_all(demo.get_stream()).parse().unwrap();
|
||||||
pretty_assertions::assert_eq!(expected.interval_per_tick, state.interval_per_tick);
|
|
||||||
pretty_assertions::assert_eq!(expected.rounds, state.rounds);
|
|
||||||
pretty_assertions::assert_eq!(expected.users, state.users);
|
|
||||||
pretty_assertions::assert_eq!(expected, state);
|
pretty_assertions::assert_eq!(expected, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test_case("test_data/small.dem", "test_data/small_game_state.json"; "small.dem")]
|
#[test_case("small.dem", "small_game_state.json"; "small.dem")]
|
||||||
#[test_case("test_data/gully.dem", "test_data/gully_game_state.json"; "gully.dem")]
|
#[test_case("gully.dem", "gully_game_state.json"; "gully.dem")]
|
||||||
fn game_state_test(input_file: &str, snapshot_file: &str) {
|
fn game_state_test(input_file: &str, snapshot_file: &str) {
|
||||||
let file = fs::read(input_file).expect("Unable to read file");
|
let file = fs::read(format!("test_data/{}", input_file)).expect("Unable to read file");
|
||||||
let demo = Demo::new(&file);
|
let demo = Demo::new(&file);
|
||||||
let (_, state) = DemoParser::new_with_analyser(demo.get_stream(), GameStateAnalyser::new())
|
let (_, state) = DemoParser::new_with_analyser(demo.get_stream(), GameStateAnalyser::new())
|
||||||
.parse()
|
.parse()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let expected: GameState = serde_json::from_slice(
|
let expected: GameState = serde_json::from_slice(
|
||||||
fs::read(snapshot_file)
|
fs::read(format!("test_data/{}", snapshot_file))
|
||||||
.expect("Unable to read file")
|
.expect("Unable to read file")
|
||||||
.as_slice(),
|
.as_slice(),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue