diff --git a/README.md b/README.md index d2623b6f..bd381df6 100644 --- a/README.md +++ b/README.md @@ -153,9 +153,16 @@ True/Flase if player is pressing button. (buttons is the real value of m_nButtonDownMaskPrev and the others are derived from it) -#### Match info (same for all players) +#### Match info | Name | Real name | | :-------------------: | :----------------------------------- | +|team_rounds_total|m_iScore| +|team_surrendered|m_bSurrendered| +|team_name|m_szTeamname| +|team_score_overtime|m_scoreOvertime| +|team_match_stat|m_szTeamMatchStat| +|team_num_map_victories|m_numMapVictories| +|team_score_first_half| m_scoreFirstHalf | | team_score_second_half | m_scoreSecondHalf | | team_clan_name | m_szClanTeamname | | is_freeze_period | m_bFreezePeriod | diff --git a/src/parser/src/collect_data.rs b/src/parser/src/collect_data.rs index d7c0dc6f..5a18494d 100644 --- a/src/parser/src/collect_data.rs +++ b/src/parser/src/collect_data.rs @@ -121,7 +121,6 @@ impl ParserThread { // All values come trough here. None if cant be found. match self.find_prop(prop_info, entity_id, player) { Ok(prop) => { - // println!("{} {:?}", prop_info.prop_name, prop); self.output .entry(prop_info.id) .or_insert_with(|| PropColumn::new()) @@ -129,7 +128,6 @@ impl ParserThread { } Err(_e) => { // Ultimate debugger is to print this error - // println!("{} {:?} {}", self.tick, _e, prop_info.prop_name); self.output .entry(prop_info.id) .or_insert_with(|| PropColumn::new()) @@ -315,10 +313,12 @@ impl ParserThread { None => return Err(PropCollectionError::SpecialidsItemDefNotSet), }; match self.find_weapon_prop(&item_def_id, entity_id) { - Ok(Variant::U32(def_idx)) => match WEAPINDICIES.get(&def_idx) { - Some(v) => return Ok(Variant::String(v.to_string())), - None => return Err(PropCollectionError::WeaponIdxMappingNotFound), - }, + Ok(Variant::U32(def_idx)) => { + match WEAPINDICIES.get(&def_idx) { + Some(v) => return Ok(Variant::String(v.to_string())), + None => return Err(PropCollectionError::WeaponIdxMappingNotFound), + }; + } Ok(_) => return Err(PropCollectionError::WeaponDefVariantWrongType), Err(e) => Err(e), } diff --git a/src/parser/src/entities.rs b/src/parser/src/entities.rs index b6d8d928..7750d4f7 100644 --- a/src/parser/src/entities.rs +++ b/src/parser/src/entities.rs @@ -284,25 +284,37 @@ impl ParserThread { }, Err(_) => None, }; - match player_entid { - Some(e) => { - if e != 2047 && steamid != Some(0) && team_num != Some(1) { - self.players.insert( - e, - PlayerMetaData { - name: name, - team_num: team_num, - player_entity_id: player_entid, - steamid: steamid, - controller_entid: Some(*entity_id), - }, - ); + if let Some(e) = player_entid { + if e != 2047 && steamid != Some(0) && team_num != Some(1) { + match self.should_remove(steamid) { + Some(eid) => { + self.players.remove(&eid); + } + None => {} } + self.players.insert( + e, + PlayerMetaData { + name: name, + team_num: team_num, + player_entity_id: player_entid, + steamid: steamid, + controller_entid: Some(*entity_id), + }, + ); } - _ => {} } Ok(()) } + fn should_remove(&self, steamid: Option) -> Option { + for (entid, player) in &self.players { + if player.steamid == steamid { + return Some(*entid); + } + } + None + } + fn create_new_entity(&mut self, bitreader: &mut Bitreader, entity_id: &i32) -> Result<(), DemoParserError> { let cls_id: u32 = bitreader.read_nbits(8)?; // Both of these are not used. Don't think they are interesting for the parser diff --git a/src/parser/src/game_events.rs b/src/parser/src/game_events.rs index 55ac4e03..4f38248d 100644 --- a/src/parser/src/game_events.rs +++ b/src/parser/src/game_events.rs @@ -36,7 +36,7 @@ impl Parser { impl ParserThread { pub fn parse_event(&mut self, bytes: &[u8]) -> Result<(), DemoParserError> { - if self.wanted_events.len() == 0 { + if self.wanted_events.len() == 0 && self.wanted_events.first() != Some(&"all".to_string()) { return Ok(()); } let event: CSVCMsg_GameEvent = Message::parse_from_bytes(&bytes).unwrap(); @@ -171,9 +171,8 @@ impl ParserThread { */ pub fn find_extra_props_events(&self, entity_id: i32, prefix: &str) -> Result, DemoParserError> { let mut extra_pairs = vec![]; - // prop name: for prop_info in &self.prop_controller.prop_infos { - // These are meant for entities not used here + // These are meant for entities and should not be collected here if prop_info.prop_name == "tick" || prop_info.prop_name == "name" || prop_info.prop_name == "steamid" { continue; } diff --git a/src/parser/src/parser.rs b/src/parser/src/parser.rs index 1424d62d..64cb1723 100644 --- a/src/parser/src/parser.rs +++ b/src/parser/src/parser.rs @@ -25,7 +25,6 @@ use rayon::iter::ParallelIterator; use rayon::prelude::IntoParallelRefIterator; use snap::raw::Decoder as SnapDecoder; use std::sync::Arc; -use std::time::Instant; #[derive(Debug)] pub struct DemoOutput { @@ -73,6 +72,7 @@ impl Parser { true => SnapDecoder::new().decompress_vec(self.read_n_bytes(size).unwrap()).unwrap(), false => self.read_n_bytes(size)?.to_vec(), }; + let ok: Result<(), DemoParserError> = match demo_cmd { DEM_SendTables => { sendtable = Some(Message::parse_from_bytes(&bytes).unwrap()); @@ -94,11 +94,6 @@ impl Parser { }; ok?; } - let input = self.create_parser_thread_input(16, true); - let mut parser = ParserThread::new(input).unwrap(); - parser.start().unwrap(); - return Ok(parser.create_output()); - let mut outputs: Vec = self .fullpacket_offsets .par_iter() @@ -184,15 +179,6 @@ impl Parser { } impl Parser { - pub fn is_ready_to_spawn_thread(&self) -> bool { - /* - println!( - "{} {} {} {}", - self.qf_map_set, self.cls_by_id_set, self.ge_list_set, self.prop_controller_is_set - ); - */ - self.qf_map_set && self.cls_by_id_set && self.ge_list_set && self.prop_controller_is_set - } pub fn parse_packet(&mut self, bytes: &[u8]) -> Result<(), DemoParserError> { let packet: CDemoPacket = Message::parse_from_bytes(bytes).unwrap(); let packet_data = packet.data.unwrap(); diff --git a/src/parser/src/parser_threads.rs b/src/parser/src/parser_threads.rs index ba6a98ad..18c6dced 100644 --- a/src/parser/src/parser_threads.rs +++ b/src/parser/src/parser_threads.rs @@ -19,6 +19,7 @@ impl ParserThread { let cmd = self.read_varint()?; let tick = self.read_varint()?; let size = self.read_varint()?; + self.tick = tick as i32; self.packets_parsed += 1; diff --git a/src/parser/src/read_bits.rs b/src/parser/src/read_bits.rs index 7eab6836..27b1fe85 100644 --- a/src/parser/src/read_bits.rs +++ b/src/parser/src/read_bits.rs @@ -26,6 +26,7 @@ pub enum DemoParserError { ClsIdOutOfBounds, UnknownGameEventVariant(String), // UnknownEntityHandle(String, V), FileNotFound(String), + NoEvents, } impl std::error::Error for DemoParserError {} diff --git a/src/parser/src/variants.rs b/src/parser/src/variants.rs index 22b84705..b83166e5 100644 --- a/src/parser/src/variants.rs +++ b/src/parser/src/variants.rs @@ -57,7 +57,6 @@ impl PropColumn { num_nones: 0, } } - pub fn new_empty_from(propcol: &PropColumn) {} pub fn len(&self) -> usize { match &self.data { diff --git a/src/python/Cargo.toml b/src/python/Cargo.toml index 4ea35b41..2c87d001 100644 --- a/src/python/Cargo.toml +++ b/src/python/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "demoparser2" -version = "0.1.6" +version = "0.2.0" edition = "2021" diff --git a/src/python/src/lib.rs b/src/python/src/lib.rs index b916ff63..d80a4cd9 100644 --- a/src/python/src/lib.rs +++ b/src/python/src/lib.rs @@ -140,7 +140,7 @@ impl DemoParser { wanted_player_props_og_names: vec![], wanted_other_props: vec![], wanted_other_props_og_names: vec![], - wanted_events: vec![], + wanted_events: vec!["all".to_string()], parse_ents: false, wanted_ticks: vec![], parse_projectiles: false, @@ -611,7 +611,12 @@ impl DemoParser { }; let event_series = match series_from_event(&output.game_events) { Ok(ser) => ser, - Err(e) => return Err(PyValueError::new_err(format!("{}", e))), + Err(_e) => { + return Err(Exception::new_err(format!( + "No {:?} events found in demo.", + event_name + ))) + } }; Ok(event_series) } @@ -905,14 +910,16 @@ pub fn series_from_multiple_events( let py_series = rust_series_to_py_series(&ser).unwrap(); all_series.push(py_series); } - let dfp = Python::with_gil(|py| { - let polars = py.import("polars").unwrap(); - let df = polars.call_method1("DataFrame", (all_series,)).unwrap(); - df.setattr("columns", column_names.to_object(py)).unwrap(); - let pandas_df = df.call_method0("to_pandas").unwrap(); - pandas_df.to_object(py) - }); - vv.push((k, dfp)); + if rows != 0 { + let dfp = Python::with_gil(|py| { + let polars = py.import("polars").unwrap(); + let df = polars.call_method1("DataFrame", (all_series,)).unwrap(); + df.setattr("columns", column_names.to_object(py)).unwrap(); + let pandas_df = df.call_method0("to_pandas").unwrap(); + pandas_df.to_object(py) + }); + vv.push((k, dfp)); + } } Ok(vv.to_object(py)) } @@ -935,6 +942,9 @@ pub fn series_from_event(events: &Vec) -> Result, DemoParse let py_series = rust_series_to_py_series(&ser).unwrap(); all_series.push(py_series); } + if rows == 0 { + return Err(DemoParserError::NoEvents); + } let dfp = Python::with_gil(|py| { let polars = py.import("polars").unwrap(); let df = polars.call_method1("DataFrame", (all_series,)).unwrap();