From 80c04dcbb9981d8d3894c6be31e4d6956c057b8d Mon Sep 17 00:00:00 2001 From: Uladzislau Nikalayevich Date: Sat, 23 Sep 2023 23:27:53 +0300 Subject: [PATCH] Fix engineFreeModel crashes --- Client/mods/deathmatch/logic/CClientModel.cpp | 38 ++++++++++++------- Client/mods/deathmatch/logic/CClientModel.h | 5 ++- .../deathmatch/logic/CClientModelManager.cpp | 2 +- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/Client/mods/deathmatch/logic/CClientModel.cpp b/Client/mods/deathmatch/logic/CClientModel.cpp index 56bd3f566b..e42ee3a695 100644 --- a/Client/mods/deathmatch/logic/CClientModel.cpp +++ b/Client/mods/deathmatch/logic/CClientModel.cpp @@ -78,30 +78,49 @@ bool CClientModel::Allocate(ushort usParentID) return false; } +// You can call it only in destructor for DFF. bool CClientModel::Deallocate() { if (!m_bAllocatedByUs) return false; + + SetParentResource(nullptr); + CModelInfo* pModelInfo = g_pGame->GetModelInfo(m_iModelID, true); if (!pModelInfo || !pModelInfo->IsValid()) return false; - SetParentResource(nullptr); + if (m_eModelType != eClientModelType::TXD) + { + // Remove model info + pModelInfo->DeallocateModel(); + } + + return true; +} + +void CClientModel::RestoreEntitiesUsingThisModel() +{ + CModelInfo* pModelInfo = g_pGame->GetModelInfo(m_iModelID, true); + if (!pModelInfo || !pModelInfo->IsValid()) + return; switch (m_eModelType) { case eClientModelType::PED: case eClientModelType::OBJECT: case eClientModelType::VEHICLE: - return DeallocateDFF(pModelInfo); + RestoreDFF(pModelInfo); + return; case eClientModelType::TXD: - return DeallocateTXD(pModelInfo); + RestoreTXD(pModelInfo); + return; default: - return false; + return; } } -bool CClientModel::DeallocateDFF(CModelInfo* pModelInfo) +void CClientModel::RestoreDFF(CModelInfo* pModelInfo) { auto unloadModelsAndCallEvents = [&](auto iterBegin, auto iterEnd, unsigned short usParentID, auto setElementModelLambda) { for (auto iter = iterBegin; iter != iterEnd; iter++) @@ -164,11 +183,6 @@ bool CClientModel::DeallocateDFF(CModelInfo* pModelInfo) // Restore DFF/TXD g_pClientGame->GetManager()->GetDFFManager()->RestoreModel(m_iModelID); - - // Remove model info - pModelInfo->DeallocateModel(); - - return true; } bool CClientModel::AllocateTXD(std::string &strTxdName) @@ -182,7 +196,7 @@ bool CClientModel::AllocateTXD(std::string &strTxdName) return false; } -bool CClientModel::DeallocateTXD(CModelInfo* pModelInfo) +void CClientModel::RestoreTXD(CModelInfo* pModelInfo) { uint uiTextureDictonarySlotID = pModelInfo->GetModel() - MAX_MODEL_DFF_ID; @@ -196,6 +210,4 @@ bool CClientModel::DeallocateTXD(CModelInfo* pModelInfo) g_pGame->GetPools()->RemoveTextureDictonarySlot(uiTextureDictonarySlotID); g_pGame->GetStreaming()->SetStreamingInfo(pModelInfo->GetModel(), 0, 0, 0, -1); - - return true; } diff --git a/Client/mods/deathmatch/logic/CClientModel.h b/Client/mods/deathmatch/logic/CClientModel.h index 27b5db24ee..903148192d 100644 --- a/Client/mods/deathmatch/logic/CClientModel.h +++ b/Client/mods/deathmatch/logic/CClientModel.h @@ -42,10 +42,11 @@ class CClientModel final bool Deallocate(void); void SetParentResource(CResource* pResource) { m_pParentResource = pResource; } CResource* GetParentResource(void) const { return m_pParentResource; } + void RestoreEntitiesUsingThisModel(); private: - bool DeallocateDFF(CModelInfo* pModelInfo); - bool DeallocateTXD(CModelInfo* pModelInfo); + void RestoreDFF(CModelInfo* pModelInfo); + void RestoreTXD(CModelInfo* pModelInfo); protected: CClientManager* m_pManager; diff --git a/Client/mods/deathmatch/logic/CClientModelManager.cpp b/Client/mods/deathmatch/logic/CClientModelManager.cpp index 2323a645c0..21d795e964 100644 --- a/Client/mods/deathmatch/logic/CClientModelManager.cpp +++ b/Client/mods/deathmatch/logic/CClientModelManager.cpp @@ -49,7 +49,7 @@ bool CClientModelManager::Remove(const std::shared_ptr& pModel) int modelId = pModel->GetModelID(); if (m_Models[modelId] != nullptr) { - m_Models[modelId]->Deallocate(); + m_Models[modelId]->RestoreEntitiesUsingThisModel(); m_Models[modelId] = nullptr; m_modelCount--; return true;