mirror of
https://codeberg.org/demostf/parser.git
synced 2026-06-03 10:14:06 +02:00
parse and encode tempentities
This commit is contained in:
parent
3055242fd9
commit
5c10c9e6ae
4 changed files with 126 additions and 30 deletions
|
|
@ -85,7 +85,7 @@ pub enum Message<'a> {
|
||||||
EntityMessage(EntityMessage<'a>),
|
EntityMessage(EntityMessage<'a>),
|
||||||
GameEvent(GameEventMessage),
|
GameEvent(GameEventMessage),
|
||||||
PacketEntities(PacketEntitiesMessage),
|
PacketEntities(PacketEntitiesMessage),
|
||||||
TempEntities(TempEntitiesMessage<'a>),
|
TempEntities(TempEntitiesMessage),
|
||||||
PreFetch(PreFetchMessage),
|
PreFetch(PreFetchMessage),
|
||||||
Menu(MenuMessage<'a>),
|
Menu(MenuMessage<'a>),
|
||||||
GameEventList(GameEventListMessage),
|
GameEventList(GameEventListMessage),
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ pub struct PacketEntity {
|
||||||
pub in_pvs: bool,
|
pub in_pvs: bool,
|
||||||
pub pvs: PVS,
|
pub pvs: PVS,
|
||||||
pub serial_number: u32,
|
pub serial_number: u32,
|
||||||
pub delay: Option<u32>,
|
pub delay: Option<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for PacketEntity {
|
impl fmt::Display for PacketEntity {
|
||||||
|
|
@ -414,7 +414,7 @@ impl PacketEntitiesMessage {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_update<'a, Props: IntoIterator<Item = &'a SendProp>>(
|
pub fn write_update<'a, Props: IntoIterator<Item = &'a SendProp>>(
|
||||||
props: Props,
|
props: Props,
|
||||||
stream: &mut BitWriteStream<LittleEndian>,
|
stream: &mut BitWriteStream<LittleEndian>,
|
||||||
send_table: &SendTable,
|
send_table: &SendTable,
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,30 @@
|
||||||
use crate::{Parse, ParserState, ReadResult, Stream};
|
|
||||||
|
|
||||||
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::packetentities::PacketEntitiesMessage;
|
||||||
use crate::demo::parser::ParseBitSkip;
|
use crate::demo::message::stringtable::{log_base2, write_var_int};
|
||||||
|
use crate::demo::packet::datatable::ClassId;
|
||||||
|
use crate::demo::parser::{Encode, ParseBitSkip};
|
||||||
|
use crate::demo::sendprop::SendProp;
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
use bitbuffer::{BitWrite, BitWriteStream, LittleEndian};
|
use crate::{Parse, ParseError, ParserState, Stream};
|
||||||
|
use bitbuffer::{
|
||||||
|
BitReadBuffer, BitReadStream, BitWrite, BitWriteSized, BitWriteStream, LittleEndian,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct TempEntitiesMessage<'a> {
|
pub struct TempEntitiesMessage {
|
||||||
pub count: u8,
|
pub events: Vec<EventInfo>,
|
||||||
pub data: Stream<'a>,
|
|
||||||
pub entities: Vec<PacketEntity>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Parse<'a> for TempEntitiesMessage<'a> {
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
fn parse(stream: &mut Stream<'a>, state: &ParserState) -> Result<Self> {
|
pub struct EventInfo {
|
||||||
|
pub class_id: ClassId,
|
||||||
|
pub fire_delay: f32,
|
||||||
|
pub reliable: bool,
|
||||||
|
pub props: Vec<SendProp>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse<'_> for TempEntitiesMessage {
|
||||||
|
fn parse(stream: &mut Stream, state: &ParserState) -> Result<Self> {
|
||||||
let count: u8 = stream.read()?;
|
let count: u8 = stream.read()?;
|
||||||
let length = if state.protocol_version > 23 {
|
let length = if state.protocol_version > 23 {
|
||||||
read_var_int(stream)?
|
read_var_int(stream)?
|
||||||
|
|
@ -23,17 +32,57 @@ impl<'a> Parse<'a> for TempEntitiesMessage<'a> {
|
||||||
stream.read_sized(17)?
|
stream.read_sized(17)?
|
||||||
};
|
};
|
||||||
let data = stream.read_bits(length as usize)?;
|
let data = stream.read_bits(length as usize)?;
|
||||||
|
let mut stream = data.clone();
|
||||||
|
let stream = &mut stream;
|
||||||
|
|
||||||
Ok(TempEntitiesMessage {
|
let (count, reliable) = if count == 0 {
|
||||||
count,
|
(1, true)
|
||||||
data,
|
} else {
|
||||||
entities: Vec::new(),
|
(count, false)
|
||||||
})
|
};
|
||||||
|
|
||||||
|
let mut events: Vec<EventInfo> = Vec::with_capacity(count as usize);
|
||||||
|
|
||||||
|
for _ in 0..count {
|
||||||
|
let delay = if stream.read()? {
|
||||||
|
let raw: u8 = stream.read()?;
|
||||||
|
raw as f32 / 100.0
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
};
|
||||||
|
|
||||||
|
let class_id = if stream.read()? {
|
||||||
|
let bits = log_base2(state.server_classes.len()) + 1;
|
||||||
|
(stream.read_sized::<u16>(bits as usize)? - 1).into()
|
||||||
|
} else {
|
||||||
|
let last = events.last().ok_or(ParseError::InvalidDemo(
|
||||||
|
"temp entity update without previous",
|
||||||
|
))?;
|
||||||
|
|
||||||
|
last.class_id
|
||||||
|
};
|
||||||
|
let send_table = state
|
||||||
|
.send_tables
|
||||||
|
.get(usize::from(class_id))
|
||||||
|
.ok_or(ParseError::UnknownServerClass(class_id))?;
|
||||||
|
|
||||||
|
let mut props = Vec::new();
|
||||||
|
PacketEntitiesMessage::read_update(stream, send_table, &mut props)?;
|
||||||
|
|
||||||
|
events.push(EventInfo {
|
||||||
|
class_id,
|
||||||
|
fire_delay: delay,
|
||||||
|
reliable,
|
||||||
|
props,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(TempEntitiesMessage { events })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ParseBitSkip<'a> for TempEntitiesMessage<'a> {
|
impl ParseBitSkip<'_> for TempEntitiesMessage {
|
||||||
fn parse_skip(stream: &mut Stream<'a>, state: &ParserState) -> Result<()> {
|
fn parse_skip(stream: &mut Stream, state: &ParserState) -> Result<()> {
|
||||||
let _: u8 = stream.read()?;
|
let _: u8 = stream.read()?;
|
||||||
let length = if state.protocol_version > 23 {
|
let length = if state.protocol_version > 23 {
|
||||||
read_var_int(stream)?
|
read_var_int(stream)?
|
||||||
|
|
@ -45,13 +94,54 @@ impl<'a> ParseBitSkip<'a> for TempEntitiesMessage<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BitWrite<LittleEndian> for TempEntitiesMessage<'_> {
|
impl Encode for TempEntitiesMessage {
|
||||||
fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
|
fn encode(&self, stream: &mut BitWriteStream<LittleEndian>, state: &ParserState) -> Result<()> {
|
||||||
if !self.entities.is_empty() {
|
let count = if self.events.len() == 1 {
|
||||||
todo!();
|
if self.events[0].reliable {
|
||||||
}
|
0
|
||||||
self.count.write(stream)?;
|
} else {
|
||||||
write_var_int(self.data.bit_len() as u32, stream)?;
|
1
|
||||||
self.data.write(stream)
|
}
|
||||||
|
} else {
|
||||||
|
self.events.len() as u8
|
||||||
|
};
|
||||||
|
count.write(stream)?;
|
||||||
|
|
||||||
|
let mut out = Vec::with_capacity(self.events.len() * 16);
|
||||||
|
let bits = {
|
||||||
|
let mut write = BitWriteStream::new(&mut out, LittleEndian);
|
||||||
|
let mut last_class_id = u16::MAX.into();
|
||||||
|
|
||||||
|
for event in self.events.iter() {
|
||||||
|
if event.fire_delay > 0.0 {
|
||||||
|
true.write(&mut write)?;
|
||||||
|
((event.fire_delay * 100.0) as u8).write(&mut write)?;
|
||||||
|
} else {
|
||||||
|
false.write(&mut write)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if event.class_id != last_class_id {
|
||||||
|
true.write(&mut write)?;
|
||||||
|
let bits = log_base2(state.server_classes.len()) + 1;
|
||||||
|
let id: u16 = event.class_id.into();
|
||||||
|
(id + 1).write_sized(&mut write, bits as usize)?;
|
||||||
|
} else {
|
||||||
|
false.write(&mut write)?;
|
||||||
|
}
|
||||||
|
last_class_id = event.class_id;
|
||||||
|
|
||||||
|
let send_table = state
|
||||||
|
.send_tables
|
||||||
|
.get(usize::from(event.class_id))
|
||||||
|
.ok_or(ParseError::UnknownServerClass(event.class_id))?;
|
||||||
|
PacketEntitiesMessage::write_update(&event.props, &mut write, send_table)?;
|
||||||
|
}
|
||||||
|
write.bit_len()
|
||||||
|
};
|
||||||
|
let mut data = BitReadStream::new(BitReadBuffer::new(&out, LittleEndian));
|
||||||
|
|
||||||
|
write_var_int(bits as u32, stream)?;
|
||||||
|
data.read_bits(bits)?.write(stream)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,12 @@ impl From<ClassId> for usize {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<ClassId> for u16 {
|
||||||
|
fn from(class: ClassId) -> Self {
|
||||||
|
class.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(BitRead, BitWrite, PartialEq, Eq, Hash, Debug, Serialize, Deserialize, Clone, Display)]
|
#[derive(BitRead, BitWrite, PartialEq, Eq, Hash, Debug, Serialize, Deserialize, Clone, Display)]
|
||||||
pub struct ServerClassName(String);
|
pub struct ServerClassName(String);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue