Skip to content

Commit 06c43c2

Browse files
authored
Merge branch 'master' into fix/improve-aclrequest-detection
2 parents 33178bc + a3508a5 commit 06c43c2

File tree

8 files changed

+234
-1082
lines changed

8 files changed

+234
-1082
lines changed

Client/game_sa/CRenderWareSA.TextureReplacing.cpp

Lines changed: 192 additions & 988 deletions
Large diffs are not rendered by default.

Client/game_sa/CRenderWareSA.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ class CRenderWareSA : public CRenderWare
3232
bool ModelInfoTXDLoadTextures(SReplacementTextures* pReplacementTextures, const SString& strFilename, const SString& buffer, bool bFilteringEnabled);
3333
bool ModelInfoTXDAddTextures(SReplacementTextures* pReplacementTextures, ushort usModelId);
3434
void ModelInfoTXDRemoveTextures(SReplacementTextures* pReplacementTextures);
35-
void ModelInfoTXDCleanupOrphanedEntries();
3635
void ClothesAddReplacement(char* pFileData, size_t fileSize, ushort usFileId);
3736
void ClothesRemoveReplacement(char* pFileData);
3837
bool HasClothesReplacementChanged();

Client/game_sa/CVehicleSA.cpp

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,11 +1360,8 @@ void CVehicleSA::SetHandlingData(CHandlingEntry* pHandling)
13601360
// Store the handling and recalculate it
13611361
m_pHandlingData = static_cast<CHandlingEntrySA*>(pHandling);
13621362
pVehicleInterface->pHandlingData = m_pHandlingData->GetInterface();
1363-
1364-
// Only recalculate if collision model is loaded (needed for suspension lines)
1365-
CModelInfo* pModelInfo = pGame->GetModelInfo(GetModelIndex());
1366-
if (pModelInfo && pModelInfo->GetInterface()->pColModel && pModelInfo->GetInterface()->pColModel->m_data)
1367-
RecalculateHandling();
1363+
1364+
RecalculateHandling();
13681365
}
13691366

13701367
void CVehicleSA::SetFlyingHandlingData(CFlyingHandlingEntry* pFlyingHandling)
@@ -1385,16 +1382,18 @@ void CVehicleSA::RecalculateHandling()
13851382
if (!pInt)
13861383
return;
13871384

1388-
// Ensure collision model is loaded before recalculating (needed for suspension lines)
13891385
CModelInfo* pModelInfo = pGame->GetModelInfo(GetModelIndex());
1390-
if (!pModelInfo || !pModelInfo->GetInterface()->pColModel || !pModelInfo->GetInterface()->pColModel->m_data)
1391-
return;
1386+
auto* pModelInterface = pModelInfo ? pModelInfo->GetInterface() : nullptr;
1387+
auto* pColModelInterface = pModelInterface ? pModelInterface->pColModel : nullptr;
1388+
bool bSuspensionDataReady = pColModelInterface && pColModelInterface->m_data;
1389+
bool bHasSuspension = pModelInfo &&
1390+
(pModelInfo->IsCar() || pModelInfo->IsMonsterTruck() || pModelInfo->IsTrailer() || pModelInfo->IsBike());
13921391

13931392
m_pHandlingData->Recalculate();
13941393

13951394
// Recalculate the suspension lines (only for vehicles that have suspension)
1396-
// Already validated that pColModel and m_data exist above
1397-
if (pModelInfo->IsCar() || pModelInfo->IsMonsterTruck() || pModelInfo->IsTrailer() || pModelInfo->IsBike())
1395+
// Skip until collision data streams in to avoid accessing null suspension lines
1396+
if (bSuspensionDataReady && bHasSuspension)
13981397
RecalculateSuspensionLines();
13991398

14001399
// Put it in our interface
@@ -1846,13 +1845,30 @@ void CVehicleSA::RecalculateSuspensionLines()
18461845
return;
18471846

18481847
// Ensure collision model is loaded before setting up suspension
1849-
if (!pModelInfo->GetInterface()->pColModel || !pModelInfo->GetInterface()->pColModel->m_data)
1848+
auto* pColModelInterface = pModelInfo->GetInterface()->pColModel;
1849+
if (!pColModelInterface || !pColModelInterface->m_data)
18501850
return;
18511851

1852-
// Note: We skip calling SetupSuspensionLines() because it's GTA SA's native code that can
1853-
// access pColModel->m_data without validation. If collision model is unloaded during execution
1854-
// (race condition), it causes crashes. CopyGlobalSuspensionLinesToPrivate() is safer as it
1855-
// validates collision model before accessing.
1852+
struct ScopedModelRef
1853+
{
1854+
explicit ScopedModelRef(CModelInfo* model)
1855+
: m_Model(model)
1856+
{
1857+
if (m_Model)
1858+
m_Model->ModelAddRef(EModelRequestType::BLOCKING, "CVehicleSA::RecalculateSuspensionLines");
1859+
}
1860+
1861+
~ScopedModelRef()
1862+
{
1863+
if (m_Model)
1864+
m_Model->RemoveRef();
1865+
}
1866+
1867+
CModelInfo* m_Model;
1868+
} modelRef(pModelInfo);
1869+
1870+
GetVehicleInterface()->SetupSuspensionLines();
1871+
18561872
CopyGlobalSuspensionLinesToPrivate();
18571873
}
18581874
}

Client/mods/deathmatch/logic/CClientGame.cpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1498,17 +1498,6 @@ void CClientGame::DoPulses()
14981498
// Collect async task scheduler results
14991499
m_pAsyncTaskScheduler->CollectResults();
15001500

1501-
// Periodically cleanup orphaned texture replacement entries (every ~5 minutes)
1502-
{
1503-
static int s_iCleanupFrameCounter = 0;
1504-
constexpr int CLEANUP_INTERVAL = 18000; // ~5 minutes at 60 FPS
1505-
if (++s_iCleanupFrameCounter >= CLEANUP_INTERVAL)
1506-
{
1507-
s_iCleanupFrameCounter = 0;
1508-
g_pGame->GetRenderWare()->ModelInfoTXDCleanupOrphanedEntries();
1509-
}
1510-
}
1511-
15121501
TIMING_CHECKPOINT("-CClientGame::DoPulses");
15131502
}
15141503

Client/mods/deathmatch/logic/RenderWareTextureGlobals.cpp

Lines changed: 0 additions & 5 deletions
This file was deleted.

Client/mods/deathmatch/premake5.lua

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ project "Client Deathmatch"
4848

4949
files {
5050
"premake5.lua",
51-
"logic/RenderWareTextureGlobals.cpp",
5251
"**.h",
5352
"**.cpp",
5453
"../../../Shared/mods/deathmatch/logic/**.cpp",

Client/sdk/game/CRenderWare.h

Lines changed: 5 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,8 @@
1111

1212
#pragma once
1313

14-
#include <cstddef>
15-
#include <cstdint>
16-
#include <memory>
17-
#include <unordered_map>
18-
#include <unordered_set>
19-
#include <utility>
2014
#include <vector>
2115

22-
#include "RenderWare.h"
23-
2416
class CClientEntityBase;
2517
class CD3DDUMMY;
2618
class CMatrix;
@@ -37,62 +29,21 @@ struct RpClump;
3729

3830
typedef CShaderItem CSHADERDUMMY;
3931

40-
extern int (__cdecl* RwTextureDestroy)(RwTexture* texture);
41-
inline int (__cdecl*& gRwTextureDestroy)(RwTexture* texture) = RwTextureDestroy;
42-
4332
// A list of custom textures to add to a model's txd
4433
struct SReplacementTextures
4534
{
46-
struct RwTextureDeleter
47-
{
48-
void operator()(RwTexture* texture) const noexcept
49-
{
50-
if (!texture)
51-
return;
52-
53-
// Fast validation: Check if pointer looks reasonable (not in low invalid range)
54-
// This catches most corruption cases without expensive VirtualQuery
55-
const uintptr_t addr = reinterpret_cast<uintptr_t>(texture);
56-
constexpr uintptr_t kMinUserAddress = 0x10000; // Below this is always invalid (null page protection)
57-
58-
// Note: Upper bound check not needed on x86 with LARGEADDRESSAWARE, as MTA has (full 4GB accessible)
59-
// On x86, uintptr_t cannot exceed 0xFFFFFFFF, so all pointers >= 0x10000 are potentially valid
60-
if (addr < kMinUserAddress)
61-
return;
62-
63-
// Only destroy if texture is orphaned (not owned by any TXD)
64-
// If txd != nullptr, the TXD owns it and will destroy it
65-
// Note: We access texture->txd without IsReadablePointer for performance.
66-
// If the pointer is invalid, we'll crash here, but that's acceptable vs
67-
// the cost of VirtualQuery on every texture destruction (1-2ms per 1000 textures).
68-
// The address range check above catches most corruption cases.
69-
if (texture->txd == nullptr && RwTextureDestroy)
70-
{
71-
RwTextureDestroy(texture);
72-
}
73-
}
74-
};
75-
76-
using TextureOwner = std::unique_ptr<RwTexture, RwTextureDeleter>;
77-
7835
struct SPerTxd
7936
{
8037
std::vector<RwTexture*> usingTextures;
8138
std::vector<RwTexture*> replacedOriginals;
82-
std::vector<ushort> modelIdsUsingTxd;
83-
std::vector<TextureOwner> ownedClones;
84-
ushort usTxdId = 0;
85-
bool bTexturesAreCopies = false;
39+
ushort usTxdId;
40+
bool bTexturesAreCopies;
8641
};
8742

88-
std::vector<RwTexture*> textures; // Raw pointers to textures (for compatibility)
89-
std::vector<SPerTxd> perTxdList; // TXD's which have been modified
90-
std::vector<ushort> usedInTxdIds;
43+
std::vector<RwTexture*> textures; // List of textures we want to inject into TXD's
44+
std::vector<SPerTxd> perTxdList; // TXD's which have been modified
45+
std::vector<ushort> usedInTxdIds;
9146
std::vector<ushort> usedInModelIds;
92-
std::unordered_set<ushort> usedInTxdIdLookup;
93-
std::unordered_set<ushort> usedInModelIdLookup;
94-
std::unordered_map<ushort, std::size_t> perTxdIndexLookup;
95-
std::vector<TextureOwner> ownedTextures; // Owned textures with automatic lifetime management (MUST BE LAST for binary compatibility)
9647
};
9748

9849
// Shader layers to render
@@ -126,7 +77,6 @@ class CRenderWare
12677
bool bFilteringEnabled) = 0;
12778
virtual bool ModelInfoTXDAddTextures(SReplacementTextures* pReplacementTextures, ushort usModelId) = 0;
12879
virtual void ModelInfoTXDRemoveTextures(SReplacementTextures* pReplacementTextures) = 0;
129-
virtual void ModelInfoTXDCleanupOrphanedEntries() = 0;
13080
virtual void ClothesAddReplacement(char* pFileData, size_t fileSize, ushort usFileId) = 0;
13181
virtual void ClothesRemoveReplacement(char* pFileData) = 0;
13282
virtual bool HasClothesReplacementChanged() = 0;

Shared/data/MTA San Andreas/MTA/locale/en_US/client.pot

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ msgid ""
88
msgstr ""
99
"Project-Id-Version: MTA San Andreas 1.x\n"
1010
"Report-Msgid-Bugs-To: \n"
11-
"POT-Creation-Date: 2025-10-24 01:59+0000\n"
11+
"POT-Creation-Date: 2025-10-27 10:21+0000\n"
1212
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
1313
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1414
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -3429,23 +3429,23 @@ msgstr ""
34293429
msgid "MTA Client verification failed!"
34303430
msgstr ""
34313431

3432-
#: Client/mods/deathmatch/logic/CClientGame.cpp:5685
3432+
#: Client/mods/deathmatch/logic/CClientGame.cpp:5674
34333433
msgid "In a ditch"
34343434
msgstr ""
34353435

3436-
#: Client/mods/deathmatch/logic/CClientGame.cpp:5685
3436+
#: Client/mods/deathmatch/logic/CClientGame.cpp:5674
34373437
msgid "En-route to hospital"
34383438
msgstr ""
34393439

3440-
#: Client/mods/deathmatch/logic/CClientGame.cpp:5685
3440+
#: Client/mods/deathmatch/logic/CClientGame.cpp:5674
34413441
msgid "Meeting their maker"
34423442
msgstr ""
34433443

3444-
#: Client/mods/deathmatch/logic/CClientGame.cpp:5685
3444+
#: Client/mods/deathmatch/logic/CClientGame.cpp:5674
34453445
msgid "Regretting their decisions"
34463446
msgstr ""
34473447

3448-
#: Client/mods/deathmatch/logic/CClientGame.cpp:5685
3448+
#: Client/mods/deathmatch/logic/CClientGame.cpp:5674
34493449
msgid "Wasted"
34503450
msgstr ""
34513451

0 commit comments

Comments
 (0)