Fix (clippy) warnings

This commit is contained in:
Lol3rrr
2024-09-22 22:25:15 +02:00
parent 041aa14fa9
commit 8b41ad5108
12 changed files with 122 additions and 141 deletions

View File

@@ -45,7 +45,7 @@ impl<'a> Bitreader<'a> {
} }
#[inline(always)] #[inline(always)]
pub fn bits_remaining(&mut self) -> Option<usize> { pub fn bits_remaining(&mut self) -> Option<usize> {
Some(self.reader.bits_remaining()?) self.reader.bits_remaining()
} }
#[inline(always)] #[inline(always)]
pub fn read_nbits(&mut self, n: u32) -> Result<u32, BitReadError> { pub fn read_nbits(&mut self, n: u32) -> Result<u32, BitReadError> {
@@ -54,16 +54,16 @@ impl<'a> Bitreader<'a> {
} }
let b = self.peek(n); let b = self.peek(n);
self.consume(n); self.consume(n);
return Ok(b as u32); Ok(b as u32)
} }
#[inline(always)] #[inline(always)]
pub fn read_u_bit_var(&mut self) -> Result<u32, BitReadError> { pub fn read_u_bit_var(&mut self) -> Result<u32, BitReadError> {
let bits = self.read_nbits(6)?; let bits = self.read_nbits(6)?;
match bits & 0b110000 { match bits & 0b110000 {
0b10000 => return Ok((bits & 0b1111) | (self.read_nbits(4)? << 4)), 0b10000 => Ok((bits & 0b1111) | (self.read_nbits(4)? << 4)),
0b100000 => return Ok((bits & 0b1111) | (self.read_nbits(8)? << 4)), 0b100000 => Ok((bits & 0b1111) | (self.read_nbits(8)? << 4)),
0b110000 => return Ok((bits & 0b1111) | (self.read_nbits(28)? << 4)), 0b110000 => Ok((bits & 0b1111) | (self.read_nbits(28)? << 4)),
_ => return Ok(bits), _ => Ok(bits),
} }
} }
#[inline(always)] #[inline(always)]
@@ -73,7 +73,7 @@ impl<'a> Bitreader<'a> {
if x & 1 != 0 { if x & 1 != 0 {
y = !y; y = !y;
} }
Ok(y as i32) Ok(y)
} }
#[inline(always)] #[inline(always)]
pub fn read_varint(&mut self) -> Result<u32, BitReadError> { pub fn read_varint(&mut self) -> Result<u32, BitReadError> {
@@ -160,18 +160,18 @@ impl<'a> Bitreader<'a> {
} }
pub fn read_ubit_var_fp(&mut self) -> Result<u32, BitReadError> { pub fn read_ubit_var_fp(&mut self) -> Result<u32, BitReadError> {
if self.read_boolean()? { if self.read_boolean()? {
return Ok(self.read_nbits(2)?); return self.read_nbits(2);
} }
if self.read_boolean()? { if self.read_boolean()? {
return Ok(self.read_nbits(4)?); return self.read_nbits(4);
} }
if self.read_boolean()? { if self.read_boolean()? {
return Ok(self.read_nbits(10)?); return self.read_nbits(10);
} }
if self.read_boolean()? { if self.read_boolean()? {
return Ok(self.read_nbits(17)?); return self.read_nbits(17);
} }
return Ok(self.read_nbits(31)?); self.read_nbits(31)
} }
#[inline(always)] #[inline(always)]
pub fn read_bit_coord(&mut self) -> Result<f32, BitReadError> { pub fn read_bit_coord(&mut self) -> Result<f32, BitReadError> {
@@ -190,7 +190,7 @@ impl<'a> Bitreader<'a> {
frac_val = self.read_nbits(5)?; frac_val = self.read_nbits(5)?;
} }
let resol: f64 = 1.0 / (1 << 5) as f64; let resol: f64 = 1.0 / (1 << 5) as f64;
let result: f32 = (int_val as f64 + (frac_val as f64 * resol) as f64) as f32; let result: f32 = (int_val as f64 + (frac_val as f64 * resol)) as f32;
if sign { if sign {
Ok(-result) Ok(-result)
} else { } else {

View File

@@ -9,6 +9,9 @@ pub enum ParseContainerError {
Other(&'static str), Other(&'static str),
} }
/// A Container models the outer layer of a CS2 demo, which starts with a specific magic string and
/// some other values. Then it just stores the raw bytes afterwards, that contain the actual demo
/// data
#[derive(Debug)] #[derive(Debug)]
pub struct Container<'b> { pub struct Container<'b> {
pub magic: &'b str, pub magic: &'b str,
@@ -16,6 +19,7 @@ pub struct Container<'b> {
} }
impl<'b> Container<'b> { impl<'b> Container<'b> {
/// Attempts to parse the given bytes into a valid cs2 demo container
pub fn parse<'ib>(input: &'ib [u8]) -> Result<Self, ParseContainerError> pub fn parse<'ib>(input: &'ib [u8]) -> Result<Self, ParseContainerError>
where where
'ib: 'b, 'ib: 'b,
@@ -25,7 +29,7 @@ impl<'b> Container<'b> {
} }
let magic = let magic =
core::str::from_utf8(&input[..8]).map_err(|e| ParseContainerError::InvalidMagic(e))?; core::str::from_utf8(&input[..8]).map_err(ParseContainerError::InvalidMagic)?;
let raw_len: [u8; 4] = input[8..12] let raw_len: [u8; 4] = input[8..12]
.try_into() .try_into()
.expect("We know that the input buffer is at least 16 bytes large"); .expect("We know that the input buffer is at least 16 bytes large");

View File

@@ -5,20 +5,33 @@ pub struct Frame<'b> {
pub inner: std::borrow::Cow<'b, [u8]>, pub inner: std::borrow::Cow<'b, [u8]>,
} }
#[derive(Debug)]
pub enum FrameParseError {
ParseVarint(()),
NotEnoughBytes,
ParseDemoCommand(i32),
}
#[derive(Debug)]
pub enum FrameDecompressError {
GettingDecompressedLength(snap::Error),
Decompressing(snap::Error),
}
impl<'b> Frame<'b> { impl<'b> Frame<'b> {
pub fn parse<'ib>(input: &'ib [u8]) -> Result<(&'ib [u8], Self), ()> pub fn parse<'ib>(input: &'ib [u8]) -> Result<(&'ib [u8], Self), FrameParseError>
where where
'ib: 'b, 'ib: 'b,
{ {
let (input, raw_cmd) = crate::varint::parse_varint(input)?; let (input, raw_cmd) = crate::varint::parse_varint(input).map_err(FrameParseError::ParseVarint)?;
let (input, tick) = crate::varint::parse_varint(input)?; let (input, tick) = crate::varint::parse_varint(input).map_err(FrameParseError::ParseVarint)?;
let (input, size) = crate::varint::parse_varint(input)?; let (input, size) = crate::varint::parse_varint(input).map_err(FrameParseError::ParseVarint)?;
if input.len() < size as usize { if input.len() < size as usize {
return Err(()); return Err(FrameParseError::NotEnoughBytes);
} }
let demo_cmd = crate::DemoCommand::try_from((raw_cmd & !64) as i32).map_err(|e| ())?; let demo_cmd = crate::DemoCommand::try_from((raw_cmd & !64) as i32).map_err(FrameParseError::ParseDemoCommand)?;
Ok(( Ok((
&input[size as usize..], &input[size as usize..],
@@ -39,7 +52,7 @@ impl<'b> Frame<'b> {
Some(self.inner.as_ref()) Some(self.inner.as_ref())
} }
pub fn decompress_with_buf<'s, 'buf>(&'s self, buf: &'b mut Vec<u8>) -> Result<&'buf [u8], ()> pub fn decompress_with_buf<'s, 'buf>(&'s self, buf: &'b mut Vec<u8>) -> Result<&'buf [u8], FrameDecompressError>
where where
's: 'buf, 's: 'buf,
{ {
@@ -48,29 +61,27 @@ impl<'b> Frame<'b> {
} }
let uncompressed_len = snap::raw::decompress_len(&self.inner).map_err(|e| { let uncompressed_len = snap::raw::decompress_len(&self.inner).map_err(|e| {
println!("Getting decompress len"); FrameDecompressError::GettingDecompressedLength(e)
()
})?; })?;
buf.resize(uncompressed_len, 0); buf.resize(uncompressed_len, 0);
snap::raw::Decoder::new() snap::raw::Decoder::new()
.decompress(&self.inner, buf.as_mut_slice()) .decompress(&self.inner, buf.as_mut_slice())
.map_err(|e| { .map_err(|e| {
println!("Decompressing"); FrameDecompressError::Decompressing(e)
()
})?; })?;
Ok(buf.as_slice()) Ok(buf.as_slice())
} }
pub fn decompress(&mut self) -> Result<(), ()> { pub fn decompress(&mut self) -> Result<(), FrameDecompressError> {
if !self.compressed { if !self.compressed {
return Ok(()); return Ok(());
} }
let decompressed = snap::raw::Decoder::new() let decompressed = snap::raw::Decoder::new()
.decompress_vec(&self.inner.as_ref()) .decompress_vec(self.inner.as_ref())
.map_err(|e| ())?; .map_err(FrameDecompressError::Decompressing)?;
self.compressed = false; self.compressed = false;
self.inner = std::borrow::Cow::Owned(decompressed); self.inner = std::borrow::Cow::Owned(decompressed);

View File

@@ -2,7 +2,7 @@ mod container;
pub use container::{Container, ParseContainerError}; pub use container::{Container, ParseContainerError};
mod frame; mod frame;
pub use frame::{Frame, FrameIterator}; pub use frame::{Frame, FrameIterator, FrameDecompressError, FrameParseError};
mod democmd; mod democmd;
pub use democmd::DemoCommand; pub use democmd::DemoCommand;

View File

@@ -1,4 +1,4 @@
use crate::{packet::DemoEvent, DemoCommand, Frame, UserId}; use crate::{packet::DemoEvent, DemoCommand, Frame, UserId, FrameDecompressError};
mod fieldpath; mod fieldpath;
pub use fieldpath::{FieldPath, Paths}; pub use fieldpath::{FieldPath, Paths};
@@ -13,7 +13,7 @@ pub use entities::EntityFilter;
#[derive(Debug)] #[derive(Debug)]
pub enum FirstPassError { pub enum FirstPassError {
DecompressFrame, DecompressFrame(FrameDecompressError),
NoDataFrame, NoDataFrame,
DecodeProtobuf(prost::DecodeError), DecodeProtobuf(prost::DecodeError),
MissingFileHeader, MissingFileHeader,
@@ -73,7 +73,6 @@ struct GameEventMapping {
#[derive(Debug)] #[derive(Debug)]
pub struct Class { pub struct Class {
class_id: i32,
name: String, name: String,
serializer: sendtables::Serializer, serializer: sendtables::Serializer,
} }
@@ -111,7 +110,7 @@ where
for frame in frames.into_iter() { for frame in frames.into_iter() {
let data = frame let data = frame
.decompress_with_buf(&mut buffer) .decompress_with_buf(&mut buffer)
.map_err(|e| FirstPassError::DecompressFrame)?; .map_err(FirstPassError::DecompressFrame)?;
match frame.cmd { match frame.cmd {
DemoCommand::FileHeader => { DemoCommand::FileHeader => {
@@ -205,7 +204,6 @@ where
cls_id as u32, cls_id as u32,
Class { Class {
name: network_name.to_owned(), name: network_name.to_owned(),
class_id: cls_id,
serializer: ser, serializer: ser,
}, },
); );
@@ -235,7 +233,7 @@ fn parse_fullpacket(data: &[u8]) -> Result<Option<crate::csgo_proto::CDemoPacket
// TODO // TODO
// Handle string table stuff // Handle string table stuff
for item in raw.string_table.iter().flat_map(|st| st.tables.iter()) { for _item in raw.string_table.iter().flat_map(|st| st.tables.iter()) {
// dbg!(&item.table_name); // dbg!(&item.table_name);
} }
@@ -324,8 +322,11 @@ fn inner_parse_packet(
let cls = entity_ctx.create_entity(entity_id, &mut bitreader)?; let cls = entity_ctx.create_entity(entity_id, &mut bitreader)?;
if let Some(baseline_bytes) = baselines.get(&cls) { if let Some(baseline_bytes) = baselines.get(&cls) {
let mut br = crate::bitreader::Bitreader::new(&baseline_bytes); let mut br = crate::bitreader::Bitreader::new(baseline_bytes);
let state = update_entity(
// TODO
// How should we handle is this?
let _state = update_entity(
entity_id, entity_id,
&mut br, &mut br,
entity_ctx, entity_ctx,
@@ -348,11 +349,9 @@ fn inner_parse_packet(
} }
} }
0b00 => { 0b00 => {
if raw.has_pvs_vis_bits() > 0 { if raw.has_pvs_vis_bits() > 0 && bitreader.read_nbits(2)? & 0x01 == 1 {
if bitreader.read_nbits(2)? & 0x01 == 1 {
continue; continue;
} }
}
let state = update_entity( let state = update_entity(
entity_id, entity_id,
@@ -385,7 +384,7 @@ fn inner_parse_packet(
match event_mapper.mapping.get(&raw.eventid()) { match event_mapper.mapping.get(&raw.eventid()) {
Some((name, keys)) => { Some((name, keys)) => {
match crate::game_event::EVENT_PARSERS.get(&name) { match crate::game_event::EVENT_PARSERS.get(name) {
Some(parser) => { Some(parser) => {
let parsed = parser.parse(keys.as_slice(), raw.clone())?; let parsed = parser.parse(keys.as_slice(), raw.clone())?;
@@ -419,11 +418,6 @@ fn inner_parse_packet(
crate::netmessagetypes::NetmessageType::CS_UM_RadioText => {} crate::netmessagetypes::NetmessageType::CS_UM_RadioText => {}
crate::netmessagetypes::NetmessageType::TE_WorldDecal => {} crate::netmessagetypes::NetmessageType::TE_WorldDecal => {}
crate::netmessagetypes::NetmessageType::TE_EffectDispatch => {} crate::netmessagetypes::NetmessageType::TE_EffectDispatch => {}
crate::netmessagetypes::NetmessageType::CS_UM_PlayerStatsUpdate => {
let raw: crate::csgo_proto::CcsUsrMsgPlayerStatsUpdate =
prost::Message::decode(msg_bytes.as_slice())?;
// dbg!(&raw);
}
crate::netmessagetypes::NetmessageType::CS_UM_EndOfMatchAllPlayersData => { crate::netmessagetypes::NetmessageType::CS_UM_EndOfMatchAllPlayersData => {
let raw: crate::csgo_proto::CcsUsrMsgEndOfMatchAllPlayersData = let raw: crate::csgo_proto::CcsUsrMsgEndOfMatchAllPlayersData =
prost::Message::decode(msg_bytes.as_slice())?; prost::Message::decode(msg_bytes.as_slice())?;

View File

@@ -89,7 +89,7 @@ pub fn find_decoder(field: &super::sendtables::ConstructorField, qf_map: &mut Qf
} }
match BASETYPE_DECODERS.get(field.field_type.base_type.as_str()) { match BASETYPE_DECODERS.get(field.field_type.base_type.as_str()) {
Some(d) => d.clone(), Some(d) => *d,
None => match field.field_type.base_type.as_str() { None => match field.field_type.base_type.as_str() {
"float32" => float_decoder(field, qf_map), "float32" => float_decoder(field, qf_map),
"Vector" => find_vector_type(3, field, qf_map), "Vector" => find_vector_type(3, field, qf_map),
@@ -138,7 +138,7 @@ fn float_decoder(field: &super::sendtables::ConstructorField, qf_map: &mut QfMap
"m_flSimulationTime" => Decoder::FloatSimulationTimeDecoder, "m_flSimulationTime" => Decoder::FloatSimulationTimeDecoder,
_ => { _ => {
if field.bitcount <= 0 || field.bitcount >= 32 { if field.bitcount <= 0 || field.bitcount >= 32 {
return Decoder::NoscaleDecoder; Decoder::NoscaleDecoder
} else { } else {
let qf = QuantalizedFloat::new( let qf = QuantalizedFloat::new(
field.bitcount as u32, field.bitcount as u32,
@@ -213,7 +213,7 @@ impl Decoder {
impl<'b> crate::bitreader::Bitreader<'b> { impl<'b> crate::bitreader::Bitreader<'b> {
pub fn read_bit_coord_pres(&mut self) -> Result<f32, super::FirstPassError> { pub fn read_bit_coord_pres(&mut self) -> Result<f32, super::FirstPassError> {
return Ok(self.read_nbits(20)? as f32 * 360.0 / (1 << 20) as f32 - 180.0); Ok(self.read_nbits(20)? as f32 * 360.0 / (1 << 20) as f32 - 180.0)
} }
pub fn decode_qfloat( pub fn decode_qfloat(
@@ -232,7 +232,7 @@ impl<'b> crate::bitreader::Bitreader<'b> {
if ammo > 0 { if ammo > 0 {
return Ok(ammo - 1); return Ok(ammo - 1);
} }
return Ok(ammo); Ok(ammo)
} }
pub fn decode_uint64(&mut self) -> Result<u64, super::FirstPassError> { pub fn decode_uint64(&mut self) -> Result<u64, super::FirstPassError> {
@@ -306,7 +306,7 @@ impl<'b> crate::bitreader::Bitreader<'b> {
Ok(v) Ok(v)
} }
pub fn read_angle(&mut self, n: usize) -> Result<f32, super::FirstPassError> { pub fn read_angle(&mut self, n: usize) -> Result<f32, super::FirstPassError> {
return Ok(self.decode_noscale()? / ((1 << n) as f32)); Ok(self.decode_noscale()? / ((1 << n) as f32))
} }
pub fn decode_normal(&mut self) -> Result<f32, super::FirstPassError> { pub fn decode_normal(&mut self) -> Result<f32, super::FirstPassError> {
@@ -331,7 +331,7 @@ impl<'b> crate::bitreader::Bitreader<'b> {
let neg_z = self.read_boolean()?; let neg_z = self.read_boolean()?;
let prod_sum = v[0] * v[0] + v[1] * v[1]; let prod_sum = v[0] * v[0] + v[1] * v[1];
if prod_sum < 1.0 { if prod_sum < 1.0 {
v[2] = (1.0 - prod_sum).sqrt() as f32; v[2] = (1.0 - prod_sum).sqrt();
} else { } else {
v[2] = 0.0; v[2] = 0.0;
} }

View File

@@ -182,26 +182,20 @@ impl QuantalizedFloat {
steps = 1 << qf.bit_count; steps = 1 << qf.bit_count;
} }
qf.offset = range_2 as f32 / steps as f32; qf.offset = range_2 as f32 / steps as f32;
qf.high = qf.low + ((range_2 as f32 - qf.offset) as f32); qf.high = qf.low + (range_2 as f32 - qf.offset);
} }
qf.assign_multipliers(steps); qf.assign_multipliers(steps);
if (qf.flags & QFF_ROUNDDOWN) != 0 { if (qf.flags & QFF_ROUNDDOWN) != 0 && qf.quantize(qf.low) == qf.low {
if qf.quantize(qf.low) == qf.low {
qf.flags &= !QFF_ROUNDDOWN; qf.flags &= !QFF_ROUNDDOWN;
} }
} if (qf.flags & QFF_ROUNDUP) != 0 && qf.quantize(qf.high) == qf.high {
if (qf.flags & QFF_ROUNDUP) != 0 {
if qf.quantize(qf.high) == qf.high {
qf.flags &= !QFF_ROUNDUP qf.flags &= !QFF_ROUNDUP
} }
} if (qf.flags & QFF_ENCODE_ZERO) != 0 && qf.quantize(0.0) == 0.0 {
if (qf.flags & QFF_ENCODE_ZERO) != 0 {
if qf.quantize(0.0) == 0.0 {
qf.flags &= !QFF_ENCODE_ZERO; qf.flags &= !QFF_ENCODE_ZERO;
} }
}
qf qf
} }

View File

@@ -7,6 +7,12 @@ pub struct FieldPath {
pub last: usize, pub last: usize,
} }
impl Default for Paths {
fn default() -> Self {
Self::new()
}
}
impl Paths { impl Paths {
pub fn new() -> Self { pub fn new() -> Self {
Self(Vec::new()) Self(Vec::new())

View File

@@ -1,3 +1,5 @@
#![allow(dead_code)]
pub const PLAYER_ENTITY_HANDLE_MISSING: i32 = 2047; pub const PLAYER_ENTITY_HANDLE_MISSING: i32 = 2047;
pub const SPECTATOR_TEAM_NUM: u32 = 1; pub const SPECTATOR_TEAM_NUM: u32 = 1;
pub const BUTTONS_BASEID: u32 = 100000; pub const BUTTONS_BASEID: u32 = 100000;
@@ -136,11 +138,8 @@ impl PropController {
path.clone(), path.clone(),
); );
} }
Field::Array(ser) => match &mut ser.field_enum.as_mut() { Field::Array(ser) => if let Field::Value(v) = &mut ser.field_enum.as_mut() {
Field::Value(v) => {
self.handle_prop(&(ser_name.clone() + "." + &v.name), v, path); self.handle_prop(&(ser_name.clone() + "." + &v.name), v, path);
}
_ => {}
}, },
Field::Vector(_x) => { Field::Vector(_x) => {
let vec_path = path.clone(); let vec_path = path.clone();
@@ -150,8 +149,7 @@ impl PropController {
for (inner_idx, f) in for (inner_idx, f) in
&mut s.serializer.fields.iter_mut().enumerate() &mut s.serializer.fields.iter_mut().enumerate()
{ {
match f { if let Field::Value(v) = f {
Field::Value(v) => {
let mut myp = vec_path.clone(); let mut myp = vec_path.clone();
myp.push(inner_idx as i32); myp.push(inner_idx as i32);
self.handle_prop( self.handle_prop(
@@ -160,8 +158,6 @@ impl PropController {
myp, myp,
); );
} }
_ => {}
}
} }
self.traverse_fields( self.traverse_fields(
&mut s.serializer.fields, &mut s.serializer.fields,
@@ -219,53 +215,50 @@ impl PropController {
self.path_to_name.insert(a, prop_name.to_string()); self.path_to_name.insert(a, prop_name.to_string());
let prop_already_exists = self.name_to_id.contains_key(&(prop_name).to_string()); let prop_already_exists = self.name_to_id.contains_key(&(prop_name).to_string());
self.set_id(&prop_name, f, is_grenade_or_weapon); self.set_id(&prop_name, f);
if !prop_already_exists { if !prop_already_exists {
self.insert_propinfo(&prop_name, f); self.insert_propinfo(&prop_name, f);
} }
f.should_parse = true; f.should_parse = true;
if full_name == "CCSPlayerPawn.CCSPlayer_WeaponServices.m_hMyWeapons" { if full_name == "CCSPlayerPawn.CCSPlayer_WeaponServices.m_hMyWeapons" {
f.prop_id = MY_WEAPONS_OFFSET as u32; f.prop_id = MY_WEAPONS_OFFSET;
} }
if full_name if full_name
== "CCSPlayerPawn.CCSPlayer_ActionTrackingServices.WeaponPurchaseCount_t.m_nCount" == "CCSPlayerPawn.CCSPlayer_ActionTrackingServices.WeaponPurchaseCount_t.m_nCount"
{ {
f.prop_id = ITEM_PURCHASE_COUNT as u32; f.prop_id = ITEM_PURCHASE_COUNT;
} }
if full_name == "CCSPlayerPawn.CCSPlayer_BuyServices.SellbackPurchaseEntry_t.m_unDefIdx" { if full_name == "CCSPlayerPawn.CCSPlayer_BuyServices.SellbackPurchaseEntry_t.m_unDefIdx" {
f.prop_id = ITEM_PURCHASE_DEF_IDX as u32; f.prop_id = ITEM_PURCHASE_DEF_IDX;
} }
if full_name == "CCSPlayerPawn.CCSPlayer_BuyServices.SellbackPurchaseEntry_t.m_nCost" { if full_name == "CCSPlayerPawn.CCSPlayer_BuyServices.SellbackPurchaseEntry_t.m_nCost" {
f.prop_id = ITEM_PURCHASE_COST as u32; f.prop_id = ITEM_PURCHASE_COST;
} }
if full_name == "CCSPlayerPawn.CCSPlayer_ActionTrackingServices.WeaponPurchaseCount_t.m_nItemDefIndex" { if full_name == "CCSPlayerPawn.CCSPlayer_ActionTrackingServices.WeaponPurchaseCount_t.m_nItemDefIndex" {
f.prop_id = ITEM_PURCHASE_NEW_DEF_IDX as u32; f.prop_id = ITEM_PURCHASE_NEW_DEF_IDX;
} }
if full_name == "CCSPlayerPawn.CCSPlayer_BuyServices.SellbackPurchaseEntry_t.m_hItem" { if full_name == "CCSPlayerPawn.CCSPlayer_BuyServices.SellbackPurchaseEntry_t.m_hItem" {
f.prop_id = ITEM_PURCHASE_HANDLE as u32; f.prop_id = ITEM_PURCHASE_HANDLE;
} }
if prop_name.contains("CEconItemAttribute.m_iRawValue32") { if prop_name.contains("CEconItemAttribute.m_iRawValue32") {
f.prop_id = WEAPON_SKIN_ID as u32; f.prop_id = WEAPON_SKIN_ID;
} }
self.id += 1; self.id += 1;
} }
fn set_id(&mut self, weap_prop: &str, f: &mut ValueField, is_grenade_or_weapon: bool) { fn set_id(&mut self, weap_prop: &str, f: &mut ValueField) {
match self.name_to_id.get(weap_prop) { match self.name_to_id.get(weap_prop) {
// If we already have an id for prop of same name then use that id. // If we already have an id for prop of same name then use that id.
// Mainly for weapon props. For example CAK47.m_iClip1 and CWeaponSCAR20.m_iClip1 // Mainly for weapon props. For example CAK47.m_iClip1 and CWeaponSCAR20.m_iClip1
// are the "same" prop. (they have same path and we want to refer to it with one id not ~20) // are the "same" prop. (they have same path and we want to refer to it with one id not ~20)
Some(id) => { Some(id) => {
f.prop_id = *id as u32; f.prop_id = *id;
self.id_to_name.insert(*id, weap_prop.to_string()); self.id_to_name.insert(*id, weap_prop.to_string());
self.set_special_ids(&weap_prop, is_grenade_or_weapon, *id);
return;
} }
None => { None => {
self.name_to_id.insert(weap_prop.to_string(), self.id); self.name_to_id.insert(weap_prop.to_string(), self.id);
self.id_to_name.insert(self.id, weap_prop.to_string()); self.id_to_name.insert(self.id, weap_prop.to_string());
f.prop_id = self.id as u32; f.prop_id = self.id;
self.set_special_ids(&weap_prop, is_grenade_or_weapon, self.id);
} }
} }
} }
@@ -274,24 +267,11 @@ impl PropController {
self.prop_infos.insert( self.prop_infos.insert(
f.prop_id, f.prop_id,
PropInfo { PropInfo {
id: f.prop_id as u32, id: f.prop_id,
prop_name: prop_name.into(), prop_name: prop_name.into(),
}, },
); );
} }
pub fn set_special_ids(&mut self, weap_prop: &str, is_grenade_or_weapon: bool, id: u32) {
// TODO
if is_grenade_or_weapon {
match weap_prop {
_ => {}
};
} else {
match weap_prop {
_ => {}
};
}
}
} }
impl SpecialIDs { impl SpecialIDs {

View File

@@ -1,8 +1,5 @@
use super::decoder; use super::decoder;
#[derive(Debug)]
pub enum ParseSendTables {}
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct Serializer { pub struct Serializer {
pub name: String, pub name: String,
@@ -138,7 +135,7 @@ fn generate_field_data(
) -> Result<ConstructorField, super::FirstPassError> { ) -> Result<ConstructorField, super::FirstPassError> {
let name = msg.symbols.get(field.var_type_sym() as usize).unwrap(); let name = msg.symbols.get(field.var_type_sym() as usize).unwrap();
let ft = find_field_type(&name, field_type_map)?; let ft = find_field_type(name, field_type_map)?;
let mut field = field_from_msg(field, msg, ft.clone())?; let mut field = field_from_msg(field, msg, ft.clone())?;
field.category = find_category(&field); field.category = find_category(&field);
@@ -166,7 +163,7 @@ fn generate_field_data(
fn generate_serializer( fn generate_serializer(
serializer: &crate::csgo_proto::ProtoFlattenedSerializerT, serializer: &crate::csgo_proto::ProtoFlattenedSerializerT,
field_data: &mut Vec<Option<ConstructorField>>, field_data: &mut [Option<ConstructorField>],
msg: &crate::csgo_proto::CsvcMsgFlattenedSerializer, msg: &crate::csgo_proto::CsvcMsgFlattenedSerializer,
serializers: &mut std::collections::HashMap<String, Serializer>, serializers: &mut std::collections::HashMap<String, Serializer>,
) -> Result<Serializer, super::FirstPassError> { ) -> Result<Serializer, super::FirstPassError> {
@@ -188,7 +185,7 @@ fn generate_serializer(
}; };
if f.field_enum_type.is_none() { if f.field_enum_type.is_none() {
f.field_enum_type = Some(create_field(&symbol, f, serializers)?); f.field_enum_type = Some(create_field(f, serializers)?);
} }
if let Some(Some(f)) = &field_data.get(fi) { if let Some(Some(f)) = &field_data.get(fi) {
if let Some(field) = &f.field_enum_type { if let Some(field) = &f.field_enum_type {
@@ -221,6 +218,7 @@ pub enum FieldCategory {
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct ConstructorField { pub struct ConstructorField {
pub var_name: String, pub var_name: String,
pub var_type: String, pub var_type: String,
@@ -245,7 +243,7 @@ static RE: std::sync::LazyLock<regex::Regex> = std::sync::LazyLock::new(|| {
regex::Regex::new(r"([^<\[\*]+)(<\s(.*)\s>)?(\*)?(\[(.*)\])?").unwrap() regex::Regex::new(r"([^<\[\*]+)(<\s(.*)\s>)?(\*)?(\[(.*)\])?").unwrap()
}); });
const POINTER_TYPES: &'static [&'static str] = &[ const POINTER_TYPES: &[&str] = &[
"CBodyComponent", "CBodyComponent",
"CLightComponent", "CLightComponent",
"CPhysicsComponent", "CPhysicsComponent",
@@ -417,7 +415,7 @@ impl FieldType {
if let Some(gt) = self.generic_type.as_ref() { if let Some(gt) = self.generic_type.as_ref() {
s += "< "; s += "< ";
s += &FieldType::to_string(&gt, true); s += &FieldType::to_string(gt, true);
s += "< "; s += "< ";
} }
if self.pointer { if self.pointer {
@@ -450,7 +448,6 @@ fn for_string(
} }
fn create_field( fn create_field(
symbol: &String,
fd: &mut ConstructorField, fd: &mut ConstructorField,
serializers: &mut std::collections::HashMap<String, Serializer>, serializers: &mut std::collections::HashMap<String, Serializer>,
) -> Result<Field, super::FirstPassError> { ) -> Result<Field, super::FirstPassError> {
@@ -578,7 +575,8 @@ impl Field {
fi.prop_id = ITEM_PURCHASE_NEW_DEF_IDX + path.path[2] as u32; fi.prop_id = ITEM_PURCHASE_NEW_DEF_IDX + path.path[2] as u32;
} }
} }
return Some(fi);
Some(fi)
} }
pub fn get_decoder(&self) -> Result<decoder::Decoder, super::FirstPassError> { pub fn get_decoder(&self) -> Result<decoder::Decoder, super::FirstPassError> {

View File

@@ -17,12 +17,12 @@ impl TryFrom<crate::csgo_proto::c_msg_source1_legacy_game_event::KeyT> for RawVa
1 if value.val_string.is_some() => Ok(Self::String(value.val_string.unwrap())), 1 if value.val_string.is_some() => Ok(Self::String(value.val_string.unwrap())),
2 if value.val_float.is_some() => Ok(Self::F32(value.val_float.unwrap())), 2 if value.val_float.is_some() => Ok(Self::F32(value.val_float.unwrap())),
3 if value.val_long.is_some() => Ok(Self::I32(value.val_long.unwrap())), 3 if value.val_long.is_some() => Ok(Self::I32(value.val_long.unwrap())),
4 if value.val_short.is_some() => Ok(Self::I32(value.val_short.unwrap() as i32)), 4 if value.val_short.is_some() => Ok(Self::I32(value.val_short.unwrap())),
5 if value.val_byte.is_some() => Ok(Self::I32(value.val_byte.unwrap() as i32)), 5 if value.val_byte.is_some() => Ok(Self::I32(value.val_byte.unwrap())),
6 if value.val_bool.is_some() => Ok(Self::Bool(value.val_bool.unwrap())), 6 if value.val_bool.is_some() => Ok(Self::Bool(value.val_bool.unwrap())),
7 if value.val_uint64.is_some() => Ok(Self::U64(value.val_uint64.unwrap())), 7 if value.val_uint64.is_some() => Ok(Self::U64(value.val_uint64.unwrap())),
8 if value.val_long.is_some() => Ok(Self::I32(value.val_long.unwrap())), 8 if value.val_long.is_some() => Ok(Self::I32(value.val_long.unwrap())),
9 if value.val_short.is_some() => Ok(Self::I32(value.val_short.unwrap() as i32)), 9 if value.val_short.is_some() => Ok(Self::I32(value.val_short.unwrap())),
_ => Err(()), _ => Err(()),
} }
} }

View File

@@ -18,9 +18,7 @@ fn mirage_1() {
assert_eq!("de_mirage", output.header.map_name()); assert_eq!("de_mirage", output.header.map_name());
for event in output.events.iter() { for event in output.events.iter() {
match event { if let DemoEvent::GameEvent(gevent) = event { if let GameEvent::PlayerDeath(death) = gevent {
DemoEvent::GameEvent(gevent) => match gevent {
GameEvent::PlayerDeath(death) => {
assert!( assert!(
death.remaining.is_empty(), death.remaining.is_empty(),
"Remaining for PlayerDeath: {:?}", "Remaining for PlayerDeath: {:?}",
@@ -32,11 +30,7 @@ fn mirage_1() {
.get(death.userid.as_ref().unwrap()) .get(death.userid.as_ref().unwrap())
.unwrap(); .unwrap();
// dbg!(died_user); // dbg!(died_user);
} } };
_ => {}
},
_ => {}
};
} }
todo!() todo!()