Skip to content

Commit abf9413

Browse files
authored
Merge branch 'master' into bugfix/buildings_rotation
2 parents ab4a1b1 + 53521fa commit abf9413

57 files changed

Lines changed: 30263 additions & 176 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/tests.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: "Tests"
2+
3+
on:
4+
push:
5+
branches: ["master", "tests"]
6+
pull_request:
7+
branches: ["master"]
8+
workflow_dispatch:
9+
10+
jobs:
11+
client-tests:
12+
name: Client Tests (x86 Debug)
13+
runs-on: windows-latest
14+
steps:
15+
- name: Checkout
16+
uses: actions/checkout@v4
17+
18+
- name: Setup MSBuild
19+
uses: microsoft/setup-msbuild@v2
20+
21+
- name: Generate project files
22+
shell: cmd
23+
run: |
24+
utils\premake5.exe install_cef
25+
utils\premake5.exe install_unifont
26+
utils\premake5.exe install_discord
27+
utils\premake5.exe vs2026
28+
29+
- name: Build Tests_Client
30+
shell: cmd
31+
run: msbuild Build\Tests_Client.vcxproj /p:Configuration=Debug /p:Platform=Win32 /p:PlatformToolset=v143 /nologo /v:minimal
32+
33+
- name: Run tests
34+
run: Bin\tests\Tests_Client_d.exe --gtest_output=xml:Bin\tests\test_results.xml
35+
36+
- name: Upload test results
37+
if: always()
38+
uses: actions/upload-artifact@v4
39+
with:
40+
name: test-results
41+
path: Bin/tests/test_results.xml

Client/game_sa/CModelInfoSA.cpp

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,8 @@ void CModelInfoSA::Remove()
608608
// Remove our reference
609609
if (m_pInterface->usNumberOfRefs > 0)
610610
{
611-
if (CTxdStore_GetTxd(m_pInterface->usTextureDictionary) != nullptr)
611+
if (pGame && !pGame->GetPools()->GetTxdPool().IsFreeTextureDictonarySlot(m_pInterface->usTextureDictionary) &&
612+
CTxdStore_GetTxd(m_pInterface->usTextureDictionary) != nullptr)
612613
CTxdStore_RemoveRef(m_pInterface->usTextureDictionary);
613614
m_pInterface->usNumberOfRefs--;
614615
}
@@ -1104,6 +1105,10 @@ void CModelInfoSA::SetTextureDictionaryID(unsigned short usID)
11041105
if (usOldTxdId == usID)
11051106
return;
11061107

1108+
// CTxdStore functions (GetTxd, AddRef, RemoveRef) crash on free pool entries.
1109+
if (!pGame || pGame->GetPools()->GetTxdPool().IsFreeTextureDictonarySlot(usID))
1110+
return;
1111+
11071112
// Slot allocated (e.g. via engineRequestTXD) but TXD data isn't loaded yet.
11081113
// For unloaded models without geometry, record the new TXD ID and transfer
11091114
// entity refs so callers' pre-added refs are consumed. Loaded models fall
@@ -1113,9 +1118,6 @@ void CModelInfoSA::SetTextureDictionaryID(unsigned short usID)
11131118
// texture data arrives later via engineImageLinkTXD + restream.
11141119
if (CTxdStore_GetTxd(usID) == nullptr)
11151120
{
1116-
if (!pGame || pGame->GetPools()->GetTxdPool().IsFreeTextureDictonarySlot(usID))
1117-
return;
1118-
11191121
if (!m_pInterface->pRwObject)
11201122
{
11211123
if (!MapContains(ms_DefaultTxdIDMap, static_cast<unsigned short>(m_dwModelID)))
@@ -1131,7 +1133,7 @@ void CModelInfoSA::SetTextureDictionaryID(unsigned short usID)
11311133
for (size_t i = 0; i < referencesCount; i++)
11321134
CTxdStore_AddRef(usID);
11331135

1134-
if (CTxdStore_GetTxd(usOldTxdId) != nullptr)
1136+
if (!pGame->GetPools()->GetTxdPool().IsFreeTextureDictonarySlot(usOldTxdId) && CTxdStore_GetTxd(usOldTxdId) != nullptr)
11351137
{
11361138
for (size_t i = 0; i < referencesCount; i++)
11371139
CTxdStore_RemoveRef(usOldTxdId);
@@ -1196,9 +1198,9 @@ void CModelInfoSA::SetTextureDictionaryID(unsigned short usID)
11961198
}
11971199
}
11981200

1199-
// Release old TXD refs after rebinding completes
1200-
// Only release if old slot is still valid to avoid crash on stale/orphaned TXD slots
1201-
if (CTxdStore_GetTxd(usOldTxdId) != nullptr)
1201+
// Release old TXD refs after rebinding. Skip if the slot was freed between
1202+
// capturing usOldTxdId and here - CTxdStore functions crash on free entries.
1203+
if (!pGame->GetPools()->GetTxdPool().IsFreeTextureDictonarySlot(usOldTxdId) && CTxdStore_GetTxd(usOldTxdId) != nullptr)
12021204
{
12031205
for (size_t i = 0; i < referencesCount; i++)
12041206
CTxdStore_RemoveRef(usOldTxdId);
@@ -2198,7 +2200,8 @@ void CModelInfoSA::ResetVehicleDummies(bool bRemoveFromDummiesMap)
21982200
{
21992201
if (pVehicleModel && pVehicleModel->usNumberOfRefs > 0)
22002202
{
2201-
if (CTxdStore_GetTxd(pVehicleModel->usTextureDictionary) != nullptr)
2203+
if (pGame && !pGame->GetPools()->GetTxdPool().IsFreeTextureDictonarySlot(pVehicleModel->usTextureDictionary) &&
2204+
CTxdStore_GetTxd(pVehicleModel->usTextureDictionary) != nullptr)
22022205
CTxdStore_RemoveRef(pVehicleModel->usTextureDictionary);
22032206
pVehicleModel->usNumberOfRefs--;
22042207
}
@@ -2215,7 +2218,8 @@ void CModelInfoSA::ResetVehicleDummies(bool bRemoveFromDummiesMap)
22152218

22162219
if (pVehicleModel->usNumberOfRefs > 0)
22172220
{
2218-
if (CTxdStore_GetTxd(pVehicleModel->usTextureDictionary) != nullptr)
2221+
if (pGame && !pGame->GetPools()->GetTxdPool().IsFreeTextureDictonarySlot(pVehicleModel->usTextureDictionary) &&
2222+
CTxdStore_GetTxd(pVehicleModel->usTextureDictionary) != nullptr)
22192223
CTxdStore_RemoveRef(pVehicleModel->usTextureDictionary);
22202224
pVehicleModel->usNumberOfRefs--;
22212225
}
@@ -2246,7 +2250,8 @@ void CModelInfoSA::ResetAllVehicleDummies()
22462250
{
22472251
if (pVehicleModel && pVehicleModel->usNumberOfRefs > 0)
22482252
{
2249-
if (CTxdStore_GetTxd(pVehicleModel->usTextureDictionary) != nullptr)
2253+
if (pGame && !pGame->GetPools()->GetTxdPool().IsFreeTextureDictonarySlot(pVehicleModel->usTextureDictionary) &&
2254+
CTxdStore_GetTxd(pVehicleModel->usTextureDictionary) != nullptr)
22502255
CTxdStore_RemoveRef(pVehicleModel->usTextureDictionary);
22512256
pVehicleModel->usNumberOfRefs--;
22522257
}
@@ -2260,7 +2265,8 @@ void CModelInfoSA::ResetAllVehicleDummies()
22602265

22612266
if (pVehicleModel->usNumberOfRefs > 0)
22622267
{
2263-
if (CTxdStore_GetTxd(pVehicleModel->usTextureDictionary) != nullptr)
2268+
if (pGame && !pGame->GetPools()->GetTxdPool().IsFreeTextureDictonarySlot(pVehicleModel->usTextureDictionary) &&
2269+
CTxdStore_GetTxd(pVehicleModel->usTextureDictionary) != nullptr)
22642270
CTxdStore_RemoveRef(pVehicleModel->usTextureDictionary);
22652271
pVehicleModel->usNumberOfRefs--;
22662272
}
@@ -2933,7 +2939,7 @@ void CModelInfoSA::MakeTimedObjectModel(ushort usBaseID)
29332939
pNewInterface->pRwObject = nullptr;
29342940
pNewInterface->usUnknown = 65535;
29352941
pNewInterface->usDynamicIndex = 65535;
2936-
pNewInterface->timeInfo.m_wOtherTimeModel = 0;
2942+
pNewInterface->timeInfo.m_wOtherTimeModel = -1;
29372943

29382944
ppModelInfo[m_dwModelID] = pNewInterface;
29392945

0 commit comments

Comments
 (0)