mirror of
https://codeberg.org/demostf/parser.git
synced 2026-06-03 18:24:05 +02:00
some write progress
This commit is contained in:
parent
67a4ca5744
commit
9a9bcdc9df
18 changed files with 286 additions and 90 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
|
@ -80,8 +80,6 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitbuffer"
|
name = "bitbuffer"
|
||||||
version = "0.8.1"
|
version = "0.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3ec331c3602bf9f2fde16a85cb3ddf13219f9653ee55c18948ff4418c85cfbb0"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitbuffer_derive",
|
"bitbuffer_derive",
|
||||||
"err-derive 0.2.4",
|
"err-derive 0.2.4",
|
||||||
|
|
@ -92,8 +90,6 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitbuffer_derive"
|
name = "bitbuffer_derive"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7f51dcbe693d21078994abd2afac5adc9bcc80fbdf80206ebdb33fec4a145693"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ name = "loop"
|
||||||
path = "src/bin/loop.rs"
|
path = "src/bin/loop.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitbuffer = "0.8.1"
|
bitbuffer = { version = "0.8", path = "../../bitbuffer" }
|
||||||
num_enum = "0.5"
|
num_enum = "0.5"
|
||||||
num-traits = "0.2"
|
num-traits = "0.2"
|
||||||
enumflags2 = "0.7"
|
enumflags2 = "0.7"
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use bitbuffer::BitRead;
|
use bitbuffer::{BitRead, BitWrite};
|
||||||
|
|
||||||
use crate::{ParseError, Result};
|
use crate::{ParseError, Result};
|
||||||
|
|
||||||
|
|
@ -41,7 +41,7 @@ pub struct GameEventEntry {
|
||||||
pub kind: GameEventValueType,
|
pub kind: GameEventValueType,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, Debug, Clone, Copy, PartialEq, Display)]
|
#[derive(BitRead, BitWrite, Debug, Clone, Copy, PartialEq, Display)]
|
||||||
#[discriminant_bits = 3]
|
#[discriminant_bits = 3]
|
||||||
pub enum GameEventValueType {
|
pub enum GameEventValueType {
|
||||||
None = 0,
|
None = 0,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use bitbuffer::BitRead;
|
use bitbuffer::{BitRead, BitWrite};
|
||||||
|
|
||||||
#[derive(BitRead, Debug, PartialEq)]
|
#[derive(BitRead, BitWrite, Debug, PartialEq)]
|
||||||
pub struct Header {
|
pub struct Header {
|
||||||
#[size = 8]
|
#[size = 8]
|
||||||
pub demo_type: String,
|
pub demo_type: String,
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
use bitbuffer::{BitRead, LittleEndian};
|
use bitbuffer::{BitRead, BitWrite, BitWriteSized, BitWriteStream, LittleEndian};
|
||||||
|
|
||||||
use crate::demo::sendprop::read_bit_coord;
|
use crate::demo::sendprop::{read_bit_coord, write_bit_coord};
|
||||||
use crate::demo::vector::Vector;
|
use crate::demo::vector::Vector;
|
||||||
use crate::{ReadResult, Stream};
|
use crate::{ReadResult, Stream};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct BSPDecalMessage {
|
pub struct BSPDecalMessage {
|
||||||
pub position: Vector,
|
pub position: Vector,
|
||||||
pub texture_index: u16,
|
pub texture_index: u16,
|
||||||
|
|
@ -16,9 +16,7 @@ pub struct BSPDecalMessage {
|
||||||
impl BitRead<'_, LittleEndian> for BSPDecalMessage {
|
impl BitRead<'_, LittleEndian> for BSPDecalMessage {
|
||||||
fn read(stream: &mut Stream) -> ReadResult<Self> {
|
fn read(stream: &mut Stream) -> ReadResult<Self> {
|
||||||
let position = {
|
let position = {
|
||||||
let has_x = stream.read()?;
|
let (has_x, has_y, has_z) = stream.read()?;
|
||||||
let has_y = stream.read()?;
|
|
||||||
let has_z = stream.read()?;
|
|
||||||
|
|
||||||
Vector {
|
Vector {
|
||||||
x: if has_x { read_bit_coord(stream)? } else { 0f32 },
|
x: if has_x { read_bit_coord(stream)? } else { 0f32 },
|
||||||
|
|
@ -44,3 +42,55 @@ impl BitRead<'_, LittleEndian> for BSPDecalMessage {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BitWrite<LittleEndian> for BSPDecalMessage {
|
||||||
|
fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
|
||||||
|
let has_x = self.position.x != 0.0;
|
||||||
|
let has_y = self.position.y != 0.0;
|
||||||
|
let has_z = self.position.z != 0.0;
|
||||||
|
(has_x, has_y, has_z).write(stream)?;
|
||||||
|
|
||||||
|
if has_x {
|
||||||
|
write_bit_coord(self.position.x, stream)?;
|
||||||
|
}
|
||||||
|
if has_y {
|
||||||
|
write_bit_coord(self.position.y, stream)?;
|
||||||
|
}
|
||||||
|
if has_z {
|
||||||
|
write_bit_coord(self.position.z, stream)?;
|
||||||
|
}
|
||||||
|
self.texture_index.write_sized(stream, 9)?;
|
||||||
|
if self.ent_index != 0 || self.model_index != 0 {
|
||||||
|
true.write(stream)?;
|
||||||
|
self.ent_index.write_sized(stream, 12)?;
|
||||||
|
self.model_index.write_sized(stream, 12)?;
|
||||||
|
} else {
|
||||||
|
false.write(stream)?;
|
||||||
|
}
|
||||||
|
self.low_priority.write(stream)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_decal_roundtrip() {
|
||||||
|
crate::test_roundtrip_encode(BSPDecalMessage {
|
||||||
|
position: Vector::default(),
|
||||||
|
texture_index: 0,
|
||||||
|
ent_index: 0,
|
||||||
|
model_index: 0,
|
||||||
|
low_priority: false,
|
||||||
|
});
|
||||||
|
crate::test_roundtrip_encode(BSPDecalMessage {
|
||||||
|
position: Vector {
|
||||||
|
x: 1.0,
|
||||||
|
y: 0.5,
|
||||||
|
z: 0.0,
|
||||||
|
},
|
||||||
|
texture_index: 12,
|
||||||
|
ent_index: 15,
|
||||||
|
model_index: 2,
|
||||||
|
low_priority: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,38 +1,38 @@
|
||||||
use crate::Stream;
|
use crate::Stream;
|
||||||
/// Messages that consists only of primitives and string and can be derived
|
/// Messages that consists only of primitives and string and can be derived
|
||||||
use bitbuffer::{BitRead, LittleEndian};
|
use bitbuffer::{BitRead, BitWrite, LittleEndian};
|
||||||
|
|
||||||
#[derive(BitRead, Debug)]
|
#[derive(BitRead, BitWrite, Debug)]
|
||||||
pub struct FileMessage {
|
pub struct FileMessage {
|
||||||
pub transfer_id: u32,
|
pub transfer_id: u32,
|
||||||
pub file_name: String,
|
pub file_name: String,
|
||||||
pub requested: bool,
|
pub requested: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, Debug)]
|
#[derive(BitRead, BitWrite, Debug)]
|
||||||
pub struct NetTickMessage {
|
pub struct NetTickMessage {
|
||||||
pub tick: u32,
|
pub tick: u32,
|
||||||
pub frame_time: u16,
|
pub frame_time: u16,
|
||||||
pub std_dev: u16,
|
pub std_dev: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, Debug)]
|
#[derive(BitRead, BitWrite, Debug)]
|
||||||
pub struct StringCmdMessage {
|
pub struct StringCmdMessage {
|
||||||
pub command: String,
|
pub command: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, Debug)]
|
#[derive(BitRead, BitWrite, Debug)]
|
||||||
pub struct SigOnStateMessage {
|
pub struct SigOnStateMessage {
|
||||||
pub state: u8,
|
pub state: u8,
|
||||||
pub count: u32,
|
pub count: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, Debug)]
|
#[derive(BitRead, BitWrite, Debug)]
|
||||||
pub struct PrintMessage {
|
pub struct PrintMessage {
|
||||||
pub value: String,
|
pub value: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, Debug)]
|
#[derive(BitRead, BitWrite, Debug)]
|
||||||
pub struct ServerInfoMessage {
|
pub struct ServerInfoMessage {
|
||||||
pub version: u16,
|
pub version: u16,
|
||||||
pub server_count: u32,
|
pub server_count: u32,
|
||||||
|
|
@ -53,18 +53,18 @@ pub struct ServerInfoMessage {
|
||||||
pub replay: bool,
|
pub replay: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, Debug)]
|
#[derive(BitRead, BitWrite, Debug)]
|
||||||
pub struct SetPauseMessage {
|
pub struct SetPauseMessage {
|
||||||
pub pause: bool,
|
pub pause: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, Debug)]
|
#[derive(BitRead, BitWrite, Debug)]
|
||||||
pub struct SetViewMessage {
|
pub struct SetViewMessage {
|
||||||
#[size = 11]
|
#[size = 11]
|
||||||
pub index: u16,
|
pub index: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, Debug)]
|
#[derive(BitRead, BitWrite, Debug)]
|
||||||
pub struct FixAngleMessage {
|
pub struct FixAngleMessage {
|
||||||
pub relative: bool,
|
pub relative: bool,
|
||||||
pub x: u16,
|
pub x: u16,
|
||||||
|
|
@ -72,7 +72,7 @@ pub struct FixAngleMessage {
|
||||||
pub z: u16,
|
pub z: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, Debug)]
|
#[derive(BitRead, BitWrite, Debug)]
|
||||||
#[endianness = "LittleEndian"]
|
#[endianness = "LittleEndian"]
|
||||||
pub struct EntityMessage<'a> {
|
pub struct EntityMessage<'a> {
|
||||||
#[size = 11]
|
#[size = 11]
|
||||||
|
|
@ -85,13 +85,13 @@ pub struct EntityMessage<'a> {
|
||||||
pub data: Stream<'a>,
|
pub data: Stream<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, Debug)]
|
#[derive(BitRead, BitWrite, Debug)]
|
||||||
pub struct PreFetchMessage {
|
pub struct PreFetchMessage {
|
||||||
#[size = 14]
|
#[size = 14]
|
||||||
pub index: u16,
|
pub index: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, Debug)]
|
#[derive(BitRead, BitWrite, Debug)]
|
||||||
#[endianness = "LittleEndian"]
|
#[endianness = "LittleEndian"]
|
||||||
pub struct MenuMessage<'a> {
|
pub struct MenuMessage<'a> {
|
||||||
pub kind: u16,
|
pub kind: u16,
|
||||||
|
|
@ -100,13 +100,13 @@ pub struct MenuMessage<'a> {
|
||||||
pub index: Stream<'a>,
|
pub index: Stream<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, Debug)]
|
#[derive(BitRead, BitWrite, Debug)]
|
||||||
pub struct GetCvarValueMessage {
|
pub struct GetCvarValueMessage {
|
||||||
pub cookie: u32,
|
pub cookie: u32,
|
||||||
pub value: String,
|
pub value: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, Debug)]
|
#[derive(BitRead, BitWrite, Debug)]
|
||||||
#[endianness = "LittleEndian"]
|
#[endianness = "LittleEndian"]
|
||||||
pub struct CmdKeyValuesMessage<'a> {
|
pub struct CmdKeyValuesMessage<'a> {
|
||||||
pub length: u32,
|
pub length: u32,
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
use bitbuffer::{BitRead, LittleEndian};
|
use bitbuffer::{BitRead, BitWrite, BitWriteStream, LittleEndian};
|
||||||
|
|
||||||
use crate::{ReadResult, Stream};
|
use crate::{ReadResult, Stream};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct VoiceInitMessage {
|
pub struct VoiceInitMessage {
|
||||||
codec: String,
|
codec: String,
|
||||||
quality: u8,
|
quality: u8,
|
||||||
|
|
@ -30,7 +30,34 @@ impl BitRead<'_, LittleEndian> for VoiceInitMessage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, Debug, Clone)]
|
impl BitWrite<LittleEndian> for VoiceInitMessage {
|
||||||
|
fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
|
||||||
|
self.codec.write(stream)?;
|
||||||
|
self.quality.write(stream)?;
|
||||||
|
|
||||||
|
if self.quality == 255 {
|
||||||
|
self.sampling_rate.write(stream)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_voice_init_roundtrip() {
|
||||||
|
crate::test_roundtrip_encode(VoiceInitMessage {
|
||||||
|
codec: "foo".into(),
|
||||||
|
quality: 0,
|
||||||
|
sampling_rate: 0,
|
||||||
|
});
|
||||||
|
crate::test_roundtrip_encode(VoiceInitMessage {
|
||||||
|
codec: "foo".into(),
|
||||||
|
quality: 255,
|
||||||
|
sampling_rate: 12,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(BitRead, BitWrite, Debug, Clone)]
|
||||||
#[endianness = "LittleEndian"]
|
#[endianness = "LittleEndian"]
|
||||||
pub struct VoiceDataMessage<'a> {
|
pub struct VoiceDataMessage<'a> {
|
||||||
client: u8,
|
client: u8,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use bitbuffer::{BitRead, LittleEndian};
|
use bitbuffer::{BitRead, BitWrite, BitWriteSized, LittleEndian};
|
||||||
|
|
||||||
use crate::{ReadResult, Stream};
|
use crate::{ReadResult, Stream};
|
||||||
|
|
||||||
|
|
@ -17,3 +17,13 @@ impl BitRead<'_, LittleEndian> for ConsoleCmdPacket {
|
||||||
Ok(ConsoleCmdPacket { tick, command })
|
Ok(ConsoleCmdPacket { tick, command })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BitWrite<LittleEndian> for ConsoleCmdPacket {
|
||||||
|
fn write(&self, stream: &mut bitbuffer::BitWriteStream<LittleEndian>) -> ReadResult<()> {
|
||||||
|
self.tick.write(stream)?;
|
||||||
|
let len = self.command.len() as u32;
|
||||||
|
len.write(stream)?;
|
||||||
|
self.command.write_sized(stream, len as usize)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use bitbuffer::BitRead;
|
use bitbuffer::{BitRead, BitWrite};
|
||||||
|
|
||||||
use crate::demo::parser::MalformedSendPropDefinitionError;
|
use crate::demo::parser::MalformedSendPropDefinitionError;
|
||||||
use crate::demo::sendprop::{
|
use crate::demo::sendprop::{
|
||||||
|
|
@ -11,9 +11,10 @@ use serde::{Deserialize, Serialize};
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
|
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
#[derive(BitRead, Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Display, FromStr)]
|
#[derive(
|
||||||
|
BitRead, BitWrite, Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Display, FromStr,
|
||||||
|
)]
|
||||||
pub struct ClassId(u16);
|
pub struct ClassId(u16);
|
||||||
|
|
||||||
impl From<u16> for ClassId {
|
impl From<u16> for ClassId {
|
||||||
|
|
@ -28,8 +29,8 @@ impl From<ClassId> for usize {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, PartialEq, Eq, Hash, Debug, Serialize, Deserialize, Clone, Display)]
|
#[derive(BitRead, BitWrite, PartialEq, Eq, Hash, Debug, Serialize, Deserialize, Clone, Display)]
|
||||||
pub struct ServerClassName(Rc<String>);
|
pub struct ServerClassName(String);
|
||||||
|
|
||||||
impl ServerClassName {
|
impl ServerClassName {
|
||||||
pub fn as_str(&self) -> &str {
|
pub fn as_str(&self) -> &str {
|
||||||
|
|
@ -39,11 +40,11 @@ impl ServerClassName {
|
||||||
|
|
||||||
impl From<String> for ServerClassName {
|
impl From<String> for ServerClassName {
|
||||||
fn from(value: String) -> Self {
|
fn from(value: String) -> Self {
|
||||||
Self(Rc::new(value))
|
Self(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, Debug, Clone)]
|
#[derive(BitRead, BitWrite, Debug, Clone)]
|
||||||
pub struct ServerClass {
|
pub struct ServerClass {
|
||||||
pub id: ClassId,
|
pub id: ClassId,
|
||||||
pub name: ServerClassName,
|
pub name: ServerClassName,
|
||||||
|
|
@ -52,6 +53,7 @@ pub struct ServerClass {
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
BitRead,
|
BitRead,
|
||||||
|
BitWrite,
|
||||||
PartialEq,
|
PartialEq,
|
||||||
Eq,
|
Eq,
|
||||||
Hash,
|
Hash,
|
||||||
|
|
@ -64,7 +66,7 @@ pub struct ServerClass {
|
||||||
Ord,
|
Ord,
|
||||||
Default,
|
Default,
|
||||||
)]
|
)]
|
||||||
pub struct SendTableName(Rc<String>);
|
pub struct SendTableName(String);
|
||||||
|
|
||||||
impl SendTableName {
|
impl SendTableName {
|
||||||
pub fn as_str(&self) -> &str {
|
pub fn as_str(&self) -> &str {
|
||||||
|
|
@ -74,7 +76,7 @@ impl SendTableName {
|
||||||
|
|
||||||
impl From<String> for SendTableName {
|
impl From<String> for SendTableName {
|
||||||
fn from(value: String) -> Self {
|
fn from(value: String) -> Self {
|
||||||
Self(Rc::new(value))
|
Self(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
use bitbuffer::{bit_size_of, BitRead, Endianness, LazyBitRead, LittleEndian};
|
use bitbuffer::{bit_size_of, BitRead, BitWrite, Endianness, LazyBitRead, LittleEndian};
|
||||||
|
|
||||||
use crate::demo::message::{Message, MessageType};
|
use crate::demo::message::{Message, MessageType};
|
||||||
use crate::demo::vector::Vector;
|
use crate::demo::vector::Vector;
|
||||||
use crate::{Parse, ParserState, ReadResult, Result, Stream};
|
use crate::{Parse, ParserState, ReadResult, Result, Stream};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Debug, BitRead)]
|
#[derive(Debug, BitRead, BitWrite)]
|
||||||
pub struct MessagePacketMeta {
|
pub struct MessagePacketMeta {
|
||||||
pub flags: u32, // TODO
|
pub flags: u32, // TODO
|
||||||
pub view_angles: ViewAngles,
|
pub view_angles: ViewAngles,
|
||||||
|
|
@ -20,7 +20,7 @@ pub struct MessagePacket<'a> {
|
||||||
pub meta: LazyBitRead<'a, MessagePacketMeta, LittleEndian>,
|
pub meta: LazyBitRead<'a, MessagePacketMeta, LittleEndian>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct ViewAngles {
|
pub struct ViewAngles {
|
||||||
pub origin: (Vector, Vector),
|
pub origin: (Vector, Vector),
|
||||||
pub angles: (Vector, Vector),
|
pub angles: (Vector, Vector),
|
||||||
|
|
@ -29,12 +29,10 @@ pub struct ViewAngles {
|
||||||
|
|
||||||
impl<E: Endianness> BitRead<'_, E> for ViewAngles {
|
impl<E: Endianness> BitRead<'_, E> for ViewAngles {
|
||||||
fn read(stream: &mut bitbuffer::BitReadStream<E>) -> ReadResult<Self> {
|
fn read(stream: &mut bitbuffer::BitReadStream<E>) -> ReadResult<Self> {
|
||||||
let view_origin_1 = Vector::read(stream)?;
|
let vectors = <[Vector; 6]>::read(stream)?;
|
||||||
let view_angle_1 = Vector::read(stream)?;
|
let origin = (vectors[3], vectors[0]);
|
||||||
let local_view_angle_1 = Vector::read(stream)?;
|
let angles = (vectors[4], vectors[1]);
|
||||||
let origin = (Vector::read(stream)?, view_origin_1);
|
let local_angles = (vectors[5], vectors[2]);
|
||||||
let angles = (Vector::read(stream)?, view_angle_1);
|
|
||||||
let local_angles = (Vector::read(stream)?, local_view_angle_1);
|
|
||||||
Ok(ViewAngles {
|
Ok(ViewAngles {
|
||||||
origin,
|
origin,
|
||||||
angles,
|
angles,
|
||||||
|
|
@ -47,6 +45,67 @@ impl<E: Endianness> BitRead<'_, E> for ViewAngles {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<E: Endianness> BitWrite<E> for ViewAngles {
|
||||||
|
fn write(&self, stream: &mut bitbuffer::BitWriteStream<E>) -> ReadResult<()> {
|
||||||
|
[
|
||||||
|
self.origin.1,
|
||||||
|
self.angles.1,
|
||||||
|
self.local_angles.1,
|
||||||
|
self.origin.0,
|
||||||
|
self.angles.0,
|
||||||
|
self.local_angles.0,
|
||||||
|
]
|
||||||
|
.write(stream)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_view_angles_roundtrip() {
|
||||||
|
crate::test_roundtrip_encode(ViewAngles {
|
||||||
|
origin: (Vector::default(), Vector::default()),
|
||||||
|
angles: (Vector::default(), Vector::default()),
|
||||||
|
local_angles: (Vector::default(), Vector::default()),
|
||||||
|
});
|
||||||
|
crate::test_roundtrip_encode(ViewAngles {
|
||||||
|
origin: (
|
||||||
|
Vector {
|
||||||
|
x: 1.0,
|
||||||
|
y: 1.0,
|
||||||
|
z: 1.0,
|
||||||
|
},
|
||||||
|
Vector {
|
||||||
|
x: 2.0,
|
||||||
|
y: 2.0,
|
||||||
|
z: 2.0,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
angles: (
|
||||||
|
Vector {
|
||||||
|
x: 3.0,
|
||||||
|
y: 3.0,
|
||||||
|
z: 3.0,
|
||||||
|
},
|
||||||
|
Vector {
|
||||||
|
x: 4.0,
|
||||||
|
y: 4.0,
|
||||||
|
z: 4.0,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
local_angles: (
|
||||||
|
Vector {
|
||||||
|
x: 5.0,
|
||||||
|
y: 5.0,
|
||||||
|
z: 5.0,
|
||||||
|
},
|
||||||
|
Vector {
|
||||||
|
x: 6.0,
|
||||||
|
y: 6.0,
|
||||||
|
z: 6.0,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> Parse<'a> for MessagePacket<'a> {
|
impl<'a> Parse<'a> for MessagePacket<'a> {
|
||||||
fn parse(stream: &mut Stream<'a>, _state: &ParserState) -> Result<Self> {
|
fn parse(stream: &mut Stream<'a>, _state: &ParserState) -> Result<Self> {
|
||||||
let tick = stream.read()?;
|
let tick = stream.read()?;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use bitbuffer::BitRead;
|
use bitbuffer::{BitRead, BitWrite};
|
||||||
use num_enum::TryFromPrimitive;
|
use num_enum::TryFromPrimitive;
|
||||||
|
|
||||||
use crate::{Parse, ParserState, Result, Stream};
|
use crate::{Parse, ParserState, Result, Stream};
|
||||||
|
|
@ -25,13 +25,13 @@ pub enum Packet<'a> {
|
||||||
Message(MessagePacket<'a>),
|
Message(MessagePacket<'a>),
|
||||||
SyncTick(SyncTickPacket),
|
SyncTick(SyncTickPacket),
|
||||||
ConsoleCmd(ConsoleCmdPacket),
|
ConsoleCmd(ConsoleCmdPacket),
|
||||||
UserCmd(UserCmdPacket),
|
UserCmd(UserCmdPacket<'a>),
|
||||||
DataTables(DataTablePacket),
|
DataTables(DataTablePacket),
|
||||||
Stop(StopPacket),
|
Stop(StopPacket),
|
||||||
StringTables(StringTablePacket<'a>),
|
StringTables(StringTablePacket<'a>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, TryFromPrimitive, Debug, Clone, Copy)]
|
#[derive(BitRead, BitWrite, TryFromPrimitive, Debug, Clone, Copy)]
|
||||||
#[discriminant_bits = 8]
|
#[discriminant_bits = 8]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum PacketType {
|
pub enum PacketType {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,4 @@
|
||||||
use bitbuffer::{BitRead, LittleEndian};
|
use bitbuffer::{BitRead, BitWrite};
|
||||||
|
|
||||||
use crate::{ReadResult, Stream};
|
#[derive(Debug, BitRead, BitWrite)]
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct StopPacket;
|
pub struct StopPacket;
|
||||||
|
|
||||||
impl BitRead<'_, LittleEndian> for StopPacket {
|
|
||||||
fn read(_stream: &mut Stream) -> ReadResult<Self> {
|
|
||||||
Ok(StopPacket)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use bitbuffer::{BitRead, LittleEndian};
|
use bitbuffer::{BitRead, BitWrite, LittleEndian};
|
||||||
|
|
||||||
use crate::demo::message::stringtable::StringTableMeta;
|
use crate::demo::message::stringtable::StringTableMeta;
|
||||||
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
||||||
use std::borrow::{Borrow, Cow};
|
use std::borrow::{Borrow, Cow};
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
|
|
||||||
#[derive(BitRead, Clone, Copy, Debug)]
|
#[derive(BitRead, BitWrite, Clone, Copy, Debug)]
|
||||||
pub struct FixedUserDataSize {
|
pub struct FixedUserDataSize {
|
||||||
#[size = 12]
|
#[size = 12]
|
||||||
pub size: u16,
|
pub size: u16,
|
||||||
|
|
@ -62,7 +62,7 @@ impl<'a> BitRead<'a, LittleEndian> for StringTable<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, Clone, Debug)]
|
#[derive(BitRead, BitWrite, Clone, Debug)]
|
||||||
#[endianness = "LittleEndian"]
|
#[endianness = "LittleEndian"]
|
||||||
pub struct ExtraData<'a> {
|
pub struct ExtraData<'a> {
|
||||||
pub byte_len: u16,
|
pub byte_len: u16,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use bitbuffer::BitRead;
|
use bitbuffer::{BitRead, BitWrite};
|
||||||
|
|
||||||
#[derive(BitRead, Debug)]
|
#[derive(BitRead, BitWrite, Debug)]
|
||||||
pub struct SyncTickPacket {
|
pub struct SyncTickPacket {
|
||||||
pub tick: u32,
|
pub tick: u32,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,12 @@
|
||||||
use bitbuffer::{BitRead, LittleEndian};
|
use crate::Stream;
|
||||||
|
use bitbuffer::{BitRead, BitWrite, LittleEndian};
|
||||||
|
|
||||||
use crate::{ReadResult, Stream};
|
#[derive(Debug, BitRead, BitWrite)]
|
||||||
|
#[endianness = "LittleEndian"]
|
||||||
#[derive(Debug)]
|
pub struct UserCmdPacket<'a> {
|
||||||
pub struct UserCmdPacket {
|
|
||||||
tick: u32,
|
tick: u32,
|
||||||
sequence_out: u32,
|
sequence_out: u32,
|
||||||
}
|
len: u32,
|
||||||
|
#[size = "len.saturating_mul(8)"]
|
||||||
impl BitRead<'_, LittleEndian> for UserCmdPacket {
|
data: Stream<'a>,
|
||||||
fn read(stream: &mut Stream) -> ReadResult<Self> {
|
|
||||||
let tick = stream.read()?;
|
|
||||||
let sequence_out = stream.read()?;
|
|
||||||
let len: u32 = stream.read()?;
|
|
||||||
stream.skip_bits(len as usize * 8)?;
|
|
||||||
// TODO parse the packet data
|
|
||||||
Ok(UserCmdPacket { tick, sequence_out })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use bitbuffer::{BitRead, LittleEndian};
|
use bitbuffer::{BitRead, BitWrite, BitWriteSized, BitWriteStream, LittleEndian};
|
||||||
use enumflags2::{bitflags, BitFlags};
|
use enumflags2::{bitflags, BitFlags};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
|
@ -10,6 +10,7 @@ use crate::consthash::ConstFnvHash;
|
||||||
use crate::demo::message::stringtable::log_base2;
|
use crate::demo::message::stringtable::log_base2;
|
||||||
use crate::demo::packet::datatable::SendTableName;
|
use crate::demo::packet::datatable::SendTableName;
|
||||||
use crate::demo::parser::MalformedSendPropDefinitionError;
|
use crate::demo::parser::MalformedSendPropDefinitionError;
|
||||||
|
use num_traits::Signed;
|
||||||
use parse_display::Display;
|
use parse_display::Display;
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use std::convert::{TryFrom, TryInto};
|
use std::convert::{TryFrom, TryInto};
|
||||||
|
|
@ -816,6 +817,52 @@ pub fn read_bit_coord(stream: &mut Stream) -> ReadResult<f32> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn write_bit_coord(val: f32, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
|
||||||
|
let has_int = val.abs() >= 1.0;
|
||||||
|
has_int.write(stream)?;
|
||||||
|
let has_frac = val.fract() != 0.0;
|
||||||
|
has_frac.write(stream)?;
|
||||||
|
|
||||||
|
if has_frac || has_int {
|
||||||
|
let sign = val.is_negative();
|
||||||
|
sign.write(stream)?;
|
||||||
|
}
|
||||||
|
let abs = val.abs();
|
||||||
|
if has_int {
|
||||||
|
(abs as u16 - 1).write_sized(stream, 14)?;
|
||||||
|
}
|
||||||
|
if has_frac {
|
||||||
|
let frac_val = (abs.fract() / get_frac_factor(5)) as u8;
|
||||||
|
frac_val.write_sized(stream, 5)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bit_coord_roundtrip() {
|
||||||
|
use bitbuffer::BitReadBuffer;
|
||||||
|
|
||||||
|
let mut write = BitWriteStream::new(LittleEndian);
|
||||||
|
write_bit_coord(0.0, &mut write).unwrap();
|
||||||
|
let pos1 = write.bit_len();
|
||||||
|
write_bit_coord(123.0, &mut write).unwrap();
|
||||||
|
let pos2 = write.bit_len();
|
||||||
|
write_bit_coord(123.4375, &mut write).unwrap();
|
||||||
|
let pos3 = write.bit_len();
|
||||||
|
write_bit_coord(-0.4375, &mut write).unwrap();
|
||||||
|
let pos4 = write.bit_len();
|
||||||
|
|
||||||
|
let mut read = Stream::from(BitReadBuffer::new_owned(write.finish(), LittleEndian));
|
||||||
|
assert_eq!(0.0, read_bit_coord(&mut read).unwrap());
|
||||||
|
assert_eq!(pos1, read.pos());
|
||||||
|
assert_eq!(123.0, read_bit_coord(&mut read).unwrap());
|
||||||
|
assert_eq!(pos2, read.pos());
|
||||||
|
assert_eq!(123.4375, read_bit_coord(&mut read).unwrap());
|
||||||
|
assert_eq!(pos3, read.pos());
|
||||||
|
assert_eq!(-0.4375, read_bit_coord(&mut read).unwrap());
|
||||||
|
assert_eq!(pos4, read.pos());
|
||||||
|
}
|
||||||
|
|
||||||
fn get_frac_factor(bits: usize) -> f32 {
|
fn get_frac_factor(bits: usize) -> f32 {
|
||||||
1.0 / ((1 << bits) as f32)
|
1.0 / ((1 << bits) as f32)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
use bitbuffer::BitRead;
|
use bitbuffer::{BitRead, BitWrite};
|
||||||
use parse_display::Display;
|
use parse_display::Display;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(BitRead, Debug, Clone, Copy, Default, Serialize, Deserialize, Display)]
|
#[derive(BitRead, BitWrite, Debug, Clone, Copy, Default, Serialize, Deserialize, Display)]
|
||||||
#[display("({x}, {y}, {z})")]
|
#[display("({x}, {y}, {z})")]
|
||||||
pub struct Vector {
|
pub struct Vector {
|
||||||
pub x: f32,
|
pub x: f32,
|
||||||
|
|
@ -16,7 +16,7 @@ impl PartialEq for Vector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, Debug, Clone, Copy, Default, Serialize, Deserialize, Display)]
|
#[derive(BitRead, BitWrite, Debug, Clone, Copy, Default, Serialize, Deserialize, Display)]
|
||||||
#[display("({x}, {y})")]
|
#[display("({x}, {y})")]
|
||||||
pub struct VectorXY {
|
pub struct VectorXY {
|
||||||
pub x: f32,
|
pub x: f32,
|
||||||
|
|
|
||||||
21
src/lib.rs
21
src/lib.rs
|
|
@ -12,3 +12,24 @@ pub use crate::demo::{
|
||||||
pub(crate) mod consthash;
|
pub(crate) mod consthash;
|
||||||
pub mod demo;
|
pub mod demo;
|
||||||
mod nullhasher;
|
mod nullhasher;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[track_caller]
|
||||||
|
fn test_roundtrip_encode<
|
||||||
|
'a,
|
||||||
|
T: bitbuffer::BitRead<'a, bitbuffer::LittleEndian>
|
||||||
|
+ bitbuffer::BitWrite<bitbuffer::LittleEndian>
|
||||||
|
+ std::fmt::Debug
|
||||||
|
+ std::cmp::PartialEq,
|
||||||
|
>(
|
||||||
|
val: T,
|
||||||
|
) {
|
||||||
|
use bitbuffer::{BitReadBuffer, BitReadStream, BitWriteStream, LittleEndian};
|
||||||
|
let mut stream = BitWriteStream::new(LittleEndian);
|
||||||
|
val.write(&mut stream).unwrap();
|
||||||
|
let pos = stream.bit_len();
|
||||||
|
|
||||||
|
let mut read = BitReadStream::new(BitReadBuffer::new_owned(stream.finish(), LittleEndian));
|
||||||
|
assert_eq!(val, read.read().unwrap());
|
||||||
|
assert_eq!(pos, read.pos());
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue