@@ -1471,6 +1471,11 @@ CModelTexturesInfo* CRenderWareSA::GetModelTexturesInfo(unsigned short usModelId
14711471
14721472 if (bIsStaleEntry)
14731473 {
1474+ unsigned int uiTxdStreamId = usTxdId + pGame->GetBaseIDforTXD ();
1475+ CStreamingInfo* pStreamInfoBusyCheck = pGame->GetStreaming ()->GetStreamingInfo (uiTxdStreamId);
1476+ bool bBusy = pStreamInfoBusyCheck && (pStreamInfoBusyCheck->loadState == eModelLoadState::LOADSTATE_READING || pStreamInfoBusyCheck->loadState == eModelLoadState::LOADSTATE_FINISHING );
1477+ if (bBusy && !pCurrentTxd)
1478+ return nullptr ;
14741479
14751480 // Cache replacement textures to re-apply after TXD reload
14761481 std::unordered_map<unsigned short , CModelInfoSA*> modelInfoCache;
@@ -1485,8 +1490,11 @@ CModelTexturesInfo* CRenderWareSA::GetModelTexturesInfo(unsigned short usModelId
14851490 }
14861491
14871492 std::vector<std::pair<SReplacementTextures*, std::vector<unsigned short >>> replacementsToReapply;
1493+ std::vector<SReplacementTextures*> originalUsed;
14881494 for (SReplacementTextures* pReplacement : info.usedByReplacements )
14891495 {
1496+ if (pReplacement)
1497+ originalUsed.push_back (pReplacement);
14901498 std::vector<unsigned short > modelIds;
14911499 for (unsigned short modelId : pReplacement->usedInModelIds )
14921500 {
@@ -1693,18 +1701,47 @@ CModelTexturesInfo* CRenderWareSA::GetModelTexturesInfo(unsigned short usModelId
16931701 }
16941702 info.usedByReplacements .clear ();
16951703
1704+ auto restoreState = [&]()
1705+ {
1706+ for (SReplacementTextures* pReplacement : originalUsed)
1707+ {
1708+ if (!pReplacement)
1709+ continue ;
1710+ if (std::find (info.usedByReplacements .begin (), info.usedByReplacements .end (), pReplacement) == info.usedByReplacements .end ())
1711+ info.usedByReplacements .push_back (pReplacement);
1712+ }
1713+ for (auto & entry : replacementsToReapply)
1714+ {
1715+ SReplacementTextures* pReplacement = entry.first ;
1716+ if (!pReplacement)
1717+ continue ;
1718+ for (unsigned short modelId : entry.second )
1719+ pReplacement->usedInModelIds .insert (modelId);
1720+ }
1721+ };
1722+
16961723 if (pCurrentTxd)
16971724 {
16981725 info.pTxd = pCurrentTxd;
16991726 PopulateOriginalTextures (info, pCurrentTxd);
1727+ restoreState ();
17001728 }
17011729 else
17021730 {
17031731 unsigned int uiTxdStreamId = usTxdId + pGame->GetBaseIDforTXD ();
1704- pGame->GetStreaming ()->RequestModel (uiTxdStreamId, 0x16 );
1705- pGame->GetStreaming ()->LoadAllRequestedModels (true , " CRenderWareSA::GetModelTexturesInfo-TXD" );
1706-
1707- pModelInfo->Request (BLOCKING , " CRenderWareSA::GetModelTexturesInfo" );
1732+ CStreamingInfo* pStreamInfo = pGame->GetStreaming ()->GetStreamingInfo (uiTxdStreamId);
1733+ bool bLoaded = pStreamInfo && pStreamInfo->loadState == eModelLoadState::LOADSTATE_LOADED ;
1734+ bool bBusyStream = pStreamInfo && (pStreamInfo->loadState == eModelLoadState::LOADSTATE_READING || pStreamInfo->loadState == eModelLoadState::LOADSTATE_FINISHING );
1735+ if (bBusyStream)
1736+ {
1737+ restoreState ();
1738+ return nullptr ;
1739+ }
1740+ if (!bLoaded)
1741+ {
1742+ pGame->GetStreaming ()->RequestModel (uiTxdStreamId, 0x16 );
1743+ pGame->GetStreaming ()->LoadAllRequestedModels (false , " GetModelTexturesInfo-txd" );
1744+ }
17081745
17091746 unsigned short uiNewTxdId = pModelInfo->GetTextureDictionaryID ();
17101747
@@ -1727,12 +1764,69 @@ CModelTexturesInfo* CRenderWareSA::GetModelTexturesInfo(unsigned short usModelId
17271764 }
17281765 else
17291766 {
1730- if (!info.bHasLeakedTextures && CTxdStore_GetNumRefs (usTxdId) > 0 )
1731- CRenderWareSA::DebugTxdRemoveRef (usTxdId, " GetModelTexturesInfo-blocking-fail" );
1732- else if (info.bHasLeakedTextures )
1733- g_PendingLeakedTxdRefs.insert (usTxdId);
1734- MapRemove (ms_ModelTexturesInfoMap, usTxdId);
1735- return nullptr ;
1767+ pGame->GetStreaming ()->LoadAllRequestedModels (false , " GetModelTexturesInfo-txd-retry" );
1768+ pCurrentTxd = CTxdStore_GetTxd (usTxdId);
1769+
1770+ if (pCurrentTxd)
1771+ {
1772+ info.pTxd = pCurrentTxd;
1773+ PopulateOriginalTextures (info, pCurrentTxd);
1774+ restoreState ();
1775+ }
1776+ else
1777+ {
1778+ CStreamingInfo* pStreamInfoRetry = pGame->GetStreaming ()->GetStreamingInfo (uiTxdStreamId);
1779+ bool bBusyRetry = pStreamInfoRetry && (pStreamInfoRetry->loadState == eModelLoadState::LOADSTATE_READING || pStreamInfoRetry->loadState == eModelLoadState::LOADSTATE_FINISHING );
1780+ if (bBusyRetry)
1781+ {
1782+ restoreState ();
1783+ return nullptr ;
1784+ }
1785+
1786+ // Second pass: if TXD still not present and stream isn't marked loaded, push a fresh request before the final load pass.
1787+ if (!pStreamInfoRetry || pStreamInfoRetry->loadState != eModelLoadState::LOADSTATE_LOADED )
1788+ pGame->GetStreaming ()->RequestModel (uiTxdStreamId, 0x16 );
1789+ pGame->GetStreaming ()->LoadAllRequestedModels (false , " GetModelTexturesInfo-txd-retry2" );
1790+ pCurrentTxd = CTxdStore_GetTxd (usTxdId);
1791+
1792+ if (pCurrentTxd)
1793+ {
1794+ info.pTxd = pCurrentTxd;
1795+ PopulateOriginalTextures (info, pCurrentTxd);
1796+ }
1797+ else
1798+ {
1799+ CStreamingInfo* pStreamInfoRetry2 = pGame->GetStreaming ()->GetStreamingInfo (uiTxdStreamId);
1800+ bool bBusy = pStreamInfoRetry2 && (pStreamInfoRetry2->loadState == eModelLoadState::LOADSTATE_READING || pStreamInfoRetry2->loadState == eModelLoadState::LOADSTATE_FINISHING );
1801+ if (bBusy)
1802+ {
1803+ restoreState ();
1804+ return nullptr ;
1805+ }
1806+
1807+ if (!pStreamInfoRetry2 || pStreamInfoRetry2->loadState != eModelLoadState::LOADSTATE_LOADED )
1808+ pGame->GetStreaming ()->RequestModel (uiTxdStreamId, 0x16 );
1809+ pGame->GetStreaming ()->LoadAllRequestedModels (true , " GetModelTexturesInfo-txd-retry3" );
1810+ pCurrentTxd = CTxdStore_GetTxd (usTxdId);
1811+
1812+ if (pCurrentTxd)
1813+ {
1814+ info.pTxd = pCurrentTxd;
1815+ PopulateOriginalTextures (info, pCurrentTxd);
1816+ restoreState ();
1817+ }
1818+ else
1819+ {
1820+ restoreState ();
1821+ if (!info.bHasLeakedTextures && CTxdStore_GetNumRefs (usTxdId) > 0 )
1822+ CRenderWareSA::DebugTxdRemoveRef (usTxdId, " GetModelTexturesInfo-blocking-fail" );
1823+ else if (info.bHasLeakedTextures )
1824+ g_PendingLeakedTxdRefs.insert (usTxdId);
1825+ MapRemove (ms_ModelTexturesInfoMap, usTxdId);
1826+ return nullptr ;
1827+ }
1828+ }
1829+ }
17361830 }
17371831 }
17381832
@@ -1807,10 +1901,39 @@ CModelTexturesInfo* CRenderWareSA::GetModelTexturesInfo(unsigned short usModelId
18071901 if (!pTxd)
18081902 {
18091903 unsigned int uiTxdStreamId = usTxdId + pGame->GetBaseIDforTXD ();
1810- pGame->GetStreaming ()->RequestModel (uiTxdStreamId, 0x16 );
1811- pGame->GetStreaming ()->LoadAllRequestedModels (true , " CRenderWareSA::GetModelTexturesInfo-TXD" );
1812-
1904+ CStreamingInfo* pStreamInfo = pGame->GetStreaming ()->GetStreamingInfo (uiTxdStreamId);
1905+ bool bLoaded = pStreamInfo && pStreamInfo->loadState == eModelLoadState::LOADSTATE_LOADED ;
1906+ if (!bLoaded)
1907+ {
1908+ pGame->GetStreaming ()->RequestModel (uiTxdStreamId, 0x16 );
1909+ pGame->GetStreaming ()->LoadAllRequestedModels (false , " GetModelTexturesInfo-txd" );
1910+ }
18131911 pTxd = CTxdStore_GetTxd (usTxdId);
1912+
1913+ if (!pTxd)
1914+ {
1915+ CStreamingInfo* pStreamInfoRetry = pGame->GetStreaming ()->GetStreamingInfo (uiTxdStreamId);
1916+ bool bBusy = pStreamInfoRetry && (pStreamInfoRetry->loadState == eModelLoadState::LOADSTATE_READING || pStreamInfoRetry->loadState == eModelLoadState::LOADSTATE_FINISHING );
1917+ if (bBusy)
1918+ return nullptr ;
1919+
1920+ pGame->GetStreaming ()->LoadAllRequestedModels (false , " GetModelTexturesInfo-txd-retry" );
1921+ pTxd = CTxdStore_GetTxd (usTxdId);
1922+
1923+ if (!pTxd)
1924+ {
1925+ CStreamingInfo* pStreamInfoRetry2 = pGame->GetStreaming ()->GetStreamingInfo (uiTxdStreamId);
1926+ bool bBusyRetry = pStreamInfoRetry2 && (pStreamInfoRetry2->loadState == eModelLoadState::LOADSTATE_READING || pStreamInfoRetry2->loadState == eModelLoadState::LOADSTATE_FINISHING );
1927+ if (bBusyRetry)
1928+ return nullptr ;
1929+
1930+ if (!pStreamInfoRetry2 || pStreamInfoRetry2->loadState != eModelLoadState::LOADSTATE_LOADED )
1931+ pGame->GetStreaming ()->RequestModel (uiTxdStreamId, 0x16 );
1932+ pGame->GetStreaming ()->LoadAllRequestedModels (false , " GetModelTexturesInfo-txd-retry2" );
1933+ pTxd = CTxdStore_GetTxd (usTxdId);
1934+ }
1935+ }
1936+
18141937 if (pTxd)
18151938 CRenderWareSA::DebugTxdAddRef (usTxdId, " GetModelTexturesInfo-cache-miss" );
18161939 }
0 commit comments