From 798c99ea77fb995ace9794706c55c93cc0f4d93a Mon Sep 17 00:00:00 2001 From: Flashmyname Date: Thu, 10 Sep 2026 14:06:43 +0200 Subject: [PATCH] Stream out model users when an IMG link is restored --- Client/mods/deathmatch/logic/CClientIMG.cpp | 23 +++++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/Client/mods/deathmatch/logic/CClientIMG.cpp b/Client/mods/deathmatch/logic/CClientIMG.cpp index 950ee5fd819..fdf9f335b77 100644 --- a/Client/mods/deathmatch/logic/CClientIMG.cpp +++ b/Client/mods/deathmatch/logic/CClientIMG.cpp @@ -17,6 +17,17 @@ struct tImgHeader unsigned int uiFilesCount; }; +// SetStreamingInfo force-removes the model's RwObject, and the streamer no longer tracks it +// after the archive change, so entities still using it have to be streamed out first +static void StreamOutModelUsers(unsigned int uiModelID) +{ + if (CClientVehicleManager::IsValidModel(uiModelID)) + g_pClientGame->GetVehicleManager()->RestreamVehicles(static_cast(uiModelID)); + + if (CClientPedManager::IsValidWeaponModel(uiModelID)) + g_pClientGame->GetPedManager()->RestreamWeapon(static_cast(uiModelID)); +} + CClientIMG::CClientIMG(class CClientManager* pManager, ElementID ID) : ClassInit(this), CClientEntity(ID), m_pImgManager(pManager->GetIMGManager()), m_ucArchiveID(INVALID_ARCHIVE_ID), m_LargestFileSizeBlocks(0) { @@ -180,6 +191,7 @@ bool CClientIMG::StreamDisable() // Unlink all models for (const auto& v : m_restoreInfo) { + StreamOutModelUsers(v.uiModelID); g_pGame->GetStreaming()->SetStreamingInfo(v.uiModelID, v.ucStreamID, v.uiOffset, v.usSize); } m_restoreInfo.clear(); @@ -219,15 +231,7 @@ bool CClientIMG::LinkModel(unsigned int uiModelID, size_t uiFileID) m_restoreInfo.emplace_back(uiModelID, pCurrInfo->offsetInBlocks, pCurrInfo->sizeInBlocks, pCurrInfo->archiveId); - // Internally stream out the vehicle before calling CStreamingSA::RemoveModel - // otherwise a crash will occur if the player is inside a vehicle that gets unloaded by the streamer - if (CClientVehicleManager::IsValidModel(uiModelID)) - g_pClientGame->GetVehicleManager()->RestreamVehicles(static_cast(uiModelID)); - - // Weapon models already in a ped's hand keep their old RW clump until the weapon slot is - // re-requested, same as vehicles above (see CClientDFF::ReplaceWeaponModel for the equivalent case) - if (CClientPedManager::IsValidWeaponModel(uiModelID)) - g_pClientGame->GetPedManager()->RestreamWeapon(static_cast(uiModelID)); + StreamOutModelUsers(uiModelID); g_pGame->GetStreaming()->SetStreamingInfo(uiModelID, m_ucArchiveID, pFileInfo->uiOffset, pFileInfo->usSize); @@ -242,6 +246,7 @@ bool CClientIMG::UnlinkModel(unsigned int uiModelID) if (it == m_restoreInfo.end()) return false; + StreamOutModelUsers(uiModelID); g_pGame->GetStreaming()->SetStreamingInfo(uiModelID, it->ucStreamID, it->uiOffset, it->usSize); m_restoreInfo.erase(it);