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

proper baseline index type

This commit is contained in:
Robin Appelman 2024-04-07 16:09:14 +02:00
commit e0ec7db236
3 changed files with 111 additions and 39 deletions

View file

@ -1,4 +1,7 @@
use bitbuffer::{BitRead, BitReadSized, BitWrite, BitWriteSized, BitWriteStream, LittleEndian}; use bitbuffer::{
BitRead, BitReadSized, BitReadStream, BitWrite, BitWriteSized, BitWriteStream, Endianness,
LittleEndian,
};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr}; use serde_repr::{Deserialize_repr, Serialize_repr};
use std::borrow::Cow; use std::borrow::Cow;
@ -85,6 +88,57 @@ pub enum UpdateType {
Delete = 0b11, Delete = 0b11,
} }
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(Debug, Eq, PartialEq, Copy, Clone, Serialize_repr, Deserialize_repr, Default)]
#[repr(u8)]
pub enum BaselineIndex {
#[default]
First = 0,
Second = 1,
}
impl BaselineIndex {
pub fn other(self) -> Self {
match self {
BaselineIndex::First => BaselineIndex::Second,
BaselineIndex::Second => BaselineIndex::First,
}
}
}
impl From<bool> for BaselineIndex {
fn from(value: bool) -> Self {
match value {
false => BaselineIndex::First,
true => BaselineIndex::Second,
}
}
}
impl<E: Endianness> BitRead<'_, E> for BaselineIndex {
fn read(stream: &mut BitReadStream<'_, E>) -> ReadResult<Self> {
bool::read(stream).map(BaselineIndex::from)
}
unsafe fn read_unchecked(stream: &mut BitReadStream<'_, E>, end: bool) -> ReadResult<Self> {
bool::read_unchecked(stream, end).map(BaselineIndex::from)
}
fn bit_size() -> Option<usize> {
Some(1)
}
}
impl<E: Endianness> BitWrite<E> for BaselineIndex {
fn write(&self, stream: &mut BitWriteStream<E>) -> ReadResult<()> {
let val = match self {
BaselineIndex::First => false,
BaselineIndex::Second => true,
};
bool::write(&val, stream)
}
}
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PacketEntity { pub struct PacketEntity {
@ -96,7 +150,7 @@ pub struct PacketEntity {
pub serial_number: u32, pub serial_number: u32,
pub delay: Option<f32>, pub delay: Option<f32>,
pub delta: Option<ServerTick>, pub delta: Option<ServerTick>,
pub baseline_index: usize, pub baseline_index: BaselineIndex,
} }
impl fmt::Display for PacketEntity { impl fmt::Display for PacketEntity {
@ -244,7 +298,7 @@ pub struct PacketEntitiesMessage {
pub removed_entities: Vec<EntityId>, pub removed_entities: Vec<EntityId>,
pub max_entries: u16, pub max_entries: u16,
pub delta: Option<ServerTick>, pub delta: Option<ServerTick>,
pub base_line: u8, pub base_line: BaselineIndex,
pub updated_base_line: bool, pub updated_base_line: bool,
} }
@ -275,7 +329,7 @@ fn get_entity_for_update(
serial_number: 0, serial_number: 0,
delay: None, delay: None,
delta, delta,
baseline_index: 0, baseline_index: BaselineIndex::First,
}) })
} }
@ -283,7 +337,7 @@ impl Parse<'_> for PacketEntitiesMessage {
fn parse(stream: &mut Stream, state: &ParserState) -> Result<Self> { fn parse(stream: &mut Stream, state: &ParserState) -> Result<Self> {
let max_entries = stream.read_sized(11)?; let max_entries = stream.read_sized(11)?;
let delta: Option<ServerTick> = stream.read()?; let delta: Option<ServerTick> = stream.read()?;
let base_line = stream.read_sized(1)?; let base_line = stream.read()?;
let updated_entries: u16 = stream.read_sized(11)?; let updated_entries: u16 = stream.read_sized(11)?;
let length: u32 = stream.read_sized(20)?; let length: u32 = stream.read_sized(20)?;
let updated_base_line = stream.read()?; let updated_base_line = stream.read()?;
@ -306,7 +360,7 @@ impl Parse<'_> for PacketEntitiesMessage {
let update_type = data.read()?; let update_type = data.read()?;
if update_type == UpdateType::Enter { if update_type == UpdateType::Enter {
let mut entity = let mut entity =
Self::read_enter(&mut data, entity_index, state, base_line as usize, delta)?; Self::read_enter(&mut data, entity_index, state, base_line, delta)?;
let send_table = get_send_table(state, entity.server_class)?; let send_table = get_send_table(state, entity.server_class)?;
Self::read_update(&mut data, send_table, &mut entity.props, entity_index)?; Self::read_update(&mut data, send_table, &mut entity.props, entity_index)?;
@ -332,7 +386,7 @@ impl Parse<'_> for PacketEntitiesMessage {
serial_number: 0, serial_number: 0,
delay: None, delay: None,
delta, delta,
baseline_index: 0, baseline_index: BaselineIndex::First,
}); });
} }
} }
@ -361,7 +415,7 @@ impl Encode for PacketEntitiesMessage {
if let Some(delta) = self.delta { if let Some(delta) = self.delta {
delta.write(stream)?; delta.write(stream)?;
} }
self.base_line.write_sized(stream, 1)?; self.base_line.write(stream)?;
self.entities.len().write_sized(stream, 11)?; self.entities.len().write_sized(stream, 11)?;
stream.reserve_int(20, |stream| { stream.reserve_int(20, |stream| {
@ -411,7 +465,7 @@ impl PacketEntitiesMessage {
stream: &mut Stream, stream: &mut Stream,
entity_index: EntityId, entity_index: EntityId,
state: &ParserState, state: &ParserState,
baseline_index: usize, baseline_index: BaselineIndex,
delta: Option<ServerTick>, delta: Option<ServerTick>,
) -> Result<PacketEntity> { ) -> Result<PacketEntity> {
let bits = log_base2(state.server_classes.len()) + 1; let bits = log_base2(state.server_classes.len()) + 1;
@ -600,7 +654,7 @@ fn test_packet_entitier_message_roundtrip() {
removed_entities: vec![], removed_entities: vec![],
max_entries: 0, max_entries: 0,
delta: None, delta: None,
base_line: 0, base_line: BaselineIndex::First,
updated_base_line: false, updated_base_line: false,
}, },
&state, &state,
@ -616,12 +670,12 @@ fn test_packet_entitier_message_roundtrip() {
serial_number: 0, serial_number: 0,
delay: None, delay: None,
delta: None, delta: None,
baseline_index: 0, baseline_index: BaselineIndex::First,
}], }],
removed_entities: vec![], removed_entities: vec![],
max_entries: 4, max_entries: 4,
delta: None, delta: None,
base_line: 0, base_line: BaselineIndex::First,
updated_base_line: false, updated_base_line: false,
}, },
&state, &state,
@ -638,7 +692,7 @@ fn test_packet_entitier_message_roundtrip() {
serial_number: 0, serial_number: 0,
delay: None, delay: None,
delta: None, delta: None,
baseline_index: 0, baseline_index: BaselineIndex::First,
}, },
PacketEntity { PacketEntity {
server_class: ClassId::from(1), server_class: ClassId::from(1),
@ -660,13 +714,13 @@ fn test_packet_entitier_message_roundtrip() {
serial_number: 0, serial_number: 0,
delay: None, delay: None,
delta: None, delta: None,
baseline_index: 0, baseline_index: BaselineIndex::First,
}, },
PacketEntity { PacketEntity {
server_class: ClassId::from(1), server_class: ClassId::from(1),
entity_index: EntityId::from(5u32), entity_index: EntityId::from(5u32),
delta: None, delta: None,
baseline_index: 0, baseline_index: BaselineIndex::First,
props: vec![ props: vec![
SendProp { SendProp {
index: 0, index: 0,
@ -688,7 +742,7 @@ fn test_packet_entitier_message_roundtrip() {
removed_entities: vec![], removed_entities: vec![],
max_entries: 4, max_entries: 4,
delta: None, delta: None,
base_line: 0, base_line: BaselineIndex::First,
updated_base_line: false, updated_base_line: false,
}, },
&state, &state,

View file

@ -1,5 +1,5 @@
use bitbuffer::{ use bitbuffer::{
BitReadBuffer, BitReadStream, BitWrite, BitWriteSized, BitWriteStream, LittleEndian, BitError, BitReadBuffer, BitReadStream, BitWrite, BitWriteSized, BitWriteStream, LittleEndian,
}; };
use num_traits::{PrimInt, Unsigned}; use num_traits::{PrimInt, Unsigned};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};

View file

@ -5,7 +5,7 @@ use std::collections::HashMap;
use crate::demo::gamevent::GameEventDefinition; use crate::demo::gamevent::GameEventDefinition;
use crate::demo::message::packetentities::{ use crate::demo::message::packetentities::{
EntityId, PacketEntitiesMessage, PacketEntity, UpdateType, BaselineIndex, EntityId, PacketEntitiesMessage, PacketEntity, UpdateType,
}; };
use crate::demo::message::stringtable::StringTableMeta; use crate::demo::message::stringtable::StringTableMeta;
use crate::demo::message::{Message, MessageType}; use crate::demo::message::{Message, MessageType};
@ -130,15 +130,29 @@ impl<'a> ParserState {
// }) // })
} }
fn get_instance_baseline(&self, index: BaselineIndex) -> &Baseline {
match index {
BaselineIndex::First => &self.instance_baselines[0],
BaselineIndex::Second => &self.instance_baselines[1],
}
}
fn get_instance_baseline_mut(&mut self, index: BaselineIndex) -> &mut Baseline {
match index {
BaselineIndex::First => &mut self.instance_baselines[0],
BaselineIndex::Second => &mut self.instance_baselines[1],
}
}
pub fn get_baseline( pub fn get_baseline(
&self, &self,
baseline_index: usize, baseline_index: BaselineIndex,
entity_index: EntityId, entity_index: EntityId,
class_id: ClassId, class_id: ClassId,
send_table: &SendTable, send_table: &SendTable,
is_delta: bool, is_delta: bool,
) -> Result<Cow<[SendProp]>> { ) -> Result<Cow<[SendProp]>> {
match self.instance_baselines[baseline_index].get(entity_index) { match self.get_instance_baseline(baseline_index).get(entity_index) {
Some(baseline) if baseline.server_class == class_id && is_delta => { Some(baseline) if baseline.server_class == class_id && is_delta => {
Ok(Cow::Borrowed(&baseline.props)) Ok(Cow::Borrowed(&baseline.props))
} }
@ -245,10 +259,10 @@ impl<'a> ParserState {
} }
if ent_message.updated_base_line { if ent_message.updated_base_line {
let old_index = ent_message.base_line as usize; let old_index = ent_message.base_line;
let new_index = 1 - old_index; let new_index = old_index.other();
let [baseline1, baseline2] = &mut self.instance_baselines; let [baseline1, baseline2] = &mut self.instance_baselines;
if old_index == 0 { if old_index == BaselineIndex::First {
baseline2.copy_from(baseline1); baseline2.copy_from(baseline1);
} else { } else {
baseline1.copy_from(baseline2); baseline1.copy_from(baseline2);
@ -256,19 +270,22 @@ impl<'a> ParserState {
for entity in ent_message.entities { for entity in ent_message.entities {
if entity.update_type == UpdateType::Enter { if entity.update_type == UpdateType::Enter {
let updated_baseline = let updated_baseline = match self
match self.instance_baselines[old_index].get(entity.entity_index) { .get_instance_baseline(old_index)
Some(baseline_entity) .get(entity.entity_index)
if baseline_entity.server_class == entity.server_class {
&& ent_message.delta.is_some() => Some(baseline_entity)
{ if baseline_entity.server_class == entity.server_class
let mut updated_baseline = baseline_entity.clone(); && ent_message.delta.is_some() =>
updated_baseline.apply_update(&entity.props); {
updated_baseline let mut updated_baseline = baseline_entity.clone();
} updated_baseline.apply_update(&entity.props);
_ => entity.into(), updated_baseline
}; }
self.instance_baselines[new_index].set(updated_baseline); _ => entity.into(),
};
self.get_instance_baseline_mut(new_index)
.set(updated_baseline);
} }
} }
} }
@ -324,8 +341,9 @@ impl Baseline {
} }
fn set(&mut self, entity: BaselineEntity) { fn set(&mut self, entity: BaselineEntity) {
let index = entity.entity_id; if let Some(instance) = self.instances.get_mut(usize::from(entity.entity_id)) {
self.instances[usize::from(index)] = Some(entity); *instance = Some(entity);
}
} }
pub fn keys(&self) -> impl Iterator<Item = EntityId> + '_ { pub fn keys(&self) -> impl Iterator<Item = EntityId> + '_ {
@ -401,7 +419,7 @@ impl From<BaselineEntity> for PacketEntity {
serial_number: baseline.serial, serial_number: baseline.serial,
delay: None, delay: None,
delta: None, delta: None,
baseline_index: 0, baseline_index: BaselineIndex::First,
} }
} }
} }