From 295844a8ca95af94450c9da6ff6cde547df29caa Mon Sep 17 00:00:00 2001 From: Uladzislau Nikalayevich Date: Mon, 26 Aug 2024 16:57:02 +0300 Subject: [PATCH 1/2] Fix engineRequestModel crash caused by CResourceModelStreamer (#3675) * Fix crash * Fix refs count * Use reference --------- Co-authored-by: TEDERIs --- Client/mods/deathmatch/logic/CResourceModelStreamer.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Client/mods/deathmatch/logic/CResourceModelStreamer.cpp b/Client/mods/deathmatch/logic/CResourceModelStreamer.cpp index 9c58219d8b..c6c2eb30d1 100644 --- a/Client/mods/deathmatch/logic/CResourceModelStreamer.cpp +++ b/Client/mods/deathmatch/logic/CResourceModelStreamer.cpp @@ -106,7 +106,11 @@ void CResourceModelStreamer::ReleaseAll() void CResourceModelStreamer::FullyReleaseModel(std::uint16_t modelId) { - std::uint16_t &refsCount = m_requestedModels[modelId]; + auto refs = m_requestedModels.find(modelId); + if (refs == m_requestedModels.end()) + return; + + std::uint16_t& refsCount = refs->second; if (refsCount > 0) { From 4e7afa2586c6992a75ac5312378c1096d87148ae Mon Sep 17 00:00:00 2001 From: TEDERIs Date: Tue, 27 Aug 2024 14:59:45 +0700 Subject: [PATCH 2/2] setElementModel memory leak fix (#3671) * Memory leak fix * Misprint fix * Clean up * Use CEntitySAInterface::DeleteRwObject --- Client/core/CCore.cpp | 5 ---- Client/core/CCore.h | 1 - Client/core/CModelCacheManager.cpp | 28 +-------------------- Client/core/CModelCacheManager.h | 1 - Client/game_sa/CPedSA.cpp | 16 ++++-------- Client/game_sa/CPedSA.h | 1 - Client/mods/deathmatch/logic/CClientPed.cpp | 17 +------------ Client/sdk/core/CCoreInterface.h | 1 - Client/sdk/game/CPed.h | 1 - 9 files changed, 7 insertions(+), 64 deletions(-) diff --git a/Client/core/CCore.cpp b/Client/core/CCore.cpp index 849eee0afc..364836e111 100644 --- a/Client/core/CCore.cpp +++ b/Client/core/CCore.cpp @@ -2181,11 +2181,6 @@ CModelCacheManager* CCore::GetModelCacheManager() return m_pModelCacheManager; } -void CCore::AddModelToPersistentCache(ushort usModelId) -{ - return GetModelCacheManager()->AddModelToPersistentCache(usModelId); -} - void CCore::StaticIdleHandler() { g_pCore->IdleHandler(); diff --git a/Client/core/CCore.h b/Client/core/CCore.h index 55460a6f4f..3439a484de 100644 --- a/Client/core/CCore.h +++ b/Client/core/CCore.h @@ -253,7 +253,6 @@ class CCore : public CCoreInterface, public CSingleton EDiagnosticDebugType GetDiagnosticDebug(); void SetDiagnosticDebug(EDiagnosticDebugType value); CModelCacheManager* GetModelCacheManager(); - void AddModelToPersistentCache(ushort usModelId); static void StaticIdleHandler(); void IdleHandler(); diff --git a/Client/core/CModelCacheManager.cpp b/Client/core/CModelCacheManager.cpp index 00c762fa80..40fa7c8ff4 100644 --- a/Client/core/CModelCacheManager.cpp +++ b/Client/core/CModelCacheManager.cpp @@ -47,7 +47,6 @@ class CModelCacheManagerImpl : public CModelCacheManager virtual void OnClientClose(); virtual void UpdatePedModelCaching(const std::map& newNeedCacheList); virtual void UpdateVehicleModelCaching(const std::map& newNeedCacheList); - virtual void AddModelToPersistentCache(ushort usModelId); virtual void SetCustomLimits(std::optional numVehicles, std::optional numPeds); // CModelCacheManagerImpl methods @@ -72,7 +71,6 @@ class CModelCacheManagerImpl : public CModelCacheManager bool m_IsUsingCustomVehicleCacheLimit{}; //< If `true` the value is set by the scripter, otherwise is calculated in `DoPulse()` std::map m_PedModelCacheInfoMap{}; std::map m_VehicleModelCacheInfoMap{}; - std::set m_PermoLoadedModels{}; }; /////////////////////////////////////////////////////////////// @@ -266,22 +264,6 @@ void CModelCacheManagerImpl::DoPulse() } } -/////////////////////////////////////////////////////////////// -// -// CModelCacheManagerImpl::AddModelToPersistentCache -// -// Keep this model around 4 evar now -// -/////////////////////////////////////////////////////////////// -void CModelCacheManagerImpl::AddModelToPersistentCache(ushort usModelId) -{ - if (!MapContains(m_PermoLoadedModels, usModelId)) - { - AddModelRefCount(usModelId); - MapInsert(m_PermoLoadedModels, usModelId); - } -} - /////////////////////////////////////////////////////////////// // // CModelCacheManagerImpl::UpdatePedModelCaching @@ -542,13 +524,5 @@ void CModelCacheManagerImpl::OnRestreamModel(ushort usModelId) OutputDebugLine(SString("[Cache] End caching model %d (OnRestreamModel)", usModelId)); } } - } - - // Also check the permo list - if (MapContains(m_PermoLoadedModels, usModelId)) - { - SubModelRefCount(usModelId); - MapRemove(m_PermoLoadedModels, usModelId); - OutputDebugLine(SString("[Cache] End permo-caching model %d (OnRestreamModel)", usModelId)); - } + } } diff --git a/Client/core/CModelCacheManager.h b/Client/core/CModelCacheManager.h index ee54cbedfe..7d7952d0b5 100644 --- a/Client/core/CModelCacheManager.h +++ b/Client/core/CModelCacheManager.h @@ -24,7 +24,6 @@ class CModelCacheManager virtual void OnClientClose() = 0; virtual void UpdatePedModelCaching(const std::map& newNeedCacheList) = 0; virtual void UpdateVehicleModelCaching(const std::map& newNeedCacheList) = 0; - virtual void AddModelToPersistentCache(ushort usModelId) = 0; virtual void SetCustomLimits(std::optional numVehicles, std::optional numPeds) = 0; }; diff --git a/Client/game_sa/CPedSA.cpp b/Client/game_sa/CPedSA.cpp index 009e618e8c..1ae9f942f8 100644 --- a/Client/game_sa/CPedSA.cpp +++ b/Client/game_sa/CPedSA.cpp @@ -98,8 +98,12 @@ void CPedSA::Init() void CPedSA::SetModelIndex(DWORD dwModelIndex) { - DWORD dwFunction = FUNC_SetModelIndex; + // Delete any existing RwObject first + GetPedInterface()->DeleteRwObject(); + + // Set new model DWORD dwThis = (DWORD)GetInterface(); + DWORD dwFunction = FUNC_SetModelIndex; _asm { mov ecx, dwThis @@ -116,16 +120,6 @@ void CPedSA::SetModelIndex(DWORD dwModelIndex) } } -// Hacky thing done for the local player when changing model -void CPedSA::RemoveGeometryRef() -{ - RpClump* pClump = (RpClump*)GetInterface()->m_pRwObject; - RpAtomic* pAtomic = (RpAtomic*)((pClump->atomics.root.next) - 0x8); - RpGeometry* pGeometry = pAtomic->geometry; - if (pGeometry->refs > 1) - pGeometry->refs--; -} - bool CPedSA::IsInWater() { CTask* pTask = m_pPedIntelligence->GetTaskManager()->GetTask(TASK_PRIORITY_EVENT_RESPONSE_NONTEMP); diff --git a/Client/game_sa/CPedSA.h b/Client/game_sa/CPedSA.h index daae468472..fee84fd651 100644 --- a/Client/game_sa/CPedSA.h +++ b/Client/game_sa/CPedSA.h @@ -295,7 +295,6 @@ class CPedSA : public virtual CPed, public virtual CPhysicalSA CPedSAInterface* GetPedInterface() { return (CPedSAInterface*)GetInterface(); } void Init(); void SetModelIndex(DWORD dwModelIndex); - void RemoveGeometryRef(); void AttachPedToEntity(DWORD dwEntityInterface, CVector* vector, unsigned short sDirection, float fRotationLimit, eWeaponType weaponType, bool bChangeCamera); void DetachPedFromEntity(); diff --git a/Client/mods/deathmatch/logic/CClientPed.cpp b/Client/mods/deathmatch/logic/CClientPed.cpp index 81faab7efd..5716bea120 100644 --- a/Client/mods/deathmatch/logic/CClientPed.cpp +++ b/Client/mods/deathmatch/logic/CClientPed.cpp @@ -3927,22 +3927,7 @@ void CClientPed::_ChangeModel() // So make sure clothes geometry is built now... m_pClothes->AddAllToModel(); m_pPlayerPed->RebuildPlayer(); - - // ...and decrement the extra ref - #ifdef NO_CRASH_FIX_TEST2 - m_pPlayerPed->RemoveGeometryRef(); - #endif - } - else - { - // When the local player changes to another (non CJ) model, the geometry gets an extra ref from somewhere, causing a memory leak. - // So decrement the extra ref here - #ifdef NO_CRASH_FIX_TEST - m_pPlayerPed->RemoveGeometryRef(); - #endif - // As we will have problem removing the geometry later, we might as well keep the model cached until exit - g_pCore->AddModelToPersistentCache((ushort)m_ulModel); - } + } // Remove reference to the old model we used (Flag extra GTA reference to be removed as well) pLoadedModel->RemoveRef(true); diff --git a/Client/sdk/core/CCoreInterface.h b/Client/sdk/core/CCoreInterface.h index aea1ca9054..c591d546e5 100644 --- a/Client/sdk/core/CCoreInterface.h +++ b/Client/sdk/core/CCoreInterface.h @@ -160,7 +160,6 @@ class CCoreInterface virtual EDiagnosticDebugType GetDiagnosticDebug() = 0; virtual void SetDiagnosticDebug(EDiagnosticDebugType value) = 0; virtual CModelCacheManager* GetModelCacheManager() = 0; - virtual void AddModelToPersistentCache(ushort usModelId) = 0; virtual void UpdateDummyProgress(int iValue = -1, const char* szType = "") = 0; virtual void SetDummyProgressUpdateAlways(bool bAlways) = 0; diff --git a/Client/sdk/game/CPed.h b/Client/sdk/game/CPed.h index 29bbf60104..4e91cdb8b4 100644 --- a/Client/sdk/game/CPed.h +++ b/Client/sdk/game/CPed.h @@ -191,7 +191,6 @@ class CPed : public virtual CPhysical virtual void Respawn(CVector* position, bool bCameraCut) = 0; virtual void SetModelIndex(unsigned long ulModel) = 0; - virtual void RemoveGeometryRef() = 0; virtual float GetHealth() = 0; virtual void SetHealth(float fHealth) = 0;