From 10da0883a10be097ad3fdf1819ee64ecd64c0259 Mon Sep 17 00:00:00 2001 From: Janek <development@superyu.xyz> Date: Wed, 17 Apr 2024 18:55:46 +0200 Subject: [PATCH] feat: faster bomb holder search Fully batched bomb holder search --- src/dma/context/mod.rs | 94 ++++++++++++++++++++++++++++++++++++++- src/dma/mod.rs | 48 ++++++-------------- src/dma/threaddata/mod.rs | 2 +- 3 files changed, 108 insertions(+), 36 deletions(-) diff --git a/src/dma/context/mod.rs b/src/dma/context/mod.rs index 8ee5e75..755bc4b 100755 --- a/src/dma/context/mod.rs +++ b/src/dma/context/mod.rs @@ -144,6 +144,97 @@ impl DmaCtx { Ok(is_controller) } + pub fn get_c4_holder(&mut self, pawns: Vec<Address>, entity_list: Address) -> Option<Address> { + // (pawn, wep_services, wep_count, wep_base) + let mut data_vec: Vec<(Address, u64, i32, u64)> = pawns + .into_iter() + .map(|pawn| (pawn, 0u64, 0i32, 0u64)) + .collect(); + + // Get wep_services + let mut batcher = self.process.batcher(); + data_vec.iter_mut().for_each(|(pawn, wep_services, _, _)| { + batcher.read_into(*pawn + cs2dumper::client::C_BasePlayerPawn::m_pWeaponServices, wep_services); + }); + drop(batcher); + + // Get wep_count and wep_base + let mut batcher = self.process.batcher(); + data_vec.iter_mut().for_each(|(_, wep_services, wep_count, wep_base)| { + batcher.read_into((*wep_services + cs2dumper::client::CPlayer_WeaponServices::m_hMyWeapons as u64).into(), wep_count); + batcher.read_into((*wep_services + cs2dumper::client::CPlayer_WeaponServices::m_hMyWeapons as u64 + 0x8).into() , wep_base); + }); + drop(batcher); + + // Rebuild data vec + // Vec<(pawn, wep_base, Vec<(buff, buff2)>)> + let mut data_vec: Vec<(Address, u64, Vec<(u64, i32)>)> = data_vec + .into_iter() + .map(|(pawn, _, wep_count, wep_base)| { + let weps = (0..wep_count).into_iter().map(|idx| (0u64, idx)).collect(); + (pawn, wep_base, weps) + }) + .collect(); + + // Get handle + let mut batcher = self.process.batcher(); + data_vec.iter_mut().for_each(|(_, wep_base, wep_data_vec)| { + wep_data_vec.iter_mut().for_each(|(_, idx)| { + let b: Address = (*wep_base).into(); + batcher.read_into(b + * idx * 0x4, idx); + }); + }); + drop(batcher); + + // Get list entry + let mut batcher = self.process.batcher(); + data_vec.iter_mut().for_each(|(_, _, wep_data_vec)| { + wep_data_vec.iter_mut().for_each(|(list_entry, handle)| { + batcher.read_into(entity_list + 0x8 * ((*handle & 0x7FFF) >> 9) + 16, list_entry); + }); + }); + drop(batcher); + + // Get wep ptr + let mut batcher = self.process.batcher(); + data_vec.iter_mut().for_each(|(_, _, wep_data_vec)| { + wep_data_vec.iter_mut().for_each(|(list_entry, handle)| { + let le: Address = (*list_entry).into(); + batcher.read_into(le + 120 * (*handle & 0x1FF), list_entry); + }); + }); + drop(batcher); + + // Get wep data + let mut batcher = self.process.batcher(); + data_vec.iter_mut().for_each(|(_, _, wep_data_vec)| { + wep_data_vec.iter_mut().for_each(|(wep_ptr, _)| { + let b: Address = (*wep_ptr).into(); + batcher.read_into(b + cs2dumper::client::C_BaseEntity::m_nSubclassID + 0x8, wep_ptr); + }); + }); + drop(batcher); + + // Get wep id + let mut batcher = self.process.batcher(); + data_vec.iter_mut().for_each(|(_, _, wep_data_vec)| { + wep_data_vec.iter_mut().for_each(|(wep_data, id)| { + let b: Address = (*wep_data).into(); + batcher.read_into(b + cs2dumper::client::CCSWeaponBaseVData::m_WeaponType, id); + }); + }); + drop(batcher); + + let holder = data_vec.into_iter().find(|(_, _, wep_data_vec)| { + wep_data_vec.iter().find(|(_, id)| { *id == 7 }).is_some() + }); + + match holder { + Some((addr, _, _)) => Some(addr), + None => None, + } + } + // Todo: Optimize this function: find another way to do this pub fn has_c4(&mut self, pawn: Address, entity_list: Address) -> anyhow::Result<bool> { let mut has_c4 = false; @@ -165,7 +256,8 @@ impl DmaCtx { let ptr = self.process.read_addr64(list_entry + 120 * (handle & 0x1FF))?; Some(ptr) } - } { + } + { let wep_data = self.process.read_addr64(wep_ptr + cs2dumper::client::C_BaseEntity::m_nSubclassID + 0x8)?; let id: i32 = self.process.read(wep_data + cs2dumper::client::CCSWeaponBaseVData::m_WeaponType)?; diff --git a/src/dma/mod.rs b/src/dma/mod.rs index 5b4da83..5e926e7 100755 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -1,8 +1,8 @@ use std::{thread, time::{Duration, Instant}}; -use memflow::{os::Process, types::Address, mem::MemoryView}; +use memflow::{os::Process, mem::MemoryView}; -use crate::{enums::{TeamID, PlayerType}, comms::{EntityData, PlayerData, RadarData, ArcRwlockRadarData, BombData}}; +use crate::{enums::PlayerType, comms::{EntityData, PlayerData, RadarData, ArcRwlockRadarData, BombData}}; use self::{context::DmaCtx, threaddata::CsData}; @@ -54,6 +54,12 @@ pub async fn run(radar_data: ArcRwlockRadarData, connector: Connector, pcileech_ data.recheck_bomb_holder = true; } + if data.recheck_bomb_holder { + let pawns = data.players.clone().into_iter().map(|(_, pawn)| pawn).collect(); + data.bomb_holder = ctx.get_c4_holder(pawns, data.entity_list.into()); + data.recheck_bomb_holder = false; + } + let bomb_defuse_timeleft: f32 = { if data.bomb_planted && !data.bomb_exploded && !data.bomb_defused { if let Some(bomb_stamp) = data.bomb_planted_stamp { @@ -123,23 +129,9 @@ pub async fn run(radar_data: ArcRwlockRadarData, connector: Connector, pcileech_ ).unwrap(); if local_data.health > 0 { - let has_bomb = { - if data.bomb_planted || data.bomb_dropped { - false - } else if data.recheck_bomb_holder { - if local_data.team == Some(TeamID::T) && !data.bomb_dropped && !data.bomb_planted { - let is_holder = ctx.has_c4( - data.local_pawn.into(), data.entity_list.into() - ).unwrap_or(false); - - if is_holder { - data.bomb_holder = data.local.into(); - data.recheck_bomb_holder = false; - } - - is_holder - } else { false } - } else { Address::from(data.local) == data.bomb_holder } + let has_bomb = match data.bomb_holder { + Some(bh) => data.local_pawn == bh.to_umem(), + None => false, }; entity_data.push( @@ -164,21 +156,9 @@ pub async fn run(radar_data: ArcRwlockRadarData, connector: Connector, pcileech_ continue; } - let has_bomb = { - if data.bomb_planted { - false - } else if data.recheck_bomb_holder { - if player_data.team == Some(TeamID::T) && !data.bomb_dropped && !data.bomb_planted { - let is_holder = ctx.has_c4(*pawn, data.entity_list.into()).unwrap_or(false); - - if is_holder { - data.bomb_holder = *controller; - data.recheck_bomb_holder = false; - } - - is_holder - } else { false } - } else { *controller == data.bomb_holder } + let has_bomb = match data.bomb_holder { + Some(bh) => *pawn == bh, + None => false, }; let player_type = { diff --git a/src/dma/threaddata/mod.rs b/src/dma/threaddata/mod.rs index efdf66f..40df3c0 100755 --- a/src/dma/threaddata/mod.rs +++ b/src/dma/threaddata/mod.rs @@ -9,7 +9,7 @@ pub struct CsData { // Entities pub players: Vec<(Address, Address)>, pub bomb: Address, - pub bomb_holder: Address, + pub bomb_holder: Option<Address>, pub recheck_bomb_holder: bool, // Pointers