Dynamically allocate entity hitbox cache to reduce memory usage.
This commit is contained in:
parent
a60f52fa9d
commit
08dcfe7ffd
@ -224,5 +224,6 @@ inline CachedEntity &Get(int idx)
|
|||||||
}
|
}
|
||||||
void Update();
|
void Update();
|
||||||
void Invalidate();
|
void Invalidate();
|
||||||
|
void Shutdown();
|
||||||
extern int max;
|
extern int max;
|
||||||
} // namespace entity_cache
|
} // namespace entity_cache
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <cdll_int.h>
|
#include <cdll_int.h>
|
||||||
#include <studio.h>
|
#include <studio.h>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
// Forward declaration from entitycache.hpp
|
// Forward declaration from entitycache.hpp
|
||||||
class CachedEntity;
|
class CachedEntity;
|
||||||
@ -39,7 +40,7 @@ public:
|
|||||||
void Init();
|
void Init();
|
||||||
int GetNumHitboxes();
|
int GetNumHitboxes();
|
||||||
void Reset();
|
void Reset();
|
||||||
matrix3x4_t *GetBones();
|
matrix3x4_t *GetBones(int numbones = -1);
|
||||||
|
|
||||||
int m_nNumHitboxes;
|
int m_nNumHitboxes;
|
||||||
bool m_bModelSet;
|
bool m_bModelSet;
|
||||||
@ -52,9 +53,9 @@ public:
|
|||||||
bool m_VisCheckValidationFlags[CACHE_MAX_HITBOXES]{ false };
|
bool m_VisCheckValidationFlags[CACHE_MAX_HITBOXES]{ false };
|
||||||
bool m_VisCheck[CACHE_MAX_HITBOXES]{ false };
|
bool m_VisCheck[CACHE_MAX_HITBOXES]{ false };
|
||||||
bool m_CacheValidationFlags[CACHE_MAX_HITBOXES]{ false };
|
bool m_CacheValidationFlags[CACHE_MAX_HITBOXES]{ false };
|
||||||
CachedHitbox m_CacheInternal[CACHE_MAX_HITBOXES]{};
|
std::vector<CachedHitbox> m_CacheInternal;
|
||||||
|
|
||||||
matrix3x4_t bones[128];
|
std::vector<matrix3x4_t> bones;
|
||||||
bool bones_setup{ false };
|
bool bones_setup{ false };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -78,7 +78,6 @@ has_debug_info "$CATHOOK" || SYMBOLS=false
|
|||||||
if [ $SYMBOLS == false ]; then
|
if [ $SYMBOLS == false ]; then
|
||||||
echo "No debug symbols detected!"
|
echo "No debug symbols detected!"
|
||||||
proccount=$(grep -c '^processor' /proc/cpuinfo)
|
proccount=$(grep -c '^processor' /proc/cpuinfo)
|
||||||
\cp ./build/CMakeCache.txt ./scripts/CMakeCacheBackup.txt
|
|
||||||
pushd build
|
pushd build
|
||||||
cmake -DInternal_Symbolized=true .. && cmake --build . --target cathook -- -j$proccount
|
cmake -DInternal_Symbolized=true .. && cmake --build . --target cathook -- -j$proccount
|
||||||
popd
|
popd
|
||||||
|
@ -326,7 +326,7 @@ bool shouldCrit()
|
|||||||
static bool can_beggars_crit = false;
|
static bool can_beggars_crit = false;
|
||||||
static bool attacked_last_tick = false;
|
static bool attacked_last_tick = false;
|
||||||
|
|
||||||
bool canWeaponCrit(bool canShootCheck = true)
|
bool canWeaponCrit(bool draw = false)
|
||||||
{
|
{
|
||||||
// Is weapon elligible for crits?
|
// Is weapon elligible for crits?
|
||||||
IClientEntity *weapon = RAW_ENT(LOCAL_W);
|
IClientEntity *weapon = RAW_ENT(LOCAL_W);
|
||||||
@ -344,9 +344,9 @@ bool canWeaponCrit(bool canShootCheck = true)
|
|||||||
// Misc checks
|
// Misc checks
|
||||||
if (!isAllowedToWithdrawFromBucket(weapon))
|
if (!isAllowedToWithdrawFromBucket(weapon))
|
||||||
return false;
|
return false;
|
||||||
if (canShootCheck && !CanShoot() && !isRapidFire(weapon))
|
if (!draw && !CanShoot() && !isRapidFire(weapon))
|
||||||
return false;
|
return false;
|
||||||
if (CE_INT(LOCAL_W, netvar.iItemDefinitionIndex) == 730 && !can_beggars_crit)
|
if (!draw && CE_INT(LOCAL_W, netvar.iItemDefinitionIndex) == 730 && !can_beggars_crit)
|
||||||
return false;
|
return false;
|
||||||
// Check if we have done enough damage to crit
|
// Check if we have done enough damage to crit
|
||||||
auto crit_mult_info = critMultInfo(weapon);
|
auto crit_mult_info = critMultInfo(weapon);
|
||||||
@ -752,7 +752,7 @@ void Draw()
|
|||||||
// fixObservedCritchance(wep);
|
// fixObservedCritchance(wep);
|
||||||
|
|
||||||
// Used by multiple things
|
// Used by multiple things
|
||||||
bool can_crit = canWeaponCrit(false);
|
bool can_crit = canWeaponCrit(true);
|
||||||
|
|
||||||
if (bucket != last_bucket || wep->entindex() != last_wep || update_shots.test_and_set(500))
|
if (bucket != last_bucket || wep->entindex() != last_wep || update_shots.test_and_set(500))
|
||||||
{
|
{
|
||||||
|
@ -164,5 +164,14 @@ void Invalidate()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Shutdown()
|
||||||
|
{
|
||||||
|
for (auto &ent : array)
|
||||||
|
{
|
||||||
|
ent.Reset();
|
||||||
|
ent.hitboxes.Reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int max = 0;
|
int max = 0;
|
||||||
} // namespace entity_cache
|
} // namespace entity_cache
|
||||||
|
@ -105,7 +105,7 @@ static settings::Boolean bonecache_enabled{ "source.use-bone-cache", "false" };
|
|||||||
|
|
||||||
static std::mutex setupbones_mutex;
|
static std::mutex setupbones_mutex;
|
||||||
|
|
||||||
matrix3x4_t *EntityHitboxCache::GetBones()
|
matrix3x4_t *EntityHitboxCache::GetBones(int numbones)
|
||||||
{
|
{
|
||||||
static float bones_setup_time = 0.0f;
|
static float bones_setup_time = 0.0f;
|
||||||
switch (*setupbones_time)
|
switch (*setupbones_time)
|
||||||
@ -126,13 +126,24 @@ matrix3x4_t *EntityHitboxCache::GetBones()
|
|||||||
}
|
}
|
||||||
if (!bones_setup)
|
if (!bones_setup)
|
||||||
{
|
{
|
||||||
|
// If numbones is not set, get it from some terrible and unnamed variable
|
||||||
|
if (numbones == -1)
|
||||||
|
{
|
||||||
|
if (parent_ref->m_Type() == ENTITY_PLAYER)
|
||||||
|
numbones = CE_INT(parent_ref, 0x844);
|
||||||
|
else
|
||||||
|
numbones = MAXSTUDIOBONES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bones.size() < (size_t) numbones)
|
||||||
|
bones.resize(numbones);
|
||||||
if (g_Settings.is_create_move)
|
if (g_Settings.is_create_move)
|
||||||
{
|
{
|
||||||
#if !ENABLE_TEXTMODE
|
#if !ENABLE_TEXTMODE
|
||||||
if (!*bonecache_enabled || parent_ref->m_Type() != ENTITY_PLAYER || IsPlayerInvisible(parent_ref))
|
if (!*bonecache_enabled || parent_ref->m_Type() != ENTITY_PLAYER || IsPlayerInvisible(parent_ref))
|
||||||
{
|
{
|
||||||
PROF_SECTION(bone_setup);
|
PROF_SECTION(bone_setup);
|
||||||
bones_setup = RAW_ENT(parent_ref)->SetupBones(bones, MAXSTUDIOBONES, 0x7FF00, bones_setup_time);
|
bones_setup = RAW_ENT(parent_ref)->SetupBones(bones.data(), numbones, 0x7FF00, bones_setup_time);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -140,24 +151,24 @@ matrix3x4_t *EntityHitboxCache::GetBones()
|
|||||||
auto to_copy = CE_VAR(parent_ref, 0x838, matrix3x4_t *);
|
auto to_copy = CE_VAR(parent_ref, 0x838, matrix3x4_t *);
|
||||||
if (to_copy)
|
if (to_copy)
|
||||||
{
|
{
|
||||||
bones->Invalidate();
|
// This is catastrophically bad, don't do this. Someone needs to fix this.
|
||||||
memcpy((matrix3x4_t *) bones, to_copy, 48 * (CE_INT(parent_ref, 0x844)));
|
memcpy(bones.data(), to_copy, sizeof(matrix3x4_t) * numbones);
|
||||||
bones_setup = true;
|
bones_setup = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PROF_SECTION(bone_setup);
|
PROF_SECTION(bone_setup);
|
||||||
bones_setup = RAW_ENT(parent_ref)->SetupBones(bones, MAXSTUDIOBONES, 0x7FF00, bones_setup_time);
|
bones_setup = RAW_ENT(parent_ref)->SetupBones(bones.data(), numbones, 0x7FF00, bones_setup_time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// Textmode bots miss/shoot at nothing when the tf2 bonecache is used
|
// Textmode bots miss/shoot at nothing when the tf2 bonecache is used
|
||||||
PROF_SECTION(bone_setup);
|
PROF_SECTION(bone_setup);
|
||||||
bones_setup = RAW_ENT(parent_ref)->SetupBones(bones, MAXSTUDIOBONES, 0x7FF00, bones_setup_time);
|
bones_setup = RAW_ENT(parent_ref)->SetupBones(bones, numbones, 0x7FF00, bones_setup_time);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return bones;
|
return bones.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityHitboxCache::Reset()
|
void EntityHitboxCache::Reset()
|
||||||
@ -165,8 +176,10 @@ void EntityHitboxCache::Reset()
|
|||||||
memset(m_VisCheck, 0, sizeof(bool) * CACHE_MAX_HITBOXES);
|
memset(m_VisCheck, 0, sizeof(bool) * CACHE_MAX_HITBOXES);
|
||||||
memset(m_VisCheckValidationFlags, 0, sizeof(bool) * CACHE_MAX_HITBOXES);
|
memset(m_VisCheckValidationFlags, 0, sizeof(bool) * CACHE_MAX_HITBOXES);
|
||||||
memset(m_CacheValidationFlags, 0, sizeof(bool) * CACHE_MAX_HITBOXES);
|
memset(m_CacheValidationFlags, 0, sizeof(bool) * CACHE_MAX_HITBOXES);
|
||||||
memset(m_CacheInternal, 0, sizeof(CachedHitbox) * CACHE_MAX_HITBOXES);
|
m_CacheInternal.clear();
|
||||||
memset(&bones, 0, sizeof(matrix3x4_t) * 128);
|
m_CacheInternal.shrink_to_fit();
|
||||||
|
bones.clear();
|
||||||
|
bones.shrink_to_fit();
|
||||||
m_nNumHitboxes = 0;
|
m_nNumHitboxes = 0;
|
||||||
m_bInit = false;
|
m_bInit = false;
|
||||||
m_bModelSet = false;
|
m_bModelSet = false;
|
||||||
@ -198,13 +211,15 @@ CachedHitbox *EntityHitboxCache::GetHitbox(int id)
|
|||||||
auto set = shdr->pHitboxSet(CE_INT(parent_ref, netvar.iHitboxSet));
|
auto set = shdr->pHitboxSet(CE_INT(parent_ref, netvar.iHitboxSet));
|
||||||
if (!dynamic_cast<mstudiohitboxset_t *>(set))
|
if (!dynamic_cast<mstudiohitboxset_t *>(set))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
if (m_nNumHitboxes > m_CacheInternal.size())
|
||||||
|
m_CacheInternal.resize(m_nNumHitboxes);
|
||||||
box = set->pHitbox(id);
|
box = set->pHitbox(id);
|
||||||
if (!box)
|
if (!box)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (box->bone < 0 || box->bone >= MAXSTUDIOBONES)
|
if (box->bone < 0 || box->bone >= MAXSTUDIOBONES)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
VectorTransform(box->bbmin, GetBones()[box->bone], m_CacheInternal[id].min);
|
VectorTransform(box->bbmin, GetBones(shdr->numbones)[box->bone], m_CacheInternal[id].min);
|
||||||
VectorTransform(box->bbmax, GetBones()[box->bone], m_CacheInternal[id].max);
|
VectorTransform(box->bbmax, GetBones(shdr->numbones)[box->bone], m_CacheInternal[id].max);
|
||||||
m_CacheInternal[id].bbox = box;
|
m_CacheInternal[id].bbox = box;
|
||||||
m_CacheInternal[id].center = (m_CacheInternal[id].min + m_CacheInternal[id].max) / 2;
|
m_CacheInternal[id].center = (m_CacheInternal[id].min + m_CacheInternal[id].max) / 2;
|
||||||
m_CacheValidationFlags[id] = true;
|
m_CacheValidationFlags[id] = true;
|
||||||
|
@ -6,9 +6,8 @@ namespace EC
|
|||||||
|
|
||||||
struct EventCallbackData
|
struct EventCallbackData
|
||||||
{
|
{
|
||||||
explicit EventCallbackData(const EventFunction &function, std::string name, enum ec_priority priority) : function{ function }, priority{ int(priority) }, section{ name }, event_name{ name }
|
explicit EventCallbackData(const EventFunction &function, std::string name, enum ec_priority priority) : function{ function }, priority{ int(priority) }, section(name), event_name{ name }
|
||||||
{
|
{
|
||||||
section.m_name = name;
|
|
||||||
}
|
}
|
||||||
EventFunction function;
|
EventFunction function;
|
||||||
int priority;
|
int priority;
|
||||||
|
@ -17,6 +17,8 @@ DEFINE_HOOKED_METHOD(LevelShutdown, void, void *this_)
|
|||||||
g_Settings.bInvalid = true;
|
g_Settings.bInvalid = true;
|
||||||
chat_stack::Reset();
|
chat_stack::Reset();
|
||||||
EC::run(EC::LevelShutdown);
|
EC::run(EC::LevelShutdown);
|
||||||
|
// Free memory for hitbox cache
|
||||||
|
entity_cache::Shutdown();
|
||||||
#if ENABLE_IPC
|
#if ENABLE_IPC
|
||||||
if (ipc::peer)
|
if (ipc::peer)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user