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:
parent
a7a8318083
commit
e0ec7db236
3 changed files with 111 additions and 39 deletions
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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};
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue