optimize (not done yet)
- alpha-alpha implementation of CachedView in csflow.
- MUCH faster entity cache build time thanks to two professionally engineered functions 😎
This commit is contained in:
@@ -16,12 +16,12 @@ impl MemoryClass for CBaseEntity {
|
||||
|
||||
impl BaseEntity for CBaseEntity {
|
||||
fn from_index(ctx: &mut CheatCtx, entity_list: Address, index: i32) -> Result<Option<CBaseEntity>, Error> {
|
||||
let list_entry = ctx.process.read_addr64(entity_list + 8 * (index >> 9) + 16)?;
|
||||
let list_entry = ctx.memory.read_addr64(entity_list + 8 * (index >> 9) + 16)?;
|
||||
if list_entry.is_null() && !list_entry.is_valid() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let player_ptr = ctx.process.read_addr64(list_entry + 120 * (index & 0x1FF))?;
|
||||
let player_ptr = ctx.memory.read_addr64(list_entry + 120 * (index & 0x1FF))?;
|
||||
if player_ptr.is_null() && !player_ptr.is_valid() {
|
||||
return Ok(None);
|
||||
}
|
||||
@@ -30,14 +30,28 @@ impl BaseEntity for CBaseEntity {
|
||||
}
|
||||
|
||||
fn pos(&self, ctx: &mut CheatCtx) -> Result<Vec3, Error> {
|
||||
let node = ctx.process.read_addr64(self.0 + cs2dumper::client::C_BaseEntity::m_pGameSceneNode)?;
|
||||
Ok(ctx.process.read(node + cs2dumper::client::CGameSceneNode::m_vecAbsOrigin)?)
|
||||
let node = ctx.memory.read_addr64(self.0 + cs2dumper::client::C_BaseEntity::m_pGameSceneNode)?;
|
||||
Ok(ctx.memory.read(node + cs2dumper::client::CGameSceneNode::m_vecAbsOrigin)?)
|
||||
}
|
||||
|
||||
fn class_name(&self, ctx: &mut CheatCtx) -> Result<String, Error> {
|
||||
let entity_identity_ptr = ctx.process.read_addr64(self.0 + cs2dumper::client::CEntityInstance::m_pEntity)?;
|
||||
let class_name_ptr = ctx.process.read_addr64(entity_identity_ptr + cs2dumper::client::CEntityIdentity::m_designerName)?;
|
||||
Ok(ctx.process.read_char_string_n(class_name_ptr, 32)?)
|
||||
Ok(ctx.memory.read_char_string_n(class_name_ptr, 32)?)
|
||||
}
|
||||
|
||||
fn next_by_class(&self, ctx: &mut CheatCtx) -> Result<Self, Error> where Self: std::marker::Sized {
|
||||
let entity_identity_ptr = ctx.process.read_addr64(self.0 + cs2dumper::client::CEntityInstance::m_pEntity)?;
|
||||
let next_by_class_ptr = ctx.process.read_addr64(entity_identity_ptr + cs2dumper::client::CEntityIdentity::m_pNextByClass)?;
|
||||
let entity_ptr = ctx.process.read_addr64(next_by_class_ptr)?;
|
||||
Ok(Self(entity_ptr))
|
||||
}
|
||||
|
||||
fn previous_by_class(&self, ctx: &mut CheatCtx) -> Result<Self, Error> where Self: std::marker::Sized {
|
||||
let entity_identity_ptr = ctx.memory.read_addr64(self.0 + cs2dumper::client::CEntityInstance::m_pEntity)?;
|
||||
let next_by_class_ptr = ctx.process.read_addr64(entity_identity_ptr + cs2dumper::client::CEntityIdentity::m_pPrevByClass)?;
|
||||
let entity_ptr = ctx.process.read_addr64(next_by_class_ptr)?;
|
||||
Ok(Self(entity_ptr))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,4 +59,24 @@ impl CBaseEntity {
|
||||
pub fn to_player_controller(&self) -> super::CPlayerController {
|
||||
super::CPlayerController::new(self.0)
|
||||
}
|
||||
|
||||
/// Professionally engineered function to quickly check if the entity has class name "weapon_c4"
|
||||
pub fn is_dropped_c4(&self, ctx: &mut CheatCtx) -> Result<bool, Error> {
|
||||
let entity_identity_ptr = ctx.process.read_addr64(self.0 + cs2dumper::client::CEntityInstance::m_pEntity)?;
|
||||
let class_name_ptr = ctx.process.read_addr64(entity_identity_ptr + cs2dumper::client::CEntityIdentity::m_designerName)?;
|
||||
|
||||
let data = ctx.process.read_raw(class_name_ptr + 7, 2)?;
|
||||
let is_c4 = data == "c4".as_bytes();
|
||||
Ok(is_c4)
|
||||
}
|
||||
|
||||
/// Professionally engineered function to quickly check if the entity has class name "cs_player_controller"
|
||||
pub fn is_cs_player_controller(&self, ctx: &mut CheatCtx) -> Result<bool, Error> {
|
||||
let entity_identity_ptr = ctx.process.read_addr64(self.0 + cs2dumper::client::CEntityInstance::m_pEntity)?;
|
||||
let class_name_ptr = ctx.process.read_addr64(entity_identity_ptr + cs2dumper::client::CEntityIdentity::m_designerName)?;
|
||||
|
||||
let data = ctx.process.read_raw(class_name_ptr, 20)?;
|
||||
let is_controller = data == "cs_player_controller".as_bytes();
|
||||
Ok(is_controller)
|
||||
}
|
||||
}
|
||||
@@ -18,12 +18,12 @@ impl MemoryClass for CPlayerController {
|
||||
|
||||
impl BaseEntity for CPlayerController {
|
||||
fn from_index(ctx: &mut CheatCtx, entity_list: Address, index: i32) -> Result<Option<CPlayerController>, Error> {
|
||||
let list_entry = ctx.process.read_addr64(entity_list + 8 * (index >> 9) + 16)?;
|
||||
let list_entry = ctx.memory.read_addr64(entity_list + 8 * (index >> 9) + 16)?;
|
||||
if list_entry.is_null() && !list_entry.is_valid() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let player_ptr = ctx.process.read_addr64(list_entry + 120 * (index & 0x1FF))?;
|
||||
let player_ptr = ctx.memory.read_addr64(list_entry + 120 * (index & 0x1FF))?;
|
||||
if player_ptr.is_null() && !player_ptr.is_valid() {
|
||||
return Ok(None);
|
||||
}
|
||||
@@ -31,27 +31,52 @@ impl BaseEntity for CPlayerController {
|
||||
Ok(Some(Self::new(player_ptr)))
|
||||
}
|
||||
|
||||
/// This function is slower because of an additional pointer read, use pawn.pos() instead.
|
||||
fn pos(&self, ctx: &mut CheatCtx) -> Result<Vec3, Error> {
|
||||
let node = ctx.process.read_addr64(self.0 + cs2dumper::client::C_BaseEntity::m_pGameSceneNode)?;
|
||||
Ok(ctx.process.read(node + cs2dumper::client::CGameSceneNode::m_vecAbsOrigin)?)
|
||||
let node = ctx.memory.read_addr64(self.0 + cs2dumper::client::C_BaseEntity::m_pGameSceneNode)?;
|
||||
Ok(ctx.memory.read(node + cs2dumper::client::CGameSceneNode::m_vecAbsOrigin)?)
|
||||
}
|
||||
|
||||
fn class_name(&self, ctx: &mut CheatCtx) -> Result<String, Error> {
|
||||
let entity_identity_ptr = ctx.process.read_addr64(self.0 + cs2dumper::client::CEntityInstance::m_pEntity)?;
|
||||
let class_name_ptr = ctx.process.read_addr64(entity_identity_ptr + cs2dumper::client::CEntityIdentity::m_designerName)?;
|
||||
Ok(ctx.process.read_char_string_n(class_name_ptr, 32)?)
|
||||
Ok(ctx.memory.read_char_string_n(class_name_ptr, 32)?)
|
||||
}
|
||||
|
||||
fn next_by_class(&self, ctx: &mut CheatCtx) -> Result<Self, Error> where Self: std::marker::Sized {
|
||||
let entity_identity_ptr = ctx.process.read_addr64(self.0 + cs2dumper::client::CEntityInstance::m_pEntity)?;
|
||||
let next_by_class_ptr = ctx.process.read_addr64(entity_identity_ptr + cs2dumper::client::CEntityIdentity::m_pNextByClass)?;
|
||||
|
||||
let class_name_ptr = ctx.process.read_addr64(entity_identity_ptr + cs2dumper::client::CEntityIdentity::m_designerName)?;
|
||||
let class_name= ctx.process.read_char_string_n(class_name_ptr, 32)?;
|
||||
|
||||
println!("class_name: {}", class_name);
|
||||
|
||||
let stringable_index: i32 = ctx.process.read(entity_identity_ptr + cs2dumper::client::CEntityIdentity::m_nameStringableIndex)?;
|
||||
println!("stringable_index: {}", stringable_index);
|
||||
|
||||
let entity_ptr = ctx.process.read_addr64(next_by_class_ptr)?;
|
||||
println!("entity_ptr: {}", entity_ptr);
|
||||
Ok(Self(entity_ptr))
|
||||
}
|
||||
|
||||
fn previous_by_class(&self, ctx: &mut CheatCtx) -> Result<Self, Error> where Self: std::marker::Sized {
|
||||
let entity_identity_ptr = ctx.process.read_addr64(self.0 + cs2dumper::client::CEntityInstance::m_pEntity)?;
|
||||
let next_by_class_ptr = ctx.process.read_addr64(entity_identity_ptr + cs2dumper::client::CEntityIdentity::m_pPrevByClass)?;
|
||||
let entity_ptr = ctx.process.read_addr64(next_by_class_ptr)?;
|
||||
Ok(Self(entity_ptr))
|
||||
}
|
||||
}
|
||||
|
||||
impl CPlayerController {
|
||||
pub fn get_pawn(&self, ctx: &mut CheatCtx, entity_list: Address) -> Result<Option<super::CPlayerPawn>, Error> {
|
||||
let uhandle = ctx.process.read(self.0 + cs2dumper::client::CCSPlayerController::m_hPlayerPawn)?;
|
||||
let uhandle = ctx.memory.read(self.0 + cs2dumper::client::CCSPlayerController::m_hPlayerPawn)?;
|
||||
super::CPlayerPawn::from_uhandle(ctx, entity_list, uhandle)
|
||||
}
|
||||
|
||||
// Technically something that should be in the BaseEntity trait, but we are only gonna use it on CPlayerController
|
||||
pub fn get_team(&self, ctx: &mut CheatCtx) -> Result<Option<TeamID>, Error> {
|
||||
let team_num: i32 = ctx.process.read(self.0 + cs2dumper::client::C_BaseEntity::m_iTeamNum)?;
|
||||
let team_num: i32 = ctx.memory.read(self.0 + cs2dumper::client::C_BaseEntity::m_iTeamNum)?;
|
||||
Ok(TeamID::from_i32(team_num))
|
||||
}
|
||||
|
||||
|
||||
@@ -17,12 +17,12 @@ impl MemoryClass for CPlayerPawn {
|
||||
|
||||
impl CPlayerPawn {
|
||||
pub fn from_uhandle(ctx: &mut CheatCtx, entity_list: Address, uhandle: u32) -> Result<Option<Self>, Error> {
|
||||
let list_entry = ctx.process.read_addr64(entity_list + 0x8 * ((uhandle & 0x7FFF) >> 9) + 16)?;
|
||||
let list_entry = ctx.memory.read_addr64(entity_list + 0x8 * ((uhandle & 0x7FFF) >> 9) + 16)?;
|
||||
|
||||
if list_entry.is_null() || !list_entry.is_valid() {
|
||||
Ok(None)
|
||||
} else {
|
||||
let ptr = ctx.process.read_addr64(list_entry + 120 * (uhandle & 0x1FF))?;
|
||||
let ptr = ctx.memory.read_addr64(list_entry + 120 * (uhandle & 0x1FF))?;
|
||||
Ok(Some(Self(ptr)))
|
||||
}
|
||||
}
|
||||
@@ -30,27 +30,27 @@ impl CPlayerPawn {
|
||||
// Todo: Optimize this function: find another way to do this
|
||||
pub fn has_c4(&self, ctx: &mut CheatCtx, entity_list: Address) -> Result<bool, Error> {
|
||||
let mut has_c4 = false;
|
||||
let wep_services = ctx.process.read_addr64(self.0 + cs2dumper::client::C_BasePlayerPawn::m_pWeaponServices)?;
|
||||
let wep_count: i32 = ctx.process.read(wep_services + cs2dumper::client::CPlayer_WeaponServices::m_hMyWeapons)?;
|
||||
let wep_base = ctx.process.read_addr64(wep_services + cs2dumper::client::CPlayer_WeaponServices::m_hMyWeapons + 0x8)?;
|
||||
let wep_services = ctx.memory.read_addr64(self.0 + cs2dumper::client::C_BasePlayerPawn::m_pWeaponServices)?;
|
||||
let wep_count: i32 = ctx.memory.read(wep_services + cs2dumper::client::CPlayer_WeaponServices::m_hMyWeapons)?;
|
||||
let wep_base = ctx.memory.read_addr64(wep_services + cs2dumper::client::CPlayer_WeaponServices::m_hMyWeapons + 0x8)?;
|
||||
|
||||
for wep_idx in 0..wep_count {
|
||||
let handle: i32 = ctx.process.read(wep_base + wep_idx * 0x4)?;
|
||||
let handle: i32 = ctx.memory.read(wep_base + wep_idx * 0x4)?;
|
||||
if handle == -1 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let list_entry = ctx.process.read_addr64(entity_list + 0x8 * ((handle & 0x7FFF) >> 9) + 16)?;
|
||||
let list_entry = ctx.memory.read_addr64(entity_list + 0x8 * ((handle & 0x7FFF) >> 9) + 16)?;
|
||||
if let Some(wep_ptr) = {
|
||||
if list_entry.is_null() || !list_entry.is_valid() {
|
||||
None
|
||||
} else {
|
||||
let ptr = ctx.process.read_addr64(list_entry + 120 * (handle & 0x1FF))?;
|
||||
let ptr = ctx.memory.read_addr64(list_entry + 120 * (handle & 0x1FF))?;
|
||||
Some(ptr)
|
||||
}
|
||||
} {
|
||||
let wep_data = ctx.process.read_addr64(wep_ptr + cs2dumper::client::C_BaseEntity::m_nSubclassID + 0x8)?;
|
||||
let id: i32 = ctx.process.read(wep_data + cs2dumper::client::CCSWeaponBaseVData::m_WeaponType)?;
|
||||
let wep_data = ctx.memory.read_addr64(wep_ptr + cs2dumper::client::C_BaseEntity::m_nSubclassID + 0x8)?;
|
||||
let id: i32 = ctx.memory.read(wep_data + cs2dumper::client::CCSWeaponBaseVData::m_WeaponType)?;
|
||||
|
||||
if id == 7 {
|
||||
has_c4 = true;
|
||||
@@ -63,15 +63,15 @@ impl CPlayerPawn {
|
||||
}
|
||||
|
||||
pub fn pos(&self, ctx: &mut CheatCtx) -> Result<Vec3, Error> {
|
||||
Ok(ctx.process.read(self.0 + cs2dumper::client::C_BasePlayerPawn::m_vOldOrigin)?)
|
||||
Ok(ctx.memory.read(self.0 + cs2dumper::client::C_BasePlayerPawn::m_vOldOrigin)?)
|
||||
}
|
||||
|
||||
pub fn angles(&self, ctx: &mut CheatCtx) -> Result<Vec3, Error> {
|
||||
Ok(ctx.process.read(self.0 + cs2dumper::client::C_CSPlayerPawnBase::m_angEyeAngles)?)
|
||||
Ok(ctx.memory.read(self.0 + cs2dumper::client::C_CSPlayerPawnBase::m_angEyeAngles)?)
|
||||
}
|
||||
|
||||
pub fn health(&self, ctx: &mut CheatCtx) -> Result<u32, Error> {
|
||||
Ok(ctx.process.read(self.0 + cs2dumper::client::C_BaseEntity::m_iHealth)?)
|
||||
Ok(ctx.memory.read(self.0 + cs2dumper::client::C_BaseEntity::m_iHealth)?)
|
||||
}
|
||||
|
||||
/// Same as ::get_health > 0
|
||||
|
||||
@@ -16,20 +16,20 @@ impl MemoryClass for GameRules {
|
||||
|
||||
impl GameRules {
|
||||
pub fn bomb_dropped(&self, ctx: &mut CheatCtx) -> Result<bool, Error> {
|
||||
let data: u8 = ctx.process.read(self.0 + cs2dumper::client::C_CSGameRules::m_bBombDropped)?;
|
||||
let data: u8 = ctx.memory.read(self.0 + cs2dumper::client::C_CSGameRules::m_bBombDropped)?;
|
||||
Ok(data != 0)
|
||||
}
|
||||
|
||||
pub fn total_rounds_played(&self, ctx: &mut CheatCtx) -> Result<i32, Error> {
|
||||
Ok(ctx.process.read(self.0 + cs2dumper::client::C_CSGameRules::m_totalRoundsPlayed)?)
|
||||
Ok(ctx.memory.read(self.0 + cs2dumper::client::C_CSGameRules::m_totalRoundsPlayed)?)
|
||||
}
|
||||
|
||||
pub fn game_phase(&self, ctx: &mut CheatCtx) -> Result<i32, Error> {
|
||||
Ok(ctx.process.read(self.0 + cs2dumper::client::C_CSGameRules::m_gamePhase)?)
|
||||
Ok(ctx.memory.read(self.0 + cs2dumper::client::C_CSGameRules::m_gamePhase)?)
|
||||
}
|
||||
|
||||
pub fn bomb_planted(&self, ctx: &mut CheatCtx) -> Result<bool, Error> {
|
||||
let data: u8 = ctx.process.read(self.0 + cs2dumper::client::C_CSGameRules::m_bBombPlanted)?;
|
||||
let data: u8 = ctx.memory.read(self.0 + cs2dumper::client::C_CSGameRules::m_bBombPlanted)?;
|
||||
Ok(data != 0)
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
use memflow::{types::Address, mem::MemoryView};
|
||||
use crate::{traits::MemoryClass, CheatCtx, Error};
|
||||
use crate::{traits::MemoryClass, CheatCtx, Error, cached_view::INVALIDATE_ALWAYS};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct GlobalVars(Address);
|
||||
@@ -16,6 +16,7 @@ impl MemoryClass for GlobalVars {
|
||||
|
||||
impl GlobalVars {
|
||||
pub fn real_time(&self, ctx: &mut CheatCtx) -> Result<f32, Error> {
|
||||
ctx.cache_controller.set_next_flags(INVALIDATE_ALWAYS);
|
||||
Ok(ctx.process.read(self.0)?)
|
||||
}
|
||||
|
||||
@@ -40,7 +41,7 @@ impl GlobalVars {
|
||||
}
|
||||
|
||||
pub fn map_name(&self, ctx: &mut CheatCtx) -> Result<String, Error> {
|
||||
let ptr = ctx.process.read_addr64(self.0 + 0x188)?;
|
||||
let ptr = ctx.memory.read_addr64(self.0 + 0x188)?;
|
||||
Ok(ctx.process.read_char_string_n(ptr, 32)?)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user