Add some more types and improve typing for player events
This commit is contained in:
@@ -1,60 +1,4 @@
|
|||||||
use crate::csgo_proto;
|
use crate::{csgo_proto, RawValue, UserId};
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum RawValue {
|
|
||||||
String(String),
|
|
||||||
F32(f32),
|
|
||||||
I32(i32),
|
|
||||||
Bool(bool),
|
|
||||||
U64(u64),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<crate::csgo_proto::c_msg_source1_legacy_game_event::KeyT> for RawValue {
|
|
||||||
type Error = ();
|
|
||||||
|
|
||||||
fn try_from(value: crate::csgo_proto::c_msg_source1_legacy_game_event::KeyT) -> Result<Self, Self::Error> {
|
|
||||||
match value.r#type() {
|
|
||||||
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())),
|
|
||||||
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)),
|
|
||||||
5 if value.val_byte.is_some() => Ok(Self::I32(value.val_byte.unwrap() as i32)),
|
|
||||||
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())),
|
|
||||||
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)),
|
|
||||||
_ => Err(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<RawValue> for i32 {
|
|
||||||
type Error = ();
|
|
||||||
fn try_from(value: RawValue) -> Result<Self, Self::Error> {
|
|
||||||
match value {
|
|
||||||
RawValue::I32(v) => Ok(v),
|
|
||||||
_ => Err(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl TryFrom<RawValue> for bool {
|
|
||||||
type Error = ();
|
|
||||||
fn try_from(value: RawValue) -> Result<Self, Self::Error> {
|
|
||||||
match value {
|
|
||||||
RawValue::Bool(v) => Ok(v),
|
|
||||||
_ => Err(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl TryFrom<RawValue> for String {
|
|
||||||
type Error = ();
|
|
||||||
fn try_from(value: RawValue) -> Result<Self, Self::Error> {
|
|
||||||
match value {
|
|
||||||
RawValue::String(v) => Ok(v),
|
|
||||||
_ => Err(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! define_event {
|
macro_rules! define_event {
|
||||||
($name:ident, $target:path $(, ($field:ident, $field_ty:ty))*) => {
|
($name:ident, $target:path $(, ($field:ident, $field_ty:ty))*) => {
|
||||||
@@ -87,12 +31,48 @@ macro_rules! define_event {
|
|||||||
|
|
||||||
define_event!(HltvVersionInfo, GameEvent::HltvVersionInfo);
|
define_event!(HltvVersionInfo, GameEvent::HltvVersionInfo);
|
||||||
|
|
||||||
define_event!(ItemEquip, GameEvent::ItemEquip, (userid, i32), (hassilencer, bool), (hastracers, bool), (item, String), (issilenced, bool), (canzoom, bool), (ispainted, bool), (weptype, i32), (defindex, i32));
|
define_event!(
|
||||||
define_event!(ItemPickup, GameEvent::ItemPickup, (userid, RawValue), (item, RawValue), (silent, RawValue), (defindex, RawValue));
|
ItemEquip,
|
||||||
|
GameEvent::ItemEquip,
|
||||||
|
(userid, UserId),
|
||||||
|
(hassilencer, bool),
|
||||||
|
(hastracers, bool),
|
||||||
|
(item, String),
|
||||||
|
(issilenced, bool),
|
||||||
|
(canzoom, bool),
|
||||||
|
(ispainted, bool),
|
||||||
|
(weptype, i32),
|
||||||
|
(defindex, i32)
|
||||||
|
);
|
||||||
|
define_event!(
|
||||||
|
ItemPickup,
|
||||||
|
GameEvent::ItemPickup,
|
||||||
|
(userid, UserId),
|
||||||
|
(item, RawValue),
|
||||||
|
(silent, RawValue),
|
||||||
|
(defindex, RawValue)
|
||||||
|
);
|
||||||
|
|
||||||
define_event!(WeaponReload, GameEvent::WeaponReload, (userid, RawValue), (userid_pawn, RawValue));
|
define_event!(
|
||||||
define_event!(WeaponZoom, GameEvent::WeaponZoom, (userid, RawValue), (userid_pawn, RawValue));
|
WeaponReload,
|
||||||
define_event!(WeaponFire, GameEvent::WeaponFire, (userid, RawValue), (weapon, RawValue), (silenced, RawValue), (userid_pawn, RawValue));
|
GameEvent::WeaponReload,
|
||||||
|
(userid, UserId),
|
||||||
|
(userid_pawn, RawValue)
|
||||||
|
);
|
||||||
|
define_event!(
|
||||||
|
WeaponZoom,
|
||||||
|
GameEvent::WeaponZoom,
|
||||||
|
(userid, UserId),
|
||||||
|
(userid_pawn, RawValue)
|
||||||
|
);
|
||||||
|
define_event!(
|
||||||
|
WeaponFire,
|
||||||
|
GameEvent::WeaponFire,
|
||||||
|
(userid, UserId),
|
||||||
|
(weapon, RawValue),
|
||||||
|
(silenced, RawValue),
|
||||||
|
(userid_pawn, RawValue)
|
||||||
|
);
|
||||||
|
|
||||||
define_event!(SmokeGrenadeDetonate, GameEvent::SmokeGrenadeDetonate);
|
define_event!(SmokeGrenadeDetonate, GameEvent::SmokeGrenadeDetonate);
|
||||||
define_event!(SmokeGrenadeExpired, GameEvent::SmokeGrenadeExpired);
|
define_event!(SmokeGrenadeExpired, GameEvent::SmokeGrenadeExpired);
|
||||||
@@ -103,16 +83,106 @@ define_event!(FlashbangDetonate, GameEvent::FlashbangDetonate);
|
|||||||
define_event!(DecoyStarted, GameEvent::DecoyStarted);
|
define_event!(DecoyStarted, GameEvent::DecoyStarted);
|
||||||
define_event!(DecoyDetonate, GameEvent::DecoyDetonate);
|
define_event!(DecoyDetonate, GameEvent::DecoyDetonate);
|
||||||
|
|
||||||
define_event!(PlayerConnect, GameEvent::PlayerConnect, (address, RawValue), (bot, RawValue), (name, RawValue), (userid, RawValue), (networkid, RawValue), (xuid, RawValue));
|
define_event!(
|
||||||
define_event!(PlayerConnectFull, GameEvent::PlayerConnectFull, (userid, RawValue));
|
PlayerConnect,
|
||||||
define_event!(PlayerDisconnect, GameEvent::PlayerDisconnect, (userid, RawValue), (reason, RawValue), (name, RawValue), (networkid, RawValue), (xuid, RawValue));
|
GameEvent::PlayerConnect,
|
||||||
define_event!(PlayerFootstep, GameEvent::PlayerFootstep);
|
(address, RawValue),
|
||||||
define_event!(PlayerJump, GameEvent::PlayerJump);
|
(bot, RawValue),
|
||||||
define_event!(PlayerHurt, GameEvent::PlayerHurt);
|
(name, RawValue),
|
||||||
define_event!(PlayerDeath, GameEvent::PlayerDeath);
|
(userid, i32),
|
||||||
define_event!(PlayerSpawn, GameEvent::PlayerSpawn);
|
(networkid, RawValue),
|
||||||
define_event!(PlayerBlind, GameEvent::PlayerBlind);
|
(xuid, RawValue)
|
||||||
define_event!(PlayerTeam, GameEvent::PlayerTeam, (userid, RawValue), (team, RawValue), (oldteam, RawValue), (disconnect, RawValue), (silent, RawValue), (isbot, RawValue), (userid_pawn, RawValue));
|
);
|
||||||
|
define_event!(
|
||||||
|
PlayerConnectFull,
|
||||||
|
GameEvent::PlayerConnectFull,
|
||||||
|
(userid, UserId)
|
||||||
|
);
|
||||||
|
define_event!(
|
||||||
|
PlayerDisconnect,
|
||||||
|
GameEvent::PlayerDisconnect,
|
||||||
|
(userid, UserId),
|
||||||
|
(reason, RawValue),
|
||||||
|
(name, RawValue),
|
||||||
|
(networkid, RawValue),
|
||||||
|
(xuid, RawValue)
|
||||||
|
);
|
||||||
|
define_event!(
|
||||||
|
PlayerFootstep,
|
||||||
|
GameEvent::PlayerFootstep,
|
||||||
|
(userid, UserId),
|
||||||
|
(userid_pawn, RawValue)
|
||||||
|
);
|
||||||
|
define_event!(PlayerJump, GameEvent::PlayerJump, (userid, i32));
|
||||||
|
define_event!(
|
||||||
|
PlayerHurt,
|
||||||
|
GameEvent::PlayerHurt,
|
||||||
|
(userid, UserId),
|
||||||
|
(attacker, UserId),
|
||||||
|
(health, RawValue),
|
||||||
|
(armor, RawValue),
|
||||||
|
(weapon, String),
|
||||||
|
(dmg_health, RawValue),
|
||||||
|
(dmg_armor, RawValue),
|
||||||
|
(hitgroup, RawValue),
|
||||||
|
(userid_pawn, RawValue),
|
||||||
|
(attacker_pawn, RawValue)
|
||||||
|
);
|
||||||
|
define_event!(
|
||||||
|
PlayerDeath,
|
||||||
|
GameEvent::PlayerDeath,
|
||||||
|
(userid, UserId),
|
||||||
|
(attacker, UserId),
|
||||||
|
(assister, UserId),
|
||||||
|
(assistedflash, bool),
|
||||||
|
(weapon, String),
|
||||||
|
(weapon_itemid, String),
|
||||||
|
(weapon_fauxitemid, String),
|
||||||
|
(weapon_originalowner_xuid, String),
|
||||||
|
(headshot, bool),
|
||||||
|
(dominated, RawValue),
|
||||||
|
(revenge, RawValue),
|
||||||
|
(wipe, RawValue),
|
||||||
|
(penetrated, RawValue),
|
||||||
|
(noreplay, bool),
|
||||||
|
(noscope, bool),
|
||||||
|
(thrusmoke, bool),
|
||||||
|
(attackerblind, bool),
|
||||||
|
(distance, RawValue),
|
||||||
|
(userid_pawn, RawValue),
|
||||||
|
(attacker_pawn, RawValue),
|
||||||
|
(assister_pawn, RawValue),
|
||||||
|
(dmg_health, RawValue),
|
||||||
|
(dmg_armor, RawValue),
|
||||||
|
(hitgroup, RawValue),
|
||||||
|
(attackerinair, bool)
|
||||||
|
);
|
||||||
|
define_event!(
|
||||||
|
PlayerSpawn,
|
||||||
|
GameEvent::PlayerSpawn,
|
||||||
|
(userid, UserId),
|
||||||
|
(inrestart, RawValue),
|
||||||
|
(userid_pawn, RawValue)
|
||||||
|
);
|
||||||
|
define_event!(
|
||||||
|
PlayerBlind,
|
||||||
|
GameEvent::PlayerBlind,
|
||||||
|
(userid, UserId),
|
||||||
|
(attacker, RawValue),
|
||||||
|
(entityid, RawValue),
|
||||||
|
(blind_duration, RawValue)
|
||||||
|
);
|
||||||
|
define_event!(
|
||||||
|
PlayerTeam,
|
||||||
|
GameEvent::PlayerTeam,
|
||||||
|
(userid, UserId),
|
||||||
|
(team, RawValue),
|
||||||
|
(oldteam, RawValue),
|
||||||
|
(disconnect, RawValue),
|
||||||
|
(silent, RawValue),
|
||||||
|
(isbot, RawValue),
|
||||||
|
(userid_pawn, RawValue)
|
||||||
|
);
|
||||||
|
|
||||||
define_event!(BulletDamage, GameEvent::BulletDamage);
|
define_event!(BulletDamage, GameEvent::BulletDamage);
|
||||||
|
|
||||||
@@ -138,12 +208,18 @@ define_event!(RoundPreRestart, GameEvent::RoundPreRestart);
|
|||||||
define_event!(RoundTimeWarning, GameEvent::RoundTimeWarning);
|
define_event!(RoundTimeWarning, GameEvent::RoundTimeWarning);
|
||||||
define_event!(RoundFinalBeep, GameEvent::RoundFinalBeep);
|
define_event!(RoundFinalBeep, GameEvent::RoundFinalBeep);
|
||||||
define_event!(BuyTimeEnded, GameEvent::BuyTimeEnded);
|
define_event!(BuyTimeEnded, GameEvent::BuyTimeEnded);
|
||||||
define_event!(RoundAnnounceLastRoundHalf, GameEvent::RoundAnnounceLastRoundHalf);
|
define_event!(
|
||||||
|
RoundAnnounceLastRoundHalf,
|
||||||
|
GameEvent::RoundAnnounceLastRoundHalf
|
||||||
|
);
|
||||||
define_event!(AnnouncePhaseEnd, GameEvent::AnnouncePhaseEnd);
|
define_event!(AnnouncePhaseEnd, GameEvent::AnnouncePhaseEnd);
|
||||||
|
|
||||||
define_event!(WinPanelMatch, GameEvent::WinPanelMatch);
|
define_event!(WinPanelMatch, GameEvent::WinPanelMatch);
|
||||||
|
|
||||||
type ParseFn = fn(keys: &[csgo_proto::csvc_msg_game_event_list::KeyT], event: csgo_proto::CMsgSource1LegacyGameEvent) -> Result<GameEvent, ParseGameEventError>;
|
type ParseFn = fn(
|
||||||
|
keys: &[csgo_proto::csvc_msg_game_event_list::KeyT],
|
||||||
|
event: csgo_proto::CMsgSource1LegacyGameEvent,
|
||||||
|
) -> Result<GameEvent, ParseGameEventError>;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@@ -203,7 +279,7 @@ pub enum GameEvent {
|
|||||||
BuyTimeEnded(BuyTimeEnded),
|
BuyTimeEnded(BuyTimeEnded),
|
||||||
RoundAnnounceLastRoundHalf(RoundAnnounceLastRoundHalf),
|
RoundAnnounceLastRoundHalf(RoundAnnounceLastRoundHalf),
|
||||||
AnnouncePhaseEnd(AnnouncePhaseEnd),
|
AnnouncePhaseEnd(AnnouncePhaseEnd),
|
||||||
|
|
||||||
WinPanelMatch(WinPanelMatch),
|
WinPanelMatch(WinPanelMatch),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,7 +293,7 @@ pub static EVENT_PARSERS: phf::Map<&'static str, GameEventParser> = phf::phf_map
|
|||||||
|
|
||||||
"item_equip" => GameEventParser::new(ItemEquip::parse),
|
"item_equip" => GameEventParser::new(ItemEquip::parse),
|
||||||
"item_pickup" => GameEventParser::new(ItemPickup::parse),
|
"item_pickup" => GameEventParser::new(ItemPickup::parse),
|
||||||
|
|
||||||
"weapon_reload" => GameEventParser::new(WeaponReload::parse),
|
"weapon_reload" => GameEventParser::new(WeaponReload::parse),
|
||||||
"weapon_zoom" => GameEventParser::new(WeaponZoom::parse),
|
"weapon_zoom" => GameEventParser::new(WeaponZoom::parse),
|
||||||
"weapon_fire" => GameEventParser::new(WeaponFire::parse),
|
"weapon_fire" => GameEventParser::new(WeaponFire::parse),
|
||||||
@@ -230,7 +306,7 @@ pub static EVENT_PARSERS: phf::Map<&'static str, GameEventParser> = phf::phf_map
|
|||||||
"flashbang_detonate" => GameEventParser::new(FlashbangDetonate::parse),
|
"flashbang_detonate" => GameEventParser::new(FlashbangDetonate::parse),
|
||||||
"decoy_started" => GameEventParser::new(DecoyStarted::parse),
|
"decoy_started" => GameEventParser::new(DecoyStarted::parse),
|
||||||
"decoy_detonate" => GameEventParser::new(DecoyDetonate::parse),
|
"decoy_detonate" => GameEventParser::new(DecoyDetonate::parse),
|
||||||
|
|
||||||
"player_connect" => GameEventParser::new(PlayerConnect::parse),
|
"player_connect" => GameEventParser::new(PlayerConnect::parse),
|
||||||
"player_connect_full" => GameEventParser::new(PlayerConnectFull::parse),
|
"player_connect_full" => GameEventParser::new(PlayerConnectFull::parse),
|
||||||
"player_disconnect" => GameEventParser::new(PlayerDisconnect::parse),
|
"player_disconnect" => GameEventParser::new(PlayerDisconnect::parse),
|
||||||
@@ -241,7 +317,7 @@ pub static EVENT_PARSERS: phf::Map<&'static str, GameEventParser> = phf::phf_map
|
|||||||
"player_spawn" => GameEventParser::new(PlayerSpawn::parse),
|
"player_spawn" => GameEventParser::new(PlayerSpawn::parse),
|
||||||
"player_blind" => GameEventParser::new(PlayerBlind::parse),
|
"player_blind" => GameEventParser::new(PlayerBlind::parse),
|
||||||
"player_team" => GameEventParser::new(PlayerTeam::parse),
|
"player_team" => GameEventParser::new(PlayerTeam::parse),
|
||||||
|
|
||||||
"bullet_damage" => GameEventParser::new(BulletDamage::parse),
|
"bullet_damage" => GameEventParser::new(BulletDamage::parse),
|
||||||
|
|
||||||
"other_death" => GameEventParser::new(OtherDeath::parse),
|
"other_death" => GameEventParser::new(OtherDeath::parse),
|
||||||
@@ -273,17 +349,22 @@ pub static EVENT_PARSERS: phf::Map<&'static str, GameEventParser> = phf::phf_map
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub struct GameEventParser {
|
pub struct GameEventParser {
|
||||||
inner: fn(keys: &[csgo_proto::csvc_msg_game_event_list::KeyT], event: csgo_proto::CMsgSource1LegacyGameEvent) -> Result<GameEvent, ParseGameEventError>,
|
inner: fn(
|
||||||
|
keys: &[csgo_proto::csvc_msg_game_event_list::KeyT],
|
||||||
|
event: csgo_proto::CMsgSource1LegacyGameEvent,
|
||||||
|
) -> Result<GameEvent, ParseGameEventError>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GameEventParser {
|
impl GameEventParser {
|
||||||
pub const fn new(func: ParseFn) -> Self {
|
pub const fn new(func: ParseFn) -> Self {
|
||||||
Self {
|
Self { inner: func }
|
||||||
inner: func,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(&self, keys: &[csgo_proto::csvc_msg_game_event_list::KeyT], event: csgo_proto::CMsgSource1LegacyGameEvent) -> Result<GameEvent, ParseGameEventError> {
|
pub fn parse(
|
||||||
|
&self,
|
||||||
|
keys: &[csgo_proto::csvc_msg_game_event_list::KeyT],
|
||||||
|
event: csgo_proto::CMsgSource1LegacyGameEvent,
|
||||||
|
) -> Result<GameEvent, ParseGameEventError> {
|
||||||
if keys.len() != event.keys.len() {
|
if keys.len() != event.keys.len() {
|
||||||
return Err(ParseGameEventError::MismatchedKeysFields);
|
return Err(ParseGameEventError::MismatchedKeysFields);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ mod packet;
|
|||||||
pub use packet::DemoEvent;
|
pub use packet::DemoEvent;
|
||||||
pub mod game_event;
|
pub mod game_event;
|
||||||
|
|
||||||
|
mod values;
|
||||||
|
pub use values::*;
|
||||||
|
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
|
|
||||||
pub mod csgo_proto {
|
pub mod csgo_proto {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::{packet::DemoEvent, DemoCommand, Frame};
|
use crate::{packet::DemoEvent, DemoCommand, Frame, UserId};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum FirstPassError {
|
pub enum FirstPassError {
|
||||||
@@ -8,7 +8,7 @@ pub enum FirstPassError {
|
|||||||
MissingFileHeader,
|
MissingFileHeader,
|
||||||
MissingFileInfo,
|
MissingFileInfo,
|
||||||
Bitreader(crate::bitreader::BitReadError),
|
Bitreader(crate::bitreader::BitReadError),
|
||||||
ParseGameEventError(crate::game_event::ParseGameEventError)
|
ParseGameEventError(crate::game_event::ParseGameEventError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<prost::DecodeError> for FirstPassError {
|
impl From<prost::DecodeError> for FirstPassError {
|
||||||
@@ -38,12 +38,18 @@ pub struct FirstPassOutput {
|
|||||||
pub header: crate::csgo_proto::CDemoFileHeader,
|
pub header: crate::csgo_proto::CDemoFileHeader,
|
||||||
pub info: crate::csgo_proto::CDemoFileInfo,
|
pub info: crate::csgo_proto::CDemoFileInfo,
|
||||||
pub events: Vec<DemoEvent>,
|
pub events: Vec<DemoEvent>,
|
||||||
pub player_info: std::collections::HashMap<i32, Player>,
|
pub player_info: std::collections::HashMap<UserId, Player>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct GameEventMapping {
|
struct GameEventMapping {
|
||||||
mapping: std::collections::HashMap<i32, (String, Vec<crate::csgo_proto::csvc_msg_game_event_list::KeyT>)>,
|
mapping: std::collections::HashMap<
|
||||||
|
i32,
|
||||||
|
(
|
||||||
|
String,
|
||||||
|
Vec<crate::csgo_proto::csvc_msg_game_event_list::KeyT>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse<'b, FI>(frames: FI) -> Result<FirstPassOutput, FirstPassError>
|
pub fn parse<'b, FI>(frames: FI) -> Result<FirstPassOutput, FirstPassError>
|
||||||
@@ -87,14 +93,19 @@ where
|
|||||||
let header = header.ok_or(FirstPassError::MissingFileHeader)?;
|
let header = header.ok_or(FirstPassError::MissingFileHeader)?;
|
||||||
let info = file_info.ok_or(FirstPassError::MissingFileInfo)?;
|
let info = file_info.ok_or(FirstPassError::MissingFileInfo)?;
|
||||||
|
|
||||||
Ok(FirstPassOutput { header, info, events, player_info })
|
Ok(FirstPassOutput {
|
||||||
|
header,
|
||||||
|
info,
|
||||||
|
events,
|
||||||
|
player_info,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_fullpacket(
|
fn parse_fullpacket(
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
events: &mut Vec<DemoEvent>,
|
events: &mut Vec<DemoEvent>,
|
||||||
event_mapper: &mut GameEventMapping,
|
event_mapper: &mut GameEventMapping,
|
||||||
player_info: &mut std::collections::HashMap<i32, Player>,
|
player_info: &mut std::collections::HashMap<UserId, Player>,
|
||||||
) -> Result<(), FirstPassError> {
|
) -> Result<(), FirstPassError> {
|
||||||
let raw: crate::csgo_proto::CDemoFullPacket = prost::Message::decode(data)?;
|
let raw: crate::csgo_proto::CDemoFullPacket = prost::Message::decode(data)?;
|
||||||
|
|
||||||
@@ -115,7 +126,7 @@ fn parse_packet(
|
|||||||
data: &[u8],
|
data: &[u8],
|
||||||
events: &mut Vec<DemoEvent>,
|
events: &mut Vec<DemoEvent>,
|
||||||
event_mapper: &mut GameEventMapping,
|
event_mapper: &mut GameEventMapping,
|
||||||
player_info: &mut std::collections::HashMap<i32, Player>,
|
player_info: &mut std::collections::HashMap<UserId, Player>,
|
||||||
) -> Result<(), FirstPassError> {
|
) -> Result<(), FirstPassError> {
|
||||||
let raw: crate::csgo_proto::CDemoPacket = prost::Message::decode(data)?;
|
let raw: crate::csgo_proto::CDemoPacket = prost::Message::decode(data)?;
|
||||||
|
|
||||||
@@ -128,7 +139,7 @@ fn inner_parse_packet(
|
|||||||
raw: &crate::csgo_proto::CDemoPacket,
|
raw: &crate::csgo_proto::CDemoPacket,
|
||||||
events: &mut Vec<DemoEvent>,
|
events: &mut Vec<DemoEvent>,
|
||||||
event_mapper: &mut GameEventMapping,
|
event_mapper: &mut GameEventMapping,
|
||||||
player_info: &mut std::collections::HashMap<i32, Player>,
|
player_info: &mut std::collections::HashMap<UserId, Player>,
|
||||||
) -> Result<(), FirstPassError> {
|
) -> Result<(), FirstPassError> {
|
||||||
let mut bitreader = crate::bitreader::Bitreader::new(raw.data());
|
let mut bitreader = crate::bitreader::Bitreader::new(raw.data());
|
||||||
|
|
||||||
@@ -167,7 +178,8 @@ fn inner_parse_packet(
|
|||||||
events.push(DemoEvent::ServerInfo(raw));
|
events.push(DemoEvent::ServerInfo(raw));
|
||||||
}
|
}
|
||||||
crate::netmessagetypes::NetmessageType::net_SignonState => {
|
crate::netmessagetypes::NetmessageType::net_SignonState => {
|
||||||
let raw: crate::csgo_proto::CnetMsgSignonState = prost::Message::decode(msg_bytes.as_slice())?;
|
let raw: crate::csgo_proto::CnetMsgSignonState =
|
||||||
|
prost::Message::decode(msg_bytes.as_slice())?;
|
||||||
dbg!(raw);
|
dbg!(raw);
|
||||||
}
|
}
|
||||||
crate::netmessagetypes::NetmessageType::net_Tick => {
|
crate::netmessagetypes::NetmessageType::net_Tick => {
|
||||||
@@ -228,13 +240,17 @@ fn inner_parse_packet(
|
|||||||
crate::netmessagetypes::NetmessageType::TE_EffectDispatch => {}
|
crate::netmessagetypes::NetmessageType::TE_EffectDispatch => {}
|
||||||
crate::netmessagetypes::NetmessageType::CS_UM_PlayerStatsUpdate => {}
|
crate::netmessagetypes::NetmessageType::CS_UM_PlayerStatsUpdate => {}
|
||||||
crate::netmessagetypes::NetmessageType::CS_UM_EndOfMatchAllPlayersData => {
|
crate::netmessagetypes::NetmessageType::CS_UM_EndOfMatchAllPlayersData => {
|
||||||
let raw: crate::csgo_proto::CcsUsrMsgEndOfMatchAllPlayersData = prost::Message::decode(msg_bytes.as_slice())?;
|
let raw: crate::csgo_proto::CcsUsrMsgEndOfMatchAllPlayersData =
|
||||||
|
prost::Message::decode(msg_bytes.as_slice())?;
|
||||||
|
|
||||||
for data in raw.allplayerdata {
|
for data in raw.allplayerdata {
|
||||||
player_info.insert(data.slot(), Player {
|
player_info.insert(
|
||||||
name: data.name.unwrap(),
|
UserId(data.slot()),
|
||||||
xuid: data.xuid.unwrap(),
|
Player {
|
||||||
});
|
name: data.name.unwrap(),
|
||||||
|
xuid: data.xuid.unwrap(),
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
crate::netmessagetypes::NetmessageType::TE_PhysicsProp => {}
|
crate::netmessagetypes::NetmessageType::TE_PhysicsProp => {}
|
||||||
|
|||||||
71
src/values.rs
Normal file
71
src/values.rs
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
#[derive(Debug)]
|
||||||
|
pub enum RawValue {
|
||||||
|
String(String),
|
||||||
|
F32(f32),
|
||||||
|
I32(i32),
|
||||||
|
Bool(bool),
|
||||||
|
U64(u64),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<crate::csgo_proto::c_msg_source1_legacy_game_event::KeyT> for RawValue {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_from(
|
||||||
|
value: crate::csgo_proto::c_msg_source1_legacy_game_event::KeyT,
|
||||||
|
) -> Result<Self, Self::Error> {
|
||||||
|
match value.r#type() {
|
||||||
|
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())),
|
||||||
|
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)),
|
||||||
|
5 if value.val_byte.is_some() => Ok(Self::I32(value.val_byte.unwrap() as i32)),
|
||||||
|
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())),
|
||||||
|
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)),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<RawValue> for i32 {
|
||||||
|
type Error = ();
|
||||||
|
fn try_from(value: RawValue) -> Result<Self, Self::Error> {
|
||||||
|
match value {
|
||||||
|
RawValue::I32(v) => Ok(v),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl TryFrom<RawValue> for bool {
|
||||||
|
type Error = ();
|
||||||
|
fn try_from(value: RawValue) -> Result<Self, Self::Error> {
|
||||||
|
match value {
|
||||||
|
RawValue::Bool(v) => Ok(v),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl TryFrom<RawValue> for String {
|
||||||
|
type Error = ();
|
||||||
|
fn try_from(value: RawValue) -> Result<Self, Self::Error> {
|
||||||
|
match value {
|
||||||
|
RawValue::String(v) => Ok(v),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||||
|
pub struct UserId(pub(crate) i32);
|
||||||
|
|
||||||
|
impl TryFrom<RawValue> for UserId {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_from(value: RawValue) -> Result<Self, Self::Error> {
|
||||||
|
match value {
|
||||||
|
RawValue::I32(v) => Ok(Self(v)),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use csdemo::{game_event::GameEvent, DemoEvent};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn mirage_1() {
|
fn mirage_1() {
|
||||||
let content = std::fs::read("testfiles/mirage.dem").unwrap();
|
let content = std::fs::read("testfiles/mirage.dem").unwrap();
|
||||||
@@ -11,7 +13,27 @@ fn mirage_1() {
|
|||||||
|
|
||||||
assert_eq!("de_mirage", output.header.map_name());
|
assert_eq!("de_mirage", output.header.map_name());
|
||||||
|
|
||||||
todo!()
|
for event in output.events.iter() {
|
||||||
|
match event {
|
||||||
|
DemoEvent::GameEvent(gevent) => match gevent {
|
||||||
|
GameEvent::PlayerDeath(death) => {
|
||||||
|
assert!(
|
||||||
|
death.remaining.is_empty(),
|
||||||
|
"Remaining for PlayerDeath: {:?}",
|
||||||
|
death.remaining
|
||||||
|
);
|
||||||
|
|
||||||
|
let died_user = output
|
||||||
|
.player_info
|
||||||
|
.get(death.userid.as_ref().unwrap())
|
||||||
|
.unwrap();
|
||||||
|
dbg!(died_user);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user